OLD | NEW |
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" |
(...skipping 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
349 | 349 |
350 GrGLSLXferProcessor* createGLSLInstance() const override; | 350 GrGLSLXferProcessor* createGLSLInstance() const override; |
351 | 351 |
352 BlendFormula getBlendFormula() const { return fBlendFormula; } | 352 BlendFormula getBlendFormula() const { return fBlendFormula; } |
353 | 353 |
354 private: | 354 private: |
355 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, | 355 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, |
356 const GrProcOptInfo& coveragePO
I, | 356 const GrProcOptInfo& coveragePO
I, |
357 bool doesStencilWrite, | 357 bool doesStencilWrite, |
358 GrColor* overrideColor, | 358 GrColor* overrideColor, |
359 const GrCaps& caps) override; | 359 const GrCaps& caps) const overr
ide; |
360 | 360 |
361 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override; | 361 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override; |
362 | 362 |
363 bool onHasSecondaryOutput() const override { return fBlendFormula.hasSeconda
ryOutput(); } | 363 bool onHasSecondaryOutput() const override { return fBlendFormula.hasSeconda
ryOutput(); } |
364 | 364 |
365 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { | 365 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { |
366 blendInfo->fEquation = fBlendFormula.fBlendEquation; | 366 blendInfo->fEquation = fBlendFormula.fBlendEquation; |
367 blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff; | 367 blendInfo->fSrcBlend = fBlendFormula.fSrcCoeff; |
368 blendInfo->fDstBlend = fBlendFormula.fDstCoeff; | 368 blendInfo->fDstBlend = fBlendFormula.fDstCoeff; |
369 blendInfo->fWriteColor = fBlendFormula.modifiesDst(); | 369 blendInfo->fWriteColor = fBlendFormula.modifiesDst(); |
(...skipping 14 matching lines...) Expand all Loading... |
384 static void append_color_output(const PorterDuffXferProcessor& xp, | 384 static void append_color_output(const PorterDuffXferProcessor& xp, |
385 GrGLSLXPFragmentBuilder* fragBuilder, | 385 GrGLSLXPFragmentBuilder* fragBuilder, |
386 BlendFormula::OutputType outputType, const char*
output, | 386 BlendFormula::OutputType outputType, const char*
output, |
387 const char* inColor, const char* inCoverage) { | 387 const char* inColor, const char* inCoverage) { |
388 switch (outputType) { | 388 switch (outputType) { |
389 case BlendFormula::kNone_OutputType: | 389 case BlendFormula::kNone_OutputType: |
390 fragBuilder->codeAppendf("%s = vec4(0.0);", output); | 390 fragBuilder->codeAppendf("%s = vec4(0.0);", output); |
391 break; | 391 break; |
392 case BlendFormula::kCoverage_OutputType: | 392 case BlendFormula::kCoverage_OutputType: |
393 // We can have a coverage formula while not reading coverage if ther
e are mixed samples. | 393 // We can have a coverage formula while not reading coverage if ther
e are mixed samples. |
394 fragBuilder->codeAppendf("%s = %s;", | 394 if (inCoverage) { |
395 output, xp.readsCoverage() ? inCoverage : "ve
c4(1.0)"); | 395 fragBuilder->codeAppendf("%s = %s;", output, inCoverage); |
| 396 } else { |
| 397 fragBuilder->codeAppendf("%s = vec4(1.0);", output); |
| 398 } |
396 break; | 399 break; |
397 case BlendFormula::kModulate_OutputType: | 400 case BlendFormula::kModulate_OutputType: |
398 if (xp.readsCoverage()) { | 401 if (inCoverage) { |
399 fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCov
erage); | 402 fragBuilder->codeAppendf("%s = %s * %s;", output, inColor, inCov
erage); |
400 } else { | 403 } else { |
401 fragBuilder->codeAppendf("%s = %s;", output, inColor); | 404 fragBuilder->codeAppendf("%s = %s;", output, inColor); |
402 } | 405 } |
403 break; | 406 break; |
404 case BlendFormula::kSAModulate_OutputType: | 407 case BlendFormula::kSAModulate_OutputType: |
405 if (xp.readsCoverage()) { | 408 if (inCoverage) { |
406 fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inC
overage); | 409 fragBuilder->codeAppendf("%s = %s.a * %s;", output, inColor, inC
overage); |
407 } else { | 410 } else { |
408 fragBuilder->codeAppendf("%s = %s;", output, inColor); | 411 fragBuilder->codeAppendf("%s = %s;", output, inColor); |
409 } | 412 } |
410 break; | 413 break; |
411 case BlendFormula::kISAModulate_OutputType: | 414 case BlendFormula::kISAModulate_OutputType: |
412 if (xp.readsCoverage()) { | 415 if (inCoverage) { |
413 fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inCo
lor, inCoverage); | 416 fragBuilder->codeAppendf("%s = (1.0 - %s.a) * %s;", output, inCo
lor, inCoverage); |
414 } else { | 417 } else { |
415 fragBuilder->codeAppendf("%s = vec4(1.0 - %s.a);", output, inCol
or); | 418 fragBuilder->codeAppendf("%s = vec4(1.0 - %s.a);", output, inCol
or); |
416 } | 419 } |
417 break; | 420 break; |
418 case BlendFormula::kISCModulate_OutputType: | 421 case BlendFormula::kISCModulate_OutputType: |
419 if (xp.readsCoverage()) { | 422 if (inCoverage) { |
420 fragBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", output,
inColor, inCoverage); | 423 fragBuilder->codeAppendf("%s = (vec4(1.0) - %s) * %s;", output,
inColor, inCoverage); |
421 } else { | 424 } else { |
422 fragBuilder->codeAppendf("%s = vec4(1.0) - %s;", output, inColor
); | 425 fragBuilder->codeAppendf("%s = vec4(1.0) - %s;", output, inColor
); |
423 } | 426 } |
424 break; | 427 break; |
425 default: | 428 default: |
426 SkFAIL("Unsupported output type."); | 429 SkFAIL("Unsupported output type."); |
427 break; | 430 break; |
428 } | 431 } |
429 } | 432 } |
430 | 433 |
431 class GLPorterDuffXferProcessor : public GrGLSLXferProcessor { | 434 class GLPorterDuffXferProcessor : public GrGLSLXferProcessor { |
432 public: | 435 public: |
433 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) { | 436 static void GenKey(const GrProcessor& processor, GrProcessorKeyBuilder* b) { |
434 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcess
or>(); | 437 const PorterDuffXferProcessor& xp = processor.cast<PorterDuffXferProcess
or>(); |
435 b->add32(SkToInt(xp.readsCoverage()) | | 438 b->add32(xp.getBlendFormula().fPrimaryOutputType | |
436 (xp.getBlendFormula().fPrimaryOutputType << 1) | | 439 (xp.getBlendFormula().fSecondaryOutputType << 3)); |
437 (xp.getBlendFormula().fSecondaryOutputType << 4)); | |
438 GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8); | 440 GR_STATIC_ASSERT(BlendFormula::kLast_OutputType < 8); |
439 }; | 441 }; |
440 | 442 |
441 private: | 443 private: |
442 void emitOutputsForBlendState(const EmitArgs& args) override { | 444 void emitOutputsForBlendState(const EmitArgs& args) override { |
443 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso
r>(); | 445 const PorterDuffXferProcessor& xp = args.fXP.cast<PorterDuffXferProcesso
r>(); |
444 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; | 446 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; |
445 | 447 |
446 BlendFormula blendFormula = xp.getBlendFormula(); | 448 BlendFormula blendFormula = xp.getBlendFormula(); |
447 if (blendFormula.hasSecondaryOutput()) { | 449 if (blendFormula.hasSecondaryOutput()) { |
(...skipping 18 matching lines...) Expand all Loading... |
466 | 468 |
467 GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const { | 469 GrGLSLXferProcessor* PorterDuffXferProcessor::createGLSLInstance() const { |
468 return new GLPorterDuffXferProcessor; | 470 return new GLPorterDuffXferProcessor; |
469 } | 471 } |
470 | 472 |
471 GrXferProcessor::OptFlags | 473 GrXferProcessor::OptFlags |
472 PorterDuffXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI, | 474 PorterDuffXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI, |
473 const GrProcOptInfo& coveragePOI, | 475 const GrProcOptInfo& coveragePOI, |
474 bool doesStencilWrite, | 476 bool doesStencilWrite, |
475 GrColor* overrideColor, | 477 GrColor* overrideColor, |
476 const GrCaps& caps) { | 478 const GrCaps& caps) const { |
477 GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags; | 479 GrXferProcessor::OptFlags optFlags = GrXferProcessor::kNone_OptFlags; |
478 if (!fBlendFormula.modifiesDst()) { | 480 if (!fBlendFormula.modifiesDst()) { |
479 if (!doesStencilWrite) { | 481 if (!doesStencilWrite) { |
480 optFlags |= GrXferProcessor::kSkipDraw_OptFlag; | 482 optFlags |= GrXferProcessor::kSkipDraw_OptFlag; |
481 } | 483 } |
482 optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag | | 484 optFlags |= (GrXferProcessor::kIgnoreColor_OptFlag | |
483 GrXferProcessor::kIgnoreCoverage_OptFlag | | 485 GrXferProcessor::kIgnoreCoverage_OptFlag | |
484 GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag); | 486 GrXferProcessor::kCanTweakAlphaForCoverage_OptFlag); |
485 } else { | 487 } else { |
486 if (!fBlendFormula.usesInputColor()) { | 488 if (!fBlendFormula.usesInputColor()) { |
(...skipping 24 matching lines...) Expand all Loading... |
511 } | 513 } |
512 | 514 |
513 const char* name() const override { return "Porter Duff Shader"; } | 515 const char* name() const override { return "Porter Duff Shader"; } |
514 | 516 |
515 GrGLSLXferProcessor* createGLSLInstance() const override; | 517 GrGLSLXferProcessor* createGLSLInstance() const override; |
516 | 518 |
517 SkXfermode::Mode getXfermode() const { return fXfermode; } | 519 SkXfermode::Mode getXfermode() const { return fXfermode; } |
518 | 520 |
519 private: | 521 private: |
520 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo&, const GrP
rocOptInfo&, | 522 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo&, const GrP
rocOptInfo&, |
521 bool, GrColor*, const GrCaps&)
override { | 523 bool, GrColor*, const GrCaps&)
const override { |
522 return kNone_OptFlags; | 524 return kNone_OptFlags; |
523 } | 525 } |
524 | 526 |
525 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override; | 527 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override; |
526 | 528 |
527 bool onIsEqual(const GrXferProcessor& xpBase) const override { | 529 bool onIsEqual(const GrXferProcessor& xpBase) const override { |
528 const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>(); | 530 const ShaderPDXferProcessor& xp = xpBase.cast<ShaderPDXferProcessor>(); |
529 return fXfermode == xp.fXfermode; | 531 return fXfermode == xp.fXfermode; |
530 } | 532 } |
531 | 533 |
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
583 | 585 |
584 GrGLSLXferProcessor* createGLSLInstance() const override; | 586 GrGLSLXferProcessor* createGLSLInstance() const override; |
585 | 587 |
586 private: | 588 private: |
587 PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha); | 589 PDLCDXferProcessor(GrColor blendConstant, uint8_t alpha); |
588 | 590 |
589 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, | 591 GrXferProcessor::OptFlags onGetOptimizations(const GrProcOptInfo& colorPOI, |
590 const GrProcOptInfo& coveragePO
I, | 592 const GrProcOptInfo& coveragePO
I, |
591 bool doesStencilWrite, | 593 bool doesStencilWrite, |
592 GrColor* overrideColor, | 594 GrColor* overrideColor, |
593 const GrCaps& caps) override; | 595 const GrCaps& caps) const overr
ide; |
594 | 596 |
595 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override; | 597 void onGetGLSLProcessorKey(const GrGLSLCaps& caps, GrProcessorKeyBuilder* b)
const override; |
596 | 598 |
597 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { | 599 void onGetBlendInfo(GrXferProcessor::BlendInfo* blendInfo) const override { |
598 blendInfo->fSrcBlend = kConstC_GrBlendCoeff; | 600 blendInfo->fSrcBlend = kConstC_GrBlendCoeff; |
599 blendInfo->fDstBlend = kISC_GrBlendCoeff; | 601 blendInfo->fDstBlend = kISC_GrBlendCoeff; |
600 blendInfo->fBlendConstant = fBlendConstant; | 602 blendInfo->fBlendConstant = fBlendConstant; |
601 } | 603 } |
602 | 604 |
603 bool onIsEqual(const GrXferProcessor& xpBase) const override { | 605 bool onIsEqual(const GrXferProcessor& xpBase) const override { |
(...skipping 18 matching lines...) Expand all Loading... |
622 GLPDLCDXferProcessor(const GrProcessor&) {} | 624 GLPDLCDXferProcessor(const GrProcessor&) {} |
623 | 625 |
624 virtual ~GLPDLCDXferProcessor() {} | 626 virtual ~GLPDLCDXferProcessor() {} |
625 | 627 |
626 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps, | 628 static void GenKey(const GrProcessor& processor, const GrGLSLCaps& caps, |
627 GrProcessorKeyBuilder* b) {} | 629 GrProcessorKeyBuilder* b) {} |
628 | 630 |
629 private: | 631 private: |
630 void emitOutputsForBlendState(const EmitArgs& args) override { | 632 void emitOutputsForBlendState(const EmitArgs& args) override { |
631 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; | 633 GrGLSLXPFragmentBuilder* fragBuilder = args.fXPFragBuilder; |
| 634 SkASSERT(args.fInputCoverage); |
632 fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInp
utColor, | 635 fragBuilder->codeAppendf("%s = %s * %s;", args.fOutputPrimary, args.fInp
utColor, |
633 args.fInputCoverage); | 636 args.fInputCoverage); |
634 } | 637 } |
635 | 638 |
636 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) over
ride {}; | 639 void onSetData(const GrGLSLProgramDataManager&, const GrXferProcessor&) over
ride {}; |
637 | 640 |
638 typedef GrGLSLXferProcessor INHERITED; | 641 typedef GrGLSLXferProcessor INHERITED; |
639 }; | 642 }; |
640 | 643 |
641 /////////////////////////////////////////////////////////////////////////////// | 644 /////////////////////////////////////////////////////////////////////////////// |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
673 | 676 |
674 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const { | 677 GrGLSLXferProcessor* PDLCDXferProcessor::createGLSLInstance() const { |
675 return new GLPDLCDXferProcessor(*this); | 678 return new GLPDLCDXferProcessor(*this); |
676 } | 679 } |
677 | 680 |
678 GrXferProcessor::OptFlags | 681 GrXferProcessor::OptFlags |
679 PDLCDXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI, | 682 PDLCDXferProcessor::onGetOptimizations(const GrProcOptInfo& colorPOI, |
680 const GrProcOptInfo& coveragePOI, | 683 const GrProcOptInfo& coveragePOI, |
681 bool doesStencilWrite, | 684 bool doesStencilWrite, |
682 GrColor* overrideColor, | 685 GrColor* overrideColor, |
683 const GrCaps& caps) { | 686 const GrCaps& caps) const { |
684 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha | 687 // We want to force our primary output to be alpha * Coverage, where alp
ha is the alpha |
685 // value of the blend the constant. We should already have valid blend c
oeff's if we are at | 688 // value of the blend the constant. We should already have valid blend c
oeff's if we are at |
686 // a point where we have RGB coverage. We don't need any color stages si
nce the known color | 689 // a point where we have RGB coverage. We don't need any color stages si
nce the known color |
687 // output is already baked into the blendConstant. | 690 // output is already baked into the blendConstant. |
688 *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha); | 691 *overrideColor = GrColorPackRGBA(fAlpha, fAlpha, fAlpha, fAlpha); |
689 return GrXferProcessor::kOverrideColor_OptFlag; | 692 return GrXferProcessor::kOverrideColor_OptFlag; |
690 } | 693 } |
691 | 694 |
692 /////////////////////////////////////////////////////////////////////////////// | 695 /////////////////////////////////////////////////////////////////////////////// |
693 | 696 |
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
835 ////////////////////////////////////////////////////////////////////////////////
//////////////// | 838 ////////////////////////////////////////////////////////////////////////////////
//////////////// |
836 // SrcOver Global functions | 839 // SrcOver Global functions |
837 ////////////////////////////////////////////////////////////////////////////////
//////////////// | 840 ////////////////////////////////////////////////////////////////////////////////
//////////////// |
838 | 841 |
839 GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor( | 842 GrXferProcessor* GrPorterDuffXPFactory::CreateSrcOverXferProcessor( |
840 const GrCaps& caps, | 843 const GrCaps& caps, |
841 const GrProcOptInfo& colorPOI, | 844 const GrProcOptInfo& colorPOI, |
842 const GrProcOptInfo& covPOI, | 845 const GrProcOptInfo& covPOI, |
843 bool hasMixedSamples, | 846 bool hasMixedSamples, |
844 const GrXferProcessor::DstTexture* dstTexture) { | 847 const GrXferProcessor::DstTexture* dstTexture) { |
| 848 if (!covPOI.isFourChannelOutput() && |
| 849 !(covPOI.isSolidWhite() && !hasMixedSamples && colorPOI.isOpaque())) { |
| 850 static BlendFormula gSrcOverBlendFormula = COEFF_FORMULA(kOne_GrBlendCoe
ff, |
| 851 kISA_GrBlendCoe
ff); |
| 852 static PorterDuffXferProcessor gSrcOverXP(gSrcOverBlendFormula); |
| 853 SkASSERT(!dstTexture || !dstTexture->texture()); |
| 854 gSrcOverXP.ref(); |
| 855 return &gSrcOverXP; |
| 856 } |
| 857 |
845 BlendFormula blendFormula; | 858 BlendFormula blendFormula; |
846 if (covPOI.isFourChannelOutput()) { | 859 if (covPOI.isFourChannelOutput()) { |
847 if (kRGBA_GrColorComponentFlags == colorPOI.validFlags() && | 860 if (kRGBA_GrColorComponentFlags == colorPOI.validFlags() && |
848 !caps.shaderCaps()->dualSourceBlendingSupport() && | 861 !caps.shaderCaps()->dualSourceBlendingSupport() && |
849 !caps.shaderCaps()->dstReadInShaderSupport()) { | 862 !caps.shaderCaps()->dstReadInShaderSupport()) { |
850 // If we don't have dual source blending or in shader dst reads, we
fall | 863 // If we don't have dual source blending or in shader dst reads, we
fall |
851 // back to this trick for rendering SrcOver LCD text instead of doin
g a | 864 // back to this trick for rendering SrcOver LCD text instead of doin
g a |
852 // dst copy. | 865 // dst copy. |
853 SkASSERT(!dstTexture || !dstTexture->texture()); | 866 SkASSERT(!dstTexture || !dstTexture->texture()); |
854 return PDLCDXferProcessor::Create(SkXfermode::kSrcOver_Mode, colorPO
I); | 867 return PDLCDXferProcessor::Create(SkXfermode::kSrcOver_Mode, colorPO
I); |
(...skipping 30 matching lines...) Expand all Loading... |
885 return false; | 898 return false; |
886 } | 899 } |
887 return get_lcd_blend_formula(covPOI, SkXfermode::kSrcOver_Mode).hasSecon
daryOutput(); | 900 return get_lcd_blend_formula(covPOI, SkXfermode::kSrcOver_Mode).hasSecon
daryOutput(); |
888 } | 901 } |
889 // We fallback on the shader XP when the blend formula would use dual source
blending but we | 902 // We fallback on the shader XP when the blend formula would use dual source
blending but we |
890 // don't have support for it. | 903 // don't have support for it. |
891 return get_blend_formula(colorPOI, covPOI, | 904 return get_blend_formula(colorPOI, covPOI, |
892 hasMixedSamples, SkXfermode::kSrcOver_Mode).hasSeco
ndaryOutput(); | 905 hasMixedSamples, SkXfermode::kSrcOver_Mode).hasSeco
ndaryOutput(); |
893 } | 906 } |
894 | 907 |
OLD | NEW |