Fix for HardwareBufferRenderer pre-rotation
Updated transform matrix to match the implementation
within VulkanSurface.cpp
Updated getFrame logic to return the logical dimensions
of a HardwareBuffer target instead of the width/height
of a HardwareBuffer in case pre-rotation transforms
are applied
Fixes: 276362013
Test: Updated HardwareBufferRendererTests
Change-Id: I9877af52a81804facc8b89b65cce3433b96655dc
diff --git a/graphics/java/android/graphics/HardwareBufferRenderer.java b/graphics/java/android/graphics/HardwareBufferRenderer.java
index 361dc59..e04f13c 100644
--- a/graphics/java/android/graphics/HardwareBufferRenderer.java
+++ b/graphics/java/android/graphics/HardwareBufferRenderer.java
@@ -275,11 +275,22 @@
Consumer<RenderResult> wrapped = consumable -> executor.execute(
() -> renderCallback.accept(consumable));
if (!isClosed()) {
+ int renderWidth;
+ int renderHeight;
+ if (mTransform == SurfaceControl.BUFFER_TRANSFORM_ROTATE_90
+ || mTransform == SurfaceControl.BUFFER_TRANSFORM_ROTATE_270) {
+ renderWidth = mHardwareBuffer.getHeight();
+ renderHeight = mHardwareBuffer.getWidth();
+ } else {
+ renderWidth = mHardwareBuffer.getWidth();
+ renderHeight = mHardwareBuffer.getHeight();
+ }
+
nRender(
mProxy,
mTransform,
- mHardwareBuffer.getWidth(),
- mHardwareBuffer.getHeight(),
+ renderWidth,
+ renderHeight,
mColorSpace.getNativeInstance(),
wrapped);
} else {
diff --git a/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
index 768dfcd..706f18c 100644
--- a/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
+++ b/libs/hwui/jni/android_graphics_HardwareBufferRenderer.cpp
@@ -85,28 +85,20 @@
}
static SkMatrix createMatrixFromBufferTransform(SkScalar width, SkScalar height, int transform) {
- auto matrix = SkMatrix();
switch (transform) {
case ANATIVEWINDOW_TRANSFORM_ROTATE_90:
- matrix.setRotate(90);
- matrix.postTranslate(width, 0);
- break;
+ return SkMatrix::MakeAll(0, -1, height, 1, 0, 0, 0, 0, 1);
case ANATIVEWINDOW_TRANSFORM_ROTATE_180:
- matrix.setRotate(180);
- matrix.postTranslate(width, height);
- break;
+ return SkMatrix::MakeAll(-1, 0, width, 0, -1, height, 0, 0, 1);
case ANATIVEWINDOW_TRANSFORM_ROTATE_270:
- matrix.setRotate(270);
- matrix.postTranslate(0, width);
- break;
+ return SkMatrix::MakeAll(0, 1, 0, -1, 0, width, 0, 0, 1);
default:
ALOGE("Invalid transform provided. Transform should be validated from"
"the java side. Leveraging identity transform as a fallback");
[[fallthrough]];
case ANATIVEWINDOW_TRANSFORM_IDENTITY:
- break;
+ return SkMatrix::I();
}
- return matrix;
}
static int android_graphics_HardwareBufferRenderer_render(JNIEnv* env, jobject, jlong renderProxy,
@@ -117,8 +109,8 @@
auto skHeight = static_cast<SkScalar>(height);
auto matrix = createMatrixFromBufferTransform(skWidth, skHeight, transform);
auto colorSpace = GraphicsJNI::getNativeColorSpace(colorspacePtr);
- proxy->setHardwareBufferRenderParams(
- HardwareBufferRenderParams(matrix, colorSpace, createRenderCallback(env, consumer)));
+ proxy->setHardwareBufferRenderParams(HardwareBufferRenderParams(
+ width, height, matrix, colorSpace, createRenderCallback(env, consumer)));
nsecs_t vsync = systemTime(SYSTEM_TIME_MONOTONIC);
UiFrameInfoBuilder(proxy->frameInfo())
.setVsync(vsync, vsync, UiFrameInfoBuilder::INVALID_VSYNC_ID,
diff --git a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
index 202a62c..cc987bc 100644
--- a/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaOpenGLPipeline.cpp
@@ -69,15 +69,9 @@
}
Frame SkiaOpenGLPipeline::getFrame() {
- if (mHardwareBuffer) {
- AHardwareBuffer_Desc description;
- AHardwareBuffer_describe(mHardwareBuffer, &description);
- return Frame(description.width, description.height, 0);
- } else {
- LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
- "drawRenderNode called on a context with no surface!");
- return mEglManager.beginFrame(mEglSurface);
- }
+ LOG_ALWAYS_FATAL_IF(mEglSurface == EGL_NO_SURFACE,
+ "drawRenderNode called on a context with no surface!");
+ return mEglManager.beginFrame(mEglSurface);
}
IRenderPipeline::DrawResult SkiaOpenGLPipeline::draw(
diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
index 99298bc..c8f2e69 100644
--- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
+++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp
@@ -66,15 +66,8 @@
}
Frame SkiaVulkanPipeline::getFrame() {
- if (mHardwareBuffer) {
- AHardwareBuffer_Desc description;
- AHardwareBuffer_describe(mHardwareBuffer, &description);
- return Frame(description.width, description.height, 0);
- } else {
- LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr,
- "getFrame() called on a context with no surface!");
- return vulkanManager().dequeueNextBuffer(mVkSurface);
- }
+ LOG_ALWAYS_FATAL_IF(mVkSurface == nullptr, "getFrame() called on a context with no surface!");
+ return vulkanManager().dequeueNextBuffer(mVkSurface);
}
IRenderPipeline::DrawResult SkiaVulkanPipeline::draw(
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index dd781bb..6b2c995 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -528,6 +528,14 @@
sendLoadResetHint();
}
+Frame CanvasContext::getFrame() {
+ if (mHardwareBuffer != nullptr) {
+ return {mBufferParams.getLogicalWidth(), mBufferParams.getLogicalHeight(), 0};
+ } else {
+ return mRenderPipeline->getFrame();
+ }
+}
+
void CanvasContext::draw() {
if (auto grContext = getGrContext()) {
if (grContext->abandoned()) {
@@ -569,7 +577,8 @@
mCurrentFrameInfo->markIssueDrawCommandsStart();
- Frame frame = mRenderPipeline->getFrame();
+ Frame frame = getFrame();
+
SkRect windowDirty = computeDirtyRect(frame, &dirty);
ATRACE_FORMAT("Drawing " RECT_STRING, SK_RECT_ARGS(dirty));
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index b26c018..3f25339 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -264,6 +264,8 @@
FrameInfo* getFrameInfoFromLast4(uint64_t frameNumber, uint32_t surfaceControlId);
+ Frame getFrame();
+
// The same type as Frame.mWidth and Frame.mHeight
int32_t mLastFrameWidth = 0;
int32_t mLastFrameHeight = 0;
diff --git a/libs/hwui/renderthread/HardwareBufferRenderParams.h b/libs/hwui/renderthread/HardwareBufferRenderParams.h
index 91fe3f6..8c942d0 100644
--- a/libs/hwui/renderthread/HardwareBufferRenderParams.h
+++ b/libs/hwui/renderthread/HardwareBufferRenderParams.h
@@ -36,9 +36,12 @@
class HardwareBufferRenderParams {
public:
HardwareBufferRenderParams() = default;
- HardwareBufferRenderParams(const SkMatrix& transform, const sk_sp<SkColorSpace>& colorSpace,
+ HardwareBufferRenderParams(int32_t logicalWidth, int32_t logicalHeight,
+ const SkMatrix& transform, const sk_sp<SkColorSpace>& colorSpace,
RenderCallback&& callback)
- : mTransform(transform)
+ : mLogicalWidth(logicalWidth)
+ , mLogicalHeight(logicalHeight)
+ , mTransform(transform)
, mColorSpace(colorSpace)
, mRenderCallback(std::move(callback)) {}
const SkMatrix& getTransform() const { return mTransform; }
@@ -50,7 +53,12 @@
}
}
+ int32_t getLogicalWidth() { return mLogicalWidth; }
+ int32_t getLogicalHeight() { return mLogicalHeight; }
+
private:
+ int32_t mLogicalWidth;
+ int32_t mLogicalHeight;
SkMatrix mTransform = SkMatrix::I();
sk_sp<SkColorSpace> mColorSpace = SkColorSpace::MakeSRGB();
RenderCallback mRenderCallback = nullptr;