aboutsummaryrefslogtreecommitdiffhomepage
path: root/tests/DrawOpAtlasTest.cpp
diff options
context:
space:
mode:
authorGravatar Robert Phillips <robertphillips@google.com>2018-03-01 10:24:02 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-03-01 15:47:34 +0000
commit4bc7011802e411da74eb2d213d6328e42f7dce1c (patch)
treece17ae0fba6ccf8dfd060d318b23cd6fb454c58b /tests/DrawOpAtlasTest.cpp
parenta63d6900d3baa23d6340a265bd0cf4f55ca2fdd9 (diff)
Separate creation time & flush time behavior in GrDrawOpAtlas (take 3)
This CL clarifies what is going on in the GrDrawOpAtlas and GrAtlasGlyphCache. For the GrDrawOpAtlas: At creation time all the allowed pages are created (with their backing GrTextureProxies) but they aren't instantiated. The GrDrawOpAtlas::instantiate call is called in preFlushCB and allocates any pages known to be needed at the start of flush GrDrawOpAtlas::addToAtlas is called at flush time and, if a new page is activated, will instantiated it at that time. During compaction, an unused page will be deInstantiated but its Plots and backing GrTextureProxy will remain alive. The GrAtlasGlyphCache reflects the changes to the GrDrawOpAtlas It now carries a GrProxyProvider for when it needs to create an atlas It passes in a GrResourceProvider* at flush time to allow instantiation. It does not, yet, allocate that GrDrawOpAtlases it might ever require. TBR=bsalomon@google.com Change-Id: I276d339d81e7b709140e082a7b58c5584f73ab70 Reviewed-on: https://skia-review.googlesource.com/111100 Commit-Queue: Robert Phillips <robertphillips@google.com> Reviewed-by: Jim Van Verth <jvanverth@google.com>
Diffstat (limited to 'tests/DrawOpAtlasTest.cpp')
-rw-r--r--tests/DrawOpAtlasTest.cpp132
1 files changed, 132 insertions, 0 deletions
diff --git a/tests/DrawOpAtlasTest.cpp b/tests/DrawOpAtlasTest.cpp
new file mode 100644
index 0000000000..a34618e38f
--- /dev/null
+++ b/tests/DrawOpAtlasTest.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright 2018 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkTypes.h"
+
+#if SK_SUPPORT_GPU
+
+#include "GrContextPriv.h"
+#include "Test.h"
+#include "text/GrAtlasGlyphCache.h"
+
+static const int kNumPlots = 2;
+static const int kPlotSize = 32;
+static const int kAtlasSize = kNumPlots * kPlotSize;
+
+int GrDrawOpAtlas::numAllocated_TestingOnly() const {
+ int count = 0;
+ for (uint32_t i = 0; i < this->maxPages(); ++i) {
+ if (fProxies[i]->priv().isInstantiated()) {
+ ++count;
+ }
+ }
+
+ return count;
+}
+
+void EvictionFunc(GrDrawOpAtlas::AtlasID atlasID, void*) {
+ SkASSERT(0); // The unit test shouldn't exercise this code path
+}
+
+static void check(skiatest::Reporter* r, GrDrawOpAtlas* atlas,
+ uint32_t expectedActive, uint32_t expectedMax, int expectedAlloced) {
+ REPORTER_ASSERT(r, expectedActive == atlas->numActivePages());
+ REPORTER_ASSERT(r, expectedMax == atlas->maxPages());
+ REPORTER_ASSERT(r, expectedAlloced == atlas->numAllocated_TestingOnly());
+}
+
+class TestingUploadTarget : public GrDeferredUploadTarget {
+public:
+ TestingUploadTarget() { }
+
+ const GrTokenTracker* tokenTracker() final {
+ return &fTokenTracker;
+ }
+
+ GrDeferredUploadToken addInlineUpload(GrDeferredTextureUploadFn&&) final {
+ SkASSERT(0); // this test shouldn't invoke this code path
+ return fTokenTracker.nextDrawToken();
+ }
+
+ virtual GrDeferredUploadToken addASAPUpload(GrDeferredTextureUploadFn&& upload) final {
+ return fTokenTracker.nextTokenToFlush();
+ }
+
+ void issueDrawToken() { fTokenTracker.issueDrawToken(); }
+ void flushToken() { fTokenTracker.flushToken(); }
+
+private:
+ GrTokenTracker fTokenTracker;
+
+ typedef GrDeferredUploadTarget INHERITED;
+};
+
+static bool fill_plot(GrDrawOpAtlas* atlas,
+ GrResourceProvider* resourceProvider,
+ GrDeferredUploadTarget* target,
+ GrDrawOpAtlas::AtlasID* atlasID,
+ int alpha) {
+ SkImageInfo ii = SkImageInfo::MakeA8(kPlotSize, kPlotSize);
+
+ SkBitmap data;
+ data.allocPixels(ii);
+ data.eraseARGB(alpha, 0, 0, 0);
+
+ SkIPoint16 loc;
+ bool result = atlas->addToAtlas(resourceProvider, atlasID, target, kPlotSize, kPlotSize,
+ data.getAddr(0, 0), &loc);
+ return result;
+}
+
+
+DEF_GPUTEST_FOR_RENDERING_CONTEXTS(DrawOpAtlas, reporter, ctxInfo) {
+ auto context = ctxInfo.grContext();
+ auto proxyProvider = context->contextPriv().proxyProvider();
+ auto resourceProvider = context->contextPriv().resourceProvider();
+ auto drawingManager = context->contextPriv().drawingManager();
+
+ GrOnFlushResourceProvider onFlushResourceProvider(drawingManager);
+ TestingUploadTarget uploadTarget;
+
+ std::unique_ptr<GrDrawOpAtlas> atlas = GrDrawOpAtlas::Make(
+ proxyProvider,
+ kAlpha_8_GrPixelConfig,
+ kAtlasSize, kAtlasSize,
+ kNumPlots, kNumPlots,
+ GrDrawOpAtlas::AllowMultitexturing::kYes,
+ EvictionFunc, nullptr);
+ check(reporter, atlas.get(), 0, 4, 0);
+
+ // Fill up the first level
+ GrDrawOpAtlas::AtlasID atlasIDs[kNumPlots * kNumPlots];
+ for (int i = 0; i < kNumPlots * kNumPlots; ++i) {
+ bool result = fill_plot(atlas.get(), resourceProvider, &uploadTarget, &atlasIDs[i], i*32);
+ REPORTER_ASSERT(reporter, result);
+ check(reporter, atlas.get(), 1, 4, 1);
+ }
+
+ atlas->instantiate(&onFlushResourceProvider);
+ check(reporter, atlas.get(), 1, 4, 1);
+
+ // Force allocation of a second level
+ GrDrawOpAtlas::AtlasID atlasID;
+ bool result = fill_plot(atlas.get(), resourceProvider, &uploadTarget, &atlasID, 4*32);
+ REPORTER_ASSERT(reporter, result);
+ check(reporter, atlas.get(), 2, 4, 2);
+
+ // Simulate a lot of draws using only the first plot. The last texture should be compacted.
+ for (int i = 0; i < 512; ++i) {
+ atlas->setLastUseToken(atlasIDs[0], uploadTarget.tokenTracker()->nextDrawToken());
+ uploadTarget.issueDrawToken();
+ uploadTarget.flushToken();
+ atlas->compact(uploadTarget.tokenTracker()->nextTokenToFlush());
+ }
+
+ check(reporter, atlas.get(), 1, 4, 1);
+}
+
+#endif