xref: /aosp_15_r20/external/skia/tests/DMSAATest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2021 Google Inc.
3*c8dee2aaSAndroid Build Coastguard Worker  *
4*c8dee2aaSAndroid Build Coastguard Worker  * Use of this source code is governed by a BSD-style license that can be
5*c8dee2aaSAndroid Build Coastguard Worker  * found in the LICENSE file.
6*c8dee2aaSAndroid Build Coastguard Worker  */
7*c8dee2aaSAndroid Build Coastguard Worker 
8*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkAlphaType.h"
9*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBitmap.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkBlendMode.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColor.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorType.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImage.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkImageInfo.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPaint.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkPoint.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkScalar.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurface.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurfaceProps.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkVertices.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrContextOptions.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkImageGanesh.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/SkSurfaceGanesh.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkColorData.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/core/SkBlendModePriv.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/SkBackingFit.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPaint.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPixmap.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrXferProcessor.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SurfaceDrawContext.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "tests/CtsEnforcement.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "tools/gpu/ContextType.h"
47*c8dee2aaSAndroid Build Coastguard Worker 
48*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
49*c8dee2aaSAndroid Build Coastguard Worker #include <cstring>
50*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
51*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
52*c8dee2aaSAndroid Build Coastguard Worker 
53*c8dee2aaSAndroid Build Coastguard Worker namespace {
54*c8dee2aaSAndroid Build Coastguard Worker 
55*c8dee2aaSAndroid Build Coastguard Worker static SkSurfaceProps kDMSAAProps(SkSurfaceProps::kDynamicMSAA_Flag, kUnknown_SkPixelGeometry);
56*c8dee2aaSAndroid Build Coastguard Worker static SkSurfaceProps kBasicProps(0, kUnknown_SkPixelGeometry);
57*c8dee2aaSAndroid Build Coastguard Worker constexpr static SkPMColor4f kTransYellow = {.5f,.5f,.0f,.5f};
58*c8dee2aaSAndroid Build Coastguard Worker constexpr static SkPMColor4f kTransCyan = {.0f,.5f,.5f,.5f};
59*c8dee2aaSAndroid Build Coastguard Worker constexpr static int kWidth=10, kHeight=10;
60*c8dee2aaSAndroid Build Coastguard Worker 
61*c8dee2aaSAndroid Build Coastguard Worker }
62*c8dee2aaSAndroid Build Coastguard Worker 
draw_paint_with_aa(skgpu::ganesh::SurfaceDrawContext * sdc,const SkPMColor4f & color,SkBlendMode blendMode)63*c8dee2aaSAndroid Build Coastguard Worker static void draw_paint_with_aa(skgpu::ganesh::SurfaceDrawContext* sdc,
64*c8dee2aaSAndroid Build Coastguard Worker                                const SkPMColor4f& color,
65*c8dee2aaSAndroid Build Coastguard Worker                                SkBlendMode blendMode) {
66*c8dee2aaSAndroid Build Coastguard Worker     GrPaint paint;
67*c8dee2aaSAndroid Build Coastguard Worker     paint.setColor4f(color);
68*c8dee2aaSAndroid Build Coastguard Worker     paint.setXPFactory(GrXPFactory::FromBlendMode(blendMode));
69*c8dee2aaSAndroid Build Coastguard Worker     sdc->drawRect(nullptr, std::move(paint), GrAA::kYes, SkMatrix::I(),
70*c8dee2aaSAndroid Build Coastguard Worker                   SkRect::MakeIWH(kWidth, kHeight), nullptr);
71*c8dee2aaSAndroid Build Coastguard Worker }
72*c8dee2aaSAndroid Build Coastguard Worker 
draw_paint_with_dmsaa(skgpu::ganesh::SurfaceDrawContext * sdc,const SkPMColor4f & color,SkBlendMode blendMode)73*c8dee2aaSAndroid Build Coastguard Worker static void draw_paint_with_dmsaa(skgpu::ganesh::SurfaceDrawContext* sdc,
74*c8dee2aaSAndroid Build Coastguard Worker                                   const SkPMColor4f& color,
75*c8dee2aaSAndroid Build Coastguard Worker                                   SkBlendMode blendMode) {
76*c8dee2aaSAndroid Build Coastguard Worker     // drawVertices should always trigger dmsaa, but draw something non-rectangular just to be 100%
77*c8dee2aaSAndroid Build Coastguard Worker     // certain.
78*c8dee2aaSAndroid Build Coastguard Worker     static const SkPoint kVertices[3] = {{-.5f,-.5f}, {kWidth * 2.1f, 0}, {0, kHeight * 2.1f}};
79*c8dee2aaSAndroid Build Coastguard Worker     SkVertices::Builder builder(SkVertices::kTriangles_VertexMode, 3, 0, 0);
80*c8dee2aaSAndroid Build Coastguard Worker     memcpy(builder.positions(), kVertices, sizeof(kVertices));
81*c8dee2aaSAndroid Build Coastguard Worker     auto vertices = builder.detach();
82*c8dee2aaSAndroid Build Coastguard Worker 
83*c8dee2aaSAndroid Build Coastguard Worker     GrPaint paint;
84*c8dee2aaSAndroid Build Coastguard Worker     paint.setColor4f(color);
85*c8dee2aaSAndroid Build Coastguard Worker     paint.setXPFactory(GrXPFactory::FromBlendMode(blendMode));
86*c8dee2aaSAndroid Build Coastguard Worker     sdc->drawVertices(nullptr, std::move(paint), SkMatrix::I(), vertices);
87*c8dee2aaSAndroid Build Coastguard Worker }
88*c8dee2aaSAndroid Build Coastguard Worker 
fuzzy_equals(const float a[4],const SkPMColor4f & b)89*c8dee2aaSAndroid Build Coastguard Worker static bool fuzzy_equals(const float a[4], const SkPMColor4f& b) {
90*c8dee2aaSAndroid Build Coastguard Worker     constexpr static float kTolerance = 2.5f / 256;
91*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < 4; ++i) {
92*c8dee2aaSAndroid Build Coastguard Worker         if (!SkScalarNearlyEqual(a[i], b.vec()[i], kTolerance)) {
93*c8dee2aaSAndroid Build Coastguard Worker             return false;
94*c8dee2aaSAndroid Build Coastguard Worker         }
95*c8dee2aaSAndroid Build Coastguard Worker     }
96*c8dee2aaSAndroid Build Coastguard Worker     return true;
97*c8dee2aaSAndroid Build Coastguard Worker }
98*c8dee2aaSAndroid Build Coastguard Worker 
check_sdc_color(skiatest::Reporter * reporter,skgpu::ganesh::SurfaceDrawContext * sdc,GrDirectContext * ctx,const SkPMColor4f & color)99*c8dee2aaSAndroid Build Coastguard Worker static void check_sdc_color(skiatest::Reporter* reporter,
100*c8dee2aaSAndroid Build Coastguard Worker                             skgpu::ganesh::SurfaceDrawContext* sdc,
101*c8dee2aaSAndroid Build Coastguard Worker                             GrDirectContext* ctx,
102*c8dee2aaSAndroid Build Coastguard Worker                             const SkPMColor4f& color) {
103*c8dee2aaSAndroid Build Coastguard Worker     auto info = SkImageInfo::Make(kWidth, kHeight, kRGBA_F32_SkColorType, kPremul_SkAlphaType);
104*c8dee2aaSAndroid Build Coastguard Worker     GrPixmap pixmap = GrPixmap::Allocate(info);
105*c8dee2aaSAndroid Build Coastguard Worker     sdc->readPixels(ctx, pixmap, {0, 0});
106*c8dee2aaSAndroid Build Coastguard Worker     auto pix = static_cast<const float*>(pixmap.addr());
107*c8dee2aaSAndroid Build Coastguard Worker     for (int y = 0; y < kHeight; ++y) {
108*c8dee2aaSAndroid Build Coastguard Worker         for (int x = 0; x < kWidth; ++x) {
109*c8dee2aaSAndroid Build Coastguard Worker             if (!fuzzy_equals(pix, color)) {
110*c8dee2aaSAndroid Build Coastguard Worker                 ERRORF(reporter, "SDC color mismatch.\n"
111*c8dee2aaSAndroid Build Coastguard Worker                                  "Got      [%0.3f, %0.3f, %0.3f, %0.3f]\n"
112*c8dee2aaSAndroid Build Coastguard Worker                                  "Expected [%0.3f, %0.3f, %0.3f, %0.3f]",
113*c8dee2aaSAndroid Build Coastguard Worker                        pix[0], pix[1], pix[2], pix[3], color.fR, color.fG, color.fB, color.fA);
114*c8dee2aaSAndroid Build Coastguard Worker                 return;
115*c8dee2aaSAndroid Build Coastguard Worker             }
116*c8dee2aaSAndroid Build Coastguard Worker             pix += 4;
117*c8dee2aaSAndroid Build Coastguard Worker         }
118*c8dee2aaSAndroid Build Coastguard Worker     }
119*c8dee2aaSAndroid Build Coastguard Worker }
120*c8dee2aaSAndroid Build Coastguard Worker 
121*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_CONTEXTS(DMSAA_preserve_contents,
122*c8dee2aaSAndroid Build Coastguard Worker                              &skgpu::IsRenderingContext,
123*c8dee2aaSAndroid Build Coastguard Worker                              reporter,
124*c8dee2aaSAndroid Build Coastguard Worker                              ctxInfo,
125*c8dee2aaSAndroid Build Coastguard Worker                              nullptr,
126*c8dee2aaSAndroid Build Coastguard Worker                              CtsEnforcement::kApiLevel_T) {
127*c8dee2aaSAndroid Build Coastguard Worker     auto dContext = ctxInfo.directContext();
128*c8dee2aaSAndroid Build Coastguard Worker     auto sdc = skgpu::ganesh::SurfaceDrawContext::Make(dContext,
129*c8dee2aaSAndroid Build Coastguard Worker                                                        GrColorType::kRGBA_8888,
130*c8dee2aaSAndroid Build Coastguard Worker                                                        nullptr,
131*c8dee2aaSAndroid Build Coastguard Worker                                                        SkBackingFit::kApprox,
132*c8dee2aaSAndroid Build Coastguard Worker                                                        {kWidth, kHeight},
133*c8dee2aaSAndroid Build Coastguard Worker                                                        kDMSAAProps,
134*c8dee2aaSAndroid Build Coastguard Worker                                                        /*label=*/{});
135*c8dee2aaSAndroid Build Coastguard Worker 
136*c8dee2aaSAndroid Build Coastguard Worker     // Initialize the texture and dmsaa attachment with transparent.
137*c8dee2aaSAndroid Build Coastguard Worker     draw_paint_with_dmsaa(sdc.get(), SK_PMColor4fTRANSPARENT, SkBlendMode::kSrc);
138*c8dee2aaSAndroid Build Coastguard Worker     check_sdc_color(reporter, sdc.get(), dContext, SK_PMColor4fTRANSPARENT);
139*c8dee2aaSAndroid Build Coastguard Worker 
140*c8dee2aaSAndroid Build Coastguard Worker     // Clear the main texture to yellow.
141*c8dee2aaSAndroid Build Coastguard Worker     sdc->clear(kTransYellow);
142*c8dee2aaSAndroid Build Coastguard Worker 
143*c8dee2aaSAndroid Build Coastguard Worker     // Close the opsTask by doing a readback.
144*c8dee2aaSAndroid Build Coastguard Worker     check_sdc_color(reporter, sdc.get(), dContext, kTransYellow);
145*c8dee2aaSAndroid Build Coastguard Worker 
146*c8dee2aaSAndroid Build Coastguard Worker     // Now the DMSAA attachment is clear and the texture is yellow. Blend cyan into the DMSAA
147*c8dee2aaSAndroid Build Coastguard Worker     // attachment. This will fail if the yellow from the main texture doesn't get copied into the
148*c8dee2aaSAndroid Build Coastguard Worker     // DMSAA attachment before the renderPass.
149*c8dee2aaSAndroid Build Coastguard Worker     draw_paint_with_dmsaa(sdc.get(), kTransCyan, SkBlendMode::kSrcOver);
150*c8dee2aaSAndroid Build Coastguard Worker     SkPMColor4f dstColor = SkBlendMode_Apply(SkBlendMode::kSrcOver, kTransCyan, kTransYellow);
151*c8dee2aaSAndroid Build Coastguard Worker 
152*c8dee2aaSAndroid Build Coastguard Worker     check_sdc_color(reporter, sdc.get(), dContext, dstColor);
153*c8dee2aaSAndroid Build Coastguard Worker }
154*c8dee2aaSAndroid Build Coastguard Worker 
require_dst_reads(GrContextOptions * options)155*c8dee2aaSAndroid Build Coastguard Worker static void require_dst_reads(GrContextOptions* options) {
156*c8dee2aaSAndroid Build Coastguard Worker     options->fSuppressAdvancedBlendEquations = true;
157*c8dee2aaSAndroid Build Coastguard Worker     options->fSuppressFramebufferFetch = true;
158*c8dee2aaSAndroid Build Coastguard Worker }
159*c8dee2aaSAndroid Build Coastguard Worker 
160*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_CONTEXTS(DMSAA_dst_read,
161*c8dee2aaSAndroid Build Coastguard Worker                              &skgpu::IsRenderingContext,
162*c8dee2aaSAndroid Build Coastguard Worker                              reporter,
163*c8dee2aaSAndroid Build Coastguard Worker                              ctxInfo,
164*c8dee2aaSAndroid Build Coastguard Worker                              require_dst_reads,
165*c8dee2aaSAndroid Build Coastguard Worker                              CtsEnforcement::kApiLevel_T) {
166*c8dee2aaSAndroid Build Coastguard Worker     auto dContext = ctxInfo.directContext();
167*c8dee2aaSAndroid Build Coastguard Worker     auto sdc = skgpu::ganesh::SurfaceDrawContext::Make(dContext,
168*c8dee2aaSAndroid Build Coastguard Worker                                                        GrColorType::kRGBA_8888,
169*c8dee2aaSAndroid Build Coastguard Worker                                                        nullptr,
170*c8dee2aaSAndroid Build Coastguard Worker                                                        SkBackingFit::kApprox,
171*c8dee2aaSAndroid Build Coastguard Worker                                                        {kWidth, kHeight},
172*c8dee2aaSAndroid Build Coastguard Worker                                                        kDMSAAProps,
173*c8dee2aaSAndroid Build Coastguard Worker                                                        /*label=*/{});
174*c8dee2aaSAndroid Build Coastguard Worker 
175*c8dee2aaSAndroid Build Coastguard Worker     // Initialize the texture and dmsaa attachment with transparent.
176*c8dee2aaSAndroid Build Coastguard Worker     draw_paint_with_dmsaa(sdc.get(), SK_PMColor4fTRANSPARENT, SkBlendMode::kSrc);
177*c8dee2aaSAndroid Build Coastguard Worker     check_sdc_color(reporter, sdc.get(), dContext, SK_PMColor4fTRANSPARENT);
178*c8dee2aaSAndroid Build Coastguard Worker 
179*c8dee2aaSAndroid Build Coastguard Worker     sdc->clear(SK_PMColor4fWHITE);
180*c8dee2aaSAndroid Build Coastguard Worker     SkPMColor4f dstColor = SK_PMColor4fWHITE;
181*c8dee2aaSAndroid Build Coastguard Worker 
182*c8dee2aaSAndroid Build Coastguard Worker     draw_paint_with_dmsaa(sdc.get(), kTransYellow, SkBlendMode::kDarken);
183*c8dee2aaSAndroid Build Coastguard Worker     dstColor = SkBlendMode_Apply(SkBlendMode::kDarken, kTransYellow, dstColor);
184*c8dee2aaSAndroid Build Coastguard Worker 
185*c8dee2aaSAndroid Build Coastguard Worker     draw_paint_with_dmsaa(sdc.get(), kTransCyan, SkBlendMode::kDarken);
186*c8dee2aaSAndroid Build Coastguard Worker     dstColor = SkBlendMode_Apply(SkBlendMode::kDarken, kTransCyan, dstColor);
187*c8dee2aaSAndroid Build Coastguard Worker 
188*c8dee2aaSAndroid Build Coastguard Worker     check_sdc_color(reporter, sdc.get(), dContext, dstColor);
189*c8dee2aaSAndroid Build Coastguard Worker }
190*c8dee2aaSAndroid Build Coastguard Worker 
191*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_CONTEXTS(DMSAA_aa_dst_read_after_dmsaa,
192*c8dee2aaSAndroid Build Coastguard Worker                              &skgpu::IsRenderingContext,
193*c8dee2aaSAndroid Build Coastguard Worker                              reporter,
194*c8dee2aaSAndroid Build Coastguard Worker                              ctxInfo,
195*c8dee2aaSAndroid Build Coastguard Worker                              require_dst_reads,
196*c8dee2aaSAndroid Build Coastguard Worker                              CtsEnforcement::kApiLevel_T) {
197*c8dee2aaSAndroid Build Coastguard Worker     auto dContext = ctxInfo.directContext();
198*c8dee2aaSAndroid Build Coastguard Worker     auto sdc = skgpu::ganesh::SurfaceDrawContext::Make(dContext,
199*c8dee2aaSAndroid Build Coastguard Worker                                                        GrColorType::kRGBA_8888,
200*c8dee2aaSAndroid Build Coastguard Worker                                                        nullptr,
201*c8dee2aaSAndroid Build Coastguard Worker                                                        SkBackingFit::kApprox,
202*c8dee2aaSAndroid Build Coastguard Worker                                                        {kWidth, kHeight},
203*c8dee2aaSAndroid Build Coastguard Worker                                                        kDMSAAProps,
204*c8dee2aaSAndroid Build Coastguard Worker                                                        /*label=*/{});
205*c8dee2aaSAndroid Build Coastguard Worker 
206*c8dee2aaSAndroid Build Coastguard Worker     // Initialize the texture and dmsaa attachment with transparent.
207*c8dee2aaSAndroid Build Coastguard Worker     draw_paint_with_dmsaa(sdc.get(), SK_PMColor4fTRANSPARENT, SkBlendMode::kSrc);
208*c8dee2aaSAndroid Build Coastguard Worker     check_sdc_color(reporter, sdc.get(), dContext, SK_PMColor4fTRANSPARENT);
209*c8dee2aaSAndroid Build Coastguard Worker 
210*c8dee2aaSAndroid Build Coastguard Worker     sdc->clear(SK_PMColor4fWHITE);
211*c8dee2aaSAndroid Build Coastguard Worker     SkPMColor4f dstColor = SK_PMColor4fWHITE;
212*c8dee2aaSAndroid Build Coastguard Worker 
213*c8dee2aaSAndroid Build Coastguard Worker     draw_paint_with_dmsaa(sdc.get(), kTransYellow, SkBlendMode::kDarken);
214*c8dee2aaSAndroid Build Coastguard Worker     dstColor = SkBlendMode_Apply(SkBlendMode::kDarken, kTransYellow, dstColor);
215*c8dee2aaSAndroid Build Coastguard Worker 
216*c8dee2aaSAndroid Build Coastguard Worker     // Draw with aa after dmsaa. This should break up the render pass and issue a texture barrier.
217*c8dee2aaSAndroid Build Coastguard Worker     draw_paint_with_aa(sdc.get(), kTransCyan, SkBlendMode::kDarken);
218*c8dee2aaSAndroid Build Coastguard Worker     dstColor = SkBlendMode_Apply(SkBlendMode::kDarken, kTransCyan, dstColor);
219*c8dee2aaSAndroid Build Coastguard Worker 
220*c8dee2aaSAndroid Build Coastguard Worker     check_sdc_color(reporter, sdc.get(), dContext, dstColor);
221*c8dee2aaSAndroid Build Coastguard Worker }
222*c8dee2aaSAndroid Build Coastguard Worker 
223*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_CONTEXTS(DMSAA_dst_read_with_existing_barrier,
224*c8dee2aaSAndroid Build Coastguard Worker                              &skgpu::IsRenderingContext,
225*c8dee2aaSAndroid Build Coastguard Worker                              reporter,
226*c8dee2aaSAndroid Build Coastguard Worker                              ctxInfo,
227*c8dee2aaSAndroid Build Coastguard Worker                              require_dst_reads,
228*c8dee2aaSAndroid Build Coastguard Worker                              CtsEnforcement::kApiLevel_T) {
229*c8dee2aaSAndroid Build Coastguard Worker     auto dContext = ctxInfo.directContext();
230*c8dee2aaSAndroid Build Coastguard Worker     auto sdc = skgpu::ganesh::SurfaceDrawContext::Make(dContext,
231*c8dee2aaSAndroid Build Coastguard Worker                                                        GrColorType::kRGBA_8888,
232*c8dee2aaSAndroid Build Coastguard Worker                                                        nullptr,
233*c8dee2aaSAndroid Build Coastguard Worker                                                        SkBackingFit::kApprox,
234*c8dee2aaSAndroid Build Coastguard Worker                                                        {kWidth, kHeight},
235*c8dee2aaSAndroid Build Coastguard Worker                                                        kDMSAAProps,
236*c8dee2aaSAndroid Build Coastguard Worker                                                        /*label=*/{});
237*c8dee2aaSAndroid Build Coastguard Worker 
238*c8dee2aaSAndroid Build Coastguard Worker     // Initialize the texture and dmsaa attachment with transparent.
239*c8dee2aaSAndroid Build Coastguard Worker     draw_paint_with_dmsaa(sdc.get(), SK_PMColor4fTRANSPARENT, SkBlendMode::kSrc);
240*c8dee2aaSAndroid Build Coastguard Worker     check_sdc_color(reporter, sdc.get(), dContext, SK_PMColor4fTRANSPARENT);
241*c8dee2aaSAndroid Build Coastguard Worker 
242*c8dee2aaSAndroid Build Coastguard Worker     sdc->clear(SK_PMColor4fWHITE);
243*c8dee2aaSAndroid Build Coastguard Worker     SkPMColor4f dstColor = SK_PMColor4fWHITE;
244*c8dee2aaSAndroid Build Coastguard Worker 
245*c8dee2aaSAndroid Build Coastguard Worker     // Blend to the texture (not the dmsaa attachment) with a dst read. This creates a texture
246*c8dee2aaSAndroid Build Coastguard Worker     // barrier.
247*c8dee2aaSAndroid Build Coastguard Worker     draw_paint_with_aa(sdc.get(), kTransYellow, SkBlendMode::kDarken);
248*c8dee2aaSAndroid Build Coastguard Worker     dstColor = SkBlendMode_Apply(SkBlendMode::kDarken, kTransYellow, dstColor);
249*c8dee2aaSAndroid Build Coastguard Worker 
250*c8dee2aaSAndroid Build Coastguard Worker     // Blend to the msaa attachment _without_ a dst read. This ensures we respect the prior texture
251*c8dee2aaSAndroid Build Coastguard Worker     // barrier by splitting the opsTask.
252*c8dee2aaSAndroid Build Coastguard Worker     draw_paint_with_dmsaa(sdc.get(), kTransCyan, SkBlendMode::kSrcOver);
253*c8dee2aaSAndroid Build Coastguard Worker     dstColor = SkBlendMode_Apply(SkBlendMode::kSrcOver, kTransCyan, dstColor);
254*c8dee2aaSAndroid Build Coastguard Worker 
255*c8dee2aaSAndroid Build Coastguard Worker     check_sdc_color(reporter, sdc.get(), dContext, dstColor);
256*c8dee2aaSAndroid Build Coastguard Worker }
257*c8dee2aaSAndroid Build Coastguard Worker 
258*c8dee2aaSAndroid Build Coastguard Worker // This test is used to test for crbug.com/1241134. The bug appears on Adreno5xx devices with OS
259*c8dee2aaSAndroid Build Coastguard Worker // PQ3A. It does not repro on the earlier PPR1 version since the extend blend func extension was not
260*c8dee2aaSAndroid Build Coastguard Worker // present on the older driver.
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DMSAA_dual_source_blend_disable,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)261*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(DMSAA_dual_source_blend_disable,
262*c8dee2aaSAndroid Build Coastguard Worker                                        reporter,
263*c8dee2aaSAndroid Build Coastguard Worker                                        ctxInfo,
264*c8dee2aaSAndroid Build Coastguard Worker                                        CtsEnforcement::kApiLevel_T) {
265*c8dee2aaSAndroid Build Coastguard Worker     SkISize surfaceDims = {100, 100};
266*c8dee2aaSAndroid Build Coastguard Worker     SkISize texDims = {50, 50};
267*c8dee2aaSAndroid Build Coastguard Worker     auto context = ctxInfo.directContext();
268*c8dee2aaSAndroid Build Coastguard Worker 
269*c8dee2aaSAndroid Build Coastguard Worker     auto sourceTexture = context->createBackendTexture(texDims.width(),
270*c8dee2aaSAndroid Build Coastguard Worker                                                        texDims.height(),
271*c8dee2aaSAndroid Build Coastguard Worker                                                        kRGBA_8888_SkColorType,
272*c8dee2aaSAndroid Build Coastguard Worker                                                        SkColors::kBlue,
273*c8dee2aaSAndroid Build Coastguard Worker                                                        skgpu::Mipmapped::kNo,
274*c8dee2aaSAndroid Build Coastguard Worker                                                        GrRenderable::kYes,
275*c8dee2aaSAndroid Build Coastguard Worker                                                        GrProtected::kNo);
276*c8dee2aaSAndroid Build Coastguard Worker 
277*c8dee2aaSAndroid Build Coastguard Worker     auto sourceImage = SkImages::BorrowTextureFrom(context,
278*c8dee2aaSAndroid Build Coastguard Worker                                                    sourceTexture,
279*c8dee2aaSAndroid Build Coastguard Worker                                                    kTopLeft_GrSurfaceOrigin,
280*c8dee2aaSAndroid Build Coastguard Worker                                                    kRGBA_8888_SkColorType,
281*c8dee2aaSAndroid Build Coastguard Worker                                                    kPremul_SkAlphaType,
282*c8dee2aaSAndroid Build Coastguard Worker                                                    nullptr);
283*c8dee2aaSAndroid Build Coastguard Worker 
284*c8dee2aaSAndroid Build Coastguard Worker     auto texture1 = context->createBackendTexture(surfaceDims.width(),
285*c8dee2aaSAndroid Build Coastguard Worker                                                   surfaceDims.height(),
286*c8dee2aaSAndroid Build Coastguard Worker                                                   kRGBA_8888_SkColorType,
287*c8dee2aaSAndroid Build Coastguard Worker                                                   SkColors::kRed,
288*c8dee2aaSAndroid Build Coastguard Worker                                                   skgpu::Mipmapped::kNo,
289*c8dee2aaSAndroid Build Coastguard Worker                                                   GrRenderable::kYes,
290*c8dee2aaSAndroid Build Coastguard Worker                                                   GrProtected::kNo);
291*c8dee2aaSAndroid Build Coastguard Worker 
292*c8dee2aaSAndroid Build Coastguard Worker     auto texture2 = context->createBackendTexture(surfaceDims.width(),
293*c8dee2aaSAndroid Build Coastguard Worker                                                   surfaceDims.height(),
294*c8dee2aaSAndroid Build Coastguard Worker                                                   kRGBA_8888_SkColorType,
295*c8dee2aaSAndroid Build Coastguard Worker                                                   SkColors::kYellow,
296*c8dee2aaSAndroid Build Coastguard Worker                                                   skgpu::Mipmapped::kNo,
297*c8dee2aaSAndroid Build Coastguard Worker                                                   GrRenderable::kYes,
298*c8dee2aaSAndroid Build Coastguard Worker                                                   GrProtected::kNo);
299*c8dee2aaSAndroid Build Coastguard Worker 
300*c8dee2aaSAndroid Build Coastguard Worker     SkPaint paint;
301*c8dee2aaSAndroid Build Coastguard Worker     paint.setBlendMode(SkBlendMode::kSrc);
302*c8dee2aaSAndroid Build Coastguard Worker 
303*c8dee2aaSAndroid Build Coastguard Worker     SkRect srcRect = SkRect::MakeIWH(texDims.width(), texDims.height());
304*c8dee2aaSAndroid Build Coastguard Worker     SkRect dstRect = SkRect::MakeXYWH(texDims.width()/2, texDims.height()/2,
305*c8dee2aaSAndroid Build Coastguard Worker                                       texDims.width(), texDims.height());
306*c8dee2aaSAndroid Build Coastguard Worker 
307*c8dee2aaSAndroid Build Coastguard Worker     // First we do an image draw to a DMSAA surface with kSrc blend mode. This will trigger us to
308*c8dee2aaSAndroid Build Coastguard Worker     // use dual source blending if supported.
309*c8dee2aaSAndroid Build Coastguard Worker     // Note: The draw here doesn't actually use the dmsaa multisampled buffer. However, by using
310*c8dee2aaSAndroid Build Coastguard Worker     // a dmsaa surface it forces us to use the FillRRectOp instead of the normal FillQuad path. It
311*c8dee2aaSAndroid Build Coastguard Worker     // is unclear why, but using the FillRRectOp is required to repro the bug.
312*c8dee2aaSAndroid Build Coastguard Worker     {
313*c8dee2aaSAndroid Build Coastguard Worker         auto surface = SkSurfaces::WrapBackendTexture(context,
314*c8dee2aaSAndroid Build Coastguard Worker                                                       texture1,
315*c8dee2aaSAndroid Build Coastguard Worker                                                       kTopLeft_GrSurfaceOrigin,
316*c8dee2aaSAndroid Build Coastguard Worker                                                       1,
317*c8dee2aaSAndroid Build Coastguard Worker                                                       kRGBA_8888_SkColorType,
318*c8dee2aaSAndroid Build Coastguard Worker                                                       nullptr,
319*c8dee2aaSAndroid Build Coastguard Worker                                                       &kDMSAAProps);
320*c8dee2aaSAndroid Build Coastguard Worker 
321*c8dee2aaSAndroid Build Coastguard Worker         surface->getCanvas()->drawImageRect(sourceImage,
322*c8dee2aaSAndroid Build Coastguard Worker                                             srcRect,
323*c8dee2aaSAndroid Build Coastguard Worker                                             dstRect,
324*c8dee2aaSAndroid Build Coastguard Worker                                             SkSamplingOptions(),
325*c8dee2aaSAndroid Build Coastguard Worker                                             &paint,
326*c8dee2aaSAndroid Build Coastguard Worker                                             SkCanvas::kStrict_SrcRectConstraint);
327*c8dee2aaSAndroid Build Coastguard Worker         // Make sure there isn't any batching
328*c8dee2aaSAndroid Build Coastguard Worker         context->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
329*c8dee2aaSAndroid Build Coastguard Worker     }
330*c8dee2aaSAndroid Build Coastguard Worker 
331*c8dee2aaSAndroid Build Coastguard Worker     // Next we do an image draw to a different surface that doesn't have the dmsaa flag. This will
332*c8dee2aaSAndroid Build Coastguard Worker     // trigger use to disable blending. However, when the bug is present the driver still seems to
333*c8dee2aaSAndroid Build Coastguard Worker     // try and use a "src2" blend value and ends up just writing the original dst color of yellow.
334*c8dee2aaSAndroid Build Coastguard Worker     {
335*c8dee2aaSAndroid Build Coastguard Worker         auto surface = SkSurfaces::WrapBackendTexture(context,
336*c8dee2aaSAndroid Build Coastguard Worker                                                       texture2,
337*c8dee2aaSAndroid Build Coastguard Worker                                                       kTopLeft_GrSurfaceOrigin,
338*c8dee2aaSAndroid Build Coastguard Worker                                                       1,
339*c8dee2aaSAndroid Build Coastguard Worker                                                       kRGBA_8888_SkColorType,
340*c8dee2aaSAndroid Build Coastguard Worker                                                       nullptr,
341*c8dee2aaSAndroid Build Coastguard Worker                                                       &kBasicProps);
342*c8dee2aaSAndroid Build Coastguard Worker 
343*c8dee2aaSAndroid Build Coastguard Worker         surface->getCanvas()->drawImageRect(sourceImage,
344*c8dee2aaSAndroid Build Coastguard Worker                                             srcRect,
345*c8dee2aaSAndroid Build Coastguard Worker                                             dstRect,
346*c8dee2aaSAndroid Build Coastguard Worker                                             SkSamplingOptions(),
347*c8dee2aaSAndroid Build Coastguard Worker                                             &paint,
348*c8dee2aaSAndroid Build Coastguard Worker                                             SkCanvas::kStrict_SrcRectConstraint);
349*c8dee2aaSAndroid Build Coastguard Worker         context->flushAndSubmit(surface.get(), GrSyncCpu::kNo);
350*c8dee2aaSAndroid Build Coastguard Worker     }
351*c8dee2aaSAndroid Build Coastguard Worker 
352*c8dee2aaSAndroid Build Coastguard Worker     {
353*c8dee2aaSAndroid Build Coastguard Worker         auto readImage = SkImages::BorrowTextureFrom(context,
354*c8dee2aaSAndroid Build Coastguard Worker                                                      texture2,
355*c8dee2aaSAndroid Build Coastguard Worker                                                      kTopLeft_GrSurfaceOrigin,
356*c8dee2aaSAndroid Build Coastguard Worker                                                      kRGBA_8888_SkColorType,
357*c8dee2aaSAndroid Build Coastguard Worker                                                      kPremul_SkAlphaType,
358*c8dee2aaSAndroid Build Coastguard Worker                                                      nullptr);
359*c8dee2aaSAndroid Build Coastguard Worker         SkImageInfo dstIInfo = SkImageInfo::Make(texDims.width(),
360*c8dee2aaSAndroid Build Coastguard Worker                                                  texDims.height(),
361*c8dee2aaSAndroid Build Coastguard Worker                                                  kRGBA_8888_SkColorType,
362*c8dee2aaSAndroid Build Coastguard Worker                                                  kPremul_SkAlphaType,
363*c8dee2aaSAndroid Build Coastguard Worker                                                  nullptr);
364*c8dee2aaSAndroid Build Coastguard Worker 
365*c8dee2aaSAndroid Build Coastguard Worker         SkBitmap bitmap;
366*c8dee2aaSAndroid Build Coastguard Worker         bitmap.allocPixels(dstIInfo);
367*c8dee2aaSAndroid Build Coastguard Worker 
368*c8dee2aaSAndroid Build Coastguard Worker         bool success = readImage->readPixels(context, bitmap.pixmap(), dstRect.fLeft, dstRect.fTop);
369*c8dee2aaSAndroid Build Coastguard Worker         if (!success) {
370*c8dee2aaSAndroid Build Coastguard Worker             ERRORF(reporter, "Failed to read pixels");
371*c8dee2aaSAndroid Build Coastguard Worker             return;
372*c8dee2aaSAndroid Build Coastguard Worker         }
373*c8dee2aaSAndroid Build Coastguard Worker         auto pix = static_cast<const uint32_t*>(bitmap.getAddr(0, 0));
374*c8dee2aaSAndroid Build Coastguard Worker         for (int x = 0; x < 50; ++x) {
375*c8dee2aaSAndroid Build Coastguard Worker             for (int y = 0; y < 50; ++y) {
376*c8dee2aaSAndroid Build Coastguard Worker                 uint32_t pixColor = pix[x + y * 50];
377*c8dee2aaSAndroid Build Coastguard Worker                 if (pixColor != 0xFFFF0000) {
378*c8dee2aaSAndroid Build Coastguard Worker                     ERRORF(reporter, "Didn't get a blue pixel at %d, %d. Got 0x%8X",
379*c8dee2aaSAndroid Build Coastguard Worker                            x, y, pixColor);
380*c8dee2aaSAndroid Build Coastguard Worker                     continue;
381*c8dee2aaSAndroid Build Coastguard Worker                 }
382*c8dee2aaSAndroid Build Coastguard Worker             }
383*c8dee2aaSAndroid Build Coastguard Worker         }
384*c8dee2aaSAndroid Build Coastguard Worker     }
385*c8dee2aaSAndroid Build Coastguard Worker     sourceImage.reset();
386*c8dee2aaSAndroid Build Coastguard Worker     // Need to make sure the gpu is fully finished before deleting the textures
387*c8dee2aaSAndroid Build Coastguard Worker     context->flushAndSubmit(GrSyncCpu::kYes);
388*c8dee2aaSAndroid Build Coastguard Worker     context->deleteBackendTexture(sourceTexture);
389*c8dee2aaSAndroid Build Coastguard Worker     context->deleteBackendTexture(texture1);
390*c8dee2aaSAndroid Build Coastguard Worker     context->deleteBackendTexture(texture2);
391*c8dee2aaSAndroid Build Coastguard Worker }
392