diff options
author | 2020-08-17 17:15:54 -0700 | |
---|---|---|
committer | 2020-08-19 13:49:50 -0700 | |
commit | 322cb9c4e8256b36123277eb072ee9050298d211 (patch) | |
tree | 9dc2ee58b55d061cbe5340532380d1267e95d2c8 | |
parent | fc42a99ea5712883c9872d34a523d972c26c9d6f (diff) |
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
-rw-r--r-- | api/current.txt | 4 | ||||
-rw-r--r-- | graphics/java/android/graphics/BlurShader.java | 65 | ||||
-rw-r--r-- | libs/hwui/Android.bp | 1 | ||||
-rw-r--r-- | libs/hwui/jni/Shader.cpp | 23 | ||||
-rw-r--r-- | libs/hwui/shader/BlurShader.cpp | 38 | ||||
-rw-r--r-- | libs/hwui/shader/BlurShader.h | 42 | ||||
-rw-r--r-- | libs/hwui/shader/Shader.h | 4 | ||||
-rw-r--r-- | non-updatable-api/current.txt | 4 | ||||
-rw-r--r-- | tests/HwAccelerationTest/AndroidManifest.xml | 9 | ||||
-rw-r--r-- | tests/HwAccelerationTest/src/com/android/test/hwui/BlurActivity.java | 110 |
10 files changed, 299 insertions, 1 deletions
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<const SkMatrix*>(matrixPtr); + auto* inputShader = reinterpret_cast<Shader*>(shaderHandle); + + auto* blurShader = new BlurShader( + sigmaX, + sigmaY, + inputShader, + matrix + ); + return reinterpret_cast<jlong>(blurShader); +} + +/////////////////////////////////////////////////////////////////////////////////////////////// + static jlong RuntimeShader_create(JNIEnv* env, jobject, jlong shaderFactory, jlong matrixPtr, jbyteArray inputs, jlong colorSpaceHandle, jboolean isOpaque) { auto* effect = reinterpret_cast<SkRuntimeEffect*>(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<SkImageFilter> 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<SkImageFilter> makeSkImageFilter() override; +private: + sk_sp<SkImageFilter> 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 @@ </intent-filter> </activity> + <activity android:name="BlurActivity" + android:label="Shaders/Blur" + android:exported="true"> + <intent-filter> + <action android:name="android.intent.action.MAIN"/> + <category android:name="com.android.test.hwui.TEST"/> + </intent-filter> + </activity> + <activity android:name="TextActivity" android:label="Text/Simple Text" android:theme="@android:style/Theme.NoTitleBar" diff --git a/tests/HwAccelerationTest/src/com/android/test/hwui/BlurActivity.java b/tests/HwAccelerationTest/src/com/android/test/hwui/BlurActivity.java new file mode 100644 index 000000000000..033fb0ec35d2 --- /dev/null +++ b/tests/HwAccelerationTest/src/com/android/test/hwui/BlurActivity.java @@ -0,0 +1,110 @@ +/* + * 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 com.android.test.hwui; + +import android.app.Activity; +import android.content.Context; +import android.graphics.BlurShader; +import android.graphics.Canvas; +import android.graphics.Color; +import android.graphics.LinearGradient; +import android.graphics.Paint; +import android.graphics.Shader; +import android.os.Bundle; +import android.view.Gravity; +import android.view.View; +import android.widget.LinearLayout; + +@SuppressWarnings({"UnusedDeclaration"}) +public class BlurActivity extends Activity { + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + LinearLayout layout = new LinearLayout(this); + layout.setClipChildren(false); + layout.setGravity(Gravity.CENTER); + layout.setOrientation(LinearLayout.VERTICAL); + + + LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(500, 500); + params.bottomMargin = 100; + + layout.addView(new BlurGradientView(this), params); + layout.addView(new BlurView(this), params); + + setContentView(layout); + } + + public static class BlurGradientView extends View { + private BlurShader mBlurShader = null; + private Paint mPaint; + + public BlurGradientView(Context c) { + super(c); + } + + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + if (changed || mBlurShader == null) { + LinearGradient gradient = new LinearGradient( + 0f, + 0f, + right - left, + bottom - top, + Color.CYAN, + Color.YELLOW, + Shader.TileMode.CLAMP + ); + mBlurShader = new BlurShader(30f, 40f, gradient); + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setShader(mBlurShader); + } + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint); + } + } + + public static class BlurView extends View { + + private final BlurShader mBlurShader; + private final Paint mPaint; + + public BlurView(Context c) { + super(c); + + mBlurShader = new BlurShader(20f, 20f, null); + mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); + mPaint.setShader(mBlurShader); + } + + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + + mPaint.setColor(Color.BLUE); + canvas.drawRect(0, 0, getWidth(), getHeight(), mPaint); + + mPaint.setColor(Color.RED); + canvas.drawCircle(getWidth() / 2f, getHeight() / 2f, 50f, mPaint); + } + } +} |