summaryrefslogtreecommitdiffstats
path: root/ui
diff options
context:
space:
mode:
Diffstat (limited to 'ui')
-rw-r--r--ui/gfx/gl/generate_bindings.py220
-rw-r--r--ui/gfx/gl/gl.gyp5
-rw-r--r--ui/gfx/gl/gl_bindings_skia_in_process.cc9
-rw-r--r--ui/gfx/gl/gl_context.cc11
-rw-r--r--ui/gfx/gl/gl_context.h5
-rw-r--r--ui/gfx/gl/gl_context_cgl.cc5
-rw-r--r--ui/gfx/gl/gl_context_egl.cc5
-rw-r--r--ui/gfx/gl/gl_context_glx.cc5
-rw-r--r--ui/gfx/gl/gl_context_osmesa.cc5
-rw-r--r--ui/gfx/gl/gl_context_wgl.cc5
-rw-r--r--ui/gfx/gl/gl_implementation.cc34
-rw-r--r--ui/gfx/gl/gl_implementation.h11
-rw-r--r--ui/gfx/gl/gl_implementation_linux.cc25
-rw-r--r--ui/gfx/gl/gl_implementation_mac.cc20
-rw-r--r--ui/gfx/gl/gl_implementation_win.cc25
-rw-r--r--ui/gfx/gl/gl_interface.h8
16 files changed, 361 insertions, 37 deletions
diff --git a/ui/gfx/gl/generate_bindings.py b/ui/gfx/gl/generate_bindings.py
index 9d5ecf8..6260a8e 100644
--- a/ui/gfx/gl/generate_bindings.py
+++ b/ui/gfx/gl/generate_bindings.py
@@ -7,6 +7,7 @@
"""code generator for GL/GLES extension wrangler."""
import os
+import collections
import re
import sys
@@ -19,7 +20,7 @@ GL_FUNCTIONS = [
['void', ['glBindBuffer'], 'GLenum target, GLuint buffer'],
['void', ['glBindFragDataLocation'],
'GLuint program, GLuint colorNumber, const char* name'],
-['void', ['glBindFragDataLocationIndexedARB'],
+['void', ['glBindFragDataLocationIndexed'],
'GLuint program, GLuint colorNumber, GLuint index, const char* name'],
['void', ['glBindFramebufferEXT', 'glBindFramebuffer'],
'GLenum target, GLuint framebuffer'],
@@ -33,11 +34,11 @@ GL_FUNCTIONS = [
['void', ['glBlendFunc'], 'GLenum sfactor, GLenum dfactor'],
['void', ['glBlendFuncSeparate'],
'GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha'],
-['void', ['glBlitFramebufferEXT', 'BlitFramebuffer'],
+['void', ['glBlitFramebufferEXT', 'glBlitFramebuffer'],
'GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, '
'GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, '
'GLbitfield mask, GLenum filter'],
-['void', ['glBlitFramebufferANGLE', 'BlitFramebuffer'],
+['void', ['glBlitFramebufferANGLE', 'glBlitFramebuffer'],
'GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, '
'GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, '
'GLbitfield mask, GLenum filter'],
@@ -181,7 +182,7 @@ GL_FUNCTIONS = [
['GLboolean', ['glIsTexture'], 'GLuint texture'],
['void', ['glLineWidth'], 'GLfloat width'],
['void', ['glLinkProgram'], 'GLuint program'],
-['void*', ['glMapBuffer'], 'GLenum target, GLenum access'],
+['void*', ['glMapBuffer', 'glMapBufferOES'], 'GLenum target, GLenum access'],
['void', ['glPixelStorei'], 'GLenum pname, GLint param'],
['void', ['glPolygonOffset'], 'GLfloat factor, GLfloat units'],
['void', ['glQueryCounter'], 'GLuint id, GLenum target'],
@@ -251,7 +252,7 @@ GL_FUNCTIONS = [
'GLint location, GLsizei count, GLboolean transpose, const GLfloat* value'],
['void', ['glUniformMatrix4fv'],
'GLint location, GLsizei count, GLboolean transpose, const GLfloat* value'],
-['GLboolean', ['glUnmapBuffer'], 'GLenum target'],
+['GLboolean', ['glUnmapBuffer', 'glUnmapBufferOES'], 'GLenum target'],
['void', ['glUseProgram'], 'GLuint program'],
['void', ['glValidateProgram'], 'GLuint program'],
['void', ['glVertexAttrib1f'], 'GLuint indx, GLfloat x'],
@@ -465,11 +466,14 @@ GLX_FUNCTIONS = [
]
FUNCTION_SETS = [
- [GL_FUNCTIONS, 'gl'],
- [OSMESA_FUNCTIONS, 'osmesa'],
- [EGL_FUNCTIONS, 'egl'],
- [WGL_FUNCTIONS, 'wgl'],
- [GLX_FUNCTIONS, 'glx'],
+ [GL_FUNCTIONS, 'gl', ['../../../third_party/mesa/MesaLib/include/GL/glext.h',
+ '../../../gpu/GLES2/gl2ext.h']],
+ [OSMESA_FUNCTIONS, 'osmesa', []],
+ [EGL_FUNCTIONS, 'egl', ['../../../gpu/EGL/eglext.h']],
+ [WGL_FUNCTIONS, 'wgl', [
+ '../../../third_party/mesa/MesaLib/include/GL/wglext.h']],
+ [GLX_FUNCTIONS, 'glx', [
+ '../../../third_party/mesa/MesaLib/include/GL/glxext.h']],
]
def GenerateHeader(file, functions, set_name):
@@ -489,7 +493,11 @@ def GenerateHeader(file, functions, set_name):
file.write('\n')
file.write('namespace gfx {\n')
file.write('\n')
+ file.write('class GLContext;\n')
+ file.write('\n')
file.write('void InitializeGLBindings%s();\n' % set_name.upper())
+ file.write('void InitializeGLExtensionBindings%s(GLContext* context);\n' %
+ set_name.upper())
file.write('void InitializeDebugGLBindings%s();\n' % set_name.upper())
# Write typedefs for function pointer types. Always use the GL name for the
@@ -519,7 +527,7 @@ def GenerateHeader(file, functions, set_name):
set_name.upper())
-def GenerateSource(file, functions, set_name):
+def GenerateSource(file, functions, set_name, used_extension_functions):
"""Generates gl_binding_autogen_x.cc"""
# Write file header.
@@ -530,12 +538,16 @@ def GenerateSource(file, functions, set_name):
file.write('// This file is automatically generated.\n')
file.write('\n')
file.write('#include "ui/gfx/gl/gl_bindings.h"\n')
+ file.write('#include "ui/gfx/gl/gl_context.h"\n')
file.write('#include "ui/gfx/gl/gl_implementation.h"\n')
# Write definitions of function pointers.
file.write('\n')
file.write('namespace gfx {\n')
file.write('\n')
+ file.write('static bool g_debugBindingsInitialized;\n')
+ file.write('static void UpdateDebugGLExtensionBindings();\n')
+ file.write('\n')
for [return_type, names, arguments] in functions:
file.write('%sProc g_%s;\n' % (names[0], names[0]))
@@ -543,18 +555,45 @@ def GenerateSource(file, functions, set_name):
for [return_type, names, arguments] in functions:
file.write('static %sProc g_debug_%s;\n' % (names[0], names[0]))
- # Write function to initialize the function pointers.
+ # 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.
file.write('\n')
file.write('void InitializeGLBindings%s() {\n' % set_name.upper())
for [return_type, names, arguments] in functions:
- for name in names:
- file.write(' if (!g_%s)\n' % names[0])
+ for i, name in enumerate(names):
+ if i:
+ file.write(' if (!g_%s)\n ' % names[0])
file.write(
- ' g_%s = reinterpret_cast<%sProc>(GetGLProcAddress("%s"));\n' %
+ ' g_%s = reinterpret_cast<%sProc>(GetGLCoreProcAddress("%s"));\n' %
(names[0], names[0], name))
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 InitializeGLExtensionBindings%s(GLContext* context) {\n' %
+ set_name.upper())
+ file.write(' DCHECK(context && context->IsCurrent(NULL));\n')
+ for extension, ext_functions in used_extension_functions:
+ file.write(' if (context->HasExtension("%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 (!g_%s)\n ' % entry_point_name)
+ file.write(
+ ' g_%s = reinterpret_cast<%sProc>(GetGLProcAddress("%s"));\n' %
+ (entry_point_name, entry_point_name, function_name))
+ queried_entry_points.add(entry_point_name)
+ file.write(' }\n')
+ file.write(' if (g_debugBindingsInitialized)\n')
+ file.write(' UpdateDebugGLExtensionBindings();\n')
+ file.write('}\n')
+ file.write('\n')
+
# Write logging wrappers for each function.
file.write('extern "C" {\n')
for [return_type, names, arguments] in functions:
@@ -597,19 +636,31 @@ def GenerateSource(file, functions, set_name):
file.write('}\n')
file.write('} // extern "C"\n')
- # Write function to initialize the function pointers.
+ # Write function to initialize the debug function pointers.
file.write('\n')
file.write('void InitializeDebugGLBindings%s() {\n' % set_name.upper())
for [return_type, names, arguments] in functions:
- for name in names:
- file.write(' if (!g_debug_%s) {\n' % names[0])
- file.write(' g_debug_%s = g_%s;\n' % (names[0], names[0]))
- file.write(' g_%s = Debug_%s;\n' % (names[0], names[0]))
- file.write(' }\n')
+ file.write(' if (!g_debug_%s) {\n' % names[0])
+ file.write(' g_debug_%s = g_%s;\n' % (names[0], names[0]))
+ file.write(' g_%s = Debug_%s;\n' % (names[0], names[0]))
+ file.write(' }\n')
+ file.write(' g_debugBindingsInitialized = true;\n')
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('static void UpdateDebugGLExtensionBindings() {\n')
+ for extension, ext_functions in used_extension_functions:
+ for name, _ in ext_functions:
+ file.write(' if (g_debug_%s != g_%s &&\n' % (name, name))
+ file.write(' g_%s != Debug_%s) {\n' % (name, name))
+ file.write(' g_debug_%s = g_%s;\n' % (name, name))
+ file.write(' g_%s = Debug_%s;\n' % (name, name))
+ file.write(' }\n')
+ file.write('}\n')
- file.write( '} // namespace gfx\n')
+ file.write('} // namespace gfx\n')
def GenerateMockSource(file, functions):
@@ -646,18 +697,135 @@ def GenerateMockSource(file, functions):
(function_name, argument_names))
file.write('}\n')
+ # Write an 'invalid' function to catch code calling through uninitialized
+ # function pointers or trying to interpret the return value of
+ # GLProcAddress().
+ file.write('\n')
+ file.write('static void MockInvalidFunction() {\n')
+ file.write(' NOTREACHED();\n')
+ file.write('}\n')
+
# Write a function to lookup a mock GL function based on its name.
file.write('\n')
file.write('void* GL_BINDING_CALL GetMockGLProcAddress(const char* name) {\n')
for [return_type, names, arguments] in functions:
file.write(' if (strcmp(name, "%s") == 0)\n' % names[0])
file.write(' return reinterpret_cast<void*>(Mock_%s);\n' % names[0])
- file.write(' return NULL;\n')
+ # 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('} // namespace gfx\n')
+def ParseExtensionFunctionsFromHeader(header_file):
+ """Parse a C extension header file and return a map from extension names to
+ a list of functions.
+
+ Args:
+ header_file: Line-iterable C header file.
+ Returns:
+ Map of extension name => functions.
+ """
+ extension_start = re.compile(r'#define ([A-Z]+_[A-Z]+_[a-zA-Z]\w+) 1')
+ extension_function = re.compile(r'.+\s+([a-z]+\w+)\s*\(.+\);')
+ typedef = re.compile(r'typedef .*')
+ macro_start = re.compile(r'^#(if|ifdef|ifndef).*')
+ macro_end = re.compile(r'^#endif.*')
+ macro_depth = 0
+ current_extension = None
+ current_extension_depth = 0
+ extensions = collections.defaultdict(lambda: [])
+ for line in header_file:
+ if macro_start.match(line):
+ macro_depth += 1
+ elif macro_end.match(line):
+ macro_depth -= 1
+ if macro_depth < current_extension_depth:
+ current_extension = None
+ match = extension_start.match(line)
+ if match:
+ current_extension = match.group(1)
+ current_extension_depth = macro_depth
+ assert current_extension not in extensions, \
+ "Duplicate extension: " + current_extension
+ match = extension_function.match(line)
+ if match and current_extension and not typedef.match(line):
+ extensions[current_extension].append(match.group(1))
+ return extensions
+
+def GetExtensionFunctions(extension_headers):
+ """Parse extension functions from a list of header files.
+
+ Args:
+ extension_headers: List of header file names.
+ Returns:
+ Map of extension name => list of functions.
+ """
+ extensions = {}
+ for header in extension_headers:
+ extensions.update(ParseExtensionFunctionsFromHeader(open(header)))
+ return extensions
+
+def GetFunctionToExtensionMap(extensions):
+ """Construct map from a function names to extensions which define the
+ function.
+
+ Args:
+ extensions: Map of extension name => functions.
+ Returns:
+ Map of function name => extension name.
+ """
+ function_to_extension = {}
+ for extension, functions in extensions.items():
+ for function in functions:
+ assert function not in function_to_extension, \
+ "Duplicate function: " + function
+ function_to_extension[function] = extension
+ return function_to_extension
+
+def LooksLikeExtensionFunction(function):
+ """Heuristic to see if a function name is consistent with extension function
+ naming."""
+ vendor = re.match(r'\w+?([A-Z][A-Z]+)$', function)
+ return vendor is not None and not vendor.group(1) in ['GL', 'API', 'DC']
+
+def GetUsedExtensionFunctions(functions, extension_headers):
+ """Determine which functions belong to extensions.
+
+ Args:
+ functions: List of (return type, function names, arguments).
+ extension_headers: List of header file names.
+ Returns:
+ List of (extension name, [function name alternatives]) sorted with least
+ preferred extensions first.
+ """
+ # Parse known extensions.
+ extensions = GetExtensionFunctions(extension_headers)
+ functions_to_extensions = GetFunctionToExtensionMap(extensions)
+
+ # Collect all used extension functions.
+ used_extension_functions = collections.defaultdict(lambda: [])
+ for [return_type, names, arguments] in functions:
+ for name in names:
+ # Make sure we know about all extension functions.
+ if (LooksLikeExtensionFunction(name) and
+ not name in functions_to_extensions):
+ 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:
+ extension = functions_to_extensions[name]
+ used_extension_functions[extension].append((names[0], name))
+
+ 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
def main(argv):
"""This is the main function."""
@@ -667,7 +835,7 @@ def main(argv):
else:
dir = '.'
- for [functions, set_name] in FUNCTION_SETS:
+ for [functions, set_name, extension_headers] in FUNCTION_SETS:
header_file = open(
os.path.join(dir, 'gl_bindings_autogen_%s.h' % set_name), 'wb')
GenerateHeader(header_file, functions, set_name)
@@ -675,7 +843,9 @@ def main(argv):
source_file = open(
os.path.join(dir, 'gl_bindings_autogen_%s.cc' % set_name), 'wb')
- GenerateSource(source_file, functions, set_name)
+ used_extension_functions = GetUsedExtensionFunctions(
+ functions, extension_headers)
+ GenerateSource(source_file, functions, set_name, used_extension_functions)
source_file.close()
source_file = open(os.path.join(dir, 'gl_bindings_autogen_mock.cc'), 'wb')
diff --git a/ui/gfx/gl/gl.gyp b/ui/gfx/gl/gl.gyp
index f29f270..22e40b9 100644
--- a/ui/gfx/gl/gl.gyp
+++ b/ui/gfx/gl/gl.gyp
@@ -87,6 +87,11 @@
'action_name': 'generate_gl_bindings',
'inputs': [
'generate_bindings.py',
+ '../../../gpu/GLES2/gl2ext.h',
+ '../../../gpu/EGL/eglext.h',
+ '../../../third_party/mesa/MesaLib/include/GL/glext.h',
+ '../../../third_party/mesa/MesaLib/include/GL/glxext.h',
+ '../../../third_party/mesa/MesaLib/include/GL/wglext.h',
],
'outputs': [
'<(gl_binding_output_dir)/gl_bindings_autogen_egl.cc',
diff --git a/ui/gfx/gl/gl_bindings_skia_in_process.cc b/ui/gfx/gl/gl_bindings_skia_in_process.cc
index 1fafda0..0be194a 100644
--- a/ui/gfx/gl/gl_bindings_skia_in_process.cc
+++ b/ui/gfx/gl/gl_bindings_skia_in_process.cc
@@ -43,9 +43,9 @@ GLvoid StubGLBindFragDataLocation(GLuint program, GLuint colorNumber,
glBindFragDataLocation(program, colorNumber, name);
}
-GLvoid StubGLBindFragDataLocationIndexedARB(GLuint program, GLuint colorNumber,
- GLuint index, const GLchar * name) {
- glBindFragDataLocationIndexedARB(program, colorNumber, index, name);
+GLvoid StubGLBindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
+ GLuint index, const GLchar * name) {
+ glBindFragDataLocationIndexed(program, colorNumber, index, name);
}
GLvoid StubGLBindFramebuffer(GLenum target, GLuint framebuffer) {
@@ -661,9 +661,8 @@ GrGLInterface* CreateInProcessSkiaGLBinding() {
interface->fMapBuffer = StubGLMapBuffer;
interface->fUnmapBuffer = StubGLUnmapBuffer;
interface->fBindFragDataLocationIndexed =
- StubGLBindFragDataLocationIndexedARB;
+ StubGLBindFragDataLocationIndexed;
return interface;
}
} // namespace gfx
-
diff --git a/ui/gfx/gl/gl_context.cc b/ui/gfx/gl/gl_context.cc
index 6c25052e..6053bdb 100644
--- a/ui/gfx/gl/gl_context.cc
+++ b/ui/gfx/gl/gl_context.cc
@@ -81,4 +81,15 @@ bool GLContext::WasAllocatedUsingARBRobustness() {
return false;
}
+bool GLContext::InitializeExtensionBindings() {
+ DCHECK(IsCurrent(NULL));
+ static bool initialized = false;
+ if (initialized)
+ return initialized;
+ initialized = InitializeGLExtensionBindings(GetGLImplementation(), this);
+ if (!initialized)
+ LOG(ERROR) << "Could not initialize extension bindings.";
+ return initialized;
+}
+
} // namespace gfx
diff --git a/ui/gfx/gl/gl_context.h b/ui/gfx/gl/gl_context.h
index 3046485..67fe57e 100644
--- a/ui/gfx/gl/gl_context.h
+++ b/ui/gfx/gl/gl_context.h
@@ -77,6 +77,11 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
virtual ~GLContext();
static void SetCurrent(GLContext* context, GLSurface* surface);
+ // Initialize function pointers to extension functions in the GL
+ // implementation. Should be called immediately after this context is made
+ // current.
+ bool InitializeExtensionBindings();
+
private:
scoped_refptr<GLShareGroup> share_group_;
friend class base::RefCounted<GLContext>;
diff --git a/ui/gfx/gl/gl_context_cgl.cc b/ui/gfx/gl/gl_context_cgl.cc
index 0e96bd4..8790602 100644
--- a/ui/gfx/gl/gl_context_cgl.cc
+++ b/ui/gfx/gl/gl_context_cgl.cc
@@ -103,6 +103,11 @@ bool GLContextCGL::MakeCurrent(GLSurface* surface) {
}
SetCurrent(this, surface);
+ if (!InitializeExtensionBindings()) {
+ ReleaseCurrent(surface);
+ return false;
+ }
+
if (!surface->OnMakeCurrent(this)) {
LOG(ERROR) << "Unable to make gl context current.";
return false;
diff --git a/ui/gfx/gl/gl_context_egl.cc b/ui/gfx/gl/gl_context_egl.cc
index 6c69f79..d9b6950 100644
--- a/ui/gfx/gl/gl_context_egl.cc
+++ b/ui/gfx/gl/gl_context_egl.cc
@@ -96,6 +96,11 @@ bool GLContextEGL::MakeCurrent(GLSurface* surface) {
}
SetCurrent(this, surface);
+ if (!InitializeExtensionBindings()) {
+ ReleaseCurrent(surface);
+ return false;
+ }
+
if (!surface->OnMakeCurrent(this)) {
LOG(ERROR) << "Could not make current.";
return false;
diff --git a/ui/gfx/gl/gl_context_glx.cc b/ui/gfx/gl/gl_context_glx.cc
index 0f392e6..3e89981 100644
--- a/ui/gfx/gl/gl_context_glx.cc
+++ b/ui/gfx/gl/gl_context_glx.cc
@@ -178,6 +178,11 @@ bool GLContextGLX::MakeCurrent(GLSurface* surface) {
}
SetCurrent(this, surface);
+ if (!InitializeExtensionBindings()) {
+ ReleaseCurrent(surface);
+ return false;
+ }
+
if (!surface->OnMakeCurrent(this)) {
LOG(ERROR) << "Could not make current.";
return false;
diff --git a/ui/gfx/gl/gl_context_osmesa.cc b/ui/gfx/gl/gl_context_osmesa.cc
index df7766d..efa6d16 100644
--- a/ui/gfx/gl/gl_context_osmesa.cc
+++ b/ui/gfx/gl/gl_context_osmesa.cc
@@ -70,6 +70,11 @@ bool GLContextOSMesa::MakeCurrent(GLSurface* surface) {
OSMesaPixelStore(OSMESA_Y_UP, 0);
SetCurrent(this, surface);
+ if (!InitializeExtensionBindings()) {
+ ReleaseCurrent(surface);
+ return false;
+ }
+
if (!surface->OnMakeCurrent(this)) {
LOG(ERROR) << "Could not make current.";
return false;
diff --git a/ui/gfx/gl/gl_context_wgl.cc b/ui/gfx/gl/gl_context_wgl.cc
index 01506c0..87e50a3 100644
--- a/ui/gfx/gl/gl_context_wgl.cc
+++ b/ui/gfx/gl/gl_context_wgl.cc
@@ -83,6 +83,11 @@ bool GLContextWGL::MakeCurrent(GLSurface* surface) {
}
SetCurrent(this, surface);
+ if (!InitializeExtensionBindings()) {
+ ReleaseCurrent(surface);
+ return false;
+ }
+
if (!surface->OnMakeCurrent(this)) {
LOG(ERROR) << "Could not make current.";
return false;
diff --git a/ui/gfx/gl/gl_implementation.cc b/ui/gfx/gl/gl_implementation.cc
index 19cc91c..f7ad2ee 100644
--- a/ui/gfx/gl/gl_implementation.cc
+++ b/ui/gfx/gl/gl_implementation.cc
@@ -41,6 +41,21 @@ void CleanupNativeLibraries(void* unused) {
g_libraries = NULL;
}
}
+
+bool ExportsCoreFunctionsFromGetProcAddress(GLImplementation implementation) {
+ switch (GetGLImplementation()) {
+ case kGLImplementationDesktopGL:
+ case kGLImplementationOSMesaGL:
+ case kGLImplementationMockGL:
+ return true;
+ case kGLImplementationEGLGLES2:
+ return false;
+ default:
+ NOTREACHED();
+ return true;
+ }
+}
+
}
GLImplementation GetNamedGLImplementation(const std::string& name) {
@@ -137,7 +152,7 @@ void SetGLGetProcAddressProc(GLGetProcAddressProc proc) {
g_get_proc_address = proc;
}
-void* GetGLProcAddress(const char* name) {
+void* GetGLCoreProcAddress(const char* name) {
DCHECK(g_gl_implementation != kGLImplementationNone);
if (g_libraries) {
@@ -148,8 +163,8 @@ void* GetGLProcAddress(const char* name) {
return proc;
}
}
-
- if (g_get_proc_address) {
+ if (ExportsCoreFunctionsFromGetProcAddress(g_gl_implementation) &&
+ g_get_proc_address) {
void* proc = g_get_proc_address(name);
if (proc)
return proc;
@@ -158,4 +173,17 @@ void* GetGLProcAddress(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;
+}
+
} // namespace gfx
diff --git a/ui/gfx/gl/gl_implementation.h b/ui/gfx/gl/gl_implementation.h
index 9024ca1..5d5ab55 100644
--- a/ui/gfx/gl/gl_implementation.h
+++ b/ui/gfx/gl/gl_implementation.h
@@ -15,6 +15,8 @@
namespace gfx {
+class GLContext;
+
// The GL implementation currently in use.
enum GLImplementation {
kGLImplementationNone,
@@ -33,6 +35,10 @@ typedef void* (*GLGetProcAddressProc)(const char* name);
// Initialize a particular GL implementation.
GL_EXPORT bool InitializeGLBindings(GLImplementation implementation);
+// Initialize extension function bindings for a GL implementation.
+GL_EXPORT bool InitializeGLExtensionBindings(GLImplementation implementation,
+ GLContext* context);
+
// Initialize Debug logging wrappers for GL bindings.
void InitializeDebugGLBindings();
@@ -66,6 +72,11 @@ void AddGLNativeLibrary(base::NativeLibrary library);
// 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.
void* GetGLProcAddress(const char* name);
diff --git a/ui/gfx/gl/gl_implementation_linux.cc b/ui/gfx/gl/gl_implementation_linux.cc
index 568edeb..952e62e 100644
--- a/ui/gfx/gl/gl_implementation_linux.cc
+++ b/ui/gfx/gl/gl_implementation_linux.cc
@@ -179,6 +179,31 @@ bool InitializeGLBindings(GLImplementation implementation) {
return true;
}
+bool InitializeGLExtensionBindings(GLImplementation implementation,
+ GLContext* context) {
+ switch (implementation) {
+ case kGLImplementationOSMesaGL:
+ InitializeGLExtensionBindingsGL(context);
+ InitializeGLExtensionBindingsOSMESA(context);
+ break;
+ case kGLImplementationDesktopGL:
+ InitializeGLExtensionBindingsGL(context);
+ InitializeGLExtensionBindingsGLX(context);
+ break;
+ case kGLImplementationEGLGLES2:
+ InitializeGLExtensionBindingsGL(context);
+ InitializeGLExtensionBindingsEGL(context);
+ break;
+ case kGLImplementationMockGL:
+ InitializeGLExtensionBindingsGL(context);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
void InitializeDebugGLBindings() {
InitializeDebugGLBindingsEGL();
InitializeDebugGLBindingsGL();
diff --git a/ui/gfx/gl/gl_implementation_mac.cc b/ui/gfx/gl/gl_implementation_mac.cc
index 780f6a7..24d2c4d 100644
--- a/ui/gfx/gl/gl_implementation_mac.cc
+++ b/ui/gfx/gl/gl_implementation_mac.cc
@@ -96,6 +96,26 @@ bool InitializeGLBindings(GLImplementation implementation) {
return true;
}
+bool InitializeGLExtensionBindings(GLImplementation implementation,
+ GLContext* context) {
+ switch (implementation) {
+ case kGLImplementationOSMesaGL:
+ InitializeGLExtensionBindingsGL(context);
+ InitializeGLExtensionBindingsOSMESA(context);
+ break;
+ case kGLImplementationDesktopGL:
+ InitializeGLExtensionBindingsGL(context);
+ break;
+ case kGLImplementationMockGL:
+ InitializeGLExtensionBindingsGL(context);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
void InitializeDebugGLBindings() {
InitializeDebugGLBindingsGL();
InitializeDebugGLBindingsOSMESA();
diff --git a/ui/gfx/gl/gl_implementation_win.cc b/ui/gfx/gl/gl_implementation_win.cc
index de0ee31..7b74316 100644
--- a/ui/gfx/gl/gl_implementation_win.cc
+++ b/ui/gfx/gl/gl_implementation_win.cc
@@ -207,6 +207,31 @@ bool InitializeGLBindings(GLImplementation implementation) {
return true;
}
+bool InitializeGLExtensionBindings(GLImplementation implementation,
+ GLContext* context) {
+ switch (implementation) {
+ case kGLImplementationOSMesaGL:
+ InitializeGLExtensionBindingsGL(context);
+ InitializeGLExtensionBindingsOSMESA(context);
+ break;
+ case kGLImplementationEGLGLES2:
+ InitializeGLExtensionBindingsGL(context);
+ InitializeGLExtensionBindingsEGL(context);
+ break;
+ case kGLImplementationDesktopGL:
+ InitializeGLExtensionBindingsGL(context);
+ InitializeGLExtensionBindingsWGL(context);
+ break;
+ case kGLImplementationMockGL:
+ InitializeGLExtensionBindingsGL(context);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
void InitializeDebugGLBindings() {
InitializeDebugGLBindingsEGL();
InitializeDebugGLBindingsGL();
diff --git a/ui/gfx/gl/gl_interface.h b/ui/gfx/gl/gl_interface.h
index 97363b7..5783e50 100644
--- a/ui/gfx/gl/gl_interface.h
+++ b/ui/gfx/gl/gl_interface.h
@@ -36,10 +36,10 @@ class GL_EXPORT GLInterface {
virtual void BindBuffer(GLenum target, GLuint buffer) = 0;
- virtual void BindFragDataLocationIndexedARB(GLuint program,
- GLuint colorNumber,
- GLuint index,
- const char* name) = 0;
+ virtual void BindFragDataLocationIndexed(GLuint program,
+ GLuint colorNumber,
+ GLuint index,
+ const char* name) = 0;
virtual void BindFragDataLocation(GLuint program,
GLuint colorNumber,