diff options
Diffstat (limited to 'libs/hwui/FontRenderer.cpp')
-rw-r--r-- | libs/hwui/FontRenderer.cpp | 104 |
1 files changed, 62 insertions, 42 deletions
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 26c7e5d..543cfa2 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -31,7 +31,9 @@ #include "Caches.h" #include "Debug.h" +#include "Extensions.h" #include "FontRenderer.h" +#include "PixelBuffer.h" #include "Rect.h" namespace android { @@ -55,7 +57,6 @@ FontRenderer::FontRenderer() : mGammaTable = NULL; mInitialized = false; - mMaxNumberOfQuads = 1024; mCurrentCacheTexture = NULL; @@ -132,26 +133,13 @@ void FontRenderer::flushAllAndInvalidate() { for (uint32_t i = 0; i < mCacheTextures.size(); i++) { mCacheTextures[i]->init(); } - -#if DEBUG_FONT_RENDERER - uint16_t totalGlyphs = 0; - for (uint32_t i = 0; i < mCacheTextures.size(); i++) { - totalGlyphs += mCacheTextures[i]->getGlyphCount(); - // Erase caches, just as a debugging facility - 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::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->getTexture()) { + if (cacheTexture->getPixelBuffer()) { cacheTexture->init(); LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); while (it.next()) { @@ -225,7 +213,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp uint32_t cacheWidth = cacheTexture->getWidth(); - if (!cacheTexture->getTexture()) { + if (!cacheTexture->getPixelBuffer()) { Caches::getInstance().activeTexture(0); // Large-glyph texture memory is allocated only as needed cacheTexture->allocateTexture(); @@ -238,7 +226,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp // or anti-aliased (8 bits per pixel) SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); - uint8_t* cacheBuffer = cacheTexture->getTexture(); + uint8_t* cacheBuffer = cacheTexture->getPixelBuffer()->map(); uint32_t cacheX = 0, bX = 0, cacheY = 0, bY = 0; // Copy the glyph image, taking the mask format into account @@ -304,7 +292,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp } CacheTexture* FontRenderer::createCacheTexture(int width, int height, bool allocate) { - CacheTexture* cacheTexture = new CacheTexture(width, height, mMaxNumberOfQuads); + CacheTexture* cacheTexture = new CacheTexture(width, height, gMaxNumberOfQuads); if (allocate) { Caches::getInstance().activeTexture(0); @@ -331,12 +319,12 @@ void FontRenderer::initTextTexture() { // Avoid having to reallocate memory and render quad by quad void FontRenderer::initVertexArrayBuffers() { - uint32_t numIndices = mMaxNumberOfQuads * 6; + uint32_t numIndices = gMaxNumberOfQuads * 6; uint32_t indexBufferSizeBytes = numIndices * sizeof(uint16_t); uint16_t* indexBufferData = (uint16_t*) malloc(indexBufferSizeBytes); // Four verts, two triangles , six indices per quad - for (uint32_t i = 0; i < mMaxNumberOfQuads; i++) { + for (uint32_t i = 0; i < gMaxNumberOfQuads; i++) { int i6 = i * 6; int i4 = i * 4; @@ -375,34 +363,40 @@ void FontRenderer::checkTextureUpdate() { Caches& caches = Caches::getInstance(); GLuint lastTextureId = 0; + + bool resetPixelStore = false; + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + // 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->isDirty() && cacheTexture->getTexture()) { - // Can't copy inner rect; glTexSubimage expects pointer to deal with entire buffer - // of data. So expand the dirty rect to the encompassing horizontal stripe. - const Rect* dirtyRect = cacheTexture->getDirtyRect(); - uint32_t x = 0; - uint32_t y = dirtyRect->top; - uint32_t width = cacheTexture->getWidth(); - uint32_t height = dirtyRect->getHeight(); - void* textureData = cacheTexture->getTexture() + y * width; - + if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) { if (cacheTexture->getTextureId() != lastTextureId) { lastTextureId = cacheTexture->getTextureId(); caches.activeTexture(0); glBindTexture(GL_TEXTURE_2D, lastTextureId); } + + if (cacheTexture->upload()) { + resetPixelStore = true; + } + #if DEBUG_FONT_RENDERER ALOGD("glTexSubimage for cacheTexture %d: x, y, width height = %d, %d, %d, %d", i, x, y, width, height); #endif - glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, - GL_ALPHA, GL_UNSIGNED_BYTE, textureData); - cacheTexture->setDirty(false); } } + // Unbind any PBO we might have used to update textures + caches.unbindPixelBuffer(); + + // Reset to default unpack row length to avoid affecting texture + // uploads in other parts of the renderer + if (resetPixelStore) { + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + } + mUploadTexture = false; } @@ -512,13 +506,14 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch uint32_t startIndex, uint32_t len, int numGlyphs, uint32_t radius, const float* positions) { checkInit(); + DropShadow image; + image.width = 0; + image.height = 0; + image.image = NULL; + image.penX = 0; + image.penY = 0; + if (!mCurrentFont) { - DropShadow image; - image.width = 0; - image.height = 0; - image.image = NULL; - image.penX = 0; - image.penY = 0; return image; } @@ -532,6 +527,11 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius; uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius; + uint32_t maxSize = Caches::getInstance().maxTextureSize; + if (paddedWidth > maxSize || paddedHeight > maxSize) { + return image; + } + // Align buffers for renderscript usage if (paddedWidth & (RS_CPU_ALLOCATION_ALIGNMENT - 1)) { paddedWidth += RS_CPU_ALLOCATION_ALIGNMENT - paddedWidth % RS_CPU_ALLOCATION_ALIGNMENT; @@ -551,10 +551,12 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY, Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions); + // Unbind any PBO we might have used + Caches::getInstance().unbindPixelBuffer(); + blurImage(&dataBuffer, paddedWidth, paddedHeight, radius); } - DropShadow image; image.width = paddedWidth; image.height = paddedHeight; image.image = dataBuffer; @@ -585,9 +587,13 @@ void FontRenderer::precache(SkPaint* paint, const char* text, int numGlyphs, con font->precache(paint, text, numGlyphs); } +void FontRenderer::endPrecaching() { + checkTextureUpdate(); +} + bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, int x, int y, - const float* positions, Rect* bounds, Functor* functor) { + const float* positions, Rect* bounds, Functor* functor, bool forceFinish) { if (!mCurrentFont) { ALOGE("No font set"); return false; @@ -595,7 +601,10 @@ bool FontRenderer::renderPosText(SkPaint* paint, const Rect* clip, const char *t initRender(clip, bounds, functor); mCurrentFont->render(paint, text, startIndex, len, numGlyphs, x, y, positions); - finishRender(); + + if (forceFinish) { + finishRender(); + } return mDrawn; } @@ -663,5 +672,16 @@ void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int *image = outImage; } +uint32_t FontRenderer::getCacheSize() const { + uint32_t size = 0; + for (uint32_t i = 0; i < mCacheTextures.size(); i++) { + CacheTexture* cacheTexture = mCacheTextures[i]; + if (cacheTexture && cacheTexture->getPixelBuffer()) { + size += cacheTexture->getPixelBuffer()->getSize(); + } + } + return size; +} + }; // namespace uirenderer }; // namespace android |