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