From 1adcf8859cc9414591038e440e3f22382c8e4aa0 Mon Sep 17 00:00:00 2001 From: "reed@google.com" Date: Thu, 13 Dec 2012 21:39:56 +0000 Subject: Goal: ensure we always balance lock/unlock pixels calls. A big caller of lockPixels is setContext in the bitmapshader. This change replaces beginSession/endSession with adding endContext(), and adds debugging code to ensure that 1. setContext calls are never nested 2. endContext is always called after each setContext call. Review URL: https://codereview.appspot.com/6937046 git-svn-id: http://skia.googlecode.com/svn/trunk@6798 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/core/SkBlitter.cpp | 52 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 31 insertions(+), 21 deletions(-) (limited to 'src/core/SkBlitter.cpp') diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp index 85331c23c3..1234f43c3f 100644 --- a/src/core/SkBlitter.cpp +++ b/src/core/SkBlitter.cpp @@ -572,16 +572,30 @@ public: void setMask(const SkMask* mask) { fMask = mask; } virtual bool setContext(const SkBitmap& device, const SkPaint& paint, - const SkMatrix& matrix) { + const SkMatrix& matrix) SK_OVERRIDE { + if (!this->INHERITED::setContext(device, paint, matrix)) { + return false; + } if (fProxy) { - return fProxy->setContext(device, paint, matrix); + if (!fProxy->setContext(device, paint, matrix)) { + // must keep our set/end context calls balanced + this->INHERITED::endContext(); + return false; + } } else { fPMColor = SkPreMultiplyColor(paint.getColor()); - return this->INHERITED::setContext(device, paint, matrix); } + return true; + } + + virtual void endContext() SK_OVERRIDE { + if (fProxy) { + fProxy->endContext(); + } + this->INHERITED::endContext(); } - virtual void shadeSpan(int x, int y, SkPMColor span[], int count) { + virtual void shadeSpan(int x, int y, SkPMColor span[], int count) SK_OVERRIDE { if (fProxy) { fProxy->shadeSpan(x, y, span, count); } @@ -645,20 +659,6 @@ public: } } - virtual void beginSession() { - this->INHERITED::beginSession(); - if (fProxy) { - fProxy->beginSession(); - } - } - - virtual void endSession() { - if (fProxy) { - fProxy->endSession(); - } - this->INHERITED::endSession(); - } - SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(Sk3DShader) protected: @@ -907,8 +907,17 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device, // if there is one, the shader will take care of it. } + /* + * We need to have balanced calls to the shader: + * setContext + * endContext + * We make the first call here, in case it fails we can abort the draw. + * The endContext() call is made by the blitter (assuming setContext did + * not fail) in its destructor. + */ if (shader && !shader->setContext(device, *paint, matrix)) { - return SkNEW(SkNullBlitter); + SK_PLACEMENT_NEW(blitter, SkNullBlitter, storage, storageSize); + return blitter; } switch (device.getConfig()) { @@ -978,14 +987,15 @@ SkShaderBlitter::SkShaderBlitter(const SkBitmap& device, const SkPaint& paint) : INHERITED(device) { fShader = paint.getShader(); SkASSERT(fShader); + SkASSERT(fShader->setContextHasBeenCalled()); fShader->ref(); - fShader->beginSession(); fShaderFlags = fShader->getFlags(); } SkShaderBlitter::~SkShaderBlitter() { - fShader->endSession(); + SkASSERT(fShader->setContextHasBeenCalled()); + fShader->endContext(); fShader->unref(); } -- cgit v1.2.3