2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #ifndef GrClipMaskCache_DEFINED
9 #define GrClipMaskCache_DEFINED
11 #include "GrContext.h"
12 #include "SkClipStack.h"
18 * The stencil buffer stores the last clip path - providing a single entry
19 * "cache". This class provides similar functionality for AA clip paths
21 class GrClipMaskCache : SkNoncopyable {
27 while (!fStack.empty()) {
28 GrClipStackFrame* temp = (GrClipStackFrame*) fStack.back();
29 temp->~GrClipStackFrame();
34 bool canReuse(int32_t clipGenID, const SkIRect& bounds) {
36 SkASSERT(clipGenID != SkClipStack::kWideOpenGenID);
37 SkASSERT(clipGenID != SkClipStack::kEmptyGenID);
39 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
41 // We could reuse the mask if bounds is a subset of last bounds. We'd have to communicate
42 // an offset to the caller.
43 if (back->fLastMask.texture() &&
44 back->fLastBound == bounds &&
45 back->fLastClipGenID == clipGenID) {
58 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
64 * After a "push" the clip state is entirely open. Currently, the
65 * entire clip stack will be re-rendered into a new clip mask.
66 * TODO: can we take advantage of the nested nature of the clips to
67 * reduce the mask creation cost?
72 //SkASSERT(!fStack.empty());
74 if (!fStack.empty()) {
75 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
77 back->~GrClipStackFrame();
82 int32_t getLastClipGenID() const {
85 return SkClipStack::kInvalidGenID;
88 return ((GrClipStackFrame*) fStack.back())->fLastClipGenID;
91 GrTexture* getLastMask() {
98 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
100 return back->fLastMask.texture();
103 const GrTexture* getLastMask() const {
105 if (fStack.empty()) {
110 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
112 return back->fLastMask.texture();
115 void acquireMask(int32_t clipGenID,
116 const GrTextureDesc& desc,
117 const SkIRect& bound) {
119 if (fStack.empty()) {
124 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
126 back->acquireMask(fContext, clipGenID, desc, bound);
129 int getLastMaskWidth() const {
131 if (fStack.empty()) {
136 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
138 if (NULL == back->fLastMask.texture()) {
142 return back->fLastMask.texture()->width();
145 int getLastMaskHeight() const {
147 if (fStack.empty()) {
152 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
154 if (NULL == back->fLastMask.texture()) {
158 return back->fLastMask.texture()->height();
161 void getLastBound(SkIRect* bound) const {
163 if (fStack.empty()) {
169 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
171 *bound = back->fLastBound;
174 void setContext(GrContext* context) {
178 GrContext* getContext() {
182 void releaseResources() {
184 SkDeque::F2BIter iter(fStack);
185 for (GrClipStackFrame* frame = (GrClipStackFrame*) iter.next();
187 frame = (GrClipStackFrame*) iter.next()) {
193 struct GrClipStackFrame {
199 void acquireMask(GrContext* context,
201 const GrTextureDesc& desc,
202 const SkIRect& bound) {
204 fLastClipGenID = clipGenID;
206 fLastMask.set(context, desc);
212 fLastClipGenID = SkClipStack::kInvalidGenID;
216 fLastMask.set(NULL, desc);
217 fLastBound.setEmpty();
220 int32_t fLastClipGenID;
221 // The mask's width & height values are used by GrClipMaskManager to correctly scale the
222 // texture coords for the geometry drawn with this mask.
223 GrAutoScratchTexture fLastMask;
224 // fLastBound stores the bounding box of the clip mask in clip-stack space. This rect is
225 // used by GrClipMaskManager to position a rect and compute texture coords for the mask.
232 typedef SkNoncopyable INHERITED;
235 #endif // GrClipMaskCache_DEFINED