• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
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/GrGlyphCache.h"
15 
16 static const int kNumPlots = 2;
17 static const int kPlotSize = 32;
18 static const int kAtlasSize = kNumPlots * kPlotSize;
19 
numAllocated_TestingOnly() const20 int 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 
EvictionFunc(GrDrawOpAtlas::AtlasID atlasID,void *)31 void EvictionFunc(GrDrawOpAtlas::AtlasID atlasID, void*) {
32     SkASSERT(0); // The unit test shouldn't exercise this code path
33 }
34 
check(skiatest::Reporter * r,GrDrawOpAtlas * atlas,uint32_t expectedActive,uint32_t expectedMax,int expectedAlloced)35 static 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 
42 class TestingUploadTarget : public GrDeferredUploadTarget {
43 public:
TestingUploadTarget()44     TestingUploadTarget() { }
45 
tokenTracker()46     const GrTokenTracker* tokenTracker() final {
47         return &fTokenTracker;
48     }
49 
addInlineUpload(GrDeferredTextureUploadFn &&)50     GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) final {
51         SkASSERT(0); // this test shouldn't invoke this code path
52         return fTokenTracker.nextDrawToken();
53     }
54 
addASAPUpload(GrDeferredTextureUploadFn && upload)55     virtual GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&& upload) final {
56         return fTokenTracker.nextTokenToFlush();
57     }
58 
issueDrawToken()59     void issueDrawToken() { fTokenTracker.issueDrawToken(); }
flushToken()60     void flushToken() { fTokenTracker.flushToken(); }
61 
62 private:
63     GrTokenTracker fTokenTracker;
64 
65     typedef GrDeferredUploadTarget INHERITED;
66 };
67 
fill_plot(GrDrawOpAtlas * atlas,GrResourceProvider * resourceProvider,GrDeferredUploadTarget * target,GrDrawOpAtlas::AtlasID * atlasID,int alpha)68 static 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 
DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DrawOpAtlas,reporter,ctxInfo)86 DEF_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
133