blob: 6b484e8af83e15918b63a53704f34ab26de42378 [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() &&
bsalomonc8dc1f72014-08-21 13:02:13 -070044 !back->fLastMask.texture()->wasDestroyed() &&
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000045 back->fLastBound == bounds &&
46 back->fLastClipGenID == clipGenID) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000047 return true;
48 }
49
50 return false;
51 }
52
53 void reset() {
54 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000055// SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000056 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() {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000073 //SkASSERT(!fStack.empty());
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000074
75 if (!fStack.empty()) {
76 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
77
78 back->~GrClipStackFrame();
79 fStack.pop_back();
80 }
81 }
82
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000083 int32_t getLastClipGenID() const {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000084
85 if (fStack.empty()) {
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000086 return SkClipStack::kInvalidGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000087 }
88
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000089 return ((GrClipStackFrame*) fStack.back())->fLastClipGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000090 }
91
92 GrTexture* getLastMask() {
93
94 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +000095 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000096 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()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000107 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000108 return NULL;
109 }
110
111 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
112
113 return back->fLastMask.texture();
114 }
115
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000116 void acquireMask(int32_t clipGenID,
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000117 const GrTextureDesc& desc,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000118 const SkIRect& bound) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000119
120 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000121 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000122 return;
123 }
124
125 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
126
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000127 back->acquireMask(fContext, clipGenID, desc, bound);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000128 }
129
130 int getLastMaskWidth() const {
131
132 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000133 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000134 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()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000149 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000150 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
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000162 void getLastBound(SkIRect* bound) const {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000163
164 if (fStack.empty()) {
tfarina@chromium.orgf6de4752013-08-17 00:02:59 +0000165 SkASSERT(false);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000166 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
bsalomonc8dc1f72014-08-21 13:02:13 -0700183 // TODO: Remove this when we hold cache keys instead of refs to textures.
184 void purgeResources() {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000185 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
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000193private:
194 struct GrClipStackFrame {
195
196 GrClipStackFrame() {
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000197 this->reset();
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000198 }
199
200 void acquireMask(GrContext* context,
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000201 int32_t clipGenID,
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000202 const GrTextureDesc& desc,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000203 const SkIRect& bound) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000204
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000205 fLastClipGenID = clipGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000206
207 fLastMask.set(context, desc);
208
209 fLastBound = bound;
210 }
211
212 void reset () {
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000213 fLastClipGenID = SkClipStack::kInvalidGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000214
215 GrTextureDesc desc;
216
217 fLastMask.set(NULL, desc);
218 fLastBound.setEmpty();
219 }
220
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000221 int32_t fLastClipGenID;
222 // The mask's width & height values are used by GrClipMaskManager to correctly scale the
bsalomonc8dc1f72014-08-21 13:02:13 -0700223 // 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.
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000225 GrAutoScratchTexture fLastMask;
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000226 // 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.
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000228 SkIRect fLastBound;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000229 };
230
231 GrContext* fContext;
232 SkDeque fStack;
233
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000234 typedef SkNoncopyable INHERITED;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000235};
236
237#endif // GrClipMaskCache_DEFINED