| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2016 Google Inc. | 2 * Copyright 2016 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 "GrClipStackClip.h" | 8 #include "GrClipStackClip.h" |
| 9 | 9 |
| 10 #include "GrDrawingManager.h" | 10 #include "GrDrawingManager.h" |
| (...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 *resultFP = nullptr; | 235 *resultFP = nullptr; |
| 236 if (fps.count()) { | 236 if (fps.count()) { |
| 237 *resultFP = GrFragmentProcessor::RunInSeries(fps.begin(), fps.count()); | 237 *resultFP = GrFragmentProcessor::RunInSeries(fps.begin(), fps.count()); |
| 238 } | 238 } |
| 239 return true; | 239 return true; |
| 240 } | 240 } |
| 241 | 241 |
| 242 //////////////////////////////////////////////////////////////////////////////// | 242 //////////////////////////////////////////////////////////////////////////////// |
| 243 // sort out what kind of clip mask needs to be created: alpha, stencil, | 243 // sort out what kind of clip mask needs to be created: alpha, stencil, |
| 244 // scissor, or entirely software | 244 // scissor, or entirely software |
| 245 bool GrClipStackClip::apply(GrContext* context, | 245 bool GrClipStackClip::apply(GrContext* context, GrDrawContext* drawContext, bool
useHWAA, |
| 246 GrDrawContext* drawContext, | 246 bool hasUserStencilSettings, GrAppliedClip* out) con
st { |
| 247 const SkRect* origDevBounds, | |
| 248 bool useHWAA, | |
| 249 bool hasUserStencilSettings, | |
| 250 GrAppliedClip* out) const { | |
| 251 if (!fStack || fStack->isWideOpen()) { | 247 if (!fStack || fStack->isWideOpen()) { |
| 252 return true; | 248 return true; |
| 253 } | 249 } |
| 254 | 250 |
| 255 SkRect devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height
()); | 251 SkRect devBounds = SkRect::MakeIWH(drawContext->width(), drawContext->height
()); |
| 256 if (origDevBounds && !devBounds.intersect(*origDevBounds)) { | 252 if (!devBounds.intersect(out->clippedDrawBounds())) { |
| 257 return false; | 253 return false; |
| 258 } | 254 } |
| 259 | 255 |
| 260 const SkScalar clipX = SkIntToScalar(fOrigin.x()), | 256 const SkScalar clipX = SkIntToScalar(fOrigin.x()), |
| 261 clipY = SkIntToScalar(fOrigin.y()); | 257 clipY = SkIntToScalar(fOrigin.y()); |
| 262 | 258 |
| 263 SkRect clipSpaceDevBounds = devBounds.makeOffset(clipX, clipY); | 259 SkRect clipSpaceDevBounds = devBounds.makeOffset(clipX, clipY); |
| 264 const GrReducedClip reducedClip(*fStack, clipSpaceDevBounds); | 260 const GrReducedClip reducedClip(*fStack, clipSpaceDevBounds); |
| 265 | 261 |
| 262 if (reducedClip.hasIBounds() && |
| 263 !GrClip::IsInsideClip(reducedClip.ibounds(), clipSpaceDevBounds)) { |
| 264 SkIRect scissorSpaceIBounds(reducedClip.ibounds()); |
| 265 scissorSpaceIBounds.offset(-fOrigin); |
| 266 out->addScissor(scissorSpaceIBounds); |
| 267 } |
| 268 |
| 266 if (reducedClip.elements().isEmpty()) { | 269 if (reducedClip.elements().isEmpty()) { |
| 267 if (GrReducedClip::InitialState::kAllOut == reducedClip.initialState())
{ | 270 return InitialState::kAllIn == reducedClip.initialState(); |
| 268 return false; | |
| 269 } | |
| 270 if (!GrClip::IsInsideClip(reducedClip.iBounds(), clipSpaceDevBounds)) { | |
| 271 SkIRect scissorSpaceIBounds(reducedClip.iBounds()); | |
| 272 scissorSpaceIBounds.offset(-fOrigin); | |
| 273 out->makeScissored(scissorSpaceIBounds); | |
| 274 } | |
| 275 return true; | |
| 276 } | 271 } |
| 277 | 272 |
| 273 SkASSERT(reducedClip.hasIBounds()); |
| 274 |
| 278 // An element count of 4 was chosen because of the common pattern in Blink o
f: | 275 // An element count of 4 was chosen because of the common pattern in Blink o
f: |
| 279 // isect RR | 276 // isect RR |
| 280 // diff RR | 277 // diff RR |
| 281 // isect convex_poly | 278 // isect convex_poly |
| 282 // isect convex_poly | 279 // isect convex_poly |
| 283 // when drawing rounded div borders. This could probably be tuned based on a | 280 // when drawing rounded div borders. This could probably be tuned based on a |
| 284 // configuration's relative costs of switching RTs to generate a mask vs | 281 // configuration's relative costs of switching RTs to generate a mask vs |
| 285 // longer shaders. | 282 // longer shaders. |
| 286 if (reducedClip.elements().count() <= kMaxAnalyticElements) { | 283 if (reducedClip.elements().count() <= kMaxAnalyticElements) { |
| 287 // When there are multiple samples we want to do per-sample clipping, no
t compute a | 284 // When there are multiple samples we want to do per-sample clipping, no
t compute a |
| 288 // fractional pixel coverage. | 285 // fractional pixel coverage. |
| 289 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled(); | 286 bool disallowAnalyticAA = drawContext->isStencilBufferMultisampled(); |
| 290 if (disallowAnalyticAA && !drawContext->numColorSamples()) { | 287 if (disallowAnalyticAA && !drawContext->numColorSamples()) { |
| 291 // With a single color sample, any coverage info is lost from color
once it hits the | 288 // With a single color sample, any coverage info is lost from color
once it hits the |
| 292 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe | 289 // color buffer anyway, so we may as well use coverage AA if nothing
else in the pipe |
| 293 // is multisampled. | 290 // is multisampled. |
| 294 disallowAnalyticAA = useHWAA || hasUserStencilSettings; | 291 disallowAnalyticAA = useHWAA || hasUserStencilSettings; |
| 295 } | 292 } |
| 296 sk_sp<GrFragmentProcessor> clipFP; | 293 sk_sp<GrFragmentProcessor> clipFP; |
| 297 if (reducedClip.requiresAA() && | 294 if (reducedClip.requiresAA() && |
| 298 get_analytic_clip_processor(reducedClip.elements(), disallowAnalytic
AA, | 295 get_analytic_clip_processor(reducedClip.elements(), disallowAnalytic
AA, |
| 299 {-clipX, -clipY}, devBounds, &clipFP)) { | 296 {-clipX, -clipY}, devBounds, &clipFP)) { |
| 300 SkIRect scissorSpaceIBounds(reducedClip.iBounds()); | 297 out->addCoverageFP(std::move(clipFP)); |
| 301 scissorSpaceIBounds.offset(-fOrigin); | |
| 302 if (GrClip::IsInsideClip(scissorSpaceIBounds, devBounds)) { | |
| 303 out->makeFPBased(std::move(clipFP), SkRect::Make(scissorSpaceIBo
unds)); | |
| 304 } else { | |
| 305 out->makeScissoredFPBased(std::move(clipFP), scissorSpaceIBounds
); | |
| 306 } | |
| 307 return true; | 298 return true; |
| 308 } | 299 } |
| 309 } | 300 } |
| 310 | 301 |
| 311 // If the stencil buffer is multisampled we can use it to do everything. | 302 // If the stencil buffer is multisampled we can use it to do everything. |
| 312 if (!drawContext->isStencilBufferMultisampled() && reducedClip.requiresAA())
{ | 303 if (!drawContext->isStencilBufferMultisampled() && reducedClip.requiresAA())
{ |
| 313 sk_sp<GrTexture> result; | 304 sk_sp<GrTexture> result; |
| 314 | 305 |
| 315 // The top-left of the mask corresponds to the top-left corner of the bo
unds. | 306 // The top-left of the mask corresponds to the top-left corner of the bo
unds. |
| 316 SkVector clipToMaskOffset = { | 307 SkVector clipToMaskOffset = { |
| 317 SkIntToScalar(-reducedClip.left()), | 308 SkIntToScalar(-reducedClip.left()), |
| 318 SkIntToScalar(-reducedClip.top()) | 309 SkIntToScalar(-reducedClip.top()) |
| 319 }; | 310 }; |
| 320 | 311 |
| 321 if (UseSWOnlyPath(context, hasUserStencilSettings, drawContext, | 312 if (UseSWOnlyPath(context, hasUserStencilSettings, drawContext, |
| 322 clipToMaskOffset, reducedClip.elements())) { | 313 clipToMaskOffset, reducedClip.elements())) { |
| 323 // The clip geometry is complex enough that it will be more efficien
t to create it | 314 // The clip geometry is complex enough that it will be more efficien
t to create it |
| 324 // entirely in software | 315 // entirely in software |
| 325 result = CreateSoftwareClipMask(context->textureProvider(), reducedC
lip, | 316 result = CreateSoftwareClipMask(context->textureProvider(), reducedC
lip, |
| 326 clipToMaskOffset); | 317 clipToMaskOffset); |
| 327 } else { | 318 } else { |
| 328 result = CreateAlphaClipMask(context, reducedClip, clipToMaskOffset)
; | 319 result = CreateAlphaClipMask(context, reducedClip, clipToMaskOffset)
; |
| 329 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug | 320 // If createAlphaClipMask fails it means UseSWOnlyPath has a bug |
| 330 SkASSERT(result); | 321 SkASSERT(result); |
| 331 } | 322 } |
| 332 | 323 |
| 333 if (result) { | 324 if (result) { |
| 334 // The mask's top left coord should be pinned to the rounded-out top
left corner of | 325 // The mask's top left coord should be pinned to the rounded-out top
left corner of |
| 335 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. | 326 // clipSpace bounds. We determine the mask's position WRT to the ren
der target here. |
| 336 SkIRect rtSpaceMaskBounds = reducedClip.iBounds(); | 327 SkIRect rtSpaceMaskBounds = reducedClip.ibounds(); |
| 337 rtSpaceMaskBounds.offset(-fOrigin); | 328 rtSpaceMaskBounds.offset(-fOrigin); |
| 338 out->makeFPBased(create_fp_for_mask(result.get(), rtSpaceMaskBounds)
, | 329 out->addCoverageFP(create_fp_for_mask(result.get(), rtSpaceMaskBound
s)); |
| 339 SkRect::Make(rtSpaceMaskBounds)); | |
| 340 return true; | 330 return true; |
| 341 } | 331 } |
| 342 // if alpha clip mask creation fails fall through to the non-AA code pat
hs | 332 // if alpha clip mask creation fails fall through to the non-AA code pat
hs |
| 343 } | 333 } |
| 344 | 334 |
| 345 // use the stencil clip if we can't represent the clip as a rectangle. | 335 // use the stencil clip if we can't represent the clip as a rectangle. |
| 346 SkIPoint clipSpaceToStencilSpaceOffset = -fOrigin; | 336 SkIPoint clipSpaceToStencilSpaceOffset = -fOrigin; |
| 347 CreateStencilClipMask(context, drawContext, reducedClip, clipSpaceToStencilS
paceOffset); | 337 CreateStencilClipMask(context, drawContext, reducedClip, clipSpaceToStencilS
paceOffset); |
| 348 | 338 out->addStencilClip(); |
| 349 // This must occur after createStencilClipMask. That function may change the
scissor. Also, it | |
| 350 // only guarantees that the stencil mask is correct within the bounds it was
passed, so we must | |
| 351 // use both stencil and scissor test to the bounds for the final draw. | |
| 352 if (GrClip::IsInsideClip(reducedClip.iBounds(), clipSpaceDevBounds)) { | |
| 353 out->makeStencil(true, devBounds); | |
| 354 } else { | |
| 355 SkIRect scissorSpaceIBounds(reducedClip.iBounds()); | |
| 356 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | |
| 357 out->makeScissoredStencil(scissorSpaceIBounds); | |
| 358 } | |
| 359 return true; | 339 return true; |
| 360 } | 340 } |
| 361 | 341 |
| 362 static bool stencil_element(GrDrawContext* dc, | 342 static bool stencil_element(GrDrawContext* dc, |
| 363 const GrFixedClip& clip, | 343 const GrFixedClip& clip, |
| 364 const GrUserStencilSettings* ss, | 344 const GrUserStencilSettings* ss, |
| 365 const SkMatrix& viewMatrix, | 345 const SkMatrix& viewMatrix, |
| 366 const SkClipStack::Element* element) { | 346 const SkClipStack::Element* element) { |
| 367 | 347 |
| 368 // TODO: Draw rrects directly here. | 348 // TODO: Draw rrects directly here. |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 431 builder[0] = clipGenID; | 411 builder[0] = clipGenID; |
| 432 builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16); | 412 builder[1] = SkToU16(bounds.fLeft) | (SkToU16(bounds.fRight) << 16); |
| 433 builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16); | 413 builder[2] = SkToU16(bounds.fTop) | (SkToU16(bounds.fBottom) << 16); |
| 434 } | 414 } |
| 435 | 415 |
| 436 sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context, | 416 sk_sp<GrTexture> GrClipStackClip::CreateAlphaClipMask(GrContext* context, |
| 437 const GrReducedClip& reduc
edClip, | 417 const GrReducedClip& reduc
edClip, |
| 438 const SkVector& clipToMask
Offset) { | 418 const SkVector& clipToMask
Offset) { |
| 439 GrResourceProvider* resourceProvider = context->resourceProvider(); | 419 GrResourceProvider* resourceProvider = context->resourceProvider(); |
| 440 GrUniqueKey key; | 420 GrUniqueKey key; |
| 441 GetClipMaskKey(reducedClip.genID(), reducedClip.iBounds(), &key); | 421 GetClipMaskKey(reducedClip.genID(), reducedClip.ibounds(), &key); |
| 442 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)
) { | 422 if (GrTexture* texture = resourceProvider->findAndRefTextureByUniqueKey(key)
) { |
| 443 return sk_sp<GrTexture>(texture); | 423 return sk_sp<GrTexture>(texture); |
| 444 } | 424 } |
| 445 | 425 |
| 446 // There's no texture in the cache. Let's try to allocate it then. | 426 // There's no texture in the cache. Let's try to allocate it then. |
| 447 GrPixelConfig config = kRGBA_8888_GrPixelConfig; | 427 GrPixelConfig config = kRGBA_8888_GrPixelConfig; |
| 448 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { | 428 if (context->caps()->isConfigRenderable(kAlpha_8_GrPixelConfig, false)) { |
| 449 config = kAlpha_8_GrPixelConfig; | 429 config = kAlpha_8_GrPixelConfig; |
| 450 } | 430 } |
| 451 | 431 |
| 452 sk_sp<GrDrawContext> dc(context->makeDrawContext(SkBackingFit::kApprox, | 432 sk_sp<GrDrawContext> dc(context->makeDrawContext(SkBackingFit::kApprox, |
| 453 reducedClip.width(), | 433 reducedClip.width(), |
| 454 reducedClip.height(), | 434 reducedClip.height(), |
| 455 config, nullptr)); | 435 config, nullptr)); |
| 456 if (!dc) { | 436 if (!dc) { |
| 457 return nullptr; | 437 return nullptr; |
| 458 } | 438 } |
| 459 | 439 |
| 460 // The texture may be larger than necessary, this rect represents the part o
f the texture | 440 // The texture may be larger than necessary, this rect represents the part o
f the texture |
| 461 // we populate with a rasterization of the clip. | 441 // we populate with a rasterization of the clip. |
| 462 SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip.
height()); | 442 SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip.
height()); |
| 463 | 443 |
| 464 // The scratch texture that we are drawing into can be substantially larger
than the mask. Only | 444 // The scratch texture that we are drawing into can be substantially larger
than the mask. Only |
| 465 // clear the part that we care about. | 445 // clear the part that we care about. |
| 466 dc->clear(&maskSpaceIBounds, | 446 dc->clear(&maskSpaceIBounds, InitialState::kAllIn == reducedClip.initialStat
e() ? -1 : 0, true); |
| 467 GrReducedClip::InitialState::kAllIn == reducedClip.initialState()
? -1 : 0, | |
| 468 true); | |
| 469 | 447 |
| 470 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip | 448 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip |
| 471 // space. | 449 // space. |
| 472 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); | 450 const SkMatrix translate = SkMatrix::MakeTrans(clipToMaskOffset.fX, clipToMa
skOffset.fY); |
| 473 | 451 |
| 474 // It is important that we use maskSpaceIBounds as the stencil rect in the b
elow loop. | 452 // It is important that we use maskSpaceIBounds as the stencil rect in the b
elow loop. |
| 475 // The second pass that zeros the stencil buffer renders the rect maskSpaceI
Bounds so the first | 453 // The second pass that zeros the stencil buffer renders the rect maskSpaceI
Bounds so the first |
| 476 // pass must not set values outside of this bounds or stencil values outside
the rect won't be | 454 // pass must not set values outside of this bounds or stencil values outside
the rect won't be |
| 477 // cleared. | 455 // cleared. |
| 478 | 456 |
| (...skipping 27 matching lines...) Expand all Loading... |
| 506 0x0000, | 484 0x0000, |
| 507 GrUserStencilTest::kEqual, | 485 GrUserStencilTest::kEqual, |
| 508 0xffff, | 486 0xffff, |
| 509 GrUserStencilOp::kZero, | 487 GrUserStencilOp::kZero, |
| 510 GrUserStencilOp::kZero, | 488 GrUserStencilOp::kZero, |
| 511 0xffff>() | 489 0xffff>() |
| 512 ); | 490 ); |
| 513 if (!dc->drawContextPriv().drawAndStencilRect(clip, &kDrawOutsideEle
ment, | 491 if (!dc->drawContextPriv().drawAndStencilRect(clip, &kDrawOutsideEle
ment, |
| 514 op, !invert, false, | 492 op, !invert, false, |
| 515 translate, | 493 translate, |
| 516 SkRect::Make(reducedCl
ip.iBounds()))) { | 494 SkRect::Make(reducedCl
ip.ibounds()))) { |
| 517 return nullptr; | 495 return nullptr; |
| 518 } | 496 } |
| 519 } else { | 497 } else { |
| 520 // all the remaining ops can just be directly draw into the accumula
tion buffer | 498 // all the remaining ops can just be directly draw into the accumula
tion buffer |
| 521 GrPaint paint; | 499 GrPaint paint; |
| 522 paint.setAntiAlias(element->isAA()); | 500 paint.setAntiAlias(element->isAA()); |
| 523 paint.setCoverageSetOpXPFactory(op, false); | 501 paint.setCoverageSetOpXPFactory(op, false); |
| 524 | 502 |
| 525 draw_element(dc.get(), GrNoClip(), paint, translate, element); | 503 draw_element(dc.get(), GrNoClip(), paint, translate, element); |
| 526 } | 504 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 541 const SkIPoint& clipSpaceToStencilOf
fset) { | 519 const SkIPoint& clipSpaceToStencilOf
fset) { |
| 542 SkASSERT(drawContext); | 520 SkASSERT(drawContext); |
| 543 | 521 |
| 544 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach
StencilAttachment( | 522 GrStencilAttachment* stencilAttachment = context->resourceProvider()->attach
StencilAttachment( |
| 545 drawContext->accessRenderTar
get()); | 523 drawContext->accessRenderTar
get()); |
| 546 if (nullptr == stencilAttachment) { | 524 if (nullptr == stencilAttachment) { |
| 547 return false; | 525 return false; |
| 548 } | 526 } |
| 549 | 527 |
| 550 // TODO: these need to be swapped over to using a StencilAttachmentProxy | 528 // TODO: these need to be swapped over to using a StencilAttachmentProxy |
| 551 if (stencilAttachment->mustRenderClip(reducedClip.genID(), reducedClip.iBoun
ds(), | 529 if (stencilAttachment->mustRenderClip(reducedClip.genID(), reducedClip.iboun
ds(), |
| 552 clipSpaceToStencilOffset)) { | 530 clipSpaceToStencilOffset)) { |
| 553 stencilAttachment->setLastClip(reducedClip.genID(), reducedClip.iBounds(
), | 531 stencilAttachment->setLastClip(reducedClip.genID(), reducedClip.ibounds(
), |
| 554 clipSpaceToStencilOffset); | 532 clipSpaceToStencilOffset); |
| 555 // Set the matrix so that rendered clip elements are transformed from cl
ip to stencil space. | 533 // Set the matrix so that rendered clip elements are transformed from cl
ip to stencil space. |
| 556 SkVector translate = { | 534 SkVector translate = { |
| 557 SkIntToScalar(clipSpaceToStencilOffset.fX), | 535 SkIntToScalar(clipSpaceToStencilOffset.fX), |
| 558 SkIntToScalar(clipSpaceToStencilOffset.fY) | 536 SkIntToScalar(clipSpaceToStencilOffset.fY) |
| 559 }; | 537 }; |
| 560 SkMatrix viewMatrix; | 538 SkMatrix viewMatrix; |
| 561 viewMatrix.setTranslate(translate); | 539 viewMatrix.setTranslate(translate); |
| 562 | 540 |
| 563 // We set the current clip to the bounds so that our recursive draws are
scissored to them. | 541 // We set the current clip to the bounds so that our recursive draws are
scissored to them. |
| 564 SkIRect stencilSpaceIBounds(reducedClip.iBounds()); | 542 SkIRect stencilSpaceIBounds(reducedClip.ibounds()); |
| 565 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); | 543 stencilSpaceIBounds.offset(clipSpaceToStencilOffset); |
| 566 GrFixedClip clip(stencilSpaceIBounds); | 544 GrFixedClip clip(stencilSpaceIBounds); |
| 567 | 545 |
| 568 bool insideClip = GrReducedClip::InitialState::kAllIn == reducedClip.ini
tialState(); | 546 bool insideClip = InitialState::kAllIn == reducedClip.initialState(); |
| 569 drawContext->drawContextPriv().clearStencilClip(stencilSpaceIBounds, ins
ideClip); | 547 drawContext->drawContextPriv().clearStencilClip(stencilSpaceIBounds, ins
ideClip); |
| 570 | 548 |
| 571 // walk through each clip element and perform its set op | 549 // walk through each clip element and perform its set op |
| 572 // with the existing clip. | 550 // with the existing clip. |
| 573 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.ne
xt()) { | 551 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.ne
xt()) { |
| 574 const Element* element = iter.get(); | 552 const Element* element = iter.get(); |
| 575 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultis
ampled(); | 553 bool useHWAA = element->isAA() && drawContext->isStencilBufferMultis
ampled(); |
| 576 | 554 |
| 577 bool fillInverted = false; | 555 bool fillInverted = false; |
| 578 // enabled at bottom of loop | 556 // enabled at bottom of loop |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 664 args.fClip = &clip; | 642 args.fClip = &clip; |
| 665 args.fViewMatrix = &viewMatrix; | 643 args.fViewMatrix = &viewMatrix; |
| 666 args.fIsAA = element->isAA(); | 644 args.fIsAA = element->isAA(); |
| 667 args.fShape = &shape; | 645 args.fShape = &shape; |
| 668 pr->stencilPath(args); | 646 pr->stencilPath(args); |
| 669 } | 647 } |
| 670 } | 648 } |
| 671 } | 649 } |
| 672 } | 650 } |
| 673 | 651 |
| 652 // Just enable stencil clip. The passes choose whether or not they w
ill actually use it. |
| 653 clip.enableStencilClip(); |
| 654 |
| 674 // now we modify the clip bit by rendering either the clip | 655 // now we modify the clip bit by rendering either the clip |
| 675 // element directly or a bounding rect of the entire clip. | 656 // element directly or a bounding rect of the entire clip. |
| 676 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass
; ++pass) { | 657 for (GrUserStencilSettings const* const* pass = stencilPasses; *pass
; ++pass) { |
| 677 | |
| 678 if (drawDirectToClip) { | 658 if (drawDirectToClip) { |
| 679 if (Element::kRect_Type == element->getType()) { | 659 if (Element::kRect_Type == element->getType()) { |
| 680 clip.enableStencilClip(element->getRect().makeOffset(tra
nslate.fX, | |
| 681 tra
nslate.fY)); | |
| 682 drawContext->drawContextPriv().stencilRect(clip, *pass,
useHWAA, viewMatrix, | 660 drawContext->drawContextPriv().stencilRect(clip, *pass,
useHWAA, viewMatrix, |
| 683 element->getR
ect()); | 661 element->getR
ect()); |
| 684 } else { | 662 } else { |
| 685 GrShape shape(clipPath, GrStyle::SimpleFill()); | 663 GrShape shape(clipPath, GrStyle::SimpleFill()); |
| 686 GrPaint paint; | 664 GrPaint paint; |
| 687 SkRect bounds = clipPath.getBounds(); | |
| 688 bounds.offset(translate.fX, translate.fY); | |
| 689 clip.enableStencilClip(bounds); | |
| 690 paint.setXPFactory(GrDisableColorXPFactory::Make()); | 665 paint.setXPFactory(GrDisableColorXPFactory::Make()); |
| 691 paint.setAntiAlias(element->isAA()); | 666 paint.setAntiAlias(element->isAA()); |
| 692 GrPathRenderer::DrawPathArgs args; | 667 GrPathRenderer::DrawPathArgs args; |
| 693 args.fResourceProvider = context->resourceProvider(); | 668 args.fResourceProvider = context->resourceProvider(); |
| 694 args.fPaint = &paint; | 669 args.fPaint = &paint; |
| 695 args.fUserStencilSettings = *pass; | 670 args.fUserStencilSettings = *pass; |
| 696 args.fDrawContext = drawContext; | 671 args.fDrawContext = drawContext; |
| 697 args.fClip = &clip; | 672 args.fClip = &clip; |
| 698 args.fViewMatrix = &viewMatrix; | 673 args.fViewMatrix = &viewMatrix; |
| 699 args.fShape = &shape; | 674 args.fShape = &shape; |
| 700 args.fAntiAlias = false; | 675 args.fAntiAlias = false; |
| 701 args.fGammaCorrect = false; | 676 args.fGammaCorrect = false; |
| 702 pr->drawPath(args); | 677 pr->drawPath(args); |
| 703 } | 678 } |
| 704 } else { | 679 } else { |
| 705 // The view matrix is setup to do clip space -> stencil spac
e translation, so | 680 // The view matrix is setup to do clip space -> stencil spac
e translation, so |
| 706 // draw rect in clip space. | 681 // draw rect in clip space. |
| 707 SkRect bounds = SkRect::Make(reducedClip.iBounds()); | |
| 708 bounds.offset(translate.fX, translate.fY); | |
| 709 clip.enableStencilClip(bounds); | |
| 710 drawContext->drawContextPriv().stencilRect(clip, *pass, fals
e, viewMatrix, | 682 drawContext->drawContextPriv().stencilRect(clip, *pass, fals
e, viewMatrix, |
| 711 SkRect::Make(redu
cedClip.iBounds())); | 683 SkRect::Make(redu
cedClip.ibounds())); |
| 712 } | 684 } |
| 713 } | 685 } |
| 714 } | 686 } |
| 715 } | 687 } |
| 716 return true; | 688 return true; |
| 717 } | 689 } |
| 718 | 690 |
| 719 //////////////////////////////////////////////////////////////////////////////// | 691 //////////////////////////////////////////////////////////////////////////////// |
| 720 sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP
rovider, | 692 sk_sp<GrTexture> GrClipStackClip::CreateSoftwareClipMask(GrTextureProvider* texP
rovider, |
| 721 const GrReducedClip& re
ducedClip, | 693 const GrReducedClip& re
ducedClip, |
| 722 const SkVector& clipToM
askOffset) { | 694 const SkVector& clipToM
askOffset) { |
| 723 GrUniqueKey key; | 695 GrUniqueKey key; |
| 724 GetClipMaskKey(reducedClip.genID(), reducedClip.iBounds(), &key); | 696 GetClipMaskKey(reducedClip.genID(), reducedClip.ibounds(), &key); |
| 725 if (GrTexture* texture = texProvider->findAndRefTextureByUniqueKey(key)) { | 697 if (GrTexture* texture = texProvider->findAndRefTextureByUniqueKey(key)) { |
| 726 return sk_sp<GrTexture>(texture); | 698 return sk_sp<GrTexture>(texture); |
| 727 } | 699 } |
| 728 | 700 |
| 729 // The mask texture may be larger than necessary. We round out the clip spac
e bounds and pin | 701 // The mask texture may be larger than necessary. We round out the clip spac
e bounds and pin |
| 730 // the top left corner of the resulting rect to the top left of the texture. | 702 // the top left corner of the resulting rect to the top left of the texture. |
| 731 SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip.
height()); | 703 SkIRect maskSpaceIBounds = SkIRect::MakeWH(reducedClip.width(), reducedClip.
height()); |
| 732 | 704 |
| 733 GrSWMaskHelper helper(texProvider); | 705 GrSWMaskHelper helper(texProvider); |
| 734 | 706 |
| 735 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip | 707 // Set the matrix so that rendered clip elements are transformed to mask spa
ce from clip |
| 736 // space. | 708 // space. |
| 737 SkMatrix translate; | 709 SkMatrix translate; |
| 738 translate.setTranslate(clipToMaskOffset); | 710 translate.setTranslate(clipToMaskOffset); |
| 739 | 711 |
| 740 helper.init(maskSpaceIBounds, &translate); | 712 helper.init(maskSpaceIBounds, &translate); |
| 741 helper.clear(GrReducedClip::InitialState::kAllIn == reducedClip.initialState
() ? 0xFF : 0x00); | 713 helper.clear(InitialState::kAllIn == reducedClip.initialState() ? 0xFF : 0x0
0); |
| 742 | 714 |
| 743 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next()
) { | 715 for (ElementList::Iter iter(reducedClip.elements()); iter.get(); iter.next()
) { |
| 744 const Element* element = iter.get(); | 716 const Element* element = iter.get(); |
| 745 SkRegion::Op op = element->getOp(); | 717 SkRegion::Op op = element->getOp(); |
| 746 | 718 |
| 747 if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op ==
op) { | 719 if (SkRegion::kIntersect_Op == op || SkRegion::kReverseDifference_Op ==
op) { |
| 748 // Intersect and reverse difference require modifying pixels outside
of the geometry | 720 // Intersect and reverse difference require modifying pixels outside
of the geometry |
| 749 // that is being "drawn". In both cases we erase all the pixels outs
ide of the geometry | 721 // that is being "drawn". In both cases we erase all the pixels outs
ide of the geometry |
| 750 // but leave the pixels inside the geometry alone. For reverse diffe
rence we invert all | 722 // but leave the pixels inside the geometry alone. For reverse diffe
rence we invert all |
| 751 // the pixels before clearing the ones outside the geometry. | 723 // the pixels before clearing the ones outside the geometry. |
| 752 if (SkRegion::kReverseDifference_Op == op) { | 724 if (SkRegion::kReverseDifference_Op == op) { |
| 753 SkRect temp = SkRect::Make(reducedClip.iBounds()); | 725 SkRect temp = SkRect::Make(reducedClip.ibounds()); |
| 754 // invert the entire scene | 726 // invert the entire scene |
| 755 helper.drawRect(temp, SkRegion::kXOR_Op, false, 0xFF); | 727 helper.drawRect(temp, SkRegion::kXOR_Op, false, 0xFF); |
| 756 } | 728 } |
| 757 SkPath clipPath; | 729 SkPath clipPath; |
| 758 element->asPath(&clipPath); | 730 element->asPath(&clipPath); |
| 759 clipPath.toggleInverseFillType(); | 731 clipPath.toggleInverseFillType(); |
| 760 GrShape shape(clipPath, GrStyle::SimpleFill()); | 732 GrShape shape(clipPath, GrStyle::SimpleFill()); |
| 761 helper.drawShape(shape, SkRegion::kReplace_Op, element->isAA(), 0x00
); | 733 helper.drawShape(shape, SkRegion::kReplace_Op, element->isAA(), 0x00
); |
| 762 continue; | 734 continue; |
| 763 } | 735 } |
| (...skipping 19 matching lines...) Expand all Loading... |
| 783 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); | 755 sk_sp<GrTexture> result(texProvider->createApproxTexture(desc)); |
| 784 if (!result) { | 756 if (!result) { |
| 785 return nullptr; | 757 return nullptr; |
| 786 } | 758 } |
| 787 result->resourcePriv().setUniqueKey(key); | 759 result->resourcePriv().setUniqueKey(key); |
| 788 | 760 |
| 789 helper.toTexture(result.get()); | 761 helper.toTexture(result.get()); |
| 790 | 762 |
| 791 return result; | 763 return result; |
| 792 } | 764 } |
| OLD | NEW |