Upstream version 7.36.149.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->fLastBound == bounds &&
45             back->fLastClipGenID == clipGenID) {
46             return true;
47         }
48
49         return false;
50     }
51
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
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
82     int32_t getLastClipGenID() const {
83
84         if (fStack.empty()) {
85             return SkClipStack::kInvalidGenID;
86         }
87
88         return ((GrClipStackFrame*) fStack.back())->fLastClipGenID;
89     }
90
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
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
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
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
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
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
174     void setContext(GrContext* context) {
175         fContext = context;
176     }
177
178     GrContext* getContext() {
179         return fContext;
180     }
181
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
195         GrClipStackFrame() {
196             this->reset();
197         }
198
199         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
211         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