aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-13 22:16:30 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-13 22:16:30 +0000
commita641f3f18e5319773989812a888f3fad49e4f2ad (patch)
treed090e4695e6f7970db27bdac351b3dfcccb02ec2 /src/core
parentcbcef708914f3b5e9bb63ad3d87261378026e29b (diff)
reland 6798 w/ fix for bitmap-as-mask pixel-locking
git-svn-id: http://skia.googlecode.com/svn/trunk@6806 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkBitmapProcShader.cpp18
-rw-r--r--src/core/SkBitmapProcShader.h3
-rw-r--r--src/core/SkBlitter.cpp52
-rw-r--r--src/core/SkColorFilter.cpp28
-rw-r--r--src/core/SkComposeShader.cpp38
-rw-r--r--src/core/SkDraw.cpp24
-rw-r--r--src/core/SkFilterShader.h14
-rw-r--r--src/core/SkShader.cpp24
8 files changed, 103 insertions, 98 deletions
diff --git a/src/core/SkBitmapProcShader.cpp b/src/core/SkBitmapProcShader.cpp
index df2caee2ca..3e4116651d 100644
--- a/src/core/SkBitmapProcShader.cpp
+++ b/src/core/SkBitmapProcShader.cpp
@@ -41,18 +41,6 @@ SkBitmapProcShader::SkBitmapProcShader(SkFlattenableReadBuffer& buffer)
fFlags = 0; // computed in setContext
}
-void SkBitmapProcShader::beginSession() {
- this->INHERITED::beginSession();
-
- fRawBitmap.lockPixels();
-}
-
-void SkBitmapProcShader::endSession() {
- fRawBitmap.unlockPixels();
-
- this->INHERITED::endSession();
-}
-
SkShader::BitmapType SkBitmapProcShader::asABitmap(SkBitmap* texture,
SkMatrix* texM,
TileMode xy[]) const {
@@ -102,6 +90,7 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
}
if (!fState.chooseProcs(this->getTotalInverse(), paint)) {
+ fState.fOrigBitmap.unlockPixels();
return false;
}
@@ -149,6 +138,11 @@ bool SkBitmapProcShader::setContext(const SkBitmap& device,
return true;
}
+void SkBitmapProcShader::endContext() {
+ fState.fOrigBitmap.unlockPixels();
+ this->INHERITED::endContext();
+}
+
#define BUF_MAX 128
#define TEST_BUFFER_OVERRITEx
diff --git a/src/core/SkBitmapProcShader.h b/src/core/SkBitmapProcShader.h
index 23e099250b..cb791d0c92 100644
--- a/src/core/SkBitmapProcShader.h
+++ b/src/core/SkBitmapProcShader.h
@@ -20,12 +20,11 @@ public:
// overrides from SkShader
virtual bool isOpaque() const SK_OVERRIDE;
virtual bool setContext(const SkBitmap&, const SkPaint&, const SkMatrix&);
+ virtual void endContext();
virtual uint32_t getFlags() { return fFlags; }
virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
virtual ShadeProc asAShadeProc(void** ctx) SK_OVERRIDE;
virtual void shadeSpan16(int x, int y, uint16_t dstC[], int count);
- virtual void beginSession();
- virtual void endSession();
virtual BitmapType asABitmap(SkBitmap*, SkMatrix*, TileMode*) const;
static bool CanDo(const SkBitmap&, TileMode tx, TileMode ty);
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();
}
diff --git a/src/core/SkColorFilter.cpp b/src/core/SkColorFilter.cpp
index 6d9f4ba3a6..156fb8fb96 100644
--- a/src/core/SkColorFilter.cpp
+++ b/src/core/SkColorFilter.cpp
@@ -62,16 +62,6 @@ SkFilterShader::~SkFilterShader() {
fShader->unref();
}
-void SkFilterShader::beginSession() {
- this->INHERITED::beginSession();
- fShader->beginSession();
-}
-
-void SkFilterShader::endSession() {
- fShader->endSession();
- this->INHERITED::endSession();
-}
-
void SkFilterShader::flatten(SkFlattenableWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
buffer.writeFlattenable(fShader);
@@ -96,8 +86,22 @@ uint32_t SkFilterShader::getFlags() {
bool SkFilterShader::setContext(const SkBitmap& device,
const SkPaint& paint,
const SkMatrix& matrix) {
- return this->INHERITED::setContext(device, paint, matrix) &&
- fShader->setContext(device, paint, matrix);
+ // we need to keep the setContext/endContext calls balanced. If we return
+ // false, our endContext() will not be called.
+
+ if (!this->INHERITED::setContext(device, paint, matrix)) {
+ return false;
+ }
+ if (!fShader->setContext(device, paint, matrix)) {
+ this->INHERITED::endContext();
+ return false;
+ }
+ return true;
+}
+
+void SkFilterShader::endContext() {
+ fShader->endContext();
+ this->INHERITED::endContext();
}
void SkFilterShader::shadeSpan(int x, int y, SkPMColor result[], int count) {
diff --git a/src/core/SkComposeShader.cpp b/src/core/SkComposeShader.cpp
index 2fe7a20980..92ffaf7d91 100644
--- a/src/core/SkComposeShader.cpp
+++ b/src/core/SkComposeShader.cpp
@@ -43,18 +43,6 @@ SkComposeShader::~SkComposeShader() {
fShaderA->unref();
}
-void SkComposeShader::beginSession() {
- this->INHERITED::beginSession();
- fShaderA->beginSession();
- fShaderB->beginSession();
-}
-
-void SkComposeShader::endSession() {
- fShaderA->endSession();
- fShaderB->endSession();
- this->INHERITED::endSession();
-}
-
class SkAutoAlphaRestore {
public:
SkAutoAlphaRestore(SkPaint* paint, uint8_t newAlpha) {
@@ -81,7 +69,10 @@ void SkComposeShader::flatten(SkFlattenableWriteBuffer& buffer) const {
/* We call setContext on our two worker shaders. However, we
always let them see opaque alpha, and if the paint really
is translucent, then we apply that after the fact.
-*/
+
+ We need to keep the calls to setContext/endContext balanced, since if we
+ return false, our endContext() will not be called.
+ */
bool SkComposeShader::setContext(const SkBitmap& device,
const SkPaint& paint,
const SkMatrix& matrix) {
@@ -98,8 +89,25 @@ bool SkComposeShader::setContext(const SkBitmap& device,
SkAutoAlphaRestore restore(const_cast<SkPaint*>(&paint), 0xFF);
- return fShaderA->setContext(device, paint, tmpM) &&
- fShaderB->setContext(device, paint, tmpM);
+ bool setContextA = fShaderA->setContext(device, paint, tmpM);
+ bool setContextB = fShaderB->setContext(device, paint, tmpM);
+ if (!setContextA || !setContextB) {
+ if (setContextB) {
+ fShaderB->endContext();
+ }
+ else if (setContextA) {
+ fShaderA->endContext();
+ }
+ this->INHERITED::endContext();
+ return false;
+ }
+ return true;
+}
+
+void SkComposeShader::endContext() {
+ fShaderB->endContext();
+ fShaderA->endContext();
+ this->INHERITED::endContext();
}
// larger is better (fewer times we have to loop), but we shouldn't
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 3035afe1ef..2f748d9930 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -1098,6 +1098,11 @@ void SkDraw::drawBitmapAsMask(const SkBitmap& bitmap,
int ix = SkScalarRound(fMatrix->getTranslateX());
int iy = SkScalarRound(fMatrix->getTranslateY());
+ SkAutoLockPixels alp(bitmap);
+ if (!bitmap.readyToDraw()) {
+ return;
+ }
+
SkMask mask;
mask.fBounds.set(ix, iy, ix + bitmap.width(), iy + bitmap.height());
mask.fFormat = SkMask::kA8_Format;
@@ -1228,13 +1233,6 @@ void SkDraw::drawBitmap(const SkBitmap& bitmap, const SkMatrix& prematrix,
}
}
- // only lock the pixels if we passed the clip and bounder tests
- SkAutoLockPixels alp(bitmap);
- // after the lock, check if we are valid
- if (!bitmap.readyToDraw()) {
- return;
- }
-
if (bitmap.getConfig() != SkBitmap::kA8_Config &&
just_translate(matrix, bitmap)) {
int ix = SkScalarRound(matrix.getTranslateX());
@@ -2279,7 +2277,7 @@ public:
bool setup(const SkPoint pts[], const SkColor colors[], int, int, int);
- virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count);
+ virtual void shadeSpan(int x, int y, SkPMColor dstC[], int count) SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkTriColorShader)
@@ -2406,7 +2404,7 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
if (NULL != colors) {
if (NULL == textures) {
// just colors (no texture)
- p.setShader(&triShader);
+ shader = p.setShader(&triShader);
} else {
// colors * texture
SkASSERT(shader);
@@ -2421,6 +2419,7 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
if (releaseMode) {
xmode->unref();
}
+ shader = compose;
}
}
@@ -2436,18 +2435,13 @@ void SkDraw::drawVertices(SkCanvas::VertexMode vmode, int count,
savedLocalM = shader->getLocalMatrix();
}
- if (NULL != colors) {
- if (!triShader.setContext(*fBitmap, p, *fMatrix)) {
- colors = NULL;
- }
- }
-
while (vertProc(&state)) {
if (NULL != textures) {
if (texture_to_matrix(state, vertices, textures, &tempM)) {
tempM.postConcat(savedLocalM);
shader->setLocalMatrix(tempM);
// need to recal setContext since we changed the local matrix
+ shader->endContext();
if (!shader->setContext(*fBitmap, p, *fMatrix)) {
continue;
}
diff --git a/src/core/SkFilterShader.h b/src/core/SkFilterShader.h
index f637584718..ded3125adc 100644
--- a/src/core/SkFilterShader.h
+++ b/src/core/SkFilterShader.h
@@ -17,14 +17,12 @@ public:
SkFilterShader(SkShader* shader, SkColorFilter* filter);
virtual ~SkFilterShader();
- // override
- virtual uint32_t getFlags();
- virtual bool setContext(const SkBitmap& device, const SkPaint& paint,
- const SkMatrix& matrix);
- virtual void shadeSpan(int x, int y, SkPMColor result[], int count);
- virtual void shadeSpan16(int x, int y, uint16_t result[], int count);
- virtual void beginSession();
- virtual void endSession();
+ virtual uint32_t getFlags() SK_OVERRIDE;
+ virtual bool setContext(const SkBitmap&, const SkPaint&,
+ const SkMatrix&) SK_OVERRIDE;
+ virtual void endContext() SK_OVERRIDE;
+ virtual void shadeSpan(int x, int y, SkPMColor[], int count) SK_OVERRIDE;
+ virtual void shadeSpan16(int x, int y, uint16_t[], int count) SK_OVERRIDE;
SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(SkFilterShader)
diff --git a/src/core/SkShader.cpp b/src/core/SkShader.cpp
index 2b20e3d31f..706c1b79f5 100644
--- a/src/core/SkShader.cpp
+++ b/src/core/SkShader.cpp
@@ -17,7 +17,7 @@ SK_DEFINE_INST_COUNT(SkShader)
SkShader::SkShader() {
fLocalMatrix.reset();
- SkDEBUGCODE(fInSession = false;)
+ SkDEBUGCODE(fInSetContext = false;)
}
SkShader::SkShader(SkFlattenableReadBuffer& buffer)
@@ -28,21 +28,11 @@ SkShader::SkShader(SkFlattenableReadBuffer& buffer)
fLocalMatrix.reset();
}
- SkDEBUGCODE(fInSession = false;)
+ SkDEBUGCODE(fInSetContext = false;)
}
SkShader::~SkShader() {
- SkASSERT(!fInSession);
-}
-
-void SkShader::beginSession() {
- SkASSERT(!fInSession);
- SkDEBUGCODE(fInSession = true;)
-}
-
-void SkShader::endSession() {
- SkASSERT(fInSession);
- SkDEBUGCODE(fInSession = false;)
+ SkASSERT(!fInSetContext);
}
void SkShader::flatten(SkFlattenableWriteBuffer& buffer) const {
@@ -57,6 +47,8 @@ void SkShader::flatten(SkFlattenableWriteBuffer& buffer) const {
bool SkShader::setContext(const SkBitmap& device,
const SkPaint& paint,
const SkMatrix& matrix) {
+ SkASSERT(!this->setContextHasBeenCalled());
+
const SkMatrix* m = &matrix;
SkMatrix total;
@@ -68,11 +60,17 @@ bool SkShader::setContext(const SkBitmap& device,
}
if (m->invert(&fTotalInverse)) {
fTotalInverseClass = (uint8_t)ComputeMatrixClass(fTotalInverse);
+ SkDEBUGCODE(fInSetContext = true;)
return true;
}
return false;
}
+void SkShader::endContext() {
+ SkASSERT(fInSetContext);
+ SkDEBUGCODE(fInSetContext = false;)
+}
+
SkShader::ShadeProc SkShader::asAShadeProc(void** ctx) {
return NULL;
}