diff options
35 files changed, 772 insertions, 246 deletions
diff --git a/content/common/gpu/image_transport_surface_calayer_mac.h b/content/common/gpu/image_transport_surface_calayer_mac.h index 47aaeb0..bb7c3a8 100644 --- a/content/common/gpu/image_transport_surface_calayer_mac.h +++ b/content/common/gpu/image_transport_surface_calayer_mac.h @@ -8,7 +8,6 @@ #include "base/mac/scoped_nsobject.h" #include "content/common/gpu/image_transport_surface_fbo_mac.h" #include "ui/base/cocoa/remote_layer_api.h" -#include "ui/gl/gl_bindings.h" #include "ui/gl/gpu_switching_observer.h" #include "ui/gl/scoped_cgl.h" @@ -78,6 +77,15 @@ class CALayerStorageProvider gfx::Size fbo_pixel_size_; float fbo_scale_factor_; + // State for the Core Profile code path. + GLuint program_; + GLuint vertex_shader_; + GLuint fragment_shader_; + GLuint position_location_; + GLuint tex_location_; + GLuint vertex_buffer_; + GLuint vertex_array_; + // The CALayer that the current frame is being drawn into. base::scoped_nsobject<CAContext> context_; base::scoped_nsobject<ImageTransportLayer> layer_; diff --git a/content/common/gpu/image_transport_surface_calayer_mac.mm b/content/common/gpu/image_transport_surface_calayer_mac.mm index afcfc56..88e85b2 100644 --- a/content/common/gpu/image_transport_surface_calayer_mac.mm +++ b/content/common/gpu/image_transport_surface_calayer_mac.mm @@ -104,6 +104,13 @@ CALayerStorageProvider::CALayerStorageProvider( can_draw_returned_false_count_(0), fbo_texture_(0), fbo_scale_factor_(1), + program_(0), + vertex_shader_(0), + fragment_shader_(0), + position_location_(0), + tex_location_(0), + vertex_buffer_(0), + vertex_array_(0), recreate_layer_after_gpu_switch_(false), pending_draw_weak_factory_(this) { ui::GpuSwitchingManager::GetInstance()->AddObserver(this); @@ -126,16 +133,109 @@ bool CALayerStorageProvider::AllocateColorBufferStorage( LOG(ERROR) << "OpenGL error hit but ignored before allocating buffer " << "storage: " << error; } - glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, - 0, - GL_RGBA, - pixel_size.width(), - pixel_size.height(), - 0, - GL_RGBA, - GL_UNSIGNED_BYTE, - NULL); - glFlush(); + + if (gfx::GetGLImplementation() == + gfx::kGLImplementationDesktopGLCoreProfile) { + glTexImage2D(GL_TEXTURE_2D, + 0, + GL_RGBA, + pixel_size.width(), + pixel_size.height(), + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + NULL); + glFlush(); + + if (!vertex_shader_) { + const char* source = + "#version 150\n" + "in vec4 position;\n" + "out vec2 texcoord;\n" + "void main() {\n" + " texcoord = vec2(position.x, position.y);\n" + " gl_Position = vec4(2*position.x-1, 2*position.y-1,\n" + " position.z, position.w);\n" + "}\n"; + vertex_shader_ = glCreateShader(GL_VERTEX_SHADER); + glShaderSource(vertex_shader_, 1, &source, NULL); + glCompileShader(vertex_shader_); +#if DCHECK_IS_ON() + GLint status = GL_FALSE; + glGetShaderiv(vertex_shader_, GL_COMPILE_STATUS, &status); + DCHECK(status == GL_TRUE); +#endif + } + if (!fragment_shader_) { + const char* source = + "#version 150\n" + "uniform sampler2D tex;\n" + "in vec2 texcoord;\n" + "out vec4 frag_color;\n" + "void main() {\n" + " frag_color = texture(tex, texcoord);\n" + "}\n"; + fragment_shader_ = glCreateShader(GL_FRAGMENT_SHADER); + glShaderSource(fragment_shader_, 1, &source, NULL); + glCompileShader(fragment_shader_); +#if DCHECK_IS_ON() + GLint status = GL_FALSE; + glGetShaderiv(fragment_shader_, GL_COMPILE_STATUS, &status); + DCHECK(status == GL_TRUE); +#endif + } + if (!program_) { + program_ = glCreateProgram(); + glAttachShader(program_, vertex_shader_); + glAttachShader(program_, fragment_shader_); + glBindFragDataLocation(program_, 0, "frag_color"); + glLinkProgram(program_); +#if DCHECK_IS_ON() + GLint status = GL_FALSE; + glGetProgramiv(program_, GL_LINK_STATUS, &status); + DCHECK(status == GL_TRUE); +#endif + position_location_ = glGetAttribLocation(program_, "position"); + tex_location_ = glGetUniformLocation(program_, "tex"); + } + if (!vertex_buffer_) { + GLfloat vertex_data[24] = { + 0, 0, 0, 1, + 1, 0, 0, 1, + 1, 1, 0, 1, + 1, 1, 0, 1, + 0, 1, 0, 1, + 0, 0, 0, 1, + }; + glGenBuffersARB(1, &vertex_buffer_); + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), + vertex_data, GL_STATIC_DRAW); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + if (!vertex_array_) { + glGenVertexArraysOES(1, &vertex_array_); + glBindVertexArrayOES(vertex_array_); + { + glEnableVertexAttribArray(position_location_); + glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_); + glVertexAttribPointer(position_location_, 4, GL_FLOAT, GL_FALSE, 0, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); + } + glBindVertexArrayOES(0); + } + } else { + glTexImage2D(GL_TEXTURE_RECTANGLE_ARB, + 0, + GL_RGBA, + pixel_size.width(), + pixel_size.height(), + 0, + GL_RGBA, + GL_UNSIGNED_BYTE, + NULL); + glFlush(); + } bool hit_error = false; while ((error = glGetError()) != GL_NO_ERROR) { @@ -157,6 +257,25 @@ bool CALayerStorageProvider::AllocateColorBufferStorage( } void CALayerStorageProvider::FreeColorBufferStorage() { + if (gfx::GetGLImplementation() == + gfx::kGLImplementationDesktopGLCoreProfile) { + if (vertex_shader_) + glDeleteShader(vertex_shader_); + if (fragment_shader_) + glDeleteShader(fragment_shader_); + if (program_) + glDeleteProgram(program_); + if (vertex_buffer_) + glDeleteBuffersARB(1, &vertex_buffer_); + if (vertex_array_) + glDeleteVertexArraysOES(1, &vertex_array_); + vertex_shader_ = 0; + fragment_shader_ = 0; + program_ = 0; + vertex_buffer_ = 0; + vertex_array_ = 0; + } + // Note that |context_| still holds a reference to |layer_|, and will until // a new frame is swapped in. [layer_ resetStorageProvider]; @@ -313,45 +432,69 @@ bool CALayerStorageProvider::LayerCanDraw() { } void CALayerStorageProvider::LayerDoDraw() { - GLint viewport[4] = {0, 0, 0, 0}; - glGetIntegerv(GL_VIEWPORT, viewport); - gfx::Size viewport_size(viewport[2], viewport[3]); - - // Set the coordinate system to be one-to-one with pixels. - glMatrixMode(GL_PROJECTION); - glLoadIdentity(); - glOrtho(0, viewport_size.width(), 0, viewport_size.height(), -1, 1); - glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); - - // Reset drawing state and draw a fullscreen quad. - glUseProgram(0); - glDisable(GL_BLEND); - glDisable(GL_CULL_FACE); - glDisable(GL_DEPTH_TEST); - glDisable(GL_STENCIL_TEST); - glDisable(GL_SCISSOR_TEST); - glColor4f(1, 1, 1, 1); - glActiveTexture(GL_TEXTURE0); - glEnable(GL_TEXTURE_RECTANGLE_ARB); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fbo_texture_); - glBegin(GL_QUADS); - { - glTexCoord2f(0, 0); - glVertex2f(0, 0); - - glTexCoord2f(0, fbo_pixel_size_.height()); - glVertex2f(0, fbo_pixel_size_.height()); - - glTexCoord2f(fbo_pixel_size_.width(), fbo_pixel_size_.height()); - glVertex2f(fbo_pixel_size_.width(), fbo_pixel_size_.height()); - - glTexCoord2f(fbo_pixel_size_.width(), 0); - glVertex2f(fbo_pixel_size_.width(), 0); + if (gfx::GetGLImplementation() == + gfx::kGLImplementationDesktopGLCoreProfile) { + glClearColor(1, 0, 1, 1); + glClear(GL_COLOR_BUFFER_BIT); + glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_SCISSOR_TEST); + + DCHECK(glIsProgram(program_)); + glUseProgram(program_); + glBindVertexArrayOES(vertex_array_); + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, fbo_texture_); + glUniform1i(tex_location_, 0); + + glDisable(GL_CULL_FACE); + glDrawArrays(GL_TRIANGLES, 0, 6); + glBindVertexArrayOES(0); + glUseProgram(0); + } else { + GLint viewport[4] = {0, 0, 0, 0}; + glGetIntegerv(GL_VIEWPORT, viewport); + gfx::Size viewport_size(viewport[2], viewport[3]); + + // Set the coordinate system to be one-to-one with pixels. + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glOrtho(0, viewport_size.width(), 0, viewport_size.height(), -1, 1); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + // Reset drawing state and draw a fullscreen quad. + glUseProgram(0); + glDisable(GL_BLEND); + glDisable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_STENCIL_TEST); + glDisable(GL_SCISSOR_TEST); + glColor4f(1, 1, 1, 1); + glActiveTexture(GL_TEXTURE0); + glEnable(GL_TEXTURE_RECTANGLE_ARB); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, fbo_texture_); + glBegin(GL_QUADS); + { + glTexCoord2f(0, 0); + glVertex2f(0, 0); + + glTexCoord2f(0, fbo_pixel_size_.height()); + glVertex2f(0, fbo_pixel_size_.height()); + + glTexCoord2f(fbo_pixel_size_.width(), fbo_pixel_size_.height()); + glVertex2f(fbo_pixel_size_.width(), fbo_pixel_size_.height()); + + glTexCoord2f(fbo_pixel_size_.width(), 0); + glVertex2f(fbo_pixel_size_.width(), 0); + } + glEnd(); + glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); + glDisable(GL_TEXTURE_RECTANGLE_ARB); } - glEnd(); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0); - glDisable(GL_TEXTURE_RECTANGLE_ARB); GLint current_renderer_id = 0; if (CGLGetParameter(CGLGetCurrentContext(), diff --git a/content/common/gpu/image_transport_surface_fbo_mac.mm b/content/common/gpu/image_transport_surface_fbo_mac.mm index 95a09f9..cb4e3a0 100644 --- a/content/common/gpu/image_transport_surface_fbo_mac.mm +++ b/content/common/gpu/image_transport_surface_fbo_mac.mm @@ -15,6 +15,13 @@ namespace content { +scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface( + GpuChannelManager* manager, + GpuCommandBufferStub* stub, + gfx::PluginWindowHandle handle) { + return new ImageTransportSurfaceFBO(manager, stub, handle); +} + ImageTransportSurfaceFBO::ImageTransportSurfaceFBO( GpuChannelManager* manager, GpuCommandBufferStub* stub, @@ -43,7 +50,9 @@ bool ImageTransportSurfaceFBO::Initialize() { // Only support IOSurfaces if the GL implementation is the native desktop GL. // IO surfaces will not work with, for example, OSMesa software renderer // GL contexts. - if (gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL && + if (gfx::GetGLImplementation() != + gfx::kGLImplementationDesktopGLCoreProfile && + gfx::GetGLImplementation() != gfx::kGLImplementationDesktopGL && gfx::GetGLImplementation() != gfx::kGLImplementationAppleGL) return false; @@ -116,8 +125,13 @@ void ImageTransportSurfaceFBO::NotifyWasBound() { glUseProgram(0); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); DCHECK(status == GL_FRAMEBUFFER_COMPLETE); - glBegin(GL_TRIANGLES); - glEnd(); + if (gfx::GetGLImplementation() == gfx::kGLImplementationDesktopGL) { + // These aren't present in the core profile. + // TODO(ccameron): verify this workaround isn't still needed with + // the core profile. + glBegin(GL_TRIANGLES); + glEnd(); + } glUseProgram(old_program); } @@ -298,7 +312,19 @@ void ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer( // GL_TEXTURE_RECTANGLE_ARB is the best supported render target on // Mac OS X and is required for IOSurface interoperability. GLint previous_texture_id = 0; - glGetIntegerv(GL_TEXTURE_BINDING_RECTANGLE_ARB, &previous_texture_id); + + GLenum texture_target = GL_TEXTURE_RECTANGLE_ARB; + GLenum texture_binding_target = GL_TEXTURE_BINDING_RECTANGLE_ARB; + // However, the remote core animation path on the core profile will + // be the preferred combination going forward. + if (gfx::GetGLImplementation() == + gfx::kGLImplementationDesktopGLCoreProfile && + ui::RemoteLayerAPISupported()) { + texture_target = GL_TEXTURE_2D; + texture_binding_target = GL_TEXTURE_BINDING_2D; + } + + glGetIntegerv(texture_binding_target, &previous_texture_id); // Free the old IO Surface first to reduce memory fragmentation. DestroyFramebuffer(); @@ -308,17 +334,17 @@ void ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer( glGenTextures(1, &texture_id_); - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, texture_id_); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, + glBindTexture(texture_target, texture_id_); + glTexParameteri(texture_target, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(texture_target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_RECTANGLE_ARB, + glTexParameteri(texture_target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, - GL_TEXTURE_RECTANGLE_ARB, + texture_target, texture_id_, 0); @@ -373,7 +399,7 @@ void ImageTransportSurfaceFBO::AllocateOrResizeFramebuffer( has_complete_framebuffer_ = true; - glBindTexture(GL_TEXTURE_RECTANGLE_ARB, previous_texture_id); + glBindTexture(texture_target, previous_texture_id); // The FBO remains bound for this GL context. } diff --git a/content/common/gpu/image_transport_surface_iosurface_mac.h b/content/common/gpu/image_transport_surface_iosurface_mac.h index d25f91f..797c4ec 100644 --- a/content/common/gpu/image_transport_surface_iosurface_mac.h +++ b/content/common/gpu/image_transport_surface_iosurface_mac.h @@ -8,7 +8,6 @@ #include <list> #include "content/common/gpu/image_transport_surface_fbo_mac.h" -#include "ui/gl/gl_bindings.h" // Note that this must be included after gl_bindings.h to avoid conflicts. #include <OpenGL/CGLIOSurface.h> diff --git a/content/common/gpu/image_transport_surface_mac.mm b/content/common/gpu/image_transport_surface_mac.mm index 0f40f23..7966d5a 100644 --- a/content/common/gpu/image_transport_surface_mac.mm +++ b/content/common/gpu/image_transport_surface_mac.mm @@ -2,7 +2,7 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "content/common/gpu/image_transport_surface_fbo_mac.h" +#include "content/common/gpu/image_transport_surface.h" #include "content/common/gpu/gpu_messages.h" #include "ui/gfx/native_widget_types.h" @@ -11,6 +11,12 @@ #include "ui/gl/gl_surface_osmesa.h" namespace content { + +scoped_refptr<gfx::GLSurface> ImageTransportSurfaceCreateNativeSurface( + GpuChannelManager* manager, + GpuCommandBufferStub* stub, + gfx::PluginWindowHandle handle); + namespace { // A subclass of GLSurfaceOSMesa that doesn't print an error message when @@ -47,9 +53,10 @@ scoped_refptr<gfx::GLSurface> ImageTransportSurface::CreateNativeSurface( switch (gfx::GetGLImplementation()) { case gfx::kGLImplementationDesktopGL: + case gfx::kGLImplementationDesktopGLCoreProfile: case gfx::kGLImplementationAppleGL: - return scoped_refptr<gfx::GLSurface>(new ImageTransportSurfaceFBO( - manager, stub, surface_handle.handle)); + return ImageTransportSurfaceCreateNativeSurface(manager, stub, + surface_handle.handle); default: // Content shell in DRT mode spins up a gpu process which needs an // image transport surface, but that surface isn't used to read pixel diff --git a/gpu/command_buffer/build_gles2_cmd_buffer.py b/gpu/command_buffer/build_gles2_cmd_buffer.py index aa7be79..0407033 100755 --- a/gpu/command_buffer/build_gles2_cmd_buffer.py +++ b/gpu/command_buffer/build_gles2_cmd_buffer.py @@ -386,7 +386,8 @@ _STATES = { 'name': 'hint_generate_mipmap', 'type': 'GLenum', 'enum': 'GL_GENERATE_MIPMAP_HINT', - 'default': 'GL_DONT_CARE' + 'default': 'GL_DONT_CARE', + 'gl_version_flag': '!is_desktop_core_profile' }, { 'name': 'hint_fragment_shader_derivative', @@ -9652,11 +9653,21 @@ void ContextState::InitState(const ContextState *prev_state) const { else: file.Write(" if (prev_state->%s != %s) {\n " % (item_name, item_name)) + if 'gl_version_flag' in item: + item_name = item['gl_version_flag'] + inverted = '' + if item_name[0] == '!': + inverted = '!' + item_name = item_name[1:] + file.Write(" if (%sfeature_info_->gl_version_info().%s) {\n" % + (inverted, item_name)) file.Write(" gl%s(%s, %s);\n" % (state['func'], (item['enum_set'] if 'enum_set' in item else item['enum']), item['name'])) + if 'gl_version_flag' in item: + file.Write(" }\n") if test_prev: if 'extension_flag' in item: file.Write(" ") diff --git a/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc b/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc index dcc7e18..6d8562f 100644 --- a/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc +++ b/gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc @@ -17,6 +17,7 @@ AsyncPixelTransferManager* AsyncPixelTransferManager::Create( switch (gfx::GetGLImplementation()) { case gfx::kGLImplementationOSMesaGL: case gfx::kGLImplementationDesktopGL: + case gfx::kGLImplementationDesktopGLCoreProfile: case gfx::kGLImplementationAppleGL: return new AsyncPixelTransferManagerIdle(true); case gfx::kGLImplementationMockGL: diff --git a/gpu/command_buffer/service/context_group.cc b/gpu/command_buffer/service/context_group.cc index d918526..17871b9 100644 --- a/gpu/command_buffer/service/context_group.cc +++ b/gpu/command_buffer/service/context_group.cc @@ -97,7 +97,8 @@ bool ContextGroup::Initialize( GL_MAX_RENDERBUFFER_SIZE, kMinRenderbufferSize, &max_renderbuffer_size)) { LOG(ERROR) << "ContextGroup::Initialize failed because maximum " - << "renderbuffer size too small."; + << "renderbuffer size too small (" << max_renderbuffer_size + << ", should be " << kMinRenderbufferSize << ")."; return false; } GLint max_samples = 0; @@ -121,15 +122,13 @@ bool ContextGroup::Initialize( draw_buffer_ = GL_BACK; } - const bool depth24_supported = feature_info_->feature_flags().oes_depth24; - buffer_manager_.reset( new BufferManager(memory_tracker_.get(), feature_info_.get())); framebuffer_manager_.reset( new FramebufferManager(max_draw_buffers_, max_color_attachments_)); renderbuffer_manager_.reset(new RenderbufferManager( memory_tracker_.get(), max_renderbuffer_size, max_samples, - depth24_supported)); + feature_info_.get())); shader_manager_.reset(new ShaderManager()); valuebuffer_manager_.reset( new ValuebufferManager(subscription_ref_set_.get(), @@ -213,7 +212,7 @@ bool ContextGroup::Initialize( return false; } - if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) { + if (feature_info_->gl_version_info().BehavesLikeGLES()) { GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, &max_fragment_uniform_vectors_); GetIntegerv(GL_MAX_VARYING_VECTORS, &max_varying_vectors_); diff --git a/gpu/command_buffer/service/context_state_impl_autogen.h b/gpu/command_buffer/service/context_state_impl_autogen.h index 467f1ce..e6c63a6 100644 --- a/gpu/command_buffer/service/context_state_impl_autogen.h +++ b/gpu/command_buffer/service/context_state_impl_autogen.h @@ -242,7 +242,9 @@ void ContextState::InitState(const ContextState* prev_state) const { if ((front_face != prev_state->front_face)) glFrontFace(front_face); if (prev_state->hint_generate_mipmap != hint_generate_mipmap) { - glHint(GL_GENERATE_MIPMAP_HINT, hint_generate_mipmap); + if (!feature_info_->gl_version_info().is_desktop_core_profile) { + glHint(GL_GENERATE_MIPMAP_HINT, hint_generate_mipmap); + } } if (feature_info_->feature_flags().oes_standard_derivatives) { if (prev_state->hint_fragment_shader_derivative != @@ -330,7 +332,9 @@ void ContextState::InitState(const ContextState* prev_state) const { glDepthMask(cached_depth_mask); glDepthRange(z_near, z_far); glFrontFace(front_face); - glHint(GL_GENERATE_MIPMAP_HINT, hint_generate_mipmap); + if (!feature_info_->gl_version_info().is_desktop_core_profile) { + glHint(GL_GENERATE_MIPMAP_HINT, hint_generate_mipmap); + } if (feature_info_->feature_flags().oes_standard_derivatives) { glHint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES, hint_fragment_shader_derivative); diff --git a/gpu/command_buffer/service/feature_info.cc b/gpu/command_buffer/service/feature_info.cc index 6675ba7..0ff5be1 100644 --- a/gpu/command_buffer/service/feature_info.cc +++ b/gpu/command_buffer/service/feature_info.cc @@ -44,6 +44,10 @@ class StringSet { Init(str); } + StringSet(const std::vector<std::string>& strs) { + string_set_.insert(strs.begin(), strs.end()); + } + void Init(const char* s) { std::string str(s ? s : ""); Init(str); @@ -63,6 +67,10 @@ class StringSet { return string_set_.find(s) != string_set_.end(); } + const std::set<std::string>& GetImpl() { + return string_set_; + } + private: std::set<std::string> string_set_; }; @@ -272,15 +280,35 @@ bool IsGL_REDSupportedOnFBOs() { void FeatureInfo::InitializeFeatures() { // Figure out what extensions to turn on. - StringSet extensions( - reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS))); + StringSet extensions; + // We need to figure out how to query the extension string before we + // have a GLVersionInfo available. + const char* version_str = + reinterpret_cast<const char*>(glGetString(GL_VERSION)); + unsigned major_version, minor_version; + bool is_es, is_es3; + gfx::GLVersionInfo::ParseVersionString( + version_str, &major_version, &minor_version, &is_es, &is_es3); + if (!is_es && major_version >= 3) { + std::vector<std::string> exts; + GLint num_extensions = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); + for (GLint i = 0; i < num_extensions; ++i) { + const char* extension = reinterpret_cast<const char*>( + glGetStringi(GL_EXTENSIONS, i)); + DCHECK(extension != NULL); + exts.push_back(extension); + } + extensions = exts; + } else { + extensions = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); + } const char* renderer_str = reinterpret_cast<const char*>(glGetString(GL_RENDERER)); - const char* version_str = - reinterpret_cast<const char*>(glGetString(GL_VERSION)); - gl_version_info_.reset(new gfx::GLVersionInfo(version_str, renderer_str)); + gl_version_info_.reset(new gfx::GLVersionInfo( + version_str, renderer_str, extensions.GetImpl())); AddExtensionString("GL_ANGLE_translated_shader_source"); AddExtensionString("GL_CHROMIUM_async_pixel_transfers"); @@ -402,7 +430,8 @@ void FeatureInfo::InitializeFeatures() { (extensions.Contains("GL_ARB_depth_texture") || extensions.Contains("GL_OES_depth_texture") || extensions.Contains("GL_ANGLE_depth_texture") || - gl_version_info_->is_es3)) { + gl_version_info_->is_es3 || + gl_version_info_->is_desktop_core_profile)) { enable_depth_texture = true; feature_flags_.angle_depth_texture = extensions.Contains("GL_ANGLE_depth_texture"); @@ -421,7 +450,8 @@ void FeatureInfo::InitializeFeatures() { if (extensions.Contains("GL_EXT_packed_depth_stencil") || extensions.Contains("GL_OES_packed_depth_stencil") || - gl_version_info_->is_es3) { + gl_version_info_->is_es3 || + gl_version_info_->is_desktop_core_profile) { AddExtensionString("GL_OES_packed_depth_stencil"); feature_flags_.packed_depth24_stencil8 = true; if (enable_depth_texture) { @@ -435,6 +465,7 @@ void FeatureInfo::InitializeFeatures() { } if (gl_version_info_->is_es3 || + gl_version_info_->is_desktop_core_profile || extensions.Contains("GL_OES_vertex_array_object") || extensions.Contains("GL_ARB_vertex_array_object") || extensions.Contains("GL_APPLE_vertex_array_object")) { @@ -526,6 +557,7 @@ void FeatureInfo::InitializeFeatures() { // Check if we should allow GL_OES_texture_npot if (gl_version_info_->is_es3 || + gl_version_info_->is_desktop_core_profile || extensions.Contains("GL_ARB_texture_non_power_of_two") || extensions.Contains("GL_OES_texture_npot")) { AddExtensionString("GL_OES_texture_npot"); @@ -541,7 +573,8 @@ void FeatureInfo::InitializeFeatures() { bool may_enable_chromium_color_buffer_float = false; - if (extensions.Contains("GL_ARB_texture_float")) { + if (extensions.Contains("GL_ARB_texture_float") || + gl_version_info_->is_desktop_core_profile) { enable_texture_float = true; enable_texture_float_linear = true; enable_texture_half_float = true; @@ -663,12 +696,14 @@ void FeatureInfo::InitializeFeatures() { if (!workarounds_.disable_multisampling) { bool ext_has_multisample = extensions.Contains("GL_EXT_framebuffer_multisample") || - gl_version_info_->is_es3; + 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"); } - feature_flags_.use_core_framebuffer_multisample = gl_version_info_->is_es3; + 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); @@ -753,7 +788,8 @@ void FeatureInfo::InitializeFeatures() { // applications to start using it; they should use ordinary non- // power-of-two textures. However, for unit testing purposes we // expose it on all supported platforms. - if (extensions.Contains("GL_ARB_texture_rectangle")) { + if (extensions.Contains("GL_ARB_texture_rectangle") || + gl_version_info_->is_desktop_core_profile) { AddExtensionString("GL_ARB_texture_rectangle"); feature_flags_.arb_texture_rectangle = true; validators_.texture_bind_target.AddValue(GL_TEXTURE_RECTANGLE_ARB); @@ -803,7 +839,8 @@ void FeatureInfo::InitializeFeatures() { !enable_texture_format_bgra8888); if (extensions.Contains("GL_EXT_texture_storage") || extensions.Contains("GL_ARB_texture_storage") || - support_texture_storage_on_es3) { + support_texture_storage_on_es3 || + gl_version_info_->is_desktop_core_profile) { feature_flags_.ext_texture_storage = true; AddExtensionString("GL_EXT_texture_storage"); validators_.texture_parameter.AddValue(GL_TEXTURE_IMMUTABLE_FORMAT_EXT); @@ -865,7 +902,8 @@ void FeatureInfo::InitializeFeatures() { if (!workarounds_.disable_ext_draw_buffers && (vendor_agnostic_draw_buffers || (extensions.Contains("GL_NV_draw_buffers") && - gl_version_info_->is_es3))) { + gl_version_info_->is_es3) || + gl_version_info_->is_desktop_core_profile)) { AddExtensionString("GL_EXT_draw_buffers"); feature_flags_.ext_draw_buffers = true; @@ -937,6 +975,7 @@ void FeatureInfo::InitializeFeatures() { feature_flags_.map_buffer_range = gl_version_info_->is_es3 || + gl_version_info_->is_desktop_core_profile || extensions.Contains("GL_ARB_map_buffer_range") || extensions.Contains("GL_EXT_map_buffer_range"); @@ -944,6 +983,7 @@ void FeatureInfo::InitializeFeatures() { // extension is still advertised. bool has_pixel_buffers = gl_version_info_->is_es3 || + gl_version_info_->is_desktop_core_profile || extensions.Contains("GL_ARB_pixel_buffer_object") || extensions.Contains("GL_NV_pixel_buffer_object"); @@ -1017,7 +1057,8 @@ void FeatureInfo::InitializeFeatures() { } } - if ((gl_version_info_->is_es3 || extensions.Contains("GL_EXT_texture_rg") || + if ((gl_version_info_->is_es3 || gl_version_info_->is_desktop_core_profile || + extensions.Contains("GL_EXT_texture_rg") || extensions.Contains("GL_ARB_texture_rg")) && IsGL_REDSupportedOnFBOs()) { feature_flags_.ext_texture_rg = true; diff --git a/gpu/command_buffer/service/feature_info_unittest.cc b/gpu/command_buffer/service/feature_info_unittest.cc index 177ef10..f4b2dac 100644 --- a/gpu/command_buffer/service/feature_info_unittest.cc +++ b/gpu/command_buffer/service/feature_info_unittest.cc @@ -42,7 +42,13 @@ class FeatureInfoTest : public GpuServiceTest { } void SetupInitExpectations(const char* extensions) { - SetupInitExpectationsWithGLVersion(extensions, "", "3.0"); + std::string extensions_str = extensions; + // Most of the tests' expectations currently assume the desktop + // OpenGL compatibility profile. + if (extensions_str.find("GL_ARB_compatibility") == std::string::npos) { + extensions_str += " GL_ARB_compatibility"; + } + SetupInitExpectationsWithGLVersion(extensions_str.c_str(), "", "3.0"); } void SetupInitExpectationsWithGLVersion( @@ -1382,7 +1388,8 @@ TEST_F(FeatureInfoTest, ARBSyncDisabled) { TEST_F(FeatureInfoTest, InitializeCHROMIUM_path_rendering) { SetupInitExpectationsWithGLVersion( - "GL_NV_path_rendering GL_EXT_direct_state_access", "", "4.3"); + "GL_ARB_compatibility GL_NV_path_rendering GL_EXT_direct_state_access", + "", "4.3"); EXPECT_TRUE(info_->feature_flags().chromium_path_rendering); EXPECT_THAT(info_->extensions(), HasSubstr("GL_CHROMIUM_path_rendering")); } @@ -1395,21 +1402,22 @@ TEST_F(FeatureInfoTest, InitializeCHROMIUM_path_rendering2) { } TEST_F(FeatureInfoTest, InitializeNoCHROMIUM_path_rendering) { - SetupInitExpectationsWithGLVersion("", "", "4.3"); + SetupInitExpectationsWithGLVersion("GL_ARB_compatibility", "", "4.3"); EXPECT_FALSE(info_->feature_flags().chromium_path_rendering); EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_CHROMIUM_path_rendering"))); } TEST_F(FeatureInfoTest, InitializeNoCHROMIUM_path_rendering2) { - SetupInitExpectationsWithGLVersion("GL_NV_path_rendering", "", "4.3"); + SetupInitExpectationsWithGLVersion( + "GL_ARB_compatibility GL_NV_path_rendering", "", "4.3"); EXPECT_FALSE(info_->feature_flags().chromium_path_rendering); EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_CHROMIUM_path_rendering"))); } TEST_F(FeatureInfoTest, InitializeNoKHR_blend_equation_advanced) { - SetupInitExpectationsWithGLVersion("", "", "4.3"); + SetupInitExpectationsWithGLVersion("GL_ARB_compatibility", "", "4.3"); EXPECT_FALSE(info_->feature_flags().blend_equation_advanced); EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_KHR_blend_equation_advanced"))); @@ -1428,7 +1436,7 @@ TEST_F(FeatureInfoTest, InitializeNV_blend_equations_advanced) { } TEST_F(FeatureInfoTest, InitializeNoKHR_blend_equation_advanced_coherent) { - SetupInitExpectationsWithGLVersion("", "", "4.3"); + SetupInitExpectationsWithGLVersion("GL_ARB_compatibility ", "", "4.3"); EXPECT_FALSE(info_->feature_flags().blend_equation_advanced_coherent); EXPECT_THAT(info_->extensions(), Not(HasSubstr("GL_KHR_blend_equation_advanced_coherent"))); diff --git a/gpu/command_buffer/service/framebuffer_manager_unittest.cc b/gpu/command_buffer/service/framebuffer_manager_unittest.cc index ddd3739..66fb260 100644 --- a/gpu/command_buffer/service/framebuffer_manager_unittest.cc +++ b/gpu/command_buffer/service/framebuffer_manager_unittest.cc @@ -26,7 +26,6 @@ const GLint kMaxRenderbufferSize = 64; const GLint kMaxSamples = 4; const uint32 kMaxDrawBuffers = 16; const uint32 kMaxColorAttachments = 16; -const bool kDepth24Supported = false; const bool kUseDefaultTextures = false; } // namespace @@ -35,27 +34,30 @@ class FramebufferManagerTest : public GpuServiceTest { public: FramebufferManagerTest() : manager_(1, 1), - texture_manager_(NULL, - new FeatureInfo(), - kMaxTextureSize, - kMaxCubemapSize, - kMaxRectangleTextureSize, - kUseDefaultTextures), - renderbuffer_manager_(NULL, - kMaxRenderbufferSize, - kMaxSamples, - kDepth24Supported) {} + feature_info_(new FeatureInfo()) { + texture_manager_.reset(new TextureManager(NULL, + feature_info_.get(), + kMaxTextureSize, + kMaxCubemapSize, + kMaxRectangleTextureSize, + kUseDefaultTextures)); + renderbuffer_manager_.reset(new RenderbufferManager(NULL, + kMaxRenderbufferSize, + kMaxSamples, + feature_info_.get())); + } ~FramebufferManagerTest() override { manager_.Destroy(false); - texture_manager_.Destroy(false); - renderbuffer_manager_.Destroy(false); + texture_manager_->Destroy(false); + renderbuffer_manager_->Destroy(false); } protected: FramebufferManager manager_; - TextureManager texture_manager_; - RenderbufferManager renderbuffer_manager_; + scoped_refptr<FeatureInfo> feature_info_; + scoped_ptr<TextureManager> texture_manager_; + scoped_ptr<RenderbufferManager> renderbuffer_manager_; }; TEST_F(FramebufferManagerTest, Basic) { @@ -109,20 +111,22 @@ class FramebufferInfoTest : public GpuServiceTest { FramebufferInfoTest() : manager_(kMaxDrawBuffers, kMaxColorAttachments), - feature_info_(new FeatureInfo()), - renderbuffer_manager_(NULL, kMaxRenderbufferSize, kMaxSamples, - kDepth24Supported) { + feature_info_(new FeatureInfo()) { texture_manager_.reset(new TextureManager(NULL, feature_info_.get(), kMaxTextureSize, kMaxCubemapSize, kMaxRectangleTextureSize, kUseDefaultTextures)); + renderbuffer_manager_.reset(new RenderbufferManager(NULL, + kMaxRenderbufferSize, + kMaxSamples, + feature_info_.get())); } ~FramebufferInfoTest() override { manager_.Destroy(false); texture_manager_->Destroy(false); - renderbuffer_manager_.Destroy(false); + renderbuffer_manager_->Destroy(false); } protected: @@ -145,7 +149,7 @@ class FramebufferInfoTest : public GpuServiceTest { Framebuffer* framebuffer_; scoped_refptr<FeatureInfo> feature_info_; scoped_ptr<TextureManager> texture_manager_; - RenderbufferManager renderbuffer_manager_; + scoped_ptr<RenderbufferManager> renderbuffer_manager_; scoped_ptr<MockErrorState> error_state_; }; @@ -205,10 +209,10 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { EXPECT_FALSE( framebuffer_->HasUnclearedAttachment(GL_DEPTH_STENCIL_ATTACHMENT)); - renderbuffer_manager_.CreateRenderbuffer( + renderbuffer_manager_->CreateRenderbuffer( kRenderbufferClient1Id, kRenderbufferService1Id); Renderbuffer* renderbuffer1 = - renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id); + renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient1Id); ASSERT_TRUE(renderbuffer1 != NULL); // check adding one attachment @@ -224,13 +228,13 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { EXPECT_TRUE(framebuffer_->IsCleared()); // Try a format that's not good for COLOR_ATTACHMENT0. - renderbuffer_manager_.SetInfo( + renderbuffer_manager_->SetInfo( renderbuffer1, kSamples1, kBadFormat1, kWidth1, kHeight1); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT), framebuffer_->IsPossiblyComplete()); // Try a good format. - renderbuffer_manager_.SetInfo( + renderbuffer_manager_->SetInfo( renderbuffer1, kSamples1, kFormat1, kWidth1, kHeight1); EXPECT_EQ(static_cast<GLenum>(kFormat1), framebuffer_->GetColorAttachmentFormat()); @@ -241,10 +245,10 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { EXPECT_FALSE(framebuffer_->IsCleared()); // check adding another - renderbuffer_manager_.CreateRenderbuffer( + renderbuffer_manager_->CreateRenderbuffer( kRenderbufferClient2Id, kRenderbufferService2Id); Renderbuffer* renderbuffer2 = - renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient2Id); + renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient2Id); ASSERT_TRUE(renderbuffer2 != NULL); framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, renderbuffer2); EXPECT_TRUE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)); @@ -263,7 +267,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { status == GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT); EXPECT_FALSE(framebuffer_->IsCleared()); - renderbuffer_manager_.SetInfo( + renderbuffer_manager_->SetInfo( renderbuffer2, kSamples2, kFormat2, kWidth2, kHeight2); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), framebuffer_->IsPossiblyComplete()); @@ -272,7 +276,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { // check marking them as cleared. manager_.MarkAttachmentsAsCleared( - framebuffer_, &renderbuffer_manager_, texture_manager_.get()); + framebuffer_, renderbuffer_manager_.get(), texture_manager_.get()); EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)); EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_DEPTH_ATTACHMENT)); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_COMPLETE), @@ -280,14 +284,14 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { EXPECT_TRUE(framebuffer_->IsCleared()); // Check adding one that is already cleared. - renderbuffer_manager_.CreateRenderbuffer( + renderbuffer_manager_->CreateRenderbuffer( kRenderbufferClient3Id, kRenderbufferService3Id); Renderbuffer* renderbuffer3 = - renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient3Id); + renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient3Id); ASSERT_TRUE(renderbuffer3 != NULL); - renderbuffer_manager_.SetInfo( + renderbuffer_manager_->SetInfo( renderbuffer3, kSamples3, kFormat3, kWidth3, kHeight3); - renderbuffer_manager_.SetCleared(renderbuffer3, true); + renderbuffer_manager_->SetCleared(renderbuffer3, true); framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, renderbuffer3); EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_STENCIL_ATTACHMENT)); @@ -300,7 +304,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { EXPECT_TRUE(framebuffer_->IsCleared()); // Check marking the renderbuffer as unclared. - renderbuffer_manager_.SetInfo( + renderbuffer_manager_->SetInfo( renderbuffer1, kSamples1, kFormat1, kWidth1, kHeight1); EXPECT_EQ(static_cast<GLenum>(kFormat1), framebuffer_->GetColorAttachmentFormat()); @@ -323,17 +327,17 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { // Clear it. manager_.MarkAttachmentsAsCleared( - framebuffer_, &renderbuffer_manager_, texture_manager_.get()); + framebuffer_, renderbuffer_manager_.get(), texture_manager_.get()); EXPECT_FALSE(framebuffer_->HasUnclearedAttachment(GL_COLOR_ATTACHMENT0)); EXPECT_TRUE(framebuffer_->IsCleared()); // Check replacing an attachment - renderbuffer_manager_.CreateRenderbuffer( + renderbuffer_manager_->CreateRenderbuffer( kRenderbufferClient4Id, kRenderbufferService4Id); Renderbuffer* renderbuffer4 = - renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient4Id); + renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient4Id); ASSERT_TRUE(renderbuffer4 != NULL); - renderbuffer_manager_.SetInfo( + renderbuffer_manager_->SetInfo( renderbuffer4, kSamples4, kFormat4, kWidth4, kHeight4); framebuffer_->AttachRenderbuffer(GL_STENCIL_ATTACHMENT, renderbuffer4); @@ -351,7 +355,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { framebuffer_->IsPossiblyComplete()); // Check changing an attachment. - renderbuffer_manager_.SetInfo( + renderbuffer_manager_->SetInfo( renderbuffer4, kSamples4, kFormat4, kWidth4 + 1, kHeight4); attachment = framebuffer_->GetAttachment(GL_STENCIL_ATTACHMENT); @@ -379,7 +383,7 @@ TEST_F(FramebufferInfoTest, AttachRenderbuffer) { // Remove depth, Set color to 0 size. framebuffer_->AttachRenderbuffer(GL_DEPTH_ATTACHMENT, NULL); - renderbuffer_manager_.SetInfo(renderbuffer1, kSamples1, kFormat1, 0, 0); + renderbuffer_manager_->SetInfo(renderbuffer1, kSamples1, kFormat1, 0, 0); EXPECT_EQ(static_cast<GLenum>(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT), framebuffer_->IsPossiblyComplete()); @@ -735,15 +739,15 @@ TEST_F(FramebufferInfoTest, UnbindRenderbuffer) { const GLuint kRenderbufferClient2Id = 34; const GLuint kRenderbufferService2Id = 334; - renderbuffer_manager_.CreateRenderbuffer( + renderbuffer_manager_->CreateRenderbuffer( kRenderbufferClient1Id, kRenderbufferService1Id); Renderbuffer* renderbuffer1 = - renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id); + renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient1Id); ASSERT_TRUE(renderbuffer1 != NULL); - renderbuffer_manager_.CreateRenderbuffer( + renderbuffer_manager_->CreateRenderbuffer( kRenderbufferClient2Id, kRenderbufferService2Id); Renderbuffer* renderbuffer2 = - renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient2Id); + renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient2Id); ASSERT_TRUE(renderbuffer2 != NULL); // Attach to 2 attachment points. @@ -811,10 +815,10 @@ TEST_F(FramebufferInfoTest, IsCompleteMarkAsComplete) { const GLint kLevel1 = 0; const GLint kSamples1 = 0; - renderbuffer_manager_.CreateRenderbuffer( + renderbuffer_manager_->CreateRenderbuffer( kRenderbufferClient1Id, kRenderbufferService1Id); Renderbuffer* renderbuffer1 = - renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id); + renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient1Id); ASSERT_TRUE(renderbuffer1 != NULL); texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id); scoped_refptr<TextureRef> texture2( @@ -836,7 +840,7 @@ TEST_F(FramebufferInfoTest, IsCompleteMarkAsComplete) { // Check MarkAttachmentsAsCleared marks as complete. manager_.MarkAttachmentsAsCleared( - framebuffer_, &renderbuffer_manager_, texture_manager_.get()); + framebuffer_, renderbuffer_manager_.get(), texture_manager_.get()); EXPECT_TRUE(manager_.IsComplete(framebuffer_)); // Check Unbind marks as not complete. @@ -857,10 +861,10 @@ TEST_F(FramebufferInfoTest, GetStatus) { const GLint kLevel1 = 0; const GLint kSamples1 = 0; - renderbuffer_manager_.CreateRenderbuffer( + renderbuffer_manager_->CreateRenderbuffer( kRenderbufferClient1Id, kRenderbufferService1Id); Renderbuffer* renderbuffer1 = - renderbuffer_manager_.GetRenderbuffer(kRenderbufferClient1Id); + renderbuffer_manager_->GetRenderbuffer(kRenderbufferClient1Id); ASSERT_TRUE(renderbuffer1 != NULL); texture_manager_->CreateTexture(kTextureClient2Id, kTextureService2Id); scoped_refptr<TextureRef> texture2( diff --git a/gpu/command_buffer/service/gles2_cmd_decoder.cc b/gpu/command_buffer/service/gles2_cmd_decoder.cc index 3abe199..d402c93 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder.cc @@ -2733,17 +2733,39 @@ bool GLES2DecoderImpl::Initialize( // can't do anything about that. if (!surfaceless_) { - GLint v = 0; - glGetIntegerv(GL_ALPHA_BITS, &v); + GLint alpha_bits = 0; + GLint depth_bits = 0; + GLint stencil_bits = 0; + + bool default_fb = (GetBackbufferServiceId() == 0); + + if (feature_info_->gl_version_info().is_desktop_core_profile) { + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, + default_fb ? GL_BACK_LEFT : GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &alpha_bits); + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, + default_fb ? GL_DEPTH : GL_DEPTH_ATTACHMENT, + GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &depth_bits); + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, + default_fb ? GL_STENCIL : GL_STENCIL_ATTACHMENT, + GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &stencil_bits); + } else { + glGetIntegerv(GL_ALPHA_BITS, &alpha_bits); + glGetIntegerv(GL_DEPTH_BITS, &depth_bits); + glGetIntegerv(GL_STENCIL_BITS, &stencil_bits); + } + // This checks if the user requested RGBA and we have RGBA then RGBA. If // the user requested RGB then RGB. If the user did not specify a // preference than use whatever we were given. Same for DEPTH and STENCIL. back_buffer_color_format_ = - (attrib_parser.alpha_size != 0 && v > 0) ? GL_RGBA : GL_RGB; - glGetIntegerv(GL_DEPTH_BITS, &v); - back_buffer_has_depth_ = attrib_parser.depth_size != 0 && v > 0; - glGetIntegerv(GL_STENCIL_BITS, &v); - back_buffer_has_stencil_ = attrib_parser.stencil_size != 0 && v > 0; + (attrib_parser.alpha_size != 0 && alpha_bits > 0) ? GL_RGBA : GL_RGB; + back_buffer_has_depth_ = attrib_parser.depth_size != 0 && depth_bits > 0; + back_buffer_has_stencil_ = + attrib_parser.stencil_size != 0 && stencil_bits > 0; } state_.viewport_width = surface->GetSize().width(); @@ -2756,7 +2778,7 @@ bool GLES2DecoderImpl::Initialize( // mailing list archives. It also implicitly enables the desktop GL // capability GL_POINT_SPRITE to provide access to the gl_PointCoord // variable in fragment shaders. - if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { + if (!feature_info_->gl_version_info().BehavesLikeGLES()) { glEnable(GL_VERTEX_PROGRAM_POINT_SIZE); glEnable(GL_POINT_SPRITE); } @@ -4749,23 +4771,93 @@ bool GLES2DecoderImpl::GetHelper( *num_written = 1; if (params) { GLint v = 0; - glGetIntegerv(GL_ALPHA_BITS, &v); - params[0] = BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0; + if (feature_info_->gl_version_info().is_desktop_core_profile) { + Framebuffer* framebuffer = + GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); + if (framebuffer) { + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, + GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE, &v); + } else { + v = (back_buffer_color_format_ == GL_RGBA ? 8 : 0); + } + } else { + glGetIntegerv(GL_ALPHA_BITS, &v); + } + params[0] = + BoundFramebufferHasColorAttachmentWithAlpha(false) ? v : 0; } return true; case GL_DEPTH_BITS: *num_written = 1; if (params) { GLint v = 0; - glGetIntegerv(GL_DEPTH_BITS, &v); + if (feature_info_->gl_version_info().is_desktop_core_profile) { + Framebuffer* framebuffer = + GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); + if (framebuffer) { + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, + GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE, &v); + } else { + v = (back_buffer_has_depth_ ? 24 : 0); + } + } else { + glGetIntegerv(GL_DEPTH_BITS, &v); + } params[0] = BoundFramebufferHasDepthAttachment() ? v : 0; } return true; + case GL_RED_BITS: + case GL_GREEN_BITS: + case GL_BLUE_BITS: + *num_written = 1; + if (params) { + GLint v = 0; + if (feature_info_->gl_version_info().is_desktop_core_profile) { + Framebuffer* framebuffer = + GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); + if (framebuffer) { + GLenum framebuffer_enum = 0; + switch (pname) { + case GL_RED_BITS: + framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE; + break; + case GL_GREEN_BITS: + framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE; + break; + case GL_BLUE_BITS: + framebuffer_enum = GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE; + break; + } + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, framebuffer_enum, &v); + } else { + v = 8; + } + } else { + glGetIntegerv(pname, &v); + } + params[0] = v; + } + return true; case GL_STENCIL_BITS: *num_written = 1; if (params) { GLint v = 0; - glGetIntegerv(GL_STENCIL_BITS, &v); + if (feature_info_->gl_version_info().is_desktop_core_profile) { + Framebuffer* framebuffer = + GetFramebufferInfoForTarget(GL_DRAW_FRAMEBUFFER_EXT); + if (framebuffer) { + glGetFramebufferAttachmentParameterivEXT( + GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, + GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE, &v); + } else { + v = (back_buffer_has_stencil_ ? 8 : 0); + } + } else { + glGetIntegerv(GL_STENCIL_BITS, &v); + } params[0] = BoundFramebufferHasStencilAttachment() ? v : 0; } return true; @@ -6612,7 +6704,7 @@ bool GLES2DecoderImpl::SimulateAttrib0( DCHECK(simulated); *simulated = false; - if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) + if (feature_info_->gl_version_info().BehavesLikeGLES()) return true; const VertexAttrib* attrib = @@ -8358,7 +8450,8 @@ error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size, LOCAL_SET_GL_ERROR_INVALID_ENUM("glGetString", name, "name"); return error::kNoError; } - const char* str = reinterpret_cast<const char*>(glGetString(name)); + + const char* str = nullptr; std::string extensions; switch (name) { case GL_VERSION: @@ -8373,6 +8466,8 @@ error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size, // They are used by WEBGL_debug_renderer_info. if (!force_webgl_glsl_validation_) str = "Chromium"; + else + str = reinterpret_cast<const char*>(glGetString(name)); break; case GL_EXTENSIONS: { @@ -8418,6 +8513,7 @@ error::Error GLES2DecoderImpl::HandleGetString(uint32 immediate_data_size, } break; default: + str = reinterpret_cast<const char*>(glGetString(name)); break; } Bucket* bucket = CreateBucket(c.bucket_id); diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc index 119096bb..8648134 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc @@ -126,6 +126,7 @@ void GLES2DecoderTestBase::SetUp() { // Autogenerated tests do not overwrite version or extension string, // so we have to pick something that supports everything here. init.gl_version = "4.4"; + init.extensions += " GL_ARB_compatibility"; init.has_alpha = true; init.has_depth = true; init.request_alpha = true; @@ -321,13 +322,15 @@ void GLES2DecoderTestBase::InitDecoderWithCommandLine( .WillOnce(SetArgumentPointee<1>(normalized_init.has_stencil ? 8 : 0)) .RetiresOnSaturation(); - EXPECT_CALL(*gl_, Enable(GL_VERTEX_PROGRAM_POINT_SIZE)) - .Times(1) - .RetiresOnSaturation(); + if (!group_->feature_info()->gl_version_info().BehavesLikeGLES()) { + EXPECT_CALL(*gl_, Enable(GL_VERTEX_PROGRAM_POINT_SIZE)) + .Times(1) + .RetiresOnSaturation(); - EXPECT_CALL(*gl_, Enable(GL_POINT_SPRITE)) - .Times(1) - .RetiresOnSaturation(); + EXPECT_CALL(*gl_, Enable(GL_POINT_SPRITE)) + .Times(1) + .RetiresOnSaturation(); + } static GLint max_viewport_dims[] = { kMaxViewportWidth, @@ -1684,7 +1687,7 @@ void GLES2DecoderTestBase::DeleteIndexBuffer() { void GLES2DecoderTestBase::AddExpectationsForSimulatedAttrib0WithError( GLsizei num_vertices, GLuint buffer_id, GLenum error) { - if (gfx::GetGLImplementation() == gfx::kGLImplementationEGLGLES2) { + if (group_->feature_info()->gl_version_info().BehavesLikeGLES()) { return; } diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc index 957b53b..fc5e2de 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc @@ -60,7 +60,10 @@ class GLES2DecoderGeometryInstancingTest : public GLES2DecoderWithShaderTest { void SetUp() override { InitState init; init.extensions = "GL_ANGLE_instanced_arrays"; - init.gl_version = "opengl es 2.0"; + // Most of the tests in this file assume they're running on + // desktop OpenGL, and large portions of the tests will become + // no-ops if they aren't. + init.gl_version = "opengl 2.1"; init.has_alpha = true; init.has_depth = true; init.request_alpha = true; diff --git a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc index 21526b1..4255ffa 100644 --- a/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc +++ b/gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc @@ -1543,7 +1543,7 @@ class GLES2DecoderMultisampledRenderToTextureTest *gl_, RenderbufferStorageMultisampleIMG(GL_RENDERBUFFER, TestHelper::kMaxSamples, - GL_RGBA, + GL_RGBA4, TestHelper::kMaxRenderbufferSize, 1)) .Times(1) @@ -1553,7 +1553,7 @@ class GLES2DecoderMultisampledRenderToTextureTest *gl_, RenderbufferStorageMultisampleEXT(GL_RENDERBUFFER, TestHelper::kMaxSamples, - GL_RGBA, + GL_RGBA4, TestHelper::kMaxRenderbufferSize, 1)) .Times(1) diff --git a/gpu/command_buffer/service/renderbuffer_manager.cc b/gpu/command_buffer/service/renderbuffer_manager.cc index 4b4337e..2af22de 100644 --- a/gpu/command_buffer/service/renderbuffer_manager.cc +++ b/gpu/command_buffer/service/renderbuffer_manager.cc @@ -8,6 +8,7 @@ #include "base/strings/stringprintf.h" #include "base/trace_event/trace_event.h" #include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gles2_cmd_decoder.h" #include "gpu/command_buffer/service/memory_tracking.h" #include "ui/gl/gl_implementation.h" @@ -43,12 +44,12 @@ RenderbufferManager::RenderbufferManager( MemoryTracker* memory_tracker, GLint max_renderbuffer_size, GLint max_samples, - bool depth24_supported) + FeatureInfo* feature_info) : memory_tracker_( new MemoryTypeTracker(memory_tracker, MemoryTracker::kUnmanaged)), max_renderbuffer_size_(max_renderbuffer_size), max_samples_(max_samples), - depth24_supported_(depth24_supported), + feature_info_(feature_info), num_uncleared_renderbuffers_(0), renderbuffer_count_(0), have_context_(true) { @@ -210,7 +211,7 @@ bool RenderbufferManager::ComputeEstimatedRenderbufferSize(int width, GLenum RenderbufferManager::InternalRenderbufferFormatToImplFormat( GLenum impl_format) const { - if (gfx::GetGLImplementation() != gfx::kGLImplementationEGLGLES2) { + if (!feature_info_->gl_version_info().BehavesLikeGLES()) { switch (impl_format) { case GL_DEPTH_COMPONENT16: return GL_DEPTH_COMPONENT; @@ -222,7 +223,8 @@ GLenum RenderbufferManager::InternalRenderbufferFormatToImplFormat( } } else { // Upgrade 16-bit depth to 24-bit if possible. - if (impl_format == GL_DEPTH_COMPONENT16 && depth24_supported_) + if (impl_format == GL_DEPTH_COMPONENT16 && + feature_info_->feature_flags().oes_depth24) return GL_DEPTH_COMPONENT24; } return impl_format; diff --git a/gpu/command_buffer/service/renderbuffer_manager.h b/gpu/command_buffer/service/renderbuffer_manager.h index 71f830a..be4cc09 100644 --- a/gpu/command_buffer/service/renderbuffer_manager.h +++ b/gpu/command_buffer/service/renderbuffer_manager.h @@ -17,6 +17,7 @@ namespace gpu { namespace gles2 { +class FeatureInfo; class RenderbufferManager; // Info about a Renderbuffer. @@ -128,7 +129,7 @@ class GPU_EXPORT RenderbufferManager { RenderbufferManager(MemoryTracker* memory_tracker, GLint max_renderbuffer_size, GLint max_samples, - bool depth24_supported); + FeatureInfo* feature_info); ~RenderbufferManager(); GLint max_renderbuffer_size() const { @@ -182,7 +183,8 @@ class GPU_EXPORT RenderbufferManager { GLint max_renderbuffer_size_; GLint max_samples_; - bool depth24_supported_; + + scoped_refptr<FeatureInfo> feature_info_; int num_uncleared_renderbuffers_; diff --git a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc index 7c625e6..7633f68 100644 --- a/gpu/command_buffer/service/renderbuffer_manager_unittest.cc +++ b/gpu/command_buffer/service/renderbuffer_manager_unittest.cc @@ -6,8 +6,10 @@ #include <set> #include "gpu/command_buffer/common/gles2_cmd_utils.h" +#include "gpu/command_buffer/service/feature_info.h" #include "gpu/command_buffer/service/gpu_service_test.h" #include "gpu/command_buffer/service/mocks.h" +#include "gpu/command_buffer/service/test_helper.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_mock.h" @@ -23,10 +25,19 @@ class RenderbufferManagerTestBase : public GpuServiceTest { static const GLint kMaxSamples = 4; protected: - void SetUpBase(MemoryTracker* memory_tracker, bool depth24_supported) { + void SetUpBase(MemoryTracker* memory_tracker, + bool depth24_supported, + bool use_gles) { GpuServiceTest::SetUp(); + feature_info_ = new FeatureInfo(); + TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( + gl_.get(), + depth24_supported ? "GL_OES_depth24" : "", + "", + use_gles ? "OpenGL ES 2.0" : "OpenGL 2.1"); + feature_info_->Initialize(); manager_.reset(new RenderbufferManager( - memory_tracker, kMaxSize, kMaxSamples, depth24_supported)); + memory_tracker, kMaxSize, kMaxSamples, feature_info_.get())); } void TearDown() override { @@ -35,6 +46,7 @@ class RenderbufferManagerTestBase : public GpuServiceTest { GpuServiceTest::TearDown(); } + scoped_refptr<FeatureInfo> feature_info_; scoped_ptr<RenderbufferManager> manager_; }; @@ -42,7 +54,8 @@ class RenderbufferManagerTest : public RenderbufferManagerTestBase { protected: void SetUp() override { bool depth24_supported = false; - SetUpBase(NULL, depth24_supported); + bool use_gles = false; + SetUpBase(NULL, depth24_supported, use_gles); } }; @@ -52,7 +65,8 @@ class RenderbufferManagerMemoryTrackerTest void SetUp() override { mock_memory_tracker_ = new StrictMock<MockMemoryTracker>(); bool depth24_supported = false; - SetUpBase(mock_memory_tracker_.get(), depth24_supported); + bool use_gles = false; + SetUpBase(mock_memory_tracker_.get(), depth24_supported, use_gles); } scoped_refptr<MockMemoryTracker> mock_memory_tracker_; @@ -291,29 +305,34 @@ TEST_F(RenderbufferManagerTest, AddToSignature) { .RetiresOnSaturation(); } -class RenderbufferManagerFormatTest : public RenderbufferManagerTestBase { +class RenderbufferManagerFormatGLESTest : public RenderbufferManagerTestBase { protected: void SetUp() override { bool depth24_supported = true; - SetUpBase(NULL, depth24_supported); + bool use_gles = true; + SetUpBase(NULL, depth24_supported, use_gles); } }; -TEST_F(RenderbufferManagerFormatTest, UpgradeDepthFormatOnGLES) { - gfx::GLImplementation prev_impl = gfx::GetGLImplementation(); - gfx::SetGLImplementation(gfx::kGLImplementationEGLGLES2); +TEST_F(RenderbufferManagerFormatGLESTest, UpgradeDepthFormatOnGLES) { GLenum impl_format = manager_->InternalRenderbufferFormatToImplFormat(GL_DEPTH_COMPONENT16); - gfx::SetGLImplementation(prev_impl); EXPECT_EQ(static_cast<GLenum>(GL_DEPTH_COMPONENT24), impl_format); } -TEST_F(RenderbufferManagerFormatTest, UseUnsizedDepthFormatOnNonGLES) { - gfx::GLImplementation prev_impl = gfx::GetGLImplementation(); - gfx::SetGLImplementation(gfx::kGLImplementationDesktopGL); +class RenderbufferManagerFormatNonGLESTest : + public RenderbufferManagerTestBase { + protected: + void SetUp() override { + bool depth24_supported = true; + bool use_gles = false; + SetUpBase(NULL, depth24_supported, use_gles); + } +}; + +TEST_F(RenderbufferManagerFormatNonGLESTest, UseUnsizedDepthFormatOnNonGLES) { GLenum impl_format = manager_->InternalRenderbufferFormatToImplFormat(GL_DEPTH_COMPONENT16); - gfx::SetGLImplementation(prev_impl); EXPECT_EQ(static_cast<GLenum>(GL_DEPTH_COMPONENT), impl_format); } diff --git a/gpu/command_buffer/service/shader_translator.cc b/gpu/command_buffer/service/shader_translator.cc index c0904c7b..b4a94fc 100644 --- a/gpu/command_buffer/service/shader_translator.cc +++ b/gpu/command_buffer/service/shader_translator.cc @@ -15,6 +15,7 @@ #include "base/strings/string_number_conversions.h" #include "base/trace_event/trace_event.h" #include "gpu/command_buffer/service/gpu_switches.h" +#include "ui/gl/gl_implementation.h" namespace gpu { namespace gles2 { @@ -120,8 +121,15 @@ bool ShaderTranslator::Init( if (glsl_implementation_type == kGlslES) { shader_output = SH_ESSL_OUTPUT; } else { - shader_output = (shader_spec == SH_WEBGL2_SPEC) ? SH_GLSL_CORE_OUTPUT : - SH_GLSL_COMPATIBILITY_OUTPUT; + // TODO(kbr): clean up the tests of shader_spec and + // gfx::GetGLImplementation(). crbug.com/471960 + if (shader_spec == SH_WEBGL2_SPEC || + gfx::GetGLImplementation() == + gfx::kGLImplementationDesktopGLCoreProfile) { + shader_output = SH_GLSL_CORE_OUTPUT; + } else { + shader_output = SH_GLSL_COMPATIBILITY_OUTPUT; + } } { diff --git a/gpu/command_buffer/service/test_helper.cc b/gpu/command_buffer/service/test_helper.cc index 096a60c..2104ddb 100644 --- a/gpu/command_buffer/service/test_helper.cc +++ b/gpu/command_buffer/service/test_helper.cc @@ -18,6 +18,7 @@ #include "gpu/command_buffer/service/texture_manager.h" #include "testing/gtest/include/gtest/gtest.h" #include "ui/gl/gl_mock.h" +#include "ui/gl/gl_version_info.h" using ::testing::_; using ::testing::DoAll; @@ -80,6 +81,8 @@ const GLint TestHelper::kMaxVertexUniformVectors; const GLint TestHelper::kMaxVertexUniformComponents; #endif +std::vector<std::string> TestHelper::split_extensions_; + void TestHelper::SetupTextureInitializationExpectations( ::gfx::MockGLInterface* gl, GLenum target, @@ -270,14 +273,14 @@ void TestHelper::SetupContextGroupInitExpectations( SetupFeatureInfoInitExpectationsWithGLVersion(gl, extensions, "", gl_version); - std::string l_version(base::StringToLowerASCII(std::string(gl_version))); - bool is_es3 = (l_version.substr(0, 12) == "opengl es 3."); + gfx::GLVersionInfo gl_info(gl_version, "", extensions); EXPECT_CALL(*gl, GetIntegerv(GL_MAX_RENDERBUFFER_SIZE, _)) .WillOnce(SetArgumentPointee<1>(kMaxRenderbufferSize)) .RetiresOnSaturation(); if (strstr(extensions, "GL_EXT_framebuffer_multisample") || - strstr(extensions, "GL_EXT_multisampled_render_to_texture") || is_es3) { + strstr(extensions, "GL_EXT_multisampled_render_to_texture") || + gl_info.is_es3) { EXPECT_CALL(*gl, GetIntegerv(GL_MAX_SAMPLES, _)) .WillOnce(SetArgumentPointee<1>(kMaxSamples)) .RetiresOnSaturation(); @@ -309,15 +312,28 @@ void TestHelper::SetupContextGroupInitExpectations( EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, _)) .WillOnce(SetArgumentPointee<1>(kMaxVertexTextureImageUnits)) .RetiresOnSaturation(); - EXPECT_CALL(*gl, GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, _)) - .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformComponents)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VARYING_FLOATS, _)) - .WillOnce(SetArgumentPointee<1>(kMaxVaryingFloats)) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, _)) - .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformComponents)) - .RetiresOnSaturation(); + + if (gl_info.is_es) { + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_VECTORS, _)) + .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformVectors)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VARYING_VECTORS, _)) + .WillOnce(SetArgumentPointee<1>(kMaxVaryingVectors)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_UNIFORM_VECTORS, _)) + .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformVectors)) + .RetiresOnSaturation(); + } else { + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_FRAGMENT_UNIFORM_COMPONENTS, _)) + .WillOnce(SetArgumentPointee<1>(kMaxFragmentUniformComponents)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VARYING_FLOATS, _)) + .WillOnce(SetArgumentPointee<1>(kMaxVaryingFloats)) + .RetiresOnSaturation(); + EXPECT_CALL(*gl, GetIntegerv(GL_MAX_VERTEX_UNIFORM_COMPONENTS, _)) + .WillOnce(SetArgumentPointee<1>(kMaxVertexUniformComponents)) + .RetiresOnSaturation(); + } bool use_default_textures = bind_generates_resource; SetupTextureManagerInitExpectations(gl, extensions, use_default_textures); @@ -335,21 +351,39 @@ void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( const char* gl_version) { InSequence sequence; - EXPECT_CALL(*gl, GetString(GL_EXTENSIONS)) - .WillOnce(Return(reinterpret_cast<const uint8*>(extensions))) - .RetiresOnSaturation(); - EXPECT_CALL(*gl, GetString(GL_RENDERER)) - .WillOnce(Return(reinterpret_cast<const uint8*>(gl_renderer))) - .RetiresOnSaturation(); EXPECT_CALL(*gl, GetString(GL_VERSION)) .WillOnce(Return(reinterpret_cast<const uint8*>(gl_version))) .RetiresOnSaturation(); - std::string l_version(base::StringToLowerASCII(std::string(gl_version))); - bool is_es3 = (l_version.substr(0, 12) == "opengl es 3."); + // Persistent storage is needed for the split extension string. + split_extensions_.clear(); + if (extensions) { + Tokenize(extensions, " ", &split_extensions_); + } + + gfx::GLVersionInfo gl_info(gl_version, gl_renderer, extensions); + if (!gl_info.is_es && gl_info.major_version >= 3) { + EXPECT_CALL(*gl, GetIntegerv(GL_NUM_EXTENSIONS, _)) + .WillOnce(SetArgumentPointee<1>(split_extensions_.size())) + .RetiresOnSaturation(); + for (size_t ii = 0; ii < split_extensions_.size(); ++ii) { + EXPECT_CALL(*gl, GetStringi(GL_EXTENSIONS, ii)) + .WillOnce(Return(reinterpret_cast<const uint8*>( + split_extensions_[ii].c_str()))) + .RetiresOnSaturation(); + } + } else { + EXPECT_CALL(*gl, GetString(GL_EXTENSIONS)) + .WillOnce(Return(reinterpret_cast<const uint8*>(extensions))) + .RetiresOnSaturation(); + } + + EXPECT_CALL(*gl, GetString(GL_RENDERER)) + .WillOnce(Return(reinterpret_cast<const uint8*>(gl_renderer))) + .RetiresOnSaturation(); if (strstr(extensions, "GL_ARB_texture_float") || - (is_es3 && strstr(extensions, "GL_EXT_color_buffer_float"))) { + (gl_info.is_es3 && strstr(extensions, "GL_EXT_color_buffer_float"))) { static const GLuint tx_ids[] = {101, 102}; static const GLuint fb_ids[] = {103, 104}; const GLsizei width = 16; @@ -390,7 +424,7 @@ void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( GL_RGB, GL_FLOAT, _)) .Times(1) .RetiresOnSaturation(); - if (is_es3) { + if (gl_info.is_es3) { EXPECT_CALL(*gl, CheckFramebufferStatusEXT(GL_FRAMEBUFFER)) .WillOnce(Return(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT)) .RetiresOnSaturation(); @@ -420,7 +454,7 @@ void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( if (strstr(extensions, "GL_EXT_draw_buffers") || strstr(extensions, "GL_ARB_draw_buffers") || - (is_es3 && strstr(extensions, "GL_NV_draw_buffers"))) { + (gl_info.is_es3 && strstr(extensions, "GL_NV_draw_buffers"))) { EXPECT_CALL(*gl, GetIntegerv(GL_MAX_COLOR_ATTACHMENTS_EXT, _)) .WillOnce(SetArgumentPointee<1>(8)) .RetiresOnSaturation(); @@ -429,7 +463,7 @@ void TestHelper::SetupFeatureInfoInitExpectationsWithGLVersion( .RetiresOnSaturation(); } - if (is_es3 || strstr(extensions, "GL_EXT_texture_rg") || + if (gl_info.is_es3 || strstr(extensions, "GL_EXT_texture_rg") || (strstr(extensions, "GL_ARB_texture_rg"))) { static const GLuint tx_ids[] = {101, 102}; static const GLuint fb_ids[] = {103, 104}; diff --git a/gpu/command_buffer/service/test_helper.h b/gpu/command_buffer/service/test_helper.h index a536cce..2cf3f96 100644 --- a/gpu/command_buffer/service/test_helper.h +++ b/gpu/command_buffer/service/test_helper.h @@ -5,6 +5,9 @@ #ifndef GPU_COMMAND_BUFFER_SERVICE_TEST_HELPER_H_ #define GPU_COMMAND_BUFFER_SERVICE_TEST_HELPER_H_ +#include <string> +#include <vector> + #include "gpu/command_buffer/service/shader_translator.h" #include "ui/gl/gl_implementation.h" #include "ui/gl/gl_mock.h" @@ -140,6 +143,8 @@ class TestHelper { static void SetupTextureDestructionExpectations(::gfx::MockGLInterface* gl, GLenum target, bool use_default_textures); + + static std::vector<std::string> split_extensions_; }; // This object temporaritly Sets what gfx::GetGLImplementation returns. During diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py index fdeb96c..9b5d9f5 100755 --- a/ui/gl/generate_bindings.py +++ b/ui/gl/generate_bindings.py @@ -25,6 +25,7 @@ UNCONDITIONALLY_BOUND_EXTENSIONS = set([ 'WGL_ARB_extensions_string', 'WGL_EXT_extensions_string', 'GL_CHROMIUM_gles_depth_binding_hack', # crbug.com/448206 + 'GL_CHROMIUM_glgetstringi_hack', # crbug.com/470396 ]) """Function binding conditions can be specified manually by supplying a versions @@ -612,7 +613,10 @@ GL_FUNCTIONS = [ 'names': ['glGetString'], 'arguments': 'GLenum name', }, { 'return_type': 'const GLubyte*', - 'names': ['glGetStringi'], + # This is needed for bootstrapping on the desktop GL core profile. + # It won't be called unless the expected GL version is used. + 'versions': [{ 'name': 'glGetStringi', + 'extensions': ['GL_CHROMIUM_glgetstringi_hack'] }], 'arguments': 'GLenum name, GLuint index', }, { 'return_type': 'void', 'versions': [{ 'name': 'glGetSynciv', @@ -1775,7 +1779,7 @@ def GenerateMockHeader(file, functions, set_name): file.write('\n') -def GenerateSource(file, functions, set_name, used_extensions): +def GenerateSource(file, functions, set_name, used_extensions, options): """Generates gl_bindings_autogen_x.cc""" set_header_name = "ui/gl/gl_" + set_name.lower() + "_api_implementation.h" @@ -1971,6 +1975,11 @@ namespace gfx { (set_name.lower(), function_name, argument_names)) if 'logging_code' in func: file.write("%s\n" % func['logging_code']) + if options.generate_dchecks and set_name == 'gl': + file.write(' {\n') + file.write(' GLenum error = g_driver_gl.debug_fn.glGetErrorFn();\n') + file.write(' DCHECK(error == 0);\n') + file.write(' }\n') else: file.write(' GL_SERVICE_LOG("%s" << "(" %s << ")");\n' % (function_name, log_argument_names)) @@ -1980,6 +1989,11 @@ namespace gfx { file.write("%s\n" % func['logging_code']) else: file.write(' GL_SERVICE_LOG("GL_RESULT: " << result);\n') + if options.generate_dchecks and set_name == 'gl': + file.write(' {\n') + file.write(' GLenum _error = g_driver_gl.debug_fn.glGetErrorFn();\n') + file.write(' DCHECK(_error == 0);\n') + file.write(' }\n') file.write(' return result;\n') file.write('}\n') file.write('} // extern "C"\n') @@ -2448,6 +2462,9 @@ def main(argv): parser = optparse.OptionParser() parser.add_option('--inputs', action='store_true') parser.add_option('--verify-order', action='store_true') + parser.add_option('--generate-dchecks', action='store_true', + help='Generates DCHECKs into the logging functions ' + 'asserting no GL errors (useful for debugging)') options, args = parser.parse_args(argv) @@ -2512,7 +2529,7 @@ def main(argv): source_file = open( os.path.join(directory, 'gl_bindings_autogen_%s.cc' % set_name), 'wb') - GenerateSource(source_file, functions, set_name, used_extensions) + GenerateSource(source_file, functions, set_name, used_extensions, options) source_file.close() ClangFormat(source_file.name) diff --git a/ui/gl/gl_bindings_autogen_gl.cc b/ui/gl/gl_bindings_autogen_gl.cc index 726f545..54e8f34 100644 --- a/ui/gl/gl_bindings_autogen_gl.cc +++ b/ui/gl/gl_bindings_autogen_gl.cc @@ -226,7 +226,8 @@ void DriverGL::InitializeStaticBindings() { GetGLProcAddress("glGetShaderSource")); fn.glGetStringFn = reinterpret_cast<glGetStringProc>(GetGLProcAddress("glGetString")); - fn.glGetStringiFn = 0; + fn.glGetStringiFn = + reinterpret_cast<glGetStringiProc>(GetGLProcAddress("glGetStringi")); fn.glGetSyncivFn = 0; fn.glGetTexLevelParameterfvFn = 0; fn.glGetTexLevelParameterivFn = 0; @@ -477,6 +478,8 @@ void DriverGL::InitializeDynamicBindings(GLContext* context) { ext.b_GL_CHROMIUM_gles_depth_binding_hack = extensions.find("GL_CHROMIUM_gles_depth_binding_hack ") != std::string::npos; + ext.b_GL_CHROMIUM_glgetstringi_hack = + extensions.find("GL_CHROMIUM_glgetstringi_hack ") != std::string::npos; ext.b_GL_EXT_debug_marker = extensions.find("GL_EXT_debug_marker ") != std::string::npos; ext.b_GL_EXT_direct_state_access = @@ -1368,13 +1371,6 @@ void DriverGL::InitializeDynamicBindings(GLContext* context) { DCHECK(fn.glGetShaderPrecisionFormatFn); } - debug_fn.glGetStringiFn = 0; - if (ver->IsAtLeastGL(3u, 0u) || ver->IsAtLeastGLES(3u, 0u)) { - fn.glGetStringiFn = - reinterpret_cast<glGetStringiProc>(GetGLProcAddress("glGetStringi")); - DCHECK(fn.glGetStringiFn); - } - debug_fn.glGetSyncivFn = 0; if (ver->IsAtLeastGL(3u, 2u) || ver->IsAtLeastGLES(3u, 0u) || ext.b_GL_ARB_sync) { diff --git a/ui/gl/gl_bindings_autogen_gl.h b/ui/gl/gl_bindings_autogen_gl.h index 4a4acc9..0494657 100644 --- a/ui/gl/gl_bindings_autogen_gl.h +++ b/ui/gl/gl_bindings_autogen_gl.h @@ -898,6 +898,7 @@ struct ExtensionsGL { bool b_GL_ARB_timer_query; bool b_GL_ARB_vertex_array_object; bool b_GL_CHROMIUM_gles_depth_binding_hack; + bool b_GL_CHROMIUM_glgetstringi_hack; bool b_GL_EXT_debug_marker; bool b_GL_EXT_direct_state_access; bool b_GL_EXT_discard_framebuffer; diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc index e64d031..4795d58 100644 --- a/ui/gl/gl_context.cc +++ b/ui/gl/gl_context.cc @@ -9,6 +9,7 @@ #include "base/command_line.h" #include "base/lazy_instance.h" #include "base/logging.h" +#include "base/strings/string_util.h" #include "base/threading/thread_local.h" #include "ui/gl/gl_bindings.h" #include "ui/gl/gl_context.h" @@ -84,8 +85,22 @@ void GLContext::SetUnbindFboOnMakeCurrent() { std::string GLContext::GetExtensions() { DCHECK(IsCurrent(NULL)); - const char* ext = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); - return std::string(ext ? ext : ""); + if (gfx::GetGLImplementation() != + gfx::kGLImplementationDesktopGLCoreProfile) { + const char* ext = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); + return std::string(ext ? ext : ""); + } + + std::vector<std::string> exts; + GLint num_extensions = 0; + glGetIntegerv(GL_NUM_EXTENSIONS, &num_extensions); + for (GLint i = 0; i < num_extensions; ++i) { + const char* extension = reinterpret_cast<const char*>( + glGetStringi(GL_EXTENSIONS, i)); + DCHECK(extension != NULL); + exts.push_back(extension); + } + return JoinString(exts, " "); } std::string GLContext::GetGLVersion() { @@ -135,7 +150,9 @@ const GLVersionInfo* GLContext::GetVersionInfo() { std::string version = GetGLVersion(); std::string renderer = GetGLRenderer(); version_info_ = - make_scoped_ptr(new GLVersionInfo(version.c_str(), renderer.c_str())); + make_scoped_ptr(new GLVersionInfo( + version.c_str(), renderer.c_str(), + GetExtensions().c_str())); } return version_info_.get(); } diff --git a/ui/gl/gl_context_cgl.cc b/ui/gl/gl_context_cgl.cc index 102407c..2fd20a0 100644 --- a/ui/gl/gl_context_cgl.cc +++ b/ui/gl/gl_context_cgl.cc @@ -47,6 +47,15 @@ static CGLPixelFormatObj GetPixelFormat() { attribs.push_back((CGLPixelFormatAttribute) kCGLRendererGenericFloatID); g_support_renderer_switching = false; } + if (GetGLImplementation() == kGLImplementationDesktopGLCoreProfile) { + // These constants don't exist in the 10.6 SDK against which + // Chromium currently compiles. + const int kOpenGLProfile = 99; + const int kOpenGL3_2Core = 0x3200; + attribs.push_back(static_cast<CGLPixelFormatAttribute>(kOpenGLProfile)); + attribs.push_back(static_cast<CGLPixelFormatAttribute>(kOpenGL3_2Core)); + } + attribs.push_back((CGLPixelFormatAttribute) 0); GLint num_virtual_screens; diff --git a/ui/gl/gl_context_mac.mm b/ui/gl/gl_context_mac.mm index aa5516f..b20cee2 100644 --- a/ui/gl/gl_context_mac.mm +++ b/ui/gl/gl_context_mac.mm @@ -24,6 +24,7 @@ scoped_refptr<GLContext> GLContext::CreateGLContext( TRACE_EVENT0("gpu", "GLContext::CreateGLContext"); switch (GetGLImplementation()) { case kGLImplementationDesktopGL: + case kGLImplementationDesktopGLCoreProfile: case kGLImplementationAppleGL: { scoped_refptr<GLContext> context; // Note that with virtualization we might still be able to make current diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc index 5bea3f1..6752a25 100644 --- a/ui/gl/gl_gl_api_implementation.cc +++ b/ui/gl/gl_gl_api_implementation.cc @@ -331,8 +331,10 @@ const GLVersionInfo* GetGLVersionInfo() { void InitializeDynamicGLBindingsGL(GLContext* context) { g_driver_gl.InitializeCustomDynamicBindings(context); DCHECK(context && context->IsCurrent(NULL) && !g_version_info); - g_version_info = new GLVersionInfo(context->GetGLVersion().c_str(), - context->GetGLRenderer().c_str()); + g_version_info = new GLVersionInfo( + context->GetGLVersion().c_str(), + context->GetGLRenderer().c_str(), + context->GetExtensions().c_str()); } void InitializeDebugGLBindingsGL() { @@ -435,8 +437,7 @@ void VirtualGLApi::Initialize(DriverGL* driver, GLContext* real_context) { real_context_ = real_context; DCHECK(real_context->IsCurrent(NULL)); - std::string ext_string( - reinterpret_cast<const char*>(driver_->fn.glGetStringFn(GL_EXTENSIONS))); + std::string ext_string = real_context->GetExtensions(); std::vector<std::string> ext; Tokenize(ext_string, " ", &ext); diff --git a/ui/gl/gl_implementation.cc b/ui/gl/gl_implementation.cc index 74b95b8..a307fb0 100644 --- a/ui/gl/gl_implementation.cc +++ b/ui/gl/gl_implementation.cc @@ -99,6 +99,7 @@ GLImplementation GetGLImplementation() { bool HasDesktopGLFeatures() { return kGLImplementationDesktopGL == g_gl_implementation || + kGLImplementationDesktopGLCoreProfile == g_gl_implementation || kGLImplementationOSMesaGL == g_gl_implementation || kGLImplementationAppleGL == g_gl_implementation; } diff --git a/ui/gl/gl_implementation.h b/ui/gl/gl_implementation.h index 7319b47..6ee43e7 100644 --- a/ui/gl/gl_implementation.h +++ b/ui/gl/gl_implementation.h @@ -21,6 +21,7 @@ class GLContext; enum GLImplementation { kGLImplementationNone, kGLImplementationDesktopGL, + kGLImplementationDesktopGLCoreProfile, kGLImplementationOSMesaGL, kGLImplementationAppleGL, kGLImplementationEGLGLES2, diff --git a/ui/gl/gl_implementation_mac.cc b/ui/gl/gl_implementation_mac.cc index d818f05..8704eb9 100644 --- a/ui/gl/gl_implementation_mac.cc +++ b/ui/gl/gl_implementation_mac.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/base_paths.h" +#include "base/command_line.h" #include "base/files/file_path.h" #include "base/logging.h" #include "base/mac/foundation_util.h" @@ -22,6 +23,10 @@ const char kOpenGLFrameworkPath[] = } // namespace void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) { + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kEnableUnsafeES3APIs)) { + impls->push_back(kGLImplementationDesktopGLCoreProfile); + } impls->push_back(kGLImplementationDesktopGL); impls->push_back(kGLImplementationAppleGL); impls->push_back(kGLImplementationOSMesaGL); @@ -82,6 +87,7 @@ bool InitializeStaticGLBindings(GLImplementation implementation) { break; } case kGLImplementationDesktopGL: + case kGLImplementationDesktopGLCoreProfile: case kGLImplementationAppleGL: { base::NativeLibrary library = base::LoadNativeLibrary( base::FilePath(kOpenGLFrameworkPath), NULL); @@ -113,6 +119,7 @@ bool InitializeDynamicGLBindings(GLImplementation implementation, switch (implementation) { case kGLImplementationOSMesaGL: case kGLImplementationDesktopGL: + case kGLImplementationDesktopGLCoreProfile: case kGLImplementationAppleGL: InitializeDynamicGLBindingsGL(context); break; diff --git a/ui/gl/gl_surface_mac.cc b/ui/gl/gl_surface_mac.cc index 4ba560d..85e9714 100644 --- a/ui/gl/gl_surface_mac.cc +++ b/ui/gl/gl_surface_mac.cc @@ -95,6 +95,7 @@ bool InitializeOneOffForSandbox() { bool GLSurface::InitializeOneOffInternal() { switch (GetGLImplementation()) { case kGLImplementationDesktopGL: + case kGLImplementationDesktopGLCoreProfile: case kGLImplementationAppleGL: if (!InitializeOneOffForSandbox()) { LOG(ERROR) << "GLSurfaceCGL::InitializeOneOff failed."; @@ -112,6 +113,7 @@ scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface( TRACE_EVENT0("gpu", "GLSurface::CreateViewGLSurface"); switch (GetGLImplementation()) { case kGLImplementationDesktopGL: + case kGLImplementationDesktopGLCoreProfile: case kGLImplementationAppleGL: { NOTIMPLEMENTED() << "No onscreen support on Mac."; return NULL; @@ -143,6 +145,7 @@ scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface( return surface; } case kGLImplementationDesktopGL: + case kGLImplementationDesktopGLCoreProfile: case kGLImplementationAppleGL: { scoped_refptr<GLSurface> surface(new NoOpGLSurface(size)); if (!surface->Initialize()) diff --git a/ui/gl/gl_version_info.cc b/ui/gl/gl_version_info.cc index e2aa0de..415faf3 100644 --- a/ui/gl/gl_version_info.cc +++ b/ui/gl/gl_version_info.cc @@ -10,33 +10,64 @@ namespace gfx { +GLVersionInfo::GLVersionInfo(const char* version_str, const char* renderer_str, + const char* extensions_str) + : GLVersionInfo(version_str, renderer_str) { + is_desktop_core_profile = + !is_es && major_version >= 3 && + !strstr(extensions_str, "GL_ARB_compatibility"); +} + +GLVersionInfo::GLVersionInfo(const char* version_str, const char* renderer_str, + const std::set<std::string>& extensions) + : GLVersionInfo(version_str, renderer_str) { + is_desktop_core_profile = + !is_es && major_version >= 3 && + extensions.find("GL_ARB_compatibility") == extensions.end(); +} + GLVersionInfo::GLVersionInfo(const char* version_str, const char* renderer_str) : is_es(false), is_angle(false), major_version(0), minor_version(0), - is_es3(false) { + is_es3(false), + is_desktop_core_profile(false) { if (version_str) { - std::string lstr(base::StringToLowerASCII(std::string(version_str))); - is_es = (lstr.length() > 12) && (lstr.substr(0, 9) == "opengl es"); - if (is_es) - lstr = lstr.substr(10, 3); - base::StringTokenizer tokenizer(lstr.begin(), lstr.end(), "."); - unsigned major, minor; - if (tokenizer.GetNext() && - base::StringToUint(tokenizer.token_piece(), &major)) { - major_version = major; - if (tokenizer.GetNext() && - base::StringToUint(tokenizer.token_piece(), &minor)) { - minor_version = minor; - } - } - if (is_es && major_version == 3) - is_es3 = true; + ParseVersionString(version_str, &major_version, &minor_version, + &is_es, &is_es3); } if (renderer_str) { is_angle = StartsWithASCII(renderer_str, "ANGLE", true); } } +void GLVersionInfo::ParseVersionString(const char* version_str, + unsigned* major_version, + unsigned* minor_version, + bool* is_es, + bool* is_es3) { + // Make sure the outputs are always initialized. + *major_version = 0; + *minor_version = 0; + *is_es = false; + *is_es3 = false; + std::string lstr(base::StringToLowerASCII(std::string(version_str))); + *is_es = (lstr.length() > 12) && (lstr.substr(0, 9) == "opengl es"); + if (*is_es) + lstr = lstr.substr(10, 3); + base::StringTokenizer tokenizer(lstr.begin(), lstr.end(), "."); + unsigned major, minor; + if (tokenizer.GetNext() && + base::StringToUint(tokenizer.token_piece(), &major)) { + *major_version = major; + if (tokenizer.GetNext() && + base::StringToUint(tokenizer.token_piece(), &minor)) { + *minor_version = minor; + } + } + if (*is_es && *major_version == 3) + *is_es3 = true; +} + } // namespace gfx diff --git a/ui/gl/gl_version_info.h b/ui/gl/gl_version_info.h index d8f2730..1bfca20 100644 --- a/ui/gl/gl_version_info.h +++ b/ui/gl/gl_version_info.h @@ -5,6 +5,7 @@ #ifndef UI_GL_GL_VERSION_INFO_H_ #define UI_GL_GL_VERSION_INFO_H_ +#include <set> #include <string> #include "base/basictypes.h" #include "ui/gl/gl_export.h" @@ -12,7 +13,11 @@ namespace gfx { struct GL_EXPORT GLVersionInfo { - GLVersionInfo(const char* version_str, const char* renderer_str); + GLVersionInfo(const char* version_str, const char* renderer_str, + const char* extensions_str); + + GLVersionInfo(const char* version_str, const char* renderer_str, + const std::set<std::string>& exts); bool IsAtLeastGL(unsigned major, unsigned minor) const { return !is_es && (major_version > major || @@ -24,13 +29,26 @@ struct GL_EXPORT GLVersionInfo { (major_version == major && minor_version >= minor)); } + bool BehavesLikeGLES() const { + return is_es || is_desktop_core_profile; + } + + static void ParseVersionString(const char* version_str, + unsigned* major_version, + unsigned* minor_version, + bool* is_es, + bool* is_es3); + bool is_es; bool is_angle; unsigned major_version; unsigned minor_version; bool is_es3; + bool is_desktop_core_profile; private: + GLVersionInfo(const char* version_str, const char* renderer_str); + DISALLOW_COPY_AND_ASSIGN(GLVersionInfo); }; |