From beeb97c94da3b2a4b3acfae7817f8d2fea70c8e8 Mon Sep 17 00:00:00 2001 From: "robertphillips@google.com" Date: Wed, 9 May 2012 21:15:28 +0000 Subject: Added stack to AA clip mask cache http://codereview.appspot.com/6201058/ git-svn-id: http://skia.googlecode.com/svn/trunk@3885 2bbb7eff-a529-9590-31e7-b0007b416f81 --- src/gpu/GrClipMaskManager.cpp | 2 +- src/gpu/GrClipMaskManager.h | 222 +++++++++++++++++++++++++++++++------ src/gpu/GrSoftwarePathRenderer.cpp | 1 + 3 files changed, 191 insertions(+), 34 deletions(-) (limited to 'src') 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 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 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()); -- cgit v1.2.3