summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkbr <kbr@chromium.org>2015-03-31 12:49:12 -0700
committerCommit bot <commit-bot@chromium.org>2015-03-31 19:50:00 +0000
commitc9f0e10c369408bdc80c158a882949f5121f3a7a (patch)
tree199653659aebd5cb137eae8a20fd5cee73abc207
parente0fd6c1d6106a5720fdd97dcefb7dcfd6b4743af (diff)
downloadchromium_src-c9f0e10c369408bdc80c158a882949f5121f3a7a.zip
chromium_src-c9f0e10c369408bdc80c158a882949f5121f3a7a.tar.gz
chromium_src-c9f0e10c369408bdc80c158a882949f5121f3a7a.tar.bz2
Added support for desktop OpenGL's Core Profile on Mac OS X.
Joint work with ccameron@, thanks to whom for the ImageTransportSurface changes and some of the others. When --enable-unsafe-es3-apis is specified, use the core profile rather than the compatibility profile for all OpenGL contexts on Mac OS X. This CL adds the core profile as another known GLImplementation which behaves mostly like OpenGL ES, but partly like desktop GL, and has some differences compared to both. It is likely that Chrome will upgrade to the Core Profile on all platforms using desktop OpenGL, and that support for the compatibility profile will be dropped. Tested with both regular and WebGL content, with all combinations of --enable-unsafe-es3-apis and --disable-remote-core-animation. BUG=470396 Review URL: https://codereview.chromium.org/1038763004 Cr-Commit-Position: refs/heads/master@{#323091}
-rw-r--r--content/common/gpu/image_transport_surface_calayer_mac.h10
-rw-r--r--content/common/gpu/image_transport_surface_calayer_mac.mm239
-rw-r--r--content/common/gpu/image_transport_surface_fbo_mac.mm48
-rw-r--r--content/common/gpu/image_transport_surface_iosurface_mac.h1
-rw-r--r--content/common/gpu/image_transport_surface_mac.mm13
-rwxr-xr-xgpu/command_buffer/build_gles2_cmd_buffer.py13
-rw-r--r--gpu/command_buffer/service/async_pixel_transfer_manager_mac.cc1
-rw-r--r--gpu/command_buffer/service/context_group.cc9
-rw-r--r--gpu/command_buffer/service/context_state_impl_autogen.h8
-rw-r--r--gpu/command_buffer/service/feature_info.cc69
-rw-r--r--gpu/command_buffer/service/feature_info_unittest.cc20
-rw-r--r--gpu/command_buffer/service/framebuffer_manager_unittest.cc100
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder.cc124
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_base.cc17
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_drawing.cc5
-rw-r--r--gpu/command_buffer/service/gles2_cmd_decoder_unittest_framebuffers.cc4
-rw-r--r--gpu/command_buffer/service/renderbuffer_manager.cc10
-rw-r--r--gpu/command_buffer/service/renderbuffer_manager.h6
-rw-r--r--gpu/command_buffer/service/renderbuffer_manager_unittest.cc47
-rw-r--r--gpu/command_buffer/service/shader_translator.cc12
-rw-r--r--gpu/command_buffer/service/test_helper.cc82
-rw-r--r--gpu/command_buffer/service/test_helper.h5
-rwxr-xr-xui/gl/generate_bindings.py23
-rw-r--r--ui/gl/gl_bindings_autogen_gl.cc12
-rw-r--r--ui/gl/gl_bindings_autogen_gl.h1
-rw-r--r--ui/gl/gl_context.cc23
-rw-r--r--ui/gl/gl_context_cgl.cc9
-rw-r--r--ui/gl/gl_context_mac.mm1
-rw-r--r--ui/gl/gl_gl_api_implementation.cc9
-rw-r--r--ui/gl/gl_implementation.cc1
-rw-r--r--ui/gl/gl_implementation.h1
-rw-r--r--ui/gl/gl_implementation_mac.cc7
-rw-r--r--ui/gl/gl_surface_mac.cc3
-rw-r--r--ui/gl/gl_version_info.cc65
-rw-r--r--ui/gl/gl_version_info.h20
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);
};