summaryrefslogtreecommitdiffstats
path: root/gpu
diff options
context:
space:
mode:
authorkkinnunen <kkinnunen@nvidia.com>2015-09-04 06:14:57 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-04 13:15:32 +0000
commit28e57fb8caf8c0daf4be0692777aa9229cfdaa8b (patch)
tree263398d22f9b82a03d59bd4b216430039800eda9 /gpu
parentc2d06cbfc33cb4a48d0c78c264de1103fa2fc881 (diff)
downloadchromium_src-28e57fb8caf8c0daf4be0692777aa9229cfdaa8b.zip
chromium_src-28e57fb8caf8c0daf4be0692777aa9229cfdaa8b.tar.gz
chromium_src-28e57fb8caf8c0daf4be0692777aa9229cfdaa8b.tar.bz2
command_buffer: Implement EXT_multisample_compatibility
Implement EXT_multisample_compatibility OpenGL ES extension in command buffer. Skia needs this in order to enable and disable multisampling when using GL path rendering. BUG=506765 Committed: https://crrev.com/e3237bbb682e52f92d5bd18dcab672677e4e3bc4 Cr-Commit-Position: refs/heads/master@{#346847} Review URL: https://codereview.chromium.org/1231673006 Cr-Commit-Position: refs/heads/master@{#347390}
Diffstat (limited to 'gpu')
-rw-r--r--gpu/BUILD.gn1
-rw-r--r--gpu/GLES2/gl2extchromium.h6
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py41
-rw-r--r--gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h6
-rw-r--r--gpu/command_buffer/service/context_state_autogen.h15
-rw-r--r--gpu/command_buffer/service/context_state_impl_autogen.h54
-rw-r--r--gpu/command_buffer/service/feature_info.cc45
-rw-r--r--gpu/command_buffer/service/feature_info.h1
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_autogen.h16
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h6
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc22
-rw-r--r--gpu/command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc3
-rw-r--r--gpu/command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc296
-rw-r--r--gpu/gpu.gyp1
14 files changed, 484 insertions, 29 deletions
diff --git a/gpu/BUILD.gn b/gpu/BUILD.gn
index dbd236c..4a1f543 100644
--- a/gpu/BUILD.gn
+++ b/gpu/BUILD.gn
@@ -126,6 +126,7 @@ test("gl_tests") {
"command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc",
"command_buffer/tests/gl_cube_map_texture_unittest.cc",
"command_buffer/tests/gl_depth_texture_unittest.cc",
+ "command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc",
"command_buffer/tests/gl_gpu_memory_buffer_unittest.cc",
"command_buffer/tests/gl_lose_context_chromium_unittest.cc",
"command_buffer/tests/gl_manager.cc",
diff --git a/gpu/GLES2/gl2extchromium.h b/gpu/GLES2/gl2extchromium.h
index 157458c..a04355a 100644
--- a/gpu/GLES2/gl2extchromium.h
+++ b/gpu/GLES2/gl2extchromium.h
@@ -987,6 +987,12 @@ typedef void(GL_APIENTRYP* PFNGLSTENCILTHENCOVERSTROKEPATHCHROMIUMPROC)(
#endif /* GL_CHROMIUM_path_rendering */
+#ifndef GL_EXT_multisample_compatibility
+#define GL_EXT_multisample_compatibility 1
+#define GL_MULTISAMPLE_EXT 0x809D
+#define GL_SAMPLE_ALPHA_TO_ONE_EXT 0x809F
+#endif /* GL_EXT_multisample_compatiblity */
+
#ifdef __cplusplus
}
#endif
diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py
index ae927d4..e9e18ff 100755
--- a/gpu/command_buffer/build_gles2_cmd_buffer.py
+++ b/gpu/command_buffer/build_gles2_cmd_buffer.py
@@ -84,6 +84,10 @@ _CAPABILITY_FLAGS = [
'state_flag': 'framebuffer_state_.clear_state_dirty'},
{'name': 'rasterizer_discard', 'es3': True},
{'name': 'primitive_restart_fixed_index', 'es3': True},
+ {'name': 'multisample_ext', 'default': True,
+ 'extension_flag': 'ext_multisample_compatibility'},
+ {'name': 'sample_alpha_to_one_ext',
+ 'extension_flag': 'ext_multisample_compatibility'},
]
_STATES = {
@@ -1087,9 +1091,11 @@ _NAMED_TYPE_INFO = {
'Capability': {
'type': 'GLenum',
'valid': ["GL_%s" % cap['name'].upper() for cap in _CAPABILITY_FLAGS
- if 'es3' not in cap or cap['es3'] != True],
+ if ('es3' not in cap or cap['es3'] != True)
+ and 'extension_flag' not in cap],
'valid_es3': ["GL_%s" % cap['name'].upper() for cap in _CAPABILITY_FLAGS
- if 'es3' in cap and cap['es3'] == True],
+ if ('es3' in cap and cap['es3'] == True)
+ and 'extension_flag' not in cap],
'invalid': [
'GL_CLIP_PLANE0',
'GL_POINT_SPRITE',
@@ -9892,6 +9898,8 @@ class GLGenerator(object):
f.write("struct EnableFlags {\n")
f.write(" EnableFlags();\n")
for capability in _CAPABILITY_FLAGS:
+ if 'extension_flag' in capability:
+ continue
f.write(" bool %s;\n" % capability['name'])
f.write("};\n\n")
self.generated_cpp_filenames.append(filename)
@@ -9997,6 +10005,9 @@ void ContextState::InitCapabilities(const ContextState* prev_state) const {
capability_es3 = 'es3' in capability and capability['es3'] == True
if capability_es3 and not es3_caps or not capability_es3 and es3_caps:
continue
+ if 'extension_flag' in capability:
+ f.write(" if (feature_info_->feature_flags().%s) {\n " %
+ capability['extension_flag'])
if test_prev:
f.write(""" if (prev_state->enable_flags.cached_%s !=
enable_flags.cached_%s) {\n""" %
@@ -10005,6 +10016,8 @@ void ContextState::InitCapabilities(const ContextState* prev_state) const {
(capability_name.upper(), capability_name))
if test_prev:
f.write(" }")
+ if 'extension_flag' in capability:
+ f.write(" }")
f.write(" if (prev_state) {")
WriteCapabilities(True, False)
@@ -10130,6 +10143,8 @@ void ContextState::InitState(const ContextState *prev_state) const {
with CHeaderWriter(filename, comment) as f:
code = []
for capability in _CAPABILITY_FLAGS:
+ if 'extension_flag' in capability:
+ continue
code.append("%s(%s)" %
(capability['name'],
('false', 'true')['default' in capability]))
@@ -10145,6 +10160,8 @@ bool ClientContextState::SetCapabilityState(
switch (cap) {
""")
for capability in _CAPABILITY_FLAGS:
+ if 'extension_flag' in capability:
+ continue
f.write(" case GL_%s:\n" % capability['name'].upper())
f.write(""" if (enable_flags.%(name)s != enabled) {
*changed = true;
@@ -10162,6 +10179,8 @@ bool ClientContextState::SetCapabilityState(
switch (cap) {
""")
for capability in _CAPABILITY_FLAGS:
+ if 'extension_flag' in capability:
+ continue
f.write(" case GL_%s:\n" % capability['name'].upper())
f.write(" *enabled = enable_flags.%s;\n" % capability['name'])
f.write(" return true;\n")
@@ -10259,11 +10278,17 @@ bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
bool es3_capable) {""")
for capability in _CAPABILITY_FLAGS:
capability_es3 = 'es3' in capability and capability['es3'] == True
- if not capability_es3:
- f.write(" ExpectEnableDisable(GL_%s, %s);\n" %
- (capability['name'].upper(),
- ('false', 'true')['default' in capability]))
-
+ if capability_es3:
+ continue
+ if 'extension_flag' in capability:
+ f.write(" if (group_->feature_info()->feature_flags().%s) {\n" %
+ capability['extension_flag'])
+ f.write(" ")
+ f.write(" ExpectEnableDisable(GL_%s, %s);\n" %
+ (capability['name'].upper(),
+ ('false', 'true')['default' in capability]))
+ if 'extension_flag' in capability:
+ f.write(" }")
f.write(" if (es3_capable) {")
for capability in _CAPABILITY_FLAGS:
capability_es3 = 'es3' in capability and capability['es3'] == True
@@ -10909,6 +10934,8 @@ def main(argv):
if not item['enum'] in gl_state_valid:
gl_state_valid.append(item['enum'])
for capability in _CAPABILITY_FLAGS:
+ if 'extension_flag' in capability:
+ continue
valid_value = "GL_%s" % capability['name'].upper()
if not valid_value in gl_state_valid:
gl_state_valid.append(valid_value)
diff --git a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
index 2af659e..b9cde956 100644
--- a/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
+++ b/gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h
@@ -1822,6 +1822,9 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
0x8C1D, "GL_TEXTURE_BINDING_2D_ARRAY",
},
{
+ 0x809F, "GL_SAMPLE_ALPHA_TO_ONE_EXT",
+ },
+ {
0x8DDF, "GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT",
},
{
@@ -3358,6 +3361,9 @@ static const GLES2Util::EnumToString enum_to_string_table[] = {
0x8823, "GL_WRITEONLY_RENDERING_QCOM",
},
{
+ 0x809D, "GL_MULTISAMPLE_EXT",
+ },
+ {
0x8824, "GL_MAX_DRAW_BUFFERS_EXT",
},
{
diff --git a/gpu/command_buffer/service/context_state_autogen.h b/gpu/command_buffer/service/context_state_autogen.h
index 7ca2faa..7278a24 100644
--- a/gpu/command_buffer/service/context_state_autogen.h
+++ b/gpu/command_buffer/service/context_state_autogen.h
@@ -36,6 +36,10 @@ struct EnableFlags {
bool cached_rasterizer_discard;
bool primitive_restart_fixed_index;
bool cached_primitive_restart_fixed_index;
+ bool multisample_ext;
+ bool cached_multisample_ext;
+ bool sample_alpha_to_one_ext;
+ bool cached_sample_alpha_to_one_ext;
};
GLfloat blend_color_red;
@@ -169,6 +173,17 @@ inline void SetDeviceCapabilityState(GLenum cap, bool enable) {
return;
enable_flags.cached_primitive_restart_fixed_index = enable;
break;
+ case GL_MULTISAMPLE_EXT:
+ if (enable_flags.cached_multisample_ext == enable && !ignore_cached_state)
+ return;
+ enable_flags.cached_multisample_ext = enable;
+ break;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ if (enable_flags.cached_sample_alpha_to_one_ext == enable &&
+ !ignore_cached_state)
+ return;
+ enable_flags.cached_sample_alpha_to_one_ext = enable;
+ break;
default:
NOTREACHED();
return;
diff --git a/gpu/command_buffer/service/context_state_impl_autogen.h b/gpu/command_buffer/service/context_state_impl_autogen.h
index 450f0e2..ce9f70f 100644
--- a/gpu/command_buffer/service/context_state_impl_autogen.h
+++ b/gpu/command_buffer/service/context_state_impl_autogen.h
@@ -34,7 +34,11 @@ ContextState::EnableFlags::EnableFlags()
rasterizer_discard(false),
cached_rasterizer_discard(false),
primitive_restart_fixed_index(false),
- cached_primitive_restart_fixed_index(false) {}
+ cached_primitive_restart_fixed_index(false),
+ multisample_ext(true),
+ cached_multisample_ext(true),
+ sample_alpha_to_one_ext(false),
+ cached_sample_alpha_to_one_ext(false) {}
void ContextState::Initialize() {
blend_color_red = 0.0f;
@@ -176,6 +180,19 @@ void ContextState::InitCapabilities(const ContextState* prev_state) const {
enable_flags.cached_stencil_test) {
EnableDisable(GL_STENCIL_TEST, enable_flags.cached_stencil_test);
}
+ if (feature_info_->feature_flags().ext_multisample_compatibility) {
+ if (prev_state->enable_flags.cached_multisample_ext !=
+ enable_flags.cached_multisample_ext) {
+ EnableDisable(GL_MULTISAMPLE_EXT, enable_flags.cached_multisample_ext);
+ }
+ }
+ if (feature_info_->feature_flags().ext_multisample_compatibility) {
+ if (prev_state->enable_flags.cached_sample_alpha_to_one_ext !=
+ enable_flags.cached_sample_alpha_to_one_ext) {
+ EnableDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT,
+ enable_flags.cached_sample_alpha_to_one_ext);
+ }
+ }
if (feature_info_->IsES3Capable()) {
if (prev_state->enable_flags.cached_rasterizer_discard !=
enable_flags.cached_rasterizer_discard) {
@@ -200,6 +217,13 @@ void ContextState::InitCapabilities(const ContextState* prev_state) const {
EnableDisable(GL_SAMPLE_COVERAGE, enable_flags.cached_sample_coverage);
EnableDisable(GL_SCISSOR_TEST, enable_flags.cached_scissor_test);
EnableDisable(GL_STENCIL_TEST, enable_flags.cached_stencil_test);
+ if (feature_info_->feature_flags().ext_multisample_compatibility) {
+ EnableDisable(GL_MULTISAMPLE_EXT, enable_flags.cached_multisample_ext);
+ }
+ if (feature_info_->feature_flags().ext_multisample_compatibility) {
+ EnableDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT,
+ enable_flags.cached_sample_alpha_to_one_ext);
+ }
if (feature_info_->IsES3Capable()) {
EnableDisable(GL_RASTERIZER_DISCARD,
enable_flags.cached_rasterizer_discard);
@@ -408,6 +432,10 @@ bool ContextState::GetEnabled(GLenum cap) const {
return enable_flags.rasterizer_discard;
case GL_PRIMITIVE_RESTART_FIXED_INDEX:
return enable_flags.primitive_restart_fixed_index;
+ case GL_MULTISAMPLE_EXT:
+ return enable_flags.multisample_ext;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ return enable_flags.sample_alpha_to_one_ext;
default:
NOTREACHED();
return false;
@@ -781,6 +809,18 @@ bool ContextState::GetStateAsGLint(GLenum pname,
static_cast<GLint>(enable_flags.primitive_restart_fixed_index);
}
return true;
+ case GL_MULTISAMPLE_EXT:
+ *num_written = 1;
+ if (params) {
+ params[0] = static_cast<GLint>(enable_flags.multisample_ext);
+ }
+ return true;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *num_written = 1;
+ if (params) {
+ params[0] = static_cast<GLint>(enable_flags.sample_alpha_to_one_ext);
+ }
+ return true;
default:
return false;
}
@@ -1149,6 +1189,18 @@ bool ContextState::GetStateAsGLfloat(GLenum pname,
static_cast<GLfloat>(enable_flags.primitive_restart_fixed_index);
}
return true;
+ case GL_MULTISAMPLE_EXT:
+ *num_written = 1;
+ if (params) {
+ params[0] = static_cast<GLfloat>(enable_flags.multisample_ext);
+ }
+ return true;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ *num_written = 1;
+ if (params) {
+ params[0] = static_cast<GLfloat>(enable_flags.sample_alpha_to_one_ext);
+ }
+ return true;
default:
return false;
}
diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc
index b3c5be6..49b6e85 100644
--- a/gpu/command_buffer/service/feature_info.cc
+++ b/gpu/command_buffer/service/feature_info.cc
@@ -171,7 +171,8 @@ FeatureInfo::FeatureFlags::FeatureFlags()
chromium_image_ycbcr_422(false),
enable_subscribe_uniform(false),
emulate_primitive_restart_fixed_index(false),
- ext_render_buffer_format_bgra8888(false) {}
+ ext_render_buffer_format_bgra8888(false),
+ ext_multisample_compatibility(false) {}
FeatureInfo::Workarounds::Workarounds() :
#define GPU_OP(type, name) name(false),
@@ -694,26 +695,32 @@ void FeatureInfo::InitializeFeatures() {
}
// Check for multisample support
- if (!workarounds_.disable_chromium_framebuffer_multisample) {
- bool ext_has_multisample =
- extensions.Contains("GL_EXT_framebuffer_multisample") ||
- gl_version_info_->is_es3 ||
- gl_version_info_->is_desktop_core_profile;
- if (gl_version_info_->is_angle) {
- ext_has_multisample |=
- extensions.Contains("GL_ANGLE_framebuffer_multisample");
- }
+ bool ext_has_multisample =
+ !workarounds_.disable_chromium_framebuffer_multisample &&
+ (extensions.Contains("GL_EXT_framebuffer_multisample") ||
+ gl_version_info_->is_es3 || gl_version_info_->is_desktop_core_profile ||
+ (gl_version_info_->is_angle &&
+ extensions.Contains("GL_ANGLE_framebuffer_multisample")));
+
+ if (ext_has_multisample) {
feature_flags_.use_core_framebuffer_multisample =
gl_version_info_->is_es3 || gl_version_info_->is_desktop_core_profile;
- if (ext_has_multisample) {
- feature_flags_.chromium_framebuffer_multisample = true;
- validators_.frame_buffer_target.AddValue(GL_READ_FRAMEBUFFER_EXT);
- validators_.frame_buffer_target.AddValue(GL_DRAW_FRAMEBUFFER_EXT);
- validators_.g_l_state.AddValue(GL_READ_FRAMEBUFFER_BINDING_EXT);
- validators_.g_l_state.AddValue(GL_MAX_SAMPLES_EXT);
- validators_.render_buffer_parameter.AddValue(GL_RENDERBUFFER_SAMPLES_EXT);
- AddExtensionString("GL_CHROMIUM_framebuffer_multisample");
- }
+ feature_flags_.chromium_framebuffer_multisample = true;
+ validators_.frame_buffer_target.AddValue(GL_READ_FRAMEBUFFER_EXT);
+ validators_.frame_buffer_target.AddValue(GL_DRAW_FRAMEBUFFER_EXT);
+ validators_.g_l_state.AddValue(GL_READ_FRAMEBUFFER_BINDING_EXT);
+ validators_.g_l_state.AddValue(GL_MAX_SAMPLES_EXT);
+ validators_.render_buffer_parameter.AddValue(GL_RENDERBUFFER_SAMPLES_EXT);
+ AddExtensionString("GL_CHROMIUM_framebuffer_multisample");
+ }
+
+ if (ext_has_multisample &&
+ (!gl_version_info_->is_es ||
+ extensions.Contains("GL_EXT_multisample_compatibility"))) {
+ AddExtensionString("GL_EXT_multisample_compatibility");
+ feature_flags_.ext_multisample_compatibility = true;
+ validators_.capability.AddValue(GL_MULTISAMPLE_EXT);
+ validators_.capability.AddValue(GL_SAMPLE_ALPHA_TO_ONE_EXT);
}
if (!workarounds_.disable_multisampled_render_to_texture) {
diff --git a/gpu/command_buffer/service/feature_info.h b/gpu/command_buffer/service/feature_info.h
index dae148a..68f928a 100644
--- a/gpu/command_buffer/service/feature_info.h
+++ b/gpu/command_buffer/service/feature_info.h
@@ -84,6 +84,7 @@ class GPU_EXPORT FeatureInfo : public base::RefCounted<FeatureInfo> {
bool enable_subscribe_uniform;
bool emulate_primitive_restart_fixed_index;
bool ext_render_buffer_format_bgra8888;
+ bool ext_multisample_compatibility;
};
struct Workarounds {
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
index 797fda6..1684d30 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_autogen.h
@@ -5164,6 +5164,22 @@ bool GLES2DecoderImpl::SetCapabilityState(GLenum cap, bool enabled) {
return true;
}
return false;
+ case GL_MULTISAMPLE_EXT:
+ state_.enable_flags.multisample_ext = enabled;
+ if (state_.enable_flags.cached_multisample_ext != enabled ||
+ state_.ignore_cached_state) {
+ state_.enable_flags.cached_multisample_ext = enabled;
+ return true;
+ }
+ return false;
+ case GL_SAMPLE_ALPHA_TO_ONE_EXT:
+ state_.enable_flags.sample_alpha_to_one_ext = enabled;
+ if (state_.enable_flags.cached_sample_alpha_to_one_ext != enabled ||
+ state_.ignore_cached_state) {
+ state_.enable_flags.cached_sample_alpha_to_one_ext = enabled;
+ return true;
+ }
+ return false;
default:
NOTREACHED();
return false;
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
index dd11716..d934bce 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h
@@ -22,6 +22,12 @@ void GLES2DecoderTestBase::SetupInitCapabilitiesExpectations(bool es3_capable) {
ExpectEnableDisable(GL_SAMPLE_COVERAGE, false);
ExpectEnableDisable(GL_SCISSOR_TEST, false);
ExpectEnableDisable(GL_STENCIL_TEST, false);
+ if (group_->feature_info()->feature_flags().ext_multisample_compatibility) {
+ ExpectEnableDisable(GL_MULTISAMPLE_EXT, true);
+ }
+ if (group_->feature_info()->feature_flags().ext_multisample_compatibility) {
+ ExpectEnableDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT, false);
+ }
if (es3_capable) {
ExpectEnableDisable(GL_RASTERIZER_DISCARD, false);
ExpectEnableDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX, false);
diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
index 916f2aa..352b76a 100644
--- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
+++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc
@@ -185,6 +185,27 @@ INSTANTIATE_TEST_CASE_P(Service,
GLES2DecoderTestWithBlendEquationAdvanced,
::testing::Bool());
+class GLES2DecoderTestWithEXTMultisampleCompatibility
+ : public GLES2DecoderTest {
+ public:
+ GLES2DecoderTestWithEXTMultisampleCompatibility() {}
+
+ void SetUp() override {
+ InitState init;
+ init.gl_version = "opengl es 3.1";
+ init.has_alpha = true;
+ init.has_depth = true;
+ init.request_alpha = true;
+ init.request_depth = true;
+ init.bind_generates_resource = true;
+ init.extensions = "GL_EXT_multisample_compatibility ";
+ InitDecoder(init);
+ }
+};
+INSTANTIATE_TEST_CASE_P(Service,
+ GLES2DecoderTestWithEXTMultisampleCompatibility,
+ ::testing::Bool());
+
TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering, GenDeletePaths) {
static GLuint kFirstClientID = client_path_id_ + 88;
static GLsizei kPathCount = 58;
@@ -997,4 +1018,3 @@ TEST_P(GLES2DecoderTestWithCHROMIUMPathRendering,
} // namespace gles2
} // namespace gpu
-
diff --git a/gpu/command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc b/gpu/command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc
index 9d36a26..8268b66 100644
--- a/gpu/command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc
+++ b/gpu/command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc
@@ -44,7 +44,8 @@ TEST_F(GLChromiumFramebufferMultisampleTest, CachedBindingsTest) {
}
TEST_F(GLChromiumFramebufferMultisampleTest, DrawAndResolve) {
- if (!GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample")) {
+ if (!(GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample") &&
+ GLTestHelper::HasExtension("GL_OES_rgb8_rgba8"))) {
return;
}
diff --git a/gpu/command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc b/gpu/command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc
new file mode 100644
index 0000000..988b0e62
--- /dev/null
+++ b/gpu/command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc
@@ -0,0 +1,296 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <GLES2/gl2.h>
+#include <GLES2/gl2ext.h>
+#include <GLES2/gl2extchromium.h>
+
+#include "gpu/command_buffer/tests/gl_manager.h"
+#include "gpu/command_buffer/tests/gl_test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+#define SHADER0(Src) #Src
+
+namespace {
+uint32 GetPixel(GLint x,
+ GLint y,
+ uint8* r = nullptr,
+ uint8* g = nullptr,
+ uint8* b = nullptr,
+ uint8* a = nullptr) {
+ uint8 pixels[4];
+ memset(pixels, GLTestHelper::kCheckClearValue, sizeof(pixels));
+ glReadPixels(x, y, 1, 1, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
+ if (r) {
+ *r = pixels[0];
+ }
+ if (g) {
+ *g = pixels[1];
+ }
+ if (b) {
+ *b = pixels[2];
+ }
+ if (a) {
+ *a = pixels[3];
+ }
+ uint32 result;
+ memcpy(&result, pixels, sizeof(result));
+ return result;
+}
+} // namespace
+
+namespace gpu {
+
+class EXTMultisampleCompatibilityTest : public testing::Test {
+ public:
+ protected:
+ static const GLuint kWidth = 100;
+ static const GLuint kHeight = 100;
+
+ void SetUp() override { gl_.Initialize(GLManager::Options()); }
+
+ void TearDown() override { gl_.Destroy(); }
+
+ void PrepareForDraw() {
+ static const char* v_shader_str = SHADER0(
+ attribute vec4 a_Position; void main() { gl_Position = a_Position; });
+ static const char* f_shader_str =
+ SHADER0(precision mediump float; uniform vec4 color;
+ void main() { gl_FragColor = color; });
+
+ GLuint program = GLTestHelper::LoadProgram(v_shader_str, f_shader_str);
+ glUseProgram(program);
+ GLuint position_loc = glGetAttribLocation(program, "a_Position");
+ color_loc_ = glGetUniformLocation(program, "color");
+
+ GLuint vbo = 0;
+ glGenBuffers(1, &vbo);
+ glBindBuffer(GL_ARRAY_BUFFER, vbo);
+ static float vertices[] = {
+ 1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f,
+ -1.0f, 1.0f, -1.0f, -1.0f, -1.0f, 1.0f, -1.0f, 1.0f, 1.0f,
+ };
+ glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
+ glEnableVertexAttribArray(position_loc);
+ glVertexAttribPointer(position_loc, 2, GL_FLOAT, GL_FALSE, 0, 0);
+
+ // Create a sample buffer.
+ GLsizei num_samples = 4, max_samples = 0;
+ glGetIntegerv(GL_MAX_SAMPLES, &max_samples);
+ num_samples = std::min(num_samples, max_samples);
+ GLuint sample_rb;
+ glGenRenderbuffers(1, &sample_rb);
+ glBindRenderbuffer(GL_RENDERBUFFER, sample_rb);
+ glRenderbufferStorageMultisampleCHROMIUM(GL_RENDERBUFFER, num_samples,
+ GL_RGBA8_OES, kWidth, kHeight);
+ GLint param = 0;
+ glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES,
+ &param);
+ EXPECT_GE(param, num_samples);
+
+ glGenFramebuffers(1, &sample_fbo_);
+ glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo_);
+ glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
+ GL_RENDERBUFFER, sample_rb);
+ EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+ glCheckFramebufferStatus(GL_FRAMEBUFFER));
+ glBindFramebuffer(GL_FRAMEBUFFER, 0);
+
+ // Create another FBO to resolve the multisample buffer into.
+ GLuint resolve_tex;
+ glGenTextures(1, &resolve_tex);
+ glBindTexture(GL_TEXTURE_2D, resolve_tex);
+ glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, kWidth, kHeight, 0, GL_RGBA,
+ GL_UNSIGNED_BYTE, NULL);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+ glGenFramebuffers(1, &resolve_fbo_);
+ glBindFramebuffer(GL_FRAMEBUFFER, resolve_fbo_);
+ glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
+ resolve_tex, 0);
+ EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE),
+ glCheckFramebufferStatus(GL_FRAMEBUFFER));
+
+ glViewport(0, 0, kWidth, kHeight);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+ glEnable(GL_BLEND);
+ glBindFramebuffer(GL_FRAMEBUFFER, sample_fbo_);
+ glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ }
+
+ void PrepareForVerify() {
+ // Resolve.
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, sample_fbo_);
+ glBindFramebuffer(GL_DRAW_FRAMEBUFFER, resolve_fbo_);
+ glClearColor(1.0f, 0.0f, 0.0f, 0.0f);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glBlitFramebufferCHROMIUM(0, 0, kWidth, kHeight, 0, 0, kWidth, kHeight,
+ GL_COLOR_BUFFER_BIT, GL_NEAREST);
+ glBindFramebuffer(GL_READ_FRAMEBUFFER, resolve_fbo_);
+ }
+
+ bool IsApplicable() const {
+ return GLTestHelper::HasExtension("GL_EXT_multisample_compatibility") &&
+ GLTestHelper::HasExtension("GL_CHROMIUM_framebuffer_multisample") &&
+ GLTestHelper::HasExtension("GL_OES_rgb8_rgba8");
+ }
+ GLuint sample_fbo_;
+ GLuint resolve_fbo_;
+ GLuint color_loc_;
+
+ GLManager gl_;
+};
+
+TEST_F(EXTMultisampleCompatibilityTest, TestSimple) {
+ if (!IsApplicable()) {
+ return;
+ }
+
+ EXPECT_TRUE(glIsEnabled(GL_MULTISAMPLE_EXT));
+ glDisable(GL_MULTISAMPLE_EXT);
+ EXPECT_FALSE(glIsEnabled(GL_MULTISAMPLE_EXT));
+ glEnable(GL_MULTISAMPLE_EXT);
+ EXPECT_TRUE(glIsEnabled(GL_MULTISAMPLE_EXT));
+
+ EXPECT_FALSE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
+ glEnable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+ EXPECT_TRUE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
+ glDisable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+ EXPECT_FALSE(glIsEnabled(GL_SAMPLE_ALPHA_TO_ONE_EXT));
+
+ EXPECT_EQ(static_cast<GLenum>(GL_NO_ERROR), glGetError());
+}
+
+TEST_F(EXTMultisampleCompatibilityTest, DrawAndResolve) {
+ // Test that disabling GL_MULTISAMPLE_EXT is handled correctly.
+ if (!IsApplicable()) {
+ return;
+ }
+ PrepareForDraw();
+
+ static const float kBlue[] = {0.0f, 0.0f, 1.0f, 1.0f};
+ static const float kGreen[] = {0.0f, 1.0f, 0.0f, 1.0f};
+ static const float kRed[] = {1.0f, 0.0f, 0.0f, 1.0f};
+
+ // Green: from top right to bottom left.
+ glUniform4fv(color_loc_, 1, kGreen);
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+
+ // Blue: from top left to bottom right.
+ glUniform4fv(color_loc_, 1, kBlue);
+ glDrawArrays(GL_TRIANGLES, 3, 3);
+
+ // Red, without MSAA: from bottom left to top right.
+ glDisable(GL_MULTISAMPLE_EXT);
+ glUniform4fv(color_loc_, 1, kRed);
+ glDrawArrays(GL_TRIANGLES, 6, 3);
+
+ PrepareForVerify();
+
+ // Top-left: Green triangle hits 50% of the samples. Blue hits 50% of the
+ // samples. The pixel should be {0, 127, 127, 255}. For accuracy reasons,
+ // Test only that multisampling is on, eg. that fractional results result
+ // in <255 pixel value.
+ uint8 r, g, b, a;
+ GetPixel(0, kHeight - 1, &r, &g, &b, &a);
+ EXPECT_EQ(0u, r);
+ EXPECT_GT(255u, g);
+ EXPECT_GT(255u, b);
+ EXPECT_EQ(255u, a);
+
+ // Top-right: Green triangle hits 50% of the samples. Red hits 100% of the
+ // samples, since it is not multisampled. Should be {255, 0, 0, 255}.
+ GetPixel(kWidth - 1, kHeight - 1, &r, &g, &b, &a);
+ EXPECT_EQ(255u, r);
+ EXPECT_EQ(0u, g);
+ EXPECT_EQ(0u, b);
+ EXPECT_EQ(255u, a);
+
+ // Bottom-right: Blue triangle hits 50% of the samples. Red triangle
+ // hits 100% of the samples. Should be {255, 0, 0, 255}.
+ GetPixel(kWidth - 1, 0, &r, &g, &b, &a);
+ EXPECT_EQ(255u, r);
+ EXPECT_EQ(0u, g);
+ EXPECT_EQ(0u, b);
+ EXPECT_EQ(255u, a);
+
+ // Low-left: Green triangle hits 50% of the samples. Blue hits 100% of the
+ // samples. Red hits 100% of the samples, since it is not multisampled.
+ // Should be {255, 0, 0, 255}.
+ GetPixel(0, 0, &r, &g, &b, &a);
+ EXPECT_EQ(255u, r);
+ EXPECT_EQ(0u, g);
+ EXPECT_EQ(0u, b);
+ EXPECT_EQ(255u, a);
+
+ // Middle point: Green triangle hits 50% of the samples, blue 50% of the
+ // samples. Red does not hit.
+ GetPixel(kWidth / 2 - 1, kHeight / 2, &r, &g, &b, &a);
+ EXPECT_EQ(0u, r);
+ EXPECT_GT(255u, g);
+ EXPECT_GT(255u, b);
+ EXPECT_EQ(255u, a);
+}
+
+TEST_F(EXTMultisampleCompatibilityTest, DrawAlphaOneAndResolve) {
+ // Test that enabling GL_SAMPLE_ALPHA_TO_ONE_EXT affects rendering.
+ if (!IsApplicable()) {
+ return;
+ }
+
+ // SAMPLE_ALPHA_TO_ONE is specified to transform alpha values of
+ // covered samples to 1.0. In order to detect it, we use non-1.0
+ // alpha.
+ static const float kBlue[] = {0.0f, 0.0f, 1.0f, 0.5f};
+ static const float kGreen[] = {0.0f, 1.0f, 0.0f, 0.5f};
+ static const float kRed[] = {1.0f, 0.0f, 0.0f, 0.5f};
+
+ // Different drivers seem to behave differently with respect to
+ // resulting alpha value. These might be due to different MSAA
+ // sample counts causing different samples to hit. Testing exact or
+ // even approximate sample values is not that easy. Thus, just test
+ // representative positions which have fractional pixels, inspecting
+ // that normal rendering is different to SAMPLE_ALPHA_TO_ONE
+ // rendering.
+ uint32 result[2][5];
+
+ for (int pass = 0; pass < 2; ++pass) {
+ PrepareForDraw();
+ if (pass == 1) {
+ glEnable(GL_SAMPLE_ALPHA_TO_ONE_EXT);
+ }
+ glUniform4fv(color_loc_, 1, kGreen);
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+
+ glUniform4fv(color_loc_, 1, kBlue);
+ glDrawArrays(GL_TRIANGLES, 3, 3);
+
+ glDisable(GL_MULTISAMPLE_EXT);
+ glUniform4fv(color_loc_, 1, kRed);
+ glDrawArrays(GL_TRIANGLES, 6, 3);
+
+ PrepareForVerify();
+
+ // Top-left.
+ result[pass][0] = GetPixel(0, kHeight - 1);
+ // Top-right.
+ result[pass][1] = GetPixel(kWidth - 1, kHeight - 1);
+ // Bottom-right.
+ result[pass][2] = GetPixel(kWidth - 1, 0);
+ // Low-left.
+ result[pass][3] = GetPixel(1, 1);
+ // Middle point.
+ result[pass][4] = GetPixel(kWidth / 2 - 1, kHeight / 2);
+ }
+ EXPECT_NE(result[0][0], result[1][0]);
+ EXPECT_NE(result[0][1], result[1][1]);
+ EXPECT_NE(result[0][2], result[1][2]);
+ EXPECT_NE(result[0][3], result[1][3]);
+ EXPECT_NE(result[0][4], result[1][4]);
+}
+
+} // namespace gpu
diff --git a/gpu/gpu.gyp b/gpu/gpu.gyp
index 48a7794..e002848 100644
--- a/gpu/gpu.gyp
+++ b/gpu/gpu.gyp
@@ -359,6 +359,7 @@
'command_buffer/tests/gl_copy_texture_CHROMIUM_unittest.cc',
'command_buffer/tests/gl_cube_map_texture_unittest.cc',
'command_buffer/tests/gl_depth_texture_unittest.cc',
+ 'command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc',
'command_buffer/tests/gl_gpu_memory_buffer_unittest.cc',
'command_buffer/tests/gl_lose_context_chromium_unittest.cc',
'command_buffer/tests/gl_manager.cc',