Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bce29d2a authored by Chris Craik's avatar Chris Craik Committed by Android (Google) Code Review
Browse files

Merge "Use RenderScript for large text blurs"

parents eff99182 3f76e65d
Loading
Loading
Loading
Loading
+8 −3
Original line number Diff line number Diff line
@@ -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 \
@@ -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

+48 −12
Original line number Diff line number Diff line
@@ -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,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
+14 −2
Original line number Diff line number Diff line
@@ -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
+1 −1
Original line number Diff line number Diff line
@@ -222,7 +222,7 @@ ShadowTexture* TextDropShadowCache::get(SkPaint* paint, const char* text, uint32
        }

        // Cleanup shadow
        delete[] shadow.image;
        delete shadow.image;
    }

    return texture;
+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