Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: src/gpu/effects/GrPorterDuffXferProcessor.cpp

Issue 1164973002: Add mixed samples support to XPs (Closed) Base URL: https://skia.googlesource.com/skia.git@upload2_reenablebea
Patch Set: Created 5 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright 2014 Google Inc. 2 * Copyright 2014 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/GrPorterDuffXferProcessor.h" 8 #include "effects/GrPorterDuffXferProcessor.h"
9 9
10 #include "GrBlend.h" 10 #include "GrBlend.h"
11 #include "GrCaps.h" 11 #include "GrCaps.h"
12 #include "GrPipelineBuilder.h"
12 #include "GrProcessor.h" 13 #include "GrProcessor.h"
13 #include "GrProcOptInfo.h" 14 #include "GrProcOptInfo.h"
14 #include "GrTypes.h" 15 #include "GrTypes.h"
15 #include "GrXferProcessor.h" 16 #include "GrXferProcessor.h"
16 #include "gl/GrGLXferProcessor.h" 17 #include "gl/GrGLXferProcessor.h"
17 #include "gl/builders/GrGLFragmentShaderBuilder.h" 18 #include "gl/builders/GrGLFragmentShaderBuilder.h"
18 #include "gl/builders/GrGLProgramBuilder.h" 19 #include "gl/builders/GrGLProgramBuilder.h"
19 20
20 /** 21 /**
21 * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage. 22 * Wraps the shader outputs and HW blend state that comprise a Porter Duff blend mode with coverage.
(...skipping 259 matching lines...) Expand 10 before | Expand all | Expand 10 after
281 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 282 /* src-out */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
282 /* dst-out */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_Out putType), 283 /* dst-out */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kCoverage_Out putType),
283 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff), 284 /* src-atop */ COEFF_FORMULA( kDA_GrBlendCoeff, kISA_GrBlendCoeff),
284 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff), 285 /* dst-atop */ COEFF_FORMULA( kIDA_GrBlendCoeff, kOne_GrBlendCoeff),
285 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff), 286 /* xor */ COEFF_FORMULA( kIDA_GrBlendCoeff, kISA_GrBlendCoeff),
286 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff), 287 /* plus */ COEFF_FORMULA( kOne_GrBlendCoeff, kOne_GrBlendCoeff),
287 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_ OutputType), 288 /* modulate */ COVERAGE_SRC_COEFF_ZERO_FORMULA(BlendFormula::kISCModulate_ OutputType),
288 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff), 289 /* screen */ COEFF_FORMULA( kOne_GrBlendCoeff, kISC_GrBlendCoeff),
289 }}}; 290 }}};
290 291
291 static BlendFormula get_blend_formula(SkXfermode::Mode xfermode, 292 static BlendFormula get_blend_formula(const GrPipelineBuilder& builder,
292 const GrProcOptInfo& colorPOI, 293 const GrProcOptInfo& colorPOI,
293 const GrProcOptInfo& coveragePOI) { 294 const GrProcOptInfo& coveragePOI,
295 SkXfermode::Mode xfermode) {
294 SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode); 296 SkASSERT(xfermode >= 0 && xfermode <= SkXfermode::kLastCoeffMode);
295 SkASSERT(!coveragePOI.isFourChannelOutput()); 297 SkASSERT(!coveragePOI.isFourChannelOutput());
296 298
297 return gBlendTable[colorPOI.isOpaque()][!coveragePOI.isSolidWhite()][xfermod e]; 299 bool conflatesCoverage = !coveragePOI.isSolidWhite() || builder.hasMixedSamp les();
300 return gBlendTable[colorPOI.isOpaque()][conflatesCoverage][xfermode];
298 } 301 }
299 302
300 /////////////////////////////////////////////////////////////////////////////// 303 ///////////////////////////////////////////////////////////////////////////////
301 304
302 class PorterDuffXferProcessor : public GrXferProcessor { 305 class PorterDuffXferProcessor : public GrXferProcessor {
303 public: 306 public:
304 static GrXferProcessor* Create(BlendFormula blendFormula) { 307 PorterDuffXferProcessor(BlendFormula blendFormula) : fBlendFormula(blendForm ula) {
305 return SkNEW_ARGS(PorterDuffXferProcessor, (blendFormula)); 308 this->initClassID<PorterDuffXferProcessor>();
306 } 309 }
307 310
308 const char* name() const override { return "Porter Duff"; } 311 const char* name() const override { return "Porter Duff"; }
309 bool hasSecondaryOutput() const override { return fBlendFormula.hasSecondary Output(); }
310 312
311 GrGLXferProcessor* createGLInstance() const override; 313 GrGLXferProcessor* createGLInstance() const override;
312 314
313 BlendFormula getBlendFormula() const { return fBlendFormula; } 315 BlendFormula getBlendFormula() const { return fBlendFormula; }
314 316
315 private: 317 private:
316 PorterDuffXferProcessor(BlendFormula blendFormula) : fBlendFormula(blendForm ula) {
317 this->initClassID<PorterDuffXferProcessor>();
318 }
319
320 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, 318 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
321 const GrProcOptInfo& coveragePO I, 319 const GrProcOptInfo& coveragePO I,
322 bool doesStencilWrite, 320 bool doesStencilWrite,
323 GrColor* overrideColor, 321 GrColor* overrideColor,
324 const GrCaps& caps) override; 322 const GrCaps& caps) override;
325 323
326 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override; 324 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override;
327 325
326 bool onHasSecondaryOutput() const override { return fBlendFormula.hasSeconda ryOutput(); }
327
328 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { 328 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override {
329 blendInfo->fEquation = fBlendFormula.fBlendEquation; 329 blendInfo->fEquation = fBlendFormula.fBlendEquation;
330 blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff; 330 blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff;
331 blendInfo->fDstBlend = fBlendFormula.fDstCoeff; 331 blendInfo->fDstBlend = fBlendFormula.fDstCoeff;
332 blendInfo->fWriteColor = fBlendFormula.modifiesDst(); 332 blendInfo->fWriteColor = fBlendFormula.modifiesDst();
333 } 333 }
334 334
335 bool onIsEqual(const GrXferProcessor& xpBase) const override { 335 bool onIsEqual(const GrXferProcessor& xpBase) const override {
336 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor> (); 336 const PorterDuffXferProcessor& xp = xpBase.cast<PorterDuffXferProcessor> ();
337 return fBlendFormula == xp.fBlendFormula; 337 return fBlendFormula == xp.fBlendFormula;
338 } 338 }
339 339
340 const BlendFormula fBlendFormula; 340 const BlendFormula fBlendFormula;
341 341
342 typedef GrXferProcessor INHERITED; 342 typedef GrXferProcessor INHERITED;
343 }; 343 };
344 344
345 /////////////////////////////////////////////////////////////////////////////// 345 ///////////////////////////////////////////////////////////////////////////////
346 346
347 static void append_color_output(const PorterDuffXferProcessor& xp, GrGLXPFragmen tBuilder* fsBuilder, 347 static void append_color_output(const PorterDuffXferProcessor& xp, GrGLXPFragmen tBuilder* fsBuilder,
348 BlendFormula::OutputType outputType, const char* output, 348 BlendFormula::OutputType outputType, const char* output,
349 const char* inColor, const char* inCoverage) { 349 const char* inColor, const char* inCoverage) {
350 switch (outputType) { 350 switch (outputType) {
351 case BlendFormula::kNone_OutputType: 351 case BlendFormula::kNone_OutputType:
352 fsBuilder->codeAppendf("%s = vec4(0.0);", output); 352 fsBuilder->codeAppendf("%s = vec4(0.0);", output);
353 break; 353 break;
354 case BlendFormula::kCoverage_OutputType: 354 case BlendFormula::kCoverage_OutputType:
355 // We can have a coverage formula while not reading coverage if ther e are mixed samples.
355 fsBuilder->codeAppendf("%s = %s;", 356 fsBuilder->codeAppendf("%s = %s;",
356 output, xp.readsCoverage() ? inCoverage : "ve c4(1.0)"); 357 output, xp.readsCoverage() ? inCoverage : "ve c4(1.0)");
357 break; 358 break;
358 case BlendFormula::kModulate_OutputType: 359 case BlendFormula::kModulate_OutputType:
359 if (xp.readsCoverage()) { 360 if (xp.readsCoverage()) {
360 fsBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCover age); 361 fsBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCover age);
361 } else { 362 } else {
362 fsBuilder->codeAppendf("%s = %s;", output, inColor); 363 fsBuilder->codeAppendf("%s = %s;", output, inColor);
363 } 364 }
364 break; 365 break;
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after
447 optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag; 448 optFlags |= GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag;
448 } 449 }
449 } 450 }
450 return optFlags; 451 return optFlags;
451 } 452 }
452 453
453 /////////////////////////////////////////////////////////////////////////////// 454 ///////////////////////////////////////////////////////////////////////////////
454 455
455 class ShaderPDXferProcessor : public GrXferProcessor { 456 class ShaderPDXferProcessor : public GrXferProcessor {
456 public: 457 public:
457 static GrXferProcessor* Create(SkXfermode::Mode xfermode, const DstTexture* dstTexture) { 458 ShaderPDXferProcessor(const GrPipelineBuilder& builder,
458 return SkNEW_ARGS(ShaderPDXferProcessor, (xfermode, dstTexture)); 459 const DstTexture* dstTexture,
460 SkXfermode::Mode xfermode)
461 : INHERITED(builder, dstTexture, true)
462 , fXfermode(xfermode) {
463 this->initClassID<ShaderPDXferProcessor>();
459 } 464 }
460 465
461 const char* name() const override { return "Porter Duff Shader"; } 466 const char* name() const override { return "Porter Duff Shader"; }
462 bool hasSecondaryOutput() const override { return false; }
463 467
464 GrGLXferProcessor* createGLInstance() const override; 468 GrGLXferProcessor* createGLInstance() const override;
465 469
466 SkXfermode::Mode getXfermode() const { return fXfermode; } 470 SkXfermode::Mode getXfermode() const { return fXfermode; }
467 471
468 private: 472 private:
469 ShaderPDXferProcessor(SkXfermode::Mode xfermode, const DstTexture* dstTextur e)
470 : INHERITED(dstTexture, true)
471 , fXfermode(xfermode) {
472 this->initClassID<ShaderPDXferProcessor>();
473 }
474
475 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo&, const GrP rocOptInfo&, 473 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo&, const GrP rocOptInfo&,
476 bool, GrColor*, const GrCaps&) override { 474 bool, GrColor*, const GrCaps&) override {
477 return kNone_Opt; 475 return kNone_Opt;
478 } 476 }
479 477
480 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override; 478 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override;
481 479
482 bool onIsEqual(const GrXferProcessor& xpBase) const override { 480 bool onIsEqual(const GrXferProcessor& xpBase) const override {
483 const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>(); 481 const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>();
484 return fXfermode == xp.fXfermode; 482 return fXfermode == xp.fXfermode;
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 class PDLCDXferProcessor : public GrXferProcessor { 587 class PDLCDXferProcessor : public GrXferProcessor {
590 public: 588 public:
591 static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrProcOptInf o& colorPOI); 589 static GrXferProcessor* Create(SkXfermode::Mode xfermode, const GrProcOptInf o& colorPOI);
592 590
593 ~PDLCDXferProcessor() override; 591 ~PDLCDXferProcessor() override;
594 592
595 const char* name() const override { return "Porter Duff LCD"; } 593 const char* name() const override { return "Porter Duff LCD"; }
596 594
597 GrGLXferProcessor* createGLInstance() const override; 595 GrGLXferProcessor* createGLInstance() const override;
598 596
599 bool hasSecondaryOutput() const override { return false; }
600
601 private: 597 private:
602 PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha); 598 PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha);
603 599
604 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, 600 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI,
605 const GrProcOptInfo& coveragePO I, 601 const GrProcOptInfo& coveragePO I,
606 bool doesStencilWrite, 602 bool doesStencilWrite,
607 GrColor* overrideColor, 603 GrColor* overrideColor,
608 const GrCaps& caps) override; 604 const GrCaps& caps) override;
609 605
610 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override; 606 void onGetGLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b) c onst override;
(...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after
738 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == SkXfermode::kLastCoeffMode + 1); 734 GR_STATIC_ASSERT(SK_ARRAY_COUNT(gFactories) == SkXfermode::kLastCoeffMode + 1);
739 735
740 if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) { 736 if (xfermode < 0 || xfermode > SkXfermode::kLastCoeffMode) {
741 return NULL; 737 return NULL;
742 } 738 }
743 return SkRef(gFactories[xfermode]); 739 return SkRef(gFactories[xfermode]);
744 } 740 }
745 741
746 GrXferProcessor* 742 GrXferProcessor*
747 GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps, 743 GrPorterDuffXPFactory::onCreateXferProcessor(const GrCaps& caps,
744 const GrPipelineBuilder& builder,
748 const GrProcOptInfo& colorPOI, 745 const GrProcOptInfo& colorPOI,
749 const GrProcOptInfo& covPOI, 746 const GrProcOptInfo& covPOI,
750 const DstTexture* dstTexture) const { 747 const DstTexture* dstTexture) const {
751 if (covPOI.isFourChannelOutput()) { 748 if (covPOI.isFourChannelOutput()) {
752 SkASSERT(!dstTexture || !dstTexture->texture()); 749 SkASSERT(!dstTexture || !dstTexture->texture());
753 return PDLCDXferProcessor::Create(fXfermode, colorPOI); 750 return PDLCDXferProcessor::Create(fXfermode, colorPOI);
754 } 751 }
755 752
756 BlendFormula blendFormula = get_blend_formula(fXfermode, colorPOI, covPOI); 753 BlendFormula blendFormula = get_blend_formula(builder, colorPOI, covPOI, fXf ermode);
757 if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlend ingSupport()) { 754 if (blendFormula.hasSecondaryOutput() && !caps.shaderCaps()->dualSourceBlend ingSupport()) {
758 return ShaderPDXferProcessor::Create(fXfermode, dstTexture); 755 return SkNEW_ARGS(ShaderPDXferProcessor, (builder, dstTexture, fXfermode ));
759 } 756 }
760 757
761 SkASSERT(!dstTexture || !dstTexture->texture()); 758 SkASSERT(!dstTexture || !dstTexture->texture());
762 return PorterDuffXferProcessor::Create(blendFormula); 759 return SkNEW_ARGS(PorterDuffXferProcessor, (blendFormula));
763 } 760 }
764 761
765 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/, 762 bool GrPorterDuffXPFactory::supportsRGBCoverage(GrColor /*knownColor*/,
766 uint32_t knownColorFlags) const { 763 uint32_t knownColorFlags) const {
767 if (SkXfermode::kSrcOver_Mode == fXfermode && 764 if (SkXfermode::kSrcOver_Mode == fXfermode &&
768 kRGBA_GrColorComponentFlags == knownColorFlags) { 765 kRGBA_GrColorComponentFlags == knownColorFlags) {
769 return true; 766 return true;
770 } 767 }
771 return false; 768 return false;
772 } 769 }
(...skipping 23 matching lines...) Expand all
796 blendedColor->fKnownColorFlags = colorPOI.validFlags(); 793 blendedColor->fKnownColorFlags = colorPOI.validFlags();
797 return; 794 return;
798 795
799 default: 796 default:
800 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags; 797 blendedColor->fKnownColorFlags = kNone_GrColorComponentFlags;
801 return; 798 return;
802 } 799 }
803 } 800 }
804 801
805 bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps, 802 bool GrPorterDuffXPFactory::willReadDstColor(const GrCaps& caps,
803 const GrPipelineBuilder& builder,
806 const GrProcOptInfo& colorPOI, 804 const GrProcOptInfo& colorPOI,
807 const GrProcOptInfo& coveragePOI) c onst { 805 const GrProcOptInfo& coveragePOI) c onst {
806 if (caps.shaderCaps()->dualSourceBlendingSupport()) {
807 return false;
808 }
808 if (coveragePOI.isFourChannelOutput()) { 809 if (coveragePOI.isFourChannelOutput()) {
809 return false; // The LCD XP never does a dst read. 810 return false; // The LCD XP will abort rather than doing a dst read.
810 } 811 }
811
812 // We fallback on the shader XP when the blend formula would use dual source blending but we 812 // We fallback on the shader XP when the blend formula would use dual source blending but we
813 // don't have support for it. 813 // don't have support for it.
814 return !caps.shaderCaps()->dualSourceBlendingSupport() && 814 return get_blend_formula(builder, colorPOI, coveragePOI, fXfermode).hasSecon daryOutput();
815 get_blend_formula(fXfermode, colorPOI, coveragePOI).hasSecondaryOutpu t();
816 } 815 }
817 816
818 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory); 817 GR_DEFINE_XP_FACTORY_TEST(GrPorterDuffXPFactory);
819 818
820 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random, 819 GrXPFactory* GrPorterDuffXPFactory::TestCreate(SkRandom* random,
821 GrContext*, 820 GrContext*,
822 const GrCaps&, 821 const GrCaps&,
823 GrTexture*[]) { 822 GrTexture*[]) {
824 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k LastCoeffMode)); 823 SkXfermode::Mode mode = SkXfermode::Mode(random->nextULessThan(SkXfermode::k LastCoeffMode));
825 return GrPorterDuffXPFactory::Create(mode); 824 return GrPorterDuffXPFactory::Create(mode);
826 } 825 }
827 826
828 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp, 827 void GrPorterDuffXPFactory::TestGetXPOutputTypes(const GrXferProcessor* xp,
829 int* outPrimary, 828 int* outPrimary,
830 int* outSecondary) { 829 int* outSecondary) {
831 if (!!strcmp(xp->name(), "Porter Duff")) { 830 if (!!strcmp(xp->name(), "Porter Duff")) {
832 *outPrimary = *outSecondary = -1; 831 *outPrimary = *outSecondary = -1;
833 return; 832 return;
834 } 833 }
835 BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)- >getBlendFormula(); 834 BlendFormula blendFormula = static_cast<const PorterDuffXferProcessor*>(xp)- >getBlendFormula();
836 *outPrimary = blendFormula.fPrimaryOutputType; 835 *outPrimary = blendFormula.fPrimaryOutputType;
837 *outSecondary = blendFormula.fSecondaryOutputType; 836 *outSecondary = blendFormula.fSecondaryOutputType;
838 } 837 }
839 838
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698