aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-14 13:13:55 +0000
committerGravatar reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-12-14 13:13:55 +0000
commitea033606a06d05d2d42aa7118409fee798e53167 (patch)
treeeaa1a57aaf7655745d0806d5b5290f86486f0970 /src/core
parent8234e5448bf672d332880e75dd6d8ca82c1cd521 (diff)
add per-draw checks for lockcounts
Review URL: https://codereview.appspot.com/6943056 git-svn-id: http://skia.googlecode.com/svn/trunk@6815 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkBlitter.cpp4
-rw-r--r--src/core/SkBlitter.h8
-rw-r--r--src/core/SkCanvas.cpp74
-rw-r--r--src/core/SkDraw.cpp7
4 files changed, 93 insertions, 0 deletions
diff --git a/src/core/SkBlitter.cpp b/src/core/SkBlitter.cpp
index 1589d51d3a..efe9d11a9d 100644
--- a/src/core/SkBlitter.cpp
+++ b/src/core/SkBlitter.cpp
@@ -22,6 +22,8 @@
SkBlitter::~SkBlitter() {}
+bool SkBlitter::isNullBlitter() const { return false; }
+
const SkBitmap* SkBlitter::justAnOpaqueColor(uint32_t* value) {
return NULL;
}
@@ -236,6 +238,8 @@ const SkBitmap* SkNullBlitter::justAnOpaqueColor(uint32_t* value) {
return NULL;
}
+bool SkNullBlitter::isNullBlitter() const { return true; }
+
///////////////////////////////////////////////////////////////////////////////
static int compute_anti_width(const int16_t runs[]) {
diff --git a/src/core/SkBlitter.h b/src/core/SkBlitter.h
index ce74a28d0e..0a075f89ad 100644
--- a/src/core/SkBlitter.h
+++ b/src/core/SkBlitter.h
@@ -51,6 +51,13 @@ public:
*/
virtual const SkBitmap* justAnOpaqueColor(uint32_t* value);
+ /**
+ * Special method just to identify the null blitter, which is returned
+ * from Choose() if the request cannot be fulfilled. Default impl
+ * returns false.
+ */
+ virtual bool isNullBlitter() const;
+
///@name non-virtual helpers
void blitMaskRegion(const SkMask& mask, const SkRegion& clip);
void blitRectRegion(const SkIRect& rect, const SkRegion& clip);
@@ -92,6 +99,7 @@ public:
virtual void blitRect(int x, int y, int width, int height) SK_OVERRIDE;
virtual void blitMask(const SkMask&, const SkIRect& clip) SK_OVERRIDE;
virtual const SkBitmap* justAnOpaqueColor(uint32_t* value) SK_OVERRIDE;
+ virtual bool isNullBlitter() const SK_OVERRIDE;
};
/** Wraps another (real) blitter, and ensures that the real blitter is only
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 7d25c2848c..096b42dc79 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -55,6 +55,52 @@ SK_DEFINE_INST_COUNT(SkDrawFilter)
#define dec_canvas()
#endif
+#ifdef SK_DEBUG
+#include "SkPixelRef.h"
+
+class AutoCheckLockCountBalance {
+public:
+ AutoCheckLockCountBalance(const SkBitmap& bm) : fPixelRef(bm.pixelRef()) {
+ fLockCount = fPixelRef ? fPixelRef->getLockCount() : 0;
+ }
+ ~AutoCheckLockCountBalance() {
+ const int count = fPixelRef ? fPixelRef->getLockCount() : 0;
+ SkASSERT(count == fLockCount);
+ }
+
+private:
+ const SkPixelRef* fPixelRef;
+ int fLockCount;
+};
+
+class AutoCheckNoSetContext {
+public:
+ AutoCheckNoSetContext(const SkPaint& paint) : fPaint(paint) {
+ this->assertNoSetContext(fPaint);
+ }
+ ~AutoCheckNoSetContext() {
+ this->assertNoSetContext(fPaint);
+ }
+
+private:
+ const SkPaint& fPaint;
+
+ void assertNoSetContext(const SkPaint& paint) {
+ SkShader* s = paint.getShader();
+ if (s) {
+ SkASSERT(!s->setContextHasBeenCalled());
+ }
+ }
+};
+
+#define CHECK_LOCKCOUNT_BALANCE(bitmap) AutoCheckLockCountBalance clcb(bitmap)
+#define CHECK_SHADER_NOSETCONTEXT(paint) AutoCheckNoSetContext cshsc(paint)
+
+#else
+ #define CHECK_LOCKCOUNT_BALANCE(bitmap)
+ #define CHECK_SHADER_NOSETCONTEXT(paint)
+#endif
+
typedef SkTLazy<SkPaint> SkLazyPaint;
void SkCanvas::predrawNotify() {
@@ -963,6 +1009,7 @@ void SkCanvas::internalDrawDevice(SkDevice* srcDev, int x, int y,
void SkCanvas::drawSprite(const SkBitmap& bitmap, int x, int y,
const SkPaint* paint) {
SkDEBUGCODE(bitmap.validate();)
+ CHECK_LOCKCOUNT_BALANCE(bitmap);
if (reject_bitmap(bitmap)) {
return;
@@ -1422,6 +1469,8 @@ void SkCanvas::drawPaint(const SkPaint& paint) {
}
void SkCanvas::internalDrawPaint(const SkPaint& paint) {
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
LOOPER_BEGIN(paint, SkDrawFilter::kPaint_Type)
while (iter.next()) {
@@ -1437,6 +1486,8 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
return;
}
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
if (paint.canComputeFastBounds()) {
SkRect r;
// special-case 2 points (common for drawing a single line)
@@ -1463,6 +1514,8 @@ void SkCanvas::drawPoints(PointMode mode, size_t count, const SkPoint pts[],
}
void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
if (paint.canComputeFastBounds()) {
SkRect storage;
if (this->quickReject(paint.computeFastBounds(r, &storage))) {
@@ -1480,6 +1533,8 @@ void SkCanvas::drawRect(const SkRect& r, const SkPaint& paint) {
}
void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
if (paint.canComputeFastBounds()) {
SkRect storage;
if (this->quickReject(paint.computeFastBounds(oval, &storage))) {
@@ -1494,6 +1549,8 @@ void SkCanvas::drawOval(const SkRect& oval, const SkPaint& paint) {
}
void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
if (paint.canComputeFastBounds()) {
SkRect storage;
if (this->quickReject(paint.computeFastBounds(rrect.getBounds(), &storage))) {
@@ -1514,6 +1571,8 @@ void SkCanvas::drawRRect(const SkRRect& rrect, const SkPaint& paint) {
void SkCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
if (!path.isFinite()) {
return;
}
@@ -1571,6 +1630,8 @@ void SkCanvas::internalDrawBitmapRect(const SkBitmap& bitmap, const SkRect* src,
return;
}
+ CHECK_LOCKCOUNT_BALANCE(bitmap);
+
if (NULL == paint || paint->canComputeFastBounds()) {
SkRect storage;
const SkRect* bounds = &dst;
@@ -1611,6 +1672,7 @@ void SkCanvas::drawBitmapMatrix(const SkBitmap& bitmap, const SkMatrix& matrix,
void SkCanvas::commonDrawBitmap(const SkBitmap& bitmap, const SkIRect* srcRect,
const SkMatrix& matrix, const SkPaint& paint) {
SkDEBUGCODE(bitmap.validate();)
+ CHECK_LOCKCOUNT_BALANCE(bitmap);
LOOPER_BEGIN(paint, SkDrawFilter::kBitmap_Type)
@@ -1790,6 +1852,8 @@ void SkCanvas::DrawTextDecorations(const SkDraw& draw, const SkPaint& paint,
void SkCanvas::drawText(const void* text, size_t byteLength,
SkScalar x, SkScalar y, const SkPaint& paint) {
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
@@ -1804,6 +1868,8 @@ void SkCanvas::drawText(const void* text, size_t byteLength,
void SkCanvas::drawPosText(const void* text, size_t byteLength,
const SkPoint pos[], const SkPaint& paint) {
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
@@ -1818,6 +1884,8 @@ void SkCanvas::drawPosText(const void* text, size_t byteLength,
void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
const SkScalar xpos[], SkScalar constY,
const SkPaint& paint) {
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
@@ -1832,6 +1900,8 @@ void SkCanvas::drawPosTextH(const void* text, size_t byteLength,
void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint) {
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
@@ -1846,6 +1916,8 @@ void SkCanvas::drawTextOnPath(const void* text, size_t byteLength,
void SkCanvas::drawPosTextOnPath(const void* text, size_t byteLength,
const SkPoint pos[], const SkPaint& paint,
const SkPath& path, const SkMatrix* matrix) {
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
LOOPER_BEGIN(paint, SkDrawFilter::kText_Type)
while (iter.next()) {
@@ -1862,6 +1934,8 @@ void SkCanvas::drawVertices(VertexMode vmode, int vertexCount,
const SkColor colors[], SkXfermode* xmode,
const uint16_t indices[], int indexCount,
const SkPaint& paint) {
+ CHECK_SHADER_NOSETCONTEXT(paint);
+
LOOPER_BEGIN(paint, SkDrawFilter::kPath_Type)
while (iter.next()) {
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index 2f748d9930..b6eb6825d6 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -2424,6 +2424,13 @@ 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.
+ if (blitter->isNullBlitter()) {
+ return;
+ }
+
// setup our state and function pointer for iterating triangles
VertState state(count, indices, indexCount);
VertState::Proc vertProc = state.chooseProc(vmode);