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