Commit 166875eb by Jeff Gilbert Committed by Commit Bot

Don't clamp in glBlendColor if context supports renderable [half-]float.

Add test for glBlendColor >1.0, skipped on D3D9 since it's unsupportable there. Bug: angleproject:3323 Change-Id: I3fcf867dae96bdadf8a0183269d8f27b659d0baf Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1541723Reviewed-by: 's avatarJonah Ryan-Davis <jonahr@google.com> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Commit-Queue: Jeff Gilbert <jgilbert@mozilla.com>
parent a61e273a
...@@ -4924,7 +4924,7 @@ void Context::blendBarrier() ...@@ -4924,7 +4924,7 @@ void Context::blendBarrier()
void Context::blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha) void Context::blendColor(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha)
{ {
mState.setBlendColor(clamp01(red), clamp01(green), clamp01(blue), clamp01(alpha)); mState.setBlendColor(red, green, blue, alpha);
} }
void Context::blendEquation(GLenum mode) void Context::blendEquation(GLenum mode)
......
...@@ -725,6 +725,20 @@ void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha ...@@ -725,6 +725,20 @@ void State::setBlendFactors(GLenum sourceRGB, GLenum destRGB, GLenum sourceAlpha
void State::setBlendColor(float red, float green, float blue, float alpha) void State::setBlendColor(float red, float green, float blue, float alpha)
{ {
// In ES2 without render-to-float extensions, BlendColor clamps to [0,1] on store.
// On ES3+, or with render-to-float exts enabled, it does not clamp on store.
const bool isES2 = mClientVersion.major == 2;
const bool hasFloatBlending =
mExtensions.colorBufferFloat || mExtensions.colorBufferHalfFloat ||
mExtensions.colorBufferFloatRGB || mExtensions.colorBufferFloatRGBA;
if (isES2 && !hasFloatBlending)
{
red = clamp01(red);
green = clamp01(green);
blue = clamp01(blue);
alpha = clamp01(alpha);
}
mBlendColor.red = red; mBlendColor.red = red;
mBlendColor.green = green; mBlendColor.green = green;
mBlendColor.blue = blue; mBlendColor.blue = blue;
......
...@@ -215,18 +215,19 @@ void main() ...@@ -215,18 +215,19 @@ void main()
0, 0, GLColor32F(floatData[0], floatData[1], floatData[2], floatData[3]), 1.0f); 0, 0, GLColor32F(floatData[0], floatData[1], floatData[2], floatData[3]), 1.0f);
} }
void TestExtFloatBlend(bool shouldBlend) void TestExtFloatBlend(GLenum internalFormat, GLenum type, bool shouldBlend)
{ {
constexpr char kVS[] = constexpr char kVS[] =
R"(void main() R"(void main()
{ {
gl_PointSize = 1.0;
gl_Position = vec4(0, 0, 0, 1); gl_Position = vec4(0, 0, 0, 1);
})"; })";
constexpr char kFS[] = constexpr char kFS[] =
R"(void main() R"(void main()
{ {
gl_FragColor = vec4(0, 1, 0, 1); gl_FragColor = vec4(0.5, 0, 0, 0);
})"; })";
ANGLE_GL_PROGRAM(program, kVS, kFS); ANGLE_GL_PROGRAM(program, kVS, kFS);
...@@ -234,7 +235,7 @@ void main() ...@@ -234,7 +235,7 @@ void main()
GLTexture texture; GLTexture texture;
glBindTexture(GL_TEXTURE_2D, texture); glBindTexture(GL_TEXTURE_2D, texture);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA32F, 1, 1, 0, GL_RGBA, GL_FLOAT, nullptr); glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, 1, 1, 0, GL_RGBA, type, nullptr);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
GLFramebuffer fbo; GLFramebuffer fbo;
...@@ -242,20 +243,37 @@ void main() ...@@ -242,20 +243,37 @@ void main()
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0); glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
ASSERT_EGLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER)); ASSERT_EGLENUM_EQ(GL_FRAMEBUFFER_COMPLETE, glCheckFramebufferStatus(GL_FRAMEBUFFER));
glClearColor(1, 0, 1, 1);
glClear(GL_COLOR_BUFFER_BIT);
EXPECT_PIXEL_COLOR32F_NEAR(0, 0, GLColor32F(1, 0, 1, 1), 0.001f);
glDisable(GL_BLEND); glDisable(GL_BLEND);
glDrawArrays(GL_POINTS, 0, 1); glDrawArrays(GL_POINTS, 0, 1);
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_CONSTANT_COLOR, GL_ZERO);
glBlendColor(10, 1, 1, 1);
glViewport(0, 0, 1, 1);
glDrawArrays(GL_POINTS, 0, 1); glDrawArrays(GL_POINTS, 0, 1);
if (shouldBlend) if (!shouldBlend)
{ {
EXPECT_GL_NO_ERROR(); EXPECT_GL_ERROR(GL_INVALID_OPERATION);
return;
} }
else EXPECT_GL_NO_ERROR();
if (!IsOpenGLES())
{ {
EXPECT_GL_ERROR(GL_INVALID_OPERATION); // GLES test machines will need a workaround.
EXPECT_PIXEL_COLOR32F_NEAR(0, 0, GLColor32F(5, 0, 0, 0), 0.001f);
} }
// Check sure that non-float attachments clamp BLEND_COLOR.
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 1, 1, 0, GL_RGBA, GL_UNSIGNED_BYTE, nullptr);
glDrawArrays(GL_POINTS, 0, 1);
EXPECT_PIXEL_COLOR_NEAR(0, 0, GLColor(0x80, 0, 0, 0), 1);
} }
void TestDifferentStencilMaskAndRef(GLenum errIfMismatch); void TestDifferentStencilMaskAndRef(GLenum errIfMismatch);
...@@ -3133,27 +3151,81 @@ void main() ...@@ -3133,27 +3151,81 @@ void main()
EXPECT_GL_NO_ERROR(); EXPECT_GL_NO_ERROR();
} }
static void TestBlendColor(const bool shouldClamp)
{
auto expected = GLColor32F(5, 0, 0, 0);
glBlendColor(expected.R, expected.G, expected.B, expected.A);
if (shouldClamp)
{
expected.R = 1;
}
float arr[4] = {};
glGetFloatv(GL_BLEND_COLOR, arr);
const auto actual = GLColor32F(arr[0], arr[1], arr[2], arr[3]);
EXPECT_COLOR_NEAR(expected, actual, 0.001);
}
// Test if blending of float32 color attachment generates GL_INVALID_OPERATION when // Test if blending of float32 color attachment generates GL_INVALID_OPERATION when
// GL_EXT_float_blend is not enabled // GL_EXT_float_blend is not enabled
TEST_P(WebGLCompatibilityTest, FloatBlend) TEST_P(WebGLCompatibilityTest, FloatBlend)
{ {
ANGLE_SKIP_TEST_IF(!IsGLExtensionRequestable("GL_EXT_float_blend"));
if (getClientMajorVersion() >= 3) if (getClientMajorVersion() >= 3)
{ {
TestBlendColor(false);
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float"));
} }
else else
{ {
TestBlendColor(true);
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_float")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_float"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba")); ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_CHROMIUM_color_buffer_float_rgba"));
} }
TestExtFloatBlend(false); TestBlendColor(false);
// -
glRequestExtensionANGLE("GL_EXT_float_blend"); TestExtFloatBlend(GL_RGBA32F, GL_FLOAT, false);
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_float_blend"));
ASSERT_GL_NO_ERROR(); ASSERT_GL_NO_ERROR();
TestExtFloatBlend(true); // D3D9 supports float rendering explicitly, supports blending operations in practice,
// but cannot support float blend colors.
ANGLE_SKIP_TEST_IF(IsD3D9());
TestExtFloatBlend(GL_RGBA32F, GL_FLOAT, true);
}
// Test the blending of float16 color attachments
TEST_P(WebGLCompatibilityTest, HalfFloatBlend)
{
GLenum internalFormat = GL_RGBA16F;
GLenum type = GL_FLOAT;
if (getClientMajorVersion() >= 3)
{
TestBlendColor(false);
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_float"));
}
else
{
TestBlendColor(true);
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_OES_texture_half_float"));
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_color_buffer_half_float"));
internalFormat = GL_RGBA;
type = GL_HALF_FLOAT_OES;
}
TestBlendColor(false);
// -
// D3D9 supports float rendering explicitly, supports blending operations in practice,
// but cannot support float blend colors.
ANGLE_SKIP_TEST_IF(IsD3D9());
TestExtFloatBlend(internalFormat, type, true);
} }
TEST_P(WebGLCompatibilityTest, R16FTextures) TEST_P(WebGLCompatibilityTest, R16FTextures)
......
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