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