Home | History | Annotate | Download | only in opts
      1 /*
      2  **
      3  ** Copyright 2009, The Android Open Source Project
      4  **
      5  ** Licensed under the Apache License, Version 2.0 (the "License");
      6  ** you may not use this file except in compliance with the License.
      7  ** You may obtain a copy of the License at
      8  **
      9  **     http://www.apache.org/licenses/LICENSE-2.0
     10  **
     11  ** Unless required by applicable law or agreed to in writing, software
     12  ** distributed under the License is distributed on an "AS IS" BASIS,
     13  ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14  ** See the License for the specific language governing permissions and
     15  ** limitations under the License.
     16  */
     17 
     18 #include "SkBitmapProcState_opts_SSE2.h"
     19 #include "SkBlitRow_opts_SSE2.h"
     20 #include "SkUtils_opts_SSE2.h"
     21 #include "SkUtils.h"
     22 
     23 /* This file must *not* be compiled with -msse or -msse2, otherwise
     24    gcc may generate sse2 even for scalar ops (and thus give an invalid
     25    instruction on Pentium3 on the code below).  Only files named *_SSE2.cpp
     26    in this directory should be compiled with -msse2. */
     27 
     28 #if defined(__x86_64__) || defined(_WIN64)
     29 /* All x86_64 machines have SSE2, so don't even bother checking. */
     30 static inline bool hasSSE2() {
     31     return true;
     32 }
     33 #else
     34 #ifdef _MSC_VER
     35 static inline void getcpuid(int info_type, int info[4]) {
     36     __asm {
     37         mov    eax, [info_type]
     38         cpuid
     39         mov    edi, [info]
     40         mov    [edi], eax
     41         mov    [edi+4], ebx
     42         mov    [edi+8], ecx
     43         mov    [edi+12], edx
     44     }
     45 }
     46 #else
     47 static inline void getcpuid(int info_type, int info[4]) {
     48     // We save and restore ebx, so this code can be compatible with -fPIC
     49     asm volatile (
     50         "pushl %%ebx      \n\t"
     51         "cpuid            \n\t"
     52         "movl %%ebx, %1   \n\t"
     53         "popl %%ebx       \n\t"
     54         : "=a"(info[0]), "=r"(info[1]), "=c"(info[2]), "=d"(info[3])
     55         : "a"(info_type)
     56     );
     57 }
     58 #endif
     59 
     60 static inline bool hasSSE2() {
     61     int cpu_info[4] = { 0 };
     62     getcpuid(1, cpu_info);
     63     return (cpu_info[3] & (1<<26)) != 0;
     64 }
     65 #endif
     66 
     67 void SkBitmapProcState::platformProcs() {
     68     if (hasSSE2()) {
     69         if (fSampleProc32 == S32_opaque_D32_filter_DX) {
     70             fSampleProc32 = S32_opaque_D32_filter_DX_SSE2;
     71         } else if (fSampleProc32 == S32_alpha_D32_filter_DX) {
     72             fSampleProc32 = S32_alpha_D32_filter_DX_SSE2;
     73         }
     74     }
     75 }
     76 
     77 static SkBlitRow::Proc32 platform_32_procs[] = {
     78     NULL,                               // S32_Opaque,
     79     S32_Blend_BlitRow32_SSE2,           // S32_Blend,
     80     S32A_Opaque_BlitRow32_SSE2,         // S32A_Opaque
     81     S32A_Blend_BlitRow32_SSE2,          // S32A_Blend,
     82 };
     83 
     84 SkBlitRow::Proc SkBlitRow::PlatformProcs4444(unsigned flags) {
     85     return NULL;
     86 }
     87 
     88 SkBlitRow::Proc SkBlitRow::PlatformProcs565(unsigned flags) {
     89     return NULL;
     90 }
     91 
     92 SkBlitRow::ColorProc SkBlitRow::PlatformColorProc() {
     93     if (hasSSE2()) {
     94         return Color32_SSE2;
     95     } else {
     96         return NULL;
     97     }
     98 }
     99 
    100 SkBlitRow::Proc32 SkBlitRow::PlatformProcs32(unsigned flags) {
    101     if (hasSSE2()) {
    102         return platform_32_procs[flags];
    103     } else {
    104         return NULL;
    105     }
    106 }
    107 
    108 
    109 SkBlitMask::Proc SkBlitMask::PlatformProcs(SkBitmap::Config dstConfig,
    110                                            SkColor color)
    111 {
    112 
    113     SkBlitMask::Proc proc = NULL;
    114     if (hasSSE2()) {
    115         switch (dstConfig) {
    116             case SkBitmap::kARGB_8888_Config:
    117                 // TODO: is our current SSE2 faster than the portable, even in
    118                 // the case of black or opaque? If so, no need for this check.
    119                 if ( SK_ColorBLACK != color && 0xFF != SkColorGetA(color))
    120                     proc = SkARGB32_BlitMask_SSE2;
    121                 break;
    122             default:
    123                  break;
    124         }
    125     }
    126     return proc;
    127 }
    128 
    129 SkMemset16Proc SkMemset16GetPlatformProc() {
    130     if (hasSSE2()) {
    131         return sk_memset16_SSE2;
    132     } else {
    133         return NULL;
    134     }
    135 }
    136 
    137 SkMemset32Proc SkMemset32GetPlatformProc() {
    138     if (hasSSE2()) {
    139         return sk_memset32_SSE2;
    140     } else {
    141         return NULL;
    142     }
    143 }
    144