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