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 "GrCaps.h" | 9 #include "GrCaps.h" |
10 #include "GrDrawingManager.h" | 10 #include "GrDrawingManager.h" |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
55 const SkRect& rect) { | 55 const SkRect& rect) { |
56 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, v
iewMatrix, rect, | 56 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, v
iewMatrix, rect, |
57 nullptr,
nullptr)); | 57 nullptr,
nullptr)); |
58 drawTarget->drawBatch(pipelineBuilder, batch); | 58 drawTarget->drawBatch(pipelineBuilder, batch); |
59 } | 59 } |
60 | 60 |
61 // Does the path in 'element' require SW rendering? If so, return true (and, | 61 // Does the path in 'element' require SW rendering? If so, return true (and, |
62 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set | 62 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set |
63 // 'prOut' to the non-SW path renderer that will do the job). | 63 // 'prOut' to the non-SW path renderer that will do the job). |
64 bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context, | 64 bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context, |
65 bool hasUserStencilSettings, | 65 bool isStencilDisabled, |
66 const GrRenderTarget* rt, | 66 const GrRenderTarget* rt, |
67 const SkMatrix& viewMatrix, | 67 const SkMatrix& viewMatrix, |
68 const Element* element, | 68 const Element* element, |
69 GrPathRenderer** prOut, | 69 GrPathRenderer** prOut, |
70 bool needsStencil) { | 70 bool needsStencil) { |
71 if (Element::kRect_Type == element->getType()) { | 71 if (Element::kRect_Type == element->getType()) { |
72 // rects can always be drawn directly w/o using the software path | 72 // rects can always be drawn directly w/o using the software path |
73 // TODO: skip rrects once we're drawing them directly. | 73 // TODO: skip rrects once we're drawing them directly. |
74 if (prOut) { | 74 if (prOut) { |
75 *prOut = nullptr; | 75 *prOut = nullptr; |
(...skipping 21 matching lines...) Expand all Loading... |
97 ? GrPathRendererChain::kColorAntiAlias_DrawType | 97 ? GrPathRendererChain::kColorAntiAlias_DrawType |
98 : GrPathRendererChain::kColor_DrawType; | 98 : GrPathRendererChain::kColor_DrawType; |
99 } | 99 } |
100 | 100 |
101 GrPathRenderer::CanDrawPathArgs canDrawArgs; | 101 GrPathRenderer::CanDrawPathArgs canDrawArgs; |
102 canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); | 102 canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); |
103 canDrawArgs.fViewMatrix = &viewMatrix; | 103 canDrawArgs.fViewMatrix = &viewMatrix; |
104 canDrawArgs.fPath = &path; | 104 canDrawArgs.fPath = &path; |
105 canDrawArgs.fStyle = &GrStyle::SimpleFill(); | 105 canDrawArgs.fStyle = &GrStyle::SimpleFill(); |
106 canDrawArgs.fAntiAlias = element->isAA(); | 106 canDrawArgs.fAntiAlias = element->isAA(); |
107 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings; | 107 canDrawArgs.fIsStencilDisabled = isStencilDisabled; |
108 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled(); | 108 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled(); |
109 | 109 |
110 // the 'false' parameter disallows use of the SW path renderer | 110 // the 'false' parameter disallows use of the SW path renderer |
111 GrPathRenderer* pr = context->drawingManager()->getPathRenderer(canDrawA
rgs, false, type); | 111 GrPathRenderer* pr = context->drawingManager()->getPathRenderer(canDrawA
rgs, false, type); |
112 if (prOut) { | 112 if (prOut) { |
113 *prOut = pr; | 113 *prOut = pr; |
114 } | 114 } |
115 return SkToBool(!pr); | 115 return SkToBool(!pr); |
116 } | 116 } |
117 } | 117 } |
118 | 118 |
119 // Determines whether it is possible to draw the element to both the stencil buf
fer and the | 119 // Determines whether it is possible to draw the element to both the stencil buf
fer and the |
120 // alpha mask simultaneously. If so and the element is a path a compatible path
renderer is | 120 // alpha mask simultaneously. If so and the element is a path a compatible path
renderer is |
121 // also returned. | 121 // also returned. |
122 GrPathRenderer* GrClipMaskManager::GetPathRenderer(GrContext* context, | 122 GrPathRenderer* GrClipMaskManager::GetPathRenderer(GrContext* context, |
123 GrTexture* texture, | 123 GrTexture* texture, |
124 const SkMatrix& viewMatrix, | 124 const SkMatrix& viewMatrix, |
125 const SkClipStack::Element* e
lement) { | 125 const SkClipStack::Element* e
lement) { |
126 GrPathRenderer* pr; | 126 GrPathRenderer* pr; |
127 constexpr bool kNeedsStencil = true; | 127 static const bool kNeedsStencil = true; |
128 constexpr bool kHasUserStencilSettings = false; | 128 static const bool kStencilIsDisabled = true; |
129 PathNeedsSWRenderer(context, | 129 PathNeedsSWRenderer(context, |
130 kHasUserStencilSettings, | 130 kStencilIsDisabled, |
131 texture->asRenderTarget(), | 131 texture->asRenderTarget(), |
132 viewMatrix, | 132 viewMatrix, |
133 element, | 133 element, |
134 &pr, | 134 &pr, |
135 kNeedsStencil); | 135 kNeedsStencil); |
136 return pr; | 136 return pr; |
137 } | 137 } |
138 | 138 |
139 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget, bool debugClipBat
chToBounds) | 139 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget, bool debugClipBat
chToBounds) |
140 : fDrawTarget(drawTarget) | 140 : fDrawTarget(drawTarget) |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
172 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); | 172 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); |
173 | 173 |
174 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { | 174 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { |
175 const Element* element = iter.get(); | 175 const Element* element = iter.get(); |
176 | 176 |
177 SkRegion::Op op = element->getOp(); | 177 SkRegion::Op op = element->getOp(); |
178 bool invert = element->isInverseFilled(); | 178 bool invert = element->isInverseFilled(); |
179 bool needsStencil = invert || | 179 bool needsStencil = invert || |
180 SkRegion::kIntersect_Op == op || SkRegion::kReverseD
ifference_Op == op; | 180 SkRegion::kIntersect_Op == op || SkRegion::kReverseD
ifference_Op == op; |
181 | 181 |
182 if (PathNeedsSWRenderer(context, pipelineBuilder.hasUserStencilSettings(
), | 182 if (PathNeedsSWRenderer(context, pipelineBuilder.getStencil().isDisabled
(), |
183 rt, translate, element, nullptr, needsStencil))
{ | 183 rt, translate, element, nullptr, needsStencil))
{ |
184 return true; | 184 return true; |
185 } | 185 } |
186 } | 186 } |
187 return false; | 187 return false; |
188 } | 188 } |
189 | 189 |
190 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, | 190 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, |
191 bool abortIfAA, | 191 bool abortIfAA, |
192 SkVector& clipToRTOffset, | 192 SkVector& clipToRTOffset, |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
310 *out = GrClip(intersect); | 310 *out = GrClip(intersect); |
311 } else { | 311 } else { |
312 *out = clip; | 312 *out = clip; |
313 } | 313 } |
314 break; | 314 break; |
315 } | 315 } |
316 } | 316 } |
317 } | 317 } |
318 | 318 |
319 bool GrClipMaskManager::setupScissorClip(const GrPipelineBuilder& pipelineBuilde
r, | 319 bool GrClipMaskManager::setupScissorClip(const GrPipelineBuilder& pipelineBuilde
r, |
| 320 GrPipelineBuilder::AutoRestoreStencil*
ars, |
320 const SkIRect& clipScissor, | 321 const SkIRect& clipScissor, |
321 const SkRect* devBounds, | 322 const SkRect* devBounds, |
322 GrAppliedClip* out) { | 323 GrAppliedClip* out) { |
323 SkASSERT(kModifyClip_StencilClipMode != fClipMode); // TODO: Remove fClipMod
e. | 324 if (kRespectClip_StencilClipMode == fClipMode) { |
324 fClipMode = kIgnoreClip_StencilClipMode; | 325 fClipMode = kIgnoreClip_StencilClipMode; |
| 326 } |
325 | 327 |
326 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); | 328 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
327 | 329 |
328 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); | 330 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); |
329 SkIRect devBoundsScissor; | 331 SkIRect devBoundsScissor; |
330 const SkIRect* scissor = &clipScissor; | 332 const SkIRect* scissor = &clipScissor; |
331 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; | 333 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; |
332 if (doDevBoundsClip) { | 334 if (doDevBoundsClip) { |
333 devBounds->roundOut(&devBoundsScissor); | 335 devBounds->roundOut(&devBoundsScissor); |
334 if (devBoundsScissor.intersect(clipScissor)) { | 336 if (devBoundsScissor.intersect(clipScissor)) { |
335 scissor = &devBoundsScissor; | 337 scissor = &devBoundsScissor; |
336 } | 338 } |
337 } | 339 } |
338 | 340 |
339 if (scissor->contains(clipSpaceRTIBounds)) { | 341 if (scissor->contains(clipSpaceRTIBounds)) { |
340 // This counts as wide open | 342 // This counts as wide open |
| 343 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
341 return true; | 344 return true; |
342 } | 345 } |
343 | 346 |
344 if (clipSpaceRTIBounds.intersect(*scissor)) { | 347 if (clipSpaceRTIBounds.intersect(*scissor)) { |
345 out->fScissorState.set(clipSpaceRTIBounds); | 348 out->fScissorState.set(clipSpaceRTIBounds); |
| 349 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
346 return true; | 350 return true; |
347 } | 351 } |
348 return false; | 352 return false; |
349 } | 353 } |
350 | 354 |
351 //////////////////////////////////////////////////////////////////////////////// | 355 //////////////////////////////////////////////////////////////////////////////// |
352 // sort out what kind of clip mask needs to be created: alpha, stencil, | 356 // sort out what kind of clip mask needs to be created: alpha, stencil, |
353 // scissor, or entirely software | 357 // scissor, or entirely software |
354 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, | 358 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, |
| 359 GrPipelineBuilder::AutoRestoreStencil* ars
, |
355 const SkRect* devBounds, | 360 const SkRect* devBounds, |
356 GrAppliedClip* out) { | 361 GrAppliedClip* out) { |
357 if (kRespectClip_StencilClipMode == fClipMode) { | 362 if (kRespectClip_StencilClipMode == fClipMode) { |
358 fClipMode = kIgnoreClip_StencilClipMode; | 363 fClipMode = kIgnoreClip_StencilClipMode; |
359 } | 364 } |
360 | 365 |
361 GrReducedClip::ElementList elements; | 366 GrReducedClip::ElementList elements; |
362 int32_t genID = 0; | 367 int32_t genID = 0; |
363 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat
e; | 368 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat
e; |
364 SkIRect clipSpaceIBounds; | 369 SkIRect clipSpaceIBounds; |
365 bool requiresAA = false; | 370 bool requiresAA = false; |
366 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); | 371 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
367 | 372 |
368 // GrDrawTarget should have filtered this for us | 373 // GrDrawTarget should have filtered this for us |
369 SkASSERT(rt); | 374 SkASSERT(rt); |
370 | 375 |
371 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); | 376 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); |
372 GrClip devBoundsClip; | 377 GrClip devBoundsClip; |
373 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; | 378 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; |
374 if (doDevBoundsClip) { | 379 if (doDevBoundsClip) { |
375 add_rect_to_clip(pipelineBuilder.clip(), *devBounds, &devBoundsClip); | 380 add_rect_to_clip(pipelineBuilder.clip(), *devBounds, &devBoundsClip); |
376 } | 381 } |
377 const GrClip& clip = doDevBoundsClip ? devBoundsClip : pipelineBuilder.clip(
); | 382 const GrClip& clip = doDevBoundsClip ? devBoundsClip : pipelineBuilder.clip(
); |
378 | 383 |
379 if (clip.isWideOpen(clipSpaceRTIBounds)) { | 384 if (clip.isWideOpen(clipSpaceRTIBounds)) { |
| 385 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
380 return true; | 386 return true; |
381 } | 387 } |
382 | 388 |
383 // The clip mask manager always draws with a single IRect so we special case
that logic here | 389 // The clip mask manager always draws with a single IRect so we special case
that logic here |
384 // Image filters just use a rect, so we also special case that logic | 390 // Image filters just use a rect, so we also special case that logic |
385 switch (clip.clipType()) { | 391 switch (clip.clipType()) { |
386 case GrClip::kWideOpen_ClipType: | 392 case GrClip::kWideOpen_ClipType: |
387 SkFAIL("Should have caught this with clip.isWideOpen()"); | 393 SkFAIL("Should have caught this with clip.isWideOpen()"); |
388 return true; | 394 return true; |
389 case GrClip::kIRect_ClipType: { | 395 case GrClip::kIRect_ClipType: { |
390 SkIRect scissor = clip.irect(); | 396 SkIRect scissor = clip.irect(); |
391 if (scissor.intersect(clipSpaceRTIBounds)) { | 397 if (scissor.intersect(clipSpaceRTIBounds)) { |
392 out->fScissorState.set(scissor); | 398 out->fScissorState.set(scissor); |
393 out->fHasStencilClip = kIgnoreClip_StencilClipMode != fClipMode; | 399 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
394 return true; | 400 return true; |
395 } | 401 } |
396 return false; | 402 return false; |
397 } | 403 } |
398 case GrClip::kClipStack_ClipType: { | 404 case GrClip::kClipStack_ClipType: { |
399 clipSpaceRTIBounds.offset(clip.origin()); | 405 clipSpaceRTIBounds.offset(clip.origin()); |
400 SkIRect clipSpaceReduceQueryBounds; | 406 SkIRect clipSpaceReduceQueryBounds; |
401 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0 | 407 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0 |
402 if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) { | 408 if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) { |
403 SkIRect devIBounds = devBounds->roundOut(); | 409 SkIRect devIBounds = devBounds->roundOut(); |
404 devIBounds.offset(clip.origin()); | 410 devIBounds.offset(clip.origin()); |
405 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, de
vIBounds)) { | 411 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, de
vIBounds)) { |
406 return false; | 412 return false; |
407 } | 413 } |
408 } else { | 414 } else { |
409 clipSpaceReduceQueryBounds = clipSpaceRTIBounds; | 415 clipSpaceReduceQueryBounds = clipSpaceRTIBounds; |
410 } | 416 } |
411 GrReducedClip::ReduceClipStack(*clip.clipStack(), | 417 GrReducedClip::ReduceClipStack(*clip.clipStack(), |
412 clipSpaceReduceQueryBounds, | 418 clipSpaceReduceQueryBounds, |
413 &elements, | 419 &elements, |
414 &genID, | 420 &genID, |
415 &initialState, | 421 &initialState, |
416 &clipSpaceIBounds, | 422 &clipSpaceIBounds, |
417 &requiresAA); | 423 &requiresAA); |
418 if (elements.isEmpty()) { | 424 if (elements.isEmpty()) { |
419 if (GrReducedClip::kAllIn_InitialState == initialState) { | 425 if (GrReducedClip::kAllIn_InitialState == initialState) { |
420 if (clipSpaceIBounds == clipSpaceRTIBounds) { | 426 if (clipSpaceIBounds == clipSpaceRTIBounds) { |
| 427 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
421 return true; | 428 return true; |
422 } | 429 } |
423 } else { | 430 } else { |
424 return false; | 431 return false; |
425 } | 432 } |
426 } | 433 } |
427 } break; | 434 } break; |
428 } | 435 } |
429 | 436 |
430 SkASSERT(kIgnoreClip_StencilClipMode == fClipMode); // TODO: Remove fClipMod
e. | |
431 | |
432 // An element count of 4 was chosen because of the common pattern in Blink o
f: | 437 // An element count of 4 was chosen because of the common pattern in Blink o
f: |
433 // isect RR | 438 // isect RR |
434 // diff RR | 439 // diff RR |
435 // isect convex_poly | 440 // isect convex_poly |
436 // isect convex_poly | 441 // isect convex_poly |
437 // when drawing rounded div borders. This could probably be tuned based on a | 442 // when drawing rounded div borders. This could probably be tuned based on a |
438 // configuration's relative costs of switching RTs to generate a mask vs | 443 // configuration's relative costs of switching RTs to generate a mask vs |
439 // longer shaders. | 444 // longer shaders. |
440 if (elements.count() <= kMaxAnalyticElements) { | 445 if (elements.count() <= kMaxAnalyticElements) { |
441 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), | 446 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), |
442 SkIntToScalar(-clip.origin().fY) }; | 447 SkIntToScalar(-clip.origin().fY) }; |
443 // When there are multiple samples we want to do per-sample clipping, no
t compute a | 448 // When there are multiple samples we want to do per-sample clipping, no
t compute a |
444 // fractional pixel coverage. | 449 // fractional pixel coverage. |
445 bool disallowAnalyticAA = rt->isStencilBufferMultisampled(); | 450 bool disallowAnalyticAA = rt->isStencilBufferMultisampled(); |
446 if (disallowAnalyticAA && !rt->numColorSamples()) { | 451 if (disallowAnalyticAA && !rt->numColorSamples()) { |
447 // With a single color sample, any coverage info is lost from color
once it hits the | 452 // With a single color sample, any coverage info is lost from color
once it hits the |
448 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe | 453 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe |
449 // is multisampled. | 454 // is multisampled. |
450 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || | 455 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || |
451 pipelineBuilder.hasUserStencilSettings(); | 456 !pipelineBuilder.getStencil().isDisabled(); |
452 } | 457 } |
453 const GrFragmentProcessor* clipFP = nullptr; | 458 const GrFragmentProcessor* clipFP = nullptr; |
454 if (elements.isEmpty() || | 459 if (elements.isEmpty() || |
455 (requiresAA && | 460 (requiresAA && |
456 this->getAnalyticClipProcessor(elements, disallowAnalyticAA, clipTo
RTOffset, devBounds, | 461 this->getAnalyticClipProcessor(elements, disallowAnalyticAA, clipTo
RTOffset, devBounds, |
457 &clipFP))) { | 462 &clipFP))) { |
458 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 463 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
459 scissorSpaceIBounds.offset(-clip.origin()); | 464 scissorSpaceIBounds.offset(-clip.origin()); |
460 if (nullptr == devBounds || | 465 if (nullptr == devBounds || |
461 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { | 466 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { |
462 out->fScissorState.set(scissorSpaceIBounds); | 467 out->fScissorState.set(scissorSpaceIBounds); |
463 } | 468 } |
| 469 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
464 out->fClipCoverageFP.reset(clipFP); | 470 out->fClipCoverageFP.reset(clipFP); |
465 return true; | 471 return true; |
466 } | 472 } |
467 } | 473 } |
468 | 474 |
469 // If the stencil buffer is multisampled we can use it to do everything. | 475 // If the stencil buffer is multisampled we can use it to do everything. |
470 if (!rt->isStencilBufferMultisampled() && requiresAA) { | 476 if (!rt->isStencilBufferMultisampled() && requiresAA) { |
471 SkAutoTUnref<GrTexture> result; | 477 SkAutoTUnref<GrTexture> result; |
472 | 478 |
473 // The top-left of the mask corresponds to the top-left corner of the bo
unds. | 479 // The top-left of the mask corresponds to the top-left corner of the bo
unds. |
(...skipping 21 matching lines...) Expand all Loading... |
495 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug | 501 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug |
496 SkASSERT(result); | 502 SkASSERT(result); |
497 } | 503 } |
498 | 504 |
499 if (result) { | 505 if (result) { |
500 // The mask's top left coord should be pinned to the rounded-out top
left corner of | 506 // The mask's top left coord should be pinned to the rounded-out top
left corner of |
501 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. | 507 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. |
502 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; | 508 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
503 rtSpaceMaskBounds.offset(-clip.origin()); | 509 rtSpaceMaskBounds.offset(-clip.origin()); |
504 out->fClipCoverageFP.reset(create_fp_for_mask(result, rtSpaceMaskBou
nds)); | 510 out->fClipCoverageFP.reset(create_fp_for_mask(result, rtSpaceMaskBou
nds)); |
| 511 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
505 return true; | 512 return true; |
506 } | 513 } |
507 // if alpha clip mask creation fails fall through to the non-AA code pat
hs | 514 // if alpha clip mask creation fails fall through to the non-AA code pat
hs |
508 } | 515 } |
509 | 516 |
510 // use the stencil clip if we can't represent the clip as a rectangle. | 517 // use the stencil clip if we can't represent the clip as a rectangle. |
511 SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin(); | 518 SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin(); |
512 this->createStencilClipMask(rt, | 519 this->createStencilClipMask(rt, |
513 genID, | 520 genID, |
514 initialState, | 521 initialState, |
515 elements, | 522 elements, |
516 clipSpaceIBounds, | 523 clipSpaceIBounds, |
517 clipSpaceToStencilSpaceOffset); | 524 clipSpaceToStencilSpaceOffset); |
518 | 525 |
519 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it | 526 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it |
520 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must | 527 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must |
521 // use both stencil and scissor test to the bounds for the final draw. | 528 // use both stencil and scissor test to the bounds for the final draw. |
522 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 529 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
523 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 530 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
524 out->fScissorState.set(scissorSpaceIBounds); | 531 out->fScissorState.set(scissorSpaceIBounds); |
525 SkASSERT(kRespectClip_StencilClipMode == fClipMode); // TODO: Remove fClipMo
de. | 532 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
526 out->fHasStencilClip = true; | |
527 return true; | 533 return true; |
528 } | 534 } |
529 | 535 |
530 static bool stencil_element(GrDrawContext* dc, | 536 static bool stencil_element(GrDrawContext* dc, |
531 const SkIRect* scissorRect, | 537 const SkIRect* scissorRect, |
532 const GrUserStencilSettings* ss, | 538 const GrStencilSettings& ss, |
533 const SkMatrix& viewMatrix, | 539 const SkMatrix& viewMatrix, |
534 const SkClipStack::Element* element) { | 540 const SkClipStack::Element* element) { |
535 | 541 |
536 // TODO: Draw rrects directly here. | 542 // TODO: Draw rrects directly here. |
537 switch (element->getType()) { | 543 switch (element->getType()) { |
538 case Element::kEmpty_Type: | 544 case Element::kEmpty_Type: |
539 SkDEBUGFAIL("Should never get here with an empty element."); | 545 SkDEBUGFAIL("Should never get here with an empty element."); |
540 break; | 546 break; |
541 case Element::kRect_Type: | 547 case Element::kRect_Type: |
542 return dc->drawContextPriv().drawAndStencilRect(scissorRect, ss, | 548 return dc->drawContextPriv().drawAndStencilRect(scissorRect, ss, |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
668 if (Element::kRect_Type != element->getType() && !pr) { | 674 if (Element::kRect_Type != element->getType() && !pr) { |
669 // UseSWOnlyPath should now filter out all cases where gpu-side
mask merging would | 675 // UseSWOnlyPath should now filter out all cases where gpu-side
mask merging would |
670 // be performed (i.e., pr would be NULL for a non-rect path). | 676 // be performed (i.e., pr would be NULL for a non-rect path). |
671 // See https://bug.skia.org/4519 for rationale and details. | 677 // See https://bug.skia.org/4519 for rationale and details. |
672 SkASSERT(0); | 678 SkASSERT(0); |
673 } | 679 } |
674 #endif | 680 #endif |
675 | 681 |
676 // draw directly into the result with the stencil set to make the pi
xels affected | 682 // draw directly into the result with the stencil set to make the pi
xels affected |
677 // by the clip shape be non-zero. | 683 // by the clip shape be non-zero. |
678 static constexpr GrUserStencilSettings kStencilInElement( | 684 static constexpr GrStencilSettings kStencilInElement( |
679 GrUserStencilSettings::StaticInit< | 685 kReplace_StencilOp, |
680 0xffff, | 686 kReplace_StencilOp, |
681 GrUserStencilTest::kAlways, | 687 kAlways_StencilFunc, |
682 0xffff, | 688 0xffff, |
683 GrUserStencilOp::kReplace, | 689 0xffff, |
684 GrUserStencilOp::kReplace, | 690 0xffff); |
685 0xffff>() | 691 if (!stencil_element(dc.get(), &maskSpaceIBounds, kStencilInElement, |
686 ); | |
687 if (!stencil_element(dc.get(), &maskSpaceIBounds, &kStencilInElement
, | |
688 translate, element)) { | 692 translate, element)) { |
689 texture->resourcePriv().removeUniqueKey(); | 693 texture->resourcePriv().removeUniqueKey(); |
690 return nullptr; | 694 return nullptr; |
691 } | 695 } |
692 | 696 |
693 // Draw to the exterior pixels (those with a zero stencil value). | 697 // Draw to the exterior pixels (those with a zero stencil value). |
694 static constexpr GrUserStencilSettings kDrawOutsideElement( | 698 static constexpr GrStencilSettings kDrawOutsideElement( |
695 GrUserStencilSettings::StaticInit< | 699 kZero_StencilOp, |
696 0x0000, | 700 kZero_StencilOp, |
697 GrUserStencilTest::kEqual, | 701 kEqual_StencilFunc, |
698 0xffff, | 702 0xffff, |
699 GrUserStencilOp::kZero, | 703 0x0000, |
700 GrUserStencilOp::kZero, | 704 0xffff); |
701 0xffff>() | 705 if (!dc->drawContextPriv().drawAndStencilRect(&maskSpaceIBounds, kDr
awOutsideElement, |
702 ); | |
703 if (!dc->drawContextPriv().drawAndStencilRect(&maskSpaceIBounds, &kD
rawOutsideElement, | |
704 op, !invert, false, | 706 op, !invert, false, |
705 translate, | 707 translate, |
706 SkRect::Make(clipSpace
IBounds))) { | 708 SkRect::Make(clipSpace
IBounds))) { |
707 texture->resourcePriv().removeUniqueKey(); | 709 texture->resourcePriv().removeUniqueKey(); |
708 return nullptr; | 710 return nullptr; |
709 } | 711 } |
710 } else { | 712 } else { |
711 // all the remaining ops can just be directly draw into the accumula
tion buffer | 713 // all the remaining ops can just be directly draw into the accumula
tion buffer |
712 GrPaint paint; | 714 GrPaint paint; |
713 paint.setAntiAlias(element->isAA()); | 715 paint.setAntiAlias(element->isAA()); |
(...skipping 30 matching lines...) Expand all Loading... |
744 SkIntToScalar(clipSpaceToStencilOffset.fY) | 746 SkIntToScalar(clipSpaceToStencilOffset.fY) |
745 }; | 747 }; |
746 SkMatrix viewMatrix; | 748 SkMatrix viewMatrix; |
747 viewMatrix.setTranslate(translate); | 749 viewMatrix.setTranslate(translate); |
748 | 750 |
749 // We set the current clip to the bounds so that our recursive draws are
scissored to them. | 751 // We set the current clip to the bounds so that our recursive draws are
scissored to them. |
750 SkIRect stencilSpaceIBounds(clipSpaceIBounds); | 752 SkIRect stencilSpaceIBounds(clipSpaceIBounds); |
751 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); | 753 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); |
752 GrClip clip(stencilSpaceIBounds); | 754 GrClip clip(stencilSpaceIBounds); |
753 | 755 |
| 756 int clipBit = stencilAttachment->bits(); |
| 757 SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil
buffers"); |
| 758 clipBit = (1 << (clipBit-1)); |
| 759 |
754 fDrawTarget->cmmAccess().clearStencilClip(stencilSpaceIBounds, | 760 fDrawTarget->cmmAccess().clearStencilClip(stencilSpaceIBounds, |
755 GrReducedClip::kAllIn_InitialState == initialState, rt); | 761 GrReducedClip::kAllIn_InitialState == initialState, rt); |
756 | 762 |
757 // walk through each clip element and perform its set op | 763 // walk through each clip element and perform its set op |
758 // with the existing clip. | 764 // with the existing clip. |
759 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { | 765 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { |
760 const Element* element = iter.get(); | 766 const Element* element = iter.get(); |
761 | 767 |
762 GrPipelineBuilder pipelineBuilder; | 768 GrPipelineBuilder pipelineBuilder; |
763 pipelineBuilder.setClip(clip); | 769 pipelineBuilder.setClip(clip); |
(...skipping 21 matching lines...) Expand all Loading... |
785 if (Element::kRect_Type == element->getType()) { | 791 if (Element::kRect_Type == element->getType()) { |
786 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; | 792 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; |
787 fillInverted = false; | 793 fillInverted = false; |
788 } else { | 794 } else { |
789 element->asPath(&clipPath); | 795 element->asPath(&clipPath); |
790 fillInverted = clipPath.isInverseFillType(); | 796 fillInverted = clipPath.isInverseFillType(); |
791 if (fillInverted) { | 797 if (fillInverted) { |
792 clipPath.toggleInverseFillType(); | 798 clipPath.toggleInverseFillType(); |
793 } | 799 } |
794 | 800 |
795 SkASSERT(!pipelineBuilder.hasUserStencilSettings()); | 801 SkASSERT(pipelineBuilder.getStencil().isDisabled()); |
796 | 802 |
797 GrPathRenderer::CanDrawPathArgs canDrawArgs; | 803 GrPathRenderer::CanDrawPathArgs canDrawArgs; |
798 canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps
(); | 804 canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps
(); |
799 canDrawArgs.fViewMatrix = &viewMatrix; | 805 canDrawArgs.fViewMatrix = &viewMatrix; |
800 canDrawArgs.fPath = &clipPath; | 806 canDrawArgs.fPath = &clipPath; |
801 canDrawArgs.fStyle = &GrStyle::SimpleFill(); | 807 canDrawArgs.fStyle = &GrStyle::SimpleFill(); |
802 canDrawArgs.fAntiAlias = false; | 808 canDrawArgs.fAntiAlias = false; |
803 canDrawArgs.fHasUserStencilSettings = pipelineBuilder.hasUserSte
ncilSettings(); | 809 canDrawArgs.fIsStencilDisabled = pipelineBuilder.getStencil().is
Disabled(); |
804 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampl
ed(); | 810 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampl
ed(); |
805 | 811 |
806 pr = this->getContext()->drawingManager()->getPathRenderer(canDr
awArgs, false, | 812 pr = this->getContext()->drawingManager()->getPathRenderer(canDr
awArgs, false, |
807 GrPat
hRendererChain::kStencilOnly_DrawType, | 813 GrPat
hRendererChain::kStencilOnly_DrawType, |
808 &sten
cilSupport); | 814 &sten
cilSupport); |
809 if (nullptr == pr) { | 815 if (nullptr == pr) { |
810 return false; | 816 return false; |
811 } | 817 } |
812 } | 818 } |
813 | 819 |
| 820 int passes; |
| 821 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClip
Passes]; |
| 822 |
814 bool canRenderDirectToStencil = | 823 bool canRenderDirectToStencil = |
815 GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; | 824 GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; |
816 bool drawDirectToClip; // Given the renderer, the element, | 825 bool canDrawDirectToClip; // Given the renderer, the element, |
817 // fill rule, and set operation should | 826 // fill rule, and set operation can |
818 // we render the element directly to | 827 // we render the element directly to |
819 // stencil bit used for clipping. | 828 // stencil bit used for clipping. |
820 GrUserStencilSettings const* const* stencilPasses = | 829 canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, |
821 GrStencilSettings::GetClipPasses(op, canRenderDirectToStencil, f
illInverted, | 830 canRenderDire
ctToStencil, |
822 &drawDirectToClip); | 831 clipBit, |
| 832 fillInverted, |
| 833 &passes, |
| 834 stencilSettin
gs); |
823 | 835 |
824 // draw the element to the client stencil bits if necessary | 836 // draw the element to the client stencil bits if necessary |
825 if (!drawDirectToClip) { | 837 if (!canDrawDirectToClip) { |
826 static constexpr GrUserStencilSettings kDrawToStencil( | 838 static constexpr GrStencilSettings kDrawToStencil( |
827 GrUserStencilSettings::StaticInit< | 839 kIncClamp_StencilOp, |
828 0x0000, | 840 kIncClamp_StencilOp, |
829 GrUserStencilTest::kAlways, | 841 kAlways_StencilFunc, |
830 0xffff, | 842 0xffff, |
831 GrUserStencilOp::kIncMaybeClamp, | 843 0x0000, |
832 GrUserStencilOp::kIncMaybeClamp, | 844 0xffff); |
833 0xffff>() | |
834 ); | |
835 if (Element::kRect_Type == element->getType()) { | 845 if (Element::kRect_Type == element->getType()) { |
836 pipelineBuilder.setUserStencil(&kDrawToStencil); | 846 *pipelineBuilder.stencil() = kDrawToStencil; |
837 | 847 |
838 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, | 848 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, |
839 element->getRect()); | 849 element->getRect()); |
840 } else { | 850 } else { |
841 if (!clipPath.isEmpty()) { | 851 if (!clipPath.isEmpty()) { |
842 if (canRenderDirectToStencil) { | 852 if (canRenderDirectToStencil) { |
843 pipelineBuilder.setUserStencil(&kDrawToStencil); | 853 *pipelineBuilder.stencil() = kDrawToStencil; |
844 | 854 |
845 GrPathRenderer::DrawPathArgs args; | 855 GrPathRenderer::DrawPathArgs args; |
846 args.fTarget = fDrawTarget; | 856 args.fTarget = fDrawTarget; |
847 args.fResourceProvider = this->getContext()->resourc
eProvider(); | 857 args.fResourceProvider = this->getContext()->resourc
eProvider(); |
848 args.fPipelineBuilder = &pipelineBuilder; | 858 args.fPipelineBuilder = &pipelineBuilder; |
849 args.fColor = GrColor_WHITE; | 859 args.fColor = GrColor_WHITE; |
850 args.fViewMatrix = &viewMatrix; | 860 args.fViewMatrix = &viewMatrix; |
851 args.fPath = &clipPath; | 861 args.fPath = &clipPath; |
852 args.fStyle = &GrStyle::SimpleFill(); | 862 args.fStyle = &GrStyle::SimpleFill(); |
853 args.fAntiAlias = false; | 863 args.fAntiAlias = false; |
854 args.fGammaCorrect = false; | 864 args.fGammaCorrect = false; |
855 pr->drawPath(args); | 865 pr->drawPath(args); |
856 } else { | 866 } else { |
857 GrPathRenderer::StencilPathArgs args; | 867 GrPathRenderer::StencilPathArgs args; |
858 args.fTarget = fDrawTarget; | 868 args.fTarget = fDrawTarget; |
859 args.fResourceProvider = this->getContext()->resourc
eProvider(); | 869 args.fResourceProvider = this->getContext()->resourc
eProvider(); |
860 args.fPipelineBuilder = &pipelineBuilder; | 870 args.fPipelineBuilder = &pipelineBuilder; |
861 args.fViewMatrix = &viewMatrix; | 871 args.fViewMatrix = &viewMatrix; |
862 args.fPath = &clipPath; | 872 args.fPath = &clipPath; |
863 pr->stencilPath(args); | 873 pr->stencilPath(args); |
864 } | 874 } |
865 } | 875 } |
866 } | 876 } |
867 } | 877 } |
868 | 878 |
869 // now we modify the clip bit by rendering either the clip | 879 // now we modify the clip bit by rendering either the clip |
870 // element directly or a bounding rect of the entire clip. | 880 // element directly or a bounding rect of the entire clip. |
871 fClipMode = kModifyClip_StencilClipMode; | 881 fClipMode = kModifyClip_StencilClipMode; |
872 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass
; ++pass) { | 882 for (int p = 0; p < passes; ++p) { |
873 pipelineBuilder.setUserStencil(*pass); | 883 *pipelineBuilder.stencil() = stencilSettings[p]; |
874 | 884 |
875 if (drawDirectToClip) { | 885 if (canDrawDirectToClip) { |
876 if (Element::kRect_Type == element->getType()) { | 886 if (Element::kRect_Type == element->getType()) { |
877 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_W
HITE, viewMatrix, | 887 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_W
HITE, viewMatrix, |
878 element->getRect()); | 888 element->getRect()); |
879 } else { | 889 } else { |
880 GrPathRenderer::DrawPathArgs args; | 890 GrPathRenderer::DrawPathArgs args; |
881 args.fTarget = fDrawTarget; | 891 args.fTarget = fDrawTarget; |
882 args.fResourceProvider = this->getContext()->resourcePro
vider(); | 892 args.fResourceProvider = this->getContext()->resourcePro
vider(); |
883 args.fPipelineBuilder = &pipelineBuilder; | 893 args.fPipelineBuilder = &pipelineBuilder; |
884 args.fColor = GrColor_WHITE; | 894 args.fColor = GrColor_WHITE; |
885 args.fViewMatrix = &viewMatrix; | 895 args.fViewMatrix = &viewMatrix; |
886 args.fPath = &clipPath; | 896 args.fPath = &clipPath; |
887 args.fStyle = &GrStyle::SimpleFill(); | 897 args.fStyle = &GrStyle::SimpleFill(); |
888 args.fAntiAlias = false; | 898 args.fAntiAlias = false; |
889 args.fGammaCorrect = false; | 899 args.fGammaCorrect = false; |
890 pr->drawPath(args); | 900 pr->drawPath(args); |
891 } | 901 } |
892 } else { | 902 } else { |
893 // The view matrix is setup to do clip space -> stencil spac
e translation, so | 903 // The view matrix is setup to do clip space -> stencil spac
e translation, so |
894 // draw rect in clip space. | 904 // draw rect in clip space. |
895 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, | 905 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, |
896 SkRect::Make(clipSpaceIBounds)); | 906 SkRect::Make(clipSpaceIBounds)); |
897 } | 907 } |
898 } | 908 } |
899 } | 909 } |
900 } | 910 } |
901 fClipMode = kRespectClip_StencilClipMode; | 911 fClipMode = kRespectClip_StencilClipMode; |
902 return true; | 912 return true; |
903 } | 913 } |
904 | 914 |
| 915 // mapping of clip-respecting stencil funcs to normal stencil funcs |
| 916 // mapping depends on whether stencil-clipping is in effect. |
| 917 static const GrStencilFunc |
| 918 gSpecialToBasicStencilFunc[2][kClipStencilFuncCnt] = { |
| 919 {// Stencil-Clipping is DISABLED, we are effectively always inside the clip |
| 920 // In the Clip Funcs |
| 921 kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc |
| 922 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc |
| 923 kLess_StencilFunc, // kLessIfInClip_StencilFunc |
| 924 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc |
| 925 // Special in the clip func that forces user's ref to be 0. |
| 926 kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc |
| 927 // make ref 0 and do normal nequal. |
| 928 }, |
| 929 {// Stencil-Clipping is ENABLED |
| 930 // In the Clip Funcs |
| 931 kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc |
| 932 // eq stencil clip bit, mask |
| 933 // out user bits. |
| 934 |
| 935 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc |
| 936 // add stencil bit to mask and ref |
| 937 |
| 938 kLess_StencilFunc, // kLessIfInClip_StencilFunc |
| 939 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc |
| 940 // for both of these we can add |
| 941 // the clip bit to the mask and |
| 942 // ref and compare as normal |
| 943 // Special in the clip func that forces user's ref to be 0. |
| 944 kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc |
| 945 // make ref have only the clip bit set |
| 946 // and make comparison be less |
| 947 // 10..0 < 1..user_bits.. |
| 948 } |
| 949 }; |
| 950 |
| 951 void GrClipMaskManager::setPipelineBuilderStencil(const GrPipelineBuilder& pipel
ineBuilder, |
| 952 GrPipelineBuilder::AutoRestore
Stencil* ars) { |
| 953 // We make two copies of the StencilSettings here (except in the early |
| 954 // exit scenario. One copy from draw state to the stack var. Then another |
| 955 // from the stack var to the gpu. We could make this class hold a ptr to |
| 956 // GrGpu's fStencilSettings and eliminate the stack copy here. |
| 957 |
| 958 // use stencil for clipping if clipping is enabled and the clip |
| 959 // has been written into the stencil. |
| 960 GrStencilSettings settings; |
| 961 |
| 962 // The GrGpu client may not be using the stencil buffer but we may need to |
| 963 // enable it in order to respect a stencil clip. |
| 964 if (pipelineBuilder.getStencil().isDisabled()) { |
| 965 if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) { |
| 966 static constexpr GrStencilSettings kBasicApplyClipSettings( |
| 967 kKeep_StencilOp, |
| 968 kKeep_StencilOp, |
| 969 kAlwaysIfInClip_StencilFunc, |
| 970 0x0000, |
| 971 0x0000, |
| 972 0x0000); |
| 973 settings = kBasicApplyClipSettings; |
| 974 } else { |
| 975 return; |
| 976 } |
| 977 } else { |
| 978 settings = pipelineBuilder.getStencil(); |
| 979 } |
| 980 |
| 981 int stencilBits = 0; |
| 982 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
| 983 GrStencilAttachment* stencilAttachment = this->resourceProvider()->attachSte
ncilAttachment(rt); |
| 984 if (stencilAttachment) { |
| 985 stencilBits = stencilAttachment->bits(); |
| 986 } |
| 987 |
| 988 SkASSERT(this->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp()); |
| 989 SkASSERT(this->caps()->twoSidedStencilSupport() || !settings.isTwoSided()); |
| 990 this->adjustStencilParams(&settings, fClipMode, stencilBits); |
| 991 ars->set(&pipelineBuilder); |
| 992 ars->setStencil(settings); |
| 993 } |
| 994 |
| 995 void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, |
| 996 StencilClipMode mode, |
| 997 int stencilBitCnt) { |
| 998 SkASSERT(stencilBitCnt > 0); |
| 999 |
| 1000 if (kModifyClip_StencilClipMode == mode) { |
| 1001 // We assume that this clip manager itself is drawing to the GrGpu and |
| 1002 // has already setup the correct values. |
| 1003 return; |
| 1004 } |
| 1005 |
| 1006 unsigned int clipBit = (1 << (stencilBitCnt - 1)); |
| 1007 unsigned int userBits = clipBit - 1; |
| 1008 |
| 1009 GrStencilSettings::Face face = GrStencilSettings::kFront_Face; |
| 1010 bool twoSided = this->caps()->twoSidedStencilSupport(); |
| 1011 |
| 1012 bool finished = false; |
| 1013 while (!finished) { |
| 1014 GrStencilFunc func = settings->func(face); |
| 1015 uint16_t writeMask = settings->writeMask(face); |
| 1016 uint16_t funcMask = settings->funcMask(face); |
| 1017 uint16_t funcRef = settings->funcRef(face); |
| 1018 |
| 1019 SkASSERT((unsigned) func < kStencilFuncCnt); |
| 1020 |
| 1021 writeMask &= userBits; |
| 1022 |
| 1023 if (func >= kBasicStencilFuncCnt) { |
| 1024 int respectClip = kRespectClip_StencilClipMode == mode; |
| 1025 if (respectClip) { |
| 1026 switch (func) { |
| 1027 case kAlwaysIfInClip_StencilFunc: |
| 1028 funcMask = clipBit; |
| 1029 funcRef = clipBit; |
| 1030 break; |
| 1031 case kEqualIfInClip_StencilFunc: |
| 1032 case kLessIfInClip_StencilFunc: |
| 1033 case kLEqualIfInClip_StencilFunc: |
| 1034 funcMask = (funcMask & userBits) | clipBit; |
| 1035 funcRef = (funcRef & userBits) | clipBit; |
| 1036 break; |
| 1037 case kNonZeroIfInClip_StencilFunc: |
| 1038 funcMask = (funcMask & userBits) | clipBit; |
| 1039 funcRef = clipBit; |
| 1040 break; |
| 1041 default: |
| 1042 SkFAIL("Unknown stencil func"); |
| 1043 } |
| 1044 } else { |
| 1045 funcMask &= userBits; |
| 1046 funcRef &= userBits; |
| 1047 } |
| 1048 const GrStencilFunc* table = |
| 1049 gSpecialToBasicStencilFunc[respectClip]; |
| 1050 func = table[func - kBasicStencilFuncCnt]; |
| 1051 SkASSERT(func >= 0 && func < kBasicStencilFuncCnt); |
| 1052 } else { |
| 1053 funcMask &= userBits; |
| 1054 funcRef &= userBits; |
| 1055 } |
| 1056 |
| 1057 settings->setFunc(face, func); |
| 1058 settings->setWriteMask(face, writeMask); |
| 1059 settings->setFuncMask(face, funcMask); |
| 1060 settings->setFuncRef(face, funcRef); |
| 1061 |
| 1062 if (GrStencilSettings::kFront_Face == face) { |
| 1063 face = GrStencilSettings::kBack_Face; |
| 1064 finished = !twoSided; |
| 1065 } else { |
| 1066 finished = true; |
| 1067 } |
| 1068 } |
| 1069 if (!twoSided) { |
| 1070 settings->copyFrontSettingsToBack(); |
| 1071 } |
| 1072 } |
| 1073 |
905 //////////////////////////////////////////////////////////////////////////////// | 1074 //////////////////////////////////////////////////////////////////////////////// |
906 GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, | 1075 GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, |
907 int32_t elementsGenID, | 1076 int32_t elementsGenID, |
908 GrReducedClip::InitialState
initialState, | 1077 GrReducedClip::InitialState
initialState, |
909 const GrReducedClip::Elemen
tList& elements, | 1078 const GrReducedClip::Elemen
tList& elements, |
910 const SkVector& clipToMaskO
ffset, | 1079 const SkVector& clipToMaskO
ffset, |
911 const SkIRect& clipSpaceIBo
unds) { | 1080 const SkIRect& clipSpaceIBo
unds) { |
912 GrUniqueKey key; | 1081 GrUniqueKey key; |
913 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); | 1082 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); |
914 GrResourceProvider* resourceProvider = context->resourceProvider(); | 1083 GrResourceProvider* resourceProvider = context->resourceProvider(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0
); | 1141 GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0
); |
973 if (!result) { | 1142 if (!result) { |
974 return nullptr; | 1143 return nullptr; |
975 } | 1144 } |
976 result->resourcePriv().setUniqueKey(key); | 1145 result->resourcePriv().setUniqueKey(key); |
977 | 1146 |
978 helper.toTexture(result); | 1147 helper.toTexture(result); |
979 | 1148 |
980 return result; | 1149 return result; |
981 } | 1150 } |
| 1151 |
| 1152 //////////////////////////////////////////////////////////////////////////////// |
| 1153 |
| 1154 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc
ilAttachment, |
| 1155 GrStencilSettings* settings) { |
| 1156 if (stencilAttachment) { |
| 1157 int stencilBits = stencilAttachment->bits(); |
| 1158 this->adjustStencilParams(settings, fClipMode, stencilBits); |
| 1159 } |
| 1160 } |
OLD | NEW |