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 "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 
     18 static 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 
     25 static 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 
     43 static 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 
     50 static 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 
     68 bool 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 
     88 SkRGB565_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 
    108 SkRGB565_Shader_Blitter::~SkRGB565_Shader_Blitter() {
    109     sk_free(fBuffer);
    110 }
    111 
    112 void 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 
    122 void 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