Flutter Engine
The Flutter Engine
GrPorterDuffTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
16#include "include/gpu/GrTypes.h"
20#include "src/gpu/Blend.h"
21#include "src/gpu/Swizzle.h"
37#include "tests/Test.h"
40
41#include <initializer_list>
42#include <utility>
43
44class GrTextureProxy;
45
46////////////////////////////////////////////////////////////////////////////////
47
52static void test_lcd_coverage(skiatest::Reporter* reporter, const GrCaps& caps);
54
56 GrMockOptions mockOptions;
57 mockOptions.fDualSourceBlendingSupport = true;
59 const GrCaps& caps = *context->priv().getGpu()->caps();
60
62 SK_ABORT("Null context does not support dual source blending.");
63 }
64
71}
72
73////////////////////////////////////////////////////////////////////////////////
74
75#define TEST_ASSERT(...) REPORTER_ASSERT(reporter, __VA_ARGS__)
76
77enum {
84};
85static const int kInvalid_OutputType = -1;
86
88 const GrProcessorAnalysisColor& colorInput,
89 GrProcessorAnalysisCoverage coverageInput,
90 const GrCaps& caps) {
92 paint.setXPFactory(xpf);
93 GrProcessorSet procs(std::move(paint));
94 SkPMColor4f overrideColor;
95 GrProcessorSet::Analysis analysis = procs.finalize(
96 colorInput, coverageInput, nullptr, &GrUserStencilSettings::kUnused, caps,
97 GrClampType::kAuto, &overrideColor);
98 return analysis;
99}
100
102public:
103 struct XPInfo {
105 GrProcessorAnalysisColor inputColor, GrProcessorAnalysisCoverage inputCoverage) {
106 const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode);
107
108 bool isLCD = GrProcessorAnalysisCoverage::kLCD == inputCoverage;
109
110 GrProcessorSet::Analysis analysis = do_analysis(xpf, inputColor, inputCoverage, caps);
115 GrXPFactory::MakeXferProcessor(xpf, inputColor, inputCoverage, caps,
117 TEST_ASSERT(!analysis.requiresDstTexture() ||
118 (isLCD &&
120 (SkBlendMode::kSrcOver != xfermode ||
121 !inputColor.isOpaque())));
122 // Porter Duff modes currently only use fixed-function or shader blending, and Ganesh
123 // doesn't yet make use of framebuffer fetches that require a barrier
124 // (e.g., QCOM_shader_framebuffer_fetch_noncoherent). So dst textures and xfer barriers
125 // should always go hand in hand for Porter Duff modes.
128 fBlendInfo = xp->getBlendInfo();
130 (isLCD && (SkBlendMode::kSrcOver != xfermode ||
131 !inputColor.isOpaque())));
134 }
135
142 };
143
144 static void GetXPOutputTypes(const GrXferProcessor* xp, int* outPrimary, int* outSecondary) {
145 GrPorterDuffXPFactory::TestGetXPOutputTypes(xp, outPrimary, outSecondary);
146 }
147};
148
152
153 for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
154 SkBlendMode xfermode = static_cast<SkBlendMode>(m);
155 const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, inputColor, inputCoverage);
156 switch (xfermode) {
167 break;
178 break;
189 break;
200 break;
211 break;
222 break;
233 break;
244 break;
255 break;
266 break;
277 break;
288 break;
299 break;
310 break;
321 break;
322 default:
323 ERRORF(reporter, "Invalid xfermode.");
324 break;
325 }
326 }
327}
331
332 for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
333 SkBlendMode xfermode = static_cast<SkBlendMode>(m);
334 const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, inputColor, inputCoverage);
335 switch (xfermode) {
346 break;
357 break;
368 break;
379 break;
390 break;
401 break;
412 break;
423 break;
434 break;
445 break;
456 break;
467 break;
478 break;
489 break;
500 break;
501 default:
502 ERRORF(reporter, "Invalid xfermode.");
503 break;
504 }
505 }
506}
507
509 GrProcessorAnalysisColor inputColor(
512
513 for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
514 SkBlendMode xfermode = static_cast<SkBlendMode>(m);
515 const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, inputColor, inputCoverage);
516 switch (xfermode) {
527 break;
538 break;
549 break;
560 break;
571 break;
582 break;
593 break;
604 break;
615 break;
626 break;
637 break;
648 break;
659 break;
670 break;
681 break;
682 default:
683 ERRORF(reporter, "Invalid xfermode.");
684 break;
685 }
686 }
687}
688
692
693 for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
694 SkBlendMode xfermode = static_cast<SkBlendMode>(m);
695 const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, inputColor, inputCoverage);
696 switch (xfermode) {
707 break;
718 break;
729 break;
740 break;
751 break;
762 break;
773 break;
784 break;
795 break;
806 break;
817 break;
828 break;
839 break;
848 break;
859 break;
860 default:
861 ERRORF(reporter, "Invalid xfermode.");
862 break;
863 }
864 }
865}
866
870
871 for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
872 SkBlendMode xfermode = static_cast<SkBlendMode>(m);
873 const GrPorterDuffTest::XPInfo xpi(reporter, xfermode, caps, inputColor, inputCoverage);
874
875 switch (xfermode) {
886 break;
897 break;
908 break;
910 // We don't specialize opaque src-over. See note in GrPorterDuffXferProcessor.cpp
920 } else {
922 }
924 break;
935 break;
946 break;
957 break;
968 break;
979 break;
990 break;
1001 break;
1002 case SkBlendMode::kXor:
1012 break;
1013 case SkBlendMode::kPlus:
1023 break;
1034 break;
1045 break;
1046 default:
1047 ERRORF(reporter, "Invalid xfermode.");
1048 break;
1049 }
1050 }
1051}
1052
1054 constexpr GrClampType autoClamp = GrClampType::kAuto;
1061 GrXPFactory::MakeXferProcessor(xpf, color, coverage, caps, autoClamp));
1062 if (!xp_opaque) {
1063 ERRORF(reporter, "Failed to create an XP with LCD coverage.");
1064 return;
1065 }
1066
1067 skgpu::BlendInfo blendInfo = xp_opaque->getBlendInfo();
1068 TEST_ASSERT(blendInfo.fWritesColor);
1069
1070 // Test with non-opaque alpha
1076 GrXPFactory::MakeXferProcessor(xpf, color, coverage, caps, autoClamp));
1077 if (!xp) {
1078 ERRORF(reporter, "Failed to create an XP with LCD coverage.");
1079 return;
1080 }
1081
1082 blendInfo = xp->getBlendInfo();
1083 TEST_ASSERT(blendInfo.fWritesColor);
1084}
1085
1088 opts.fSuppressDualSourceBlending = true;
1089 sk_gpu_test::GrContextFactory mockFactory(opts);
1090 auto ctx = mockFactory.get(skgpu::ContextType::kMock);
1091 if (!ctx) {
1092 SK_ABORT("Failed to create mock context without ARB_blend_func_extended.");
1093 }
1094
1095 GrProxyProvider* proxyProvider = ctx->priv().proxyProvider();
1096 const GrCaps& caps = *ctx->priv().caps();
1098 SK_ABORT("Mock context failed to honor request for no ARB_blend_func_extended.");
1099 }
1100
1101 auto mbet = sk_gpu_test::ManagedBackendTexture::MakeWithoutData(
1103 if (!mbet) {
1104 ERRORF(reporter, "Could not make texture.");
1105 return;
1106 }
1107 GrDstProxyView fakeDstProxyView;
1108 {
1109 sk_sp<GrTextureProxy> proxy = proxyProvider->wrapBackendTexture(
1111 mbet->refCountedCallback());
1112 skgpu::Swizzle swizzle =
1113 caps.getReadSwizzle(mbet->texture().getBackendFormat(), GrColorType::kRGBA_8888);
1114 fakeDstProxyView.setProxyView({std::move(proxy), kTopLeft_GrSurfaceOrigin, swizzle});
1115 }
1116
1117 static const GrProcessorAnalysisColor colorInputs[] = {
1121
1122 for (const auto& colorInput : colorInputs) {
1123 for (GrProcessorAnalysisCoverage coverageType :
1125 for (int m = 0; m <= (int)SkBlendMode::kLastCoeffMode; m++) {
1126 SkBlendMode xfermode = static_cast<SkBlendMode>(m);
1127 const GrXPFactory* xpf = GrPorterDuffXPFactory::Get(xfermode);
1129 GrXPFactory::MakeXferProcessor(xpf, colorInput, coverageType, caps,
1131 if (!xp) {
1132 ERRORF(reporter, "Failed to create an XP without dual source blending.");
1133 return;
1134 }
1136 }
1137 }
1138 }
1139}
const char * options
reporter
Definition: FontMgrTest.cpp:39
static GrColor GrColorPackRGBA(unsigned r, unsigned g, unsigned b, unsigned a)
Definition: GrColor.h:46
#define TEST_ASSERT(...)
@ kISAModulate_OutputType
@ kSAModulate_OutputType
@ kModulate_OutputType
@ kISCModulate_OutputType
@ kNone_OutputType
@ kCoverage_OutputType
static void test_color_not_opaque_no_coverage(skiatest::Reporter *reporter, const GrCaps &caps)
DEF_GANESH_TEST(GrPorterDuff, reporter,, CtsEnforcement::kApiLevel_T)
static void test_color_opaque_no_coverage(skiatest::Reporter *reporter, const GrCaps &caps)
static void test_color_opaque_with_coverage(skiatest::Reporter *reporter, const GrCaps &caps)
static void test_color_unknown_with_coverage(skiatest::Reporter *reporter, const GrCaps &caps)
static void test_lcd_coverage_fallback_case(skiatest::Reporter *reporter, const GrCaps &caps)
static GrProcessorSet::Analysis do_analysis(const GrXPFactory *xpf, const GrProcessorAnalysisColor &colorInput, GrProcessorAnalysisCoverage coverageInput, const GrCaps &caps)
static const int kInvalid_OutputType
static void test_lcd_coverage(skiatest::Reporter *reporter, const GrCaps &caps)
GrProcessorAnalysisCoverage
GrClampType
Definition: GrTypesPriv.h:228
@ kRead_GrIOType
Definition: GrTypesPriv.h:403
@ kBorrow_GrWrapOwnership
Definition: GrTypesPriv.h:79
@ kTopLeft_GrSurfaceOrigin
Definition: GrTypes.h:148
#define SK_ABORT(message,...)
Definition: SkAssert.h:70
SkBlendMode
Definition: SkBlendMode.h:38
@ kSrcOut
r = s * (1-da)
@ kPlus
r = min(s + d, 1)
@ kDstIn
r = d * sa
@ kModulate
r = s*d
@ kLastCoeffMode
last porter duff blend mode
@ kScreen
r = s + d - s*d
@ kSrcOver
r = s + (1-sa)*d
@ kXor
r = s*(1-da) + d*(1-sa)
@ kSrcATop
r = s*da + d*(1-sa)
@ kDstATop
r = d*sa + s*(1-da)
@ kDstOver
r = d + (1-da)*s
@ kDstOut
r = d * (1-sa)
@ kSrcIn
r = s * da
@ kClear
r = 0
@ kRGBA_8888_SkColorType
pixel with 8 bits for red, green, blue, alpha; in 32-bit word
Definition: SkColorType.h:24
static bool isLCD(const SkScalerContextRec &rec)
#define ERRORF(r,...)
Definition: Test.h:293
Definition: GrCaps.h:57
const GrShaderCaps * shaderCaps() const
Definition: GrCaps.h:63
bool shouldCollapseSrcOverToSrcWhenAble() const
Definition: GrCaps.h:179
skgpu::Swizzle getReadSwizzle(const GrBackendFormat &format, GrColorType colorType) const
Definition: GrCaps.cpp:443
static sk_sp< GrDirectContext > MakeMock(const GrMockOptions *, const GrContextOptions &)
GrDirectContextPriv priv()
void setProxyView(GrSurfaceProxyView view)
const GrCaps * caps() const
Definition: GrGpu.h:73
static void GetXPOutputTypes(const GrXferProcessor *xp, int *outPrimary, int *outSecondary)
static const GrXPFactory * Get(SkBlendMode blendMode)
bool inputColorIsIgnored() const
bool requiresNonOverlappingDraws() const
bool unaffectedByDstValue() const
bool requiresDstTexture() const
bool isCompatibleWithCoverageAsAlpha() const
Analysis finalize(const GrProcessorAnalysisColor &, const GrProcessorAnalysisCoverage, const GrAppliedClip *, const GrUserStencilSettings *, const GrCaps &, GrClampType, SkPMColor4f *inputColorOverride)
sk_sp< GrTextureProxy > wrapBackendTexture(const GrBackendTexture &, GrWrapOwnership, GrWrapCacheable, GrIOType, sk_sp< skgpu::RefCntedCallback >=nullptr)
static sk_sp< const GrXferProcessor > MakeXferProcessor(const GrXPFactory *, const GrProcessorAnalysisColor &, GrProcessorAnalysisCoverage, const GrCaps &caps, GrClampType)
static AnalysisProperties GetAnalysisProperties(const GrXPFactory *, const GrProcessorAnalysisColor &, const GrProcessorAnalysisCoverage &, const GrCaps &, GrClampType)
bool hasSecondaryOutput() const
skgpu::BlendInfo getBlendInfo() const
bool willReadDstColor() const
GrDirectContext * get(ContextType type, ContextOverrides overrides=ContextOverrides::kNone)
T * get() const
Definition: SkRefCnt.h:303
const Paint & paint
Definition: color_source.cc:38
DlColor color
@ kMock
Dawn on OpenGL ES.
static constexpr bool BlendCoeffRefsSrc2(const BlendCoeff coeff)
Definition: Blend.h:113
bool fDualSourceBlendingSupport
Definition: GrMockTypes.h:160
XPInfo(skiatest::Reporter *reporter, SkBlendMode xfermode, const GrCaps &caps, GrProcessorAnalysisColor inputColor, GrProcessorAnalysisCoverage inputCoverage)
bool fDstReadInShaderSupport
Definition: GrShaderCaps.h:34
static const GrUserStencilSettings & kUnused
static SkRGBA4f FromBytes_RGBA(uint32_t color)
bool fDualSourceBlendingSupport
Definition: SkSLUtil.h:84
skgpu::BlendCoeff fDstBlend
Definition: Blend.h:96
bool fWritesColor
Definition: Blend.h:98
skgpu::BlendCoeff fSrcBlend
Definition: Blend.h:95