aboutsummaryrefslogtreecommitdiffhomepage
path: root/src
diff options
context:
space:
mode:
authorGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-05-09 21:15:28 +0000
committerGravatar robertphillips@google.com <robertphillips@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2012-05-09 21:15:28 +0000
commitbeeb97c94da3b2a4b3acfae7817f8d2fea70c8e8 (patch)
treedeb59c601629f1b31465e02cbbd15addf63b115f /src
parent683001ce0de70c859ea5e5353245b18cadbefc45 (diff)
Added stack to AA clip mask cache
Diffstat (limited to 'src')
-rw-r--r--src/gpu/GrClipMaskManager.cpp2
-rw-r--r--src/gpu/GrClipMaskManager.h222
-rw-r--r--src/gpu/GrSoftwarePathRenderer.cpp1
3 files changed, 191 insertions, 34 deletions
diff --git a/src/gpu/GrClipMaskManager.cpp b/src/gpu/GrClipMaskManager.cpp
index 1a892d80dc..f8c43b0491 100644
--- a/src/gpu/GrClipMaskManager.cpp
+++ b/src/gpu/GrClipMaskManager.cpp
@@ -396,7 +396,7 @@ bool GrClipMaskManager::createAlphaClipMask(GrGpu* gpu,
if (fAACache.canReuse(clipIn, rt->width(), rt->height())) {
*result = fAACache.getLastMask();
- *resultBounds = fAACache.getLastBound();
+ fAACache.getLastBound(resultBounds);
return true;
}
diff --git a/src/gpu/GrClipMaskManager.h b/src/gpu/GrClipMaskManager.h
index f827948202..65205679d5 100644
--- a/src/gpu/GrClipMaskManager.h
+++ b/src/gpu/GrClipMaskManager.h
@@ -15,6 +15,7 @@
#include "GrClip.h"
#include "SkRefCnt.h"
#include "GrTexture.h"
+#include "SkDeque.h"
class GrGpu;
class GrPathRenderer;
@@ -42,22 +43,34 @@ struct ScissoringSettings {
*/
class GrClipMaskCache : public GrNoncopyable {
public:
- GrClipMaskCache() {
- reset();
+ GrClipMaskCache()
+ : fStack(sizeof(GrClipStackFrame)) {
+ // We need an initial frame to capture the clip state prior to
+ // any pushes
+ new (fStack.push_back()) GrClipStackFrame();
}
- void reset () {
- fLastWidth = -1;
- fLastHeight = -1;
- fLastClip.setEmpty();
- fLastMask.reset(NULL);
- fLastBound.MakeEmpty();
+ ~GrClipMaskCache() {
+
+ while (!fStack.empty()) {
+ GrClipStackFrame* temp = (GrClipStackFrame*) fStack.back();
+ temp->~GrClipStackFrame();
+ fStack.pop_back();
+ }
}
bool canReuse(const GrClip& clip, int width, int height) {
- if (fLastWidth >= width &&
- fLastHeight >= height &&
- clip == fLastClip) {
+
+ if (fStack.empty()) {
+ GrAssert(false);
+ return false;
+ }
+
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ if (back->fLastWidth >= width &&
+ back->fLastHeight >= height &&
+ clip == back->fLastClip) {
return true;
}
@@ -67,61 +80,204 @@ public:
void set(const GrClip& clip, int width, int height,
GrTexture* mask, const GrRect& bound) {
- fLastWidth = width;
- fLastHeight = height;
- fLastClip = clip;
+ if (fStack.empty()) {
+ GrAssert(false);
+ return;
+ }
+
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ back->fLastWidth = width;
+ back->fLastHeight = height;
+ back->fLastClip = clip;
SkSafeRef(mask);
- fLastMask.reset(mask);
- fLastBound = bound;
+ back->fLastMask.reset(mask);
+ back->fLastBound = bound;
+ }
+
+ void reset() {
+ if (fStack.empty()) {
+ GrAssert(false);
+ return;
+ }
+
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ back->reset();
+ }
+
+ /**
+ * After a "push" the clip state is entirely open. Currently, the
+ * entire clip stack will be re-rendered into a new clip mask.
+ * TODO: can we take advantage of the nested nature of the clips to
+ * reduce the mask creation cost?
+ */
+ void push() {
+ new (fStack.push_back()) GrClipStackFrame();
+ }
+
+ void pop() {
+ GrAssert(!fStack.empty());
+
+ if (!fStack.empty()) {
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ back->~GrClipStackFrame();
+ fStack.pop_back();
+ }
}
int getLastWidth() const {
- return fLastWidth;
+
+ if (fStack.empty()) {
+ GrAssert(false);
+ return -1;
+ }
+
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ return back->fLastWidth;
}
int getLastHeight() const {
- return fLastHeight;
+
+ if (fStack.empty()) {
+ GrAssert(false);
+ return -1;
+ }
+
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ return back->fLastHeight;
}
- const GrClip& getLastClip() const {
- return fLastClip;
+ void getLastClip(GrClip* clip) const {
+
+ if (fStack.empty()) {
+ GrAssert(false);
+ clip->setEmpty();
+ return;
+ }
+
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ *clip = back->fLastClip;
}
GrTexture* getLastMask() {
- return fLastMask.get();
+
+ if (fStack.empty()) {
+ GrAssert(false);
+ return NULL;
+ }
+
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ return back->fLastMask.get();
+ }
+
+ const GrTexture* getLastMask() const {
+
+ if (fStack.empty()) {
+ GrAssert(false);
+ return NULL;
+ }
+
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ return back->fLastMask.get();
}
GrTexture* detachLastMask() {
- return fLastMask.detach();
+
+ if (fStack.empty()) {
+ GrAssert(false);
+ return NULL;
+ }
+
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ return back->fLastMask.detach();
}
int getLastMaskWidth() const {
- if (NULL == fLastMask.get()) {
+
+ if (fStack.empty()) {
+ GrAssert(false);
+ return -1;
+ }
+
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ if (NULL == back->fLastMask.get()) {
return -1;
}
- return fLastMask.get()->width();
+ return back->fLastMask.get()->width();
}
int getLastMaskHeight() const {
- if (NULL == fLastMask.get()) {
+
+ if (fStack.empty()) {
+ GrAssert(false);
return -1;
}
- return fLastMask.get()->height();
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ if (NULL == back->fLastMask.get()) {
+ return -1;
+ }
+
+ return back->fLastMask.get()->height();
}
- const GrRect& getLastBound() const {
- return fLastBound;
+ void getLastBound(GrRect* bound) const {
+
+ if (fStack.empty()) {
+ GrAssert(false);
+ bound->setEmpty();
+ return;
+ }
+
+ GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
+
+ *bound = back->fLastBound;
}
protected:
private:
- int fLastWidth;
- int fLastHeight;
- GrClip fLastClip;
- SkAutoTUnref<GrTexture> fLastMask;
- GrRect fLastBound;
+ struct GrClipStackFrame {
+
+ GrClipStackFrame() {
+ reset();
+ }
+
+ void reset () {
+ fLastWidth = -1;
+ fLastHeight = -1;
+ fLastClip.setEmpty();
+ fLastMask.reset(NULL);
+ fLastBound.setEmpty();
+ }
+
+ // fLastWidth & fLastHeight store the render target size used when
+ // creating the mask. They factor into the reuse decision (in canReuse)
+ // TODO: We should probably use the mask's width & height rather than
+ // the render target's width & height for reuse decisions
+ int fLastWidth;
+ int fLastHeight;
+ GrClip fLastClip;
+ // The mask's width & height values are used in setupDrawStateAAClip to
+ // correctly scale the uvs for geometry drawn with this mask
+ SkAutoTUnref<GrTexture> fLastMask;
+ // fLastBound stores the bounding box of the clip mask in canvas
+ // space. The left and top fields are used to offset the uvs for
+ // geometry drawn with this mask (in setupDrawStateAAClip)
+ GrRect fLastBound;
+ };
+
+ SkDeque fStack;
typedef GrNoncopyable INHERITED;
};
diff --git a/src/gpu/GrSoftwarePathRenderer.cpp b/src/gpu/GrSoftwarePathRenderer.cpp
index cbec9653de..22e4a2641a 100644
--- a/src/gpu/GrSoftwarePathRenderer.cpp
+++ b/src/gpu/GrSoftwarePathRenderer.cpp
@@ -232,6 +232,7 @@ bool GrSoftwarePathRenderer::onDrawPath(const SkPath& path,
// rendering (kGlyphMaskStage in GrBatchedTextContext)
kPathMaskStage = GrPaint::kTotalStages,
};
+ GrAssert(NULL == target->drawState()->getTexture(kPathMaskStage));
target->drawState()->setTexture(kPathMaskStage, texture);
target->drawState()->sampler(kPathMaskStage)->reset();
GrScalar w = GrIntToScalar(pathBounds.width());