blob: 3fa1b190c84ad3e144166a93a001183181fa6a9b [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 */
Michael Ludwigfe13ca32019-11-21 10:26:41 -05007#include "src/core/SkBlendModePriv.h"
Robert Phillipse837e612019-11-15 11:02:50 -05008#include "src/gpu/GrClip.h"
9#include "src/gpu/GrContextPriv.h"
10#include "src/gpu/GrRenderTargetContext.h"
11#include "src/gpu/ops/GrFillRectOp.h"
12#include "src/gpu/ops/GrTextureOp.h"
13#include "tests/Test.h"
14
15static std::unique_ptr<GrRenderTargetContext> new_RTC(GrContext* context) {
16 return context->priv().makeDeferredRenderTargetContext(SkBackingFit::kExact, 128, 128,
17 GrColorType::kRGBA_8888, nullptr);
18}
19
Robert Phillipse837e612019-11-15 11:02:50 -050020sk_sp<GrSurfaceProxy> create_proxy(GrContext* context) {
21 GrSurfaceDesc desc;
22 desc.fConfig = kRGBA_8888_GrPixelConfig;
23 desc.fWidth = 128;
24 desc.fHeight = 128;
25
26 const GrBackendFormat format = context->priv().caps()->getDefaultBackendFormat(
27 GrColorType::kRGBA_8888,
28 GrRenderable::kYes);
29
30 return context->priv().proxyProvider()->createProxy(
31 format, desc, GrRenderable::kYes, 1, kTopLeft_GrSurfaceOrigin, GrMipMapped::kNo,
32 SkBackingFit::kExact, SkBudgeted::kNo, GrProtected::kNo, GrInternalSurfaceFlags::kNone);
33}
Robert Phillipse837e612019-11-15 11:02:50 -050034
35typedef GrQuadAAFlags (*PerQuadAAFunc)(int i);
36
37typedef void (*BulkRectTest)(skiatest::Reporter* reporter, GrContext* context,
Michael Ludwigfe13ca32019-11-21 10:26:41 -050038 PerQuadAAFunc perQuadAA, GrAAType overallAA, SkBlendMode blendMode,
Robert Phillipse837e612019-11-15 11:02:50 -050039 int requestedTotNumQuads, int expectedNumOps);
40
41//-------------------------------------------------------------------------------------------------
42static void bulk_fill_rect_create_test(skiatest::Reporter* reporter, GrContext* context,
43 PerQuadAAFunc perQuadAA, GrAAType overallAA,
Michael Ludwigfe13ca32019-11-21 10:26:41 -050044 SkBlendMode blendMode,
Robert Phillipse837e612019-11-15 11:02:50 -050045 int requestedTotNumQuads, int expectedNumOps) {
46
47 std::unique_ptr<GrRenderTargetContext> rtc = new_RTC(context);
48
49 auto quads = new GrRenderTargetContext::QuadSetEntry[requestedTotNumQuads];
50
51 for (int i = 0; i < requestedTotNumQuads; ++i) {
52 quads[i].fRect = SkRect::MakeWH(100.5f, 100.5f); // prevent the int non-AA optimization
53 quads[i].fColor = SK_PMColor4fWHITE;
54 quads[i].fLocalMatrix = SkMatrix::I();
55 quads[i].fAAFlags = perQuadAA(i);
56 }
57
58 GrPaint paint;
Michael Ludwigfe13ca32019-11-21 10:26:41 -050059 paint.setXPFactory(SkBlendMode_AsXPFactory(blendMode));
Robert Phillipse837e612019-11-15 11:02:50 -050060 GrFillRectOp::AddFillRectOps(rtc.get(), GrNoClip(), context, std::move(paint), overallAA,
61 SkMatrix::I(), quads, requestedTotNumQuads);
62
63 GrOpsTask* opsTask = rtc->testingOnly_PeekLastOpsTask();
64 int actualNumOps = opsTask->numOpChains();
65
66 int actualTotNumQuads = 0;
67
68 for (int i = 0; i < actualNumOps; ++i) {
69 const GrOp* tmp = opsTask->getChain(i);
70 REPORTER_ASSERT(reporter, tmp->classID() == GrFillRectOp::ClassID());
71 REPORTER_ASSERT(reporter, tmp->isChainTail());
72 actualTotNumQuads += ((GrDrawOp*) tmp)->numQuads();
73 }
74
75 REPORTER_ASSERT(reporter, expectedNumOps == actualNumOps);
76 REPORTER_ASSERT(reporter, requestedTotNumQuads == actualTotNumQuads);
77
78 context->flush();
79
80 delete[] quads;
81}
82
Robert Phillipse837e612019-11-15 11:02:50 -050083//-------------------------------------------------------------------------------------------------
84static void bulk_texture_rect_create_test(skiatest::Reporter* reporter, GrContext* context,
85 PerQuadAAFunc perQuadAA, GrAAType overallAA,
Michael Ludwigfe13ca32019-11-21 10:26:41 -050086 SkBlendMode blendMode,
Robert Phillipse837e612019-11-15 11:02:50 -050087 int requestedTotNumQuads, int expectedNumOps) {
88
89 std::unique_ptr<GrRenderTargetContext> rtc = new_RTC(context);
90
Michael Ludwigfe13ca32019-11-21 10:26:41 -050091 sk_sp<GrSurfaceProxy> proxyA = create_proxy(context);
92 sk_sp<GrSurfaceProxy> proxyB = create_proxy(context);
93 GrSurfaceProxyView proxyViewA(std::move(proxyA), kTopLeft_GrSurfaceOrigin, GrSwizzle::RGBA());
94 GrSurfaceProxyView proxyViewB(std::move(proxyB), kTopLeft_GrSurfaceOrigin, GrSwizzle::RGBA());
Robert Phillipse837e612019-11-15 11:02:50 -050095
96 auto set = new GrRenderTargetContext::TextureSetEntry[requestedTotNumQuads];
97
98 for (int i = 0; i < requestedTotNumQuads; ++i) {
Michael Ludwigfe13ca32019-11-21 10:26:41 -050099 // Alternate between two proxies to prevent op merging if the batch API was forced to submit
100 // one op at a time (to work, this does require that all fDstRects overlap).
101 set[i].fProxyView = i % 2 == 0 ? proxyViewA : proxyViewB;
Brian Salomon078e8fa2019-11-22 04:10:18 +0000102 set[i].fSrcColorType = GrColorType::kRGBA_8888;
Robert Phillipse837e612019-11-15 11:02:50 -0500103 set[i].fSrcRect = SkRect::MakeWH(100.0f, 100.0f);
104 set[i].fDstRect = SkRect::MakeWH(100.5f, 100.5f); // prevent the int non-AA optimization
105 set[i].fDstClipQuad = nullptr;
106 set[i].fPreViewMatrix = nullptr;
107 set[i].fAlpha = 1.0f;
108 set[i].fAAFlags = perQuadAA(i);
109 }
110
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500111 GrTextureOp::AddTextureSetOps(rtc.get(), GrNoClip(), context, set, requestedTotNumQuads,
Robert Phillipse837e612019-11-15 11:02:50 -0500112 GrSamplerState::Filter::kNearest,
113 GrTextureOp::Saturate::kYes,
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500114 blendMode,
Robert Phillipse837e612019-11-15 11:02:50 -0500115 overallAA,
116 SkCanvas::kStrict_SrcRectConstraint,
117 SkMatrix::I(), nullptr);
118
119 GrOpsTask* opsTask = rtc->testingOnly_PeekLastOpsTask();
120 int actualNumOps = opsTask->numOpChains();
121
122 int actualTotNumQuads = 0;
123
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500124 if (blendMode != SkBlendMode::kSrcOver ||
125 !context->priv().caps()->dynamicStateArrayGeometryProcessorTextureSupport()) {
126 // In either of these two cases, GrTextureOp creates one op per quad instead. Since
127 // each entry alternates proxies but overlaps geometrically, this will prevent the ops
128 // from being merged back into fewer ops.
129 expectedNumOps = requestedTotNumQuads;
130 }
131 uint32_t expectedOpID = blendMode == SkBlendMode::kSrcOver ? GrTextureOp::ClassID()
132 : GrFillRectOp::ClassID();
Robert Phillipse837e612019-11-15 11:02:50 -0500133 for (int i = 0; i < actualNumOps; ++i) {
134 const GrOp* tmp = opsTask->getChain(i);
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500135 REPORTER_ASSERT(reporter, tmp->classID() == expectedOpID);
Robert Phillipse837e612019-11-15 11:02:50 -0500136 REPORTER_ASSERT(reporter, tmp->isChainTail());
137 actualTotNumQuads += ((GrDrawOp*) tmp)->numQuads();
138 }
139
140 REPORTER_ASSERT(reporter, expectedNumOps == actualNumOps);
141 REPORTER_ASSERT(reporter, requestedTotNumQuads == actualTotNumQuads);
142
143 context->flush();
144
145 delete[] set;
146}
Robert Phillipse837e612019-11-15 11:02:50 -0500147
148//-------------------------------------------------------------------------------------------------
149static void run_test(GrContext* context, skiatest::Reporter* reporter, BulkRectTest test) {
Robert Phillipse837e612019-11-15 11:02:50 -0500150 // This is the simple case where there is no AA at all. We expect 2 non-AA clumps of quads.
151 {
152 auto noAA = [](int i) -> GrQuadAAFlags {
153 return GrQuadAAFlags::kNone;
154 };
155
156 static const int kNumExpectedOps = 2;
157
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500158 test(reporter, context, noAA, GrAAType::kNone, SkBlendMode::kSrcOver,
Robert Phillipse837e612019-11-15 11:02:50 -0500159 2*GrResourceProvider::MaxNumNonAAQuads(), kNumExpectedOps);
160 }
161
162 // This is the same as the above case except the overall AA is kCoverage. However, since
163 // the per-quad AA is still none, all the quads should be downgraded to non-AA.
164 {
165 auto noAA = [](int i) -> GrQuadAAFlags {
166 return GrQuadAAFlags::kNone;
167 };
168
169 static const int kNumExpectedOps = 2;
170
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500171 test(reporter, context, noAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
Robert Phillipse837e612019-11-15 11:02:50 -0500172 2*GrResourceProvider::MaxNumNonAAQuads(), kNumExpectedOps);
173 }
174
175 // This case has an overall AA of kCoverage but the per-quad AA alternates.
176 // We should end up with several aa-sized clumps
177 {
178 auto alternateAA = [](int i) -> GrQuadAAFlags {
179 return (i % 2) ? GrQuadAAFlags::kAll : GrQuadAAFlags::kNone;
180 };
181
182 int numExpectedOps = 2*GrResourceProvider::MaxNumNonAAQuads() /
183 GrResourceProvider::MaxNumAAQuads();
184
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500185 test(reporter, context, alternateAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
Robert Phillipse837e612019-11-15 11:02:50 -0500186 2*GrResourceProvider::MaxNumNonAAQuads(), numExpectedOps);
187 }
188
189 // In this case we have a run of MaxNumAAQuads non-AA quads and then AA quads. This
190 // exercises the case where we have a clump of quads that can't be upgraded to AA bc of
191 // its size. We expect one clump of non-AA quads followed by one clump of AA quads.
192 {
193 auto runOfNonAA = [](int i) -> GrQuadAAFlags {
194 return (i < GrResourceProvider::MaxNumAAQuads()) ? GrQuadAAFlags::kNone
195 : GrQuadAAFlags::kAll;
196 };
197
198 static const int kNumExpectedOps = 2;
199
Michael Ludwigfe13ca32019-11-21 10:26:41 -0500200 test(reporter, context, runOfNonAA, GrAAType::kCoverage, SkBlendMode::kSrcOver,
201 2*GrResourceProvider::MaxNumAAQuads(), kNumExpectedOps);
202 }
203
204 // In this case we use a blend mode other than src-over, which hits the GrFillRectOp fallback
205 // code path for GrTextureOp. We pass in the expected results if batching was successful, to
206 // that bulk_fill_rect_create_test batches on all modes; bulk_texture_rect_create_test is
207 // responsible for revising its expectations.
208 {
209 auto fixedAA = [](int i) -> GrQuadAAFlags {
210 return GrQuadAAFlags::kAll;
211 };
212
213 static const int kNumExpectedOps = 2;
214
215 test(reporter, context, fixedAA, GrAAType::kCoverage, SkBlendMode::kSrcATop,
Robert Phillipse837e612019-11-15 11:02:50 -0500216 2*GrResourceProvider::MaxNumAAQuads(), kNumExpectedOps);
217 }
218}
219
220DEF_GPUTEST_FOR_RENDERING_CONTEXTS(BulkFillRectTest, reporter, ctxInfo) {
221 run_test(ctxInfo.grContext(), reporter, bulk_fill_rect_create_test);
222}
223
Robert Phillipse837e612019-11-15 11:02:50 -0500224DEF_GPUTEST_FOR_RENDERING_CONTEXTS(BulkTextureRectTest, reporter, ctxInfo) {
225 run_test(ctxInfo.grContext(), reporter, bulk_texture_rect_create_test);
226}