1 /* libs/graphics/sgl/SkSpriteBlitter_RGB16.cpp 2 ** 3 ** Copyright 2006, 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 "SkSpriteBlitter.h" 19 #include "SkBlitRow.h" 20 #include "SkTemplates.h" 21 #include "SkUtils.h" 22 #include "SkColorPriv.h" 23 24 #define D16_S32A_Opaque_Pixel(dst, sc) \ 25 do { \ 26 if (sc) { \ 27 *dst = SkSrcOver32To16(sc, *dst); \ 28 } \ 29 } while (0) 30 31 static inline void D16_S32A_Blend_Pixel_helper(uint16_t* dst, SkPMColor sc, 32 unsigned src_scale) { 33 uint16_t dc = *dst; 34 unsigned sa = SkGetPackedA32(sc); 35 unsigned dr, dg, db; 36 37 if (255 == sa) { 38 dr = SkAlphaBlend(SkPacked32ToR16(sc), SkGetPackedR16(dc), src_scale); 39 dg = SkAlphaBlend(SkPacked32ToG16(sc), SkGetPackedG16(dc), src_scale); 40 db = SkAlphaBlend(SkPacked32ToB16(sc), SkGetPackedB16(dc), src_scale); 41 } else { 42 unsigned dst_scale = 255 - SkAlphaMul(sa, src_scale); 43 dr = (SkPacked32ToR16(sc) * src_scale + 44 SkGetPackedR16(dc) * dst_scale) >> 8; 45 dg = (SkPacked32ToG16(sc) * src_scale + 46 SkGetPackedG16(dc) * dst_scale) >> 8; 47 db = (SkPacked32ToB16(sc) * src_scale + 48 SkGetPackedB16(dc) * dst_scale) >> 8; 49 } 50 *dst = SkPackRGB16(dr, dg, db); 51 } 52 53 #define D16_S32A_Blend_Pixel(dst, sc, src_scale) \ 54 do { if (sc) D16_S32A_Blend_Pixel_helper(dst, sc, src_scale); } while (0) 55 56 57 /////////////////////////////////////////////////////////////////////////////// 58 59 class Sprite_D16_S16_Opaque : public SkSpriteBlitter { 60 public: 61 Sprite_D16_S16_Opaque(const SkBitmap& source) 62 : SkSpriteBlitter(source) {} 63 64 // overrides 65 virtual void blitRect(int x, int y, int width, int height) { 66 SK_RESTRICT uint16_t* dst = fDevice->getAddr16(x, y); 67 const SK_RESTRICT uint16_t* src = fSource->getAddr16(x - fLeft, 68 y - fTop); 69 unsigned dstRB = fDevice->rowBytes(); 70 unsigned srcRB = fSource->rowBytes(); 71 72 while (--height >= 0) { 73 memcpy(dst, src, width << 1); 74 dst = (uint16_t*)((char*)dst + dstRB); 75 src = (const uint16_t*)((const char*)src + srcRB); 76 } 77 } 78 }; 79 80 #define D16_S16_Blend_Pixel(dst, sc, scale) \ 81 do { \ 82 uint16_t dc = *dst; \ 83 *dst = SkBlendRGB16(sc, dc, scale); \ 84 } while (0) 85 86 #define SkSPRITE_CLASSNAME Sprite_D16_S16_Blend 87 #define SkSPRITE_ARGS , uint8_t alpha 88 #define SkSPRITE_FIELDS uint8_t fSrcAlpha; 89 #define SkSPRITE_INIT fSrcAlpha = alpha; 90 #define SkSPRITE_DST_TYPE uint16_t 91 #define SkSPRITE_SRC_TYPE uint16_t 92 #define SkSPRITE_DST_GETADDR getAddr16 93 #define SkSPRITE_SRC_GETADDR getAddr16 94 #define SkSPRITE_PREAMBLE(srcBM, x, y) int scale = SkAlpha255To256(fSrcAlpha); 95 #define SkSPRITE_BLIT_PIXEL(dst, src) D16_S16_Blend_Pixel(dst, src, scale) 96 #define SkSPRITE_NEXT_ROW 97 #define SkSPRITE_POSTAMBLE(srcBM) 98 #include "SkSpriteBlitterTemplate.h" 99 100 /////////////////////////////////////////////////////////////////////////////// 101 102 #define D16_S4444_Opaque(dst, sc) \ 103 do { \ 104 uint16_t dc = *dst; \ 105 *dst = SkSrcOver4444To16(sc, dc); \ 106 } while (0) 107 108 #define SkSPRITE_CLASSNAME Sprite_D16_S4444_Opaque 109 #define SkSPRITE_ARGS 110 #define SkSPRITE_FIELDS 111 #define SkSPRITE_INIT 112 #define SkSPRITE_DST_TYPE uint16_t 113 #define SkSPRITE_SRC_TYPE SkPMColor16 114 #define SkSPRITE_DST_GETADDR getAddr16 115 #define SkSPRITE_SRC_GETADDR getAddr16 116 #define SkSPRITE_PREAMBLE(srcBM, x, y) 117 #define SkSPRITE_BLIT_PIXEL(dst, src) D16_S4444_Opaque(dst, src) 118 #define SkSPRITE_NEXT_ROW 119 #define SkSPRITE_POSTAMBLE(srcBM) 120 #include "SkSpriteBlitterTemplate.h" 121 122 #define D16_S4444_Blend(dst, sc, scale16) \ 123 do { \ 124 uint16_t dc = *dst; \ 125 *dst = SkBlend4444To16(sc, dc, scale16); \ 126 } while (0) 127 128 129 #define SkSPRITE_CLASSNAME Sprite_D16_S4444_Blend 130 #define SkSPRITE_ARGS , uint8_t alpha 131 #define SkSPRITE_FIELDS uint8_t fSrcAlpha; 132 #define SkSPRITE_INIT fSrcAlpha = alpha; 133 #define SkSPRITE_DST_TYPE uint16_t 134 #define SkSPRITE_SRC_TYPE uint16_t 135 #define SkSPRITE_DST_GETADDR getAddr16 136 #define SkSPRITE_SRC_GETADDR getAddr16 137 #define SkSPRITE_PREAMBLE(srcBM, x, y) int scale = SkAlpha15To16(fSrcAlpha); 138 #define SkSPRITE_BLIT_PIXEL(dst, src) D16_S4444_Blend(dst, src, scale) 139 #define SkSPRITE_NEXT_ROW 140 #define SkSPRITE_POSTAMBLE(srcBM) 141 #include "SkSpriteBlitterTemplate.h" 142 143 /////////////////////////////////////////////////////////////////////////////// 144 145 #define SkSPRITE_CLASSNAME Sprite_D16_SIndex8A_Opaque 146 #define SkSPRITE_ARGS 147 #define SkSPRITE_FIELDS 148 #define SkSPRITE_INIT 149 #define SkSPRITE_DST_TYPE uint16_t 150 #define SkSPRITE_SRC_TYPE uint8_t 151 #define SkSPRITE_DST_GETADDR getAddr16 152 #define SkSPRITE_SRC_GETADDR getAddr8 153 #define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.getColorTable()->lockColors() 154 #define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Opaque_Pixel(dst, ctable[src]) 155 #define SkSPRITE_NEXT_ROW 156 #define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors(false) 157 #include "SkSpriteBlitterTemplate.h" 158 159 #define SkSPRITE_CLASSNAME Sprite_D16_SIndex8A_Blend 160 #define SkSPRITE_ARGS , uint8_t alpha 161 #define SkSPRITE_FIELDS uint8_t fSrcAlpha; 162 #define SkSPRITE_INIT fSrcAlpha = alpha; 163 #define SkSPRITE_DST_TYPE uint16_t 164 #define SkSPRITE_SRC_TYPE uint8_t 165 #define SkSPRITE_DST_GETADDR getAddr16 166 #define SkSPRITE_SRC_GETADDR getAddr8 167 #define SkSPRITE_PREAMBLE(srcBM, x, y) const SkPMColor* ctable = srcBM.getColorTable()->lockColors(); unsigned src_scale = SkAlpha255To256(fSrcAlpha); 168 #define SkSPRITE_BLIT_PIXEL(dst, src) D16_S32A_Blend_Pixel(dst, ctable[src], src_scale) 169 #define SkSPRITE_NEXT_ROW 170 #define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlockColors(false); 171 #include "SkSpriteBlitterTemplate.h" 172 173 /////////////////////////////////////////////////////////////////////////////// 174 175 static intptr_t asint(const void* ptr) { 176 return reinterpret_cast<const char*>(ptr) - (const char*)0; 177 } 178 179 static void blitrow_d16_si8(SK_RESTRICT uint16_t* dst, 180 SK_RESTRICT const uint8_t* src, int count, 181 SK_RESTRICT const uint16_t* ctable) { 182 if (count <= 8) { 183 do { 184 *dst++ = ctable[*src++]; 185 } while (--count); 186 return; 187 } 188 189 // eat src until we're on a 4byte boundary 190 while (asint(src) & 3) { 191 *dst++ = ctable[*src++]; 192 count -= 1; 193 } 194 195 int qcount = count >> 2; 196 SkASSERT(qcount > 0); 197 const uint32_t* qsrc = reinterpret_cast<const uint32_t*>(src); 198 if (asint(dst) & 2) { 199 do { 200 uint32_t s4 = *qsrc++; 201 #ifdef SK_CPU_LENDIAN 202 *dst++ = ctable[s4 & 0xFF]; 203 *dst++ = ctable[(s4 >> 8) & 0xFF]; 204 *dst++ = ctable[(s4 >> 16) & 0xFF]; 205 *dst++ = ctable[s4 >> 24]; 206 #else // BENDIAN 207 *dst++ = ctable[s4 >> 24]; 208 *dst++ = ctable[(s4 >> 16) & 0xFF]; 209 *dst++ = ctable[(s4 >> 8) & 0xFF]; 210 *dst++ = ctable[s4 & 0xFF]; 211 #endif 212 } while (--qcount); 213 } else { // dst is on a 4byte boundary 214 uint32_t* ddst = reinterpret_cast<uint32_t*>(dst); 215 do { 216 uint32_t s4 = *qsrc++; 217 #ifdef SK_CPU_LENDIAN 218 *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF]; 219 *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF]; 220 #else // BENDIAN 221 *ddst++ = (ctable[s4 >> 24] << 16) | ctable[(s4 >> 16) & 0xFF]; 222 *ddst++ = (ctable[(s4 >> 8) & 0xFF] << 16) | ctable[s4 & 0xFF]; 223 #endif 224 } while (--qcount); 225 dst = reinterpret_cast<uint16_t*>(ddst); 226 } 227 src = reinterpret_cast<const uint8_t*>(qsrc); 228 count &= 3; 229 // catch any remaining (will be < 4) 230 while (--count >= 0) { 231 *dst++ = ctable[*src++]; 232 } 233 } 234 235 #define SkSPRITE_ROW_PROC(d, s, n, x, y) blitrow_d16_si8(d, s, n, ctable) 236 237 #define SkSPRITE_CLASSNAME Sprite_D16_SIndex8_Opaque 238 #define SkSPRITE_ARGS 239 #define SkSPRITE_FIELDS 240 #define SkSPRITE_INIT 241 #define SkSPRITE_DST_TYPE uint16_t 242 #define SkSPRITE_SRC_TYPE uint8_t 243 #define SkSPRITE_DST_GETADDR getAddr16 244 #define SkSPRITE_SRC_GETADDR getAddr8 245 #define SkSPRITE_PREAMBLE(srcBM, x, y) const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache() 246 #define SkSPRITE_BLIT_PIXEL(dst, src) *dst = ctable[src] 247 #define SkSPRITE_NEXT_ROW 248 #define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlock16BitCache() 249 #include "SkSpriteBlitterTemplate.h" 250 251 #define SkSPRITE_CLASSNAME Sprite_D16_SIndex8_Blend 252 #define SkSPRITE_ARGS , uint8_t alpha 253 #define SkSPRITE_FIELDS uint8_t fSrcAlpha; 254 #define SkSPRITE_INIT fSrcAlpha = alpha; 255 #define SkSPRITE_DST_TYPE uint16_t 256 #define SkSPRITE_SRC_TYPE uint8_t 257 #define SkSPRITE_DST_GETADDR getAddr16 258 #define SkSPRITE_SRC_GETADDR getAddr8 259 #define SkSPRITE_PREAMBLE(srcBM, x, y) const uint16_t* ctable = srcBM.getColorTable()->lock16BitCache(); unsigned src_scale = SkAlpha255To256(fSrcAlpha); 260 #define SkSPRITE_BLIT_PIXEL(dst, src) D16_S16_Blend_Pixel(dst, ctable[src], src_scale) 261 #define SkSPRITE_NEXT_ROW 262 #define SkSPRITE_POSTAMBLE(srcBM) srcBM.getColorTable()->unlock16BitCache(); 263 #include "SkSpriteBlitterTemplate.h" 264 265 /////////////////////////////////////////////////////////////////////////////// 266 267 class Sprite_D16_S32_BlitRowProc : public SkSpriteBlitter { 268 public: 269 Sprite_D16_S32_BlitRowProc(const SkBitmap& source) 270 : SkSpriteBlitter(source) {} 271 272 // overrides 273 274 virtual void setup(const SkBitmap& device, int left, int top, 275 const SkPaint& paint) { 276 this->INHERITED::setup(device, left, top, paint); 277 278 unsigned flags = 0; 279 280 if (paint.getAlpha() < 0xFF) { 281 flags |= SkBlitRow::kGlobalAlpha_Flag; 282 } 283 if (!fSource->isOpaque()) { 284 flags |= SkBlitRow::kSrcPixelAlpha_Flag; 285 } 286 if (paint.isDither()) { 287 flags |= SkBlitRow::kDither_Flag; 288 } 289 fProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config); 290 } 291 292 virtual void blitRect(int x, int y, int width, int height) { 293 SK_RESTRICT uint16_t* dst = fDevice->getAddr16(x, y); 294 const SK_RESTRICT SkPMColor* src = fSource->getAddr32(x - fLeft, 295 y - fTop); 296 unsigned dstRB = fDevice->rowBytes(); 297 unsigned srcRB = fSource->rowBytes(); 298 SkBlitRow::Proc proc = fProc; 299 U8CPU alpha = fPaint->getAlpha(); 300 301 while (--height >= 0) { 302 proc(dst, src, width, alpha, x, y); 303 y += 1; 304 dst = (SK_RESTRICT uint16_t*)((char*)dst + dstRB); 305 src = (const SK_RESTRICT SkPMColor*)((const char*)src + srcRB); 306 } 307 } 308 309 private: 310 SkBlitRow::Proc fProc; 311 312 typedef SkSpriteBlitter INHERITED; 313 }; 314 315 /////////////////////////////////////////////////////////////////////////////// 316 317 #include "SkTemplatesPriv.h" 318 319 SkSpriteBlitter* SkSpriteBlitter::ChooseD16(const SkBitmap& source, 320 const SkPaint& paint, 321 void* storage, size_t storageSize) { 322 if (paint.getMaskFilter() != NULL) { // may add cases for this 323 return NULL; 324 } 325 if (paint.getXfermode() != NULL) { // may add cases for this 326 return NULL; 327 } 328 if (paint.getColorFilter() != NULL) { // may add cases for this 329 return NULL; 330 } 331 332 SkSpriteBlitter* blitter = NULL; 333 unsigned alpha = paint.getAlpha(); 334 335 switch (source.getConfig()) { 336 case SkBitmap::kARGB_8888_Config: 337 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S32_BlitRowProc, 338 storage, storageSize, (source)); 339 break; 340 case SkBitmap::kARGB_4444_Config: 341 if (255 == alpha) { 342 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Opaque, 343 storage, storageSize, (source)); 344 } else { 345 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S4444_Blend, 346 storage, storageSize, (source, alpha >> 4)); 347 } 348 break; 349 case SkBitmap::kRGB_565_Config: 350 if (255 == alpha) { 351 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Opaque, 352 storage, storageSize, (source)); 353 } else { 354 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_S16_Blend, 355 storage, storageSize, (source, alpha)); 356 } 357 break; 358 case SkBitmap::kIndex8_Config: 359 if (paint.isDither()) { 360 // we don't support dither yet in these special cases 361 break; 362 } 363 if (source.isOpaque()) { 364 if (255 == alpha) { 365 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Opaque, 366 storage, storageSize, (source)); 367 } else { 368 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8_Blend, 369 storage, storageSize, (source, alpha)); 370 } 371 } else { 372 if (255 == alpha) { 373 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Opaque, 374 storage, storageSize, (source)); 375 } else { 376 SK_PLACEMENT_NEW_ARGS(blitter, Sprite_D16_SIndex8A_Blend, 377 storage, storageSize, (source, alpha)); 378 } 379 } 380 break; 381 default: 382 break; 383 } 384 return blitter; 385 } 386 387