Merge "Remove CacheTextureLine structure from FontRenderer" into jb-mr1-dev
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) {
|
bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY) {
|
||||||
if (glyph.fHeight + TEXTURE_BORDER_SIZE > mMaxHeight) {
|
if (glyph.fHeight + TEXTURE_BORDER_SIZE > mHeight) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -138,7 +138,7 @@ bool CacheTextureLine::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uin
|
|||||||
roundedUpW = glyphW;
|
roundedUpW = glyphW;
|
||||||
}
|
}
|
||||||
*retOriginX = cacheBlock->mX;
|
*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,
|
// If this is the remainder space, create a new cache block for this column. Otherwise,
|
||||||
// adjust the info about this column.
|
// adjust the info about this column.
|
||||||
if (cacheBlock->mY == TEXTURE_BORDER_SIZE) {
|
if (cacheBlock->mY == TEXTURE_BORDER_SIZE) {
|
||||||
@@ -146,10 +146,10 @@ bool CacheTextureLine::fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uin
|
|||||||
// Adjust remainder space dimensions
|
// Adjust remainder space dimensions
|
||||||
cacheBlock->mWidth -= roundedUpW;
|
cacheBlock->mWidth -= roundedUpW;
|
||||||
cacheBlock->mX += roundedUpW;
|
cacheBlock->mX += roundedUpW;
|
||||||
if (mMaxHeight - glyphH >= glyphH) {
|
if (mHeight - glyphH >= glyphH) {
|
||||||
// There's enough height left over to create a new CacheBlock
|
// There's enough height left over to create a new CacheBlock
|
||||||
CacheBlock *newBlock = new CacheBlock(oldX, glyphH, roundedUpW,
|
CacheBlock *newBlock = new CacheBlock(oldX, glyphH, roundedUpW,
|
||||||
mMaxHeight - glyphH);
|
mHeight - glyphH);
|
||||||
#if DEBUG_FONT_RENDERER
|
#if DEBUG_FONT_RENDERER
|
||||||
ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d",
|
ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d",
|
||||||
newBlock, newBlock->mX, newBlock->mY,
|
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++) {
|
for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
|
||||||
CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueAt(i);
|
CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueAt(i);
|
||||||
if (cacheLine == NULL || cachedGlyph->mCachedTextureLine == cacheLine) {
|
if (cacheTexture == NULL || cachedGlyph->mCacheTexture == cacheTexture) {
|
||||||
cachedGlyph->mIsValid = false;
|
cachedGlyph->mIsValid = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -260,7 +260,7 @@ void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y,
|
|||||||
mState->appendMeshQuad(nPenX, nPenY, u1, v2,
|
mState->appendMeshQuad(nPenX, nPenY, u1, v2,
|
||||||
nPenX + width, nPenY, u2, v2,
|
nPenX + width, nPenY, u2, v2,
|
||||||
nPenX + width, nPenY - height, u2, v1,
|
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,
|
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 endX = glyph->mStartX + glyph->mBitmapWidth;
|
||||||
uint32_t endY = glyph->mStartY + glyph->mBitmapHeight;
|
uint32_t endY = glyph->mStartY + glyph->mBitmapHeight;
|
||||||
|
|
||||||
CacheTexture *cacheTexture = glyph->mCachedTextureLine->mCacheTexture;
|
CacheTexture *cacheTexture = glyph->mCacheTexture;
|
||||||
uint32_t cacheWidth = cacheTexture->mWidth;
|
uint32_t cacheWidth = cacheTexture->mWidth;
|
||||||
const uint8_t* cacheBuffer = cacheTexture->mTexture;
|
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->fY + destination[2].fY, u2, v1,
|
||||||
position->fX + destination[3].fX,
|
position->fX + destination[3].fX,
|
||||||
position->fY + destination[3].fY, u1, v1,
|
position->fY + destination[3].fY, u1, v1,
|
||||||
glyph->mCachedTextureLine->mCacheTexture);
|
glyph->mCacheTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
CachedGlyphInfo* Font::getCachedGlyph(SkPaint* paint, glyph_t textUnit) {
|
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->mBitmapWidth = skiaGlyph.fWidth;
|
||||||
glyph->mBitmapHeight = skiaGlyph.fHeight;
|
glyph->mBitmapHeight = skiaGlyph.fHeight;
|
||||||
|
|
||||||
uint32_t cacheWidth = glyph->mCachedTextureLine->mCacheTexture->mWidth;
|
uint32_t cacheWidth = glyph->mCacheTexture->mWidth;
|
||||||
uint32_t cacheHeight = glyph->mCachedTextureLine->mCacheTexture->mHeight;
|
uint32_t cacheHeight = glyph->mCacheTexture->mHeight;
|
||||||
|
|
||||||
glyph->mBitmapMinU = startX / (float) cacheWidth;
|
glyph->mBitmapMinU = startX / (float) cacheWidth;
|
||||||
glyph->mBitmapMinV = startY / (float) cacheHeight;
|
glyph->mBitmapMinV = startY / (float) cacheHeight;
|
||||||
@@ -620,10 +620,6 @@ FontRenderer::FontRenderer() {
|
|||||||
mTextMeshPtr = NULL;
|
mTextMeshPtr = NULL;
|
||||||
mCurrentCacheTexture = NULL;
|
mCurrentCacheTexture = NULL;
|
||||||
mLastCacheTexture = NULL;
|
mLastCacheTexture = NULL;
|
||||||
mCacheTextureSmall = NULL;
|
|
||||||
mCacheTexture128 = NULL;
|
|
||||||
mCacheTexture256 = NULL;
|
|
||||||
mCacheTexture512 = NULL;
|
|
||||||
|
|
||||||
mLinearFiltering = false;
|
mLinearFiltering = false;
|
||||||
|
|
||||||
@@ -659,10 +655,10 @@ FontRenderer::FontRenderer() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FontRenderer::~FontRenderer() {
|
FontRenderer::~FontRenderer() {
|
||||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||||
delete mCacheLines[i];
|
delete mCacheTextures[i];
|
||||||
}
|
}
|
||||||
mCacheLines.clear();
|
mCacheTextures.clear();
|
||||||
|
|
||||||
if (mInitialized) {
|
if (mInitialized) {
|
||||||
// Unbinding the buffer shouldn't be necessary but it crashes with some drivers
|
// Unbinding the buffer shouldn't be necessary but it crashes with some drivers
|
||||||
@@ -670,10 +666,6 @@ FontRenderer::~FontRenderer() {
|
|||||||
glDeleteBuffers(1, &mIndexBufferID);
|
glDeleteBuffers(1, &mIndexBufferID);
|
||||||
|
|
||||||
delete[] mTextMeshPtr;
|
delete[] mTextMeshPtr;
|
||||||
delete mCacheTextureSmall;
|
|
||||||
delete mCacheTexture128;
|
|
||||||
delete mCacheTexture256;
|
|
||||||
delete mCacheTexture512;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Vector<Font*> fontsToDereference = mActiveFonts;
|
Vector<Font*> fontsToDereference = mActiveFonts;
|
||||||
@@ -692,29 +684,19 @@ void FontRenderer::flushAllAndInvalidate() {
|
|||||||
mActiveFonts[i]->invalidateTextureCache();
|
mActiveFonts[i]->invalidateTextureCache();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t totalGlyphs = 0;
|
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
mCacheTextures[i]->init();
|
||||||
totalGlyphs += mCacheLines[i]->mNumGlyphs;
|
|
||||||
mCacheLines[i]->init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if DEBUG_FONT_RENDERER
|
#if DEBUG_FONT_RENDERER
|
||||||
// Erase caches, just as a debugging facility
|
uint16_t totalGlyphs = 0;
|
||||||
if (mCacheTextureSmall && mCacheTextureSmall->mTexture) {
|
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||||
memset(mCacheTextureSmall->mTexture, 0,
|
totalGlyphs += mCacheTextures[i]->mNumGlyphs;
|
||||||
mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight);
|
// Erase caches, just as a debugging facility
|
||||||
}
|
if (mCacheTextures[i]->mTexture) {
|
||||||
if (mCacheTexture128 && mCacheTexture128->mTexture) {
|
memset(mCacheTextures[i]->mTexture, 0,
|
||||||
memset(mCacheTexture128->mTexture, 0,
|
mCacheTextures[i]->mWidth * mCacheTextures[i]->mHeight);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
ALOGD("Flushing caches: glyphs cached = %d", totalGlyphs);
|
ALOGD("Flushing caches: glyphs cached = %d", totalGlyphs);
|
||||||
#endif
|
#endif
|
||||||
@@ -730,38 +712,17 @@ void FontRenderer::deallocateTextureMemory(CacheTexture *cacheTexture) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FontRenderer::flushLargeCaches() {
|
void FontRenderer::flushLargeCaches() {
|
||||||
if ((!mCacheTexture128 || !mCacheTexture128->mTexture) &&
|
// Start from 1; don't deallocate smallest/default texture
|
||||||
(!mCacheTexture256 || !mCacheTexture256->mTexture) &&
|
for (uint32_t i = 1; i < mCacheTextures.size(); i++) {
|
||||||
(!mCacheTexture512 || !mCacheTexture512->mTexture)) {
|
CacheTexture* cacheTexture = mCacheTextures[i];
|
||||||
// Typical case; no large glyph caches allocated
|
if (cacheTexture->mTexture != NULL) {
|
||||||
return;
|
cacheTexture->init();
|
||||||
}
|
for (uint32_t j = 0; j < mActiveFonts.size(); j++) {
|
||||||
|
mActiveFonts[j]->invalidateTextureCache(cacheTexture);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
deallocateTextureMemory(cacheTexture);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
deallocateTextureMemory(mCacheTexture128);
|
|
||||||
deallocateTextureMemory(mCacheTexture256);
|
|
||||||
deallocateTextureMemory(mCacheTexture512);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FontRenderer::allocateTextureMemory(CacheTexture* cacheTexture) {
|
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);
|
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,
|
void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
|
||||||
uint32_t* retOriginX, uint32_t* retOriginY) {
|
uint32_t* retOriginX, uint32_t* retOriginY) {
|
||||||
checkInit();
|
checkInit();
|
||||||
cachedGlyph->mIsValid = false;
|
cachedGlyph->mIsValid = false;
|
||||||
// If the glyph is too tall, don't cache it
|
// 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",
|
ALOGE("Font size too large to fit in cache. width, height = %i, %i",
|
||||||
(int) glyph.fWidth, (int) glyph.fHeight);
|
(int) glyph.fWidth, (int) glyph.fHeight);
|
||||||
return;
|
return;
|
||||||
@@ -804,36 +777,22 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
|
|||||||
uint32_t startX = 0;
|
uint32_t startX = 0;
|
||||||
uint32_t startY = 0;
|
uint32_t startY = 0;
|
||||||
|
|
||||||
bool bitmapFit = false;
|
CacheTexture* cacheTexture = cacheBitmapInTexture(glyph, &startX, &startY);
|
||||||
CacheTextureLine *cacheLine;
|
|
||||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
|
||||||
bitmapFit = mCacheLines[i]->fitBitmap(glyph, &startX, &startY);
|
|
||||||
if (bitmapFit) {
|
|
||||||
cacheLine = mCacheLines[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the new glyph didn't fit, flush the state so far and invalidate everything
|
// If the new glyph didn't fit, flush the state so far and invalidate everything
|
||||||
if (!bitmapFit) {
|
if (!cacheTexture) {
|
||||||
flushAllAndInvalidate();
|
flushAllAndInvalidate();
|
||||||
|
|
||||||
// Try to fit it again
|
// Try to fit it again
|
||||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
cacheTexture = cacheBitmapInTexture(glyph, &startX, &startY);
|
||||||
bitmapFit = mCacheLines[i]->fitBitmap(glyph, &startX, &startY);
|
|
||||||
if (bitmapFit) {
|
|
||||||
cacheLine = mCacheLines[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// if we still don't fit, something is wrong and we shouldn't draw
|
// if we still don't fit, something is wrong and we shouldn't draw
|
||||||
if (!bitmapFit) {
|
if (!cacheTexture) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cachedGlyph->mCachedTextureLine = cacheLine;
|
cachedGlyph->mCacheTexture = cacheTexture;
|
||||||
|
|
||||||
*retOriginX = startX;
|
*retOriginX = startX;
|
||||||
*retOriginY = startY;
|
*retOriginY = startY;
|
||||||
@@ -841,9 +800,8 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
|
|||||||
uint32_t endX = startX + glyph.fWidth;
|
uint32_t endX = startX + glyph.fWidth;
|
||||||
uint32_t endY = startY + glyph.fHeight;
|
uint32_t endY = startY + glyph.fHeight;
|
||||||
|
|
||||||
uint32_t cacheWidth = cacheLine->mMaxWidth;
|
uint32_t cacheWidth = cacheTexture->mWidth;
|
||||||
|
|
||||||
CacheTexture* cacheTexture = cacheLine->mCacheTexture;
|
|
||||||
if (!cacheTexture->mTexture) {
|
if (!cacheTexture->mTexture) {
|
||||||
// Large-glyph texture memory is allocated only as needed
|
// Large-glyph texture memory is allocated only as needed
|
||||||
allocateTextureMemory(cacheTexture);
|
allocateTextureMemory(cacheTexture);
|
||||||
@@ -896,17 +854,10 @@ CacheTexture* FontRenderer::createCacheTexture(int width, int height, bool alloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
void FontRenderer::initTextTexture() {
|
void FontRenderer::initTextTexture() {
|
||||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||||
delete mCacheLines[i];
|
delete mCacheTextures[i];
|
||||||
}
|
|
||||||
mCacheLines.clear();
|
|
||||||
|
|
||||||
if (mCacheTextureSmall) {
|
|
||||||
delete mCacheTextureSmall;
|
|
||||||
delete mCacheTexture128;
|
|
||||||
delete mCacheTexture256;
|
|
||||||
delete mCacheTexture512;
|
|
||||||
}
|
}
|
||||||
|
mCacheTextures.clear();
|
||||||
|
|
||||||
// Next, use other, separate caches for large glyphs.
|
// Next, use other, separate caches for large glyphs.
|
||||||
uint16_t maxWidth = 0;
|
uint16_t maxWidth = 0;
|
||||||
@@ -918,35 +869,12 @@ void FontRenderer::initTextTexture() {
|
|||||||
maxWidth = MAX_TEXT_CACHE_WIDTH;
|
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;
|
mUploadTexture = false;
|
||||||
// Split up our default cache texture into lines of certain widths
|
mCacheTextures.push(createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, true));
|
||||||
int nextLine = 0;
|
mCacheTextures.push(createCacheTexture(maxWidth, 256, false));
|
||||||
mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 18, nextLine, mCacheTextureSmall));
|
mCacheTextures.push(createCacheTexture(maxWidth, 256, false));
|
||||||
nextLine += mCacheLines.top()->mMaxHeight;
|
mCacheTextures.push(createCacheTexture(maxWidth, 512, false));
|
||||||
mCacheLines.push(new CacheTextureLine(mSmallCacheWidth, 26, nextLine, mCacheTextureSmall));
|
mCurrentCacheTexture = mCacheTextures[0];
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Avoid having to reallocate memory and render quad by quad
|
// Avoid having to reallocate memory and render quad by quad
|
||||||
@@ -1001,16 +929,14 @@ void FontRenderer::checkTextureUpdate() {
|
|||||||
|
|
||||||
Caches& caches = Caches::getInstance();
|
Caches& caches = Caches::getInstance();
|
||||||
GLuint lastTextureId = 0;
|
GLuint lastTextureId = 0;
|
||||||
// Iterate over all the cache lines and see which ones need to be updated
|
// Iterate over all the cache textures and see which ones need to be updated
|
||||||
for (uint32_t i = 0; i < mCacheLines.size(); i++) {
|
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||||
CacheTextureLine* cl = mCacheLines[i];
|
CacheTexture* cacheTexture = mCacheTextures[i];
|
||||||
if (cl->mDirty && cl->mCacheTexture->mTexture != NULL) {
|
if (cacheTexture->mDirty && cacheTexture->mTexture != NULL) {
|
||||||
CacheTexture* cacheTexture = cl->mCacheTexture;
|
|
||||||
uint32_t xOffset = 0;
|
uint32_t xOffset = 0;
|
||||||
uint32_t yOffset = cl->mCurrentRow;
|
uint32_t width = cacheTexture->mWidth;
|
||||||
uint32_t width = cl->mMaxWidth;
|
uint32_t height = cacheTexture->mHeight;
|
||||||
uint32_t height = cl->mMaxHeight;
|
void* textureData = cacheTexture->mTexture;
|
||||||
void* textureData = cacheTexture->mTexture + (yOffset * width);
|
|
||||||
|
|
||||||
if (cacheTexture->mTextureId != lastTextureId) {
|
if (cacheTexture->mTextureId != lastTextureId) {
|
||||||
caches.activeTexture(0);
|
caches.activeTexture(0);
|
||||||
@@ -1018,13 +944,13 @@ void FontRenderer::checkTextureUpdate() {
|
|||||||
lastTextureId = cacheTexture->mTextureId;
|
lastTextureId = cacheTexture->mTextureId;
|
||||||
}
|
}
|
||||||
#if DEBUG_FONT_RENDERER
|
#if DEBUG_FONT_RENDERER
|
||||||
ALOGD("glTextSubimage for cacheLine %d: xOff, yOff, width height = %d, %d, %d, %d", i,
|
ALOGD("glTextSubimage for cacheTexture %d: xOff, width height = %d, %d, %d",
|
||||||
xOffset, yOffset, width, height);
|
i, xOffset, width, height);
|
||||||
#endif
|
#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);
|
GL_ALPHA, GL_UNSIGNED_BYTE, textureData);
|
||||||
|
|
||||||
cl->mDirty = false;
|
cacheTexture->mDirty = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -61,35 +61,14 @@ namespace uirenderer {
|
|||||||
|
|
||||||
class FontRenderer;
|
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.
|
* CacheBlock is a node in a linked list of current free space areas in a CacheTexture.
|
||||||
* Using CacheBlocks enables us to pack the cache line from top to bottom as well as left to right.
|
* 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
|
* 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
|
* 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
|
* 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
|
* 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.
|
* a new column as appropriate.
|
||||||
*
|
*
|
||||||
* As columns fill up, we remove their CacheBlock from the list to avoid having to check
|
* 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:
|
public:
|
||||||
CacheTextureLine(uint16_t maxWidth, uint16_t maxHeight, uint32_t currentRow,
|
CacheTexture(uint16_t width, uint16_t height) :
|
||||||
CacheTexture* cacheTexture):
|
mTexture(NULL), mTextureId(0), mWidth(width), mHeight(height),
|
||||||
mMaxHeight(maxHeight),
|
mLinearFiltering(false), mDirty(false), mNumGlyphs(0) {
|
||||||
mMaxWidth(maxWidth),
|
|
||||||
mCurrentRow(currentRow),
|
|
||||||
mDirty(false),
|
|
||||||
mNumGlyphs(0),
|
|
||||||
mCacheTexture(cacheTexture) {
|
|
||||||
mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
|
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();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,17 +134,18 @@ public:
|
|||||||
// reset, then create a new remainder space to start again
|
// reset, then create a new remainder space to start again
|
||||||
reset();
|
reset();
|
||||||
mCacheBlocks = new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE,
|
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);
|
bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
|
||||||
|
|
||||||
uint16_t mMaxHeight;
|
uint8_t* mTexture;
|
||||||
uint16_t mMaxWidth;
|
GLuint mTextureId;
|
||||||
uint32_t mCurrentRow;
|
uint16_t mWidth;
|
||||||
|
uint16_t mHeight;
|
||||||
|
bool mLinearFiltering;
|
||||||
bool mDirty;
|
bool mDirty;
|
||||||
uint16_t mNumGlyphs;
|
uint16_t mNumGlyphs;
|
||||||
CacheTexture* mCacheTexture;
|
|
||||||
CacheBlock* mCacheBlocks;
|
CacheBlock* mCacheBlocks;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -193,7 +174,7 @@ struct CachedGlyphInfo {
|
|||||||
// Auto-kerning
|
// Auto-kerning
|
||||||
SkFixed mLsbDelta;
|
SkFixed mLsbDelta;
|
||||||
SkFixed mRsbDelta;
|
SkFixed mRsbDelta;
|
||||||
CacheTextureLine* mCachedTextureLine;
|
CacheTexture* mCacheTexture;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@@ -260,7 +241,7 @@ protected:
|
|||||||
// Cache of glyphs
|
// Cache of glyphs
|
||||||
DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
|
DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
|
||||||
|
|
||||||
void invalidateTextureCache(CacheTextureLine *cacheLine = NULL);
|
void invalidateTextureCache(CacheTexture *cacheTexture = NULL);
|
||||||
|
|
||||||
CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
|
CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph);
|
||||||
void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
|
void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph);
|
||||||
@@ -364,17 +345,11 @@ public:
|
|||||||
|
|
||||||
uint32_t getCacheSize() const {
|
uint32_t getCacheSize() const {
|
||||||
uint32_t size = 0;
|
uint32_t size = 0;
|
||||||
if (mCacheTextureSmall != NULL && mCacheTextureSmall->mTexture != NULL) {
|
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
|
||||||
size += mCacheTextureSmall->mWidth * mCacheTextureSmall->mHeight;
|
CacheTexture* cacheTexture = mCacheTextures[i];
|
||||||
}
|
if (cacheTexture != NULL && cacheTexture->mTexture != NULL) {
|
||||||
if (mCacheTexture128 != NULL && mCacheTexture128->mTexture != NULL) {
|
size += cacheTexture->mWidth * cacheTexture->mHeight;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
@@ -390,6 +365,7 @@ protected:
|
|||||||
CacheTexture* createCacheTexture(int width, int height, bool allocate);
|
CacheTexture* createCacheTexture(int width, int height, bool allocate);
|
||||||
void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
|
void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph,
|
||||||
uint32_t *retOriginX, uint32_t *retOriginY);
|
uint32_t *retOriginX, uint32_t *retOriginY);
|
||||||
|
CacheTexture* cacheBitmapInTexture(const SkGlyph& glyph, uint32_t* startX, uint32_t* startY);
|
||||||
|
|
||||||
void flushAllAndInvalidate();
|
void flushAllAndInvalidate();
|
||||||
void initVertexArrayBuffers();
|
void initVertexArrayBuffers();
|
||||||
@@ -415,17 +391,13 @@ protected:
|
|||||||
uint32_t mSmallCacheWidth;
|
uint32_t mSmallCacheWidth;
|
||||||
uint32_t mSmallCacheHeight;
|
uint32_t mSmallCacheHeight;
|
||||||
|
|
||||||
Vector<CacheTextureLine*> mCacheLines;
|
Vector<CacheTexture*> mCacheTextures;
|
||||||
|
|
||||||
Font* mCurrentFont;
|
Font* mCurrentFont;
|
||||||
Vector<Font*> mActiveFonts;
|
Vector<Font*> mActiveFonts;
|
||||||
|
|
||||||
CacheTexture* mCurrentCacheTexture;
|
CacheTexture* mCurrentCacheTexture;
|
||||||
CacheTexture* mLastCacheTexture;
|
CacheTexture* mLastCacheTexture;
|
||||||
CacheTexture* mCacheTextureSmall;
|
|
||||||
CacheTexture* mCacheTexture128;
|
|
||||||
CacheTexture* mCacheTexture256;
|
|
||||||
CacheTexture* mCacheTexture512;
|
|
||||||
|
|
||||||
void checkTextureUpdate();
|
void checkTextureUpdate();
|
||||||
bool mUploadTexture;
|
bool mUploadTexture;
|
||||||
|
|||||||
Reference in New Issue
Block a user