blob: edba54d372368951bfe1b2d8e32b7ba1d4eb3734 [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
bsalomonedd77a12015-05-29 09:45:57 -070011#include "GrResourceProvider.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:
bsalomonedd77a12015-05-29 09:45:57 -070023 GrClipMaskCache(GrResourceProvider*);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000024
25 ~GrClipMaskCache() {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000026 while (!fStack.empty()) {
27 GrClipStackFrame* temp = (GrClipStackFrame*) fStack.back();
28 temp->~GrClipStackFrame();
29 fStack.pop_back();
30 }
31 }
32
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000033 bool canReuse(int32_t clipGenID, const SkIRect& bounds) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000034
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000035 SkASSERT(clipGenID != SkClipStack::kWideOpenGenID);
36 SkASSERT(clipGenID != SkClipStack::kEmptyGenID);
37
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +000038 GrClipStackFrame* back = (GrClipStackFrame*) fStack.back();
39
bsalomon@google.com4c2443e2012-12-06 20:58:57 +000040 // We could reuse the mask if bounds is a subset of last bounds. We'd have to communicate
41 // an offset to the caller.
bsalomon427cf282014-10-16 13:41:43 -070042 if (back->fLastMask &&
43 !back->fLastMask->wasDestroyed() &&
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
bsalomon427cf282014-10-16 13:41:43 -0700100 return back->fLastMask;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000101 }
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
bsalomon427cf282014-10-16 13:41:43 -0700112 return back->fLastMask;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000113 }
114
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000115 void acquireMask(int32_t clipGenID,
bsalomonf2703d82014-10-28 14:33:06 -0700116 const GrSurfaceDesc& 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
bsalomonedd77a12015-05-29 09:45:57 -0700126 back->acquireMask(fResourceProvider, 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
bsalomon427cf282014-10-16 13:41:43 -0700138 if (NULL == back->fLastMask) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000139 return -1;
140 }
141
bsalomon427cf282014-10-16 13:41:43 -0700142 return back->fLastMask->width();
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000143 }
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
bsalomon427cf282014-10-16 13:41:43 -0700154 if (NULL == back->fLastMask) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000155 return -1;
156 }
157
bsalomon427cf282014-10-16 13:41:43 -0700158 return back->fLastMask->height();
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000159 }
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
bsalomonc8dc1f72014-08-21 13:02:13 -0700174 // TODO: Remove this when we hold cache keys instead of refs to textures.
175 void purgeResources() {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000176 SkDeque::F2BIter iter(fStack);
177 for (GrClipStackFrame* frame = (GrClipStackFrame*) iter.next();
178 frame != NULL;
179 frame = (GrClipStackFrame*) iter.next()) {
180 frame->reset();
181 }
182 }
183
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000184private:
185 struct GrClipStackFrame {
186
187 GrClipStackFrame() {
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000188 this->reset();
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000189 }
190
bsalomonedd77a12015-05-29 09:45:57 -0700191 void acquireMask(GrResourceProvider* resourceProvider,
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000192 int32_t clipGenID,
bsalomonf2703d82014-10-28 14:33:06 -0700193 const GrSurfaceDesc& desc,
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000194 const SkIRect& bound) {
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000195
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000196 fLastClipGenID = clipGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000197
bsalomoneae62002015-07-31 13:59:30 -0700198 // TODO: Determine if we really need the NoPendingIO flag anymore.
199 // (http://skbug.com/4156)
200 static const uint32_t kFlags = GrResourceProvider::kNoPendingIO_Flag;
201 fLastMask.reset(resourceProvider->createApproxTexture(desc, kFlags));
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000202
203 fLastBound = bound;
204 }
205
206 void reset () {
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000207 fLastClipGenID = SkClipStack::kInvalidGenID;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000208
bsalomonf2703d82014-10-28 14:33:06 -0700209 GrSurfaceDesc desc;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000210
bsalomon427cf282014-10-16 13:41:43 -0700211 fLastMask.reset(NULL);
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000212 fLastBound.setEmpty();
213 }
214
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000215 int32_t fLastClipGenID;
216 // The mask's width & height values are used by GrClipMaskManager to correctly scale the
bsalomonc8dc1f72014-08-21 13:02:13 -0700217 // texture coords for the geometry drawn with this mask. TODO: This should be a cache key
218 // and not a hard ref to a texture.
bsalomon427cf282014-10-16 13:41:43 -0700219 SkAutoTUnref<GrTexture> fLastMask;
bsalomon@google.com4c2443e2012-12-06 20:58:57 +0000220 // fLastBound stores the bounding box of the clip mask in clip-stack space. This rect is
221 // used by GrClipMaskManager to position a rect and compute texture coords for the mask.
commit-bot@chromium.orgfd03d4a2013-07-17 21:39:42 +0000222 SkIRect fLastBound;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000223 };
224
bsalomonedd77a12015-05-29 09:45:57 -0700225 SkDeque fStack;
226 GrResourceProvider* fResourceProvider;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000227
commit-bot@chromium.orga0b40282013-09-18 13:00:55 +0000228 typedef SkNoncopyable INHERITED;
robertphillips@google.com1fcc1b82012-08-29 12:52:05 +0000229};
230
231#endif // GrClipMaskCache_DEFINED