Merge "Minor optimization to skip bitmap copy during luma sampling" into rvc-dev

This commit is contained in:
Winson Chung
2020-03-19 23:08:08 +00:00
committed by Android (Google) Code Review
2 changed files with 53 additions and 14 deletions

View File

@@ -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());

View File

@@ -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)