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 |