aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/AAClipBench.cpp91
-rw-r--r--src/gpu/GrClipMaskManager.cpp57
-rw-r--r--src/gpu/GrClipMaskManager.h51
3 files changed, 184 insertions, 15 deletions
diff --git a/bench/AAClipBench.cpp b/bench/AAClipBench.cpp
index 39088c1a78..ea4f6da5ac 100644
--- a/bench/AAClipBench.cpp
+++ b/bench/AAClipBench.cpp
@@ -10,7 +10,84 @@
#include "SkPath.h"
#include "SkRegion.h"
#include "SkString.h"
+#include "SkCanvas.h"
+
+////////////////////////////////////////////////////////////////////////////////
+// This bench tests out AA/BW clipping via canvas' clipPath and clipRect calls
+class AAClipBench : public SkBenchmark {
+ SkString fName;
+ SkPath fClipPath;
+ SkRect fClipRect;
+ SkRect fDrawRect;
+ bool fDoPath;
+ bool fDoAA;
+
+ enum {
+ N = SkBENCHLOOP(200),
+ };
+
+public:
+ AAClipBench(void* param, bool doPath, bool doAA)
+ : INHERITED(param) {
+ fDoPath = doPath;
+ fDoAA = doAA;
+
+ fName.printf("aaclip_%s_%s",
+ doPath ? "path" : "rect",
+ doAA ? "AA" : "BW");
+
+ fClipRect.set(SkFloatToScalar(10.5), SkFloatToScalar(10.5),
+ SkFloatToScalar(50.5), SkFloatToScalar(50.5));
+ fClipPath.addRoundRect(fClipRect, SkIntToScalar(10), SkIntToScalar(10));
+ fDrawRect.set(SkIntToScalar(0), SkIntToScalar(0),
+ SkIntToScalar(100), SkIntToScalar(100));
+
+ SkASSERT(fClipPath.isConvex());
+ }
+
+protected:
+ virtual const char* onGetName() { return fName.c_str(); }
+ virtual void onDraw(SkCanvas* canvas) {
+
+ SkPaint paint;
+ this->setupPaint(&paint);
+
+ for (int i = 0; i < N; ++i) {
+ // jostle the clip regions each time to prevent caching
+ fClipRect.offset((i % 2) == 0 ? SkIntToScalar(10) : SkIntToScalar(-10), 0);
+ fClipPath.reset();
+ fClipPath.addRoundRect(fClipRect,
+ SkIntToScalar(5), SkIntToScalar(5));
+ SkASSERT(fClipPath.isConvex());
+
+ canvas->save();
+#if 1
+ if (fDoPath) {
+ canvas->clipPath(fClipPath, SkRegion::kReplace_Op, fDoAA);
+ } else {
+ canvas->clipRect(fClipRect, SkRegion::kReplace_Op, fDoAA);
+ }
+
+ canvas->drawRect(fDrawRect, paint);
+#else
+ // this path tests out directly draw the clip primitive
+ // use it to comparing just drawing the clip vs. drawing using
+ // the clip
+ if (fDoPath) {
+ canvas->drawPath(fClipPath, paint);
+ } else {
+ canvas->drawRect(fClipRect, paint);
+ }
+#endif
+ canvas->restore();
+ }
+ }
+private:
+ typedef SkBenchmark INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
class AAClipBuilderBench : public SkBenchmark {
SkString fName;
SkPath fPath;
@@ -56,6 +133,7 @@ private:
typedef SkBenchmark INHERITED;
};
+////////////////////////////////////////////////////////////////////////////////
class AAClipRegionBench : public SkBenchmark {
public:
AAClipRegionBench(void* param) : INHERITED(param) {
@@ -88,7 +166,7 @@ private:
typedef SkBenchmark INHERITED;
};
-///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////
static SkBenchmark* Fact0(void* p) { return SkNEW_ARGS(AAClipBuilderBench, (p, false, false)); }
static SkBenchmark* Fact1(void* p) { return SkNEW_ARGS(AAClipBuilderBench, (p, false, true)); }
@@ -102,3 +180,14 @@ static BenchRegistry gReg3(Fact3);
static SkBenchmark* Fact01(void* p) { return SkNEW_ARGS(AAClipRegionBench, (p)); }
static BenchRegistry gReg01(Fact01);
+
+static SkBenchmark* Fact000(void* p) { return SkNEW_ARGS(AAClipBench, (p, false, false)); }
+static SkBenchmark* Fact001(void* p) { return SkNEW_ARGS(AAClipBench, (p, false, true)); }
+static SkBenchmark* Fact002(void* p) { return SkNEW_ARGS(AAClipBench, (p, true, false)); }
+static SkBenchmark* Fact003(void* p) { return SkNEW_ARGS(AAClipBench, (p, true, true)); }
+
+static BenchRegistry gReg000(Fact000);
+static BenchRegistry gReg001(Fact001);
+static BenchRegistry gReg002(Fact002);
+static BenchRegistry gReg003(Fact003);
+
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index f4b0721404..1a892d80dc 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -340,7 +340,6 @@ namespace {
void clear(GrGpu* gpu,
GrTexture* target,
- const GrRect& bounds,
GrColor color) {
GrDrawState* drawState = gpu->drawState();
GrAssert(NULL != drawState);
@@ -350,6 +349,36 @@ void clear(GrGpu* gpu,
gpu->clear(NULL, color);
}
+// get a texture to act as a temporary buffer for AA clip boolean operations
+// TODO: given the expense of createTexture we may want to just cache this too
+void needTemp(GrGpu *gpu, const GrTextureDesc& desc, GrTexture** temp) {
+ if (NULL != *temp) {
+ // we've already allocated the temp texture
+ return;
+ }
+
+ *temp = gpu->createTexture(desc, NULL, 0);
+}
+
+}
+
+void GrClipMaskManager::getAccum(GrGpu* gpu,
+ const GrTextureDesc& desc,
+ GrTexture** accum) {
+ GrAssert(NULL == *accum);
+
+ // since we are getting an accumulator we know our cache is shot. See
+ // if we can reuse the texture stored in the cache
+ if (fAACache.getLastMaskWidth() >= desc.fWidth &&
+ fAACache.getLastMaskHeight() >= desc.fHeight) {
+ // we can just reuse the existing texture
+ *accum = fAACache.detachLastMask();
+ fAACache.reset();
+ } else {
+ *accum = gpu->createTexture(desc, NULL, 0);
+ }
+
+ GrAssert(1 == (*accum)->getRefCnt());
}
////////////////////////////////////////////////////////////////////////////////
@@ -403,7 +432,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
GrAssert(SkScalarIsInt(bounds.width()));
GrAssert(SkScalarIsInt(bounds.height()));
- GrTextureDesc desc = {
+ const GrTextureDesc desc = {
kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit,
SkScalarCeilToInt(bounds.width()),
SkScalarCeilToInt(bounds.height()),
@@ -414,12 +443,12 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
GrRect newRTBounds;
newRTBounds.setLTRB(0, 0, bounds.width(), bounds.height());
- GrTexture* accum = gpu->createTexture(desc, NULL, 0);
- GrTexture* temp = gpu->createTexture(desc, NULL, 0);
- if (NULL == accum || NULL == temp) {
+ GrTexture* accum = NULL, *temp = NULL;
+
+ getAccum(gpu, desc, &accum);
+ if (NULL == accum) {
fClipMaskInAlpha = false;
SkSafeUnref(accum);
- SkSafeUnref(temp);
return false;
}
@@ -437,7 +466,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
m.setTranslate(-bounds.fLeft, -bounds.fTop);
- drawState->preConcatViewMatrix(m);
+ drawState->setViewMatrix(m);
}
bool clearToInside;
@@ -447,7 +476,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
&clearToInside,
&startOp);
- clear(gpu, accum, newRTBounds, clearToInside ? 0xffffffff : 0x00000000);
+ clear(gpu, accum, clearToInside ? 0xffffffff : 0x00000000);
// walk through each clip element and perform its set op
for (int c = start; c < count; ++c) {
@@ -460,7 +489,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
// replace ops and alter GrClip to allow them through
// clear the accumulator and draw the new object directly into it
- clear(gpu, accum, newRTBounds, 0x00000000);
+ clear(gpu, accum, 0x00000000);
setUpBooleanBlendCoeffs(drawState, op);
this->drawClipShape(gpu, accum, clipIn, c);
@@ -474,8 +503,15 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
continue;
}
+ needTemp(gpu, desc, &temp);
+ if (NULL == temp) {
+ fClipMaskInAlpha = false;
+ SkSafeUnref(accum);
+ return false;
+ }
+
// clear the temp target & draw into it
- clear(gpu, temp, newRTBounds, 0x00000000);
+ clear(gpu, temp, 0x00000000);
setUpBooleanBlendCoeffs(drawState, SkRegion::kReplace_Op);
this->drawClipShape(gpu, temp, clipIn, c);
@@ -517,6 +553,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
*resultBounds = bounds;
SkSafeUnref(accum); // fAACache still has a ref to accum
SkSafeUnref(temp);
+
return true;
}
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index 516ec95e30..f827948202 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -14,6 +14,7 @@
#include "GrNoncopyable.h"
#include "GrClip.h"
#include "SkRefCnt.h"
+#include "GrTexture.h"
class GrGpu;
class GrPathRenderer;
@@ -41,9 +42,15 @@ struct ScissoringSettings {
*/
class GrClipMaskCache : public GrNoncopyable {
public:
- GrClipMaskCache()
- : fLastWidth(-1)
- , fLastHeight(-1) {
+ GrClipMaskCache() {
+ reset();
+ }
+
+ void reset () {
+ fLastWidth = -1;
+ fLastHeight = -1;
+ fLastClip.setEmpty();
+ fLastMask.reset(NULL);
fLastBound.MakeEmpty();
}
@@ -68,10 +75,42 @@ public:
fLastBound = bound;
}
- GrTexture* getLastMask() {
+ int getLastWidth() const {
+ return fLastWidth;
+ }
+
+ int getLastHeight() const {
+ return fLastHeight;
+ }
+
+ const GrClip& getLastClip() const {
+ return fLastClip;
+ }
+
+ GrTexture* getLastMask() {
return fLastMask.get();
}
+ GrTexture* detachLastMask() {
+ return fLastMask.detach();
+ }
+
+ int getLastMaskWidth() const {
+ if (NULL == fLastMask.get()) {
+ return -1;
+ }
+
+ return fLastMask.get()->width();
+ }
+
+ int getLastMaskHeight() const {
+ if (NULL == fLastMask.get()) {
+ return -1;
+ }
+
+ return fLastMask.get()->height();
+ }
+
const GrRect& getLastBound() const {
return fLastBound;
}
@@ -150,6 +189,10 @@ private:
const GrRect& rect,
GrTexture* texture);
+ void getAccum(GrGpu* gpu,
+ const GrTextureDesc& desc,
+ GrTexture** accum);
+
// determines the path renderer used to draw a clip path element.
GrPathRenderer* getClipPathRenderer(GrGpu* gpu,
const SkPath& path,