From 322cb9c4e8256b36123277eb072ee9050298d211 Mon Sep 17 00:00:00 2001 From: Nader Jawad Date: Mon, 17 Aug 2020 17:15:54 -0700 Subject: [PATCH] Added BlurShader API Created BlurShader framework API along with native implementation as an implementation of the Shader wrapper that maps to either SkShader or SkImageFilter Bug: 143468037 Test: Added CTS test to verify BlurShader Change-Id: I05fcf7ba79e9d552f8b0738f7382f7826cd94e21 --- api/current.txt | 4 + .../java/android/graphics/BlurShader.java | 65 +++++++++++ libs/hwui/Android.bp | 1 + libs/hwui/jni/Shader.cpp | 23 ++++ libs/hwui/shader/BlurShader.cpp | 38 ++++++ libs/hwui/shader/BlurShader.h | 42 +++++++ libs/hwui/shader/Shader.h | 4 +- non-updatable-api/current.txt | 4 + tests/HwAccelerationTest/AndroidManifest.xml | 9 ++ .../com/android/test/hwui/BlurActivity.java | 110 ++++++++++++++++++ 10 files changed, 299 insertions(+), 1 deletion(-) create mode 100644 graphics/java/android/graphics/BlurShader.java create mode 100644 libs/hwui/shader/BlurShader.cpp create mode 100644 libs/hwui/shader/BlurShader.h create mode 100644 tests/HwAccelerationTest/src/com/android/test/hwui/BlurActivity.java diff --git a/api/current.txt b/api/current.txt index 532c3d938334..f037d2707d3c 100644 --- a/api/current.txt +++ b/api/current.txt @@ -14250,6 +14250,10 @@ package android.graphics { enum_constant public static final android.graphics.BlurMaskFilter.Blur SOLID; } + public final class BlurShader extends android.graphics.Shader { + ctor public BlurShader(float, float, @Nullable android.graphics.Shader); + } + public class Camera { ctor public Camera(); method public void applyToCanvas(android.graphics.Canvas); diff --git a/graphics/java/android/graphics/BlurShader.java b/graphics/java/android/graphics/BlurShader.java new file mode 100644 index 000000000000..779a89051060 --- /dev/null +++ b/graphics/java/android/graphics/BlurShader.java @@ -0,0 +1,65 @@ +/* + * Copyright (C) 2020 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. + */ + +package android.graphics; + +import android.annotation.Nullable; + +/** + * A subclass of shader that blurs input from another {@link android.graphics.Shader} instance + * or all the drawing commands with the {@link android.graphics.Paint} that this shader is + * attached to. + */ +public final class BlurShader extends Shader { + + private final float mRadiusX; + private final float mRadiusY; + private final Shader mInputShader; + + private long mNativeInputShader = 0; + + /** + * Create a {@link BlurShader} that blurs the contents of the optional input shader + * with the specified radius along the x and y axis. If no input shader is provided + * then all drawing commands issued with a {@link android.graphics.Paint} that this + * shader is installed in will be blurred + * @param radiusX Radius of blur along the X axis + * @param radiusY Radius of blur along the Y axis + * @param inputShader Input shader that provides the content to be blurred + */ + public BlurShader(float radiusX, float radiusY, @Nullable Shader inputShader) { + mRadiusX = radiusX; + mRadiusY = radiusY; + mInputShader = inputShader; + } + + /** @hide **/ + @Override + protected long createNativeInstance(long nativeMatrix) { + mNativeInputShader = mInputShader != null ? mInputShader.getNativeInstance() : 0; + return nativeCreate(nativeMatrix, mRadiusX, mRadiusY, mNativeInputShader); + } + + /** @hide **/ + @Override + protected boolean shouldDiscardNativeInstance() { + long currentNativeInstance = mInputShader != null ? mInputShader.getNativeInstance() : 0; + return mNativeInputShader != currentNativeInstance; + } + + private static native long nativeCreate(long nativeMatrix, float radiusX, float radiusY, + long inputShader); +} diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp index 0b13754271b9..90d2537d97a8 100644 --- a/libs/hwui/Android.bp +++ b/libs/hwui/Android.bp @@ -464,6 +464,7 @@ cc_defaults { "RootRenderNode.cpp", "shader/Shader.cpp", "shader/BitmapShader.cpp", + "shader/BlurShader.cpp", "shader/ComposeShader.cpp", "shader/LinearGradientShader.cpp", "shader/RadialGradientShader.cpp", diff --git a/libs/hwui/jni/Shader.cpp b/libs/hwui/jni/Shader.cpp index 9b1972ed664f..7cb77233846f 100644 --- a/libs/hwui/jni/Shader.cpp +++ b/libs/hwui/jni/Shader.cpp @@ -7,6 +7,7 @@ #include "include/effects/SkRuntimeEffect.h" #include "shader/Shader.h" #include "shader/BitmapShader.h" +#include "shader/BlurShader.h" #include "shader/ComposeShader.h" #include "shader/LinearGradientShader.h" #include "shader/RadialGradientShader.h" @@ -222,6 +223,22 @@ static jlong ComposeShader_create(JNIEnv* env, jobject o, jlong matrixPtr, /////////////////////////////////////////////////////////////////////////////////////////////// +static jlong BlurShader_create(JNIEnv* env , jobject o, jlong matrixPtr, jfloat sigmaX, + jfloat sigmaY, jlong shaderHandle) { + auto* matrix = reinterpret_cast(matrixPtr); + auto* inputShader = reinterpret_cast(shaderHandle); + + auto* blurShader = new BlurShader( + sigmaX, + sigmaY, + inputShader, + matrix + ); + return reinterpret_cast(blurShader); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// + static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderFactory, jlong matrixPtr, jbyteArray inputs, jlong colorSpaceHandle, jboolean isOpaque) { auto* effect = reinterpret_cast(shaderFactory); @@ -273,6 +290,10 @@ static const JNINativeMethod gBitmapShaderMethods[] = { { "nativeCreate", "(JJII)J", (void*)BitmapShader_constructor }, }; +static const JNINativeMethod gBlurShaderMethods[] = { + { "nativeCreate", "(JFFJ)J", (void*)BlurShader_create } +}; + static const JNINativeMethod gLinearGradientMethods[] = { { "nativeCreate", "(JFFFF[J[FIJ)J", (void*)LinearGradient_create }, }; @@ -304,6 +325,8 @@ int register_android_graphics_Shader(JNIEnv* env) NELEM(gShaderMethods)); android::RegisterMethodsOrDie(env, "android/graphics/BitmapShader", gBitmapShaderMethods, NELEM(gBitmapShaderMethods)); + android::RegisterMethodsOrDie(env, "android/graphics/BlurShader", gBlurShaderMethods, + NELEM(gBlurShaderMethods)); android::RegisterMethodsOrDie(env, "android/graphics/LinearGradient", gLinearGradientMethods, NELEM(gLinearGradientMethods)); android::RegisterMethodsOrDie(env, "android/graphics/RadialGradient", gRadialGradientMethods, diff --git a/libs/hwui/shader/BlurShader.cpp b/libs/hwui/shader/BlurShader.cpp new file mode 100644 index 000000000000..4d18cdd27e4e --- /dev/null +++ b/libs/hwui/shader/BlurShader.cpp @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2020 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. + */ + +#include "BlurShader.h" +#include "SkImageFilters.h" +#include "SkRefCnt.h" +#include "utils/Blur.h" + +namespace android::uirenderer { +BlurShader::BlurShader(float radiusX, float radiusY, Shader* inputShader, const SkMatrix* matrix) + : Shader(matrix) + , skImageFilter( + SkImageFilters::Blur( + Blur::convertRadiusToSigma(radiusX), + Blur::convertRadiusToSigma(radiusY), + inputShader ? inputShader->asSkImageFilter() : nullptr) + ) { } + +sk_sp BlurShader::makeSkImageFilter() { + return skImageFilter; +} + +BlurShader::~BlurShader() {} + +} // namespace android::uirenderer \ No newline at end of file diff --git a/libs/hwui/shader/BlurShader.h b/libs/hwui/shader/BlurShader.h new file mode 100644 index 000000000000..9eb22bd11f4a --- /dev/null +++ b/libs/hwui/shader/BlurShader.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2020 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. + */ + +#pragma once +#include "Shader.h" + +namespace android::uirenderer { + +/** + * Shader implementation that blurs another Shader instance or the source bitmap + */ +class BlurShader : public Shader { +public: + /** + * Creates a BlurShader instance with the provided radius values to blur along the x and y + * axis accordingly. + * + * This will blur the contents of the provided input shader if it is non-null, otherwise + * the source bitmap will be blurred instead. + */ + BlurShader(float radiusX, float radiusY, Shader* inputShader, const SkMatrix* matrix); + ~BlurShader() override; +protected: + sk_sp makeSkImageFilter() override; +private: + sk_sp skImageFilter; +}; + +} // namespace android::uirenderer \ No newline at end of file diff --git a/libs/hwui/shader/Shader.h b/libs/hwui/shader/Shader.h index 3c0cdaae8253..6403e1147ded 100644 --- a/libs/hwui/shader/Shader.h +++ b/libs/hwui/shader/Shader.h @@ -32,7 +32,9 @@ namespace android::uirenderer { class Shader: public SkRefCnt { public: /** - * Creates a Shader instance with an optional transformation matrix + * Creates a Shader instance with an optional transformation matrix. The transformation matrix + * is copied internally and ownership is unchanged. It is the responsibility of the caller to + * deallocate it appropriately. * @param matrix Optional matrix to transform the underlying SkShader or SkImageFilter */ Shader(const SkMatrix* matrix); diff --git a/non-updatable-api/current.txt b/non-updatable-api/current.txt index f9d0d14c7335..59668697c4fe 100644 --- a/non-updatable-api/current.txt +++ b/non-updatable-api/current.txt @@ -14250,6 +14250,10 @@ package android.graphics { enum_constant public static final android.graphics.BlurMaskFilter.Blur SOLID; } + public final class BlurShader extends android.graphics.Shader { + ctor public BlurShader(float, float, @Nullable android.graphics.Shader); + } + public class Camera { ctor public Camera(); method public void applyToCanvas(android.graphics.Canvas); diff --git a/tests/HwAccelerationTest/AndroidManifest.xml b/tests/HwAccelerationTest/AndroidManifest.xml index 7790043859a0..05a59ef7fc72 100644 --- a/tests/HwAccelerationTest/AndroidManifest.xml +++ b/tests/HwAccelerationTest/AndroidManifest.xml @@ -744,6 +744,15 @@ + + + + + + +