diff options
author | Chris Craik <ccraik@google.com> | 2012-11-14 16:11:10 -0800 |
---|---|---|
committer | Chris Craik <ccraik@google.com> | 2013-02-12 17:45:28 -0800 |
commit | 3f76e65d251ead65fe8ff98e3bd4c7623fbaac07 (patch) | |
tree | b8dfc636012f670aba6a348340ae12770ab63372 /libs | |
parent | d04892d207d50378356feef181ac4e4eff9652d7 (diff) | |
download | frameworks_base-3f76e65d251ead65fe8ff98e3bd4c7623fbaac07.zip frameworks_base-3f76e65d251ead65fe8ff98e3bd4c7623fbaac07.tar.gz frameworks_base-3f76e65d251ead65fe8ff98e3bd4c7623fbaac07.tar.bz2 |
Use RenderScript for large text blurs
Still fall back to simple path for small tasks
Change-Id: I492f1b3f7d6fec1738f3e45cbfb15864bd23a392
Diffstat (limited to 'libs')
-rw-r--r-- | libs/hwui/Android.mk | 11 | ||||
-rw-r--r-- | libs/hwui/FontRenderer.cpp | 60 | ||||
-rw-r--r-- | libs/hwui/FontRenderer.h | 16 | ||||
-rw-r--r-- | libs/hwui/TextDropShadowCache.cpp | 2 | ||||
-rw-r--r-- | libs/hwui/utils/Timing.h | 42 |
5 files changed, 113 insertions, 18 deletions
diff --git a/libs/hwui/Android.mk b/libs/hwui/Android.mk index 2111a56..2a63153 100644 --- a/libs/hwui/Android.mk +++ b/libs/hwui/Android.mk @@ -37,6 +37,8 @@ ifeq ($(USE_OPENGL_RENDERER),true) TextureCache.cpp \ TextDropShadowCache.cpp + intermediates := $(call intermediates-dir-for,STATIC_LIBRARIES,libRS,TARGET,) + LOCAL_C_INCLUDES += \ $(JNI_H_INCLUDE) \ $(LOCAL_PATH)/../../include/utils \ @@ -45,11 +47,14 @@ ifeq ($(USE_OPENGL_RENDERER),true) external/skia/include/images \ external/skia/src/core \ external/skia/src/ports \ - external/skia/include/utils + external/skia/include/utils \ + $(intermediates) \ + frameworks/rs/cpp \ + frameworks/rs LOCAL_CFLAGS += -DUSE_OPENGL_RENDERER -DGL_GLEXT_PROTOTYPES LOCAL_MODULE_CLASS := SHARED_LIBRARIES - LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia libui + LOCAL_SHARED_LIBRARIES := libcutils libutils libGLESv2 libskia libui libRS libRScpp LOCAL_MODULE := libhwui LOCAL_MODULE_TAGS := optional @@ -63,5 +68,5 @@ ifeq ($(USE_OPENGL_RENDERER),true) include $(BUILD_SHARED_LIBRARY) - include $(call all-makefiles-under,$(LOCAL_PATH)) + include $(call all-makefiles-under,$(LOCAL_PATH)) endif diff --git a/libs/hwui/FontRenderer.cpp b/libs/hwui/FontRenderer.cpp index d8297da..965e33a 100644 --- a/libs/hwui/FontRenderer.cpp +++ b/libs/hwui/FontRenderer.cpp @@ -23,6 +23,9 @@ #include <utils/Log.h> +#include "RenderScript.h" + +#include "utils/Timing.h" #include "Caches.h" #include "Debug.h" #include "FontRenderer.h" @@ -31,6 +34,9 @@ namespace android { namespace uirenderer { +// blur inputs smaller than this constant will bypass renderscript +#define RS_MIN_INPUT_CUTOFF 10000 + /////////////////////////////////////////////////////////////////////////////// // FontRenderer /////////////////////////////////////////////////////////////////////////////// @@ -544,18 +550,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; @@ -752,18 +762,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 diff --git a/libs/hwui/FontRenderer.h b/libs/hwui/FontRenderer.h index 3964bca..d0c44ef 100644 --- a/libs/hwui/FontRenderer.h +++ b/libs/hwui/FontRenderer.h @@ -31,6 +31,12 @@ #include "Matrix.h" #include "Properties.h" +namespace RSC { + class Element; + class RS; + class ScriptIntrinsicBlur; +} + namespace android { namespace uirenderer { @@ -178,13 +184,19 @@ private: Vector<uint32_t> mDrawCounts; Vector<CacheTexture*> mDrawCacheTextures; - /** We should consider multi-threading this code or using Renderscript **/ + // RS constructs + sp<RSC::RS> mRs; + sp<const RSC::Element> mRsElement; + 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); - static void blurImage(uint8_t* image, int32_t width, int32_t height, int32_t radius); + + // the input image handle may have its pointer replaced (to avoid copies) + void blurImage(uint8_t** image, int32_t width, int32_t height, int32_t radius); }; }; // namespace uirenderer diff --git a/libs/hwui/TextDropShadowCache.cpp b/libs/hwui/TextDropShadowCache.cpp index 9c7a5ab..db7bd48 100644 --- a/libs/hwui/TextDropShadowCache.cpp +++ b/libs/hwui/TextDropShadowCache.cpp @@ -222,7 +222,7 @@ ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32 } // Cleanup shadow - delete[] shadow.image; + delete shadow.image; } return texture; diff --git a/libs/hwui/utils/Timing.h b/libs/hwui/utils/Timing.h new file mode 100644 index 0000000..eced987 --- /dev/null +++ b/libs/hwui/utils/Timing.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2013 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_TIMING_H +#define ANDROID_HWUI_TIMING_H + +#include <sys/time.h> + +#define TIME_METHOD() MethodTimer __method_timer(__func__) +class MethodTimer { +public: + MethodTimer(const char* name) + : mMethodName(name) { + gettimeofday(&mStart, NULL); + } + + ~MethodTimer() { + struct timeval stop; + gettimeofday(&stop, NULL); + long long elapsed = (stop.tv_sec * 1000000) - (mStart.tv_sec * 1000000) + + (stop.tv_usec - mStart.tv_usec); + ALOGD("%s took %.2fms", mMethodName, elapsed / 1000.0); + } +private: + const char* mMethodName; + struct timeval mStart; +}; + +#endif |