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 "GrAAConvexPathRenderer.h" | 9 #include "GrAAConvexPathRenderer.h" |
10 #include "GrAAHairLinePathRenderer.h" | 10 #include "GrAAHairLinePathRenderer.h" |
(...skipping 312 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
323 // use both stencil and scissor test to the bounds for the final draw. | 323 // use both stencil and scissor test to the bounds for the final draw. |
324 SkIRect scissorSpaceIBounds(clipSpaceIBounds); | 324 SkIRect scissorSpaceIBounds(clipSpaceIBounds); |
325 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); | 325 scissorSpaceIBounds.offset(clipSpaceToStencilSpaceOffset); |
326 scissorState->set(scissorSpaceIBounds); | 326 scissorState->set(scissorSpaceIBounds); |
327 this->setDrawStateStencil(drawState, ars); | 327 this->setDrawStateStencil(drawState, ars); |
328 return true; | 328 return true; |
329 } | 329 } |
330 | 330 |
331 namespace { | 331 namespace { |
332 //////////////////////////////////////////////////////////////////////////////// | 332 //////////////////////////////////////////////////////////////////////////////// |
333 // set up the OpenGL blend function to perform the specified | 333 // Set a coverage drawing XPF on the drawState for the given op and invertCovera ge mode |
334 // boolean operation for alpha clip mask creation | 334 void set_coverage_drawing_xpf(SkRegion::Op op, bool invertCoverage, GrDrawState* drawState) { |
335 void setup_boolean_blendcoeffs(SkRegion::Op op, GrDrawState* drawState) { | 335 SkASSERT(op <= SkRegion::kLastOp); |
336 // TODO: once we have a coverageDrawing XP this will all use that instead of PD | 336 drawState->setCoverageSetOpXPFactory(op, invertCoverage); |
337 switch (op) { | |
338 case SkRegion::kReplace_Op: | |
339 drawState->setPorterDuffXPFactory(kOne_GrBlendCoeff, kZero_GrBlendCo eff); | |
340 break; | |
341 case SkRegion::kIntersect_Op: | |
342 drawState->setPorterDuffXPFactory(kDC_GrBlendCoeff, kZero_GrBlendCoe ff); | |
343 break; | |
344 case SkRegion::kUnion_Op: | |
345 drawState->setPorterDuffXPFactory(kOne_GrBlendCoeff, kISC_GrBlendCoe ff); | |
346 break; | |
347 case SkRegion::kXOR_Op: | |
348 drawState->setPorterDuffXPFactory(kIDC_GrBlendCoeff, kISC_GrBlendCoe ff); | |
349 break; | |
350 case SkRegion::kDifference_Op: | |
351 drawState->setPorterDuffXPFactory(kZero_GrBlendCoeff, kISC_GrBlendCo eff); | |
352 break; | |
353 case SkRegion::kReverseDifference_Op: | |
354 drawState->setPorterDuffXPFactory(kIDC_GrBlendCoeff, kZero_GrBlendCo eff); | |
355 break; | |
356 default: | |
357 SkASSERT(false); | |
358 break; | |
359 } | |
360 } | 337 } |
361 } | 338 } |
362 | 339 |
363 //////////////////////////////////////////////////////////////////////////////// | 340 //////////////////////////////////////////////////////////////////////////////// |
364 bool GrClipMaskManager::drawElement(GrDrawState* drawState, | 341 bool GrClipMaskManager::drawElement(GrDrawState* drawState, |
365 GrColor color, | 342 GrColor color, |
366 GrTexture* target, | 343 GrTexture* target, |
367 const SkClipStack::Element* element, | 344 const SkClipStack::Element* element, |
368 GrPathRenderer* pr) { | 345 GrPathRenderer* pr) { |
369 GrDrawTarget::AutoGeometryPush agp(fClipTarget); | 346 GrDrawTarget::AutoGeometryPush agp(fClipTarget); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
444 void GrClipMaskManager::mergeMask(GrDrawState* drawState, | 421 void GrClipMaskManager::mergeMask(GrDrawState* drawState, |
445 GrTexture* dstMask, | 422 GrTexture* dstMask, |
446 GrTexture* srcMask, | 423 GrTexture* srcMask, |
447 SkRegion::Op op, | 424 SkRegion::Op op, |
448 const SkIRect& dstBound, | 425 const SkIRect& dstBound, |
449 const SkIRect& srcBound) { | 426 const SkIRect& srcBound) { |
450 SkAssertResult(drawState->setIdentityViewMatrix()); | 427 SkAssertResult(drawState->setIdentityViewMatrix()); |
451 | 428 |
452 drawState->setRenderTarget(dstMask->asRenderTarget()); | 429 drawState->setRenderTarget(dstMask->asRenderTarget()); |
453 | 430 |
454 setup_boolean_blendcoeffs(op, drawState); | 431 // We want to invert the coverage here |
bsalomon
2014/12/16 17:35:56
we do??
egdaniel
2014/12/17 21:12:37
changed to false and changed to use coverageProces
| |
432 set_coverage_drawing_xpf(op, true, drawState); | |
455 | 433 |
456 SkMatrix sampleM; | 434 SkMatrix sampleM; |
457 sampleM.setIDiv(srcMask->width(), srcMask->height()); | 435 sampleM.setIDiv(srcMask->width(), srcMask->height()); |
458 | 436 |
459 drawState->addColorProcessor( | 437 drawState->addColorProcessor( |
460 GrTextureDomainEffect::Create(srcMask, | 438 GrTextureDomainEffect::Create(srcMask, |
461 sampleM, | 439 sampleM, |
462 GrTextureDomain::MakeTexelDomain(srcMask, srcBound), | 440 GrTextureDomain::MakeTexelDomain(srcMask, srcBound), |
463 GrTextureDomain::kDecal_Mode, | 441 GrTextureDomain::kDecal_Mode, |
464 GrTextureParams::kNone_FilterMode))->unref (); | 442 GrTextureParams::kNone_FilterMode))->unref (); |
443 // The color passed in here does not matter since the coverageSetOpXP won't read it. | |
465 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkRect::Make(dstBound) ); | 444 fClipTarget->drawSimpleRect(drawState, GrColor_WHITE, SkRect::Make(dstBound) ); |
466 } | 445 } |
467 | 446 |
468 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { | 447 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { |
469 GrSurfaceDesc desc; | 448 GrSurfaceDesc desc; |
470 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; | 449 desc.fFlags = kRenderTarget_GrSurfaceFlag|kNoStencil_GrSurfaceFlag; |
471 desc.fWidth = width; | 450 desc.fWidth = width; |
472 desc.fHeight = height; | 451 desc.fHeight = height; |
473 desc.fConfig = kAlpha_8_GrPixelConfig; | 452 desc.fConfig = kAlpha_8_GrPixelConfig; |
474 | 453 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
560 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); | 539 GrDrawTarget::AutoClipRestore acr(fClipTarget, maskSpaceIBounds); |
561 SkAutoTUnref<GrTexture> temp; | 540 SkAutoTUnref<GrTexture> temp; |
562 | 541 |
563 // walk through each clip element and perform its set op | 542 // walk through each clip element and perform its set op |
564 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get() ; iter.next()) { | 543 for (GrReducedClip::ElementList::Iter iter = elements.headIter(); iter.get() ; iter.next()) { |
565 const Element* element = iter.get(); | 544 const Element* element = iter.get(); |
566 SkRegion::Op op = element->getOp(); | 545 SkRegion::Op op = element->getOp(); |
567 bool invert = element->isInverseFilled(); | 546 bool invert = element->isInverseFilled(); |
568 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) { | 547 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere nce_Op == op) { |
569 GrDrawState drawState(translate); | 548 GrDrawState drawState(translate); |
570 // We're drawing a coverage mask and want coverage to be run through the blend function. | 549 drawState.enableState(GrDrawState::kClip_StateBit); |
571 drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | | |
572 GrDrawState::kClip_StateBit); | |
573 | 550 |
574 GrPathRenderer* pr = NULL; | 551 GrPathRenderer* pr = NULL; |
575 bool useTemp = !this->canStencilAndDrawElement(&drawState, result, & pr, element); | 552 bool useTemp = !this->canStencilAndDrawElement(&drawState, result, & pr, element); |
576 GrTexture* dst; | 553 GrTexture* dst; |
577 // This is the bounds of the clip element in the space of the alpha- mask. The temporary | 554 // This is the bounds of the clip element in the space of the alpha- mask. The temporary |
578 // mask buffer can be substantially larger than the actually clip st ack element. We | 555 // mask buffer can be substantially larger than the actually clip st ack element. We |
579 // touch the minimum number of pixels necessary and use decal mode t o combine it with | 556 // touch the minimum number of pixels necessary and use decal mode t o combine it with |
580 // the accumulator. | 557 // the accumulator. |
581 SkIRect maskSpaceElementIBounds; | 558 SkIRect maskSpaceElementIBounds; |
582 | 559 |
(...skipping 13 matching lines...) Expand all Loading... | |
596 fAACache.reset(); | 573 fAACache.reset(); |
597 return NULL; | 574 return NULL; |
598 } | 575 } |
599 } | 576 } |
600 dst = temp; | 577 dst = temp; |
601 // clear the temp target and set blend to replace | 578 // clear the temp target and set blend to replace |
602 fClipTarget->clear(&maskSpaceElementIBounds, | 579 fClipTarget->clear(&maskSpaceElementIBounds, |
603 invert ? 0xffffffff : 0x00000000, | 580 invert ? 0xffffffff : 0x00000000, |
604 true, | 581 true, |
605 dst->asRenderTarget()); | 582 dst->asRenderTarget()); |
606 setup_boolean_blendcoeffs(SkRegion::kReplace_Op, &drawState); | 583 set_coverage_drawing_xpf(SkRegion::kReplace_Op, invert, &drawSta te); |
607 } else { | 584 } else { |
608 // draw directly into the result with the stencil set to make th e pixels affected | 585 // draw directly into the result with the stencil set to make th e pixels affected |
609 // by the clip shape be non-zero. | 586 // by the clip shape be non-zero. |
610 dst = result; | 587 dst = result; |
611 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, | 588 GR_STATIC_CONST_SAME_STENCIL(kStencilInElement, |
612 kReplace_StencilOp, | 589 kReplace_StencilOp, |
613 kReplace_StencilOp, | 590 kReplace_StencilOp, |
614 kAlways_StencilFunc, | 591 kAlways_StencilFunc, |
615 0xffff, | 592 0xffff, |
616 0xffff, | 593 0xffff, |
617 0xffff); | 594 0xffff); |
618 drawState.setStencil(kStencilInElement); | 595 drawState.setStencil(kStencilInElement); |
619 setup_boolean_blendcoeffs(op, &drawState); | 596 set_coverage_drawing_xpf(op, invert, &drawState); |
620 } | 597 } |
621 | 598 |
622 // We have to backup the drawstate because the drawElement call may call into | 599 // The color passed in here does not matter since the coverageSetOpX P won't read it. |
623 // renderers which consume it. | 600 if (!this->drawElement(&drawState, GrColor_WHITE, dst, element, pr)) { |
bsalomon
2014/12/16 17:35:56
Can drawElement just not take a color then?
egdaniel
2014/12/17 21:12:37
Done.
| |
624 GrDrawState backupDrawState(drawState); | |
625 | |
626 if (!this->drawElement(&drawState, invert ? GrColor_TRANS_BLACK : | |
627 GrColor_WHITE, dst, elem ent, pr)) { | |
628 fAACache.reset(); | 601 fAACache.reset(); |
629 return NULL; | 602 return NULL; |
630 } | 603 } |
631 | 604 |
605 // We have to make a new drawstate because the drawElement call may call into | |
bsalomon
2014/12/16 17:35:56
I'm not sure this comment adds much value. A new d
egdaniel
2014/12/17 21:12:37
removed
| |
606 // renderers which consume it. We also need to use a different cover age drawing xp which | |
607 // inverts the coverage. | |
608 GrDrawState backgroundDrawState(translate); | |
609 backgroundDrawState.enableState(GrDrawState::kClip_StateBit); | |
610 backgroundDrawState.setRenderTarget(result->asRenderTarget()); | |
611 | |
632 if (useTemp) { | 612 if (useTemp) { |
633 // Now draw into the accumulator using the real operation and th e temp buffer as a | 613 // Now draw into the accumulator using the real operation and th e temp buffer as a |
634 // texture | 614 // texture |
635 this->mergeMask(&backupDrawState, | 615 this->mergeMask(&backgroundDrawState, |
636 result, | 616 result, |
637 temp, | 617 temp, |
638 op, | 618 op, |
639 maskSpaceIBounds, | 619 maskSpaceIBounds, |
640 maskSpaceElementIBounds); | 620 maskSpaceElementIBounds); |
641 } else { | 621 } else { |
622 set_coverage_drawing_xpf(op, !invert, &backgroundDrawState); | |
642 // Draw to the exterior pixels (those with a zero stencil value) . | 623 // Draw to the exterior pixels (those with a zero stencil value) . |
643 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, | 624 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, |
644 kZero_StencilOp, | 625 kZero_StencilOp, |
645 kZero_StencilOp, | 626 kZero_StencilOp, |
646 kEqual_StencilFunc, | 627 kEqual_StencilFunc, |
647 0xffff, | 628 0xffff, |
648 0x0000, | 629 0x0000, |
649 0xffff); | 630 0xffff); |
650 backupDrawState.setStencil(kDrawOutsideElement); | 631 backgroundDrawState.setStencil(kDrawOutsideElement); |
651 fClipTarget->drawSimpleRect(&backupDrawState, | 632 // The color passed in here does not matter since the coverageSe tOpXP won't read it. |
652 invert ? GrColor_WHITE : GrColor_TRA NS_BLACK, | 633 fClipTarget->drawSimpleRect(&backgroundDrawState, GrColor_WHITE, clipSpaceIBounds); |
653 clipSpaceIBounds); | |
654 } | 634 } |
655 } else { | 635 } else { |
656 GrDrawState drawState(translate); | 636 GrDrawState drawState(translate); |
657 drawState.enableState(GrDrawState::kCoverageDrawing_StateBit | | 637 drawState.enableState(GrDrawState::kClip_StateBit); |
658 GrDrawState::kClip_StateBit); | |
659 | 638 |
660 // all the remaining ops can just be directly draw into the accumula tion buffer | 639 // all the remaining ops can just be directly draw into the accumula tion buffer |
661 setup_boolean_blendcoeffs(op, &drawState); | 640 set_coverage_drawing_xpf(op, false, &drawState); |
641 // The color passed in here does not matter since the coverageSetOpX P won't read it. | |
662 this->drawElement(&drawState, GrColor_WHITE, result, element); | 642 this->drawElement(&drawState, GrColor_WHITE, result, element); |
663 } | 643 } |
664 } | 644 } |
665 | 645 |
666 fCurrClipMaskType = kAlpha_ClipMaskType; | 646 fCurrClipMaskType = kAlpha_ClipMaskType; |
667 return result; | 647 return result; |
668 } | 648 } |
669 | 649 |
670 //////////////////////////////////////////////////////////////////////////////// | 650 //////////////////////////////////////////////////////////////////////////////// |
671 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device | 651 // Create a 1-bit clip mask in the stencil buffer. 'devClipBounds' are in device |
(...skipping 409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1081 } | 1061 } |
1082 | 1062 |
1083 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu ffer, | 1063 void GrClipMaskManager::adjustPathStencilParams(const GrStencilBuffer* stencilBu ffer, |
1084 GrStencilSettings* settings) { | 1064 GrStencilSettings* settings) { |
1085 // TODO: dynamically attach a stencil buffer | 1065 // TODO: dynamically attach a stencil buffer |
1086 if (stencilBuffer) { | 1066 if (stencilBuffer) { |
1087 int stencilBits = stencilBuffer->bits(); | 1067 int stencilBits = stencilBuffer->bits(); |
1088 this->adjustStencilParams(settings, fClipMode, stencilBits); | 1068 this->adjustStencilParams(settings, fClipMode, stencilBits); |
1089 } | 1069 } |
1090 } | 1070 } |
OLD | NEW |