| 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 |