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 28 matching lines...) Expand all Loading... |
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 tryStencilFirst) { |
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 if (prOut) { |
| 62 *prOut = nullptr; |
| 63 } |
| 64 return false; |
| 65 } else { |
| 66 // We shouldn't get here with an empty clip element. |
| 67 SkASSERT(Element::kEmpty_Type != element->getType()); |
| 68 |
| 69 // the gpu alpha mask will draw the inverse paths as non-inverse to a te
mp buffer |
| 70 SkPath path; |
| 71 element->asPath(&path); |
| 72 if (path.isInverseFillType()) { |
| 73 path.toggleInverseFillType(); |
| 74 } |
| 75 GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle); |
| 76 |
| 77 GrPathRendererChain::DrawType type; |
| 78 |
| 79 if (tryStencilFirst) { |
| 80 type = element->isAA() |
| 81 ? GrPathRendererChain::kStencilAndColorAntiAlias_Dra
wType |
| 82 : GrPathRendererChain::kStencilAndColor_DrawType; |
| 83 } else { |
| 84 type = element->isAA() |
| 85 ? GrPathRendererChain::kColorAntiAlias_DrawType |
| 86 : GrPathRendererChain::kColor_DrawType; |
| 87 } |
| 88 |
| 89 // the 'false' parameter disallows use of the SW path renderer |
| 90 GrPathRenderer* pr = context->getPathRenderer(&pipelineBuilder, viewMatr
ix, path, |
| 91 stroke, false, type); |
| 92 if (tryStencilFirst && !pr) { |
| 93 // If the path can't be stenciled, createAlphaClipMask falls back to
color rendering |
| 94 // it into a temporary buffer. If that fails then SW is truly requir
ed. |
| 95 type = element->isAA() |
| 96 ? GrPathRendererChain::kColorAntiAlias_DrawType |
| 97 : GrPathRendererChain::kColor_DrawType; |
| 98 |
| 99 pr = context->getPathRenderer(&pipelineBuilder, viewMatrix, path, st
roke, false, type); |
| 100 } |
| 101 |
| 102 if (prOut) { |
| 103 *prOut = pr; |
| 104 } |
| 105 return SkToBool(!pr); |
59 } | 106 } |
60 // last (false) parameter disallows use of the SW path renderer | |
61 GrPathRendererChain::DrawType type = doAA ? | |
62 GrPathRendererChain::kColorAntiAlias_Dr
awType : | |
63 GrPathRendererChain::kColor_DrawType; | |
64 | |
65 return nullptr == context->getPathRenderer(&pipelineBuilder, viewMatrix, *pa
th, stroke, | |
66 false, type); | |
67 } | 107 } |
68 | 108 |
69 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget) | 109 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget) |
70 : fDrawTarget(drawTarget) | 110 : fDrawTarget(drawTarget) |
71 , fClipMode(kIgnoreClip_StencilClipMode) { | 111 , fClipMode(kIgnoreClip_StencilClipMode) { |
72 } | 112 } |
73 | 113 |
74 GrContext* GrClipMaskManager::getContext() { return fDrawTarget->cmmAccess().con
text(); } | 114 GrContext* GrClipMaskManager::getContext() { return fDrawTarget->cmmAccess().con
text(); } |
75 | 115 |
76 /* | 116 /* |
77 * This method traverses the clip stack to see if the GrSoftwarePathRenderer | 117 * 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 | 118 * 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. | 119 * entire clip should be rendered in SW and then uploaded en masse to the gpu. |
80 */ | 120 */ |
81 bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder, | 121 bool GrClipMaskManager::useSWOnlyPath(const GrPipelineBuilder& pipelineBuilder, |
82 const SkVector& clipToMaskOffset, | 122 const SkVector& clipToMaskOffset, |
83 const GrReducedClip::ElementList& elements
) { | 123 const GrReducedClip::ElementList& elements
) { |
84 // TODO: generalize this function so that when | 124 // TODO: generalize this function so that when |
85 // a clip gets complex enough it can just be done in SW regardless | 125 // a clip gets complex enough it can just be done in SW regardless |
86 // of whether it would invoke the GrSoftwarePathRenderer. | 126 // of whether it would invoke the GrSoftwarePathRenderer. |
87 GrStrokeInfo stroke(SkStrokeRec::kFill_InitStyle); | |
88 | 127 |
89 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip | 128 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip |
90 // space. | 129 // space. |
91 SkMatrix translate; | 130 SkMatrix translate; |
92 translate.setTranslate(clipToMaskOffset); | 131 translate.setTranslate(clipToMaskOffset); |
93 | 132 |
94 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { | 133 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { |
95 const Element* element = iter.get(); | 134 const Element* element = iter.get(); |
96 // rects can always be drawn directly w/o using the software path | 135 |
97 // Skip rrects once we're drawing them directly. | 136 SkRegion::Op op = element->getOp(); |
98 if (Element::kRect_Type != element->getType()) { | 137 bool invert = element->isInverseFilled(); |
99 SkPath path; | 138 bool tryStencilFirst = invert || |
100 element->asPath(&path); | 139 SkRegion::kIntersect_Op == op || |
101 if (path_needs_SW_renderer(this->getContext(), pipelineBuilder, tran
slate, | 140 SkRegion::kReverseDifference_Op == op; |
102 path, stroke, element->isAA())) { | 141 |
103 return true; | 142 if (path_needs_SW_renderer(this->getContext(), pipelineBuilder, translat
e, |
104 } | 143 element, nullptr, tryStencilFirst)) { |
| 144 return true; |
105 } | 145 } |
106 } | 146 } |
107 return false; | 147 return false; |
108 } | 148 } |
109 | 149 |
110 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, | 150 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, |
111 bool abortIfAA, | 151 bool abortIfAA, |
112 SkVector& clipToRTOffset, | 152 SkVector& clipToRTOffset, |
113 const SkRect* drawBounds, | 153 const SkRect* drawBounds, |
114 const GrFragmentProcessor** res
ultFP) { | 154 const GrFragmentProcessor** res
ultFP) { |
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
318 initialState, | 358 initialState, |
319 elements, | 359 elements, |
320 clipToMaskOffset, | 360 clipToMaskOffset, |
321 clipSpaceIBounds)); | 361 clipSpaceIBounds)); |
322 } else { | 362 } else { |
323 result.reset(this->createAlphaClipMask(genID, | 363 result.reset(this->createAlphaClipMask(genID, |
324 initialState, | 364 initialState, |
325 elements, | 365 elements, |
326 clipToMaskOffset, | 366 clipToMaskOffset, |
327 clipSpaceIBounds)); | 367 clipSpaceIBounds)); |
| 368 // If createAlphaClipMask fails it means useSWOnlyPath has a bug |
| 369 SkASSERT(result); |
328 } | 370 } |
329 | 371 |
330 if (result) { | 372 if (result) { |
331 // The mask's top left coord should be pinned to the rounded-out top
left corner of | 373 // The mask's top left coord should be pinned to the rounded-out top
left corner of |
332 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. | 374 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. |
333 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; | 375 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
334 rtSpaceMaskBounds.offset(-clip.origin()); | 376 rtSpaceMaskBounds.offset(-clip.origin()); |
335 out->fClipCoverageFP.reset(create_fp_for_mask(result, rtSpaceMaskBou
nds)); | 377 out->fClipCoverageFP.reset(create_fp_for_mask(result, rtSpaceMaskBou
nds)); |
336 this->setPipelineBuilderStencil(pipelineBuilder, ars); | 378 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
337 return true; | 379 return true; |
(...skipping 776 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1114 | 1156 |
1115 //////////////////////////////////////////////////////////////////////////////// | 1157 //////////////////////////////////////////////////////////////////////////////// |
1116 | 1158 |
1117 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc
ilAttachment, | 1159 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc
ilAttachment, |
1118 GrStencilSettings* settings) { | 1160 GrStencilSettings* settings) { |
1119 if (stencilAttachment) { | 1161 if (stencilAttachment) { |
1120 int stencilBits = stencilAttachment->bits(); | 1162 int stencilBits = stencilAttachment->bits(); |
1121 this->adjustStencilParams(settings, fClipMode, stencilBits); | 1163 this->adjustStencilParams(settings, fClipMode, stencilBits); |
1122 } | 1164 } |
1123 } | 1165 } |
OLD | NEW |