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