summaryrefslogtreecommitdiffstats
path: root/libs
diff options
context:
space:
mode:
authorChris Craik <ccraik@google.com>2012-11-14 16:11:10 -0800
committerChris Craik <ccraik@google.com>2013-02-12 17:45:28 -0800
commit3f76e65d251ead65fe8ff98e3bd4c7623fbaac07 (patch)
treeb8dfc636012f670aba6a348340ae12770ab63372 /libs
parentd04892d207d50378356feef181ac4e4eff9652d7 (diff)
downloadframeworks_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.mk11
-rw-r--r--libs/hwui/FontRenderer.cpp60
-rw-r--r--libs/hwui/FontRenderer.h16
-rw-r--r--libs/hwui/TextDropShadowCache.cpp2
-rw-r--r--libs/hwui/utils/Timing.h42
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