OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
6 */ | 6 */ |
7 | 7 |
8 #include "GrClipMaskManager.h" | 8 #include "GrClipMaskManager.h" |
9 #include "GrAAConvexPathRenderer.h" | 9 #include "GrAAConvexPathRenderer.h" |
10 #include "GrAAHairLinePathRenderer.h" | 10 #include "GrAAHairLinePathRenderer.h" |
(...skipping 13 matching lines...) Expand all Loading... |
24 #include "effects/GrTextureDomain.h" | 24 #include "effects/GrTextureDomain.h" |
25 | 25 |
26 #define GR_AA_CLIP 1 | 26 #define GR_AA_CLIP 1 |
27 typedef SkClipStack::Element Element; | 27 typedef SkClipStack::Element Element; |
28 | 28 |
29 //////////////////////////////////////////////////////////////////////////////// | 29 //////////////////////////////////////////////////////////////////////////////// |
30 namespace { | 30 namespace { |
31 // set up the draw state to enable the aa clipping mask. Besides setting up the | 31 // set up the draw state to enable the aa clipping mask. Besides setting up the |
32 // stage matrix this also alters the vertex layout | 32 // stage matrix this also alters the vertex layout |
33 void setup_drawstate_aaclip(const SkIRect &devBound, | 33 void setup_drawstate_aaclip(const SkIRect &devBound, |
34 GrDrawState* drawState, | 34 GrPipelineBuilder* pipelineBuilder, |
35 GrTexture* result) { | 35 GrTexture* result) { |
36 SkASSERT(drawState); | 36 SkASSERT(pipelineBuilder); |
37 | 37 |
38 SkMatrix mat; | 38 SkMatrix mat; |
39 // We use device coords to compute the texture coordinates. We set our matri
x to be a | 39 // We use device coords to compute the texture coordinates. We set our matri
x to be a |
40 // translation to the devBound, and then a scaling matrix to normalized coor
ds. | 40 // translation to the devBound, and then a scaling matrix to normalized coor
ds. |
41 mat.setIDiv(result->width(), result->height()); | 41 mat.setIDiv(result->width(), result->height()); |
42 mat.preTranslate(SkIntToScalar(-devBound.fLeft), | 42 mat.preTranslate(SkIntToScalar(-devBound.fLeft), |
43 SkIntToScalar(-devBound.fTop)); | 43 SkIntToScalar(-devBound.fTop)); |
44 | 44 |
45 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); | 45 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); |
46 // This could be a long-lived effect that is cached with the alpha-mask. | 46 // This could be a long-lived effect that is cached with the alpha-mask. |
47 drawState->addCoverageProcessor( | 47 pipelineBuilder->addCoverageProcessor( |
48 GrTextureDomainEffect::Create(result, | 48 GrTextureDomainEffect::Create(result, |
49 mat, | 49 mat, |
50 GrTextureDomain::MakeTexelDomain(result, d
omainTexels), | 50 GrTextureDomain::MakeTexelDomain(result, d
omainTexels), |
51 GrTextureDomain::kDecal_Mode, | 51 GrTextureDomain::kDecal_Mode, |
52 GrTextureParams::kNone_FilterMode, | 52 GrTextureParams::kNone_FilterMode, |
53 kDevice_GrCoordSet))->unref(); | 53 kDevice_GrCoordSet))->unref(); |
54 } | 54 } |
55 | 55 |
56 bool path_needs_SW_renderer(GrContext* context, | 56 bool path_needs_SW_renderer(GrContext* context, |
57 const GrDrawTarget* gpu, | 57 const GrDrawTarget* gpu, |
58 const GrDrawState* drawState, | 58 const GrPipelineBuilder* pipelineBuilder, |
59 const SkMatrix& viewMatrix, | 59 const SkMatrix& viewMatrix, |
60 const SkPath& origPath, | 60 const SkPath& origPath, |
61 const SkStrokeRec& stroke, | 61 const SkStrokeRec& stroke, |
62 bool doAA) { | 62 bool doAA) { |
63 // the gpu alpha mask will draw the inverse paths as non-inverse to a temp b
uffer | 63 // the gpu alpha mask will draw the inverse paths as non-inverse to a temp b
uffer |
64 SkTCopyOnFirstWrite<SkPath> path(origPath); | 64 SkTCopyOnFirstWrite<SkPath> path(origPath); |
65 if (path->isInverseFillType()) { | 65 if (path->isInverseFillType()) { |
66 path.writable()->toggleInverseFillType(); | 66 path.writable()->toggleInverseFillType(); |
67 } | 67 } |
68 // last (false) parameter disallows use of the SW path renderer | 68 // last (false) parameter disallows use of the SW path renderer |
69 GrPathRendererChain::DrawType type = doAA ? | 69 GrPathRendererChain::DrawType type = doAA ? |
70 GrPathRendererChain::kColorAntiAlias_Dr
awType : | 70 GrPathRendererChain::kColorAntiAlias_Dr
awType : |
71 GrPathRendererChain::kColor_DrawType; | 71 GrPathRendererChain::kColor_DrawType; |
72 | 72 |
73 return NULL == context->getPathRenderer(gpu, drawState, viewMatrix, *path, s
troke, false, type); | 73 return NULL == context->getPathRenderer(gpu, pipelineBuilder, viewMatrix, *p
ath, stroke, |
| 74 false, type); |
74 } | 75 } |
75 } | 76 } |
76 | 77 |
77 /* | 78 /* |
78 * This method traverses the clip stack to see if the GrSoftwarePathRenderer | 79 * This method traverses the clip stack to see if the GrSoftwarePathRenderer |
79 * will be used on any element. If so, it returns true to indicate that the | 80 * will be used on any element. If so, it returns true to indicate that the |
80 * entire clip should be rendered in SW and then uploaded en masse to the gpu. | 81 * entire clip should be rendered in SW and then uploaded en masse to the gpu. |
81 */ | 82 */ |
82 bool GrClipMaskManager::useSWOnlyPath(const GrDrawState* drawState, | 83 bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder* pipelineBuilder, |
83 const SkVector& clipToMaskOffset, | 84 const SkVector& clipToMaskOffset, |
84 const GrReducedClip::ElementList& elements
) { | 85 const GrReducedClip::ElementList& elements
) { |
85 // TODO: generalize this function so that when | 86 // TODO: generalize this function so that when |
86 // a clip gets complex enough it can just be done in SW regardless | 87 // a clip gets complex enough it can just be done in SW regardless |
87 // of whether it would invoke the GrSoftwarePathRenderer. | 88 // of whether it would invoke the GrSoftwarePathRenderer. |
88 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 89 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
89 | 90 |
90 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip | 91 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip |
91 // space. | 92 // space. |
92 SkMatrix translate; | 93 SkMatrix translate; |
93 translate.setTranslate(clipToMaskOffset); | 94 translate.setTranslate(clipToMaskOffset); |
94 | 95 |
95 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { | 96 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { |
96 const Element* element = iter.get(); | 97 const Element* element = iter.get(); |
97 // rects can always be drawn directly w/o using the software path | 98 // rects can always be drawn directly w/o using the software path |
98 // Skip rrects once we're drawing them directly. | 99 // Skip rrects once we're drawing them directly. |
99 if (Element::kRect_Type != element->getType()) { | 100 if (Element::kRect_Type != element->getType()) { |
100 SkPath path; | 101 SkPath path; |
101 element->asPath(&path); | 102 element->asPath(&path); |
102 if (path_needs_SW_renderer(this->getContext(), fClipTarget, drawStat
e, translate, | 103 if (path_needs_SW_renderer(this->getContext(), fClipTarget, pipeline
Builder, translate, |
103 path, stroke, element->isAA())) { | 104 path, stroke, element->isAA())) { |
104 return true; | 105 return true; |
105 } | 106 } |
106 } | 107 } |
107 } | 108 } |
108 return false; | 109 return false; |
109 } | 110 } |
110 | 111 |
111 bool GrClipMaskManager::installClipEffects(GrDrawState* drawState, | 112 bool GrClipMaskManager::installClipEffects(GrPipelineBuilder* pipelineBuilder, |
112 GrDrawState::AutoRestoreEffects* are, | 113 GrPipelineBuilder::AutoRestoreEffects
* are, |
113 const GrReducedClip::ElementList& ele
ments, | 114 const GrReducedClip::ElementList& ele
ments, |
114 const SkVector& clipToRTOffset, | 115 const SkVector& clipToRTOffset, |
115 const SkRect* drawBounds) { | 116 const SkRect* drawBounds) { |
116 SkRect boundsInClipSpace; | 117 SkRect boundsInClipSpace; |
117 if (drawBounds) { | 118 if (drawBounds) { |
118 boundsInClipSpace = *drawBounds; | 119 boundsInClipSpace = *drawBounds; |
119 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); | 120 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); |
120 } | 121 } |
121 | 122 |
122 are->set(drawState); | 123 are->set(pipelineBuilder); |
123 GrRenderTarget* rt = drawState->getRenderTarget(); | 124 GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); |
124 GrReducedClip::ElementList::Iter iter(elements); | 125 GrReducedClip::ElementList::Iter iter(elements); |
125 bool failed = false; | 126 bool failed = false; |
126 while (iter.get()) { | 127 while (iter.get()) { |
127 SkRegion::Op op = iter.get()->getOp(); | 128 SkRegion::Op op = iter.get()->getOp(); |
128 bool invert; | 129 bool invert; |
129 bool skip = false; | 130 bool skip = false; |
130 switch (op) { | 131 switch (op) { |
131 case SkRegion::kReplace_Op: | 132 case SkRegion::kReplace_Op: |
132 SkASSERT(iter.get() == elements.head()); | 133 SkASSERT(iter.get() == elements.head()); |
133 // Fallthrough, handled same as intersect. | 134 // Fallthrough, handled same as intersect. |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
179 case SkClipStack::Element::kRect_Type: { | 180 case SkClipStack::Element::kRect_Type: { |
180 SkRect rect = iter.get()->getRect(); | 181 SkRect rect = iter.get()->getRect(); |
181 rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); | 182 rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); |
182 fp.reset(GrConvexPolyEffect::Create(edgeType, rect)); | 183 fp.reset(GrConvexPolyEffect::Create(edgeType, rect)); |
183 break; | 184 break; |
184 } | 185 } |
185 default: | 186 default: |
186 break; | 187 break; |
187 } | 188 } |
188 if (fp) { | 189 if (fp) { |
189 drawState->addCoverageProcessor(fp); | 190 pipelineBuilder->addCoverageProcessor(fp); |
190 } else { | 191 } else { |
191 failed = true; | 192 failed = true; |
192 break; | 193 break; |
193 } | 194 } |
194 } | 195 } |
195 iter.next(); | 196 iter.next(); |
196 } | 197 } |
197 | 198 |
198 if (failed) { | 199 if (failed) { |
199 are->set(NULL); | 200 are->set(NULL); |
200 } | 201 } |
201 return !failed; | 202 return !failed; |
202 } | 203 } |
203 | 204 |
204 //////////////////////////////////////////////////////////////////////////////// | 205 //////////////////////////////////////////////////////////////////////////////// |
205 // sort out what kind of clip mask needs to be created: alpha, stencil, | 206 // sort out what kind of clip mask needs to be created: alpha, stencil, |
206 // scissor, or entirely software | 207 // scissor, or entirely software |
207 bool GrClipMaskManager::setupClipping(GrDrawState* drawState, | 208 bool GrClipMaskManager::setupClipping(GrPipelineBuilder* pipelineBuilder, |
208 GrDrawState::AutoRestoreEffects* are, | 209 GrPipelineBuilder::AutoRestoreEffects* are
, |
209 GrDrawState::AutoRestoreStencil* ars, | 210 GrPipelineBuilder::AutoRestoreStencil* ars
, |
210 GrScissorState* scissorState, | 211 GrScissorState* scissorState, |
211 const GrClipData* clipDataIn, | 212 const GrClipData* clipDataIn, |
212 const SkRect* devBounds) { | 213 const SkRect* devBounds) { |
213 fCurrClipMaskType = kNone_ClipMaskType; | 214 fCurrClipMaskType = kNone_ClipMaskType; |
214 if (kRespectClip_StencilClipMode == fClipMode) { | 215 if (kRespectClip_StencilClipMode == fClipMode) { |
215 fClipMode = kIgnoreClip_StencilClipMode; | 216 fClipMode = kIgnoreClip_StencilClipMode; |
216 } | 217 } |
217 | 218 |
218 GrReducedClip::ElementList elements(16); | 219 GrReducedClip::ElementList elements(16); |
219 int32_t genID; | 220 int32_t genID; |
220 GrReducedClip::InitialState initialState; | 221 GrReducedClip::InitialState initialState; |
221 SkIRect clipSpaceIBounds; | 222 SkIRect clipSpaceIBounds; |
222 bool requiresAA; | 223 bool requiresAA; |
223 GrRenderTarget* rt = drawState->getRenderTarget(); | 224 GrRenderTarget* rt = pipelineBuilder->getRenderTarget(); |
224 | 225 |
225 // GrDrawTarget should have filtered this for us | 226 // GrDrawTarget should have filtered this for us |
226 SkASSERT(rt); | 227 SkASSERT(rt); |
227 | 228 |
228 bool ignoreClip = !drawState->isClipState() || clipDataIn->fClipStack->isWid
eOpen(); | 229 bool ignoreClip = !pipelineBuilder->isClipState() || clipDataIn->fClipStack-
>isWideOpen(); |
229 if (!ignoreClip) { | 230 if (!ignoreClip) { |
230 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); | 231 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); |
231 clipSpaceRTIBounds.offset(clipDataIn->fOrigin); | 232 clipSpaceRTIBounds.offset(clipDataIn->fOrigin); |
232 GrReducedClip::ReduceClipStack(*clipDataIn->fClipStack, | 233 GrReducedClip::ReduceClipStack(*clipDataIn->fClipStack, |
233 clipSpaceRTIBounds, | 234 clipSpaceRTIBounds, |
234 &elements, | 235 &elements, |
235 &genID, | 236 &genID, |
236 &initialState, | 237 &initialState, |
237 &clipSpaceIBounds, | 238 &clipSpaceIBounds, |
238 &requiresAA); | 239 &requiresAA); |
239 if (elements.isEmpty()) { | 240 if (elements.isEmpty()) { |
240 if (GrReducedClip::kAllIn_InitialState == initialState) { | 241 if (GrReducedClip::kAllIn_InitialState == initialState) { |
241 ignoreClip = clipSpaceIBounds == clipSpaceRTIBounds; | 242 ignoreClip = clipSpaceIBounds == clipSpaceRTIBounds; |
242 } else { | 243 } else { |
243 return false; | 244 return false; |
244 } | 245 } |
245 } | 246 } |
246 } | 247 } |
247 | 248 |
248 if (ignoreClip) { | 249 if (ignoreClip) { |
249 this->setDrawStateStencil(drawState, ars); | 250 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
250 return true; | 251 return true; |
251 } | 252 } |
252 | 253 |
253 // An element count of 4 was chosen because of the common pattern in Blink o
f: | 254 // An element count of 4 was chosen because of the common pattern in Blink o
f: |
254 // isect RR | 255 // isect RR |
255 // diff RR | 256 // diff RR |
256 // isect convex_poly | 257 // isect convex_poly |
257 // isect convex_poly | 258 // isect convex_poly |
258 // when drawing rounded div borders. This could probably be tuned based on a | 259 // when drawing rounded div borders. This could probably be tuned based on a |
259 // configuration's relative costs of switching RTs to generate a mask vs | 260 // configuration's relative costs of switching RTs to generate a mask vs |
260 // longer shaders. | 261 // longer shaders. |
261 if (elements.count() <= 4) { | 262 if (elements.count() <= 4) { |
262 SkVector clipToRTOffset = { SkIntToScalar(-clipDataIn->fOrigin.fX), | 263 SkVector clipToRTOffset = { SkIntToScalar(-clipDataIn->fOrigin.fX), |
263 SkIntToScalar(-clipDataIn->fOrigin.fY) }; | 264 SkIntToScalar(-clipDataIn->fOrigin.fY) }; |
264 if (elements.isEmpty() || | 265 if (elements.isEmpty() || |
265 (requiresAA && this->installClipEffects(drawState, are, elements, cl
ipToRTOffset, | 266 (requiresAA && this->installClipEffects(pipelineBuilder, are, elemen
ts, clipToRTOffset, |
266 devBounds))) { | 267 devBounds))) { |
267 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 268 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
268 scissorSpaceIBounds.offset(-clipDataIn->fOrigin); | 269 scissorSpaceIBounds.offset(-clipDataIn->fOrigin); |
269 if (NULL == devBounds || | 270 if (NULL == devBounds || |
270 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { | 271 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { |
271 scissorState->set(scissorSpaceIBounds); | 272 scissorState->set(scissorSpaceIBounds); |
272 } | 273 } |
273 this->setDrawStateStencil(drawState, ars); | 274 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
274 return true; | 275 return true; |
275 } | 276 } |
276 } | 277 } |
277 | 278 |
278 #if GR_AA_CLIP | 279 #if GR_AA_CLIP |
279 // If MSAA is enabled we can do everything in the stencil buffer. | 280 // If MSAA is enabled we can do everything in the stencil buffer. |
280 if (0 == rt->numSamples() && requiresAA) { | 281 if (0 == rt->numSamples() && requiresAA) { |
281 GrTexture* result = NULL; | 282 GrTexture* result = NULL; |
282 | 283 |
283 // The top-left of the mask corresponds to the top-left corner of the bo
unds. | 284 // The top-left of the mask corresponds to the top-left corner of the bo
unds. |
284 SkVector clipToMaskOffset = { | 285 SkVector clipToMaskOffset = { |
285 SkIntToScalar(-clipSpaceIBounds.fLeft), | 286 SkIntToScalar(-clipSpaceIBounds.fLeft), |
286 SkIntToScalar(-clipSpaceIBounds.fTop) | 287 SkIntToScalar(-clipSpaceIBounds.fTop) |
287 }; | 288 }; |
288 | 289 |
289 if (this->useSWOnlyPath(drawState, clipToMaskOffset, elements)) { | 290 if (this->useSWOnlyPath(pipelineBuilder, clipToMaskOffset, elements)) { |
290 // The clip geometry is complex enough that it will be more efficien
t to create it | 291 // The clip geometry is complex enough that it will be more efficien
t to create it |
291 // entirely in software | 292 // entirely in software |
292 result = this->createSoftwareClipMask(genID, | 293 result = this->createSoftwareClipMask(genID, |
293 initialState, | 294 initialState, |
294 elements, | 295 elements, |
295 clipToMaskOffset, | 296 clipToMaskOffset, |
296 clipSpaceIBounds); | 297 clipSpaceIBounds); |
297 } else { | 298 } else { |
298 result = this->createAlphaClipMask(genID, | 299 result = this->createAlphaClipMask(genID, |
299 initialState, | 300 initialState, |
300 elements, | 301 elements, |
301 clipToMaskOffset, | 302 clipToMaskOffset, |
302 clipSpaceIBounds); | 303 clipSpaceIBounds); |
303 } | 304 } |
304 | 305 |
305 if (result) { | 306 if (result) { |
306 // The mask's top left coord should be pinned to the rounded-out top
left corner of | 307 // The mask's top left coord should be pinned to the rounded-out top
left corner of |
307 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. | 308 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. |
308 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; | 309 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
309 rtSpaceMaskBounds.offset(-clipDataIn->fOrigin); | 310 rtSpaceMaskBounds.offset(-clipDataIn->fOrigin); |
310 setup_drawstate_aaclip(rtSpaceMaskBounds, drawState, result); | 311 setup_drawstate_aaclip(rtSpaceMaskBounds, pipelineBuilder, result); |
311 this->setDrawStateStencil(drawState, ars); | 312 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
312 return true; | 313 return true; |
313 } | 314 } |
314 // if alpha clip mask creation fails fall through to the non-AA code pat
hs | 315 // if alpha clip mask creation fails fall through to the non-AA code pat
hs |
315 } | 316 } |
316 #endif // GR_AA_CLIP | 317 #endif // GR_AA_CLIP |
317 | 318 |
318 // Either a hard (stencil buffer) clip was explicitly requested or an anti-a
liased clip couldn't | 319 // Either a hard (stencil buffer) clip was explicitly requested or an anti-a
liased clip couldn't |
319 // be created. In either case, free up the texture in the anti-aliased mask
cache. | 320 // be created. In either case, free up the texture in the anti-aliased mask
cache. |
320 // TODO: this may require more investigation. Ganesh performs a lot of utili
ty draws (e.g., | 321 // TODO: this may require more investigation. Ganesh performs a lot of utili
ty draws (e.g., |
321 // clears, InOrderDrawBuffer playbacks) that hit the stencil buffer path. Th
ese may be | 322 // clears, InOrderDrawBuffer playbacks) that hit the stencil buffer path. Th
ese may be |
322 // "incorrectly" clearing the AA cache. | 323 // "incorrectly" clearing the AA cache. |
323 fAACache.reset(); | 324 fAACache.reset(); |
324 | 325 |
325 // use the stencil clip if we can't represent the clip as a rectangle. | 326 // use the stencil clip if we can't represent the clip as a rectangle. |
326 SkIPoint clipSpaceToStencilSpaceOffset = -clipDataIn->fOrigin; | 327 SkIPoint clipSpaceToStencilSpaceOffset = -clipDataIn->fOrigin; |
327 this->createStencilClipMask(rt, | 328 this->createStencilClipMask(rt, |
328 genID, | 329 genID, |
329 initialState, | 330 initialState, |
330 elements, | 331 elements, |
331 clipSpaceIBounds, | 332 clipSpaceIBounds, |
332 clipSpaceToStencilSpaceOffset); | 333 clipSpaceToStencilSpaceOffset); |
333 | 334 |
334 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it | 335 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it |
335 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must | 336 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must |
336 // use both stencil and scissor test to the bounds for the final draw. | 337 // use both stencil and scissor test to the bounds for the final draw. |
337 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 338 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
338 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 339 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
339 scissorState->set(scissorSpaceIBounds); | 340 scissorState->set(scissorSpaceIBounds); |
340 this->setDrawStateStencil(drawState, ars); | 341 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
341 return true; | 342 return true; |
342 } | 343 } |
343 | 344 |
344 namespace { | 345 namespace { |
345 //////////////////////////////////////////////////////////////////////////////// | 346 //////////////////////////////////////////////////////////////////////////////// |
346 // Set a coverage drawing XPF on the drawState for the given op and invertCovera
ge mode | 347 // Set a coverage drawing XPF on the pipelineBuilder for the given op and invert
Coverage mode |
347 void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage, GrDrawState*
drawState) { | 348 void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage, |
| 349 GrPipelineBuilder* pipelineBuilder) { |
348 SkASSERT(op <= SkRegion::kLastOp); | 350 SkASSERT(op <= SkRegion::kLastOp); |
349 drawState->setCoverageSetOpXPFactory(op, invertCoverage); | 351 pipelineBuilder->setCoverageSetOpXPFactory(op, invertCoverage); |
350 } | 352 } |
351 } | 353 } |
352 | 354 |
353 //////////////////////////////////////////////////////////////////////////////// | 355 //////////////////////////////////////////////////////////////////////////////// |
354 bool GrClipMaskManager::drawElement(GrDrawState* drawState, | 356 bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder, |
355 const SkMatrix& viewMatrix, | 357 const SkMatrix& viewMatrix, |
356 GrTexture* target, | 358 GrTexture* target, |
357 const SkClipStack::Element* element, | 359 const SkClipStack::Element* element, |
358 GrPathRenderer* pr) { | 360 GrPathRenderer* pr) { |
359 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 361 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
360 | 362 |
361 drawState->setRenderTarget(target->asRenderTarget()); | 363 pipelineBuilder->setRenderTarget(target->asRenderTarget()); |
362 | 364 |
363 // The color we use to draw does not matter since we will always be using a
GrCoverageSetOpXP | 365 // The color we use to draw does not matter since we will always be using a
GrCoverageSetOpXP |
364 // which ignores color. | 366 // which ignores color. |
365 GrColor color = GrColor_WHITE; | 367 GrColor color = GrColor_WHITE; |
366 | 368 |
367 // TODO: Draw rrects directly here. | 369 // TODO: Draw rrects directly here. |
368 switch (element->getType()) { | 370 switch (element->getType()) { |
369 case Element::kEmpty_Type: | 371 case Element::kEmpty_Type: |
370 SkDEBUGFAIL("Should never get here with an empty element."); | 372 SkDEBUGFAIL("Should never get here with an empty element."); |
371 break; | 373 break; |
372 case Element::kRect_Type: | 374 case Element::kRect_Type: |
373 // TODO: Do rects directly to the accumulator using a aa-rect GrProc
essor that covers | 375 // TODO: Do rects directly to the accumulator using a aa-rect GrProc
essor that covers |
374 // the entire mask bounds and writes 0 outside the rect. | 376 // the entire mask bounds and writes 0 outside the rect. |
375 if (element->isAA()) { | 377 if (element->isAA()) { |
376 SkRect devRect = element->getRect(); | 378 SkRect devRect = element->getRect(); |
377 viewMatrix.mapRect(&devRect); | 379 viewMatrix.mapRect(&devRect); |
378 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, | 380 this->getContext()->getAARectRenderer()->fillAARect(fClipTarget, |
379 drawState, | 381 pipelineBuil
der, |
380 color, | 382 color, |
381 viewMatrix, | 383 viewMatrix, |
382 element->get
Rect(), | 384 element->get
Rect(), |
383 devRect); | 385 devRect); |
384 } else { | 386 } else { |
385 fClipTarget->drawSimpleRect(drawState, color, viewMatrix, elemen
t->getRect()); | 387 fClipTarget->drawSimpleRect(pipelineBuilder, color, viewMatrix,
element->getRect()); |
386 } | 388 } |
387 return true; | 389 return true; |
388 default: { | 390 default: { |
389 SkPath path; | 391 SkPath path; |
390 element->asPath(&path); | 392 element->asPath(&path); |
391 path.setIsVolatile(true); | 393 path.setIsVolatile(true); |
392 if (path.isInverseFillType()) { | 394 if (path.isInverseFillType()) { |
393 path.toggleInverseFillType(); | 395 path.toggleInverseFillType(); |
394 } | 396 } |
395 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 397 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
396 if (NULL == pr) { | 398 if (NULL == pr) { |
397 GrPathRendererChain::DrawType type; | 399 GrPathRendererChain::DrawType type; |
398 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr
awType : | 400 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr
awType : |
399 GrPathRendererChain::kColor_DrawType; | 401 GrPathRendererChain::kColor_DrawType; |
400 pr = this->getContext()->getPathRenderer(fClipTarget, drawState,
viewMatrix, path, | 402 pr = this->getContext()->getPathRenderer(fClipTarget, pipelineBu
ilder, viewMatrix, |
401 stroke, false, type); | 403 path, stroke, false, ty
pe); |
402 } | 404 } |
403 if (NULL == pr) { | 405 if (NULL == pr) { |
404 return false; | 406 return false; |
405 } | 407 } |
406 | 408 |
407 pr->drawPath(fClipTarget, drawState, color, viewMatrix, path, stroke
, element->isAA()); | 409 pr->drawPath(fClipTarget, pipelineBuilder, color, viewMatrix, path,
stroke, |
| 410 element->isAA()); |
408 break; | 411 break; |
409 } | 412 } |
410 } | 413 } |
411 return true; | 414 return true; |
412 } | 415 } |
413 | 416 |
414 bool GrClipMaskManager::canStencilAndDrawElement(GrDrawState* drawState, | 417 bool GrClipMaskManager::canStencilAndDrawElement(GrPipelineBuilder* pipelineBuil
der, |
415 GrTexture* target, | 418 GrTexture* target, |
416 GrPathRenderer** pr, | 419 GrPathRenderer** pr, |
417 const SkClipStack::Element* ele
ment) { | 420 const SkClipStack::Element* ele
ment) { |
418 drawState->setRenderTarget(target->asRenderTarget()); | 421 pipelineBuilder->setRenderTarget(target->asRenderTarget()); |
419 | 422 |
420 if (Element::kRect_Type == element->getType()) { | 423 if (Element::kRect_Type == element->getType()) { |
421 return true; | 424 return true; |
422 } else { | 425 } else { |
423 // We shouldn't get here with an empty clip element. | 426 // We shouldn't get here with an empty clip element. |
424 SkASSERT(Element::kEmpty_Type != element->getType()); | 427 SkASSERT(Element::kEmpty_Type != element->getType()); |
425 SkPath path; | 428 SkPath path; |
426 element->asPath(&path); | 429 element->asPath(&path); |
427 if (path.isInverseFillType()) { | 430 if (path.isInverseFillType()) { |
428 path.toggleInverseFillType(); | 431 path.toggleInverseFillType(); |
429 } | 432 } |
430 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 433 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
431 GrPathRendererChain::DrawType type = element->isAA() ? | 434 GrPathRendererChain::DrawType type = element->isAA() ? |
432 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : | 435 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType : |
433 GrPathRendererChain::kStencilAndColor_DrawType; | 436 GrPathRendererChain::kStencilAndColor_DrawType; |
434 *pr = this->getContext()->getPathRenderer(fClipTarget, drawState, SkMatr
ix::I(), path, | 437 *pr = this->getContext()->getPathRenderer(fClipTarget, pipelineBuilder,
SkMatrix::I(), path, |
435 stroke, false, type); | 438 stroke, false, type); |
436 return SkToBool(*pr); | 439 return SkToBool(*pr); |
437 } | 440 } |
438 } | 441 } |
439 | 442 |
440 void GrClipMaskManager::mergeMask(GrDrawState* drawState, | 443 void GrClipMaskManager::mergeMask(GrPipelineBuilder* pipelineBuilder, |
441 GrTexture* dstMask, | 444 GrTexture* dstMask, |
442 GrTexture* srcMask, | 445 GrTexture* srcMask, |
443 SkRegion::Op op, | 446 SkRegion::Op op, |
444 const SkIRect& dstBound, | 447 const SkIRect& dstBound, |
445 const SkIRect& srcBound) { | 448 const SkIRect& srcBound) { |
446 drawState->setRenderTarget(dstMask->asRenderTarget()); | 449 pipelineBuilder->setRenderTarget(dstMask->asRenderTarget()); |
447 | 450 |
448 // We want to invert the coverage here | 451 // We want to invert the coverage here |
449 set_coverage_drawing_xpf(op, false, drawState); | 452 set_coverage_drawing_xpf(op, false, pipelineBuilder); |
450 | 453 |
451 SkMatrix sampleM; | 454 SkMatrix sampleM; |
452 sampleM.setIDiv(srcMask->width(), srcMask->height()); | 455 sampleM.setIDiv(srcMask->width(), srcMask->height()); |
453 | 456 |
454 drawState->addCoverageProcessor( | 457 pipelineBuilder->addCoverageProcessor( |
455 GrTextureDomainEffect::Create(srcMask, | 458 GrTextureDomainEffect::Create(srcMask, |
456 sampleM, | 459 sampleM, |
457 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), | 460 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), |
458 GrTextureDomain::kDecal_Mode, | 461 GrTextureDomain::kDecal_Mode, |
459 GrTextureParams::kNone_FilterMode))->unref
(); | 462 GrTextureParams::kNone_FilterMode))->unref
(); |
460 // The color passed in here does not matter since the coverageSetOpXP won't
read it. | 463 // The color passed in here does not matter since the coverageSetOpXP won't
read it. |
461 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkMatrix::I(), SkRect:
:Make(dstBound)); | 464 fClipTarget->drawSimpleRect(pipelineBuilder, GrColor_WHITE, SkMatrix::I(), |
| 465 SkRect::Make(dstBound)); |
462 } | 466 } |
463 | 467 |
464 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { | 468 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { |
465 GrSurfaceDesc desc; | 469 GrSurfaceDesc desc; |
466 desc.fFlags = kRenderTarget_GrSurfaceFlag; | 470 desc.fFlags = kRenderTarget_GrSurfaceFlag; |
467 desc.fWidth = width; | 471 desc.fWidth = width; |
468 desc.fHeight = height; | 472 desc.fHeight = height; |
469 if (this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { | 473 if (this->getContext()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { |
470 desc.fConfig = kAlpha_8_GrPixelConfig; | 474 desc.fConfig = kAlpha_8_GrPixelConfig; |
471 } else { | 475 } else { |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
556 // cleared. | 560 // cleared. |
557 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); | 561 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); |
558 SkAutoTUnref<GrTexture> temp; | 562 SkAutoTUnref<GrTexture> temp; |
559 | 563 |
560 // walk through each clip element and perform its set op | 564 // walk through each clip element and perform its set op |
561 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { | 565 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { |
562 const Element* element = iter.get(); | 566 const Element* element = iter.get(); |
563 SkRegion::Op op = element->getOp(); | 567 SkRegion::Op op = element->getOp(); |
564 bool invert = element->isInverseFilled(); | 568 bool invert = element->isInverseFilled(); |
565 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { | 569 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { |
566 GrDrawState drawState; | 570 GrPipelineBuilder pipelineBuilder; |
567 drawState.enableState(GrDrawState::kClip_StateBit); | 571 pipelineBuilder.enableState(GrPipelineBuilder::kClip_StateBit); |
568 | 572 |
569 GrPathRenderer* pr = NULL; | 573 GrPathRenderer* pr = NULL; |
570 bool useTemp = !this->canStencilAndDrawElement(&drawState, result, &
pr, element); | 574 bool useTemp = !this->canStencilAndDrawElement(&pipelineBuilder, res
ult, &pr, element); |
571 GrTexture* dst; | 575 GrTexture* dst; |
572 // This is the bounds of the clip element in the space of the alpha-
mask. The temporary | 576 // This is the bounds of the clip element in the space of the alpha-
mask. The temporary |
573 // mask buffer can be substantially larger than the actually clip st
ack element. We | 577 // mask buffer can be substantially larger than the actually clip st
ack element. We |
574 // touch the minimum number of pixels necessary and use decal mode t
o combine it with | 578 // touch the minimum number of pixels necessary and use decal mode t
o combine it with |
575 // the accumulator. | 579 // the accumulator. |
576 SkIRect maskSpaceElementIBounds; | 580 SkIRect maskSpaceElementIBounds; |
577 | 581 |
578 if (useTemp) { | 582 if (useTemp) { |
579 if (invert) { | 583 if (invert) { |
580 maskSpaceElementIBounds = maskSpaceIBounds; | 584 maskSpaceElementIBounds = maskSpaceIBounds; |
(...skipping 10 matching lines...) Expand all Loading... |
591 fAACache.reset(); | 595 fAACache.reset(); |
592 return NULL; | 596 return NULL; |
593 } | 597 } |
594 } | 598 } |
595 dst = temp; | 599 dst = temp; |
596 // clear the temp target and set blend to replace | 600 // clear the temp target and set blend to replace |
597 fClipTarget->clear(&maskSpaceElementIBounds, | 601 fClipTarget->clear(&maskSpaceElementIBounds, |
598 invert ? 0xffffffff : 0x00000000, | 602 invert ? 0xffffffff : 0x00000000, |
599 true, | 603 true, |
600 dst->asRenderTarget()); | 604 dst->asRenderTarget()); |
601 set_coverage_drawing_xpf(SkRegion::kReplace_Op, invert, &drawSta
te); | 605 set_coverage_drawing_xpf(SkRegion::kReplace_Op, invert, &pipelin
eBuilder); |
602 } else { | 606 } else { |
603 // draw directly into the result with the stencil set to make th
e pixels affected | 607 // draw directly into the result with the stencil set to make th
e pixels affected |
604 // by the clip shape be non-zero. | 608 // by the clip shape be non-zero. |
605 dst = result; | 609 dst = result; |
606 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, | 610 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, |
607 kReplace_StencilOp, | 611 kReplace_StencilOp, |
608 kReplace_StencilOp, | 612 kReplace_StencilOp, |
609 kAlways_StencilFunc, | 613 kAlways_StencilFunc, |
610 0xffff, | 614 0xffff, |
611 0xffff, | 615 0xffff, |
612 0xffff); | 616 0xffff); |
613 drawState.setStencil(kStencilInElement); | 617 pipelineBuilder.setStencil(kStencilInElement); |
614 set_coverage_drawing_xpf(op, invert, &drawState); | 618 set_coverage_drawing_xpf(op, invert, &pipelineBuilder); |
615 } | 619 } |
616 | 620 |
617 if (!this->drawElement(&drawState, translate, dst, element, pr)) { | 621 if (!this->drawElement(&pipelineBuilder, translate, dst, element, pr
)) { |
618 fAACache.reset(); | 622 fAACache.reset(); |
619 return NULL; | 623 return NULL; |
620 } | 624 } |
621 | 625 |
622 if (useTemp) { | 626 if (useTemp) { |
623 GrDrawState backgroundDrawState; | 627 GrPipelineBuilder backgroundPipelineBuilder; |
624 backgroundDrawState.enableState(GrDrawState::kClip_StateBit); | 628 backgroundPipelineBuilder.enableState(GrPipelineBuilder::kClip_S
tateBit); |
625 backgroundDrawState.setRenderTarget(result->asRenderTarget()); | 629 backgroundPipelineBuilder.setRenderTarget(result->asRenderTarget
()); |
626 | 630 |
627 // Now draw into the accumulator using the real operation and th
e temp buffer as a | 631 // Now draw into the accumulator using the real operation and th
e temp buffer as a |
628 // texture | 632 // texture |
629 this->mergeMask(&backgroundDrawState, | 633 this->mergeMask(&backgroundPipelineBuilder, |
630 result, | 634 result, |
631 temp, | 635 temp, |
632 op, | 636 op, |
633 maskSpaceIBounds, | 637 maskSpaceIBounds, |
634 maskSpaceElementIBounds); | 638 maskSpaceElementIBounds); |
635 } else { | 639 } else { |
636 GrDrawState backgroundDrawState; | 640 GrPipelineBuilder backgroundPipelineBuilder; |
637 backgroundDrawState.enableState(GrDrawState::kClip_StateBit); | 641 backgroundPipelineBuilder.enableState(GrPipelineBuilder::kClip_S
tateBit); |
638 backgroundDrawState.setRenderTarget(result->asRenderTarget()); | 642 backgroundPipelineBuilder.setRenderTarget(result->asRenderTarget
()); |
639 | 643 |
640 set_coverage_drawing_xpf(op, !invert, &backgroundDrawState); | 644 set_coverage_drawing_xpf(op, !invert, &backgroundPipelineBuilder
); |
641 // Draw to the exterior pixels (those with a zero stencil value)
. | 645 // Draw to the exterior pixels (those with a zero stencil value)
. |
642 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, | 646 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, |
643 kZero_StencilOp, | 647 kZero_StencilOp, |
644 kZero_StencilOp, | 648 kZero_StencilOp, |
645 kEqual_StencilFunc, | 649 kEqual_StencilFunc, |
646 0xffff, | 650 0xffff, |
647 0x0000, | 651 0x0000, |
648 0xffff); | 652 0xffff); |
649 backgroundDrawState.setStencil(kDrawOutsideElement); | 653 backgroundPipelineBuilder.setStencil(kDrawOutsideElement); |
650 // The color passed in here does not matter since the coverageSe
tOpXP won't read it. | 654 // The color passed in here does not matter since the coverageSe
tOpXP won't read it. |
651 fClipTarget->drawSimpleRect(&backgroundDrawState, GrColor_WHITE,
translate, | 655 fClipTarget->drawSimpleRect(&backgroundPipelineBuilder, GrColor_
WHITE, translate, |
652 clipSpaceIBounds); | 656 clipSpaceIBounds); |
653 } | 657 } |
654 } else { | 658 } else { |
655 GrDrawState drawState; | 659 GrPipelineBuilder pipelineBuilder; |
656 drawState.enableState(GrDrawState::kClip_StateBit); | 660 pipelineBuilder.enableState(GrPipelineBuilder::kClip_StateBit); |
657 | 661 |
658 // all the remaining ops can just be directly draw into the accumula
tion buffer | 662 // all the remaining ops can just be directly draw into the accumula
tion buffer |
659 set_coverage_drawing_xpf(op, false, &drawState); | 663 set_coverage_drawing_xpf(op, false, &pipelineBuilder); |
660 // The color passed in here does not matter since the coverageSetOpX
P won't read it. | 664 // The color passed in here does not matter since the coverageSetOpX
P won't read it. |
661 this->drawElement(&drawState, translate, result, element); | 665 this->drawElement(&pipelineBuilder, translate, result, element); |
662 } | 666 } |
663 } | 667 } |
664 | 668 |
665 fCurrClipMaskType = kAlpha_ClipMaskType; | 669 fCurrClipMaskType = kAlpha_ClipMaskType; |
666 return result; | 670 return result; |
667 } | 671 } |
668 | 672 |
669 //////////////////////////////////////////////////////////////////////////////// | 673 //////////////////////////////////////////////////////////////////////////////// |
670 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 674 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
671 // (as opposed to canvas) coordinates | 675 // (as opposed to canvas) coordinates |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
705 | 709 |
706 fClipTarget->clearStencilClip(stencilSpaceIBounds, | 710 fClipTarget->clearStencilClip(stencilSpaceIBounds, |
707 GrReducedClip::kAllIn_InitialState == init
ialState, | 711 GrReducedClip::kAllIn_InitialState == init
ialState, |
708 rt); | 712 rt); |
709 | 713 |
710 // walk through each clip element and perform its set op | 714 // walk through each clip element and perform its set op |
711 // with the existing clip. | 715 // with the existing clip. |
712 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { | 716 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { |
713 const Element* element = iter.get(); | 717 const Element* element = iter.get(); |
714 | 718 |
715 GrDrawState drawState; | 719 GrPipelineBuilder pipelineBuilder; |
716 drawState.setRenderTarget(rt); | 720 pipelineBuilder.setRenderTarget(rt); |
717 drawState.enableState(GrDrawState::kClip_StateBit); | 721 pipelineBuilder.enableState(GrPipelineBuilder::kClip_StateBit); |
718 | 722 |
719 drawState.setDisableColorXPFactory(); | 723 pipelineBuilder.setDisableColorXPFactory(); |
720 | 724 |
721 // if the target is MSAA then we want MSAA enabled when the clip is
soft | 725 // if the target is MSAA then we want MSAA enabled when the clip is
soft |
722 if (rt->isMultisampled()) { | 726 if (rt->isMultisampled()) { |
723 drawState.setState(GrDrawState::kHWAntialias_StateBit, element->
isAA()); | 727 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_StateBi
t, element->isAA()); |
724 } | 728 } |
725 | 729 |
726 bool fillInverted = false; | 730 bool fillInverted = false; |
727 // enabled at bottom of loop | 731 // enabled at bottom of loop |
728 fClipMode = kIgnoreClip_StencilClipMode; | 732 fClipMode = kIgnoreClip_StencilClipMode; |
729 | 733 |
730 // This will be used to determine whether the clip shape can be rend
ered into the | 734 // This will be used to determine whether the clip shape can be rend
ered into the |
731 // stencil with arbitrary stencil settings. | 735 // stencil with arbitrary stencil settings. |
732 GrPathRenderer::StencilSupport stencilSupport; | 736 GrPathRenderer::StencilSupport stencilSupport; |
733 | 737 |
734 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); | 738 SkStrokeRec stroke(SkStrokeRec::kFill_InitStyle); |
735 SkRegion::Op op = element->getOp(); | 739 SkRegion::Op op = element->getOp(); |
736 | 740 |
737 GrPathRenderer* pr = NULL; | 741 GrPathRenderer* pr = NULL; |
738 SkPath clipPath; | 742 SkPath clipPath; |
739 if (Element::kRect_Type == element->getType()) { | 743 if (Element::kRect_Type == element->getType()) { |
740 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; | 744 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; |
741 fillInverted = false; | 745 fillInverted = false; |
742 } else { | 746 } else { |
743 element->asPath(&clipPath); | 747 element->asPath(&clipPath); |
744 fillInverted = clipPath.isInverseFillType(); | 748 fillInverted = clipPath.isInverseFillType(); |
745 if (fillInverted) { | 749 if (fillInverted) { |
746 clipPath.toggleInverseFillType(); | 750 clipPath.toggleInverseFillType(); |
747 } | 751 } |
748 pr = this->getContext()->getPathRenderer(fClipTarget, | 752 pr = this->getContext()->getPathRenderer(fClipTarget, |
749 &drawState, | 753 &pipelineBuilder, |
750 viewMatrix, | 754 viewMatrix, |
751 clipPath, | 755 clipPath, |
752 stroke, | 756 stroke, |
753 false, | 757 false, |
754 GrPathRendererChain::kS
tencilOnly_DrawType, | 758 GrPathRendererChain::kS
tencilOnly_DrawType, |
755 &stencilSupport); | 759 &stencilSupport); |
756 if (NULL == pr) { | 760 if (NULL == pr) { |
757 return false; | 761 return false; |
758 } | 762 } |
759 } | 763 } |
(...skipping 17 matching lines...) Expand all Loading... |
777 // draw the element to the client stencil bits if necessary | 781 // draw the element to the client stencil bits if necessary |
778 if (!canDrawDirectToClip) { | 782 if (!canDrawDirectToClip) { |
779 GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, | 783 GR_STATIC_CONST_SAME_STENCIL(gDrawToStencil, |
780 kIncClamp_StencilOp, | 784 kIncClamp_StencilOp, |
781 kIncClamp_StencilOp, | 785 kIncClamp_StencilOp, |
782 kAlways_StencilFunc, | 786 kAlways_StencilFunc, |
783 0xffff, | 787 0xffff, |
784 0x0000, | 788 0x0000, |
785 0xffff); | 789 0xffff); |
786 if (Element::kRect_Type == element->getType()) { | 790 if (Element::kRect_Type == element->getType()) { |
787 *drawState.stencil() = gDrawToStencil; | 791 *pipelineBuilder.stencil() = gDrawToStencil; |
788 fClipTarget->drawSimpleRect(&drawState, GrColor_WHITE, viewM
atrix, | 792 fClipTarget->drawSimpleRect(&pipelineBuilder, GrColor_WHITE,
viewMatrix, |
789 element->getRect()); | 793 element->getRect()); |
790 } else { | 794 } else { |
791 if (!clipPath.isEmpty()) { | 795 if (!clipPath.isEmpty()) { |
792 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 796 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
793 if (canRenderDirectToStencil) { | 797 if (canRenderDirectToStencil) { |
794 *drawState.stencil() = gDrawToStencil; | 798 *pipelineBuilder.stencil() = gDrawToStencil; |
795 pr->drawPath(fClipTarget, &drawState, GrColor_WHITE,
viewMatrix, | 799 pr->drawPath(fClipTarget, &pipelineBuilder, GrColor_
WHITE, viewMatrix, |
796 clipPath, stroke, false); | 800 clipPath, stroke, false); |
797 } else { | 801 } else { |
798 pr->stencilPath(fClipTarget, &drawState, viewMatrix,
clipPath, stroke); | 802 pr->stencilPath(fClipTarget, &pipelineBuilder, viewM
atrix, clipPath, |
| 803 stroke); |
799 } | 804 } |
800 } | 805 } |
801 } | 806 } |
802 } | 807 } |
803 | 808 |
804 // now we modify the clip bit by rendering either the clip | 809 // now we modify the clip bit by rendering either the clip |
805 // element directly or a bounding rect of the entire clip. | 810 // element directly or a bounding rect of the entire clip. |
806 fClipMode = kModifyClip_StencilClipMode; | 811 fClipMode = kModifyClip_StencilClipMode; |
807 for (int p = 0; p < passes; ++p) { | 812 for (int p = 0; p < passes; ++p) { |
808 GrDrawState drawStateCopy(drawState); | 813 GrPipelineBuilder pipelineBuilderCopy(pipelineBuilder); |
809 *drawStateCopy.stencil() = stencilSettings[p]; | 814 *pipelineBuilderCopy.stencil() = stencilSettings[p]; |
810 | 815 |
811 if (canDrawDirectToClip) { | 816 if (canDrawDirectToClip) { |
812 if (Element::kRect_Type == element->getType()) { | 817 if (Element::kRect_Type == element->getType()) { |
813 fClipTarget->drawSimpleRect(&drawStateCopy, GrColor_WHIT
E, viewMatrix, | 818 fClipTarget->drawSimpleRect(&pipelineBuilderCopy, GrColo
r_WHITE, viewMatrix, |
814 element->getRect()); | 819 element->getRect()); |
815 } else { | 820 } else { |
816 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 821 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
817 pr->drawPath(fClipTarget, &drawStateCopy, GrColor_WHITE,
viewMatrix, | 822 pr->drawPath(fClipTarget, &pipelineBuilderCopy, GrColor_
WHITE, viewMatrix, |
818 clipPath, stroke, false); | 823 clipPath, stroke, false); |
819 } | 824 } |
820 } else { | 825 } else { |
821 // The view matrix is setup to do clip space -> stencil spac
e translation, so | 826 // The view matrix is setup to do clip space -> stencil spac
e translation, so |
822 // draw rect in clip space. | 827 // draw rect in clip space. |
823 fClipTarget->drawSimpleRect(&drawStateCopy, GrColor_WHITE, v
iewMatrix, | 828 fClipTarget->drawSimpleRect(&pipelineBuilderCopy, GrColor_WH
ITE, viewMatrix, |
824 SkRect::Make(clipSpaceIBounds)); | 829 SkRect::Make(clipSpaceIBounds)); |
825 } | 830 } |
826 } | 831 } |
827 } | 832 } |
828 } | 833 } |
829 // set this last because recursive draws may overwrite it back to kNone. | 834 // set this last because recursive draws may overwrite it back to kNone. |
830 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); | 835 SkASSERT(kNone_ClipMaskType == fCurrClipMaskType); |
831 fCurrClipMaskType = kStencil_ClipMaskType; | 836 fCurrClipMaskType = kStencil_ClipMaskType; |
832 fClipMode = kRespectClip_StencilClipMode; | 837 fClipMode = kRespectClip_StencilClipMode; |
833 return true; | 838 return true; |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
878 kKeep_StencilOp, | 883 kKeep_StencilOp, |
879 kKeep_StencilOp, | 884 kKeep_StencilOp, |
880 kAlwaysIfInClip_StencilFunc, | 885 kAlwaysIfInClip_StencilFunc, |
881 0x0000, | 886 0x0000, |
882 0x0000, | 887 0x0000, |
883 0x0000); | 888 0x0000); |
884 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); | 889 return *GR_CONST_STENCIL_SETTINGS_PTR_FROM_STRUCT_PTR(&gSettings); |
885 } | 890 } |
886 } | 891 } |
887 | 892 |
888 void GrClipMaskManager::setDrawStateStencil(GrDrawState* drawState, | 893 void GrClipMaskManager::setPipelineBuilderStencil(GrPipelineBuilder* pipelineBui
lder, |
889 GrDrawState::AutoRestoreStencil* ars
) { | 894 GrPipelineBuilder::AutoRestore
Stencil* ars) { |
890 // We make two copies of the StencilSettings here (except in the early | 895 // We make two copies of the StencilSettings here (except in the early |
891 // exit scenario. One copy from draw state to the stack var. Then another | 896 // exit scenario. One copy from draw state to the stack var. Then another |
892 // from the stack var to the gpu. We could make this class hold a ptr to | 897 // from the stack var to the gpu. We could make this class hold a ptr to |
893 // GrGpu's fStencilSettings and eliminate the stack copy here. | 898 // GrGpu's fStencilSettings and eliminate the stack copy here. |
894 | 899 |
895 // use stencil for clipping if clipping is enabled and the clip | 900 // use stencil for clipping if clipping is enabled and the clip |
896 // has been written into the stencil. | 901 // has been written into the stencil. |
897 GrStencilSettings settings; | 902 GrStencilSettings settings; |
898 | 903 |
899 // The GrGpu client may not be using the stencil buffer but we may need to | 904 // The GrGpu client may not be using the stencil buffer but we may need to |
900 // enable it in order to respect a stencil clip. | 905 // enable it in order to respect a stencil clip. |
901 if (drawState->getStencil().isDisabled()) { | 906 if (pipelineBuilder->getStencil().isDisabled()) { |
902 if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) { | 907 if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) { |
903 settings = basic_apply_stencil_clip_settings(); | 908 settings = basic_apply_stencil_clip_settings(); |
904 } else { | 909 } else { |
905 return; | 910 return; |
906 } | 911 } |
907 } else { | 912 } else { |
908 settings = drawState->getStencil(); | 913 settings = pipelineBuilder->getStencil(); |
909 } | 914 } |
910 | 915 |
911 // TODO: dynamically attach a stencil buffer | 916 // TODO: dynamically attach a stencil buffer |
912 int stencilBits = 0; | 917 int stencilBits = 0; |
913 GrStencilBuffer* stencilBuffer = drawState->getRenderTarget()->getStencilBuf
fer(); | 918 GrStencilBuffer* stencilBuffer = pipelineBuilder->getRenderTarget()->getSten
cilBuffer(); |
914 if (stencilBuffer) { | 919 if (stencilBuffer) { |
915 stencilBits = stencilBuffer->bits(); | 920 stencilBits = stencilBuffer->bits(); |
916 } | 921 } |
917 | 922 |
918 SkASSERT(fClipTarget->caps()->stencilWrapOpsSupport() || !settings.usesWrapO
p()); | 923 SkASSERT(fClipTarget->caps()->stencilWrapOpsSupport() || !settings.usesWrapO
p()); |
919 SkASSERT(fClipTarget->caps()->twoSidedStencilSupport() || !settings.isTwoSid
ed()); | 924 SkASSERT(fClipTarget->caps()->twoSidedStencilSupport() || !settings.isTwoSid
ed()); |
920 this->adjustStencilParams(&settings, fClipMode, stencilBits); | 925 this->adjustStencilParams(&settings, fClipMode, stencilBits); |
921 ars->set(drawState); | 926 ars->set(pipelineBuilder); |
922 drawState->setStencil(settings); | 927 pipelineBuilder->setStencil(settings); |
923 } | 928 } |
924 | 929 |
925 void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, | 930 void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, |
926 StencilClipMode mode, | 931 StencilClipMode mode, |
927 int stencilBitCnt) { | 932 int stencilBitCnt) { |
928 SkASSERT(stencilBitCnt > 0); | 933 SkASSERT(stencilBitCnt > 0); |
929 | 934 |
930 if (kModifyClip_StencilClipMode == mode) { | 935 if (kModifyClip_StencilClipMode == mode) { |
931 // We assume that this clip manager itself is drawing to the GrGpu and | 936 // We assume that this clip manager itself is drawing to the GrGpu and |
932 // has already setup the correct values. | 937 // has already setup the correct values. |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1086 } | 1091 } |
1087 | 1092 |
1088 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu
ffer, | 1093 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu
ffer, |
1089 GrStencilSettings* settings) { | 1094 GrStencilSettings* settings) { |
1090 // TODO: dynamically attach a stencil buffer | 1095 // TODO: dynamically attach a stencil buffer |
1091 if (stencilBuffer) { | 1096 if (stencilBuffer) { |
1092 int stencilBits = stencilBuffer->bits(); | 1097 int stencilBits = stencilBuffer->bits(); |
1093 this->adjustStencilParams(settings, fClipMode, stencilBits); | 1098 this->adjustStencilParams(settings, fClipMode, stencilBits); |
1094 } | 1099 } |
1095 } | 1100 } |
OLD | NEW |