Commit 17d27031 by Kenneth Russell Committed by Commit Bot

Fix BlitFramebuffer validation for BGRA sources and targets.

It is legal to blit between GL_RGBA8 and GL_BGRA8 sources and destinations when resolving multisampled renderbuffers. Expand BlitFramebuffer's validation to handle this case. Work around a bug in macOS' OpenGL driver querying the number of samples for GL_BGRA8. Query GL_MAX_VERTEX_OUTPUT_COMPONENTS on the Core Profile to work around an error generated on macOS when querying GL_MAX_VARYING_COMPONENTS. Expand the BlitFramebuffer tests to cover these cases and start running them on the OpenGL backend. BUG=angleproject:891 Change-Id: I4829585d2b6428ce0bc7509c4734d33709a0930b Reviewed-on: https://chromium-review.googlesource.com/582268 Commit-Queue: Geoff Lang <geofflang@chromium.org> Reviewed-by: 's avatarKenneth Russell <kbr@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 1da00653
...@@ -458,6 +458,24 @@ bool Format::SameSized(const Format &a, const Format &b) ...@@ -458,6 +458,24 @@ bool Format::SameSized(const Format &a, const Format &b)
return a.info->sizedInternalFormat == b.info->sizedInternalFormat; return a.info->sizedInternalFormat == b.info->sizedInternalFormat;
} }
static GLenum EquivalentBlitInternalFormat(GLenum internalformat)
{
// BlitFramebuffer works if the color channels are identically
// sized, even if there is a swizzle (for example, blitting from a
// multisampled RGBA8 renderbuffer to a BGRA8 texture). This could
// be expanded and/or autogenerated if that is found necessary.
if (internalformat == GL_BGRA8_EXT)
return GL_RGBA8;
return internalformat;
}
// static
bool Format::EquivalentForBlit(const Format &a, const Format &b)
{
return (EquivalentBlitInternalFormat(a.info->sizedInternalFormat) ==
EquivalentBlitInternalFormat(b.info->sizedInternalFormat));
}
// static // static
Format Format::Invalid() Format Format::Invalid()
{ {
......
...@@ -150,6 +150,7 @@ struct Format ...@@ -150,6 +150,7 @@ struct Format
static Format Invalid(); static Format Invalid();
static bool SameSized(const Format &a, const Format &b); static bool SameSized(const Format &a, const Format &b);
static bool EquivalentForBlit(const Format &a, const Format &b);
friend std::ostream &operator<<(std::ostream &os, const Format &fmt); friend std::ostream &operator<<(std::ostream &os, const Format &fmt);
......
...@@ -133,6 +133,10 @@ struct WorkaroundsGL ...@@ -133,6 +133,10 @@ struct WorkaroundsGL
// On some NVIDIA drivers the point size range reported from the API is inconsistent with the // On some NVIDIA drivers the point size range reported from the API is inconsistent with the
// actual behavior. Clamp the point size to the value from the API to fix this. // actual behavior. Clamp the point size to the value from the API to fix this.
bool clampPointSize = false; bool clampPointSize = false;
// Calling getInternalformativ for GL_NUM_SAMPLES and the internal
// format GL_BGRA8_EXT generates a GL_INVALID_ENUM error on macOS.
bool avoidInternalFormativForBGRA8 = false;
}; };
} // namespace rx } // namespace rx
......
...@@ -89,8 +89,12 @@ static bool MeetsRequirements(const FunctionsGL *functions, const nativegl::Supp ...@@ -89,8 +89,12 @@ static bool MeetsRequirements(const FunctionsGL *functions, const nativegl::Supp
} }
} }
static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, GLenum internalFormat) static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions,
const WorkaroundsGL &workarounds,
GLenum internalFormat)
{ {
ASSERT(functions->getError() == GL_NO_ERROR);
gl::TextureCaps textureCaps; gl::TextureCaps textureCaps;
const nativegl::InternalFormat &formatInfo = nativegl::GetInternalFormatInfo(internalFormat, functions->standard); const nativegl::InternalFormat &formatInfo = nativegl::GetInternalFormatInfo(internalFormat, functions->standard);
...@@ -102,16 +106,27 @@ static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, G ...@@ -102,16 +106,27 @@ static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, G
// extension GL_ARB_internalformat_query // extension GL_ARB_internalformat_query
if (textureCaps.renderable && functions->getInternalformativ) if (textureCaps.renderable && functions->getInternalformativ)
{ {
GLenum queryInternalFormat = internalFormat;
if (internalFormat == GL_BGRA8_EXT && workarounds.avoidInternalFormativForBGRA8)
{
// Querying GL_NUM_SAMPLE_COUNTS for GL_BGRA8_EXT generates an INVALID_ENUM error on
// macOS' Core Profile OpenGL driver. It seems however that allocating a multisampled
// renderbuffer of this format succeeds. To avoid breaking multisampling for this
// format, query the supported sample counts for GL_RGBA8 instead.
queryInternalFormat = GL_RGBA8;
}
GLint numSamples = 0; GLint numSamples = 0;
functions->getInternalformativ(GL_RENDERBUFFER, internalFormat, GL_NUM_SAMPLE_COUNTS, 1, &numSamples); functions->getInternalformativ(GL_RENDERBUFFER, queryInternalFormat, GL_NUM_SAMPLE_COUNTS,
1, &numSamples);
if (numSamples > 0) if (numSamples > 0)
{ {
std::vector<GLint> samples(numSamples); std::vector<GLint> samples(numSamples);
functions->getInternalformativ(GL_RENDERBUFFER, internalFormat, GL_SAMPLES, functions->getInternalformativ(GL_RENDERBUFFER, queryInternalFormat, GL_SAMPLES,
static_cast<GLsizei>(samples.size()), &samples[0]); static_cast<GLsizei>(samples.size()), &samples[0]);
GLenum queryInternalFormat = internalFormat;
if (internalFormat == GL_STENCIL_INDEX8) if (internalFormat == GL_STENCIL_INDEX8)
{ {
// The query below does generates an error with STENCIL_INDEX8 on NVIDIA driver // The query below does generates an error with STENCIL_INDEX8 on NVIDIA driver
...@@ -149,6 +164,7 @@ static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, G ...@@ -149,6 +164,7 @@ static gl::TextureCaps GenerateTextureFormatCaps(const FunctionsGL *functions, G
} }
} }
ASSERT(functions->getError() == GL_NO_ERROR);
return textureCaps; return textureCaps;
} }
...@@ -229,7 +245,8 @@ void GenerateCaps(const FunctionsGL *functions, ...@@ -229,7 +245,8 @@ void GenerateCaps(const FunctionsGL *functions,
const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats(); const gl::FormatSet &allFormats = gl::GetAllSizedInternalFormats();
for (GLenum internalFormat : allFormats) for (GLenum internalFormat : allFormats)
{ {
gl::TextureCaps textureCaps = GenerateTextureFormatCaps(functions, internalFormat); gl::TextureCaps textureCaps =
GenerateTextureFormatCaps(functions, workarounds, internalFormat);
textureCapsMap->insert(internalFormat, textureCaps); textureCapsMap->insert(internalFormat, textureCaps);
if (gl::GetSizedInternalFormatInfo(internalFormat).compressed) if (gl::GetSizedInternalFormatInfo(internalFormat).compressed)
...@@ -539,9 +556,14 @@ void GenerateCaps(const FunctionsGL *functions, ...@@ -539,9 +556,14 @@ void GenerateCaps(const FunctionsGL *functions,
LimitVersion(maxSupportedESVersion, gl::Version(2, 0)); LimitVersion(maxSupportedESVersion, gl::Version(2, 0));
} }
if (functions->isAtLeastGL(gl::Version(3, 0)) || if (functions->isAtLeastGL(gl::Version(3, 2)) &&
functions->hasGLExtension("GL_ARB_ES2_compatibility") || (functions->profile & GL_CONTEXT_CORE_PROFILE_BIT) != 0)
functions->isAtLeastGLES(gl::Version(2, 0))) {
caps->maxVaryingComponents = QuerySingleGLInt(functions, GL_MAX_VERTEX_OUTPUT_COMPONENTS);
}
else if (functions->isAtLeastGL(gl::Version(3, 0)) ||
functions->hasGLExtension("GL_ARB_ES2_compatibility") ||
functions->isAtLeastGLES(gl::Version(2, 0)))
{ {
caps->maxVaryingComponents = QuerySingleGLInt(functions, GL_MAX_VARYING_COMPONENTS); caps->maxVaryingComponents = QuerySingleGLInt(functions, GL_MAX_VARYING_COMPONENTS);
} }
...@@ -1061,6 +1083,12 @@ void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workaround ...@@ -1061,6 +1083,12 @@ void GenerateWorkarounds(const FunctionsGL *functions, WorkaroundsGL *workaround
workarounds->clampPointSize = true; workarounds->clampPointSize = true;
#endif #endif
#if defined(ANGLE_PLATFORM_APPLE)
workarounds->avoidInternalFormativForBGRA8 = true;
#else
workarounds->avoidInternalFormativForBGRA8 = IsAMD(vendor);
#endif
} }
void ApplyWorkarounds(const FunctionsGL *functions, gl::Workarounds *workarounds) void ApplyWorkarounds(const FunctionsGL *functions, gl::Workarounds *workarounds)
......
...@@ -1727,7 +1727,7 @@ bool ValidateBlitFramebufferParameters(ValidationContext *context, ...@@ -1727,7 +1727,7 @@ bool ValidateBlitFramebufferParameters(ValidationContext *context,
} }
if (readColorBuffer->getSamples() > 0 && if (readColorBuffer->getSamples() > 0 &&
(!Format::SameSized(readFormat, drawFormat) || !sameBounds)) (!Format::EquivalentForBlit(readFormat, drawFormat) || !sameBounds))
{ {
context->handleError(InvalidOperation()); context->handleError(InvalidOperation());
return false; return false;
...@@ -1778,7 +1778,7 @@ bool ValidateBlitFramebufferParameters(ValidationContext *context, ...@@ -1778,7 +1778,7 @@ bool ValidateBlitFramebufferParameters(ValidationContext *context,
if (readBuffer && drawBuffer) if (readBuffer && drawBuffer)
{ {
if (!Format::SameSized(readBuffer->getFormat(), drawBuffer->getFormat())) if (!Format::EquivalentForBlit(readBuffer->getFormat(), drawBuffer->getFormat()))
{ {
context->handleError(InvalidOperation()); context->handleError(InvalidOperation());
return false; return false;
......
...@@ -2350,8 +2350,8 @@ bool ValidateBlitFramebufferANGLE(Context *context, ...@@ -2350,8 +2350,8 @@ bool ValidateBlitFramebufferANGLE(Context *context,
} }
// Return an error if the destination formats do not match // Return an error if the destination formats do not match
if (!Format::SameSized(attachment->getFormat(), if (!Format::EquivalentForBlit(attachment->getFormat(),
readColorAttachment->getFormat())) readColorAttachment->getFormat()))
{ {
context->handleError(InvalidOperation()); context->handleError(InvalidOperation());
return false; return false;
......
...@@ -52,7 +52,11 @@ class BlitFramebufferANGLETest : public ANGLETest ...@@ -52,7 +52,11 @@ class BlitFramebufferANGLETest : public ANGLETest
mRGBAColorbuffer = 0; mRGBAColorbuffer = 0;
mRGBAFBO = 0; mRGBAFBO = 0;
mRGBAMultisampledRenderbuffer = 0;
mRGBAMultisampledFBO = 0;
mBGRAColorbuffer = 0;
mBGRAFBO = 0;
mBGRAMultisampledRenderbuffer = 0; mBGRAMultisampledRenderbuffer = 0;
mBGRAMultisampledFBO = 0; mBGRAMultisampledFBO = 0;
} }
...@@ -205,9 +209,10 @@ class BlitFramebufferANGLETest : public ANGLETest ...@@ -205,9 +209,10 @@ class BlitFramebufferANGLETest : public ANGLETest
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
} }
if (extensionEnabled("GL_ANGLE_framebuffer_multisample")) if (extensionEnabled("GL_ANGLE_framebuffer_multisample") &&
extensionEnabled("GL_OES_rgb8_rgba8"))
{ {
// Test blit between RGBA and multisampled BGRA // RGBA single-sampled framebuffer
glGenTextures(1, &mRGBAColorbuffer); glGenTextures(1, &mRGBAColorbuffer);
glBindTexture(GL_TEXTURE_2D, mRGBAColorbuffer); glBindTexture(GL_TEXTURE_2D, mRGBAColorbuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA, glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, getWindowWidth(), getWindowHeight(), 0, GL_RGBA,
...@@ -220,16 +225,50 @@ class BlitFramebufferANGLETest : public ANGLETest ...@@ -220,16 +225,50 @@ class BlitFramebufferANGLETest : public ANGLETest
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
glGenRenderbuffers(1, &mBGRAMultisampledRenderbuffer); // RGBA multisampled framebuffer
glBindRenderbuffer(GL_RENDERBUFFER, mBGRAMultisampledRenderbuffer); glGenRenderbuffers(1, &mRGBAMultisampledRenderbuffer);
glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_BGRA8_EXT, getWindowWidth(), getWindowHeight()); glBindRenderbuffer(GL_RENDERBUFFER, mRGBAMultisampledRenderbuffer);
glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_RGBA8, getWindowWidth(),
getWindowHeight());
glGenFramebuffers(1, &mBGRAMultisampledFBO); glGenFramebuffers(1, &mRGBAMultisampledFBO);
glBindFramebuffer(GL_FRAMEBUFFER, mBGRAMultisampledFBO); glBindFramebuffer(GL_FRAMEBUFFER, mRGBAMultisampledFBO);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, mBGRAMultisampledRenderbuffer); glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
mRGBAMultisampledRenderbuffer);
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
if (extensionEnabled("GL_EXT_texture_format_BGRA8888"))
{
// BGRA single-sampled framebuffer
glGenTextures(1, &mBGRAColorbuffer);
glBindTexture(GL_TEXTURE_2D, mBGRAColorbuffer);
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, getWindowWidth(), getWindowHeight(), 0,
GL_BGRA_EXT, GL_UNSIGNED_BYTE, nullptr);
glGenFramebuffers(1, &mBGRAFBO);
glBindFramebuffer(GL_FRAMEBUFFER, mBGRAFBO);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
mBGRAColorbuffer, 0);
ASSERT_GL_NO_ERROR();
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
// BGRA multisampled framebuffer
glGenRenderbuffers(1, &mBGRAMultisampledRenderbuffer);
glBindRenderbuffer(GL_RENDERBUFFER, mBGRAMultisampledRenderbuffer);
glRenderbufferStorageMultisampleANGLE(GL_RENDERBUFFER, 1, GL_BGRA8_EXT,
getWindowWidth(), getWindowHeight());
glGenFramebuffers(1, &mBGRAMultisampledFBO);
glBindFramebuffer(GL_FRAMEBUFFER, mBGRAMultisampledFBO);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER,
mBGRAMultisampledRenderbuffer);
ASSERT_GL_NO_ERROR();
ASSERT_GLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
}
} }
glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO); glBindFramebuffer(GL_FRAMEBUFFER, mOriginalFBO);
...@@ -271,7 +310,27 @@ class BlitFramebufferANGLETest : public ANGLETest ...@@ -271,7 +310,27 @@ class BlitFramebufferANGLETest : public ANGLETest
if (mRGBAFBO != 0) if (mRGBAFBO != 0)
{ {
glDeleteFramebuffers(1, &mBGRAMultisampledFBO); glDeleteFramebuffers(1, &mRGBAFBO);
}
if (mRGBAMultisampledRenderbuffer != 0)
{
glDeleteRenderbuffers(1, &mRGBAMultisampledRenderbuffer);
}
if (mRGBAMultisampledFBO != 0)
{
glDeleteFramebuffers(1, &mRGBAMultisampledFBO);
}
if (mBGRAColorbuffer != 0)
{
glDeleteTextures(1, &mBGRAColorbuffer);
}
if (mBGRAFBO != 0)
{
glDeleteFramebuffers(1, &mBGRAFBO);
} }
if (mBGRAMultisampledRenderbuffer != 0) if (mBGRAMultisampledRenderbuffer != 0)
...@@ -287,6 +346,37 @@ class BlitFramebufferANGLETest : public ANGLETest ...@@ -287,6 +346,37 @@ class BlitFramebufferANGLETest : public ANGLETest
ANGLETest::TearDown(); ANGLETest::TearDown();
} }
void multisampleTestHelper(GLuint readFramebuffer, GLuint drawFramebuffer)
{
glClearColor(0.0, 1.0, 0.0, 1.0);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, readFramebuffer);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_READ_FRAMEBUFFER, readFramebuffer);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, drawFramebuffer);
glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(),
getWindowHeight(), GL_COLOR_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_NO_ERROR();
glBindFramebuffer(GL_READ_FRAMEBUFFER, drawFramebuffer);
EXPECT_PIXEL_EQ(getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, getWindowHeight() / 4, 0, 255, 0, 255);
EXPECT_PIXEL_EQ(3 * getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 255, 0, 255);
EXPECT_PIXEL_EQ(getWindowWidth() / 4, 3 * getWindowHeight() / 4, 0, 255, 0, 255);
}
bool checkExtension(const std::string &extension)
{
if (!extensionEnabled(extension))
{
std::cout << "Test skipped because " << extension << " not supported." << std::endl;
return false;
}
return true;
}
GLuint mCheckerProgram; GLuint mCheckerProgram;
GLuint mBlueProgram; GLuint mBlueProgram;
...@@ -315,7 +405,11 @@ class BlitFramebufferANGLETest : public ANGLETest ...@@ -315,7 +405,11 @@ class BlitFramebufferANGLETest : public ANGLETest
GLuint mRGBAColorbuffer; GLuint mRGBAColorbuffer;
GLuint mRGBAFBO; GLuint mRGBAFBO;
GLuint mRGBAMultisampledRenderbuffer;
GLuint mRGBAMultisampledFBO;
GLuint mBGRAColorbuffer;
GLuint mBGRAFBO;
GLuint mBGRAMultisampledRenderbuffer; GLuint mBGRAMultisampledRenderbuffer;
GLuint mBGRAMultisampledFBO; GLuint mBGRAMultisampledFBO;
}; };
...@@ -824,6 +918,60 @@ TEST_P(BlitFramebufferANGLETest, BlitMRT) ...@@ -824,6 +918,60 @@ TEST_P(BlitFramebufferANGLETest, BlitMRT)
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, mMRTColorBuffer1, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT1_EXT, GL_TEXTURE_2D, mMRTColorBuffer1, 0);
} }
// Test multisampled framebuffer blits if supported
TEST_P(BlitFramebufferANGLETest, MultisampledRGBAToRGBA)
{
if (!checkExtension("GL_ANGLE_framebuffer_multisample"))
return;
if (!checkExtension("GL_OES_rgb8_rgba8"))
return;
multisampleTestHelper(mRGBAMultisampledFBO, mRGBAFBO);
}
TEST_P(BlitFramebufferANGLETest, MultisampledRGBAToBGRA)
{
if (!checkExtension("GL_ANGLE_framebuffer_multisample"))
return;
if (!checkExtension("GL_OES_rgb8_rgba8"))
return;
if (!checkExtension("GL_EXT_texture_format_BGRA8888"))
return;
multisampleTestHelper(mRGBAMultisampledFBO, mBGRAFBO);
}
TEST_P(BlitFramebufferANGLETest, MultisampledBGRAToRGBA)
{
if (!checkExtension("GL_ANGLE_framebuffer_multisample"))
return;
if (!checkExtension("GL_OES_rgb8_rgba8"))
return;
if (!checkExtension("GL_EXT_texture_format_BGRA8888"))
return;
multisampleTestHelper(mBGRAMultisampledFBO, mRGBAFBO);
}
TEST_P(BlitFramebufferANGLETest, MultisampledBGRAToBGRA)
{
if (!checkExtension("GL_ANGLE_framebuffer_multisample"))
return;
if (!checkExtension("GL_OES_rgb8_rgba8"))
return;
if (!checkExtension("GL_EXT_texture_format_BGRA8888"))
return;
multisampleTestHelper(mBGRAMultisampledFBO, mBGRAFBO);
}
// Make sure that attempts to stretch in a blit call issue an error // Make sure that attempts to stretch in a blit call issue an error
TEST_P(BlitFramebufferANGLETest, ErrorStretching) TEST_P(BlitFramebufferANGLETest, ErrorStretching)
{ {
...@@ -888,18 +1036,6 @@ TEST_P(BlitFramebufferANGLETest, Errors) ...@@ -888,18 +1036,6 @@ TEST_P(BlitFramebufferANGLETest, Errors)
glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(), glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
GL_COLOR_BUFFER_BIT, GL_NEAREST); GL_COLOR_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_ERROR(GL_INVALID_OPERATION); EXPECT_GL_ERROR(GL_INVALID_OPERATION);
if (extensionEnabled("GL_ANGLE_framebuffer_multisample"))
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, mBGRAMultisampledFBO);
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, mRGBAFBO);
EXPECT_GL_NO_ERROR();
glBlitFramebufferANGLE(0, 0, getWindowWidth(), getWindowHeight(), 0, 0, getWindowWidth(), getWindowHeight(),
GL_COLOR_BUFFER_BIT, GL_NEAREST);
EXPECT_GL_ERROR(GL_INVALID_OPERATION);
}
} }
// TODO(geofflang): Fix the dependence on glBlitFramebufferANGLE without checks and assuming the // TODO(geofflang): Fix the dependence on glBlitFramebufferANGLE without checks and assuming the
...@@ -1070,6 +1206,8 @@ TEST_P(BlitFramebufferTest, MultisampleStencil) ...@@ -1070,6 +1206,8 @@ TEST_P(BlitFramebufferTest, MultisampleStencil)
ANGLE_INSTANTIATE_TEST(BlitFramebufferANGLETest, ANGLE_INSTANTIATE_TEST(BlitFramebufferANGLETest,
ES2_D3D9(), ES2_D3D9(),
ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE), ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_COPY_ANGLE),
ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE)); ES2_D3D11(EGL_EXPERIMENTAL_PRESENT_PATH_FAST_ANGLE),
ES2_OPENGL(),
ES3_OPENGL());
ANGLE_INSTANTIATE_TEST(BlitFramebufferTest, ES3_D3D11()); ANGLE_INSTANTIATE_TEST(BlitFramebufferTest, ES3_D3D11());
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