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

Commit ef3da571 authored by Nader Jawad's avatar Nader Jawad Committed by Android (Google) Code Review
Browse files

Merge "Introduce more RenderEffect APIs"

parents e4cbd037 0081a9c6
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -15610,6 +15610,19 @@ package android.graphics {
    method public final boolean next(android.graphics.Rect);
  }
  public final class RenderEffect {
    method @NonNull public static android.graphics.RenderEffect createBitmapEffect(@NonNull android.graphics.Bitmap);
    method @NonNull public static android.graphics.RenderEffect createBitmapEffect(@NonNull android.graphics.Bitmap, @Nullable android.graphics.Rect, @NonNull android.graphics.Rect);
    method @NonNull public static android.graphics.RenderEffect createBlendModeEffect(@NonNull android.graphics.RenderEffect, @NonNull android.graphics.RenderEffect, @NonNull android.graphics.BlendMode);
    method @NonNull public static android.graphics.RenderEffect createBlurEffect(float, float, @NonNull android.graphics.RenderEffect, @NonNull android.graphics.Shader.TileMode);
    method @NonNull public static android.graphics.RenderEffect createBlurEffect(float, float, @NonNull android.graphics.Shader.TileMode);
    method @NonNull public static android.graphics.RenderEffect createChainEffect(@NonNull android.graphics.RenderEffect, @NonNull android.graphics.RenderEffect);
    method @NonNull public static android.graphics.RenderEffect createColorFilterEffect(@NonNull android.graphics.ColorFilter, @NonNull android.graphics.RenderEffect);
    method @NonNull public static android.graphics.RenderEffect createColorFilterEffect(@NonNull android.graphics.ColorFilter);
    method @NonNull public static android.graphics.RenderEffect createOffsetEffect(float, float);
    method @NonNull public static android.graphics.RenderEffect createOffsetEffect(float, float, @NonNull android.graphics.RenderEffect);
  }
  public final class RenderNode {
    ctor public RenderNode(@Nullable String);
    method @NonNull public android.graphics.RecordingCanvas beginRecording(int, int);
@@ -15669,6 +15682,7 @@ package android.graphics {
    method public boolean setPosition(@NonNull android.graphics.Rect);
    method public boolean setProjectBackwards(boolean);
    method public boolean setProjectionReceiver(boolean);
    method public void setRenderEffect(@Nullable android.graphics.RenderEffect);
    method public boolean setRotationX(float);
    method public boolean setRotationY(float);
    method public boolean setRotationZ(float);
+14 −0
Original line number Diff line number Diff line
@@ -15592,6 +15592,19 @@ package android.graphics {
    method public final boolean next(android.graphics.Rect);
  }
  public final class RenderEffect {
    method @NonNull public static android.graphics.RenderEffect createBitmapEffect(@NonNull android.graphics.Bitmap);
    method @NonNull public static android.graphics.RenderEffect createBitmapEffect(@NonNull android.graphics.Bitmap, @Nullable android.graphics.Rect, @NonNull android.graphics.Rect);
    method @NonNull public static android.graphics.RenderEffect createBlendModeEffect(@NonNull android.graphics.RenderEffect, @NonNull android.graphics.RenderEffect, @NonNull android.graphics.BlendMode);
    method @NonNull public static android.graphics.RenderEffect createBlurEffect(float, float, @NonNull android.graphics.RenderEffect, @NonNull android.graphics.Shader.TileMode);
    method @NonNull public static android.graphics.RenderEffect createBlurEffect(float, float, @NonNull android.graphics.Shader.TileMode);
    method @NonNull public static android.graphics.RenderEffect createChainEffect(@NonNull android.graphics.RenderEffect, @NonNull android.graphics.RenderEffect);
    method @NonNull public static android.graphics.RenderEffect createColorFilterEffect(@NonNull android.graphics.ColorFilter, @NonNull android.graphics.RenderEffect);
    method @NonNull public static android.graphics.RenderEffect createColorFilterEffect(@NonNull android.graphics.ColorFilter);
    method @NonNull public static android.graphics.RenderEffect createOffsetEffect(float, float);
    method @NonNull public static android.graphics.RenderEffect createOffsetEffect(float, float, @NonNull android.graphics.RenderEffect);
  }
  public final class RenderNode {
    ctor public RenderNode(@Nullable String);
    method @NonNull public android.graphics.RecordingCanvas beginRecording(int, int);
@@ -15651,6 +15664,7 @@ package android.graphics {
    method public boolean setPosition(@NonNull android.graphics.Rect);
    method public boolean setProjectBackwards(boolean);
    method public boolean setProjectionReceiver(boolean);
    method public void setRenderEffect(@Nullable android.graphics.RenderEffect);
    method public boolean setRotationX(float);
    method public boolean setRotationY(float);
    method public boolean setRotationZ(float);
+158 −3
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.graphics;

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.Shader.TileMode;

import libcore.util.NativeAllocationRegistry;
@@ -24,8 +25,6 @@ import libcore.util.NativeAllocationRegistry;
/**
 * Intermediate rendering step used to render drawing commands with a corresponding
 * visual effect
 *
 * @hide
 */
public final class RenderEffect {

@@ -99,7 +98,7 @@ public final class RenderEffect {
    /**
     * Create a {@link RenderEffect} that blurs the contents of the
     * {@link android.graphics.RenderNode} that this RenderEffect is installed on with the
     * specified radius along hte x and y axis.
     * specified radius along the x and y axis.
     * @param radiusX Radius of blur along the X axis
     * @param radiusY Radius of blur along the Y axis
     * @param edgeTreatment Policy for how to blur content near edges of the blur kernel
@@ -120,6 +119,156 @@ public final class RenderEffect {
            );
    }

    /**
     * Create a {@link RenderEffect} that renders the contents of the input {@link Bitmap}.
     * This is useful to create an input for other {@link RenderEffect} types such as
     * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, TileMode)} or
     * {@link RenderEffect#createColorFilterEffect(ColorFilter, RenderEffect)}
     *
     * @param bitmap The source bitmap to be rendered by the created {@link RenderEffect}
     */
    @NonNull
    public static RenderEffect createBitmapEffect(@NonNull Bitmap bitmap) {
        float right = bitmap.getWidth();
        float bottom = bitmap.getHeight();
        return new RenderEffect(
                nativeCreateBitmapEffect(
                        bitmap.getNativeInstance(),
                        0f,
                        0f,
                        right,
                        bottom,
                        0f,
                        0f,
                        right,
                        bottom
                )
        );
    }

    /**
     * Create a {@link RenderEffect} that renders the contents of the input {@link Bitmap}.
     * This is useful to create an input for other {@link RenderEffect} types such as
     * {@link RenderEffect#createBlurEffect(float, float, RenderEffect, TileMode)} or
     * {@link RenderEffect#createColorFilterEffect(ColorFilter, RenderEffect)}
     *
     * @param bitmap The source bitmap to be rendered by the created {@link RenderEffect}
     * @param src Optional subset of the bitmap to be part of the rendered output. If null
     *            is provided, the entire bitmap bounds are used.
     * @param dst Bounds of the destination which the bitmap is translated and scaled to be
     *            drawn into
     */
    @NonNull
    public static RenderEffect createBitmapEffect(
            @NonNull Bitmap bitmap,
            @Nullable Rect src,
            @NonNull Rect dst
    ) {
        long bitmapHandle = bitmap.getNativeInstance();
        int left = src == null ? 0 : src.left;
        int top = src == null ? 0 : src.top;
        int right = src == null ? bitmap.getWidth() : src.right;
        int bottom = src == null ? bitmap.getHeight() : src.bottom;
        return new RenderEffect(
                nativeCreateBitmapEffect(
                        bitmapHandle,
                        left,
                        top,
                        right,
                        bottom,
                        dst.left,
                        dst.top,
                        dst.right,
                        dst.bottom
                )
        );
    }

    /**
     * Create a filter that applies the color filter to the provided RenderEffect
     *
     * @param colorFilter ColorFilter applied to the content in the input RenderEffect
     * @param renderEffect Source to be transformed by the specified {@link ColorFilter}
     */
    @NonNull
    public static RenderEffect createColorFilterEffect(
            @NonNull ColorFilter colorFilter,
            @NonNull RenderEffect renderEffect
    ) {
        return new RenderEffect(
                nativeCreateColorFilterEffect(
                    colorFilter.getNativeInstance(),
                    renderEffect.getNativeInstance()
                )
            );
    }

    /**
     * Create a filter that applies the color filter to the contents of the
     * {@link android.graphics.RenderNode} that this RenderEffect is installed on
     * @param colorFilter ColorFilter applied to the content in the input RenderEffect
     */
    @NonNull
    public static RenderEffect createColorFilterEffect(@NonNull ColorFilter colorFilter) {
        return new RenderEffect(
                nativeCreateColorFilterEffect(
                        colorFilter.getNativeInstance(),
                        0
                )
        );
    }

    /**
     * {@link RenderEffect} that is a composition of 2 other {@link RenderEffect} instances
     * combined by the specified {@link BlendMode}
     *
     * @param dst The Dst pixels used in blending, if null the source bitmap is used.
     * @param src The Src pixels used in blending, if null the source bitmap is use
     * @param blendMode The {@link BlendMode} to be used to combine colors from the two
     *                  {@link RenderEffect}s
     */
    @NonNull
    public static RenderEffect createBlendModeEffect(
            @NonNull RenderEffect dst,
            @NonNull RenderEffect src,
            @NonNull BlendMode blendMode
    ) {
        return new RenderEffect(
                nativeCreateBlendModeEffect(
                        dst.getNativeInstance(),
                        src.getNativeInstance(),
                        blendMode.getXfermode().porterDuffMode
                )
        );
    }

    /**
     * Create a filter that composes 'inner' with 'outer', such that the results of 'inner' are
     * treated as the source bitmap passed to 'outer', i.e.
     *
     * result = outer(inner(source)).
     *
     * Consumers should favor explicit chaining of {@link RenderEffect} instances at creation time
     * rather than using chain effect. Chain effects are useful for situations where the input or
     * output are provided from elsewhere and the input or output {@link RenderEffect} need to be
     * changed.
     *
     * @param outer {@link RenderEffect} that consumes the output of {@param inner} as its input
     * @param inner {@link RenderEffect} that is consumed as input by {@param outer}
     */
    @NonNull
    public static RenderEffect createChainEffect(
            @NonNull RenderEffect outer,
            @NonNull RenderEffect inner
    ) {
        return new RenderEffect(
                nativeCreateChainEffect(
                    outer.getNativeInstance(),
                    inner.getNativeInstance()
                )
            );
    }

    private final long mNativeRenderEffect;

    /* only constructed from static factory methods */
@@ -141,5 +290,11 @@ public final class RenderEffect {
            float offsetX, float offsetY, long nativeInput);
    private static native long nativeCreateBlurEffect(
            float radiusX, float radiusY, long nativeInput, int edgeTreatment);
    private static native long nativeCreateBitmapEffect(
            long bitmapHandle, float srcLeft, float srcTop, float srcRight, float srcBottom,
            float dstLeft, float dstTop, float dstRight, float dstBottom);
    private static native long nativeCreateColorFilterEffect(long colorFilter, long nativeInput);
    private static native long nativeCreateBlendModeEffect(long dst, long src, int blendmode);
    private static native long nativeCreateChainEffect(long outer, long inner);
    private static native long nativeGetFinalizer();
}
+0 −2
Original line number Diff line number Diff line
@@ -858,8 +858,6 @@ public final class RenderNode {
     * be blurred when this RenderNode is drawn into the destination.
     * @param renderEffect to be applied to the RenderNode. Passing null clears all previously
     *          configured RenderEffects
     *
     * @hide
     */
    public void setRenderEffect(@Nullable RenderEffect renderEffect) {
        nSetRenderEffect(mNativeRenderNode,
+72 −1
Original line number Diff line number Diff line
@@ -48,6 +48,73 @@ static jlong createBlurEffect(JNIEnv* env , jobject, jfloat radiusX,
    return reinterpret_cast<jlong>(blurFilter.release());
}

static jlong createBitmapEffect(
    JNIEnv* env,
    jobject,
    jlong bitmapHandle,
    jfloat srcLeft,
    jfloat srcTop,
    jfloat srcRight,
    jfloat srcBottom,
    jfloat dstLeft,
    jfloat dstTop,
    jfloat dstRight,
    jfloat dstBottom
) {
    sk_sp<SkImage> image = android::bitmap::toBitmap(bitmapHandle).makeImage();
    SkRect srcRect = SkRect::MakeLTRB(srcLeft, srcTop, srcRight, srcBottom);
    SkRect dstRect = SkRect::MakeLTRB(dstLeft, dstTop, dstRight, dstBottom);
    sk_sp<SkImageFilter> bitmapFilter =
        SkImageFilters::Image(image, srcRect, dstRect, kLow_SkFilterQuality);
    return reinterpret_cast<jlong>(bitmapFilter.release());
}

static jlong createColorFilterEffect(
    JNIEnv* env,
    jobject,
    jlong colorFilterHandle,
    jlong inputFilterHandle
) {
    auto* colorFilter = reinterpret_cast<const SkColorFilter*>(colorFilterHandle);
    auto* inputFilter = reinterpret_cast<const SkImageFilter*>(inputFilterHandle);
    sk_sp<SkImageFilter> colorFilterImageFilter = SkImageFilters::ColorFilter(
            sk_ref_sp(colorFilter), sk_ref_sp(inputFilter), nullptr);
   return reinterpret_cast<jlong>(colorFilterImageFilter.release());
}

static jlong createBlendModeEffect(
    JNIEnv* env,
    jobject,
    jlong backgroundImageFilterHandle,
    jlong foregroundImageFilterHandle,
    jint blendmodeHandle
) {
    auto* backgroundFilter = reinterpret_cast<const SkImageFilter*>(backgroundImageFilterHandle);
    auto* foregroundFilter = reinterpret_cast<const SkImageFilter*>(foregroundImageFilterHandle);
    SkBlendMode blendMode = static_cast<SkBlendMode>(blendmodeHandle);
    sk_sp<SkImageFilter> xfermodeFilter = SkImageFilters::Blend(
            blendMode,
            sk_ref_sp(backgroundFilter),
            sk_ref_sp(foregroundFilter)
    );
    return reinterpret_cast<jlong>(xfermodeFilter.release());
}

static jlong createChainEffect(
    JNIEnv* env,
    jobject,
    jlong outerFilterHandle,
    jlong innerFilterHandle
) {
    auto* outerImageFilter = reinterpret_cast<const SkImageFilter*>(outerFilterHandle);
    auto* innerImageFilter = reinterpret_cast<const SkImageFilter*>(innerFilterHandle);
    sk_sp<SkImageFilter> composeFilter = SkImageFilters::Compose(
        sk_ref_sp(outerImageFilter),
        sk_ref_sp(innerImageFilter)
    );
    return reinterpret_cast<jlong>(composeFilter.release());
}

static void RenderEffect_safeUnref(SkImageFilter* filter) {
    SkSafeUnref(filter);
}
@@ -59,7 +126,11 @@ static jlong getRenderEffectFinalizer(JNIEnv*, jobject) {
static const JNINativeMethod gRenderEffectMethods[] = {
    {"nativeGetFinalizer", "()J", (void*)getRenderEffectFinalizer},
    {"nativeCreateOffsetEffect", "(FFJ)J", (void*)createOffsetEffect},
    {"nativeCreateBlurEffect", "(FFJI)J", (void*)createBlurEffect}
    {"nativeCreateBlurEffect", "(FFJI)J", (void*)createBlurEffect},
    {"nativeCreateBitmapEffect", "(JFFFFFFFF)J", (void*)createBitmapEffect},
    {"nativeCreateColorFilterEffect", "(JJ)J", (void*)createColorFilterEffect},
    {"nativeCreateBlendModeEffect", "(JJI)J", (void*)createBlendModeEffect},
    {"nativeCreateChainEffect", "(JJ)J", (void*)createChainEffect}
};

int register_android_graphics_RenderEffect(JNIEnv* env) {