• 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 "SkClipStack.h"
13 #include "SkTypes.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 : SkNoncopyable {
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         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
40 
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) {
46             return true;
47         }
48 
49         return false;
50     }
51 
reset()52     void reset() {
53         if (fStack.empty()) {
54 //            SkASSERT(false);
55             return;
56         }
57 
58         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
59 
60         back->reset();
61     }
62 
63     /**
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?
68      */
69     void push();
70 
pop()71     void pop() {
72         //SkASSERT(!fStack.empty());
73 
74         if (!fStack.empty()) {
75             GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
76 
77             back->~GrClipStackFrame();
78             fStack.pop_back();
79         }
80     }
81 
getLastClipGenID()82     int32_t getLastClipGenID() const {
83 
84         if (fStack.empty()) {
85             return SkClipStack::kInvalidGenID;
86         }
87 
88         return ((GrClipStackFrame*) fStack.back())->fLastClipGenID;
89     }
90 
getLastMask()91     GrTexture* getLastMask() {
92 
93         if (fStack.empty()) {
94             SkASSERT(false);
95             return NULL;
96         }
97 
98         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
99 
100         return back->fLastMask.texture();
101     }
102 
getLastMask()103     const GrTexture* getLastMask() const {
104 
105         if (fStack.empty()) {
106             SkASSERT(false);
107             return NULL;
108         }
109 
110         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
111 
112         return back->fLastMask.texture();
113     }
114 
acquireMask(int32_t clipGenID,const GrTextureDesc & desc,const SkIRect & bound)115     void acquireMask(int32_t clipGenID,
116                      const GrTextureDesc& desc,
117                      const SkIRect& bound) {
118 
119         if (fStack.empty()) {
120             SkASSERT(false);
121             return;
122         }
123 
124         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
125 
126         back->acquireMask(fContext, clipGenID, desc, bound);
127     }
128 
getLastMaskWidth()129     int getLastMaskWidth() const {
130 
131         if (fStack.empty()) {
132             SkASSERT(false);
133             return -1;
134         }
135 
136         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
137 
138         if (NULL == back->fLastMask.texture()) {
139             return -1;
140         }
141 
142         return back->fLastMask.texture()->width();
143     }
144 
getLastMaskHeight()145     int getLastMaskHeight() const {
146 
147         if (fStack.empty()) {
148             SkASSERT(false);
149             return -1;
150         }
151 
152         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
153 
154         if (NULL == back->fLastMask.texture()) {
155             return -1;
156         }
157 
158         return back->fLastMask.texture()->height();
159     }
160 
getLastBound(SkIRect * bound)161     void getLastBound(SkIRect* bound) const {
162 
163         if (fStack.empty()) {
164             SkASSERT(false);
165             bound->setEmpty();
166             return;
167         }
168 
169         GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
170 
171         *bound = back->fLastBound;
172     }
173 
setContext(GrContext * context)174     void setContext(GrContext* context) {
175         fContext = context;
176     }
177 
getContext()178     GrContext* getContext() {
179         return fContext;
180     }
181 
releaseResources()182     void releaseResources() {
183 
184         SkDeque::F2BIter iter(fStack);
185         for (GrClipStackFrame* frame = (GrClipStackFrame*) iter.next();
186                 frame != NULL;
187                 frame = (GrClipStackFrame*) iter.next()) {
188             frame->reset();
189         }
190     }
191 
192 private:
193     struct GrClipStackFrame {
194 
GrClipStackFrameGrClipStackFrame195         GrClipStackFrame() {
196             this->reset();
197         }
198 
acquireMaskGrClipStackFrame199         void acquireMask(GrContext* context,
200                          int32_t clipGenID,
201                          const GrTextureDesc& desc,
202                          const SkIRect& bound) {
203 
204             fLastClipGenID = clipGenID;
205 
206             fLastMask.set(context, desc);
207 
208             fLastBound = bound;
209         }
210 
resetGrClipStackFrame211         void reset () {
212             fLastClipGenID = SkClipStack::kInvalidGenID;
213 
214             GrTextureDesc desc;
215 
216             fLastMask.set(NULL, desc);
217             fLastBound.setEmpty();
218         }
219 
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.
226         SkIRect                 fLastBound;
227     };
228 
229     GrContext*   fContext;
230     SkDeque      fStack;
231 
232     typedef SkNoncopyable INHERITED;
233 };
234 
235 #endif // GrClipMaskCache_DEFINED
236