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->fLastMask.texture()->wasDestroyed() &&
45 back->fLastBound == bounds &&
46 back->fLastClipGenID == clipGenID) {
59 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
65 * After a "push" the clip state is entirely open. Currently, the
66 * entire clip stack will be re-rendered into a new clip mask.
67 * TODO: can we take advantage of the nested nature of the clips to
68 * reduce the mask creation cost?
73 //SkASSERT(!fStack.empty());
75 if (!fStack.empty()) {
76 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
78 back->~GrClipStackFrame();
83 int32_t getLastClipGenID() const {
86 return SkClipStack::kInvalidGenID;
89 return ((GrClipStackFrame*) fStack.back())->fLastClipGenID;
92 GrTexture* getLastMask() {
99 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
101 return back->fLastMask.texture();
104 const GrTexture* getLastMask() const {
106 if (fStack.empty()) {
111 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
113 return back->fLastMask.texture();
116 void acquireMask(int32_t clipGenID,
117 const GrTextureDesc& desc,
118 const SkIRect& bound) {
120 if (fStack.empty()) {
125 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
127 back->acquireMask(fContext, clipGenID, desc, bound);
130 int getLastMaskWidth() const {
132 if (fStack.empty()) {
137 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
139 if (NULL == back->fLastMask.texture()) {
143 return back->fLastMask.texture()->width();
146 int getLastMaskHeight() const {
148 if (fStack.empty()) {
153 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
155 if (NULL == back->fLastMask.texture()) {
159 return back->fLastMask.texture()->height();
162 void getLastBound(SkIRect* bound) const {
164 if (fStack.empty()) {
170 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
172 *bound = back->fLastBound;
175 void setContext(GrContext* context) {
179 GrContext* getContext() {
183 // TODO: Remove this when we hold cache keys instead of refs to textures.
184 void purgeResources() {
185 SkDeque::F2BIter iter(fStack);
186 for (GrClipStackFrame* frame = (GrClipStackFrame*) iter.next();
188 frame = (GrClipStackFrame*) iter.next()) {
194 struct GrClipStackFrame {
200 void acquireMask(GrContext* context,
202 const GrTextureDesc& desc,
203 const SkIRect& bound) {
205 fLastClipGenID = clipGenID;
207 fLastMask.set(context, desc);
213 fLastClipGenID = SkClipStack::kInvalidGenID;
217 fLastMask.set(NULL, desc);
218 fLastBound.setEmpty();
221 int32_t fLastClipGenID;
222 // The mask's width & height values are used by GrClipMaskManager to correctly scale the
223 // texture coords for the geometry drawn with this mask. TODO: This should be a cache key
224 // and not a hard ref to a texture.
225 GrAutoScratchTexture fLastMask;
226 // fLastBound stores the bounding box of the clip mask in clip-stack space. This rect is
227 // used by GrClipMaskManager to position a rect and compute texture coords for the mask.
234 typedef SkNoncopyable INHERITED;
237 #endif // GrClipMaskCache_DEFINED