| 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 |