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 14 matching lines...) Expand all Loading... |
25 #include "effects/GrRRectEffect.h" | 25 #include "effects/GrRRectEffect.h" |
26 #include "effects/GrTextureDomain.h" | 26 #include "effects/GrTextureDomain.h" |
27 | 27 |
28 typedef SkClipStack::Element Element; | 28 typedef SkClipStack::Element Element; |
29 | 29 |
30 static const int kMaxAnalyticElements = 4; | 30 static const int kMaxAnalyticElements = 4; |
31 | 31 |
32 //////////////////////////////////////////////////////////////////////////////// | 32 //////////////////////////////////////////////////////////////////////////////// |
33 // set up the draw state to enable the aa clipping mask. Besides setting up the | 33 // set up the draw state to enable the aa clipping mask. Besides setting up the |
34 // stage matrix this also alters the vertex layout | 34 // stage matrix this also alters the vertex layout |
35 static sk_sp<const GrFragmentProcessor> create_fp_for_mask(GrTexture* result, | 35 static sk_sp<GrFragmentProcessor> create_fp_for_mask(GrTexture* result, |
36 const SkIRect &devBou
nd) { | 36 const SkIRect &devBound) { |
37 SkMatrix mat; | 37 SkMatrix mat; |
38 // We use device coords to compute the texture coordinates. We set our matri
x to be a | 38 // We use device coords to compute the texture coordinates. We set our matri
x to be a |
39 // translation to the devBound, and then a scaling matrix to normalized coor
ds. | 39 // translation to the devBound, and then a scaling matrix to normalized coor
ds. |
40 mat.setIDiv(result->width(), result->height()); | 40 mat.setIDiv(result->width(), result->height()); |
41 mat.preTranslate(SkIntToScalar(-devBound.fLeft), | 41 mat.preTranslate(SkIntToScalar(-devBound.fLeft), |
42 SkIntToScalar(-devBound.fTop)); | 42 SkIntToScalar(-devBound.fTop)); |
43 | 43 |
44 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); | 44 SkIRect domainTexels = SkIRect::MakeWH(devBound.width(), devBound.height()); |
45 return sk_sp<const GrFragmentProcessor>(GrTextureDomainEffect::Create( | 45 return sk_sp<GrFragmentProcessor>(GrTextureDomainEffect::Make( |
46 result, | 46 result, |
47 mat, | 47 mat, |
48 GrTextureDomain::MakeTexelDomain(result
, domainTexels), | 48 GrTextureDomain::MakeTexelDomain(result
, domainTexels), |
49 GrTextureDomain::kDecal_Mode, | 49 GrTextureDomain::kDecal_Mode, |
50 GrTextureParams::kNone_FilterMode, | 50 GrTextureParams::kNone_FilterMode, |
51 kDevice_GrCoordSet)); | 51 kDevice_GrCoordSet)); |
52 } | 52 } |
53 | 53 |
54 void GrClipMaskManager::DrawNonAARect(GrDrawContext* drawContext, | 54 void GrClipMaskManager::DrawNonAARect(GrDrawContext* drawContext, |
55 const GrFixedClip& clip, | 55 const GrFixedClip& clip, |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
149 return true; | 149 return true; |
150 } | 150 } |
151 } | 151 } |
152 return false; | 152 return false; |
153 } | 153 } |
154 | 154 |
155 static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elemen
ts, | 155 static bool get_analytic_clip_processor(const GrReducedClip::ElementList& elemen
ts, |
156 bool abortIfAA, | 156 bool abortIfAA, |
157 SkVector& clipToRTOffset, | 157 SkVector& clipToRTOffset, |
158 const SkRect* drawBounds, | 158 const SkRect* drawBounds, |
159 sk_sp<const GrFragmentProcessor>* result
FP) { | 159 sk_sp<GrFragmentProcessor>* resultFP) { |
160 SkRect boundsInClipSpace; | 160 SkRect boundsInClipSpace; |
161 if (drawBounds) { | 161 if (drawBounds) { |
162 boundsInClipSpace = *drawBounds; | 162 boundsInClipSpace = *drawBounds; |
163 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); | 163 boundsInClipSpace.offset(-clipToRTOffset.fX, -clipToRTOffset.fY); |
164 } | 164 } |
165 SkASSERT(elements.count() <= kMaxAnalyticElements); | 165 SkASSERT(elements.count() <= kMaxAnalyticElements); |
166 const GrFragmentProcessor* fps[kMaxAnalyticElements]; | 166 SkSTArray<kMaxAnalyticElements, sk_sp<GrFragmentProcessor>> fps; |
167 for (int i = 0; i < kMaxAnalyticElements; ++i) { | |
168 fps[i] = nullptr; | |
169 } | |
170 int fpCnt = 0; | |
171 GrReducedClip::ElementList::Iter iter(elements); | 167 GrReducedClip::ElementList::Iter iter(elements); |
172 bool failed = false; | |
173 while (iter.get()) { | 168 while (iter.get()) { |
174 SkRegion::Op op = iter.get()->getOp(); | 169 SkRegion::Op op = iter.get()->getOp(); |
175 bool invert; | 170 bool invert; |
176 bool skip = false; | 171 bool skip = false; |
177 switch (op) { | 172 switch (op) { |
178 case SkRegion::kReplace_Op: | 173 case SkRegion::kReplace_Op: |
179 SkASSERT(iter.get() == elements.head()); | 174 SkASSERT(iter.get() == elements.head()); |
180 // Fallthrough, handled same as intersect. | 175 // Fallthrough, handled same as intersect. |
181 case SkRegion::kIntersect_Op: | 176 case SkRegion::kIntersect_Op: |
182 invert = false; | 177 invert = false; |
183 if (drawBounds && iter.get()->contains(boundsInClipSpace)) { | 178 if (drawBounds && iter.get()->contains(boundsInClipSpace)) { |
184 skip = true; | 179 skip = true; |
185 } | 180 } |
186 break; | 181 break; |
187 case SkRegion::kDifference_Op: | 182 case SkRegion::kDifference_Op: |
188 invert = true; | 183 invert = true; |
189 // We don't currently have a cheap test for whether a rect is fu
lly outside an | 184 // We don't currently have a cheap test for whether a rect is fu
lly outside an |
190 // element's primitive, so don't attempt to set skip. | 185 // element's primitive, so don't attempt to set skip. |
191 break; | 186 break; |
192 default: | 187 default: |
193 failed = true; | 188 return false; |
194 break; | |
195 } | |
196 if (failed) { | |
197 break; | |
198 } | 189 } |
199 if (!skip) { | 190 if (!skip) { |
200 GrPrimitiveEdgeType edgeType; | 191 GrPrimitiveEdgeType edgeType; |
201 if (iter.get()->isAA()) { | 192 if (iter.get()->isAA()) { |
202 if (abortIfAA) { | 193 if (abortIfAA) { |
203 failed = true; | 194 return false; |
204 break; | |
205 } | 195 } |
206 edgeType = | 196 edgeType = |
207 invert ? kInverseFillAA_GrProcessorEdgeType : kFillAA_GrProc
essorEdgeType; | 197 invert ? kInverseFillAA_GrProcessorEdgeType : kFillAA_GrProc
essorEdgeType; |
208 } else { | 198 } else { |
209 edgeType = | 199 edgeType = |
210 invert ? kInverseFillBW_GrProcessorEdgeType : kFillBW_GrProc
essorEdgeType; | 200 invert ? kInverseFillBW_GrProcessorEdgeType : kFillBW_GrProc
essorEdgeType; |
211 } | 201 } |
212 | 202 |
213 switch (iter.get()->getType()) { | 203 switch (iter.get()->getType()) { |
214 case SkClipStack::Element::kPath_Type: | 204 case SkClipStack::Element::kPath_Type: |
215 fps[fpCnt] = GrConvexPolyEffect::Create(edgeType, iter.get()
->getPath(), | 205 fps.emplace_back(GrConvexPolyEffect::Make(edgeType, iter.get
()->getPath(), |
216 &clipToRTOffset); | 206 &clipToRTOffset)); |
217 break; | 207 break; |
218 case SkClipStack::Element::kRRect_Type: { | 208 case SkClipStack::Element::kRRect_Type: { |
219 SkRRect rrect = iter.get()->getRRect(); | 209 SkRRect rrect = iter.get()->getRRect(); |
220 rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY); | 210 rrect.offset(clipToRTOffset.fX, clipToRTOffset.fY); |
221 fps[fpCnt] = GrRRectEffect::Create(edgeType, rrect); | 211 fps.emplace_back(GrRRectEffect::Make(edgeType, rrect)); |
222 break; | 212 break; |
223 } | 213 } |
224 case SkClipStack::Element::kRect_Type: { | 214 case SkClipStack::Element::kRect_Type: { |
225 SkRect rect = iter.get()->getRect(); | 215 SkRect rect = iter.get()->getRect(); |
226 rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); | 216 rect.offset(clipToRTOffset.fX, clipToRTOffset.fY); |
227 fps[fpCnt] = GrConvexPolyEffect::Create(edgeType, rect); | 217 fps.emplace_back(GrConvexPolyEffect::Make(edgeType, rect)); |
228 break; | 218 break; |
229 } | 219 } |
230 default: | 220 default: |
231 break; | 221 break; |
232 } | 222 } |
233 if (!fps[fpCnt]) { | 223 if (!fps.back()) { |
234 failed = true; | 224 return false; |
235 break; | |
236 } | 225 } |
237 fpCnt++; | |
238 } | 226 } |
239 iter.next(); | 227 iter.next(); |
240 } | 228 } |
241 | 229 |
242 *resultFP = nullptr; | 230 *resultFP = nullptr; |
243 if (!failed && fpCnt) { | 231 if (fps.count()) { |
244 resultFP->reset(GrFragmentProcessor::RunInSeries(fps, fpCnt)); | 232 *resultFP = GrFragmentProcessor::RunInSeries(fps.begin(), fps.count()); |
245 } | 233 } |
246 for (int i = 0; i < fpCnt; ++i) { | 234 return true; |
247 fps[i]->unref(); | |
248 } | |
249 return !failed; | |
250 } | 235 } |
251 | 236 |
252 //////////////////////////////////////////////////////////////////////////////// | 237 //////////////////////////////////////////////////////////////////////////////// |
253 // sort out what kind of clip mask needs to be created: alpha, stencil, | 238 // sort out what kind of clip mask needs to be created: alpha, stencil, |
254 // scissor, or entirely software | 239 // scissor, or entirely software |
255 bool GrClipMaskManager::SetupClipping(GrContext* context, | 240 bool GrClipMaskManager::SetupClipping(GrContext* context, |
256 const GrPipelineBuilder& pipelineBuilder, | 241 const GrPipelineBuilder& pipelineBuilder, |
257 GrDrawContext* drawContext, | 242 GrDrawContext* drawContext, |
258 const GrClipStackClip& clip, | 243 const GrClipStackClip& clip, |
259 const SkRect* devBounds, | 244 const SkRect* devBounds, |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 // When there are multiple samples we want to do per-sample clipping, no
t compute a | 298 // When there are multiple samples we want to do per-sample clipping, no
t compute a |
314 // fractional pixel coverage. | 299 // fractional pixel coverage. |
315 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled(); | 300 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled(); |
316 if (disallowAnalyticAA && !drawContext->numColorSamples()) { | 301 if (disallowAnalyticAA && !drawContext->numColorSamples()) { |
317 // With a single color sample, any coverage info is lost from color
once it hits the | 302 // With a single color sample, any coverage info is lost from color
once it hits the |
318 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe | 303 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe |
319 // is multisampled. | 304 // is multisampled. |
320 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || | 305 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || |
321 pipelineBuilder.hasUserStencilSettings(); | 306 pipelineBuilder.hasUserStencilSettings(); |
322 } | 307 } |
323 sk_sp<const GrFragmentProcessor> clipFP; | 308 sk_sp<GrFragmentProcessor> clipFP; |
324 if (elements.isEmpty() || | 309 if (elements.isEmpty() || |
325 (requiresAA && | 310 (requiresAA && |
326 get_analytic_clip_processor(elements, disallowAnalyticAA, clipToRTO
ffset, devBounds, | 311 get_analytic_clip_processor(elements, disallowAnalyticAA, clipToRTO
ffset, devBounds, |
327 &clipFP))) { | 312 &clipFP))) { |
328 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 313 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
329 scissorSpaceIBounds.offset(-clip.origin()); | 314 scissorSpaceIBounds.offset(-clip.origin()); |
330 if (!devBounds || !SkRect::Make(scissorSpaceIBounds).contains(*devBo
unds)) { | 315 if (!devBounds || !SkRect::Make(scissorSpaceIBounds).contains(*devBo
unds)) { |
331 out->makeScissoredFPBased(clipFP, scissorSpaceIBounds); | 316 out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds
); |
332 return true; | 317 return true; |
333 } | 318 } |
334 out->makeFPBased(clipFP); | 319 out->makeFPBased(std::move(clipFP)); |
335 return true; | 320 return true; |
336 } | 321 } |
337 } | 322 } |
338 | 323 |
339 // If the stencil buffer is multisampled we can use it to do everything. | 324 // If the stencil buffer is multisampled we can use it to do everything. |
340 if (!drawContext->isStencilBufferMultisampled() && requiresAA) { | 325 if (!drawContext->isStencilBufferMultisampled() && requiresAA) { |
341 sk_sp<GrTexture> result; | 326 sk_sp<GrTexture> result; |
342 | 327 |
343 // The top-left of the mask corresponds to the top-left corner of the bo
unds. | 328 // The top-left of the mask corresponds to the top-left corner of the bo
unds. |
344 SkVector clipToMaskOffset = { | 329 SkVector clipToMaskOffset = { |
(...skipping 331 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
676 GrUserStencilOp::kIncMaybeClamp, | 661 GrUserStencilOp::kIncMaybeClamp, |
677 0xffff>() | 662 0xffff>() |
678 ); | 663 ); |
679 if (Element::kRect_Type == element->getType()) { | 664 if (Element::kRect_Type == element->getType()) { |
680 DrawNonAARect(drawContext, clip, viewMatrix, | 665 DrawNonAARect(drawContext, clip, viewMatrix, |
681 element->getRect(), element->isAA(), &kDrawToS
tencil); | 666 element->getRect(), element->isAA(), &kDrawToS
tencil); |
682 } else { | 667 } else { |
683 if (!clipPath.isEmpty()) { | 668 if (!clipPath.isEmpty()) { |
684 if (canRenderDirectToStencil) { | 669 if (canRenderDirectToStencil) { |
685 GrPaint paint; | 670 GrPaint paint; |
686 SkSafeUnref(paint.setXPFactory(GrDisableColorXPFacto
ry::Create())); | 671 paint.setXPFactory(GrDisableColorXPFactory::Make()); |
687 paint.setAntiAlias(element->isAA()); | 672 paint.setAntiAlias(element->isAA()); |
688 | 673 |
689 GrPathRenderer::DrawPathArgs args; | 674 GrPathRenderer::DrawPathArgs args; |
690 args.fResourceProvider = context->resourceProvider()
; | 675 args.fResourceProvider = context->resourceProvider()
; |
691 args.fPaint = &paint; | 676 args.fPaint = &paint; |
692 args.fUserStencilSettings = &kDrawToStencil; | 677 args.fUserStencilSettings = &kDrawToStencil; |
693 args.fDrawContext = drawContext; | 678 args.fDrawContext = drawContext; |
694 args.fClip = &clip; | 679 args.fClip = &clip; |
695 args.fColor = GrColor_WHITE; | 680 args.fColor = GrColor_WHITE; |
696 args.fViewMatrix = &viewMatrix; | 681 args.fViewMatrix = &viewMatrix; |
(...skipping 20 matching lines...) Expand all Loading... |
717 // element directly or a bounding rect of the entire clip. | 702 // element directly or a bounding rect of the entire clip. |
718 clip.enableStencilClip(true); | 703 clip.enableStencilClip(true); |
719 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass
; ++pass) { | 704 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass
; ++pass) { |
720 | 705 |
721 if (drawDirectToClip) { | 706 if (drawDirectToClip) { |
722 if (Element::kRect_Type == element->getType()) { | 707 if (Element::kRect_Type == element->getType()) { |
723 DrawNonAARect(drawContext, clip, | 708 DrawNonAARect(drawContext, clip, |
724 viewMatrix, element->getRect(), element->i
sAA(), *pass); | 709 viewMatrix, element->getRect(), element->i
sAA(), *pass); |
725 } else { | 710 } else { |
726 GrPaint paint; | 711 GrPaint paint; |
727 SkSafeUnref(paint.setXPFactory(GrDisableColorXPFactory::
Create())); | 712 paint.setXPFactory(GrDisableColorXPFactory::Make()); |
728 paint.setAntiAlias(element->isAA()); | 713 paint.setAntiAlias(element->isAA()); |
729 | 714 |
730 GrPathRenderer::DrawPathArgs args; | 715 GrPathRenderer::DrawPathArgs args; |
731 args.fResourceProvider = context->resourceProvider(); | 716 args.fResourceProvider = context->resourceProvider(); |
732 args.fPaint = &paint; | 717 args.fPaint = &paint; |
733 args.fUserStencilSettings = *pass; | 718 args.fUserStencilSettings = *pass; |
734 args.fDrawContext = drawContext; | 719 args.fDrawContext = drawContext; |
735 args.fClip = &clip; | 720 args.fClip = &clip; |
736 args.fColor = GrColor_WHITE; | 721 args.fColor = GrColor_WHITE; |
737 args.fViewMatrix = &viewMatrix; | 722 args.fViewMatrix = &viewMatrix; |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
823 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); | 808 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); |
824 if (!result) { | 809 if (!result) { |
825 return nullptr; | 810 return nullptr; |
826 } | 811 } |
827 result->resourcePriv().setUniqueKey(key); | 812 result->resourcePriv().setUniqueKey(key); |
828 | 813 |
829 helper.toTexture(result.get()); | 814 helper.toTexture(result.get()); |
830 | 815 |
831 return result; | 816 return result; |
832 } | 817 } |
OLD | NEW |