summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
authoroetuaho@nvidia.com <oetuaho@nvidia.com@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-17 21:31:00 +0000
committeroetuaho@nvidia.com <oetuaho@nvidia.com@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-17 21:31:00 +0000
commita37d7ff28cf1c56e1858abbf93d18ed227199d43 (patch)
treee132b417b5738510d4a9944130c64c9b8a58839b /ui
parentc53c94738a7fe7dd596eae410561e5144de499f2 (diff)
downloadchromium_src-a37d7ff28cf1c56e1858abbf93d18ed227199d43.zip
chromium_src-a37d7ff28cf1c56e1858abbf93d18ed227199d43.tar.gz
chromium_src-a37d7ff28cf1c56e1858abbf93d18ed227199d43.tar.bz2
Take GL version and extensions correctly into account when binding functions
Platform libraries may return non-null function pointers from dlsym or getProcAddress for unsupported GL functions. Previously the function binding logic tried to address this with a separate extension function binding step, but since some of the bindings were still done without consulting the extension string, this failed to account for some conflicts between core and extension functions such as glDiscardFramebufferEXT vs. glInvalidateFramebuffer. Fix this by binding all functions that have multiple versions only after the context has been made current, and consulting the extension and version strings. The logic for binding each function is now only in one place in the generated code and easy to follow. The patch still does not guarantee that the function pointers would be set to null if the function is unsupported. It only attempts to guarantee that an incorrect version of a function is not bound in case another version is supported. The patch is conservative like this to avoid requiring the exact specification of binding conditions in case a function only has one name, and to make it less likely to expose bugs elsewhere. GetGLCoreProcAddress and GetGLProcAddress are combined into one function, which always first looks for the function pointer with dlsym and then with GetProcAddress. The new conditions for binding make sure that this does not result in errors. The patched bindings do not query for incorrect OES or ARB extension strings without the GL_ prefix. Including the incorrect extension strings without the prefix is assumed to have been a mistake. This applies to OES_get_program_binary, OES_vertex_array_object, ARB_get_program_binary, ARB_vertex_array_object, and APPLE_vertex_array_object. BUG=322489 TEST=gpu_unittests, cc_unittests, WebGL conformance tests Review URL: https://codereview.chromium.org/98643013 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@245623 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r--ui/compositor/test/test_suite.cc2
-rwxr-xr-xui/gl/generate_bindings.py545
-rw-r--r--ui/gl/gl.gyp4
-rw-r--r--ui/gl/gl_bindings.h28
-rw-r--r--ui/gl/gl_context.cc23
-rw-r--r--ui/gl/gl_context.h17
-rw-r--r--ui/gl/gl_context_cgl.cc2
-rw-r--r--ui/gl/gl_context_egl.cc2
-rw-r--r--ui/gl/gl_context_glx.cc2
-rw-r--r--ui/gl/gl_context_nsview.mm4
-rw-r--r--ui/gl/gl_context_osmesa.cc2
-rw-r--r--ui/gl/gl_context_stub_with_extensions.cc30
-rw-r--r--ui/gl/gl_context_stub_with_extensions.h37
-rw-r--r--ui/gl/gl_context_wgl.cc2
-rw-r--r--ui/gl/gl_egl_api_implementation.cc8
-rw-r--r--ui/gl/gl_egl_api_implementation.h4
-rw-r--r--ui/gl/gl_gl_api_implementation.cc16
-rw-r--r--ui/gl/gl_gl_api_implementation.h4
-rw-r--r--ui/gl/gl_glx_api_implementation.cc8
-rw-r--r--ui/gl/gl_glx_api_implementation.h4
-rw-r--r--ui/gl/gl_implementation.cc33
-rw-r--r--ui/gl/gl_implementation.h20
-rw-r--r--ui/gl/gl_implementation_android.cc27
-rw-r--r--ui/gl/gl_implementation_linux.cc6
-rw-r--r--ui/gl/gl_implementation_linux.h2
-rw-r--r--ui/gl/gl_implementation_mac.cc27
-rw-r--r--ui/gl/gl_implementation_ozone.cc31
-rw-r--r--ui/gl/gl_implementation_win.cc81
-rw-r--r--ui/gl/gl_implementation_x11.cc37
-rw-r--r--ui/gl/gl_osmesa_api_implementation.cc8
-rw-r--r--ui/gl/gl_osmesa_api_implementation.h4
-rw-r--r--ui/gl/gl_surface.cc4
-rw-r--r--ui/gl/gl_surface_wgl.cc19
-rw-r--r--ui/gl/gl_surface_win.cc2
-rw-r--r--ui/gl/gl_version_info.cc38
-rw-r--r--ui/gl/gl_version_info.h34
-rw-r--r--ui/gl/gl_wgl_api_implementation.cc8
-rw-r--r--ui/gl/gl_wgl_api_implementation.h4
38 files changed, 728 insertions, 401 deletions
diff --git a/ui/compositor/test/test_suite.cc b/ui/compositor/test/test_suite.cc
index b9253ec..aa21ece 100644
--- a/ui/compositor/test/test_suite.cc
+++ b/ui/compositor/test/test_suite.cc
@@ -31,7 +31,7 @@ void CompositorTestSuite::Initialize() {
#if defined(USE_X11)
XInitThreads();
#endif
- CHECK(gfx::InitializeGLBindings(gfx::kGLImplementationOSMesaGL));
+ CHECK(gfx::InitializeStaticGLBindings(gfx::kGLImplementationOSMesaGL));
base::TestSuite::Initialize();
gfx::RegisterPathProvider();
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
index f054baa..ed42225 100755
--- a/ui/gl/generate_bindings.py
+++ b/ui/gl/generate_bindings.py
@@ -11,6 +11,26 @@ import collections
import re
import sys
+"""In case there are multiple versions of the same function, one that's listed
+first takes priority if its conditions are met. If the function is an extension
+function, finding the extension from the extension string is a condition for
+binding it. The last version of the function is treated as a fallback option in
+case no other versions were bound, so a non-null function pointer in the
+bindings does not guarantee that the function is supported.
+
+Function binding conditions can be specified manually by supplying a versions
+array instead of the names array. Each version has the following keys:
+ name: Mandatory. Name of the function. Multiple versions can have the same
+ name but different conditions.
+ gl_versions: List of GL versions where the function is found.
+ extensions: Extensions where the function is found. If not specified, the
+ extensions are determined based on GL header files.
+ If the function exists in an extension header, you may specify
+ an empty array to prevent making that a condition for binding.
+
+By default, the function gets its name from the first name in its names or
+versions array. This can be overridden by supplying a 'known_as' key.
+"""
GL_FUNCTIONS = [
{ 'return_type': 'void',
'names': ['glActiveTexture'],
@@ -313,11 +333,13 @@ GL_FUNCTIONS = [
'names': ['glGetIntegerv'],
'arguments': 'GLenum pname, GLint* params', },
{ 'return_type': 'void',
- 'names': ['glGetProgramBinary', 'glGetProgramBinaryOES'],
+ 'known_as': 'glGetProgramBinary',
+ 'versions': [{ 'name': 'glGetProgramBinaryOES' },
+ { 'name': 'glGetProgramBinary',
+ 'extensions': ['GL_ARB_get_program_binary'] },
+ { 'name': 'glGetProgramBinary' }],
'arguments': 'GLuint program, GLsizei bufSize, GLsizei* length, '
- 'GLenum* binaryFormat, GLvoid* binary',
- 'other_extensions': ['ARB_get_program_binary',
- 'OES_get_program_binary'] },
+ 'GLenum* binaryFormat, GLvoid* binary' },
{ 'return_type': 'void',
'names': ['glGetProgramiv'],
'arguments': 'GLuint program, GLenum pname, GLint* params', },
@@ -435,7 +457,8 @@ GL_FUNCTIONS = [
'names': ['glLinkProgram'],
'arguments': 'GLuint program', },
{ 'return_type': 'void*',
- 'names': ['glMapBuffer', 'glMapBufferOES'],
+ 'known_as': 'glMapBuffer',
+ 'names': ['glMapBufferOES', 'glMapBuffer'],
'arguments': 'GLenum target, GLenum access', },
{ 'return_type': 'void*',
'names': ['glMapBufferRange'],
@@ -454,15 +477,18 @@ GL_FUNCTIONS = [
'names': ['glPolygonOffset'],
'arguments': 'GLfloat factor, GLfloat units', },
{ 'return_type': 'void',
- 'names': ['glProgramBinary', 'glProgramBinaryOES'],
+ 'known_as': 'glProgramBinary',
+ 'versions': [{ 'name': 'glProgramBinaryOES' },
+ { 'name': 'glProgramBinary',
+ 'extensions': ['GL_ARB_get_program_binary'] },
+ { 'name': 'glProgramBinary' }],
'arguments': 'GLuint program, GLenum binaryFormat, '
- 'const GLvoid* binary, GLsizei length',
- 'other_extensions': ['ARB_get_program_binary',
- 'OES_get_program_binary'] },
+ 'const GLvoid* binary, GLsizei length' },
{ 'return_type': 'void',
- 'names': ['glProgramParameteri'],
- 'arguments': 'GLuint program, GLenum pname, GLint value',
- 'other_extensions': ['ARB_get_program_binary'] },
+ 'versions': [{ 'name': 'glProgramParameteri',
+ 'extensions': ['GL_ARB_get_program_binary'] },
+ { 'name': 'glProgramParameteri' }],
+ 'arguments': 'GLuint program, GLenum pname, GLint value' },
{ 'return_type': 'void',
'names': ['glQueryCounter'],
'arguments': 'GLuint id, GLenum target', },
@@ -477,10 +503,27 @@ GL_FUNCTIONS = [
{ 'return_type': 'void',
'names': ['glReleaseShaderCompiler'],
'arguments': 'void', },
+# Multisampling API is different in different GL versions, some require an
+# explicit resolve step for renderbuffers and/or FBO texture attachments and
+# some do not. Multiple alternatives might be present in a single
+# implementation, which require different use of the API and may have
+# different performance (explicit resolve performing worse, for example).
+# So even though the function signature is the same across versions, we split
+# their definitions so that the function to use can be chosen correctly at a
+# higher level.
+# TODO(oetuaho@nvidia.com): Some of these might still be possible to combine.
+# This could also fix weirdness in the mock bindings that's caused by the same
+# function name appearing multiple times.
+# This is the ES3 function, which requires explicit resolve:
{ 'return_type': 'void',
'names': ['glRenderbufferStorageMultisample'],
'arguments': 'GLenum target, GLsizei samples, GLenum internalformat, '
'GLsizei width, GLsizei height', },
+# In desktop GL, EXT and core versions both have an explicit resolve step,
+# though desktop core GL implicitly resolves when drawing to a window.
+# TODO(oetuaho@nvidia.com): Right now this function also doubles as ES2 EXT
+# function, which has implicit resolve, and for which the fallback is wrong.
+# Fix this.
{ 'return_type': 'void',
'names': ['glRenderbufferStorageMultisampleEXT',
'glRenderbufferStorageMultisample'],
@@ -511,8 +554,8 @@ GL_FUNCTIONS = [
'const void* binary, GLsizei length', },
{ 'return_type': 'void',
'names': ['glShaderSource'],
- 'arguments':
- 'GLuint shader, GLsizei count, const char* const* str, const GLint* length',
+ 'arguments': 'GLuint shader, GLsizei count, const char* const* str, '
+ 'const GLint* length',
'logging_code': """
GL_SERVICE_LOG_CODE_BLOCK({
for (GLsizei ii = 0; ii < count; ++ii) {
@@ -636,7 +679,8 @@ GL_FUNCTIONS = [
'arguments': 'GLint location, GLsizei count, '
'GLboolean transpose, const GLfloat* value', },
{ 'return_type': 'GLboolean',
- 'names': ['glUnmapBuffer', 'glUnmapBufferOES'],
+ 'known_as': 'glUnmapBuffer',
+ 'names': ['glUnmapBufferOES', 'glUnmapBuffer'],
'arguments': 'GLenum target', },
{ 'return_type': 'void',
'names': ['glUseProgram'],
@@ -712,51 +756,67 @@ GL_FUNCTIONS = [
'arguments':
'GLsync sync, GLbitfield flags, GLuint64 timeout', },
{ 'return_type': 'void',
- 'names': ['glDrawArraysInstancedANGLE', 'glDrawArraysInstancedARB'],
+ 'known_as': 'glDrawArraysInstancedANGLE',
+ 'names': ['glDrawArraysInstancedARB', 'glDrawArraysInstancedANGLE'],
'arguments': 'GLenum mode, GLint first, GLsizei count, GLsizei primcount', },
{ 'return_type': 'void',
- 'names': ['glDrawElementsInstancedANGLE', 'glDrawElementsInstancedARB'],
+ 'known_as': 'glDrawElementsInstancedANGLE',
+ 'names': ['glDrawElementsInstancedARB', 'glDrawElementsInstancedANGLE'],
'arguments':
'GLenum mode, GLsizei count, GLenum type, const void* indices, '
'GLsizei primcount', },
{ 'return_type': 'void',
- 'names': ['glVertexAttribDivisorANGLE', 'glVertexAttribDivisorARB'],
+ 'known_as': 'glVertexAttribDivisorANGLE',
+ 'names': ['glVertexAttribDivisorARB', 'glVertexAttribDivisorANGLE'],
'arguments':
'GLuint index, GLuint divisor', },
{ 'return_type': 'void',
- 'names': ['glGenVertexArraysOES',
- 'glGenVertexArraysAPPLE',
- 'glGenVertexArrays'],
- 'arguments': 'GLsizei n, GLuint* arrays',
- 'other_extensions': ['OES_vertex_array_object',
- 'APPLE_vertex_array_object',
- 'ARB_vertex_array_object'] },
-{ 'return_type': 'void',
- 'names': ['glDeleteVertexArraysOES',
- 'glDeleteVertexArraysAPPLE',
- 'glDeleteVertexArrays'],
- 'arguments': 'GLsizei n, const GLuint* arrays',
- 'other_extensions': ['OES_vertex_array_object',
- 'APPLE_vertex_array_object',
- 'ARB_vertex_array_object'] },
-{ 'return_type': 'void',
- 'names': ['glBindVertexArrayOES',
- 'glBindVertexArrayAPPLE',
- 'glBindVertexArray'],
- 'arguments': 'GLuint array',
- 'other_extensions': ['OES_vertex_array_object',
- 'APPLE_vertex_array_object',
- 'ARB_vertex_array_object'] },
+ 'known_as': 'glGenVertexArraysOES',
+ 'versions': [{ 'name': 'glGenVertexArrays',
+ 'gl_versions': ['gl3', 'gl4'] },
+ { 'name': 'glGenVertexArrays',
+ 'extensions': ['GL_ARB_vertex_array_object'] },
+ { 'name': 'glGenVertexArraysOES' },
+ { 'name': 'glGenVertexArraysAPPLE',
+ 'extensions': ['GL_APPLE_vertex_array_object'] }],
+ 'arguments': 'GLsizei n, GLuint* arrays', },
+{ 'return_type': 'void',
+ 'known_as': 'glDeleteVertexArraysOES',
+ 'versions': [{ 'name': 'glDeleteVertexArrays',
+ 'gl_versions': ['gl3', 'gl4'] },
+ { 'name': 'glDeleteVertexArrays',
+ 'extensions': ['GL_ARB_vertex_array_object'] },
+ { 'name': 'glDeleteVertexArraysOES' },
+ { 'name': 'glDeleteVertexArraysAPPLE',
+ 'extensions': ['GL_APPLE_vertex_array_object'] }],
+ 'arguments': 'GLsizei n, const GLuint* arrays' },
+{ 'return_type': 'void',
+ 'known_as': 'glBindVertexArrayOES',
+ 'versions': [{ 'name': 'glBindVertexArray',
+ 'gl_versions': ['gl3', 'gl4'] },
+ { 'name': 'glBindVertexArray',
+ 'extensions': ['GL_ARB_vertex_array_object'] },
+ { 'name': 'glBindVertexArrayOES' },
+ { 'name': 'glBindVertexArrayAPPLE',
+ 'extensions': ['GL_APPLE_vertex_array_object'] }],
+ 'arguments': 'GLuint array' },
{ 'return_type': 'GLboolean',
- 'names': ['glIsVertexArrayOES',
- 'glIsVertexArrayAPPLE',
- 'glIsVertexArray'],
- 'arguments': 'GLuint array',
- 'other_extensions': ['OES_vertex_array_object',
- 'APPLE_vertex_array_object',
- 'ARB_vertex_array_object'] },
-{ 'return_type': 'void',
- 'names': ['glDiscardFramebufferEXT', 'glInvalidateFramebuffer'],
+ 'known_as': 'glIsVertexArrayOES',
+ 'versions': [{ 'name': 'glIsVertexArray',
+ 'gl_versions': ['gl3', 'gl4'] },
+ { 'name': 'glIsVertexArray',
+ 'extensions': ['GL_ARB_vertex_array_object'] },
+ { 'name': 'glIsVertexArrayOES' },
+ { 'name': 'glIsVertexArrayAPPLE',
+ 'extensions': ['GL_APPLE_vertex_array_object'] }],
+ 'arguments': 'GLuint array' },
+{ 'return_type': 'void',
+ 'known_as': 'glDiscardFramebufferEXT',
+ 'versions': [{ 'name': 'glInvalidateFramebuffer',
+ 'gl_versions': ['es3'],
+ 'extensions': [] },
+ { 'name': 'glDiscardFramebufferEXT',
+ 'gl_versions': ['es1', 'es2'] }],
'arguments': 'GLenum target, GLsizei numAttachments, '
'const GLenum* attachments' },
]
@@ -845,15 +905,15 @@ EGL_FUNCTIONS = [
'arguments':
'EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value', },
{ 'return_type': 'EGLImageKHR',
- 'names': ['eglCreateImageKHR'],
+ 'versions': [{ 'name': 'eglCreateImageKHR',
+ 'extensions': ['EGL_KHR_image_base'] }],
'arguments':
'EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, '
- 'const EGLint* attrib_list',
- 'other_extensions': ['EGL_KHR_image_base'] },
+ 'const EGLint* attrib_list' },
{ 'return_type': 'EGLBoolean',
- 'names': ['eglDestroyImageKHR'],
- 'arguments': 'EGLDisplay dpy, EGLImageKHR image',
- 'other_extensions': ['EGL_KHR_image_base'] },
+ 'versions': [{ 'name' : 'eglDestroyImageKHR',
+ 'extensions': ['EGL_KHR_image_base'] }],
+ 'arguments': 'EGLDisplay dpy, EGLImageKHR image' },
{ 'return_type': 'EGLSurface',
'names': ['eglCreateWindowSurface'],
'arguments': 'EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, '
@@ -951,23 +1011,23 @@ EGL_FUNCTIONS = [
'arguments':
'EGLDisplay dpy, EGLSurface surface, EGLint attribute, void** value', },
{ 'return_type': 'EGLSyncKHR',
- 'names': ['eglCreateSyncKHR'],
- 'arguments': 'EGLDisplay dpy, EGLenum type, const EGLint* attrib_list',
- 'other_extensions': ['EGL_KHR_fence_sync'] },
+ 'versions': [{ 'name': 'eglCreateSyncKHR',
+ 'extensions': ['EGL_KHR_fence_sync'] }],
+ 'arguments': 'EGLDisplay dpy, EGLenum type, const EGLint* attrib_list' },
{ 'return_type': 'EGLint',
- 'names': ['eglClientWaitSyncKHR'],
+ 'versions': [{ 'name': 'eglClientWaitSyncKHR',
+ 'extensions': ['EGL_KHR_fence_sync'] }],
'arguments': 'EGLDisplay dpy, EGLSyncKHR sync, EGLint flags, '
- 'EGLTimeKHR timeout',
- 'other_extensions': ['EGL_KHR_fence_sync'] },
+ 'EGLTimeKHR timeout' },
{ 'return_type': 'EGLBoolean',
- 'names': ['eglGetSyncAttribKHR'],
+ 'versions': [{ 'name': 'eglGetSyncAttribKHR',
+ 'extensions': ['EGL_KHR_fence_sync'] }],
'arguments': 'EGLDisplay dpy, EGLSyncKHR sync, EGLint attribute, '
- 'EGLint* value',
- 'other_extensions': ['EGL_KHR_fence_sync'] },
+ 'EGLint* value' },
{ 'return_type': 'EGLBoolean',
- 'names': ['eglDestroySyncKHR'],
- 'arguments': 'EGLDisplay dpy, EGLSyncKHR sync',
- 'other_extensions': ['EGL_KHR_fence_sync'] },
+ 'versions': [{ 'name': 'eglDestroySyncKHR',
+ 'extensions': ['EGL_KHR_fence_sync'] }],
+ 'arguments': 'EGLDisplay dpy, EGLSyncKHR sync' },
{ 'return_type': 'EGLBoolean',
'names': ['eglGetSyncValuesCHROMIUM'],
'arguments':
@@ -975,9 +1035,9 @@ EGL_FUNCTIONS = [
'EGLuint64CHROMIUM* ust, EGLuint64CHROMIUM* msc, '
'EGLuint64CHROMIUM* sbc', },
{ 'return_type': 'EGLint',
- 'names': ['eglWaitSyncKHR'],
- 'arguments': 'EGLDisplay dpy, EGLSyncKHR sync, EGLint flags',
- 'other_extensions': ['EGL_KHR_wait_sync'] },
+ 'versions': [{ 'name': 'eglWaitSyncKHR',
+ 'extensions': ['EGL_KHR_fence_sync'] }],
+ 'arguments': 'EGLDisplay dpy, EGLSyncKHR sync, EGLint flags' }
]
WGL_FUNCTIONS = [
@@ -1227,7 +1287,7 @@ FUNCTION_SETS = [
[GLX_FUNCTIONS, [], 'glx', ['GL/glx.h', 'GL/glxext.h'], []],
]
-def GenerateHeader(file, functions, set_name, used_extension_functions):
+def GenerateHeader(file, functions, set_name, used_extensions):
"""Generates gl_bindings_autogen_x.h"""
# Write file header.
@@ -1252,12 +1312,12 @@ class GLContext;
file.write('\n')
for func in functions:
file.write('typedef %s (GL_BINDING_CALL *%sProc)(%s);\n' %
- (func['return_type'], func['names'][0], func['arguments']))
+ (func['return_type'], func['known_as'], func['arguments']))
# Write declarations for booleans indicating which extensions are available.
file.write('\n')
file.write("struct Extensions%s {\n" % set_name.upper())
- for extension, ext_functions in used_extension_functions:
+ for extension in sorted(used_extensions):
file.write(' bool b_%s;\n' % extension)
file.write('};\n')
file.write('\n')
@@ -1265,7 +1325,7 @@ class GLContext;
# Write Procs struct.
file.write("struct Procs%s {\n" % set_name.upper())
for func in functions:
- file.write(' %sProc %sFn;\n' % (func['names'][0], func['names'][0]))
+ file.write(' %sProc %sFn;\n' % (func['known_as'], func['known_as']))
file.write('};\n')
file.write('\n')
@@ -1279,7 +1339,7 @@ class GLContext;
""" % {'name': set_name.upper()})
for func in functions:
file.write(' virtual %s %sFn(%s) = 0;\n' %
- (func['return_type'], func['names'][0], func['arguments']))
+ (func['return_type'], func['known_as'], func['arguments']))
file.write('};\n')
file.write('\n')
@@ -1290,14 +1350,14 @@ class GLContext;
file.write('\n')
for func in functions:
file.write('#define %s ::gfx::g_current_%s_context->%sFn\n' %
- (func['names'][0], set_name.lower(), func['names'][0]))
+ (func['known_as'], set_name.lower(), func['known_as']))
file.write('\n')
file.write('#endif // UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' %
set_name.upper())
-def GenerateAPIHeader(file, functions, set_name, used_extension_functions):
+def GenerateAPIHeader(file, functions, set_name):
"""Generates gl_bindings_api_autogen_x.h"""
# Write file header.
@@ -1313,12 +1373,12 @@ def GenerateAPIHeader(file, functions, set_name, used_extension_functions):
# Write API declaration.
for func in functions:
file.write(' virtual %s %sFn(%s) OVERRIDE;\n' %
- (func['return_type'], func['names'][0], func['arguments']))
+ (func['return_type'], func['known_as'], func['arguments']))
file.write('\n')
-def GenerateMockHeader(file, functions, set_name, used_extension_functions):
+def GenerateMockHeader(file, functions, set_name):
"""Generates gl_mock_autogen_x.h"""
# Write file header.
@@ -1340,13 +1400,12 @@ def GenerateMockHeader(file, functions, set_name, used_extension_functions):
if len(args):
arg_count = func['arguments'].count(',') + 1
file.write(' MOCK_METHOD%d(%s, %s(%s));\n' %
- (arg_count, func['names'][0][2:], func['return_type'], args))
+ (arg_count, func['known_as'][2:], func['return_type'], args))
file.write('\n')
-def GenerateInterfaceHeader(
- file, functions, set_name, used_extension_functions):
+def GenerateInterfaceHeader(file, functions, set_name):
"""Generates gl_interface_autogen_x.h"""
# Write file header.
@@ -1365,13 +1424,13 @@ def GenerateInterfaceHeader(
if args == 'void':
args = ''
file.write(' virtual %s %s(%s) = 0;\n' %
- (func['return_type'], func['names'][0][2:], args))
+ (func['return_type'], func['known_as'][2:], args))
file.write('\n')
def GenerateSource(
- file, functions, nulldraw_functions, set_name, used_extension_functions):
+ file, functions, nulldraw_functions, set_name, used_extensions):
"""Generates gl_bindings_autogen_x.cc"""
# Write file header.
@@ -1388,6 +1447,7 @@ def GenerateSource(
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_version_info.h"
#include "ui/gl/gl_%s_api_implementation.h"
using gpu::gles2::GLES2Util;
@@ -1395,78 +1455,161 @@ using gpu::gles2::GLES2Util;
namespace gfx {
""" % set_name.lower())
- # Write definitions of function pointers.
file.write('\n')
file.write('static bool g_debugBindingsInitialized;\n')
file.write('Driver%s g_driver_%s;\n' % (set_name.upper(), set_name.lower()))
file.write('\n')
- # Write function to initialize the core function pointers. The code assumes
- # any non-NULL pointer returned by GetGLCoreProcAddress() is valid, although
- # it may be overwritten by an extension function pointer later.
+ # Write stub functions that take the place of some functions before a context
+ # is initialized. This is done to provide clear asserts on debug build and to
+ # avoid crashing in case of a bug on release build.
+ file.write('\n')
+ for func in functions:
+ unique_names = set([version['name'] for version in func['versions']])
+ if len(unique_names) > 1:
+ file.write('%s %sNotBound(%s) {\n' %
+ (func['return_type'], func['known_as'], func['arguments']))
+ file.write(' NOTREACHED();\n')
+ return_type = func['return_type'].lower()
+ # Returning 0 works for booleans, integers and pointers.
+ if return_type != 'void':
+ file.write(' return 0;\n')
+ file.write('}\n')
+
+ # Write function to initialize the function pointers that are always the same
+ # and to initialize bindings where choice of the function depends on the
+ # extension string or the GL version to point to stub functions.
file.write('\n')
- file.write('void Driver%s::InitializeBindings() {\n' %
+ file.write('void Driver%s::InitializeStaticBindings() {\n' %
set_name.upper())
+
+ def WriteFuncBinding(file, known_as, version_name):
+ file.write(
+ ' fn.%sFn = reinterpret_cast<%sProc>(GetGLProcAddress("%s"));\n' %
+ (known_as, known_as, version_name))
+
for func in functions:
- first_name = func['names'][0]
- for i, name in enumerate(func['names']):
- if i:
- file.write(' if (!fn.%sFn)\n ' % first_name)
- file.write(
- ' fn.%sFn = reinterpret_cast<%sProc>('
- 'GetGLCoreProcAddress("%s"));\n' %
- (first_name, first_name, name))
+ unique_names = set([version['name'] for version in func['versions']])
+ if len(unique_names) == 1:
+ WriteFuncBinding(file, func['known_as'], func['known_as'])
+ else:
+ file.write(' fn.%sFn = reinterpret_cast<%sProc>(%sNotBound);\n' %
+ (func['known_as'], func['known_as'], func['known_as']))
+
file.write('}\n')
file.write('\n')
- # Write function to initialize the extension function pointers. This function
- # uses a current context to query which extensions are actually supported.
- file.write("""void Driver%s::InitializeExtensionBindings(
- GLContext* context) {
+ # Write function to initialize bindings where choice of the function depends
+ # on the extension string or the GL version.
+ file.write("""void Driver%s::InitializeDynamicBindings(GLContext* context) {
+ DCHECK(context && context->IsCurrent(NULL));
+ const GLVersionInfo* ver ALLOW_UNUSED = context->GetVersionInfo();
+ std::string extensions ALLOW_UNUSED = context->GetExtensions();
+ extensions += " ";
+
""" % set_name.upper())
- file.write(' DCHECK(context && context->IsCurrent(NULL));\n')
- for extension, ext_functions in used_extension_functions:
- file.write(' ext.b_%s = context->HasExtension("%s");\n' %
+ for extension in sorted(used_extensions):
+ # Extra space at the end of the extension name is intentional, it is used
+ # as a separator
+ file.write(' ext.b_%s = extensions.find("%s ") != std::string::npos;\n' %
(extension, extension))
- file.write(' if (ext.b_%s) {\n' %
- (extension))
- queried_entry_points = set()
- for entry_point_name, function_name in ext_functions:
- # Replace the pointer unconditionally unless this extension has several
- # alternatives for the same entry point (e.g.,
- # GL_ARB_blend_func_extended).
- if entry_point_name in queried_entry_points:
- file.write(' if (!fn.%sFn)\n ' % entry_point_name)
- file.write(
- ' fn.%sFn = reinterpret_cast<%sProc>(GetGLProcAddress("%s"));\n' %
- (entry_point_name, entry_point_name, function_name))
- queried_entry_points.add(entry_point_name)
- file.write(' }\n')
+
+ def WrapOr(cond):
+ if ' || ' in cond:
+ return '(%s)' % cond
+ return cond
+
+ def WrapAnd(cond):
+ if ' && ' in cond:
+ return '(%s)' % cond
+ return cond
+
+ def VersionCondition(version):
+ conditions = []
+ if 'gl_versions' in version:
+ gl_versions = version['gl_versions']
+ version_cond = ' || '.join(['ver->is_%s' % gl for gl in gl_versions])
+ conditions.append(WrapOr(version_cond))
+ if 'extensions' in version and version['extensions']:
+ ext_cond = ' || '.join(['ext.b_%s' % e for e in version['extensions']])
+ conditions.append(WrapOr(ext_cond))
+ return ' && '.join(conditions)
+
+ def WriteConditionalFuncBinding(file, func):
+ # Functions with only one version are always bound unconditionally
+ assert len(func['versions']) > 1
+ known_as = func['known_as']
+ i = 0
+ first_version = True
+ while i < len(func['versions']):
+ version = func['versions'][i]
+ cond = VersionCondition(version)
+ combined_conditions = [WrapAnd(cond)]
+ last_version = i + 1 == len(func['versions'])
+ while not last_version and \
+ func['versions'][i + 1]['name'] == version['name']:
+ i += 1
+ combinable_cond = VersionCondition(func['versions'][i])
+ combined_conditions.append(WrapAnd(combinable_cond))
+ last_version = i + 1 == len(func['versions'])
+ if len(combined_conditions) > 1:
+ if [1 for cond in combined_conditions if cond == '']:
+ cond = ''
+ else:
+ cond = ' || '.join(combined_conditions)
+ # Don't make the last possible binding conditional on anything else but
+ # that the function isn't already bound to avoid verbose specification
+ # of functions which have both ARB and core versions with the same name,
+ # and to be able to bind to mock extension functions in unit tests which
+ # call InitializeDynamicGLBindings with a stub context that doesn't have
+ # extensions in its extension string.
+ # TODO(oetuaho@nvidia.com): Get rid of the fallback.
+ # http://crbug.com/325668
+ if cond != '' and not last_version:
+ if not first_version:
+ file.write(' if (!fn.%sFn && (%s))\n ' % (known_as, cond))
+ else:
+ file.write(' if (%s)\n ' % cond)
+ elif not first_version:
+ file.write(' if (!fn.%sFn)\n ' % known_as)
+ WriteFuncBinding(file, known_as, version['name'])
+ i += 1
+ first_version = False
+
+ for func in functions:
+ unique_names = set([version['name'] for version in func['versions']])
+ if len(unique_names) > 1:
+ file.write('\n')
+ file.write(' fn.%sFn = 0;\n' % func['known_as'])
+ file.write(' debug_fn.%sFn = 0;\n' % func['known_as'])
+ WriteConditionalFuncBinding(file, func)
+
+ # Some new function pointers have been added, so update them in debug bindings
+ file.write('\n')
file.write(' if (g_debugBindingsInitialized)\n')
- file.write(' UpdateDebugExtensionBindings();\n')
+ file.write(' InitializeDebugBindings();\n')
file.write('}\n')
file.write('\n')
# Write empty stubs for functions that want one.
file.write('extern "C" {\n')
for func in nulldraw_functions:
- names = func['names']
+ known_as = func['known_as']
return_type = func['return_type']
arguments = func['arguments']
file.write('\n')
file.write('static %s GL_BINDING_CALL Stub_%s(%s) {}\n' %
- (return_type, names[0], arguments))
+ (return_type, known_as, arguments))
file.write('} // extern "C"\n')
# Write logging wrappers for each function.
file.write('extern "C" {\n')
for func in functions:
- names = func['names']
return_type = func['return_type']
arguments = func['arguments']
file.write('\n')
file.write('static %s GL_BINDING_CALL Debug_%s(%s) {\n' %
- (return_type, names[0], arguments))
+ (return_type, func['known_as'], arguments))
argument_names = re.sub(
r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2', arguments)
argument_names = re.sub(
@@ -1488,9 +1631,9 @@ namespace gfx {
log_argument_names)
log_argument_names = re.sub(
r'CONSTVOID_([a-zA-Z0-9_]+)',
- r'static_cast<const void*>(\1)', log_argument_names);
+ r'static_cast<const void*>(\1)', log_argument_names)
log_argument_names = re.sub(
- r'CONSTCHAR_([a-zA-Z0-9_]+)', r'\1', log_argument_names);
+ r'CONSTCHAR_([a-zA-Z0-9_]+)', r'\1', log_argument_names)
log_argument_names = re.sub(
r'GLenum_([a-zA-Z0-9_]+)', r'GLES2Util::GetStringEnum(\1)',
log_argument_names)
@@ -1503,7 +1646,7 @@ namespace gfx {
log_argument_names = ''
else:
log_argument_names = " << " + log_argument_names
- function_name = names[0]
+ function_name = func['known_as']
if return_type == 'void':
file.write(' GL_SERVICE_LOG("%s" << "(" %s << ")");\n' %
(function_name, log_argument_names))
@@ -1519,7 +1662,7 @@ namespace gfx {
if 'logging_code' in func:
file.write("%s\n" % func['logging_code'])
else:
- file.write(' GL_SERVICE_LOG("GL_RESULT: " << result);\n');
+ file.write(' GL_SERVICE_LOG("GL_RESULT: " << result);\n')
file.write(' return result;\n')
file.write('}\n')
file.write('} // extern "C"\n')
@@ -1529,7 +1672,7 @@ namespace gfx {
file.write('void Driver%s::InitializeDebugBindings() {\n' %
set_name.upper())
for func in functions:
- first_name = func['names'][0]
+ first_name = func['known_as']
file.write(' if (!debug_fn.%sFn) {\n' % first_name)
file.write(' debug_fn.%sFn = fn.%sFn;\n' % (first_name, first_name))
file.write(' fn.%sFn = Debug_%s;\n' % (first_name, first_name))
@@ -1544,24 +1687,10 @@ namespace gfx {
set_name.upper())
for func in nulldraw_functions:
- first_name = func['names'][0]
+ first_name = func['known_as']
file.write(' fn.%sFn = Stub_%s;\n' % (first_name, first_name))
file.write('}\n')
- # Write function to update the debug function pointers to extension functions
- # after the extensions have been initialized.
- file.write('\n')
- file.write('void Driver%s::UpdateDebugExtensionBindings() {\n' %
- set_name.upper())
- for extension, ext_functions in used_extension_functions:
- for name, _ in ext_functions:
- file.write(' if (debug_fn.%sFn != fn.%sFn &&\n' % (name, name))
- file.write(' fn.%sFn != Debug_%s) {\n' % (name, name))
- file.write(' debug_fn.%sFn = fn.%sFn;\n' % (name, name))
- file.write(' fn.%sFn = Debug_%s;\n' % (name, name))
- file.write(' }\n')
- file.write('}\n')
-
# Write function to clear all function pointers.
file.write('\n')
file.write("""void Driver%s::ClearBindings() {
@@ -1571,19 +1700,18 @@ namespace gfx {
# Write GLApiBase functions
for func in functions:
- names = func['names']
+ function_name = func['known_as']
return_type = func['return_type']
arguments = func['arguments']
file.write('\n')
file.write('%s %sApiBase::%sFn(%s) {\n' %
- (return_type, set_name.upper(), names[0], arguments))
+ (return_type, set_name.upper(), function_name, arguments))
argument_names = re.sub(
r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2', arguments)
argument_names = re.sub(
r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2', argument_names)
if argument_names == 'void' or argument_names == '':
argument_names = ''
- function_name = names[0]
if return_type == 'void':
file.write(' driver_->fn.%sFn(%s);\n' %
(function_name, argument_names))
@@ -1594,19 +1722,18 @@ namespace gfx {
# Write TraceGLApi functions
for func in functions:
- names = func['names']
+ function_name = func['known_as']
return_type = func['return_type']
arguments = func['arguments']
file.write('\n')
file.write('%s Trace%sApi::%sFn(%s) {\n' %
- (return_type, set_name.upper(), names[0], arguments))
+ (return_type, set_name.upper(), function_name, arguments))
argument_names = re.sub(
r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2', arguments)
argument_names = re.sub(
r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2', argument_names)
if argument_names == 'void' or argument_names == '':
argument_names = ''
- function_name = names[0]
file.write(' TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::%s")\n' %
function_name)
if return_type == 'void':
@@ -1641,12 +1768,12 @@ namespace gfx {
for func in functions:
file.write('\n')
file.write('%s GL_BINDING_CALL Mock_%s(%s) {\n' %
- (func['return_type'], func['names'][0], func['arguments']))
- argument_names = re.sub(r'(const )?[a-zA-Z0-9]+((\s*const\s*)?\*)* ([a-zA-Z0-9]+)', r'\4',
- func['arguments'])
+ (func['return_type'], func['known_as'], func['arguments']))
+ arg_re = r'(const )?[a-zA-Z0-9]+((\s*const\s*)?\*)* ([a-zA-Z0-9]+)'
+ argument_names = re.sub(arg_re, r'\4', func['arguments'])
if argument_names == 'void':
argument_names = ''
- function_name = func['names'][0][2:]
+ function_name = func['known_as'][2:]
if func['return_type'] == 'void':
file.write(' GLInterface::GetGLInterface()->%s(%s);\n' %
(function_name, argument_names))
@@ -1667,12 +1794,14 @@ namespace gfx {
file.write('\n')
file.write('void* GL_BINDING_CALL GetMockGLProcAddress(const char* name) {\n')
for func in functions:
- first_name = func['names'][0]
- file.write(' if (strcmp(name, "%s") == 0)\n' % first_name)
- file.write(' return reinterpret_cast<void*>(Mock_%s);\n' % first_name)
+ unique_names = set([version['name'] for version in func['versions']])
+ for name in unique_names:
+ file.write(' if (strcmp(name, "%s") == 0)\n' % name)
+ file.write(
+ ' return reinterpret_cast<void*>(Mock_%s);\n' % func['known_as'])
# Always return a non-NULL pointer like some EGL implementations do.
file.write(' return reinterpret_cast<void*>(&MockInvalidFunction);\n')
- file.write('}\n');
+ file.write('}\n')
file.write('\n')
file.write('} // namespace gfx\n')
@@ -1755,49 +1884,45 @@ def LooksLikeExtensionFunction(function):
return vendor is not None and not vendor.group(1) in ['GL', 'API', 'DC']
-def GetUsedExtensionFunctions(functions, extension_headers, extra_extensions):
- """Determine which functions belong to extensions.
+def FillExtensionsFromHeaders(functions, extension_headers, extra_extensions):
+ """Determine which functions belong to extensions based on extension headers,
+ and fill in this information to the functions table for functions that don't
+ already have the information.
Args:
- functions: List of (return type, function names, arguments).
+ functions: List of (return type, function versions, arguments).
extension_headers: List of header file names.
+ extra_extensions: Extensions to add to the list.
Returns:
- List of (extension name, [function name alternatives]) sorted with least
- preferred extensions first.
+ Set of used extensions.
"""
# Parse known extensions.
extensions = GetExtensionFunctions(extension_headers)
functions_to_extensions = GetFunctionToExtensionMap(extensions)
- # Collect all used extension functions.
- used_extension_functions = collections.defaultdict(lambda: [])
+ # Fill in the extension information.
+ used_extensions = set()
for func in functions:
- for name in func['names']:
- # Make sure we know about all extension functions.
- if (LooksLikeExtensionFunction(name) and
- not name in functions_to_extensions):
+ for version in func['versions']:
+ name = version['name']
+ # Make sure we know about all extensions and extension functions.
+ if 'extensions' in version:
+ used_extensions.update(version['extensions'])
+ elif name in functions_to_extensions:
+ # If there are multiple versions with the same name, assume that they
+ # already have all the correct conditions, we can't just blindly add
+ # the same extension conditions to all of them
+ if len([v for v in func['versions'] if v['name'] == name]) == 1:
+ version['extensions'] = functions_to_extensions[name]
+ used_extensions.update(version['extensions'])
+ elif LooksLikeExtensionFunction(name):
raise RuntimeError('%s looks like an extension function but does not '
'belong to any of the known extensions.' % name)
- if name in functions_to_extensions:
- extensions = functions_to_extensions[name][:]
- if 'other_extensions' in func:
- extensions.extend(func['other_extensions'])
- for extension in extensions:
- used_extension_functions[extension].append((func['names'][0], name))
# Add extensions that do not have any functions.
- used_extension_functions.update(dict(
- [(e, []) for e in extra_extensions if e not in used_extension_functions]))
+ used_extensions.update(extra_extensions)
- def ExtensionSortKey(name):
- # Prefer ratified extensions and EXTs.
- preferences = ['_ARB_', '_OES_', '_EXT_', '']
- for i, category in enumerate(preferences):
- if category in name:
- return -i
- used_extension_functions = sorted(used_extension_functions.items(),
- key = lambda item: ExtensionSortKey(item[0]))
- return used_extension_functions
+ return used_extensions
def ResolveHeader(header, header_paths):
@@ -1837,54 +1962,66 @@ def main(argv):
print ResolveHeader(header, options.header_paths)
return 0
+ directory = '.'
if len(args) >= 1:
- dir = args[0]
- else:
- dir = '.'
+ directory = args[0]
for [functions,
nulldraw_functions,
set_name,
extension_headers,
extensions] in FUNCTION_SETS:
+ # Function names can be specified in two ways (list of unique names or list
+ # of versions with different binding conditions). Fill in the data to the
+ # versions list in case it is missing, so that can be used from here on:
+ for func in functions + nulldraw_functions:
+ assert 'versions' in func or 'names' in func, 'Function with no names'
+ if 'versions' not in func:
+ func['versions'] = [{'name': n} for n in func['names']]
+ # Use the first version's name unless otherwise specified
+ if 'known_as' not in func:
+ func['known_as'] = func['versions'][0]['name']
+ # Make sure that 'names' is not accidentally used instead of 'versions'
+ if 'names' in func:
+ del func['names']
+
extension_headers = [ResolveHeader(h, options.header_paths)
for h in extension_headers]
- used_extension_functions = GetUsedExtensionFunctions(
+ used_extensions = FillExtensionsFromHeaders(
functions, extension_headers, extensions)
header_file = open(
- os.path.join(dir, 'gl_bindings_autogen_%s.h' % set_name), 'wb')
- GenerateHeader(header_file, functions, set_name, used_extension_functions)
+ os.path.join(directory, 'gl_bindings_autogen_%s.h' % set_name), 'wb')
+ GenerateHeader(header_file, functions, set_name, used_extensions)
header_file.close()
header_file = open(
- os.path.join(dir, 'gl_bindings_api_autogen_%s.h' % set_name), 'wb')
- GenerateAPIHeader(
- header_file, functions, set_name, used_extension_functions)
+ os.path.join(directory, 'gl_bindings_api_autogen_%s.h' % set_name),
+ 'wb')
+ GenerateAPIHeader(header_file, functions, set_name)
header_file.close()
source_file = open(
- os.path.join(dir, 'gl_bindings_autogen_%s.cc' % set_name), 'wb')
+ os.path.join(directory, 'gl_bindings_autogen_%s.cc' % set_name), 'wb')
GenerateSource(source_file,
functions,
nulldraw_functions,
set_name,
- used_extension_functions)
+ used_extensions)
source_file.close()
header_file = open(
- os.path.join(dir, 'gl_interface_autogen_%s.h' % set_name), 'wb')
- GenerateInterfaceHeader(
- header_file, functions, set_name, used_extension_functions)
+ os.path.join(directory, 'gl_interface_autogen_%s.h' % set_name), 'wb')
+ GenerateInterfaceHeader(header_file, functions, set_name)
header_file.close()
header_file = open(
- os.path.join(dir, 'gl_mock_autogen_%s.h' % set_name), 'wb')
- GenerateMockHeader(
- header_file, functions, set_name, used_extension_functions)
+ os.path.join(directory, 'gl_mock_autogen_%s.h' % set_name), 'wb')
+ GenerateMockHeader(header_file, functions, set_name)
header_file.close()
- source_file = open(os.path.join(dir, 'gl_bindings_autogen_mock.cc'), 'wb')
+ source_file = open(os.path.join(directory, 'gl_bindings_autogen_mock.cc'),
+ 'wb')
GenerateMockSource(source_file, GL_FUNCTIONS)
source_file.close()
return 0
diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp
index 712d6f9..5e1c4d40 100644
--- a/ui/gl/gl.gyp
+++ b/ui/gl/gl.gyp
@@ -61,6 +61,8 @@
'gl_context_osmesa.h',
'gl_context_stub.cc',
'gl_context_stub.h',
+ 'gl_context_stub_with_extensions.cc',
+ 'gl_context_stub_with_extensions.h',
'gl_context_win.cc',
'gl_context_x11.cc',
'gl_export.h',
@@ -107,6 +109,8 @@
'gl_surface_osmesa.h',
'gl_switches.cc',
'gl_switches.h',
+ 'gl_version_info.cc',
+ 'gl_version_info.h',
'gpu_switching_manager.cc',
'gpu_switching_manager.h',
'io_surface_support_mac.cc',
diff --git a/ui/gl/gl_bindings.h b/ui/gl/gl_bindings.h
index abde8c8..fd24c42 100644
--- a/ui/gl/gl_bindings.h
+++ b/ui/gl/gl_bindings.h
@@ -225,12 +225,11 @@ typedef uint64 EGLuint64CHROMIUM;
namespace gfx {
struct GL_EXPORT DriverGL {
- void Initialize();
- void InitializeExtensions(GLContext* context);
+ void InitializeStaticBindings();
+ void InitializeCustomDynamicBindings(GLContext* context);
void InitializeDebugBindings();
void InitializeNullDrawBindings();
void ClearBindings();
- void UpdateDebugExtensionBindings();
ProcsGL fn;
ProcsGL orig_fn;
@@ -238,16 +237,14 @@ struct GL_EXPORT DriverGL {
ExtensionsGL ext;
private:
- void InitializeBindings();
- void InitializeExtensionBindings(GLContext* context);
+ void InitializeDynamicBindings(GLContext* context);
};
struct GL_EXPORT DriverOSMESA {
- void InitializeBindings();
- void InitializeExtensionBindings(GLContext* context);
+ void InitializeStaticBindings();
+ void InitializeDynamicBindings(GLContext* context);
void InitializeDebugBindings();
void ClearBindings();
- void UpdateDebugExtensionBindings();
ProcsOSMESA fn;
ProcsOSMESA debug_fn;
@@ -256,11 +253,10 @@ struct GL_EXPORT DriverOSMESA {
#if defined(OS_WIN)
struct GL_EXPORT DriverWGL {
- void InitializeBindings();
- void InitializeExtensionBindings(GLContext* context);
+ void InitializeStaticBindings();
+ void InitializeDynamicBindings(GLContext* context);
void InitializeDebugBindings();
void ClearBindings();
- void UpdateDebugExtensionBindings();
ProcsWGL fn;
ProcsWGL debug_fn;
@@ -270,11 +266,10 @@ struct GL_EXPORT DriverWGL {
#if defined(OS_WIN) || defined(USE_X11) || defined(OS_ANDROID) || defined(USE_OZONE)
struct GL_EXPORT DriverEGL {
- void InitializeBindings();
- void InitializeExtensionBindings(GLContext* context);
+ void InitializeStaticBindings();
+ void InitializeDynamicBindings(GLContext* context);
void InitializeDebugBindings();
void ClearBindings();
- void UpdateDebugExtensionBindings();
ProcsEGL fn;
ProcsEGL debug_fn;
@@ -284,11 +279,10 @@ struct GL_EXPORT DriverEGL {
#if defined(USE_X11)
struct GL_EXPORT DriverGLX {
- void InitializeBindings();
- void InitializeExtensionBindings(GLContext* context);
+ void InitializeStaticBindings();
+ void InitializeDynamicBindings(GLContext* context);
void InitializeDebugBindings();
void ClearBindings();
- void UpdateDebugExtensionBindings();
ProcsGLX fn;
ProcsGLX debug_fn;
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc
index 1bc4d12..dc3a3e8 100644
--- a/ui/gl/gl_context.cc
+++ b/ui/gl/gl_context.cc
@@ -14,6 +14,7 @@
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_surface.h"
#include "ui/gl/gl_switches.h"
+#include "ui/gl/gl_version_info.h"
namespace gfx {
@@ -58,6 +59,13 @@ std::string GLContext::GetExtensions() {
return std::string(ext ? ext : "");
}
+std::string GLContext::GetGLVersion() {
+ DCHECK(IsCurrent(NULL));
+ const char *version =
+ reinterpret_cast<const char*>(glGetString(GL_VERSION));
+ return std::string(version ? version : "");
+}
+
bool GLContext::HasExtension(const char* name) {
std::string extensions = GetExtensions();
extensions += " ";
@@ -68,6 +76,15 @@ bool GLContext::HasExtension(const char* name) {
return extensions.find(delimited_name) != std::string::npos;
}
+const GLVersionInfo* GLContext::GetVersionInfo() {
+ if(!version_info_) {
+ std::string version = GetGLVersion();
+ version_info_ = scoped_ptr<GLVersionInfo>(
+ new GLVersionInfo(version.c_str()));
+ }
+ return version_info_.get();
+}
+
GLShareGroup* GLContext::share_group() {
return share_group_.get();
}
@@ -114,14 +131,14 @@ bool GLContext::WasAllocatedUsingRobustnessExtension() {
return false;
}
-bool GLContext::InitializeExtensionBindings() {
+bool GLContext::InitializeDynamicBindings() {
DCHECK(IsCurrent(NULL));
static bool initialized = false;
if (initialized)
return initialized;
- initialized = InitializeGLExtensionBindings(GetGLImplementation(), this);
+ initialized = InitializeDynamicGLBindings(GetGLImplementation(), this);
if (!initialized)
- LOG(ERROR) << "Could not initialize extension bindings.";
+ LOG(ERROR) << "Could not initialize dynamic bindings.";
return initialized;
}
diff --git a/ui/gl/gl_context.h b/ui/gl/gl_context.h
index 3eb390f..66a7631 100644
--- a/ui/gl/gl_context.h
+++ b/ui/gl/gl_context.h
@@ -18,6 +18,7 @@ namespace gfx {
class GLSurface;
class VirtualGLApi;
+struct GLVersionInfo;
// Encapsulates an OpenGL context, hiding platform specific management.
class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
@@ -76,6 +77,10 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
// context must be current.
bool HasExtension(const char* name);
+ // Returns version info of the underlying GL context. The context must be
+ // current.
+ const GLVersionInfo* GetVersionInfo();
+
GLShareGroup* share_group();
// Create a GL context that is compatible with the given surface.
@@ -110,14 +115,17 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
static void SetRealGLApi();
virtual void SetCurrent(GLSurface* surface);
- // Initialize function pointers to extension functions in the GL
- // implementation. Should be called immediately after this context is made
- // current.
- bool InitializeExtensionBindings();
+ // Initialize function pointers to functions where the bound version depends
+ // on GL version or supported extensions. Should be called immediately after
+ // this context is made current.
+ bool InitializeDynamicBindings();
// Returns the last real (non-virtual) GLContext made current.
static GLContext* GetRealCurrent();
+ // Returns the GL version string. The context must be current.
+ virtual std::string GetGLVersion();
+
private:
friend class base::RefCounted<GLContext>;
@@ -127,6 +135,7 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
scoped_refptr<GLShareGroup> share_group_;
scoped_ptr<VirtualGLApi> virtual_gl_api_;
scoped_ptr<GLStateRestorer> state_restorer_;
+ scoped_ptr<GLVersionInfo> version_info_;
DISALLOW_COPY_AND_ASSIGN(GLContext);
};
diff --git a/ui/gl/gl_context_cgl.cc b/ui/gl/gl_context_cgl.cc
index 0b63b4b..151c484d 100644
--- a/ui/gl/gl_context_cgl.cc
+++ b/ui/gl/gl_context_cgl.cc
@@ -190,7 +190,7 @@ bool GLContextCGL::MakeCurrent(GLSurface* surface) {
SetRealGLApi();
SetCurrent(surface);
- if (!InitializeExtensionBindings()) {
+ if (!InitializeDynamicBindings()) {
ReleaseCurrent(surface);
return false;
}
diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc
index cd6b534..856d84c 100644
--- a/ui/gl/gl_context_egl.cc
+++ b/ui/gl/gl_context_egl.cc
@@ -115,7 +115,7 @@ bool GLContextEGL::MakeCurrent(GLSurface* surface) {
SetRealGLApi();
SetCurrent(surface);
- if (!InitializeExtensionBindings()) {
+ if (!InitializeDynamicBindings()) {
ReleaseCurrent(surface);
return false;
}
diff --git a/ui/gl/gl_context_glx.cc b/ui/gl/gl_context_glx.cc
index 407d600..248d04b 100644
--- a/ui/gl/gl_context_glx.cc
+++ b/ui/gl/gl_context_glx.cc
@@ -127,7 +127,7 @@ bool GLContextGLX::MakeCurrent(GLSurface* surface) {
SetRealGLApi();
SetCurrent(surface);
- if (!InitializeExtensionBindings()) {
+ if (!InitializeDynamicBindings()) {
ReleaseCurrent(surface);
Destroy();
return false;
diff --git a/ui/gl/gl_context_nsview.mm b/ui/gl/gl_context_nsview.mm
index dd7a5a6..8f38d08 100644
--- a/ui/gl/gl_context_nsview.mm
+++ b/ui/gl/gl_context_nsview.mm
@@ -66,6 +66,10 @@ bool GLContextNSView::MakeCurrent(GLSurface* surface) {
SetRealGLApi();
SetCurrent(surface);
+ if (!InitializeDynamicBindings()) {
+ ReleaseCurrent(surface);
+ return false;
+ }
if (!surface->OnMakeCurrent(this)) {
LOG(ERROR) << "Unable to make gl context current.";
diff --git a/ui/gl/gl_context_osmesa.cc b/ui/gl/gl_context_osmesa.cc
index cb71aa5..e7ccba9 100644
--- a/ui/gl/gl_context_osmesa.cc
+++ b/ui/gl/gl_context_osmesa.cc
@@ -69,7 +69,7 @@ bool GLContextOSMesa::MakeCurrent(GLSurface* surface) {
OSMesaPixelStore(OSMESA_Y_UP, 0);
SetCurrent(surface);
- if (!InitializeExtensionBindings()) {
+ if (!InitializeDynamicBindings()) {
ReleaseCurrent(surface);
return false;
}
diff --git a/ui/gl/gl_context_stub_with_extensions.cc b/ui/gl/gl_context_stub_with_extensions.cc
new file mode 100644
index 0000000..1065df7
--- /dev/null
+++ b/ui/gl/gl_context_stub_with_extensions.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_context_stub_with_extensions.h"
+
+namespace gfx {
+
+void GLContextStubWithExtensions::AddExtensionsString(const char* extensions) {
+ if (extensions == NULL)
+ return;
+
+ if (extensions_.size() != 0)
+ extensions_ += ' ';
+ extensions_ += extensions;
+}
+
+std::string GLContextStubWithExtensions::GetExtensions() {
+ return extensions_;
+}
+
+void GLContextStubWithExtensions::SetGLVersionString(const char* version_str) {
+ version_str_ = std::string(version_str ? version_str : "");
+}
+
+std::string GLContextStubWithExtensions::GetGLVersion() {
+ return version_str_;
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_context_stub_with_extensions.h b/ui/gl/gl_context_stub_with_extensions.h
new file mode 100644
index 0000000..e048990
--- /dev/null
+++ b/ui/gl/gl_context_stub_with_extensions.h
@@ -0,0 +1,37 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_CONTEXT_STUB_WITH_EXTENSIONS_H_
+#define UI_GL_GL_CONTEXT_STUB_WITH_EXTENSIONS_H_
+
+#include "ui/gl/gl_context_stub.h"
+
+namespace gfx {
+
+// Lightweight GLContext stub implementation that returns a constructed
+// extensions string. We use this to create a context that we can use to
+// initialize GL extensions with, without actually creating a platform context.
+class GL_EXPORT GLContextStubWithExtensions : public gfx::GLContextStub {
+ public:
+ GLContextStubWithExtensions() {}
+ virtual std::string GetExtensions() OVERRIDE;
+
+ void AddExtensionsString(const char* extensions);
+ void SetGLVersionString(const char* version_str);
+
+ protected:
+ virtual std::string GetGLVersion() OVERRIDE;
+
+ virtual ~GLContextStubWithExtensions() {}
+
+ private:
+ std::string extensions_;
+ std::string version_str_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLContextStubWithExtensions);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_CONTEXT_STUB_WITH_EXTENSIONS_H_
diff --git a/ui/gl/gl_context_wgl.cc b/ui/gl/gl_context_wgl.cc
index 8ee90dd..41f1b63 100644
--- a/ui/gl/gl_context_wgl.cc
+++ b/ui/gl/gl_context_wgl.cc
@@ -85,7 +85,7 @@ bool GLContextWGL::MakeCurrent(GLSurface* surface) {
SetRealGLApi();
SetCurrent(surface);
- if (!InitializeExtensionBindings()) {
+ if (!InitializeDynamicBindings()) {
ReleaseCurrent(surface);
return false;
}
diff --git a/ui/gl/gl_egl_api_implementation.cc b/ui/gl/gl_egl_api_implementation.cc
index 43aa138..b3b55b8 100644
--- a/ui/gl/gl_egl_api_implementation.cc
+++ b/ui/gl/gl_egl_api_implementation.cc
@@ -9,8 +9,8 @@ namespace gfx {
RealEGLApi* g_real_egl;
-void InitializeGLBindingsEGL() {
- g_driver_egl.InitializeBindings();
+void InitializeStaticGLBindingsEGL() {
+ g_driver_egl.InitializeStaticBindings();
if (!g_real_egl) {
g_real_egl = new RealEGLApi();
}
@@ -18,8 +18,8 @@ void InitializeGLBindingsEGL() {
g_current_egl_context = g_real_egl;
}
-void InitializeGLExtensionBindingsEGL(GLContext* context) {
- g_driver_egl.InitializeExtensionBindings(context);
+void InitializeDynamicGLBindingsEGL(GLContext* context) {
+ g_driver_egl.InitializeDynamicBindings(context);
}
void InitializeDebugGLBindingsEGL() {
diff --git a/ui/gl/gl_egl_api_implementation.h b/ui/gl/gl_egl_api_implementation.h
index 5b76f02..aef46ee 100644
--- a/ui/gl/gl_egl_api_implementation.h
+++ b/ui/gl/gl_egl_api_implementation.h
@@ -14,8 +14,8 @@ namespace gfx {
class GLContext;
struct GLWindowSystemBindingInfo;
-void InitializeGLBindingsEGL();
-void InitializeGLExtensionBindingsEGL(GLContext* context);
+void InitializeStaticGLBindingsEGL();
+void InitializeDynamicGLBindingsEGL(GLContext* context);
void InitializeDebugGLBindingsEGL();
void ClearGLBindingsEGL();
bool GetGLWindowSystemBindingInfoEGL(GLWindowSystemBindingInfo* info);
diff --git a/ui/gl/gl_gl_api_implementation.cc b/ui/gl/gl_gl_api_implementation.cc
index d859af8..ce8a711 100644
--- a/ui/gl/gl_gl_api_implementation.cc
+++ b/ui/gl/gl_gl_api_implementation.cc
@@ -146,12 +146,8 @@ static void GL_BINDING_CALL CustomRenderbufferStorageMultisampleEXT(
} // anonymous namespace
-void DriverGL::Initialize() {
- InitializeBindings();
-}
-
-void DriverGL::InitializeExtensions(GLContext* context) {
- InitializeExtensionBindings(context);
+void DriverGL::InitializeCustomDynamicBindings(GLContext* context) {
+ InitializeDynamicBindings(context);
orig_fn = fn;
fn.glTexImage2DFn =
reinterpret_cast<glTexImage2DProc>(CustomTexImage2D);
@@ -167,9 +163,9 @@ void DriverGL::InitializeExtensions(GLContext* context) {
CustomRenderbufferStorageMultisampleEXT);
}
-void InitializeGLBindingsGL() {
+void InitializeStaticGLBindingsGL() {
g_current_gl_context_tls = new base::ThreadLocalPointer<GLApi>;
- g_driver_gl.Initialize();
+ g_driver_gl.InitializeStaticBindings();
if (!g_real_gl) {
g_real_gl = new RealGLApi();
g_trace_gl = new TraceGLApi(g_real_gl);
@@ -195,8 +191,8 @@ void SetGLToRealGLApi() {
SetGLApi(g_gl);
}
-void InitializeGLExtensionBindingsGL(GLContext* context) {
- g_driver_gl.InitializeExtensions(context);
+void InitializeDynamicGLBindingsGL(GLContext* context) {
+ g_driver_gl.InitializeCustomDynamicBindings(context);
}
void InitializeDebugGLBindingsGL() {
diff --git a/ui/gl/gl_gl_api_implementation.h b/ui/gl/gl_gl_api_implementation.h
index f54c552..43aedaf 100644
--- a/ui/gl/gl_gl_api_implementation.h
+++ b/ui/gl/gl_gl_api_implementation.h
@@ -19,8 +19,8 @@ namespace gfx {
class GLContext;
class GLSurface;
-void InitializeGLBindingsGL();
-void InitializeGLExtensionBindingsGL(GLContext* context);
+void InitializeStaticGLBindingsGL();
+void InitializeDynamicGLBindingsGL(GLContext* context);
void InitializeDebugGLBindingsGL();
void InitializeNullDrawGLBindingsGL();
void ClearGLBindingsGL();
diff --git a/ui/gl/gl_glx_api_implementation.cc b/ui/gl/gl_glx_api_implementation.cc
index 4a43534..444a1b2 100644
--- a/ui/gl/gl_glx_api_implementation.cc
+++ b/ui/gl/gl_glx_api_implementation.cc
@@ -9,8 +9,8 @@ namespace gfx {
RealGLXApi* g_real_glx;
-void InitializeGLBindingsGLX() {
- g_driver_glx.InitializeBindings();
+void InitializeStaticGLBindingsGLX() {
+ g_driver_glx.InitializeStaticBindings();
if (!g_real_glx) {
g_real_glx = new RealGLXApi();
}
@@ -18,8 +18,8 @@ void InitializeGLBindingsGLX() {
g_current_glx_context = g_real_glx;
}
-void InitializeGLExtensionBindingsGLX(GLContext* context) {
- g_driver_glx.InitializeExtensionBindings(context);
+void InitializeDynamicGLBindingsGLX(GLContext* context) {
+ g_driver_glx.InitializeDynamicBindings(context);
}
void InitializeDebugGLBindingsGLX() {
diff --git a/ui/gl/gl_glx_api_implementation.h b/ui/gl/gl_glx_api_implementation.h
index e9eb3da..634db4e 100644
--- a/ui/gl/gl_glx_api_implementation.h
+++ b/ui/gl/gl_glx_api_implementation.h
@@ -14,8 +14,8 @@ namespace gfx {
class GLContext;
struct GLWindowSystemBindingInfo;
-void InitializeGLBindingsGLX();
-void InitializeGLExtensionBindingsGLX(GLContext* context);
+void InitializeStaticGLBindingsGLX();
+void InitializeDynamicGLBindingsGLX(GLContext* context);
void InitializeDebugGLBindingsGLX();
void ClearGLBindingsGLX();
bool GetGLWindowSystemBindingInfoGLX(GLWindowSystemBindingInfo* info);
diff --git a/ui/gl/gl_implementation.cc b/ui/gl/gl_implementation.cc
index 5dac760..ee874db 100644
--- a/ui/gl/gl_implementation.cc
+++ b/ui/gl/gl_implementation.cc
@@ -46,21 +46,6 @@ void CleanupNativeLibraries(void* unused) {
}
}
-bool ExportsCoreFunctionsFromGetProcAddress(GLImplementation implementation) {
- switch (GetGLImplementation()) {
- case kGLImplementationDesktopGL:
- case kGLImplementationOSMesaGL:
- case kGLImplementationAppleGL:
- case kGLImplementationMockGL:
- return true;
- case kGLImplementationEGLGLES2:
- return false;
- default:
- NOTREACHED();
- return true;
- }
-}
-
}
base::ThreadLocalPointer<GLApi>* g_current_gl_context_tls = NULL;
@@ -138,7 +123,7 @@ void SetGLGetProcAddressProc(GLGetProcAddressProc proc) {
g_get_proc_address = proc;
}
-void* GetGLCoreProcAddress(const char* name) {
+void* GetGLProcAddress(const char* name) {
DCHECK(g_gl_implementation != kGLImplementationNone);
if (g_libraries) {
@@ -149,8 +134,7 @@ void* GetGLCoreProcAddress(const char* name) {
return proc;
}
}
- if (ExportsCoreFunctionsFromGetProcAddress(g_gl_implementation) &&
- g_get_proc_address) {
+ if (g_get_proc_address) {
void* proc = g_get_proc_address(name);
if (proc)
return proc;
@@ -159,19 +143,6 @@ void* GetGLCoreProcAddress(const char* name) {
return NULL;
}
-void* GetGLProcAddress(const char* name) {
- DCHECK(g_gl_implementation != kGLImplementationNone);
-
- void* proc = GetGLCoreProcAddress(name);
- if (!proc && g_get_proc_address) {
- proc = g_get_proc_address(name);
- if (proc)
- return proc;
- }
-
- return proc;
-}
-
void InitializeNullDrawGLBindings() {
// This is platform independent, so it does not need to live in a platform
// specific implementation file.
diff --git a/ui/gl/gl_implementation.h b/ui/gl/gl_implementation.h
index 3c0d9e5..045101c 100644
--- a/ui/gl/gl_implementation.h
+++ b/ui/gl/gl_implementation.h
@@ -42,10 +42,11 @@ typedef void* (*GLGetProcAddressProc)(const char* name);
#endif
// Initialize a particular GL implementation.
-GL_EXPORT bool InitializeGLBindings(GLImplementation implementation);
+GL_EXPORT bool InitializeStaticGLBindings(GLImplementation implementation);
-// Initialize extension function bindings for a GL implementation.
-GL_EXPORT bool InitializeGLExtensionBindings(GLImplementation implementation,
+// Initialize function bindings that depend on the context for a GL
+// implementation.
+GL_EXPORT bool InitializeDynamicGLBindings(GLImplementation implementation,
GLContext* context);
// Initialize Debug logging wrappers for GL bindings.
@@ -81,12 +82,13 @@ void UnloadGLNativeLibraries();
// Set an additional function that will be called to find GL entry points.
void SetGLGetProcAddressProc(GLGetProcAddressProc proc);
-// Find a core (non-extension) entry point in the current GL implementation. On
-// EGL based implementations core entry points will not be queried through
-// GLGetProcAddressProc.
-void* GetGLCoreProcAddress(const char* name);
-
-// Find an entry point in the current GL implementation.
+// Find an entry point in the current GL implementation. Note that the function
+// may return a non-null pointer to something else than the GL function if an
+// unsupported function is queried. Spec-compliant eglGetProcAddress and
+// glxGetProcAddress are allowed to return garbage for unsupported functions,
+// and when querying functions from the EGL library supplied by Android, it may
+// return a function that prints a log message about the function being
+// unsupported.
void* GetGLProcAddress(const char* name);
// Return information about the GL window system binding implementation (e.g.,
diff --git a/ui/gl/gl_implementation_android.cc b/ui/gl/gl_implementation_android.cc
index 63528ae..0b01133 100644
--- a/ui/gl/gl_implementation_android.cc
+++ b/ui/gl/gl_implementation_android.cc
@@ -9,6 +9,7 @@
#include "base/native_library.h"
#include "base/path_service.h"
#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context_stub_with_extensions.h"
#include "ui/gl/gl_egl_api_implementation.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_implementation.h"
@@ -47,7 +48,7 @@ void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
impls->push_back(kGLImplementationEGLGLES2);
}
-bool InitializeGLBindings(GLImplementation implementation) {
+bool InitializeStaticGLBindings(GLImplementation implementation) {
// Prevent reinitialization with a different implementation. Once the gpu
// unit tests have initialized with kGLImplementationMock, we don't want to
// later switch to another GL implementation.
@@ -81,8 +82,8 @@ bool InitializeGLBindings(GLImplementation implementation) {
AddGLNativeLibrary(gles_library);
SetGLImplementation(kGLImplementationEGLGLES2);
- InitializeGLBindingsGL();
- InitializeGLBindingsEGL();
+ InitializeStaticGLBindingsGL();
+ InitializeStaticGLBindingsEGL();
// These two functions take single precision float rather than double
// precision float parameters in GLES.
@@ -93,26 +94,32 @@ bool InitializeGLBindings(GLImplementation implementation) {
case kGLImplementationMockGL: {
SetGLGetProcAddressProc(GetMockGLProcAddress);
SetGLImplementation(kGLImplementationMockGL);
- InitializeGLBindingsGL();
+ InitializeStaticGLBindingsGL();
break;
}
default:
- NOTIMPLEMENTED() << "InitializeGLBindings on Android";
+ NOTIMPLEMENTED() << "InitializeStaticGLBindings on Android";
return false;
}
return true;
}
-bool InitializeGLExtensionBindings(GLImplementation implementation,
- GLContext* context) {
+bool InitializeDynamicGLBindings(GLImplementation implementation,
+ GLContext* context) {
switch (implementation) {
case kGLImplementationEGLGLES2:
- InitializeGLExtensionBindingsGL(context);
- InitializeGLExtensionBindingsEGL(context);
+ InitializeDynamicGLBindingsGL(context);
+ InitializeDynamicGLBindingsEGL(context);
break;
case kGLImplementationMockGL:
- InitializeGLExtensionBindingsGL(context);
+ if (!context) {
+ scoped_refptr<GLContextStubWithExtensions> mock_context(
+ new GLContextStubWithExtensions());
+ mock_context->SetGLVersionString("opengl es 3.0");
+ InitializeDynamicGLBindingsGL(mock_context.get());
+ } else
+ InitializeDynamicGLBindingsGL(context);
break;
default:
return false;
diff --git a/ui/gl/gl_implementation_linux.cc b/ui/gl/gl_implementation_linux.cc
index ba7a809..0968dfe 100644
--- a/ui/gl/gl_implementation_linux.cc
+++ b/ui/gl/gl_implementation_linux.cc
@@ -30,7 +30,7 @@ base::NativeLibrary LoadLibrary(const char* filename) {
return LoadLibrary(base::FilePath(filename));
}
-bool InitializeGLBindingsOSMesaGL() {
+bool InitializeStaticGLBindingsOSMesaGL() {
base::FilePath module_path;
if (!PathService::Get(base::DIR_MODULE, &module_path)) {
LOG(ERROR) << "PathService::Get failed.";
@@ -55,8 +55,8 @@ bool InitializeGLBindingsOSMesaGL() {
AddGLNativeLibrary(library);
SetGLImplementation(kGLImplementationOSMesaGL);
- InitializeGLBindingsGL();
- InitializeGLBindingsOSMESA();
+ InitializeStaticGLBindingsGL();
+ InitializeStaticGLBindingsOSMESA();
return true;
}
diff --git a/ui/gl/gl_implementation_linux.h b/ui/gl/gl_implementation_linux.h
index 31b5798..1c32d4c 100644
--- a/ui/gl/gl_implementation_linux.h
+++ b/ui/gl/gl_implementation_linux.h
@@ -7,7 +7,7 @@
namespace gfx {
-bool InitializeGLBindingsOSMesaGL();
+bool InitializeStaticGLBindingsOSMesaGL();
base::NativeLibrary LoadLibrary(const char* filename);
base::NativeLibrary LoadLibrary(const base::FilePath& filename);
diff --git a/ui/gl/gl_implementation_mac.cc b/ui/gl/gl_implementation_mac.cc
index 36bb7e3..e768970 100644
--- a/ui/gl/gl_implementation_mac.cc
+++ b/ui/gl/gl_implementation_mac.cc
@@ -10,6 +10,7 @@
#include "base/path_service.h"
#include "base/threading/thread_restrictions.h"
#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context_stub_with_extensions.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_osmesa_api_implementation.h"
@@ -26,7 +27,7 @@ void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
impls->push_back(kGLImplementationOSMesaGL);
}
-bool InitializeGLBindings(GLImplementation implementation) {
+bool InitializeStaticGLBindings(GLImplementation implementation) {
// Prevent reinitialization with a different implementation. Once the gpu
// unit tests have initialized with kGLImplementationMock, we don't want to
// later switch to another GL implementation.
@@ -77,8 +78,8 @@ bool InitializeGLBindings(GLImplementation implementation) {
AddGLNativeLibrary(library);
SetGLImplementation(kGLImplementationOSMesaGL);
- InitializeGLBindingsGL();
- InitializeGLBindingsOSMESA();
+ InitializeStaticGLBindingsGL();
+ InitializeStaticGLBindingsOSMESA();
break;
}
case kGLImplementationDesktopGL:
@@ -93,13 +94,13 @@ bool InitializeGLBindings(GLImplementation implementation) {
AddGLNativeLibrary(library);
SetGLImplementation(implementation);
- InitializeGLBindingsGL();
+ InitializeStaticGLBindingsGL();
break;
}
case kGLImplementationMockGL: {
SetGLGetProcAddressProc(GetMockGLProcAddress);
SetGLImplementation(kGLImplementationMockGL);
- InitializeGLBindingsGL();
+ InitializeStaticGLBindingsGL();
break;
}
default:
@@ -109,19 +110,25 @@ bool InitializeGLBindings(GLImplementation implementation) {
return true;
}
-bool InitializeGLExtensionBindings(GLImplementation implementation,
+bool InitializeDynamicGLBindings(GLImplementation implementation,
GLContext* context) {
switch (implementation) {
case kGLImplementationOSMesaGL:
- InitializeGLExtensionBindingsGL(context);
- InitializeGLExtensionBindingsOSMESA(context);
+ InitializeDynamicGLBindingsGL(context);
+ InitializeDynamicGLBindingsOSMESA(context);
break;
case kGLImplementationDesktopGL:
case kGLImplementationAppleGL:
- InitializeGLExtensionBindingsGL(context);
+ InitializeDynamicGLBindingsGL(context);
break;
case kGLImplementationMockGL:
- InitializeGLExtensionBindingsGL(context);
+ if (!context) {
+ scoped_refptr<GLContextStubWithExtensions> mock_context(
+ new GLContextStubWithExtensions());
+ mock_context->SetGLVersionString("3.0");
+ InitializeDynamicGLBindingsGL(mock_context.get());
+ } else
+ InitializeDynamicGLBindingsGL(context);
break;
default:
return false;
diff --git a/ui/gl/gl_implementation_ozone.cc b/ui/gl/gl_implementation_ozone.cc
index 10ab44d..0d9fe6b 100644
--- a/ui/gl/gl_implementation_ozone.cc
+++ b/ui/gl/gl_implementation_ozone.cc
@@ -5,6 +5,7 @@
#include "base/bind.h"
#include "ui/gfx/ozone/surface_factory_ozone.h"
#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context_stub_with_extensions.h"
#include "ui/gl/gl_egl_api_implementation.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_implementation.h"
@@ -32,7 +33,7 @@ void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
impls->push_back(kGLImplementationOSMesaGL);
}
-bool InitializeGLBindings(GLImplementation implementation) {
+bool InitializeStaticGLBindings(GLImplementation implementation) {
// Prevent reinitialization with a different implementation. Once the gpu
// unit tests have initialized with kGLImplementationMock, we don't want to
// later switch to another GL implementation.
@@ -41,7 +42,7 @@ bool InitializeGLBindings(GLImplementation implementation) {
switch (implementation) {
case kGLImplementationOSMesaGL:
- return InitializeGLBindingsOSMesaGL();
+ return InitializeStaticGLBindingsOSMesaGL();
case kGLImplementationEGLGLES2:
ui::OzonePlatform::Initialize();
if (!gfx::SurfaceFactoryOzone::GetInstance()->LoadEGLGLES2Bindings(
@@ -49,8 +50,8 @@ bool InitializeGLBindings(GLImplementation implementation) {
base::Bind(&SetGLGetProcAddressProc)))
return false;
SetGLImplementation(kGLImplementationEGLGLES2);
- InitializeGLBindingsGL();
- InitializeGLBindingsEGL();
+ InitializeStaticGLBindingsGL();
+ InitializeStaticGLBindingsEGL();
// These two functions take single precision float rather than double
// precision float parameters in GLES.
@@ -60,7 +61,7 @@ bool InitializeGLBindings(GLImplementation implementation) {
case kGLImplementationMockGL: {
SetGLGetProcAddressProc(GetMockGLProcAddress);
SetGLImplementation(kGLImplementationMockGL);
- InitializeGLBindingsGL();
+ InitializeStaticGLBindingsGL();
break;
}
default:
@@ -72,19 +73,25 @@ bool InitializeGLBindings(GLImplementation implementation) {
return true;
}
-bool InitializeGLExtensionBindings(GLImplementation implementation,
- GLContext* context) {
+bool InitializeDynamicGLBindings(GLImplementation implementation,
+ GLContext* context) {
switch (implementation) {
case kGLImplementationOSMesaGL:
- InitializeGLExtensionBindingsGL(context);
- InitializeGLExtensionBindingsOSMESA(context);
+ InitializeDynamicGLBindingsGL(context);
+ InitializeDynamicGLBindingsOSMESA(context);
break;
case kGLImplementationEGLGLES2:
- InitializeGLExtensionBindingsGL(context);
- InitializeGLExtensionBindingsEGL(context);
+ InitializeDynamicGLBindingsGL(context);
+ InitializeDynamicGLBindingsEGL(context);
break;
case kGLImplementationMockGL:
- InitializeGLExtensionBindingsGL(context);
+ if (!context) {
+ scoped_refptr<GLContextStubWithExtensions> mock_context(
+ new GLContextStubWithExtensions());
+ mock_context->SetGLVersionString("3.0");
+ InitializeDynamicGLBindingsGL(mock_context.get());
+ } else
+ InitializeDynamicGLBindingsGL(context);
break;
default:
return false;
diff --git a/ui/gl/gl_implementation_win.cc b/ui/gl/gl_implementation_win.cc
index 87328a3..02f6dc1 100644
--- a/ui/gl/gl_implementation_win.cc
+++ b/ui/gl/gl_implementation_win.cc
@@ -17,10 +17,12 @@
#include "base/threading/thread_restrictions.h"
#include "base/win/windows_version.h"
#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context_stub_with_extensions.h"
#include "ui/gl/gl_egl_api_implementation.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_osmesa_api_implementation.h"
+#include "ui/gl/gl_surface_wgl.h"
#include "ui/gl/gl_wgl_api_implementation.h"
#if defined(ENABLE_SWIFTSHADER)
@@ -106,7 +108,7 @@ void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
impls->push_back(kGLImplementationOSMesaGL);
}
-bool InitializeGLBindings(GLImplementation implementation) {
+bool InitializeStaticGLBindings(GLImplementation implementation) {
// Prevent reinitialization with a different implementation. Once the gpu
// unit tests have initialized with kGLImplementationMock, we don't want to
// later switch to another GL implementation.
@@ -148,8 +150,8 @@ bool InitializeGLBindings(GLImplementation implementation) {
AddGLNativeLibrary(library);
SetGLImplementation(kGLImplementationOSMesaGL);
- InitializeGLBindingsGL();
- InitializeGLBindingsOSMESA();
+ InitializeStaticGLBindingsGL();
+ InitializeStaticGLBindingsOSMESA();
break;
}
case kGLImplementationEGLGLES2: {
@@ -234,8 +236,8 @@ bool InitializeGLBindings(GLImplementation implementation) {
AddGLNativeLibrary(gles_library);
SetGLImplementation(kGLImplementationEGLGLES2);
- InitializeGLBindingsGL();
- InitializeGLBindingsEGL();
+ InitializeStaticGLBindingsGL();
+ InitializeStaticGLBindingsEGL();
// These two functions take single precision float rather than double
// precision float parameters in GLES.
@@ -244,8 +246,6 @@ bool InitializeGLBindings(GLImplementation implementation) {
break;
}
case kGLImplementationDesktopGL: {
- // When using Windows OpenGL, first try wglGetProcAddress and then
- // Windows GetProcAddress.
base::NativeLibrary library = base::LoadNativeLibrary(
base::FilePath(L"opengl32.dll"), NULL);
if (!library) {
@@ -267,14 +267,53 @@ bool InitializeGLBindings(GLImplementation implementation) {
AddGLNativeLibrary(library);
SetGLImplementation(kGLImplementationDesktopGL);
- InitializeGLBindingsGL();
- InitializeGLBindingsWGL();
+ // Initialize GL surface and get some functions needed for the context
+ // creation below.
+ if (!GLSurfaceWGL::InitializeOneOff()) {
+ LOG(ERROR) << "GLSurfaceWGL::InitializeOneOff failed.";
+ return false;
+ }
+ wglCreateContextProc wglCreateContextFn =
+ reinterpret_cast<wglCreateContextProc>(
+ GetGLProcAddress("wglCreateContext"));
+ wglDeleteContextProc wglDeleteContextFn =
+ reinterpret_cast<wglDeleteContextProc>(
+ GetGLProcAddress("wglDeleteContext"));
+ wglMakeCurrentProc wglMakeCurrentFn =
+ reinterpret_cast<wglMakeCurrentProc>(
+ GetGLProcAddress("wglMakeCurrent"));
+
+ // Create a temporary GL context to bind to entry points. This is needed
+ // because wglGetProcAddress is specified to return NULL for all queries
+ // if a context is not current in MSDN documentation, and the static
+ // bindings may contain functions that need to be queried with
+ // wglGetProcAddress. OpenGL wiki further warns that other error values
+ // than NULL could also be returned from wglGetProcAddress on some
+ // implementations, so we need to clear the WGL bindings and reinitialize
+ // them after the context creation.
+ HGLRC gl_context = wglCreateContextFn(GLSurfaceWGL::GetDisplayDC());
+ if (!gl_context) {
+ LOG(ERROR) << "Failed to create temporary context.";
+ return false;
+ }
+ if (!wglMakeCurrentFn(GLSurfaceWGL::GetDisplayDC(), gl_context)) {
+ LOG(ERROR) << "Failed to make temporary GL context current.";
+ wglDeleteContextFn(gl_context);
+ return false;
+ }
+
+ InitializeStaticGLBindingsGL();
+ InitializeStaticGLBindingsWGL();
+
+ wglMakeCurrent(NULL, NULL);
+ wglDeleteContext(gl_context);
+
break;
}
case kGLImplementationMockGL: {
SetGLGetProcAddressProc(GetMockGLProcAddress);
SetGLImplementation(kGLImplementationMockGL);
- InitializeGLBindingsGL();
+ InitializeStaticGLBindingsGL();
break;
}
default:
@@ -284,23 +323,29 @@ bool InitializeGLBindings(GLImplementation implementation) {
return true;
}
-bool InitializeGLExtensionBindings(GLImplementation implementation,
+bool InitializeDynamicGLBindings(GLImplementation implementation,
GLContext* context) {
switch (implementation) {
case kGLImplementationOSMesaGL:
- InitializeGLExtensionBindingsGL(context);
- InitializeGLExtensionBindingsOSMESA(context);
+ InitializeDynamicGLBindingsGL(context);
+ InitializeDynamicGLBindingsOSMESA(context);
break;
case kGLImplementationEGLGLES2:
- InitializeGLExtensionBindingsGL(context);
- InitializeGLExtensionBindingsEGL(context);
+ InitializeDynamicGLBindingsGL(context);
+ InitializeDynamicGLBindingsEGL(context);
break;
case kGLImplementationDesktopGL:
- InitializeGLExtensionBindingsGL(context);
- InitializeGLExtensionBindingsWGL(context);
+ InitializeDynamicGLBindingsGL(context);
+ InitializeDynamicGLBindingsWGL(context);
break;
case kGLImplementationMockGL:
- InitializeGLExtensionBindingsGL(context);
+ if (!context) {
+ scoped_refptr<GLContextStubWithExtensions> mock_context(
+ new GLContextStubWithExtensions());
+ mock_context->SetGLVersionString("3.0");
+ InitializeDynamicGLBindingsGL(mock_context.get());
+ } else
+ InitializeDynamicGLBindingsGL(context);
break;
default:
return false;
diff --git a/ui/gl/gl_implementation_x11.cc b/ui/gl/gl_implementation_x11.cc
index 01ee655..f85dff3 100644
--- a/ui/gl/gl_implementation_x11.cc
+++ b/ui/gl/gl_implementation_x11.cc
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/threading/thread_restrictions.h"
#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context_stub_with_extensions.h"
#include "ui/gl/gl_egl_api_implementation.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_glx_api_implementation.h"
@@ -38,7 +39,7 @@ void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
impls->push_back(kGLImplementationOSMesaGL);
}
-bool InitializeGLBindings(GLImplementation implementation) {
+bool InitializeStaticGLBindings(GLImplementation implementation) {
// Prevent reinitialization with a different implementation. Once the gpu
// unit tests have initialized with kGLImplementationMock, we don't want to
// later switch to another GL implementation.
@@ -53,7 +54,7 @@ bool InitializeGLBindings(GLImplementation implementation) {
switch (implementation) {
case kGLImplementationOSMesaGL:
- return InitializeGLBindingsOSMesaGL();
+ return InitializeStaticGLBindingsOSMesaGL();
case kGLImplementationDesktopGL: {
base::NativeLibrary library = NULL;
const CommandLine* command_line = CommandLine::ForCurrentProcess();
@@ -87,8 +88,8 @@ bool InitializeGLBindings(GLImplementation implementation) {
AddGLNativeLibrary(library);
SetGLImplementation(kGLImplementationDesktopGL);
- InitializeGLBindingsGL();
- InitializeGLBindingsGLX();
+ InitializeStaticGLBindingsGL();
+ InitializeStaticGLBindingsGLX();
break;
}
case kGLImplementationEGLGLES2: {
@@ -117,8 +118,8 @@ bool InitializeGLBindings(GLImplementation implementation) {
AddGLNativeLibrary(gles_library);
SetGLImplementation(kGLImplementationEGLGLES2);
- InitializeGLBindingsGL();
- InitializeGLBindingsEGL();
+ InitializeStaticGLBindingsGL();
+ InitializeStaticGLBindingsEGL();
// These two functions take single precision float rather than double
// precision float parameters in GLES.
@@ -129,7 +130,7 @@ bool InitializeGLBindings(GLImplementation implementation) {
case kGLImplementationMockGL: {
SetGLGetProcAddressProc(GetMockGLProcAddress);
SetGLImplementation(kGLImplementationMockGL);
- InitializeGLBindingsGL();
+ InitializeStaticGLBindingsGL();
break;
}
default:
@@ -140,23 +141,29 @@ bool InitializeGLBindings(GLImplementation implementation) {
return true;
}
-bool InitializeGLExtensionBindings(GLImplementation implementation,
+bool InitializeDynamicGLBindings(GLImplementation implementation,
GLContext* context) {
switch (implementation) {
case kGLImplementationOSMesaGL:
- InitializeGLExtensionBindingsGL(context);
- InitializeGLExtensionBindingsOSMESA(context);
+ InitializeDynamicGLBindingsGL(context);
+ InitializeDynamicGLBindingsOSMESA(context);
break;
case kGLImplementationDesktopGL:
- InitializeGLExtensionBindingsGL(context);
- InitializeGLExtensionBindingsGLX(context);
+ InitializeDynamicGLBindingsGL(context);
+ InitializeDynamicGLBindingsGLX(context);
break;
case kGLImplementationEGLGLES2:
- InitializeGLExtensionBindingsGL(context);
- InitializeGLExtensionBindingsEGL(context);
+ InitializeDynamicGLBindingsGL(context);
+ InitializeDynamicGLBindingsEGL(context);
break;
case kGLImplementationMockGL:
- InitializeGLExtensionBindingsGL(context);
+ if (!context) {
+ scoped_refptr<GLContextStubWithExtensions> mock_context(
+ new GLContextStubWithExtensions());
+ mock_context->SetGLVersionString("3.0");
+ InitializeDynamicGLBindingsGL(mock_context.get());
+ } else
+ InitializeDynamicGLBindingsGL(context);
break;
default:
return false;
diff --git a/ui/gl/gl_osmesa_api_implementation.cc b/ui/gl/gl_osmesa_api_implementation.cc
index 5b32d22..f23c299 100644
--- a/ui/gl/gl_osmesa_api_implementation.cc
+++ b/ui/gl/gl_osmesa_api_implementation.cc
@@ -8,8 +8,8 @@ namespace gfx {
RealOSMESAApi* g_real_osmesa;
-void InitializeGLBindingsOSMESA() {
- g_driver_osmesa.InitializeBindings();
+void InitializeStaticGLBindingsOSMESA() {
+ g_driver_osmesa.InitializeStaticBindings();
if (!g_real_osmesa) {
g_real_osmesa = new RealOSMESAApi();
}
@@ -17,8 +17,8 @@ void InitializeGLBindingsOSMESA() {
g_current_osmesa_context = g_real_osmesa;
}
-void InitializeGLExtensionBindingsOSMESA(GLContext* context) {
- g_driver_osmesa.InitializeExtensionBindings(context);
+void InitializeDynamicGLBindingsOSMESA(GLContext* context) {
+ g_driver_osmesa.InitializeDynamicBindings(context);
}
void InitializeDebugGLBindingsOSMESA() {
diff --git a/ui/gl/gl_osmesa_api_implementation.h b/ui/gl/gl_osmesa_api_implementation.h
index c09da85..66f4a34 100644
--- a/ui/gl/gl_osmesa_api_implementation.h
+++ b/ui/gl/gl_osmesa_api_implementation.h
@@ -13,8 +13,8 @@ namespace gfx {
class GLContext;
-void InitializeGLBindingsOSMESA();
-void InitializeGLExtensionBindingsOSMESA(GLContext* context);
+void InitializeStaticGLBindingsOSMESA();
+void InitializeDynamicGLBindingsOSMESA(GLContext* context);
void InitializeDebugGLBindingsOSMESA();
void ClearGLBindingsOSMESA();
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc
index 55bc1b8..a52a3f7 100644
--- a/ui/gl/gl_surface.cc
+++ b/ui/gl/gl_surface.cc
@@ -55,10 +55,10 @@ bool GLSurface::InitializeOneOff() {
}
}
- initialized = InitializeGLBindings(impl) && InitializeOneOffInternal();
+ initialized = InitializeStaticGLBindings(impl) && InitializeOneOffInternal();
if (!initialized && fallback_to_osmesa) {
ClearGLBindings();
- initialized = InitializeGLBindings(kGLImplementationOSMesaGL) &&
+ initialized = InitializeStaticGLBindings(kGLImplementationOSMesaGL) &&
InitializeOneOffInternal();
}
diff --git a/ui/gl/gl_surface_wgl.cc b/ui/gl/gl_surface_wgl.cc
index 045a624..e301bce 100644
--- a/ui/gl/gl_surface_wgl.cc
+++ b/ui/gl/gl_surface_wgl.cc
@@ -165,25 +165,6 @@ bool GLSurfaceWGL::InitializeOneOff() {
if (!wgl_display->Init())
return false;
- // Create a temporary GL context to bind to extension entry points.
- HGLRC gl_context = wglCreateContext(wgl_display->device_context());
- if (!gl_context) {
- LOG(ERROR) << "Failed to create temporary context.";
- return false;
- }
- if (!wglMakeCurrent(wgl_display->device_context(), gl_context)) {
- LOG(ERROR) << "Failed to make temporary GL context current.";
- wglDeleteContext(gl_context);
- return false;
- }
- // Get bindings to extension functions that cannot be acquired without a
- // current context.
- InitializeGLBindingsGL();
- InitializeGLBindingsWGL();
-
- wglMakeCurrent(NULL, NULL);
- wglDeleteContext(gl_context);
-
g_display = wgl_display.release();
initialized = true;
return true;
diff --git a/ui/gl/gl_surface_win.cc b/ui/gl/gl_surface_win.cc
index 62bd498..6307f14 100644
--- a/ui/gl/gl_surface_win.cc
+++ b/ui/gl/gl_surface_win.cc
@@ -83,7 +83,7 @@ class DWMVSyncProvider : public VSyncProvider {
};
// Helper routine that does one-off initialization like determining the
-// pixel format and initializing the GL bindings.
+// pixel format.
bool GLSurface::InitializeOneOffInternal() {
switch (GetGLImplementation()) {
case kGLImplementationDesktopGL:
diff --git a/ui/gl/gl_version_info.cc b/ui/gl/gl_version_info.cc
new file mode 100644
index 0000000..a45219a
--- /dev/null
+++ b/ui/gl/gl_version_info.cc
@@ -0,0 +1,38 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_version_info.h"
+
+#include "base/strings/string_util.h"
+
+namespace gfx {
+
+GLVersionInfo::GLVersionInfo(const char* version_str)
+ : is_es(false),
+ is_es1(false),
+ is_es2(false),
+ is_es3(false),
+ is_gl1(false),
+ is_gl2(false),
+ is_gl3(false),
+ is_gl4(false) {
+ if (version_str) {
+ std::string lstr(StringToLowerASCII(std::string(version_str)));
+ is_es = (lstr.substr(0, 9) == "opengl es");
+ if (is_es) {
+ is_es1 = (lstr.substr(9, 2) == "-c" && lstr.substr(13, 2) == "1.");
+ is_es2 = (lstr.substr(9, 3) == " 2.");
+ is_es3 = (lstr.substr(9, 3) == " 3.");
+ } else {
+ is_gl2 = (lstr.substr(0, 2) == "2.");
+ is_gl3 = (lstr.substr(0, 2) == "3.");
+ is_gl4 = (lstr.substr(0, 2) == "4.");
+ // In early GL versions, GetString output format is implementation
+ // dependent.
+ is_gl1 = !is_gl2 && !is_gl3 && !is_gl4;
+ }
+ }
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_version_info.h b/ui/gl/gl_version_info.h
new file mode 100644
index 0000000..c8ecb07
--- /dev/null
+++ b/ui/gl/gl_version_info.h
@@ -0,0 +1,34 @@
+// Copyright 2014 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_VERSION_INFO_H_
+#define UI_GL_GL_VERSION_INFO_H_
+
+#include <string>
+#include "base/basictypes.h"
+
+namespace gfx {
+
+struct GLVersionInfo {
+ explicit GLVersionInfo(const char* version_str);
+
+ // New flags, such as is_gl4_4 could be introduced as needed.
+ // For now, this level of granularity is enough.
+ bool is_es;
+ bool is_es1;
+ bool is_es2;
+ bool is_es3;
+
+ bool is_gl1;
+ bool is_gl2;
+ bool is_gl3;
+ bool is_gl4;
+
+private:
+ DISALLOW_COPY_AND_ASSIGN(GLVersionInfo);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_VERSION_INFO_H_
diff --git a/ui/gl/gl_wgl_api_implementation.cc b/ui/gl/gl_wgl_api_implementation.cc
index e3f71d8..889a53f 100644
--- a/ui/gl/gl_wgl_api_implementation.cc
+++ b/ui/gl/gl_wgl_api_implementation.cc
@@ -9,8 +9,8 @@ namespace gfx {
RealWGLApi* g_real_wgl;
-void InitializeGLBindingsWGL() {
- g_driver_wgl.InitializeBindings();
+void InitializeStaticGLBindingsWGL() {
+ g_driver_wgl.InitializeStaticBindings();
if (!g_real_wgl) {
g_real_wgl = new RealWGLApi();
}
@@ -18,8 +18,8 @@ void InitializeGLBindingsWGL() {
g_current_wgl_context = g_real_wgl;
}
-void InitializeGLExtensionBindingsWGL(GLContext* context) {
- g_driver_wgl.InitializeExtensionBindings(context);
+void InitializeDynamicGLBindingsWGL(GLContext* context) {
+ g_driver_wgl.InitializeDynamicBindings(context);
}
void InitializeDebugGLBindingsWGL() {
diff --git a/ui/gl/gl_wgl_api_implementation.h b/ui/gl/gl_wgl_api_implementation.h
index 866623e..07a52756 100644
--- a/ui/gl/gl_wgl_api_implementation.h
+++ b/ui/gl/gl_wgl_api_implementation.h
@@ -14,8 +14,8 @@ namespace gfx {
class GLContext;
struct GLWindowSystemBindingInfo;
-void InitializeGLBindingsWGL();
-void InitializeGLExtensionBindingsWGL(GLContext* context);
+void InitializeStaticGLBindingsWGL();
+void InitializeDynamicGLBindingsWGL(GLContext* context);
void InitializeDebugGLBindingsWGL();
void ClearGLBindingsWGL();
bool GetGLWindowSystemBindingInfoWGL(GLWindowSystemBindingInfo* info);