fix for perf regression on ugamsolutions / msaa16
BUG=skia: Review URL: https://codereview.chromium.org/1076853002
This commit is contained in:
parent
8ed3b9a386
commit
62db8ba68b
@ -701,13 +701,19 @@ public:
|
||||
return;
|
||||
}
|
||||
|
||||
GrTexture* texture = fFontCache->getTexture(fMaskFormat);
|
||||
if (!texture) {
|
||||
SkDebugf("Could not allocate backing texture for atlas\n");
|
||||
return;
|
||||
}
|
||||
|
||||
GrTextureParams params(SkShader::kClamp_TileMode, GrTextureParams::kNone_FilterMode);
|
||||
|
||||
// This will be ignored in the non A8 case
|
||||
bool opaqueVertexColors = GrColorIsOpaque(this->color());
|
||||
SkAutoTUnref<const GrGeometryProcessor> gp(
|
||||
GrBitmapTextGeoProc::Create(this->color(),
|
||||
fFontCache->getTexture(fMaskFormat),
|
||||
texture,
|
||||
params,
|
||||
fMaskFormat,
|
||||
opaqueVertexColors,
|
||||
|
@ -34,57 +34,41 @@ static GrBatchAtlas* make_atlas(GrContext* context, GrPixelConfig config,
|
||||
return SkNEW_ARGS(GrBatchAtlas, (texture, numPlotsX, numPlotsY));
|
||||
}
|
||||
|
||||
int GrBatchFontCache::MaskFormatToAtlasIndex(GrMaskFormat format) {
|
||||
static const int sAtlasIndices[] = {
|
||||
kA8_GrMaskFormat,
|
||||
kA565_GrMaskFormat,
|
||||
kARGB_GrMaskFormat,
|
||||
};
|
||||
SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, array_size_mismatch);
|
||||
|
||||
SkASSERT(sAtlasIndices[format] < kMaskFormatCount);
|
||||
return sAtlasIndices[format];
|
||||
}
|
||||
|
||||
GrMaskFormat GrBatchFontCache::AtlasIndexToMaskFormat(int atlasIndex) {
|
||||
static GrMaskFormat sMaskFormats[] = {
|
||||
kA8_GrMaskFormat,
|
||||
kA565_GrMaskFormat,
|
||||
kARGB_GrMaskFormat,
|
||||
};
|
||||
SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sMaskFormats) == kMaskFormatCount, array_size_mismatch);
|
||||
|
||||
SkASSERT(sMaskFormats[atlasIndex] < kMaskFormatCount);
|
||||
return sMaskFormats[atlasIndex];
|
||||
}
|
||||
|
||||
GrBatchFontCache::GrBatchFontCache()
|
||||
: fPreserveStrike(NULL) {
|
||||
}
|
||||
|
||||
void GrBatchFontCache::init(GrContext* context) {
|
||||
for (int i = 0; i < kMaskFormatCount; i++) {
|
||||
GrMaskFormat format = AtlasIndexToMaskFormat(i);
|
||||
bool GrBatchFontCache::initAtlas(GrMaskFormat format) {
|
||||
int index = MaskFormatToAtlasIndex(format);
|
||||
if (!fAtlases[index]) {
|
||||
GrPixelConfig config = this->getPixelConfig(format);
|
||||
|
||||
if (kA8_GrMaskFormat == format) {
|
||||
fAtlases[i] = make_atlas(context, config,
|
||||
GR_FONT_ATLAS_A8_TEXTURE_WIDTH,
|
||||
GR_FONT_ATLAS_TEXTURE_HEIGHT,
|
||||
GR_FONT_ATLAS_A8_NUM_PLOTS_X,
|
||||
GR_FONT_ATLAS_NUM_PLOTS_Y);
|
||||
fAtlases[index] = make_atlas(fContext, config,
|
||||
GR_FONT_ATLAS_A8_TEXTURE_WIDTH,
|
||||
GR_FONT_ATLAS_TEXTURE_HEIGHT,
|
||||
GR_FONT_ATLAS_A8_NUM_PLOTS_X,
|
||||
GR_FONT_ATLAS_NUM_PLOTS_Y);
|
||||
} else {
|
||||
fAtlases[i] = make_atlas(context, config,
|
||||
GR_FONT_ATLAS_TEXTURE_WIDTH,
|
||||
GR_FONT_ATLAS_TEXTURE_HEIGHT,
|
||||
GR_FONT_ATLAS_NUM_PLOTS_X,
|
||||
GR_FONT_ATLAS_NUM_PLOTS_Y);
|
||||
fAtlases[index] = make_atlas(fContext, config,
|
||||
GR_FONT_ATLAS_TEXTURE_WIDTH,
|
||||
GR_FONT_ATLAS_TEXTURE_HEIGHT,
|
||||
GR_FONT_ATLAS_NUM_PLOTS_X,
|
||||
GR_FONT_ATLAS_NUM_PLOTS_Y);
|
||||
}
|
||||
|
||||
if (fAtlases[i]) {
|
||||
fAtlases[i]->registerEvictionCallback(&GrBatchFontCache::HandleEviction, (void*)this);
|
||||
// Atlas creation can fail
|
||||
if (fAtlases[index]) {
|
||||
fAtlases[index]->registerEvictionCallback(&GrBatchFontCache::HandleEviction,
|
||||
(void*)this);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
GrBatchFontCache::GrBatchFontCache(GrContext* context)
|
||||
: fContext(context)
|
||||
, fPreserveStrike(NULL) {
|
||||
for (int i = 0; i < kMaskFormatCount; ++i) {
|
||||
fAtlases[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GrBatchFontCache::~GrBatchFontCache() {
|
||||
@ -98,12 +82,6 @@ GrBatchFontCache::~GrBatchFontCache() {
|
||||
}
|
||||
}
|
||||
|
||||
GrBatchTextStrike* GrBatchFontCache::generateStrike(GrFontScaler* scaler) {
|
||||
GrBatchTextStrike* strike = SkNEW_ARGS(GrBatchTextStrike, (this, scaler->getKey()));
|
||||
fCache.add(strike);
|
||||
return strike;
|
||||
}
|
||||
|
||||
void GrBatchFontCache::freeAll() {
|
||||
SkTDynamicHash<GrBatchTextStrike, GrFontDescKey>::Iter iter(&fCache);
|
||||
while (!iter.done()) {
|
||||
@ -117,49 +95,6 @@ void GrBatchFontCache::freeAll() {
|
||||
}
|
||||
}
|
||||
|
||||
inline GrBatchAtlas* GrBatchFontCache::getAtlas(GrMaskFormat format) const {
|
||||
int atlasIndex = MaskFormatToAtlasIndex(format);
|
||||
SkASSERT(fAtlases[atlasIndex]);
|
||||
return fAtlases[atlasIndex];
|
||||
}
|
||||
|
||||
bool GrBatchFontCache::hasGlyph(GrGlyph* glyph) {
|
||||
SkASSERT(glyph);
|
||||
return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID);
|
||||
}
|
||||
|
||||
void GrBatchFontCache::addGlyphToBulkAndSetUseToken(GrBatchAtlas::BulkUseTokenUpdater* updater,
|
||||
GrGlyph* glyph,
|
||||
GrBatchAtlas::BatchToken token) {
|
||||
SkASSERT(glyph);
|
||||
updater->add(glyph->fID);
|
||||
this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fID, token);
|
||||
}
|
||||
|
||||
void GrBatchFontCache::setUseTokenBulk(const GrBatchAtlas::BulkUseTokenUpdater& updater,
|
||||
GrBatchAtlas::BatchToken token,
|
||||
GrMaskFormat format) {
|
||||
this->getAtlas(format)->setLastUseTokenBulk(updater, token);
|
||||
}
|
||||
|
||||
bool GrBatchFontCache::addToAtlas(GrBatchTextStrike* strike, GrBatchAtlas::AtlasID* id,
|
||||
GrBatchTarget* batchTarget,
|
||||
GrMaskFormat format, int width, int height, const void* image,
|
||||
SkIPoint16* loc) {
|
||||
fPreserveStrike = strike;
|
||||
return this->getAtlas(format)->addToAtlas(id, batchTarget, width, height, image, loc);
|
||||
}
|
||||
|
||||
uint64_t GrBatchFontCache::atlasGeneration(GrMaskFormat format) const {
|
||||
return this->getAtlas(format)->atlasGeneration();
|
||||
}
|
||||
|
||||
GrTexture* GrBatchFontCache::getTexture(GrMaskFormat format) {
|
||||
int atlasIndex = MaskFormatToAtlasIndex(format);
|
||||
SkASSERT(fAtlases[atlasIndex]);
|
||||
return fAtlases[atlasIndex]->getTexture();
|
||||
}
|
||||
|
||||
GrPixelConfig GrBatchFontCache::getPixelConfig(GrMaskFormat format) const {
|
||||
static const GrPixelConfig kPixelConfigs[] = {
|
||||
kAlpha_8_GrPixelConfig,
|
||||
|
@ -75,18 +75,17 @@ private:
|
||||
/*
|
||||
* GrBatchFontCache manages strikes which are indexed by a GrFontScaler. These strikes can then be
|
||||
* used to individual Glyph Masks. The GrBatchFontCache also manages GrBatchAtlases, though this is
|
||||
* more or less transparent to the client(aside from atlasGeneration, described below)
|
||||
* more or less transparent to the client(aside from atlasGeneration, described below).
|
||||
* Note - we used to initialize the backing atlas for the GrBatchFontCache at initialization time.
|
||||
* However, this caused a regression, even when the GrBatchFontCache was unused. We now initialize
|
||||
* the backing atlases lazily. Its not immediately clear why this improves the situation.
|
||||
*/
|
||||
class GrBatchFontCache {
|
||||
public:
|
||||
GrBatchFontCache();
|
||||
GrBatchFontCache(GrContext*);
|
||||
~GrBatchFontCache();
|
||||
|
||||
// Initializes the GrBatchFontCache on the owning GrContext
|
||||
void init(GrContext*);
|
||||
|
||||
inline GrBatchTextStrike* getStrike(GrFontScaler* scaler) {
|
||||
|
||||
GrBatchTextStrike* strike = fCache.find(*(scaler->getKey()));
|
||||
if (NULL == strike) {
|
||||
strike = this->generateStrike(scaler);
|
||||
@ -94,49 +93,93 @@ public:
|
||||
return strike;
|
||||
}
|
||||
|
||||
bool hasGlyph(GrGlyph* glyph);
|
||||
void freeAll();
|
||||
|
||||
// if getTexture returns NULL, the client must not try to use other functions on the
|
||||
// GrBatchFontCache which use the atlas. This function *must* be called first, before other
|
||||
// functions which use the atlas.
|
||||
GrTexture* getTexture(GrMaskFormat format) {
|
||||
if (this->initAtlas(format)) {
|
||||
return this->getAtlas(format)->getTexture();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool hasGlyph(GrGlyph* glyph) {
|
||||
SkASSERT(glyph);
|
||||
return this->getAtlas(glyph->fMaskFormat)->hasID(glyph->fID);
|
||||
}
|
||||
|
||||
// To ensure the GrBatchAtlas does not evict the Glyph Mask from its texture backing store,
|
||||
// the client must pass in the currentToken from the GrBatchTarget along with the GrGlyph.
|
||||
// A BulkUseTokenUpdater is used to manage bulk last use token updating in the Atlas.
|
||||
// For convenience, this function will also set the use token for the current glyph if required
|
||||
// NOTE: the bulk uploader is only valid if the subrun has a valid atlasGeneration
|
||||
void addGlyphToBulkAndSetUseToken(GrBatchAtlas::BulkUseTokenUpdater*, GrGlyph*,
|
||||
GrBatchAtlas::BatchToken);
|
||||
void addGlyphToBulkAndSetUseToken(GrBatchAtlas::BulkUseTokenUpdater* updater,
|
||||
GrGlyph* glyph, GrBatchAtlas::BatchToken token) {
|
||||
SkASSERT(glyph);
|
||||
updater->add(glyph->fID);
|
||||
this->getAtlas(glyph->fMaskFormat)->setLastUseToken(glyph->fID, token);
|
||||
}
|
||||
|
||||
void setUseTokenBulk(const GrBatchAtlas::BulkUseTokenUpdater&, GrBatchAtlas::BatchToken,
|
||||
GrMaskFormat);
|
||||
void setUseTokenBulk(const GrBatchAtlas::BulkUseTokenUpdater& updater,
|
||||
GrBatchAtlas::BatchToken token,
|
||||
GrMaskFormat format) {
|
||||
this->getAtlas(format)->setLastUseTokenBulk(updater, token);
|
||||
}
|
||||
|
||||
// add to texture atlas that matches this format
|
||||
bool addToAtlas(GrBatchTextStrike*, GrBatchAtlas::AtlasID*, GrBatchTarget*,
|
||||
GrMaskFormat, int width, int height, const void* image,
|
||||
SkIPoint16* loc);
|
||||
bool addToAtlas(GrBatchTextStrike* strike, GrBatchAtlas::AtlasID* id,
|
||||
GrBatchTarget* batchTarget,
|
||||
GrMaskFormat format, int width, int height, const void* image,
|
||||
SkIPoint16* loc) {
|
||||
fPreserveStrike = strike;
|
||||
return this->getAtlas(format)->addToAtlas(id, batchTarget, width, height, image, loc);
|
||||
}
|
||||
|
||||
// Some clients may wish to verify the integrity of the texture backing store of the
|
||||
// GrBatchAtlas. The atlasGeneration returned below is a monitonically increasing number which
|
||||
// changes everytime something is removed from the texture backing store.
|
||||
uint64_t atlasGeneration(GrMaskFormat) const;
|
||||
uint64_t atlasGeneration(GrMaskFormat format) const {
|
||||
return this->getAtlas(format)->atlasGeneration();
|
||||
}
|
||||
|
||||
void freeAll();
|
||||
|
||||
GrTexture* getTexture(GrMaskFormat);
|
||||
GrPixelConfig getPixelConfig(GrMaskFormat) const;
|
||||
|
||||
void dump() const;
|
||||
|
||||
private:
|
||||
// There is a 1:1 mapping between GrMaskFormats and atlas indices
|
||||
static int MaskFormatToAtlasIndex(GrMaskFormat);
|
||||
static GrMaskFormat AtlasIndexToMaskFormat(int atlasIndex);
|
||||
static int MaskFormatToAtlasIndex(GrMaskFormat format) {
|
||||
static const int sAtlasIndices[] = {
|
||||
kA8_GrMaskFormat,
|
||||
kA565_GrMaskFormat,
|
||||
kARGB_GrMaskFormat,
|
||||
};
|
||||
SK_COMPILE_ASSERT(SK_ARRAY_COUNT(sAtlasIndices) == kMaskFormatCount, array_size_mismatch);
|
||||
|
||||
GrBatchTextStrike* generateStrike(GrFontScaler*);
|
||||
SkASSERT(sAtlasIndices[format] < kMaskFormatCount);
|
||||
return sAtlasIndices[format];
|
||||
}
|
||||
|
||||
inline GrBatchAtlas* getAtlas(GrMaskFormat) const;
|
||||
bool initAtlas(GrMaskFormat);
|
||||
|
||||
GrBatchTextStrike* generateStrike(GrFontScaler* scaler) {
|
||||
GrBatchTextStrike* strike = SkNEW_ARGS(GrBatchTextStrike, (this, scaler->getKey()));
|
||||
fCache.add(strike);
|
||||
return strike;
|
||||
}
|
||||
|
||||
GrBatchAtlas* getAtlas(GrMaskFormat format) const {
|
||||
int atlasIndex = MaskFormatToAtlasIndex(format);
|
||||
SkASSERT(fAtlases[atlasIndex]);
|
||||
return fAtlases[atlasIndex];
|
||||
}
|
||||
|
||||
static void HandleEviction(GrBatchAtlas::AtlasID, void*);
|
||||
|
||||
GrContext* fContext;
|
||||
SkTDynamicHash<GrBatchTextStrike, GrFontDescKey> fCache;
|
||||
|
||||
GrBatchAtlas* fAtlases[kMaskFormatCount];
|
||||
GrBatchTextStrike* fPreserveStrike;
|
||||
};
|
||||
|
@ -135,8 +135,7 @@ void GrContext::initCommon() {
|
||||
this->setupDrawBuffer();
|
||||
|
||||
// GrBatchFontCache will eventually replace GrFontCache
|
||||
fBatchFontCache = SkNEW(GrBatchFontCache);
|
||||
fBatchFontCache->init(this);
|
||||
fBatchFontCache = SkNEW_ARGS(GrBatchFontCache, (this));
|
||||
|
||||
fTextBlobCache.reset(SkNEW(GrTextBlobCache));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user