fix for perf regression on ugamsolutions / msaa16

BUG=skia:

Review URL: https://codereview.chromium.org/1076853002
This commit is contained in:
joshualitt 2015-04-09 08:22:37 -07:00 committed by Commit bot
parent 8ed3b9a386
commit 62db8ba68b
4 changed files with 102 additions and 119 deletions

View File

@ -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,

View File

@ -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,

View File

@ -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;
};

View File

@ -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));
}