diff options
author | kkinnunen <kkinnunen@nvidia.com> | 2015-09-04 06:14:57 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-04 13:15:32 +0000 |
commit | 28e57fb8caf8c0daf4be0692777aa9229cfdaa8b (patch) | |
tree | 263398d22f9b82a03d59bd4b216430039800eda9 | |
parent | c2d06cbfc33cb4a48d0c78c264de1103fa2fc881 (diff) | |
download | chromium_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}
-rw-r--r-- | gpu/BUILD.gn | 1 | ||||
-rw-r--r-- | gpu/GLES2/gl2extchromium.h | 6 | ||||
-rwxr-xr-x | gpu/command_buffer/build_gles2_cmd_buffer.py | 41 | ||||
-rw-r--r-- | gpu/command_buffer/common/gles2_cmd_utils_implementation_autogen.h | 6 | ||||
-rw-r--r-- | gpu/command_buffer/service/context_state_autogen.h | 15 | ||||
-rw-r--r-- | gpu/command_buffer/service/context_state_impl_autogen.h | 54 | ||||
-rw-r--r-- | gpu/command_buffer/service/feature_info.cc | 45 | ||||
-rw-r--r-- | gpu/command_buffer/service/feature_info.h | 1 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_autogen.h | 16 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest_0_autogen.h | 6 | ||||
-rw-r--r-- | gpu/command_buffer/service/gles2_cmd_decoder_unittest_extensions.cc | 22 | ||||
-rw-r--r-- | gpu/command_buffer/tests/gl_chromium_framebuffer_multisample_unittest.cc | 3 | ||||
-rw-r--r-- | gpu/command_buffer/tests/gl_ext_multisample_compatibility_unittest.cc | 296 | ||||
-rw-r--r-- | gpu/gpu.gyp | 1 | ||||
-rw-r--r-- | ui/gl/gl_bindings.h | 6 | ||||
-rw-r--r-- | ui/gl/gl_enums_implementation_autogen.h | 11 |
16 files changed, 500 insertions, 30 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, + ¶m); + 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', diff --git a/ui/gl/gl_bindings.h b/ui/gl/gl_bindings.h index 0972598..008c994 100644 --- a/ui/gl/gl_bindings.h +++ b/ui/gl/gl_bindings.h @@ -258,6 +258,12 @@ #define GL_PATH_STENCIL_VALUE_MASK_CHROMIUM 0x90B9 #endif +#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_compatibility */ + #ifndef GL_KHR_blend_equation_advanced #define GL_KHR_blend_equation_advanced 1 #define GL_COLORBURN_KHR 0x929A diff --git a/ui/gl/gl_enums_implementation_autogen.h b/ui/gl/gl_enums_implementation_autogen.h index de370da..6fd72a9 100644 --- a/ui/gl/gl_enums_implementation_autogen.h +++ b/ui/gl/gl_enums_implementation_autogen.h @@ -247,6 +247,9 @@ static const GLEnums::EnumToString enum_to_string_table[] = { 0x8A53, "GL_SYNC_OBJECT_APPLE", }, { + 0x78FB, "GL_RGB_YCBCR_422_CHROMIUM", + }, + { 0x8DF8, "GL_SHADER_BINARY_FORMATS", }, { @@ -403,7 +406,7 @@ static const GLEnums::EnumToString enum_to_string_table[] = { 0x821A, "GL_DEPTH_STENCIL_ATTACHMENT", }, { - 0x8A40, "GL_UNIFORM_BLOCK_DATA_SIZE", + 0x809D, "GL_MULTISAMPLE_EXT", }, { 0x821D, "GL_NUM_EXTENSIONS", @@ -1825,6 +1828,9 @@ static const GLEnums::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", }, { @@ -2806,6 +2812,9 @@ static const GLEnums::EnumToString enum_to_string_table[] = { 0x8051, "GL_RGB8_OES", }, { + 0x8A40, "GL_UNIFORM_BLOCK_DATA_SIZE", + }, + { 0x8CAD, "GL_DEPTH32F_STENCIL8", }, { |