blob: a34618e38f4b5715f0e4b4a654ba23827468b6d8 [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
8#include "SkTypes.h"
9
10#if SK_SUPPORT_GPU
11
12#include "GrContextPriv.h"
13#include "Test.h"
14#include "text/GrAtlasGlyphCache.h"
15
16static const int kNumPlots = 2;
17static const int kPlotSize = 32;
18static const int kAtlasSize = kNumPlots * kPlotSize;
19
20int GrDrawOpAtlas::numAllocated_TestingOnly() const {
21 int count = 0;
22 for (uint32_t i = 0; i < this->maxPages(); ++i) {
23 if (fProxies[i]->priv().isInstantiated()) {
24 ++count;
25 }
26 }
27
28 return count;
29}
30
31void EvictionFunc(GrDrawOpAtlas::AtlasID atlasID, void*) {
32 SkASSERT(0); // The unit test shouldn't exercise this code path
33}
34
35static void check(skiatest::Reporter* r, GrDrawOpAtlas* atlas,
36 uint32_t expectedActive, uint32_t expectedMax, int expectedAlloced) {
37 REPORTER_ASSERT(r, expectedActive == atlas->numActivePages());
38 REPORTER_ASSERT(r, expectedMax == atlas->maxPages());
39 REPORTER_ASSERT(r, expectedAlloced == atlas->numAllocated_TestingOnly());
40}
41
42class TestingUploadTarget : public GrDeferredUploadTarget {
43public:
44 TestingUploadTarget() { }
45
46 const GrTokenTracker* tokenTracker() final {
47 return &fTokenTracker;
48 }
49
50 GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) final {
51 SkASSERT(0); // this test shouldn't invoke this code path
52 return fTokenTracker.nextDrawToken();
53 }
54
55 virtual GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&& upload) final {
56 return fTokenTracker.nextTokenToFlush();
57 }
58
59 void issueDrawToken() { fTokenTracker.issueDrawToken(); }
60 void flushToken() { fTokenTracker.flushToken(); }
61
62private:
63 GrTokenTracker fTokenTracker;
64
65 typedef GrDeferredUploadTarget INHERITED;
66};
67
68static bool fill_plot(GrDrawOpAtlas* atlas,
69 GrResourceProvider* resourceProvider,
70 GrDeferredUploadTarget* target,
71 GrDrawOpAtlas::AtlasID* atlasID,
72 int alpha) {
73 SkImageInfo ii = SkImageInfo::MakeA8(kPlotSize, kPlotSize);
74
75 SkBitmap data;
76 data.allocPixels(ii);
77 data.eraseARGB(alpha, 0, 0, 0);
78
79 SkIPoint16 loc;
80 bool result = atlas->addToAtlas(resourceProvider, atlasID, target, kPlotSize, kPlotSize,
81 data.getAddr(0, 0), &loc);
82 return result;
83}
84
85
86DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DrawOpAtlas, reporter, ctxInfo) {
87 auto context = ctxInfo.grContext();
88 auto proxyProvider = context->contextPriv().proxyProvider();
89 auto resourceProvider = context->contextPriv().resourceProvider();
90 auto drawingManager = context->contextPriv().drawingManager();
91
92 GrOnFlushResourceProvider onFlushResourceProvider(drawingManager);
93 TestingUploadTarget uploadTarget;
94
95 std::unique_ptr<GrDrawOpAtlas> atlas = GrDrawOpAtlas::Make(
96 proxyProvider,
97 kAlpha_8_GrPixelConfig,
98 kAtlasSize, kAtlasSize,
99 kNumPlots, kNumPlots,
100 GrDrawOpAtlas::AllowMultitexturing::kYes,
101 EvictionFunc, nullptr);
102 check(reporter, atlas.get(), 0, 4, 0);
103
104 // Fill up the first level
105 GrDrawOpAtlas::AtlasID atlasIDs[kNumPlots * kNumPlots];
106 for (int i = 0; i < kNumPlots * kNumPlots; ++i) {
107 bool result = fill_plot(atlas.get(), resourceProvider, &uploadTarget, &atlasIDs[i], i*32);
108 REPORTER_ASSERT(reporter, result);
109 check(reporter, atlas.get(), 1, 4, 1);
110 }
111
112 atlas->instantiate(&onFlushResourceProvider);
113 check(reporter, atlas.get(), 1, 4, 1);
114
115 // Force allocation of a second level
116 GrDrawOpAtlas::AtlasID atlasID;
117 bool result = fill_plot(atlas.get(), resourceProvider, &uploadTarget, &atlasID, 4*32);
118 REPORTER_ASSERT(reporter, result);
119 check(reporter, atlas.get(), 2, 4, 2);
120
121 // Simulate a lot of draws using only the first plot. The last texture should be compacted.
122 for (int i = 0; i < 512; ++i) {
123 atlas->setLastUseToken(atlasIDs[0], uploadTarget.tokenTracker()->nextDrawToken());
124 uploadTarget.issueDrawToken();
125 uploadTarget.flushToken();
126 atlas->compact(uploadTarget.tokenTracker()->nextTokenToFlush());
127 }
128
129 check(reporter, atlas.get(), 1, 4, 1);
130}
131
132#endif