SkBlitter_RGB16.cpp revision 8a1c16ff38322f0210116fa7293eb8817c7e477e
18a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/* libs/graphics/sgl/SkBlitter_RGB16.cpp 28a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 38a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Copyright 2006, The Android Open Source Project 48a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 58a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Licensed under the Apache License, Version 2.0 (the "License"); 68a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** you may not use this file except in compliance with the License. 78a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** You may obtain a copy of the License at 88a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 98a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** http://www.apache.org/licenses/LICENSE-2.0 108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** 118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** Unless required by applicable law or agreed to in writing, software 128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** distributed under the License is distributed on an "AS IS" BASIS, 138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** See the License for the specific language governing permissions and 158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com** limitations under the License. 168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com*/ 178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitRow.h" 198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkCoreBlitters.h" 208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkColorPriv.h" 218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkDither.h" 228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkShader.h" 238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkUtils.h" 248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkXfermode.h" 258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other, 278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count) { 288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count > 0) { 298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // see if we need to write one short before we can cast to an 4byte ptr 308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // (we do this subtract rather than (unsigned)dst so we don't get warnings 318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // on 64bit machines) 328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (((char*)dst - (char*)0) & 2) { 338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *dst++ = value; 348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count -= 1; 358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap(value, other); 368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // fast way to set [value,other] pairs 398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef SK_CPU_BENDIAN 408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1); 418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1); 438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count & 1) { 468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com dst[count - 1] = value; 478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkBitmap& device, const SkPaint& paint) 548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : SkRGB16_Blitter(device, paint) { 558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(paint.getShader() == NULL); 568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(paint.getColorFilter() == NULL); 578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(paint.getXfermode() == NULL); 588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(paint.getColor() == SK_ColorBLACK); 598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 1 628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define black_8_pixels(mask, dst) \ 638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { \ 648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x80) dst[0] = 0; \ 658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x40) dst[1] = 0; \ 668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x20) dst[2] = 0; \ 678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x10) dst[3] = 0; \ 688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x08) dst[4] = 0; \ 698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x04) dst[5] = 0; \ 708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x02) dst[6] = 0; \ 718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x01) dst[7] = 0; \ 728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (0) 738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline black_8_pixels(U8CPU mask, uint16_t dst[]) 758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x80) dst[0] = 0; 778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x40) dst[1] = 0; 788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x20) dst[2] = 0; 798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x10) dst[3] = 0; 808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x08) dst[4] = 0; 818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x04) dst[5] = 0; 828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x02) dst[6] = 0; 838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x01) dst[7] = 0; 848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME SkRGB16_Black_BlitBW 888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS 898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst) black_8_pixels(mask, dst) 908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR getAddr16 918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE uint16_t 928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h" 938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Black_Blitter::blitMask(const SkMask& SK_RESTRICT mask, 958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& SK_RESTRICT clip) 968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SK_RESTRICT { 978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask.fFormat == SkMask::kBW_Format) { 988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRGB16_Black_BlitBW(fDevice, mask, clip); 998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop); 1018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop); 1028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned width = clip.width(); 1038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned height = clip.height(); 1048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned deviceRB = fDevice.rowBytes() - (width << 1); 1058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned maskRB = mask.fRowBytes - width; 1068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((int)height > 0); 1088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((int)width > 0); 1098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((int)deviceRB >= 0); 1108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((int)maskRB >= 0); 1118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 1138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned w = width; 1148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 1158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned aa = *alpha++; 1168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa)); 1178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += 1; 1188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--w != 0); 1198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device = (uint16_t*)((char*)device + deviceRB); 1208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com alpha += maskRB; 1218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--height != 0); 1228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Black_Blitter::blitAntiH(int x, int y, 1268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkAlpha* SK_RESTRICT antialias, 1278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const int16_t* SK_RESTRICT runs) 1288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SK_RESTRICT { 1298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 1328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = runs[0]; 1338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count >= 0); 1348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count <= 0) { 1358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 1368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 1388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned aa = antialias[0]; 1408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias += count; 1418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (aa) { 1428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (aa == 255) { 1438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(device, 0, count << 1); 1448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 1458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa = SkAlpha255To256(255 - aa); 1468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 1478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *device = SkAlphaMulRGB16(*device, aa); 1488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += 1; 1498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--count != 0); 1508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 1518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += count; 1548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////////////// 1588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////////////////// 1598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Blitter::SkRGB16_Blitter(const SkBitmap& device, const SkPaint& paint) 1618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : INHERITED(device) { 1628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkColor color = paint.getColor(); 1638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fSrcColor32 = SkPreMultiplyColor(color); 1658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fScale = SkAlpha255To256(SkColorGetA(color)); 1668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int r = SkColorGetR(color); 1688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int g = SkColorGetG(color); 1698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int b = SkColorGetB(color); 1708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b); 1728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we're dithered, use fRawDither16 to hold that. 1738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((fDoDither = paint.isDither()) != false) { 1748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fRawDither16 = SkDitherPack888ToRGB16(r, g, b); 1758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS), 1788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS), 1798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS)); 1808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comconst SkBitmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) { 1838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!fDoDither && 256 == fScale) { 1848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *value = fRawColor16; 1858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return &fDevice; 1868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return NULL; 1888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 1898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitH(int x, int y, int width) SK_RESTRICT { 1918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(width > 0); 1928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(x + width <= fDevice.width()); 1938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fScale == 0) { 1958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 1968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 1978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 1988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 1998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t srcColor = fColor16; 2008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (256 == fScale) { 2028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fRawColor16 == srcColor); 2038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDoDither) { 2048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t ditherColor = fRawDither16; 2058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((x ^ y) & 1) { 2068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap(ditherColor, srcColor); 2078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_dither_memset16(device, srcColor, ditherColor, width); 2098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_memset16(device, srcColor, width); 2118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // TODO: respect fDoDither 2148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor src32 = fSrcColor32; 2158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 2168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *device = SkSrcOver32To16(src32, *device); 2178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += 1; 2188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--width != 0); 2198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com// return 1 or 0 from a bool 2238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic int Bool2Int(bool value) { 2248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return !!value; 2258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 2268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitAntiH(int x, int y, 2288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkAlpha* SK_RESTRICT antialias, 2298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const int16_t* SK_RESTRICT runs) SK_RESTRICT { 2308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fScale == 0) { 2318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 2358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t srcColor = fRawColor16; 2368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned scale = fScale; 2378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int ditherInt = Bool2Int(fDoDither); 2388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (256 == scale) { 2408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t ditherColor = fRawDither16; 2418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we have no dithering, this will always fail 2428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((x ^ y) & ditherInt) { 2438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap(ditherColor, srcColor); 2448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 2468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = runs[0]; 2478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count >= 0); 2488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count <= 0) { 2498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 2528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned aa = antialias[0]; 2548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias += count; 2558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (aa) { 2568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (aa == 255) { 2578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (ditherInt) { 2588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_dither_memset16(device, srcColor, 2598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ditherColor, count); 2608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_memset16(device, srcColor, count); 2628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // TODO: respect fDoDither 2658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned scale5 = SkAlpha255To256(aa) >> 3; 2668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5; 2678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale5 = 32 - scale5; // now we can use it on the device 2688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int n = count; 2698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 2708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 2718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 2728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--n != 0); 2738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com goto DONE; 2748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += count; 2778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com DONE: 2798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // if we have no dithering, this will always fail 2808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count & ditherInt) { 2818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap(ditherColor, srcColor); 2828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 2858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // TODO: respect fDoDither 2868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 2878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = runs[0]; 2888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count >= 0); 2898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count <= 0) { 2908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 2918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 2928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 2938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 2948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned aa = antialias[0]; 2958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias += count; 2968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (aa) { 2978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3); 2988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t src32 = SkExpand_rgb_16(srcColor) * scale5; 2998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale5 = 32 - scale5; 3008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 3018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 3028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 3038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--count != 0); 3048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 3058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += count; 3078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com////////////////////////////////////////////////////////////////////////////////////// 3128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define solid_8_pixels(mask, dst, color) \ 3148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { \ 3158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x80) dst[0] = color; \ 3168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x40) dst[1] = color; \ 3178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x20) dst[2] = color; \ 3188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x10) dst[3] = color; \ 3198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x08) dst[4] = color; \ 3208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x04) dst[5] = color; \ 3218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x02) dst[6] = color; \ 3228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask & 0x01) dst[7] = color; \ 3238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (0) 3248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME SkRGB16_BlitBW 3268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS , uint16_t color 3278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst) solid_8_pixels(mask, dst, color) 3288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR getAddr16 3298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE uint16_t 3308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h" 3318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale, 3338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com U16CPU srcColor) { 3348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale); 3358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale); 3368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale); 3378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale); 3388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale); 3398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale); 3408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale); 3418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale); 3428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_NAME SkRGB16_BlendBW 3458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_ARGS , unsigned dst_scale, U16CPU src_color 3468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_BLIT8(mask, dst) blend_8_pixels(mask, dst, dst_scale, src_color) 3478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_GETADDR getAddr16 3488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#define SK_BLITBWMASK_DEVTYPE uint16_t 3498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#include "SkBlitBWMaskTemplate.h" 3508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) { 3528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5)); 3538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 3548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitMask(const SkMask& SK_RESTRICT mask, 3568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkIRect& SK_RESTRICT clip) SK_RESTRICT { 3578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fScale == 0) { 3588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 3598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (mask.fFormat == SkMask::kBW_Format) { 3618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fScale == 256) { 3628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRGB16_BlitBW(fDevice, mask, clip, fColor16); 3638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 3648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16); 3658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 3678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 3688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* SK_RESTRICT device = fDevice.getAddr16(clip.fLeft, clip.fTop); 3708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const uint8_t* SK_RESTRICT alpha = mask.getAddr(clip.fLeft, clip.fTop); 3718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = clip.width(); 3728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int height = clip.height(); 3738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned deviceRB = fDevice.rowBytes() - (width << 1); 3748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned maskRB = mask.fRowBytes - width; 3758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t color32 = SkExpand_rgb_16(fRawColor16); 3768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 3778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (256 == fScale) { 3788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 3798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int w = width; 3808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 3818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *device = blend_compact(color32, SkExpand_rgb_16(*device), 3828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkAlpha255To256(*alpha++) >> 3); 3838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += 1; 3848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--w != 0); 3858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device = (uint16_t*)((char*)device + deviceRB); 3868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com alpha += maskRB; 3878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--height != 0); 3888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // scale < 256 3898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned scale256 = fScale; 3908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 3918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int w = width; 3928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 3938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned aa = *alpha++; 3948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3); 3958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t src32 = color32 * scale; 3968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale); 3978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *device++ = SkCompact_rgb_16((src32 + dst32) >> 5); 3988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--w != 0); 3998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device = (uint16_t*)((char*)device + deviceRB); 4008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com alpha += maskRB; 4018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--height != 0); 4028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) { 4068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fScale == 0) { 4078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 4088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 4108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t color16 = fRawColor16; 4118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned deviceRB = fDevice.rowBytes(); 4128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (alpha + fScale == (255 + 256)) { 4148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDoDither) { 4158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t ditherColor = fRawDither16; 4168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((x ^ y) & 1) { 4178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap(ditherColor, color16); 4188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 4208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device[0] = color16; 4218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device = (uint16_t*)((char*)device + deviceRB); 4228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap(ditherColor, color16); 4238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--height != 0); 4248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 4258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 4268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device[0] = color16; 4278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device = (uint16_t*)((char*)device + deviceRB); 4288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--height != 0); 4298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 4318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // TODO: respect fDoDither 4328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3); 4338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t src32 = SkExpand_rgb_16(color16) * scale5; 4348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com scale5 = 32 - scale5; 4358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com do { 4368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t dst32 = SkExpand_rgb_16(*device) * scale5; 4378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com *device = SkCompact_rgb_16((src32 + dst32) >> 5); 4388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device = (uint16_t*)((char*)device + deviceRB); 4398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } while (--height != 0); 4408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Blitter::blitRect(int x, int y, int width, int height) { 4448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height()); 4458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fScale == 0) { 4478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return; 4488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 4508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned deviceRB = fDevice.rowBytes(); 4518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t color16 = fColor16; 4528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (256 == fScale) { 4548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (fDoDither) { 4558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t ditherColor = fRawDither16; 4568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if ((x ^ y) & 1) { 4578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap(ditherColor, color16); 4588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (--height >= 0) { 4608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_dither_memset16(device, color16, ditherColor, width); 4618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkTSwap(ditherColor, color16); 4628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device = (uint16_t*)((char*)device + deviceRB); 4638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // no dither 4658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (--height >= 0) { 4668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_memset16(device, color16, width); 4678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device = (uint16_t*)((char*)device + deviceRB); 4688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 4718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor src32 = fSrcColor32; 4728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com while (--height >= 0) { 4738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (int i = width - 1; i >= 0; --i) { 4748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device[i] = SkSrcOver32To16(src32, device[i]); 4758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device = (uint16_t*)((char*)device + deviceRB); 4778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 4798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 4828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader16_Blitter::SkRGB16_Shader16_Blitter(const SkBitmap& device, 4848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) 4858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com : SkRGB16_Shader_Blitter(device, paint) { 4868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(SkShader::CanCallShadeSpan16(fShader->getFlags())); 4878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 4888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader16_Blitter::blitH(int x, int y, int width) SK_RESTRICT { 4908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(x + width <= fDevice.width()); 4918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 4938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* shader = fShader; 4948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 4958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int alpha = shader->getSpan16Alpha(); 4968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0xFF == alpha) { 4978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->shadeSpan16(x, y, device, width); 4988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 4998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* span16 = (uint16_t*)fBuffer; 5008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->shadeSpan16(x, y, span16, width); 5018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlendRGB16(span16, device, SkAlpha255To256(alpha), width); 5028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader16_Blitter::blitAntiH(int x, int y, 5068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkAlpha* SK_RESTRICT antialias, 5078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const int16_t* SK_RESTRICT runs) 5088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SK_RESTRICT { 5098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* shader = fShader; 5108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor* SK_RESTRICT span = fBuffer; 5118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 5128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int alpha = shader->getSpan16Alpha(); 5148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* span16 = (uint16_t*)span; 5158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0xFF == alpha) { 5178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 5188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = *runs; 5198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count <= 0) { 5208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 5218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count <= fDevice.width()); // don't overrun fBuffer 5238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int aa = *antialias; 5258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (aa == 255) { 5268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // go direct to the device! 5278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->shadeSpan16(x, y, device, count); 5288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else if (aa) { 5298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->shadeSpan16(x, y, span16, count); 5308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlendRGB16(span16, device, SkAlpha255To256(aa), count); 5318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += count; 5338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 5348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias += count; 5358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += count; 5368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { // span alpha is < 255 5388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com alpha = SkAlpha255To256(alpha); 5398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 5408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = *runs; 5418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count <= 0) { 5428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 5438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count <= fDevice.width()); // don't overrun fBuffer 5458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int aa = SkAlphaMul(*antialias, alpha); 5478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (aa) { 5488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->shadeSpan16(x, y, span16, count); 5498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlendRGB16(span16, device, SkAlpha255To256(aa), count); 5508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += count; 5538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 5548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias += count; 5558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += count; 5568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////////////// 5618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkBitmap& device, 5638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkPaint& paint) 5648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com: INHERITED(device, paint) { 5658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(paint.getXfermode() == NULL); 5668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor)); 5688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // compute SkBlitRow::Procs 5708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com unsigned flags = 0; 5718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint32_t shaderFlags = fShader->getFlags(); 5738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // shaders take care of global alpha, so we never set it in SkBlitRow 5748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) { 5758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com flags |= SkBlitRow::kSrcPixelAlpha_Flag; 5768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // don't dither if the shader is really 16bit 5788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (paint.isDither() && !(shaderFlags & SkShader::kIntrinsicly16_Flag)) { 5798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com flags |= SkBlitRow::kDither_Flag; 5808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 5818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // used when we know our global alpha is 0xFF 5828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOpaqueProc = SkBlitRow::Factory(flags, SkBitmap::kRGB_565_Config); 5838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // used when we know our global alpha is < 0xFF 5848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAlphaProc = SkBlitRow::Factory(flags | SkBlitRow::kGlobalAlpha_Flag, 5858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBitmap::kRGB_565_Config); 5868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() { 5898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_free(fBuffer); 5908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Blitter::blitH(int x, int y, int width) { 5938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(x + width <= fDevice.width()); 5948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 5958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fShader->shadeSpan(x, y, fBuffer, width); 5968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com // shaders take care of global alpha, so we pass 0xFF (should be ignored) 5978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fOpaqueProc(fDevice.getAddr16(x, y), fBuffer, width, 0xFF, x, y); 5988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 5998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) { 6018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = 0; 6028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 6038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int n = *runs; 6048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (n == 0 || *aa == 0) { 6058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 6068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += n; 6088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa += n; 6098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count += n; 6108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return count; 6128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Blitter::blitAntiH(int x, int y, 6158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkAlpha* SK_RESTRICT antialias, 6168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const int16_t* SK_RESTRICT runs) 6178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SK_RESTRICT { 6188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* shader = fShader; 6198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor* SK_RESTRICT span = fBuffer; 6208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 6218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 6238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = *runs; 6248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count <= 0) { 6258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 6268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int aa = *antialias; 6288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == aa) { 6298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += count; 6308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 6318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias += count; 6328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += count; 6338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 6348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count); 6378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer 6398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->shadeSpan(x, y, span, nonZeroCount); 6408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor* localSpan = span; 6428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 6438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkBlitRow::Proc proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc; 6448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com proc(device, localSpan, count, aa, x, y); 6458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += count; 6478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += count; 6488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 6498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias += count; 6508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com nonZeroCount -= count; 6518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (nonZeroCount == 0) { 6528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 6538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com localSpan += count; 6558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(nonZeroCount > 0); 6568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count = *runs; 6578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count > 0); 6588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa = *antialias; 6598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 6618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com/////////////////////////////////////////////////////////////////////// 6648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter( 6668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkBitmap& device, const SkPaint& paint) 6678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com: INHERITED(device, paint) { 6688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fXfermode = paint.getXfermode(); 6698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(fXfermode); 6708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fXfermode->ref(); 6718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int width = device.width(); 6738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor)); 6748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fAAExpand = (uint8_t*)(fBuffer + width); 6758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comSkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() { 6788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fXfermode->unref(); 6798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sk_free(fBuffer); 6808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) { 6838a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(x + width <= fDevice.width()); 6848a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6858a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* device = fDevice.getAddr16(x, y); 6868a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor* span = fBuffer; 6878a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6888a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fShader->shadeSpan(x, y, span, width); 6898a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com fXfermode->xfer16(device, span, width, NULL); 6908a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 6918a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 6928a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comvoid SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y, 6938a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const SkAlpha* SK_RESTRICT antialias, 6948a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com const int16_t* SK_RESTRICT runs) SK_RESTRICT { 6958a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkShader* shader = fShader; 6968a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkXfermode* mode = fXfermode; 6978a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor* SK_RESTRICT span = fBuffer; 6988a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint8_t* SK_RESTRICT aaExpand = fAAExpand; 6998a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com uint16_t* SK_RESTRICT device = fDevice.getAddr16(x, y); 7008a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7018a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 7028a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int count = *runs; 7038a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (count <= 0) { 7048a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 7058a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7068a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int aa = *antialias; 7078a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (0 == aa) { 7088a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += count; 7098a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 7108a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias += count; 7118a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += count; 7128a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com continue; 7138a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7148a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7158a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int nonZeroCount = count + count_nonzero_span(runs + count, 7168a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias + count); 7178a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7188a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer 7198a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com shader->shadeSpan(x, y, span, nonZeroCount); 7208a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7218a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com x += nonZeroCount; 7228a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkPMColor* localSpan = span; 7238a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com for (;;) { 7248a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (aa == 0xFF) { 7258a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mode->xfer16(device, localSpan, count, NULL); 7268a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } else { 7278a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(aa); 7288a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com memset(aaExpand, aa, count); 7298a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com mode->xfer16(device, localSpan, count, aaExpand); 7308a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7318a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com device += count; 7328a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com runs += count; 7338a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com antialias += count; 7348a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com nonZeroCount -= count; 7358a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com if (nonZeroCount == 0) { 7368a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com break; 7378a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7388a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com localSpan += count; 7398a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(nonZeroCount > 0); 7408a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com count = *runs; 7418a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT(count > 0); 7428a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com aa = *antialias; 7438a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7448a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com } 7458a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7468a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7478a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com//////////////////////// 7488a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7498a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#if 0 7508a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.comstatic inline uint16_t aa_blendS32D16(SkPMColor src, U16CPU dst, int aa 7518a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef DITHER_SHADER 7528a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com , int dither 7538a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 7548a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com ) 7558a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com{ 7568a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com SkASSERT((unsigned)aa <= 255); 7578a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7588a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int src_scale = SkAlpha255To256(aa); 7598a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sa = SkGetPackedA32(src); 7608a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int dst_scale = SkAlpha255To256(255 - SkAlphaMul(sa, src_scale)); 7618a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7628a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#ifdef DITHER_SHADER 7638a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sr = SkGetPackedR32(src); 7648a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sg = SkGetPackedG32(src); 7658a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sb = SkGetPackedB32(src); 7668a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sr = SkDITHER_R32To16(sr, dither); 7678a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sg = SkDITHER_G32To16(sg, dither); 7688a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com sb = SkDITHER_B32To16(sb, dither); 7698a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#else 7708a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sr = SkPacked32ToR16(src); 7718a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sg = SkPacked32ToG16(src); 7728a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int sb = SkPacked32ToB16(src); 7738a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 7748a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7758a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int dr = (sr * src_scale + SkGetPackedR16(dst) * dst_scale) >> 8; 7768a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int dg = (sg * src_scale + SkGetPackedG16(dst) * dst_scale) >> 8; 7778a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com int db = (sb * src_scale + SkGetPackedB16(dst) * dst_scale) >> 8; 7788a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 7798a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com return SkPackRGB16(dr, dg, db); 7808a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com} 7818a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com#endif 7828a1c16ff38322f0210116fa7293eb8817c7e477ereed@android.com 783