xref: /aosp_15_r20/external/skia/tests/BulkRectTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
1*c8dee2aaSAndroid Build Coastguard Worker /*
2*c8dee2aaSAndroid Build Coastguard Worker  * Copyright 2019 Google LLC
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/SkBlendMode.h"
10*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkCanvas.h"
11*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkColorSpace.h"
12*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkMatrix.h"
13*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRect.h"
14*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkRefCnt.h"
15*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSamplingOptions.h"
16*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSize.h"
17*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkSurfaceProps.h"
18*c8dee2aaSAndroid Build Coastguard Worker #include "include/core/SkTypes.h"
19*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/GpuTypes.h"
20*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrBackendSurface.h"
21*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrDirectContext.h"
22*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrRecordingContext.h"
23*c8dee2aaSAndroid Build Coastguard Worker #include "include/gpu/ganesh/GrTypes.h"
24*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/SkColorData.h"
25*c8dee2aaSAndroid Build Coastguard Worker #include "include/private/gpu/ganesh/GrTypesPriv.h"
26*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/SkBackingFit.h"
27*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/Swizzle.h"
28*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrCaps.h"
29*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrColorSpaceXform.h"
30*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrDirectContextPriv.h"
31*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrOpsTypes.h"
32*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrPaint.h"
33*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrProxyProvider.h"
34*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrRecordingContextPriv.h"
35*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrResourceProvider.h"
36*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSamplerState.h"
37*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxy.h"
38*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrSurfaceProxyView.h"
39*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/GrXferProcessor.h"
40*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/SurfaceDrawContext.h"
41*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/geometry/GrQuad.h"
42*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/FillRectOp.h"
43*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrDrawOp.h"
44*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/GrOp.h"
45*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/OpsTask.h"
46*c8dee2aaSAndroid Build Coastguard Worker #include "src/gpu/ganesh/ops/TextureOp.h"
47*c8dee2aaSAndroid Build Coastguard Worker #include "tests/CtsEnforcement.h"
48*c8dee2aaSAndroid Build Coastguard Worker #include "tests/Test.h"
49*c8dee2aaSAndroid Build Coastguard Worker 
50*c8dee2aaSAndroid Build Coastguard Worker #include <cstdint>
51*c8dee2aaSAndroid Build Coastguard Worker #include <memory>
52*c8dee2aaSAndroid Build Coastguard Worker #include <utility>
53*c8dee2aaSAndroid Build Coastguard Worker 
54*c8dee2aaSAndroid Build Coastguard Worker struct GrContextOptions;
55*c8dee2aaSAndroid Build Coastguard Worker 
56*c8dee2aaSAndroid Build Coastguard Worker using namespace skgpu::ganesh;
57*c8dee2aaSAndroid Build Coastguard Worker 
new_SDC(GrRecordingContext * rContext)58*c8dee2aaSAndroid Build Coastguard Worker static std::unique_ptr<skgpu::ganesh::SurfaceDrawContext> new_SDC(GrRecordingContext* rContext) {
59*c8dee2aaSAndroid Build Coastguard Worker     return skgpu::ganesh::SurfaceDrawContext::Make(rContext,
60*c8dee2aaSAndroid Build Coastguard Worker                                                    GrColorType::kRGBA_8888,
61*c8dee2aaSAndroid Build Coastguard Worker                                                    nullptr,
62*c8dee2aaSAndroid Build Coastguard Worker                                                    SkBackingFit::kExact,
63*c8dee2aaSAndroid Build Coastguard Worker                                                    {128, 128},
64*c8dee2aaSAndroid Build Coastguard Worker                                                    SkSurfaceProps(),
65*c8dee2aaSAndroid Build Coastguard Worker                                                    /*label=*/{});
66*c8dee2aaSAndroid Build Coastguard Worker }
67*c8dee2aaSAndroid Build Coastguard Worker 
create_proxy(GrRecordingContext * rContext)68*c8dee2aaSAndroid Build Coastguard Worker static sk_sp<GrSurfaceProxy> create_proxy(GrRecordingContext* rContext) {
69*c8dee2aaSAndroid Build Coastguard Worker     using namespace skgpu;
70*c8dee2aaSAndroid Build Coastguard Worker 
71*c8dee2aaSAndroid Build Coastguard Worker     static constexpr SkISize kDimensions = {128, 128};
72*c8dee2aaSAndroid Build Coastguard Worker 
73*c8dee2aaSAndroid Build Coastguard Worker     Protected isProtected = Protected(rContext->priv().caps()->supportsProtectedContent());
74*c8dee2aaSAndroid Build Coastguard Worker 
75*c8dee2aaSAndroid Build Coastguard Worker     const GrBackendFormat format = rContext->priv().caps()->getDefaultBackendFormat(
76*c8dee2aaSAndroid Build Coastguard Worker                                                                            GrColorType::kRGBA_8888,
77*c8dee2aaSAndroid Build Coastguard Worker                                                                            GrRenderable::kYes);
78*c8dee2aaSAndroid Build Coastguard Worker     return rContext->priv().proxyProvider()->createProxy(format,
79*c8dee2aaSAndroid Build Coastguard Worker                                                          kDimensions,
80*c8dee2aaSAndroid Build Coastguard Worker                                                          GrRenderable::kYes,
81*c8dee2aaSAndroid Build Coastguard Worker                                                          1,
82*c8dee2aaSAndroid Build Coastguard Worker                                                          Mipmapped::kNo,
83*c8dee2aaSAndroid Build Coastguard Worker                                                          SkBackingFit::kExact,
84*c8dee2aaSAndroid Build Coastguard Worker                                                          Budgeted::kNo,
85*c8dee2aaSAndroid Build Coastguard Worker                                                          isProtected,
86*c8dee2aaSAndroid Build Coastguard Worker                                                          /*label=*/"CreateSurfaceProxy",
87*c8dee2aaSAndroid Build Coastguard Worker                                                          GrInternalSurfaceFlags::kNone);
88*c8dee2aaSAndroid Build Coastguard Worker }
89*c8dee2aaSAndroid Build Coastguard Worker 
90*c8dee2aaSAndroid Build Coastguard Worker typedef GrQuadAAFlags (*PerQuadAAFunc)(int i);
91*c8dee2aaSAndroid Build Coastguard Worker 
92*c8dee2aaSAndroid Build Coastguard Worker typedef void (*BulkRectTest)(skiatest::Reporter*,
93*c8dee2aaSAndroid Build Coastguard Worker                              GrDirectContext*,
94*c8dee2aaSAndroid Build Coastguard Worker                              PerQuadAAFunc,
95*c8dee2aaSAndroid Build Coastguard Worker                              GrAAType overallAA,
96*c8dee2aaSAndroid Build Coastguard Worker                              SkBlendMode,
97*c8dee2aaSAndroid Build Coastguard Worker                              bool addOneByOne,
98*c8dee2aaSAndroid Build Coastguard Worker                              bool allUniqueProxies,
99*c8dee2aaSAndroid Build Coastguard Worker                              int requestedTotNumQuads,
100*c8dee2aaSAndroid Build Coastguard Worker                              int expectedNumOps);
101*c8dee2aaSAndroid Build Coastguard Worker 
102*c8dee2aaSAndroid Build Coastguard Worker //-------------------------------------------------------------------------------------------------
fillrectop_creation_test(skiatest::Reporter * reporter,GrDirectContext * dContext,PerQuadAAFunc perQuadAA,GrAAType overallAA,SkBlendMode blendMode,bool addOneByOne,bool allUniqueProxies,int requestedTotNumQuads,int expectedNumOps)103*c8dee2aaSAndroid Build Coastguard Worker static void fillrectop_creation_test(skiatest::Reporter* reporter, GrDirectContext* dContext,
104*c8dee2aaSAndroid Build Coastguard Worker                                      PerQuadAAFunc perQuadAA, GrAAType overallAA,
105*c8dee2aaSAndroid Build Coastguard Worker                                      SkBlendMode blendMode, bool addOneByOne,
106*c8dee2aaSAndroid Build Coastguard Worker                                      bool allUniqueProxies,
107*c8dee2aaSAndroid Build Coastguard Worker                                      int requestedTotNumQuads, int expectedNumOps) {
108*c8dee2aaSAndroid Build Coastguard Worker 
109*c8dee2aaSAndroid Build Coastguard Worker     if (addOneByOne || allUniqueProxies) {
110*c8dee2aaSAndroid Build Coastguard Worker         return;
111*c8dee2aaSAndroid Build Coastguard Worker     }
112*c8dee2aaSAndroid Build Coastguard Worker 
113*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<skgpu::ganesh::SurfaceDrawContext> sdc = new_SDC(dContext);
114*c8dee2aaSAndroid Build Coastguard Worker 
115*c8dee2aaSAndroid Build Coastguard Worker     auto quads = new GrQuadSetEntry[requestedTotNumQuads];
116*c8dee2aaSAndroid Build Coastguard Worker 
117*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < requestedTotNumQuads; ++i) {
118*c8dee2aaSAndroid Build Coastguard Worker         quads[i].fRect = SkRect::MakeWH(100.5f, 100.5f); // prevent the int non-AA optimization
119*c8dee2aaSAndroid Build Coastguard Worker         quads[i].fColor = SK_PMColor4fWHITE;
120*c8dee2aaSAndroid Build Coastguard Worker         quads[i].fLocalMatrix = SkMatrix::I();
121*c8dee2aaSAndroid Build Coastguard Worker         quads[i].fAAFlags = perQuadAA(i);
122*c8dee2aaSAndroid Build Coastguard Worker     }
123*c8dee2aaSAndroid Build Coastguard Worker 
124*c8dee2aaSAndroid Build Coastguard Worker     GrPaint paint;
125*c8dee2aaSAndroid Build Coastguard Worker     paint.setXPFactory(GrXPFactory::FromBlendMode(blendMode));
126*c8dee2aaSAndroid Build Coastguard Worker 
127*c8dee2aaSAndroid Build Coastguard Worker     skgpu::ganesh::FillRectOp::AddFillRectOps(sdc.get(),
128*c8dee2aaSAndroid Build Coastguard Worker                                               nullptr,
129*c8dee2aaSAndroid Build Coastguard Worker                                               dContext,
130*c8dee2aaSAndroid Build Coastguard Worker                                               std::move(paint),
131*c8dee2aaSAndroid Build Coastguard Worker                                               overallAA,
132*c8dee2aaSAndroid Build Coastguard Worker                                               SkMatrix::I(),
133*c8dee2aaSAndroid Build Coastguard Worker                                               quads,
134*c8dee2aaSAndroid Build Coastguard Worker                                               requestedTotNumQuads);
135*c8dee2aaSAndroid Build Coastguard Worker 
136*c8dee2aaSAndroid Build Coastguard Worker     auto opsTask = sdc->testingOnly_PeekLastOpsTask();
137*c8dee2aaSAndroid Build Coastguard Worker     int actualNumOps = opsTask->numOpChains();
138*c8dee2aaSAndroid Build Coastguard Worker 
139*c8dee2aaSAndroid Build Coastguard Worker     int actualTotNumQuads = 0;
140*c8dee2aaSAndroid Build Coastguard Worker 
141*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < actualNumOps; ++i) {
142*c8dee2aaSAndroid Build Coastguard Worker         const GrOp* tmp = opsTask->getChain(i);
143*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, tmp->classID() == skgpu::ganesh::FillRectOp::ClassID());
144*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, tmp->isChainTail());
145*c8dee2aaSAndroid Build Coastguard Worker         actualTotNumQuads += ((const GrDrawOp*) tmp)->numQuads();
146*c8dee2aaSAndroid Build Coastguard Worker     }
147*c8dee2aaSAndroid Build Coastguard Worker 
148*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, expectedNumOps == actualNumOps);
149*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, requestedTotNumQuads == actualTotNumQuads);
150*c8dee2aaSAndroid Build Coastguard Worker 
151*c8dee2aaSAndroid Build Coastguard Worker     dContext->flushAndSubmit();
152*c8dee2aaSAndroid Build Coastguard Worker 
153*c8dee2aaSAndroid Build Coastguard Worker     delete[] quads;
154*c8dee2aaSAndroid Build Coastguard Worker }
155*c8dee2aaSAndroid Build Coastguard Worker 
156*c8dee2aaSAndroid Build Coastguard Worker //-------------------------------------------------------------------------------------------------
textureop_creation_test(skiatest::Reporter * reporter,GrDirectContext * dContext,PerQuadAAFunc perQuadAA,GrAAType overallAA,SkBlendMode blendMode,bool addOneByOne,bool allUniqueProxies,int requestedTotNumQuads,int expectedNumOps)157*c8dee2aaSAndroid Build Coastguard Worker static void textureop_creation_test(skiatest::Reporter* reporter, GrDirectContext* dContext,
158*c8dee2aaSAndroid Build Coastguard Worker                                     PerQuadAAFunc perQuadAA, GrAAType overallAA,
159*c8dee2aaSAndroid Build Coastguard Worker                                     SkBlendMode blendMode, bool addOneByOne,
160*c8dee2aaSAndroid Build Coastguard Worker                                     bool allUniqueProxies,
161*c8dee2aaSAndroid Build Coastguard Worker                                     int requestedTotNumQuads, int expectedNumOps) {
162*c8dee2aaSAndroid Build Coastguard Worker     std::unique_ptr<skgpu::ganesh::SurfaceDrawContext> sdc = new_SDC(dContext);
163*c8dee2aaSAndroid Build Coastguard Worker 
164*c8dee2aaSAndroid Build Coastguard Worker     GrSurfaceProxyView proxyViewA, proxyViewB;
165*c8dee2aaSAndroid Build Coastguard Worker 
166*c8dee2aaSAndroid Build Coastguard Worker     if (!allUniqueProxies) {
167*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<GrSurfaceProxy> proxyA = create_proxy(dContext);
168*c8dee2aaSAndroid Build Coastguard Worker         sk_sp<GrSurfaceProxy> proxyB = create_proxy(dContext);
169*c8dee2aaSAndroid Build Coastguard Worker         proxyViewA = GrSurfaceProxyView(std::move(proxyA),
170*c8dee2aaSAndroid Build Coastguard Worker                                         kTopLeft_GrSurfaceOrigin,
171*c8dee2aaSAndroid Build Coastguard Worker                                         skgpu::Swizzle::RGBA());
172*c8dee2aaSAndroid Build Coastguard Worker         proxyViewB = GrSurfaceProxyView(std::move(proxyB),
173*c8dee2aaSAndroid Build Coastguard Worker                                         kTopLeft_GrSurfaceOrigin,
174*c8dee2aaSAndroid Build Coastguard Worker                                         skgpu::Swizzle::RGBA());
175*c8dee2aaSAndroid Build Coastguard Worker     }
176*c8dee2aaSAndroid Build Coastguard Worker 
177*c8dee2aaSAndroid Build Coastguard Worker     auto set = new GrTextureSetEntry[requestedTotNumQuads];
178*c8dee2aaSAndroid Build Coastguard Worker 
179*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < requestedTotNumQuads; ++i) {
180*c8dee2aaSAndroid Build Coastguard Worker         if (!allUniqueProxies) {
181*c8dee2aaSAndroid Build Coastguard Worker             // Alternate between two proxies to prevent op merging if the batch API was forced to
182*c8dee2aaSAndroid Build Coastguard Worker             // submit one op at a time (to work, this does require that all fDstRects overlap).
183*c8dee2aaSAndroid Build Coastguard Worker             set[i].fProxyView = i % 2 == 0 ? proxyViewA : proxyViewB;
184*c8dee2aaSAndroid Build Coastguard Worker         } else {
185*c8dee2aaSAndroid Build Coastguard Worker             // Each op gets its own proxy to force chaining only
186*c8dee2aaSAndroid Build Coastguard Worker             sk_sp<GrSurfaceProxy> proxyA = create_proxy(dContext);
187*c8dee2aaSAndroid Build Coastguard Worker             set[i].fProxyView = GrSurfaceProxyView(std::move(proxyA),
188*c8dee2aaSAndroid Build Coastguard Worker                                                    kTopLeft_GrSurfaceOrigin,
189*c8dee2aaSAndroid Build Coastguard Worker                                                    skgpu::Swizzle::RGBA());
190*c8dee2aaSAndroid Build Coastguard Worker         }
191*c8dee2aaSAndroid Build Coastguard Worker 
192*c8dee2aaSAndroid Build Coastguard Worker         set[i].fSrcAlphaType = kPremul_SkAlphaType;
193*c8dee2aaSAndroid Build Coastguard Worker         set[i].fSrcRect = SkRect::MakeWH(100.0f, 100.0f);
194*c8dee2aaSAndroid Build Coastguard Worker         set[i].fDstRect = SkRect::MakeWH(100.5f, 100.5f); // prevent the int non-AA optimization
195*c8dee2aaSAndroid Build Coastguard Worker         set[i].fDstClipQuad = nullptr;
196*c8dee2aaSAndroid Build Coastguard Worker         set[i].fPreViewMatrix = nullptr;
197*c8dee2aaSAndroid Build Coastguard Worker         set[i].fColor = {1.f, 1.f, 1.f, 1.f};
198*c8dee2aaSAndroid Build Coastguard Worker         set[i].fAAFlags = perQuadAA(i);
199*c8dee2aaSAndroid Build Coastguard Worker     }
200*c8dee2aaSAndroid Build Coastguard Worker 
201*c8dee2aaSAndroid Build Coastguard Worker     if (addOneByOne) {
202*c8dee2aaSAndroid Build Coastguard Worker         for (int i = 0; i < requestedTotNumQuads; ++i) {
203*c8dee2aaSAndroid Build Coastguard Worker             DrawQuad quad;
204*c8dee2aaSAndroid Build Coastguard Worker 
205*c8dee2aaSAndroid Build Coastguard Worker             quad.fDevice = GrQuad::MakeFromRect(set[i].fDstRect,  SkMatrix::I());
206*c8dee2aaSAndroid Build Coastguard Worker             quad.fLocal = GrQuad(set[i].fSrcRect);
207*c8dee2aaSAndroid Build Coastguard Worker             quad.fEdgeFlags = set[i].fAAFlags;
208*c8dee2aaSAndroid Build Coastguard Worker 
209*c8dee2aaSAndroid Build Coastguard Worker             GrOp::Owner op = TextureOp::Make(dContext,
210*c8dee2aaSAndroid Build Coastguard Worker                                              set[i].fProxyView,
211*c8dee2aaSAndroid Build Coastguard Worker                                              set[i].fSrcAlphaType,
212*c8dee2aaSAndroid Build Coastguard Worker                                              nullptr,
213*c8dee2aaSAndroid Build Coastguard Worker                                              GrSamplerState::Filter::kNearest,
214*c8dee2aaSAndroid Build Coastguard Worker                                              GrSamplerState::MipmapMode::kNone,
215*c8dee2aaSAndroid Build Coastguard Worker                                              set[i].fColor,
216*c8dee2aaSAndroid Build Coastguard Worker                                              TextureOp::Saturate::kYes,
217*c8dee2aaSAndroid Build Coastguard Worker                                              blendMode,
218*c8dee2aaSAndroid Build Coastguard Worker                                              overallAA,
219*c8dee2aaSAndroid Build Coastguard Worker                                              &quad,
220*c8dee2aaSAndroid Build Coastguard Worker                                              nullptr);
221*c8dee2aaSAndroid Build Coastguard Worker             sdc->addDrawOp(nullptr, std::move(op));
222*c8dee2aaSAndroid Build Coastguard Worker         }
223*c8dee2aaSAndroid Build Coastguard Worker     } else {
224*c8dee2aaSAndroid Build Coastguard Worker         TextureOp::AddTextureSetOps(sdc.get(),
225*c8dee2aaSAndroid Build Coastguard Worker                                     nullptr,
226*c8dee2aaSAndroid Build Coastguard Worker                                     dContext,
227*c8dee2aaSAndroid Build Coastguard Worker                                     set,
228*c8dee2aaSAndroid Build Coastguard Worker                                     requestedTotNumQuads,
229*c8dee2aaSAndroid Build Coastguard Worker                                     requestedTotNumQuads,  // We alternate so proxyCnt == cnt
230*c8dee2aaSAndroid Build Coastguard Worker                                     GrSamplerState::Filter::kNearest,
231*c8dee2aaSAndroid Build Coastguard Worker                                     GrSamplerState::MipmapMode::kNone,
232*c8dee2aaSAndroid Build Coastguard Worker                                     TextureOp::Saturate::kYes,
233*c8dee2aaSAndroid Build Coastguard Worker                                     blendMode,
234*c8dee2aaSAndroid Build Coastguard Worker                                     overallAA,
235*c8dee2aaSAndroid Build Coastguard Worker                                     SkCanvas::kStrict_SrcRectConstraint,
236*c8dee2aaSAndroid Build Coastguard Worker                                     SkMatrix::I(),
237*c8dee2aaSAndroid Build Coastguard Worker                                     nullptr);
238*c8dee2aaSAndroid Build Coastguard Worker     }
239*c8dee2aaSAndroid Build Coastguard Worker 
240*c8dee2aaSAndroid Build Coastguard Worker     auto opsTask = sdc->testingOnly_PeekLastOpsTask();
241*c8dee2aaSAndroid Build Coastguard Worker     int actualNumOps = opsTask->numOpChains();
242*c8dee2aaSAndroid Build Coastguard Worker 
243*c8dee2aaSAndroid Build Coastguard Worker     int actualTotNumQuads = 0;
244*c8dee2aaSAndroid Build Coastguard Worker 
245*c8dee2aaSAndroid Build Coastguard Worker     if (blendMode != SkBlendMode::kSrcOver ||
246*c8dee2aaSAndroid Build Coastguard Worker         !dContext->priv().caps()->dynamicStateArrayGeometryProcessorTextureSupport()) {
247*c8dee2aaSAndroid Build Coastguard Worker         // In either of these two cases, TextureOp creates one op per quad instead. Since
248*c8dee2aaSAndroid Build Coastguard Worker         // each entry alternates proxies but overlaps geometrically, this will prevent the ops
249*c8dee2aaSAndroid Build Coastguard Worker         // from being merged back into fewer ops.
250*c8dee2aaSAndroid Build Coastguard Worker         expectedNumOps = requestedTotNumQuads;
251*c8dee2aaSAndroid Build Coastguard Worker     }
252*c8dee2aaSAndroid Build Coastguard Worker     uint32_t expectedOpID = blendMode == SkBlendMode::kSrcOver
253*c8dee2aaSAndroid Build Coastguard Worker                                     ? TextureOp::ClassID()
254*c8dee2aaSAndroid Build Coastguard Worker                                     : skgpu::ganesh::FillRectOp::ClassID();
255*c8dee2aaSAndroid Build Coastguard Worker     for (int i = 0; i < actualNumOps; ++i) {
256*c8dee2aaSAndroid Build Coastguard Worker         const GrOp* tmp = opsTask->getChain(i);
257*c8dee2aaSAndroid Build Coastguard Worker         REPORTER_ASSERT(reporter, allUniqueProxies || tmp->isChainTail());
258*c8dee2aaSAndroid Build Coastguard Worker         while (tmp) {
259*c8dee2aaSAndroid Build Coastguard Worker             REPORTER_ASSERT(reporter, tmp->classID() == expectedOpID);
260*c8dee2aaSAndroid Build Coastguard Worker             actualTotNumQuads += ((const GrDrawOp*) tmp)->numQuads();
261*c8dee2aaSAndroid Build Coastguard Worker             tmp = tmp->nextInChain();
262*c8dee2aaSAndroid Build Coastguard Worker         }
263*c8dee2aaSAndroid Build Coastguard Worker     }
264*c8dee2aaSAndroid Build Coastguard Worker 
265*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, expectedNumOps == actualNumOps);
266*c8dee2aaSAndroid Build Coastguard Worker     REPORTER_ASSERT(reporter, requestedTotNumQuads == actualTotNumQuads);
267*c8dee2aaSAndroid Build Coastguard Worker 
268*c8dee2aaSAndroid Build Coastguard Worker     dContext->flushAndSubmit();
269*c8dee2aaSAndroid Build Coastguard Worker 
270*c8dee2aaSAndroid Build Coastguard Worker     delete[] set;
271*c8dee2aaSAndroid Build Coastguard Worker }
272*c8dee2aaSAndroid Build Coastguard Worker 
273*c8dee2aaSAndroid Build Coastguard Worker //-------------------------------------------------------------------------------------------------
run_test(GrDirectContext * dContext,skiatest::Reporter * reporter,BulkRectTest test)274*c8dee2aaSAndroid Build Coastguard Worker static void run_test(GrDirectContext* dContext, skiatest::Reporter* reporter, BulkRectTest test) {
275*c8dee2aaSAndroid Build Coastguard Worker 
276*c8dee2aaSAndroid Build Coastguard Worker     // This is the simple case where there is no AA at all. We expect 2 non-AA clumps of quads.
277*c8dee2aaSAndroid Build Coastguard Worker     {
278*c8dee2aaSAndroid Build Coastguard Worker         auto noAA = [](int i) -> GrQuadAAFlags {
279*c8dee2aaSAndroid Build Coastguard Worker             return GrQuadAAFlags::kNone;
280*c8dee2aaSAndroid Build Coastguard Worker         };
281*c8dee2aaSAndroid Build Coastguard Worker 
282*c8dee2aaSAndroid Build Coastguard Worker         static const int kNumExpectedOps = 2;
283*c8dee2aaSAndroid Build Coastguard Worker 
284*c8dee2aaSAndroid Build Coastguard Worker         test(reporter, dContext, noAA, GrAAType::kNone, SkBlendMode::kSrcOver,
285*c8dee2aaSAndroid Build Coastguard Worker              false, false, 2*GrResourceProvider::MaxNumNonAAQuads(), kNumExpectedOps);
286*c8dee2aaSAndroid Build Coastguard Worker     }
287*c8dee2aaSAndroid Build Coastguard Worker 
288*c8dee2aaSAndroid Build Coastguard Worker     // This is the same as the above case except the overall AA is kCoverage. However, since
289*c8dee2aaSAndroid Build Coastguard Worker     // the per-quad AA is still none, all the quads should be downgraded to non-AA.
290*c8dee2aaSAndroid Build Coastguard Worker     {
291*c8dee2aaSAndroid Build Coastguard Worker         auto noAA = [](int i) -> GrQuadAAFlags {
292*c8dee2aaSAndroid Build Coastguard Worker             return GrQuadAAFlags::kNone;
293*c8dee2aaSAndroid Build Coastguard Worker         };
294*c8dee2aaSAndroid Build Coastguard Worker 
295*c8dee2aaSAndroid Build Coastguard Worker         static const int kNumExpectedOps = 2;
296*c8dee2aaSAndroid Build Coastguard Worker 
297*c8dee2aaSAndroid Build Coastguard Worker         test(reporter, dContext, noAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
298*c8dee2aaSAndroid Build Coastguard Worker              false, false, 2*GrResourceProvider::MaxNumNonAAQuads(), kNumExpectedOps);
299*c8dee2aaSAndroid Build Coastguard Worker     }
300*c8dee2aaSAndroid Build Coastguard Worker 
301*c8dee2aaSAndroid Build Coastguard Worker     // This case has an overall AA of kCoverage but the per-quad AA alternates.
302*c8dee2aaSAndroid Build Coastguard Worker     // We should end up with several aa-sized clumps
303*c8dee2aaSAndroid Build Coastguard Worker     {
304*c8dee2aaSAndroid Build Coastguard Worker         auto alternateAA = [](int i) -> GrQuadAAFlags {
305*c8dee2aaSAndroid Build Coastguard Worker             return (i % 2) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
306*c8dee2aaSAndroid Build Coastguard Worker         };
307*c8dee2aaSAndroid Build Coastguard Worker 
308*c8dee2aaSAndroid Build Coastguard Worker         int numExpectedOps = 2*GrResourceProvider::MaxNumNonAAQuads() /
309*c8dee2aaSAndroid Build Coastguard Worker                                                  GrResourceProvider::MaxNumAAQuads();
310*c8dee2aaSAndroid Build Coastguard Worker 
311*c8dee2aaSAndroid Build Coastguard Worker         test(reporter, dContext, alternateAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
312*c8dee2aaSAndroid Build Coastguard Worker              false, false, 2*GrResourceProvider::MaxNumNonAAQuads(), numExpectedOps);
313*c8dee2aaSAndroid Build Coastguard Worker     }
314*c8dee2aaSAndroid Build Coastguard Worker 
315*c8dee2aaSAndroid Build Coastguard Worker     // In this case we have a run of MaxNumAAQuads non-AA quads and then AA quads. This
316*c8dee2aaSAndroid Build Coastguard Worker     // exercises the case where we have a clump of quads that can't be upgraded to AA bc of
317*c8dee2aaSAndroid Build Coastguard Worker     // its size. We expect one clump of non-AA quads followed by one clump of AA quads.
318*c8dee2aaSAndroid Build Coastguard Worker     {
319*c8dee2aaSAndroid Build Coastguard Worker         auto runOfNonAA = [](int i) -> GrQuadAAFlags {
320*c8dee2aaSAndroid Build Coastguard Worker             return (i < GrResourceProvider::MaxNumAAQuads()) ? GrQuadAAFlags::kNone
321*c8dee2aaSAndroid Build Coastguard Worker                                                              : GrQuadAAFlags::kAll;
322*c8dee2aaSAndroid Build Coastguard Worker         };
323*c8dee2aaSAndroid Build Coastguard Worker 
324*c8dee2aaSAndroid Build Coastguard Worker         static const int kNumExpectedOps = 2;
325*c8dee2aaSAndroid Build Coastguard Worker 
326*c8dee2aaSAndroid Build Coastguard Worker         test(reporter, dContext, runOfNonAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
327*c8dee2aaSAndroid Build Coastguard Worker              false, false, 2*GrResourceProvider::MaxNumAAQuads(), kNumExpectedOps);
328*c8dee2aaSAndroid Build Coastguard Worker     }
329*c8dee2aaSAndroid Build Coastguard Worker 
330*c8dee2aaSAndroid Build Coastguard Worker     // In this case we use a blend mode other than src-over, which hits the FillRectOp fallback
331*c8dee2aaSAndroid Build Coastguard Worker     // code path for TextureOp. We pass in the expected results if batching was successful, to
332*c8dee2aaSAndroid Build Coastguard Worker     // that bulk_fill_rect_create_test batches on all modes; bulk_texture_rect_create_test is
333*c8dee2aaSAndroid Build Coastguard Worker     // responsible for revising its expectations.
334*c8dee2aaSAndroid Build Coastguard Worker     {
335*c8dee2aaSAndroid Build Coastguard Worker         auto fixedAA = [](int i) -> GrQuadAAFlags {
336*c8dee2aaSAndroid Build Coastguard Worker             return GrQuadAAFlags::kAll;
337*c8dee2aaSAndroid Build Coastguard Worker         };
338*c8dee2aaSAndroid Build Coastguard Worker 
339*c8dee2aaSAndroid Build Coastguard Worker         static const int kNumExpectedOps = 2;
340*c8dee2aaSAndroid Build Coastguard Worker 
341*c8dee2aaSAndroid Build Coastguard Worker         test(reporter, dContext, fixedAA, GrAAType::kCoverage, SkBlendMode::kSrcATop,
342*c8dee2aaSAndroid Build Coastguard Worker              false, false, 2*GrResourceProvider::MaxNumAAQuads(), kNumExpectedOps);
343*c8dee2aaSAndroid Build Coastguard Worker     }
344*c8dee2aaSAndroid Build Coastguard Worker 
345*c8dee2aaSAndroid Build Coastguard Worker     // This repros crbug.com/1108475, where we create 1024 non-AA texture ops w/ one coverage-AA
346*c8dee2aaSAndroid Build Coastguard Worker     // texture op in the middle. Because each op has its own texture, all the texture ops
347*c8dee2aaSAndroid Build Coastguard Worker     // get chained together so the quad count can exceed the AA maximum.
348*c8dee2aaSAndroid Build Coastguard Worker     {
349*c8dee2aaSAndroid Build Coastguard Worker         auto onlyOneAA = [](int i) -> GrQuadAAFlags {
350*c8dee2aaSAndroid Build Coastguard Worker             return i == 256 ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
351*c8dee2aaSAndroid Build Coastguard Worker         };
352*c8dee2aaSAndroid Build Coastguard Worker 
353*c8dee2aaSAndroid Build Coastguard Worker         static const int kNumExpectedOps = 3;
354*c8dee2aaSAndroid Build Coastguard Worker 
355*c8dee2aaSAndroid Build Coastguard Worker         test(reporter, dContext, onlyOneAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
356*c8dee2aaSAndroid Build Coastguard Worker              true, true, 1024, kNumExpectedOps);
357*c8dee2aaSAndroid Build Coastguard Worker     }
358*c8dee2aaSAndroid Build Coastguard Worker 
359*c8dee2aaSAndroid Build Coastguard Worker     // This repros a problem related to crbug.com/1108475. In this case, the bulk creation
360*c8dee2aaSAndroid Build Coastguard Worker     // method had no way to break up the set of texture ops at the AA quad limit.
361*c8dee2aaSAndroid Build Coastguard Worker     {
362*c8dee2aaSAndroid Build Coastguard Worker         auto onlyOneAA = [](int i) -> GrQuadAAFlags {
363*c8dee2aaSAndroid Build Coastguard Worker             return i == 256 ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
364*c8dee2aaSAndroid Build Coastguard Worker         };
365*c8dee2aaSAndroid Build Coastguard Worker 
366*c8dee2aaSAndroid Build Coastguard Worker         static const int kNumExpectedOps = 2;
367*c8dee2aaSAndroid Build Coastguard Worker 
368*c8dee2aaSAndroid Build Coastguard Worker         test(reporter, dContext, onlyOneAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
369*c8dee2aaSAndroid Build Coastguard Worker              false, true, 1024, kNumExpectedOps);
370*c8dee2aaSAndroid Build Coastguard Worker     }
371*c8dee2aaSAndroid Build Coastguard Worker 
372*c8dee2aaSAndroid Build Coastguard Worker }
373*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(BulkFillRectTest,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)374*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(BulkFillRectTest,
375*c8dee2aaSAndroid Build Coastguard Worker                                        reporter,
376*c8dee2aaSAndroid Build Coastguard Worker                                        ctxInfo,
377*c8dee2aaSAndroid Build Coastguard Worker                                        CtsEnforcement::kApiLevel_T) {
378*c8dee2aaSAndroid Build Coastguard Worker     run_test(ctxInfo.directContext(), reporter, fillrectop_creation_test);
379*c8dee2aaSAndroid Build Coastguard Worker }
380*c8dee2aaSAndroid Build Coastguard Worker 
DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(BulkTextureRectTest,reporter,ctxInfo,CtsEnforcement::kApiLevel_T)381*c8dee2aaSAndroid Build Coastguard Worker DEF_GANESH_TEST_FOR_RENDERING_CONTEXTS(BulkTextureRectTest,
382*c8dee2aaSAndroid Build Coastguard Worker                                        reporter,
383*c8dee2aaSAndroid Build Coastguard Worker                                        ctxInfo,
384*c8dee2aaSAndroid Build Coastguard Worker                                        CtsEnforcement::kApiLevel_T) {
385*c8dee2aaSAndroid Build Coastguard Worker     run_test(ctxInfo.directContext(), reporter, textureop_creation_test);
386*c8dee2aaSAndroid Build Coastguard Worker }
387