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

Commit 0bfc89b9 authored by chaviw's avatar chaviw
Browse files

Use BLAST layer for screen rotation, surface freezer, and organizer

Use a BLAST layer when taking a screenshot and using it for an
animation. This is simple enough to do with BLAST instead of a buffer
queue since we can just submit a single buffer and it will be presented.

Added new methods in SurfaceControl to support sending a buffer and
colorSpace.

Test: ScreenRotation
Test: Freeform animation
Bug: 170765639
Change-Id: I72081ab833d76fac40667eed52cf16798112a5b6
parent 266e0913
Loading
Loading
Loading
Loading
+30 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import android.annotation.TestApi;
import android.compat.annotation.UnsupportedAppUsage;
import android.graphics.Bitmap;
import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.PixelFormat;
import android.graphics.Point;
@@ -189,6 +190,10 @@ public final class SurfaceControl implements Parcelable {
            long barrierObject, long frame);
    private static native void nativeReparent(long transactionObj, long nativeObject,
            long newParentNativeObject);
    private static native void nativeSetBuffer(long transactionObj, long nativeObject,
            GraphicBuffer buffer);
    private static native void nativeSetColorSpace(long transactionObj, long nativeObject,
            int colorSpace);

    private static native void nativeOverrideHdrTypes(IBinder displayToken, int[] modes);

@@ -3365,6 +3370,31 @@ public final class SurfaceControl implements Parcelable {
            return this;
        }

        /**
         * Set a buffer for a SurfaceControl. This can only be used for SurfaceControls that were
         * created as type {@link #FX_SURFACE_BLAST}
         *
         * @hide
         */
        public Transaction setBuffer(SurfaceControl sc, GraphicBuffer buffer) {
            checkPreconditions(sc);
            nativeSetBuffer(mNativeObject, sc.mNativeObject, buffer);
            return this;
        }

        /**
         * Set the color space for the SurfaceControl. The supported color spaces are SRGB
         * and Display P3, other color spaces will be treated as SRGB. This can only be used for
         * SurfaceControls that were created as type {@link #FX_SURFACE_BLAST}
         *
         * @hide
         */
        public Transaction setColorSpace(SurfaceControl sc, ColorSpace colorSpace) {
            checkPreconditions(sc);
            nativeSetColorSpace(mNativeObject, sc.mNativeObject, colorSpace.getId());
            return this;
        }

         /**
         * Merge the other transaction into this transaction, clearing the
         * other transaction as if it had been applied.
+31 −0
Original line number Diff line number Diff line
@@ -30,6 +30,7 @@
#include <android/hardware/display/IDeviceProductInfoConstants.h>
#include <android/os/IInputConstants.h>
#include <android_runtime/AndroidRuntime.h>
#include <android_runtime/android_graphics_GraphicBuffer.h>
#include <android_runtime/android_hardware_HardwareBuffer.h>
#include <android_runtime/android_view_Surface.h>
#include <android_runtime/android_view_SurfaceSession.h>
@@ -253,6 +254,15 @@ constexpr jint fromDataspaceToNamedColorSpaceValue(const ui::Dataspace dataspace
    }
}

constexpr ui::Dataspace fromNamedColorSpaceValueToDataspace(const jint colorSpace) {
    switch (colorSpace) {
        case JNamedColorSpace::DISPLAY_P3:
            return ui::Dataspace::DISPLAY_P3;
        default:
            return ui::Dataspace::V0_SRGB;
    }
}

constexpr ui::Dataspace pickDataspaceFromColorMode(const ui::ColorMode colorMode) {
    switch (colorMode) {
        case ui::ColorMode::DISPLAY_P3:
@@ -553,6 +563,23 @@ static void nativeSetGeometry(JNIEnv* env, jclass clazz, jlong transactionObj, j
    transaction->setGeometry(ctrl, source, dst, orientation);
}

static void nativeSetBuffer(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject,
                            jobject bufferObject) {
    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
    sp<GraphicBuffer> buffer(
            android_graphics_GraphicBuffer_getNativeGraphicsBuffer(env, bufferObject));
    transaction->setBuffer(ctrl, buffer);
}

static void nativeSetColorSpace(JNIEnv* env, jclass clazz, jlong transactionObj, jlong nativeObject,
                                jint colorSpace) {
    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
    SurfaceControl* const ctrl = reinterpret_cast<SurfaceControl*>(nativeObject);
    ui::Dataspace dataspace = fromNamedColorSpaceValueToDataspace(colorSpace);
    transaction->setDataspace(ctrl, dataspace);
}

static void nativeSetBlurRegions(JNIEnv* env, jclass clazz, jlong transactionObj,
                                 jlong nativeObject, jobjectArray regions, jint regionsLength) {
    auto transaction = reinterpret_cast<SurfaceComposerClient::Transaction*>(transactionObj);
@@ -1880,6 +1907,10 @@ static const JNINativeMethod sSurfaceControlMethods[] = {
            (void*)nativeGetDisplayedContentSample },
    {"nativeSetGeometry", "(JJLandroid/graphics/Rect;Landroid/graphics/Rect;J)V",
            (void*)nativeSetGeometry },
    {"nativeSetBuffer", "(JJLandroid/graphics/GraphicBuffer;)V",
            (void*)nativeSetBuffer },
    {"nativeSetColorSpace", "(JJI)V",
            (void*)nativeSetColorSpace },
    {"nativeSyncInputWindows", "(J)V",
            (void*)nativeSyncInputWindows },
    {"nativeGetDisplayBrightnessSupport", "(Landroid/os/IBinder;)Z",
+15 −16
Original line number Diff line number Diff line
@@ -36,9 +36,11 @@ import static com.android.server.wm.WindowStateAnimator.WINDOW_FREEZE_LAYER;
import android.animation.ArgbEvaluator;
import android.content.Context;
import android.graphics.Color;
import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
import android.os.Trace;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
@@ -210,9 +212,9 @@ class ScreenRotationAnimation {
            String name = "RotationLayer";
            mScreenshotLayer = displayContent.makeOverlay()
                    .setName(name)
                    .setBufferSize(mWidth, mHeight)
                    .setSecure(isSecure)
                    .setCallsite("ScreenRotationAnimation")
                    .setBLASTLayer()
                    .build();
            // This is the way to tell the input system to exclude this surface from occlusion
            // detection since we don't have a window for it. We do this because this window is
@@ -225,32 +227,29 @@ class ScreenRotationAnimation {
                    .setCallsite("ScreenRotationAnimation")
                    .build();

            final Surface surface = mService.mSurfaceFactory.get();
            // In case display bounds change, screenshot buffer and surface may mismatch so
            // set a scaling mode.
            surface.copyFrom(mScreenshotLayer);
            surface.setScalingMode(Surface.SCALING_MODE_SCALE_TO_WINDOW);

            HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
            Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                    "ScreenRotationAnimation#getMedianBorderLuma");
            mStartLuma = RotationAnimationUtils.getMedianBorderLuma(
                    screenshotBuffer.getHardwareBuffer(), screenshotBuffer.getColorSpace());
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
            try {
                surface.attachAndQueueBufferWithColorSpace(screenshotBuffer.getHardwareBuffer(),
            mStartLuma = RotationAnimationUtils.getMedianBorderLuma(hardwareBuffer,
                    screenshotBuffer.getColorSpace());
            } catch (RuntimeException e) {
                Slog.w(TAG, "Failed to attach screenshot - " + e.getMessage());
            }
            Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);

            GraphicBuffer buffer = GraphicBuffer.createFromHardwareBuffer(
                    screenshotBuffer.getHardwareBuffer());
            // Scale the layer to the display size.
            float dsdx = (float) mWidth / hardwareBuffer.getWidth();
            float dsdy = (float) mHeight / hardwareBuffer.getHeight();

            t.setLayer(mScreenshotLayer, SCREEN_FREEZE_LAYER_BASE);
            t.reparent(mBackColorSurface, displayContent.getSurfaceControl());
            t.setLayer(mBackColorSurface, -1);
            t.setColor(mBackColorSurface, new float[]{mStartLuma, mStartLuma, mStartLuma});
            t.setAlpha(mBackColorSurface, 1);
            t.setBuffer(mScreenshotLayer, buffer);
            t.setColorSpace(mScreenshotLayer, screenshotBuffer.getColorSpace());
            t.setMatrix(mScreenshotLayer, dsdx, 0, 0, dsdy);
            t.show(mScreenshotLayer);
            t.show(mBackColorSurface);
            surface.destroy();

        } catch (OutOfResourcesException e) {
            Slog.w(TAG, "Unable to allocate freeze surface", e);
+6 −10
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_SCREEN_ROTATI

import android.annotation.NonNull;
import android.annotation.Nullable;
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.hardware.HardwareBuffer;
@@ -153,29 +154,24 @@ class SurfaceFreezer {
         */
        Snapshot(Supplier<Surface> surfaceFactory, SurfaceControl.Transaction t,
                SurfaceControl.ScreenshotHardwareBuffer screenshotBuffer, SurfaceControl parent) {
            Surface drawSurface = surfaceFactory.get();
            // We can't use a delegating constructor since we need to
            // reference this::onAnimationFinished
            HardwareBuffer hardwareBuffer = screenshotBuffer.getHardwareBuffer();
            final int width = hardwareBuffer.getWidth();
            final int height = hardwareBuffer.getHeight();
            GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
                    screenshotBuffer.getHardwareBuffer());

            mSurfaceControl = mAnimatable.makeAnimationLeash()
                    .setName("snapshot anim: " + mAnimatable.toString())
                    .setBufferSize(width, height)
                    .setFormat(PixelFormat.TRANSLUCENT)
                    .setParent(parent)
                    .setSecure(screenshotBuffer.containsSecureLayers())
                    .setCallsite("SurfaceFreezer.Snapshot")
                    .setBLASTLayer()
                    .build();

            ProtoLog.i(WM_SHOW_TRANSACTIONS, "  THUMBNAIL %s: CREATE", mSurfaceControl);

            // Transfer the thumbnail to the surface
            drawSurface.copyFrom(mSurfaceControl);
            drawSurface.attachAndQueueBufferWithColorSpace(hardwareBuffer,
                    screenshotBuffer.getColorSpace());
            drawSurface.release();
            t.setBuffer(mSurfaceControl, graphicBuffer);
            t.setColorSpace(mSurfaceControl, screenshotBuffer.getColorSpace());
            t.show(mSurfaceControl);

            // We parent the thumbnail to the container, and just place it on top of anything else
+9 −6
Original line number Diff line number Diff line
@@ -36,6 +36,7 @@ import android.annotation.Nullable;
import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.GraphicBuffer;
import android.graphics.PixelFormat;
import android.graphics.Rect;
import android.os.Binder;
@@ -45,7 +46,6 @@ import android.os.Parcel;
import android.os.RemoteException;
import android.util.ArraySet;
import android.util.Slog;
import android.view.Surface;
import android.view.SurfaceControl;
import android.window.IDisplayAreaOrganizerController;
import android.window.ITaskOrganizerController;
@@ -766,18 +766,21 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub
            return false;
        }

        GraphicBuffer graphicBuffer = GraphicBuffer.createFromHardwareBuffer(
                buffer.getHardwareBuffer());
        SurfaceControl screenshot = mService.mWindowManager.mSurfaceControlFactory.apply(null)
                .setName(wc.getName() + " - Organizer Screenshot")
                .setBufferSize(bounds.width(), bounds.height())
                .setFormat(PixelFormat.TRANSLUCENT)
                .setParent(wc.getParentSurfaceControl())
                .setSecure(buffer.containsSecureLayers())
                .setCallsite("WindowOrganizerController.takeScreenshot")
                .setBLASTLayer()
                .build();

        Surface surface = new Surface();
        surface.copyFrom(screenshot);
        surface.attachAndQueueBufferWithColorSpace(buffer.getHardwareBuffer(), null);
        surface.release();
        SurfaceControl.Transaction transaction = mService.mWindowManager.mTransactionFactory.get();
        transaction.setBuffer(screenshot, graphicBuffer);
        transaction.setColorSpace(screenshot, buffer.getColorSpace());
        transaction.apply();

        outSurfaceControl.copyFrom(screenshot, "WindowOrganizerController.takeScreenshot");
        return true;
Loading