diff options
-rw-r--r-- | libs/hwui/Android.bp | 7 | ||||
-rw-r--r-- | libs/hwui/BakedOpDispatcher.cpp | 138 | ||||
-rw-r--r-- | libs/hwui/BakedOpDispatcher.h | 2 | ||||
-rw-r--r-- | libs/hwui/BakedOpState.h | 2 | ||||
-rw-r--r-- | libs/hwui/Caches.cpp | 17 | ||||
-rw-r--r-- | libs/hwui/Caches.h | 5 | ||||
-rw-r--r-- | libs/hwui/DisplayList.h | 1 | ||||
-rw-r--r-- | libs/hwui/FontRenderer.cpp | 802 | ||||
-rw-r--r-- | libs/hwui/FontRenderer.h | 208 | ||||
-rw-r--r-- | libs/hwui/FrameBuilder.cpp | 42 | ||||
-rw-r--r-- | libs/hwui/GammaFontRenderer.cpp | 43 | ||||
-rw-r--r-- | libs/hwui/GammaFontRenderer.h | 70 | ||||
-rw-r--r-- | libs/hwui/GlopBuilder.cpp | 19 | ||||
-rw-r--r-- | libs/hwui/RecordedOp.h | 2 | ||||
-rw-r--r-- | libs/hwui/TextDropShadowCache.cpp | 209 | ||||
-rw-r--r-- | libs/hwui/TextDropShadowCache.h | 164 | ||||
-rw-r--r-- | libs/hwui/font/CacheTexture.cpp | 355 | ||||
-rw-r--r-- | libs/hwui/font/CacheTexture.h | 173 | ||||
-rw-r--r-- | libs/hwui/font/Font.cpp | 490 | ||||
-rw-r--r-- | libs/hwui/font/Font.h | 161 | ||||
-rw-r--r-- | libs/hwui/font/FontCacheHistoryTracker.cpp | 100 | ||||
-rw-r--r-- | libs/hwui/font/FontCacheHistoryTracker.h | 65 | ||||
-rw-r--r-- | libs/hwui/font/FontUtil.h | 46 | ||||
-rw-r--r-- | libs/hwui/tests/microbench/FontBench.cpp | 50 |
24 files changed, 13 insertions, 3158 deletions
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 065b822b50ad..3495c4f2acef 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -75,7 +75,6 @@ cc_defaults { cc_defaults { name: "hwui_bugreport_font_cache_usage", - srcs: ["font/FontCacheHistoryTracker.cpp"], cflags: ["-DBUGREPORT_FONT_CACHE_USAGE"], } @@ -152,8 +151,6 @@ cc_defaults { "hwui/AnimatedImageDrawable.cpp", "hwui/AnimatedImageThread.cpp", "hwui/Bitmap.cpp", - "font/CacheTexture.cpp", - "font/Font.cpp", "hwui/Canvas.cpp", "hwui/MinikinSkia.cpp", "hwui/MinikinUtils.cpp", @@ -215,11 +212,9 @@ cc_defaults { "DeviceInfo.cpp", "DisplayList.cpp", "FboCache.cpp", - "FontRenderer.cpp", "FrameBuilder.cpp", "FrameInfo.cpp", "FrameInfoVisualizer.cpp", - "GammaFontRenderer.cpp", "GlLayer.cpp", "GlopBuilder.cpp", "GpuMemoryTracker.cpp", @@ -259,7 +254,6 @@ cc_defaults { "Snapshot.cpp", "SpotShadow.cpp", "TessellationCache.cpp", - "TextDropShadowCache.cpp", "Texture.cpp", "TextureCache.cpp", "VectorDrawable.cpp", @@ -413,7 +407,6 @@ cc_benchmark { srcs: [ "tests/microbench/main.cpp", "tests/microbench/DisplayListCanvasBench.cpp", - "tests/microbench/FontBench.cpp", "tests/microbench/FrameBuilderBench.cpp", "tests/microbench/LinearAllocatorBench.cpp", "tests/microbench/PathParserBench.cpp", diff --git a/libs/hwui/BakedOpDispatcher.cpp b/libs/hwui/BakedOpDispatcher.cpp index f78cb418c5cd..2c7aab8b784e 100644 --- a/libs/hwui/BakedOpDispatcher.cpp +++ b/libs/hwui/BakedOpDispatcher.cpp @@ -187,121 +187,14 @@ void BakedOpDispatcher::onMergedPatchOps(BakedOpRenderer& renderer, static void renderTextShadow(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& textOpState) { - if (CC_LIKELY(!PaintUtils::hasTextShadow(op.paint))) return; - - FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer(); - fontRenderer.setFont(op.paint, SkMatrix::I()); - renderer.caches().textureState().activateTexture(0); - - PaintUtils::TextShadow textShadow; - if (!PaintUtils::getTextShadow(op.paint, &textShadow)) { - LOG_ALWAYS_FATAL("failed to query shadow attributes"); - } - - renderer.caches().dropShadowCache.setFontRenderer(fontRenderer); - ShadowTexture* texture = renderer.caches().dropShadowCache.get( - op.paint, op.glyphs, op.glyphCount, textShadow.radius, op.positions); - // If the drop shadow exceeds the max texture size or couldn't be - // allocated, skip drawing - if (!texture) return; - const AutoTexture autoCleanup(texture); - - const float sx = op.x - texture->left + textShadow.dx; - const float sy = op.y - texture->top + textShadow.dy; - - Glop glop; - GlopBuilder(renderer.renderState(), renderer.caches(), &glop) - .setRoundRectClipState(textOpState.roundRectClipState) - .setMeshTexturedUnitQuad(nullptr) - .setFillShadowTexturePaint(*texture, textShadow.color, *op.paint, textOpState.alpha) - .setTransform(textOpState.computedState.transform, TransformFlags::None) - .setModelViewMapUnitToRect(Rect(sx, sy, sx + texture->width(), sy + texture->height())) - .build(); - - // Compute damage bounds and clip (since may differ from those in textOpState). - // Bounds should be same as text op, but with dx/dy offset and radius outset - // applied in local space. - auto& transform = textOpState.computedState.transform; - Rect shadowBounds = op.unmappedBounds; // STROKE - const bool expandForStroke = op.paint->getStyle() != SkPaint::kFill_Style; - if (expandForStroke) { - shadowBounds.outset(op.paint->getStrokeWidth() * 0.5f); - } - shadowBounds.translate(textShadow.dx, textShadow.dy); - shadowBounds.outset(textShadow.radius, textShadow.radius); - transform.mapRect(shadowBounds); - if (CC_UNLIKELY(expandForStroke && - (!transform.isPureTranslate() || op.paint->getStrokeWidth() < 1.0f))) { - shadowBounds.outset(0.5f); - } - - auto clipState = textOpState.computedState.clipState; - if (clipState->mode != ClipMode::Rectangle || !clipState->rect.contains(shadowBounds)) { - // need clip, so pass it and clip bounds - shadowBounds.doIntersect(clipState->rect); - } else { - // don't need clip, ignore - clipState = nullptr; - } - - renderer.renderGlop(&shadowBounds, clipState, glop); + // DEAD CODE } enum class TextRenderType { Defer, Flush }; static void renderText(BakedOpRenderer& renderer, const TextOp& op, const BakedOpState& state, const ClipBase* renderClip, TextRenderType renderType) { - FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer(); - float x = op.x; - float y = op.y; - const Matrix4& transform = state.computedState.transform; - const bool pureTranslate = transform.isPureTranslate(); - if (CC_LIKELY(pureTranslate)) { - x = floorf(x + transform.getTranslateX() + 0.5f); - y = floorf(y + transform.getTranslateY() + 0.5f); - fontRenderer.setFont(op.paint, SkMatrix::I()); - fontRenderer.setTextureFiltering(false); - } else if (CC_UNLIKELY(transform.isPerspective())) { - fontRenderer.setFont(op.paint, SkMatrix::I()); - fontRenderer.setTextureFiltering(true); - } else { - // We only pass a partial transform to the font renderer. That partial - // matrix defines how glyphs are rasterized. Typically we want glyphs - // to be rasterized at their final size on screen, which means the partial - // matrix needs to take the scale factor into account. - // When a partial matrix is used to transform glyphs during rasterization, - // the mesh is generated with the inverse transform (in the case of scale, - // the mesh is generated at 1.0 / scale for instance.) This allows us to - // apply the full transform matrix at draw time in the vertex shader. - // Applying the full matrix in the shader is the easiest way to handle - // rotation and perspective and allows us to always generated quads in the - // font renderer which greatly simplifies the code, clipping in particular. - float sx, sy; - transform.decomposeScale(sx, sy); - fontRenderer.setFont(op.paint, SkMatrix::MakeScale(roundf(std::max(1.0f, sx)), - roundf(std::max(1.0f, sy)))); - fontRenderer.setTextureFiltering(true); - } - Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); - - int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha; - SkBlendMode mode = PaintUtils::getBlendModeDirect(op.paint); - TextDrawFunctor functor(&renderer, &state, renderClip, x, y, pureTranslate, alpha, mode, - op.paint); - - bool forceFinish = (renderType == TextRenderType::Flush); - bool mustDirtyRenderTarget = renderer.offscreenRenderTarget(); - const Rect* localOpClip = pureTranslate ? &state.computedState.clipRect() : nullptr; - fontRenderer.renderPosText(op.paint, localOpClip, op.glyphs, op.glyphCount, x, y, op.positions, - mustDirtyRenderTarget ? &layerBounds : nullptr, &functor, - forceFinish); - - if (mustDirtyRenderTarget) { - if (!pureTranslate) { - transform.mapRect(layerBounds); - } - renderer.dirtyRenderTarget(layerBounds); - } + // DEAD CODE } void BakedOpDispatcher::onMergedTextOps(BakedOpRenderer& renderer, @@ -747,32 +640,7 @@ void BakedOpDispatcher::onTextOp(BakedOpRenderer& renderer, const TextOp& op, void BakedOpDispatcher::onTextOnPathOp(BakedOpRenderer& renderer, const TextOnPathOp& op, const BakedOpState& state) { - // Note: can't trust clipSideFlags since we record with unmappedBounds == clip. - // TODO: respect clipSideFlags, once we record with bounds - auto renderTargetClip = state.computedState.clipState; - - FontRenderer& fontRenderer = renderer.caches().fontRenderer.getFontRenderer(); - fontRenderer.setFont(op.paint, SkMatrix::I()); - fontRenderer.setTextureFiltering(true); - - Rect layerBounds(FLT_MAX / 2.0f, FLT_MAX / 2.0f, FLT_MIN / 2.0f, FLT_MIN / 2.0f); - - int alpha = PaintUtils::getAlphaDirect(op.paint) * state.alpha; - SkBlendMode mode = PaintUtils::getBlendModeDirect(op.paint); - TextDrawFunctor functor(&renderer, &state, renderTargetClip, 0.0f, 0.0f, false, alpha, mode, - op.paint); - - bool mustDirtyRenderTarget = renderer.offscreenRenderTarget(); - const Rect localSpaceClip = state.computedState.computeLocalSpaceClip(); - if (fontRenderer.renderTextOnPath(op.paint, &localSpaceClip, op.glyphs, op.glyphCount, op.path, - op.hOffset, op.vOffset, - mustDirtyRenderTarget ? &layerBounds : nullptr, &functor)) { - if (mustDirtyRenderTarget) { - // manually dirty render target, since TextDrawFunctor won't - state.computedState.transform.mapRect(layerBounds); - renderer.dirtyRenderTarget(layerBounds); - } - } + // DEAD CODE } void BakedOpDispatcher::onTextureLayerOp(BakedOpRenderer& renderer, const TextureLayerOp& op, diff --git a/libs/hwui/BakedOpDispatcher.h b/libs/hwui/BakedOpDispatcher.h index e3708685afc9..cc3287075ef8 100644 --- a/libs/hwui/BakedOpDispatcher.h +++ b/libs/hwui/BakedOpDispatcher.h @@ -23,6 +23,8 @@ namespace android { namespace uirenderer { +class BakedOpRenderer; + /** * Provides all "onBitmapOp(...)" style static methods for every op type, which convert the * RecordedOps and their state to Glops, and renders them with the provided BakedOpRenderer. diff --git a/libs/hwui/BakedOpState.h b/libs/hwui/BakedOpState.h index c74475516cdc..e12dfbb18ea0 100644 --- a/libs/hwui/BakedOpState.h +++ b/libs/hwui/BakedOpState.h @@ -25,6 +25,8 @@ namespace android { namespace uirenderer { +class BakedOpState; + namespace OpClipSideFlags { enum { None = 0x0, diff --git a/libs/hwui/Caches.cpp b/libs/hwui/Caches.cpp index 3c774a3313d2..6aefb3564339 100644 --- a/libs/hwui/Caches.cpp +++ b/libs/hwui/Caches.cpp @@ -16,14 +16,10 @@ #include "Caches.h" -#include "GammaFontRenderer.h" #include "GlLayer.h" #include "Properties.h" #include "ShadowTessellator.h" #include "renderstate/RenderState.h" -#ifdef BUGREPORT_FONT_CACHE_USAGE -#include "font/FontCacheHistoryTracker.h" -#endif #include "utils/GLUtils.h" #include <cutils/properties.h> @@ -186,13 +182,9 @@ void Caches::dumpMemoryUsage(String8& log) { pathCache.getMaxSize()); log.appendFormat(" TessellationCache %8d / %8d\n", tessellationCache.getSize(), tessellationCache.getMaxSize()); - log.appendFormat(" TextDropShadowCache %8d / %8d\n", dropShadowCache.getSize(), - dropShadowCache.getMaxSize()); log.appendFormat(" PatchCache %8d / %8d\n", patchCache.getSize(), patchCache.getMaxSize()); - fontRenderer.dumpMemoryUsage(log); - log.appendFormat("Other:\n"); log.appendFormat(" FboCache %8d / %8d\n", fboCache.getSize(), fboCache.getMaxSize()); @@ -202,16 +194,10 @@ void Caches::dumpMemoryUsage(String8& log) { total += gradientCache.getSize(); total += pathCache.getSize(); total += tessellationCache.getSize(); - total += dropShadowCache.getSize(); total += patchCache.getSize(); - total += fontRenderer.getSize(); log.appendFormat("Total memory usage:\n"); log.appendFormat(" %d bytes, %.2f MB\n", total, total / 1024.0f / 1024.0f); - -#ifdef BUGREPORT_FONT_CACHE_USAGE - fontRenderer.getFontRenderer().historyTracker().dump(log); -#endif } /////////////////////////////////////////////////////////////////////////////// @@ -230,13 +216,10 @@ void Caches::flush(FlushMode mode) { case FlushMode::Full: textureCache.clear(); patchCache.clear(); - dropShadowCache.clear(); gradientCache.clear(); - fontRenderer.clear(); fboCache.clear(); // fall through case FlushMode::Moderate: - fontRenderer.flush(); textureCache.flush(); pathCache.clear(); tessellationCache.clear(); diff --git a/libs/hwui/Caches.h b/libs/hwui/Caches.h index 97328324df04..ed2d0b350d1b 100644 --- a/libs/hwui/Caches.h +++ b/libs/hwui/Caches.h @@ -19,7 +19,6 @@ #include "DeviceInfo.h" #include "Extensions.h" #include "FboCache.h" -#include "GammaFontRenderer.h" #include "GradientCache.h" #include "PatchCache.h" #include "PathCache.h" @@ -27,7 +26,6 @@ #include "RenderBufferCache.h" #include "ResourceCache.h" #include "TessellationCache.h" -#include "TextDropShadowCache.h" #include "TextureCache.h" #include "renderstate/PixelBufferState.h" #include "renderstate/TextureState.h" @@ -149,11 +147,8 @@ public: PathCache pathCache; ProgramCache programCache; TessellationCache tessellationCache; - TextDropShadowCache dropShadowCache; FboCache fboCache; - GammaFontRenderer fontRenderer; - TaskManager tasks; bool gpuPixelBuffersEnabled; diff --git a/libs/hwui/DisplayList.h b/libs/hwui/DisplayList.h index 0cfc3b701aff..7a9c65dd365b 100644 --- a/libs/hwui/DisplayList.h +++ b/libs/hwui/DisplayList.h @@ -50,6 +50,7 @@ class SkRegion; namespace android { namespace uirenderer { +struct ClipBase; class Rect; class Layer; diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp deleted file mode 100644 index bbcedb15335d..000000000000 --- a/libs/hwui/FontRenderer.cpp +++ /dev/null @@ -1,802 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "FontRenderer.h" - -#include "BakedOpDispatcher.h" -#include "BakedOpRenderer.h" -#include "BakedOpState.h" -#include "Caches.h" -#include "Debug.h" -#include "Extensions.h" -#include "Glop.h" -#include "GlopBuilder.h" -#include "PixelBuffer.h" -#include "Rect.h" -#include "font/Font.h" -#include "renderstate/RenderState.h" -#include "utils/Blur.h" -#include "utils/Timing.h" - -#include <RenderScript.h> -#include <SkGlyph.h> -#include <SkUtils.h> -#include <utils/Log.h> -#include <algorithm> - -namespace android { -namespace uirenderer { - -// blur inputs smaller than this constant will bypass renderscript -#define RS_MIN_INPUT_CUTOFF 10000 - -/////////////////////////////////////////////////////////////////////////////// -// TextSetupFunctor -/////////////////////////////////////////////////////////////////////////////// - -void TextDrawFunctor::draw(CacheTexture& texture, bool linearFiltering) { - int textureFillFlags = TextureFillFlags::None; - if (texture.getFormat() == GL_ALPHA) { - textureFillFlags |= TextureFillFlags::IsAlphaMaskTexture; - } - if (linearFiltering) { - textureFillFlags |= TextureFillFlags::ForceFilter; - } - int transformFlags = - pureTranslate ? TransformFlags::MeshIgnoresCanvasTransform : TransformFlags::None; -#ifdef ANDROID_ENABLE_LINEAR_BLENDING - bool gammaCorrection = true; -#else - bool gammaCorrection = false; -#endif - Glop glop; - GlopBuilder(renderer->renderState(), renderer->caches(), &glop) - .setRoundRectClipState(bakedState->roundRectClipState) - .setMeshTexturedIndexedQuads(texture.mesh(), texture.meshElementCount()) - .setFillTexturePaint(texture.getTexture(), textureFillFlags, paint, bakedState->alpha) - .setGammaCorrection(gammaCorrection) - .setTransform(bakedState->computedState.transform, transformFlags) - .setModelViewIdentityEmptyBounds() - .build(); - // Note: don't pass dirty bounds here, so user must manage passing dirty bounds to renderer - renderer->renderGlop(nullptr, clip, glop); -} - -/////////////////////////////////////////////////////////////////////////////// -// FontRenderer -/////////////////////////////////////////////////////////////////////////////// - -static bool sLogFontRendererCreate = true; - -FontRenderer::FontRenderer(const uint8_t* gammaTable) - : mGammaTable(gammaTable) - , 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"); - } - - auto deviceInfo = DeviceInfo::get(); - auto displayInfo = deviceInfo->displayInfo(); - int maxTextureSize = deviceInfo->maxTextureSize(); - - // Adjust cache size based on Pixel's desnsity. - constexpr float PIXEL_DENSITY = 2.6; - const float densityRatio = displayInfo.density / PIXEL_DENSITY; - - // TODO: Most devices are hardcoded with this configuration, does it need to be dynamic? - mSmallCacheWidth = - OffscreenBuffer::computeIdealDimension(std::min(1024, maxTextureSize) * densityRatio); - mSmallCacheHeight = - OffscreenBuffer::computeIdealDimension(std::min(1024, maxTextureSize) * densityRatio); - mLargeCacheWidth = - OffscreenBuffer::computeIdealDimension(std::min(2048, maxTextureSize) * densityRatio); - mLargeCacheHeight = - OffscreenBuffer::computeIdealDimension(std::min(1024, maxTextureSize) * densityRatio); - - if (sLogFontRendererCreate) { - INIT_LOGD(" Text cache sizes, in pixels: %i x %i, %i x %i, %i x %i, %i x %i", - mSmallCacheWidth, mSmallCacheHeight, mLargeCacheWidth, mLargeCacheHeight >> 1, - mLargeCacheWidth, mLargeCacheHeight >> 1, mLargeCacheWidth, mLargeCacheHeight); - } - - sLogFontRendererCreate = false; -} - -void clearCacheTextures(std::vector<CacheTexture*>& cacheTextures) { - for (uint32_t i = 0; i < cacheTextures.size(); i++) { - delete cacheTextures[i]; - } - cacheTextures.clear(); -} - -FontRenderer::~FontRenderer() { - clearCacheTextures(mACacheTextures); - clearCacheTextures(mRGBACacheTextures); - - LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); - while (it.next()) { - delete it.value(); - } - mActiveFonts.clear(); -} - -void FontRenderer::flushAllAndInvalidate() { - issueDrawCommand(); - - LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); - while (it.next()) { - it.value()->invalidateTextureCache(); - } - - for (uint32_t i = 0; i < mACacheTextures.size(); i++) { - mACacheTextures[i]->init(); - -#ifdef BUGREPORT_FONT_CACHE_USAGE - mHistoryTracker.glyphsCleared(mACacheTextures[i]); -#endif - } - - for (uint32_t i = 0; i < mRGBACacheTextures.size(); i++) { - mRGBACacheTextures[i]->init(); -#ifdef BUGREPORT_FONT_CACHE_USAGE - mHistoryTracker.glyphsCleared(mRGBACacheTextures[i]); -#endif - } - - mDrawn = false; -} - -void FontRenderer::flushLargeCaches(std::vector<CacheTexture*>& cacheTextures) { - // Start from 1; don't deallocate smallest/default texture - for (uint32_t i = 1; i < cacheTextures.size(); i++) { - CacheTexture* cacheTexture = cacheTextures[i]; - if (cacheTexture->getPixelBuffer()) { - cacheTexture->init(); -#ifdef BUGREPORT_FONT_CACHE_USAGE - mHistoryTracker.glyphsCleared(cacheTexture); -#endif - LruCache<Font::FontDescription, Font*>::Iterator it(mActiveFonts); - while (it.next()) { - it.value()->invalidateTextureCache(cacheTexture); - } - cacheTexture->releasePixelBuffer(); - } - } -} - -void FontRenderer::flushLargeCaches() { - flushLargeCaches(mACacheTextures); - flushLargeCaches(mRGBACacheTextures); -} - -CacheTexture* FontRenderer::cacheBitmapInTexture(std::vector<CacheTexture*>& cacheTextures, - const SkGlyph& glyph, uint32_t* startX, - uint32_t* startY) { - for (uint32_t i = 0; i < cacheTextures.size(); i++) { - if (cacheTextures[i]->fitBitmap(glyph, startX, startY)) { - return cacheTextures[i]; - } - } - // Could not fit glyph into current cache textures - return nullptr; -} - -void FontRenderer::cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, - uint32_t* retOriginX, uint32_t* retOriginY, bool precaching) { - checkInit(); - - // If the glyph bitmap is empty let's assum the glyph is valid - // so we can avoid doing extra work later on - if (glyph.fWidth == 0 || glyph.fHeight == 0) { - cachedGlyph->mIsValid = true; - cachedGlyph->mCacheTexture = nullptr; - return; - } - - cachedGlyph->mIsValid = false; - - // choose an appropriate cache texture list for this glyph format - SkMask::Format format = static_cast<SkMask::Format>(glyph.fMaskFormat); - std::vector<CacheTexture*>* cacheTextures = nullptr; - switch (format) { - case SkMask::kA8_Format: - case SkMask::kBW_Format: - cacheTextures = &mACacheTextures; - break; - case SkMask::kARGB32_Format: - cacheTextures = &mRGBACacheTextures; - break; - default: -#if DEBUG_FONT_RENDERER - ALOGD("getCacheTexturesForFormat: unknown SkMask format %x", format); -#endif - return; - } - - // If the glyph is too tall, don't cache it - if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > - (*cacheTextures)[cacheTextures->size() - 1]->getHeight()) { - ALOGE("Font size too large to fit in cache. width, height = %i, %i", (int)glyph.fWidth, - (int)glyph.fHeight); - return; - } - - // Now copy the bitmap into the cache texture - uint32_t startX = 0; - uint32_t startY = 0; - - CacheTexture* cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY); - - if (!cacheTexture) { - if (!precaching) { - // If the new glyph didn't fit and we are not just trying to precache it, - // clear out the cache and try again - flushAllAndInvalidate(); - cacheTexture = cacheBitmapInTexture(*cacheTextures, glyph, &startX, &startY); - } - - if (!cacheTexture) { - // either the glyph didn't fit or we're precaching and will cache it when we draw - return; - } - } - - cachedGlyph->mCacheTexture = cacheTexture; - - *retOriginX = startX; - *retOriginY = startY; - - uint32_t endX = startX + glyph.fWidth; - uint32_t endY = startY + glyph.fHeight; - - uint32_t cacheWidth = cacheTexture->getWidth(); - - if (!cacheTexture->getPixelBuffer()) { - Caches::getInstance().textureState().activateTexture(0); - // Large-glyph texture memory is allocated only as needed - cacheTexture->allocatePixelBuffer(); - } - if (!cacheTexture->mesh()) { - cacheTexture->allocateMesh(); - } - - uint8_t* cacheBuffer = cacheTexture->getPixelBuffer()->map(); - uint8_t* bitmapBuffer = (uint8_t*)glyph.fImage; - int srcStride = glyph.rowBytes(); - - // Copy the glyph image, taking the mask format into account - switch (format) { - case SkMask::kA8_Format: { - uint32_t row = - (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX - TEXTURE_BORDER_SIZE; - // write leading border line - memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); - // write glyph data - if (mGammaTable) { - for (uint32_t cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) { - row = cacheY * cacheWidth; - cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; - for (uint32_t cacheX = startX, bX = 0; cacheX < endX; cacheX++, bX++) { - uint8_t tempCol = bitmapBuffer[bY + bX]; - cacheBuffer[row + cacheX] = mGammaTable[tempCol]; - } - cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; - } - } else { - for (uint32_t cacheY = startY, bY = 0; cacheY < endY; cacheY++, bY += srcStride) { - row = cacheY * cacheWidth; - memcpy(&cacheBuffer[row + startX], &bitmapBuffer[bY], glyph.fWidth); - cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; - cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; - } - } - // write trailing border line - row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE; - memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); - break; - } - case SkMask::kARGB32_Format: { - // prep data lengths - const size_t formatSize = PixelBuffer::formatSize(GL_RGBA); - const size_t borderSize = formatSize * TEXTURE_BORDER_SIZE; - size_t rowSize = formatSize * glyph.fWidth; - // prep advances - size_t dstStride = formatSize * cacheWidth; - // prep indices - // - we actually start one row early, and then increment before first copy - uint8_t* src = &bitmapBuffer[0 - srcStride]; - uint8_t* dst = &cacheBuffer[cacheTexture->getOffset(startX, startY - 1)]; - uint8_t* dstEnd = &cacheBuffer[cacheTexture->getOffset(startX, endY - 1)]; - uint8_t* dstL = dst - borderSize; - uint8_t* dstR = dst + rowSize; - // write leading border line - memset(dstL, 0, rowSize + 2 * borderSize); - // write glyph data - while (dst < dstEnd) { - memset(dstL += dstStride, 0, borderSize); // leading border column - memcpy(dst += dstStride, src += srcStride, rowSize); // glyph data - memset(dstR += dstStride, 0, borderSize); // trailing border column - } - // write trailing border line - memset(dstL += dstStride, 0, rowSize + 2 * borderSize); - break; - } - case SkMask::kBW_Format: { - uint32_t cacheX = 0, cacheY = 0; - uint32_t row = - (startY - TEXTURE_BORDER_SIZE) * cacheWidth + startX - TEXTURE_BORDER_SIZE; - static const uint8_t COLORS[2] = {0, 255}; - // write leading border line - memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); - // write glyph data - for (cacheY = startY; cacheY < endY; cacheY++) { - cacheX = startX; - int rowBytes = srcStride; - uint8_t* buffer = bitmapBuffer; - - row = cacheY * cacheWidth; - cacheBuffer[row + startX - TEXTURE_BORDER_SIZE] = 0; - while (--rowBytes >= 0) { - uint8_t b = *buffer++; - for (int8_t mask = 7; mask >= 0 && cacheX < endX; mask--) { - cacheBuffer[cacheY * cacheWidth + cacheX++] = COLORS[(b >> mask) & 0x1]; - } - } - cacheBuffer[row + endX + TEXTURE_BORDER_SIZE - 1] = 0; - - bitmapBuffer += srcStride; - } - // write trailing border line - row = (endY + TEXTURE_BORDER_SIZE - 1) * cacheWidth + startX - TEXTURE_BORDER_SIZE; - memset(&cacheBuffer[row], 0, glyph.fWidth + 2 * TEXTURE_BORDER_SIZE); - break; - } - default: - ALOGW("Unknown glyph format: 0x%x", format); - break; - } - - cachedGlyph->mIsValid = true; - -#ifdef BUGREPORT_FONT_CACHE_USAGE - mHistoryTracker.glyphUploaded(cacheTexture, startX, startY, glyph.fWidth, glyph.fHeight); -#endif -} - -CacheTexture* FontRenderer::createCacheTexture(int width, int height, GLenum format, - bool allocate) { - CacheTexture* cacheTexture = new CacheTexture(width, height, format, kMaxNumberOfQuads); - - if (allocate) { - Caches::getInstance().textureState().activateTexture(0); - cacheTexture->allocatePixelBuffer(); - cacheTexture->allocateMesh(); - } - - return cacheTexture; -} - -void FontRenderer::initTextTexture() { - clearCacheTextures(mACacheTextures); - clearCacheTextures(mRGBACacheTextures); - - mUploadTexture = false; - mACacheTextures.push_back( - createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, GL_ALPHA, true)); - mACacheTextures.push_back( - createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, GL_ALPHA, false)); - mACacheTextures.push_back( - createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, GL_ALPHA, false)); - mACacheTextures.push_back( - createCacheTexture(mLargeCacheWidth, mLargeCacheHeight, GL_ALPHA, false)); - mRGBACacheTextures.push_back( - createCacheTexture(mSmallCacheWidth, mSmallCacheHeight, GL_RGBA, false)); - mRGBACacheTextures.push_back( - createCacheTexture(mLargeCacheWidth, mLargeCacheHeight >> 1, GL_RGBA, false)); - mCurrentCacheTexture = mACacheTextures[0]; -} - -// We don't want to allocate anything unless we actually draw text -void FontRenderer::checkInit() { - if (mInitialized) { - return; - } - - initTextTexture(); - - mInitialized = true; -} - -void checkTextureUpdateForCache(Caches& caches, std::vector<CacheTexture*>& cacheTextures, - bool& resetPixelStore, GLuint& lastTextureId) { - for (uint32_t i = 0; i < cacheTextures.size(); i++) { - CacheTexture* cacheTexture = cacheTextures[i]; - if (cacheTexture->isDirty() && cacheTexture->getPixelBuffer()) { - if (cacheTexture->getTextureId() != lastTextureId) { - lastTextureId = cacheTexture->getTextureId(); - caches.textureState().activateTexture(0); - caches.textureState().bindTexture(lastTextureId); - } - - if (cacheTexture->upload()) { - resetPixelStore = true; - } - } - } -} - -void FontRenderer::checkTextureUpdate() { - if (!mUploadTexture) { - return; - } - - Caches& caches = Caches::getInstance(); - GLuint lastTextureId = 0; - - bool resetPixelStore = false; - - // Iterate over all the cache textures and see which ones need to be updated - checkTextureUpdateForCache(caches, mACacheTextures, resetPixelStore, lastTextureId); - checkTextureUpdateForCache(caches, mRGBACacheTextures, resetPixelStore, lastTextureId); - - // Unbind any PBO we might have used to update textures - caches.pixelBufferState().unbind(); - - // 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; -} - -void FontRenderer::issueDrawCommand(std::vector<CacheTexture*>& cacheTextures) { - if (!mFunctor) return; - - bool first = true; - for (uint32_t i = 0; i < cacheTextures.size(); i++) { - CacheTexture* texture = cacheTextures[i]; - if (texture->canDraw()) { - if (first) { - checkTextureUpdate(); - first = false; - mDrawn = true; - } - - mFunctor->draw(*texture, mLinearFiltering); - - texture->resetMesh(); - } - } -} - -void FontRenderer::issueDrawCommand() { - issueDrawCommand(mACacheTextures); - issueDrawCommand(mRGBACacheTextures); -} - -void FontRenderer::appendMeshQuadNoClip(float x1, float y1, float u1, float v1, float x2, float y2, - float u2, float v2, float x3, float y3, float u3, float v3, - float x4, float y4, float u4, float v4, - CacheTexture* texture) { - if (texture != mCurrentCacheTexture) { - // Now use the new texture id - mCurrentCacheTexture = texture; - } - - mCurrentCacheTexture->addQuad(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4); -} - -void FontRenderer::appendMeshQuad(float x1, float y1, float u1, float v1, float x2, float y2, - float u2, float v2, float x3, float y3, float u3, float v3, - float x4, float y4, float u4, float v4, CacheTexture* texture) { - if (mClip && (x1 > mClip->right || y1 < mClip->top || x2 < mClip->left || y4 > mClip->bottom)) { - return; - } - - appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture); - - if (mBounds) { - mBounds->left = std::min(mBounds->left, x1); - mBounds->top = std::min(mBounds->top, y3); - mBounds->right = std::max(mBounds->right, x3); - mBounds->bottom = std::max(mBounds->bottom, y1); - } - - if (mCurrentCacheTexture->endOfMesh()) { - issueDrawCommand(); - } -} - -void FontRenderer::appendRotatedMeshQuad(float x1, float y1, float u1, float v1, float x2, float y2, - float u2, float v2, float x3, float y3, float u3, float v3, - float x4, float y4, float u4, float v4, - CacheTexture* texture) { - appendMeshQuadNoClip(x1, y1, u1, v1, x2, y2, u2, v2, x3, y3, u3, v3, x4, y4, u4, v4, texture); - - if (mBounds) { - mBounds->left = std::min(mBounds->left, std::min(x1, std::min(x2, std::min(x3, x4)))); - mBounds->top = std::min(mBounds->top, std::min(y1, std::min(y2, std::min(y3, y4)))); - mBounds->right = std::max(mBounds->right, std::max(x1, std::max(x2, std::max(x3, x4)))); - mBounds->bottom = std::max(mBounds->bottom, std::max(y1, std::max(y2, std::max(y3, y4)))); - } - - if (mCurrentCacheTexture->endOfMesh()) { - issueDrawCommand(); - } -} - -void FontRenderer::setFont(const SkPaint* paint, const SkMatrix& matrix) { - mCurrentFont = Font::create(this, paint, matrix); -} - -FontRenderer::DropShadow FontRenderer::renderDropShadow(const SkPaint* paint, const glyph_t* glyphs, - int numGlyphs, float radius, - const float* positions) { - checkInit(); - - DropShadow image; - image.width = 0; - image.height = 0; - image.image = nullptr; - image.penX = 0; - image.penY = 0; - - if (!mCurrentFont) { - return image; - } - - mDrawn = false; - mClip = nullptr; - mBounds = nullptr; - - Rect bounds; - mCurrentFont->measure(paint, glyphs, numGlyphs, &bounds, positions); - - uint32_t intRadius = Blur::convertRadiusToInt(radius); - uint32_t paddedWidth = (uint32_t)(bounds.right - bounds.left) + 2 * intRadius; - uint32_t paddedHeight = (uint32_t)(bounds.top - bounds.bottom) + 2 * intRadius; - - 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; - } - int size = paddedWidth * paddedHeight; - uint8_t* dataBuffer = (uint8_t*)memalign(RS_CPU_ALLOCATION_ALIGNMENT, size); - - memset(dataBuffer, 0, size); - - int penX = intRadius - bounds.left; - int penY = intRadius - bounds.bottom; - - if ((bounds.right > bounds.left) && (bounds.top > bounds.bottom)) { - // text has non-whitespace, so draw and blur to create the shadow - // 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, glyphs, numGlyphs, penX, penY, Font::BITMAP, dataBuffer, - paddedWidth, paddedHeight, nullptr, positions); - - // Unbind any PBO we might have used - Caches::getInstance().pixelBufferState().unbind(); - - blurImage(&dataBuffer, paddedWidth, paddedHeight, radius); - } - - image.width = paddedWidth; - image.height = paddedHeight; - image.image = dataBuffer; - image.penX = penX; - image.penY = penY; - - return image; -} - -void FontRenderer::initRender(const Rect* clip, Rect* bounds, TextDrawFunctor* functor) { - checkInit(); - - mDrawn = false; - mBounds = bounds; - mFunctor = functor; - mClip = clip; -} - -void FontRenderer::finishRender() { - mBounds = nullptr; - mClip = nullptr; - - issueDrawCommand(); -} - -void FontRenderer::precache(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, - const SkMatrix& matrix) { - Font* font = Font::create(this, paint, matrix); - font->precache(paint, glyphs, numGlyphs); -} - -void FontRenderer::endPrecaching() { - checkTextureUpdate(); -} - -bool FontRenderer::renderPosText(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs, - int numGlyphs, int x, int y, const float* positions, Rect* bounds, - TextDrawFunctor* functor, bool forceFinish) { - if (!mCurrentFont) { - ALOGE("No font set"); - return false; - } - - initRender(clip, bounds, functor); - mCurrentFont->render(paint, glyphs, numGlyphs, x, y, positions); - - if (forceFinish) { - finishRender(); - } - - return mDrawn; -} - -bool FontRenderer::renderTextOnPath(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs, - int numGlyphs, const SkPath* path, float hOffset, float vOffset, - Rect* bounds, TextDrawFunctor* functor) { - if (!mCurrentFont) { - ALOGE("No font set"); - return false; - } - - initRender(clip, bounds, functor); - mCurrentFont->render(paint, glyphs, numGlyphs, path, hOffset, vOffset); - finishRender(); - - return mDrawn; -} - -void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, float radius) { - uint32_t intRadius = Blur::convertRadiusToInt(radius); - if (width * height * intRadius >= RS_MIN_INPUT_CUTOFF && radius <= 25.0f) { - uint8_t* outImage = (uint8_t*)memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height); - - 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 - if (!mRs->init("", RSC::RS_INIT_LOW_LATENCY | RSC::RS_INIT_SYNCHRONOUS)) { - mRs.clear(); - ALOGE("blur RS failed to init"); - } else { - mRsElement = RSC::Element::A_8(mRs); - mRsScript = RSC::ScriptIntrinsicBlur::create(mRs, mRsElement); - } - } - 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, - RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, *image); - RSC::sp<RSC::Allocation> aout = RSC::Allocation::createTyped( - mRs, t, RS_ALLOCATION_MIPMAP_NONE, - RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, outImage); - - mRsScript->setRadius(radius); - mRsScript->setInput(ain); - mRsScript->forEach(aout); - - // replace the original image's pointer, avoiding a copy back to the original buffer - free(*image); - *image = outImage; - - return; - } - } - - std::unique_ptr<float[]> gaussian(new float[2 * intRadius + 1]); - Blur::generateGaussianWeights(gaussian.get(), radius); - - 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 std::vector<CacheTexture*>& cacheTextures) { - uint32_t size = 0; - for (uint32_t i = 0; i < cacheTextures.size(); i++) { - CacheTexture* cacheTexture = cacheTextures[i]; - if (cacheTexture && cacheTexture->getPixelBuffer()) { - size += cacheTexture->getPixelBuffer()->getSize(); - } - } - return size; -} - -static uint32_t calculateFreeCacheSize(const std::vector<CacheTexture*>& cacheTextures) { - uint32_t size = 0; - for (uint32_t i = 0; i < cacheTextures.size(); i++) { - CacheTexture* cacheTexture = cacheTextures[i]; - if (cacheTexture && cacheTexture->getPixelBuffer()) { - size += cacheTexture->calculateFreeMemory(); - } - } - return size; -} - -const std::vector<CacheTexture*>& FontRenderer::cacheTexturesForFormat(GLenum format) const { - switch (format) { - case GL_ALPHA: { - return mACacheTextures; - } - case GL_RGBA: { - return mRGBACacheTextures; - } - default: { - LOG_ALWAYS_FATAL("Unsupported format: %d", format); - // Impossible to hit this, but the compiler doesn't know that - return *(new std::vector<CacheTexture*>()); - } - } -} - -static void dumpTextures(String8& log, const char* tag, - const std::vector<CacheTexture*>& cacheTextures) { - for (uint32_t i = 0; i < cacheTextures.size(); i++) { - CacheTexture* cacheTexture = cacheTextures[i]; - if (cacheTexture && cacheTexture->getPixelBuffer()) { - uint32_t free = cacheTexture->calculateFreeMemory(); - uint32_t total = cacheTexture->getPixelBuffer()->getSize(); - log.appendFormat(" %-4s texture %d %8d / %8d\n", tag, i, total - free, total); - } - } -} - -void FontRenderer::dumpMemoryUsage(String8& log) const { - const uint32_t sizeA8 = getCacheSize(GL_ALPHA); - const uint32_t usedA8 = sizeA8 - getFreeCacheSize(GL_ALPHA); - const uint32_t sizeRGBA = getCacheSize(GL_RGBA); - const uint32_t usedRGBA = sizeRGBA - getFreeCacheSize(GL_RGBA); - log.appendFormat(" FontRenderer A8 %8d / %8d\n", usedA8, sizeA8); - dumpTextures(log, "A8", cacheTexturesForFormat(GL_ALPHA)); - log.appendFormat(" FontRenderer RGBA %8d / %8d\n", usedRGBA, sizeRGBA); - dumpTextures(log, "RGBA", cacheTexturesForFormat(GL_RGBA)); - log.appendFormat(" FontRenderer total %8d / %8d\n", usedA8 + usedRGBA, sizeA8 + sizeRGBA); -} - -uint32_t FontRenderer::getCacheSize(GLenum format) const { - return calculateCacheSize(cacheTexturesForFormat(format)); -} - -uint32_t FontRenderer::getFreeCacheSize(GLenum format) const { - return calculateFreeCacheSize(cacheTexturesForFormat(format)); -} - -uint32_t FontRenderer::getSize() const { - return getCacheSize(GL_ALPHA) + getCacheSize(GL_RGBA); -} - -}; // namespace uirenderer -}; // namespace android diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h deleted file mode 100644 index 6b9dec4719cb..000000000000 --- a/libs/hwui/FontRenderer.h +++ /dev/null @@ -1,208 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "font/CacheTexture.h" -#include "font/CachedGlyphInfo.h" -#include "font/Font.h" -#include "font/FontUtil.h" -#ifdef BUGREPORT_FONT_CACHE_USAGE -#include "font/FontCacheHistoryTracker.h" -#endif - -#include <utils/LruCache.h> -#include <utils/String8.h> -#include <utils/StrongPointer.h> - -#include <SkPaint.h> - -#include <GLES2/gl2.h> - -#include <vector> - -#include "RenderScript.h" -namespace RSC { -class Element; -class RS; -class ScriptIntrinsicBlur; -class sp; -} - -namespace android { -namespace uirenderer { - -class BakedOpState; -class BakedOpRenderer; -struct ClipBase; - -class TextDrawFunctor { -public: - TextDrawFunctor(BakedOpRenderer* renderer, const BakedOpState* bakedState, const ClipBase* clip, - float x, float y, bool pureTranslate, int alpha, SkBlendMode mode, - const SkPaint* paint) - : renderer(renderer) - , bakedState(bakedState) - , clip(clip) - , x(x) - , y(y) - , pureTranslate(pureTranslate) - , alpha(alpha) - , mode(mode) - , paint(paint) {} - - void draw(CacheTexture& texture, bool linearFiltering); - - BakedOpRenderer* renderer; - const BakedOpState* bakedState; - const ClipBase* clip; - float x; - float y; - bool pureTranslate; - int alpha; - SkBlendMode mode; - const SkPaint* paint; -}; - -class FontRenderer { -public: - explicit FontRenderer(const uint8_t* gammaTable); - ~FontRenderer(); - - void flushLargeCaches(std::vector<CacheTexture*>& cacheTextures); - void flushLargeCaches(); - - void setFont(const SkPaint* paint, const SkMatrix& matrix); - - void precache(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, - const SkMatrix& matrix); - void endPrecaching(); - - bool renderPosText(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs, int numGlyphs, - int x, int y, const float* positions, Rect* outBounds, - TextDrawFunctor* functor, bool forceFinish = true); - - bool renderTextOnPath(const SkPaint* paint, const Rect* clip, const glyph_t* glyphs, - int numGlyphs, const SkPath* path, float hOffset, float vOffset, - Rect* outBounds, TextDrawFunctor* functor); - - struct DropShadow { - uint32_t width; - uint32_t height; - uint8_t* image; - int32_t penX; - int32_t penY; - }; - - // After renderDropShadow returns, the called owns the memory in DropShadow.image - // and is responsible for releasing it when it's done with it - DropShadow renderDropShadow(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, - float radius, const float* positions); - - void setTextureFiltering(bool linearFiltering) { mLinearFiltering = linearFiltering; } - - uint32_t getSize() const; - void dumpMemoryUsage(String8& log) const; - -#ifdef BUGREPORT_FONT_CACHE_USAGE - FontCacheHistoryTracker& historyTracker() { return mHistoryTracker; } -#endif - -private: - friend class Font; - - const uint8_t* mGammaTable; - - void allocateTextureMemory(CacheTexture* cacheTexture); - void deallocateTextureMemory(CacheTexture* cacheTexture); - void initTextTexture(); - CacheTexture* createCacheTexture(int width, int height, GLenum format, bool allocate); - void cacheBitmap(const SkGlyph& glyph, CachedGlyphInfo* cachedGlyph, uint32_t* retOriginX, - uint32_t* retOriginY, bool precaching); - CacheTexture* cacheBitmapInTexture(std::vector<CacheTexture*>& cacheTextures, - const SkGlyph& glyph, uint32_t* startX, uint32_t* startY); - - void flushAllAndInvalidate(); - - void checkInit(); - void initRender(const Rect* clip, Rect* bounds, TextDrawFunctor* functor); - void finishRender(); - - void issueDrawCommand(std::vector<CacheTexture*>& cacheTextures); - void issueDrawCommand(); - void appendMeshQuadNoClip(float x1, float y1, float u1, float v1, float x2, float y2, float u2, - float v2, float x3, float y3, float u3, float v3, float x4, float y4, - float u4, float v4, CacheTexture* texture); - void appendMeshQuad(float x1, float y1, float u1, float v1, float x2, float y2, float u2, - float v2, float x3, float y3, float u3, float v3, float x4, float y4, - float u4, float v4, CacheTexture* texture); - void appendRotatedMeshQuad(float x1, float y1, float u1, float v1, float x2, float y2, float u2, - float v2, float x3, float y3, float u3, float v3, float x4, float y4, - float u4, float v4, CacheTexture* texture); - - void checkTextureUpdate(); - - void setTextureDirty() { mUploadTexture = true; } - - const std::vector<CacheTexture*>& cacheTexturesForFormat(GLenum format) const; - uint32_t getCacheSize(GLenum format) const; - uint32_t getFreeCacheSize(GLenum format) const; - - uint32_t mSmallCacheWidth; - uint32_t mSmallCacheHeight; - uint32_t mLargeCacheWidth; - uint32_t mLargeCacheHeight; - - std::vector<CacheTexture*> mACacheTextures; - std::vector<CacheTexture*> mRGBACacheTextures; - - Font* mCurrentFont; - LruCache<Font::FontDescription, Font*> mActiveFonts; - - CacheTexture* mCurrentCacheTexture; - - bool mUploadTexture; - - TextDrawFunctor* mFunctor; - const Rect* mClip; - Rect* mBounds; - bool mDrawn; - - bool mInitialized; - - bool mLinearFiltering; - -#ifdef BUGREPORT_FONT_CACHE_USAGE - FontCacheHistoryTracker mHistoryTracker; -#endif - - // RS constructs - RSC::sp<RSC::RS> mRs; - RSC::sp<const RSC::Element> mRsElement; - RSC::sp<RSC::ScriptIntrinsicBlur> mRsScript; - - static void computeGaussianWeights(float* weights, int32_t radius); - static void horizontalBlur(float* weights, int32_t radius, const uint8_t* source, uint8_t* dest, - int32_t width, int32_t height); - static void verticalBlur(float* weights, int32_t radius, const uint8_t* source, uint8_t* dest, - int32_t width, int32_t height); - - // the input image handle may have its pointer replaced (to avoid copies) - void blurImage(uint8_t** image, int32_t width, int32_t height, float radius); -}; - -}; // namespace uirenderer -}; // namespace android diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp index ced37ede0746..049cd450c822 100644 --- a/libs/hwui/FrameBuilder.cpp +++ b/libs/hwui/FrameBuilder.cpp @@ -722,48 +722,12 @@ void FrameBuilder::deferSimpleRectsOp(const SimpleRectsOp& op) { currentLayer().deferUnmergeableOp(mAllocator, bakedState, OpBatchType::Vertices); } -static batchid_t textBatchId(const SkPaint& paint) { - // TODO: better handling of shader (since we won't care about color then) - return paint.getColor() == SK_ColorBLACK ? OpBatchType::Text : OpBatchType::ColorText; -} - void FrameBuilder::deferTextOp(const TextOp& op) { - BakedOpState* bakedState = BakedOpState::tryStrokeableOpConstruct( - mAllocator, *mCanvasState.writableSnapshot(), op, - BakedOpState::StrokeBehavior::StyleDefined, false); - if (!bakedState) return; // quick rejected - - batchid_t batchId = textBatchId(*(op.paint)); - if (bakedState->computedState.transform.isPureTranslate() && - PaintUtils::getBlendModeDirect(op.paint) == SkBlendMode::kSrcOver && - hasMergeableClip(*bakedState)) { - mergeid_t mergeId = reinterpret_cast<mergeid_t>(op.paint->getColor()); - currentLayer().deferMergeableOp(mAllocator, bakedState, batchId, mergeId); - } else { - currentLayer().deferUnmergeableOp(mAllocator, bakedState, batchId); - } - - FontRenderer& fontRenderer = mCaches.fontRenderer.getFontRenderer(); - auto& totalTransform = bakedState->computedState.transform; - if (totalTransform.isPureTranslate() || totalTransform.isPerspective()) { - fontRenderer.precache(op.paint, op.glyphs, op.glyphCount, SkMatrix::I()); - } else { - // Partial transform case, see BakedOpDispatcher::renderTextOp - float sx, sy; - totalTransform.decomposeScale(sx, sy); - fontRenderer.precache( - op.paint, op.glyphs, op.glyphCount, - SkMatrix::MakeScale(roundf(std::max(1.0f, sx)), roundf(std::max(1.0f, sy)))); - } + // DEAD CODE } void FrameBuilder::deferTextOnPathOp(const TextOnPathOp& op) { - BakedOpState* bakedState = tryBakeUnboundedOpState(op); - if (!bakedState) return; // quick rejected - currentLayer().deferUnmergeableOp(mAllocator, bakedState, textBatchId(*(op.paint))); - - mCaches.fontRenderer.getFontRenderer().precache(op.paint, op.glyphs, op.glyphCount, - SkMatrix::I()); + // DEAD CODE } void FrameBuilder::deferTextureLayerOp(const TextureLayerOp& op) { @@ -969,7 +933,7 @@ void FrameBuilder::deferEndUnclippedLayerOp(const EndUnclippedLayerOp& /* ignore } void FrameBuilder::finishDefer() { - mCaches.fontRenderer.endPrecaching(); + // DEAD CODE } } // namespace uirenderer diff --git a/libs/hwui/GammaFontRenderer.cpp b/libs/hwui/GammaFontRenderer.cpp deleted file mode 100644 index 88fb16234388..000000000000 --- a/libs/hwui/GammaFontRenderer.cpp +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "GammaFontRenderer.h" -#include "Debug.h" -#include "Properties.h" - -namespace android { -namespace uirenderer { - -GammaFontRenderer::GammaFontRenderer() { - INIT_LOGD("Creating lookup gamma font renderer"); - -#ifndef ANDROID_ENABLE_LINEAR_BLENDING - // Compute the gamma tables - const float gamma = 1.0f / Properties::textGamma; - for (uint32_t i = 0; i <= 255; i++) { - mGammaTable[i] = uint8_t((float)::floor(pow(i / 255.0f, gamma) * 255.0f + 0.5f)); - } -#endif -} - -void GammaFontRenderer::endPrecaching() { - if (mRenderer) { - mRenderer->endPrecaching(); - } -} - -}; // namespace uirenderer -}; // namespace android diff --git a/libs/hwui/GammaFontRenderer.h b/libs/hwui/GammaFontRenderer.h deleted file mode 100644 index e9002442c64f..000000000000 --- a/libs/hwui/GammaFontRenderer.h +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HWUI_GAMMA_FONT_RENDERER_H -#define ANDROID_HWUI_GAMMA_FONT_RENDERER_H - -#include "FontRenderer.h" - -namespace android { -namespace uirenderer { - -class GammaFontRenderer { -public: - GammaFontRenderer(); - - void clear() { mRenderer.reset(nullptr); } - - void flush() { - if (mRenderer) { - mRenderer->flushLargeCaches(); - } - } - - FontRenderer& getFontRenderer() { - if (!mRenderer) { - const uint8_t* table = nullptr; -#ifndef ANDROID_ENABLE_LINEAR_BLENDING - table = &mGammaTable[0]; -#endif - mRenderer.reset(new FontRenderer(table)); - } - return *mRenderer; - } - - void dumpMemoryUsage(String8& log) const { - if (mRenderer) { - mRenderer->dumpMemoryUsage(log); - } else { - log.appendFormat("FontRenderer doesn't exist.\n"); - } - } - - uint32_t getSize() const { return mRenderer ? mRenderer->getSize() : 0; } - - void endPrecaching(); - -private: - std::unique_ptr<FontRenderer> mRenderer; -#ifndef ANDROID_ENABLE_LINEAR_BLENDING - uint8_t mGammaTable[256]; -#endif -}; - -}; // namespace uirenderer -}; // namespace android - -#endif // ANDROID_HWUI_GAMMA_FONT_RENDERER_H diff --git a/libs/hwui/GlopBuilder.cpp b/libs/hwui/GlopBuilder.cpp index 2f107a004731..941373d8ef5a 100644 --- a/libs/hwui/GlopBuilder.cpp +++ b/libs/hwui/GlopBuilder.cpp @@ -381,24 +381,7 @@ GlopBuilder& GlopBuilder::setFillPathTexturePaint(PathTexture& texture, const Sk GlopBuilder& GlopBuilder::setFillShadowTexturePaint(ShadowTexture& texture, int shadowColor, const SkPaint& paint, float alphaScale) { - TRIGGER_STAGE(kFillStage); - REQUIRE_STAGES(kMeshStage | kRoundRectClipStage); - - // specify invalid filter/clamp, since these are always static for ShadowTextures - mOutGlop->fill.texture = {&texture, GL_INVALID_ENUM, GL_INVALID_ENUM, nullptr}; - - const int ALPHA_BITMASK = SK_ColorBLACK; - const int COLOR_BITMASK = ~ALPHA_BITMASK; - if ((shadowColor & ALPHA_BITMASK) == ALPHA_BITMASK) { - // shadow color is fully opaque: override its alpha with that of paint - shadowColor &= paint.getColor() | COLOR_BITMASK; - } - - setFill(shadowColor, alphaScale, paint.getBlendMode(), Blend::ModeOrderSwap::NoSwap, - paint.getShader(), paint.getColorFilter()); - - mDescription.hasAlpha8Texture = true; - mDescription.modulate = mOutGlop->fill.color.isNotBlack(); + // DEAD CODE return *this; } diff --git a/libs/hwui/RecordedOp.h b/libs/hwui/RecordedOp.h index 2d0185aaa9e2..f5146912ea37 100644 --- a/libs/hwui/RecordedOp.h +++ b/libs/hwui/RecordedOp.h @@ -22,7 +22,6 @@ #include "RenderNode.h" #include "TessellationCache.h" #include "Vector.h" -#include "font/FontUtil.h" #include "utils/LinearAllocator.h" #include "utils/PaintUtils.h" @@ -38,6 +37,7 @@ struct ClipBase; class OffscreenBuffer; class RenderNode; class DeferredLayerUpdater; +typedef uint16_t glyph_t; struct Vertex; diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp deleted file mode 100644 index c892ceb3e14d..000000000000 --- a/libs/hwui/TextDropShadowCache.cpp +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <utils/JenkinsHash.h> - -#include "Caches.h" -#include "Debug.h" -#include "FontRenderer.h" -#include "Properties.h" -#include "TextDropShadowCache.h" - -namespace android { -namespace uirenderer { - -/////////////////////////////////////////////////////////////////////////////// -// Cache support -/////////////////////////////////////////////////////////////////////////////// - -hash_t ShadowText::hash() const { - uint32_t hash = JenkinsHashMix(0, glyphCount); - hash = JenkinsHashMix(hash, android::hash_type(radius)); - hash = JenkinsHashMix(hash, android::hash_type(textSize)); - hash = JenkinsHashMix(hash, android::hash_type(typeface)); - hash = JenkinsHashMix(hash, flags); - hash = JenkinsHashMix(hash, android::hash_type(italicStyle)); - hash = JenkinsHashMix(hash, android::hash_type(scaleX)); - if (glyphs) { - hash = JenkinsHashMixShorts(hash, reinterpret_cast<const uint16_t*>(glyphs), glyphCount); - } - if (positions) { - for (uint32_t i = 0; i < glyphCount * 2; i++) { - hash = JenkinsHashMix(hash, android::hash_type(positions[i])); - } - } - return JenkinsHashWhiten(hash); -} - -int ShadowText::compare(const ShadowText& lhs, const ShadowText& rhs) { - int deltaInt = int(lhs.glyphCount) - int(rhs.glyphCount); - if (deltaInt != 0) return deltaInt; - - deltaInt = lhs.flags - rhs.flags; - if (deltaInt != 0) return deltaInt; - - if (lhs.radius < rhs.radius) return -1; - if (lhs.radius > rhs.radius) return +1; - - if (lhs.typeface < rhs.typeface) return -1; - if (lhs.typeface > rhs.typeface) return +1; - - if (lhs.textSize < rhs.textSize) return -1; - if (lhs.textSize > rhs.textSize) return +1; - - if (lhs.italicStyle < rhs.italicStyle) return -1; - if (lhs.italicStyle > rhs.italicStyle) return +1; - - if (lhs.scaleX < rhs.scaleX) return -1; - if (lhs.scaleX > rhs.scaleX) return +1; - - if (lhs.glyphs != rhs.glyphs) { - if (!lhs.glyphs) return -1; - if (!rhs.glyphs) return +1; - - deltaInt = memcmp(lhs.glyphs, rhs.glyphs, lhs.glyphCount * sizeof(glyph_t)); - if (deltaInt != 0) return deltaInt; - } - - if (lhs.positions != rhs.positions) { - if (!lhs.positions) return -1; - if (!rhs.positions) return +1; - - return memcmp(lhs.positions, rhs.positions, lhs.glyphCount * sizeof(float) * 2); - } - - return 0; -} - -/////////////////////////////////////////////////////////////////////////////// -// Constructors/destructor -/////////////////////////////////////////////////////////////////////////////// - -TextDropShadowCache::TextDropShadowCache() - : TextDropShadowCache(DeviceInfo::multiplyByResolution(2)) {} - -TextDropShadowCache::TextDropShadowCache(uint32_t maxByteSize) - : mCache(LruCache<ShadowText, ShadowTexture*>::kUnlimitedCapacity) - , mSize(0) - , mMaxSize(maxByteSize) { - mCache.setOnEntryRemovedListener(this); - mDebugEnabled = Properties::debugLevel & kDebugMoreCaches; -} - -TextDropShadowCache::~TextDropShadowCache() { - mCache.clear(); -} - -/////////////////////////////////////////////////////////////////////////////// -// Size management -/////////////////////////////////////////////////////////////////////////////// - -uint32_t TextDropShadowCache::getSize() { - return mSize; -} - -uint32_t TextDropShadowCache::getMaxSize() { - return mMaxSize; -} - -/////////////////////////////////////////////////////////////////////////////// -// Callbacks -/////////////////////////////////////////////////////////////////////////////// - -void TextDropShadowCache::operator()(ShadowText&, ShadowTexture*& texture) { - if (texture) { - mSize -= texture->objectSize(); - - if (mDebugEnabled) { - ALOGD("Shadow texture deleted, size = %d", texture->bitmapSize); - } - - texture->deleteTexture(); - delete texture; - } -} - -/////////////////////////////////////////////////////////////////////////////// -// Caching -/////////////////////////////////////////////////////////////////////////////// - -void TextDropShadowCache::clear() { - mCache.clear(); -} - -ShadowTexture* TextDropShadowCache::get(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, - float radius, const float* positions) { - ShadowText entry(paint, radius, numGlyphs, glyphs, positions); - ShadowTexture* texture = mCache.get(entry); - - if (!texture) { - SkPaint paintCopy(*paint); - paintCopy.setTextAlign(SkPaint::kLeft_Align); - FontRenderer::DropShadow shadow = - mRenderer->renderDropShadow(&paintCopy, glyphs, numGlyphs, radius, positions); - - if (!shadow.image) { - return nullptr; - } - - Caches& caches = Caches::getInstance(); - - texture = new ShadowTexture(caches); - texture->left = shadow.penX; - texture->top = shadow.penY; - texture->generation = 0; - texture->blend = true; - - const uint32_t size = shadow.width * shadow.height; - - // Don't even try to cache a bitmap that's bigger than the cache - if (size < mMaxSize) { - while (mSize + size > mMaxSize) { - LOG_ALWAYS_FATAL_IF(!mCache.removeOldest(), - "Failed to remove oldest from cache. mSize = %" PRIu32 - ", mCache.size() = %zu", - mSize, mCache.size()); - } - } - - // Textures are Alpha8 - texture->upload(GL_ALPHA, shadow.width, shadow.height, GL_ALPHA, GL_UNSIGNED_BYTE, - shadow.image); - texture->setFilter(GL_LINEAR); - texture->setWrap(GL_CLAMP_TO_EDGE); - - if (size < mMaxSize) { - if (mDebugEnabled) { - ALOGD("Shadow texture created, size = %d", texture->bitmapSize); - } - - entry.copyTextLocally(); - - mSize += texture->objectSize(); - mCache.put(entry, texture); - } else { - texture->cleanup = true; - } - - // Cleanup shadow - free(shadow.image); - } - - return texture; -} - -}; // namespace uirenderer -}; // namespace android diff --git a/libs/hwui/TextDropShadowCache.h b/libs/hwui/TextDropShadowCache.h deleted file mode 100644 index 86a012970f17..000000000000 --- a/libs/hwui/TextDropShadowCache.h +++ /dev/null @@ -1,164 +0,0 @@ -/* - * Copyright (C) 2010 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H -#define ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H - -#include <GLES2/gl2.h> - -#include <SkPaint.h> - -#include <utils/LruCache.h> -#include <utils/String16.h> - -#include "Texture.h" -#include "font/Font.h" - -namespace android { -namespace uirenderer { - -class Caches; -class FontRenderer; - -struct ShadowText { - ShadowText() - : glyphCount(0) - , radius(0.0f) - , textSize(0.0f) - , typeface(nullptr) - , flags(0) - , italicStyle(0.0f) - , scaleX(0) - , glyphs(nullptr) - , positions(nullptr) {} - - // len is the number of bytes in text - ShadowText(const SkPaint* paint, float radius, uint32_t glyphCount, const glyph_t* srcGlyphs, - const float* positions) - : glyphCount(glyphCount) - , radius(radius) - , textSize(paint->getTextSize()) - , typeface(paint->getTypeface()) - , flags(paint->isFakeBoldText() ? Font::kFakeBold : 0) - , italicStyle(paint->getTextSkewX()) - , scaleX(paint->getTextScaleX()) - , glyphs(srcGlyphs) - , positions(positions) {} - - ~ShadowText() {} - - hash_t hash() const; - - static int compare(const ShadowText& lhs, const ShadowText& rhs); - - bool operator==(const ShadowText& other) const { return compare(*this, other) == 0; } - - bool operator!=(const ShadowText& other) const { return compare(*this, other) != 0; } - - void copyTextLocally() { - str.setTo(reinterpret_cast<const char16_t*>(glyphs), glyphCount); - glyphs = reinterpret_cast<const glyph_t*>(str.string()); - if (positions != nullptr) { - positionsCopy.clear(); - positionsCopy.appendArray(positions, glyphCount * 2); - positions = positionsCopy.array(); - } - } - - uint32_t glyphCount; - float radius; - float textSize; - SkTypeface* typeface; - uint32_t flags; - float italicStyle; - float scaleX; - const glyph_t* glyphs; - const float* positions; - - // Not directly used to compute the cache key - String16 str; - Vector<float> positionsCopy; - -}; // struct ShadowText - -// Caching support - -inline int strictly_order_type(const ShadowText& lhs, const ShadowText& rhs) { - return ShadowText::compare(lhs, rhs) < 0; -} - -inline int compare_type(const ShadowText& lhs, const ShadowText& rhs) { - return ShadowText::compare(lhs, rhs); -} - -inline hash_t hash_type(const ShadowText& entry) { - return entry.hash(); -} - -/** - * Alpha texture used to represent a shadow. - */ -struct ShadowTexture : public Texture { - explicit ShadowTexture(Caches& caches) : Texture(caches) {} - - float left; - float top; -}; // struct ShadowTexture - -class TextDropShadowCache : public OnEntryRemoved<ShadowText, ShadowTexture*> { -public: - TextDropShadowCache(); - explicit TextDropShadowCache(uint32_t maxByteSize); - ~TextDropShadowCache(); - - /** - * Used as a callback when an entry is removed from the cache. - * Do not invoke directly. - */ - void operator()(ShadowText& text, ShadowTexture*& texture) override; - - ShadowTexture* get(const SkPaint* paint, const glyph_t* text, int numGlyphs, float radius, - const float* positions); - - /** - * Clears the cache. This causes all textures to be deleted. - */ - void clear(); - - void setFontRenderer(FontRenderer& fontRenderer) { mRenderer = &fontRenderer; } - - /** - * Returns the maximum size of the cache in bytes. - */ - uint32_t getMaxSize(); - /** - * Returns the current size of the cache in bytes. - */ - uint32_t getSize(); - -private: - LruCache<ShadowText, ShadowTexture*> mCache; - - uint32_t mSize; - const uint32_t mMaxSize; - FontRenderer* mRenderer = nullptr; - bool mDebugEnabled; -}; // class TextDropShadowCache - -}; // namespace uirenderer -}; // namespace android - -#endif // ANDROID_HWUI_TEXT_DROP_SHADOW_CACHE_H diff --git a/libs/hwui/font/CacheTexture.cpp b/libs/hwui/font/CacheTexture.cpp deleted file mode 100644 index 5dd8bb8119e9..000000000000 --- a/libs/hwui/font/CacheTexture.cpp +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <SkGlyph.h> - -#include "../Caches.h" -#include "../Debug.h" -#include "../Extensions.h" -#include "../PixelBuffer.h" -#include "CacheTexture.h" -#include "FontUtil.h" - -namespace android { -namespace uirenderer { - -/////////////////////////////////////////////////////////////////////////////// -// CacheBlock -/////////////////////////////////////////////////////////////////////////////// - -/** - * Insert new block into existing linked list of blocks. Blocks are sorted in increasing-width - * order, except for the final block (the remainder space at the right, since we fill from the - * left). - */ -CacheBlock* CacheBlock::insertBlock(CacheBlock* head, CacheBlock* newBlock) { -#if DEBUG_FONT_RENDERER - ALOGD("insertBlock: this, x, y, w, h = %p, %d, %d, %d, %d", newBlock, newBlock->mX, - newBlock->mY, newBlock->mWidth, newBlock->mHeight); -#endif - - CacheBlock* currBlock = head; - CacheBlock* prevBlock = nullptr; - - while (currBlock && currBlock->mY != TEXTURE_BORDER_SIZE) { - if (newBlock->mWidth < currBlock->mWidth) { - newBlock->mNext = currBlock; - newBlock->mPrev = prevBlock; - currBlock->mPrev = newBlock; - - if (prevBlock) { - prevBlock->mNext = newBlock; - return head; - } else { - return newBlock; - } - } - - prevBlock = currBlock; - currBlock = currBlock->mNext; - } - - // new block larger than all others - insert at end (but before the remainder space, if there) - newBlock->mNext = currBlock; - newBlock->mPrev = prevBlock; - - if (currBlock) { - currBlock->mPrev = newBlock; - } - - if (prevBlock) { - prevBlock->mNext = newBlock; - return head; - } else { - return newBlock; - } -} - -CacheBlock* CacheBlock::removeBlock(CacheBlock* head, CacheBlock* blockToRemove) { -#if DEBUG_FONT_RENDERER - ALOGD("removeBlock: this, x, y, w, h = %p, %d, %d, %d, %d", blockToRemove, blockToRemove->mX, - blockToRemove->mY, blockToRemove->mWidth, blockToRemove->mHeight); -#endif - - CacheBlock* newHead = head; - CacheBlock* nextBlock = blockToRemove->mNext; - CacheBlock* prevBlock = blockToRemove->mPrev; - - if (prevBlock) { - // If this doesn't hold, we have a use-after-free below. - LOG_ALWAYS_FATAL_IF(head == blockToRemove, - "removeBlock: head should not have a previous block"); - prevBlock->mNext = nextBlock; - } else { - newHead = nextBlock; - } - - if (nextBlock) { - nextBlock->mPrev = prevBlock; - } - - delete blockToRemove; - - return newHead; -} - -/////////////////////////////////////////////////////////////////////////////// -// CacheTexture -/////////////////////////////////////////////////////////////////////////////// - -CacheTexture::CacheTexture(uint16_t width, uint16_t height, GLenum format, uint32_t maxQuadCount) - : mTexture(Caches::getInstance()) - , mWidth(width) - , mHeight(height) - , mFormat(format) - , mMaxQuadCount(maxQuadCount) - , mCaches(Caches::getInstance()) { - mTexture.blend = true; - - mCacheBlocks = - new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, - getWidth() - TEXTURE_BORDER_SIZE, getHeight() - TEXTURE_BORDER_SIZE); - - // OpenGL ES 3.0+ lets us specify the row length for unpack operations such - // as glTexSubImage2D(). This allows us to upload a sub-rectangle of a texture. - // With OpenGL ES 2.0 we have to upload entire stripes instead. - mHasUnpackRowLength = mCaches.extensions().hasUnpackRowLength(); -} - -CacheTexture::~CacheTexture() { - releaseMesh(); - releasePixelBuffer(); - reset(); -} - -void CacheTexture::reset() { - // Delete existing cache blocks - while (mCacheBlocks != nullptr) { - CacheBlock* tmpBlock = mCacheBlocks; - mCacheBlocks = mCacheBlocks->mNext; - delete tmpBlock; - } - mNumGlyphs = 0; - mCurrentQuad = 0; -} - -void CacheTexture::init() { - // reset, then create a new remainder space to start again - reset(); - mCacheBlocks = - new CacheBlock(TEXTURE_BORDER_SIZE, TEXTURE_BORDER_SIZE, - getWidth() - TEXTURE_BORDER_SIZE, getHeight() - TEXTURE_BORDER_SIZE); -} - -void CacheTexture::releaseMesh() { - delete[] mMesh; -} - -void CacheTexture::releasePixelBuffer() { - if (mPixelBuffer) { - delete mPixelBuffer; - mPixelBuffer = nullptr; - } - mTexture.deleteTexture(); - mDirty = false; - mCurrentQuad = 0; -} - -void CacheTexture::setLinearFiltering(bool linearFiltering) { - mTexture.setFilter(linearFiltering ? GL_LINEAR : GL_NEAREST); -} - -void CacheTexture::allocateMesh() { - if (!mMesh) { - mMesh = new TextureVertex[mMaxQuadCount * 4]; - } -} - -void CacheTexture::allocatePixelBuffer() { - if (!mPixelBuffer) { - mPixelBuffer = PixelBuffer::create(mFormat, getWidth(), getHeight()); - } - - GLint internalFormat = mFormat; - if (mFormat == GL_RGBA) { - internalFormat = mCaches.rgbaInternalFormat(); - } - - mTexture.resize(mWidth, mHeight, internalFormat, mFormat); - mTexture.setFilter(getLinearFiltering() ? GL_LINEAR : GL_NEAREST); - mTexture.setWrap(GL_CLAMP_TO_EDGE); -} - -bool CacheTexture::upload() { - const Rect& dirtyRect = mDirtyRect; - - // align the x direction to 32 and y direction to 4 for better performance - uint32_t x = (((uint32_t)dirtyRect.left) & (~0x1F)); - uint32_t y = (((uint32_t)dirtyRect.top) & (~0x3)); - uint32_t r = ((((uint32_t)dirtyRect.right) + 0x1F) & (~0x1F)) - x; - uint32_t b = ((((uint32_t)dirtyRect.bottom) + 0x3) & (~0x3)) - y; - uint32_t width = (r > getWidth() ? getWidth() : r); - uint32_t height = (b > getHeight() ? getHeight() : b); - - // The unpack row length only needs to be specified when a new - // texture is bound - if (mHasUnpackRowLength) { - glPixelStorei(GL_UNPACK_ROW_LENGTH, getWidth()); - } else { - x = 0; - width = getWidth(); - } - - mPixelBuffer->upload(x, y, width, height); - setDirty(false); - - return mHasUnpackRowLength; -} - -void CacheTexture::setDirty(bool dirty) { - mDirty = dirty; - if (!dirty) { - mDirtyRect.setEmpty(); - } -} - -bool CacheTexture::fitBitmap(const SkGlyph& glyph, uint32_t* retOriginX, uint32_t* retOriginY) { - switch (glyph.fMaskFormat) { - case SkMask::kA8_Format: - case SkMask::kBW_Format: - if (mFormat != GL_ALPHA) { -#if DEBUG_FONT_RENDERER - ALOGD("fitBitmap: texture format %x is inappropriate for monochromatic glyphs", - mFormat); -#endif - return false; - } - break; - case SkMask::kARGB32_Format: - if (mFormat != GL_RGBA) { -#if DEBUG_FONT_RENDERER - ALOGD("fitBitmap: texture format %x is inappropriate for colour glyphs", mFormat); -#endif - return false; - } - break; - default: -#if DEBUG_FONT_RENDERER - ALOGD("fitBitmap: unknown glyph format %x encountered", glyph.fMaskFormat); -#endif - return false; - } - - if (glyph.fHeight + TEXTURE_BORDER_SIZE * 2 > getHeight()) { - return false; - } - - uint16_t glyphW = glyph.fWidth + TEXTURE_BORDER_SIZE; - uint16_t glyphH = glyph.fHeight + TEXTURE_BORDER_SIZE; - - // roundedUpW equals glyphW to the next multiple of CACHE_BLOCK_ROUNDING_SIZE. - // This columns for glyphs that are close but not necessarily exactly the same size. It trades - // off the loss of a few pixels for some glyphs against the ability to store more glyphs - // of varying sizes in one block. - uint16_t roundedUpW = (glyphW + CACHE_BLOCK_ROUNDING_SIZE - 1) & -CACHE_BLOCK_ROUNDING_SIZE; - - CacheBlock* cacheBlock = mCacheBlocks; - while (cacheBlock) { - // Store glyph in this block iff: it fits the block's remaining space and: - // it's the remainder space (mY == 0) or there's only enough height for this one glyph - // or it's within ROUNDING_SIZE of the block width - if (roundedUpW <= cacheBlock->mWidth && glyphH <= cacheBlock->mHeight && - (cacheBlock->mY == TEXTURE_BORDER_SIZE || - (cacheBlock->mWidth - roundedUpW < CACHE_BLOCK_ROUNDING_SIZE))) { - if (cacheBlock->mHeight - glyphH < glyphH) { - // Only enough space for this glyph - don't bother rounding up the width - roundedUpW = glyphW; - } - - *retOriginX = cacheBlock->mX; - *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) { - uint16_t oldX = cacheBlock->mX; - // Adjust remainder space dimensions - cacheBlock->mWidth -= roundedUpW; - cacheBlock->mX += roundedUpW; - - if (getHeight() - glyphH >= glyphH) { - // There's enough height left over to create a new CacheBlock - CacheBlock* newBlock = - new CacheBlock(oldX, glyphH + TEXTURE_BORDER_SIZE, roundedUpW, - getHeight() - glyphH - TEXTURE_BORDER_SIZE); -#if DEBUG_FONT_RENDERER - ALOGD("fitBitmap: Created new block: this, x, y, w, h = %p, %d, %d, %d, %d", - newBlock, newBlock->mX, newBlock->mY, newBlock->mWidth, - newBlock->mHeight); -#endif - mCacheBlocks = CacheBlock::insertBlock(mCacheBlocks, newBlock); - } - } else { - // Insert into current column and adjust column dimensions - cacheBlock->mY += glyphH; - cacheBlock->mHeight -= glyphH; -#if DEBUG_FONT_RENDERER - ALOGD("fitBitmap: Added to existing block: this, x, y, w, h = %p, %d, %d, %d, %d", - cacheBlock, cacheBlock->mX, cacheBlock->mY, cacheBlock->mWidth, - cacheBlock->mHeight); -#endif - } - - if (cacheBlock->mHeight < std::min(glyphH, glyphW)) { - // If remaining space in this block is too small to be useful, remove it - mCacheBlocks = CacheBlock::removeBlock(mCacheBlocks, cacheBlock); - } - - mDirty = true; - const Rect r(*retOriginX - TEXTURE_BORDER_SIZE, *retOriginY - TEXTURE_BORDER_SIZE, - *retOriginX + glyphW, *retOriginY + glyphH); - mDirtyRect.unionWith(r); - mNumGlyphs++; - -#if DEBUG_FONT_RENDERER - ALOGD("fitBitmap: current block list:"); - mCacheBlocks->output(); -#endif - - return true; - } - cacheBlock = cacheBlock->mNext; - } -#if DEBUG_FONT_RENDERER - ALOGD("fitBitmap: returning false for glyph of size %d, %d", glyphW, glyphH); -#endif - return false; -} - -uint32_t CacheTexture::calculateFreeMemory() const { - CacheBlock* cacheBlock = mCacheBlocks; - uint32_t free = 0; - // currently only two formats are supported: GL_ALPHA or GL_RGBA; - uint32_t bpp = mFormat == GL_RGBA ? 4 : 1; - while (cacheBlock) { - free += bpp * cacheBlock->mWidth * cacheBlock->mHeight; - cacheBlock = cacheBlock->mNext; - } - return free; -} - -}; // namespace uirenderer -}; // namespace android diff --git a/libs/hwui/font/CacheTexture.h b/libs/hwui/font/CacheTexture.h deleted file mode 100644 index 654378eeb47e..000000000000 --- a/libs/hwui/font/CacheTexture.h +++ /dev/null @@ -1,173 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HWUI_CACHE_TEXTURE_H -#define ANDROID_HWUI_CACHE_TEXTURE_H - -#include "PixelBuffer.h" -#include "Rect.h" -#include "Texture.h" -#include "Vertex.h" - -#include <GLES3/gl3.h> -#include <SkGlyph.h> -#include <utils/Log.h> - -namespace android { -namespace uirenderer { - -class Caches; - -/** - * 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, creating - * a new column as appropriate. - * - * As columns fill up, we remove their CacheBlock from the list to avoid having to check - * small blocks in the future. - */ -struct CacheBlock { - uint16_t mX; - uint16_t mY; - uint16_t mWidth; - uint16_t mHeight; - CacheBlock* mNext; - CacheBlock* mPrev; - - CacheBlock(uint16_t x, uint16_t y, uint16_t width, uint16_t height) - : mX(x), mY(y), mWidth(width), mHeight(height), mNext(nullptr), mPrev(nullptr) {} - - static CacheBlock* insertBlock(CacheBlock* head, CacheBlock* newBlock); - static CacheBlock* removeBlock(CacheBlock* head, CacheBlock* blockToRemove); - - void output() { - CacheBlock* currBlock = this; - while (currBlock) { - ALOGD("Block: this, x, y, w, h = %p, %d, %d, %d, %d", currBlock, currBlock->mX, - currBlock->mY, currBlock->mWidth, currBlock->mHeight); - currBlock = currBlock->mNext; - } - } -}; - -class CacheTexture { -public: - CacheTexture(uint16_t width, uint16_t height, GLenum format, uint32_t maxQuadCount); - ~CacheTexture(); - - void reset(); - void init(); - - void releaseMesh(); - void releasePixelBuffer(); - - void allocatePixelBuffer(); - void allocateMesh(); - - // Returns true if glPixelStorei(GL_UNPACK_ROW_LENGTH) must be reset - // This method will also call setDirty(false) - bool upload(); - - 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 GLenum getFormat() const { return mFormat; } - - inline uint32_t getOffset(uint16_t x, uint16_t y) const { - return (y * getWidth() + x) * PixelBuffer::formatSize(mFormat); - } - - inline const Rect* getDirtyRect() const { return &mDirtyRect; } - - inline PixelBuffer* getPixelBuffer() const { return mPixelBuffer; } - - Texture& getTexture() { - allocatePixelBuffer(); - return mTexture; - } - - GLuint getTextureId() { - allocatePixelBuffer(); - return mTexture.id(); - } - - inline bool isDirty() const { return mDirty; } - - inline bool getLinearFiltering() const { return mLinearFiltering; } - - /** - * This method assumes that the proper texture unit is active. - */ - void setLinearFiltering(bool linearFiltering); - - inline uint16_t getGlyphCount() const { return mNumGlyphs; } - - TextureVertex* mesh() const { return mMesh; } - - uint32_t meshElementCount() const { return mCurrentQuad * 6; } - - uint16_t* indices() const { return (uint16_t*)nullptr; } - - void resetMesh() { mCurrentQuad = 0; } - - inline void addQuad(float x1, float y1, float u1, float v1, float x2, float y2, float u2, - float v2, float x3, float y3, float u3, float v3, float x4, float y4, - float u4, float v4) { - TextureVertex* mesh = mMesh + mCurrentQuad * 4; - TextureVertex::set(mesh++, x2, y2, u2, v2); - TextureVertex::set(mesh++, x3, y3, u3, v3); - TextureVertex::set(mesh++, x1, y1, u1, v1); - TextureVertex::set(mesh++, x4, y4, u4, v4); - mCurrentQuad++; - } - - bool canDraw() const { return mCurrentQuad > 0; } - - bool endOfMesh() const { return mCurrentQuad == mMaxQuadCount; } - - uint32_t calculateFreeMemory() const; - -private: - void setDirty(bool dirty); - - PixelBuffer* mPixelBuffer = nullptr; - Texture mTexture; - uint32_t mWidth, mHeight; - GLenum mFormat; - bool mLinearFiltering = false; - bool mDirty = false; - uint16_t mNumGlyphs = 0; - TextureVertex* mMesh = nullptr; - uint32_t mCurrentQuad = 0; - uint32_t mMaxQuadCount; - Caches& mCaches; - CacheBlock* mCacheBlocks; - bool mHasUnpackRowLength; - Rect mDirtyRect; -}; - -}; // namespace uirenderer -}; // namespace android - -#endif // ANDROID_HWUI_CACHE_TEXTURE_H diff --git a/libs/hwui/font/Font.cpp b/libs/hwui/font/Font.cpp deleted file mode 100644 index 884ccd9afaca..000000000000 --- a/libs/hwui/font/Font.cpp +++ /dev/null @@ -1,490 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <cutils/compiler.h> - -#include <utils/JenkinsHash.h> -#include <utils/Trace.h> - -#include <SkGlyph.h> -#include <SkGlyphCache.h> -#include <SkSurfaceProps.h> -#include <SkUtils.h> - -#include "../Debug.h" -#include "../FontRenderer.h" -#include "../PixelBuffer.h" -#include "../Properties.h" -#include "Font.h" -#include "FontUtil.h" - -namespace android { -namespace uirenderer { - -/////////////////////////////////////////////////////////////////////////////// -// Font -/////////////////////////////////////////////////////////////////////////////// - -Font::Font(FontRenderer* state, const Font::FontDescription& desc) - : mState(state), mDescription(desc) {} - -Font::FontDescription::FontDescription(const SkPaint* paint, const SkMatrix& rasterMatrix) - : mLookupTransform(rasterMatrix) { - mFontId = SkTypeface::UniqueID(paint->getTypeface()); - mFontSize = paint->getTextSize(); - mFlags = 0; - if (paint->isFakeBoldText()) { - mFlags |= Font::kFakeBold; - } - mItalicStyle = paint->getTextSkewX(); - mScaleX = paint->getTextScaleX(); - mStyle = paint->getStyle(); - mStrokeWidth = paint->getStrokeWidth(); - mAntiAliasing = paint->isAntiAlias(); - mHinting = paint->getHinting(); - if (!mLookupTransform.invert(&mInverseLookupTransform)) { - ALOGW("Could not query the inverse lookup transform for this font"); - } -} - -Font::~Font() { - for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) { - delete mCachedGlyphs.valueAt(i); - } -} - -hash_t Font::FontDescription::hash() const { - uint32_t hash = JenkinsHashMix(0, mFontId); - hash = JenkinsHashMix(hash, android::hash_type(mFontSize)); - hash = JenkinsHashMix(hash, android::hash_type(mFlags)); - hash = JenkinsHashMix(hash, android::hash_type(mItalicStyle)); - hash = JenkinsHashMix(hash, android::hash_type(mScaleX)); - hash = JenkinsHashMix(hash, android::hash_type(mStyle)); - hash = JenkinsHashMix(hash, android::hash_type(mStrokeWidth)); - hash = JenkinsHashMix(hash, int(mAntiAliasing)); - hash = JenkinsHashMix(hash, android::hash_type(mHinting)); - hash = JenkinsHashMix(hash, android::hash_type(mLookupTransform[SkMatrix::kMScaleX])); - hash = JenkinsHashMix(hash, android::hash_type(mLookupTransform[SkMatrix::kMScaleY])); - return JenkinsHashWhiten(hash); -} - -int Font::FontDescription::compare(const Font::FontDescription& lhs, - const Font::FontDescription& rhs) { - int deltaInt = int(lhs.mFontId) - int(rhs.mFontId); - if (deltaInt != 0) return deltaInt; - - if (lhs.mFontSize < rhs.mFontSize) return -1; - if (lhs.mFontSize > rhs.mFontSize) return +1; - - if (lhs.mItalicStyle < rhs.mItalicStyle) return -1; - if (lhs.mItalicStyle > rhs.mItalicStyle) return +1; - - deltaInt = int(lhs.mFlags) - int(rhs.mFlags); - if (deltaInt != 0) return deltaInt; - - if (lhs.mScaleX < rhs.mScaleX) return -1; - if (lhs.mScaleX > rhs.mScaleX) return +1; - - deltaInt = int(lhs.mStyle) - int(rhs.mStyle); - if (deltaInt != 0) return deltaInt; - - if (lhs.mStrokeWidth < rhs.mStrokeWidth) return -1; - if (lhs.mStrokeWidth > rhs.mStrokeWidth) return +1; - - deltaInt = int(lhs.mAntiAliasing) - int(rhs.mAntiAliasing); - if (deltaInt != 0) return deltaInt; - - deltaInt = int(lhs.mHinting) - int(rhs.mHinting); - if (deltaInt != 0) return deltaInt; - - if (lhs.mLookupTransform[SkMatrix::kMScaleX] < rhs.mLookupTransform[SkMatrix::kMScaleX]) - return -1; - if (lhs.mLookupTransform[SkMatrix::kMScaleX] > rhs.mLookupTransform[SkMatrix::kMScaleX]) - return +1; - - if (lhs.mLookupTransform[SkMatrix::kMScaleY] < rhs.mLookupTransform[SkMatrix::kMScaleY]) - return -1; - if (lhs.mLookupTransform[SkMatrix::kMScaleY] > rhs.mLookupTransform[SkMatrix::kMScaleY]) - return +1; - - return 0; -} - -void Font::invalidateTextureCache(CacheTexture* cacheTexture) { - for (uint32_t i = 0; i < mCachedGlyphs.size(); i++) { - CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueAt(i); - if (!cacheTexture || cachedGlyph->mCacheTexture == cacheTexture) { - cachedGlyph->mIsValid = false; - } - } -} - -void Font::measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, - uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos) { - int width = (int)glyph->mBitmapWidth; - int height = (int)glyph->mBitmapHeight; - - int nPenX = x + glyph->mBitmapLeft; - int nPenY = y + glyph->mBitmapTop; - - if (bounds->bottom > nPenY) { - bounds->bottom = nPenY; - } - if (bounds->left > nPenX) { - bounds->left = nPenX; - } - if (bounds->right < nPenX + width) { - bounds->right = nPenX + width; - } - if (bounds->top < nPenY + height) { - bounds->top = nPenY + height; - } -} - -void Font::drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, - uint32_t bitmapH, Rect* bounds, const float* pos) { - float width = (float)glyph->mBitmapWidth; - float height = (float)glyph->mBitmapHeight; - - float nPenX = x + glyph->mBitmapLeft; - float nPenY = y + glyph->mBitmapTop + height; - - float u1 = glyph->mBitmapMinU; - float u2 = glyph->mBitmapMaxU; - float v1 = glyph->mBitmapMinV; - float v2 = glyph->mBitmapMaxV; - - mState->appendMeshQuad(nPenX, nPenY, u1, v2, nPenX + width, nPenY, u2, v2, nPenX + width, - nPenY - height, u2, v1, nPenX, nPenY - height, u1, v1, - glyph->mCacheTexture); -} - -void Font::drawCachedGlyphTransformed(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, - uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, - const float* pos) { - float width = (float)glyph->mBitmapWidth; - float height = (float)glyph->mBitmapHeight; - - SkPoint p[4]; - p[0].iset(glyph->mBitmapLeft, glyph->mBitmapTop + height); - p[1].iset(glyph->mBitmapLeft + width, glyph->mBitmapTop + height); - p[2].iset(glyph->mBitmapLeft + width, glyph->mBitmapTop); - p[3].iset(glyph->mBitmapLeft, glyph->mBitmapTop); - - mDescription.mInverseLookupTransform.mapPoints(p, 4); - - p[0].offset(x, y); - p[1].offset(x, y); - p[2].offset(x, y); - p[3].offset(x, y); - - float u1 = glyph->mBitmapMinU; - float u2 = glyph->mBitmapMaxU; - float v1 = glyph->mBitmapMinV; - float v2 = glyph->mBitmapMaxV; - - mState->appendRotatedMeshQuad(p[0].x(), p[0].y(), u1, v2, p[1].x(), p[1].y(), u2, v2, p[2].x(), - p[2].y(), u2, v1, p[3].x(), p[3].y(), u1, v1, - glyph->mCacheTexture); -} - -void Font::drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, - uint32_t bitmapWidth, uint32_t bitmapHeight, Rect* bounds, - const float* pos) { - int dstX = x + glyph->mBitmapLeft; - int dstY = y + glyph->mBitmapTop; - - CacheTexture* cacheTexture = glyph->mCacheTexture; - PixelBuffer* pixelBuffer = cacheTexture->getPixelBuffer(); - - uint32_t formatSize = PixelBuffer::formatSize(pixelBuffer->getFormat()); - uint32_t alpha_channel_offset = PixelBuffer::formatAlphaOffset(pixelBuffer->getFormat()); - uint32_t cacheWidth = cacheTexture->getWidth(); - uint32_t srcStride = formatSize * cacheWidth; - uint32_t startY = glyph->mStartY * srcStride; - uint32_t endY = startY + (glyph->mBitmapHeight * srcStride); - - const uint8_t* cacheBuffer = pixelBuffer->map(); - - for (uint32_t cacheY = startY, bitmapY = dstY * bitmapWidth; cacheY < endY; - cacheY += srcStride, bitmapY += bitmapWidth) { - for (uint32_t i = 0; i < glyph->mBitmapWidth; ++i) { - uint8_t* dst = &(bitmap[bitmapY + dstX + i]); - const uint8_t& src = - cacheBuffer[cacheY + (glyph->mStartX + i) * formatSize + alpha_channel_offset]; - // Add alpha values to a max of 255, full opacity. This is done to handle - // fonts/strings where glyphs overlap. - *dst = std::min(*dst + src, 255); - } - } -} - -void Font::drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset, - SkPathMeasure& measure, SkPoint* position, SkVector* tangent) { - const float halfWidth = glyph->mBitmapWidth * 0.5f; - const float height = glyph->mBitmapHeight; - - vOffset += glyph->mBitmapTop + height; - - SkPoint destination[4]; - bool ok = measure.getPosTan(x + hOffset + glyph->mBitmapLeft + halfWidth, position, tangent); - if (!ok) { - ALOGW("The path for drawTextOnPath is empty or null"); - } - - // Move along the tangent and offset by the normal - destination[0].set(-tangent->fX * halfWidth - tangent->fY * vOffset, - -tangent->fY * halfWidth + tangent->fX * vOffset); - destination[1].set(tangent->fX * halfWidth - tangent->fY * vOffset, - tangent->fY * halfWidth + tangent->fX * vOffset); - destination[2].set(destination[1].fX + tangent->fY * height, - destination[1].fY - tangent->fX * height); - destination[3].set(destination[0].fX + tangent->fY * height, - destination[0].fY - tangent->fX * height); - - const float u1 = glyph->mBitmapMinU; - const float u2 = glyph->mBitmapMaxU; - const float v1 = glyph->mBitmapMinV; - const float v2 = glyph->mBitmapMaxV; - - mState->appendRotatedMeshQuad( - position->x() + destination[0].x(), position->y() + destination[0].y(), u1, v2, - position->x() + destination[1].x(), position->y() + destination[1].y(), u2, v2, - position->x() + destination[2].x(), position->y() + destination[2].y(), u2, v1, - position->x() + destination[3].x(), position->y() + destination[3].y(), u1, v1, - glyph->mCacheTexture); -} - -CachedGlyphInfo* Font::getCachedGlyph(const SkPaint* paint, glyph_t textUnit, bool precaching) { - CachedGlyphInfo* cachedGlyph = mCachedGlyphs.valueFor(textUnit); - if (cachedGlyph) { - // Is the glyph still in texture cache? - if (!cachedGlyph->mIsValid) { - SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry); - SkAutoGlyphCacheNoGamma autoCache(*paint, &surfaceProps, - &mDescription.mLookupTransform); - const SkGlyph& skiaGlyph = GET_METRICS(autoCache.get(), textUnit); - updateGlyphCache(paint, skiaGlyph, autoCache.get(), cachedGlyph, precaching); - } - } else { - cachedGlyph = cacheGlyph(paint, textUnit, precaching); - } - - return cachedGlyph; -} - -void Font::render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, int x, int y, - const float* positions) { - render(paint, glyphs, numGlyphs, x, y, FRAMEBUFFER, nullptr, 0, 0, nullptr, positions); -} - -void Font::render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, const SkPath* path, - float hOffset, float vOffset) { - if (numGlyphs == 0 || glyphs == nullptr) { - return; - } - - int glyphsCount = 0; - int prevRsbDelta = 0; - - float penX = 0.0f; - - SkPoint position; - SkVector tangent; - - SkPathMeasure measure(*path, false); - float pathLength = SkScalarToFloat(measure.getLength()); - - if (paint->getTextAlign() != SkPaint::kLeft_Align) { - float textWidth = SkScalarToFloat(paint->measureText(glyphs, numGlyphs * 2)); - float pathOffset = pathLength; - if (paint->getTextAlign() == SkPaint::kCenter_Align) { - textWidth *= 0.5f; - pathOffset *= 0.5f; - } - penX += pathOffset - textWidth; - } - - while (glyphsCount < numGlyphs && penX < pathLength) { - glyph_t glyph = *(glyphs++); - - if (IS_END_OF_STRING(glyph)) { - break; - } - - CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph); - penX += AUTO_KERN(prevRsbDelta, cachedGlyph->mLsbDelta); - prevRsbDelta = cachedGlyph->mRsbDelta; - - if (cachedGlyph->mIsValid && cachedGlyph->mCacheTexture) { - drawCachedGlyph(cachedGlyph, penX, hOffset, vOffset, measure, &position, &tangent); - } - - penX += cachedGlyph->mAdvanceX; - - glyphsCount++; - } -} - -void Font::measure(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, Rect* bounds, - const float* positions) { - if (bounds == nullptr) { - ALOGE("No return rectangle provided to measure text"); - return; - } - bounds->set(1e6, -1e6, -1e6, 1e6); - render(paint, glyphs, numGlyphs, 0, 0, MEASURE, nullptr, 0, 0, bounds, positions); -} - -void Font::precache(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs) { - if (numGlyphs == 0 || glyphs == nullptr) { - return; - } - - int glyphsCount = 0; - while (glyphsCount < numGlyphs) { - glyph_t glyph = *(glyphs++); - - // Reached the end of the string - if (IS_END_OF_STRING(glyph)) { - break; - } - - getCachedGlyph(paint, glyph, true); - glyphsCount++; - } -} - -void Font::render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, int x, int y, - RenderMode mode, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, - Rect* bounds, const float* positions) { - if (numGlyphs == 0 || glyphs == nullptr) { - return; - } - - static RenderGlyph gRenderGlyph[] = {&android::uirenderer::Font::drawCachedGlyph, - &android::uirenderer::Font::drawCachedGlyphTransformed, - &android::uirenderer::Font::drawCachedGlyphBitmap, - &android::uirenderer::Font::drawCachedGlyphBitmap, - &android::uirenderer::Font::measureCachedGlyph, - &android::uirenderer::Font::measureCachedGlyph}; - RenderGlyph render = gRenderGlyph[(mode << 1) + !mIdentityTransform]; - - int glyphsCount = 0; - - while (glyphsCount < numGlyphs) { - glyph_t glyph = *(glyphs++); - - // Reached the end of the string - if (IS_END_OF_STRING(glyph)) { - break; - } - - CachedGlyphInfo* cachedGlyph = getCachedGlyph(paint, glyph); - - // If it's still not valid, we couldn't cache it, so we shouldn't - // draw garbage; also skip empty glyphs (spaces) - if (cachedGlyph->mIsValid && cachedGlyph->mCacheTexture) { - int penX = x + (int)roundf(positions[(glyphsCount << 1)]); - int penY = y + (int)roundf(positions[(glyphsCount << 1) + 1]); -#ifdef BUGREPORT_FONT_CACHE_USAGE - mState->historyTracker().glyphRendered(cachedGlyph, penX, penY); -#endif - (*this.*render)(cachedGlyph, penX, penY, bitmap, bitmapW, bitmapH, bounds, positions); - } else { -#ifdef BUGREPORT_FONT_CACHE_USAGE - mState->historyTracker().glyphRendered(cachedGlyph, -1, -1); -#endif - } - - glyphsCount++; - } -} - -void Font::updateGlyphCache(const SkPaint* paint, const SkGlyph& skiaGlyph, - SkGlyphCache* skiaGlyphCache, CachedGlyphInfo* glyph, bool precaching) { - glyph->mAdvanceX = skiaGlyph.fAdvanceX; - glyph->mAdvanceY = skiaGlyph.fAdvanceY; - glyph->mBitmapLeft = skiaGlyph.fLeft; - glyph->mBitmapTop = skiaGlyph.fTop; - glyph->mLsbDelta = skiaGlyph.fLsbDelta; - glyph->mRsbDelta = skiaGlyph.fRsbDelta; - - uint32_t startX = 0; - uint32_t startY = 0; - - // Get the bitmap for the glyph - if (!skiaGlyph.fImage) { - skiaGlyphCache->findImage(skiaGlyph); - } - mState->cacheBitmap(skiaGlyph, glyph, &startX, &startY, precaching); - - if (!glyph->mIsValid) { - return; - } - - uint32_t endX = startX + skiaGlyph.fWidth; - uint32_t endY = startY + skiaGlyph.fHeight; - - glyph->mStartX = startX; - glyph->mStartY = startY; - glyph->mBitmapWidth = skiaGlyph.fWidth; - glyph->mBitmapHeight = skiaGlyph.fHeight; - - bool empty = skiaGlyph.fWidth == 0 || skiaGlyph.fHeight == 0; - if (!empty) { - uint32_t cacheWidth = glyph->mCacheTexture->getWidth(); - uint32_t cacheHeight = glyph->mCacheTexture->getHeight(); - - glyph->mBitmapMinU = startX / (float)cacheWidth; - glyph->mBitmapMinV = startY / (float)cacheHeight; - glyph->mBitmapMaxU = endX / (float)cacheWidth; - glyph->mBitmapMaxV = endY / (float)cacheHeight; - - mState->setTextureDirty(); - } -} - -CachedGlyphInfo* Font::cacheGlyph(const SkPaint* paint, glyph_t glyph, bool precaching) { - CachedGlyphInfo* newGlyph = new CachedGlyphInfo(); - mCachedGlyphs.add(glyph, newGlyph); - - SkSurfaceProps surfaceProps(0, kUnknown_SkPixelGeometry); - SkAutoGlyphCacheNoGamma autoCache(*paint, &surfaceProps, &mDescription.mLookupTransform); - const SkGlyph& skiaGlyph = GET_METRICS(autoCache.get(), glyph); - newGlyph->mIsValid = false; - newGlyph->mGlyphIndex = skiaGlyph.fID; - - updateGlyphCache(paint, skiaGlyph, autoCache.get(), newGlyph, precaching); - - return newGlyph; -} - -Font* Font::create(FontRenderer* state, const SkPaint* paint, const SkMatrix& matrix) { - FontDescription description(paint, matrix); - Font* font = state->mActiveFonts.get(description); - - if (!font) { - font = new Font(state, description); - state->mActiveFonts.put(description, font); - } - font->mIdentityTransform = matrix.isIdentity(); - - return font; -} - -}; // namespace uirenderer -}; // namespace android diff --git a/libs/hwui/font/Font.h b/libs/hwui/font/Font.h deleted file mode 100644 index 85221bc069f1..000000000000 --- a/libs/hwui/font/Font.h +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HWUI_FONT_H -#define ANDROID_HWUI_FONT_H - -#include <vector> - -#include <utils/KeyedVector.h> - -#include <SkPaint.h> -#include <SkPathMeasure.h> -#include <SkScalar.h> -#include <SkTypeface.h> - -#include "../Matrix.h" -#include "../Rect.h" -#include "FontUtil.h" - -class SkGlyphCache; - -namespace android { -namespace uirenderer { - -/////////////////////////////////////////////////////////////////////////////// -// Font -/////////////////////////////////////////////////////////////////////////////// - -struct CachedGlyphInfo; -class CacheTexture; -class FontRenderer; - -/** - * Represents a font, defined by a Skia font id and a font size. A font is used - * to generate glyphs and cache them in the FontState. - */ -class Font { -public: - enum Style { kFakeBold = 1 }; - - struct FontDescription { - FontDescription(const SkPaint* paint, const SkMatrix& matrix); - - static int compare(const FontDescription& lhs, const FontDescription& rhs); - - hash_t hash() const; - - bool operator==(const FontDescription& other) const { return compare(*this, other) == 0; } - - bool operator!=(const FontDescription& other) const { return compare(*this, other) != 0; } - - SkFontID mFontId; - float mFontSize; - int mFlags; - float mItalicStyle; - float mScaleX; - uint8_t mStyle; - float mStrokeWidth; - bool mAntiAliasing; - uint8_t mHinting; - SkMatrix mLookupTransform; - SkMatrix mInverseLookupTransform; - }; - - ~Font(); - - void render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, int x, int y, - const float* positions); - - void render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, const SkPath* path, - float hOffset, float vOffset); - - const Font::FontDescription& getDescription() const { return mDescription; } - - /** - * Creates a new font associated with the specified font state. - */ - static Font* create(FontRenderer* state, const SkPaint* paint, const SkMatrix& matrix); - -private: - friend class FontRenderer; - - Font(FontRenderer* state, const Font::FontDescription& desc); - - typedef void (Font::*RenderGlyph)(CachedGlyphInfo*, int, int, uint8_t*, uint32_t, uint32_t, - Rect*, const float*); - - enum RenderMode { - FRAMEBUFFER, - BITMAP, - MEASURE, - }; - - void precache(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs); - - void render(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, int x, int y, - RenderMode mode, uint8_t* bitmap, uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, - const float* positions); - - void measure(const SkPaint* paint, const glyph_t* glyphs, int numGlyphs, Rect* bounds, - const float* positions); - - void invalidateTextureCache(CacheTexture* cacheTexture = nullptr); - - CachedGlyphInfo* cacheGlyph(const SkPaint* paint, glyph_t glyph, bool precaching); - void updateGlyphCache(const SkPaint* paint, const SkGlyph& skiaGlyph, - SkGlyphCache* skiaGlyphCache, CachedGlyphInfo* glyph, bool precaching); - - void measureCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, - uint32_t bitmapH, Rect* bounds, const float* pos); - void drawCachedGlyph(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, uint32_t bitmapW, - uint32_t bitmapH, Rect* bounds, const float* pos); - void drawCachedGlyphTransformed(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, - uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, - const float* pos); - void drawCachedGlyphBitmap(CachedGlyphInfo* glyph, int x, int y, uint8_t* bitmap, - uint32_t bitmapW, uint32_t bitmapH, Rect* bounds, const float* pos); - void drawCachedGlyph(CachedGlyphInfo* glyph, float x, float hOffset, float vOffset, - SkPathMeasure& measure, SkPoint* position, SkVector* tangent); - - CachedGlyphInfo* getCachedGlyph(const SkPaint* paint, glyph_t textUnit, - bool precaching = false); - - FontRenderer* mState; - FontDescription mDescription; - - // Cache of glyphs - DefaultKeyedVector<glyph_t, CachedGlyphInfo*> mCachedGlyphs; - - bool mIdentityTransform; -}; - -inline int strictly_order_type(const Font::FontDescription& lhs, const Font::FontDescription& rhs) { - return Font::FontDescription::compare(lhs, rhs) < 0; -} - -inline int compare_type(const Font::FontDescription& lhs, const Font::FontDescription& rhs) { - return Font::FontDescription::compare(lhs, rhs); -} - -inline hash_t hash_type(const Font::FontDescription& entry) { - return entry.hash(); -} - -}; // namespace uirenderer -}; // namespace android - -#endif // ANDROID_HWUI_FONT_H diff --git a/libs/hwui/font/FontCacheHistoryTracker.cpp b/libs/hwui/font/FontCacheHistoryTracker.cpp deleted file mode 100644 index 5b61c494524a..000000000000 --- a/libs/hwui/font/FontCacheHistoryTracker.cpp +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "FontCacheHistoryTracker.h" - -#include "CacheTexture.h" -#include "CachedGlyphInfo.h" - -namespace android { -namespace uirenderer { - -void FontCacheHistoryTracker::dumpCachedGlyph(String8& log, const CachedGlyph& glyph) { - log.appendFormat("glyph (texture %p, position: (%d, %d), size: %dx%d, gen: %d)", glyph.texture, - glyph.startX, glyph.startY, glyph.bitmapW, glyph.bitmapH, glyph.generation); -} - -void FontCacheHistoryTracker::dumpRenderEntry(String8& log, const RenderEntry& entry) { - if (entry.penX == -1 && entry.penY == -1) { - log.appendFormat(" glyph skipped in gen: %d\n", entry.glyph.generation); - } else { - log.appendFormat(" rendered "); - dumpCachedGlyph(log, entry.glyph); - log.appendFormat(" at (%d, %d)\n", entry.penX, entry.penY); - } -} - -void FontCacheHistoryTracker::dumpUploadEntry(String8& log, const CachedGlyph& glyph) { - if (glyph.bitmapW == 0 && glyph.bitmapH == 0) { - log.appendFormat(" cleared cachetexture %p in gen %d\n", glyph.texture, - glyph.generation); - } else { - log.appendFormat(" uploaded "); - dumpCachedGlyph(log, glyph); - log.appendFormat("\n"); - } -} - -void FontCacheHistoryTracker::dump(String8& log) const { - log.appendFormat("FontCacheHistory: \n"); - log.appendFormat(" Upload history: \n"); - for (size_t i = 0; i < mUploadHistory.size(); i++) { - dumpUploadEntry(log, mUploadHistory[i]); - } - log.appendFormat(" Render history: \n"); - for (size_t i = 0; i < mRenderHistory.size(); i++) { - dumpRenderEntry(log, mRenderHistory[i]); - } -} - -void FontCacheHistoryTracker::glyphRendered(CachedGlyphInfo* glyphInfo, int penX, int penY) { - RenderEntry& entry = mRenderHistory.next(); - entry.glyph.generation = generation; - entry.glyph.texture = glyphInfo->mCacheTexture; - entry.glyph.startX = glyphInfo->mStartX; - entry.glyph.startY = glyphInfo->mStartY; - entry.glyph.bitmapW = glyphInfo->mBitmapWidth; - entry.glyph.bitmapH = glyphInfo->mBitmapHeight; - entry.penX = penX; - entry.penY = penY; -} - -void FontCacheHistoryTracker::glyphUploaded(CacheTexture* texture, uint32_t x, uint32_t y, - uint16_t glyphW, uint16_t glyphH) { - CachedGlyph& glyph = mUploadHistory.next(); - glyph.generation = generation; - glyph.texture = texture; - glyph.startX = x; - glyph.startY = y; - glyph.bitmapW = glyphW; - glyph.bitmapH = glyphH; -} - -void FontCacheHistoryTracker::glyphsCleared(CacheTexture* texture) { - CachedGlyph& glyph = mUploadHistory.next(); - glyph.generation = generation; - glyph.texture = texture; - glyph.startX = 0; - glyph.startY = 0; - glyph.bitmapW = 0; - glyph.bitmapH = 0; -} - -void FontCacheHistoryTracker::frameCompleted() { - generation++; -} -}; // namespace uirenderer -}; // namespace android diff --git a/libs/hwui/font/FontCacheHistoryTracker.h b/libs/hwui/font/FontCacheHistoryTracker.h deleted file mode 100644 index 4b9ceccc09c9..000000000000 --- a/libs/hwui/font/FontCacheHistoryTracker.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once -#include "../utils/RingBuffer.h" - -#include <utils/String8.h> - -namespace android { -namespace uirenderer { - -class CacheTexture; -struct CachedGlyphInfo; - -// Tracks glyph uploads and recent rendered/skipped glyphs, so it can give an idea -// what a missing character is: skipped glyph, wrong coordinates in cache texture etc. -class FontCacheHistoryTracker { -public: - void glyphRendered(CachedGlyphInfo*, int penX, int penY); - void glyphUploaded(CacheTexture*, uint32_t x, uint32_t y, uint16_t glyphW, uint16_t glyphH); - void glyphsCleared(CacheTexture*); - void frameCompleted(); - - void dump(String8& log) const; - -private: - struct CachedGlyph { - void* texture; - uint16_t generation; - uint16_t startX; - uint16_t startY; - uint16_t bitmapW; - uint16_t bitmapH; - }; - - struct RenderEntry { - CachedGlyph glyph; - int penX; - int penY; - }; - - static void dumpCachedGlyph(String8& log, const CachedGlyph& glyph); - static void dumpRenderEntry(String8& log, const RenderEntry& entry); - static void dumpUploadEntry(String8& log, const CachedGlyph& glyph); - - RingBuffer<RenderEntry, 300> mRenderHistory; - RingBuffer<CachedGlyph, 120> mUploadHistory; - uint16_t generation = 0; -}; - -}; // namespace uirenderer -}; // namespace android
\ No newline at end of file diff --git a/libs/hwui/font/FontUtil.h b/libs/hwui/font/FontUtil.h deleted file mode 100644 index 596e153db6a9..000000000000 --- a/libs/hwui/font/FontUtil.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2012 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef ANDROID_HWUI_FONT_UTIL_H -#define ANDROID_HWUI_FONT_UTIL_H - -#include <SkUtils.h> - -#include "Properties.h" - -/////////////////////////////////////////////////////////////////////////////// -// Defines -/////////////////////////////////////////////////////////////////////////////// - -#ifdef TEXTURE_BORDER_SIZE -#if TEXTURE_BORDER_SIZE != 1 -#error TEXTURE_BORDER_SIZE other than 1 is not currently supported -#endif -#else -#define TEXTURE_BORDER_SIZE 1 -#endif - -#define CACHE_BLOCK_ROUNDING_SIZE 4 - -typedef uint16_t glyph_t; -#define GET_METRICS(cache, glyph) cache->getGlyphIDMetrics(glyph) -#define IS_END_OF_STRING(glyph) false - -// prev, next are assumed to be signed x.6 fixed-point numbers with range -// [-1, 1]. Result is an integral float. -#define AUTO_KERN(prev, next) static_cast<float>(((next) - (prev) + 32) >> 6) - -#endif // ANDROID_HWUI_FONT_UTIL_H diff --git a/libs/hwui/tests/microbench/FontBench.cpp b/libs/hwui/tests/microbench/FontBench.cpp deleted file mode 100644 index 4e9b540a5c3d..000000000000 --- a/libs/hwui/tests/microbench/FontBench.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (C) 2016 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <benchmark/benchmark.h> - -#include "GammaFontRenderer.h" -#include "tests/common/TestUtils.h" - -#include <SkPaint.h> - -using namespace android; -using namespace android::uirenderer; - -void BM_FontRenderer_precache_cachehits(benchmark::State& state) { - TestUtils::runOnRenderThread([&state](renderthread::RenderThread& thread) { - SkPaint paint; - paint.setTextSize(20); - paint.setTextEncoding(SkPaint::kGlyphID_TextEncoding); - GammaFontRenderer gammaFontRenderer; - FontRenderer& fontRenderer = gammaFontRenderer.getFontRenderer(); - fontRenderer.setFont(&paint, SkMatrix::I()); - - std::vector<glyph_t> glyphs; - std::vector<float> positions; - float totalAdvance; - uirenderer::Rect bounds; - TestUtils::layoutTextUnscaled(paint, "This is a test", &glyphs, &positions, &totalAdvance, - &bounds); - - fontRenderer.precache(&paint, glyphs.data(), glyphs.size(), SkMatrix::I()); - - while (state.KeepRunning()) { - fontRenderer.precache(&paint, glyphs.data(), glyphs.size(), SkMatrix::I()); - } - }); -} -BENCHMARK(BM_FontRenderer_precache_cachehits); |