blob: 2e61d242d3da2a46e9efff4ea306930b674ab4e4 [file] [log] [blame]
Robert Phillips4bc70112018-03-01 10:24:02 -05001/*
2 * Copyright 2018 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkBitmap.h"
9#include "include/core/SkColor.h"
10#include "include/core/SkColorSpace.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040011#include "include/core/SkFont.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050012#include "include/core/SkImageInfo.h"
13#include "include/core/SkMatrix.h"
14#include "include/core/SkPaint.h"
15#include "include/core/SkPoint.h"
16#include "include/core/SkRefCnt.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040017#include "include/core/SkSize.h"
18#include "include/core/SkTypes.h"
19#include "include/gpu/GrBackendSurface.h"
Robert Phillips6d344c32020-07-06 10:56:46 -040020#include "include/gpu/GrDirectContext.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050021#include "include/private/GrTypesPriv.h"
22#include "src/core/SkIPoint16.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040023#include "src/gpu/GrCaps.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050024#include "src/gpu/GrDeferredUpload.h"
Adlai Hollera0693042020-10-14 11:23:11 -040025#include "src/gpu/GrDirectContextPriv.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050026#include "src/gpu/GrDrawOpAtlas.h"
27#include "src/gpu/GrDrawingManager.h"
28#include "src/gpu/GrMemoryPool.h"
29#include "src/gpu/GrOnFlushResourceProvider.h"
30#include "src/gpu/GrOpFlushState.h"
Brian Salomoneebe7352020-12-09 16:37:04 -050031#include "src/gpu/GrSurfaceDrawContext.h"
Greg Danielf91aeb22019-06-18 09:58:02 -040032#include "src/gpu/GrTextureProxy.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050033#include "src/gpu/GrXferProcessor.h"
Herb Derby4598fa12020-06-10 14:54:22 -040034#include "src/gpu/ops/GrAtlasTextOp.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050035#include "src/gpu/ops/GrDrawOp.h"
Ben Wagner9707a7e2019-05-06 17:17:19 -040036#include "src/gpu/ops/GrOp.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050037#include "src/gpu/text/GrAtlasManager.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050038#include "tests/Test.h"
39#include "tools/gpu/GrContextFactory.h"
Ben Wagnerd90cd3b2018-05-22 10:48:08 -040040
41#include <memory>
Ben Wagner9707a7e2019-05-06 17:17:19 -040042#include <utility>
Ben Wagnerd90cd3b2018-05-22 10:48:08 -040043
44class GrResourceProvider;
Robert Phillips4bc70112018-03-01 10:24:02 -050045
46static const int kNumPlots = 2;
47static const int kPlotSize = 32;
48static const int kAtlasSize = kNumPlots * kPlotSize;
49
50int GrDrawOpAtlas::numAllocated_TestingOnly() const {
51 int count = 0;
52 for (uint32_t i = 0; i < this->maxPages(); ++i) {
Greg Daniel9715b6c2019-12-10 15:03:10 -050053 if (fViews[i].proxy()->isInstantiated()) {
Robert Phillips4bc70112018-03-01 10:24:02 -050054 ++count;
55 }
56 }
57
58 return count;
59}
60
Kevin Lubickb5502b22018-03-12 10:17:06 -040061void GrAtlasManager::setMaxPages_TestingOnly(uint32_t maxPages) {
Robert Phillipsd2e9f762018-03-07 11:54:37 -050062 for (int i = 0; i < kMaskFormatCount; i++) {
63 if (fAtlases[i]) {
Kevin Lubickb5502b22018-03-12 10:17:06 -040064 fAtlases[i]->setMaxPages_TestingOnly(maxPages);
Robert Phillipsd2e9f762018-03-07 11:54:37 -050065 }
66 }
67}
68
69void GrDrawOpAtlas::setMaxPages_TestingOnly(uint32_t maxPages) {
70 SkASSERT(!fNumActivePages);
71
72 fMaxPages = maxPages;
73}
74
Herb Derby1a496c52020-01-22 17:26:56 -050075class DummyEvict : public GrDrawOpAtlas::EvictionCallback {
76public:
Robert Phillipsf3953d02020-04-13 11:38:03 -040077 void evict(GrDrawOpAtlas::PlotLocator) override {
Herb Derby1a496c52020-01-22 17:26:56 -050078 SkASSERT(0); // The unit test shouldn't exercise this code path
79 }
80};
Robert Phillips4bc70112018-03-01 10:24:02 -050081
82static void check(skiatest::Reporter* r, GrDrawOpAtlas* atlas,
83 uint32_t expectedActive, uint32_t expectedMax, int expectedAlloced) {
84 REPORTER_ASSERT(r, expectedActive == atlas->numActivePages());
85 REPORTER_ASSERT(r, expectedMax == atlas->maxPages());
86 REPORTER_ASSERT(r, expectedAlloced == atlas->numAllocated_TestingOnly());
87}
88
89class TestingUploadTarget : public GrDeferredUploadTarget {
90public:
91 TestingUploadTarget() { }
92
Robert Phillipsd2e9f762018-03-07 11:54:37 -050093 const GrTokenTracker* tokenTracker() final { return &fTokenTracker; }
94 GrTokenTracker* writeableTokenTracker() { return &fTokenTracker; }
Robert Phillips4bc70112018-03-01 10:24:02 -050095
96 GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) final {
97 SkASSERT(0); // this test shouldn't invoke this code path
98 return fTokenTracker.nextDrawToken();
99 }
100
John Stiles1cf2c8d2020-08-13 22:58:04 -0400101 GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&& upload) final {
Robert Phillips4bc70112018-03-01 10:24:02 -0500102 return fTokenTracker.nextTokenToFlush();
103 }
104
105 void issueDrawToken() { fTokenTracker.issueDrawToken(); }
106 void flushToken() { fTokenTracker.flushToken(); }
107
108private:
109 GrTokenTracker fTokenTracker;
110
John Stiles7571f9e2020-09-02 22:42:33 -0400111 using INHERITED = GrDeferredUploadTarget;
Robert Phillips4bc70112018-03-01 10:24:02 -0500112};
113
114static bool fill_plot(GrDrawOpAtlas* atlas,
115 GrResourceProvider* resourceProvider,
116 GrDeferredUploadTarget* target,
Robert Phillips6d3bc292020-04-06 10:29:28 -0400117 GrDrawOpAtlas::AtlasLocator* atlasLocator,
Robert Phillips4bc70112018-03-01 10:24:02 -0500118 int alpha) {
119 SkImageInfo ii = SkImageInfo::MakeA8(kPlotSize, kPlotSize);
120
121 SkBitmap data;
122 data.allocPixels(ii);
123 data.eraseARGB(alpha, 0, 0, 0);
124
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500125 GrDrawOpAtlas::ErrorCode code;
Robert Phillips6d3bc292020-04-06 10:29:28 -0400126 code = atlas->addToAtlas(resourceProvider, target, kPlotSize, kPlotSize,
127 data.getAddr(0, 0), atlasLocator);
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500128 return GrDrawOpAtlas::ErrorCode::kSucceeded == code;
Robert Phillips4bc70112018-03-01 10:24:02 -0500129}
130
131
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500132// This is a basic DrawOpAtlas test. It simply verifies that multitexture atlases correctly
133// add and remove pages. Note that this is simulating flush-time behavior.
134DEF_GPUTEST_FOR_RENDERING_CONTEXTS(BasicDrawOpAtlas, reporter, ctxInfo) {
Robert Phillips6d344c32020-07-06 10:56:46 -0400135 auto context = ctxInfo.directContext();
Robert Phillips9da87e02019-02-04 13:26:26 -0500136 auto proxyProvider = context->priv().proxyProvider();
137 auto resourceProvider = context->priv().resourceProvider();
138 auto drawingManager = context->priv().drawingManager();
Robert Phillips0a15cc62019-07-30 12:49:10 -0400139 const GrCaps* caps = context->priv().caps();
Robert Phillips4bc70112018-03-01 10:24:02 -0500140
141 GrOnFlushResourceProvider onFlushResourceProvider(drawingManager);
142 TestingUploadTarget uploadTarget;
143
Robert Phillips0a15cc62019-07-30 12:49:10 -0400144 GrBackendFormat format = caps->getDefaultBackendFormat(GrColorType::kAlpha_8,
145 GrRenderable::kNo);
Greg Daniel4065d452018-11-16 15:43:41 -0500146
Herb Derby1a496c52020-01-22 17:26:56 -0500147 DummyEvict evictor;
Herb Derby0ef780b2020-01-24 15:57:11 -0500148 GrDrawOpAtlas::GenerationCounter counter;
Herb Derby1a496c52020-01-22 17:26:56 -0500149
Robert Phillips4bc70112018-03-01 10:24:02 -0500150 std::unique_ptr<GrDrawOpAtlas> atlas = GrDrawOpAtlas::Make(
151 proxyProvider,
Greg Daniel4065d452018-11-16 15:43:41 -0500152 format,
Robert Phillips42dda082019-05-14 13:29:45 -0400153 GrColorType::kAlpha_8,
Robert Phillips4bc70112018-03-01 10:24:02 -0500154 kAtlasSize, kAtlasSize,
Jim Van Verthf6206f92018-12-14 08:22:24 -0500155 kAtlasSize/kNumPlots, kAtlasSize/kNumPlots,
Herb Derby0ef780b2020-01-24 15:57:11 -0500156 &counter,
Robert Phillips4bc70112018-03-01 10:24:02 -0500157 GrDrawOpAtlas::AllowMultitexturing::kYes,
Herb Derby1a496c52020-01-22 17:26:56 -0500158 &evictor);
Robert Phillips4bc70112018-03-01 10:24:02 -0500159 check(reporter, atlas.get(), 0, 4, 0);
160
161 // Fill up the first level
Robert Phillips6d3bc292020-04-06 10:29:28 -0400162 GrDrawOpAtlas::AtlasLocator atlasLocators[kNumPlots * kNumPlots];
Robert Phillips4bc70112018-03-01 10:24:02 -0500163 for (int i = 0; i < kNumPlots * kNumPlots; ++i) {
Herb Derby4d721712020-01-24 14:31:16 -0500164 bool result = fill_plot(
Robert Phillips6d3bc292020-04-06 10:29:28 -0400165 atlas.get(), resourceProvider, &uploadTarget, &atlasLocators[i], i * 32);
Robert Phillips4bc70112018-03-01 10:24:02 -0500166 REPORTER_ASSERT(reporter, result);
167 check(reporter, atlas.get(), 1, 4, 1);
168 }
169
170 atlas->instantiate(&onFlushResourceProvider);
171 check(reporter, atlas.get(), 1, 4, 1);
172
173 // Force allocation of a second level
Robert Phillips6d3bc292020-04-06 10:29:28 -0400174 GrDrawOpAtlas::AtlasLocator atlasLocator;
175 bool result = fill_plot(atlas.get(), resourceProvider, &uploadTarget, &atlasLocator, 4 * 32);
Robert Phillips4bc70112018-03-01 10:24:02 -0500176 REPORTER_ASSERT(reporter, result);
177 check(reporter, atlas.get(), 2, 4, 2);
178
179 // Simulate a lot of draws using only the first plot. The last texture should be compacted.
180 for (int i = 0; i < 512; ++i) {
Robert Phillips6d3bc292020-04-06 10:29:28 -0400181 atlas->setLastUseToken(atlasLocators[0], uploadTarget.tokenTracker()->nextDrawToken());
Robert Phillips4bc70112018-03-01 10:24:02 -0500182 uploadTarget.issueDrawToken();
183 uploadTarget.flushToken();
184 atlas->compact(uploadTarget.tokenTracker()->nextTokenToFlush());
185 }
186
187 check(reporter, atlas.get(), 1, 4, 1);
188}
189
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500190// This test verifies that the GrAtlasTextOp::onPrepare method correctly handles a failure
191// when allocating an atlas page.
192DEF_GPUTEST_FOR_RENDERING_CONTEXTS(GrAtlasTextOpPreparation, reporter, ctxInfo) {
193
Robert Phillips6d344c32020-07-06 10:56:46 -0400194 auto context = ctxInfo.directContext();
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500195
Robert Phillips9da87e02019-02-04 13:26:26 -0500196 auto gpu = context->priv().getGpu();
197 auto resourceProvider = context->priv().resourceProvider();
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500198
Brian Salomoneebe7352020-12-09 16:37:04 -0500199 auto rtc = GrSurfaceDrawContext::Make(
Greg Daniele20fcad2020-01-08 11:52:34 -0500200 context, GrColorType::kRGBA_8888, nullptr, SkBackingFit::kApprox, {32, 32});
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500201
202 SkPaint paint;
203 paint.setColor(SK_ColorRED);
Mike Reed191e64b2019-01-02 15:35:29 -0500204
205 SkFont font;
206 font.setEdging(SkFont::Edging::kAlias);
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500207
208 const char* text = "a";
Brian Osman449b1152020-04-15 16:43:00 -0400209 SkSimpleMatrixProvider matrixProvider(SkMatrix::I());
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500210
Herb Derbyc76d4092020-10-07 16:46:15 -0400211 GrOp::Owner op =
Herb Derby4598fa12020-06-10 14:54:22 -0400212 GrAtlasTextOp::CreateOpTestingOnly(
213 rtc.get(), paint, font, matrixProvider, text, 16, 16);
Ben Wagner525e8762020-07-09 16:19:35 -0400214 if (!op) {
215 return;
216 }
Herb Derby4598fa12020-06-10 14:54:22 -0400217
Chris Dalton6ce447a2019-06-23 18:07:38 -0600218 bool hasMixedSampledCoverage = false;
Herb Derbyc76d4092020-10-07 16:46:15 -0400219 GrAtlasTextOp* atlasTextOp = (GrAtlasTextOp*)op.get();
220 atlasTextOp->finalize(
221 *context->priv().caps(), nullptr, hasMixedSampledCoverage, GrClampType::kAuto);
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500222
223 TestingUploadTarget uploadTarget;
224
Robert Phillipse5f73282019-06-18 17:15:04 -0400225 GrOpFlushState flushState(gpu, resourceProvider, uploadTarget.writeableTokenTracker());
Greg Daniel16f5c652019-10-29 11:26:01 -0400226
Brian Salomon8afde5f2020-04-01 16:22:00 -0400227 GrSurfaceProxyView surfaceView = rtc->writeSurfaceView();
Robert Phillips901aff02019-10-08 12:32:56 -0400228 GrOpFlushState::OpArgs opArgs(op.get(),
Adlai Hollere2296f72020-11-19 13:41:26 -0500229 surfaceView,
Robert Phillips901aff02019-10-08 12:32:56 -0400230 nullptr,
Greg Danield358cbe2020-09-11 09:33:54 -0400231 GrXferProcessor::DstProxyView(),
Greg Daniel42dbca52020-11-20 10:22:43 -0500232 GrXferBarrierFlags::kNone,
233 GrLoadOp::kLoad);
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500234
Leon Scroggins III3a683c82020-07-31 14:16:57 -0400235 // Modify the atlas manager so it can't allocate any pages. This will force a failure
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500236 // in the preparation of the text op
Robert Phillips9da87e02019-02-04 13:26:26 -0500237 auto atlasManager = context->priv().getAtlasManager();
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500238 unsigned int numProxies;
Greg Daniel9715b6c2019-12-10 15:03:10 -0500239 atlasManager->getViews(kA8_GrMaskFormat, &numProxies);
Robert Phillipsd2e9f762018-03-07 11:54:37 -0500240 atlasManager->setMaxPages_TestingOnly(0);
241
242 flushState.setOpArgs(&opArgs);
243 op->prepare(&flushState);
244 flushState.setOpArgs(nullptr);
245}
Herb Derby15d9ef22018-10-18 13:41:32 -0400246
Jim Van Verthf6206f92018-12-14 08:22:24 -0500247void test_atlas_config(skiatest::Reporter* reporter, int maxTextureSize, size_t maxBytes,
248 GrMaskFormat maskFormat, SkISize expectedDimensions,
249 SkISize expectedPlotDimensions) {
250 GrDrawOpAtlasConfig config(maxTextureSize, maxBytes);
251 REPORTER_ASSERT(reporter, config.atlasDimensions(maskFormat) == expectedDimensions);
252 REPORTER_ASSERT(reporter, config.plotDimensions(maskFormat) == expectedPlotDimensions);
253}
254
Herb Derby15d9ef22018-10-18 13:41:32 -0400255DEF_GPUTEST(GrDrawOpAtlasConfig_Basic, reporter, options) {
Jim Van Verthf6206f92018-12-14 08:22:24 -0500256 // 1/4 MB
257 test_atlas_config(reporter, 65536, 256 * 1024, kARGB_GrMaskFormat,
258 { 256, 256 }, { 256, 256 });
259 test_atlas_config(reporter, 65536, 256 * 1024, kA8_GrMaskFormat,
260 { 512, 512 }, { 256, 256 });
261 // 1/2 MB
262 test_atlas_config(reporter, 65536, 512 * 1024, kARGB_GrMaskFormat,
263 { 512, 256 }, { 256, 256 });
264 test_atlas_config(reporter, 65536, 512 * 1024, kA8_GrMaskFormat,
265 { 1024, 512 }, { 256, 256 });
266 // 1 MB
267 test_atlas_config(reporter, 65536, 1024 * 1024, kARGB_GrMaskFormat,
268 { 512, 512 }, { 256, 256 });
269 test_atlas_config(reporter, 65536, 1024 * 1024, kA8_GrMaskFormat,
270 { 1024, 1024 }, { 256, 256 });
271 // 2 MB
272 test_atlas_config(reporter, 65536, 2 * 1024 * 1024, kARGB_GrMaskFormat,
273 { 1024, 512 }, { 256, 256 });
274 test_atlas_config(reporter, 65536, 2 * 1024 * 1024, kA8_GrMaskFormat,
275 { 2048, 1024 }, { 512, 256 });
276 // 4 MB
277 test_atlas_config(reporter, 65536, 4 * 1024 * 1024, kARGB_GrMaskFormat,
278 { 1024, 1024 }, { 256, 256 });
279 test_atlas_config(reporter, 65536, 4 * 1024 * 1024, kA8_GrMaskFormat,
Jim Van Verth578b0892018-12-20 20:48:55 +0000280 { 2048, 2048 }, { 512, 512 });
Jim Van Verthf6206f92018-12-14 08:22:24 -0500281 // 8 MB
282 test_atlas_config(reporter, 65536, 8 * 1024 * 1024, kARGB_GrMaskFormat,
283 { 2048, 1024 }, { 256, 256 });
284 test_atlas_config(reporter, 65536, 8 * 1024 * 1024, kA8_GrMaskFormat,
Jim Van Verth578b0892018-12-20 20:48:55 +0000285 { 2048, 2048 }, { 512, 512 });
Jim Van Verthf6206f92018-12-14 08:22:24 -0500286 // 16 MB (should be same as 8 MB)
287 test_atlas_config(reporter, 65536, 16 * 1024 * 1024, kARGB_GrMaskFormat,
288 { 2048, 1024 }, { 256, 256 });
289 test_atlas_config(reporter, 65536, 16 * 1024 * 1024, kA8_GrMaskFormat,
Jim Van Verth578b0892018-12-20 20:48:55 +0000290 { 2048, 2048 }, { 512, 512 });
Jim Van Verthf6206f92018-12-14 08:22:24 -0500291
292 // 4MB, restricted texture size
293 test_atlas_config(reporter, 1024, 8 * 1024 * 1024, kARGB_GrMaskFormat,
294 { 1024, 1024 }, { 256, 256 });
295 test_atlas_config(reporter, 1024, 8 * 1024 * 1024, kA8_GrMaskFormat,
296 { 1024, 1024 }, { 256, 256 });
297
298 // 3 MB (should be same as 2 MB)
299 test_atlas_config(reporter, 65536, 3 * 1024 * 1024, kARGB_GrMaskFormat,
300 { 1024, 512 }, { 256, 256 });
301 test_atlas_config(reporter, 65536, 3 * 1024 * 1024, kA8_GrMaskFormat,
302 { 2048, 1024 }, { 512, 256 });
303
304 // minimum size
305 test_atlas_config(reporter, 65536, 0, kARGB_GrMaskFormat,
306 { 256, 256 }, { 256, 256 });
307 test_atlas_config(reporter, 65536, 0, kA8_GrMaskFormat,
308 { 512, 512 }, { 256, 256 });
Brian Salomon58f153c2018-10-18 21:51:15 -0400309}