diff options
Diffstat (limited to 'libs/hwui/FontRenderer.cpp')
-rw-r--r-- | libs/hwui/FontRenderer.cpp | 60 |
1 files changed, 48 insertions, 12 deletions
diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index 97988f7..5d5e6a5 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -22,6 +22,9 @@ #include <utils/Log.h> +#include "RenderScript.h" + +#include "utils/Timing.h" #include "Caches.h" #include "Debug.h" #include "FontRenderer.h" @@ -30,6 +33,9 @@ namespace android { namespace uirenderer { +// blur inputs smaller than this constant will bypass renderscript +#define RS_MIN_INPUT_CUTOFF 10000 + /////////////////////////////////////////////////////////////////////////////// // FontRenderer /////////////////////////////////////////////////////////////////////////////// @@ -543,18 +549,22 @@ FontRenderer::DropShadow FontRenderer::renderDropShadow(SkPaint* paint, const ch uint32_t paddedWidth = (uint32_t) (bounds.right - bounds.left) + 2 * radius; uint32_t paddedHeight = (uint32_t) (bounds.top - bounds.bottom) + 2 * radius; - uint8_t* dataBuffer = new uint8_t[paddedWidth * paddedHeight]; - for (uint32_t i = 0; i < paddedWidth * paddedHeight; i++) { - dataBuffer[i] = 0; + // 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 = radius - bounds.left; int penY = radius - bounds.bottom; mCurrentFont->render(paint, text, startIndex, len, numGlyphs, penX, penY, Font::BITMAP, dataBuffer, paddedWidth, paddedHeight, NULL, positions); - blurImage(dataBuffer, paddedWidth, paddedHeight, radius); + blurImage(&dataBuffer, paddedWidth, paddedHeight, radius); DropShadow image; image.width = paddedWidth; @@ -751,18 +761,44 @@ void FontRenderer::verticalBlur(float* weights, int32_t radius, } } +void FontRenderer::blurImage(uint8_t** image, int32_t width, int32_t height, int32_t radius) { + if (width * height * radius < RS_MIN_INPUT_CUTOFF) { + float *gaussian = new float[2 * radius + 1]; + computeGaussianWeights(gaussian, radius); -void FontRenderer::blurImage(uint8_t *image, int32_t width, int32_t height, int32_t radius) { - float *gaussian = new float[2 * radius + 1]; - computeGaussianWeights(gaussian, radius); + uint8_t* scratch = new uint8_t[width * height]; + + horizontalBlur(gaussian, radius, *image, scratch, width, height); + verticalBlur(gaussian, radius, scratch, *image, width, height); + + delete[] gaussian; + delete[] scratch; + } + + uint8_t* outImage = (uint8_t*)memalign(RS_CPU_ALLOCATION_ALIGNMENT, width * height); + + if (mRs.get() == 0) { + mRs = new RSC::RS(); + if (!mRs->init(true, true)) { + ALOGE("blur RS failed to init"); + } + + mRsElement = RSC::Element::A_8(mRs); + mRsScript = new RSC::ScriptIntrinsicBlur(mRs, mRsElement); + } - uint8_t* scratch = new uint8_t[width * height]; + sp<const RSC::Type> t = RSC::Type::create(mRs, mRsElement, width, height, 0); + sp<RSC::Allocation> ain = RSC::Allocation::createTyped(mRs, t, RS_ALLOCATION_MIPMAP_NONE, + RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, *image); + sp<RSC::Allocation> aout = RSC::Allocation::createTyped(mRs, t, RS_ALLOCATION_MIPMAP_NONE, + RS_ALLOCATION_USAGE_SCRIPT | RS_ALLOCATION_USAGE_SHARED, outImage); - horizontalBlur(gaussian, radius, image, scratch, width, height); - verticalBlur(gaussian, radius, scratch, image, width, height); + mRsScript->setRadius(radius); + mRsScript->blur(ain, aout); - delete[] gaussian; - delete[] scratch; + // replace the original image's pointer, avoiding a copy back to the original buffer + delete *image; + *image = outImage; } }; // namespace uirenderer |