blob: 97b4b515cc9b72b40161f3af5d9aa470b9468604 [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.orga0b40282013-09-18 13:00:55 +000021class GrClipMaskCache : public 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
39 if (SkClipStack::kInvalidGenID == clipGenID) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000040 return false;
41 }
42
43 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
44
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000045 // We could reuse the mask if bounds is a subset of last bounds. We'd have to communicate
46 // an offset to the caller.
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000047 if (back->fLastMask.texture() &&
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000048 back->fLastBound == bounds &&
49 back->fLastClipGenID == clipGenID) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000050 return true;
51 }
52
53 return false;
54 }
55
56 void reset() {
57 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000058// SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000059 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
75 void pop() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000076 //SkASSERT(!fStack.empty());
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000077
78 if (!fStack.empty()) {
79 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
80
81 back->~GrClipStackFrame();
82 fStack.pop_back();
83 }
84 }
85
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000086 int32_t getLastClipGenID() const {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000087
88 if (fStack.empty()) {
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000089 return SkClipStack::kInvalidGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000090 }
91
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000092 return ((GrClipStackFrame*) fStack.back())->fLastClipGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000093 }
94
95 GrTexture* getLastMask() {
96
97 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000098 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000099 return NULL;
100 }
101
102 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
103
104 return back->fLastMask.texture();
105 }
106
107 const GrTexture* getLastMask() const {
108
109 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000110 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000111 return NULL;
112 }
113
114 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
115
116 return back->fLastMask.texture();
117 }
118
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000119 void acquireMask(int32_t clipGenID,
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000120 const GrTextureDesc& desc,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000121 const SkIRect& bound) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000122
123 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000124 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000125 return;
126 }
127
128 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
129
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000130 back->acquireMask(fContext, clipGenID, desc, bound);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000131 }
132
133 int getLastMaskWidth() const {
134
135 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000136 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000137 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
149 int getLastMaskHeight() const {
150
151 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000152 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000153 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
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000165 void getLastBound(SkIRect* bound) const {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000166
167 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000168 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000169 bound->setEmpty();
170 return;
171 }
172
173 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
174
175 *bound = back->fLastBound;
176 }
177
178 void setContext(GrContext* context) {
179 fContext = context;
180 }
181
182 GrContext* getContext() {
183 return fContext;
184 }
185
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
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000196private:
197 struct GrClipStackFrame {
198
199 GrClipStackFrame() {
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000200 this->reset();
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000201 }
202
203 void acquireMask(GrContext* context,
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000204 int32_t clipGenID,
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000205 const GrTextureDesc& desc,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000206 const SkIRect& bound) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000207
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000208 fLastClipGenID = clipGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000209
210 fLastMask.set(context, desc);
211
212 fLastBound = bound;
213 }
214
215 void reset () {
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000216 fLastClipGenID = SkClipStack::kInvalidGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000217
218 GrTextureDesc desc;
219
220 fLastMask.set(NULL, desc);
221 fLastBound.setEmpty();
222 }
223
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000224 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.
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000227 GrAutoScratchTexture fLastMask;
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000228 // 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.
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000230 SkIRect fLastBound;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000231 };
232
233 GrContext* fContext;
234 SkDeque fStack;
235
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000236 typedef SkNoncopyable INHERITED;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000237};
238
239#endif // GrClipMaskCache_DEFINED