SkSpriteBlitter_ARGB32.cpp revision c240e719b2bebd3711ade4e6fe056921aa7b0521
1 2/* 3 * Copyright 2006 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#include "SkSpriteBlitter.h" 11#include "SkBlitRow.h" 12#include "SkColorFilter.h" 13#include "SkColorPriv.h" 14#include "SkTemplates.h" 15#include "SkUtils.h" 16#include "SkXfermode.h" 17 18/////////////////////////////////////////////////////////////////////////////// 19 20class Sprite_D32_S32 : public SkSpriteBlitter { 21public: 22 Sprite_D32_S32(const SkPixmap& src, U8CPU alpha) : INHERITED(src) { 23 SkASSERT(src.colorType() == kN32_SkColorType); 24 25 unsigned flags32 = 0; 26 if (255 != alpha) { 27 flags32 |= SkBlitRow::kGlobalAlpha_Flag32; 28 } 29 if (!src.isOpaque()) { 30 flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; 31 } 32 33 fProc32 = SkBlitRow::Factory32(flags32); 34 fAlpha = alpha; 35 } 36 37 void blitRect(int x, int y, int width, int height) override { 38 SkASSERT(width > 0 && height > 0); 39 uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y); 40 const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); 41 size_t dstRB = fDevice->rowBytes(); 42 size_t srcRB = fSource.rowBytes(); 43 SkBlitRow::Proc32 proc = fProc32; 44 U8CPU alpha = fAlpha; 45 46 do { 47 proc(dst, src, width, alpha); 48 dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); 49 src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); 50 } while (--height != 0); 51 } 52 53private: 54 SkBlitRow::Proc32 fProc32; 55 U8CPU fAlpha; 56 57 typedef SkSpriteBlitter INHERITED; 58}; 59 60/////////////////////////////////////////////////////////////////////////////// 61 62class Sprite_D32_XferFilter : public SkSpriteBlitter { 63public: 64 Sprite_D32_XferFilter(const SkPixmap& source, const SkPaint& paint) : SkSpriteBlitter(source) { 65 fColorFilter = paint.getColorFilter(); 66 SkSafeRef(fColorFilter); 67 68 fXfermode = paint.getXfermode(); 69 SkSafeRef(fXfermode); 70 71 fBufferSize = 0; 72 fBuffer = NULL; 73 74 unsigned flags32 = 0; 75 if (255 != paint.getAlpha()) { 76 flags32 |= SkBlitRow::kGlobalAlpha_Flag32; 77 } 78 if (!source.isOpaque()) { 79 flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; 80 } 81 82 fProc32 = SkBlitRow::Factory32(flags32); 83 fAlpha = paint.getAlpha(); 84 } 85 86 virtual ~Sprite_D32_XferFilter() { 87 delete[] fBuffer; 88 SkSafeUnref(fXfermode); 89 SkSafeUnref(fColorFilter); 90 } 91 92 void setup(const SkBitmap& device, int left, int top, const SkPaint& paint) override { 93 this->INHERITED::setup(device, left, top, paint); 94 95 int width = device.width(); 96 if (width > fBufferSize) { 97 fBufferSize = width; 98 delete[] fBuffer; 99 fBuffer = new SkPMColor[width]; 100 } 101 } 102 103protected: 104 SkColorFilter* fColorFilter; 105 SkXfermode* fXfermode; 106 int fBufferSize; 107 SkPMColor* fBuffer; 108 SkBlitRow::Proc32 fProc32; 109 U8CPU fAlpha; 110 111private: 112 typedef SkSpriteBlitter INHERITED; 113}; 114 115/////////////////////////////////////////////////////////////////////////////// 116 117class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter { 118public: 119 Sprite_D32_S32A_XferFilter(const SkPixmap& source, const SkPaint& paint) 120 : Sprite_D32_XferFilter(source, paint) {} 121 122 void blitRect(int x, int y, int width, int height) override { 123 SkASSERT(width > 0 && height > 0); 124 uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y); 125 const uint32_t* SK_RESTRICT src = fSource.addr32(x - fLeft, y - fTop); 126 size_t dstRB = fDevice->rowBytes(); 127 size_t srcRB = fSource.rowBytes(); 128 SkColorFilter* colorFilter = fColorFilter; 129 SkXfermode* xfermode = fXfermode; 130 131 do { 132 const SkPMColor* tmp = src; 133 134 if (colorFilter) { 135 colorFilter->filterSpan(src, width, fBuffer); 136 tmp = fBuffer; 137 } 138 139 if (xfermode) { 140 xfermode->xfer32(dst, tmp, width, NULL); 141 } else { 142 fProc32(dst, tmp, width, fAlpha); 143 } 144 145 dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); 146 src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); 147 } while (--height != 0); 148 } 149 150private: 151 typedef Sprite_D32_XferFilter INHERITED; 152}; 153 154static void fillbuffer(SkPMColor* SK_RESTRICT dst, 155 const SkPMColor16* SK_RESTRICT src, int count) { 156 SkASSERT(count > 0); 157 158 do { 159 *dst++ = SkPixel4444ToPixel32(*src++); 160 } while (--count != 0); 161} 162 163class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter { 164public: 165 Sprite_D32_S4444_XferFilter(const SkPixmap& source, const SkPaint& paint) 166 : Sprite_D32_XferFilter(source, paint) {} 167 168 void blitRect(int x, int y, int width, int height) override { 169 SkASSERT(width > 0 && height > 0); 170 SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); 171 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop); 172 size_t dstRB = fDevice->rowBytes(); 173 size_t srcRB = fSource.rowBytes(); 174 SkPMColor* SK_RESTRICT buffer = fBuffer; 175 SkColorFilter* colorFilter = fColorFilter; 176 SkXfermode* xfermode = fXfermode; 177 178 do { 179 fillbuffer(buffer, src, width); 180 181 if (colorFilter) { 182 colorFilter->filterSpan(buffer, width, buffer); 183 } 184 if (xfermode) { 185 xfermode->xfer32(dst, buffer, width, NULL); 186 } else { 187 fProc32(dst, buffer, width, fAlpha); 188 } 189 190 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 191 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 192 } while (--height != 0); 193 } 194 195private: 196 typedef Sprite_D32_XferFilter INHERITED; 197}; 198 199/////////////////////////////////////////////////////////////////////////////// 200 201static void src_row(SkPMColor* SK_RESTRICT dst, 202 const SkPMColor16* SK_RESTRICT src, int count) { 203 do { 204 *dst = SkPixel4444ToPixel32(*src); 205 src += 1; 206 dst += 1; 207 } while (--count != 0); 208} 209 210class Sprite_D32_S4444_Opaque : public SkSpriteBlitter { 211public: 212 Sprite_D32_S4444_Opaque(const SkPixmap& source) : SkSpriteBlitter(source) {} 213 214 void blitRect(int x, int y, int width, int height) override { 215 SkASSERT(width > 0 && height > 0); 216 SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); 217 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop); 218 size_t dstRB = fDevice->rowBytes(); 219 size_t srcRB = fSource.rowBytes(); 220 221 do { 222 src_row(dst, src, width); 223 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 224 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 225 } while (--height != 0); 226 } 227}; 228 229static void srcover_row(SkPMColor* SK_RESTRICT dst, 230 const SkPMColor16* SK_RESTRICT src, int count) { 231 do { 232 *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst); 233 src += 1; 234 dst += 1; 235 } while (--count != 0); 236} 237 238class Sprite_D32_S4444 : public SkSpriteBlitter { 239public: 240 Sprite_D32_S4444(const SkPixmap& source) : SkSpriteBlitter(source) {} 241 242 void blitRect(int x, int y, int width, int height) override { 243 SkASSERT(width > 0 && height > 0); 244 SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); 245 const SkPMColor16* SK_RESTRICT src = fSource.addr16(x - fLeft, y - fTop); 246 size_t dstRB = fDevice->rowBytes(); 247 size_t srcRB = fSource.rowBytes(); 248 249 do { 250 srcover_row(dst, src, width); 251 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 252 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 253 } while (--height != 0); 254 } 255}; 256 257/////////////////////////////////////////////////////////////////////////////// 258 259SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkPixmap& source, const SkPaint& paint, 260 SkTBlitterAllocator* allocator) { 261 SkASSERT(allocator != NULL); 262 263 if (paint.getMaskFilter() != NULL) { 264 return NULL; 265 } 266 267 U8CPU alpha = paint.getAlpha(); 268 SkXfermode* xfermode = paint.getXfermode(); 269 SkColorFilter* filter = paint.getColorFilter(); 270 SkSpriteBlitter* blitter = NULL; 271 272 switch (source.colorType()) { 273 case kARGB_4444_SkColorType: 274 if (alpha != 0xFF) { 275 return NULL; // we only have opaque sprites 276 } 277 if (xfermode || filter) { 278 blitter = allocator->createT<Sprite_D32_S4444_XferFilter>(source, paint); 279 } else if (source.isOpaque()) { 280 blitter = allocator->createT<Sprite_D32_S4444_Opaque>(source); 281 } else { 282 blitter = allocator->createT<Sprite_D32_S4444>(source); 283 } 284 break; 285 case kN32_SkColorType: 286 if (xfermode || filter) { 287 if (255 == alpha) { 288 // this can handle xfermode or filter, but not alpha 289 blitter = allocator->createT<Sprite_D32_S32A_XferFilter>(source, paint); 290 } 291 } else { 292 // this can handle alpha, but not xfermode or filter 293 blitter = allocator->createT<Sprite_D32_S32>(source, alpha); 294 } 295 break; 296 default: 297 break; 298 } 299 return blitter; 300} 301