blob: db7510c1dee6fd11aa696190f683825bb319fb49 [file] [log] [blame]
Robert Phillipse837e612019-11-15 11:02:50 -05001/*
2 * Copyright 2019 Google LLC
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
Robert Phillips6d344c32020-07-06 10:56:46 -04007
8#include "include/gpu/GrDirectContext.h"
Michael Ludwigfe13ca32019-11-21 10:26:41 -05009#include "src/core/SkBlendModePriv.h"
Robert Phillipse837e612019-11-15 11:02:50 -050010#include "src/gpu/GrContextPriv.h"
Robert Phillipse19babf2020-04-06 13:57:30 -040011#include "src/gpu/GrProxyProvider.h"
Robert Phillipse837e612019-11-15 11:02:50 -050012#include "src/gpu/GrRenderTargetContext.h"
13#include "src/gpu/ops/GrFillRectOp.h"
14#include "src/gpu/ops/GrTextureOp.h"
15#include "tests/Test.h"
16
Robert Phillipsfe4b4812020-07-17 14:15:51 -040017static std::unique_ptr<GrRenderTargetContext> new_RTC(GrRecordingContext* rContext) {
Greg Daniele20fcad2020-01-08 11:52:34 -050018 return GrRenderTargetContext::Make(
Robert Phillipsfe4b4812020-07-17 14:15:51 -040019 rContext, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kExact, {128, 128});
Robert Phillipse837e612019-11-15 11:02:50 -050020}
21
Robert Phillipsfe4b4812020-07-17 14:15:51 -040022sk_sp<GrSurfaceProxy> create_proxy(GrRecordingContext* rContext) {
Brian Salomona56a7462020-02-07 14:17:25 -050023 static constexpr SkISize kDimensions = {128, 128};
Robert Phillipse837e612019-11-15 11:02:50 -050024
Robert Phillipsfe4b4812020-07-17 14:15:51 -040025 const GrBackendFormat format = rContext->priv().caps()->getDefaultBackendFormat(
Robert Phillipse837e612019-11-15 11:02:50 -050026 GrColorType::kRGBA_8888,
27 GrRenderable::kYes);
Robert Phillipsfe4b4812020-07-17 14:15:51 -040028 return rContext->priv().proxyProvider()->createProxy(
Brian Salomondf1bd6d2020-03-26 20:37:01 -040029 format, kDimensions, GrRenderable::kYes, 1, GrMipMapped::kNo, SkBackingFit::kExact,
30 SkBudgeted::kNo, GrProtected::kNo, GrInternalSurfaceFlags::kNone);
Robert Phillipse837e612019-11-15 11:02:50 -050031}
Robert Phillipse837e612019-11-15 11:02:50 -050032
33typedef GrQuadAAFlags (*PerQuadAAFunc)(int i);
34
Robert Phillipsfe4b4812020-07-17 14:15:51 -040035typedef void (*BulkRectTest)(skiatest::Reporter*,
36 GrDirectContext*,
37 PerQuadAAFunc perQuadAA,
38 GrAAType overallAA,
39 SkBlendMode,
40 int requestedTotNumQuads,
41 int expectedNumOps);
Robert Phillipse837e612019-11-15 11:02:50 -050042
43//-------------------------------------------------------------------------------------------------
Robert Phillipsfe4b4812020-07-17 14:15:51 -040044static void bulk_fill_rect_create_test(skiatest::Reporter* reporter, GrDirectContext* dContext,
Robert Phillipse837e612019-11-15 11:02:50 -050045 PerQuadAAFunc perQuadAA, GrAAType overallAA,
Michael Ludwigfe13ca32019-11-21 10:26:41 -050046 SkBlendMode blendMode,
Robert Phillipse837e612019-11-15 11:02:50 -050047 int requestedTotNumQuads, int expectedNumOps) {
48
Robert Phillipsfe4b4812020-07-17 14:15:51 -040049 std::unique_ptr<GrRenderTargetContext> rtc = new_RTC(dContext);
Robert Phillipse837e612019-11-15 11:02:50 -050050
51 auto quads = new GrRenderTargetContext::QuadSetEntry[requestedTotNumQuads];
52
53 for (int i = 0; i < requestedTotNumQuads; ++i) {
54 quads[i].fRect = SkRect::MakeWH(100.5f, 100.5f); // prevent the int non-AA optimization
55 quads[i].fColor = SK_PMColor4fWHITE;
56 quads[i].fLocalMatrix = SkMatrix::I();
57 quads[i].fAAFlags = perQuadAA(i);
58 }
59
60 GrPaint paint;
Michael Ludwigfe13ca32019-11-21 10:26:41 -050061 paint.setXPFactory(SkBlendMode_AsXPFactory(blendMode));
Robert Phillipsfe4b4812020-07-17 14:15:51 -040062 GrFillRectOp::AddFillRectOps(rtc.get(), nullptr, dContext, std::move(paint), overallAA,
Robert Phillipse837e612019-11-15 11:02:50 -050063 SkMatrix::I(), quads, requestedTotNumQuads);
64
65 GrOpsTask* opsTask = rtc->testingOnly_PeekLastOpsTask();
66 int actualNumOps = opsTask->numOpChains();
67
68 int actualTotNumQuads = 0;
69
70 for (int i = 0; i < actualNumOps; ++i) {
71 const GrOp* tmp = opsTask->getChain(i);
72 REPORTER_ASSERT(reporter, tmp->classID() == GrFillRectOp::ClassID());
73 REPORTER_ASSERT(reporter, tmp->isChainTail());
74 actualTotNumQuads += ((GrDrawOp*) tmp)->numQuads();
75 }
76
77 REPORTER_ASSERT(reporter, expectedNumOps == actualNumOps);
78 REPORTER_ASSERT(reporter, requestedTotNumQuads == actualTotNumQuads);
79
Robert Phillipsfe4b4812020-07-17 14:15:51 -040080 dContext->flushAndSubmit();
Robert Phillipse837e612019-11-15 11:02:50 -050081
82 delete[] quads;
83}
84
Robert Phillipse837e612019-11-15 11:02:50 -050085//-------------------------------------------------------------------------------------------------
Robert Phillipsfe4b4812020-07-17 14:15:51 -040086static void bulk_texture_rect_create_test(skiatest::Reporter* reporter, GrDirectContext* dContext,
Robert Phillipse837e612019-11-15 11:02:50 -050087 PerQuadAAFunc perQuadAA, GrAAType overallAA,
Michael Ludwigfe13ca32019-11-21 10:26:41 -050088 SkBlendMode blendMode,
Robert Phillipse837e612019-11-15 11:02:50 -050089 int requestedTotNumQuads, int expectedNumOps) {
90
Robert Phillipsfe4b4812020-07-17 14:15:51 -040091 std::unique_ptr<GrRenderTargetContext> rtc = new_RTC(dContext);
Robert Phillipse837e612019-11-15 11:02:50 -050092
Robert Phillipsfe4b4812020-07-17 14:15:51 -040093 sk_sp<GrSurfaceProxy> proxyA = create_proxy(dContext);
94 sk_sp<GrSurfaceProxy> proxyB = create_proxy(dContext);
Michael Ludwigfe13ca32019-11-21 10:26:41 -050095 GrSurfaceProxyView proxyViewA(std::move(proxyA), kTopLeft_GrSurfaceOrigin, GrSwizzle::RGBA());
96 GrSurfaceProxyView proxyViewB(std::move(proxyB), kTopLeft_GrSurfaceOrigin, GrSwizzle::RGBA());
Robert Phillipse837e612019-11-15 11:02:50 -050097
98 auto set = new GrRenderTargetContext::TextureSetEntry[requestedTotNumQuads];
99
100 for (int i = 0; i < requestedTotNumQuads; ++i) {
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500101 // Alternate between two proxies to prevent op merging if the batch API was forced to submit
102 // one op at a time (to work, this does require that all fDstRects overlap).
103 set[i].fProxyView = i % 2 == 0 ? proxyViewA : proxyViewB;
Brian Salomonfc118442019-11-22 19:09:27 -0500104 set[i].fSrcAlphaType = kPremul_SkAlphaType;
Robert Phillipse837e612019-11-15 11:02:50 -0500105 set[i].fSrcRect = SkRect::MakeWH(100.0f, 100.0f);
106 set[i].fDstRect = SkRect::MakeWH(100.5f, 100.5f); // prevent the int non-AA optimization
107 set[i].fDstClipQuad = nullptr;
108 set[i].fPreViewMatrix = nullptr;
Michael Ludwig1c66ad92020-07-10 08:59:44 -0400109 set[i].fColor = {1.f, 1.f, 1.f, 1.f};
Robert Phillipse837e612019-11-15 11:02:50 -0500110 set[i].fAAFlags = perQuadAA(i);
111 }
112
Robert Phillipsfe4b4812020-07-17 14:15:51 -0400113 GrTextureOp::AddTextureSetOps(rtc.get(), nullptr, dContext, set, requestedTotNumQuads,
Michael Ludwig379e4962019-12-06 13:21:26 -0500114 requestedTotNumQuads, // We alternate so proxyCnt == cnt
115 GrSamplerState::Filter::kNearest,
116 GrTextureOp::Saturate::kYes,
117 blendMode,
118 overallAA,
119 SkCanvas::kStrict_SrcRectConstraint,
120 SkMatrix::I(), nullptr);
Robert Phillipse837e612019-11-15 11:02:50 -0500121
122 GrOpsTask* opsTask = rtc->testingOnly_PeekLastOpsTask();
123 int actualNumOps = opsTask->numOpChains();
124
125 int actualTotNumQuads = 0;
126
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500127 if (blendMode != SkBlendMode::kSrcOver ||
Robert Phillipsfe4b4812020-07-17 14:15:51 -0400128 !dContext->priv().caps()->dynamicStateArrayGeometryProcessorTextureSupport()) {
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500129 // In either of these two cases, GrTextureOp creates one op per quad instead. Since
130 // each entry alternates proxies but overlaps geometrically, this will prevent the ops
131 // from being merged back into fewer ops.
132 expectedNumOps = requestedTotNumQuads;
133 }
134 uint32_t expectedOpID = blendMode == SkBlendMode::kSrcOver ? GrTextureOp::ClassID()
135 : GrFillRectOp::ClassID();
Robert Phillipse837e612019-11-15 11:02:50 -0500136 for (int i = 0; i < actualNumOps; ++i) {
137 const GrOp* tmp = opsTask->getChain(i);
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500138 REPORTER_ASSERT(reporter, tmp->classID() == expectedOpID);
Robert Phillipse837e612019-11-15 11:02:50 -0500139 REPORTER_ASSERT(reporter, tmp->isChainTail());
140 actualTotNumQuads += ((GrDrawOp*) tmp)->numQuads();
141 }
142
143 REPORTER_ASSERT(reporter, expectedNumOps == actualNumOps);
144 REPORTER_ASSERT(reporter, requestedTotNumQuads == actualTotNumQuads);
145
Robert Phillipsfe4b4812020-07-17 14:15:51 -0400146 dContext->flushAndSubmit();
Robert Phillipse837e612019-11-15 11:02:50 -0500147
148 delete[] set;
149}
Robert Phillipse837e612019-11-15 11:02:50 -0500150
151//-------------------------------------------------------------------------------------------------
Robert Phillipsfe4b4812020-07-17 14:15:51 -0400152static void run_test(GrDirectContext* dContext, skiatest::Reporter* reporter, BulkRectTest test) {
Robert Phillipse837e612019-11-15 11:02:50 -0500153 // This is the simple case where there is no AA at all. We expect 2 non-AA clumps of quads.
154 {
155 auto noAA = [](int i) -> GrQuadAAFlags {
156 return GrQuadAAFlags::kNone;
157 };
158
159 static const int kNumExpectedOps = 2;
160
Robert Phillipsfe4b4812020-07-17 14:15:51 -0400161 test(reporter, dContext, noAA, GrAAType::kNone, SkBlendMode::kSrcOver,
Robert Phillipse837e612019-11-15 11:02:50 -0500162 2*GrResourceProvider::MaxNumNonAAQuads(), kNumExpectedOps);
163 }
164
165 // This is the same as the above case except the overall AA is kCoverage. However, since
166 // the per-quad AA is still none, all the quads should be downgraded to non-AA.
167 {
168 auto noAA = [](int i) -> GrQuadAAFlags {
169 return GrQuadAAFlags::kNone;
170 };
171
172 static const int kNumExpectedOps = 2;
173
Robert Phillipsfe4b4812020-07-17 14:15:51 -0400174 test(reporter, dContext, noAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
Robert Phillipse837e612019-11-15 11:02:50 -0500175 2*GrResourceProvider::MaxNumNonAAQuads(), kNumExpectedOps);
176 }
177
178 // This case has an overall AA of kCoverage but the per-quad AA alternates.
179 // We should end up with several aa-sized clumps
180 {
181 auto alternateAA = [](int i) -> GrQuadAAFlags {
182 return (i % 2) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
183 };
184
185 int numExpectedOps = 2*GrResourceProvider::MaxNumNonAAQuads() /
186 GrResourceProvider::MaxNumAAQuads();
187
Robert Phillipsfe4b4812020-07-17 14:15:51 -0400188 test(reporter, dContext, alternateAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
Robert Phillipse837e612019-11-15 11:02:50 -0500189 2*GrResourceProvider::MaxNumNonAAQuads(), numExpectedOps);
190 }
191
192 // In this case we have a run of MaxNumAAQuads non-AA quads and then AA quads. This
193 // exercises the case where we have a clump of quads that can't be upgraded to AA bc of
194 // its size. We expect one clump of non-AA quads followed by one clump of AA quads.
195 {
196 auto runOfNonAA = [](int i) -> GrQuadAAFlags {
197 return (i < GrResourceProvider::MaxNumAAQuads()) ? GrQuadAAFlags::kNone
198 : GrQuadAAFlags::kAll;
199 };
200
201 static const int kNumExpectedOps = 2;
202
Robert Phillipsfe4b4812020-07-17 14:15:51 -0400203 test(reporter, dContext, runOfNonAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500204 2*GrResourceProvider::MaxNumAAQuads(), kNumExpectedOps);
205 }
206
207 // In this case we use a blend mode other than src-over, which hits the GrFillRectOp fallback
208 // code path for GrTextureOp. We pass in the expected results if batching was successful, to
209 // that bulk_fill_rect_create_test batches on all modes; bulk_texture_rect_create_test is
210 // responsible for revising its expectations.
211 {
212 auto fixedAA = [](int i) -> GrQuadAAFlags {
213 return GrQuadAAFlags::kAll;
214 };
215
216 static const int kNumExpectedOps = 2;
217
Robert Phillipsfe4b4812020-07-17 14:15:51 -0400218 test(reporter, dContext, fixedAA, GrAAType::kCoverage, SkBlendMode::kSrcATop,
Robert Phillipse837e612019-11-15 11:02:50 -0500219 2*GrResourceProvider::MaxNumAAQuads(), kNumExpectedOps);
220 }
221}
222
223DEF_GPUTEST_FOR_RENDERING_CONTEXTS(BulkFillRectTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400224 run_test(ctxInfo.directContext(), reporter, bulk_fill_rect_create_test);
Robert Phillipse837e612019-11-15 11:02:50 -0500225}
226
Robert Phillipse837e612019-11-15 11:02:50 -0500227DEF_GPUTEST_FOR_RENDERING_CONTEXTS(BulkTextureRectTest, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400228 run_test(ctxInfo.directContext(), reporter, bulk_texture_rect_create_test);
Robert Phillipse837e612019-11-15 11:02:50 -0500229}