OLD | NEW |
1 | 1 |
2 /* | 2 /* |
3 * Copyright 2012 Google Inc. | 3 * Copyright 2012 Google Inc. |
4 * | 4 * |
5 * Use of this source code is governed by a BSD-style license that can be | 5 * Use of this source code is governed by a BSD-style license that can be |
6 * found in the LICENSE file. | 6 * found in the LICENSE file. |
7 */ | 7 */ |
8 | 8 |
9 #include "GrClipMaskManager.h" | 9 #include "GrClipMaskManager.h" |
10 #include "GrAAConvexPathRenderer.h" | 10 #include "GrAAConvexPathRenderer.h" |
(...skipping 467 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
478 | 478 |
479 drawState->addColorProcessor( | 479 drawState->addColorProcessor( |
480 GrTextureDomainEffect::Create(srcMask, | 480 GrTextureDomainEffect::Create(srcMask, |
481 sampleM, | 481 sampleM, |
482 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), | 482 GrTextureDomain::MakeTexelDomain(srcMask,
srcBound), |
483 GrTextureDomain::kDecal_Mode, | 483 GrTextureDomain::kDecal_Mode, |
484 GrTextureParams::kNone_FilterMode))->unref
(); | 484 GrTextureParams::kNone_FilterMode))->unref
(); |
485 fGpu->drawSimpleRect(SkRect::Make(dstBound)); | 485 fGpu->drawSimpleRect(SkRect::Make(dstBound)); |
486 } | 486 } |
487 | 487 |
488 // get a texture to act as a temporary buffer for AA clip boolean operations | 488 GrTexture* GrClipMaskManager::createTempMask(int width, int height) { |
489 // TODO: given the expense of createTexture we may want to just cache this too | |
490 void GrClipMaskManager::getTemp(int width, int height, GrAutoScratchTexture* tem
p) { | |
491 if (temp->texture()) { | |
492 // we've already allocated the temp texture | |
493 return; | |
494 } | |
495 | |
496 GrTextureDesc desc; | 489 GrTextureDesc desc; |
497 desc.fFlags = kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit; | 490 desc.fFlags = kRenderTarget_GrTextureFlagBit|kNoStencil_GrTextureFlagBit; |
498 desc.fWidth = width; | 491 desc.fWidth = width; |
499 desc.fHeight = height; | 492 desc.fHeight = height; |
500 desc.fConfig = kAlpha_8_GrPixelConfig; | 493 desc.fConfig = kAlpha_8_GrPixelConfig; |
501 | 494 |
502 temp->set(this->getContext(), desc); | 495 return fGpu->getContext()->refScratchTexture(desc, GrContext::kApprox_Scratc
hTexMatch); |
503 } | 496 } |
504 | 497 |
505 //////////////////////////////////////////////////////////////////////////////// | 498 //////////////////////////////////////////////////////////////////////////////// |
506 // Return the texture currently in the cache if it exists. Otherwise, return NUL
L | 499 // Return the texture currently in the cache if it exists. Otherwise, return NUL
L |
507 GrTexture* GrClipMaskManager::getCachedMaskTexture(int32_t elementsGenID, | 500 GrTexture* GrClipMaskManager::getCachedMaskTexture(int32_t elementsGenID, |
508 const SkIRect& clipSpaceIBoun
ds) { | 501 const SkIRect& clipSpaceIBoun
ds) { |
509 bool cached = fAACache.canReuse(elementsGenID, clipSpaceIBounds); | 502 bool cached = fAACache.canReuse(elementsGenID, clipSpaceIBounds); |
510 if (!cached) { | 503 if (!cached) { |
511 return NULL; | 504 return NULL; |
512 } | 505 } |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
586 true, | 579 true, |
587 result->asRenderTarget()); | 580 result->asRenderTarget()); |
588 | 581 |
589 // When we use the stencil in the below loop it is important to have this cl
ip installed. | 582 // When we use the stencil in the below loop it is important to have this cl
ip installed. |
590 // The second pass that zeros the stencil buffer renders the rect maskSpaceI
Bounds so the first | 583 // The second pass that zeros the stencil buffer renders the rect maskSpaceI
Bounds so the first |
591 // pass must not set values outside of this bounds or stencil values outside
the rect won't be | 584 // pass must not set values outside of this bounds or stencil values outside
the rect won't be |
592 // cleared. | 585 // cleared. |
593 GrDrawTarget::AutoClipRestore acr(fGpu, maskSpaceIBounds); | 586 GrDrawTarget::AutoClipRestore acr(fGpu, maskSpaceIBounds); |
594 drawState->enableState(GrDrawState::kClip_StateBit); | 587 drawState->enableState(GrDrawState::kClip_StateBit); |
595 | 588 |
596 GrAutoScratchTexture temp; | 589 SkAutoTUnref<GrTexture> temp; |
597 // walk through each clip element and perform its set op | 590 // walk through each clip element and perform its set op |
598 for (ElementList::Iter iter = elements.headIter(); iter.get(); iter.next())
{ | 591 for (ElementList::Iter iter = elements.headIter(); iter.get(); iter.next())
{ |
599 const Element* element = iter.get(); | 592 const Element* element = iter.get(); |
600 SkRegion::Op op = element->getOp(); | 593 SkRegion::Op op = element->getOp(); |
601 bool invert = element->isInverseFilled(); | 594 bool invert = element->isInverseFilled(); |
602 | 595 |
603 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { | 596 if (invert || SkRegion::kIntersect_Op == op || SkRegion::kReverseDiffere
nce_Op == op) { |
604 GrPathRenderer* pr = NULL; | 597 GrPathRenderer* pr = NULL; |
605 bool useTemp = !this->canStencilAndDrawElement(result, element, &pr)
; | 598 bool useTemp = !this->canStencilAndDrawElement(result, element, &pr)
; |
606 GrTexture* dst; | 599 GrTexture* dst; |
607 // This is the bounds of the clip element in the space of the alpha-
mask. The temporary | 600 // This is the bounds of the clip element in the space of the alpha-
mask. The temporary |
608 // mask buffer can be substantially larger than the actually clip st
ack element. We | 601 // mask buffer can be substantially larger than the actually clip st
ack element. We |
609 // touch the minimum number of pixels necessary and use decal mode t
o combine it with | 602 // touch the minimum number of pixels necessary and use decal mode t
o combine it with |
610 // the accumulator. | 603 // the accumulator. |
611 SkIRect maskSpaceElementIBounds; | 604 SkIRect maskSpaceElementIBounds; |
612 | 605 |
613 if (useTemp) { | 606 if (useTemp) { |
614 if (invert) { | 607 if (invert) { |
615 maskSpaceElementIBounds = maskSpaceIBounds; | 608 maskSpaceElementIBounds = maskSpaceIBounds; |
616 } else { | 609 } else { |
617 SkRect elementBounds = element->getBounds(); | 610 SkRect elementBounds = element->getBounds(); |
618 elementBounds.offset(clipToMaskOffset); | 611 elementBounds.offset(clipToMaskOffset); |
619 elementBounds.roundOut(&maskSpaceElementIBounds); | 612 elementBounds.roundOut(&maskSpaceElementIBounds); |
620 } | 613 } |
621 | 614 |
622 this->getTemp(maskSpaceIBounds.fRight, maskSpaceIBounds.fBottom,
&temp); | 615 if (!temp) { |
623 if (NULL == temp.texture()) { | 616 temp.reset(this->createTempMask(maskSpaceIBounds.fRight, |
624 fAACache.reset(); | 617 maskSpaceIBounds.fBottom)); |
625 return NULL; | 618 if (!temp) { |
| 619 fAACache.reset(); |
| 620 return NULL; |
| 621 } |
626 } | 622 } |
627 dst = temp.texture(); | 623 dst = temp; |
628 // clear the temp target and set blend to replace | 624 // clear the temp target and set blend to replace |
629 fGpu->clear(&maskSpaceElementIBounds, | 625 fGpu->clear(&maskSpaceElementIBounds, |
630 invert ? 0xffffffff : 0x00000000, | 626 invert ? 0xffffffff : 0x00000000, |
631 true, | 627 true, |
632 dst->asRenderTarget()); | 628 dst->asRenderTarget()); |
633 setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op); | 629 setup_boolean_blendcoeffs(drawState, SkRegion::kReplace_Op); |
634 | 630 |
635 } else { | 631 } else { |
636 // draw directly into the result with the stencil set to make th
e pixels affected | 632 // draw directly into the result with the stencil set to make th
e pixels affected |
637 // by the clip shape be non-zero. | 633 // by the clip shape be non-zero. |
(...skipping 13 matching lines...) Expand all Loading... |
651 | 647 |
652 if (!this->drawElement(dst, element, pr)) { | 648 if (!this->drawElement(dst, element, pr)) { |
653 fAACache.reset(); | 649 fAACache.reset(); |
654 return NULL; | 650 return NULL; |
655 } | 651 } |
656 | 652 |
657 if (useTemp) { | 653 if (useTemp) { |
658 // Now draw into the accumulator using the real operation and th
e temp buffer as a | 654 // Now draw into the accumulator using the real operation and th
e temp buffer as a |
659 // texture | 655 // texture |
660 this->mergeMask(result, | 656 this->mergeMask(result, |
661 temp.texture(), | 657 temp, |
662 op, | 658 op, |
663 maskSpaceIBounds, | 659 maskSpaceIBounds, |
664 maskSpaceElementIBounds); | 660 maskSpaceElementIBounds); |
665 } else { | 661 } else { |
666 // Draw to the exterior pixels (those with a zero stencil value)
. | 662 // Draw to the exterior pixels (those with a zero stencil value)
. |
667 drawState->setAlpha(invert ? 0xff : 0x00); | 663 drawState->setAlpha(invert ? 0xff : 0x00); |
668 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, | 664 GR_STATIC_CONST_SAME_STENCIL(kDrawOutsideElement, |
669 kZero_StencilOp, | 665 kZero_StencilOp, |
670 kZero_StencilOp, | 666 kZero_StencilOp, |
671 kEqual_StencilFunc, | 667 kEqual_StencilFunc, |
(...skipping 468 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1140 | 1136 |
1141 // TODO: dynamically attach a stencil buffer | 1137 // TODO: dynamically attach a stencil buffer |
1142 int stencilBits = 0; | 1138 int stencilBits = 0; |
1143 GrStencilBuffer* stencilBuffer = | 1139 GrStencilBuffer* stencilBuffer = |
1144 drawState.getRenderTarget()->getStencilBuffer(); | 1140 drawState.getRenderTarget()->getStencilBuffer(); |
1145 if (stencilBuffer) { | 1141 if (stencilBuffer) { |
1146 stencilBits = stencilBuffer->bits(); | 1142 stencilBits = stencilBuffer->bits(); |
1147 this->adjustStencilParams(settings, clipMode, stencilBits); | 1143 this->adjustStencilParams(settings, clipMode, stencilBits); |
1148 } | 1144 } |
1149 } | 1145 } |
OLD | NEW |