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;
|
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());
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user