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 "GrDrawContext.h" | 10 #include "GrDrawContext.h" |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
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, | 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 | 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). | 51 // 'prOut' to the non-SW path renderer that will do the job). |
52 static bool path_needs_SW_renderer(GrContext* context, | 52 static bool path_needs_SW_renderer(GrContext* context, |
53 const GrPipelineBuilder& pipelineBuilder, | 53 bool isStencilDisabled, |
| 54 const GrRenderTarget* rt, |
54 const SkMatrix& viewMatrix, | 55 const SkMatrix& viewMatrix, |
55 const Element* element, | 56 const Element* element, |
56 GrPathRenderer** prOut, | 57 GrPathRenderer** prOut, |
57 bool needsStencil) { | 58 bool needsStencil) { |
58 if (Element::kRect_Type == element->getType()) { | 59 if (Element::kRect_Type == element->getType()) { |
59 // rects can always be drawn directly w/o using the software path | 60 // rects can always be drawn directly w/o using the software path |
60 // TODO: skip rrects once we're drawing them directly. | 61 // TODO: skip rrects once we're drawing them directly. |
61 if (prOut) { | 62 if (prOut) { |
62 *prOut = nullptr; | 63 *prOut = nullptr; |
63 } | 64 } |
(...skipping 16 matching lines...) Expand all Loading... |
80 type = element->isAA() | 81 type = element->isAA() |
81 ? GrPathRendererChain::kStencilAndColorAntiAlias_Dra
wType | 82 ? GrPathRendererChain::kStencilAndColorAntiAlias_Dra
wType |
82 : GrPathRendererChain::kStencilAndColor_DrawType; | 83 : GrPathRendererChain::kStencilAndColor_DrawType; |
83 } else { | 84 } else { |
84 type = element->isAA() | 85 type = element->isAA() |
85 ? GrPathRendererChain::kColorAntiAlias_DrawType | 86 ? GrPathRendererChain::kColorAntiAlias_DrawType |
86 : GrPathRendererChain::kColor_DrawType; | 87 : GrPathRendererChain::kColor_DrawType; |
87 } | 88 } |
88 | 89 |
89 // the 'false' parameter disallows use of the SW path renderer | 90 // the 'false' parameter disallows use of the SW path renderer |
90 GrPathRenderer* pr = context->getPathRenderer(pipelineBuilder, viewMatri
x, path, | 91 GrPathRenderer* pr = context->getPathRenderer(viewMatrix, path, |
91 stroke, false, type); | 92 stroke, false, type, |
| 93 isStencilDisabled, |
| 94 rt->isStencilBufferMultisa
mpled()); |
92 if (prOut) { | 95 if (prOut) { |
93 *prOut = pr; | 96 *prOut = pr; |
94 } | 97 } |
95 return SkToBool(!pr); | 98 return SkToBool(!pr); |
96 } | 99 } |
97 } | 100 } |
98 | 101 |
99 // Determines whether it is possible to draw the element to both the stencil buf
fer and the | 102 // Determines whether it is possible to draw the element to both the stencil buf
fer and the |
100 // alpha mask simultaneously. If so and the element is a path a compatible path
renderer is | 103 // alpha mask simultaneously. If so and the element is a path a compatible path
renderer is |
101 // also returned. | 104 // also returned. |
102 static bool can_stencil_and_draw_element(GrContext* context, | 105 static bool can_stencil_and_draw_element(GrContext* context, |
103 GrPipelineBuilder* pipelineBuilder, | |
104 GrTexture* texture, | 106 GrTexture* texture, |
105 const SkMatrix& viewMatrix, | 107 const SkMatrix& viewMatrix, |
106 const SkClipStack::Element* element, | 108 const SkClipStack::Element* element, |
107 GrPathRenderer** pr) { | 109 GrPathRenderer** pr) { |
108 pipelineBuilder->setRenderTarget(texture->asRenderTarget()); | |
109 | |
110 static const bool kNeedsStencil = true; | 110 static const bool kNeedsStencil = true; |
| 111 static const bool kStencilIsDisabled = true; |
111 return !path_needs_SW_renderer(context, | 112 return !path_needs_SW_renderer(context, |
112 *pipelineBuilder, | 113 kStencilIsDisabled, |
| 114 texture->asRenderTarget(), |
113 viewMatrix, | 115 viewMatrix, |
114 element, | 116 element, |
115 pr, | 117 pr, |
116 kNeedsStencil); | 118 kNeedsStencil); |
117 } | 119 } |
118 | 120 |
119 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget) | 121 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget) |
120 : fDrawTarget(drawTarget) | 122 : fDrawTarget(drawTarget) |
121 , fClipMode(kIgnoreClip_StencilClipMode) { | 123 , fClipMode(kIgnoreClip_StencilClipMode) { |
122 } | 124 } |
123 | 125 |
124 GrContext* GrClipMaskManager::getContext() { return fDrawTarget->cmmAccess().con
text(); } | 126 GrContext* GrClipMaskManager::getContext() { return fDrawTarget->cmmAccess().con
text(); } |
125 | 127 |
126 /* | 128 /* |
127 * This method traverses the clip stack to see if the GrSoftwarePathRenderer | 129 * This method traverses the clip stack to see if the GrSoftwarePathRenderer |
128 * will be used on any element. If so, it returns true to indicate that the | 130 * will be used on any element. If so, it returns true to indicate that the |
129 * entire clip should be rendered in SW and then uploaded en masse to the gpu. | 131 * entire clip should be rendered in SW and then uploaded en masse to the gpu. |
130 */ | 132 */ |
131 bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder, | 133 bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder, |
| 134 const GrRenderTarget* rt, |
132 const SkVector& clipToMaskOffset, | 135 const SkVector& clipToMaskOffset, |
133 const GrReducedClip::ElementList& elements
) { | 136 const GrReducedClip::ElementList& elements
) { |
134 // TODO: generalize this function so that when | 137 // TODO: generalize this function so that when |
135 // a clip gets complex enough it can just be done in SW regardless | 138 // a clip gets complex enough it can just be done in SW regardless |
136 // of whether it would invoke the GrSoftwarePathRenderer. | 139 // of whether it would invoke the GrSoftwarePathRenderer. |
137 | 140 |
138 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip | 141 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip |
139 // space. | 142 // space. |
140 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); | 143 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); |
141 | 144 |
142 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { | 145 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { |
143 const Element* element = iter.get(); | 146 const Element* element = iter.get(); |
144 | 147 |
145 SkRegion::Op op = element->getOp(); | 148 SkRegion::Op op = element->getOp(); |
146 bool invert = element->isInverseFilled(); | 149 bool invert = element->isInverseFilled(); |
147 bool needsStencil = invert || | 150 bool needsStencil = invert || |
148 SkRegion::kIntersect_Op == op || SkRegion::kReverseD
ifference_Op == op; | 151 SkRegion::kIntersect_Op == op || SkRegion::kReverseD
ifference_Op == op; |
149 | 152 |
150 if (path_needs_SW_renderer(this->getContext(), pipelineBuilder, translat
e, | 153 if (path_needs_SW_renderer(this->getContext(), pipelineBuilder.getStenci
l().isDisabled(), |
151 element, nullptr, needsStencil)) { | 154 rt, translate, element, nullptr, needsStencil
)) { |
152 return true; | 155 return true; |
153 } | 156 } |
154 } | 157 } |
155 return false; | 158 return false; |
156 } | 159 } |
157 | 160 |
158 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, | 161 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, |
159 bool abortIfAA, | 162 bool abortIfAA, |
160 SkVector& clipToRTOffset, | 163 SkVector& clipToRTOffset, |
161 const SkRect* drawBounds, | 164 const SkRect* drawBounds, |
(...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
351 // If MSAA is enabled we can do everything in the stencil buffer. | 354 // If MSAA is enabled we can do everything in the stencil buffer. |
352 if (0 == rt->numStencilSamples() && requiresAA) { | 355 if (0 == rt->numStencilSamples() && requiresAA) { |
353 SkAutoTUnref<GrTexture> result; | 356 SkAutoTUnref<GrTexture> result; |
354 | 357 |
355 // The top-left of the mask corresponds to the top-left corner of the bo
unds. | 358 // The top-left of the mask corresponds to the top-left corner of the bo
unds. |
356 SkVector clipToMaskOffset = { | 359 SkVector clipToMaskOffset = { |
357 SkIntToScalar(-clipSpaceIBounds.fLeft), | 360 SkIntToScalar(-clipSpaceIBounds.fLeft), |
358 SkIntToScalar(-clipSpaceIBounds.fTop) | 361 SkIntToScalar(-clipSpaceIBounds.fTop) |
359 }; | 362 }; |
360 | 363 |
361 if (this->useSWOnlyPath(pipelineBuilder, clipToMaskOffset, elements)) { | 364 if (this->useSWOnlyPath(pipelineBuilder, rt, clipToMaskOffset, elements)
) { |
362 // The clip geometry is complex enough that it will be more efficien
t to create it | 365 // The clip geometry is complex enough that it will be more efficien
t to create it |
363 // entirely in software | 366 // entirely in software |
364 result.reset(this->createSoftwareClipMask(genID, | 367 result.reset(this->createSoftwareClipMask(genID, |
365 initialState, | 368 initialState, |
366 elements, | 369 elements, |
367 clipToMaskOffset, | 370 clipToMaskOffset, |
368 clipSpaceIBounds)); | 371 clipSpaceIBounds)); |
369 } else { | 372 } else { |
370 result.reset(this->createAlphaClipMask(genID, | 373 result.reset(this->createAlphaClipMask(genID, |
371 initialState, | 374 initialState, |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
417 } | 420 } |
418 } | 421 } |
419 | 422 |
420 //////////////////////////////////////////////////////////////////////////////// | 423 //////////////////////////////////////////////////////////////////////////////// |
421 bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder, | 424 bool GrClipMaskManager::drawElement(GrPipelineBuilder* pipelineBuilder, |
422 const SkMatrix& viewMatrix, | 425 const SkMatrix& viewMatrix, |
423 GrTexture* target, | 426 GrTexture* target, |
424 const SkClipStack::Element* element, | 427 const SkClipStack::Element* element, |
425 GrPathRenderer* pr) { | 428 GrPathRenderer* pr) { |
426 | 429 |
427 pipelineBuilder->setRenderTarget(target->asRenderTarget()); | 430 GrRenderTarget* rt = target->asRenderTarget(); |
| 431 pipelineBuilder->setRenderTarget(rt); |
428 | 432 |
429 // The color we use to draw does not matter since we will always be using a
GrCoverageSetOpXP | 433 // The color we use to draw does not matter since we will always be using a
GrCoverageSetOpXP |
430 // which ignores color. | 434 // which ignores color. |
431 GrColor color = GrColor_WHITE; | 435 GrColor color = GrColor_WHITE; |
432 | 436 |
433 // TODO: Draw rrects directly here. | 437 // TODO: Draw rrects directly here. |
434 switch (element->getType()) { | 438 switch (element->getType()) { |
435 case Element::kEmpty_Type: | 439 case Element::kEmpty_Type: |
436 SkDEBUGFAIL("Should never get here with an empty element."); | 440 SkDEBUGFAIL("Should never get here with an empty element."); |
437 break; | 441 break; |
(...skipping 15 matching lines...) Expand all Loading... |
453 SkPath path; | 457 SkPath path; |
454 element->asPath(&path); | 458 element->asPath(&path); |
455 if (path.isInverseFillType()) { | 459 if (path.isInverseFillType()) { |
456 path.toggleInverseFillType(); | 460 path.toggleInverseFillType(); |
457 } | 461 } |
458 GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle); | 462 GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle); |
459 if (nullptr == pr) { | 463 if (nullptr == pr) { |
460 GrPathRendererChain::DrawType type; | 464 GrPathRendererChain::DrawType type; |
461 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr
awType : | 465 type = element->isAA() ? GrPathRendererChain::kColorAntiAlias_Dr
awType : |
462 GrPathRendererChain::kColor_DrawType; | 466 GrPathRendererChain::kColor_DrawType; |
463 pr = this->getContext()->getPathRenderer(*pipelineBuilder, viewM
atrix, | 467 pr = this->getContext()->getPathRenderer(viewMatrix, |
464 path, stroke, false, ty
pe); | 468 path, stroke, false, ty
pe, |
| 469 pipelineBuilder->getSte
ncil().isDisabled(), |
| 470 rt->isStencilBufferMult
isampled()); |
465 } | 471 } |
466 if (nullptr == pr) { | 472 if (nullptr == pr) { |
467 return false; | 473 return false; |
468 } | 474 } |
469 GrPathRenderer::DrawPathArgs args; | 475 GrPathRenderer::DrawPathArgs args; |
470 args.fTarget = fDrawTarget; | 476 args.fTarget = fDrawTarget; |
471 args.fResourceProvider = this->getContext()->resourceProvider(); | 477 args.fResourceProvider = this->getContext()->resourceProvider(); |
472 args.fPipelineBuilder = pipelineBuilder; | 478 args.fPipelineBuilder = pipelineBuilder; |
473 args.fColor = color; | 479 args.fColor = color; |
474 args.fViewMatrix = &viewMatrix; | 480 args.fViewMatrix = &viewMatrix; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
599 | 605 |
600 // walk through each clip element and perform its set op | 606 // walk through each clip element and perform its set op |
601 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { | 607 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get()
; iter.next()) { |
602 const Element* element = iter.get(); | 608 const Element* element = iter.get(); |
603 SkRegion::Op op = element->getOp(); | 609 SkRegion::Op op = element->getOp(); |
604 bool invert = element->isInverseFilled(); | 610 bool invert = element->isInverseFilled(); |
605 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { | 611 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { |
606 GrPipelineBuilder pipelineBuilder; | 612 GrPipelineBuilder pipelineBuilder; |
607 | 613 |
608 pipelineBuilder.setClip(clip); | 614 pipelineBuilder.setClip(clip); |
| 615 pipelineBuilder.setRenderTarget(texture->asRenderTarget()); |
| 616 |
| 617 SkASSERT(pipelineBuilder.getStencil().isDisabled()); |
609 GrPathRenderer* pr = nullptr; | 618 GrPathRenderer* pr = nullptr; |
610 bool useTemp = !can_stencil_and_draw_element(this->getContext(), &pi
pelineBuilder, | 619 bool useTemp = !can_stencil_and_draw_element(this->getContext(), |
611 texture, translate, ele
ment, &pr); | 620 texture, translate, ele
ment, &pr); |
612 | 621 |
613 // useSWOnlyPath should now filter out all cases where gpu-side mask
merging is | 622 // useSWOnlyPath should now filter out all cases where gpu-side mask
merging is |
614 // performed. See skbug.com/4519 for rationale and details. | 623 // performed. See skbug.com/4519 for rationale and details. |
615 SkASSERT(!useTemp); | 624 SkASSERT(!useTemp); |
616 | 625 |
617 GrTexture* dst; | 626 GrTexture* dst; |
618 // This is the bounds of the clip element in the space of the alpha-
mask. The temporary | 627 // This is the bounds of the clip element in the space of the alpha-
mask. The temporary |
619 // mask buffer can be substantially larger than the actually clip st
ack element. We | 628 // mask buffer can be substantially larger than the actually clip st
ack element. We |
620 // touch the minimum number of pixels necessary and use decal mode t
o combine it with | 629 // touch the minimum number of pixels necessary and use decal mode t
o combine it with |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
779 SkPath clipPath; | 788 SkPath clipPath; |
780 if (Element::kRect_Type == element->getType()) { | 789 if (Element::kRect_Type == element->getType()) { |
781 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; | 790 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; |
782 fillInverted = false; | 791 fillInverted = false; |
783 } else { | 792 } else { |
784 element->asPath(&clipPath); | 793 element->asPath(&clipPath); |
785 fillInverted = clipPath.isInverseFillType(); | 794 fillInverted = clipPath.isInverseFillType(); |
786 if (fillInverted) { | 795 if (fillInverted) { |
787 clipPath.toggleInverseFillType(); | 796 clipPath.toggleInverseFillType(); |
788 } | 797 } |
789 pr = this->getContext()->getPathRenderer(pipelineBuilder, | 798 |
790 viewMatrix, | 799 SkASSERT(pipelineBuilder.getStencil().isDisabled()); |
| 800 |
| 801 pr = this->getContext()->getPathRenderer(viewMatrix, |
791 clipPath, | 802 clipPath, |
792 stroke, | 803 stroke, |
793 false, | 804 false, |
794 GrPathRendererChain::kS
tencilOnly_DrawType, | 805 GrPathRendererChain::kS
tencilOnly_DrawType, |
| 806 true, |
| 807 rt->isStencilBufferMult
isampled(), |
795 &stencilSupport); | 808 &stencilSupport); |
796 if (nullptr == pr) { | 809 if (nullptr == pr) { |
797 return false; | 810 return false; |
798 } | 811 } |
799 } | 812 } |
800 | 813 |
801 int passes; | 814 int passes; |
802 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClip
Passes]; | 815 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClip
Passes]; |
803 | 816 |
804 bool canRenderDirectToStencil = | 817 bool canRenderDirectToStencil = |
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1142 | 1155 |
1143 //////////////////////////////////////////////////////////////////////////////// | 1156 //////////////////////////////////////////////////////////////////////////////// |
1144 | 1157 |
1145 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc
ilAttachment, | 1158 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc
ilAttachment, |
1146 GrStencilSettings* settings) { | 1159 GrStencilSettings* settings) { |
1147 if (stencilAttachment) { | 1160 if (stencilAttachment) { |
1148 int stencilBits = stencilAttachment->bits(); | 1161 int stencilBits = stencilAttachment->bits(); |
1149 this->adjustStencilParams(settings, fClipMode, stencilBits); | 1162 this->adjustStencilParams(settings, fClipMode, stencilBits); |
1150 } | 1163 } |
1151 } | 1164 } |
OLD | NEW |