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 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
44 GR_STATIC_ASSERT(kDifference_GrBlendEquation == SkXfermode::kDifference_Mode
+ kOffset); | 44 GR_STATIC_ASSERT(kDifference_GrBlendEquation == SkXfermode::kDifference_Mode
+ kOffset); |
45 GR_STATIC_ASSERT(kExclusion_GrBlendEquation == SkXfermode::kExclusion_Mode +
kOffset); | 45 GR_STATIC_ASSERT(kExclusion_GrBlendEquation == SkXfermode::kExclusion_Mode +
kOffset); |
46 GR_STATIC_ASSERT(kMultiply_GrBlendEquation == SkXfermode::kMultiply_Mode + k
Offset); | 46 GR_STATIC_ASSERT(kMultiply_GrBlendEquation == SkXfermode::kMultiply_Mode + k
Offset); |
47 GR_STATIC_ASSERT(kHSLHue_GrBlendEquation == SkXfermode::kHue_Mode + kOffset)
; | 47 GR_STATIC_ASSERT(kHSLHue_GrBlendEquation == SkXfermode::kHue_Mode + kOffset)
; |
48 GR_STATIC_ASSERT(kHSLSaturation_GrBlendEquation == SkXfermode::kSaturation_M
ode + kOffset); | 48 GR_STATIC_ASSERT(kHSLSaturation_GrBlendEquation == SkXfermode::kSaturation_M
ode + kOffset); |
49 GR_STATIC_ASSERT(kHSLColor_GrBlendEquation == SkXfermode::kColor_Mode + kOff
set); | 49 GR_STATIC_ASSERT(kHSLColor_GrBlendEquation == SkXfermode::kColor_Mode + kOff
set); |
50 GR_STATIC_ASSERT(kHSLLuminosity_GrBlendEquation == SkXfermode::kLuminosity_M
ode + kOffset); | 50 GR_STATIC_ASSERT(kHSLLuminosity_GrBlendEquation == SkXfermode::kLuminosity_M
ode + kOffset); |
51 GR_STATIC_ASSERT(kGrBlendEquationCnt == SkXfermode::kLastMode + 1 + kOffset)
; | 51 GR_STATIC_ASSERT(kGrBlendEquationCnt == SkXfermode::kLastMode + 1 + kOffset)
; |
52 } | 52 } |
53 | 53 |
| 54 static bool can_use_hw_blend_equation(GrBlendEquation equation, |
| 55 const GrProcOptInfo& coveragePOI, |
| 56 const GrCaps& caps) { |
| 57 if (!caps.advancedBlendEquationSupport()) { |
| 58 return false; |
| 59 } |
| 60 if (coveragePOI.isFourChannelOutput()) { |
| 61 return false; // LCD coverage must be applied after the blend equation. |
| 62 } |
| 63 if (caps.advancedBlendEquationIsBlacklist(equation)) { |
| 64 return false; |
| 65 } |
| 66 return true; |
| 67 } |
| 68 |
54 static void hard_light(GrGLFragmentBuilder* fsBuilder, | 69 static void hard_light(GrGLFragmentBuilder* fsBuilder, |
55 const char* final, | 70 const char* final, |
56 const char* src, | 71 const char* src, |
57 const char* dst) { | 72 const char* dst) { |
58 static const char kComponents[] = {'r', 'g', 'b'}; | 73 static const char kComponents[] = {'r', 'g', 'b'}; |
59 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { | 74 for (size_t i = 0; i < SK_ARRAY_COUNT(kComponents); ++i) { |
60 char component = kComponents[i]; | 75 char component = kComponents[i]; |
61 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src
); | 76 fsBuilder->codeAppendf("if (2.0 * %s.%c <= %s.a) {", src, component, src
); |
62 fsBuilder->codeAppendf("%s.%c = 2.0 * %s.%c * %s.%c;", | 77 fsBuilder->codeAppendf("%s.%c = 2.0 * %s.%c * %s.%c;", |
63 final, component, src, component, dst, component)
; | 78 final, component, src, component, dst, component)
; |
(...skipping 437 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
501 | 516 |
502 return SkNEW_ARGS(GrCustomXferFP, (static_cast<SkXfermode::Mode>(mode), text
ures[0])); | 517 return SkNEW_ARGS(GrCustomXferFP, (static_cast<SkXfermode::Mode>(mode), text
ures[0])); |
503 } | 518 } |
504 | 519 |
505 /////////////////////////////////////////////////////////////////////////////// | 520 /////////////////////////////////////////////////////////////////////////////// |
506 // Xfer Processor | 521 // Xfer Processor |
507 /////////////////////////////////////////////////////////////////////////////// | 522 /////////////////////////////////////////////////////////////////////////////// |
508 | 523 |
509 class CustomXP : public GrXferProcessor { | 524 class CustomXP : public GrXferProcessor { |
510 public: | 525 public: |
511 static GrXferProcessor* Create(SkXfermode::Mode mode, const DstTexture* dstT
exture, | 526 CustomXP(SkXfermode::Mode mode, GrBlendEquation hwBlendEquation) |
512 bool willReadDstColor) { | 527 : fMode(mode), |
513 if (!GrCustomXfermode::IsSupportedMode(mode)) { | 528 fHWBlendEquation(hwBlendEquation) { |
514 return NULL; | 529 this->initClassID<CustomXP>(); |
515 } else { | |
516 return SkNEW_ARGS(CustomXP, (mode, dstTexture, willReadDstColor)); | |
517 } | |
518 } | 530 } |
519 | 531 |
520 ~CustomXP() override {}; | 532 CustomXP(SkXfermode::Mode mode, const DstTexture* dstTexture) |
| 533 : INHERITED(dstTexture, true), |
| 534 fMode(mode), |
| 535 fHWBlendEquation(static_cast<GrBlendEquation>(-1)) { |
| 536 this->initClassID<CustomXP>(); |
| 537 } |
521 | 538 |
522 const char* name() const override { return "Custom Xfermode"; } | 539 const char* name() const override { return "Custom Xfermode"; } |
523 | 540 |
524 GrGLXferProcessor* createGLInstance() const override; | 541 GrGLXferProcessor* createGLInstance() const override; |
525 | 542 |
526 bool hasSecondaryOutput() const override { return false; } | 543 bool hasSecondaryOutput() const override { return false; } |
527 | 544 |
528 SkXfermode::Mode mode() const { return fMode; } | 545 SkXfermode::Mode mode() const { return fMode; } |
529 bool hasHWBlendEquation() const { return -1 != static_cast<int>(fHWBlendEqua
tion); } | 546 bool hasHWBlendEquation() const { return -1 != static_cast<int>(fHWBlendEqua
tion); } |
530 | 547 |
531 GrBlendEquation hwBlendEquation() const { | 548 GrBlendEquation hwBlendEquation() const { |
532 SkASSERT(this->hasHWBlendEquation()); | 549 SkASSERT(this->hasHWBlendEquation()); |
533 return fHWBlendEquation; | 550 return fHWBlendEquation; |
534 } | 551 } |
535 | 552 |
536 private: | 553 private: |
537 CustomXP(SkXfermode::Mode mode, const DstTexture*, bool willReadDstColor); | |
538 | |
539 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, | 554 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, |
540 const GrProcOptInfo& coveragePO
I, | 555 const GrProcOptInfo& coveragePO
I, |
541 bool doesStencilWrite, | 556 bool doesStencilWrite, |
542 GrColor* overrideColor, | 557 GrColor* overrideColor, |
543 const GrCaps& caps) override; | 558 const GrCaps& caps) override; |
544 | 559 |
545 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override; | 560 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c
onst override; |
546 | 561 |
547 bool onWillNeedXferBarrier(const GrRenderTarget* rt, | 562 bool onWillNeedXferBarrier(const GrRenderTarget* rt, |
548 const GrCaps& caps, | 563 const GrCaps& caps, |
549 GrXferBarrierType* outBarrierType) const override
; | 564 GrXferBarrierType* outBarrierType) const override
; |
550 | 565 |
551 void onGetBlendInfo(BlendInfo*) const override; | 566 void onGetBlendInfo(BlendInfo*) const override; |
552 | 567 |
553 bool onIsEqual(const GrXferProcessor& xpBase) const override; | 568 bool onIsEqual(const GrXferProcessor& xpBase) const override; |
554 | 569 |
555 SkXfermode::Mode fMode; | 570 const SkXfermode::Mode fMode; |
556 GrBlendEquation fHWBlendEquation; | 571 const GrBlendEquation fHWBlendEquation; |
557 | 572 |
558 typedef GrXferProcessor INHERITED; | 573 typedef GrXferProcessor INHERITED; |
559 }; | 574 }; |
560 | 575 |
561 /////////////////////////////////////////////////////////////////////////////// | 576 /////////////////////////////////////////////////////////////////////////////// |
562 | 577 |
563 GrXPFactory* GrCustomXfermode::CreateXPFactory(SkXfermode::Mode mode) { | 578 GrXPFactory* GrCustomXfermode::CreateXPFactory(SkXfermode::Mode mode) { |
564 if (!GrCustomXfermode::IsSupportedMode(mode)) { | 579 if (!GrCustomXfermode::IsSupportedMode(mode)) { |
565 return NULL; | 580 return NULL; |
566 } else { | 581 } else { |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
619 } | 634 } |
620 } | 635 } |
621 | 636 |
622 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri
de {} | 637 void onSetData(const GrGLProgramDataManager&, const GrXferProcessor&) overri
de {} |
623 | 638 |
624 typedef GrGLFragmentProcessor INHERITED; | 639 typedef GrGLFragmentProcessor INHERITED; |
625 }; | 640 }; |
626 | 641 |
627 /////////////////////////////////////////////////////////////////////////////// | 642 /////////////////////////////////////////////////////////////////////////////// |
628 | 643 |
629 CustomXP::CustomXP(SkXfermode::Mode mode, const DstTexture* dstTexture, bool wil
lReadDstColor) | |
630 : INHERITED(dstTexture, willReadDstColor), | |
631 fMode(mode), | |
632 fHWBlendEquation(static_cast<GrBlendEquation>(-1)) { | |
633 this->initClassID<CustomXP>(); | |
634 } | |
635 | |
636 void CustomXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder
* b) const { | 644 void CustomXP::onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder
* b) const { |
637 GLCustomXP::GenKey(*this, caps, b); | 645 GLCustomXP::GenKey(*this, caps, b); |
638 } | 646 } |
639 | 647 |
640 GrGLXferProcessor* CustomXP::createGLInstance() const { | 648 GrGLXferProcessor* CustomXP::createGLInstance() const { |
641 SkASSERT(this->willReadDstColor() != this->hasHWBlendEquation()); | 649 SkASSERT(this->willReadDstColor() != this->hasHWBlendEquation()); |
642 return SkNEW_ARGS(GLCustomXP, (*this)); | 650 return SkNEW_ARGS(GLCustomXP, (*this)); |
643 } | 651 } |
644 | 652 |
645 bool CustomXP::onIsEqual(const GrXferProcessor& other) const { | 653 bool CustomXP::onIsEqual(const GrXferProcessor& other) const { |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
748 = blend(f*Sa, Da) | 756 = blend(f*Sa, Da) |
749 */ | 757 */ |
750 | 758 |
751 OptFlags flags = kNone_Opt; | 759 OptFlags flags = kNone_Opt; |
752 if (colorPOI.allStagesMultiplyInput()) { | 760 if (colorPOI.allStagesMultiplyInput()) { |
753 flags |= kCanTweakAlphaForCoverage_OptFlag; | 761 flags |= kCanTweakAlphaForCoverage_OptFlag; |
754 } | 762 } |
755 if (coveragePOI.isSolidWhite()) { | 763 if (coveragePOI.isSolidWhite()) { |
756 flags |= kIgnoreCoverage_OptFlag; | 764 flags |= kIgnoreCoverage_OptFlag; |
757 } | 765 } |
758 if (caps.advancedBlendEquationSupport() && !coveragePOI.isFourChannelOutput(
)) { | |
759 // This blend mode can be implemented in hardware. | |
760 fHWBlendEquation = hw_blend_equation(fMode); | |
761 } | |
762 return flags; | 766 return flags; |
763 } | 767 } |
764 | 768 |
765 bool CustomXP::onWillNeedXferBarrier(const GrRenderTarget* rt, | 769 bool CustomXP::onWillNeedXferBarrier(const GrRenderTarget* rt, |
766 const GrCaps& caps, | 770 const GrCaps& caps, |
767 GrXferBarrierType* outBarrierType) const { | 771 GrXferBarrierType* outBarrierType) const { |
768 if (this->hasHWBlendEquation() && !caps.advancedCoherentBlendEquationSupport
()) { | 772 if (this->hasHWBlendEquation() && !caps.advancedCoherentBlendEquationSupport
()) { |
769 *outBarrierType = kBlend_GrXferBarrierType; | 773 *outBarrierType = kBlend_GrXferBarrierType; |
770 return true; | 774 return true; |
771 } | 775 } |
772 return false; | 776 return false; |
773 } | 777 } |
774 | 778 |
775 void CustomXP::onGetBlendInfo(BlendInfo* blendInfo) const { | 779 void CustomXP::onGetBlendInfo(BlendInfo* blendInfo) const { |
776 if (this->hasHWBlendEquation()) { | 780 if (this->hasHWBlendEquation()) { |
777 blendInfo->fEquation = this->hwBlendEquation(); | 781 blendInfo->fEquation = this->hwBlendEquation(); |
778 } | 782 } |
779 } | 783 } |
780 | 784 |
781 /////////////////////////////////////////////////////////////////////////////// | 785 /////////////////////////////////////////////////////////////////////////////// |
782 | 786 |
783 GrCustomXPFactory::GrCustomXPFactory(SkXfermode::Mode mode) | 787 GrCustomXPFactory::GrCustomXPFactory(SkXfermode::Mode mode) |
784 : fMode(mode) { | 788 : fMode(mode), |
| 789 fHWBlendEquation(hw_blend_equation(mode)) { |
| 790 SkASSERT(GrCustomXfermode::IsSupportedMode(fMode)); |
785 this->initClassID<GrCustomXPFactory>(); | 791 this->initClassID<GrCustomXPFactory>(); |
786 } | 792 } |
787 | 793 |
788 GrXferProcessor* | 794 GrXferProcessor* |
789 GrCustomXPFactory::onCreateXferProcessor(const GrCaps& caps, | 795 GrCustomXPFactory::onCreateXferProcessor(const GrCaps& caps, |
790 const GrProcOptInfo& colorPOI, | 796 const GrProcOptInfo& colorPOI, |
791 const GrProcOptInfo& coveragePOI, | 797 const GrProcOptInfo& coveragePOI, |
792 const DstTexture* dstTexture) const { | 798 const DstTexture* dstTexture) const { |
793 return CustomXP::Create(fMode, dstTexture, this->willReadDstColor(caps, colo
rPOI, coveragePOI)); | 799 if (can_use_hw_blend_equation(fHWBlendEquation, coveragePOI, caps)) { |
| 800 SkASSERT(!dstTexture || !dstTexture->texture()); |
| 801 return SkNEW_ARGS(CustomXP, (fMode, fHWBlendEquation)); |
| 802 } |
| 803 return SkNEW_ARGS(CustomXP, (fMode, dstTexture)); |
794 } | 804 } |
795 | 805 |
796 bool GrCustomXPFactory::willReadDstColor(const GrCaps& caps, | 806 bool GrCustomXPFactory::willReadDstColor(const GrCaps& caps, |
797 const GrProcOptInfo& colorPOI, | 807 const GrProcOptInfo& colorPOI, |
798 const GrProcOptInfo& coveragePOI) const
{ | 808 const GrProcOptInfo& coveragePOI) const
{ |
799 if (!caps.advancedBlendEquationSupport()) { | 809 return !can_use_hw_blend_equation(fHWBlendEquation, coveragePOI, caps); |
800 // No hardware support for advanced blend equations; we will need to do
it in the shader. | |
801 return true; | |
802 } | |
803 if (coveragePOI.isFourChannelOutput()) { | |
804 // Advanced blend equations can't tweak alpha for RGB coverage. | |
805 return true; | |
806 } | |
807 return false; | |
808 } | 810 } |
809 | 811 |
810 void GrCustomXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI, | 812 void GrCustomXPFactory::getInvariantBlendedColor(const GrProcOptInfo& colorPOI, |
811 InvariantBlendedColor* blendedC
olor) const { | 813 InvariantBlendedColor* blendedC
olor) const { |
812 blendedColor->fWillBlendWithDst = true; | 814 blendedColor->fWillBlendWithDst = true; |
813 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; | 815 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; |
814 } | 816 } |
815 | 817 |
816 GR_DEFINE_XP_FACTORY_TEST(GrCustomXPFactory); | 818 GR_DEFINE_XP_FACTORY_TEST(GrCustomXPFactory); |
817 GrXPFactory* GrCustomXPFactory::TestCreate(SkRandom* rand, | 819 GrXPFactory* GrCustomXPFactory::TestCreate(SkRandom* rand, |
818 GrContext*, | 820 GrContext*, |
819 const GrCaps&, | 821 const GrCaps&, |
820 GrTexture*[]) { | 822 GrTexture*[]) { |
821 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLas
tSeparableMode); | 823 int mode = rand->nextRangeU(SkXfermode::kLastCoeffMode + 1, SkXfermode::kLas
tSeparableMode); |
822 | 824 |
823 return SkNEW_ARGS(GrCustomXPFactory, (static_cast<SkXfermode::Mode>(mode))); | 825 return SkNEW_ARGS(GrCustomXPFactory, (static_cast<SkXfermode::Mode>(mode))); |
824 } | 826 } |
825 | 827 |
OLD | NEW |