OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "SkBlitter.h" | 8 #include "SkBlitter.h" |
9 #include "SkBlendModePriv.h" | 9 #include "SkBlendModePriv.h" |
10 #include "SkColor.h" | 10 #include "SkColor.h" |
11 #include "SkColorFilter.h" | 11 #include "SkColorFilter.h" |
12 #include "SkOpts.h" | 12 #include "SkOpts.h" |
13 #include "SkPM4f.h" | 13 #include "SkPM4f.h" |
14 #include "SkRasterPipeline.h" | 14 #include "SkRasterPipeline.h" |
15 #include "SkShader.h" | 15 #include "SkShader.h" |
16 #include "SkXfermode.h" | 16 #include "SkXfermode.h" |
17 | 17 |
18 | 18 |
19 class SkRasterPipelineBlitter : public SkBlitter { | 19 class SkRasterPipelineBlitter : public SkBlitter { |
20 public: | 20 public: |
21 static SkBlitter* Create(const SkPixmap&, const SkPaint&, SkTBlitterAllocato
r*); | 21 static SkBlitter* Create(const SkPixmap&, const SkPaint&, SkTBlitterAllocato
r*); |
22 | 22 |
23 SkRasterPipelineBlitter(SkPixmap dst, SkBlendMode blend, SkPM4f paintColor) | 23 SkRasterPipelineBlitter(SkPixmap dst, |
| 24 SkRasterPipeline shader, |
| 25 SkBlendMode blend, |
| 26 SkPM4f paintColor) |
24 : fDst(dst) | 27 : fDst(dst) |
| 28 , fShader(shader) |
25 , fBlend(blend) | 29 , fBlend(blend) |
26 , fPaintColor(paintColor) | 30 , fPaintColor(paintColor) |
27 {} | 31 {} |
28 | 32 |
29 void blitH (int x, int y, int w) override; | 33 void blitH (int x, int y, int w) override; |
30 void blitAntiH(int x, int y, const SkAlpha[], const int16_t[]) override; | 34 void blitAntiH(int x, int y, const SkAlpha[], const int16_t[]) override; |
31 void blitMask (const SkMask&, const SkIRect& clip) override; | 35 void blitMask (const SkMask&, const SkIRect& clip) override; |
32 | 36 |
33 // TODO: The default implementations of the other blits look fine, | 37 // TODO: The default implementations of the other blits look fine, |
34 // but some of them like blitV could probably benefit from custom | 38 // but some of them like blitV could probably benefit from custom |
35 // blits using something like a SkRasterPipeline::runFew() method. | 39 // blits using something like a SkRasterPipeline::runFew() method. |
36 | 40 |
37 private: | 41 private: |
38 void append_load_d(SkRasterPipeline*) const; | 42 void append_load_d(SkRasterPipeline*) const; |
39 void append_store (SkRasterPipeline*) const; | 43 void append_store (SkRasterPipeline*) const; |
40 void append_blend (SkRasterPipeline*) const; | 44 void append_blend (SkRasterPipeline*) const; |
41 void maybe_clamp (SkRasterPipeline*) const; | 45 void maybe_clamp (SkRasterPipeline*) const; |
42 | 46 |
43 SkPixmap fDst; | 47 SkPixmap fDst; |
| 48 SkRasterPipeline fShader; |
44 SkBlendMode fBlend; | 49 SkBlendMode fBlend; |
45 SkPM4f fPaintColor; | 50 SkPM4f fPaintColor; |
46 SkRasterPipeline fShader; | |
47 | 51 |
48 // These functions are compiled lazily when first used. | 52 // These functions are compiled lazily when first used. |
49 std::function<void(size_t, size_t)> fBlitH = nullptr, | 53 std::function<void(size_t, size_t)> fBlitH = nullptr, |
50 fBlitAntiH = nullptr, | 54 fBlitAntiH = nullptr, |
51 fBlitMaskA8 = nullptr, | 55 fBlitMaskA8 = nullptr, |
52 fBlitMaskLCD16 = nullptr; | 56 fBlitMaskLCD16 = nullptr; |
53 | 57 |
54 // These values are pointed to by the compiled blit functions | 58 // These values are pointed to by the compiled blit functions |
55 // above, which allows us to adjust them from call to call. | 59 // above, which allows us to adjust them from call to call. |
56 void* fDstPtr = nullptr; | 60 void* fDstPtr = nullptr; |
(...skipping 16 matching lines...) Expand all Loading... |
73 case kRGB_565_SkColorType: return true; | 77 case kRGB_565_SkColorType: return true; |
74 default: return false; | 78 default: return false; |
75 } | 79 } |
76 } | 80 } |
77 | 81 |
78 template <typename Effect> | 82 template <typename Effect> |
79 static bool append_effect_stages(const Effect* effect, SkRasterPipeline* pipelin
e) { | 83 static bool append_effect_stages(const Effect* effect, SkRasterPipeline* pipelin
e) { |
80 return !effect || effect->appendStages(pipeline); | 84 return !effect || effect->appendStages(pipeline); |
81 } | 85 } |
82 | 86 |
83 static SkPM4f paint_color(const SkPixmap& dst, const SkPaint& paint) { | |
84 auto paintColor = paint.getColor(); | |
85 SkColor4f color; | |
86 if (dst.info().colorSpace()) { | |
87 color = SkColor4f::FromColor(paintColor); | |
88 // TODO: transform from sRGB to dst gamut. | |
89 } else { | |
90 swizzle_rb(SkNx_cast<float>(Sk4b::Load(&paintColor)) * (1/255.0f)).store
(&color); | |
91 } | |
92 return color.premul(); | |
93 } | |
94 | 87 |
95 SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, | 88 SkBlitter* SkRasterPipelineBlitter::Create(const SkPixmap& dst, |
96 const SkPaint& paint, | 89 const SkPaint& paint, |
97 SkTBlitterAllocator* alloc) { | 90 SkTBlitterAllocator* alloc) { |
98 auto blitter = alloc->createT<SkRasterPipelineBlitter>(dst, | 91 if (!supported(dst.info())) { |
99 paint.getBlendMode(), | |
100 paint_color(dst, pain
t)); | |
101 SkBlendMode* blend = &blitter->fBlend; | |
102 SkPM4f* paintColor = &blitter->fPaintColor; | |
103 SkRasterPipeline* pipeline = &blitter->fShader; | |
104 | |
105 SkShader* shader = paint.getShader(); | |
106 SkColorFilter* colorFilter = paint.getColorFilter(); | |
107 | |
108 // TODO: all temporary | |
109 if (!supported(dst.info()) || shader || !SkBlendMode_AppendStages(*blend)) { | |
110 alloc->freeLast(); | |
111 return nullptr; | 92 return nullptr; |
112 } | 93 } |
113 | 94 if (paint.getShader()) { |
114 bool is_opaque, is_constant; | 95 return nullptr; // TODO: need to work out how shaders and their context
s work |
115 if (shader) { | 96 } |
116 is_opaque = shader->isOpaque(); | 97 SkBlendMode blend = paint.getBlendMode(); |
117 is_constant = false; // TODO: shader->isConstant() | 98 if (!SkBlendMode_AppendStages(blend)) { |
118 // TODO: append shader stages, of course! | 99 return nullptr; // TODO |
119 } else { | |
120 is_opaque = paintColor->a() == 1.0f; | |
121 is_constant = true; | |
122 pipeline->append(SkRasterPipeline::constant_color, paintColor); | |
123 } | 100 } |
124 | 101 |
125 if (colorFilter) { | 102 uint32_t paintColor = paint.getColor(); |
126 if (!colorFilter->appendStages(pipeline, is_opaque)) { | 103 bool shaderIsOpaque = (paintColor >> 24) == 0xff; |
127 alloc->freeLast(); | 104 |
| 105 SkRasterPipeline shader, colorFilter; |
| 106 if (auto s = paint.getShader()) { |
| 107 shaderIsOpaque = s->isOpaque(); |
| 108 } |
| 109 if (auto cf = paint.getColorFilter()) { |
| 110 if (!cf->appendStages(&colorFilter, shaderIsOpaque)) { |
128 return nullptr; | 111 return nullptr; |
129 } | 112 } |
130 is_opaque = is_opaque && (colorFilter->getFlags() & SkColorFilter::kAlph
aUnchanged_Flag); | 113 shaderIsOpaque = shaderIsOpaque && (cf->getFlags() & SkColorFilter::kAlp
haUnchanged_Flag); |
131 } | 114 } |
132 | 115 |
133 if (is_constant) { | 116 if (shaderIsOpaque && blend == SkBlendMode::kSrcOver) { |
134 pipeline->append(SkRasterPipeline::store_f32, &paintColor); | 117 blend = SkBlendMode::kSrc; |
135 pipeline->compile()(0,1); | |
136 | |
137 *pipeline = SkRasterPipeline(); | |
138 pipeline->append(SkRasterPipeline::constant_color, paintColor); | |
139 | |
140 is_opaque = paintColor->a() == 1.0f; | |
141 } | 118 } |
142 | 119 |
143 if (is_opaque && *blend == SkBlendMode::kSrcOver) { | 120 SkColor4f color; |
144 *blend = SkBlendMode::kSrc; | 121 if (dst.info().colorSpace()) { |
| 122 color = SkColor4f::FromColor(paintColor); |
| 123 } else { |
| 124 swizzle_rb(SkNx_cast<float>(Sk4b::Load(&paintColor)) * (1/255.0f)).store
(&color); |
145 } | 125 } |
146 | 126 |
| 127 auto blitter = alloc->createT<SkRasterPipelineBlitter>(dst, shader, blend, c
olor.premul()); |
| 128 |
| 129 if (!paint.getShader()) { |
| 130 blitter->fShader.append(SkRasterPipeline::constant_color, &blitter->fPai
ntColor); |
| 131 } |
| 132 blitter->fShader.extend(colorFilter); |
| 133 |
147 return blitter; | 134 return blitter; |
148 } | 135 } |
149 | 136 |
150 void SkRasterPipelineBlitter::append_load_d(SkRasterPipeline* p) const { | 137 void SkRasterPipelineBlitter::append_load_d(SkRasterPipeline* p) const { |
151 SkASSERT(supported(fDst.info())); | 138 SkASSERT(supported(fDst.info())); |
152 | 139 |
153 switch (fDst.info().colorType()) { | 140 switch (fDst.info().colorType()) { |
154 case kN32_SkColorType: | 141 case kN32_SkColorType: |
155 if (fDst.info().gammaCloseToSRGB()) { | 142 if (fDst.info().gammaCloseToSRGB()) { |
156 p->append(SkRasterPipeline::load_d_srgb, &fDstPtr); | 143 p->append(SkRasterPipeline::load_d_srgb, &fDstPtr); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
285 case SkMask::kLCD16_Format: | 272 case SkMask::kLCD16_Format: |
286 fMaskPtr = mask.getAddrLCD16(x,y)-x; | 273 fMaskPtr = mask.getAddrLCD16(x,y)-x; |
287 fBlitMaskLCD16(x, clip.width()); | 274 fBlitMaskLCD16(x, clip.width()); |
288 break; | 275 break; |
289 default: | 276 default: |
290 // TODO | 277 // TODO |
291 break; | 278 break; |
292 } | 279 } |
293 } | 280 } |
294 } | 281 } |
OLD | NEW |