Commit b10a0dfc by Amy Liu Committed by Commit Bot

Fix flip info of colorBlit with pre-rotation.

Get wrong colorBlit results on android if there is flip operation added by glBlitFramebuffer API. Fix the implementation and add related end2end tests. Bug: angleproject:5044 Change-Id: I797f8858b3943b5effe27261e954ca1405960ef0 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2534210 Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarIan Elliott <ianelliott@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent fd97c334
...@@ -156,8 +156,10 @@ void AdjustBlitAreaForPreRotation(SurfaceRotation framebufferAngle, ...@@ -156,8 +156,10 @@ void AdjustBlitAreaForPreRotation(SurfaceRotation framebufferAngle,
} }
} }
void AdjustFramebufferDimensionsForPreRotation(SurfaceRotation framebufferAngle, void AdjustDimensionsAndFlipForPreRotation(SurfaceRotation framebufferAngle,
gl::Rectangle *framebufferDimensions) gl::Rectangle *framebufferDimensions,
bool *flipX,
bool *flipY)
{ {
switch (framebufferAngle) switch (framebufferAngle)
{ {
...@@ -166,11 +168,13 @@ void AdjustFramebufferDimensionsForPreRotation(SurfaceRotation framebufferAngle, ...@@ -166,11 +168,13 @@ void AdjustFramebufferDimensionsForPreRotation(SurfaceRotation framebufferAngle,
break; break;
case SurfaceRotation::Rotated90Degrees: case SurfaceRotation::Rotated90Degrees:
std::swap(framebufferDimensions->width, framebufferDimensions->height); std::swap(framebufferDimensions->width, framebufferDimensions->height);
std::swap(*flipX, *flipY);
break; break;
case SurfaceRotation::Rotated180Degrees: case SurfaceRotation::Rotated180Degrees:
break; break;
case SurfaceRotation::Rotated270Degrees: case SurfaceRotation::Rotated270Degrees:
std::swap(framebufferDimensions->width, framebufferDimensions->height); std::swap(framebufferDimensions->width, framebufferDimensions->height);
std::swap(*flipX, *flipY);
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -228,17 +232,17 @@ void AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle, ...@@ -228,17 +232,17 @@ void AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle,
std::swap(params->stretch[0], params->stretch[1]); std::swap(params->stretch[0], params->stretch[1]);
std::swap(params->srcOffset[0], params->srcOffset[1]); std::swap(params->srcOffset[0], params->srcOffset[1]);
std::swap(params->rotatedOffsetFactor[0], params->rotatedOffsetFactor[1]); std::swap(params->rotatedOffsetFactor[0], params->rotatedOffsetFactor[1]);
std::swap(params->flipX, params->flipY);
if (srcFramebufferAngle == framebufferAngle) if (srcFramebufferAngle == framebufferAngle)
{ {
std::swap(params->destOffset[0], params->destOffset[1]); std::swap(params->destOffset[0], params->destOffset[1]);
std::swap(params->stretch[0], params->stretch[1]); std::swap(params->stretch[0], params->stretch[1]);
std::swap(params->flipX, params->flipY);
} }
break; break;
case SurfaceRotation::Rotated180Degrees: case SurfaceRotation::Rotated180Degrees:
ASSERT(!params->flipX && params->flipY); // Combine flip info with api flip.
params->flipX = true; params->flipX = !params->flipX;
params->flipY = false; params->flipY = !params->flipY;
break; break;
case SurfaceRotation::Rotated270Degrees: case SurfaceRotation::Rotated270Degrees:
std::swap(params->stretch[0], params->stretch[1]); std::swap(params->stretch[0], params->stretch[1]);
...@@ -248,9 +252,11 @@ void AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle, ...@@ -248,9 +252,11 @@ void AdjustBlitResolveParametersForPreRotation(SurfaceRotation framebufferAngle,
{ {
std::swap(params->stretch[0], params->stretch[1]); std::swap(params->stretch[0], params->stretch[1]);
} }
ASSERT(!params->flipX && !params->flipY); // Combine flip info with api flip.
params->flipX = true; params->flipX = !params->flipX;
params->flipY = true; params->flipY = !params->flipY;
std::swap(params->flipX, params->flipY);
break; break;
default: default:
UNREACHABLE(); UNREACHABLE();
...@@ -1008,8 +1014,8 @@ angle::Result FramebufferVk::blit(const gl::Context *context, ...@@ -1008,8 +1014,8 @@ angle::Result FramebufferVk::blit(const gl::Context *context,
destFramebufferDimensions.height - srcClippedDestArea.y - srcClippedDestArea.height; destFramebufferDimensions.height - srcClippedDestArea.y - srcClippedDestArea.height;
} }
const bool flipX = sourceArea.isReversedX() != destArea.isReversedX(); bool flipX = sourceArea.isReversedX() != destArea.isReversedX();
const bool flipY = sourceArea.isReversedY() != destArea.isReversedY(); bool flipY = sourceArea.isReversedY() != destArea.isReversedY();
// GLES doesn't allow flipping the parameters of glBlitFramebuffer if performing a resolve. // GLES doesn't allow flipping the parameters of glBlitFramebuffer if performing a resolve.
ASSERT(!isResolve || ASSERT(!isResolve ||
...@@ -1029,8 +1035,8 @@ angle::Result FramebufferVk::blit(const gl::Context *context, ...@@ -1029,8 +1035,8 @@ angle::Result FramebufferVk::blit(const gl::Context *context,
{ {
AdjustBlitAreaForPreRotation(srcFramebufferRotation, sourceAreaOld, AdjustBlitAreaForPreRotation(srcFramebufferRotation, sourceAreaOld,
srcFramebufferDimensions, &sourceArea); srcFramebufferDimensions, &sourceArea);
AdjustFramebufferDimensionsForPreRotation(srcFramebufferRotation, AdjustDimensionsAndFlipForPreRotation(srcFramebufferRotation, &srcFramebufferDimensions,
&srcFramebufferDimensions); &flipX, &flipY);
} }
SurfaceRotation rememberDestFramebufferRotation = destFramebufferRotation; SurfaceRotation rememberDestFramebufferRotation = destFramebufferRotation;
if (srcFramebufferRotation == SurfaceRotation::Rotated90Degrees) if (srcFramebufferRotation == SurfaceRotation::Rotated90Degrees)
......
...@@ -415,6 +415,90 @@ TEST_P(BlitFramebufferANGLETest, BlitColorToDefault) ...@@ -415,6 +415,90 @@ TEST_P(BlitFramebufferANGLETest, BlitColorToDefault)
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::yellow); EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::yellow);
} }
// Blit color to/from default framebuffer with Flip-X/Flip-Y.
TEST_P(BlitFramebufferANGLETest, BlitColorWithFlip)
{
// OpenGL ES 3.0 Required.
ANGLE_SKIP_TEST_IF(getClientMajorVersion() < 3 ||
!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit"));
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.8f);
EXPECT_GL_NO_ERROR();
// Blit to default with x-flip.
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth(), 0, 0,
getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::yellow);
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::green);
// Blit to default with y-flip.
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, getWindowHeight(),
getWindowWidth(), 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, GLColor::yellow);
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::blue);
// Blit from default with x-flip.
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth(), 0, 0,
getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::yellow);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::red);
// Blit from default with y-flip.
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, getWindowHeight(),
getWindowWidth(), 0, GL_COLOR_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::red);
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::green);
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, GLColor::blue);
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::yellow);
}
// Draw to system framebuffer, blit whole-buffer color to user-created framebuffer. // Draw to system framebuffer, blit whole-buffer color to user-created framebuffer.
TEST_P(BlitFramebufferANGLETest, ReverseColorBlit) TEST_P(BlitFramebufferANGLETest, ReverseColorBlit)
{ {
......
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