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 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
130 PathNeedsSWRenderer(context, | 130 PathNeedsSWRenderer(context, |
131 kHasUserStencilSettings, | 131 kHasUserStencilSettings, |
132 texture->asRenderTarget(), | 132 texture->asRenderTarget(), |
133 viewMatrix, | 133 viewMatrix, |
134 element, | 134 element, |
135 &pr, | 135 &pr, |
136 kNeedsStencil); | 136 kNeedsStencil); |
137 return pr; | 137 return pr; |
138 } | 138 } |
139 | 139 |
140 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget) | |
141 : fDrawTarget(drawTarget) | |
142 , fClipMode(kIgnoreClip_StencilClipMode) { | |
143 } | |
144 | |
145 GrContext* GrClipMaskManager::getContext() { | 140 GrContext* GrClipMaskManager::getContext() { |
146 return fDrawTarget->cmmAccess().context(); | 141 return fDrawTarget->cmmAccess().context(); |
147 } | 142 } |
148 | 143 |
149 const GrCaps* GrClipMaskManager::caps() const { | 144 const GrCaps* GrClipMaskManager::caps() const { |
150 return fDrawTarget->caps(); | 145 return fDrawTarget->caps(); |
151 } | 146 } |
152 | 147 |
153 GrResourceProvider* GrClipMaskManager::resourceProvider() { | 148 GrResourceProvider* GrClipMaskManager::resourceProvider() { |
154 return fDrawTarget->cmmAccess().resourceProvider(); | 149 return fDrawTarget->cmmAccess().resourceProvider(); |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 for (int i = 0; i < fpCnt; ++i) { | 276 for (int i = 0; i < fpCnt; ++i) { |
282 fps[i]->unref(); | 277 fps[i]->unref(); |
283 } | 278 } |
284 return !failed; | 279 return !failed; |
285 } | 280 } |
286 | 281 |
287 //////////////////////////////////////////////////////////////////////////////// | 282 //////////////////////////////////////////////////////////////////////////////// |
288 // sort out what kind of clip mask needs to be created: alpha, stencil, | 283 // sort out what kind of clip mask needs to be created: alpha, stencil, |
289 // scissor, or entirely software | 284 // scissor, or entirely software |
290 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, | 285 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, |
291 const GrClip& clip, | 286 const GrClipStackClip& clip, |
292 const SkRect* devBounds, | 287 const SkRect* devBounds, |
293 GrAppliedClip* out) { | 288 GrAppliedClip* out) { |
294 if (kRespectClip_StencilClipMode == fClipMode) { | 289 if (!clip.clipStack() || clip.clipStack()->isWideOpen()) { |
295 fClipMode = kIgnoreClip_StencilClipMode; | 290 return true; |
296 } | 291 } |
297 | 292 |
298 GrReducedClip::ElementList elements; | 293 GrReducedClip::ElementList elements; |
299 int32_t genID = 0; | 294 int32_t genID = 0; |
300 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat
e; | 295 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat
e; |
301 SkIRect clipSpaceIBounds; | 296 SkIRect clipSpaceIBounds; |
302 bool requiresAA = false; | 297 bool requiresAA = false; |
303 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); | 298 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
304 | 299 |
305 // GrDrawTarget should have filtered this for us | 300 // GrDrawTarget should have filtered this for us |
306 SkASSERT(rt); | 301 SkASSERT(rt); |
307 | 302 |
308 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); | 303 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); |
309 if (clip.isWideOpen(clipSpaceRTIBounds)) { | 304 clipSpaceRTIBounds.offset(clip.origin()); |
310 return true; | 305 |
| 306 SkIRect clipSpaceReduceQueryBounds; |
| 307 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0 |
| 308 if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) { |
| 309 SkIRect devIBounds = devBounds->roundOut(); |
| 310 devIBounds.offset(clip.origin()); |
| 311 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, devIBounds
)) { |
| 312 return false; |
| 313 } |
| 314 } else { |
| 315 clipSpaceReduceQueryBounds = clipSpaceRTIBounds; |
311 } | 316 } |
312 | 317 GrReducedClip::ReduceClipStack(*clip.clipStack(), |
313 // The clip mask manager always draws with a single IRect so we special case
that logic here | 318 clipSpaceReduceQueryBounds, |
314 // Image filters just use a rect, so we also special case that logic | 319 &elements, |
315 switch (clip.clipType()) { | 320 &genID, |
316 case GrClip::kWideOpen_ClipType: | 321 &initialState, |
317 SkFAIL("Should have caught this with clip.isWideOpen()"); | 322 &clipSpaceIBounds, |
318 return true; | 323 &requiresAA); |
319 case GrClip::kIRect_ClipType: { | 324 if (elements.isEmpty()) { |
320 SkIRect scissor = clip.irect(); | 325 if (GrReducedClip::kAllIn_InitialState == initialState) { |
321 if (scissor.intersect(clipSpaceRTIBounds)) { | 326 if (clipSpaceIBounds == clipSpaceRTIBounds) { |
322 out->fScissorState.set(scissor); | |
323 out->fHasStencilClip = kIgnoreClip_StencilClipMode != fClipMode; | |
324 return true; | 327 return true; |
325 } | 328 } |
| 329 } else { |
326 return false; | 330 return false; |
327 } | 331 } |
328 case GrClip::kClipStack_ClipType: { | |
329 clipSpaceRTIBounds.offset(clip.origin()); | |
330 SkIRect clipSpaceReduceQueryBounds; | |
331 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0 | |
332 if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) { | |
333 SkIRect devIBounds = devBounds->roundOut(); | |
334 devIBounds.offset(clip.origin()); | |
335 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, de
vIBounds)) { | |
336 return false; | |
337 } | |
338 } else { | |
339 clipSpaceReduceQueryBounds = clipSpaceRTIBounds; | |
340 } | |
341 GrReducedClip::ReduceClipStack(*clip.clipStack(), | |
342 clipSpaceReduceQueryBounds, | |
343 &elements, | |
344 &genID, | |
345 &initialState, | |
346 &clipSpaceIBounds, | |
347 &requiresAA); | |
348 if (elements.isEmpty()) { | |
349 if (GrReducedClip::kAllIn_InitialState == initialState) { | |
350 if (clipSpaceIBounds == clipSpaceRTIBounds) { | |
351 return true; | |
352 } | |
353 } else { | |
354 return false; | |
355 } | |
356 } | |
357 } break; | |
358 } | 332 } |
359 | 333 |
360 SkASSERT(kIgnoreClip_StencilClipMode == fClipMode); // TODO: Remove fClipMod
e. | |
361 | |
362 // An element count of 4 was chosen because of the common pattern in Blink o
f: | 334 // An element count of 4 was chosen because of the common pattern in Blink o
f: |
363 // isect RR | 335 // isect RR |
364 // diff RR | 336 // diff RR |
365 // isect convex_poly | 337 // isect convex_poly |
366 // isect convex_poly | 338 // isect convex_poly |
367 // when drawing rounded div borders. This could probably be tuned based on a | 339 // when drawing rounded div borders. This could probably be tuned based on a |
368 // configuration's relative costs of switching RTs to generate a mask vs | 340 // configuration's relative costs of switching RTs to generate a mask vs |
369 // longer shaders. | 341 // longer shaders. |
370 if (elements.count() <= kMaxAnalyticElements) { | 342 if (elements.count() <= kMaxAnalyticElements) { |
371 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), | 343 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 elements, | 417 elements, |
446 clipSpaceIBounds, | 418 clipSpaceIBounds, |
447 clipSpaceToStencilSpaceOffset); | 419 clipSpaceToStencilSpaceOffset); |
448 | 420 |
449 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it | 421 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it |
450 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must | 422 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must |
451 // use both stencil and scissor test to the bounds for the final draw. | 423 // use both stencil and scissor test to the bounds for the final draw. |
452 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 424 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
453 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 425 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
454 out->fScissorState.set(scissorSpaceIBounds); | 426 out->fScissorState.set(scissorSpaceIBounds); |
455 SkASSERT(kRespectClip_StencilClipMode == fClipMode); // TODO: Remove fClipMo
de. | |
456 out->fHasStencilClip = true; | 427 out->fHasStencilClip = true; |
457 return true; | 428 return true; |
458 } | 429 } |
459 | 430 |
460 static bool stencil_element(GrDrawContext* dc, | 431 static bool stencil_element(GrDrawContext* dc, |
461 const GrClip& clip, | 432 const GrFixedClip& clip, |
462 const GrUserStencilSettings* ss, | 433 const GrUserStencilSettings* ss, |
463 const SkMatrix& viewMatrix, | 434 const SkMatrix& viewMatrix, |
464 const SkClipStack::Element* element) { | 435 const SkClipStack::Element* element) { |
465 | 436 |
466 // TODO: Draw rrects directly here. | 437 // TODO: Draw rrects directly here. |
467 switch (element->getType()) { | 438 switch (element->getType()) { |
468 case Element::kEmpty_Type: | 439 case Element::kEmpty_Type: |
469 SkDEBUGFAIL("Should never get here with an empty element."); | 440 SkDEBUGFAIL("Should never get here with an empty element."); |
470 break; | 441 break; |
471 case Element::kRect_Type: | 442 case Element::kRect_Type: |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
596 GrPathRenderer* pr = GetPathRenderer(context, | 567 GrPathRenderer* pr = GetPathRenderer(context, |
597 texture, translate, element); | 568 texture, translate, element); |
598 if (Element::kRect_Type != element->getType() && !pr) { | 569 if (Element::kRect_Type != element->getType() && !pr) { |
599 // UseSWOnlyPath should now filter out all cases where gpu-side
mask merging would | 570 // UseSWOnlyPath should now filter out all cases where gpu-side
mask merging would |
600 // be performed (i.e., pr would be NULL for a non-rect path). | 571 // be performed (i.e., pr would be NULL for a non-rect path). |
601 // See https://bug.skia.org/4519 for rationale and details. | 572 // See https://bug.skia.org/4519 for rationale and details. |
602 SkASSERT(0); | 573 SkASSERT(0); |
603 } | 574 } |
604 #endif | 575 #endif |
605 | 576 |
606 GrClip clip(maskSpaceIBounds); | 577 GrFixedClip clip(maskSpaceIBounds); |
607 | 578 |
608 // draw directly into the result with the stencil set to make the pi
xels affected | 579 // draw directly into the result with the stencil set to make the pi
xels affected |
609 // by the clip shape be non-zero. | 580 // by the clip shape be non-zero. |
610 static constexpr GrUserStencilSettings kStencilInElement( | 581 static constexpr GrUserStencilSettings kStencilInElement( |
611 GrUserStencilSettings::StaticInit< | 582 GrUserStencilSettings::StaticInit< |
612 0xffff, | 583 0xffff, |
613 GrUserStencilTest::kAlways, | 584 GrUserStencilTest::kAlways, |
614 0xffff, | 585 0xffff, |
615 GrUserStencilOp::kReplace, | 586 GrUserStencilOp::kReplace, |
616 GrUserStencilOp::kReplace, | 587 GrUserStencilOp::kReplace, |
(...skipping 21 matching lines...) Expand all Loading... |
638 SkRect::Make(clipSpace
IBounds))) { | 609 SkRect::Make(clipSpace
IBounds))) { |
639 texture->resourcePriv().removeUniqueKey(); | 610 texture->resourcePriv().removeUniqueKey(); |
640 return nullptr; | 611 return nullptr; |
641 } | 612 } |
642 } else { | 613 } else { |
643 // all the remaining ops can just be directly draw into the accumula
tion buffer | 614 // all the remaining ops can just be directly draw into the accumula
tion buffer |
644 GrPaint paint; | 615 GrPaint paint; |
645 paint.setAntiAlias(element->isAA()); | 616 paint.setAntiAlias(element->isAA()); |
646 paint.setCoverageSetOpXPFactory(op, false); | 617 paint.setCoverageSetOpXPFactory(op, false); |
647 | 618 |
648 draw_element(dc.get(), GrClip::WideOpen(), paint, translate, element
); | 619 draw_element(dc.get(), GrNoClip(), paint, translate, element); |
649 } | 620 } |
650 } | 621 } |
651 | 622 |
652 return texture.release(); | 623 return texture.release(); |
653 } | 624 } |
654 | 625 |
655 //////////////////////////////////////////////////////////////////////////////// | 626 //////////////////////////////////////////////////////////////////////////////// |
656 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 627 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
657 // (as opposed to canvas) coordinates | 628 // (as opposed to canvas) coordinates |
658 bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, | 629 bool GrClipMaskManager::createStencilClipMask(GrRenderTarget* rt, |
(...skipping 15 matching lines...) Expand all Loading... |
674 SkVector translate = { | 645 SkVector translate = { |
675 SkIntToScalar(clipSpaceToStencilOffset.fX), | 646 SkIntToScalar(clipSpaceToStencilOffset.fX), |
676 SkIntToScalar(clipSpaceToStencilOffset.fY) | 647 SkIntToScalar(clipSpaceToStencilOffset.fY) |
677 }; | 648 }; |
678 SkMatrix viewMatrix; | 649 SkMatrix viewMatrix; |
679 viewMatrix.setTranslate(translate); | 650 viewMatrix.setTranslate(translate); |
680 | 651 |
681 // We set the current clip to the bounds so that our recursive draws are
scissored to them. | 652 // We set the current clip to the bounds so that our recursive draws are
scissored to them. |
682 SkIRect stencilSpaceIBounds(clipSpaceIBounds); | 653 SkIRect stencilSpaceIBounds(clipSpaceIBounds); |
683 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); | 654 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); |
684 GrClip clip(stencilSpaceIBounds); | 655 GrFixedClip clip(stencilSpaceIBounds); |
685 | 656 |
686 fDrawTarget->cmmAccess().clearStencilClip(stencilSpaceIBounds, | 657 fDrawTarget->cmmAccess().clearStencilClip(stencilSpaceIBounds, |
687 GrReducedClip::kAllIn_InitialState == initialState, rt); | 658 GrReducedClip::kAllIn_InitialState == initialState, rt); |
688 | 659 |
689 // walk through each clip element and perform its set op | 660 // walk through each clip element and perform its set op |
690 // with the existing clip. | 661 // with the existing clip. |
691 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { | 662 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { |
692 const Element* element = iter.get(); | 663 const Element* element = iter.get(); |
693 | 664 |
694 GrPipelineBuilder pipelineBuilder; | 665 GrPipelineBuilder pipelineBuilder; |
695 pipelineBuilder.setRenderTarget(rt); | 666 pipelineBuilder.setRenderTarget(rt); |
696 | 667 |
697 pipelineBuilder.setDisableColorXPFactory(); | 668 pipelineBuilder.setDisableColorXPFactory(); |
698 | 669 |
699 // if the target is MSAA then we want MSAA enabled when the clip is
soft | 670 // if the target is MSAA then we want MSAA enabled when the clip is
soft |
700 if (rt->isStencilBufferMultisampled()) { | 671 if (rt->isStencilBufferMultisampled()) { |
701 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, e
lement->isAA()); | 672 pipelineBuilder.setState(GrPipelineBuilder::kHWAntialias_Flag, e
lement->isAA()); |
702 } | 673 } |
703 | 674 |
704 bool fillInverted = false; | 675 bool fillInverted = false; |
705 // enabled at bottom of loop | 676 // enabled at bottom of loop |
706 fClipMode = kIgnoreClip_StencilClipMode; | 677 clip.enableStencilClip(false); |
707 | 678 |
708 // This will be used to determine whether the clip shape can be rend
ered into the | 679 // This will be used to determine whether the clip shape can be rend
ered into the |
709 // stencil with arbitrary stencil settings. | 680 // stencil with arbitrary stencil settings. |
710 GrPathRenderer::StencilSupport stencilSupport; | 681 GrPathRenderer::StencilSupport stencilSupport; |
711 | 682 |
712 SkRegion::Op op = element->getOp(); | 683 SkRegion::Op op = element->getOp(); |
713 | 684 |
714 GrPathRenderer* pr = nullptr; | 685 GrPathRenderer* pr = nullptr; |
715 SkPath clipPath; | 686 SkPath clipPath; |
716 if (Element::kRect_Type == element->getType()) { | 687 if (Element::kRect_Type == element->getType()) { |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
794 args.fViewMatrix = &viewMatrix; | 765 args.fViewMatrix = &viewMatrix; |
795 args.fPath = &clipPath; | 766 args.fPath = &clipPath; |
796 pr->stencilPath(args); | 767 pr->stencilPath(args); |
797 } | 768 } |
798 } | 769 } |
799 } | 770 } |
800 } | 771 } |
801 | 772 |
802 // now we modify the clip bit by rendering either the clip | 773 // now we modify the clip bit by rendering either the clip |
803 // element directly or a bounding rect of the entire clip. | 774 // element directly or a bounding rect of the entire clip. |
804 fClipMode = kModifyClip_StencilClipMode; | 775 clip.enableStencilClip(true); |
805 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass
; ++pass) { | 776 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass
; ++pass) { |
806 pipelineBuilder.setUserStencil(*pass); | 777 pipelineBuilder.setUserStencil(*pass); |
807 | 778 |
808 if (drawDirectToClip) { | 779 if (drawDirectToClip) { |
809 if (Element::kRect_Type == element->getType()) { | 780 if (Element::kRect_Type == element->getType()) { |
810 draw_non_aa_rect(fDrawTarget, pipelineBuilder, clip, GrC
olor_WHITE, | 781 draw_non_aa_rect(fDrawTarget, pipelineBuilder, clip, GrC
olor_WHITE, |
811 viewMatrix, element->getRect()); | 782 viewMatrix, element->getRect()); |
812 } else { | 783 } else { |
813 GrPathRenderer::DrawPathArgs args; | 784 GrPathRenderer::DrawPathArgs args; |
814 args.fTarget = fDrawTarget; | 785 args.fTarget = fDrawTarget; |
(...skipping 10 matching lines...) Expand all Loading... |
825 } | 796 } |
826 } else { | 797 } else { |
827 // The view matrix is setup to do clip space -> stencil spac
e translation, so | 798 // The view matrix is setup to do clip space -> stencil spac
e translation, so |
828 // draw rect in clip space. | 799 // draw rect in clip space. |
829 draw_non_aa_rect(fDrawTarget, pipelineBuilder, clip, GrColor
_WHITE, viewMatrix, | 800 draw_non_aa_rect(fDrawTarget, pipelineBuilder, clip, GrColor
_WHITE, viewMatrix, |
830 SkRect::Make(clipSpaceIBounds)); | 801 SkRect::Make(clipSpaceIBounds)); |
831 } | 802 } |
832 } | 803 } |
833 } | 804 } |
834 } | 805 } |
835 fClipMode = kRespectClip_StencilClipMode; | |
836 return true; | 806 return true; |
837 } | 807 } |
838 | 808 |
839 //////////////////////////////////////////////////////////////////////////////// | 809 //////////////////////////////////////////////////////////////////////////////// |
840 GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, | 810 GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, |
841 int32_t elementsGenID, | 811 int32_t elementsGenID, |
842 GrReducedClip::InitialState
initialState, | 812 GrReducedClip::InitialState
initialState, |
843 const GrReducedClip::Elemen
tList& elements, | 813 const GrReducedClip::Elemen
tList& elements, |
844 const SkVector& clipToMaskO
ffset, | 814 const SkVector& clipToMaskO
ffset, |
845 const SkIRect& clipSpaceIBo
unds) { | 815 const SkIRect& clipSpaceIBo
unds) { |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
906 GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0
); | 876 GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0
); |
907 if (!result) { | 877 if (!result) { |
908 return nullptr; | 878 return nullptr; |
909 } | 879 } |
910 result->resourcePriv().setUniqueKey(key); | 880 result->resourcePriv().setUniqueKey(key); |
911 | 881 |
912 helper.toTexture(result); | 882 helper.toTexture(result); |
913 | 883 |
914 return result; | 884 return result; |
915 } | 885 } |
OLD | NEW |