Commit 10ee839c by Ian Elliott Committed by Commit Bot

Vulkan: Improve viewport and scissor for pre-rotation

Handle all 4 rotations and non-full-screen viewports & scissors. Test: Running NBA 2K20 while flipping phone left and right (90 & 270) + watching it in Visual Studio and with Android logcat INFO messages Bug: b/150329969 Bug: angleproject:4431 Change-Id: Icd555dbc2419aac1413452c1b306d6227784dc27 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2174961 Commit-Queue: Ian Elliott <ianelliott@google.com> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarCody Northrop <cnorthrop@google.com>
parent 1c3e322c
......@@ -270,7 +270,7 @@ SurfaceRotationType DetermineSurfaceRotation(gl::Framebuffer *framebuffer,
return SurfaceRotationType::Rotated180Degrees;
case VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR:
// Rotate gl_Position 270 degrees:
return SurfaceRotationType::Rotated180Degrees;
return SurfaceRotationType::Rotated270Degrees;
default:
UNREACHABLE();
return SurfaceRotationType::Identity;
......@@ -283,6 +283,50 @@ SurfaceRotationType DetermineSurfaceRotation(gl::Framebuffer *framebuffer,
}
}
void RotateRectangle(const SurfaceRotationType rotation,
const bool flipY,
const int framebufferWidth,
const int framebufferHeight,
const gl::Rectangle &incoming,
gl::Rectangle *outgoing)
{
// GLES's y-axis points up; Vulkan's points down.
switch (rotation)
{
case SurfaceRotationType::Identity:
// Do not rotate gl_Position (surface matches the device's orientation):
outgoing->x = incoming.x;
outgoing->y = flipY ? framebufferHeight - incoming.y - incoming.height : incoming.y;
outgoing->width = incoming.width;
outgoing->height = incoming.height;
break;
case SurfaceRotationType::Rotated90Degrees:
// Rotate gl_Position 90 degrees:
outgoing->x = incoming.y;
outgoing->y = flipY ? incoming.x : framebufferWidth - incoming.x - incoming.width;
outgoing->width = incoming.height;
outgoing->height = incoming.width;
break;
case SurfaceRotationType::Rotated180Degrees:
// Rotate gl_Position 180 degrees:
outgoing->x = framebufferWidth - incoming.x - incoming.width;
outgoing->y = flipY ? incoming.y : framebufferHeight - incoming.y - incoming.height;
outgoing->width = incoming.width;
outgoing->height = incoming.height;
break;
case SurfaceRotationType::Rotated270Degrees:
// Rotate gl_Position 270 degrees:
outgoing->x = framebufferHeight - incoming.y - incoming.height;
outgoing->y = flipY ? framebufferWidth - incoming.x - incoming.width : incoming.x;
outgoing->width = incoming.height;
outgoing->height = incoming.width;
break;
default:
UNREACHABLE();
break;
}
}
// Should not generate a copy with modern C++.
EventName GetTraceEventName(const char *title, uint32_t counter)
{
......@@ -2507,11 +2551,22 @@ bool ContextVk::isRotatedAspectRatioForDrawFBO() const
{
return IsRotatedAspectRatio(mCurrentRotationDrawFramebuffer);
}
bool ContextVk::isRotatedAspectRatioForReadFBO() const
{
return IsRotatedAspectRatio(mCurrentRotationReadFramebuffer);
}
SurfaceRotationType ContextVk::getRotationDrawFramebuffer() const
{
return mCurrentRotationDrawFramebuffer;
}
SurfaceRotationType ContextVk::getRotationReadFramebuffer() const
{
return mCurrentRotationReadFramebuffer;
}
void ContextVk::updateColorMask(const gl::BlendState &blendState)
{
mClearColorMask =
......@@ -2579,21 +2634,17 @@ void ContextVk::updateViewport(FramebufferVk *framebufferVk,
correctedHeight = viewportBoundsRangeHigh - correctedY;
}
gl::Box framebufferDimensions = framebufferVk->getState().getDimensions();
if (isRotatedAspectRatioForDrawFBO())
{
// The surface is rotated 90/270 degrees. This changes the aspect ratio of the surface.
// Swap the width and height of the viewport we calculate, and the framebuffer height that
// we use to calculate it with.
// TODO(ianelliott): handle small viewport/scissor cases. http://anglebug.com/4431
std::swap(correctedWidth, correctedHeight);
std::swap(framebufferDimensions.width, framebufferDimensions.height);
}
gl::Box fbDimensions = framebufferVk->getState().getDimensions();
gl::Rectangle correctedRect =
gl::Rectangle(correctedX, correctedY, correctedWidth, correctedHeight);
gl_vk::GetViewport(correctedRect, nearPlane, farPlane, invertViewport,
framebufferDimensions.height, &vkViewport);
gl::Rectangle rotatedRect;
RotateRectangle(getRotationDrawFramebuffer(), false, fbDimensions.width, fbDimensions.height,
correctedRect, &rotatedRect);
gl_vk::GetViewport(rotatedRect, nearPlane, farPlane, invertViewport,
// If the surface is rotated 90/270 degrees, use the framebuffer's width
// instead of the height for calculating the final viewport.
isRotatedAspectRatioForDrawFBO() ? fbDimensions.width : fbDimensions.height,
&vkViewport);
mGraphicsPipelineDesc->updateViewport(&mGraphicsPipelineTransition, vkViewport);
invalidateGraphicsDriverUniforms();
}
......@@ -2614,20 +2665,12 @@ angle::Result ContextVk::updateScissor(const gl::State &glState)
gl::ClipRectangle(renderArea, glState.getViewport(), &viewportClippedRenderArea);
gl::Rectangle scissoredArea = ClipRectToScissor(getState(), viewportClippedRenderArea, false);
if (isViewportFlipEnabledForDrawFBO())
{
scissoredArea.y = renderArea.height - scissoredArea.y - scissoredArea.height;
}
if (isRotatedAspectRatioForDrawFBO())
{
// The surface is rotated 90/270 degrees. This changes the aspect ratio of the surface.
// Swap the width and height of the scissor we use.
// TODO(ianelliott): handle small viewport/scissor cases. http://anglebug.com/4431
std::swap(scissoredArea.width, scissoredArea.height);
}
gl::Rectangle rotatedScissoredArea;
RotateRectangle(getRotationDrawFramebuffer(), isViewportFlipEnabledForDrawFBO(),
renderArea.width, renderArea.height, scissoredArea, &rotatedScissoredArea);
mGraphicsPipelineDesc->updateScissor(&mGraphicsPipelineTransition,
gl_vk::GetRect(scissoredArea));
gl_vk::GetRect(rotatedScissoredArea));
// If the scissor has grown beyond the previous scissoredRenderArea, make sure the render pass
// is restarted. Otherwise, we can continue using the same renderpass area.
......@@ -3088,7 +3131,7 @@ void ContextVk::updateSurfaceRotationDrawFramebuffer(const gl::State &glState)
void ContextVk::updateSurfaceRotationReadFramebuffer(const gl::State &glState)
{
gl::Framebuffer *readFramebuffer = glState.getReadFramebuffer();
mCurrentRotationDrawFramebuffer =
mCurrentRotationReadFramebuffer =
DetermineSurfaceRotation(readFramebuffer, mCurrentWindowSurface);
}
......
......@@ -384,6 +384,8 @@ class ContextVk : public ContextImpl, public vk::Context
// render area must be swapped.
bool isRotatedAspectRatioForDrawFBO() const;
bool isRotatedAspectRatioForReadFBO() const;
SurfaceRotationType getRotationDrawFramebuffer() const;
SurfaceRotationType getRotationReadFramebuffer() const;
void invalidateProgramBindingHelper(const gl::State &glState);
angle::Result invalidateProgramExecutableHelper(const gl::Context *context);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment