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

Commit 6c40007d authored by Winson Chung's avatar Winson Chung Committed by Automerger Merge Worker
Browse files

Merge "Minor optimization to skip bitmap copy during luma sampling" into...

Merge "Minor optimization to skip bitmap copy during luma sampling" into rvc-dev am: d972004c am: ead24e2f

Change-Id: I366788249ed76961bfaa55580c7f89d9c09eb2da
parents 82977b9a ead24e2f
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.server.wm;

import static android.os.Trace.TRACE_TAG_WINDOW_MANAGER;

import static com.android.server.wm.AnimationSpecProto.ROTATE;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC;
@@ -36,6 +38,7 @@ import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Trace;
import android.util.Slog;
import android.util.proto.ProtoOutputStream;
import android.view.Display;
@@ -205,8 +208,11 @@ class ScreenRotationAnimation {
            SurfaceControl.ScreenshotGraphicBuffer gb =
                    mService.mDisplayManagerInternal.screenshot(displayId);
            if (gb != null) {
                Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
                        "ScreenRotationAnimation#getMedianBorderLuma");
                mStartLuma = RotationAnimationUtils.getMedianBorderLuma(gb.getGraphicBuffer(),
                        gb.getColorSpace());
                Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
                try {
                    surface.attachAndQueueBufferWithColorSpace(gb.getGraphicBuffer(),
                            gb.getColorSpace());
+47 −14
Original line number Diff line number Diff line
@@ -16,16 +16,21 @@

package com.android.server.wm.utils;

import android.graphics.Bitmap;
import static android.graphics.PixelFormat.RGBA_8888;

import android.graphics.Color;
import android.graphics.ColorSpace;
import android.graphics.GraphicBuffer;
import android.graphics.Matrix;
import android.graphics.Point;
import android.graphics.Rect;
import android.media.Image;
import android.media.ImageReader;
import android.view.Display;
import android.view.Surface;
import android.view.SurfaceControl;

import java.nio.ByteBuffer;
import java.util.Arrays;


@@ -38,31 +43,59 @@ public class RotationAnimationUtils {
     * @return the average luminance of all the pixels at the borders of the bitmap
     */
    public static float getMedianBorderLuma(GraphicBuffer graphicBuffer, ColorSpace colorSpace) {
        Bitmap hwBitmap = Bitmap.wrapHardwareBuffer(graphicBuffer, colorSpace);
        if (hwBitmap == null) {
        if (graphicBuffer == null || graphicBuffer.getFormat() != RGBA_8888) {
            return 0;
        }

        Bitmap swaBitmap = hwBitmap.copy(Bitmap.Config.ARGB_8888, false);
        int height = swaBitmap.getHeight();
        int width = swaBitmap.getWidth();
        ImageReader ir = ImageReader.newInstance(graphicBuffer.getWidth(),
                graphicBuffer.getHeight(), graphicBuffer.getFormat(), 1);
        ir.getSurface().attachAndQueueBufferWithColorSpace(graphicBuffer, colorSpace);
        Image image = ir.acquireLatestImage();
        if (image == null || image.getPlanes().length == 0) {
            return 0;
        }

        Image.Plane plane = image.getPlanes()[0];
        ByteBuffer buffer = plane.getBuffer();
        int width = image.getWidth();
        int height = image.getHeight();
        int pixelStride = plane.getPixelStride();
        int rowStride = plane.getRowStride();
        float[] borderLumas = new float[2 * width + 2 * height];
        int i;
        int index = 0;
        for (i = 0; i < width; i++, index += 2) {
            borderLumas[index] = swaBitmap.getColor(i, 0).luminance();
            borderLumas[index + 1] = swaBitmap.getColor(i, height - 1).luminance();

        // Grab the top and bottom borders
        int l = 0;
        for (int x = 0; x < width; x++) {
            borderLumas[l++] = getPixelLuminance(buffer, x, 0, pixelStride, rowStride);
            borderLumas[l++] = getPixelLuminance(buffer, x, height - 1, pixelStride, rowStride);
        }
        for (i = 0; i < height; i++, index += 2) {
            borderLumas[index] = swaBitmap.getColor(0, i).luminance();
            borderLumas[index + 1] = swaBitmap.getColor(width - 1, i).luminance();

        // Grab the left and right borders
        for (int y = 0; y < height; y++) {
            borderLumas[l++] = getPixelLuminance(buffer, 0, y, pixelStride, rowStride);
            borderLumas[l++] = getPixelLuminance(buffer, width - 1, y, pixelStride, rowStride);
        }

        // Cleanup
        ir.close();

        // Oh, is this too simple and inefficient for you?
        // How about implementing a O(n) solution? https://en.wikipedia.org/wiki/Median_of_medians
        Arrays.sort(borderLumas);
        return borderLumas[borderLumas.length / 2];
    }

    private static float getPixelLuminance(ByteBuffer buffer, int x, int y,
            int pixelStride, int rowStride) {
        int offset = y * rowStride + x * pixelStride;
        int pixel = 0;
        pixel |= (buffer.get(offset) & 0xff) << 16;     // R
        pixel |= (buffer.get(offset + 1) & 0xff) << 8;  // G
        pixel |= (buffer.get(offset + 2) & 0xff);       // B
        pixel |= (buffer.get(offset + 3) & 0xff) << 24; // A
        return Color.valueOf(pixel).luminance();
    }

    /**
     * Gets the average border luma by taking a screenshot of the {@param surfaceControl}.
     * @see #getMedianBorderLuma(GraphicBuffer, ColorSpace)