SkSwizzler.cpp revision dfdec78a5d02e8690998741a9fe5b71a08ca3232
1/* 2 * Copyright 2015 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8#include "SkColorPriv.h" 9#include "SkSwizzler.h" 10#include "SkTemplates.h" 11 12// index 13 14#define A32_MASK_IN_PLACE (SkPMColor)(SK_A32_MASK << SK_A32_SHIFT) 15 16static bool swizzle_index_to_n32(void* SK_RESTRICT dstRow, 17 const uint8_t* SK_RESTRICT src, 18 int width, int deltaSrc, int, const SkPMColor ctable[]) { 19 20 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 21 SkPMColor cc = A32_MASK_IN_PLACE; 22 for (int x = 0; x < width; x++) { 23 SkPMColor c = ctable[*src]; 24 cc &= c; 25 dst[x] = c; 26 src += deltaSrc; 27 } 28 return cc != A32_MASK_IN_PLACE; 29} 30 31static bool swizzle_index_to_n32_skipZ(void* SK_RESTRICT dstRow, 32 const uint8_t* SK_RESTRICT src, 33 int width, int deltaSrc, int, 34 const SkPMColor ctable[]) { 35 36 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 37 SkPMColor cc = A32_MASK_IN_PLACE; 38 for (int x = 0; x < width; x++) { 39 SkPMColor c = ctable[*src]; 40 cc &= c; 41 if (c != 0) { 42 dst[x] = c; 43 } 44 src += deltaSrc; 45 } 46 return cc != A32_MASK_IN_PLACE; 47} 48 49#undef A32_MASK_IN_PLACE 50 51// n32 52static bool swizzle_rgbx_to_n32(void* SK_RESTRICT dstRow, 53 const uint8_t* SK_RESTRICT src, 54 int width, int deltaSrc, int, const SkPMColor[]) { 55 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 56 for (int x = 0; x < width; x++) { 57 dst[x] = SkPackARGB32(0xFF, src[0], src[1], src[2]); 58 src += deltaSrc; 59 } 60 return false; 61} 62 63static bool swizzle_rgba_to_n32_premul(void* SK_RESTRICT dstRow, 64 const uint8_t* SK_RESTRICT src, 65 int width, int deltaSrc, int, const SkPMColor[]) { 66 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 67 unsigned alphaMask = 0xFF; 68 for (int x = 0; x < width; x++) { 69 unsigned alpha = src[3]; 70 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 71 src += deltaSrc; 72 alphaMask &= alpha; 73 } 74 return alphaMask != 0xFF; 75} 76 77static bool swizzle_rgba_to_n32_unpremul(void* SK_RESTRICT dstRow, 78 const uint8_t* SK_RESTRICT src, 79 int width, int deltaSrc, int, 80 const SkPMColor[]) { 81 uint32_t* SK_RESTRICT dst = reinterpret_cast<uint32_t*>(dstRow); 82 unsigned alphaMask = 0xFF; 83 for (int x = 0; x < width; x++) { 84 unsigned alpha = src[3]; 85 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); 86 src += deltaSrc; 87 alphaMask &= alpha; 88 } 89 return alphaMask != 0xFF; 90} 91 92static bool swizzle_rgba_to_n32_premul_skipZ(void* SK_RESTRICT dstRow, 93 const uint8_t* SK_RESTRICT src, 94 int width, int deltaSrc, int, 95 const SkPMColor[]) { 96 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 97 unsigned alphaMask = 0xFF; 98 for (int x = 0; x < width; x++) { 99 unsigned alpha = src[3]; 100 if (0 != alpha) { 101 dst[x] = SkPreMultiplyARGB(alpha, src[0], src[1], src[2]); 102 } 103 src += deltaSrc; 104 alphaMask &= alpha; 105 } 106 return alphaMask != 0xFF; 107} 108 109/** 110 FIXME: This was my idea to cheat in order to continue taking advantage of skipping zeroes. 111 This would be fine for drawing normally, but not for drawing with transfer modes. Being 112 honest means we can draw correctly with transfer modes, with the cost of not being able 113 to take advantage of Android's free unwritten pages. Something to keep in mind when we 114 decide whether to switch to unpremul default. 115static bool swizzle_rgba_to_n32_unpremul_skipZ(void* SK_RESTRICT dstRow, 116 const uint8_t* SK_RESTRICT src, 117 int width, int deltaSrc, int, 118 const SkPMColor[]) { 119 SkPMColor* SK_RESTRICT dst = (SkPMColor*)dstRow; 120 unsigned alphaMask = 0xFF; 121 for (int x = 0; x < width; x++) { 122 unsigned alpha = src[3]; 123 // NOTE: We cheat here. The caller requested unpremul and skip zeroes. It's possible 124 // the color components are not zero, but we skip them anyway, meaning they'll remain 125 // zero (implied by the request to skip zeroes). 126 if (0 != alpha) { 127 dst[x] = SkPackARGB32NoCheck(alpha, src[0], src[1], src[2]); 128 } 129 src += deltaSrc; 130 alphaMask &= alpha; 131 } 132 return alphaMask != 0xFF; 133} 134*/ 135 136SkSwizzler* SkSwizzler::CreateSwizzler(SkSwizzler::SrcConfig sc, const SkPMColor* ctable, 137 const SkImageInfo& info, void* dst, 138 size_t dstRowBytes, bool skipZeroes) { 139 if (info.colorType() == kUnknown_SkColorType) { 140 return NULL; 141 } 142 if (info.minRowBytes() > dstRowBytes) { 143 return NULL; 144 } 145 if (kIndex == sc && NULL == ctable) { 146 return NULL; 147 } 148 RowProc proc = NULL; 149 switch (sc) { 150 case kIndex: 151 switch (info.colorType()) { 152 case kN32_SkColorType: 153 // We assume the color premultiplied ctable (or not) as desired. 154 if (skipZeroes) { 155 proc = &swizzle_index_to_n32_skipZ; 156 } else { 157 proc = &swizzle_index_to_n32; 158 } 159 break; 160 161 default: 162 break; 163 } 164 break; 165 case kRGBX: 166 // TODO: Support other swizzles. 167 switch (info.colorType()) { 168 case kN32_SkColorType: 169 proc = &swizzle_rgbx_to_n32; 170 break; 171 default: 172 break; 173 } 174 break; 175 case kRGBA: 176 switch (info.colorType()) { 177 case kN32_SkColorType: 178 if (info.alphaType() == kUnpremul_SkAlphaType) { 179 // Respect skipZeroes? 180 proc = &swizzle_rgba_to_n32_unpremul; 181 } else { 182 if (skipZeroes) { 183 proc = &swizzle_rgba_to_n32_premul_skipZ; 184 } else { 185 proc = &swizzle_rgba_to_n32_premul; 186 } 187 } 188 break; 189 default: 190 break; 191 } 192 break; 193 default: 194 break; 195 } 196 if (NULL == proc) { 197 return NULL; 198 } 199 return SkNEW_ARGS(SkSwizzler, (proc, ctable, BytesPerPixel(sc), info, dst, dstRowBytes)); 200} 201 202SkSwizzler::SkSwizzler(RowProc proc, const SkPMColor* ctable, int srcBpp, 203 const SkImageInfo& info, void* dst, size_t rowBytes) 204 : fRowProc(proc) 205 , fColorTable(ctable) 206 , fSrcPixelSize(srcBpp) 207 , fDstInfo(info) 208 , fDstRow(dst) 209 , fDstRowBytes(rowBytes) 210 , fCurrY(0) 211{ 212} 213 214bool SkSwizzler::next(const uint8_t* SK_RESTRICT src) { 215 SkASSERT(fCurrY < fDstInfo.height()); 216 const bool hadAlpha = fRowProc(fDstRow, src, fDstInfo.width(), fSrcPixelSize, 217 fCurrY, fColorTable); 218 fCurrY++; 219 fDstRow = SkTAddOffset<void>(fDstRow, fDstRowBytes); 220 return hadAlpha; 221} 222