| 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 |