Chromium Code Reviews| Index: src/core/SkDraw.cpp |
| diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp |
| index 946bf753101627bb77a3f9f46eb6793222eb2b9c..ad2b49b0906402229711b890bb22f5716754cf70 100644 |
| --- a/src/core/SkDraw.cpp |
| +++ b/src/core/SkDraw.cpp |
| @@ -2354,9 +2354,26 @@ class SkTriColorShader : public SkShader { |
| public: |
| SkTriColorShader() {} |
| - bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); |
| + virtual SkShader::Context* createContext( |
| + const SkBitmap&, const SkPaint&, const SkMatrix&, void*) const SK_OVERRIDE; |
| + virtual size_t contextSize() const SK_OVERRIDE; |
| - virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; |
| + class TriColorShaderContext : public SkShader::Context { |
| + public: |
| + TriColorShaderContext(const SkTriColorShader& shader, const SkBitmap& device, |
| + const SkPaint& paint, const SkMatrix& matrix); |
| + virtual ~TriColorShaderContext(); |
| + |
| + bool setup(const SkPoint pts[], const SkColor colors[], int, int, int); |
| + |
| + virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE; |
| + |
| + private: |
| + SkMatrix fDstToUnit; |
| + SkPMColor fColors[3]; |
| + |
| + typedef SkShader::Context INHERITED; |
| + }; |
| SK_TO_STRING_OVERRIDE() |
| SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader) |
| @@ -2364,15 +2381,20 @@ public: |
| protected: |
| SkTriColorShader(SkReadBuffer& buffer) : SkShader(buffer) {} |
| -private: |
| - SkMatrix fDstToUnit; |
| - SkPMColor fColors[3]; |
| - |
| typedef SkShader INHERITED; |
| }; |
| -bool SkTriColorShader::setup(const SkPoint pts[], const SkColor colors[], |
| - int index0, int index1, int index2) { |
| +SkShader::Context* SkTriColorShader::createContext(const SkBitmap& device, const SkPaint& paint, |
| + const SkMatrix& matrix, void* storage) const { |
| + if (!this->validContext(device, paint, matrix)) { |
| + return NULL; |
| + } |
| + |
| + return SkNEW_PLACEMENT_ARGS(storage, TriColorShaderContext, (*this, device, paint, matrix)); |
| +} |
| + |
| +bool SkTriColorShader::TriColorShaderContext::setup(const SkPoint pts[], const SkColor colors[], |
| + int index0, int index1, int index2) { |
| fColors[0] = SkPreMultiplyColor(colors[index0]); |
| fColors[1] = SkPreMultiplyColor(colors[index1]); |
| @@ -2407,7 +2429,18 @@ static int ScalarTo256(SkScalar v) { |
| return SkAlpha255To256(scale); |
| } |
| -void SkTriColorShader::shadeSpan(int x, int y, SkPMColor dstC[], int count) { |
| + |
| +SkTriColorShader::TriColorShaderContext::TriColorShaderContext( |
| + const SkTriColorShader& shader, const SkBitmap& device, |
| + const SkPaint& paint, const SkMatrix& matrix) |
| + : INHERITED(shader, device, paint, matrix) {} |
| + |
| +SkTriColorShader::TriColorShaderContext::~TriColorShaderContext() {} |
| + |
| +size_t SkTriColorShader::contextSize() const { |
| + return sizeof(TriColorShaderContext); |
| +} |
| +void SkTriColorShader::TriColorShaderContext::shadeSpan(int x, int y, SkPMColor dstC[], int count) { |
| SkPoint src; |
| for (int i = 0; i < count; i++) { |
| @@ -2492,6 +2525,7 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, |
| } |
| // setup the custom shader (if needed) |
| + SkAutoTUnref<SkComposeShader> composeShader; |
|
scroggo
2014/04/03 15:35:54
This should be in SkDEBUGCODE, since we only need
Dominik Grewe
2014/04/04 10:59:41
I also use it below though (outside of the assert)
|
| if (NULL != colors) { |
| if (NULL == textures) { |
| // just colors (no texture) |
| @@ -2504,9 +2538,8 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, |
| xmode = SkXfermode::Create(SkXfermode::kModulate_Mode); |
| releaseMode = true; |
| } |
| - SkShader* compose = SkNEW_ARGS(SkComposeShader, |
| - (&triShader, shader, xmode)); |
| - p.setShader(compose)->unref(); |
| + composeShader.reset(SkNEW_ARGS(SkComposeShader, (&triShader, shader, xmode))); |
| + p.setShader(composeShader); |
| if (releaseMode) { |
| xmode->unref(); |
| } |
| @@ -2514,9 +2547,7 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, |
| } |
| SkAutoBlitterChoose blitter(*fBitmap, *fMatrix, p); |
| - // important that we abort early, as below we may manipulate the shader |
| - // and that is only valid if the shader returned true from setContext. |
| - // If it returned false, then our blitter will be the NullBlitter. |
| + // Abort early if we failed to create a shader context. |
| if (blitter->isNullBlitter()) { |
| return; |
| } |
| @@ -2532,30 +2563,38 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, |
| savedLocalM = shader->getLocalMatrix(); |
| } |
| - // setContext has already been called and verified to return true |
| - // by the constructor of SkAutoBlitterChoose |
| - bool prevContextSuccess = true; |
| while (vertProc(&state)) { |
| if (NULL != textures) { |
| if (texture_to_matrix(state, vertices, textures, &tempM)) { |
| tempM.postConcat(savedLocalM); |
| shader->setLocalMatrix(tempM); |
| - // Need to recall setContext since we changed the local matrix. |
| - // However, we also need to balance the calls this with a |
| - // call to endContext which requires tracking the result of |
| - // the previous call to setContext. |
| - if (prevContextSuccess) { |
| - shader->endContext(); |
| - } |
| - prevContextSuccess = shader->setContext(*fBitmap, p, *fMatrix); |
| - if (!prevContextSuccess) { |
| + if (!blitter->resetShaderContext(*fBitmap, p, *fMatrix)) { |
| continue; |
| } |
| } |
| } |
| if (NULL != colors) { |
| - if (!triShader.setup(vertices, colors, |
| - state.f0, state.f1, state.f2)) { |
| + // Find the context for triShader. |
| + SkTriColorShader::TriColorShaderContext* triColorShaderContext; |
| + |
| + SkShader::Context* shaderContext = blitter->getShaderContext(); |
| + SkASSERT(shaderContext); |
| + if (p.getShader() == &triShader) { |
| + triColorShaderContext = |
| + static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContext); |
| + } else { |
| + // The shader is a compose shader and triShader is its first shader. |
| + SkASSERT(p.getShader() == composeShader); |
| + SkASSERT(composeShader->getShaderA() == &triShader); |
| + SkComposeShader::ComposeShaderContext* composeShaderContext = |
| + static_cast<SkComposeShader::ComposeShaderContext*>(shaderContext); |
| + SkShader::Context* shaderContextA = composeShaderContext->getShaderContextA(); |
| + triColorShaderContext = |
| + static_cast<SkTriColorShader::TriColorShaderContext*>(shaderContextA); |
| + } |
| + |
| + if (!triColorShaderContext->setup(vertices, colors, |
| + state.f0, state.f1, state.f2)) { |
| continue; |
| } |
| } |
| @@ -2570,13 +2609,6 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count, |
| if (NULL != shader) { |
| shader->setLocalMatrix(savedLocalM); |
| } |
| - |
| - // If the final call to setContext fails we must make it suceed so that the |
| - // call to endContext in the destructor for SkAutoBlitterChoose is balanced. |
| - if (!prevContextSuccess) { |
| - prevContextSuccess = shader->setContext(*fBitmap, paint, SkMatrix::I()); |
| - SkASSERT(prevContextSuccess); |
| - } |
| } else { |
| // no colors[] and no texture |
| HairProc hairProc = ChooseHairProc(paint.isAntiAlias()); |