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