Merge "Code cleanup in FontRenderer" into jb-mr1-dev

This commit is contained in:
Romain Guy
2012-09-04 16:46:19 -07:00
committed by Android (Google) Code Review
5 changed files with 122 additions and 82 deletions

View File

@@ -127,68 +127,34 @@ void FontRenderer::flushAllAndInvalidate() {
mCacheTextures[i]->init();
}
#if DEBUG_FONT_RENDERER
#if DEBUG_FONT_RENDERER
uint16_t totalGlyphs = 0;
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
totalGlyphs += mCacheTextures[i]->mNumGlyphs;
totalGlyphs += mCacheTextures[i]->getGlyphCount();
// Erase caches, just as a debugging facility
if (mCacheTextures[i]->mTexture) {
memset(mCacheTextures[i]->mTexture, 0,
mCacheTextures[i]->mWidth * mCacheTextures[i]->mHeight);
if (mCacheTextures[i]->getTexture()) {
memset(mCacheTextures[i]->getTexture(), 0,
mCacheTextures[i]->getWidth() * mCacheTextures[i]->getHeight());
}
}
ALOGD("Flushing caches: glyphs cached = %d", totalGlyphs);
#endif
}
void FontRenderer::deallocateTextureMemory(CacheTexture *cacheTexture) {
if (cacheTexture && cacheTexture->mTexture) {
glDeleteTextures(1, &cacheTexture->mTextureId);
delete[] cacheTexture->mTexture;
cacheTexture->mTexture = NULL;
cacheTexture->mTextureId = 0;
}
}
void FontRenderer::flushLargeCaches() {
// 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) {
if (cacheTexture->getTexture()) {
cacheTexture->init();
for (uint32_t j = 0; j < mActiveFonts.size(); j++) {
mActiveFonts[j]->invalidateTextureCache(cacheTexture);
}
deallocateTextureMemory(cacheTexture);
cacheTexture->releaseTexture();
}
}
}
void FontRenderer::allocateTextureMemory(CacheTexture* cacheTexture) {
int width = cacheTexture->mWidth;
int height = cacheTexture->mHeight;
cacheTexture->mTexture = new uint8_t[width * height];
if (!cacheTexture->mTextureId) {
glGenTextures(1, &cacheTexture->mTextureId);
}
Caches::getInstance().activeTexture(0);
glBindTexture(GL_TEXTURE_2D, cacheTexture->mTextureId);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Initialize texture dimensions
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, 0);
const GLenum filtering = cacheTexture->mLinearFiltering ? GL_LINEAR : GL_NEAREST;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, 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++) {
@@ -206,7 +172,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
cachedGlyph->mIsValid = false;
// If the glyph is too tall, don't cache it
if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 >
mCacheTextures[mCacheTextures.size() - 1]->mHeight) {
mCacheTextures[mCacheTextures.size() - 1]->getHeight()) {
ALOGE("Font size too large to fit in cache. width, height = %i, %i",
(int) glyph.fWidth, (int) glyph.fHeight);
return;
@@ -240,14 +206,15 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp
uint32_t endX = startX + glyph.fWidth;
uint32_t endY = startY + glyph.fHeight;
uint32_t cacheWidth = cacheTexture->mWidth;
uint32_t cacheWidth = cacheTexture->getWidth();
if (!cacheTexture->mTexture) {
if (!cacheTexture->getTexture()) {
Caches::getInstance().activeTexture(0);
// Large-glyph texture memory is allocated only as needed
allocateTextureMemory(cacheTexture);
cacheTexture->allocateTexture();
}
uint8_t* cacheBuffer = cacheTexture->mTexture;
uint8_t* cacheBuffer = cacheTexture->getTexture();
uint8_t* bitmapBuffer = (uint8_t*) glyph.fImage;
unsigned int stride = glyph.rowBytes();
@@ -287,7 +254,8 @@ CacheTexture* FontRenderer::createCacheTexture(int width, int height, bool alloc
CacheTexture* cacheTexture = new CacheTexture(width, height);
if (allocate) {
allocateTextureMemory(cacheTexture);
Caches::getInstance().activeTexture(0);
cacheTexture->allocateTexture();
}
return cacheTexture;
@@ -362,16 +330,16 @@ void FontRenderer::checkTextureUpdate() {
// 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) {
if (cacheTexture->isDirty() && cacheTexture->getTexture()) {
uint32_t xOffset = 0;
uint32_t width = cacheTexture->mWidth;
uint32_t height = cacheTexture->mHeight;
void* textureData = cacheTexture->mTexture;
uint32_t width = cacheTexture->getWidth();
uint32_t height = cacheTexture->getHeight();
void* textureData = cacheTexture->getTexture();
if (cacheTexture->mTextureId != lastTextureId) {
if (cacheTexture->getTextureId() != lastTextureId) {
lastTextureId = cacheTexture->getTextureId();
caches.activeTexture(0);
glBindTexture(GL_TEXTURE_2D, cacheTexture->mTextureId);
lastTextureId = cacheTexture->mTextureId;
glBindTexture(GL_TEXTURE_2D, lastTextureId);
}
#if DEBUG_FONT_RENDERER
ALOGD("glTextSubimage for cacheTexture %d: xOff, width height = %d, %d, %d",
@@ -380,18 +348,14 @@ void FontRenderer::checkTextureUpdate() {
glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, 0, width, height,
GL_ALPHA, GL_UNSIGNED_BYTE, textureData);
cacheTexture->mDirty = false;
cacheTexture->setDirty(false);
}
}
caches.activeTexture(0);
glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
if (mLinearFiltering != mCurrentCacheTexture->mLinearFiltering) {
const GLenum filtering = mLinearFiltering ? GL_LINEAR : GL_NEAREST;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
mCurrentCacheTexture->mLinearFiltering = mLinearFiltering;
}
glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->getTextureId());
mCurrentCacheTexture->setLinearFiltering(mLinearFiltering, false);
mLastCacheTexture = mCurrentCacheTexture;
mUploadTexture = false;

View File

@@ -85,25 +85,18 @@ public:
GLuint getTexture(bool linearFiltering = false) {
checkInit();
if (linearFiltering != mCurrentCacheTexture->mLinearFiltering) {
mCurrentCacheTexture->mLinearFiltering = linearFiltering;
mLinearFiltering = linearFiltering;
const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
mCurrentCacheTexture->setLinearFiltering(linearFiltering);
mLinearFiltering = linearFiltering;
glBindTexture(GL_TEXTURE_2D, mCurrentCacheTexture->mTextureId);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
}
return mCurrentCacheTexture->mTextureId;
return mCurrentCacheTexture->getTextureId();
}
uint32_t getCacheSize() const {
uint32_t size = 0;
for (uint32_t i = 0; i < mCacheTextures.size(); i++) {
CacheTexture* cacheTexture = mCacheTextures[i];
if (cacheTexture != NULL && cacheTexture->mTexture != NULL) {
size += cacheTexture->mWidth * cacheTexture->mHeight;
if (cacheTexture && cacheTexture->getTexture()) {
size += cacheTexture->getWidth() * cacheTexture->getHeight();
}
}
return size;

View File

@@ -103,8 +103,91 @@ public:
mWidth - TEXTURE_BORDER_SIZE, mHeight - TEXTURE_BORDER_SIZE, true);
}
void releaseTexture() {
if (mTexture) {
glDeleteTextures(1, &mTextureId);
delete[] mTexture;
mTexture = NULL;
mTextureId = 0;
}
}
/**
* This method assumes that the proper texture unit is active.
*/
void allocateTexture() {
int width = mWidth;
int height = mHeight;
mTexture = new uint8_t[width * height];
if (!mTextureId) {
glGenTextures(1, &mTextureId);
}
glBindTexture(GL_TEXTURE_2D, mTextureId);
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
// Initialize texture dimensions
glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, width, height, 0,
GL_ALPHA, GL_UNSIGNED_BYTE, 0);
const GLenum filtering = getLinearFiltering() ? GL_LINEAR : GL_NEAREST;
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
bool fitBitmap(const SkGlyph& glyph, uint32_t *retOriginX, uint32_t *retOriginY);
inline uint16_t getWidth() const {
return mWidth;
}
inline uint16_t getHeight() const {
return mHeight;
}
inline uint8_t* getTexture() const {
return mTexture;
}
inline GLuint getTextureId() const {
return mTextureId;
}
inline bool isDirty() const {
return mDirty;
}
inline void setDirty(bool dirty) {
mDirty = dirty;
}
inline bool getLinearFiltering() const {
return mLinearFiltering;
}
/**
* This method assumes that the proper texture unit is active.
*/
void setLinearFiltering(bool linearFiltering, bool bind = true) {
if (linearFiltering != mLinearFiltering) {
mLinearFiltering = linearFiltering;
const GLenum filtering = linearFiltering ? GL_LINEAR : GL_NEAREST;
if (bind) glBindTexture(GL_TEXTURE_2D, getTextureId());
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, filtering);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, filtering);
}
}
inline uint16_t getGlyphCount() const {
return mNumGlyphs;
}
private:
uint8_t* mTexture;
GLuint mTextureId;
uint16_t mWidth;

View File

@@ -48,10 +48,10 @@ Font::~Font() {
}
}
void Font::invalidateTextureCache(CacheTexture *cacheTexture) {
void Font::invalidateTextureCache(CacheTexture* cacheTexture) {
for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) {
CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueAt(i);
if (cacheTexture == NULL || cachedGlyph->mCacheTexture == cacheTexture) {
if (cacheTexture || cachedGlyph->mCacheTexture == cacheTexture) {
cachedGlyph->mIsValid = false;
}
}
@@ -106,9 +106,9 @@ 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->mCacheTexture;
uint32_t cacheWidth = cacheTexture->mWidth;
const uint8_t* cacheBuffer = cacheTexture->mTexture;
CacheTexture* cacheTexture = glyph->mCacheTexture;
uint32_t cacheWidth = cacheTexture->getWidth();
const uint8_t* cacheBuffer = cacheTexture->getTexture();
uint32_t cacheX = 0, cacheY = 0;
int32_t bX = 0, bY = 0;
@@ -392,8 +392,8 @@ void Font::updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyp
glyph->mBitmapWidth = skiaGlyph.fWidth;
glyph->mBitmapHeight = skiaGlyph.fHeight;
uint32_t cacheWidth = glyph->mCacheTexture->mWidth;
uint32_t cacheHeight = glyph->mCacheTexture->mHeight;
uint32_t cacheWidth = glyph->mCacheTexture->getWidth();
uint32_t cacheHeight = glyph->mCacheTexture->getHeight();
glyph->mBitmapMinU = startX / (float) cacheWidth;
glyph->mBitmapMinV = startY / (float) cacheHeight;

View File

@@ -94,7 +94,7 @@ private:
// Cache of glyphs
DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs;
void invalidateTextureCache(CacheTexture *cacheTexture = NULL);
void invalidateTextureCache(CacheTexture* cacheTexture = NULL);
CachedGlyphInfo* cacheGlyph(SkPaint* paint, glyph_t glyph, bool precaching);
void updateGlyphCache(SkPaint* paint, const SkGlyph& skiaGlyph, CachedGlyphInfo* glyph,