SkSpriteBlitter_ARGB32.cpp revision a624d12b2d10cff79ba4b31744d81cc2e0a8db5f
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 SkBitmap& 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 SkBitmap& source, const SkPaint& paint) 65 : SkSpriteBlitter(source) { 66 fColorFilter = paint.getColorFilter(); 67 SkSafeRef(fColorFilter); 68 69 fXfermode = paint.getXfermode(); 70 SkSafeRef(fXfermode); 71 72 fBufferSize = 0; 73 fBuffer = NULL; 74 75 unsigned flags32 = 0; 76 if (255 != paint.getAlpha()) { 77 flags32 |= SkBlitRow::kGlobalAlpha_Flag32; 78 } 79 if (!source.isOpaque()) { 80 flags32 |= SkBlitRow::kSrcPixelAlpha_Flag32; 81 } 82 83 fProc32 = SkBlitRow::Factory32(flags32); 84 fAlpha = paint.getAlpha(); 85 } 86 87 virtual ~Sprite_D32_XferFilter() { 88 delete[] fBuffer; 89 SkSafeUnref(fXfermode); 90 SkSafeUnref(fColorFilter); 91 } 92 93 bool setup(const SkBitmap& device, int left, int top, const SkPaint& paint) override { 94 if (!this->INHERITED::setup(device, left, top, paint)) { 95 return false; 96 } 97 98 int width = device.width(); 99 if (width > fBufferSize) { 100 fBufferSize = width; 101 delete[] fBuffer; 102 fBuffer = new SkPMColor[width]; 103 } 104 return true; 105 } 106 107protected: 108 SkColorFilter* fColorFilter; 109 SkXfermode* fXfermode; 110 int fBufferSize; 111 SkPMColor* fBuffer; 112 SkBlitRow::Proc32 fProc32; 113 U8CPU fAlpha; 114 115private: 116 typedef SkSpriteBlitter INHERITED; 117}; 118 119/////////////////////////////////////////////////////////////////////////////// 120 121class Sprite_D32_S32A_XferFilter : public Sprite_D32_XferFilter { 122public: 123 Sprite_D32_S32A_XferFilter(const SkBitmap& source, const SkPaint& paint) 124 : Sprite_D32_XferFilter(source, paint) {} 125 126 void blitRect(int x, int y, int width, int height) override { 127 SkASSERT(width > 0 && height > 0); 128 uint32_t* SK_RESTRICT dst = fDevice->getAddr32(x, y); 129 const uint32_t* SK_RESTRICT src = fSource->addr32(x - fLeft, y - fTop); 130 size_t dstRB = fDevice->rowBytes(); 131 size_t srcRB = fSource->rowBytes(); 132 SkColorFilter* colorFilter = fColorFilter; 133 SkXfermode* xfermode = fXfermode; 134 135 do { 136 const SkPMColor* tmp = src; 137 138 if (colorFilter) { 139 colorFilter->filterSpan(src, width, fBuffer); 140 tmp = fBuffer; 141 } 142 143 if (xfermode) { 144 xfermode->xfer32(dst, tmp, width, NULL); 145 } else { 146 fProc32(dst, tmp, width, fAlpha); 147 } 148 149 dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB); 150 src = (const uint32_t* SK_RESTRICT)((const char*)src + srcRB); 151 } while (--height != 0); 152 } 153 154private: 155 typedef Sprite_D32_XferFilter INHERITED; 156}; 157 158static void fillbuffer(SkPMColor* SK_RESTRICT dst, 159 const SkPMColor16* SK_RESTRICT src, int count) { 160 SkASSERT(count > 0); 161 162 do { 163 *dst++ = SkPixel4444ToPixel32(*src++); 164 } while (--count != 0); 165} 166 167class Sprite_D32_S4444_XferFilter : public Sprite_D32_XferFilter { 168public: 169 Sprite_D32_S4444_XferFilter(const SkBitmap& source, const SkPaint& paint) 170 : Sprite_D32_XferFilter(source, paint) {} 171 172 void blitRect(int x, int y, int width, int height) override { 173 SkASSERT(width > 0 && height > 0); 174 SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); 175 const SkPMColor16* SK_RESTRICT src = fSource->addr16(x - fLeft, y - fTop); 176 size_t dstRB = fDevice->rowBytes(); 177 size_t srcRB = fSource->rowBytes(); 178 SkPMColor* SK_RESTRICT buffer = fBuffer; 179 SkColorFilter* colorFilter = fColorFilter; 180 SkXfermode* xfermode = fXfermode; 181 182 do { 183 fillbuffer(buffer, src, width); 184 185 if (colorFilter) { 186 colorFilter->filterSpan(buffer, width, buffer); 187 } 188 if (xfermode) { 189 xfermode->xfer32(dst, buffer, width, NULL); 190 } else { 191 fProc32(dst, buffer, width, fAlpha); 192 } 193 194 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 195 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 196 } while (--height != 0); 197 } 198 199private: 200 typedef Sprite_D32_XferFilter INHERITED; 201}; 202 203/////////////////////////////////////////////////////////////////////////////// 204 205static void src_row(SkPMColor* SK_RESTRICT dst, 206 const SkPMColor16* SK_RESTRICT src, int count) { 207 do { 208 *dst = SkPixel4444ToPixel32(*src); 209 src += 1; 210 dst += 1; 211 } while (--count != 0); 212} 213 214class Sprite_D32_S4444_Opaque : public SkSpriteBlitter { 215public: 216 Sprite_D32_S4444_Opaque(const SkBitmap& source) : SkSpriteBlitter(source) {} 217 218 void blitRect(int x, int y, int width, int height) override { 219 SkASSERT(width > 0 && height > 0); 220 SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); 221 const SkPMColor16* SK_RESTRICT src = fSource->addr16(x - fLeft, y - fTop); 222 size_t dstRB = fDevice->rowBytes(); 223 size_t srcRB = fSource->rowBytes(); 224 225 do { 226 src_row(dst, src, width); 227 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 228 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 229 } while (--height != 0); 230 } 231}; 232 233static void srcover_row(SkPMColor* SK_RESTRICT dst, 234 const SkPMColor16* SK_RESTRICT src, int count) { 235 do { 236 *dst = SkPMSrcOver(SkPixel4444ToPixel32(*src), *dst); 237 src += 1; 238 dst += 1; 239 } while (--count != 0); 240} 241 242class Sprite_D32_S4444 : public SkSpriteBlitter { 243public: 244 Sprite_D32_S4444(const SkBitmap& source) : SkSpriteBlitter(source) {} 245 246 void blitRect(int x, int y, int width, int height) override { 247 SkASSERT(width > 0 && height > 0); 248 SkPMColor* SK_RESTRICT dst = fDevice->getAddr32(x, y); 249 const SkPMColor16* SK_RESTRICT src = fSource->addr16(x - fLeft, y - fTop); 250 size_t dstRB = fDevice->rowBytes(); 251 size_t srcRB = fSource->rowBytes(); 252 253 do { 254 srcover_row(dst, src, width); 255 dst = (SkPMColor* SK_RESTRICT)((char*)dst + dstRB); 256 src = (const SkPMColor16* SK_RESTRICT)((const char*)src + srcRB); 257 } while (--height != 0); 258 } 259}; 260 261/////////////////////////////////////////////////////////////////////////////// 262 263SkSpriteBlitter* SkSpriteBlitter::ChooseD32(const SkBitmap& source, const SkPaint& paint, 264 SkTBlitterAllocator* allocator) { 265 SkASSERT(allocator != NULL); 266 267 if (paint.getMaskFilter() != NULL) { 268 return NULL; 269 } 270 271 U8CPU alpha = paint.getAlpha(); 272 SkXfermode* xfermode = paint.getXfermode(); 273 SkColorFilter* filter = paint.getColorFilter(); 274 SkSpriteBlitter* blitter = NULL; 275 276 switch (source.colorType()) { 277 case kARGB_4444_SkColorType: 278 if (alpha != 0xFF) { 279 return NULL; // we only have opaque sprites 280 } 281 if (xfermode || filter) { 282 blitter = allocator->createT<Sprite_D32_S4444_XferFilter>(source, paint); 283 } else if (source.isOpaque()) { 284 blitter = allocator->createT<Sprite_D32_S4444_Opaque>(source); 285 } else { 286 blitter = allocator->createT<Sprite_D32_S4444>(source); 287 } 288 break; 289 case kN32_SkColorType: 290 if (xfermode || filter) { 291 if (255 == alpha) { 292 // this can handle xfermode or filter, but not alpha 293 blitter = allocator->createT<Sprite_D32_S32A_XferFilter>(source, paint); 294 } 295 } else { 296 // this can handle alpha, but not xfermode or filter 297 blitter = allocator->createT<Sprite_D32_S32>(source, alpha); 298 } 299 break; 300 default: 301 break; 302 } 303 return blitter; 304} 305