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