зеркало из https://github.com/AvaloniaUI/angle.git
Add support for GL_MESA_framebuffer_flip_y 3/*
This is a third CL that adds tests that exercise the extension in various use cases. Bug: chromium:1231934 Change-Id: Iae3192cd0985150b6844a2855a9a048a54353655 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3365195 Reviewed-by: Shahbaz Youssefi <syoussefi@chromium.org> Reviewed-by: Jonah Ryan-Davis <jonahr@google.com> Commit-Queue: Maksim Sisov <msisov@igalia.com>
This commit is contained in:
Родитель
a765500786
Коммит
4572a17644
|
@ -1801,13 +1801,8 @@ void GenerateCaps(const FunctionsGL *functions,
|
|||
extensions->YUVTargetEXT = functions->hasGLESExtension("GL_EXT_YUV_target");
|
||||
|
||||
// GL_MESA_framebuffer_flip_y
|
||||
if (functions->isAtLeastGL(gl::Version(4, 3)) ||
|
||||
functions->hasGLExtension("GL_MESA_framebuffer_flip_y") ||
|
||||
functions->isAtLeastGLES(gl::Version(3, 1)) ||
|
||||
functions->hasGLESExtension("GL_MESA_framebuffer_flip_y"))
|
||||
{
|
||||
extensions->framebufferFlipYMESA = true;
|
||||
}
|
||||
extensions->framebufferFlipYMESA = functions->hasGLESExtension("GL_MESA_framebuffer_flip_y") ||
|
||||
functions->hasGLExtension("GL_MESA_framebuffer_flip_y");
|
||||
|
||||
// GL_KHR_parallel_shader_compile
|
||||
extensions->parallelShaderCompileKHR = true;
|
||||
|
|
|
@ -350,6 +350,67 @@ class BlitFramebufferANGLETest : public ANGLETest
|
|||
return true;
|
||||
}
|
||||
|
||||
void BlitStencilTestHelper(bool mesaYFlip)
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
|
||||
|
||||
if (mesaYFlip)
|
||||
{
|
||||
ASSERT_TRUE(IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
}
|
||||
|
||||
glClearColor(0.0, 1.0, 0.0, 1.0);
|
||||
glClearStencil(0x0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
// Scissor half the screen so we fill the stencil only halfway
|
||||
glScissor(0, 0, getWindowWidth(), getWindowHeight() / 2);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
|
||||
// fill the stencil buffer with 0x1
|
||||
glStencilFunc(GL_ALWAYS, 0x1, 0xFF);
|
||||
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
drawQuad(mRedProgram, essl1_shaders::PositionAttrib(), 0.3f);
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
|
||||
|
||||
// These clears are not useful in theory because we're copying over them, but its
|
||||
// helpful in debugging if we see white in any result.
|
||||
glClearColor(1.0, 1.0, 1.0, 1.0);
|
||||
glClearStencil(0x0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
|
||||
getWindowHeight(), GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
|
||||
GL_NEAREST);
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
|
||||
|
||||
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::red);
|
||||
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::green);
|
||||
|
||||
glStencilFunc(GL_EQUAL, 0x1, 0xFF); // only pass if stencil buffer at pixel reads 0x1
|
||||
|
||||
drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(),
|
||||
0.8f); // blue quad will draw if stencil buffer was copied
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::blue);
|
||||
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::green);
|
||||
}
|
||||
|
||||
GLuint mCheckerProgram;
|
||||
GLuint mBlueProgram;
|
||||
GLuint mRedProgram;
|
||||
|
@ -501,6 +562,267 @@ TEST_P(BlitFramebufferANGLETest, BlitColorWithFlip)
|
|||
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::yellow);
|
||||
}
|
||||
|
||||
// Blit color to default framebuffer from another framebuffer with GL_MESA_framebuffer_flip_y.
|
||||
TEST_P(BlitFramebufferANGLETest, BlitColorWithMesaYFlipSrc)
|
||||
{
|
||||
// OpenGL ES 3.0 / GL_NV_framebuffer_blit required for flip.
|
||||
ANGLE_SKIP_TEST_IF(
|
||||
(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_NV_framebuffer_blit")) ||
|
||||
!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
|
||||
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.8f);
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
// Blit to default from y-flipped.
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
|
||||
|
||||
const int fboTargetWidth = getWindowHeight() / 2;
|
||||
const int fboTargetHeight = getWindowHeight() / 2;
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth,
|
||||
fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
|
||||
|
||||
EXPECT_PIXEL_COLOR_EQ(fboTargetWidth / 4, fboTargetHeight / 4, GLColor::red);
|
||||
EXPECT_PIXEL_COLOR_EQ(fboTargetWidth / 4, 3 * fboTargetHeight / 4, GLColor::green);
|
||||
EXPECT_PIXEL_COLOR_EQ(3 * fboTargetWidth / 4, fboTargetHeight / 4, GLColor::blue);
|
||||
EXPECT_PIXEL_COLOR_EQ(3 * fboTargetWidth / 4, 3 * fboTargetHeight / 4, GLColor::yellow);
|
||||
}
|
||||
|
||||
// Blit color to y-flipped with GL_MESA_framebuffer_flip_y framebuffer from normal framebuffer.
|
||||
TEST_P(BlitFramebufferANGLETest, BlitColorWithMesaYFlipDst)
|
||||
{
|
||||
// OpenGL ES 3.0 / GL_NV_framebuffer_blit required for flip.
|
||||
ANGLE_SKIP_TEST_IF(
|
||||
(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_NV_framebuffer_blit")) ||
|
||||
!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
|
||||
|
||||
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 from y-flipped.
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mOriginalFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mUserFBO);
|
||||
|
||||
glFramebufferParameteriMESA(GL_DRAW_FRAMEBUFFER_ANGLE, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
|
||||
const int fboTargetWidth = getWindowWidth() / 2;
|
||||
const int fboTargetHeight = getWindowHeight();
|
||||
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth,
|
||||
fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), getWindowWidth() / 2, 0,
|
||||
getWindowWidth(), getWindowHeight() / 2, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
glFramebufferParameteriMESA(GL_DRAW_FRAMEBUFFER_ANGLE, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
|
||||
|
||||
// Left side have inverted checker pattern.
|
||||
EXPECT_PIXEL_COLOR_EQ(fboTargetWidth / 4, fboTargetHeight / 4, GLColor::green);
|
||||
EXPECT_PIXEL_COLOR_EQ(fboTargetWidth / 4, 3 * fboTargetHeight / 4, GLColor::red);
|
||||
EXPECT_PIXEL_COLOR_EQ(3 * fboTargetWidth / 4, fboTargetHeight / 4, GLColor::yellow);
|
||||
EXPECT_PIXEL_COLOR_EQ(3 * fboTargetWidth / 4, 3 * fboTargetHeight / 4, GLColor::blue);
|
||||
|
||||
// Right side is split to 2 parts where upper part have non y-flipped checker pattern and the
|
||||
// bottom one has white color.
|
||||
EXPECT_PIXEL_COLOR_EQ(5 * getWindowWidth() / 8, 5 * getWindowHeight() / 8, GLColor::green);
|
||||
EXPECT_PIXEL_COLOR_EQ(5 * getWindowWidth() / 8, 7 * getWindowHeight() / 8, GLColor::red);
|
||||
EXPECT_PIXEL_COLOR_EQ(7 * getWindowWidth() / 8, 5 * getWindowHeight() / 8, GLColor::yellow);
|
||||
EXPECT_PIXEL_COLOR_EQ(7 * getWindowWidth() / 8, 7 * getWindowHeight() / 8, GLColor::blue);
|
||||
|
||||
EXPECT_PIXEL_RECT_EQ(4 * getWindowWidth() / 8, 0, getWindowWidth() / 4, getWindowHeight() / 2,
|
||||
GLColor::white);
|
||||
}
|
||||
|
||||
// Blit color to/from y-flipped with GL_MESA_framebuffer_flip_y framebuffers where dst framebuffer
|
||||
// have different size.
|
||||
TEST_P(BlitFramebufferANGLETest, BlitColorWithMesaYFlipSrcDst)
|
||||
{
|
||||
// OpenGL ES 3.0 / GL_NV_framebuffer_blit required for flip.
|
||||
ANGLE_SKIP_TEST_IF(
|
||||
(getClientMajorVersion() < 3 && !IsGLExtensionEnabled("GL_NV_framebuffer_blit")) ||
|
||||
!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
// Create a custom framebuffer as the default one cannot be flipped.
|
||||
GLTexture tex0;
|
||||
glBindTexture(GL_TEXTURE_2D, tex0);
|
||||
const int fb0Width = getWindowWidth() / 2;
|
||||
const int fb0Height = getWindowHeight() / 2;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, fb0Width, fb0Height, 0, GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
nullptr);
|
||||
|
||||
GLFramebuffer fb0;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0, 0);
|
||||
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
|
||||
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 from y-flipped.
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, fb0);
|
||||
|
||||
glFramebufferParameteriMESA(GL_DRAW_FRAMEBUFFER_ANGLE, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
glFramebufferParameteriMESA(GL_READ_FRAMEBUFFER_ANGLE, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
|
||||
const int fboTargetWidth = fb0Width / 2;
|
||||
const int fboTargetHeight = fb0Height;
|
||||
|
||||
glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fboTargetWidth,
|
||||
fboTargetHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), fb0Width / 2, 0, fb0Width,
|
||||
fb0Height / 2, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb0);
|
||||
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
|
||||
|
||||
// Left side have inverted checker pattern.
|
||||
EXPECT_PIXEL_COLOR_EQ(fboTargetWidth / 4, fboTargetHeight / 4, GLColor::red);
|
||||
EXPECT_PIXEL_COLOR_EQ(fboTargetWidth / 4, 3 * fboTargetHeight / 4, GLColor::green);
|
||||
EXPECT_PIXEL_COLOR_EQ(3 * fboTargetWidth / 4, fboTargetHeight / 4, GLColor::blue);
|
||||
EXPECT_PIXEL_COLOR_EQ(3 * fboTargetWidth / 4, 3 * fboTargetHeight / 4, GLColor::yellow);
|
||||
|
||||
// Right side is split to 2 parts where upper part have y-flipped checker pattern and the
|
||||
// bottom one has white color.
|
||||
EXPECT_PIXEL_COLOR_EQ(5 * fb0Width / 8, 5 * fb0Height / 8, GLColor::red);
|
||||
EXPECT_PIXEL_COLOR_EQ(5 * fb0Width / 8, 7 * fb0Height / 8, GLColor::green);
|
||||
EXPECT_PIXEL_COLOR_EQ(7 * fb0Width / 8, 5 * fb0Height / 8, GLColor::blue);
|
||||
EXPECT_PIXEL_COLOR_EQ(7 * fb0Width / 8, 7 * fb0Height / 8, GLColor::yellow);
|
||||
|
||||
EXPECT_PIXEL_RECT_EQ(4 * fb0Width / 8, 0, fb0Width / 4, fb0Height / 2, GLColor::white);
|
||||
}
|
||||
|
||||
// Same as BlitColorWithMesaYFlip but uses an integer buffer format.
|
||||
TEST_P(BlitFramebufferANGLETest, BlitColorWithMesaYFlipInteger)
|
||||
{
|
||||
// OpenGL ES 3.0 / GL_NV_framebuffer_blit required for flip.
|
||||
ANGLE_SKIP_TEST_IF(
|
||||
(getClientMajorVersion() < 3 || !IsGLExtensionEnabled("GL_NV_framebuffer_blit")) ||
|
||||
!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
GLTexture tex0;
|
||||
glBindTexture(GL_TEXTURE_2D, tex0);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8I, getWindowWidth(), getWindowHeight(), 0,
|
||||
GL_RGBA_INTEGER, GL_BYTE, nullptr);
|
||||
|
||||
GLFramebuffer fb0;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb0);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex0, 0);
|
||||
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
drawQuad(mCheckerProgram, essl1_shaders::PositionAttrib(), 0.8f);
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
GLTexture tex1;
|
||||
glBindTexture(GL_TEXTURE_2D, tex1);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8I, getWindowWidth(), getWindowHeight(), 0,
|
||||
GL_RGBA_INTEGER, GL_BYTE, nullptr);
|
||||
|
||||
GLFramebuffer fb1;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb1);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex1, 0);
|
||||
|
||||
// Blit to default from y-flipped.
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fb0);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, fb1);
|
||||
|
||||
const int fb1_target_width = getWindowHeight() / 3;
|
||||
const int fb1_target_height = getWindowHeight() / 3;
|
||||
|
||||
glClearColor(0.0f, 1.0f, 1.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
glBlitFramebuffer(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, fb1_target_width,
|
||||
fb1_target_height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb1);
|
||||
|
||||
// The colors outside the target must remain the same.
|
||||
EXPECT_PIXEL_8I(getWindowWidth() - 1, getWindowHeight() - 1, 0, 127, 127, 127);
|
||||
EXPECT_PIXEL_8I(getWindowWidth() - 1, 0, 0, 127, 127, 127);
|
||||
EXPECT_PIXEL_8I(0, getWindowHeight() - 1, 0, 127, 127, 127);
|
||||
EXPECT_PIXEL_8I(fb1_target_width, fb1_target_height, 0, 127, 127, 127);
|
||||
|
||||
// While inside must change.
|
||||
EXPECT_PIXEL_8I(fb1_target_width / 4, fb1_target_height / 4, 127, 0, 0, 127);
|
||||
EXPECT_PIXEL_8I(fb1_target_width / 4, 3 * fb1_target_height / 4, 0, 127, 0, 127);
|
||||
EXPECT_PIXEL_8I(3 * fb1_target_width / 4, fb1_target_height / 4, 0, 0, 127, 127);
|
||||
EXPECT_PIXEL_8I(3 * fb1_target_width / 4, 3 * fb1_target_height / 4, 127, 127, 0, 127);
|
||||
|
||||
// Blit from y-flipped to default.
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, fb1);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, fb0);
|
||||
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
// Set y-flip flag so that y-flipped frame buffer blit to the original fbo in reverse. This
|
||||
// should result in flipping y back.
|
||||
glFramebufferParameteriMESA(GL_DRAW_FRAMEBUFFER_ANGLE, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
glBlitFramebuffer(0, 0, fb1_target_width, fb1_target_height, 0, 0, getWindowWidth(),
|
||||
getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
|
||||
// And explicitly disable y-flip so that read does not implicitly use this flag.
|
||||
glFramebufferParameteriMESA(GL_DRAW_FRAMEBUFFER_ANGLE, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fb0);
|
||||
|
||||
EXPECT_PIXEL_8I(getWindowWidth() / 4, getWindowHeight() / 4, 0, 127, 0, 127);
|
||||
EXPECT_PIXEL_8I(getWindowWidth() / 4, 3 * getWindowHeight() / 4, 127, 0, 0, 127);
|
||||
EXPECT_PIXEL_8I(3 * getWindowWidth() / 4, getWindowHeight() / 4, 127, 127, 0, 127);
|
||||
EXPECT_PIXEL_8I(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 0, 127, 127);
|
||||
}
|
||||
|
||||
// Draw to system framebuffer, blit whole-buffer color to user-created framebuffer.
|
||||
TEST_P(BlitFramebufferANGLETest, ReverseColorBlit)
|
||||
{
|
||||
|
@ -927,58 +1249,22 @@ TEST_P(BlitFramebufferANGLETest, BlitStencil)
|
|||
// http://anglebug.com/5396
|
||||
ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D9());
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mUserFBO);
|
||||
BlitStencilTestHelper(false /* mesaFlipY */);
|
||||
}
|
||||
|
||||
glClearColor(0.0, 1.0, 0.0, 1.0);
|
||||
glClearStencil(0x0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
// Same as BlitStencil, but with y-flip flag set.
|
||||
TEST_P(BlitFramebufferANGLETest, BlitStencilWithMesaYFlip)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_ANGLE_framebuffer_blit") ||
|
||||
!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
// Scissor half the screen so we fill the stencil only halfway
|
||||
glScissor(0, 0, getWindowWidth(), getWindowHeight() / 2);
|
||||
glEnable(GL_SCISSOR_TEST);
|
||||
// http://anglebug.com/2205
|
||||
ANGLE_SKIP_TEST_IF(IsIntel() && IsD3D9());
|
||||
|
||||
// fill the stencil buffer with 0x1
|
||||
glStencilFunc(GL_ALWAYS, 0x1, 0xFF);
|
||||
glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
|
||||
glEnable(GL_STENCIL_TEST);
|
||||
drawQuad(mRedProgram, essl1_shaders::PositionAttrib(), 0.3f);
|
||||
// http://anglebug.com/5396
|
||||
ANGLE_SKIP_TEST_IF(IsAMD() && IsD3D9());
|
||||
|
||||
glDisable(GL_SCISSOR_TEST);
|
||||
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER_ANGLE, mOriginalFBO);
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER_ANGLE, mUserFBO);
|
||||
|
||||
// These clears are not useful in theory because we're copying over them, but its
|
||||
// helpful in debugging if we see white in any result.
|
||||
glClearColor(1.0, 1.0, 1.0, 1.0);
|
||||
glClearStencil(0x0);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
// depth blit request should be silently ignored, because the read FBO has no depth attachment
|
||||
glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
|
||||
getWindowHeight(), GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
|
||||
GL_NEAREST);
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
|
||||
|
||||
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::red);
|
||||
EXPECT_PIXEL_COLOR_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, GLColor::green);
|
||||
|
||||
glStencilFunc(GL_EQUAL, 0x1, 0xFF); // only pass if stencil buffer at pixel reads 0x1
|
||||
|
||||
drawQuad(mBlueProgram, essl1_shaders::PositionAttrib(),
|
||||
0.8f); // blue quad will draw if stencil buffer was copied
|
||||
|
||||
glDisable(GL_STENCIL_TEST);
|
||||
|
||||
EXPECT_PIXEL_COLOR_EQ(getWindowWidth() / 4, getWindowHeight() / 4, GLColor::blue);
|
||||
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::green);
|
||||
BlitStencilTestHelper(true /* mesaFlipY */);
|
||||
}
|
||||
|
||||
// make sure that attempting to blit a partial depth buffer issues an error
|
||||
|
@ -1235,6 +1521,69 @@ class BlitFramebufferTest : public ANGLETest
|
|||
glBindFramebuffer(GL_FRAMEBUFFER, *fbo);
|
||||
drawQuad(checkerProgram.get(), essl1_shaders::PositionAttrib(), 0.5f);
|
||||
}
|
||||
|
||||
void BlitDepthStencilPixelByPixelTestHelper(bool mesaYFlip)
|
||||
{
|
||||
if (mesaYFlip)
|
||||
ASSERT_TRUE(IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
|
||||
|
||||
glViewport(0, 0, 128, 1);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
GLFramebuffer srcFramebuffer;
|
||||
GLRenderbuffer srcRenderbuffer;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, srcFramebuffer);
|
||||
if (mesaYFlip)
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, srcRenderbuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 128, 1);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
|
||||
srcRenderbuffer);
|
||||
glClearDepthf(1.0f);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f, 0.5f);
|
||||
glViewport(0, 0, 256, 2);
|
||||
|
||||
GLFramebuffer dstFramebuffer;
|
||||
GLRenderbuffer dstRenderbuffer;
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFramebuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, dstRenderbuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 256, 2);
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
|
||||
dstRenderbuffer);
|
||||
|
||||
GLTexture dstColor;
|
||||
glBindTexture(GL_TEXTURE_2D, dstColor);
|
||||
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 256, 2);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dstColor, 0);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFramebuffer);
|
||||
glBlitFramebuffer(0, 0, 128, 1, 0, 0, 256, 2, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
|
||||
GL_NEAREST);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, dstFramebuffer);
|
||||
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glDepthMask(false);
|
||||
glDepthFunc(GL_LESS);
|
||||
drawQuad(drawRed, essl1_shaders::PositionAttrib(), -0.01f, 0.5f);
|
||||
EXPECT_PIXEL_RECT_EQ(64, 0, 128, 1, GLColor::red);
|
||||
|
||||
ANGLE_GL_PROGRAM(drawBlue, essl3_shaders::vs::Simple(), essl3_shaders::fs::Blue());
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(false);
|
||||
glDepthFunc(GL_GREATER);
|
||||
if (mesaYFlip)
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.01f, 0.5f);
|
||||
if (mesaYFlip)
|
||||
EXPECT_PIXEL_RECT_EQ(64, 0, 128, 1, GLColor::green);
|
||||
else
|
||||
EXPECT_PIXEL_RECT_EQ(64, 0, 128, 1, GLColor::blue);
|
||||
}
|
||||
};
|
||||
|
||||
class BlitFramebufferTestES31 : public BlitFramebufferTest
|
||||
|
@ -2552,55 +2901,15 @@ TEST_P(BlitFramebufferTest, OOBWrite)
|
|||
// Test blitting a depthStencil buffer with multiple depth values to a larger size.
|
||||
TEST_P(BlitFramebufferTest, BlitDepthStencilPixelByPixel)
|
||||
{
|
||||
ANGLE_GL_PROGRAM(drawRed, essl3_shaders::vs::Simple(), essl3_shaders::fs::Red());
|
||||
BlitDepthStencilPixelByPixelTestHelper(false /* mesaYFlip */);
|
||||
}
|
||||
|
||||
glViewport(0, 0, 128, 1);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
// Same as BlitDepthStencilPixelByPixel, but with y-flip flag set.
|
||||
TEST_P(BlitFramebufferTest, BlitDepthStencilPixelByPixelMesaYFlip)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
GLFramebuffer srcFramebuffer;
|
||||
GLRenderbuffer srcRenderbuffer;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, srcFramebuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, srcRenderbuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 128, 1);
|
||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
|
||||
srcRenderbuffer);
|
||||
glClearDepthf(1.0f);
|
||||
glClear(GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
drawQuad(drawRed, essl1_shaders::PositionAttrib(), 0.0f, 0.5f);
|
||||
glViewport(0, 0, 256, 2);
|
||||
|
||||
GLFramebuffer dstFramebuffer;
|
||||
GLRenderbuffer dstRenderbuffer;
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, dstFramebuffer);
|
||||
glBindRenderbuffer(GL_RENDERBUFFER, dstRenderbuffer);
|
||||
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 256, 2);
|
||||
glFramebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
|
||||
dstRenderbuffer);
|
||||
|
||||
GLTexture dstColor;
|
||||
glBindTexture(GL_TEXTURE_2D, dstColor);
|
||||
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, 256, 2);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, dstColor, 0);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, srcFramebuffer);
|
||||
glBlitFramebuffer(0, 0, 128, 1, 0, 0, 256, 2, GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
|
||||
GL_NEAREST);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, dstFramebuffer);
|
||||
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
glDepthMask(false);
|
||||
glDepthFunc(GL_LESS);
|
||||
drawQuad(drawRed, essl1_shaders::PositionAttrib(), -0.01f, 0.5f);
|
||||
EXPECT_PIXEL_RECT_EQ(64, 0, 128, 1, GLColor::red);
|
||||
|
||||
ANGLE_GL_PROGRAM(drawBlue, essl3_shaders::vs::Simple(), essl3_shaders::fs::Blue());
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
glDepthMask(false);
|
||||
glDepthFunc(GL_GREATER);
|
||||
drawQuad(drawBlue, essl1_shaders::PositionAttrib(), 0.01f, 0.5f);
|
||||
EXPECT_PIXEL_RECT_EQ(64, 0, 128, 1, GLColor::blue);
|
||||
BlitDepthStencilPixelByPixelTestHelper(true /* mesaYFlip */);
|
||||
}
|
||||
|
||||
// Test that a draw call to a small FBO followed by a resolve of a large FBO works.
|
||||
|
@ -2718,6 +3027,227 @@ TEST_P(BlitFramebufferTestES31, BlitMultisampledRGBX8ToRGB8)
|
|||
EXPECT_PIXEL_COLOR_EQ(3 * kWidth / 4, 3 * kHeight / 4, GLColor::yellow);
|
||||
}
|
||||
|
||||
// Test resolving a multisampled texture with blit. Draw flipped, resolve with read fbo flipped.
|
||||
TEST_P(BlitFramebufferTestES31, MultisampleFlippedResolveReadWithBlitAndFlippedDraw)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
constexpr int kSize = 16;
|
||||
glViewport(0, 0, kSize, kSize);
|
||||
|
||||
GLFramebuffer msaaFBO;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
|
||||
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
|
||||
GLTexture texture;
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
|
||||
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
|
||||
texture.get(), 0);
|
||||
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
|
||||
ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
|
||||
essl31_shaders::fs::RedGreenGradient());
|
||||
drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// Create another FBO to resolve the multisample buffer into.
|
||||
GLTexture resolveTexture;
|
||||
GLFramebuffer resolveFBO;
|
||||
glBindTexture(GL_TEXTURE_2D, resolveTexture);
|
||||
constexpr int kResolveFBOWidth = kSize - 3;
|
||||
constexpr int kResolveFBOHeight = kSize - 2;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kResolveFBOWidth, kResolveFBOHeight, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
|
||||
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
|
||||
glFramebufferParameteriMESA(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
|
||||
glBlitFramebuffer(0, 0, kResolveFBOWidth, kResolveFBOHeight, 0, 0, kResolveFBOWidth,
|
||||
kResolveFBOHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
|
||||
constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
|
||||
EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(kResolveFBOWidth - 1, 0, 199, kHalfPixelGradient, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(0, kResolveFBOHeight - 1, kHalfPixelGradient, 215, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(kResolveFBOWidth - 1, kResolveFBOHeight - 1, 199, 215, 0, 255, 1.0);
|
||||
}
|
||||
|
||||
// Test resolving a multisampled texture with blit. Draw non-flipped, resolve with read fbo flipped.
|
||||
TEST_P(BlitFramebufferTestES31, MultisampleFlippedResolveReadWithBlitAndNonFlippedDraw)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
constexpr int kSize = 16;
|
||||
glViewport(0, 0, kSize, kSize);
|
||||
|
||||
GLFramebuffer msaaFBO;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
|
||||
|
||||
// Draw non-flipped - explicitly set y-flip to 0.
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
|
||||
|
||||
GLTexture texture;
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
|
||||
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
|
||||
texture.get(), 0);
|
||||
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
|
||||
ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
|
||||
essl31_shaders::fs::RedGreenGradient());
|
||||
drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// Create another FBO to resolve the multisample buffer into.
|
||||
GLTexture resolveTexture;
|
||||
GLFramebuffer resolveFBO;
|
||||
glBindTexture(GL_TEXTURE_2D, resolveTexture);
|
||||
constexpr int kResolveFBOWidth = kSize - 3;
|
||||
constexpr int kResolveFBOHeight = kSize - 2;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kResolveFBOWidth, kResolveFBOHeight, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
|
||||
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
|
||||
// Resolve with read fbo flipped and draw fbo non-flipped
|
||||
glFramebufferParameteriMESA(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
|
||||
glBlitFramebuffer(0, 0, kResolveFBOWidth, kResolveFBOHeight, 0, 0, kResolveFBOWidth,
|
||||
kResolveFBOHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
|
||||
constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
|
||||
EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(kResolveFBOWidth - 1, 0, 199, 255 - kHalfPixelGradient, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(0, kResolveFBOHeight - 1, kHalfPixelGradient, 40, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(kResolveFBOWidth - 1, kResolveFBOHeight - 1, 199, 40, 0, 255, 1.0);
|
||||
}
|
||||
|
||||
// Test resolving a multisampled texture with blit. Draw non-flipped, resolve with draw fbo flipped
|
||||
TEST_P(BlitFramebufferTestES31, MultisampleFlippedResolveDrawWithBlitAndNonFlippedDraw)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
constexpr int kSize = 16;
|
||||
glViewport(0, 0, kSize, kSize);
|
||||
|
||||
GLFramebuffer msaaFBO;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
|
||||
|
||||
// Draw non-flipped - explicitly set y-flip to 0.
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
|
||||
|
||||
GLTexture texture;
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
|
||||
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
|
||||
texture.get(), 0);
|
||||
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
|
||||
ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
|
||||
essl31_shaders::fs::RedGreenGradient());
|
||||
drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// Create another FBO to resolve the multisample buffer into.
|
||||
GLTexture resolveTexture;
|
||||
GLFramebuffer resolveFBO;
|
||||
glBindTexture(GL_TEXTURE_2D, resolveTexture);
|
||||
constexpr int kResolveFBOWidth = kSize - 3;
|
||||
constexpr int kResolveFBOHeight = kSize - 2;
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kResolveFBOWidth, kResolveFBOHeight, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
|
||||
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
|
||||
// Resolve with draw fbo flipped and read fbo non-flipped.
|
||||
glFramebufferParameteriMESA(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
|
||||
glFramebufferParameteriMESA(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
glBlitFramebuffer(0, 0, kResolveFBOWidth, kResolveFBOHeight, 0, 0, kResolveFBOWidth,
|
||||
kResolveFBOHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
|
||||
constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
|
||||
EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(kResolveFBOWidth - 1, 0, 199, kHalfPixelGradient, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(0, kResolveFBOHeight - 1, kHalfPixelGradient, 215, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(kResolveFBOWidth - 1, kResolveFBOHeight - 1, 199, 215, 0, 255, 1.0);
|
||||
}
|
||||
|
||||
// Test resolving a multisampled texture with blit. Draw non-flipped, resolve with both read and
|
||||
// draw fbos flipped
|
||||
TEST_P(BlitFramebufferTestES31, MultisampleFlippedResolveWithBlitAndNonFlippedDraw)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
constexpr int kSize = 16;
|
||||
glViewport(0, 0, kSize, kSize);
|
||||
|
||||
GLFramebuffer msaaFBO;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, msaaFBO.get());
|
||||
|
||||
// Draw non-flipped - explicitly set y-flip to 0.
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
|
||||
|
||||
GLTexture texture;
|
||||
glBindTexture(GL_TEXTURE_2D_MULTISAMPLE, texture.get());
|
||||
glTexStorage2DMultisample(GL_TEXTURE_2D_MULTISAMPLE, 4, GL_RGBA8, kSize, kSize, false);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D_MULTISAMPLE,
|
||||
texture.get(), 0);
|
||||
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
|
||||
ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
|
||||
essl31_shaders::fs::RedGreenGradient());
|
||||
drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// Create another FBO to resolve the multisample buffer into.
|
||||
GLTexture resolveTexture;
|
||||
GLFramebuffer resolveFBO;
|
||||
constexpr int kResolveFBOWidth = kSize - 3;
|
||||
constexpr int kResolveFBOHeight = kSize - 2;
|
||||
glBindTexture(GL_TEXTURE_2D, resolveTexture);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kResolveFBOWidth, kResolveFBOHeight, 0, GL_RGBA,
|
||||
GL_UNSIGNED_BYTE, nullptr);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, resolveFBO);
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, resolveTexture, 0);
|
||||
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, msaaFBO);
|
||||
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolveFBO);
|
||||
// Resolve with draw and read fbo flipped.
|
||||
glFramebufferParameteriMESA(GL_READ_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
glFramebufferParameteriMESA(GL_DRAW_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
glBlitFramebuffer(0, 0, kResolveFBOWidth, kResolveFBOHeight, 0, 0, kResolveFBOWidth,
|
||||
kResolveFBOHeight, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, resolveFBO);
|
||||
constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
|
||||
EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(kResolveFBOWidth - 1, 0, 199, 255 - kHalfPixelGradient, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(0, kResolveFBOHeight - 1, kHalfPixelGradient, 40, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(kResolveFBOWidth - 1, kResolveFBOHeight - 1, 199, 40, 0, 255, 1.0);
|
||||
}
|
||||
|
||||
// Use this to select which configurations (e.g. which renderer, which GLES major version) these
|
||||
// tests should be run against.
|
||||
GTEST_ALLOW_UNINSTANTIATED_PARAMETERIZED_TEST(BlitFramebufferANGLETest);
|
||||
|
|
|
@ -90,6 +90,33 @@ class CopyTexImageTest : public ANGLETest
|
|||
EXPECT_PIXEL_NEAR((xs + xe) / 2, (ys + ye) / 2, data[0], data[1], data[2], data[3], 1.0);
|
||||
}
|
||||
|
||||
void verifyCheckeredResults(GLuint texture,
|
||||
const GLubyte data0[4],
|
||||
const GLubyte data1[4],
|
||||
const GLubyte data2[4],
|
||||
const GLubyte data3[4],
|
||||
GLint fboWidth,
|
||||
GLint fboHeight)
|
||||
{
|
||||
glViewport(0, 0, fboWidth, fboHeight);
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
// Draw a quad with the target texture
|
||||
glUseProgram(mTextureProgram);
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
glUniform1i(mTextureUniformLocation, 0);
|
||||
|
||||
drawQuad(mTextureProgram, essl1_shaders::PositionAttrib(), 0.5f);
|
||||
|
||||
// Expect that the rendered quad has the same color as the source texture
|
||||
EXPECT_PIXEL_EQ(fboWidth / 4, fboHeight / 4, data0[0], data0[1], data0[2], data0[3]);
|
||||
EXPECT_PIXEL_EQ(fboWidth / 4, 3 * fboHeight / 4, data1[0], data1[1], data1[2], data1[3]);
|
||||
EXPECT_PIXEL_EQ(3 * fboWidth / 4, fboHeight / 4, data2[0], data2[1], data2[2], data2[3]);
|
||||
EXPECT_PIXEL_EQ(3 * fboWidth / 4, 3 * fboHeight / 4, data3[0], data3[1], data3[2],
|
||||
data3[3]);
|
||||
}
|
||||
|
||||
void runCopyTexImageTest(GLenum format, GLubyte expected[3][4])
|
||||
{
|
||||
GLTexture tex;
|
||||
|
@ -116,6 +143,47 @@ class CopyTexImageTest : public ANGLETest
|
|||
}
|
||||
}
|
||||
|
||||
// x, y, width, height specify the portion of fbo to be copied into tex.
|
||||
// flip_y specifies if the glCopyTextImage must be done from y-flipped fbo.
|
||||
void runCopyTexImageTestCheckered(GLenum format,
|
||||
const uint32_t x[3],
|
||||
const uint32_t y[3],
|
||||
const uint32_t width[3],
|
||||
const uint32_t height[3],
|
||||
const GLubyte expectedData0[4],
|
||||
const GLubyte expectedData1[4],
|
||||
const GLubyte expectedData2[4],
|
||||
const GLubyte expectedData3[4],
|
||||
bool mesaFlipY)
|
||||
{
|
||||
GLTexture tex;
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
|
||||
// Disable mipmapping
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
// Perform the copy multiple times.
|
||||
for (size_t i = 0; i < kFboCount; ++i)
|
||||
{
|
||||
glViewport(0, 0, kFboSizes[i], kFboSizes[i]);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFbos[i]);
|
||||
|
||||
ANGLE_GL_PROGRAM(checkerProgram, essl1_shaders::vs::Passthrough(),
|
||||
essl1_shaders::fs::Checkered());
|
||||
drawQuad(checkerProgram.get(), essl1_shaders::PositionAttrib(), 0.5f);
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
if (mesaFlipY)
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, x[i], y[i], width[i], height[i], 0);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
verifyCheckeredResults(tex, expectedData0, expectedData1, expectedData2, expectedData3,
|
||||
kFboSizes[i], kFboSizes[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void runCopyTexSubImageTest(GLenum format, GLubyte expected[3][4])
|
||||
{
|
||||
GLTexture tex;
|
||||
|
@ -566,6 +634,107 @@ TEST_P(CopyTexImageTest, CopyTexSubImageFrom3DTexureOES)
|
|||
}
|
||||
}
|
||||
|
||||
// Tests image copy from y-flipped fbo works.
|
||||
TEST_P(CopyTexImageTest, CopyTexImageMesaYFlip)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
std::array<uint32_t, 3> copyOrigin{0};
|
||||
std::array<uint32_t, 3> copySize;
|
||||
for (size_t i = 0; i < kFboCount; i++)
|
||||
copySize[i] = kFboSizes[i];
|
||||
|
||||
initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
runCopyTexImageTestCheckered(GL_RGBA, copyOrigin.data(), copyOrigin.data(), copySize.data(),
|
||||
copySize.data(), GLColor::green.data(), GLColor::red.data(),
|
||||
GLColor::yellow.data(), GLColor::blue.data(),
|
||||
true /* mesaFlipY */);
|
||||
}
|
||||
|
||||
// Tests image partial copy from y-flipped fbo works.
|
||||
TEST_P(CopyTexImageTest, CopyTexImageMesaYFlipPartial)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
std::array<uint32_t, kFboCount> copyX;
|
||||
std::array<uint32_t, kFboCount> copyY{0};
|
||||
std::array<uint32_t, kFboCount> copyWidth;
|
||||
std::array<uint32_t, kFboCount> copyHeight;
|
||||
|
||||
for (size_t i = 0; i < kFboCount; i++)
|
||||
{
|
||||
copyX[i] = kFboSizes[i] / 2;
|
||||
copyHeight[i] = kFboSizes[i];
|
||||
}
|
||||
copyWidth = copyX;
|
||||
|
||||
initializeResources(GL_RGBA, GL_UNSIGNED_BYTE);
|
||||
runCopyTexImageTestCheckered(GL_RGBA, copyX.data(), copyY.data(), copyWidth.data(),
|
||||
copyHeight.data(), GLColor::yellow.data(), GLColor::blue.data(),
|
||||
GLColor::yellow.data(), GLColor::blue.data(),
|
||||
true /* mesaFlipY */);
|
||||
}
|
||||
|
||||
// Tests subimage copy from y-flipped fbo works.
|
||||
TEST_P(CopyTexImageTest, CopyTexSubImageMesaYFlip)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
GLuint format = GL_RGBA;
|
||||
initializeResources(format, GL_UNSIGNED_BYTE);
|
||||
|
||||
glViewport(0, 0, kFboSizes[0], kFboSizes[0]);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFbos[0]);
|
||||
|
||||
ANGLE_GL_PROGRAM(checkerProgram, essl1_shaders::vs::Passthrough(),
|
||||
essl1_shaders::fs::Checkered());
|
||||
drawQuad(checkerProgram.get(), essl1_shaders::PositionAttrib(), 0.5f);
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
GLTexture tex;
|
||||
glBindTexture(GL_TEXTURE_2D, tex);
|
||||
|
||||
// Disable mipmapping
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
|
||||
// Create the texture with copy of the first fbo.
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFbos[0]);
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
glCopyTexImage2D(GL_TEXTURE_2D, 0, format, 0, 0, kFboSizes[0], kFboSizes[0], 0);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// Make sure out-of-bound writes to the texture return invalid value.
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, mFbos[1]);
|
||||
drawQuad(checkerProgram.get(), essl1_shaders::PositionAttrib(), 0.5f);
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
|
||||
// xoffset < 0 and yoffset < 0
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, -1, -1, 0, 0, kFboSizes[0], kFboSizes[0]);
|
||||
ASSERT_GL_ERROR(GL_INVALID_VALUE);
|
||||
|
||||
// xoffset + width > w and yoffset + height > h
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 1, 1, 0, 0, kFboSizes[0], kFboSizes[0]);
|
||||
ASSERT_GL_ERROR(GL_INVALID_VALUE);
|
||||
|
||||
// xoffset + width > w and yoffset + height > h, out of bounds
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, -1, -1, 1 + kFboSizes[0], 1 + kFboSizes[0]);
|
||||
ASSERT_GL_ERROR(GL_INVALID_VALUE);
|
||||
|
||||
// Copy the second fbo over a portion of the image.
|
||||
GLint offset = kFboSizes[0] / 2;
|
||||
GLint extent = kFboSizes[0] - offset;
|
||||
glCopyTexSubImage2D(GL_TEXTURE_2D, 0, offset, offset, kFboSizes[1] / 2, kFboSizes[1] / 2,
|
||||
extent, extent);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// Only part of the image is changed.
|
||||
verifyCheckeredResults(tex, GLColor::green.data(), GLColor::red.data(), GLColor::yellow.data(),
|
||||
GLColor::blue.data(), kFboSizes[0], kFboSizes[0]);
|
||||
}
|
||||
|
||||
// specialization of CopyTexImageTest is added so that some tests can be explicitly run with an ES3
|
||||
// context
|
||||
class CopyTexImageTestES3 : public CopyTexImageTest
|
||||
|
|
|
@ -115,7 +115,7 @@ class CopyTextureTest : public ANGLETest
|
|||
};
|
||||
|
||||
using CopyTextureVariationsTestParams =
|
||||
std::tuple<angle::PlatformParameters, GLenum, GLenum, bool, bool, bool>;
|
||||
std::tuple<angle::PlatformParameters, GLenum, GLenum, bool, bool, bool, GLint>;
|
||||
|
||||
std::string CopyTextureVariationsTestPrint(
|
||||
const ::testing::TestParamInfo<CopyTextureVariationsTestParams> ¶msInfo)
|
||||
|
@ -184,6 +184,10 @@ std::string CopyTextureVariationsTestPrint(
|
|||
{
|
||||
out << "UnmultiplyAlpha";
|
||||
}
|
||||
if (std::get<6>(params))
|
||||
{
|
||||
out << "MesaYFlip";
|
||||
}
|
||||
|
||||
return out.str();
|
||||
}
|
||||
|
@ -422,13 +426,18 @@ class CopyTextureVariationsTest : public ANGLETestWithParam<CopyTextureVariation
|
|||
GLenum destFormat,
|
||||
bool flipY,
|
||||
bool premultiplyAlpha,
|
||||
bool unmultiplyAlpha)
|
||||
bool unmultiplyAlpha,
|
||||
GLint mesaYFlipParam)
|
||||
{
|
||||
if (!checkExtensions(sourceFormat, destFormat))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool hasMesaFbFlipYExt = IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y");
|
||||
if (mesaYFlipParam && !hasMesaFbFlipYExt)
|
||||
ASSERT_TRUE(hasMesaFbFlipYExt);
|
||||
|
||||
if (sourceFormat == GL_LUMINANCE || sourceFormat == GL_LUMINANCE_ALPHA ||
|
||||
sourceFormat == GL_ALPHA || destFormat == GL_LUMINANCE ||
|
||||
destFormat == GL_LUMINANCE_ALPHA || destFormat == GL_ALPHA)
|
||||
|
@ -457,6 +466,11 @@ class CopyTextureVariationsTest : public ANGLETestWithParam<CopyTextureVariation
|
|||
initializeSourceTexture(sourceTarget, sourceFormat, &srcColors[i * componentCount],
|
||||
componentCount);
|
||||
|
||||
if (hasMesaFbFlipYExt)
|
||||
{
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA,
|
||||
mesaYFlipParam);
|
||||
}
|
||||
glCopyTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, destFormat,
|
||||
GL_UNSIGNED_BYTE, flipY, premultiplyAlpha, unmultiplyAlpha);
|
||||
|
||||
|
@ -467,17 +481,37 @@ class CopyTextureVariationsTest : public ANGLETestWithParam<CopyTextureVariation
|
|||
|
||||
if (flipY)
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 3], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 1], 1.0);
|
||||
if (mesaYFlipParam)
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 1], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 3], 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 3], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 1], 1.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 1], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 3], 1.0);
|
||||
if (mesaYFlipParam)
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 3], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 1], 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 1], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 3], 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
@ -489,13 +523,18 @@ class CopyTextureVariationsTest : public ANGLETestWithParam<CopyTextureVariation
|
|||
GLenum destFormat,
|
||||
bool flipY,
|
||||
bool premultiplyAlpha,
|
||||
bool unmultiplyAlpha)
|
||||
bool unmultiplyAlpha,
|
||||
GLint mesaYFlipParam)
|
||||
{
|
||||
if (!checkExtensions(sourceFormat, destFormat))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool hasMesaFbFlipYExt = IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y");
|
||||
if (mesaYFlipParam && !hasMesaFbFlipYExt)
|
||||
ASSERT_TRUE(hasMesaFbFlipYExt);
|
||||
|
||||
if (sourceFormat == GL_LUMINANCE || sourceFormat == GL_LUMINANCE_ALPHA ||
|
||||
sourceFormat == GL_ALPHA || destFormat == GL_LUMINANCE ||
|
||||
destFormat == GL_LUMINANCE_ALPHA || destFormat == GL_ALPHA)
|
||||
|
@ -528,6 +567,11 @@ class CopyTextureVariationsTest : public ANGLETestWithParam<CopyTextureVariation
|
|||
glTexImage2D(GL_TEXTURE_2D, 0, destFormat, 2, 2, 0, destFormat, GL_UNSIGNED_BYTE,
|
||||
nullptr);
|
||||
|
||||
if (hasMesaFbFlipYExt)
|
||||
{
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA,
|
||||
mesaYFlipParam);
|
||||
}
|
||||
glCopySubTextureCHROMIUM(mTextures[0], 0, GL_TEXTURE_2D, mTextures[1], 0, 0, 0, 0, 0, 2,
|
||||
2, flipY, premultiplyAlpha, unmultiplyAlpha);
|
||||
|
||||
|
@ -542,17 +586,37 @@ class CopyTextureVariationsTest : public ANGLETestWithParam<CopyTextureVariation
|
|||
|
||||
if (flipY)
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 3], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 1], 1.0);
|
||||
if (mesaYFlipParam)
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 1], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 3], 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 3], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 1], 1.0);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 1], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 3], 1.0);
|
||||
if (mesaYFlipParam)
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 3], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 1], 1.0);
|
||||
}
|
||||
else
|
||||
{
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 0, destColors[i + 0], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 0, destColors[i + 1], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(0, 1, destColors[i + 2], 1.0);
|
||||
EXPECT_PIXEL_COLOR_NEAR(1, 1, destColors[i + 3], 1.0);
|
||||
}
|
||||
}
|
||||
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
@ -904,6 +968,7 @@ constexpr GLenum kCopyTextureVariationsSrcFormats[] = {
|
|||
GL_ALPHA, GL_RGB, GL_RGBA, GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_BGRA_EXT};
|
||||
constexpr GLenum kCopyTextureVariationsDstFormats[] = {GL_RGB, GL_RGBA, GL_BGRA_EXT,
|
||||
GL_SRGB_ALPHA_EXT};
|
||||
constexpr GLint kMesaYFlips[] = {0, 1};
|
||||
} // anonymous namespace
|
||||
|
||||
TEST_P(CopyTextureVariationsTest, CopyTexture)
|
||||
|
@ -917,32 +982,57 @@ TEST_P(CopyTextureVariationsTest, CopyTexture)
|
|||
ANGLE_SKIP_TEST_IF(IsWindows7() && IsNVIDIA() && IsOpenGLES());
|
||||
}
|
||||
|
||||
if (std::get<6>(GetParam()))
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
}
|
||||
|
||||
testCopyTexture(GL_TEXTURE_2D, std::get<1>(GetParam()), std::get<2>(GetParam()),
|
||||
std::get<3>(GetParam()), std::get<4>(GetParam()), std::get<5>(GetParam()));
|
||||
std::get<3>(GetParam()), std::get<4>(GetParam()), std::get<5>(GetParam()),
|
||||
std::get<6>(GetParam()));
|
||||
}
|
||||
|
||||
TEST_P(CopyTextureVariationsTest, CopySubTexture)
|
||||
{
|
||||
// http://anglebug.com/5723
|
||||
ANGLE_SKIP_TEST_IF(IsOzone());
|
||||
|
||||
if (std::get<6>(GetParam()))
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
}
|
||||
|
||||
testCopySubTexture(GL_TEXTURE_2D, std::get<1>(GetParam()), std::get<2>(GetParam()),
|
||||
std::get<3>(GetParam()), std::get<4>(GetParam()), std::get<5>(GetParam()));
|
||||
std::get<3>(GetParam()), std::get<4>(GetParam()), std::get<5>(GetParam()),
|
||||
std::get<6>(GetParam()));
|
||||
}
|
||||
|
||||
TEST_P(CopyTextureVariationsTest, CopyTextureRectangle)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_texture_rectangle"));
|
||||
|
||||
if (std::get<6>(GetParam()))
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
}
|
||||
|
||||
testCopyTexture(GL_TEXTURE_RECTANGLE_ANGLE, std::get<1>(GetParam()), std::get<2>(GetParam()),
|
||||
std::get<3>(GetParam()), std::get<4>(GetParam()), std::get<5>(GetParam()));
|
||||
std::get<3>(GetParam()), std::get<4>(GetParam()), std::get<5>(GetParam()),
|
||||
std::get<6>(GetParam()));
|
||||
}
|
||||
|
||||
TEST_P(CopyTextureVariationsTest, CopySubTextureRectangle)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_ANGLE_texture_rectangle"));
|
||||
|
||||
if (std::get<6>(GetParam()))
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
}
|
||||
|
||||
testCopySubTexture(GL_TEXTURE_RECTANGLE_ANGLE, std::get<1>(GetParam()), std::get<2>(GetParam()),
|
||||
std::get<3>(GetParam()), std::get<4>(GetParam()), std::get<5>(GetParam()));
|
||||
std::get<3>(GetParam()), std::get<4>(GetParam()), std::get<5>(GetParam()),
|
||||
std::get<6>(GetParam()));
|
||||
}
|
||||
|
||||
// Test that copying to cube maps works
|
||||
|
@ -2534,13 +2624,14 @@ TEST_P(CopyTextureTestES3, InvalidateBlitThenBlend1000Layers)
|
|||
#endif
|
||||
|
||||
ANGLE_INSTANTIATE_TEST_ES2(CopyTextureTest);
|
||||
ANGLE_INSTANTIATE_TEST_COMBINE_5(CopyTextureVariationsTest,
|
||||
ANGLE_INSTANTIATE_TEST_COMBINE_6(CopyTextureVariationsTest,
|
||||
CopyTextureVariationsTestPrint,
|
||||
testing::ValuesIn(kCopyTextureVariationsSrcFormats),
|
||||
testing::ValuesIn(kCopyTextureVariationsDstFormats),
|
||||
testing::Bool(), // flipY
|
||||
testing::Bool(), // premultiplyAlpha
|
||||
testing::Bool(), // unmultiplyAlpha
|
||||
testing::ValuesIn(kMesaYFlips),
|
||||
ES2_D3D9(),
|
||||
ES2_D3D11(),
|
||||
ES2_OPENGL(),
|
||||
|
|
|
@ -1863,6 +1863,43 @@ TEST_P(FramebufferTest_ES31, IncompleteMultisampleFixedSampleLocationsTex)
|
|||
ASSERT_GL_NO_ERROR();
|
||||
}
|
||||
|
||||
// Tests that draw to Y-flipped FBO results in correct pixels.
|
||||
TEST_P(FramebufferTest_ES31, BasicDrawToYFlippedFBO)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled("GL_MESA_framebuffer_flip_y"));
|
||||
|
||||
constexpr int kSize = 16;
|
||||
glViewport(0, 0, kSize, kSize);
|
||||
|
||||
GLFramebuffer fbo;
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fbo.get());
|
||||
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 1);
|
||||
|
||||
GLTexture texture;
|
||||
glBindTexture(GL_TEXTURE_2D, texture.get());
|
||||
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, kSize, kSize);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture.get(), 0);
|
||||
ASSERT_GL_FRAMEBUFFER_COMPLETE(GL_FRAMEBUFFER);
|
||||
|
||||
ANGLE_GL_PROGRAM(gradientProgram, essl31_shaders::vs::Passthrough(),
|
||||
essl31_shaders::fs::RedGreenGradient());
|
||||
drawQuad(gradientProgram, essl31_shaders::PositionAttrib(), 0.5f, 1.0f, true);
|
||||
ASSERT_GL_NO_ERROR();
|
||||
|
||||
// Remove the flag so that glReadPixels do not implicitly use that.
|
||||
glFramebufferParameteriMESA(GL_FRAMEBUFFER, GL_FRAMEBUFFER_FLIP_Y_MESA, 0);
|
||||
|
||||
constexpr uint8_t kHalfPixelGradient = 256 / kSize / 2;
|
||||
EXPECT_PIXEL_NEAR(0, 0, kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(kSize - 1, 0, 255 - kHalfPixelGradient, 255 - kHalfPixelGradient, 0, 255,
|
||||
1.0);
|
||||
EXPECT_PIXEL_NEAR(0, kSize - 1, kHalfPixelGradient, kHalfPixelGradient, 0, 255, 1.0);
|
||||
EXPECT_PIXEL_NEAR(kSize - 1, kSize - 1, 255 - kHalfPixelGradient, kHalfPixelGradient, 0, 255,
|
||||
1.0);
|
||||
}
|
||||
|
||||
// Test resolving a multisampled texture with blit
|
||||
TEST_P(FramebufferTest_ES31, MultisampleResolveWithBlit)
|
||||
{
|
||||
|
|
|
@ -256,6 +256,14 @@ struct CombinedPrintToStringParamName
|
|||
testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), \
|
||||
combine1, combine2, combine3, combine4, combine5), \
|
||||
print)
|
||||
#define ANGLE_INSTANTIATE_TEST_COMBINE_6(testName, print, combine1, combine2, combine3, combine4, \
|
||||
combine5, combine6, first, ...) \
|
||||
const decltype(first) testName##params[] = {first, ##__VA_ARGS__}; \
|
||||
INSTANTIATE_TEST_SUITE_P( \
|
||||
, testName, \
|
||||
testing::Combine(ANGLE_INSTANTIATE_TEST_PLATFORMS(testName), combine1, combine2, combine3, \
|
||||
combine4, combine5, combine6), \
|
||||
print)
|
||||
|
||||
// Checks if a config is expected to be supported by checking a system-based allow list.
|
||||
bool IsConfigAllowlisted(const SystemInfo &systemInfo, const PlatformParameters ¶m);
|
||||
|
|
Загрузка…
Ссылка в новой задаче