Remove CacheTextureLine structure from FontRenderer
CacheTextureLine was useful before we were packing the glyph textures; it allowed simple packing of any particular texture according to how many lines there were in a texture, and how tall those lines were. Now that we are packing more efficiently (both horizontally and vertically in any given texture line), it is more efficient to have open space in every texture, removing the need for CacheTextureLine (which now gets in the way since it limits how much can be stored in each line). This change removes CacheTextureLine and just uses CacheTexture directly, allowing caching of glyphs anywhere in the open space of each texture. As before, the packing of these glyphs is determined by the CacheBlock structure, which is a linked list of open spaces in each CacheTexture. Change-Id: Id6f628170df0f676f8743ac7de76f2377fc6a012
This commit is contained in:
@@ -109,11 +109,11 @@ CacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock *blockToRemove)
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// CacheTextureLine
|
||||
// CacheTexture
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool CacheTextureLine::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
|
||||
if (glyph.fHeight + TEXTURE_BORDER_SIZE > mMaxHeight) {
|
||||
bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
|
||||
if (glyph.fHeight + TEXTURE_BORDER_SIZE > mHeight) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ bool CacheTextureLine::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uin
|
||||
roundedUpW = glyphW;
|
||||
}
|
||||
*retOriginX = cacheBlock->mX;
|
||||
*retOriginY = mCurrentRow + cacheBlock->mY;
|
||||
*retOriginY = cacheBlock->mY;
|
||||
// If this is the remainder space, create a new cache block for this column. Otherwise,
|
||||
// adjust the info about this column.
|
||||
if (cacheBlock->mY == TEXTURE_BORDER_SIZE) {
|
||||
@@ -146,10 +146,10 @@ bool CacheTextureLine::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uin
|
||||
// Adjust remainder space dimensions
|
||||
cacheBlock->mWidth -= roundedUpW;
|
||||
cacheBlock->mX += roundedUpW;
|
||||
if (mMaxHeight - glyphH >= glyphH) {
|
||||
if (mHeight - glyphH >= glyphH) {
|
||||
// There's enough height left over to create a new CacheBlock
|
||||
CacheBlock *newBlock = new CacheBlock(oldX, glyphH, roundedUpW,
|
||||
mMaxHeight - glyphH);
|
||||
mHeight - glyphH);
|
||||
#if DEBUG_FONT_RENDERER
|
||||
ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d",
|
||||
newBlock, newBlock->mX, newBlock->mY,
|
||||
@@ -213,10 +213,10 @@ Font::~Font() {
|
||||
}
|
||||
}
|
||||
|
||||
void Font::invalidateTextureCache(CacheTextureLine *cacheLine) {
|
||||
void Font::invalidateTextureCache(CacheTexture *cacheTexture) {
|
||||
for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
|
||||
CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueAt(i);
|
||||
if (cacheLine == NULL || cachedGlyph->mCachedTextureLine == cacheLine) {
|
||||
if (cacheTexture == NULL || cachedGlyph->mCacheTexture == cacheTexture) {
|
||||
cachedGlyph->mIsValid = false;
|
||||
}
|
||||
}
|
||||
@@ -260,7 +260,7 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
|
||||
mState->appendMeshQuad(nPenX, nPenY, u1, v2,
|
||||
nPenX + width, nPenY, u2, v2,
|
||||
nPenX + width, nPenY - height, u2, v1,
|
||||
nPenX, nPenY - height, u1, v1, glyph->mCachedTextureLine->mCacheTexture);
|
||||
nPenX, nPenY - height, u1, v1, glyph->mCacheTexture);
|
||||
}
|
||||
|
||||
void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
|
||||
@@ -271,7 +271,7 @@ void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y,
|
||||
uint32_t endX = glyph->mStartX + glyph->mBitmapWidth;
|
||||
uint32_t endY = glyph->mStartY + glyph->mBitmapHeight;
|
||||
|
||||
CacheTexture *cacheTexture = glyph->mCachedTextureLine->mCacheTexture;
|
||||
CacheTexture *cacheTexture = glyph->mCacheTexture;
|
||||
uint32_t cacheWidth = cacheTexture->mWidth;
|
||||
const uint8_t* cacheBuffer = cacheTexture->mTexture;
|
||||
|
||||
@@ -325,7 +325,7 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float
|
||||
position->fY + destination[2].fY, u2, v1,
|
||||
position->fX + destination[3].fX,
|
||||
position->fY + destination[3].fY, u1, v1,
|
||||
glyph->mCachedTextureLine->mCacheTexture);
|
||||
glyph->mCacheTexture);
|
||||
}
|
||||
|
||||
CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit) {
|
||||
@@ -556,8 +556,8 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp
|
||||
glyph->mBitmapWidth = skiaGlyph.fWidth;
|
||||
glyph->mBitmapHeight = skiaGlyph.fHeight;
|
||||
|
||||
uint32_t cacheWidth = glyph->mCachedTextureLine->mCacheTexture->mWidth;
|
||||
uint32_t cacheHeight = glyph->mCachedTextureLine->mCacheTexture->mHeight;
|
||||
uint32_t cacheWidth = glyph->mCacheTexture->mWidth;
|
||||
uint32_t cacheHeight = glyph->mCacheTexture->mHeight;
|
||||
|
||||
glyph->mBitmapMinU = startX / (float) cacheWidth;
|
||||
glyph->mBitmapMinV = startY / (float) cacheHeight;
|
||||
@@ -620,10 +620,6 @@ FontRenderer::FontRenderer() {
|
||||
mTextMeshPtr = NULL;
|
||||
mCurrentCacheTexture = NULL;
|
||||
mLastCacheTexture = NULL;
|
||||
mCacheTextureSmall = NULL;
|
||||
mCacheTexture128 = NULL;
|
||||
mCacheTexture256 = NULL;
|
||||
mCacheTexture512 = NULL;
|
||||
|
||||
mLinearFiltering = false;
|
||||
|
||||
@@ -659,10 +655,10 @@ FontRenderer::FontRenderer() {
|
||||
}
|
||||
|
||||
FontRenderer::~FontRenderer() {
|
||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
||||
delete mCacheLines[i];
|
||||
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||
delete mCacheTextures[i];
|
||||
}
|
||||
mCacheLines.clear();
|
||||
mCacheTextures.clear();
|
||||
|
||||
if (mInitialized) {
|
||||
// Unbinding the buffer shouldn't be necessary but it crashes with some drivers
|
||||
@@ -670,10 +666,6 @@ FontRenderer::~FontRenderer() {
|
||||
glDeleteBuffers(1, &mIndexBufferID);
|
||||
|
||||
delete[] mTextMeshPtr;
|
||||
delete mCacheTextureSmall;
|
||||
delete mCacheTexture128;
|
||||
delete mCacheTexture256;
|
||||
delete mCacheTexture512;
|
||||
}
|
||||
|
||||
Vector<Font*> fontsToDereference = mActiveFonts;
|
||||
@@ -692,29 +684,19 @@ void FontRenderer::flushAllAndInvalidate() {
|
||||
mActiveFonts[i]->invalidateTextureCache();
|
||||
}
|
||||
|
||||
uint16_t totalGlyphs = 0;
|
||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
||||
totalGlyphs += mCacheLines[i]->mNumGlyphs;
|
||||
mCacheLines[i]->init();
|
||||
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||
mCacheTextures[i]->init();
|
||||
}
|
||||
|
||||
#if DEBUG_FONT_RENDERER
|
||||
// Erase caches, just as a debugging facility
|
||||
if (mCacheTextureSmall && mCacheTextureSmall->mTexture) {
|
||||
memset(mCacheTextureSmall->mTexture, 0,
|
||||
mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight);
|
||||
}
|
||||
if (mCacheTexture128 && mCacheTexture128->mTexture) {
|
||||
memset(mCacheTexture128->mTexture, 0,
|
||||
mCacheTexture128->mWidth * mCacheTexture128->mHeight);
|
||||
}
|
||||
if (mCacheTexture256 && mCacheTexture256->mTexture) {
|
||||
memset(mCacheTexture256->mTexture, 0,
|
||||
mCacheTexture256->mWidth * mCacheTexture256->mHeight);
|
||||
}
|
||||
if (mCacheTexture512 && mCacheTexture512->mTexture) {
|
||||
memset(mCacheTexture512->mTexture, 0,
|
||||
mCacheTexture512->mWidth * mCacheTexture512->mHeight);
|
||||
#if DEBUG_FONT_RENDERER
|
||||
uint16_t totalGlyphs = 0;
|
||||
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||
totalGlyphs += mCacheTextures[i]->mNumGlyphs;
|
||||
// Erase caches, just as a debugging facility
|
||||
if (mCacheTextures[i]->mTexture) {
|
||||
memset(mCacheTextures[i]->mTexture, 0,
|
||||
mCacheTextures[i]->mWidth * mCacheTextures[i]->mHeight);
|
||||
}
|
||||
}
|
||||
ALOGD("Flushing caches: glyphs cached = %d", totalGlyphs);
|
||||
#endif
|
||||
@@ -730,38 +712,17 @@ void FontRenderer::deallocateTextureMemory(CacheTexture *cacheTexture) {
|
||||
}
|
||||
|
||||
void FontRenderer::flushLargeCaches() {
|
||||
if ((!mCacheTexture128 || !mCacheTexture128->mTexture) &&
|
||||
(!mCacheTexture256 || !mCacheTexture256->mTexture) &&
|
||||
(!mCacheTexture512 || !mCacheTexture512->mTexture)) {
|
||||
// Typical case; no large glyph caches allocated
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
||||
CacheTextureLine* cacheLine = mCacheLines[i];
|
||||
if ((cacheLine->mCacheTexture == mCacheTexture128 ||
|
||||
cacheLine->mCacheTexture == mCacheTexture256 ||
|
||||
cacheLine->mCacheTexture == mCacheTexture512) &&
|
||||
cacheLine->mCacheTexture->mTexture != NULL) {
|
||||
#if DEBUG_FONT_RENDERER
|
||||
if (cacheLine->mCacheTexture == mCacheTexture128) {
|
||||
ALOGD("flushing cacheTexture128");
|
||||
} else if (cacheLine->mCacheTexture == mCacheTexture256) {
|
||||
ALOGD("flushing cacheTexture256");
|
||||
} else {
|
||||
ALOGD("flushing cacheTexture512");
|
||||
}
|
||||
#endif
|
||||
cacheLine->init();
|
||||
for (uint32_t i = 0; i < mActiveFonts.size(); i++) {
|
||||
mActiveFonts[i]->invalidateTextureCache(cacheLine);
|
||||
// Start from 1; don't deallocate smallest/default texture
|
||||
for (uint32_t i = 1; i < mCacheTextures.size(); i++) {
|
||||
CacheTexture* cacheTexture = mCacheTextures[i];
|
||||
if (cacheTexture->mTexture != NULL) {
|
||||
cacheTexture->init();
|
||||
for (uint32_t j = 0; j < mActiveFonts.size(); j++) {
|
||||
mActiveFonts[j]->invalidateTextureCache(cacheTexture);
|
||||
}
|
||||
deallocateTextureMemory(cacheTexture);
|
||||
}
|
||||
}
|
||||
|
||||
deallocateTextureMemory(mCacheTexture128);
|
||||
deallocateTextureMemory(mCacheTexture256);
|
||||
deallocateTextureMemory(mCacheTexture512);
|
||||
}
|
||||
|
||||
void FontRenderer::allocateTextureMemory(CacheTexture* cacheTexture) {
|
||||
@@ -789,12 +750,24 @@ void FontRenderer::allocateTextureMemory(CacheTexture* cacheTexture) {
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
}
|
||||
|
||||
CacheTexture* FontRenderer::cacheBitmapInTexture(const SkGlyph& glyph,
|
||||
uint32_t* startX, uint32_t* startY) {
|
||||
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||
if (mCacheTextures[i]->fitBitmap(glyph, startX, startY)) {
|
||||
return mCacheTextures[i];
|
||||
}
|
||||
}
|
||||
// Could not fit glyph into current cache textures
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
|
||||
uint32_t* retOriginX, uint32_t* retOriginY) {
|
||||
checkInit();
|
||||
cachedGlyph->mIsValid = false;
|
||||
// If the glyph is too tall, don't cache it
|
||||
if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > mCacheLines[mCacheLines.size() - 1]->mMaxHeight) {
|
||||
if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 >
|
||||
mCacheTextures[mCacheTextures.size() - 1]->mHeight) {
|
||||
ALOGE("Font size too large to fit in cache. width, height = %i, %i",
|
||||
(int) glyph.fWidth, (int) glyph.fHeight);
|
||||
return;
|
||||
@@ -804,36 +777,22 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
|
||||
uint32_t startX = 0;
|
||||
uint32_t startY = 0;
|
||||
|
||||
bool bitmapFit = false;
|
||||
CacheTextureLine *cacheLine;
|
||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
||||
bitmapFit = mCacheLines[i]->fitBitmap(glyph, &startX, &startY);
|
||||
if (bitmapFit) {
|
||||
cacheLine = mCacheLines[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
CacheTexture* cacheTexture = cacheBitmapInTexture(glyph, &startX, &startY);
|
||||
|
||||
// If the new glyph didn't fit, flush the state so far and invalidate everything
|
||||
if (!bitmapFit) {
|
||||
if (!cacheTexture) {
|
||||
flushAllAndInvalidate();
|
||||
|
||||
// Try to fit it again
|
||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
||||
bitmapFit = mCacheLines[i]->fitBitmap(glyph, &startX, &startY);
|
||||
if (bitmapFit) {
|
||||
cacheLine = mCacheLines[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
cacheTexture = cacheBitmapInTexture(glyph, &startX, &startY);
|
||||
|
||||
// if we still don't fit, something is wrong and we shouldn't draw
|
||||
if (!bitmapFit) {
|
||||
if (!cacheTexture) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
cachedGlyph->mCachedTextureLine = cacheLine;
|
||||
cachedGlyph->mCacheTexture = cacheTexture;
|
||||
|
||||
*retOriginX = startX;
|
||||
*retOriginY = startY;
|
||||
@@ -841,9 +800,8 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
|
||||
uint32_t endX = startX + glyph.fWidth;
|
||||
uint32_t endY = startY + glyph.fHeight;
|
||||
|
||||
uint32_t cacheWidth = cacheLine->mMaxWidth;
|
||||
uint32_t cacheWidth = cacheTexture->mWidth;
|
||||
|
||||
CacheTexture* cacheTexture = cacheLine->mCacheTexture;
|
||||
if (!cacheTexture->mTexture) {
|
||||
// Large-glyph texture memory is allocated only as needed
|
||||
allocateTextureMemory(cacheTexture);
|
||||
@@ -896,17 +854,10 @@ CacheTexture* FontRenderer::createCacheTexture(int width, int height, bool alloc
|
||||
}
|
||||
|
||||
void FontRenderer::initTextTexture() {
|
||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
||||
delete mCacheLines[i];
|
||||
}
|
||||
mCacheLines.clear();
|
||||
|
||||
if (mCacheTextureSmall) {
|
||||
delete mCacheTextureSmall;
|
||||
delete mCacheTexture128;
|
||||
delete mCacheTexture256;
|
||||
delete mCacheTexture512;
|
||||
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||
delete mCacheTextures[i];
|
||||
}
|
||||
mCacheTextures.clear();
|
||||
|
||||
// Next, use other, separate caches for large glyphs.
|
||||
uint16_t maxWidth = 0;
|
||||
@@ -918,35 +869,12 @@ void FontRenderer::initTextTexture() {
|
||||
maxWidth = MAX_TEXT_CACHE_WIDTH;
|
||||
}
|
||||
|
||||
mCacheTextureSmall = createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, true);
|
||||
mCacheTexture128 = createCacheTexture(maxWidth, 256, false);
|
||||
mCacheTexture256 = createCacheTexture(maxWidth, 256, false);
|
||||
mCacheTexture512 = createCacheTexture(maxWidth, 512, false);
|
||||
mCurrentCacheTexture = mCacheTextureSmall;
|
||||
|
||||
mUploadTexture = false;
|
||||
// Split up our default cache texture into lines of certain widths
|
||||
int nextLine = 0;
|
||||
mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 18, nextLine, mCacheTextureSmall));
|
||||
nextLine += mCacheLines.top()->mMaxHeight;
|
||||
mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 26, nextLine, mCacheTextureSmall));
|
||||
nextLine += mCacheLines.top()->mMaxHeight;
|
||||
mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 26, nextLine, mCacheTextureSmall));
|
||||
nextLine += mCacheLines.top()->mMaxHeight;
|
||||
mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 34, nextLine, mCacheTextureSmall));
|
||||
nextLine += mCacheLines.top()->mMaxHeight;
|
||||
mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 34, nextLine, mCacheTextureSmall));
|
||||
nextLine += mCacheLines.top()->mMaxHeight;
|
||||
mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 42, nextLine, mCacheTextureSmall));
|
||||
nextLine += mCacheLines.top()->mMaxHeight;
|
||||
mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, mSmallCacheHeight - nextLine,
|
||||
nextLine, mCacheTextureSmall));
|
||||
|
||||
// The first cache is split into 2 lines of height 128, the rest have just one cache line.
|
||||
mCacheLines.push(new CacheTextureLine(maxWidth, 128, 0, mCacheTexture128));
|
||||
mCacheLines.push(new CacheTextureLine(maxWidth, 128, 128, mCacheTexture128));
|
||||
mCacheLines.push(new CacheTextureLine(maxWidth, 256, 0, mCacheTexture256));
|
||||
mCacheLines.push(new CacheTextureLine(maxWidth, 512, 0, mCacheTexture512));
|
||||
mCacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, true));
|
||||
mCacheTextures.push(createCacheTexture(maxWidth, 256, false));
|
||||
mCacheTextures.push(createCacheTexture(maxWidth, 256, false));
|
||||
mCacheTextures.push(createCacheTexture(maxWidth, 512, false));
|
||||
mCurrentCacheTexture = mCacheTextures[0];
|
||||
}
|
||||
|
||||
// Avoid having to reallocate memory and render quad by quad
|
||||
@@ -1001,16 +929,14 @@ void FontRenderer::checkTextureUpdate() {
|
||||
|
||||
Caches& caches = Caches::getInstance();
|
||||
GLuint lastTextureId = 0;
|
||||
// Iterate over all the cache lines and see which ones need to be updated
|
||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
||||
CacheTextureLine* cl = mCacheLines[i];
|
||||
if (cl->mDirty && cl->mCacheTexture->mTexture != NULL) {
|
||||
CacheTexture* cacheTexture = cl->mCacheTexture;
|
||||
// Iterate over all the cache textures and see which ones need to be updated
|
||||
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||
CacheTexture* cacheTexture = mCacheTextures[i];
|
||||
if (cacheTexture->mDirty && cacheTexture->mTexture != NULL) {
|
||||
uint32_t xOffset = 0;
|
||||
uint32_t yOffset = cl->mCurrentRow;
|
||||
uint32_t width = cl->mMaxWidth;
|
||||
uint32_t height = cl->mMaxHeight;
|
||||
void* textureData = cacheTexture->mTexture + (yOffset * width);
|
||||
uint32_t width = cacheTexture->mWidth;
|
||||
uint32_t height = cacheTexture->mHeight;
|
||||
void* textureData = cacheTexture->mTexture;
|
||||
|
||||
if (cacheTexture->mTextureId != lastTextureId) {
|
||||
caches.activeTexture(0);
|
||||
@@ -1018,13 +944,13 @@ void FontRenderer::checkTextureUpdate() {
|
||||
lastTextureId = cacheTexture->mTextureId;
|
||||
}
|
||||
#if DEBUG_FONT_RENDERER
|
||||
ALOGD("glTextSubimage for cacheLine %d: xOff, yOff, width height = %d, %d, %d, %d", i,
|
||||
xOffset, yOffset, width, height);
|
||||
ALOGD("glTextSubimage for cacheTexture %d: xOff, width height = %d, %d, %d",
|
||||
i, xOffset, width, height);
|
||||
#endif
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, width, height,
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, 0, width, height,
|
||||
GL_ALPHA, GL_UNSIGNED_BYTE, textureData);
|
||||
|
||||
cl->mDirty = false;
|
||||
cacheTexture->mDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -61,35 +61,14 @@ namespace uirenderer {
|
||||
|
||||
class FontRenderer;
|
||||
|
||||
class CacheTexture {
|
||||
public:
|
||||
CacheTexture(uint16_t width, uint16_t height) :
|
||||
mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height),
|
||||
mLinearFiltering(false) { }
|
||||
~CacheTexture() {
|
||||
if (mTexture) {
|
||||
delete[] mTexture;
|
||||
}
|
||||
if (mTextureId) {
|
||||
glDeleteTextures(1, &mTextureId);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t* mTexture;
|
||||
GLuint mTextureId;
|
||||
uint16_t mWidth;
|
||||
uint16_t mHeight;
|
||||
bool mLinearFiltering;
|
||||
};
|
||||
|
||||
/**
|
||||
* CacheBlock is a noce in a linked list of current free space areas in a CacheTextureLine.
|
||||
* Using CacheBlocks enables us to pack the cache line from top to bottom as well as left to right.
|
||||
* CacheBlock is a node in a linked list of current free space areas in a CacheTexture.
|
||||
* Using CacheBlocks enables us to pack the cache from top to bottom as well as left to right.
|
||||
* When we add a glyph to the cache, we see if it fits within one of the existing columns that
|
||||
* have already been started (this is the case if the glyph fits vertically as well as
|
||||
* horizontally, and if its width is sufficiently close to the column width to avoid
|
||||
* sub-optimal packing of small glyphs into wide columns). If there is no column in which the
|
||||
* glyph fits, we check the final node, which is the remaining space in the cache line, creating
|
||||
* glyph fits, we check the final node, which is the remaining space in the cache, creating
|
||||
* a new column as appropriate.
|
||||
*
|
||||
* As columns fill up, we remove their CacheBlock from the list to avoid having to check
|
||||
@@ -122,21 +101,22 @@ struct CacheBlock {
|
||||
}
|
||||
};
|
||||
|
||||
class CacheTextureLine {
|
||||
class CacheTexture {
|
||||
public:
|
||||
CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
|
||||
CacheTexture* cacheTexture):
|
||||
mMaxHeight(maxHeight),
|
||||
mMaxWidth(maxWidth),
|
||||
mCurrentRow(currentRow),
|
||||
mDirty(false),
|
||||
mNumGlyphs(0),
|
||||
mCacheTexture(cacheTexture) {
|
||||
CacheTexture(uint16_t width, uint16_t height) :
|
||||
mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height),
|
||||
mLinearFiltering(false), mDirty(false), mNumGlyphs(0) {
|
||||
mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
|
||||
maxWidth - TEXTURE_BORDER_SIZE, maxHeight - TEXTURE_BORDER_SIZE, true);
|
||||
mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true);
|
||||
}
|
||||
|
||||
~CacheTextureLine() {
|
||||
~CacheTexture() {
|
||||
if (mTexture) {
|
||||
delete[] mTexture;
|
||||
}
|
||||
if (mTextureId) {
|
||||
glDeleteTextures(1, &mTextureId);
|
||||
}
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -154,17 +134,18 @@ public:
|
||||
// reset, then create a new remainder space to start again
|
||||
reset();
|
||||
mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
|
||||
mMaxWidth - TEXTURE_BORDER_SIZE, mMaxHeight - TEXTURE_BORDER_SIZE, true);
|
||||
mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true);
|
||||
}
|
||||
|
||||
bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
|
||||
|
||||
uint16_t mMaxHeight;
|
||||
uint16_t mMaxWidth;
|
||||
uint32_t mCurrentRow;
|
||||
uint8_t* mTexture;
|
||||
GLuint mTextureId;
|
||||
uint16_t mWidth;
|
||||
uint16_t mHeight;
|
||||
bool mLinearFiltering;
|
||||
bool mDirty;
|
||||
uint16_t mNumGlyphs;
|
||||
CacheTexture* mCacheTexture;
|
||||
CacheBlock* mCacheBlocks;
|
||||
};
|
||||
|
||||
@@ -193,7 +174,7 @@ struct CachedGlyphInfo {
|
||||
// Auto-kerning
|
||||
SkFixed mLsbDelta;
|
||||
SkFixed mRsbDelta;
|
||||
CacheTextureLine* mCachedTextureLine;
|
||||
CacheTexture* mCacheTexture;
|
||||
};
|
||||
|
||||
|
||||
@@ -260,7 +241,7 @@ protected:
|
||||
// Cache of glyphs
|
||||
DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
|
||||
|
||||
void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
|
||||
void invalidateTextureCache(CacheTexture *cacheTexture = NULL);
|
||||
|
||||
CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
|
||||
void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
|
||||
@@ -364,17 +345,11 @@ public:
|
||||
|
||||
uint32_t getCacheSize() const {
|
||||
uint32_t size = 0;
|
||||
if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
|
||||
size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
|
||||
}
|
||||
if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
|
||||
size += mCacheTexture128->mWidth * mCacheTexture128->mHeight;
|
||||
}
|
||||
if (mCacheTexture256 != NULL && mCacheTexture256->mTexture != NULL) {
|
||||
size += mCacheTexture256->mWidth * mCacheTexture256->mHeight;
|
||||
}
|
||||
if (mCacheTexture512 != NULL && mCacheTexture512->mTexture != NULL) {
|
||||
size += mCacheTexture512->mWidth * mCacheTexture512->mHeight;
|
||||
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||
CacheTexture* cacheTexture = mCacheTextures[i];
|
||||
if (cacheTexture != NULL && cacheTexture->mTexture != NULL) {
|
||||
size += cacheTexture->mWidth * cacheTexture->mHeight;
|
||||
}
|
||||
}
|
||||
return size;
|
||||
}
|
||||
@@ -390,6 +365,7 @@ protected:
|
||||
CacheTexture* createCacheTexture(int width, int height, bool allocate);
|
||||
void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
|
||||
uint32_t *retOriginX, uint32_t *retOriginY);
|
||||
CacheTexture* cacheBitmapInTexture(const SkGlyph& glyph, uint32_t* startX, uint32_t* startY);
|
||||
|
||||
void flushAllAndInvalidate();
|
||||
void initVertexArrayBuffers();
|
||||
@@ -415,17 +391,13 @@ protected:
|
||||
uint32_t mSmallCacheWidth;
|
||||
uint32_t mSmallCacheHeight;
|
||||
|
||||
Vector<CacheTextureLine*> mCacheLines;
|
||||
Vector<CacheTexture*> mCacheTextures;
|
||||
|
||||
Font* mCurrentFont;
|
||||
Vector<Font*> mActiveFonts;
|
||||
|
||||
CacheTexture* mCurrentCacheTexture;
|
||||
CacheTexture* mLastCacheTexture;
|
||||
CacheTexture* mCacheTextureSmall;
|
||||
CacheTexture* mCacheTexture128;
|
||||
CacheTexture* mCacheTexture256;
|
||||
CacheTexture* mCacheTexture512;
|
||||
|
||||
void checkTextureUpdate();
|
||||
bool mUploadTexture;
|
||||
|
||||
Reference in New Issue
Block a user