Loading libs/hwui/Android.mk +8 −3 Original line number Diff line number Diff line Loading @@ -38,6 +38,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 \ Loading @@ -46,11 +48,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 Loading libs/hwui/FontRenderer.cpp +48 −12 Original line number Diff line number Diff line Loading @@ -23,6 +23,9 @@ #include <utils/Log.h> #include "RenderScript.h" #include "utils/Timing.h" #include "Caches.h" #include "Debug.h" #include "FontRenderer.h" Loading @@ -31,6 +34,9 @@ namespace android { namespace uirenderer { // blur inputs smaller than this constant will bypass renderscript #define RS_MIN_INPUT_CUTOFF 10000 /////////////////////////////////////////////////////////////////////////////// // FontRenderer /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -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; Loading Loading @@ -752,19 +762,45 @@ void FontRenderer::verticalBlur(float* weights, int32_t radius, } } void FontRenderer::blurImage(uint8_t *image, int32_t width, int32_t height, 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); uint8_t* scratch = new uint8_t[width * height]; horizontalBlur(gaussian, radius, image, scratch, width, height); verticalBlur(gaussian, radius, scratch, image, 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); } 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); mRsScript->setRadius(radius); mRsScript->blur(ain, aout); // replace the original image's pointer, avoiding a copy back to the original buffer delete *image; *image = outImage; } }; // namespace uirenderer }; // namespace android libs/hwui/FontRenderer.h +14 −2 Original line number Diff line number Diff line Loading @@ -31,6 +31,12 @@ #include "Matrix.h" #include "Properties.h" namespace RSC { class Element; class RS; class ScriptIntrinsicBlur; } namespace android { namespace uirenderer { Loading Loading @@ -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 Loading libs/hwui/TextDropShadowCache.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -222,7 +222,7 @@ ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32 } // Cleanup shadow delete[] shadow.image; delete shadow.image; } return texture; Loading libs/hwui/utils/Timing.h 0 → 100644 +42 −0 Original line number Diff line number Diff line /* * 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 Loading
libs/hwui/Android.mk +8 −3 Original line number Diff line number Diff line Loading @@ -38,6 +38,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 \ Loading @@ -46,11 +48,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 Loading
libs/hwui/FontRenderer.cpp +48 −12 Original line number Diff line number Diff line Loading @@ -23,6 +23,9 @@ #include <utils/Log.h> #include "RenderScript.h" #include "utils/Timing.h" #include "Caches.h" #include "Debug.h" #include "FontRenderer.h" Loading @@ -31,6 +34,9 @@ namespace android { namespace uirenderer { // blur inputs smaller than this constant will bypass renderscript #define RS_MIN_INPUT_CUTOFF 10000 /////////////////////////////////////////////////////////////////////////////// // FontRenderer /////////////////////////////////////////////////////////////////////////////// Loading Loading @@ -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; Loading Loading @@ -752,19 +762,45 @@ void FontRenderer::verticalBlur(float* weights, int32_t radius, } } void FontRenderer::blurImage(uint8_t *image, int32_t width, int32_t height, 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); uint8_t* scratch = new uint8_t[width * height]; horizontalBlur(gaussian, radius, image, scratch, width, height); verticalBlur(gaussian, radius, scratch, image, 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); } 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); mRsScript->setRadius(radius); mRsScript->blur(ain, aout); // replace the original image's pointer, avoiding a copy back to the original buffer delete *image; *image = outImage; } }; // namespace uirenderer }; // namespace android
libs/hwui/FontRenderer.h +14 −2 Original line number Diff line number Diff line Loading @@ -31,6 +31,12 @@ #include "Matrix.h" #include "Properties.h" namespace RSC { class Element; class RS; class ScriptIntrinsicBlur; } namespace android { namespace uirenderer { Loading Loading @@ -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 Loading
libs/hwui/TextDropShadowCache.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -222,7 +222,7 @@ ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32 } // Cleanup shadow delete[] shadow.image; delete shadow.image; } return texture; Loading
libs/hwui/utils/Timing.h 0 → 100644 +42 −0 Original line number Diff line number Diff line /* * 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