| 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 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 55 const SkRect& rect) { | 55 const SkRect& rect) { |
| 56 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, v
iewMatrix, rect, | 56 SkAutoTUnref<GrDrawBatch> batch(GrRectBatchFactory::CreateNonAAFill(color, v
iewMatrix, rect, |
| 57 nullptr,
nullptr)); | 57 nullptr,
nullptr)); |
| 58 drawTarget->drawBatch(pipelineBuilder, batch); | 58 drawTarget->drawBatch(pipelineBuilder, batch); |
| 59 } | 59 } |
| 60 | 60 |
| 61 // Does the path in 'element' require SW rendering? If so, return true (and, | 61 // Does the path in 'element' require SW rendering? If so, return true (and, |
| 62 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set | 62 // optionally, set 'prOut' to NULL. If not, return false (and, optionally, set |
| 63 // 'prOut' to the non-SW path renderer that will do the job). | 63 // 'prOut' to the non-SW path renderer that will do the job). |
| 64 bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context, | 64 bool GrClipMaskManager::PathNeedsSWRenderer(GrContext* context, |
| 65 bool hasUserStencilSettings, | 65 bool isStencilDisabled, |
| 66 const GrRenderTarget* rt, | 66 const GrRenderTarget* rt, |
| 67 const SkMatrix& viewMatrix, | 67 const SkMatrix& viewMatrix, |
| 68 const Element* element, | 68 const Element* element, |
| 69 GrPathRenderer** prOut, | 69 GrPathRenderer** prOut, |
| 70 bool needsStencil) { | 70 bool needsStencil) { |
| 71 if (Element::kRect_Type == element->getType()) { | 71 if (Element::kRect_Type == element->getType()) { |
| 72 // rects can always be drawn directly w/o using the software path | 72 // rects can always be drawn directly w/o using the software path |
| 73 // TODO: skip rrects once we're drawing them directly. | 73 // TODO: skip rrects once we're drawing them directly. |
| 74 if (prOut) { | 74 if (prOut) { |
| 75 *prOut = nullptr; | 75 *prOut = nullptr; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 97 ? GrPathRendererChain::kColorAntiAlias_DrawType | 97 ? GrPathRendererChain::kColorAntiAlias_DrawType |
| 98 : GrPathRendererChain::kColor_DrawType; | 98 : GrPathRendererChain::kColor_DrawType; |
| 99 } | 99 } |
| 100 | 100 |
| 101 GrPathRenderer::CanDrawPathArgs canDrawArgs; | 101 GrPathRenderer::CanDrawPathArgs canDrawArgs; |
| 102 canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); | 102 canDrawArgs.fShaderCaps = context->caps()->shaderCaps(); |
| 103 canDrawArgs.fViewMatrix = &viewMatrix; | 103 canDrawArgs.fViewMatrix = &viewMatrix; |
| 104 canDrawArgs.fPath = &path; | 104 canDrawArgs.fPath = &path; |
| 105 canDrawArgs.fStyle = &GrStyle::SimpleFill(); | 105 canDrawArgs.fStyle = &GrStyle::SimpleFill(); |
| 106 canDrawArgs.fAntiAlias = element->isAA(); | 106 canDrawArgs.fAntiAlias = element->isAA(); |
| 107 canDrawArgs.fHasUserStencilSettings = hasUserStencilSettings; | 107 canDrawArgs.fIsStencilDisabled = isStencilDisabled; |
| 108 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled(); | 108 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampled(); |
| 109 | 109 |
| 110 // the 'false' parameter disallows use of the SW path renderer | 110 // the 'false' parameter disallows use of the SW path renderer |
| 111 GrPathRenderer* pr = context->drawingManager()->getPathRenderer(canDrawA
rgs, false, type); | 111 GrPathRenderer* pr = context->drawingManager()->getPathRenderer(canDrawA
rgs, false, type); |
| 112 if (prOut) { | 112 if (prOut) { |
| 113 *prOut = pr; | 113 *prOut = pr; |
| 114 } | 114 } |
| 115 return SkToBool(!pr); | 115 return SkToBool(!pr); |
| 116 } | 116 } |
| 117 } | 117 } |
| 118 | 118 |
| 119 // Determines whether it is possible to draw the element to both the stencil buf
fer and the | 119 // Determines whether it is possible to draw the element to both the stencil buf
fer and the |
| 120 // alpha mask simultaneously. If so and the element is a path a compatible path
renderer is | 120 // alpha mask simultaneously. If so and the element is a path a compatible path
renderer is |
| 121 // also returned. | 121 // also returned. |
| 122 GrPathRenderer* GrClipMaskManager::GetPathRenderer(GrContext* context, | 122 GrPathRenderer* GrClipMaskManager::GetPathRenderer(GrContext* context, |
| 123 GrTexture* texture, | 123 GrTexture* texture, |
| 124 const SkMatrix& viewMatrix, | 124 const SkMatrix& viewMatrix, |
| 125 const SkClipStack::Element* e
lement) { | 125 const SkClipStack::Element* e
lement) { |
| 126 GrPathRenderer* pr; | 126 GrPathRenderer* pr; |
| 127 constexpr bool kNeedsStencil = true; | 127 static const bool kNeedsStencil = true; |
| 128 constexpr bool kHasUserStencilSettings = false; | 128 static const bool kStencilIsDisabled = true; |
| 129 PathNeedsSWRenderer(context, | 129 PathNeedsSWRenderer(context, |
| 130 kHasUserStencilSettings, | 130 kStencilIsDisabled, |
| 131 texture->asRenderTarget(), | 131 texture->asRenderTarget(), |
| 132 viewMatrix, | 132 viewMatrix, |
| 133 element, | 133 element, |
| 134 &pr, | 134 &pr, |
| 135 kNeedsStencil); | 135 kNeedsStencil); |
| 136 return pr; | 136 return pr; |
| 137 } | 137 } |
| 138 | 138 |
| 139 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget, bool debugClipBat
chToBounds) | 139 GrClipMaskManager::GrClipMaskManager(GrDrawTarget* drawTarget, bool debugClipBat
chToBounds) |
| 140 : fDrawTarget(drawTarget) | 140 : fDrawTarget(drawTarget) |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 172 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); | 172 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); |
| 173 | 173 |
| 174 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { | 174 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.get();
iter.next()) { |
| 175 const Element* element = iter.get(); | 175 const Element* element = iter.get(); |
| 176 | 176 |
| 177 SkRegion::Op op = element->getOp(); | 177 SkRegion::Op op = element->getOp(); |
| 178 bool invert = element->isInverseFilled(); | 178 bool invert = element->isInverseFilled(); |
| 179 bool needsStencil = invert || | 179 bool needsStencil = invert || |
| 180 SkRegion::kIntersect_Op == op || SkRegion::kReverseD
ifference_Op == op; | 180 SkRegion::kIntersect_Op == op || SkRegion::kReverseD
ifference_Op == op; |
| 181 | 181 |
| 182 if (PathNeedsSWRenderer(context, pipelineBuilder.hasUserStencilSettings(
), | 182 if (PathNeedsSWRenderer(context, pipelineBuilder.getStencil().isDisabled
(), |
| 183 rt, translate, element, nullptr, needsStencil))
{ | 183 rt, translate, element, nullptr, needsStencil))
{ |
| 184 return true; | 184 return true; |
| 185 } | 185 } |
| 186 } | 186 } |
| 187 return false; | 187 return false; |
| 188 } | 188 } |
| 189 | 189 |
| 190 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, | 190 bool GrClipMaskManager::getAnalyticClipProcessor(const GrReducedClip::ElementLis
t& elements, |
| 191 bool abortIfAA, | 191 bool abortIfAA, |
| 192 SkVector& clipToRTOffset, | 192 SkVector& clipToRTOffset, |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 310 *out = GrClip(intersect); | 310 *out = GrClip(intersect); |
| 311 } else { | 311 } else { |
| 312 *out = clip; | 312 *out = clip; |
| 313 } | 313 } |
| 314 break; | 314 break; |
| 315 } | 315 } |
| 316 } | 316 } |
| 317 } | 317 } |
| 318 | 318 |
| 319 bool GrClipMaskManager::setupScissorClip(const GrPipelineBuilder& pipelineBuilde
r, | 319 bool GrClipMaskManager::setupScissorClip(const GrPipelineBuilder& pipelineBuilde
r, |
| 320 GrPipelineBuilder::AutoRestoreStencil*
ars, |
| 320 const SkIRect& clipScissor, | 321 const SkIRect& clipScissor, |
| 321 const SkRect* devBounds, | 322 const SkRect* devBounds, |
| 322 GrAppliedClip* out) { | 323 GrAppliedClip* out) { |
| 323 SkASSERT(kModifyClip_StencilClipMode != fClipMode); // TODO: Remove fClipMod
e. | 324 if (kRespectClip_StencilClipMode == fClipMode) { |
| 324 fClipMode = kIgnoreClip_StencilClipMode; | 325 fClipMode = kIgnoreClip_StencilClipMode; |
| 326 } |
| 325 | 327 |
| 326 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); | 328 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
| 327 | 329 |
| 328 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); | 330 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); |
| 329 SkIRect devBoundsScissor; | 331 SkIRect devBoundsScissor; |
| 330 const SkIRect* scissor = &clipScissor; | 332 const SkIRect* scissor = &clipScissor; |
| 331 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; | 333 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; |
| 332 if (doDevBoundsClip) { | 334 if (doDevBoundsClip) { |
| 333 devBounds->roundOut(&devBoundsScissor); | 335 devBounds->roundOut(&devBoundsScissor); |
| 334 if (devBoundsScissor.intersect(clipScissor)) { | 336 if (devBoundsScissor.intersect(clipScissor)) { |
| 335 scissor = &devBoundsScissor; | 337 scissor = &devBoundsScissor; |
| 336 } | 338 } |
| 337 } | 339 } |
| 338 | 340 |
| 339 if (scissor->contains(clipSpaceRTIBounds)) { | 341 if (scissor->contains(clipSpaceRTIBounds)) { |
| 340 // This counts as wide open | 342 // This counts as wide open |
| 343 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
| 341 return true; | 344 return true; |
| 342 } | 345 } |
| 343 | 346 |
| 344 if (clipSpaceRTIBounds.intersect(*scissor)) { | 347 if (clipSpaceRTIBounds.intersect(*scissor)) { |
| 345 out->fScissorState.set(clipSpaceRTIBounds); | 348 out->fScissorState.set(clipSpaceRTIBounds); |
| 349 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
| 346 return true; | 350 return true; |
| 347 } | 351 } |
| 348 return false; | 352 return false; |
| 349 } | 353 } |
| 350 | 354 |
| 351 //////////////////////////////////////////////////////////////////////////////// | 355 //////////////////////////////////////////////////////////////////////////////// |
| 352 // sort out what kind of clip mask needs to be created: alpha, stencil, | 356 // sort out what kind of clip mask needs to be created: alpha, stencil, |
| 353 // scissor, or entirely software | 357 // scissor, or entirely software |
| 354 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, | 358 bool GrClipMaskManager::setupClipping(const GrPipelineBuilder& pipelineBuilder, |
| 359 GrPipelineBuilder::AutoRestoreStencil* ars
, |
| 355 const SkRect* devBounds, | 360 const SkRect* devBounds, |
| 356 GrAppliedClip* out) { | 361 GrAppliedClip* out) { |
| 357 if (kRespectClip_StencilClipMode == fClipMode) { | 362 if (kRespectClip_StencilClipMode == fClipMode) { |
| 358 fClipMode = kIgnoreClip_StencilClipMode; | 363 fClipMode = kIgnoreClip_StencilClipMode; |
| 359 } | 364 } |
| 360 | 365 |
| 361 GrReducedClip::ElementList elements; | 366 GrReducedClip::ElementList elements; |
| 362 int32_t genID = 0; | 367 int32_t genID = 0; |
| 363 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat
e; | 368 GrReducedClip::InitialState initialState = GrReducedClip::kAllIn_InitialStat
e; |
| 364 SkIRect clipSpaceIBounds; | 369 SkIRect clipSpaceIBounds; |
| 365 bool requiresAA = false; | 370 bool requiresAA = false; |
| 366 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); | 371 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
| 367 | 372 |
| 368 // GrDrawTarget should have filtered this for us | 373 // GrDrawTarget should have filtered this for us |
| 369 SkASSERT(rt); | 374 SkASSERT(rt); |
| 370 | 375 |
| 371 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); | 376 SkIRect clipSpaceRTIBounds = SkIRect::MakeWH(rt->width(), rt->height()); |
| 372 GrClip devBoundsClip; | 377 GrClip devBoundsClip; |
| 373 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; | 378 bool doDevBoundsClip = fDebugClipBatchToBounds && devBounds; |
| 374 if (doDevBoundsClip) { | 379 if (doDevBoundsClip) { |
| 375 add_rect_to_clip(pipelineBuilder.clip(), *devBounds, &devBoundsClip); | 380 add_rect_to_clip(pipelineBuilder.clip(), *devBounds, &devBoundsClip); |
| 376 } | 381 } |
| 377 const GrClip& clip = doDevBoundsClip ? devBoundsClip : pipelineBuilder.clip(
); | 382 const GrClip& clip = doDevBoundsClip ? devBoundsClip : pipelineBuilder.clip(
); |
| 378 | 383 |
| 379 if (clip.isWideOpen(clipSpaceRTIBounds)) { | 384 if (clip.isWideOpen(clipSpaceRTIBounds)) { |
| 385 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
| 380 return true; | 386 return true; |
| 381 } | 387 } |
| 382 | 388 |
| 383 // The clip mask manager always draws with a single IRect so we special case
that logic here | 389 // The clip mask manager always draws with a single IRect so we special case
that logic here |
| 384 // Image filters just use a rect, so we also special case that logic | 390 // Image filters just use a rect, so we also special case that logic |
| 385 switch (clip.clipType()) { | 391 switch (clip.clipType()) { |
| 386 case GrClip::kWideOpen_ClipType: | 392 case GrClip::kWideOpen_ClipType: |
| 387 SkFAIL("Should have caught this with clip.isWideOpen()"); | 393 SkFAIL("Should have caught this with clip.isWideOpen()"); |
| 388 return true; | 394 return true; |
| 389 case GrClip::kIRect_ClipType: { | 395 case GrClip::kIRect_ClipType: { |
| 390 SkIRect scissor = clip.irect(); | 396 SkIRect scissor = clip.irect(); |
| 391 if (scissor.intersect(clipSpaceRTIBounds)) { | 397 if (scissor.intersect(clipSpaceRTIBounds)) { |
| 392 out->fScissorState.set(scissor); | 398 out->fScissorState.set(scissor); |
| 393 out->fHasStencilClip = kIgnoreClip_StencilClipMode != fClipMode; | 399 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
| 394 return true; | 400 return true; |
| 395 } | 401 } |
| 396 return false; | 402 return false; |
| 397 } | 403 } |
| 398 case GrClip::kClipStack_ClipType: { | 404 case GrClip::kClipStack_ClipType: { |
| 399 clipSpaceRTIBounds.offset(clip.origin()); | 405 clipSpaceRTIBounds.offset(clip.origin()); |
| 400 SkIRect clipSpaceReduceQueryBounds; | 406 SkIRect clipSpaceReduceQueryBounds; |
| 401 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0 | 407 #define DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION 0 |
| 402 if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) { | 408 if (devBounds && !DISABLE_DEV_BOUNDS_FOR_CLIP_REDUCTION) { |
| 403 SkIRect devIBounds = devBounds->roundOut(); | 409 SkIRect devIBounds = devBounds->roundOut(); |
| 404 devIBounds.offset(clip.origin()); | 410 devIBounds.offset(clip.origin()); |
| 405 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, de
vIBounds)) { | 411 if (!clipSpaceReduceQueryBounds.intersect(clipSpaceRTIBounds, de
vIBounds)) { |
| 406 return false; | 412 return false; |
| 407 } | 413 } |
| 408 } else { | 414 } else { |
| 409 clipSpaceReduceQueryBounds = clipSpaceRTIBounds; | 415 clipSpaceReduceQueryBounds = clipSpaceRTIBounds; |
| 410 } | 416 } |
| 411 GrReducedClip::ReduceClipStack(*clip.clipStack(), | 417 GrReducedClip::ReduceClipStack(*clip.clipStack(), |
| 412 clipSpaceReduceQueryBounds, | 418 clipSpaceReduceQueryBounds, |
| 413 &elements, | 419 &elements, |
| 414 &genID, | 420 &genID, |
| 415 &initialState, | 421 &initialState, |
| 416 &clipSpaceIBounds, | 422 &clipSpaceIBounds, |
| 417 &requiresAA); | 423 &requiresAA); |
| 418 if (elements.isEmpty()) { | 424 if (elements.isEmpty()) { |
| 419 if (GrReducedClip::kAllIn_InitialState == initialState) { | 425 if (GrReducedClip::kAllIn_InitialState == initialState) { |
| 420 if (clipSpaceIBounds == clipSpaceRTIBounds) { | 426 if (clipSpaceIBounds == clipSpaceRTIBounds) { |
| 427 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
| 421 return true; | 428 return true; |
| 422 } | 429 } |
| 423 } else { | 430 } else { |
| 424 return false; | 431 return false; |
| 425 } | 432 } |
| 426 } | 433 } |
| 427 } break; | 434 } break; |
| 428 } | 435 } |
| 429 | 436 |
| 430 SkASSERT(kIgnoreClip_StencilClipMode == fClipMode); // TODO: Remove fClipMod
e. | |
| 431 | |
| 432 // An element count of 4 was chosen because of the common pattern in Blink o
f: | 437 // An element count of 4 was chosen because of the common pattern in Blink o
f: |
| 433 // isect RR | 438 // isect RR |
| 434 // diff RR | 439 // diff RR |
| 435 // isect convex_poly | 440 // isect convex_poly |
| 436 // isect convex_poly | 441 // isect convex_poly |
| 437 // when drawing rounded div borders. This could probably be tuned based on a | 442 // when drawing rounded div borders. This could probably be tuned based on a |
| 438 // configuration's relative costs of switching RTs to generate a mask vs | 443 // configuration's relative costs of switching RTs to generate a mask vs |
| 439 // longer shaders. | 444 // longer shaders. |
| 440 if (elements.count() <= kMaxAnalyticElements) { | 445 if (elements.count() <= kMaxAnalyticElements) { |
| 441 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), | 446 SkVector clipToRTOffset = { SkIntToScalar(-clip.origin().fX), |
| 442 SkIntToScalar(-clip.origin().fY) }; | 447 SkIntToScalar(-clip.origin().fY) }; |
| 443 // When there are multiple samples we want to do per-sample clipping, no
t compute a | 448 // When there are multiple samples we want to do per-sample clipping, no
t compute a |
| 444 // fractional pixel coverage. | 449 // fractional pixel coverage. |
| 445 bool disallowAnalyticAA = rt->isStencilBufferMultisampled(); | 450 bool disallowAnalyticAA = rt->isStencilBufferMultisampled(); |
| 446 if (disallowAnalyticAA && !rt->numColorSamples()) { | 451 if (disallowAnalyticAA && !rt->numColorSamples()) { |
| 447 // With a single color sample, any coverage info is lost from color
once it hits the | 452 // With a single color sample, any coverage info is lost from color
once it hits the |
| 448 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe | 453 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe |
| 449 // is multisampled. | 454 // is multisampled. |
| 450 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || | 455 disallowAnalyticAA = pipelineBuilder.isHWAntialias() || |
| 451 pipelineBuilder.hasUserStencilSettings(); | 456 !pipelineBuilder.getStencil().isDisabled(); |
| 452 } | 457 } |
| 453 const GrFragmentProcessor* clipFP = nullptr; | 458 const GrFragmentProcessor* clipFP = nullptr; |
| 454 if (elements.isEmpty() || | 459 if (elements.isEmpty() || |
| 455 (requiresAA && | 460 (requiresAA && |
| 456 this->getAnalyticClipProcessor(elements, disallowAnalyticAA, clipTo
RTOffset, devBounds, | 461 this->getAnalyticClipProcessor(elements, disallowAnalyticAA, clipTo
RTOffset, devBounds, |
| 457 &clipFP))) { | 462 &clipFP))) { |
| 458 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 463 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
| 459 scissorSpaceIBounds.offset(-clip.origin()); | 464 scissorSpaceIBounds.offset(-clip.origin()); |
| 460 if (nullptr == devBounds || | 465 if (nullptr == devBounds || |
| 461 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { | 466 !SkRect::Make(scissorSpaceIBounds).contains(*devBounds)) { |
| 462 out->fScissorState.set(scissorSpaceIBounds); | 467 out->fScissorState.set(scissorSpaceIBounds); |
| 463 } | 468 } |
| 469 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
| 464 out->fClipCoverageFP.reset(clipFP); | 470 out->fClipCoverageFP.reset(clipFP); |
| 465 return true; | 471 return true; |
| 466 } | 472 } |
| 467 } | 473 } |
| 468 | 474 |
| 469 // If the stencil buffer is multisampled we can use it to do everything. | 475 // If the stencil buffer is multisampled we can use it to do everything. |
| 470 if (!rt->isStencilBufferMultisampled() && requiresAA) { | 476 if (!rt->isStencilBufferMultisampled() && requiresAA) { |
| 471 SkAutoTUnref<GrTexture> result; | 477 SkAutoTUnref<GrTexture> result; |
| 472 | 478 |
| 473 // The top-left of the mask corresponds to the top-left corner of the bo
unds. | 479 // The top-left of the mask corresponds to the top-left corner of the bo
unds. |
| (...skipping 21 matching lines...) Expand all Loading... |
| 495 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug | 501 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug |
| 496 SkASSERT(result); | 502 SkASSERT(result); |
| 497 } | 503 } |
| 498 | 504 |
| 499 if (result) { | 505 if (result) { |
| 500 // The mask's top left coord should be pinned to the rounded-out top
left corner of | 506 // The mask's top left coord should be pinned to the rounded-out top
left corner of |
| 501 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. | 507 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. |
| 502 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; | 508 SkIRect rtSpaceMaskBounds = clipSpaceIBounds; |
| 503 rtSpaceMaskBounds.offset(-clip.origin()); | 509 rtSpaceMaskBounds.offset(-clip.origin()); |
| 504 out->fClipCoverageFP.reset(create_fp_for_mask(result, rtSpaceMaskBou
nds)); | 510 out->fClipCoverageFP.reset(create_fp_for_mask(result, rtSpaceMaskBou
nds)); |
| 511 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
| 505 return true; | 512 return true; |
| 506 } | 513 } |
| 507 // if alpha clip mask creation fails fall through to the non-AA code pat
hs | 514 // if alpha clip mask creation fails fall through to the non-AA code pat
hs |
| 508 } | 515 } |
| 509 | 516 |
| 510 // use the stencil clip if we can't represent the clip as a rectangle. | 517 // use the stencil clip if we can't represent the clip as a rectangle. |
| 511 SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin(); | 518 SkIPoint clipSpaceToStencilSpaceOffset = -clip.origin(); |
| 512 this->createStencilClipMask(rt, | 519 this->createStencilClipMask(rt, |
| 513 genID, | 520 genID, |
| 514 initialState, | 521 initialState, |
| 515 elements, | 522 elements, |
| 516 clipSpaceIBounds, | 523 clipSpaceIBounds, |
| 517 clipSpaceToStencilSpaceOffset); | 524 clipSpaceToStencilSpaceOffset); |
| 518 | 525 |
| 519 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it | 526 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it |
| 520 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must | 527 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must |
| 521 // use both stencil and scissor test to the bounds for the final draw. | 528 // use both stencil and scissor test to the bounds for the final draw. |
| 522 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 529 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
| 523 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 530 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
| 524 out->fScissorState.set(scissorSpaceIBounds); | 531 out->fScissorState.set(scissorSpaceIBounds); |
| 525 SkASSERT(kRespectClip_StencilClipMode == fClipMode); // TODO: Remove fClipMo
de. | 532 this->setPipelineBuilderStencil(pipelineBuilder, ars); |
| 526 out->fHasStencilClip = true; | |
| 527 return true; | 533 return true; |
| 528 } | 534 } |
| 529 | 535 |
| 530 static bool stencil_element(GrDrawContext* dc, | 536 static bool stencil_element(GrDrawContext* dc, |
| 531 const SkIRect* scissorRect, | 537 const SkIRect* scissorRect, |
| 532 const GrUserStencilSettings* ss, | 538 const GrStencilSettings& ss, |
| 533 const SkMatrix& viewMatrix, | 539 const SkMatrix& viewMatrix, |
| 534 const SkClipStack::Element* element) { | 540 const SkClipStack::Element* element) { |
| 535 | 541 |
| 536 // TODO: Draw rrects directly here. | 542 // TODO: Draw rrects directly here. |
| 537 switch (element->getType()) { | 543 switch (element->getType()) { |
| 538 case Element::kEmpty_Type: | 544 case Element::kEmpty_Type: |
| 539 SkDEBUGFAIL("Should never get here with an empty element."); | 545 SkDEBUGFAIL("Should never get here with an empty element."); |
| 540 break; | 546 break; |
| 541 case Element::kRect_Type: | 547 case Element::kRect_Type: |
| 542 return dc->drawContextPriv().drawAndStencilRect(scissorRect, ss, | 548 return dc->drawContextPriv().drawAndStencilRect(scissorRect, ss, |
| (...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 668 if (Element::kRect_Type != element->getType() && !pr) { | 674 if (Element::kRect_Type != element->getType() && !pr) { |
| 669 // UseSWOnlyPath should now filter out all cases where gpu-side
mask merging would | 675 // UseSWOnlyPath should now filter out all cases where gpu-side
mask merging would |
| 670 // be performed (i.e., pr would be NULL for a non-rect path). | 676 // be performed (i.e., pr would be NULL for a non-rect path). |
| 671 // See https://bug.skia.org/4519 for rationale and details. | 677 // See https://bug.skia.org/4519 for rationale and details. |
| 672 SkASSERT(0); | 678 SkASSERT(0); |
| 673 } | 679 } |
| 674 #endif | 680 #endif |
| 675 | 681 |
| 676 // draw directly into the result with the stencil set to make the pi
xels affected | 682 // draw directly into the result with the stencil set to make the pi
xels affected |
| 677 // by the clip shape be non-zero. | 683 // by the clip shape be non-zero. |
| 678 static constexpr GrUserStencilSettings kStencilInElement( | 684 static constexpr GrStencilSettings kStencilInElement( |
| 679 GrUserStencilSettings::StaticInit< | 685 kReplace_StencilOp, |
| 680 0xffff, | 686 kReplace_StencilOp, |
| 681 GrUserStencilTest::kAlways, | 687 kAlways_StencilFunc, |
| 682 0xffff, | 688 0xffff, |
| 683 GrUserStencilOp::kReplace, | 689 0xffff, |
| 684 GrUserStencilOp::kReplace, | 690 0xffff); |
| 685 0xffff>() | 691 if (!stencil_element(dc.get(), &maskSpaceIBounds, kStencilInElement, |
| 686 ); | |
| 687 if (!stencil_element(dc.get(), &maskSpaceIBounds, &kStencilInElement
, | |
| 688 translate, element)) { | 692 translate, element)) { |
| 689 texture->resourcePriv().removeUniqueKey(); | 693 texture->resourcePriv().removeUniqueKey(); |
| 690 return nullptr; | 694 return nullptr; |
| 691 } | 695 } |
| 692 | 696 |
| 693 // Draw to the exterior pixels (those with a zero stencil value). | 697 // Draw to the exterior pixels (those with a zero stencil value). |
| 694 static constexpr GrUserStencilSettings kDrawOutsideElement( | 698 static constexpr GrStencilSettings kDrawOutsideElement( |
| 695 GrUserStencilSettings::StaticInit< | 699 kZero_StencilOp, |
| 696 0x0000, | 700 kZero_StencilOp, |
| 697 GrUserStencilTest::kEqual, | 701 kEqual_StencilFunc, |
| 698 0xffff, | 702 0xffff, |
| 699 GrUserStencilOp::kZero, | 703 0x0000, |
| 700 GrUserStencilOp::kZero, | 704 0xffff); |
| 701 0xffff>() | 705 if (!dc->drawContextPriv().drawAndStencilRect(&maskSpaceIBounds, kDr
awOutsideElement, |
| 702 ); | |
| 703 if (!dc->drawContextPriv().drawAndStencilRect(&maskSpaceIBounds, &kD
rawOutsideElement, | |
| 704 op, !invert, false, | 706 op, !invert, false, |
| 705 translate, | 707 translate, |
| 706 SkRect::Make(clipSpace
IBounds))) { | 708 SkRect::Make(clipSpace
IBounds))) { |
| 707 texture->resourcePriv().removeUniqueKey(); | 709 texture->resourcePriv().removeUniqueKey(); |
| 708 return nullptr; | 710 return nullptr; |
| 709 } | 711 } |
| 710 } else { | 712 } else { |
| 711 // all the remaining ops can just be directly draw into the accumula
tion buffer | 713 // all the remaining ops can just be directly draw into the accumula
tion buffer |
| 712 GrPaint paint; | 714 GrPaint paint; |
| 713 paint.setAntiAlias(element->isAA()); | 715 paint.setAntiAlias(element->isAA()); |
| (...skipping 30 matching lines...) Expand all Loading... |
| 744 SkIntToScalar(clipSpaceToStencilOffset.fY) | 746 SkIntToScalar(clipSpaceToStencilOffset.fY) |
| 745 }; | 747 }; |
| 746 SkMatrix viewMatrix; | 748 SkMatrix viewMatrix; |
| 747 viewMatrix.setTranslate(translate); | 749 viewMatrix.setTranslate(translate); |
| 748 | 750 |
| 749 // We set the current clip to the bounds so that our recursive draws are
scissored to them. | 751 // We set the current clip to the bounds so that our recursive draws are
scissored to them. |
| 750 SkIRect stencilSpaceIBounds(clipSpaceIBounds); | 752 SkIRect stencilSpaceIBounds(clipSpaceIBounds); |
| 751 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); | 753 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); |
| 752 GrClip clip(stencilSpaceIBounds); | 754 GrClip clip(stencilSpaceIBounds); |
| 753 | 755 |
| 756 int clipBit = stencilAttachment->bits(); |
| 757 SkASSERT((clipBit <= 16) && "Ganesh only handles 16b or smaller stencil
buffers"); |
| 758 clipBit = (1 << (clipBit-1)); |
| 759 |
| 754 fDrawTarget->cmmAccess().clearStencilClip(stencilSpaceIBounds, | 760 fDrawTarget->cmmAccess().clearStencilClip(stencilSpaceIBounds, |
| 755 GrReducedClip::kAllIn_InitialState == initialState, rt); | 761 GrReducedClip::kAllIn_InitialState == initialState, rt); |
| 756 | 762 |
| 757 // walk through each clip element and perform its set op | 763 // walk through each clip element and perform its set op |
| 758 // with the existing clip. | 764 // with the existing clip. |
| 759 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { | 765 for (GrReducedClip::ElementList::Iter iter(elements.headIter()); iter.ge
t(); iter.next()) { |
| 760 const Element* element = iter.get(); | 766 const Element* element = iter.get(); |
| 761 | 767 |
| 762 GrPipelineBuilder pipelineBuilder; | 768 GrPipelineBuilder pipelineBuilder; |
| 763 pipelineBuilder.setClip(clip); | 769 pipelineBuilder.setClip(clip); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 785 if (Element::kRect_Type == element->getType()) { | 791 if (Element::kRect_Type == element->getType()) { |
| 786 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; | 792 stencilSupport = GrPathRenderer::kNoRestriction_StencilSupport; |
| 787 fillInverted = false; | 793 fillInverted = false; |
| 788 } else { | 794 } else { |
| 789 element->asPath(&clipPath); | 795 element->asPath(&clipPath); |
| 790 fillInverted = clipPath.isInverseFillType(); | 796 fillInverted = clipPath.isInverseFillType(); |
| 791 if (fillInverted) { | 797 if (fillInverted) { |
| 792 clipPath.toggleInverseFillType(); | 798 clipPath.toggleInverseFillType(); |
| 793 } | 799 } |
| 794 | 800 |
| 795 SkASSERT(!pipelineBuilder.hasUserStencilSettings()); | 801 SkASSERT(pipelineBuilder.getStencil().isDisabled()); |
| 796 | 802 |
| 797 GrPathRenderer::CanDrawPathArgs canDrawArgs; | 803 GrPathRenderer::CanDrawPathArgs canDrawArgs; |
| 798 canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps
(); | 804 canDrawArgs.fShaderCaps = this->getContext()->caps()->shaderCaps
(); |
| 799 canDrawArgs.fViewMatrix = &viewMatrix; | 805 canDrawArgs.fViewMatrix = &viewMatrix; |
| 800 canDrawArgs.fPath = &clipPath; | 806 canDrawArgs.fPath = &clipPath; |
| 801 canDrawArgs.fStyle = &GrStyle::SimpleFill(); | 807 canDrawArgs.fStyle = &GrStyle::SimpleFill(); |
| 802 canDrawArgs.fAntiAlias = false; | 808 canDrawArgs.fAntiAlias = false; |
| 803 canDrawArgs.fHasUserStencilSettings = pipelineBuilder.hasUserSte
ncilSettings(); | 809 canDrawArgs.fIsStencilDisabled = pipelineBuilder.getStencil().is
Disabled(); |
| 804 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampl
ed(); | 810 canDrawArgs.fIsStencilBufferMSAA = rt->isStencilBufferMultisampl
ed(); |
| 805 | 811 |
| 806 pr = this->getContext()->drawingManager()->getPathRenderer(canDr
awArgs, false, | 812 pr = this->getContext()->drawingManager()->getPathRenderer(canDr
awArgs, false, |
| 807 GrPat
hRendererChain::kStencilOnly_DrawType, | 813 GrPat
hRendererChain::kStencilOnly_DrawType, |
| 808 &sten
cilSupport); | 814 &sten
cilSupport); |
| 809 if (nullptr == pr) { | 815 if (nullptr == pr) { |
| 810 return false; | 816 return false; |
| 811 } | 817 } |
| 812 } | 818 } |
| 813 | 819 |
| 820 int passes; |
| 821 GrStencilSettings stencilSettings[GrStencilSettings::kMaxStencilClip
Passes]; |
| 822 |
| 814 bool canRenderDirectToStencil = | 823 bool canRenderDirectToStencil = |
| 815 GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; | 824 GrPathRenderer::kNoRestriction_StencilSupport == stencilSupport; |
| 816 bool drawDirectToClip; // Given the renderer, the element, | 825 bool canDrawDirectToClip; // Given the renderer, the element, |
| 817 // fill rule, and set operation should | 826 // fill rule, and set operation can |
| 818 // we render the element directly to | 827 // we render the element directly to |
| 819 // stencil bit used for clipping. | 828 // stencil bit used for clipping. |
| 820 GrUserStencilSettings const* const* stencilPasses = | 829 canDrawDirectToClip = GrStencilSettings::GetClipPasses(op, |
| 821 GrStencilSettings::GetClipPasses(op, canRenderDirectToStencil, f
illInverted, | 830 canRenderDire
ctToStencil, |
| 822 &drawDirectToClip); | 831 clipBit, |
| 832 fillInverted, |
| 833 &passes, |
| 834 stencilSettin
gs); |
| 823 | 835 |
| 824 // draw the element to the client stencil bits if necessary | 836 // draw the element to the client stencil bits if necessary |
| 825 if (!drawDirectToClip) { | 837 if (!canDrawDirectToClip) { |
| 826 static constexpr GrUserStencilSettings kDrawToStencil( | 838 static constexpr GrStencilSettings kDrawToStencil( |
| 827 GrUserStencilSettings::StaticInit< | 839 kIncClamp_StencilOp, |
| 828 0x0000, | 840 kIncClamp_StencilOp, |
| 829 GrUserStencilTest::kAlways, | 841 kAlways_StencilFunc, |
| 830 0xffff, | 842 0xffff, |
| 831 GrUserStencilOp::kIncMaybeClamp, | 843 0x0000, |
| 832 GrUserStencilOp::kIncMaybeClamp, | 844 0xffff); |
| 833 0xffff>() | |
| 834 ); | |
| 835 if (Element::kRect_Type == element->getType()) { | 845 if (Element::kRect_Type == element->getType()) { |
| 836 pipelineBuilder.setUserStencil(&kDrawToStencil); | 846 *pipelineBuilder.stencil() = kDrawToStencil; |
| 837 | 847 |
| 838 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, | 848 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, |
| 839 element->getRect()); | 849 element->getRect()); |
| 840 } else { | 850 } else { |
| 841 if (!clipPath.isEmpty()) { | 851 if (!clipPath.isEmpty()) { |
| 842 if (canRenderDirectToStencil) { | 852 if (canRenderDirectToStencil) { |
| 843 pipelineBuilder.setUserStencil(&kDrawToStencil); | 853 *pipelineBuilder.stencil() = kDrawToStencil; |
| 844 | 854 |
| 845 GrPathRenderer::DrawPathArgs args; | 855 GrPathRenderer::DrawPathArgs args; |
| 846 args.fTarget = fDrawTarget; | 856 args.fTarget = fDrawTarget; |
| 847 args.fResourceProvider = this->getContext()->resourc
eProvider(); | 857 args.fResourceProvider = this->getContext()->resourc
eProvider(); |
| 848 args.fPipelineBuilder = &pipelineBuilder; | 858 args.fPipelineBuilder = &pipelineBuilder; |
| 849 args.fColor = GrColor_WHITE; | 859 args.fColor = GrColor_WHITE; |
| 850 args.fViewMatrix = &viewMatrix; | 860 args.fViewMatrix = &viewMatrix; |
| 851 args.fPath = &clipPath; | 861 args.fPath = &clipPath; |
| 852 args.fStyle = &GrStyle::SimpleFill(); | 862 args.fStyle = &GrStyle::SimpleFill(); |
| 853 args.fAntiAlias = false; | 863 args.fAntiAlias = false; |
| 854 args.fGammaCorrect = false; | 864 args.fGammaCorrect = false; |
| 855 pr->drawPath(args); | 865 pr->drawPath(args); |
| 856 } else { | 866 } else { |
| 857 GrPathRenderer::StencilPathArgs args; | 867 GrPathRenderer::StencilPathArgs args; |
| 858 args.fTarget = fDrawTarget; | 868 args.fTarget = fDrawTarget; |
| 859 args.fResourceProvider = this->getContext()->resourc
eProvider(); | 869 args.fResourceProvider = this->getContext()->resourc
eProvider(); |
| 860 args.fPipelineBuilder = &pipelineBuilder; | 870 args.fPipelineBuilder = &pipelineBuilder; |
| 861 args.fViewMatrix = &viewMatrix; | 871 args.fViewMatrix = &viewMatrix; |
| 862 args.fPath = &clipPath; | 872 args.fPath = &clipPath; |
| 863 pr->stencilPath(args); | 873 pr->stencilPath(args); |
| 864 } | 874 } |
| 865 } | 875 } |
| 866 } | 876 } |
| 867 } | 877 } |
| 868 | 878 |
| 869 // now we modify the clip bit by rendering either the clip | 879 // now we modify the clip bit by rendering either the clip |
| 870 // element directly or a bounding rect of the entire clip. | 880 // element directly or a bounding rect of the entire clip. |
| 871 fClipMode = kModifyClip_StencilClipMode; | 881 fClipMode = kModifyClip_StencilClipMode; |
| 872 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass
; ++pass) { | 882 for (int p = 0; p < passes; ++p) { |
| 873 pipelineBuilder.setUserStencil(*pass); | 883 *pipelineBuilder.stencil() = stencilSettings[p]; |
| 874 | 884 |
| 875 if (drawDirectToClip) { | 885 if (canDrawDirectToClip) { |
| 876 if (Element::kRect_Type == element->getType()) { | 886 if (Element::kRect_Type == element->getType()) { |
| 877 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_W
HITE, viewMatrix, | 887 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_W
HITE, viewMatrix, |
| 878 element->getRect()); | 888 element->getRect()); |
| 879 } else { | 889 } else { |
| 880 GrPathRenderer::DrawPathArgs args; | 890 GrPathRenderer::DrawPathArgs args; |
| 881 args.fTarget = fDrawTarget; | 891 args.fTarget = fDrawTarget; |
| 882 args.fResourceProvider = this->getContext()->resourcePro
vider(); | 892 args.fResourceProvider = this->getContext()->resourcePro
vider(); |
| 883 args.fPipelineBuilder = &pipelineBuilder; | 893 args.fPipelineBuilder = &pipelineBuilder; |
| 884 args.fColor = GrColor_WHITE; | 894 args.fColor = GrColor_WHITE; |
| 885 args.fViewMatrix = &viewMatrix; | 895 args.fViewMatrix = &viewMatrix; |
| 886 args.fPath = &clipPath; | 896 args.fPath = &clipPath; |
| 887 args.fStyle = &GrStyle::SimpleFill(); | 897 args.fStyle = &GrStyle::SimpleFill(); |
| 888 args.fAntiAlias = false; | 898 args.fAntiAlias = false; |
| 889 args.fGammaCorrect = false; | 899 args.fGammaCorrect = false; |
| 890 pr->drawPath(args); | 900 pr->drawPath(args); |
| 891 } | 901 } |
| 892 } else { | 902 } else { |
| 893 // The view matrix is setup to do clip space -> stencil spac
e translation, so | 903 // The view matrix is setup to do clip space -> stencil spac
e translation, so |
| 894 // draw rect in clip space. | 904 // draw rect in clip space. |
| 895 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, | 905 draw_non_aa_rect(fDrawTarget, pipelineBuilder, GrColor_WHITE
, viewMatrix, |
| 896 SkRect::Make(clipSpaceIBounds)); | 906 SkRect::Make(clipSpaceIBounds)); |
| 897 } | 907 } |
| 898 } | 908 } |
| 899 } | 909 } |
| 900 } | 910 } |
| 901 fClipMode = kRespectClip_StencilClipMode; | 911 fClipMode = kRespectClip_StencilClipMode; |
| 902 return true; | 912 return true; |
| 903 } | 913 } |
| 904 | 914 |
| 915 // mapping of clip-respecting stencil funcs to normal stencil funcs |
| 916 // mapping depends on whether stencil-clipping is in effect. |
| 917 static const GrStencilFunc |
| 918 gSpecialToBasicStencilFunc[2][kClipStencilFuncCnt] = { |
| 919 {// Stencil-Clipping is DISABLED, we are effectively always inside the clip |
| 920 // In the Clip Funcs |
| 921 kAlways_StencilFunc, // kAlwaysIfInClip_StencilFunc |
| 922 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc |
| 923 kLess_StencilFunc, // kLessIfInClip_StencilFunc |
| 924 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc |
| 925 // Special in the clip func that forces user's ref to be 0. |
| 926 kNotEqual_StencilFunc, // kNonZeroIfInClip_StencilFunc |
| 927 // make ref 0 and do normal nequal. |
| 928 }, |
| 929 {// Stencil-Clipping is ENABLED |
| 930 // In the Clip Funcs |
| 931 kEqual_StencilFunc, // kAlwaysIfInClip_StencilFunc |
| 932 // eq stencil clip bit, mask |
| 933 // out user bits. |
| 934 |
| 935 kEqual_StencilFunc, // kEqualIfInClip_StencilFunc |
| 936 // add stencil bit to mask and ref |
| 937 |
| 938 kLess_StencilFunc, // kLessIfInClip_StencilFunc |
| 939 kLEqual_StencilFunc, // kLEqualIfInClip_StencilFunc |
| 940 // for both of these we can add |
| 941 // the clip bit to the mask and |
| 942 // ref and compare as normal |
| 943 // Special in the clip func that forces user's ref to be 0. |
| 944 kLess_StencilFunc, // kNonZeroIfInClip_StencilFunc |
| 945 // make ref have only the clip bit set |
| 946 // and make comparison be less |
| 947 // 10..0 < 1..user_bits.. |
| 948 } |
| 949 }; |
| 950 |
| 951 void GrClipMaskManager::setPipelineBuilderStencil(const GrPipelineBuilder& pipel
ineBuilder, |
| 952 GrPipelineBuilder::AutoRestore
Stencil* ars) { |
| 953 // We make two copies of the StencilSettings here (except in the early |
| 954 // exit scenario. One copy from draw state to the stack var. Then another |
| 955 // from the stack var to the gpu. We could make this class hold a ptr to |
| 956 // GrGpu's fStencilSettings and eliminate the stack copy here. |
| 957 |
| 958 // use stencil for clipping if clipping is enabled and the clip |
| 959 // has been written into the stencil. |
| 960 GrStencilSettings settings; |
| 961 |
| 962 // The GrGpu client may not be using the stencil buffer but we may need to |
| 963 // enable it in order to respect a stencil clip. |
| 964 if (pipelineBuilder.getStencil().isDisabled()) { |
| 965 if (GrClipMaskManager::kRespectClip_StencilClipMode == fClipMode) { |
| 966 static constexpr GrStencilSettings kBasicApplyClipSettings( |
| 967 kKeep_StencilOp, |
| 968 kKeep_StencilOp, |
| 969 kAlwaysIfInClip_StencilFunc, |
| 970 0x0000, |
| 971 0x0000, |
| 972 0x0000); |
| 973 settings = kBasicApplyClipSettings; |
| 974 } else { |
| 975 return; |
| 976 } |
| 977 } else { |
| 978 settings = pipelineBuilder.getStencil(); |
| 979 } |
| 980 |
| 981 int stencilBits = 0; |
| 982 GrRenderTarget* rt = pipelineBuilder.getRenderTarget(); |
| 983 GrStencilAttachment* stencilAttachment = this->resourceProvider()->attachSte
ncilAttachment(rt); |
| 984 if (stencilAttachment) { |
| 985 stencilBits = stencilAttachment->bits(); |
| 986 } |
| 987 |
| 988 SkASSERT(this->caps()->stencilWrapOpsSupport() || !settings.usesWrapOp()); |
| 989 SkASSERT(this->caps()->twoSidedStencilSupport() || !settings.isTwoSided()); |
| 990 this->adjustStencilParams(&settings, fClipMode, stencilBits); |
| 991 ars->set(&pipelineBuilder); |
| 992 ars->setStencil(settings); |
| 993 } |
| 994 |
| 995 void GrClipMaskManager::adjustStencilParams(GrStencilSettings* settings, |
| 996 StencilClipMode mode, |
| 997 int stencilBitCnt) { |
| 998 SkASSERT(stencilBitCnt > 0); |
| 999 |
| 1000 if (kModifyClip_StencilClipMode == mode) { |
| 1001 // We assume that this clip manager itself is drawing to the GrGpu and |
| 1002 // has already setup the correct values. |
| 1003 return; |
| 1004 } |
| 1005 |
| 1006 unsigned int clipBit = (1 << (stencilBitCnt - 1)); |
| 1007 unsigned int userBits = clipBit - 1; |
| 1008 |
| 1009 GrStencilSettings::Face face = GrStencilSettings::kFront_Face; |
| 1010 bool twoSided = this->caps()->twoSidedStencilSupport(); |
| 1011 |
| 1012 bool finished = false; |
| 1013 while (!finished) { |
| 1014 GrStencilFunc func = settings->func(face); |
| 1015 uint16_t writeMask = settings->writeMask(face); |
| 1016 uint16_t funcMask = settings->funcMask(face); |
| 1017 uint16_t funcRef = settings->funcRef(face); |
| 1018 |
| 1019 SkASSERT((unsigned) func < kStencilFuncCnt); |
| 1020 |
| 1021 writeMask &= userBits; |
| 1022 |
| 1023 if (func >= kBasicStencilFuncCnt) { |
| 1024 int respectClip = kRespectClip_StencilClipMode == mode; |
| 1025 if (respectClip) { |
| 1026 switch (func) { |
| 1027 case kAlwaysIfInClip_StencilFunc: |
| 1028 funcMask = clipBit; |
| 1029 funcRef = clipBit; |
| 1030 break; |
| 1031 case kEqualIfInClip_StencilFunc: |
| 1032 case kLessIfInClip_StencilFunc: |
| 1033 case kLEqualIfInClip_StencilFunc: |
| 1034 funcMask = (funcMask & userBits) | clipBit; |
| 1035 funcRef = (funcRef & userBits) | clipBit; |
| 1036 break; |
| 1037 case kNonZeroIfInClip_StencilFunc: |
| 1038 funcMask = (funcMask & userBits) | clipBit; |
| 1039 funcRef = clipBit; |
| 1040 break; |
| 1041 default: |
| 1042 SkFAIL("Unknown stencil func"); |
| 1043 } |
| 1044 } else { |
| 1045 funcMask &= userBits; |
| 1046 funcRef &= userBits; |
| 1047 } |
| 1048 const GrStencilFunc* table = |
| 1049 gSpecialToBasicStencilFunc[respectClip]; |
| 1050 func = table[func - kBasicStencilFuncCnt]; |
| 1051 SkASSERT(func >= 0 && func < kBasicStencilFuncCnt); |
| 1052 } else { |
| 1053 funcMask &= userBits; |
| 1054 funcRef &= userBits; |
| 1055 } |
| 1056 |
| 1057 settings->setFunc(face, func); |
| 1058 settings->setWriteMask(face, writeMask); |
| 1059 settings->setFuncMask(face, funcMask); |
| 1060 settings->setFuncRef(face, funcRef); |
| 1061 |
| 1062 if (GrStencilSettings::kFront_Face == face) { |
| 1063 face = GrStencilSettings::kBack_Face; |
| 1064 finished = !twoSided; |
| 1065 } else { |
| 1066 finished = true; |
| 1067 } |
| 1068 } |
| 1069 if (!twoSided) { |
| 1070 settings->copyFrontSettingsToBack(); |
| 1071 } |
| 1072 } |
| 1073 |
| 905 //////////////////////////////////////////////////////////////////////////////// | 1074 //////////////////////////////////////////////////////////////////////////////// |
| 906 GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, | 1075 GrTexture* GrClipMaskManager::CreateSoftwareClipMask(GrContext* context, |
| 907 int32_t elementsGenID, | 1076 int32_t elementsGenID, |
| 908 GrReducedClip::InitialState
initialState, | 1077 GrReducedClip::InitialState
initialState, |
| 909 const GrReducedClip::Elemen
tList& elements, | 1078 const GrReducedClip::Elemen
tList& elements, |
| 910 const SkVector& clipToMaskO
ffset, | 1079 const SkVector& clipToMaskO
ffset, |
| 911 const SkIRect& clipSpaceIBo
unds) { | 1080 const SkIRect& clipSpaceIBo
unds) { |
| 912 GrUniqueKey key; | 1081 GrUniqueKey key; |
| 913 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); | 1082 GetClipMaskKey(elementsGenID, clipSpaceIBounds, &key); |
| 914 GrResourceProvider* resourceProvider = context->resourceProvider(); | 1083 GrResourceProvider* resourceProvider = context->resourceProvider(); |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 972 GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0
); | 1141 GrTexture* result = context->resourceProvider()->createApproxTexture(desc, 0
); |
| 973 if (!result) { | 1142 if (!result) { |
| 974 return nullptr; | 1143 return nullptr; |
| 975 } | 1144 } |
| 976 result->resourcePriv().setUniqueKey(key); | 1145 result->resourcePriv().setUniqueKey(key); |
| 977 | 1146 |
| 978 helper.toTexture(result); | 1147 helper.toTexture(result); |
| 979 | 1148 |
| 980 return result; | 1149 return result; |
| 981 } | 1150 } |
| 1151 |
| 1152 //////////////////////////////////////////////////////////////////////////////// |
| 1153 |
| 1154 void GrClipMaskManager::adjustPathStencilParams(const GrStencilAttachment* stenc
ilAttachment, |
| 1155 GrStencilSettings* settings) { |
| 1156 if (stencilAttachment) { |
| 1157 int stencilBits = stencilAttachment->bits(); |
| 1158 this->adjustStencilParams(settings, fClipMode, stencilBits); |
| 1159 } |
| 1160 } |
| OLD | NEW |