Home | History | Annotate | Download | only in core
      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