OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 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 "effects/GrCustomXfermode.h" | 8 #include "effects/GrCustomXfermode.h" |
9 #include "effects/GrCustomXfermodePriv.h" | 9 #include "effects/GrCustomXfermodePriv.h" |
10 | 10 |
11 #include "GrCoordTransform.h" | 11 #include "GrCoordTransform.h" |
12 #include "GrContext.h" | 12 #include "GrContext.h" |
13 #include "GrFragmentProcessor.h" | 13 #include "GrFragmentProcessor.h" |
14 #include "GrInvariantOutput.h" | 14 #include "GrInvariantOutput.h" |
15 #include "GrProcessor.h" | 15 #include "GrProcessor.h" |
16 #include "GrTexture.h" | 16 #include "GrTexture.h" |
17 #include "GrTextureAccess.h" | 17 #include "GrTextureAccess.h" |
18 #include "SkXfermode.h" | 18 #include "SkXfermode.h" |
19 #include "gl/GrGLCaps.h" | 19 #include "gl/GrGLCaps.h" |
| 20 #include "gl/GrGLGpu.h" |
20 #include "gl/GrGLProcessor.h" | 21 #include "gl/GrGLProcessor.h" |
21 #include "gl/GrGLProgramDataManager.h" | 22 #include "gl/GrGLProgramDataManager.h" |
22 #include "gl/builders/GrGLProgramBuilder.h" | 23 #include "gl/builders/GrGLProgramBuilder.h" |
23 | 24 |
24 bool GrCustomXfermode::IsSupportedMode(SkXfermode::Mode mode) { | 25 bool GrCustomXfermode::IsSupportedMode(SkXfermode::Mode mode) { |
25 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; | 26 return mode > SkXfermode::kLastCoeffMode && mode <= SkXfermode::kLastMode; |
26 } | 27 } |
27 | 28 |
28 /////////////////////////////////////////////////////////////////////////////// | 29 /////////////////////////////////////////////////////////////////////////////// |
29 // Static helpers | 30 // Static helpers |
30 /////////////////////////////////////////////////////////////////////////////// | 31 /////////////////////////////////////////////////////////////////////////////// |
31 | 32 |
| 33 static GrBlendEquation hw_blend_equation(SkXfermode::Mode mode) { |
| 34 enum { kOffset = kOverlay_GrBlendEquation - SkXfermode::kOverlay_Mode }; |
| 35 return static_cast<GrBlendEquation>(mode + kOffset); |
| 36 |
| 37 GR_STATIC_ASSERT(kOverlay_GrBlendEquation == SkXfermode::kOverlay_Mode + kOf
fset); |
| 38 GR_STATIC_ASSERT(kDarken_GrBlendEquation == SkXfermode::kDarken_Mode + kOffs
et); |
| 39 GR_STATIC_ASSERT(kLighten_GrBlendEquation == SkXfermode::kLighten_Mode + kOf
fset); |
| 40 GR_STATIC_ASSERT(kColorDodge_GrBlendEquation == SkXfermode::kColorDodge_Mode
+ kOffset); |
| 41 GR_STATIC_ASSERT(kColorBurn_GrBlendEquation == SkXfermode::kColorBurn_Mode +
kOffset); |
| 42 GR_STATIC_ASSERT(kHardLight_GrBlendEquation == SkXfermode::kHardLight_Mode +
kOffset); |
| 43 GR_STATIC_ASSERT(kSoftLight_GrBlendEquation == SkXfermode::kSoftLight_Mode +
kOffset); |
| 44 GR_STATIC_ASSERT(kDifference_GrBlendEquation == SkXfermode::kDifference_Mode
+ kOffset); |
| 45 GR_STATIC_ASSERT(kExclusion_GrBlendEquation == SkXfermode::kExclusion_Mode +
kOffset); |
| 46 GR_STATIC_ASSERT(kMultiply_GrBlendEquation == SkXfermode::kMultiply_Mode + k
Offset); |
| 47 GR_STATIC_ASSERT(kHSLHue_GrBlendEquation == SkXfermode::kHue_Mode + kOffset)
; |
| 48 GR_STATIC_ASSERT(kHSLSaturation_GrBlendEquation == SkXfermode::kSaturation_M
ode + kOffset); |
| 49 GR_STATIC_ASSERT(kHSLColor_GrBlendEquation == SkXfermode::kColor_Mode + kOff
set); |
| 50 GR_STATIC_ASSERT(kHSLLuminosity_GrBlendEquation == SkXfermode::kLuminosity_M
ode + kOffset); |
| 51 GR_STATIC_ASSERT(kTotalGrBlendEquationCount == SkXfermode::kLastMode + 1 + k
Offset); |
| 52 } |
| 53 |
32 static void hard_light(GrGLFragmentBuilder* fsBuilder, | 54 static void hard_light(GrGLFragmentBuilder* fsBuilder, |
33 const char* final, | 55 const char* final, |
34 const char* src, | 56 const char* src, |
35 const char* dst) { | 57 const char* dst) { |
36 static const char kComponents[] = {'r', 'g', 'b'}; | 58 static const char kComponents[] = {'r', 'g', 'b'}; |
37 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { | 59 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { |
38 char component = kComponents[i]; | 60 char component = kComponents[i]; |
39 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src
); | 61 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src
); |
40 fsBuilder->codeAppendf("%s.%c = 2.0 * %s.%c * %s.%c;", | 62 fsBuilder->codeAppendf("%s.%c = 2.0 * %s.%c * %s.%c;", |
41 final, component, src, component, dst, component)
; | 63 final, component, src, component, dst, component)
; |
(...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
503 | 525 |
504 bool hasSecondaryOutput() const override { return false; } | 526 bool hasSecondaryOutput() const override { return false; } |
505 | 527 |
506 GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI, | 528 GrXferProcessor::OptFlags getOptimizations(const GrProcOptInfo& colorPOI, |
507 const GrProcOptInfo& coveragePOI, | 529 const GrProcOptInfo& coveragePOI, |
508 bool doesStencilWrite, | 530 bool doesStencilWrite, |
509 GrColor* overrideColor, | 531 GrColor* overrideColor, |
510 const GrDrawTargetCaps& caps) ove
rride; | 532 const GrDrawTargetCaps& caps) ove
rride; |
511 | 533 |
512 SkXfermode::Mode mode() const { return fMode; } | 534 SkXfermode::Mode mode() const { return fMode; } |
| 535 bool hasCoverage() const { return fHasCoverage; } |
| 536 bool hasHWBlendEquation() const { return kInvalid_GrBlendEquation != fHWBlen
dEquation; } |
| 537 |
| 538 GrBlendEquation hwBlendEquation() const { |
| 539 SkASSERT(this->hasHWBlendEquation()); |
| 540 return fHWBlendEquation; |
| 541 } |
513 | 542 |
514 private: | 543 private: |
515 CustomXP(SkXfermode::Mode mode, const GrDeviceCoordTexture* dstCopy, bool wi
llReadDstColor); | 544 CustomXP(SkXfermode::Mode mode, const GrDeviceCoordTexture* dstCopy, bool wi
llReadDstColor); |
516 | 545 |
517 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override; | 546 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override; |
518 | 547 |
| 548 bool onWillNeedXferBarrier(const GrRenderTarget* rt, |
| 549 const GrDrawTargetCaps& caps, |
| 550 GrXferBarrierType* outBarrierType) const override
; |
| 551 |
| 552 void onGetBlendInfo(BlendInfo*) const override; |
| 553 |
519 bool onIsEqual(const GrXferProcessor& xpBase) const override; | 554 bool onIsEqual(const GrXferProcessor& xpBase) const override; |
520 | 555 |
521 SkXfermode::Mode fMode; | 556 SkXfermode::Mode fMode; |
| 557 bool fHasCoverage; |
| 558 GrBlendEquation fHWBlendEquation; |
522 | 559 |
523 typedef GrXferProcessor INHERITED; | 560 typedef GrXferProcessor INHERITED; |
524 }; | 561 }; |
525 | 562 |
526 /////////////////////////////////////////////////////////////////////////////// | 563 /////////////////////////////////////////////////////////////////////////////// |
527 | 564 |
528 GrXPFactory* GrCustomXfermode::CreateXPFactory(SkXfermode::Mode mode) { | 565 GrXPFactory* GrCustomXfermode::CreateXPFactory(SkXfermode::Mode mode) { |
529 if (!GrCustomXfermode::IsSupportedMode(mode)) { | 566 if (!GrCustomXfermode::IsSupportedMode(mode)) { |
530 return NULL; | 567 return NULL; |
531 } else { | 568 } else { |
532 return SkNEW_ARGS(GrCustomXPFactory, (mode)); | 569 return SkNEW_ARGS(GrCustomXPFactory, (mode)); |
533 } | 570 } |
534 } | 571 } |
535 | 572 |
536 /////////////////////////////////////////////////////////////////////////////// | 573 /////////////////////////////////////////////////////////////////////////////// |
537 | 574 |
538 class GLCustomXP : public GrGLXferProcessor { | 575 class GLCustomXP : public GrGLXferProcessor { |
539 public: | 576 public: |
540 GLCustomXP(const GrXferProcessor&) {} | 577 GLCustomXP(const GrXferProcessor&) {} |
541 ~GLCustomXP() override {} | 578 ~GLCustomXP() override {} |
542 | 579 |
543 static void GenKey(const GrXferProcessor& proc, const GrGLSLCaps&, GrProcess
orKeyBuilder* b) { | 580 static void GenKey(const GrXferProcessor& p, const GrGLSLCaps& caps, GrProce
ssorKeyBuilder* b) { |
544 uint32_t key = proc.numTextures(); | 581 const CustomXP& xp = p.cast<CustomXP>(); |
| 582 uint32_t key = xp.numTextures(); |
545 SkASSERT(key <= 1); | 583 SkASSERT(key <= 1); |
546 key |= proc.cast<CustomXP>().mode() << 1; | 584 key |= xp.hasCoverage() << 1; |
| 585 if (xp.hasHWBlendEquation()) { |
| 586 SkASSERT(caps.advBlendEqInteraction() > 0); // 0 will mean !xp.hasH
WBlendEquation(). |
| 587 key |= caps.advBlendEqInteraction() << 2; |
| 588 } |
| 589 if (!xp.hasHWBlendEquation() || caps.mustEnableSpecificAdvBlendEqs()) { |
| 590 GR_STATIC_ASSERT(GrGLSLCaps::kLast_AdvBlendEqInteraction < 4); |
| 591 key |= xp.mode() << 4; |
| 592 } |
547 b->add32(key); | 593 b->add32(key); |
548 } | 594 } |
549 | 595 |
550 private: | 596 private: |
551 void onEmitCode(const EmitArgs& args) override { | 597 void onEmitCode(const EmitArgs& args) override { |
552 SkXfermode::Mode mode = args.fXP.cast<CustomXP>().mode(); | 598 const CustomXP& xp = args.fXP.cast<CustomXP>(); |
553 GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); | 599 GrGLXPFragmentBuilder* fsBuilder = args.fPB->getFragmentShaderBuilder(); |
554 const char* dstColor = fsBuilder->dstColor(); | |
555 | 600 |
556 emit_custom_xfermode_code(mode, fsBuilder, args.fOutputPrimary, args.fIn
putColor, dstColor); | 601 if (xp.hasHWBlendEquation()) { |
557 | 602 // The blend mode will be implemented in hardware; only output the s
rc color. |
558 fsBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;", | 603 fsBuilder->enableAdvancedBlendEquationIfNeeded(xp.hwBlendEquation())
; |
559 args.fOutputPrimary, args.fOutputPrimary, args.fI
nputCoverage, | 604 if (xp.hasCoverage()) { |
560 args.fInputCoverage, dstColor); | 605 // Do coverage modulation by multiplying it into the src color b
efore blending. |
| 606 // (See getOptimizations()) |
| 607 fsBuilder->codeAppendf("%s = %s * %s;", |
| 608 args.fOutputPrimary, args.fInputCoverage,
args.fInputColor); |
| 609 } else { |
| 610 fsBuilder->codeAppendf("%s = %s;", args.fOutputPrimary, args.fIn
putColor); |
| 611 } |
| 612 } else { |
| 613 const char* dstColor = fsBuilder->dstColor(); |
| 614 emit_custom_xfermode_code(xp.mode(), fsBuilder, args.fOutputPrimary,
args.fInputColor, |
| 615 dstColor); |
| 616 if (xp.hasCoverage()) { |
| 617 fsBuilder->codeAppendf("%s = %s * %s + (vec4(1.0) - %s) * %s;", |
| 618 args.fOutputPrimary, args.fOutputPrimary, |
| 619 args.fInputCoverage, args.fInputCoverage,
dstColor); |
| 620 } |
| 621 } |
561 } | 622 } |
562 | 623 |
563 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri
de {} | 624 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri
de {} |
564 | 625 |
565 typedef GrGLFragmentProcessor INHERITED; | 626 typedef GrGLFragmentProcessor INHERITED; |
566 }; | 627 }; |
567 | 628 |
568 /////////////////////////////////////////////////////////////////////////////// | 629 /////////////////////////////////////////////////////////////////////////////// |
569 | 630 |
570 CustomXP::CustomXP(SkXfermode::Mode mode, const GrDeviceCoordTexture* dstCopy, | 631 CustomXP::CustomXP(SkXfermode::Mode mode, const GrDeviceCoordTexture* dstCopy, |
571 bool willReadDstColor) | 632 bool willReadDstColor) |
572 : INHERITED(dstCopy, willReadDstColor), fMode(mode) { | 633 : INHERITED(dstCopy, willReadDstColor), |
| 634 fMode(mode), |
| 635 fHasCoverage(true), |
| 636 fHWBlendEquation(kInvalid_GrBlendEquation) { |
573 this->initClassID<CustomXP>(); | 637 this->initClassID<CustomXP>(); |
574 } | 638 } |
575 | 639 |
576 void CustomXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder
* b) const { | 640 void CustomXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder
* b) const { |
577 GLCustomXP::GenKey(*this, caps, b); | 641 GLCustomXP::GenKey(*this, caps, b); |
578 } | 642 } |
579 | 643 |
580 GrGLXferProcessor* CustomXP::createGLInstance() const { | 644 GrGLXferProcessor* CustomXP::createGLInstance() const { |
| 645 SkASSERT(this->willReadDstColor() != this->hasHWBlendEquation()); |
581 return SkNEW_ARGS(GLCustomXP, (*this)); | 646 return SkNEW_ARGS(GLCustomXP, (*this)); |
582 } | 647 } |
583 | 648 |
584 bool CustomXP::onIsEqual(const GrXferProcessor& other) const { | 649 bool CustomXP::onIsEqual(const GrXferProcessor& other) const { |
585 const CustomXP& s = other.cast<CustomXP>(); | 650 const CustomXP& s = other.cast<CustomXP>(); |
586 return fMode == s.fMode; | 651 return fMode == s.fMode && |
| 652 fHasCoverage == s.fHasCoverage && |
| 653 fHWBlendEquation == s.fHWBlendEquation; |
587 } | 654 } |
588 | 655 |
589 GrXferProcessor::OptFlags CustomXP::getOptimizations(const GrProcOptInfo& colorP
OI, | 656 GrXferProcessor::OptFlags CustomXP::getOptimizations(const GrProcOptInfo& colorP
OI, |
590 const GrProcOptInfo& cove
ragePOI, | 657 const GrProcOptInfo& cove
ragePOI, |
591 bool doesStencilWrite, | 658 bool doesStencilWrite, |
592 GrColor* overrideColor, | 659 GrColor* overrideColor, |
593 const GrDrawTargetCaps& c
aps) { | 660 const GrDrawTargetCaps& c
aps) { |
594 return GrXferProcessor::kNone_Opt; | 661 /* |
| 662 Most the optimizations we do here are based on tweaking alpha for coverage. |
| 663 |
| 664 The general SVG blend equation is defined in the spec as follows: |
| 665 |
| 666 Dca' = B(Sc, Dc) * Sa * Da + Y * Sca * (1-Da) + Z * Dca * (1-Sa) |
| 667 Da' = X * Sa * Da + Y * Sa * (1-Da) + Z * Da * (1-Sa) |
| 668 |
| 669 (Note that Sca, Dca indicate RGB vectors that are premultiplied by alpha, |
| 670 and that B(Sc, Dc) is a mode-specific function that accepts non-multiplied |
| 671 RGB colors.) |
| 672 |
| 673 For every blend mode supported by this class, i.e. the "advanced" blend |
| 674 modes, X=Y=Z=1 and this equation reduces to the PDF blend equation. |
| 675 |
| 676 It can be shown that when X=Y=Z=1, these equations can modulate alpha for |
| 677 coverage. |
| 678 |
| 679 |
| 680 == Color == |
| 681 |
| 682 We substitute Y=Z=1 and define a blend() function that calculates Dca' in |
| 683 terms of premultiplied alpha only: |
| 684 |
| 685 blend(Sca, Dca, Sa, Da) = {Dca : if Sa == 0, |
| 686 Sca : if Da == 0, |
| 687 B(Sca/Sa, Dca/Da) * Sa * Da + Sca * (1-Da) + Dc
a * (1-Sa) : if Sa,Da != 0} |
| 688 |
| 689 And for coverage modulation, we use a post blend src-over model: |
| 690 |
| 691 Dca'' = f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca |
| 692 |
| 693 (Where f is the fractional coverage.) |
| 694 |
| 695 Next we show that canTweakAlphaForCoverage() is true by proving the |
| 696 following relationship: |
| 697 |
| 698 blend(f*Sca, Dca, f*Sa, Da) == f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca |
| 699 |
| 700 General case (f,Sa,Da != 0): |
| 701 |
| 702 f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca |
| 703 = f * (B(Sca/Sa, Dca/Da) * Sa * Da + Sca * (1-Da) + Dca * (1-Sa)) + (1-f
) * Dca [Sa,Da != 0, definition of blend()] |
| 704 = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) + f*Dca * (1-Sa) + Dca
- f*Dca |
| 705 = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca - f*Sca * Da + f*Dca - f*Dca * S
a + Dca - f*Dca |
| 706 = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca - f*Sca * Da - f*Dca * Sa + Dca |
| 707 = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) - f*Dca * Sa + Dca |
| 708 = B(Sca/Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) + Dca * (1 - f*Sa) |
| 709 = B(f*Sca/f*Sa, Dca/Da) * f*Sa * Da + f*Sca * (1-Da) + Dca * (1 - f*Sa)
[f!=0] |
| 710 = blend(f*Sca, Dca, f*Sa, Da) [definition of blend()] |
| 711 |
| 712 Corner cases (Sa=0, Da=0, and f=0): |
| 713 |
| 714 Sa=0: f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca |
| 715 = f * Dca + (1-f) * Dca [Sa=0, definition of blend()] |
| 716 = Dca |
| 717 = blend(0, Dca, 0, Da) [definition of blend()] |
| 718 = blend(f*Sca, Dca, f*Sa, Da) [Sa=0] |
| 719 |
| 720 Da=0: f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca |
| 721 = f * Sca + (1-f) * Dca [Da=0, definition of blend()] |
| 722 = f * Sca [Da=0] |
| 723 = blend(f*Sca, 0, f*Sa, 0) [definition of blend()] |
| 724 = blend(f*Sca, Dca, f*Sa, Da) [Da=0] |
| 725 |
| 726 f=0: f * blend(Sca, Dca, Sa, Da) + (1-f) * Dca |
| 727 = Dca [f=0] |
| 728 = blend(0, Dca, 0, Da) [definition of blend()] |
| 729 = blend(f*Sca, Dca, f*Sa, Da) [f=0] |
| 730 |
| 731 == Alpha == |
| 732 |
| 733 We substitute X=Y=Z=1 and define a blend() function that calculates Da': |
| 734 |
| 735 blend(Sa, Da) = Sa * Da + Sa * (1-Da) + Da * (1-Sa) |
| 736 = Sa * Da + Sa - Sa * Da + Da - Da * Sa |
| 737 = Sa + Da - Sa * Da |
| 738 |
| 739 We use the same model for coverage modulation as we did with color: |
| 740 |
| 741 Da'' = f * blend(Sa, Da) + (1-f) * Da |
| 742 |
| 743 And show that canTweakAlphaForCoverage() is true by proving the following |
| 744 relationship: |
| 745 |
| 746 blend(f*Sa, Da) == f * blend(Sa, Da) + (1-f) * Da |
| 747 |
| 748 |
| 749 f * blend(Sa, Da) + (1-f) * Da |
| 750 = f * (Sa + Da - Sa * Da) + (1-f) * Da |
| 751 = f*Sa + f*Da - f*Sa * Da + Da - f*Da |
| 752 = f*Sa - f*Sa * Da + Da |
| 753 = f*Sa + Da - f*Sa * Da |
| 754 = blend(f*Sa, Da) |
| 755 */ |
| 756 |
| 757 OptFlags flags = kNone_Opt; |
| 758 if (colorPOI.allStagesMultiplyInput()) { |
| 759 flags = flags | kCanTweakAlphaForCoverage_OptFlag; |
| 760 } |
| 761 if (coveragePOI.isSolidWhite()) { |
| 762 flags = flags | kIgnoreCoverage_OptFlag; |
| 763 fHasCoverage = false; |
| 764 } |
| 765 if (caps.advancedBlendEquationSupport() && !coveragePOI.isFourChannelOutput(
)) { |
| 766 // This blend mode can be implemented in hardware. |
| 767 fHWBlendEquation = hw_blend_equation(fMode); |
| 768 } |
| 769 return flags; |
| 770 } |
| 771 |
| 772 bool CustomXP::onWillNeedXferBarrier(const GrRenderTarget* rt, |
| 773 const GrDrawTargetCaps& caps, |
| 774 GrXferBarrierType* outBarrierType) const { |
| 775 if (this->hasHWBlendEquation() && !caps.advancedCoherentBlendEquationSupport
()) { |
| 776 *outBarrierType = kBlend_GrXferBarrierType; |
| 777 return true; |
| 778 } |
| 779 return false; |
| 780 } |
| 781 |
| 782 void CustomXP::onGetBlendInfo(BlendInfo* blendInfo) const { |
| 783 if (this->hasHWBlendEquation()) { |
| 784 blendInfo->fEquation = this->hwBlendEquation(); |
| 785 } |
595 } | 786 } |
596 | 787 |
597 /////////////////////////////////////////////////////////////////////////////// | 788 /////////////////////////////////////////////////////////////////////////////// |
598 | 789 |
599 GrCustomXPFactory::GrCustomXPFactory(SkXfermode::Mode mode) | 790 GrCustomXPFactory::GrCustomXPFactory(SkXfermode::Mode mode) |
600 : fMode(mode) { | 791 : fMode(mode) { |
601 this->initClassID<GrCustomXPFactory>(); | 792 this->initClassID<GrCustomXPFactory>(); |
602 } | 793 } |
603 | 794 |
604 GrXferProcessor* | 795 GrXferProcessor* |
605 GrCustomXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps, | 796 GrCustomXPFactory::onCreateXferProcessor(const GrDrawTargetCaps& caps, |
606 const GrProcOptInfo& colorPOI, | 797 const GrProcOptInfo& colorPOI, |
607 const GrProcOptInfo& coveragePOI, | 798 const GrProcOptInfo& coveragePOI, |
608 const GrDeviceCoordTexture* dstCopy) co
nst { | 799 const GrDeviceCoordTexture* dstCopy) co
nst { |
609 return CustomXP::Create(fMode, dstCopy, this->willReadDstColor(caps, colorPO
I, coveragePOI)); | 800 return CustomXP::Create(fMode, dstCopy, this->willReadDstColor(caps, colorPO
I, coveragePOI)); |
610 } | 801 } |
611 | 802 |
| 803 bool GrCustomXPFactory::willReadDstColor(const GrDrawTargetCaps& caps, |
| 804 const GrProcOptInfo& colorPOI, |
| 805 const GrProcOptInfo& coveragePOI) const
{ |
| 806 if (!caps.advancedBlendEquationSupport()) { |
| 807 // No hardware support for advanced blend equations; we will need to do
it in the shader. |
| 808 return true; |
| 809 } |
| 810 if (coveragePOI.isFourChannelOutput()) { |
| 811 // Advanced blend equations can't tweak alpha for RGB coverage. |
| 812 return true; |
| 813 } |
| 814 return false; |
| 815 } |
612 | 816 |
613 void GrCustomXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, | 817 void GrCustomXPFactory::getInvariantOutput(const GrProcOptInfo& colorPOI, |
614 const GrProcOptInfo& coveragePOI, | 818 const GrProcOptInfo& coveragePOI, |
615 GrXPFactory::InvariantOutput* out
put) const { | 819 GrXPFactory::InvariantOutput* out
put) const { |
616 output->fWillBlendWithDst = true; | 820 output->fWillBlendWithDst = true; |
617 output->fBlendedColorFlags = 0; | 821 output->fBlendedColorFlags = 0; |
618 } | 822 } |
619 | 823 |
620 GR_DEFINE_XP_FACTORY_TEST(GrCustomXPFactory); | 824 GR_DEFINE_XP_FACTORY_TEST(GrCustomXPFactory); |
621 GrXPFactory* GrCustomXPFactory::TestCreate(SkRandom* rand, | 825 GrXPFactory* GrCustomXPFactory::TestCreate(SkRandom* rand, |
622 GrContext*, | 826 GrContext*, |
623 const GrDrawTargetCaps&, | 827 const GrDrawTargetCaps&, |
624 GrTexture*[]) { | 828 GrTexture*[]) { |
625 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLas
tSeparableMode); | 829 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLas
tSeparableMode); |
626 | 830 |
627 return SkNEW_ARGS(GrCustomXPFactory, (static_cast<SkXfermode::Mode>(mode))); | 831 return SkNEW_ARGS(GrCustomXPFactory, (static_cast<SkXfermode::Mode>(mode))); |
628 } | 832 } |
629 | 833 |
OLD | NEW |