diff options
Diffstat (limited to 'libs/hwui/FontRenderer.cpp')
| -rw-r--r-- | libs/hwui/FontRenderer.cpp | 205 |
1 files changed, 115 insertions, 90 deletions
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 5b5b098..6bef7c7 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -14,7 +14,20 @@ * limitations under the License. */ -#define LOG_TAG "OpenGLRenderer" +#include "FontRenderer.h" + +#include "Caches.h" +#include "Debug.h" +#include "Extensions.h" +#include "Glop.h" +#include "GlopBuilder.h" +#include "OpenGLRenderer.h" +#include "PixelBuffer.h" +#include "Rect.h" +#include "renderstate/RenderState.h" +#include "utils/Blur.h" +#include "utils/MathUtils.h" +#include "utils/Timing.h" #include <SkGlyph.h> #include <SkUtils.h> @@ -27,30 +40,18 @@ #include <RenderScript.h> #endif -#include "utils/Blur.h" -#include "utils/Timing.h" - -#include "Caches.h" -#include "Debug.h" -#include "Extensions.h" -#include "FontRenderer.h" -#include "OpenGLRenderer.h" -#include "PixelBuffer.h" -#include "Rect.h" - namespace android { namespace uirenderer { // blur inputs smaller than this constant will bypass renderscript #define RS_MIN_INPUT_CUTOFF 10000 +#define USE_GLOPS true + /////////////////////////////////////////////////////////////////////////////// // TextSetupFunctor /////////////////////////////////////////////////////////////////////////////// -status_t TextSetupFunctor::operator ()(int what, void* data) { - Data* typedData = reinterpret_cast<Data*>(data); - GLenum glyphFormat = typedData ? typedData->glyphFormat : GL_ALPHA; - +void TextSetupFunctor::setup(GLenum glyphFormat) { renderer->setupDraw(); renderer->setupDrawTextGamma(paint); renderer->setupDrawDirtyRegionsDisabled(); @@ -87,8 +88,24 @@ status_t TextSetupFunctor::operator ()(int what, void* data) { renderer->setupDrawColorFilterUniforms(paint->getColorFilter()); renderer->setupDrawShaderUniforms(paint->getShader(), pureTranslate); renderer->setupDrawTextGammaUniforms(); +} - return NO_ERROR; +void TextSetupFunctor::draw(CacheTexture& texture, bool linearFiltering) { + int textureFillFlags = static_cast<int>(texture.getFormat() == GL_ALPHA + ? TextureFillFlags::kIsAlphaMaskTexture : TextureFillFlags::kNone); + if (linearFiltering) { + textureFillFlags |= TextureFillFlags::kForceFilter; + } + const Matrix4& transform = pureTranslate ? Matrix4::identity() : *(renderer->currentTransform()); + Glop glop; + GlopBuilder(renderer->mRenderState, renderer->mCaches, &glop) + .setMeshTexturedIndexedQuads(texture.mesh(), texture.meshElementCount()) + .setFillTexturePaint(texture.getTexture(), textureFillFlags, paint, renderer->currentSnapshot()->alpha) + .setTransform(renderer->currentSnapshot()->getOrthoMatrix(), transform, false) + .setModelViewOffsetRect(0, 0, Rect(0, 0, 0, 0)) + .setRoundRectClipState(renderer->currentSnapshot()->roundRectClipState) + .build(); + renderer->renderGlop(glop); } /////////////////////////////////////////////////////////////////////////////// @@ -97,47 +114,51 @@ status_t TextSetupFunctor::operator ()(int what, void* data) { static bool sLogFontRendererCreate = true; -FontRenderer::FontRenderer() : - mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity) { +FontRenderer::FontRenderer() + : mGammaTable(nullptr) + , mCurrentFont(nullptr) + , mActiveFonts(LruCache<Font::FontDescription, Font*>::kUnlimitedCapacity) + , mCurrentCacheTexture(nullptr) + , mUploadTexture(false) + , mFunctor(nullptr) + , mClip(nullptr) + , mBounds(nullptr) + , mDrawn(false) + , mInitialized(false) + , mLinearFiltering(false) { if (sLogFontRendererCreate) { INIT_LOGD("Creating FontRenderer"); } - mGammaTable = NULL; - mInitialized = false; - - mCurrentCacheTexture = NULL; - - mLinearFiltering = false; - mSmallCacheWidth = DEFAULT_TEXT_SMALL_CACHE_WIDTH; mSmallCacheHeight = DEFAULT_TEXT_SMALL_CACHE_HEIGHT; mLargeCacheWidth = DEFAULT_TEXT_LARGE_CACHE_WIDTH; mLargeCacheHeight = DEFAULT_TEXT_LARGE_CACHE_HEIGHT; char property[PROPERTY_VALUE_MAX]; - if (property_get(PROPERTY_TEXT_SMALL_CACHE_WIDTH, property, NULL) > 0) { + if (property_get(PROPERTY_TEXT_SMALL_CACHE_WIDTH, property, nullptr) > 0) { mSmallCacheWidth = atoi(property); } - if (property_get(PROPERTY_TEXT_SMALL_CACHE_HEIGHT, property, NULL) > 0) { + if (property_get(PROPERTY_TEXT_SMALL_CACHE_HEIGHT, property, nullptr) > 0) { mSmallCacheHeight = atoi(property); } - if (property_get(PROPERTY_TEXT_LARGE_CACHE_WIDTH, property, NULL) > 0) { + if (property_get(PROPERTY_TEXT_LARGE_CACHE_WIDTH, property, nullptr) > 0) { mLargeCacheWidth = atoi(property); } - if (property_get(PROPERTY_TEXT_LARGE_CACHE_HEIGHT, property, NULL) > 0) { + if (property_get(PROPERTY_TEXT_LARGE_CACHE_HEIGHT, property, nullptr) > 0) { mLargeCacheHeight = atoi(property); } uint32_t maxTextureSize = (uint32_t) Caches::getInstance().maxTextureSize; - mSmallCacheWidth = mSmallCacheWidth > maxTextureSize ? maxTextureSize : mSmallCacheWidth; - mSmallCacheHeight = mSmallCacheHeight > maxTextureSize ? maxTextureSize : mSmallCacheHeight; - mLargeCacheWidth = mLargeCacheWidth > maxTextureSize ? maxTextureSize : mLargeCacheWidth; - mLargeCacheHeight = mLargeCacheHeight > maxTextureSize ? maxTextureSize : mLargeCacheHeight; + + mSmallCacheWidth = MathUtils::min(mSmallCacheWidth, maxTextureSize); + mSmallCacheHeight = MathUtils::min(mSmallCacheHeight, maxTextureSize); + mLargeCacheWidth = MathUtils::min(mLargeCacheWidth, maxTextureSize); + mLargeCacheHeight = MathUtils::min(mLargeCacheHeight, maxTextureSize); if (sLogFontRendererCreate) { INIT_LOGD(" Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i", @@ -195,7 +216,7 @@ void FontRenderer::flushLargeCaches(Vector<CacheTexture*>& cacheTextures) { while (it.next()) { it.value()->invalidateTextureCache(cacheTexture); } - cacheTexture->releaseTexture(); + cacheTexture->releasePixelBuffer(); } } } @@ -213,7 +234,7 @@ CacheTexture* FontRenderer::cacheBitmapInTexture(Vector<CacheTexture*>& cacheTex } } // Could not fit glyph into current cache textures - return NULL; + return nullptr; } void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, @@ -224,7 +245,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp // so we can avoid doing extra work later on if (glyph.fWidth == 0 || glyph.fHeight == 0) { cachedGlyph->mIsValid = true; - cachedGlyph->mCacheTexture = NULL; + cachedGlyph->mCacheTexture = nullptr; return; } @@ -232,7 +253,7 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp // choose an appropriate cache texture list for this glyph format SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); - Vector<CacheTexture*>* cacheTextures = NULL; + Vector<CacheTexture*>* cacheTextures = nullptr; switch (format) { case SkMask::kA8_Format: case SkMask::kBW_Format: @@ -287,9 +308,9 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp uint32_t cacheWidth = cacheTexture->getWidth(); if (!cacheTexture->getPixelBuffer()) { - Caches::getInstance().activeTexture(0); + Caches::getInstance().textureState().activateTexture(0); // Large-glyph texture memory is allocated only as needed - cacheTexture->allocateTexture(); + cacheTexture->allocatePixelBuffer(); } if (!cacheTexture->mesh()) { cacheTexture->allocateMesh(); @@ -397,11 +418,11 @@ void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyp CacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format, bool allocate) { - CacheTexture* cacheTexture = new CacheTexture(width, height, format, gMaxNumberOfQuads); + CacheTexture* cacheTexture = new CacheTexture(width, height, format, kMaxNumberOfQuads); if (allocate) { - Caches::getInstance().activeTexture(0); - cacheTexture->allocateTexture(); + Caches::getInstance().textureState().activateTexture(0); + cacheTexture->allocatePixelBuffer(); cacheTexture->allocateMesh(); } @@ -446,8 +467,8 @@ void checkTextureUpdateForCache(Caches& caches, Vector<CacheTexture*>& cacheText if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) { if (cacheTexture->getTextureId() != lastTextureId) { lastTextureId = cacheTexture->getTextureId(); - caches.activeTexture(0); - caches.bindTexture(lastTextureId); + caches.textureState().activateTexture(0); + caches.textureState().bindTexture(lastTextureId); } if (cacheTexture->upload()) { @@ -473,7 +494,7 @@ void FontRenderer::checkTextureUpdate() { checkTextureUpdateForCache(caches, mRGBACacheTextures, resetPixelStore, lastTextureId); // Unbind any PBO we might have used to update textures - caches.unbindPixelBuffer(); + caches.pixelBufferState().unbind(); // Reset to default unpack row length to avoid affecting texture // uploads in other parts of the renderer @@ -485,44 +506,53 @@ void FontRenderer::checkTextureUpdate() { } void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) { - Caches& caches = Caches::getInstance(); + if (!mFunctor) return; + +#if !USE_GLOPS + Caches& caches = mFunctor->renderer->getCaches(); + RenderState& renderState = mFunctor->renderer->renderState(); +#endif + bool first = true; - bool force = false; + bool forceRebind = false; for (uint32_t i = 0; i < cacheTextures.size(); i++) { CacheTexture* texture = cacheTextures[i]; if (texture->canDraw()) { if (first) { - if (mFunctor) { - TextSetupFunctor::Data functorData(texture->getFormat()); - (*mFunctor)(0, &functorData); - } - checkTextureUpdate(); - caches.bindQuadIndicesBuffer(); +#if !USE_GLOPS + mFunctor->setup(texture->getFormat()); - if (!mDrawn) { - // If returns true, a VBO was bound and we must - // rebind our vertex attrib pointers even if - // they have the same values as the current pointers - force = caches.unbindMeshBuffer(); - } + renderState.meshState().bindQuadIndicesBuffer(); - caches.activeTexture(0); + // If returns true, a VBO was bound and we must + // rebind our vertex attrib pointers even if + // they have the same values as the current pointers + forceRebind = renderState.meshState().unbindMeshBuffer(); + + caches.textureState().activateTexture(0); +#endif first = false; + mDrawn = true; } +#if USE_GLOPS + mFunctor->draw(*texture, mLinearFiltering); +#endif - caches.bindTexture(texture->getTextureId()); - texture->setLinearFiltering(mLinearFiltering, false); +#if !USE_GLOPS + caches.textureState().bindTexture(texture->getTextureId()); + texture->setLinearFiltering(mLinearFiltering); TextureVertex* mesh = texture->mesh(); - caches.bindPositionVertexPointer(force, &mesh[0].x); - caches.bindTexCoordsVertexPointer(force, &mesh[0].u); - force = false; + MeshState& meshState = renderState.meshState(); + meshState.bindPositionVertexPointer(forceRebind, &mesh[0].x); + meshState.bindTexCoordsVertexPointer(forceRebind, &mesh[0].u); glDrawElements(GL_TRIANGLES, texture->meshElementCount(), GL_UNSIGNED_SHORT, texture->indices()); - +#endif texture->resetMesh(); + forceRebind = false; } } } @@ -530,8 +560,6 @@ void FontRenderer::issueDrawCommand(Vector<CacheTexture*>& cacheTextures) { void FontRenderer::issueDrawCommand() { issueDrawCommand(mACacheTextures); issueDrawCommand(mRGBACacheTextures); - - mDrawn = true; } void FontRenderer::appendMeshQuadNoClip(float x1, float y1, float u1, float v1, @@ -598,7 +626,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, co DropShadow image; image.width = 0; image.height = 0; - image.image = NULL; + image.image = nullptr; image.penX = 0; image.penY = 0; @@ -607,8 +635,8 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, co } mDrawn = false; - mClip = NULL; - mBounds = NULL; + mClip = nullptr; + mBounds = nullptr; Rect bounds; mCurrentFont->measure(paint, text, startIndex, len, numGlyphs, &bounds, positions); @@ -644,10 +672,10 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, co // NOTE: bounds.isEmpty() can't be used here, since vertical coordinates are inverted // TODO: don't draw pure whitespace in the first place, and avoid needing this check mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY, - Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions); + Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, nullptr, positions); // Unbind any PBO we might have used - Caches::getInstance().unbindPixelBuffer(); + Caches::getInstance().pixelBufferState().unbind(); blurImage(&dataBuffer, paddedWidth, paddedHeight, radius); } @@ -661,7 +689,7 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, co return image; } -void FontRenderer::initRender(const Rect* clip, Rect* bounds, Functor* functor) { +void FontRenderer::initRender(const Rect* clip, Rect* bounds, TextSetupFunctor* functor) { checkInit(); mDrawn = false; @@ -671,8 +699,8 @@ void FontRenderer::initRender(const Rect* clip, Rect* bounds, Functor* functor) } void FontRenderer::finishRender() { - mBounds = NULL; - mClip = NULL; + mBounds = nullptr; + mClip = nullptr; issueDrawCommand(); } @@ -689,7 +717,7 @@ void FontRenderer::endPrecaching() { bool FontRenderer::renderPosText(const 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, bool forceFinish) { + const float* positions, Rect* bounds, TextSetupFunctor* functor, bool forceFinish) { if (!mCurrentFont) { ALOGE("No font set"); return false; @@ -707,7 +735,7 @@ bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const c bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const char *text, uint32_t startIndex, uint32_t len, int numGlyphs, const SkPath* path, - float hOffset, float vOffset, Rect* bounds, Functor* functor) { + float hOffset, float vOffset, Rect* bounds, TextSetupFunctor* functor) { if (!mCurrentFont) { ALOGE("No font set"); return false; @@ -724,7 +752,7 @@ void FontRenderer::removeFont(const Font* font) { mActiveFonts.remove(font->getDescription()); if (mCurrentFont == font) { - mCurrentFont = NULL; + mCurrentFont = nullptr; } } @@ -734,7 +762,7 @@ void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, flo if (width * height * intRadius >= RS_MIN_INPUT_CUTOFF) { uint8_t* outImage = (uint8_t*) memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height); - if (mRs == 0) { + if (mRs == nullptr) { mRs = new RSC::RS(); // a null path is OK because there are no custom kernels used // hence nothing gets cached by RS @@ -746,7 +774,7 @@ void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, flo mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement); } } - if (mRs != 0) { + if (mRs != nullptr) { RSC::sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0); RSC::sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t, RS_ALLOCATION_MIPMAP_NONE, @@ -770,15 +798,12 @@ void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, flo } #endif - float *gaussian = new float[2 * intRadius + 1]; - Blur::generateGaussianWeights(gaussian, intRadius); - - uint8_t* scratch = new uint8_t[width * height]; - Blur::horizontal(gaussian, intRadius, *image, scratch, width, height); - Blur::vertical(gaussian, intRadius, scratch, *image, width, height); + std::unique_ptr<float[]> gaussian(new float[2 * intRadius + 1]); + Blur::generateGaussianWeights(gaussian.get(), intRadius); - delete[] gaussian; - delete[] scratch; + std::unique_ptr<uint8_t[]> scratch(new uint8_t[width * height]); + Blur::horizontal(gaussian.get(), intRadius, *image, scratch.get(), width, height); + Blur::vertical(gaussian.get(), intRadius, scratch.get(), *image, width, height); } static uint32_t calculateCacheSize(const Vector<CacheTexture*>& cacheTextures) { |
