1 /* 2 * Copyright 2017 Google Inc. 3 * 4 * Use of this source code is governed by a BSD-style license that can be 5 * found in the LICENSE file. 6 */ 7 8 #include "SkCoreBlitters.h" 9 #include "SkShader.h" 10 #include "SkUtils.h" 11 #include "SkXfermodePriv.h" 12 #include "SkBlitMask.h" 13 #include "SkColorPriv.h" 14 15 #include "SkNx.h" 16 17 static void D16_S32X_src(uint16_t dst[], const SkPMColor src[], int count, uint8_t coverage) { 18 SkASSERT(coverage == 0xFF); 19 for (int i = 0; i < count; ++i) { 20 dst[i] = SkPixel32ToPixel16(src[i]); 21 } 22 } 23 24 static void D16_S32X_src_coverage(uint16_t dst[], const SkPMColor src[], int count, 25 uint8_t coverage) { 26 switch (coverage) { 27 case 0: break; 28 case 0xFF: 29 for (int i = 0; i < count; ++i) { 30 dst[i] = SkPixel32ToPixel16(src[i]); 31 } 32 break; 33 default: 34 unsigned scale = coverage + (coverage >> 7); 35 for (int i = 0; i < count; ++i) { 36 dst[i] = SkSrcOver32To16(SkAlphaMulQ(src[i], scale), dst[i]); 37 } 38 break; 39 } 40 } 41 42 static void D16_S32A_srcover(uint16_t dst[], const SkPMColor src[], int count, uint8_t coverage) { 43 SkASSERT(coverage == 0xFF); 44 for (int i = 0; i < count; ++i) { 45 dst[i] = SkSrcOver32To16(src[i], dst[i]); 46 } 47 } 48 49 static void D16_S32A_srcover_coverage(uint16_t dst[], const SkPMColor src[], int count, 50 uint8_t coverage) { 51 switch (coverage) { 52 case 0: break; 53 case 0xFF: 54 for (int i = 0; i < count; ++i) { 55 dst[i] = SkSrcOver32To16(src[i], dst[i]); 56 } 57 break; 58 default: 59 unsigned scale = coverage + (coverage >> 7); 60 for (int i = 0; i < count; ++i) { 61 dst[i] = SkSrcOver32To16(SkAlphaMulQ(src[i], scale), dst[i]); 62 } 63 break; 64 } 65 } 66 67 bool SkRGB565_Shader_Blitter::Supports(const SkPixmap& device, const SkPaint& paint) { 68 if (device.colorType() != kRGB_565_SkColorType) { 69 return false; 70 } 71 if (device.colorSpace()) { 72 return false; 73 } 74 if (paint.getBlendMode() != SkBlendMode::kSrcOver && 75 paint.getBlendMode() != SkBlendMode::kSrc) { 76 return false; 77 } 78 if (paint.isLCDRenderText()) { 79 return false; 80 } 81 if (paint.isDither()) { 82 return false; 83 } 84 return true; 85 } 86 87 SkRGB565_Shader_Blitter::SkRGB565_Shader_Blitter(const SkPixmap& device, 88 const SkPaint& paint, SkShaderBase::Context* shaderContext) 89 : INHERITED(device, paint, shaderContext) 90 { 91 SkASSERT(shaderContext); 92 SkASSERT(Supports(device, paint)); 93 94 fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * (sizeof(SkPMColor))); 95 96 bool isOpaque = SkToBool(shaderContext->getFlags() & SkShaderBase::kOpaqueAlpha_Flag); 97 98 if (paint.getBlendMode() == SkBlendMode::kSrc || isOpaque) { 99 fBlend = D16_S32X_src; 100 fBlendCoverage = D16_S32X_src_coverage; 101 } else { // srcover 102 fBlend = isOpaque ? D16_S32X_src : D16_S32A_srcover; 103 fBlendCoverage = isOpaque ? D16_S32X_src_coverage : D16_S32A_srcover_coverage; 104 } 105 } 106 107 SkRGB565_Shader_Blitter::~SkRGB565_Shader_Blitter() { 108 sk_free(fBuffer); 109 } 110 111 void SkRGB565_Shader_Blitter::blitH(int x, int y, int width) { 112 SkASSERT(x >= 0 && y >= 0 && x + width <= fDevice.width()); 113 114 uint16_t* device = fDevice.writable_addr16(x, y); 115 116 SkPMColor* span = fBuffer; 117 fShaderContext->shadeSpan(x, y, span, width); 118 fBlend(device, span, width, 0xFF); 119 } 120 121 void SkRGB565_Shader_Blitter::blitAntiH(int x, int y, const SkAlpha coverage[], 122 const int16_t runs[]) { 123 SkPMColor* span = fBuffer; 124 uint16_t* device = fDevice.writable_addr16(x, y); 125 auto* shaderContext = fShaderContext; 126 127 for (;;) { 128 int count = *runs; 129 if (count <= 0) { 130 break; 131 } 132 int aa = *coverage; 133 if (aa) { 134 shaderContext->shadeSpan(x, y, span, count); 135 fBlendCoverage(device, span, count, aa); 136 } 137 device += count; 138 runs += count; 139 coverage += count; 140 x += count; 141 } 142 } 143