blob: b332c7be9b96e2daf8537344b1527bbdb414492f [file] [log] [blame]
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +00001/*
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"
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000012#include "SkClipStack.h"
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +000013#include "SkTypes.h"
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000014
15class 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 */
commit-bot@chromium.orge3beb6b2014-04-07 19:34:38 +000021class GrClipMaskCache : SkNoncopyable {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000022public:
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
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000034 bool canReuse(int32_t clipGenID, const SkIRect& bounds) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000035
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000036 SkASSERT(clipGenID != SkClipStack::kWideOpenGenID);
37 SkASSERT(clipGenID != SkClipStack::kEmptyGenID);
38
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000039 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
40
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000041 // We could reuse the mask if bounds is a subset of last bounds. We'd have to communicate
42 // an offset to the caller.
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000043 if (back->fLastMask.texture() &&
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000044 back->fLastBound == bounds &&
45 back->fLastClipGenID == clipGenID) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000046 return true;
47 }
48
49 return false;
50 }
51
52 void reset() {
53 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000054// SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000055 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() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000072 //SkASSERT(!fStack.empty());
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000073
74 if (!fStack.empty()) {
75 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
76
77 back->~GrClipStackFrame();
78 fStack.pop_back();
79 }
80 }
81
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000082 int32_t getLastClipGenID() const {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000083
84 if (fStack.empty()) {
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000085 return SkClipStack::kInvalidGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000086 }
87
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000088 return ((GrClipStackFrame*) fStack.back())->fLastClipGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000089 }
90
91 GrTexture* getLastMask() {
92
93 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000094 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000095 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()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000106 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000107 return NULL;
108 }
109
110 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
111
112 return back->fLastMask.texture();
113 }
114
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000115 void acquireMask(int32_t clipGenID,
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000116 const GrTextureDesc& desc,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000117 const SkIRect& bound) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000118
119 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000120 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000121 return;
122 }
123
124 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
125
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000126 back->acquireMask(fContext, clipGenID, desc, bound);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000127 }
128
129 int getLastMaskWidth() const {
130
131 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000132 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000133 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()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000148 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000149 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
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000161 void getLastBound(SkIRect* bound) const {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000162
163 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000164 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000165 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
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000192private:
193 struct GrClipStackFrame {
194
195 GrClipStackFrame() {
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000196 this->reset();
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000197 }
198
199 void acquireMask(GrContext* context,
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000200 int32_t clipGenID,
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000201 const GrTextureDesc& desc,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000202 const SkIRect& bound) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000203
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000204 fLastClipGenID = clipGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000205
206 fLastMask.set(context, desc);
207
208 fLastBound = bound;
209 }
210
211 void reset () {
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000212 fLastClipGenID = SkClipStack::kInvalidGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000213
214 GrTextureDesc desc;
215
216 fLastMask.set(NULL, desc);
217 fLastBound.setEmpty();
218 }
219
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000220 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.
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000223 GrAutoScratchTexture fLastMask;
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000224 // 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.
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000226 SkIRect fLastBound;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000227 };
228
229 GrContext* fContext;
230 SkDeque fStack;
231
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000232 typedef SkNoncopyable INHERITED;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000233};
234
235#endif // GrClipMaskCache_DEFINED