summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Nader Jawad <njawad@google.com> 2020-08-17 17:15:54 -0700
committer Nader Jawad <njawad@google.com> 2020-08-19 13:49:50 -0700
commit322cb9c4e8256b36123277eb072ee9050298d211 (patch)
tree9dc2ee58b55d061cbe5340532380d1267e95d2c8
parentfc42a99ea5712883c9872d34a523d972c26c9d6f (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.txt4
-rw-r--r--graphics/java/android/graphics/BlurShader.java65
-rw-r--r--libs/hwui/Android.bp1
-rw-r--r--libs/hwui/jni/Shader.cpp23
-rw-r--r--libs/hwui/shader/BlurShader.cpp38
-rw-r--r--libs/hwui/shader/BlurShader.h42
-rw-r--r--libs/hwui/shader/Shader.h4
-rw-r--r--non-updatable-api/current.txt4
-rw-r--r--tests/HwAccelerationTest/AndroidManifest.xml9
-rw-r--r--tests/HwAccelerationTest/src/com/android/test/hwui/BlurActivity.java110
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);
+ }
+ }
+}