1 /*
2  * Copyright 2016 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 "SkSpriteBlitter.h"
9 #include "SkSpanProcs.h"
10 #include "SkTemplates.h"
11 #include "SkXfermode.h"
12 
13 class Sprite_4f : public SkSpriteBlitter {
14 public:
Sprite_4f(const SkPixmap & src,const SkPaint & paint)15     Sprite_4f(const SkPixmap& src, const SkPaint& paint) : INHERITED(src) {
16         fXfer = paint.getXfermode();
17         fLoader = SkLoadSpanProc_Choose(src.info());
18         fFilter = SkFilterSpanProc_Choose(paint);
19         fBuffer.reset(src.width());
20     }
21 
22 protected:
23     SkXfermode*             fXfer;
24     SkLoadSpanProc          fLoader;
25     SkFilterSpanProc        fFilter;
26     SkAutoTMalloc<SkPM4f>   fBuffer;
27 
28 private:
29     typedef SkSpriteBlitter INHERITED;
30 };
31 
32 ///////////////////////////////////////////////////////////////////////////////////////////////////
33 
34 class Sprite_F16 : public Sprite_4f {
35 public:
Sprite_F16(const SkPixmap & src,const SkPaint & paint)36     Sprite_F16(const SkPixmap& src, const SkPaint& paint) : INHERITED(src, paint) {
37         uint32_t flags = SkXfermode::kDstIsFloat16_D64Flag;
38         if (src.isOpaque()) {
39             flags |= SkXfermode::kSrcIsOpaque_D64Flag;
40         }
41         fWriter = SkXfermode::GetD64Proc(fXfer, flags);
42     }
43 
blitRect(int x,int y,int width,int height)44     void blitRect(int x, int y, int width, int height) override {
45         SkASSERT(width > 0 && height > 0);
46         uint64_t* SK_RESTRICT dst = fDst.writable_addr64(x, y);
47         size_t dstRB = fDst.rowBytes();
48 
49         for (int bottom = y + height; y < bottom; ++y) {
50             fLoader(fSource, x - fLeft, y - fTop, fBuffer, width);
51             fFilter(*fPaint, fBuffer, width);
52             fWriter(fXfer, dst, fBuffer, width, nullptr);
53             dst = (uint64_t* SK_RESTRICT)((char*)dst + dstRB);
54         }
55     }
56 
57 private:
58     SkXfermode::D64Proc fWriter;
59 
60     typedef Sprite_4f INHERITED;
61 };
62 
63 
ChooseF16(const SkPixmap & source,const SkPaint & paint,SkTBlitterAllocator * allocator)64 SkSpriteBlitter* SkSpriteBlitter::ChooseF16(const SkPixmap& source, const SkPaint& paint,
65                                             SkTBlitterAllocator* allocator) {
66     SkASSERT(allocator != nullptr);
67 
68     if (paint.getMaskFilter() != nullptr) {
69         return nullptr;
70     }
71 
72     switch (source.colorType()) {
73         case kN32_SkColorType:
74         case kRGBA_F16_SkColorType:
75             return allocator->createT<Sprite_F16>(source, paint);
76         default:
77             return nullptr;
78     }
79 }
80 
81 ///////////////////////////////////////////////////////////////////////////////////////////////////
82 
83 class Sprite_sRGB : public Sprite_4f {
84 public:
Sprite_sRGB(const SkPixmap & src,const SkPaint & paint)85     Sprite_sRGB(const SkPixmap& src, const SkPaint& paint) : INHERITED(src, paint) {
86         uint32_t flags = SkXfermode::kDstIsSRGB_D32Flag;
87         if (src.isOpaque()) {
88             flags |= SkXfermode::kSrcIsOpaque_D32Flag;
89         }
90         fWriter = SkXfermode::GetD32Proc(fXfer, flags);
91     }
92 
blitRect(int x,int y,int width,int height)93     void blitRect(int x, int y, int width, int height) override {
94         SkASSERT(width > 0 && height > 0);
95         uint32_t* SK_RESTRICT dst = fDst.writable_addr32(x, y);
96         size_t dstRB = fDst.rowBytes();
97 
98         for (int bottom = y + height; y < bottom; ++y) {
99             fLoader(fSource, x - fLeft, y - fTop, fBuffer, width);
100             fFilter(*fPaint, fBuffer, width);
101             fWriter(fXfer, dst, fBuffer, width, nullptr);
102             dst = (uint32_t* SK_RESTRICT)((char*)dst + dstRB);
103         }
104     }
105 
106 protected:
107     SkXfermode::D32Proc fWriter;
108 
109 private:
110     typedef Sprite_4f INHERITED;
111 };
112 
113 
ChooseS32(const SkPixmap & source,const SkPaint & paint,SkTBlitterAllocator * allocator)114 SkSpriteBlitter* SkSpriteBlitter::ChooseS32(const SkPixmap& source, const SkPaint& paint,
115                                             SkTBlitterAllocator* allocator) {
116     SkASSERT(allocator != nullptr);
117 
118     if (paint.getMaskFilter() != nullptr) {
119         return nullptr;
120     }
121 
122     switch (source.colorType()) {
123         case kN32_SkColorType:
124         case kRGBA_F16_SkColorType:
125             return allocator->createT<Sprite_sRGB>(source, paint);
126         default:
127             return nullptr;
128     }
129 }
130