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