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

Change-Id: I366788249ed76961bfaa55580c7f89d9c09eb2da
This commit is contained in:
Winson Chung
2020-03-19 23:40:08 +00:00
committed by Automerger Merge Worker
2 changed files with 53 additions and 14 deletions

View File

@@ -16,6 +16,8 @@
package com.android.server.wm; 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.AnimationSpecProto.ROTATE;
import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION; import static com.android.server.wm.ProtoLogGroup.WM_DEBUG_ORIENTATION;
import static com.android.server.wm.ProtoLogGroup.WM_SHOW_SURFACE_ALLOC; 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.Matrix;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.os.Trace;
import android.util.Slog; import android.util.Slog;
import android.util.proto.ProtoOutputStream; import android.util.proto.ProtoOutputStream;
import android.view.Display; import android.view.Display;
@@ -205,8 +208,11 @@ class ScreenRotationAnimation {
SurfaceControl.ScreenshotGraphicBuffer gb = SurfaceControl.ScreenshotGraphicBuffer gb =
mService.mDisplayManagerInternal.screenshot(displayId); mService.mDisplayManagerInternal.screenshot(displayId);
if (gb != null) { if (gb != null) {
Trace.traceBegin(TRACE_TAG_WINDOW_MANAGER,
"ScreenRotationAnimation#getMedianBorderLuma");
mStartLuma = RotationAnimationUtils.getMedianBorderLuma(gb.getGraphicBuffer(), mStartLuma = RotationAnimationUtils.getMedianBorderLuma(gb.getGraphicBuffer(),
gb.getColorSpace()); gb.getColorSpace());
Trace.traceEnd(TRACE_TAG_WINDOW_MANAGER);
try { try {
surface.attachAndQueueBufferWithColorSpace(gb.getGraphicBuffer(), surface.attachAndQueueBufferWithColorSpace(gb.getGraphicBuffer(),
gb.getColorSpace()); gb.getColorSpace());

View File

@@ -16,16 +16,21 @@
package com.android.server.wm.utils; 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.ColorSpace;
import android.graphics.GraphicBuffer; import android.graphics.GraphicBuffer;
import android.graphics.Matrix; import android.graphics.Matrix;
import android.graphics.Point; import android.graphics.Point;
import android.graphics.Rect; import android.graphics.Rect;
import android.media.Image;
import android.media.ImageReader;
import android.view.Display; import android.view.Display;
import android.view.Surface; import android.view.Surface;
import android.view.SurfaceControl; import android.view.SurfaceControl;
import java.nio.ByteBuffer;
import java.util.Arrays; 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 * @return the average luminance of all the pixels at the borders of the bitmap
*/ */
public static float getMedianBorderLuma(GraphicBuffer graphicBuffer, ColorSpace colorSpace) { public static float getMedianBorderLuma(GraphicBuffer graphicBuffer, ColorSpace colorSpace) {
Bitmap hwBitmap = Bitmap.wrapHardwareBuffer(graphicBuffer, colorSpace); if (graphicBuffer == null || graphicBuffer.getFormat() != RGBA_8888) {
if (hwBitmap == null) {
return 0; return 0;
} }
Bitmap swaBitmap = hwBitmap.copy(Bitmap.Config.ARGB_8888, false); ImageReader ir = ImageReader.newInstance(graphicBuffer.getWidth(),
int height = swaBitmap.getHeight(); graphicBuffer.getHeight(), graphicBuffer.getFormat(), 1);
int width = swaBitmap.getWidth(); 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]; float[] borderLumas = new float[2 * width + 2 * height];
int i;
int index = 0; // Grab the top and bottom borders
for (i = 0; i < width; i++, index += 2) { int l = 0;
borderLumas[index] = swaBitmap.getColor(i, 0).luminance(); for (int x = 0; x < width; x++) {
borderLumas[index + 1] = swaBitmap.getColor(i, height - 1).luminance(); 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(); // Grab the left and right borders
borderLumas[index + 1] = swaBitmap.getColor(width - 1, i).luminance(); 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? // Oh, is this too simple and inefficient for you?
// How about implementing a O(n) solution? https://en.wikipedia.org/wiki/Median_of_medians // How about implementing a O(n) solution? https://en.wikipedia.org/wiki/Median_of_medians
Arrays.sort(borderLumas); Arrays.sort(borderLumas);
return borderLumas[borderLumas.length / 2]; 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}. * Gets the average border luma by taking a screenshot of the {@param surfaceControl}.
* @see #getMedianBorderLuma(GraphicBuffer, ColorSpace) * @see #getMedianBorderLuma(GraphicBuffer, ColorSpace)