Merge "Minor optimization to skip bitmap copy during luma sampling" into rvc-dev
This commit is contained in:
@@ -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());
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user