LCOV - code coverage report
Current view: top level - gfx/skia/skia/src/core - SkBlitter_RGB16.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 427 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 39 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright 2006 The Android Open Source Project
       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 "SkArenaAlloc.h"
       9             : #include "SkBlitRow.h"
      10             : #include "SkCoreBlitters.h"
      11             : #include "SkColorPriv.h"
      12             : #include "SkDither.h"
      13             : #include "SkShader.h"
      14             : #include "SkUtils.h"
      15             : #include "SkUtilsArm.h"
      16             : #include "SkXfermodePriv.h"
      17             : 
      18             : #if defined(SK_ARM_HAS_NEON) && defined(SK_CPU_LENDIAN)
      19             :     #include <arm_neon.h>
      20             : extern void SkRGB16BlitterBlitV_neon(uint16_t* device,
      21             :                                      int height,
      22             :                                      size_t deviceRB,
      23             :                                      unsigned scale,
      24             :                                      uint32_t src32);
      25             : #else
      26             :     // if we don't have neon, then our black blitter is worth the extra code
      27             :     #define USE_BLACK_BLITTER
      28             : #endif
      29             : 
      30           0 : void sk_dither_memset16(uint16_t dst[], uint16_t value, uint16_t other,
      31             :                         int count) {
      32           0 :     if (count > 0) {
      33             :         // see if we need to write one short before we can cast to an 4byte ptr
      34             :         // (we do this subtract rather than (unsigned)dst so we don't get warnings
      35             :         //  on 64bit machines)
      36           0 :         if (((char*)dst - (char*)0) & 2) {
      37           0 :             *dst++ = value;
      38           0 :             count -= 1;
      39           0 :             SkTSwap(value, other);
      40             :         }
      41             : 
      42             :         // fast way to set [value,other] pairs
      43             : #ifdef SK_CPU_BENDIAN
      44             :         sk_memset32((uint32_t*)dst, (value << 16) | other, count >> 1);
      45             : #else
      46           0 :         sk_memset32((uint32_t*)dst, (other << 16) | value, count >> 1);
      47             : #endif
      48             : 
      49           0 :         if (count & 1) {
      50           0 :             dst[count - 1] = value;
      51             :         }
      52             :     }
      53           0 : }
      54             : 
      55             : ///////////////////////////////////////////////////////////////////////////////
      56             : 
      57           0 : class SkRGB16_Blitter : public SkRasterBlitter {
      58             : public:
      59             :     SkRGB16_Blitter(const SkPixmap& device, const SkPaint& paint);
      60             :     void blitH(int x, int y, int width) override;
      61             :     virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
      62             :                            const int16_t* runs) override;
      63             :     void blitV(int x, int y, int height, SkAlpha alpha) override;
      64             :     void blitRect(int x, int y, int width, int height) override;
      65             :     void blitMask(const SkMask&, const SkIRect&) override;
      66             :     const SkPixmap* justAnOpaqueColor(uint32_t*) override;
      67             : 
      68             : protected:
      69             :     SkPMColor   fSrcColor32;
      70             :     uint32_t    fExpandedRaw16;
      71             :     unsigned    fScale;
      72             :     uint16_t    fColor16;       // already scaled by fScale
      73             :     uint16_t    fRawColor16;    // unscaled
      74             :     uint16_t    fRawDither16;   // unscaled
      75             :     SkBool8     fDoDither;
      76             : 
      77             :     SkBlitRow::ColorProc16 fColorProc16;
      78             : 
      79             :     // illegal
      80             :     SkRGB16_Blitter& operator=(const SkRGB16_Blitter&);
      81             : 
      82             :     typedef SkRasterBlitter INHERITED;
      83             : };
      84             : 
      85           0 : class SkRGB16_Opaque_Blitter : public SkRGB16_Blitter {
      86             : public:
      87             :     SkRGB16_Opaque_Blitter(const SkPixmap& device, const SkPaint& paint);
      88             :     void blitH(int x, int y, int width) override;
      89             :     void blitAntiH(int x, int y, const SkAlpha* antialias, const int16_t* runs) override;
      90             :     void blitV(int x, int y, int height, SkAlpha alpha) override;
      91             :     void blitRect(int x, int y, int width, int height) override;
      92             :     void blitMask(const SkMask&, const SkIRect&) override;
      93             : 
      94             : private:
      95             :     typedef SkRGB16_Blitter INHERITED;
      96             : };
      97             : 
      98             : #ifdef USE_BLACK_BLITTER
      99           0 : class SkRGB16_Black_Blitter : public SkRGB16_Opaque_Blitter {
     100             : public:
     101             :     SkRGB16_Black_Blitter(const SkPixmap& device, const SkPaint& paint);
     102             :     void blitMask(const SkMask&, const SkIRect&) override;
     103             :     void blitAntiH(int x, int y, const SkAlpha* antialias, const int16_t* runs) override;
     104             : 
     105             : private:
     106             :     typedef SkRGB16_Opaque_Blitter INHERITED;
     107             : };
     108             : #endif
     109             : 
     110             : class SkRGB16_Shader_Blitter : public SkShaderBlitter {
     111             : public:
     112             :     SkRGB16_Shader_Blitter(const SkPixmap& device, const SkPaint& paint,
     113             :                            SkShader::Context* shaderContext);
     114             :     ~SkRGB16_Shader_Blitter() override;
     115             :     void blitH(int x, int y, int width) override;
     116             :     virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
     117             :                            const int16_t* runs) override;
     118             :     void blitRect(int x, int y, int width, int height) override;
     119             : 
     120             : protected:
     121             :     SkPMColor*          fBuffer;
     122             :     SkBlitRow::Proc16   fOpaqueProc;
     123             :     SkBlitRow::Proc16   fAlphaProc;
     124             : 
     125             : private:
     126             :     // illegal
     127             :     SkRGB16_Shader_Blitter& operator=(const SkRGB16_Shader_Blitter&);
     128             : 
     129             :     typedef SkShaderBlitter INHERITED;
     130             : };
     131             : 
     132             : class SkRGB16_Shader_Xfermode_Blitter : public SkShaderBlitter {
     133             : public:
     134             :     SkRGB16_Shader_Xfermode_Blitter(const SkPixmap& device, const SkPaint& paint,
     135             :                                     SkShader::Context* shaderContext);
     136             :     ~SkRGB16_Shader_Xfermode_Blitter() override;
     137             :     void blitH(int x, int y, int width) override;
     138             :     virtual void blitAntiH(int x, int y, const SkAlpha* antialias,
     139             :                            const int16_t* runs) override;
     140             : 
     141             : private:
     142             :     SkXfermode* fXfermode;
     143             :     SkPMColor*  fBuffer;
     144             :     uint8_t*    fAAExpand;
     145             : 
     146             :     // illegal
     147             :     SkRGB16_Shader_Xfermode_Blitter& operator=(const SkRGB16_Shader_Xfermode_Blitter&);
     148             : 
     149             :     typedef SkShaderBlitter INHERITED;
     150             : };
     151             : 
     152             : ///////////////////////////////////////////////////////////////////////////////
     153             : #ifdef USE_BLACK_BLITTER
     154           0 : SkRGB16_Black_Blitter::SkRGB16_Black_Blitter(const SkPixmap& device, const SkPaint& paint)
     155           0 :     : INHERITED(device, paint) {
     156           0 :     SkASSERT(paint.getShader() == nullptr);
     157           0 :     SkASSERT(paint.getColorFilter() == nullptr);
     158           0 :     SkASSERT(paint.isSrcOver());
     159           0 :     SkASSERT(paint.getColor() == SK_ColorBLACK);
     160           0 : }
     161             : 
     162             : #if 1
     163             : #define black_8_pixels(mask, dst)       \
     164             :     do {                                \
     165             :         if (mask & 0x80) dst[0] = 0;    \
     166             :         if (mask & 0x40) dst[1] = 0;    \
     167             :         if (mask & 0x20) dst[2] = 0;    \
     168             :         if (mask & 0x10) dst[3] = 0;    \
     169             :         if (mask & 0x08) dst[4] = 0;    \
     170             :         if (mask & 0x04) dst[5] = 0;    \
     171             :         if (mask & 0x02) dst[6] = 0;    \
     172             :         if (mask & 0x01) dst[7] = 0;    \
     173             :     } while (0)
     174             : #else
     175             : static inline black_8_pixels(U8CPU mask, uint16_t dst[])
     176             : {
     177             :     if (mask & 0x80) dst[0] = 0;
     178             :     if (mask & 0x40) dst[1] = 0;
     179             :     if (mask & 0x20) dst[2] = 0;
     180             :     if (mask & 0x10) dst[3] = 0;
     181             :     if (mask & 0x08) dst[4] = 0;
     182             :     if (mask & 0x04) dst[5] = 0;
     183             :     if (mask & 0x02) dst[6] = 0;
     184             :     if (mask & 0x01) dst[7] = 0;
     185             : }
     186             : #endif
     187             : 
     188             : #define SK_BLITBWMASK_NAME                  SkRGB16_Black_BlitBW
     189             : #define SK_BLITBWMASK_ARGS
     190             : #define SK_BLITBWMASK_BLIT8(mask, dst)      black_8_pixels(mask, dst)
     191             : #define SK_BLITBWMASK_GETADDR               writable_addr16
     192             : #define SK_BLITBWMASK_DEVTYPE               uint16_t
     193             : #include "SkBlitBWMaskTemplate.h"
     194             : 
     195           0 : void SkRGB16_Black_Blitter::blitMask(const SkMask& mask,
     196             :                                      const SkIRect& clip) {
     197           0 :     if (mask.fFormat == SkMask::kBW_Format) {
     198           0 :         SkRGB16_Black_BlitBW(fDevice, mask, clip);
     199             :     } else {
     200           0 :         uint16_t* SK_RESTRICT device = fDevice.writable_addr16(clip.fLeft, clip.fTop);
     201           0 :         const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
     202           0 :         unsigned width = clip.width();
     203           0 :         unsigned height = clip.height();
     204           0 :         size_t deviceRB = fDevice.rowBytes() - (width << 1);
     205           0 :         unsigned maskRB = mask.fRowBytes - width;
     206             : 
     207           0 :         SkASSERT((int)height > 0);
     208           0 :         SkASSERT((int)width > 0);
     209           0 :         SkASSERT((int)deviceRB >= 0);
     210           0 :         SkASSERT((int)maskRB >= 0);
     211             : 
     212           0 :         do {
     213           0 :             unsigned w = width;
     214           0 :             do {
     215           0 :                 unsigned aa = *alpha++;
     216           0 :                 *device = SkAlphaMulRGB16(*device, SkAlpha255To256(255 - aa));
     217           0 :                 device += 1;
     218             :             } while (--w != 0);
     219           0 :             device = (uint16_t*)((char*)device + deviceRB);
     220           0 :             alpha += maskRB;
     221             :         } while (--height != 0);
     222             :     }
     223           0 : }
     224             : 
     225           0 : void SkRGB16_Black_Blitter::blitAntiH(int x, int y,
     226             :                                       const SkAlpha* SK_RESTRICT antialias,
     227             :                                       const int16_t* SK_RESTRICT runs) {
     228           0 :     uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
     229             : 
     230             :     for (;;) {
     231           0 :         int count = runs[0];
     232           0 :         SkASSERT(count >= 0);
     233           0 :         if (count <= 0) {
     234           0 :             return;
     235             :         }
     236           0 :         runs += count;
     237             : 
     238           0 :         unsigned aa = antialias[0];
     239           0 :         antialias += count;
     240           0 :         if (aa) {
     241           0 :             if (aa == 255) {
     242           0 :                 memset(device, 0, count << 1);
     243             :             } else {
     244           0 :                 aa = SkAlpha255To256(255 - aa);
     245           0 :                 do {
     246           0 :                     *device = SkAlphaMulRGB16(*device, aa);
     247           0 :                     device += 1;
     248             :                 } while (--count != 0);
     249           0 :                 continue;
     250             :             }
     251             :         }
     252           0 :         device += count;
     253           0 :     }
     254             : }
     255             : #endif
     256             : 
     257             : ///////////////////////////////////////////////////////////////////////////////
     258             : ///////////////////////////////////////////////////////////////////////////////
     259             : 
     260           0 : SkRGB16_Opaque_Blitter::SkRGB16_Opaque_Blitter(const SkPixmap& device, const SkPaint& paint)
     261           0 :     : INHERITED(device, paint) {}
     262             : 
     263           0 : void SkRGB16_Opaque_Blitter::blitH(int x, int y, int width) {
     264           0 :     SkASSERT(width > 0);
     265           0 :     SkASSERT(x + width <= fDevice.width());
     266           0 :     uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
     267           0 :     uint16_t srcColor = fColor16;
     268             : 
     269           0 :     SkASSERT(fRawColor16 == srcColor);
     270           0 :     if (fDoDither) {
     271           0 :         uint16_t ditherColor = fRawDither16;
     272           0 :         if ((x ^ y) & 1) {
     273           0 :             SkTSwap(ditherColor, srcColor);
     274             :         }
     275           0 :         sk_dither_memset16(device, srcColor, ditherColor, width);
     276             :     } else {
     277           0 :         sk_memset16(device, srcColor, width);
     278             :     }
     279           0 : }
     280             : 
     281             : // return 1 or 0 from a bool
     282           0 : static inline int Bool2Int(int value) {
     283           0 :     return !!value;
     284             : }
     285             : 
     286           0 : void SkRGB16_Opaque_Blitter::blitAntiH(int x, int y,
     287             :                                        const SkAlpha* SK_RESTRICT antialias,
     288             :                                        const int16_t* SK_RESTRICT runs) {
     289           0 :     uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
     290           0 :     uint16_t    srcColor = fRawColor16;
     291           0 :     uint32_t    srcExpanded = fExpandedRaw16;
     292           0 :     int         ditherInt = Bool2Int(fDoDither);
     293           0 :     uint16_t    ditherColor = fRawDither16;
     294             :     // if we have no dithering, this will always fail
     295           0 :     if ((x ^ y) & ditherInt) {
     296           0 :         SkTSwap(ditherColor, srcColor);
     297             :     }
     298             :     for (;;) {
     299           0 :         int count = runs[0];
     300           0 :         SkASSERT(count >= 0);
     301           0 :         if (count <= 0) {
     302           0 :             return;
     303             :         }
     304           0 :         runs += count;
     305             : 
     306           0 :         unsigned aa = antialias[0];
     307           0 :         antialias += count;
     308           0 :         if (aa) {
     309           0 :             if (aa == 255) {
     310           0 :                 if (ditherInt) {
     311           0 :                     sk_dither_memset16(device, srcColor,
     312           0 :                                        ditherColor, count);
     313             :                 } else {
     314           0 :                     sk_memset16(device, srcColor, count);
     315             :                 }
     316             :             } else {
     317             :                 // TODO: respect fDoDither
     318           0 :                 unsigned scale5 = SkAlpha255To256(aa) >> 3;
     319           0 :                 uint32_t src32 = srcExpanded * scale5;
     320           0 :                 scale5 = 32 - scale5; // now we can use it on the device
     321           0 :                 int n = count;
     322           0 :                 do {
     323           0 :                     uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
     324           0 :                     *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
     325             :                 } while (--n != 0);
     326           0 :                 goto DONE;
     327             :             }
     328             :         }
     329           0 :         device += count;
     330             : 
     331             :     DONE:
     332             :         // if we have no dithering, this will always fail
     333           0 :         if (count & ditherInt) {
     334           0 :             SkTSwap(ditherColor, srcColor);
     335             :         }
     336           0 :     }
     337             : }
     338             : 
     339             : #define solid_8_pixels(mask, dst, color)    \
     340             :     do {                                    \
     341             :         if (mask & 0x80) dst[0] = color;    \
     342             :         if (mask & 0x40) dst[1] = color;    \
     343             :         if (mask & 0x20) dst[2] = color;    \
     344             :         if (mask & 0x10) dst[3] = color;    \
     345             :         if (mask & 0x08) dst[4] = color;    \
     346             :         if (mask & 0x04) dst[5] = color;    \
     347             :         if (mask & 0x02) dst[6] = color;    \
     348             :         if (mask & 0x01) dst[7] = color;    \
     349             :     } while (0)
     350             : 
     351             : #define SK_BLITBWMASK_NAME                  SkRGB16_BlitBW
     352             : #define SK_BLITBWMASK_ARGS                  , uint16_t color
     353             : #define SK_BLITBWMASK_BLIT8(mask, dst)      solid_8_pixels(mask, dst, color)
     354             : #define SK_BLITBWMASK_GETADDR               writable_addr16
     355             : #define SK_BLITBWMASK_DEVTYPE               uint16_t
     356             : #include "SkBlitBWMaskTemplate.h"
     357             : 
     358           0 : static U16CPU blend_compact(uint32_t src32, uint32_t dst32, unsigned scale5) {
     359           0 :     return SkCompact_rgb_16(dst32 + ((src32 - dst32) * scale5 >> 5));
     360             : }
     361             : 
     362           0 : void SkRGB16_Opaque_Blitter::blitMask(const SkMask& mask,
     363             :                                       const SkIRect& clip) {
     364           0 :     if (mask.fFormat == SkMask::kBW_Format) {
     365           0 :         SkRGB16_BlitBW(fDevice, mask, clip, fColor16);
     366           0 :         return;
     367             :     }
     368             : 
     369           0 :     uint16_t* SK_RESTRICT device = fDevice.writable_addr16(clip.fLeft, clip.fTop);
     370           0 :     const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
     371           0 :     int width = clip.width();
     372           0 :     int height = clip.height();
     373           0 :     size_t      deviceRB = fDevice.rowBytes() - (width << 1);
     374           0 :     unsigned    maskRB = mask.fRowBytes - width;
     375           0 :     uint32_t    expanded32 = fExpandedRaw16;
     376             : 
     377             : #if defined(SK_ARM_HAS_NEON) && defined(SK_CPU_LENDIAN)
     378             : #define    UNROLL    8
     379             :     do {
     380             :         int w = width;
     381             :         if (w >= UNROLL) {
     382             :             uint32x4_t color, dev_lo, dev_hi;
     383             :             uint32x4_t wn1, wn2, tmp;
     384             :             uint32x4_t vmask_g16, vmask_ng16;
     385             :             uint16x8_t valpha, vdev;
     386             :             uint16x4_t odev_lo, odev_hi, valpha_lo, valpha_hi;
     387             : 
     388             :             // prepare constants
     389             :             vmask_g16 = vdupq_n_u32(SK_G16_MASK_IN_PLACE);
     390             :             vmask_ng16 = vdupq_n_u32(~SK_G16_MASK_IN_PLACE);
     391             :             color = vdupq_n_u32(expanded32);
     392             : 
     393             :             do {
     394             :                 // alpha is 8x8, widen and split to get a pair of 16x4
     395             :                 valpha = vaddw_u8(vdupq_n_u16(1), vld1_u8(alpha));
     396             :                 valpha = vshrq_n_u16(valpha, 3);
     397             :                 valpha_lo = vget_low_u16(valpha);
     398             :                 valpha_hi = vget_high_u16(valpha);
     399             : 
     400             :                 // load pixels
     401             :                 vdev = vld1q_u16(device);
     402             :                 dev_lo = vmovl_u16(vget_low_u16(vdev));
     403             :                 dev_hi = vmovl_u16(vget_high_u16(vdev));
     404             : 
     405             :                 // unpack them in 32 bits
     406             :                 dev_lo = (dev_lo & vmask_ng16) | vshlq_n_u32(dev_lo & vmask_g16, 16);
     407             :                 dev_hi = (dev_hi & vmask_ng16) | vshlq_n_u32(dev_hi & vmask_g16, 16);
     408             : 
     409             :                 // blend with color
     410             :                 tmp = (color - dev_lo) * vmovl_u16(valpha_lo);
     411             :                 tmp = vshrq_n_u32(tmp, 5);
     412             :                 dev_lo += tmp;
     413             : 
     414             :                 tmp = vmulq_u32(color - dev_hi, vmovl_u16(valpha_hi));
     415             :                 tmp = vshrq_n_u32(tmp, 5);
     416             :                 dev_hi += tmp;
     417             : 
     418             :                 // re-compact
     419             :                 wn1 = dev_lo & vmask_ng16;
     420             :                 wn2 = vshrq_n_u32(dev_lo, 16) & vmask_g16;
     421             :                 odev_lo = vmovn_u32(wn1 | wn2);
     422             : 
     423             :                 wn1 = dev_hi & vmask_ng16;
     424             :                 wn2 = vshrq_n_u32(dev_hi, 16) & vmask_g16;
     425             :                 odev_hi = vmovn_u32(wn1 | wn2);
     426             : 
     427             :                 // store
     428             :                 vst1q_u16(device, vcombine_u16(odev_lo, odev_hi));
     429             : 
     430             :                 device += UNROLL;
     431             :                 alpha += UNROLL;
     432             :                 w -= UNROLL;
     433             :             } while (w >= UNROLL);
     434             :         }
     435             : 
     436             :         // residuals
     437             :         while (w > 0) {
     438             :             *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
     439             :                                     SkAlpha255To256(*alpha++) >> 3);
     440             :             device += 1;
     441             :             --w;
     442             :         }
     443             :         device = (uint16_t*)((char*)device + deviceRB);
     444             :         alpha += maskRB;
     445             :     } while (--height != 0);
     446             : #undef    UNROLL
     447             : #else   // non-neon code
     448           0 :     do {
     449           0 :         int w = width;
     450           0 :         do {
     451           0 :             *device = blend_compact(expanded32, SkExpand_rgb_16(*device),
     452           0 :                                     SkAlpha255To256(*alpha++) >> 3);
     453           0 :             device += 1;
     454             :         } while (--w != 0);
     455           0 :         device = (uint16_t*)((char*)device + deviceRB);
     456           0 :         alpha += maskRB;
     457             :     } while (--height != 0);
     458             : #endif
     459             : }
     460             : 
     461           0 : void SkRGB16_Opaque_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
     462           0 :     uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
     463           0 :     size_t    deviceRB = fDevice.rowBytes();
     464             : 
     465             :     // TODO: respect fDoDither
     466           0 :     unsigned scale5 = SkAlpha255To256(alpha) >> 3;
     467           0 :     uint32_t src32 =  fExpandedRaw16 * scale5;
     468           0 :     scale5 = 32 - scale5;
     469             : #if defined(SK_ARM_HAS_NEON) && defined(SK_CPU_LENDIAN)
     470             :     SkRGB16BlitterBlitV_neon(device, height, deviceRB, scale5, src32);
     471             : #else
     472           0 :     do {
     473           0 :         uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
     474           0 :         *device = SkCompact_rgb_16((src32 + dst32) >> 5);
     475           0 :         device = (uint16_t*)((char*)device + deviceRB);
     476             :     } while (--height != 0);
     477             : #endif
     478           0 : }
     479             : 
     480           0 : void SkRGB16_Opaque_Blitter::blitRect(int x, int y, int width, int height) {
     481           0 :     SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
     482           0 :     uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
     483           0 :     size_t      deviceRB = fDevice.rowBytes();
     484           0 :     uint16_t    color16 = fColor16;
     485             : 
     486           0 :     if (fDoDither) {
     487           0 :         uint16_t ditherColor = fRawDither16;
     488           0 :         if ((x ^ y) & 1) {
     489           0 :             SkTSwap(ditherColor, color16);
     490             :         }
     491           0 :         while (--height >= 0) {
     492           0 :             sk_dither_memset16(device, color16, ditherColor, width);
     493           0 :             SkTSwap(ditherColor, color16);
     494           0 :             device = (uint16_t*)((char*)device + deviceRB);
     495             :         }
     496             :     } else {  // no dither
     497           0 :         while (--height >= 0) {
     498           0 :             sk_memset16(device, color16, width);
     499           0 :             device = (uint16_t*)((char*)device + deviceRB);
     500             :         }
     501             :     }
     502           0 : }
     503             : 
     504             : ///////////////////////////////////////////////////////////////////////////////
     505             : 
     506           0 : SkRGB16_Blitter::SkRGB16_Blitter(const SkPixmap& device, const SkPaint& paint)
     507           0 :     : INHERITED(device) {
     508           0 :     SkColor color = paint.getColor();
     509             : 
     510           0 :     fSrcColor32 = SkPreMultiplyColor(color);
     511           0 :     fScale = SkAlpha255To256(SkColorGetA(color));
     512             : 
     513           0 :     int r = SkColorGetR(color);
     514           0 :     int g = SkColorGetG(color);
     515           0 :     int b = SkColorGetB(color);
     516             : 
     517           0 :     fRawColor16 = fRawDither16 = SkPack888ToRGB16(r, g, b);
     518             :     // if we're dithered, use fRawDither16 to hold that.
     519           0 :     if ((fDoDither = paint.isDither()) != false) {
     520           0 :         fRawDither16 = SkDitherPack888ToRGB16(r, g, b);
     521             :     }
     522             : 
     523           0 :     fExpandedRaw16 = SkExpand_rgb_16(fRawColor16);
     524             : 
     525           0 :     fColor16 = SkPackRGB16( SkAlphaMul(r, fScale) >> (8 - SK_R16_BITS),
     526           0 :                             SkAlphaMul(g, fScale) >> (8 - SK_G16_BITS),
     527           0 :                             SkAlphaMul(b, fScale) >> (8 - SK_B16_BITS));
     528             : 
     529             :     // compute SkBlitRow::Procs
     530           0 :     unsigned flags = 0;
     531             : 
     532           0 :     if (SkGetPackedA32(fSrcColor32) < 0xFF) {
     533           0 :         flags |= SkBlitRow::kSrcPixelAlpha_Flag;
     534             :     }
     535             : 
     536           0 :     if (fDoDither) {
     537           0 :         flags |= SkBlitRow::kDither_Flag;
     538             :     }
     539             : 
     540           0 :     fColorProc16 = SkBlitRow::ColorFactory16(flags);
     541           0 : }
     542             : 
     543           0 : const SkPixmap* SkRGB16_Blitter::justAnOpaqueColor(uint32_t* value) {
     544           0 :     if (!fDoDither && 256 == fScale) {
     545           0 :         *value = fRawColor16;
     546           0 :         return &fDevice;
     547             :     }
     548           0 :     return nullptr;
     549             : }
     550             : 
     551           0 : void SkRGB16_Blitter::blitH(int x, int y, int width) {
     552           0 :     SkASSERT(width > 0);
     553           0 :     SkASSERT(x + width <= fDevice.width());
     554           0 :     uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
     555             : 
     556           0 :     fColorProc16(device, fSrcColor32, width, x, y);
     557           0 : }
     558             : 
     559           0 : void SkRGB16_Blitter::blitAntiH(int x, int y,
     560             :                                 const SkAlpha* SK_RESTRICT antialias,
     561             :                                 const int16_t* SK_RESTRICT runs) {
     562           0 :     uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
     563           0 :     uint32_t    srcExpanded = fExpandedRaw16;
     564           0 :     unsigned    scale = fScale;
     565             : 
     566             :     // TODO: respect fDoDither
     567             :     for (;;) {
     568           0 :         int count = runs[0];
     569           0 :         SkASSERT(count >= 0);
     570           0 :         if (count <= 0) {
     571           0 :             return;
     572             :         }
     573           0 :         runs += count;
     574             : 
     575           0 :         unsigned aa = antialias[0];
     576           0 :         antialias += count;
     577           0 :         if (aa) {
     578           0 :             unsigned scale5 = SkAlpha255To256(aa) * scale >> (8 + 3);
     579           0 :             uint32_t src32 =  srcExpanded * scale5;
     580           0 :             scale5 = 32 - scale5;
     581           0 :             do {
     582           0 :                 uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
     583           0 :                 *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
     584             :             } while (--count != 0);
     585           0 :             continue;
     586             :         }
     587           0 :         device += count;
     588           0 :     }
     589             : }
     590             : 
     591           0 : static inline void blend_8_pixels(U8CPU bw, uint16_t dst[], unsigned dst_scale,
     592             :                                   U16CPU srcColor) {
     593           0 :     if (bw & 0x80) dst[0] = srcColor + SkAlphaMulRGB16(dst[0], dst_scale);
     594           0 :     if (bw & 0x40) dst[1] = srcColor + SkAlphaMulRGB16(dst[1], dst_scale);
     595           0 :     if (bw & 0x20) dst[2] = srcColor + SkAlphaMulRGB16(dst[2], dst_scale);
     596           0 :     if (bw & 0x10) dst[3] = srcColor + SkAlphaMulRGB16(dst[3], dst_scale);
     597           0 :     if (bw & 0x08) dst[4] = srcColor + SkAlphaMulRGB16(dst[4], dst_scale);
     598           0 :     if (bw & 0x04) dst[5] = srcColor + SkAlphaMulRGB16(dst[5], dst_scale);
     599           0 :     if (bw & 0x02) dst[6] = srcColor + SkAlphaMulRGB16(dst[6], dst_scale);
     600           0 :     if (bw & 0x01) dst[7] = srcColor + SkAlphaMulRGB16(dst[7], dst_scale);
     601           0 : }
     602             : 
     603             : #define SK_BLITBWMASK_NAME                  SkRGB16_BlendBW
     604             : #define SK_BLITBWMASK_ARGS                  , unsigned dst_scale, U16CPU src_color
     605             : #define SK_BLITBWMASK_BLIT8(mask, dst)      blend_8_pixels(mask, dst, dst_scale, src_color)
     606             : #define SK_BLITBWMASK_GETADDR               writable_addr16
     607             : #define SK_BLITBWMASK_DEVTYPE               uint16_t
     608             : #include "SkBlitBWMaskTemplate.h"
     609             : 
     610           0 : void SkRGB16_Blitter::blitMask(const SkMask& mask,
     611             :                                const SkIRect& clip) {
     612           0 :     if (mask.fFormat == SkMask::kBW_Format) {
     613           0 :         SkRGB16_BlendBW(fDevice, mask, clip, 256 - fScale, fColor16);
     614           0 :         return;
     615             :     }
     616             : 
     617           0 :     uint16_t* SK_RESTRICT device = fDevice.writable_addr16(clip.fLeft, clip.fTop);
     618           0 :     const uint8_t* SK_RESTRICT alpha = mask.getAddr8(clip.fLeft, clip.fTop);
     619           0 :     int width = clip.width();
     620           0 :     int height = clip.height();
     621           0 :     size_t      deviceRB = fDevice.rowBytes() - (width << 1);
     622           0 :     unsigned    maskRB = mask.fRowBytes - width;
     623           0 :     uint32_t    color32 = fExpandedRaw16;
     624             : 
     625           0 :     unsigned scale256 = fScale;
     626           0 :     do {
     627           0 :         int w = width;
     628           0 :         do {
     629           0 :             unsigned aa = *alpha++;
     630           0 :             unsigned scale = SkAlpha255To256(aa) * scale256 >> (8 + 3);
     631           0 :             uint32_t src32 = color32 * scale;
     632           0 :             uint32_t dst32 = SkExpand_rgb_16(*device) * (32 - scale);
     633           0 :             *device++ = SkCompact_rgb_16((src32 + dst32) >> 5);
     634             :         } while (--w != 0);
     635           0 :         device = (uint16_t*)((char*)device + deviceRB);
     636           0 :         alpha += maskRB;
     637             :     } while (--height != 0);
     638             : }
     639             : 
     640           0 : void SkRGB16_Blitter::blitV(int x, int y, int height, SkAlpha alpha) {
     641           0 :     uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
     642           0 :     size_t    deviceRB = fDevice.rowBytes();
     643             : 
     644             :     // TODO: respect fDoDither
     645           0 :     unsigned scale5 = SkAlpha255To256(alpha) * fScale >> (8 + 3);
     646           0 :     uint32_t src32 =  fExpandedRaw16 * scale5;
     647           0 :     scale5 = 32 - scale5;
     648             : #if defined(SK_ARM_HAS_NEON) && defined(SK_CPU_LENDIAN)
     649             :     SkRGB16BlitterBlitV_neon(device, height, deviceRB, scale5, src32);
     650             : #else
     651           0 :     do {
     652           0 :         uint32_t dst32 = SkExpand_rgb_16(*device) * scale5;
     653           0 :         *device = SkCompact_rgb_16((src32 + dst32) >> 5);
     654           0 :         device = (uint16_t*)((char*)device + deviceRB);
     655             :     } while (--height != 0);
     656             : #endif
     657           0 : }
     658             : 
     659           0 : void SkRGB16_Blitter::blitRect(int x, int y, int width, int height) {
     660           0 :     SkASSERT(x + width <= fDevice.width() && y + height <= fDevice.height());
     661           0 :     uint16_t* SK_RESTRICT device = fDevice.writable_addr16(x, y);
     662           0 :     size_t    deviceRB = fDevice.rowBytes();
     663             : 
     664           0 :     while (--height >= 0) {
     665           0 :         fColorProc16(device, fSrcColor32, width, x, y);
     666           0 :         device = (uint16_t*)((char*)device + deviceRB);
     667             :     }
     668           0 : }
     669             : 
     670             : ///////////////////////////////////////////////////////////////////////////////
     671             : 
     672           0 : SkRGB16_Shader_Blitter::SkRGB16_Shader_Blitter(const SkPixmap& device,
     673             :                                                const SkPaint& paint,
     674           0 :                                                SkShader::Context* shaderContext)
     675           0 :     : INHERITED(device, paint, shaderContext)
     676             : {
     677           0 :     SkASSERT(paint.isSrcOver());
     678             : 
     679           0 :     fBuffer = (SkPMColor*)sk_malloc_throw(device.width() * sizeof(SkPMColor));
     680             : 
     681             :     // compute SkBlitRow::Procs
     682           0 :     unsigned flags = 0;
     683             : 
     684           0 :     uint32_t shaderFlags = fShaderFlags;
     685             :     // shaders take care of global alpha, so we never set it in SkBlitRow
     686           0 :     if (!(shaderFlags & SkShader::kOpaqueAlpha_Flag)) {
     687           0 :         flags |= SkBlitRow::kSrcPixelAlpha_Flag;
     688             :     }
     689           0 :     if (paint.isDither()) {
     690           0 :         flags |= SkBlitRow::kDither_Flag;
     691             :     }
     692             :     // used when we know our global alpha is 0xFF
     693           0 :     fOpaqueProc = SkBlitRow::Factory16(flags);
     694             :     // used when we know our global alpha is < 0xFF
     695           0 :     fAlphaProc  = SkBlitRow::Factory16(flags | SkBlitRow::kGlobalAlpha_Flag);
     696           0 : }
     697             : 
     698           0 : SkRGB16_Shader_Blitter::~SkRGB16_Shader_Blitter() {
     699           0 :     sk_free(fBuffer);
     700           0 : }
     701             : 
     702           0 : void SkRGB16_Shader_Blitter::blitH(int x, int y, int width) {
     703           0 :     SkASSERT(x + width <= fDevice.width());
     704             : 
     705           0 :     fShaderContext->shadeSpan(x, y, fBuffer, width);
     706             :     // shaders take care of global alpha, so we pass 0xFF (should be ignored)
     707           0 :     fOpaqueProc(fDevice.writable_addr16(x, y), fBuffer, width, 0xFF, x, y);
     708           0 : }
     709             : 
     710           0 : void SkRGB16_Shader_Blitter::blitRect(int x, int y, int width, int height) {
     711           0 :     SkShader::Context* shaderContext = fShaderContext;
     712           0 :     SkBlitRow::Proc16  proc = fOpaqueProc;
     713           0 :     SkPMColor*         buffer = fBuffer;
     714           0 :     uint16_t*          dst = fDevice.writable_addr16(x, y);
     715           0 :     size_t             dstRB = fDevice.rowBytes();
     716             : 
     717           0 :     if (fShaderFlags & SkShader::kConstInY32_Flag) {
     718           0 :         shaderContext->shadeSpan(x, y, buffer, width);
     719           0 :         do {
     720           0 :             proc(dst, buffer, width, 0xFF, x, y);
     721           0 :             y += 1;
     722           0 :             dst = (uint16_t*)((char*)dst + dstRB);
     723             :         } while (--height);
     724             :     } else {
     725           0 :         do {
     726           0 :             shaderContext->shadeSpan(x, y, buffer, width);
     727           0 :             proc(dst, buffer, width, 0xFF, x, y);
     728           0 :             y += 1;
     729           0 :             dst = (uint16_t*)((char*)dst + dstRB);
     730             :         } while (--height);
     731             :     }
     732           0 : }
     733             : 
     734           0 : static inline int count_nonzero_span(const int16_t runs[], const SkAlpha aa[]) {
     735           0 :     int count = 0;
     736             :     for (;;) {
     737           0 :         int n = *runs;
     738           0 :         if (n == 0 || *aa == 0) {
     739             :             break;
     740             :         }
     741           0 :         runs += n;
     742           0 :         aa += n;
     743           0 :         count += n;
     744           0 :     }
     745           0 :     return count;
     746             : }
     747             : 
     748           0 : void SkRGB16_Shader_Blitter::blitAntiH(int x, int y,
     749             :                                        const SkAlpha* SK_RESTRICT antialias,
     750             :                                        const int16_t* SK_RESTRICT runs) {
     751           0 :     SkShader::Context*     shaderContext = fShaderContext;
     752           0 :     SkPMColor* SK_RESTRICT span = fBuffer;
     753           0 :     uint16_t* SK_RESTRICT  device = fDevice.writable_addr16(x, y);
     754             : 
     755             :     for (;;) {
     756           0 :         int count = *runs;
     757           0 :         if (count <= 0) {
     758           0 :             break;
     759             :         }
     760           0 :         int aa = *antialias;
     761           0 :         if (0 == aa) {
     762           0 :             device += count;
     763           0 :             runs += count;
     764           0 :             antialias += count;
     765           0 :             x += count;
     766           0 :             continue;
     767             :         }
     768             : 
     769           0 :         int nonZeroCount = count + count_nonzero_span(runs + count, antialias + count);
     770             : 
     771           0 :         SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
     772           0 :         shaderContext->shadeSpan(x, y, span, nonZeroCount);
     773             : 
     774           0 :         SkPMColor* localSpan = span;
     775             :         for (;;) {
     776           0 :             SkBlitRow::Proc16 proc = (aa == 0xFF) ? fOpaqueProc : fAlphaProc;
     777           0 :             proc(device, localSpan, count, aa, x, y);
     778             : 
     779           0 :             x += count;
     780           0 :             device += count;
     781           0 :             runs += count;
     782           0 :             antialias += count;
     783           0 :             nonZeroCount -= count;
     784           0 :             if (nonZeroCount == 0) {
     785           0 :                 break;
     786             :             }
     787           0 :             localSpan += count;
     788           0 :             SkASSERT(nonZeroCount > 0);
     789           0 :             count = *runs;
     790           0 :             SkASSERT(count > 0);
     791           0 :             aa = *antialias;
     792           0 :         }
     793           0 :     }
     794           0 : }
     795             : 
     796             : ///////////////////////////////////////////////////////////////////////
     797             : 
     798           0 : SkRGB16_Shader_Xfermode_Blitter::SkRGB16_Shader_Xfermode_Blitter(
     799             :                                 const SkPixmap& device, const SkPaint& paint,
     800           0 :                                 SkShader::Context* shaderContext)
     801           0 :     : INHERITED(device, paint, shaderContext)
     802             : {
     803           0 :     fXfermode = SkXfermode::Peek(paint.getBlendMode());
     804           0 :     SkASSERT(fXfermode);
     805             : 
     806           0 :     int width = device.width();
     807           0 :     fBuffer = (SkPMColor*)sk_malloc_throw((width + (SkAlign4(width) >> 2)) * sizeof(SkPMColor));
     808           0 :     fAAExpand = (uint8_t*)(fBuffer + width);
     809           0 : }
     810             : 
     811           0 : SkRGB16_Shader_Xfermode_Blitter::~SkRGB16_Shader_Xfermode_Blitter() {
     812           0 :     sk_free(fBuffer);
     813           0 : }
     814             : 
     815           0 : void SkRGB16_Shader_Xfermode_Blitter::blitH(int x, int y, int width) {
     816           0 :     SkASSERT(x + width <= fDevice.width());
     817             : 
     818           0 :     uint16_t*   device = fDevice.writable_addr16(x, y);
     819           0 :     SkPMColor*  span = fBuffer;
     820             : 
     821           0 :     fShaderContext->shadeSpan(x, y, span, width);
     822           0 :     fXfermode->xfer16(device, span, width, nullptr);
     823           0 : }
     824             : 
     825           0 : void SkRGB16_Shader_Xfermode_Blitter::blitAntiH(int x, int y,
     826             :                                 const SkAlpha* SK_RESTRICT antialias,
     827             :                                 const int16_t* SK_RESTRICT runs) {
     828           0 :     SkShader::Context*     shaderContext = fShaderContext;
     829           0 :     SkXfermode*            mode = fXfermode;
     830           0 :     SkPMColor* SK_RESTRICT span = fBuffer;
     831           0 :     uint8_t* SK_RESTRICT   aaExpand = fAAExpand;
     832           0 :     uint16_t* SK_RESTRICT  device = fDevice.writable_addr16(x, y);
     833             : 
     834             :     for (;;) {
     835           0 :         int count = *runs;
     836           0 :         if (count <= 0) {
     837           0 :             break;
     838             :         }
     839           0 :         int aa = *antialias;
     840           0 :         if (0 == aa) {
     841           0 :             device += count;
     842           0 :             runs += count;
     843           0 :             antialias += count;
     844           0 :             x += count;
     845           0 :             continue;
     846             :         }
     847             : 
     848           0 :         int nonZeroCount = count + count_nonzero_span(runs + count,
     849           0 :                                                       antialias + count);
     850             : 
     851           0 :         SkASSERT(nonZeroCount <= fDevice.width()); // don't overrun fBuffer
     852           0 :         shaderContext->shadeSpan(x, y, span, nonZeroCount);
     853             : 
     854           0 :         x += nonZeroCount;
     855           0 :         SkPMColor* localSpan = span;
     856             :         for (;;) {
     857           0 :             if (aa == 0xFF) {
     858           0 :                 mode->xfer16(device, localSpan, count, nullptr);
     859             :             } else {
     860           0 :                 SkASSERT(aa);
     861           0 :                 memset(aaExpand, aa, count);
     862           0 :                 mode->xfer16(device, localSpan, count, aaExpand);
     863             :             }
     864           0 :             device += count;
     865           0 :             runs += count;
     866           0 :             antialias += count;
     867           0 :             nonZeroCount -= count;
     868           0 :             if (nonZeroCount == 0) {
     869           0 :                 break;
     870             :             }
     871           0 :             localSpan += count;
     872           0 :             SkASSERT(nonZeroCount > 0);
     873           0 :             count = *runs;
     874           0 :             SkASSERT(count > 0);
     875           0 :             aa = *antialias;
     876             :         }
     877           0 :     }
     878           0 : }
     879             : 
     880             : ///////////////////////////////////////////////////////////////////////////////
     881             : 
     882           0 : SkBlitter* SkBlitter_ChooseD565(const SkPixmap& device, const SkPaint& paint,
     883             :         SkShader::Context* shaderContext,
     884             :         SkArenaAlloc* alloc) {
     885           0 :     SkASSERT(alloc != nullptr);
     886             : 
     887             :     SkBlitter* blitter;
     888           0 :     SkShader* shader = paint.getShader();
     889           0 :     bool is_srcover = paint.isSrcOver();
     890             : 
     891             :     // we require a shader if there is an xfermode, handled by our caller
     892           0 :     SkASSERT(is_srcover || shader);
     893             : 
     894           0 :     if (shader) {
     895           0 :         SkASSERT(shaderContext != nullptr);
     896           0 :         if (!is_srcover) {
     897             :             blitter = alloc->make<SkRGB16_Shader_Xfermode_Blitter>(device, paint,
     898           0 :                                                                           shaderContext);
     899             :         } else {
     900           0 :             blitter = alloc->make<SkRGB16_Shader_Blitter>(device, paint, shaderContext);
     901             :         }
     902             :     } else {
     903             :         // no shader, no xfermode, (and we always ignore colorfilter)
     904           0 :         SkColor color = paint.getColor();
     905           0 :         if (0 == SkColorGetA(color)) {
     906           0 :             blitter = alloc->make<SkNullBlitter>();
     907             : #ifdef USE_BLACK_BLITTER
     908           0 :         } else if (SK_ColorBLACK == color) {
     909           0 :             blitter = alloc->make<SkRGB16_Black_Blitter>(device, paint);
     910             : #endif
     911           0 :         } else if (0xFF == SkColorGetA(color)) {
     912           0 :             blitter = alloc->make<SkRGB16_Opaque_Blitter>(device, paint);
     913             :         } else {
     914           0 :             blitter = alloc->make<SkRGB16_Blitter>(device, paint);
     915             :         }
     916             :     }
     917             : 
     918           0 :     return blitter;
     919             : }

Generated by: LCOV version 1.13