Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(230)

Side by Side Diff: src/gpu/GrClipMaskManager.cpp

Issue 1421533007: Fix ClipMaskManager's SW-fallback logic (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: clean up? Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/gpu/GrClipMaskManager.h ('k') | src/gpu/GrContext.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 "GrDrawContext.h" 10 #include "GrDrawContext.h"
(...skipping 28 matching lines...) Expand all
39 39
40 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); 40 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height());
41 return GrTextureDomainEffect::Create(result, 41 return GrTextureDomainEffect::Create(result,
42 mat, 42 mat,
43 GrTextureDomain::MakeTexelDomain(result , domainTexels), 43 GrTextureDomain::MakeTexelDomain(result , domainTexels),
44 GrTextureDomain::kDecal_Mode, 44 GrTextureDomain::kDecal_Mode,
45 GrTextureParams::kNone_FilterMode, 45 GrTextureParams::kNone_FilterMode,
46 kDevice_GrCoordSet); 46 kDevice_GrCoordSet);
47 } 47 }
48 48
49 // Does the path in 'element' require SW rendering? If so, return true (and,
50 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set
51 // 'prOut' to the non-SW path renderer that will do the job).
49 static bool path_needs_SW_renderer(GrContext* context, 52 static bool path_needs_SW_renderer(GrContext* context,
50 const GrPipelineBuilder& pipelineBuilder, 53 const GrPipelineBuilder& pipelineBuilder,
51 const SkMatrix& viewMatrix, 54 const SkMatrix& viewMatrix,
52 const SkPath& origPath, 55 const Element* element,
53 const GrStrokeInfo& stroke, 56 GrPathRenderer** prOut,
54 bool doAA) { 57 bool needsStencil) {
55 // the gpu alpha mask will draw the inverse paths as non-inverse to a temp b uffer 58 if (Element::kRect_Type == element->getType()) {
56 SkTCopyOnFirstWrite<SkPath> path(origPath); 59 // rects can always be drawn directly w/o using the software path
57 if (path->isInverseFillType()) { 60 // TODO: skip rrects once we're drawing them directly.
58 path.writable()->toggleInverseFillType(); 61 return false;
62 } else {
63 // We shouldn't get here with an empty clip element.
64 SkASSERT(Element::kEmpty_Type != element->getType());
65
66 // the gpu alpha mask will draw the inverse paths as non-inverse to a te mp buffer
67 SkPath path;
68 element->asPath(&path);
69 if (path.isInverseFillType()) {
70 path.toggleInverseFillType();
71 }
72 GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
73
74 GrPathRendererChain::DrawType type;
75
76 if (needsStencil) {
77 type = element->isAA()
78 ? GrPathRendererChain::kStencilAndColorAntiAlias_Dra wType
79 : GrPathRendererChain::kStencilAndColor_DrawType;
80 } else {
81 type = element->isAA()
82 ? GrPathRendererChain::kColorAntiAlias_DrawType
83 : GrPathRendererChain::kColor_DrawType;
84 }
85
86 // the 'false' parameter disallows use of the SW path renderer
87 GrPathRenderer* pr = context->getPathRenderer(pipelineBuilder, viewMatri x, path,
88 stroke, false, type);
89 if (prOut) {
90 *prOut = pr;
91 }
92 return SkToBool(!pr);
59 } 93 }
60 // last (false) parameter disallows use of the SW path renderer 94 }
61 GrPathRendererChain::DrawType type = doAA ?
62 GrPathRendererChain::kColorAntiAlias_Dr awType :
63 GrPathRendererChain::kColor_DrawType;
64 95
65 return nullptr == context->getPathRenderer(&pipelineBuilder, viewMatrix, *pa th, stroke, 96 // Determines whether it is possible to draw the element to both the stencil buf fer and the
66 false, type); 97 // alpha mask simultaneously. If so and the element is a path a compatible path renderer is
98 // also returned.
99 static bool can_stencil_and_draw_element(GrContext* context,
100 GrPipelineBuilder* pipelineBuilder,
101 GrTexture* texture,
102 const SkMatrix& viewMatrix,
103 const SkClipStack::Element* element,
104 GrPathRenderer** pr) {
105 pipelineBuilder->setRenderTarget(texture->asRenderTarget());
106
107 static const bool kNeedsStencil = true;
108 return !path_needs_SW_renderer(context,
109 *pipelineBuilder,
110 viewMatrix,
111 element,
112 pr,
113 kNeedsStencil);
67 } 114 }
68 115
69 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget) 116 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget)
70 : fDrawTarget(drawTarget) 117 : fDrawTarget(drawTarget)
71 , fClipMode(kIgnoreClip_StencilClipMode) { 118 , fClipMode(kIgnoreClip_StencilClipMode) {
72 } 119 }
73 120
74 GrContext* GrClipMaskManager::getContext() { return fDrawTarget->cmmAccess().con text(); } 121 GrContext* GrClipMaskManager::getContext() { return fDrawTarget->cmmAccess().con text(); }
75 122
76 /* 123 /*
77 * This method traverses the clip stack to see if the GrSoftwarePathRenderer 124 * This method traverses the clip stack to see if the GrSoftwarePathRenderer
78 * will be used on any element. If so, it returns true to indicate that the 125 * will be used on any element. If so, it returns true to indicate that the
79 * entire clip should be rendered in SW and then uploaded en masse to the gpu. 126 * entire clip should be rendered in SW and then uploaded en masse to the gpu.
80 */ 127 */
81 bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder, 128 bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder,
82 const SkVector& clipToMaskOffset, 129 const SkVector& clipToMaskOffset,
83 const GrReducedClip::ElementList& elements ) { 130 const GrReducedClip::ElementList& elements ) {
84 // TODO: generalize this function so that when 131 // TODO: generalize this function so that when
85 // a clip gets complex enough it can just be done in SW regardless 132 // a clip gets complex enough it can just be done in SW regardless
86 // of whether it would invoke the GrSoftwarePathRenderer. 133 // of whether it would invoke the GrSoftwarePathRenderer.
87 GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
88 134
89 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip 135 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip
90 // space. 136 // space.
91 SkMatrix translate; 137 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY);
92 translate.setTranslate(clipToMaskOffset);
93 138
94 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) { 139 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get(); iter.next()) {
95 const Element* element = iter.get(); 140 const Element* element = iter.get();
96 // rects can always be drawn directly w/o using the software path 141
97 // Skip rrects once we're drawing them directly. 142 SkRegion::Op op = element->getOp();
98 if (Element::kRect_Type != element->getType()) { 143 bool invert = element->isInverseFilled();
99 SkPath path; 144 bool needsStencil = invert ||
100 element->asPath(&path); 145 SkRegion::kIntersect_Op == op || SkRegion::kReverseD ifference_Op == op;
101 if (path_needs_SW_renderer(this->getContext(), pipelineBuilder, tran slate, 146
102 path, stroke, element->isAA())) { 147 if (path_needs_SW_renderer(this->getContext(), pipelineBuilder, translat e,
103 return true; 148 element, nullptr, needsStencil)) {
104 } 149 return true;
105 } 150 }
106 } 151 }
107 return false; 152 return false;
108 } 153 }
109 154
110 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis t& elements, 155 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis t& elements,
111 bool abortIfAA, 156 bool abortIfAA,
112 SkVector& clipToRTOffset, 157 SkVector& clipToRTOffset,
113 const SkRect* drawBounds, 158 const SkRect* drawBounds,
114 const GrFragmentProcessor** res ultFP) { 159 const GrFragmentProcessor** res ultFP) {
(...skipping 290 matching lines...) Expand 10 before | Expand all | Expand 10 after
405 element->asPath(&path); 450 element->asPath(&path);
406 path.setIsVolatile(true); 451 path.setIsVolatile(true);
407 if (path.isInverseFillType()) { 452 if (path.isInverseFillType()) {
408 path.toggleInverseFillType(); 453 path.toggleInverseFillType();
409 } 454 }
410 GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle); 455 GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
411 if (nullptr == pr) { 456 if (nullptr == pr) {
412 GrPathRendererChain::DrawType type; 457 GrPathRendererChain::DrawType type;
413 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr awType : 458 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr awType :
414 GrPathRendererChain::kColor_DrawType; 459 GrPathRendererChain::kColor_DrawType;
415 pr = this->getContext()->getPathRenderer(pipelineBuilder, viewMa trix, 460 pr = this->getContext()->getPathRenderer(*pipelineBuilder, viewM atrix,
416 path, stroke, false, ty pe); 461 path, stroke, false, ty pe);
417 } 462 }
418 if (nullptr == pr) { 463 if (nullptr == pr) {
419 return false; 464 return false;
420 } 465 }
421 GrPathRenderer::DrawPathArgs args; 466 GrPathRenderer::DrawPathArgs args;
422 args.fTarget = fDrawTarget; 467 args.fTarget = fDrawTarget;
423 args.fResourceProvider = this->getContext()->resourceProvider(); 468 args.fResourceProvider = this->getContext()->resourceProvider();
424 args.fPipelineBuilder = pipelineBuilder; 469 args.fPipelineBuilder = pipelineBuilder;
425 args.fColor = color; 470 args.fColor = color;
426 args.fViewMatrix = &viewMatrix; 471 args.fViewMatrix = &viewMatrix;
427 args.fPath = &path; 472 args.fPath = &path;
428 args.fStroke = &stroke; 473 args.fStroke = &stroke;
429 args.fAntiAlias = element->isAA(); 474 args.fAntiAlias = element->isAA();
430 pr->drawPath(args); 475 pr->drawPath(args);
431 break; 476 break;
432 } 477 }
433 } 478 }
434 return true; 479 return true;
435 } 480 }
436 481
437 bool GrClipMaskManager::canStencilAndDrawElement(GrPipelineBuilder* pipelineBuil der,
438 GrTexture* target,
439 GrPathRenderer** pr,
440 const SkClipStack::Element* ele ment) {
441 pipelineBuilder->setRenderTarget(target->asRenderTarget());
442
443 if (Element::kRect_Type == element->getType()) {
444 return true;
445 } else {
446 // We shouldn't get here with an empty clip element.
447 SkASSERT(Element::kEmpty_Type != element->getType());
448 SkPath path;
449 element->asPath(&path);
450 if (path.isInverseFillType()) {
451 path.toggleInverseFillType();
452 }
453 GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle);
454 GrPathRendererChain::DrawType type = element->isAA() ?
455 GrPathRendererChain::kStencilAndColorAntiAlias_DrawType :
456 GrPathRendererChain::kStencilAndColor_DrawType;
457 *pr = this->getContext()->getPathRenderer(pipelineBuilder, SkMatrix::I() , path,
458 stroke, false, type);
459 return SkToBool(*pr);
460 }
461 }
462
463 void GrClipMaskManager::mergeMask(GrPipelineBuilder* pipelineBuilder, 482 void GrClipMaskManager::mergeMask(GrPipelineBuilder* pipelineBuilder,
464 GrTexture* dstMask, 483 GrTexture* dstMask,
465 GrTexture* srcMask, 484 GrTexture* srcMask,
466 SkRegion::Op op, 485 SkRegion::Op op,
467 const SkIRect& dstBound, 486 const SkIRect& dstBound,
468 const SkIRect& srcBound) { 487 const SkIRect& srcBound) {
469 pipelineBuilder->setRenderTarget(dstMask->asRenderTarget()); 488 pipelineBuilder->setRenderTarget(dstMask->asRenderTarget());
470 489
471 // We want to invert the coverage here 490 // We want to invert the coverage here
472 set_coverage_drawing_xpf(op, false, pipelineBuilder); 491 set_coverage_drawing_xpf(op, false, pipelineBuilder);
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 SkAutoTUnref<GrTexture> texture(this->createCachedMask( 567 SkAutoTUnref<GrTexture> texture(this->createCachedMask(
549 clipSpaceIBounds.width(), clipSpaceIBounds.height(), key, true)); 568 clipSpaceIBounds.width(), clipSpaceIBounds.height(), key, true));
550 569
551 // There's no texture in the cache. Let's try to allocate it then. 570 // There's no texture in the cache. Let's try to allocate it then.
552 if (!texture) { 571 if (!texture) {
553 return nullptr; 572 return nullptr;
554 } 573 }
555 574
556 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip 575 // Set the matrix so that rendered clip elements are transformed to mask spa ce from clip
557 // space. 576 // space.
558 SkMatrix translate; 577 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa skOffset.fY);
559 translate.setTranslate(clipToMaskOffset);
560 578
561 // The texture may be larger than necessary, this rect represents the part o f the texture 579 // The texture may be larger than necessary, this rect represents the part o f the texture
562 // we populate with a rasterization of the clip. 580 // we populate with a rasterization of the clip.
563 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa ceIBounds.height()); 581 SkIRect maskSpaceIBounds = SkIRect::MakeWH(clipSpaceIBounds.width(), clipSpa ceIBounds.height());
564 582
565 // The scratch texture that we are drawing into can be substantially larger than the mask. Only 583 // The scratch texture that we are drawing into can be substantially larger than the mask. Only
566 // clear the part that we care about. 584 // clear the part that we care about.
567 fDrawTarget->clear(&maskSpaceIBounds, 585 fDrawTarget->clear(&maskSpaceIBounds,
568 GrReducedClip::kAllIn_InitialState == initialState ? 0xff ffffff : 0x00000000, 586 GrReducedClip::kAllIn_InitialState == initialState ? 0xff ffffff : 0x00000000,
569 true, 587 true,
570 texture->asRenderTarget()); 588 texture->asRenderTarget());
571 589
572 // When we use the stencil in the below loop it is important to have this cl ip installed. 590 // When we use the stencil in the below loop it is important to have this cl ip installed.
573 // The second pass that zeros the stencil buffer renders the rect maskSpaceI Bounds so the first 591 // The second pass that zeros the stencil buffer renders the rect maskSpaceI Bounds so the first
574 // pass must not set values outside of this bounds or stencil values outside the rect won't be 592 // pass must not set values outside of this bounds or stencil values outside the rect won't be
575 // cleared. 593 // cleared.
576 GrClip clip(maskSpaceIBounds); 594 GrClip clip(maskSpaceIBounds);
577 SkAutoTUnref<GrTexture> temp; 595 SkAutoTUnref<GrTexture> temp;
578 596
579 // walk through each clip element and perform its set op 597 // walk through each clip element and perform its set op
580 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get() ; iter.next()) { 598 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get() ; iter.next()) {
581 const Element* element = iter.get(); 599 const Element* element = iter.get();
582 SkRegion::Op op = element->getOp(); 600 SkRegion::Op op = element->getOp();
583 bool invert = element->isInverseFilled(); 601 bool invert = element->isInverseFilled();
584 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) { 602 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) {
585 GrPipelineBuilder pipelineBuilder; 603 GrPipelineBuilder pipelineBuilder;
586 604
587 pipelineBuilder.setClip(clip); 605 pipelineBuilder.setClip(clip);
588 GrPathRenderer* pr = nullptr; 606 GrPathRenderer* pr = nullptr;
589 bool useTemp = !this->canStencilAndDrawElement(&pipelineBuilder, tex ture, &pr, element); 607 bool useTemp = !can_stencil_and_draw_element(this->getContext(), &pi pelineBuilder,
608 texture, translate, ele ment, &pr);
590 GrTexture* dst; 609 GrTexture* dst;
591 // This is the bounds of the clip element in the space of the alpha- mask. The temporary 610 // This is the bounds of the clip element in the space of the alpha- mask. The temporary
592 // mask buffer can be substantially larger than the actually clip st ack element. We 611 // mask buffer can be substantially larger than the actually clip st ack element. We
593 // touch the minimum number of pixels necessary and use decal mode t o combine it with 612 // touch the minimum number of pixels necessary and use decal mode t o combine it with
594 // the accumulator. 613 // the accumulator.
595 SkIRect maskSpaceElementIBounds; 614 SkIRect maskSpaceElementIBounds;
596 615
616 SkASSERT(!useTemp);
617
597 if (useTemp) { 618 if (useTemp) {
598 if (invert) { 619 if (invert) {
599 maskSpaceElementIBounds = maskSpaceIBounds; 620 maskSpaceElementIBounds = maskSpaceIBounds;
600 } else { 621 } else {
601 SkRect elementBounds = element->getBounds(); 622 SkRect elementBounds = element->getBounds();
602 elementBounds.offset(clipToMaskOffset); 623 elementBounds.offset(clipToMaskOffset);
603 elementBounds.roundOut(&maskSpaceElementIBounds); 624 elementBounds.roundOut(&maskSpaceElementIBounds);
604 } 625 }
605 626
606 if (!temp) { 627 if (!temp) {
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
752 SkPath clipPath; 773 SkPath clipPath;
753 if (Element::kRect_Type == element->getType()) { 774 if (Element::kRect_Type == element->getType()) {
754 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; 775 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport;
755 fillInverted = false; 776 fillInverted = false;
756 } else { 777 } else {
757 element->asPath(&clipPath); 778 element->asPath(&clipPath);
758 fillInverted = clipPath.isInverseFillType(); 779 fillInverted = clipPath.isInverseFillType();
759 if (fillInverted) { 780 if (fillInverted) {
760 clipPath.toggleInverseFillType(); 781 clipPath.toggleInverseFillType();
761 } 782 }
762 pr = this->getContext()->getPathRenderer(&pipelineBuilder, 783 pr = this->getContext()->getPathRenderer(pipelineBuilder,
763 viewMatrix, 784 viewMatrix,
764 clipPath, 785 clipPath,
765 stroke, 786 stroke,
766 false, 787 false,
767 GrPathRendererChain::kS tencilOnly_DrawType, 788 GrPathRendererChain::kS tencilOnly_DrawType,
768 &stencilSupport); 789 &stencilSupport);
769 if (nullptr == pr) { 790 if (nullptr == pr) {
770 return false; 791 return false;
771 } 792 }
772 } 793 }
(...skipping 342 matching lines...) Expand 10 before | Expand all | Expand 10 after
1115 1136
1116 //////////////////////////////////////////////////////////////////////////////// 1137 ////////////////////////////////////////////////////////////////////////////////
1117 1138
1118 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc ilAttachment, 1139 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc ilAttachment,
1119 GrStencilSettings* settings) { 1140 GrStencilSettings* settings) {
1120 if (stencilAttachment) { 1141 if (stencilAttachment) {
1121 int stencilBits = stencilAttachment->bits(); 1142 int stencilBits = stencilAttachment->bits();
1122 this->adjustStencilParams(settings, fClipMode, stencilBits); 1143 this->adjustStencilParams(settings, fClipMode, stencilBits);
1123 } 1144 }
1124 } 1145 }
OLDNEW
« no previous file with comments | « src/gpu/GrClipMaskManager.h ('k') | src/gpu/GrContext.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698