* Copyright 2018 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef GrAtlasManager_DEFINED
#define GrAtlasManager_DEFINED
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrDrawOpAtlas.h"
#include "src/gpu/GrOnFlushResourceProvider.h"
#include "src/gpu/GrProxyProvider.h"
struct GrGlyph;
class GrTextStrike;
* It is only available at flush and only via the GrOpFlushState.
*
* This implies that all of the advanced atlasManager functionality (i.e.,
* adding glyphs to the atlas) are only available at flush time.
*/
class GrAtlasManager : public GrOnFlushCallbackObject {
public:
GrAtlasManager(GrProxyProvider*, GrStrikeCache*,
size_t maxTextureBytes, GrDrawOpAtlas::AllowMultitexturing, int plotOldThreshold);
~GrAtlasManager() override;
GrMaskFormat resolveMaskFormat(GrMaskFormat format) const {
if (kA565_GrMaskFormat == format &&
!fProxyProvider->caps()->getDefaultBackendFormat(GrColorType::kBGR_565,
GrRenderable::kNo).isValid()) {
format = kARGB_GrMaskFormat;
}
return format;
}
const sk_sp<GrTextureProxy>* getProxies(GrMaskFormat format, unsigned int* numActiveProxies) {
format = this->resolveMaskFormat(format);
if (this->initAtlas(format)) {
*numActiveProxies = this->getAtlas(format)->numActivePages();
return this->getAtlas(format)->getProxies();
}
*numActiveProxies = 0;
return nullptr;
}
void freeAll();
bool hasGlyph(GrGlyph* glyph);
void incAtlasHitCount() { fAtlasHitCount++; }
void incAtlasMissCount() { fAtlasMissCount++; }
float atlasHitRate() {
if (fAtlasHitCount + fAtlasMissCount == 0) {
return 0;
}
return (float)fAtlasHitCount / (fAtlasHitCount + fAtlasMissCount);
}
void resetHitCount() {
fAtlasHitCount = 0;
fAtlasMissCount = 0;
}
void addGlyphToBulkAndSetUseToken(GrDrawOpAtlas::BulkUseTokenUpdater*, GrGlyph*,
GrDeferredUploadToken);
void setUseTokenBulk(const GrDrawOpAtlas::BulkUseTokenUpdater& updater,
GrDeferredUploadToken token,
GrMaskFormat format) {
this->getAtlas(format)->setLastUseTokenBulk(updater, token);
}
GrDrawOpAtlas::ErrorCode addToAtlas(
GrResourceProvider*, GrStrikeCache*, GrTextStrike*,
GrDrawOpAtlas::AtlasID*, GrDeferredUploadTarget*, GrMaskFormat,
int width, int height, const void* image, SkIPoint16* loc);
uint64_t atlasGeneration(GrMaskFormat format) const {
return this->getAtlas(format)->atlasGeneration();
}
void preFlush(GrOnFlushResourceProvider* onFlushResourceProvider, const uint32_t*, int,
SkTArray<sk_sp<GrRenderTargetContext>>*) override {
for (int i = 0; i < kMaskFormatCount; ++i) {
if (fAtlases[i]) {
fAtlases[i]->instantiate(onFlushResourceProvider);
}
}
}
void postFlush(GrDeferredUploadToken startTokenForNextFlush,
const uint32_t* opListIDs, int numOpListIDs) override;
bool retainOnFreeGpuResources() override { return true; }
#ifdef SK_DUMP_ATLAS_IMAGE
void dump(GrContext* context) const;
#endif
void setAtlasSizesToMinimum_ForTesting();
void setMaxPages_TestingOnly(uint32_t maxPages);
private:
bool initAtlas(GrMaskFormat);
static int MaskFormatToAtlasIndex(GrMaskFormat format) { return static_cast<int>(format); }
static GrMaskFormat AtlasIndexToMaskFormat(int idx) { return static_cast<GrMaskFormat>(idx); }
GrDrawOpAtlas* getAtlas(GrMaskFormat format) const {
format = this->resolveMaskFormat(format);
int atlasIndex = MaskFormatToAtlasIndex(format);
SkASSERT(fAtlases[atlasIndex]);
return fAtlases[atlasIndex].get();
}
GrDrawOpAtlas::AllowMultitexturing fAllowMultitexturing;
std::unique_ptr<GrDrawOpAtlas> fAtlases[kMaskFormatCount];
GrProxyProvider* fProxyProvider;
sk_sp<const GrCaps> fCaps;
GrStrikeCache* fGlyphCache;
GrDrawOpAtlasConfig fAtlasConfig;
int fPlotOldThreshold;
int fAtlasHitCount;
int fAtlasMissCount;
typedef GrOnFlushCallbackObject INHERITED;
};
#endif