c4039ea466
Reland all the things This CL splits the old GrAtlasGlyphCache into a GrAtlasGlyphCache and an GrAtlasManager. The GrAtlasManager itself is split into a rather limited base class (GrRestrictedAtlasManager) and the all powerful GrAtlasManager. The GrRestrictedAtlasManager is available at op creation time and provides access to the proxies backing the atlases. The full GrAtlasManager is only available at flush time and allows instantiation of the proxies and uploading to them. In the DDL world all of the DDL Contexts will receive a GrRestrictedAtlasManager-version of the GrAtlasManager in the main thread. This future atlas manager will have had all of its GrDrawOpAtlases created (but not instantiated) so there should be no race conditions. TBR=jvanverth@google.com Change-Id: I05c6cd8d301bf2decca39765e5cae62993d9da04 Reviewed-on: https://skia-review.googlesource.com/111362 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Robert Phillips <robertphillips@google.com>
133 lines
4.4 KiB
C++
133 lines
4.4 KiB
C++
/*
|
|
* 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/GrGlyphCache.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
|