• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2012 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  */
7 
8 #ifndef GrClipMaskCache_DEFINED
9 #define GrClipMaskCache_DEFINED
10 
11 #include "GrContext.h"
12 #include "GrNoncopyable.h"
13 #include "SkClipStack.h"
14 
15 class GrTexture;
16 
17 /**
18  * The stencil buffer stores the last clip path - providing a single entry
19  * "cache". This class provides similar functionality for AA clip paths
20  */
21 class GrClipMaskCache : public GrNoncopyable {
22 public:
23     GrClipMaskCache();
24 
~GrClipMaskCache()25     ~GrClipMaskCache() {
26 
27         while (!fStack.empty()) {
28             GrClipStackFrame* temp = (GrClipStackFrame*) fStack.back();
29             temp->~GrClipStackFrame();
30             fStack.pop_back();
31         }
32     }
33 
canReuse(int32_t clipGenID,const SkIRect & bounds)34     bool canReuse(int32_t clipGenID, const SkIRect& bounds) {
35 
36         SkASSERT(clipGenID != SkClipStack::kWideOpenGenID);
37         SkASSERT(clipGenID != SkClipStack::kEmptyGenID);
38 
39         if (SkClipStack::kInvalidGenID == clipGenID) {
40             return false;
41         }
42 
43         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
44 
45         // We could reuse the mask if bounds is a subset of last bounds. We'd have to communicate
46         // an offset to the caller.
47         if (back->fLastMask.texture() &&
48             back->fLastBound == bounds &&
49             back->fLastClipGenID == clipGenID) {
50             return true;
51         }
52 
53         return false;
54     }
55 
reset()56     void reset() {
57         if (fStack.empty()) {
58 //            GrAssert(false);
59             return;
60         }
61 
62         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
63 
64         back->reset();
65     }
66 
67     /**
68      * After a "push" the clip state is entirely open. Currently, the
69      * entire clip stack will be re-rendered into a new clip mask.
70      * TODO: can we take advantage of the nested nature of the clips to
71      * reduce the mask creation cost?
72      */
73     void push();
74 
pop()75     void pop() {
76         //GrAssert(!fStack.empty());
77 
78         if (!fStack.empty()) {
79             GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
80 
81             back->~GrClipStackFrame();
82             fStack.pop_back();
83         }
84     }
85 
getLastClipGenID()86     int32_t getLastClipGenID() const {
87 
88         if (fStack.empty()) {
89             return SkClipStack::kInvalidGenID;
90         }
91 
92         return ((GrClipStackFrame*) fStack.back())->fLastClipGenID;
93     }
94 
getLastMask()95     GrTexture* getLastMask() {
96 
97         if (fStack.empty()) {
98             GrAssert(false);
99             return NULL;
100         }
101 
102         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
103 
104         return back->fLastMask.texture();
105     }
106 
getLastMask()107     const GrTexture* getLastMask() const {
108 
109         if (fStack.empty()) {
110             GrAssert(false);
111             return NULL;
112         }
113 
114         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
115 
116         return back->fLastMask.texture();
117     }
118 
acquireMask(int32_t clipGenID,const GrTextureDesc & desc,const GrIRect & bound)119     void acquireMask(int32_t clipGenID,
120                      const GrTextureDesc& desc,
121                      const GrIRect& bound) {
122 
123         if (fStack.empty()) {
124             GrAssert(false);
125             return;
126         }
127 
128         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
129 
130         back->acquireMask(fContext, clipGenID, desc, bound);
131     }
132 
getLastMaskWidth()133     int getLastMaskWidth() const {
134 
135         if (fStack.empty()) {
136             GrAssert(false);
137             return -1;
138         }
139 
140         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
141 
142         if (NULL == back->fLastMask.texture()) {
143             return -1;
144         }
145 
146         return back->fLastMask.texture()->width();
147     }
148 
getLastMaskHeight()149     int getLastMaskHeight() const {
150 
151         if (fStack.empty()) {
152             GrAssert(false);
153             return -1;
154         }
155 
156         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
157 
158         if (NULL == back->fLastMask.texture()) {
159             return -1;
160         }
161 
162         return back->fLastMask.texture()->height();
163     }
164 
getLastBound(GrIRect * bound)165     void getLastBound(GrIRect* bound) const {
166 
167         if (fStack.empty()) {
168             GrAssert(false);
169             bound->setEmpty();
170             return;
171         }
172 
173         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
174 
175         *bound = back->fLastBound;
176     }
177 
setContext(GrContext * context)178     void setContext(GrContext* context) {
179         fContext = context;
180     }
181 
getContext()182     GrContext* getContext() {
183         return fContext;
184     }
185 
releaseResources()186     void releaseResources() {
187 
188         SkDeque::F2BIter iter(fStack);
189         for (GrClipStackFrame* frame = (GrClipStackFrame*) iter.next();
190                 frame != NULL;
191                 frame = (GrClipStackFrame*) iter.next()) {
192             frame->reset();
193         }
194     }
195 
196 private:
197     struct GrClipStackFrame {
198 
GrClipStackFrameGrClipStackFrame199         GrClipStackFrame() {
200             this->reset();
201         }
202 
acquireMaskGrClipStackFrame203         void acquireMask(GrContext* context,
204                          int32_t clipGenID,
205                          const GrTextureDesc& desc,
206                          const GrIRect& bound) {
207 
208             fLastClipGenID = clipGenID;
209 
210             fLastMask.set(context, desc);
211 
212             fLastBound = bound;
213         }
214 
resetGrClipStackFrame215         void reset () {
216             fLastClipGenID = SkClipStack::kInvalidGenID;
217 
218             GrTextureDesc desc;
219 
220             fLastMask.set(NULL, desc);
221             fLastBound.setEmpty();
222         }
223 
224         int32_t                 fLastClipGenID;
225         // The mask's width & height values are used by GrClipMaskManager to correctly scale the
226         // texture coords for the geometry drawn with this mask.
227         GrAutoScratchTexture    fLastMask;
228         // fLastBound stores the bounding box of the clip mask in clip-stack space. This rect is
229         // used by GrClipMaskManager to position a rect and compute texture coords for the mask.
230         GrIRect                 fLastBound;
231     };
232 
233     GrContext*   fContext;
234     SkDeque      fStack;
235 
236     typedef GrNoncopyable INHERITED;
237 };
238 
239 #endif // GrClipMaskCache_DEFINED
240