summaryrefslogtreecommitdiffstats
path: root/ui/gl
diff options
context:
space:
mode:
authortfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-12 21:17:27 +0000
committertfarina@chromium.org <tfarina@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-05-12 21:17:27 +0000
commitc9e2cbbbcad5f0ae5b9c5ccaf6a36a8a4a61e0e7 (patch)
treee33d97dc2edae8702ddb6a17ba0d89a506412693 /ui/gl
parentfc25fd35147b2d5e74d5450e8586592c6a10813d (diff)
downloadchromium_src-c9e2cbbbcad5f0ae5b9c5ccaf6a36a8a4a61e0e7.zip
chromium_src-c9e2cbbbcad5f0ae5b9c5ccaf6a36a8a4a61e0e7.tar.gz
chromium_src-c9e2cbbbcad5f0ae5b9c5ccaf6a36a8a4a61e0e7.tar.bz2
ui: Move gl/ directory out of gfx/, up to ui/.
BUG=104040 R=ben@chromium.org TBR=tony@chromium.org Review URL: https://chromiumcodereview.appspot.com/10392068 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@136777 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui/gl')
-rw-r--r--ui/gl/DEPS4
-rw-r--r--ui/gl/OWNERS4
-rw-r--r--ui/gl/android_native_window.cc26
-rw-r--r--ui/gl/android_native_window.h32
-rw-r--r--ui/gl/egl_util.cc53
-rw-r--r--ui/gl/egl_util.h16
-rwxr-xr-xui/gl/generate_bindings.py1531
-rw-r--r--ui/gl/gl.gyp206
-rw-r--r--ui/gl/gl_bindings.h105
-rw-r--r--ui/gl/gl_bindings_skia_in_process.cc676
-rw-r--r--ui/gl/gl_bindings_skia_in_process.h21
-rw-r--r--ui/gl/gl_context.cc111
-rw-r--r--ui/gl/gl_context.h95
-rw-r--r--ui/gl/gl_context_android.cc34
-rw-r--r--ui/gl/gl_context_cgl.cc163
-rw-r--r--ui/gl/gl_context_cgl.h51
-rw-r--r--ui/gl/gl_context_egl.cc160
-rw-r--r--ui/gl/gl_context_egl.h49
-rw-r--r--ui/gl/gl_context_glx.cc253
-rw-r--r--ui/gl/gl_context_glx.h48
-rw-r--r--ui/gl/gl_context_linux.cc63
-rw-r--r--ui/gl/gl_context_mac.mm184
-rw-r--r--ui/gl/gl_context_nsview.h48
-rw-r--r--ui/gl/gl_context_nsview.mm99
-rw-r--r--ui/gl/gl_context_osmesa.cc130
-rw-r--r--ui/gl/gl_context_osmesa.h46
-rw-r--r--ui/gl/gl_context_stub.cc43
-rw-r--r--ui/gl/gl_context_stub.h38
-rw-r--r--ui/gl/gl_context_wgl.cc141
-rw-r--r--ui/gl/gl_context_wgl.h43
-rw-r--r--ui/gl/gl_context_win.cc61
-rw-r--r--ui/gl/gl_export.h26
-rw-r--r--ui/gl/gl_fence.cc108
-rw-r--r--ui/gl/gl_fence.h31
-rw-r--r--ui/gl/gl_implementation.cc151
-rw-r--r--ui/gl/gl_implementation.h86
-rw-r--r--ui/gl/gl_implementation_android.cc132
-rw-r--r--ui/gl/gl_implementation_linux.cc228
-rw-r--r--ui/gl/gl_implementation_mac.cc140
-rw-r--r--ui/gl/gl_implementation_win.cc290
-rw-r--r--ui/gl/gl_interface.cc20
-rw-r--r--ui/gl/gl_interface.h640
-rw-r--r--ui/gl/gl_share_group.cc44
-rw-r--r--ui/gl/gl_share_group.h52
-rw-r--r--ui/gl/gl_surface.cc208
-rw-r--r--ui/gl/gl_surface.h157
-rw-r--r--ui/gl/gl_surface_android.cc181
-rw-r--r--ui/gl/gl_surface_android.h45
-rw-r--r--ui/gl/gl_surface_cgl.cc101
-rw-r--r--ui/gl/gl_surface_cgl.h56
-rw-r--r--ui/gl/gl_surface_egl.cc398
-rw-r--r--ui/gl/gl_surface_egl.h106
-rw-r--r--ui/gl/gl_surface_glx.cc326
-rw-r--r--ui/gl/gl_surface_glx.h98
-rw-r--r--ui/gl/gl_surface_linux.cc339
-rw-r--r--ui/gl/gl_surface_mac.cc95
-rw-r--r--ui/gl/gl_surface_nsview.h47
-rw-r--r--ui/gl/gl_surface_nsview.mm47
-rw-r--r--ui/gl/gl_surface_osmesa.cc82
-rw-r--r--ui/gl/gl_surface_osmesa.h45
-rw-r--r--ui/gl/gl_surface_stub.cc30
-rw-r--r--ui/gl/gl_surface_stub.h34
-rw-r--r--ui/gl/gl_surface_wgl.cc366
-rw-r--r--ui/gl/gl_surface_wgl.h77
-rw-r--r--ui/gl/gl_surface_win.cc248
-rw-r--r--ui/gl/gl_switches.cc55
-rw-r--r--ui/gl/gl_switches.h39
-rw-r--r--ui/gl/gpu_preference.h25
-rw-r--r--ui/gl/scoped_make_current.cc36
-rw-r--r--ui/gl/scoped_make_current.h33
70 files changed, 9756 insertions, 0 deletions
diff --git a/ui/gl/DEPS b/ui/gl/DEPS
new file mode 100644
index 0000000..4d34aad
--- /dev/null
+++ b/ui/gl/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+third_party/angle/include",
+ "+third_party/mesa/MesaLib/include",
+]
diff --git a/ui/gl/OWNERS b/ui/gl/OWNERS
new file mode 100644
index 0000000..9ce8991
--- /dev/null
+++ b/ui/gl/OWNERS
@@ -0,0 +1,4 @@
+apatrick@chromium.org
+backer@chromium.org
+kbr@chromium.org
+gman@chromium.org
diff --git a/ui/gl/android_native_window.cc b/ui/gl/android_native_window.cc
new file mode 100644
index 0000000..f75b753
--- /dev/null
+++ b/ui/gl/android_native_window.cc
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/android_native_window.h"
+
+#include <android/native_window.h>
+
+namespace gfx {
+
+AndroidNativeWindow::AndroidNativeWindow(ANativeWindow* window)
+ : window_(window) {
+ if (window_)
+ ANativeWindow_acquire(window_);
+}
+
+AndroidNativeWindow::~AndroidNativeWindow() {
+ if (window_)
+ ANativeWindow_release(window_);
+}
+
+ANativeWindow* AndroidNativeWindow::GetNativeHandle() const {
+ return window_;
+}
+
+} // namespace gfx
diff --git a/ui/gl/android_native_window.h b/ui/gl/android_native_window.h
new file mode 100644
index 0000000..bde5904
--- /dev/null
+++ b/ui/gl/android_native_window.h
@@ -0,0 +1,32 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_ANDROID_NATIVE_WINDOW_H_
+#define UI_GL_ANDROID_NATIVE_WINDOW_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+
+struct ANativeWindow;
+
+namespace gfx {
+
+// This class deals with the Android native window ref count.
+class AndroidNativeWindow {
+ public:
+ explicit AndroidNativeWindow(ANativeWindow* window);
+ ~AndroidNativeWindow();
+
+ ANativeWindow* GetNativeHandle() const;
+
+ private:
+ ANativeWindow* window_;
+
+ DISALLOW_COPY_AND_ASSIGN(AndroidNativeWindow);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_ANDROID_NATIVE_WINDOW_H_
diff --git a/ui/gl/egl_util.cc b/ui/gl/egl_util.cc
new file mode 100644
index 0000000..91d1b12
--- /dev/null
+++ b/ui/gl/egl_util.cc
@@ -0,0 +1,53 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/egl_util.h"
+
+#if defined(OS_ANDROID)
+#include <EGL/egl.h>
+#else
+#include "third_party/angle/include/EGL/egl.h"
+#endif
+
+// This needs to be after the EGL includes
+#include "ui/gl/gl_bindings.h"
+
+namespace gfx {
+
+// Returns the last EGL error as a string.
+const char* GetLastEGLErrorString() {
+ EGLint error = eglGetError();
+ switch (error) {
+ case EGL_SUCCESS:
+ return "EGL_SUCCESS";
+ case EGL_BAD_ACCESS:
+ return "EGL_BAD_ACCESS";
+ case EGL_BAD_ALLOC:
+ return "EGL_BAD_ALLOC";
+ case EGL_BAD_ATTRIBUTE:
+ return "EGL_BAD_ATTRIBUTE";
+ case EGL_BAD_CONTEXT:
+ return "EGL_BAD_CONTEXT";
+ case EGL_BAD_CONFIG:
+ return "EGL_BAD_CONFIG";
+ case EGL_BAD_CURRENT_SURFACE:
+ return "EGL_BAD_CURRENT_SURFACE";
+ case EGL_BAD_DISPLAY:
+ return "EGL_BAD_DISPLAY";
+ case EGL_BAD_SURFACE:
+ return "EGL_BAD_SURFACE";
+ case EGL_BAD_MATCH:
+ return "EGL_BAD_MATCH";
+ case EGL_BAD_PARAMETER:
+ return "EGL_BAD_PARAMETER";
+ case EGL_BAD_NATIVE_PIXMAP:
+ return "EGL_BAD_NATIVE_PIXMAP";
+ case EGL_BAD_NATIVE_WINDOW:
+ return "EGL_BAD_NATIVE_WINDOW";
+ default:
+ return "UNKNOWN";
+ }
+}
+
+} // namespace gfx
diff --git a/ui/gl/egl_util.h b/ui/gl/egl_util.h
new file mode 100644
index 0000000..bf6a019
--- /dev/null
+++ b/ui/gl/egl_util.h
@@ -0,0 +1,16 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_EGL_UTIL_H_
+#define UI_GL_EGL_UTIL_H_
+#pragma once
+
+namespace gfx {
+
+// Returns the last EGL error as a string.
+const char* GetLastEGLErrorString();
+
+} // namespace gfx
+
+#endif // UI_GL_EGL_UTIL_H_
diff --git a/ui/gl/generate_bindings.py b/ui/gl/generate_bindings.py
new file mode 100755
index 0000000..22ab46a
--- /dev/null
+++ b/ui/gl/generate_bindings.py
@@ -0,0 +1,1531 @@
+#!/usr/bin/env python
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""code generator for GL/GLES extension wrangler."""
+
+import os
+import collections
+import re
+import sys
+
+GL_FUNCTIONS = [
+{ 'return_type': 'void',
+ 'names': ['glActiveTexture'],
+ 'arguments': 'GLenum texture', },
+{ 'return_type': 'void',
+ 'names': ['glAttachShader'],
+ 'arguments': 'GLuint program, GLuint shader', },
+{ 'return_type': 'void',
+ 'names': ['glBeginQuery'],
+ 'arguments': 'GLenum target, GLuint id', },
+{ 'return_type': 'void',
+ 'names': ['glBeginQueryARB', 'glBeginQueryEXT'],
+ 'arguments': 'GLenum target, GLuint id', },
+{ 'return_type': 'void',
+ 'names': ['glBindAttribLocation'],
+ 'arguments': 'GLuint program, GLuint index, const char* name', },
+{ 'return_type': 'void',
+ 'names': ['glBindBuffer'],
+ 'arguments': 'GLenum target, GLuint buffer', },
+{ 'return_type': 'void',
+ 'names': ['glBindFragDataLocation'],
+ 'arguments': 'GLuint program, GLuint colorNumber, const char* name', },
+{ 'return_type': 'void',
+ 'names': ['glBindFragDataLocationIndexed'],
+ 'arguments':
+ 'GLuint program, GLuint colorNumber, GLuint index, const char* name', },
+{ 'return_type': 'void',
+ 'names': ['glBindFramebufferEXT', 'glBindFramebuffer'],
+ 'arguments': 'GLenum target, GLuint framebuffer', },
+{ 'return_type': 'void',
+ 'names': ['glBindRenderbufferEXT', 'glBindRenderbuffer'],
+ 'arguments': 'GLenum target, GLuint renderbuffer', },
+{ 'return_type': 'void',
+ 'names': ['glBindTexture'],
+ 'arguments': 'GLenum target, GLuint texture', },
+{ 'return_type': 'void',
+ 'names': ['glBlendColor'],
+ 'arguments': 'GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha', },
+{ 'return_type': 'void',
+ 'names': ['glBlendEquation'],
+ 'arguments': ' GLenum mode ', },
+{ 'return_type': 'void',
+ 'names': ['glBlendEquationSeparate'],
+ 'arguments': 'GLenum modeRGB, GLenum modeAlpha', },
+{ 'return_type': 'void',
+ 'names': ['glBlendFunc'],
+ 'arguments': 'GLenum sfactor, GLenum dfactor', },
+{ 'return_type': 'void',
+ 'names': ['glBlendFuncSeparate'],
+ 'arguments':
+ 'GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha', },
+{ 'return_type': 'void',
+ 'names': ['glBlitFramebufferEXT', 'glBlitFramebuffer'],
+ 'arguments': 'GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, '
+ 'GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, '
+ 'GLbitfield mask, GLenum filter', },
+{ 'return_type': 'void',
+ 'names': ['glBlitFramebufferANGLE', 'glBlitFramebuffer'],
+ 'arguments': 'GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, '
+ 'GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, '
+ 'GLbitfield mask, GLenum filter', },
+{ 'return_type': 'void',
+ 'names': ['glBufferData'],
+ 'arguments': 'GLenum target, GLsizei size, const void* data, GLenum usage', },
+{ 'return_type': 'void',
+ 'names': ['glBufferSubData'],
+ 'arguments': 'GLenum target, GLint offset, GLsizei size, const void* data', },
+{ 'return_type': 'GLenum',
+ 'names': ['glCheckFramebufferStatusEXT',
+ 'glCheckFramebufferStatus'],
+ 'arguments': 'GLenum target',
+ 'logging_code': """
+ GL_SERVICE_LOG("GL_RESULT: " << GLES2Util::GetStringEnum(result));
+""", },
+{ 'return_type': 'void',
+ 'names': ['glClear'],
+ 'arguments': 'GLbitfield mask', },
+{ 'return_type': 'void',
+ 'names': ['glClearColor'],
+ 'arguments': 'GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha', },
+{ 'return_type': 'void',
+ 'names': ['glClearDepth'],
+ 'arguments': 'GLclampd depth', },
+{ 'return_type': 'void',
+ 'names': ['glClearDepthf'],
+ 'arguments': 'GLclampf depth', },
+{ 'return_type': 'void',
+ 'names': ['glClearStencil'],
+ 'arguments': 'GLint s', },
+{ 'return_type': 'void',
+ 'names': ['glColorMask'],
+ 'arguments':
+ 'GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha', },
+{ 'return_type': 'void',
+ 'names': ['glCompileShader'],
+ 'arguments': 'GLuint shader', },
+{ 'return_type': 'void',
+ 'names': ['glCompressedTexImage2D'],
+ 'arguments':
+ 'GLenum target, GLint level, GLenum internalformat, GLsizei width, '
+ 'GLsizei height, GLint border, GLsizei imageSize, const void* data', },
+{ 'return_type': 'void',
+ 'names': ['glCompressedTexSubImage2D'],
+ 'arguments':
+ 'GLenum target, GLint level, GLint xoffset, GLint yoffset, '
+ 'GLsizei width, GLsizei height, GLenum format, GLsizei imageSize, '
+ 'const void* data', },
+{ 'return_type': 'void',
+ 'names': ['glCopyTexImage2D'],
+ 'arguments':
+ 'GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, '
+ 'GLsizei width, GLsizei height, GLint border', },
+{ 'return_type': 'void',
+ 'names': ['glCopyTexSubImage2D'],
+ 'arguments':
+ 'GLenum target, GLint level, GLint xoffset, '
+ 'GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height', },
+{ 'return_type': 'GLuint',
+ 'names': ['glCreateProgram'],
+ 'arguments': 'void', },
+{ 'return_type': 'GLuint',
+ 'names': ['glCreateShader'],
+ 'arguments': 'GLenum type', },
+{ 'return_type': 'void',
+ 'names': ['glCullFace'],
+ 'arguments': 'GLenum mode', },
+{ 'return_type': 'void',
+ 'names': ['glDeleteBuffersARB', 'glDeleteBuffers'],
+ 'arguments': 'GLsizei n, const GLuint* buffers', },
+{ 'return_type': 'void',
+ 'names': ['glDeleteFramebuffersEXT', 'glDeleteFramebuffers'],
+ 'arguments': 'GLsizei n, const GLuint* framebuffers', },
+{ 'return_type': 'void',
+ 'names': ['glDeleteProgram'],
+ 'arguments': 'GLuint program', },
+{ 'return_type': 'void',
+ 'names': ['glDeleteQueries'],
+ 'arguments': 'GLsizei n, const GLuint* ids', },
+{ 'return_type': 'void',
+ 'names': ['glDeleteQueriesARB', 'glDeleteQueriesEXT'],
+ 'arguments': 'GLsizei n, const GLuint* ids', },
+{ 'return_type': 'void',
+ 'names': ['glDeleteRenderbuffersEXT', 'glDeleteRenderbuffers'],
+ 'arguments': 'GLsizei n, const GLuint* renderbuffers', },
+{ 'return_type': 'void',
+ 'names': ['glDeleteShader'],
+ 'arguments': 'GLuint shader', },
+{ 'return_type': 'void',
+ 'names': ['glDeleteTextures'],
+ 'arguments': 'GLsizei n, const GLuint* textures', },
+{ 'return_type': 'void',
+ 'names': ['glDepthFunc'],
+ 'arguments': 'GLenum func', },
+{ 'return_type': 'void',
+ 'names': ['glDepthMask'],
+ 'arguments': 'GLboolean flag', },
+{ 'return_type': 'void',
+ 'names': ['glDepthRange'],
+ 'arguments': 'GLclampd zNear, GLclampd zFar', },
+{ 'return_type': 'void',
+ 'names': ['glDepthRangef'],
+ 'arguments': 'GLclampf zNear, GLclampf zFar', },
+{ 'return_type': 'void',
+ 'names': ['glDetachShader'],
+ 'arguments': 'GLuint program, GLuint shader', },
+{ 'return_type': 'void',
+ 'names': ['glDisable'],
+ 'arguments': 'GLenum cap', },
+{ 'return_type': 'void',
+ 'names': ['glDisableVertexAttribArray'],
+ 'arguments': 'GLuint index', },
+{ 'return_type': 'void',
+ 'names': ['glDrawArrays'],
+ 'arguments': 'GLenum mode, GLint first, GLsizei count', },
+{ 'return_type': 'void',
+ 'names': ['glDrawBuffer'],
+ 'arguments': 'GLenum mode', },
+{ 'return_type': 'void',
+ 'names': ['glDrawBuffersARB'],
+ 'arguments': 'GLsizei n, const GLenum* bufs', },
+{ 'return_type': 'void',
+ 'names': ['glDrawElements'],
+ 'arguments':
+ 'GLenum mode, GLsizei count, GLenum type, const void* indices', },
+{ 'return_type': 'void',
+ 'names': ['glEGLImageTargetTexture2DOES'],
+ 'arguments': 'GLenum target, GLeglImageOES image', },
+{ 'return_type': 'void',
+ 'names': ['glEGLImageTargetRenderbufferStorageOES'],
+ 'arguments': 'GLenum target, GLeglImageOES image', },
+{ 'return_type': 'void',
+ 'names': ['glEnable'],
+ 'arguments': 'GLenum cap', },
+{ 'return_type': 'void',
+ 'names': ['glEnableVertexAttribArray'],
+ 'arguments': 'GLuint index', },
+{ 'return_type': 'void',
+ 'names': ['glEndQuery'],
+ 'arguments': 'GLenum target', },
+{ 'return_type': 'void',
+ 'names': ['glEndQueryARB', 'glEndQueryEXT'],
+ 'arguments': 'GLenum target', },
+{ 'return_type': 'void',
+ 'names': ['glFinish'],
+ 'arguments': 'void', },
+{ 'return_type': 'void',
+ 'names': ['glFlush'],
+ 'arguments': 'void', },
+{ 'return_type': 'void',
+ 'names': ['glFramebufferRenderbufferEXT', 'glFramebufferRenderbuffer'],
+ 'arguments': \
+ 'GLenum target, GLenum attachment, GLenum renderbuffertarget, '
+ 'GLuint renderbuffer', },
+{ 'return_type': 'void',
+ 'names': ['glFramebufferTexture2DEXT', 'glFramebufferTexture2D'],
+ 'arguments':
+ 'GLenum target, GLenum attachment, GLenum textarget, GLuint texture, '
+ 'GLint level', },
+{ 'return_type': 'void',
+ 'names': ['glFrontFace'],
+ 'arguments': 'GLenum mode', },
+{ 'return_type': 'void',
+ 'names': ['glGenBuffersARB', 'glGenBuffers'],
+ 'arguments': 'GLsizei n, GLuint* buffers', },
+{ 'return_type': 'void',
+ 'names': ['glGenQueries'],
+ 'arguments': 'GLsizei n, GLuint* ids', },
+{ 'return_type': 'void',
+ 'names': ['glGenQueriesARB', 'glGenQueriesEXT'],
+ 'arguments': 'GLsizei n, GLuint* ids', },
+{ 'return_type': 'void',
+ 'names': ['glGenerateMipmapEXT', 'glGenerateMipmap'],
+ 'arguments': 'GLenum target', },
+{ 'return_type': 'void',
+ 'names': ['glGenFramebuffersEXT', 'glGenFramebuffers'],
+ 'arguments': 'GLsizei n, GLuint* framebuffers', },
+{ 'return_type': 'void',
+ 'names': ['glGenRenderbuffersEXT', 'glGenRenderbuffers'],
+ 'arguments': 'GLsizei n, GLuint* renderbuffers', },
+{ 'return_type': 'void',
+ 'names': ['glGenTextures'],
+ 'arguments': 'GLsizei n, GLuint* textures', },
+{ 'return_type': 'void',
+ 'names': ['glGetActiveAttrib'],
+ 'arguments':
+ 'GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, '
+ 'GLint* size, GLenum* type, char* name', },
+{ 'return_type': 'void',
+ 'names': ['glGetActiveUniform'],
+ 'arguments':
+ 'GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, '
+ 'GLint* size, GLenum* type, char* name', },
+{ 'return_type': 'void',
+ 'names': ['glGetAttachedShaders'],
+ 'arguments':
+ 'GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders', },
+{ 'return_type': 'GLint',
+ 'names': ['glGetAttribLocation'],
+ 'arguments': 'GLuint program, const char* name', },
+{ 'return_type': 'void',
+ 'names': ['glGetBooleanv'],
+ 'arguments': 'GLenum pname, GLboolean* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetBufferParameteriv'],
+ 'arguments': 'GLenum target, GLenum pname, GLint* params', },
+{ 'return_type': 'GLenum',
+ 'names': ['glGetError'],
+ 'arguments': 'void',
+ 'logging_code': """
+ GL_SERVICE_LOG("GL_RESULT: " << GLES2Util::GetStringError(result));
+""", },
+{ 'return_type': 'void',
+ 'names': ['glGetFloatv'],
+ 'arguments': 'GLenum pname, GLfloat* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetFramebufferAttachmentParameterivEXT',
+ 'glGetFramebufferAttachmentParameteriv'],
+ 'arguments': 'GLenum target, '
+ 'GLenum attachment, GLenum pname, GLint* params', },
+{ 'return_type': 'GLenum',
+ 'names': ['glGetGraphicsResetStatusARB'],
+ 'arguments': 'void', },
+{ 'return_type': 'void',
+ 'names': ['glGetIntegerv'],
+ 'arguments': 'GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetProgramiv'],
+ 'arguments': 'GLuint program, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetProgramInfoLog'],
+ 'arguments':
+ 'GLuint program, GLsizei bufsize, GLsizei* length, char* infolog', },
+{ 'return_type': 'void',
+ 'names': ['glGetQueryiv'],
+ 'arguments': 'GLenum target, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetQueryivARB', 'glGetQueryivEXT'],
+ 'arguments': 'GLenum target, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetQueryObjecti64v'],
+ 'arguments': 'GLuint id, GLenum pname, GLint64* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetQueryObjectiv'],
+ 'arguments': 'GLuint id, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetQueryObjectui64v'],
+ 'arguments': 'GLuint id, GLenum pname, GLuint64* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetQueryObjectuiv'],
+ 'arguments': 'GLuint id, GLenum pname, GLuint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetQueryObjectuivARB', 'glGetQueryObjectuivEXT'],
+ 'arguments': 'GLuint id, GLenum pname, GLuint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetRenderbufferParameterivEXT', 'glGetRenderbufferParameteriv'],
+ 'arguments': 'GLenum target, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetShaderiv'],
+ 'arguments': 'GLuint shader, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetShaderInfoLog'],
+ 'arguments':
+ 'GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog', },
+{ 'return_type': 'void',
+ 'names': ['glGetShaderPrecisionFormat'],
+ 'arguments': 'GLenum shadertype, GLenum precisiontype, '
+ 'GLint* range, GLint* precision', },
+{ 'return_type': 'void',
+ 'names': ['glGetShaderSource'],
+ 'arguments':
+ 'GLuint shader, GLsizei bufsize, GLsizei* length, char* source', },
+{ 'return_type': 'const GLubyte*',
+ 'names': ['glGetString'],
+ 'arguments': 'GLenum name', },
+{ 'return_type': 'void',
+ 'names': ['glGetTexLevelParameterfv'],
+ 'arguments': 'GLenum target, GLint level, GLenum pname, GLfloat* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetTexLevelParameteriv'],
+ 'arguments': 'GLenum target, GLint level, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetTexParameterfv'],
+ 'arguments': 'GLenum target, GLenum pname, GLfloat* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetTexParameteriv'],
+ 'arguments': 'GLenum target, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetTranslatedShaderSourceANGLE'],
+ 'arguments':
+ 'GLuint shader, GLsizei bufsize, GLsizei* length, char* source', },
+{ 'return_type': 'void',
+ 'names': ['glGetUniformfv'],
+ 'arguments': 'GLuint program, GLint location, GLfloat* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetUniformiv'],
+ 'arguments': 'GLuint program, GLint location, GLint* params', },
+{ 'return_type': 'GLint',
+ 'names': ['glGetUniformLocation'],
+ 'arguments': 'GLuint program, const char* name', },
+{ 'return_type': 'void',
+ 'names': ['glGetVertexAttribfv'],
+ 'arguments': 'GLuint index, GLenum pname, GLfloat* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetVertexAttribiv'],
+ 'arguments': 'GLuint index, GLenum pname, GLint* params', },
+{ 'return_type': 'void',
+ 'names': ['glGetVertexAttribPointerv'],
+ 'arguments': 'GLuint index, GLenum pname, void** pointer', },
+{ 'return_type': 'void',
+ 'names': ['glHint'],
+ 'arguments': 'GLenum target, GLenum mode', },
+{ 'return_type': 'GLboolean',
+ 'names': ['glIsBuffer'],
+ 'arguments': 'GLuint buffer', },
+{ 'return_type': 'GLboolean',
+ 'names': ['glIsEnabled'],
+ 'arguments': 'GLenum cap', },
+{ 'return_type': 'GLboolean',
+ 'names': ['glIsFramebufferEXT', 'glIsFramebuffer'],
+ 'arguments': 'GLuint framebuffer', },
+{ 'return_type': 'GLboolean',
+ 'names': ['glIsProgram'],
+ 'arguments': 'GLuint program', },
+{ 'return_type': 'GLboolean',
+ 'names': ['glIsQueryARB', 'glIsQueryEXT'],
+ 'arguments': 'GLuint query', },
+{ 'return_type': 'GLboolean',
+ 'names': ['glIsRenderbufferEXT', 'glIsRenderbuffer'],
+ 'arguments': 'GLuint renderbuffer', },
+{ 'return_type': 'GLboolean',
+ 'names': ['glIsShader'],
+ 'arguments': 'GLuint shader', },
+{ 'return_type': 'GLboolean',
+ 'names': ['glIsTexture'],
+ 'arguments': 'GLuint texture', },
+{ 'return_type': 'void',
+ 'names': ['glLineWidth'],
+ 'arguments': 'GLfloat width', },
+{ 'return_type': 'void',
+ 'names': ['glLinkProgram'],
+ 'arguments': 'GLuint program', },
+{ 'return_type': 'void*',
+ 'names': ['glMapBuffer', 'glMapBufferOES'],
+ 'arguments': 'GLenum target, GLenum access', },
+{ 'return_type': 'void',
+ 'names': ['glPixelStorei'],
+ 'arguments': 'GLenum pname, GLint param', },
+{ 'return_type': 'void',
+ 'names': ['glPolygonOffset'],
+ 'arguments': 'GLfloat factor, GLfloat units', },
+{ 'return_type': 'void',
+ 'names': ['glQueryCounter'],
+ 'arguments': 'GLuint id, GLenum target', },
+{ 'return_type': 'void',
+ 'names': ['glReadBuffer'],
+ 'arguments': 'GLenum src', },
+{ 'return_type': 'void',
+ 'names': ['glReadPixels'],
+ 'arguments':
+ 'GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, '
+ 'GLenum type, void* pixels', },
+{ 'return_type': 'void',
+ 'names': ['glReleaseShaderCompiler'],
+ 'arguments': 'void', },
+{ 'return_type': 'void',
+ 'names': ['glRenderbufferStorageMultisampleEXT',
+ 'glRenderbufferStorageMultisample'],
+ 'arguments': 'GLenum target, GLsizei samples, GLenum internalformat, '
+ 'GLsizei width, GLsizei height', },
+{ 'return_type': 'void',
+ 'names': ['glRenderbufferStorageMultisampleANGLE',
+ 'glRenderbufferStorageMultisample'],
+ 'arguments': 'GLenum target, GLsizei samples, GLenum internalformat, '
+ 'GLsizei width, GLsizei height', },
+{ 'return_type': 'void',
+ 'names': ['glRenderbufferStorageEXT', 'glRenderbufferStorage'],
+ 'arguments':
+ 'GLenum target, GLenum internalformat, GLsizei width, GLsizei height', },
+{ 'return_type': 'void',
+ 'names': ['glSampleCoverage'],
+ 'arguments': 'GLclampf value, GLboolean invert', },
+{ 'return_type': 'void',
+ 'names': ['glScissor'],
+ 'arguments': 'GLint x, GLint y, GLsizei width, GLsizei height', },
+{ 'return_type': 'void',
+ 'names': ['glShaderBinary'],
+ 'arguments': 'GLsizei n, const GLuint* shaders, GLenum binaryformat, '
+ 'const void* binary, GLsizei length', },
+{ 'return_type': 'void',
+ 'names': ['glShaderSource'],
+ 'arguments':
+ 'GLuint shader, GLsizei count, const char** str, const GLint* length',
+ 'logging_code': """
+ GL_SERVICE_LOG_CODE_BLOCK({
+ for (GLsizei ii = 0; ii < count; ++ii) {
+ if (str[ii]) {
+ if (length && length[ii] >= 0) {
+ std::string source(str[ii], length[ii]);
+ GL_SERVICE_LOG(" " << ii << ": ---\\n" << source << "\\n---");
+ } else {
+ GL_SERVICE_LOG(" " << ii << ": ---\\n" << str[ii] << "\\n---");
+ }
+ } else {
+ GL_SERVICE_LOG(" " << ii << ": NULL");
+ }
+ }
+ });
+""", },
+{ 'return_type': 'void',
+ 'names': ['glStencilFunc'],
+ 'arguments': 'GLenum func, GLint ref, GLuint mask', },
+{ 'return_type': 'void',
+ 'names': ['glStencilFuncSeparate'],
+ 'arguments': 'GLenum face, GLenum func, GLint ref, GLuint mask', },
+{ 'return_type': 'void',
+ 'names': ['glStencilMask'],
+ 'arguments': 'GLuint mask', },
+{ 'return_type': 'void',
+ 'names': ['glStencilMaskSeparate'],
+ 'arguments': 'GLenum face, GLuint mask', },
+{ 'return_type': 'void',
+ 'names': ['glStencilOp'],
+ 'arguments': 'GLenum fail, GLenum zfail, GLenum zpass', },
+{ 'return_type': 'void',
+ 'names': ['glStencilOpSeparate'],
+ 'arguments': 'GLenum face, GLenum fail, GLenum zfail, GLenum zpass', },
+{ 'return_type': 'void',
+ 'names': ['glTexImage2D'],
+ 'arguments':
+ 'GLenum target, GLint level, GLint internalformat, GLsizei width, '
+ 'GLsizei height, GLint border, GLenum format, GLenum type, '
+ 'const void* pixels', },
+{ 'return_type': 'void',
+ 'names': ['glTexParameterf'],
+ 'arguments': 'GLenum target, GLenum pname, GLfloat param', },
+{ 'return_type': 'void',
+ 'names': ['glTexParameterfv'],
+ 'arguments': 'GLenum target, GLenum pname, const GLfloat* params', },
+{ 'return_type': 'void',
+ 'names': ['glTexParameteri'],
+ 'arguments': 'GLenum target, GLenum pname, GLint param', },
+{ 'return_type': 'void',
+ 'names': ['glTexParameteriv'],
+ 'arguments': 'GLenum target, GLenum pname, const GLint* params', },
+{ 'return_type': 'void',
+ 'names': ['glTexStorage2DEXT'],
+ 'arguments': 'GLenum target, GLsizei levels, GLenum internalformat, '
+ 'GLsizei width, GLsizei height', },
+{ 'return_type': 'void',
+ 'names': ['glTexSubImage2D'],
+ 'arguments':
+ 'GLenum target, GLint level, GLint xoffset, GLint yoffset, '
+ 'GLsizei width, GLsizei height, GLenum format, GLenum type, '
+ 'const void* pixels', },
+{ 'return_type': 'void',
+ 'names': ['glUniform1f'],
+ 'arguments': 'GLint location, GLfloat x', },
+{ 'return_type': 'void',
+ 'names': ['glUniform1fv'],
+ 'arguments': 'GLint location, GLsizei count, const GLfloat* v', },
+{ 'return_type': 'void',
+ 'names': ['glUniform1i'],
+ 'arguments': 'GLint location, GLint x', },
+{ 'return_type': 'void',
+ 'names': ['glUniform1iv'],
+ 'arguments': 'GLint location, GLsizei count, const GLint* v', },
+{ 'return_type': 'void',
+ 'names': ['glUniform2f'],
+ 'arguments': 'GLint location, GLfloat x, GLfloat y', },
+{ 'return_type': 'void',
+ 'names': ['glUniform2fv'],
+ 'arguments': 'GLint location, GLsizei count, const GLfloat* v', },
+{ 'return_type': 'void',
+ 'names': ['glUniform2i'],
+ 'arguments': 'GLint location, GLint x, GLint y', },
+{ 'return_type': 'void',
+ 'names': ['glUniform2iv'],
+ 'arguments': 'GLint location, GLsizei count, const GLint* v', },
+{ 'return_type': 'void',
+ 'names': ['glUniform3f'],
+ 'arguments': 'GLint location, GLfloat x, GLfloat y, GLfloat z', },
+{ 'return_type': 'void',
+ 'names': ['glUniform3fv'],
+ 'arguments': 'GLint location, GLsizei count, const GLfloat* v', },
+{ 'return_type': 'void',
+ 'names': ['glUniform3i'],
+ 'arguments': 'GLint location, GLint x, GLint y, GLint z', },
+{ 'return_type': 'void',
+ 'names': ['glUniform3iv'],
+ 'arguments': 'GLint location, GLsizei count, const GLint* v', },
+{ 'return_type': 'void',
+ 'names': ['glUniform4f'],
+ 'arguments': 'GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w', },
+{ 'return_type': 'void',
+ 'names': ['glUniform4fv'],
+ 'arguments': 'GLint location, GLsizei count, const GLfloat* v', },
+{ 'return_type': 'void',
+ 'names': ['glUniform4i'],
+ 'arguments': 'GLint location, GLint x, GLint y, GLint z, GLint w', },
+{ 'return_type': 'void',
+ 'names': ['glUniform4iv'],
+ 'arguments': 'GLint location, GLsizei count, const GLint* v', },
+{ 'return_type': 'void',
+ 'names': ['glUniformMatrix2fv'],
+ 'arguments': 'GLint location, GLsizei count, '
+ 'GLboolean transpose, const GLfloat* value', },
+{ 'return_type': 'void',
+ 'names': ['glUniformMatrix3fv'],
+ 'arguments': 'GLint location, GLsizei count, '
+ 'GLboolean transpose, const GLfloat* value', },
+{ 'return_type': 'void',
+ 'names': ['glUniformMatrix4fv'],
+ 'arguments': 'GLint location, GLsizei count, '
+ 'GLboolean transpose, const GLfloat* value', },
+{ 'return_type': 'GLboolean',
+ 'names': ['glUnmapBuffer', 'glUnmapBufferOES'],
+ 'arguments': 'GLenum target', },
+{ 'return_type': 'void',
+ 'names': ['glUseProgram'],
+ 'arguments': 'GLuint program', },
+{ 'return_type': 'void',
+ 'names': ['glValidateProgram'],
+ 'arguments': 'GLuint program', },
+{ 'return_type': 'void',
+ 'names': ['glVertexAttrib1f'],
+ 'arguments': 'GLuint indx, GLfloat x', },
+{ 'return_type': 'void',
+ 'names': ['glVertexAttrib1fv'],
+ 'arguments': 'GLuint indx, const GLfloat* values', },
+{ 'return_type': 'void',
+ 'names': ['glVertexAttrib2f'],
+ 'arguments': 'GLuint indx, GLfloat x, GLfloat y', },
+{ 'return_type': 'void',
+ 'names': ['glVertexAttrib2fv'],
+ 'arguments': 'GLuint indx, const GLfloat* values', },
+{ 'return_type': 'void',
+ 'names': ['glVertexAttrib3f'],
+ 'arguments': 'GLuint indx, GLfloat x, GLfloat y, GLfloat z', },
+{ 'return_type': 'void',
+ 'names': ['glVertexAttrib3fv'],
+ 'arguments': 'GLuint indx, const GLfloat* values', },
+{ 'return_type': 'void',
+ 'names': ['glVertexAttrib4f'],
+ 'arguments': 'GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w', },
+{ 'return_type': 'void',
+ 'names': ['glVertexAttrib4fv'],
+ 'arguments': 'GLuint indx, const GLfloat* values', },
+{ 'return_type': 'void',
+ 'names': ['glVertexAttribPointer'],
+ 'arguments': 'GLuint indx, GLint size, GLenum type, GLboolean normalized, '
+ 'GLsizei stride, const void* ptr', },
+{ 'return_type': 'void',
+ 'names': ['glViewport'],
+ 'arguments': 'GLint x, GLint y, GLsizei width, GLsizei height', },
+{ 'return_type': 'void',
+ 'names': ['glGenFencesNV'],
+ 'arguments': 'GLsizei n, GLuint* fences', },
+{ 'return_type': 'void',
+ 'names': ['glDeleteFencesNV'],
+ 'arguments': 'GLsizei n, const GLuint* fences', },
+{ 'return_type': 'void',
+ 'names': ['glSetFenceNV'],
+ 'arguments': 'GLuint fence, GLenum condition', },
+{ 'return_type': 'GLboolean',
+ 'names': ['glTestFenceNV'],
+ 'arguments': 'GLuint fence', },
+{ 'return_type': 'void',
+ 'names': ['glFinishFenceNV'],
+ 'arguments': 'GLuint fence', },
+{ 'return_type': 'GLboolean',
+ 'names': ['glIsFenceNV'],
+ 'arguments': 'GLuint fence', },
+{ 'return_type': 'void',
+ 'names': ['glGetFenceivNV'],
+ 'arguments': 'GLuint fence, GLenum pname, GLint* params', },
+{ 'return_type': 'GLsync',
+ 'names': ['glFenceSync'],
+ 'arguments': 'GLenum condition, GLbitfield flags', },
+{ 'return_type': 'void',
+ 'names': ['glDeleteSync'],
+ 'arguments': 'GLsync sync', },
+{ 'return_type': 'void',
+ 'names': ['glGetSynciv'],
+ 'arguments':
+ 'GLsync sync, GLenum pname, GLsizei bufSize, GLsizei* length,'
+ 'GLint* values', },
+{ 'return_type': 'void',
+ 'names': ['glDrawArraysInstancedANGLE', 'glDrawArraysInstancedARB'],
+ 'arguments': 'GLenum mode, GLint first, GLsizei count, GLsizei primcount', },
+{ 'return_type': 'void',
+ 'names': ['glDrawElementsInstancedANGLE', 'glDrawElementsInstancedARB'],
+ 'arguments':
+ 'GLenum mode, GLsizei count, GLenum type, const void* indices, '
+ 'GLsizei primcount', },
+{ 'return_type': 'void',
+ 'names': ['glVertexAttribDivisorANGLE', 'glVertexAttribDivisorARB'],
+ 'arguments':
+ 'GLuint index, GLuint divisor', },
+]
+
+OSMESA_FUNCTIONS = [
+{ 'return_type': 'OSMesaContext',
+ 'names': ['OSMesaCreateContext'],
+ 'arguments': 'GLenum format, OSMesaContext sharelist', },
+{ 'return_type': 'OSMesaContext',
+ 'names': ['OSMesaCreateContextExt'],
+ 'arguments':
+ 'GLenum format, GLint depthBits, GLint stencilBits, GLint accumBits, '
+ 'OSMesaContext sharelist', },
+{ 'return_type': 'void',
+ 'names': ['OSMesaDestroyContext'],
+ 'arguments': 'OSMesaContext ctx', },
+{ 'return_type': 'GLboolean',
+ 'names': ['OSMesaMakeCurrent'],
+ 'arguments': 'OSMesaContext ctx, void* buffer, GLenum type, GLsizei width, '
+ 'GLsizei height', },
+{ 'return_type': 'OSMesaContext',
+ 'names': ['OSMesaGetCurrentContext'],
+ 'arguments': 'void', },
+{ 'return_type': 'void',
+ 'names': ['OSMesaPixelStore'],
+ 'arguments': 'GLint pname, GLint value', },
+{ 'return_type': 'void',
+ 'names': ['OSMesaGetIntegerv'],
+ 'arguments': 'GLint pname, GLint* value', },
+{ 'return_type': 'GLboolean',
+ 'names': ['OSMesaGetDepthBuffer'],
+ 'arguments':
+ 'OSMesaContext c, GLint* width, GLint* height, GLint* bytesPerValue, '
+ 'void** buffer', },
+{ 'return_type': 'GLboolean',
+ 'names': ['OSMesaGetColorBuffer'],
+ 'arguments': 'OSMesaContext c, GLint* width, GLint* height, GLint* format, '
+ 'void** buffer', },
+{ 'return_type': 'OSMESAproc',
+ 'names': ['OSMesaGetProcAddress'],
+ 'arguments': 'const char* funcName', },
+{ 'return_type': 'void',
+ 'names': ['OSMesaColorClamp'],
+ 'arguments': 'GLboolean enable', },
+]
+
+EGL_FUNCTIONS = [
+{ 'return_type': 'EGLint',
+ 'names': ['eglGetError'],
+ 'arguments': 'void', },
+{ 'return_type': 'EGLDisplay',
+ 'names': ['eglGetDisplay'],
+ 'arguments': 'EGLNativeDisplayType display_id', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglInitialize'],
+ 'arguments': 'EGLDisplay dpy, EGLint* major, EGLint* minor', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglTerminate'],
+ 'arguments': 'EGLDisplay dpy', },
+{ 'return_type': 'const char*',
+ 'names': ['eglQueryString'],
+ 'arguments': 'EGLDisplay dpy, EGLint name', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglGetConfigs'],
+ 'arguments': 'EGLDisplay dpy, EGLConfig* configs, EGLint config_size, '
+ 'EGLint* num_config', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglChooseConfig'],
+ 'arguments': 'EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, '
+ 'EGLint config_size, EGLint* num_config', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglGetConfigAttrib'],
+ 'arguments':
+ 'EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value', },
+{ 'return_type': 'EGLImageKHR',
+ 'names': ['eglCreateImageKHR'],
+ 'arguments':
+ 'EGLDisplay dpy, EGLContext ctx, EGLenum target, EGLClientBuffer buffer, '
+ 'const EGLint* attrib_list',
+ 'other_extensions': ['EGL_KHR_image_base'] },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglDestroyImageKHR'],
+ 'arguments': 'EGLDisplay dpy, EGLImageKHR image',
+ 'other_extensions': ['EGL_KHR_image_base'] },
+{ 'return_type': 'EGLSurface',
+ 'names': ['eglCreateWindowSurface'],
+ 'arguments': 'EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, '
+ 'const EGLint* attrib_list', },
+{ 'return_type': 'EGLSurface',
+ 'names': ['eglCreatePbufferSurface'],
+ 'arguments': 'EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list', },
+{ 'return_type': 'EGLSurface',
+ 'names': ['eglCreatePixmapSurface'],
+ 'arguments': 'EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, '
+ 'const EGLint* attrib_list', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglDestroySurface'],
+ 'arguments': 'EGLDisplay dpy, EGLSurface surface', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglQuerySurface'],
+ 'arguments':
+ 'EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglBindAPI'],
+ 'arguments': 'EGLenum api', },
+{ 'return_type': 'EGLenum',
+ 'names': ['eglQueryAPI'],
+ 'arguments': 'void', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglWaitClient'],
+ 'arguments': 'void', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglReleaseThread'],
+ 'arguments': 'void', },
+{ 'return_type': 'EGLSurface',
+ 'names': ['eglCreatePbufferFromClientBuffer'],
+ 'arguments':
+ 'EGLDisplay dpy, EGLenum buftype, void* buffer, EGLConfig config, '
+ 'const EGLint* attrib_list', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglSurfaceAttrib'],
+ 'arguments':
+ 'EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglBindTexImage'],
+ 'arguments': 'EGLDisplay dpy, EGLSurface surface, EGLint buffer', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglReleaseTexImage'],
+ 'arguments': 'EGLDisplay dpy, EGLSurface surface, EGLint buffer', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglSwapInterval'],
+ 'arguments': 'EGLDisplay dpy, EGLint interval', },
+{ 'return_type': 'EGLContext',
+ 'names': ['eglCreateContext'],
+ 'arguments': 'EGLDisplay dpy, EGLConfig config, EGLContext share_context, '
+ 'const EGLint* attrib_list', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglDestroyContext'],
+ 'arguments': 'EGLDisplay dpy, EGLContext ctx', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglMakeCurrent'],
+ 'arguments':
+ 'EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx', },
+{ 'return_type': 'EGLContext',
+ 'names': ['eglGetCurrentContext'],
+ 'arguments': 'void', },
+{ 'return_type': 'EGLSurface',
+ 'names': ['eglGetCurrentSurface'],
+ 'arguments': 'EGLint readdraw', },
+{ 'return_type': 'EGLDisplay',
+ 'names': ['eglGetCurrentDisplay'],
+ 'arguments': 'void', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglQueryContext'],
+ 'arguments':
+ 'EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglWaitGL'],
+ 'arguments': 'void', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglWaitNative'],
+ 'arguments': 'EGLint engine', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglSwapBuffers'],
+ 'arguments': 'EGLDisplay dpy, EGLSurface surface', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglCopyBuffers'],
+ 'arguments':
+ 'EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target', },
+{ 'return_type': '__eglMustCastToProperFunctionPointerType',
+ 'names': ['eglGetProcAddress'],
+ 'arguments': 'const char* procname', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglPostSubBufferNV'],
+ 'arguments': 'EGLDisplay dpy, EGLSurface surface, '
+ 'EGLint x, EGLint y, EGLint width, EGLint height', },
+{ 'return_type': 'EGLBoolean',
+ 'names': ['eglQuerySurfacePointerANGLE'],
+ 'arguments':
+ 'EGLDisplay dpy, EGLSurface surface, EGLint attribute, void** value', },
+]
+
+WGL_FUNCTIONS = [
+{ 'return_type': 'HGLRC',
+ 'names': ['wglCreateContext'],
+ 'arguments': 'HDC hdc', },
+{ 'return_type': 'HGLRC',
+ 'names': ['wglCreateLayerContext'],
+ 'arguments': 'HDC hdc, int iLayerPlane', },
+{ 'return_type': 'BOOL',
+ 'names': ['wglCopyContext'],
+ 'arguments': 'HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask', },
+{ 'return_type': 'BOOL',
+ 'names': ['wglDeleteContext'],
+ 'arguments': 'HGLRC hglrc', },
+{ 'return_type': 'HGLRC',
+ 'names': ['wglGetCurrentContext'],
+ 'arguments': '', },
+{ 'return_type': 'HDC',
+ 'names': ['wglGetCurrentDC'],
+ 'arguments': '', },
+{ 'return_type': 'BOOL',
+ 'names': ['wglMakeCurrent'],
+ 'arguments': 'HDC hdc, HGLRC hglrc', },
+{ 'return_type': 'BOOL',
+ 'names': ['wglShareLists'],
+ 'arguments': 'HGLRC hglrc1, HGLRC hglrc2', },
+{ 'return_type': 'BOOL',
+ 'names': ['wglSwapIntervalEXT'],
+ 'arguments': 'int interval', },
+{ 'return_type': 'BOOL',
+ 'names': ['wglSwapLayerBuffers'],
+ 'arguments': 'HDC hdc, UINT fuPlanes', },
+{ 'return_type': 'const char*',
+ 'names': ['wglGetExtensionsStringARB'],
+ 'arguments': 'HDC hDC', },
+{ 'return_type': 'const char*',
+ 'names': ['wglGetExtensionsStringEXT'],
+ 'arguments': '', },
+{ 'return_type': 'BOOL',
+ 'names': ['wglChoosePixelFormatARB'],
+ 'arguments':
+ 'HDC dc, const int* int_attrib_list, const float* float_attrib_list, '
+ 'UINT max_formats, int* formats, UINT* num_formats', },
+{ 'return_type': 'HPBUFFERARB',
+ 'names': ['wglCreatePbufferARB'],
+ 'arguments': 'HDC hDC, int iPixelFormat, int iWidth, int iHeight, '
+ 'const int* piAttribList', },
+{ 'return_type': 'HDC',
+ 'names': ['wglGetPbufferDCARB'],
+ 'arguments': 'HPBUFFERARB hPbuffer', },
+{ 'return_type': 'int',
+ 'names': ['wglReleasePbufferDCARB'],
+ 'arguments': 'HPBUFFERARB hPbuffer, HDC hDC', },
+{ 'return_type': 'BOOL',
+ 'names': ['wglDestroyPbufferARB'],
+ 'arguments': 'HPBUFFERARB hPbuffer', },
+{ 'return_type': 'BOOL',
+ 'names': ['wglQueryPbufferARB'],
+ 'arguments': 'HPBUFFERARB hPbuffer, int iAttribute, int* piValue', },
+]
+
+GLX_FUNCTIONS = [
+{ 'return_type': 'XVisualInfo*',
+ 'names': ['glXChooseVisual'],
+ 'arguments': 'Display* dpy, int screen, int* attribList', },
+{ 'return_type': 'void',
+ 'names': ['glXCopySubBufferMESA'],
+ 'arguments': 'Display* dpy, GLXDrawable drawable, '
+ 'int x, int y, int width, int height', },
+{ 'return_type': 'GLXContext',
+ 'names': ['glXCreateContext'],
+ 'arguments':
+ 'Display* dpy, XVisualInfo* vis, GLXContext shareList, int direct', },
+{ 'return_type': 'void',
+ 'names': ['glXBindTexImageEXT'],
+ 'arguments':
+ 'Display* dpy, GLXDrawable drawable, int buffer, int* attribList', },
+{ 'return_type': 'void',
+ 'names': ['glXReleaseTexImageEXT'],
+ 'arguments': 'Display* dpy, GLXDrawable drawable, int buffer', },
+{ 'return_type': 'void',
+ 'names': ['glXDestroyContext'],
+ 'arguments': 'Display* dpy, GLXContext ctx', },
+{ 'return_type': 'int',
+ 'names': ['glXMakeCurrent'],
+ 'arguments': 'Display* dpy, GLXDrawable drawable, GLXContext ctx', },
+{ 'return_type': 'void',
+ 'names': ['glXCopyContext'],
+ 'arguments':
+ 'Display* dpy, GLXContext src, GLXContext dst, unsigned long mask', },
+{ 'return_type': 'void',
+ 'names': ['glXSwapBuffers'],
+ 'arguments': 'Display* dpy, GLXDrawable drawable', },
+{ 'return_type': 'GLXPixmap',
+ 'names': ['glXCreateGLXPixmap'],
+ 'arguments': 'Display* dpy, XVisualInfo* visual, Pixmap pixmap', },
+{ 'return_type': 'void',
+ 'names': ['glXDestroyGLXPixmap'],
+ 'arguments': 'Display* dpy, GLXPixmap pixmap', },
+{ 'return_type': 'int',
+ 'names': ['glXQueryExtension'],
+ 'arguments': 'Display* dpy, int* errorb, int* event', },
+{ 'return_type': 'int',
+ 'names': ['glXQueryVersion'],
+ 'arguments': 'Display* dpy, int* maj, int* min', },
+{ 'return_type': 'int',
+ 'names': ['glXIsDirect'],
+ 'arguments': 'Display* dpy, GLXContext ctx', },
+{ 'return_type': 'int',
+ 'names': ['glXGetConfig'],
+ 'arguments': 'Display* dpy, XVisualInfo* visual, int attrib, int* value', },
+{ 'return_type': 'GLXContext',
+ 'names': ['glXGetCurrentContext'],
+ 'arguments': 'void', },
+{ 'return_type': 'GLXDrawable',
+ 'names': ['glXGetCurrentDrawable'],
+ 'arguments': 'void', },
+{ 'return_type': 'void',
+ 'names': ['glXWaitGL'],
+ 'arguments': 'void', },
+{ 'return_type': 'void',
+ 'names': ['glXWaitX'],
+ 'arguments': 'void', },
+{ 'return_type': 'void',
+ 'names': ['glXUseXFont'],
+ 'arguments': 'Font font, int first, int count, int list', },
+{ 'return_type': 'const char*',
+ 'names': ['glXQueryExtensionsString'],
+ 'arguments': 'Display* dpy, int screen', },
+{ 'return_type': 'const char*',
+ 'names': ['glXQueryServerString'],
+ 'arguments': 'Display* dpy, int screen, int name', },
+{ 'return_type': 'const char*',
+ 'names': ['glXGetClientString'],
+ 'arguments': 'Display* dpy, int name', },
+{ 'return_type': 'Display*',
+ 'names': ['glXGetCurrentDisplay'],
+ 'arguments': 'void', },
+{ 'return_type': 'GLXFBConfig*',
+ 'names': ['glXChooseFBConfig'],
+ 'arguments':
+ 'Display* dpy, int screen, const int* attribList, int* nitems', },
+{ 'return_type': 'int',
+ 'names': ['glXGetFBConfigAttrib'],
+ 'arguments': 'Display* dpy, GLXFBConfig config, int attribute, int* value', },
+{ 'return_type': 'GLXFBConfig*',
+ 'names': ['glXGetFBConfigs'],
+ 'arguments': 'Display* dpy, int screen, int* nelements', },
+{ 'return_type': 'XVisualInfo*',
+ 'names': ['glXGetVisualFromFBConfig'],
+ 'arguments': 'Display* dpy, GLXFBConfig config', },
+{ 'return_type': 'GLXWindow',
+ 'names': ['glXCreateWindow'],
+ 'arguments':
+ 'Display* dpy, GLXFBConfig config, Window win, const int* attribList', },
+{ 'return_type': 'void',
+ 'names': ['glXDestroyWindow'],
+ 'arguments': 'Display* dpy, GLXWindow window', },
+{ 'return_type': 'GLXPixmap',
+ 'names': ['glXCreatePixmap'],
+ 'arguments': 'Display* dpy, GLXFBConfig config, '
+ 'Pixmap pixmap, const int* attribList', },
+{ 'return_type': 'void',
+ 'names': ['glXDestroyPixmap'],
+ 'arguments': 'Display* dpy, GLXPixmap pixmap', },
+{ 'return_type': 'GLXPbuffer',
+ 'names': ['glXCreatePbuffer'],
+ 'arguments': 'Display* dpy, GLXFBConfig config, const int* attribList', },
+{ 'return_type': 'void',
+ 'names': ['glXDestroyPbuffer'],
+ 'arguments': 'Display* dpy, GLXPbuffer pbuf', },
+{ 'return_type': 'void',
+ 'names': ['glXQueryDrawable'],
+ 'arguments':
+ 'Display* dpy, GLXDrawable draw, int attribute, unsigned int* value', },
+{ 'return_type': 'GLXContext',
+ 'names': ['glXCreateNewContext'],
+ 'arguments': 'Display* dpy, GLXFBConfig config, int renderType, '
+ 'GLXContext shareList, int direct', },
+{ 'return_type': 'int',
+ 'names': ['glXMakeContextCurrent'],
+ 'arguments':
+ 'Display* dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx', },
+{ 'return_type': 'GLXDrawable',
+ 'names': ['glXGetCurrentReadDrawable'],
+ 'arguments': 'void', },
+{ 'return_type': 'int',
+ 'names': ['glXQueryContext'],
+ 'arguments': 'Display* dpy, GLXContext ctx, int attribute, int* value', },
+{ 'return_type': 'void',
+ 'names': ['glXSelectEvent'],
+ 'arguments': 'Display* dpy, GLXDrawable drawable, unsigned long mask', },
+{ 'return_type': 'void',
+ 'names': ['glXGetSelectedEvent'],
+ 'arguments': 'Display* dpy, GLXDrawable drawable, unsigned long* mask', },
+{ 'return_type': 'void',
+ 'names': ['glXSwapIntervalEXT'],
+ 'arguments': 'Display* dpy, GLXDrawable drawable, int interval', },
+{ 'return_type': 'GLXFBConfig',
+ 'names': ['glXGetFBConfigFromVisualSGIX'],
+ 'arguments': 'Display* dpy, XVisualInfo* visualInfo', },
+{ 'return_type': 'GLXContext',
+ 'names': ['glXCreateContextAttribsARB'],
+ 'arguments':
+ 'Display* dpy, GLXFBConfig config, GLXContext share_context, int direct, '
+ 'const int* attrib_list', },
+]
+
+FUNCTION_SETS = [
+ [GL_FUNCTIONS, 'gl', ['../../third_party/mesa/MesaLib/include/GL/glext.h',
+ '../../third_party/khronos/GLES2/gl2ext.h'], []],
+ [OSMESA_FUNCTIONS, 'osmesa', [], []],
+ [EGL_FUNCTIONS, 'egl', ['../../third_party/khronos/EGL/eglext.h'],
+ [
+ 'EGL_ANGLE_d3d_share_handle_client_buffer',
+ ],
+ ],
+ [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, used_extension_functions):
+ """Generates gl_binding_autogen_x.h"""
+
+ # Write file header.
+ file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n')
+ file.write('// Use of this source code is governed by a BSD-style license that can be\n')
+ file.write('// found in the LICENSE file.\n')
+ file.write('\n')
+ file.write('// This file is automatically generated.\n')
+ file.write('\n')
+ file.write('#ifndef UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % set_name.upper())
+ file.write('#define UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % set_name.upper())
+
+ # Write prototype for initialization function.
+ 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())
+ file.write('void ClearGLBindings%s();\n' % set_name.upper())
+
+ # Write typedefs for function pointer types. Always use the GL name for the
+ # typedef.
+ 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']))
+
+ # Write declarations for booleans indicating which extensions are available.
+ file.write('\n')
+ for extension, ext_functions in used_extension_functions:
+ file.write('GL_EXPORT extern bool g_%s;\n' % extension)
+
+ # Write declarations for function pointers. Always use the GL name for the
+ # declaration.
+ file.write('\n')
+ for func in functions:
+ file.write('GL_EXPORT extern %sProc g_%s;\n' %
+ (func['names'][0], func['names'][0]))
+ file.write('\n')
+ file.write( '} // namespace gfx\n')
+
+ # Write macros to invoke function pointers. Always use the GL name for the
+ # macro.
+ file.write('\n')
+ for func in functions:
+ file.write('#define %s ::gfx::g_%s\n' %
+ (func['names'][0], func['names'][0]))
+
+ file.write('\n')
+ file.write('#endif // UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' %
+ set_name.upper())
+
+
+def GenerateSource(file, functions, set_name, used_extension_functions):
+ """Generates gl_binding_autogen_x.cc"""
+
+ # Write file header.
+ file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n')
+ file.write('// Use of this source code is governed by a BSD-style license that can be\n')
+ file.write('// found in the LICENSE file.\n')
+ file.write('\n')
+ file.write('// This file is automatically generated.\n')
+ file.write('\n')
+ file.write('#include <string>\n')
+ file.write('#include "gpu/command_buffer/common/gles2_cmd_utils.h"\n')
+ file.write('#include "ui/gl/gl_bindings.h"\n')
+ file.write('#include "ui/gl/gl_context.h"\n')
+ file.write('#include "ui/gl/gl_implementation.h"\n')
+
+ # Write definitions for booleans indicating which extensions are available.
+ file.write('\n')
+ file.write('using gpu::gles2::GLES2Util;\n')
+ file.write('\n')
+ file.write('namespace gfx {\n')
+ file.write('\n')
+ for extension, ext_functions in used_extension_functions:
+ file.write('bool g_%s;\n' % extension)
+
+ # Write definitions of function pointers.
+ file.write('\n')
+ file.write('static bool g_debugBindingsInitialized;\n')
+ file.write('static void UpdateDebugGLExtensionBindings();\n')
+ file.write('\n')
+ for func in functions:
+ file.write('%sProc g_%s;\n' % (func['names'][0], func['names'][0]))
+
+ file.write('\n')
+ for func in functions:
+ file.write('static %sProc g_debug_%s;\n' %
+ (func['names'][0], func['names'][0]))
+
+ # 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 func in functions:
+ first_name = func['names'][0]
+ for i, name in enumerate(func['names']):
+ if i:
+ file.write(' if (!g_%s)\n ' % first_name)
+ file.write(
+ ' g_%s = reinterpret_cast<%sProc>(GetGLCoreProcAddress("%s"));\n' %
+ (first_name, first_name, 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(' g_%s = context->HasExtension("%s");\n' %
+ (extension, extension))
+ file.write(' if (g_%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 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))
+ 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)
+ log_argument_names = re.sub(
+ r'const char\* ([a-zA-Z0-9_]+)', r'CONSTCHAR_\1', arguments)
+ log_argument_names = re.sub(
+ r'(const )?[a-zA-Z0-9_]+\* ([a-zA-Z0-9_]+)',
+ r'CONSTVOID_\2', log_argument_names)
+ log_argument_names = re.sub(
+ r'(?<!E)GLenum ([a-zA-Z0-9_]+)', r'GLenum_\1', log_argument_names)
+ log_argument_names = re.sub(
+ r'(?<!E)GLboolean ([a-zA-Z0-9_]+)', r'GLboolean_\1', log_argument_names)
+ log_argument_names = re.sub(
+ r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2',
+ log_argument_names)
+ log_argument_names = re.sub(
+ r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2',
+ log_argument_names)
+ log_argument_names = re.sub(
+ r'CONSTVOID_([a-zA-Z0-9_]+)',
+ 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);
+ log_argument_names = re.sub(
+ r'GLenum_([a-zA-Z0-9_]+)', r'GLES2Util::GetStringEnum(\1)',
+ log_argument_names)
+ log_argument_names = re.sub(
+ r'GLboolean_([a-zA-Z0-9_]+)', r'GLES2Util::GetStringBool(\1)',
+ log_argument_names)
+ log_argument_names = log_argument_names.replace(',', ' << ", " <<')
+ if argument_names == 'void' or argument_names == '':
+ argument_names = ''
+ log_argument_names = ''
+ else:
+ log_argument_names = " << " + log_argument_names
+ function_name = names[0]
+ if return_type == 'void':
+ file.write(' GL_SERVICE_LOG("%s" << "(" %s << ")");\n' %
+ (function_name, log_argument_names))
+ file.write(' g_debug_%s(%s);\n' %
+ (function_name, argument_names))
+ if 'logging_code' in func:
+ file.write("%s\n" % func['logging_code'])
+ else:
+ file.write(' GL_SERVICE_LOG("%s" << "(" %s << ")");\n' %
+ (function_name, log_argument_names))
+ file.write(' %s result = g_debug_%s(%s);\n' %
+ (return_type, function_name, argument_names))
+ if 'logging_code' in func:
+ file.write("%s\n" % func['logging_code'])
+ else:
+ file.write(' GL_SERVICE_LOG("GL_RESULT: " << result);\n');
+ file.write(' return result;\n')
+ file.write('}\n')
+ file.write('} // extern "C"\n')
+
+ # Write function to initialize the debug function pointers.
+ file.write('\n')
+ file.write('void InitializeDebugGLBindings%s() {\n' % set_name.upper())
+ for func in functions:
+ first_name = func['names'][0]
+ file.write(' if (!g_debug_%s) {\n' % first_name)
+ file.write(' g_debug_%s = g_%s;\n' % (first_name, first_name))
+ file.write(' g_%s = Debug_%s;\n' % (first_name, first_name))
+ 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')
+
+ # Write function to clear all function pointers.
+ file.write('\n')
+ file.write('void ClearGLBindings%s() {\n' % set_name.upper())
+ # Clear the availability of GL extensions.
+ for extension, ext_functions in used_extension_functions:
+ file.write(' g_%s = false;\n' % extension)
+ # Clear GL bindings.
+ file.write('\n')
+ for func in functions:
+ file.write(' g_%s = NULL;\n' % func['names'][0])
+ # Clear debug GL bindings.
+ file.write('\n')
+ for func in functions:
+ file.write(' g_debug_%s = NULL;\n' % func['names'][0])
+ file.write(' g_debugBindingsInitialized = false;\n')
+ file.write('}\n')
+
+ file.write('\n')
+ file.write('} // namespace gfx\n')
+
+
+def GenerateMockSource(file, functions):
+ """Generates functions that invoke a mock GLInterface"""
+
+ file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n')
+ file.write('// Use of this source code is governed by a BSD-style license that can be\n')
+ file.write('// found in the LICENSE file.\n')
+ file.write('\n')
+ file.write('// This file is automatically generated.\n')
+ file.write('\n')
+ file.write('#include <string.h>\n')
+ file.write('\n')
+ file.write('#include "ui/gl/gl_interface.h"\n')
+
+ file.write('\n')
+ file.write('namespace gfx {\n')
+
+ # Write function that trampoline into the GLInterface.
+ 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]+\** ([a-zA-Z0-9]+)', r'\2',
+ func['arguments'])
+ if argument_names == 'void':
+ argument_names = ''
+ function_name = func['names'][0][2:]
+ if func['return_type'] == 'void':
+ file.write(' GLInterface::GetGLInterface()->%s(%s);\n' %
+ (function_name, argument_names))
+ else:
+ file.write(' return GLInterface::GetGLInterface()->%s(%s);\n' %
+ (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 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)
+ # 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_extensions = {}
+ for extension, functions in extensions.items():
+ for function in functions:
+ if not function in function_to_extensions:
+ function_to_extensions[function] = []
+ function_to_extensions[function].append(extension)
+ return function_to_extensions
+
+
+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, extra_extensions):
+ """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 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):
+ 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]))
+
+ 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."""
+
+ if len(argv) >= 1:
+ dir = argv[0]
+ else:
+ dir = '.'
+
+ for [functions, set_name, extension_headers, extensions] in FUNCTION_SETS:
+ used_extension_functions = GetUsedExtensionFunctions(
+ 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)
+ header_file.close()
+
+ source_file = open(
+ os.path.join(dir, 'gl_bindings_autogen_%s.cc' % set_name), 'wb')
+ 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')
+ GenerateMockSource(source_file, GL_FUNCTIONS)
+ source_file.close()
+ return 0
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/ui/gl/gl.gyp b/ui/gl/gl.gyp
new file mode 100644
index 0000000..87f9803
--- /dev/null
+++ b/ui/gl/gl.gyp
@@ -0,0 +1,206 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+{
+ 'variables': {
+ 'chromium_code': 1,
+ },
+
+ 'targets': [
+ {
+ 'target_name': 'gl',
+ 'type': '<(component)',
+ 'product_name': 'gl_wrapper', # Avoid colliding with OS X's libGL.dylib
+ 'dependencies': [
+ '<(DEPTH)/base/base.gyp:base',
+ '<(DEPTH)/base/third_party/dynamic_annotations/dynamic_annotations.gyp:dynamic_annotations',
+ '<(DEPTH)/gpu/command_buffer/command_buffer.gyp:gles2_utils',
+ '<(DEPTH)/skia/skia.gyp:skia',
+ '<(DEPTH)/ui/ui.gyp:ui',
+ ],
+ 'variables': {
+ 'gl_binding_output_dir': '<(SHARED_INTERMEDIATE_DIR)/ui/gl',
+ },
+ 'defines': [
+ 'GL_IMPLEMENTATION',
+ ],
+ 'include_dirs': [
+ '<(DEPTH)/third_party/swiftshader/include',
+ '<(DEPTH)/third_party/mesa/MesaLib/include',
+ '<(gl_binding_output_dir)',
+ ],
+ 'direct_dependent_settings': {
+ 'include_dirs': [
+ '<(DEPTH)/third_party/mesa/MesaLib/include',
+ '<(gl_binding_output_dir)',
+ ],
+ },
+ 'sources': [
+ 'gl_bindings.h',
+ 'gl_bindings_skia_in_process.cc',
+ 'gl_bindings_skia_in_process.h',
+ 'gl_context.cc',
+ 'gl_context.h',
+ 'gl_context_android.cc',
+ 'gl_context_linux.cc',
+ 'gl_context_mac.mm',
+ 'gl_context_osmesa.cc',
+ 'gl_context_osmesa.h',
+ 'gl_context_stub.cc',
+ 'gl_context_stub.h',
+ 'gl_context_win.cc',
+ 'gl_export.h',
+ 'gl_fence.cc',
+ 'gl_fence.h',
+ 'gl_implementation.cc',
+ 'gl_implementation.h',
+ 'gl_implementation_android.cc',
+ 'gl_implementation_linux.cc',
+ 'gl_implementation_mac.cc',
+ 'gl_implementation_win.cc',
+ 'gl_interface.cc',
+ 'gl_interface.h',
+ 'gl_share_group.cc',
+ 'gl_share_group.h',
+ 'gl_surface.cc',
+ 'gl_surface.h',
+ 'gl_surface_android.cc',
+ 'gl_surface_android.h',
+ 'gl_surface_linux.cc',
+ 'gl_surface_mac.cc',
+ 'gl_surface_stub.cc',
+ 'gl_surface_stub.h',
+ 'gl_surface_win.cc',
+ 'gl_surface_osmesa.cc',
+ 'gl_surface_osmesa.h',
+ 'gl_switches.cc',
+ 'gl_switches.h',
+ 'scoped_make_current.cc',
+ 'scoped_make_current.h',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_gl.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_gl.h',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_mock.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_osmesa.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_osmesa.h',
+ ],
+ # hard_dependency is necessary for this target because it has actions
+ # that generate header files included by dependent targets. The header
+ # files must be generated before the dependents are compiled. The usual
+ # semantics are to allow the two targets to build concurrently.
+ 'hard_dependency': 1,
+ 'actions': [
+ {
+ 'action_name': 'generate_gl_bindings',
+ 'inputs': [
+ 'generate_bindings.py',
+ '<(DEPTH)/third_party/khronos/GLES2/gl2ext.h',
+ '<(DEPTH)/third_party/khronos/EGL/eglext.h',
+ '<(DEPTH)/third_party/mesa/MesaLib/include/GL/glext.h',
+ '<(DEPTH)/third_party/mesa/MesaLib/include/GL/glxext.h',
+ '<(DEPTH)/third_party/mesa/MesaLib/include/GL/wglext.h',
+ ],
+ 'outputs': [
+ '<(gl_binding_output_dir)/gl_bindings_autogen_egl.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_egl.h',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_gl.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_gl.h',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_glx.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_glx.h',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_mock.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_osmesa.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_osmesa.h',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_wgl.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_wgl.h',
+ ],
+ 'action': [
+ 'python',
+ 'generate_bindings.py',
+ '<(gl_binding_output_dir)',
+ ],
+ },
+ ],
+ 'conditions': [
+ ['OS != "mac"', {
+ 'sources': [
+ 'egl_util.cc',
+ 'egl_util.h',
+ 'gl_context_egl.cc',
+ 'gl_context_egl.h',
+ 'gl_surface_egl.cc',
+ 'gl_surface_egl.h',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_egl.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_egl.h',
+ ],
+ 'include_dirs': [
+ '<(DEPTH)/third_party/angle/include',
+ ],
+ }],
+ ['use_x11 == 1', {
+ 'sources': [
+ 'gl_context_glx.cc',
+ 'gl_context_glx.h',
+ 'gl_surface_glx.cc',
+ 'gl_surface_glx.h',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_glx.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_glx.h',
+ ],
+ 'all_dependent_settings': {
+ 'defines': [
+ 'GL_GLEXT_PROTOTYPES',
+ ],
+ },
+ }],
+ ['OS=="win"', {
+ 'sources': [
+ 'gl_context_wgl.cc',
+ 'gl_context_wgl.h',
+ 'gl_surface_wgl.cc',
+ 'gl_surface_wgl.h',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_wgl.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_wgl.h',
+ ],
+ 'include_dirs': [
+ '$(DXSDK_DIR)/include',
+ ],
+ }],
+ ['OS=="mac"', {
+ 'sources': [
+ 'gl_context_cgl.cc',
+ 'gl_context_cgl.h',
+ 'gl_surface_cgl.cc',
+ 'gl_surface_cgl.h',
+ ],
+ 'link_settings': {
+ 'libraries': [
+ '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework',
+ ],
+ },
+ }],
+ ['OS=="mac" and use_aura == 1', {
+ 'sources': [
+ 'gl_context_nsview.mm',
+ 'gl_context_nsview.h',
+ 'gl_surface_nsview.mm',
+ 'gl_surface_nsview.h',
+ ],
+ }],
+ ['OS=="android"', {
+ 'sources': [
+ 'android_native_window.cc',
+ 'android_native_window.h',
+ ],
+ 'sources!': [
+ '<(gl_binding_output_dir)/gl_bindings_autogen_osmesa.cc',
+ '<(gl_binding_output_dir)/gl_bindings_autogen_osmesa.h',
+ 'system_monitor_posix.cc',
+ ],
+ 'defines': [
+ 'GL_GLEXT_PROTOTYPES',
+ 'EGL_EGLEXT_PROTOTYPES',
+ ],
+ }],
+ ],
+ },
+ ],
+}
diff --git a/ui/gl/gl_bindings.h b/ui/gl/gl_bindings.h
new file mode 100644
index 0000000..625dac9
--- /dev/null
+++ b/ui/gl/gl_bindings.h
@@ -0,0 +1,105 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_BINDINGS_H_
+#define UI_GL_GL_BINDINGS_H_
+#pragma once
+
+// Includes the platform independent and platform dependent GL headers.
+// Only include this in cc files. It pulls in system headers, including
+// the X11 headers on linux, which define all kinds of macros that are
+// liable to cause conflicts.
+
+#include <GL/gl.h>
+#include <GL/glext.h>
+
+#include "base/logging.h"
+#include "build/build_config.h"
+#include "ui/gl/gl_export.h"
+
+// The standard OpenGL native extension headers are also included.
+#if defined(OS_WIN)
+#include <GL/wglext.h>
+#elif defined(OS_MACOSX)
+#include <OpenGL/OpenGL.h>
+#elif defined(USE_X11)
+#include <GL/glx.h>
+#include <GL/glxext.h>
+
+// Undefine some macros defined by X headers. This is why this file should only
+// be included in .cc files.
+#undef Bool
+#undef None
+#undef Status
+#endif
+
+#if defined(OS_WIN)
+#define GL_BINDING_CALL WINAPI
+#else
+#define GL_BINDING_CALL
+#endif
+
+#define GL_SERVICE_LOG(args) DLOG(INFO) << args;
+#if defined(NDEBUG)
+ #define GL_SERVICE_LOG_CODE_BLOCK(code)
+#else
+ #define GL_SERVICE_LOG_CODE_BLOCK(code) code
+#endif
+
+// Forward declare OSMesa types.
+typedef struct osmesa_context *OSMesaContext;
+typedef void (*OSMESAproc)();
+
+#if !defined(OS_MACOSX)
+
+// Forward declare EGL types.
+typedef unsigned int EGLBoolean;
+typedef unsigned int EGLenum;
+typedef int EGLint;
+typedef void *EGLConfig;
+typedef void *EGLContext;
+typedef void *EGLDisplay;
+typedef void *EGLImageKHR;
+typedef void *EGLSurface;
+typedef void *EGLClientBuffer;
+typedef void (*__eglMustCastToProperFunctionPointerType)(void);
+typedef void* GLeglImageOES;
+
+#if defined(OS_WIN)
+typedef HDC EGLNativeDisplayType;
+typedef HBITMAP EGLNativePixmapType;
+typedef HWND EGLNativeWindowType;
+#elif defined(OS_ANDROID)
+typedef void *EGLNativeDisplayType;
+typedef struct egl_native_pixmap_t *EGLNativePixmapType;
+typedef struct ANativeWindow *EGLNativeWindowType;
+#else
+typedef Display *EGLNativeDisplayType;
+typedef Pixmap EGLNativePixmapType;
+typedef Window EGLNativeWindowType;
+#endif
+
+#endif // !OS_MACOSX
+
+#include "gl_bindings_autogen_gl.h"
+#include "gl_bindings_autogen_osmesa.h"
+
+#if defined(OS_WIN)
+#include "gl_bindings_autogen_egl.h"
+#include "gl_bindings_autogen_wgl.h"
+#elif defined(USE_X11)
+#include "gl_bindings_autogen_egl.h"
+#include "gl_bindings_autogen_glx.h"
+#elif defined(OS_ANDROID)
+#include "gl_bindings_autogen_egl.h"
+#endif
+
+namespace gfx {
+
+// Find an entry point to the mock GL implementation.
+void* GL_BINDING_CALL GetMockGLProcAddress(const char* name);
+
+} // namespace gfx
+
+#endif // UI_GL_GL_BINDINGS_H_
diff --git a/ui/gl/gl_bindings_skia_in_process.cc b/ui/gl/gl_bindings_skia_in_process.cc
new file mode 100644
index 0000000..a2f6433
--- /dev/null
+++ b/ui/gl/gl_bindings_skia_in_process.cc
@@ -0,0 +1,676 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+
+#include "ui/gl/gl_bindings_skia_in_process.h"
+
+#include "base/logging.h"
+#include "third_party/skia/include/gpu/gl/GrGLInterface.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+
+namespace {
+
+extern "C" {
+// The following stub functions are required because the glXXX routines exported
+// via gl_bindings.h use call-type GL_BINDING_CALL, which on Windows is stdcall.
+// Skia has been built such that its GrGLInterface GL pointers are __cdecl.
+
+GLvoid StubGLActiveTexture(GLenum texture) {
+ glActiveTexture(texture);
+}
+
+GLvoid StubGLAttachShader(GLuint program, GLuint shader) {
+ glAttachShader(program, shader);
+}
+
+GLvoid StubGLBeginQuery(GLenum target, GLuint id) {
+ glBeginQuery(target, id);
+}
+
+GLvoid StubGLBindAttribLocation(GLuint program, GLuint index,
+ const char* name) {
+ glBindAttribLocation(program, index, name);
+}
+
+GLvoid StubGLBindBuffer(GLenum target, GLuint buffer) {
+ glBindBuffer(target, buffer);
+}
+
+GLvoid StubGLBindFragDataLocation(GLuint program, GLuint colorNumber,
+ const GLchar * name) {
+ glBindFragDataLocation(program, colorNumber, name);
+}
+
+GLvoid StubGLBindFragDataLocationIndexed(GLuint program, GLuint colorNumber,
+ GLuint index, const GLchar * name) {
+ glBindFragDataLocationIndexed(program, colorNumber, index, name);
+}
+
+GLvoid StubGLBindFramebuffer(GLenum target, GLuint framebuffer) {
+ glBindFramebufferEXT(target, framebuffer);
+}
+
+GLvoid StubGLBindRenderbuffer(GLenum target, GLuint renderbuffer) {
+ glBindRenderbufferEXT(target, renderbuffer);
+}
+
+GLvoid StubGLBindTexture(GLenum target, GLuint texture) {
+ glBindTexture(target, texture);
+}
+
+GLvoid StubGLBlendColor(GLclampf red, GLclampf green, GLclampf blue,
+ GLclampf alpha) {
+ glBlendColor(red, green, blue, alpha);
+}
+
+GLvoid StubGLBlendFunc(GLenum sfactor, GLenum dfactor) {
+ glBlendFunc(sfactor, dfactor);
+}
+
+GLvoid StubGLBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter) {
+ glBlitFramebufferEXT(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1,
+ mask, filter);
+}
+
+GLvoid StubGLBufferData(GLenum target, GLsizeiptr size, const void* data,
+ GLenum usage) {
+ glBufferData(target, size, data, usage);
+}
+
+GLvoid StubGLBufferSubData(GLenum target, GLintptr offset, GLsizeiptr size,
+ const void* data) {
+ glBufferSubData(target, offset, size, data);
+}
+
+GLenum StubGLCheckFramebufferStatus(GLenum target) {
+ return glCheckFramebufferStatusEXT(target);
+}
+
+GLvoid StubGLClear(GLbitfield mask) {
+ glClear(mask);
+}
+
+GLvoid StubGLClearColor(GLclampf red, GLclampf green, GLclampf blue,
+ GLclampf alpha) {
+ glClearColor(red, green, blue, alpha);
+}
+
+GLvoid StubGLClearStencil(GLint s) {
+ glClearStencil(s);
+}
+
+GLvoid StubGLColorMask(GLboolean red, GLboolean green, GLboolean blue,
+ GLboolean alpha) {
+ glColorMask(red, green, blue, alpha);
+}
+
+GLvoid StubGLCompileShader(GLuint shader) {
+ glCompileShader(shader);
+}
+
+GLvoid StubGLCompressedTexImage2D(GLenum target, GLint level,
+ GLenum internalformat, GLsizei width,
+ GLsizei height, GLint border,
+ GLsizei imageSize, const void* data) {
+ glCompressedTexImage2D(target, level, internalformat, width, height, border,
+ imageSize, data);
+}
+
+GLuint StubGLCreateProgram(void) {
+ return glCreateProgram();
+}
+
+GLuint StubGLCreateShader(GLenum type) {
+ return glCreateShader(type);
+}
+
+GLvoid StubGLCullFace(GLenum mode) {
+ glCullFace(mode);
+}
+
+GLvoid StubGLDeleteBuffers(GLsizei n, const GLuint* buffers) {
+ glDeleteBuffersARB(n, buffers);
+}
+
+GLvoid StubGLDeleteFramebuffers(GLsizei n, const GLuint* framebuffers) {
+ glDeleteFramebuffersEXT(n, framebuffers);
+}
+
+GLvoid StubGLDeleteQueries(GLsizei n, const GLuint* ids) {
+ glDeleteQueries(n, ids);
+}
+
+GLvoid StubGLDeleteProgram(GLuint program) {
+ glDeleteProgram(program);
+}
+
+GLvoid StubGLDeleteRenderbuffers(GLsizei n, const GLuint* renderbuffers) {
+ glDeleteRenderbuffersEXT(n, renderbuffers);
+}
+
+GLvoid StubGLDeleteShader(GLuint shader) {
+ glDeleteShader(shader);
+}
+
+GLvoid StubGLDeleteTextures(GLsizei n, const GLuint* textures) {
+ glDeleteTextures(n, textures);
+}
+
+GLvoid StubGLDepthMask(GLboolean flag) {
+ glDepthMask(flag);
+}
+
+GLvoid StubGLDisable(GLenum cap) {
+ glDisable(cap);
+}
+
+GLvoid StubGLDisableVertexAttribArray(GLuint index) {
+ glDisableVertexAttribArray(index);
+}
+
+GLvoid StubGLDrawArrays(GLenum mode, GLint first, GLsizei count) {
+ glDrawArrays(mode, first, count);
+}
+
+GLvoid StubGLDrawBuffer(GLenum mode) {
+ glDrawBuffer(mode);
+}
+
+GLvoid StubGLDrawBuffers(GLsizei n, const GLenum* bufs) {
+ glDrawBuffersARB(n, bufs);
+}
+
+GLvoid StubGLDrawElements(GLenum mode, GLsizei count, GLenum type,
+ const void* indices) {
+ glDrawElements(mode, count, type, indices);
+}
+
+GLvoid StubGLEnable(GLenum cap) {
+ glEnable(cap);
+}
+
+GLvoid StubGLEnableVertexAttribArray(GLuint index) {
+ glEnableVertexAttribArray(index);
+}
+
+GLvoid StubGLEndQuery(GLenum target) {
+ glEndQuery(target);
+}
+
+GLvoid StubGLFinish() {
+ glFinish();
+}
+
+GLvoid StubGLFlush() {
+ glFlush();
+}
+
+GLvoid StubGLFramebufferRenderbuffer(GLenum target, GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer) {
+ glFramebufferRenderbufferEXT(target, attachment, renderbuffertarget,
+ renderbuffer);
+}
+
+GLvoid StubGLFramebufferTexture2D(GLenum target, GLenum attachment,
+ GLenum textarget, GLuint texture,
+ GLint level) {
+ glFramebufferTexture2DEXT(target, attachment, textarget, texture, level);
+}
+
+GLvoid StubGLFrontFace(GLenum mode) {
+ glFrontFace(mode);
+}
+
+GLvoid StubGLGenBuffers(GLsizei n, GLuint* buffers) {
+ glGenBuffersARB(n, buffers);
+}
+
+GLvoid StubGLGenFramebuffers(GLsizei n, GLuint* framebuffers) {
+ glGenFramebuffersEXT(n, framebuffers);
+}
+
+GLvoid StubGLGenQueries(GLsizei n, GLuint* ids) {
+ glGenQueries(n, ids);
+}
+
+GLvoid StubGLGenRenderbuffers(GLsizei n, GLuint* renderbuffers) {
+ glGenRenderbuffersEXT(n, renderbuffers);
+}
+
+GLvoid StubGLGenTextures(GLsizei n, GLuint* textures) {
+ glGenTextures(n, textures);
+}
+
+GLvoid StubGLGetBufferParameteriv(GLenum target, GLenum pname, GLint* params) {
+ glGetBufferParameteriv(target, pname, params);
+}
+
+GLvoid StubGLGetFramebufferAttachmentParameteriv(GLenum target,
+ GLenum attachment,
+ GLenum pname, GLint* params) {
+ glGetFramebufferAttachmentParameterivEXT(target, attachment, pname, params);
+}
+
+GLenum StubGLGetError() {
+ return glGetError();
+}
+
+GLvoid StubGLGetIntegerv(GLenum pname, GLint* params) {
+ glGetIntegerv(pname, params);
+}
+
+GLvoid StubGLGetProgramInfoLog(GLuint program, GLsizei bufsize, GLsizei* length,
+ char* infolog) {
+ glGetProgramInfoLog(program, bufsize, length, infolog);
+}
+
+GLvoid StubGLGetProgramiv(GLuint program, GLenum pname, GLint* params) {
+ glGetProgramiv(program, pname, params);
+}
+
+GLvoid StubGLGetRenderbufferParameteriv(GLenum target,
+ GLenum pname, GLint* params) {
+ glGetRenderbufferParameterivEXT(target, pname, params);
+}
+
+GLvoid StubGLGetShaderInfoLog(GLuint shader, GLsizei bufsize, GLsizei* length,
+ char* infolog) {
+ glGetShaderInfoLog(shader, bufsize, length, infolog);
+}
+
+GLvoid StubGLGetShaderiv(GLuint shader, GLenum pname, GLint* params) {
+ glGetShaderiv(shader, pname, params);
+}
+
+const GLubyte* StubGLGetString(GLenum name) {
+ return glGetString(name);
+}
+
+GLvoid StubGLGetQueryiv(GLenum target, GLenum pname, GLint* params) {
+ glGetQueryiv(target, pname, params);
+}
+
+GLvoid StubGLGetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params) {
+ glGetQueryObjecti64v(id, pname, params);
+}
+
+GLvoid StubGLGetQueryObjectiv(GLuint id, GLenum pname, GLint* params) {
+ glGetQueryObjectiv(id, pname, params);
+}
+
+GLvoid StubGLGetQueryObjectui64v(GLuint id, GLenum pname, GLuint64* params) {
+ glGetQueryObjectui64v(id, pname, params);
+}
+
+GLvoid StubGLGetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) {
+ glGetQueryObjectuiv(id, pname, params);
+}
+
+GLvoid StubGLGetTexLevelParameteriv(GLenum target, GLint level,
+ GLenum pname, GLint* params) {
+ glGetTexLevelParameteriv(target, level, pname, params);
+}
+
+GLint StubGLGetUniformLocation(GLuint program, const char* name) {
+ return glGetUniformLocation(program, name);
+}
+
+GLvoid StubGLLineWidth(GLfloat width) {
+ glLineWidth(width);
+}
+
+GLvoid StubGLLinkProgram(GLuint program) {
+ glLinkProgram(program);
+}
+
+void* StubGLMapBuffer(GLenum target, GLenum access) {
+ return glMapBuffer(target, access);
+}
+
+GLvoid StubGLPixelStorei(GLenum pname, GLint param) {
+ glPixelStorei(pname, param);
+}
+
+GLvoid StubGLQueryCounter(GLuint id, GLenum target) {
+ glQueryCounter(id, target);
+}
+
+GLvoid StubGLReadBuffer(GLenum src) {
+ glReadBuffer(src);
+}
+
+GLvoid StubGLReadPixels(GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, void* pixels) {
+ glReadPixels(x, y, width, height, format, type, pixels);
+}
+
+GLvoid StubGLRenderbufferStorage(GLenum target, GLenum internalformat,
+ GLsizei width, GLsizei height) {
+ glRenderbufferStorageEXT(target, internalformat, width, height);
+}
+
+GLvoid StubGLRenderbufferStorageMultisample(GLenum target, GLsizei samples,
+ GLenum internalformat,
+ GLsizei width, GLsizei height) {
+ glRenderbufferStorageMultisampleEXT(target, samples, internalformat, width,
+ height);
+}
+
+GLvoid StubGLScissor(GLint x, GLint y, GLsizei width, GLsizei height) {
+ glScissor(x, y, width, height);
+}
+
+GLvoid StubGLShaderSource(GLuint shader, GLsizei count, const char** str,
+ const GLint* length) {
+ glShaderSource(shader, count, str, length);
+}
+
+GLvoid StubGLStencilFunc(GLenum func, GLint ref, GLuint mask) {
+ glStencilFunc(func, ref, mask);
+}
+
+GLvoid StubGLStencilFuncSeparate(GLenum face, GLenum func, GLint ref,
+ GLuint mask) {
+ glStencilFuncSeparate(face, func, ref, mask);
+}
+
+GLvoid StubGLStencilMask(GLuint mask) {
+ glStencilMask(mask);
+}
+
+GLvoid StubGLStencilMaskSeparate(GLenum face, GLuint mask) {
+ glStencilMaskSeparate(face, mask);
+}
+
+GLvoid StubGLStencilOp(GLenum fail, GLenum zfail, GLenum zpass) {
+ glStencilOp(fail, zfail, zpass);
+}
+
+GLvoid StubGLStencilOpSeparate(GLenum face, GLenum fail, GLenum zfail,
+ GLenum zpass) {
+ glStencilOpSeparate(face, fail, zfail, zpass);
+}
+
+GLvoid StubGLTexImage2D(GLenum target, GLint level, GLint internalformat,
+ GLsizei width, GLsizei height, GLint border,
+ GLenum format, GLenum type, const void* pixels) {
+ glTexImage2D(target, level, internalformat, width, height, border, format,
+ type, pixels);
+}
+
+GLvoid StubGLTexParameteri(GLenum target, GLenum pname, GLint param) {
+ glTexParameteri(target, pname, param);
+}
+
+GLvoid StubGLTexStorage2D(GLenum target, GLsizei levels, GLenum internalFormat,
+ GLsizei width, GLsizei height) {
+ glTexStorage2DEXT(target, levels, internalFormat, width, height);
+}
+
+GLvoid StubGLTexSubImage2D(GLenum target, GLint level, GLint xoffset,
+ GLint yoffset, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, const void* pixels) {
+ glTexSubImage2D(target, level, xoffset, yoffset, width, height, format, type,
+ pixels);
+}
+
+GLvoid StubGLUniform1f(GLint location, GLfloat v) {
+ glUniform1i(location, v);
+}
+
+GLvoid StubGLUniform1i(GLint location, GLint v) {
+ glUniform1i(location, v);
+}
+
+GLvoid StubGLUniform1fv(GLint location, GLsizei count, const GLfloat* v) {
+ glUniform1fv(location, count, v);
+}
+
+GLvoid StubGLUniform1iv(GLint location, GLsizei count, const GLint* v) {
+ glUniform1iv(location, count, v);
+}
+
+GLvoid StubGLUniform2f(GLint location, GLfloat v0, GLfloat v1) {
+ glUniform2i(location, v0, v1);
+}
+
+GLvoid StubGLUniform2i(GLint location, GLint v0, GLint v1) {
+ glUniform2i(location, v0, v1);
+}
+
+GLvoid StubGLUniform2fv(GLint location, GLsizei count, const GLfloat* v) {
+ glUniform2fv(location, count, v);
+}
+
+GLvoid StubGLUniform2iv(GLint location, GLsizei count, const GLint* v) {
+ glUniform2iv(location, count, v);
+}
+
+GLvoid StubGLUniform3f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2) {
+ glUniform3i(location, v0, v1, v2);
+}
+
+GLvoid StubGLUniform3i(GLint location, GLint v0, GLint v1, GLint v2) {
+ glUniform3i(location, v0, v1, v2);
+}
+
+GLvoid StubGLUniform3fv(GLint location, GLsizei count, const GLfloat* v) {
+ glUniform3fv(location, count, v);
+}
+
+GLvoid StubGLUniform3iv(GLint location, GLsizei count, const GLint* v) {
+ glUniform3iv(location, count, v);
+}
+
+GLvoid StubGLUniform4f(GLint location, GLfloat v0, GLfloat v1, GLfloat v2,
+ GLfloat v3) {
+ glUniform4i(location, v0, v1, v2, v3);
+}
+
+GLvoid StubGLUniform4i(GLint location, GLint v0, GLint v1, GLint v2,
+ GLint v3) {
+ glUniform4i(location, v0, v1, v2, v3);
+}
+
+GLvoid StubGLUniform4fv(GLint location, GLsizei count, const GLfloat* v) {
+ glUniform4fv(location, count, v);
+}
+
+GLvoid StubGLUniform4iv(GLint location, GLsizei count, const GLint* v) {
+ glUniform4iv(location, count, v);
+}
+
+GLvoid StubGLUniformMatrix2fv(GLint location, GLsizei count,
+ GLboolean transpose, const GLfloat* value) {
+ glUniformMatrix2fv(location, count, transpose, value);
+}
+
+GLvoid StubGLUniformMatrix3fv(GLint location, GLsizei count,
+ GLboolean transpose, const GLfloat* value) {
+ glUniformMatrix3fv(location, count, transpose, value);
+}
+
+GLvoid StubGLUniformMatrix4fv(GLint location, GLsizei count,
+ GLboolean transpose, const GLfloat* value) {
+ glUniformMatrix4fv(location, count, transpose, value);
+}
+
+GLboolean StubGLUnmapBuffer(GLenum target) {
+ return glUnmapBuffer(target);
+}
+
+GLvoid StubGLUseProgram(GLuint program) {
+ glUseProgram(program);
+}
+
+GLvoid StubGLVertexAttrib4fv(GLuint indx, const GLfloat* values) {
+ glVertexAttrib4fv(indx, values);
+}
+
+GLvoid StubGLVertexAttribPointer(GLuint indx, GLint size, GLenum type,
+ GLboolean normalized, GLsizei stride,
+ const void* ptr) {
+ glVertexAttribPointer(indx, size, type, normalized, stride, ptr);
+}
+
+GLvoid StubGLViewport(GLint x, GLint y, GLsizei width, GLsizei height) {
+ glViewport(x, y, width, height);
+}
+} // extern "C"
+} // namespace
+
+namespace gfx {
+
+GrGLInterface* CreateInProcessSkiaGLBinding() {
+ GrGLBinding binding;
+ switch (gfx::GetGLImplementation()) {
+ case gfx::kGLImplementationNone:
+ NOTREACHED();
+ return NULL;
+ case gfx::kGLImplementationDesktopGL:
+ case gfx::kGLImplementationAppleGL:
+ binding = kDesktop_GrGLBinding;
+ break;
+ case gfx::kGLImplementationOSMesaGL:
+ binding = kDesktop_GrGLBinding;
+ break;
+ case gfx::kGLImplementationEGLGLES2:
+ binding = kES2_GrGLBinding;
+ break;
+ case gfx::kGLImplementationMockGL:
+ NOTREACHED();
+ return NULL;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+
+ GrGLInterface* interface = new GrGLInterface;
+
+ interface->fBindingsExported = binding;
+ interface->fActiveTexture = StubGLActiveTexture;
+ interface->fAttachShader = StubGLAttachShader;
+ interface->fBeginQuery = StubGLBeginQuery;
+ interface->fBindAttribLocation = StubGLBindAttribLocation;
+ interface->fBindBuffer = StubGLBindBuffer;
+ interface->fBindFragDataLocation = StubGLBindFragDataLocation;
+ interface->fBindTexture = StubGLBindTexture;
+ interface->fBlendColor = StubGLBlendColor;
+ interface->fBlendFunc = StubGLBlendFunc;
+ interface->fBufferData = StubGLBufferData;
+ interface->fBufferSubData = StubGLBufferSubData;
+ interface->fClear = StubGLClear;
+ interface->fClearColor = StubGLClearColor;
+ interface->fClearStencil = StubGLClearStencil;
+ interface->fColorMask = StubGLColorMask;
+ interface->fCompileShader = StubGLCompileShader;
+ interface->fCompressedTexImage2D = StubGLCompressedTexImage2D;
+ interface->fCreateProgram = StubGLCreateProgram;
+ interface->fCreateShader = StubGLCreateShader;
+ interface->fCullFace = StubGLCullFace;
+ interface->fDeleteBuffers = StubGLDeleteBuffers;
+ interface->fDeleteProgram = StubGLDeleteProgram;
+ interface->fDeleteQueries = StubGLDeleteQueries;
+ interface->fDeleteShader = StubGLDeleteShader;
+ interface->fDeleteTextures = StubGLDeleteTextures;
+ interface->fDepthMask = StubGLDepthMask;
+ interface->fDisable = StubGLDisable;
+ interface->fDisableVertexAttribArray = StubGLDisableVertexAttribArray;
+ interface->fDrawArrays = StubGLDrawArrays;
+ interface->fDrawBuffer = StubGLDrawBuffer;
+ interface->fDrawBuffers = StubGLDrawBuffers;
+ interface->fDrawElements = StubGLDrawElements;
+ interface->fEnable = StubGLEnable;
+ interface->fEnableVertexAttribArray = StubGLEnableVertexAttribArray;
+ interface->fEndQuery = StubGLEndQuery;
+ interface->fFinish = StubGLFinish;
+ interface->fFlush = StubGLFlush;
+ interface->fFrontFace = StubGLFrontFace;
+ interface->fGenBuffers = StubGLGenBuffers;
+ interface->fGenQueries = StubGLGenQueries;
+ interface->fGenTextures = StubGLGenTextures;
+ interface->fGetBufferParameteriv = StubGLGetBufferParameteriv;
+ interface->fGetError = StubGLGetError;
+ interface->fGetIntegerv = StubGLGetIntegerv;
+ interface->fGetQueryiv = StubGLGetQueryiv;
+ interface->fGetQueryObjecti64v = StubGLGetQueryObjecti64v;
+ interface->fGetQueryObjectiv = StubGLGetQueryObjectiv;
+ interface->fGetQueryObjectui64v = StubGLGetQueryObjectui64v;
+ interface->fGetQueryObjectuiv = StubGLGetQueryObjectuiv;
+ interface->fGetProgramInfoLog = StubGLGetProgramInfoLog;
+ interface->fGetProgramiv = StubGLGetProgramiv;
+ interface->fGetShaderInfoLog = StubGLGetShaderInfoLog;
+ interface->fGetShaderiv = StubGLGetShaderiv;
+ interface->fGetString = StubGLGetString;
+ interface->fGetTexLevelParameteriv = StubGLGetTexLevelParameteriv;
+ interface->fGetUniformLocation = StubGLGetUniformLocation;
+ interface->fLineWidth = StubGLLineWidth;
+ interface->fLinkProgram = StubGLLinkProgram;
+ interface->fPixelStorei = StubGLPixelStorei;
+ interface->fQueryCounter = StubGLQueryCounter;
+ interface->fReadBuffer = StubGLReadBuffer;
+ interface->fReadPixels = StubGLReadPixels;
+ interface->fScissor = StubGLScissor;
+ interface->fShaderSource = StubGLShaderSource;
+ interface->fStencilFunc = StubGLStencilFunc;
+ interface->fStencilFuncSeparate = StubGLStencilFuncSeparate;
+ interface->fStencilMask = StubGLStencilMask;
+ interface->fStencilMaskSeparate = StubGLStencilMaskSeparate;
+ interface->fStencilOp = StubGLStencilOp;
+ interface->fStencilOpSeparate = StubGLStencilOpSeparate;
+ interface->fTexImage2D = StubGLTexImage2D;
+ interface->fTexParameteri = StubGLTexParameteri;
+ interface->fTexSubImage2D = StubGLTexSubImage2D;
+ interface->fTexStorage2D = StubGLTexStorage2D;
+ interface->fUniform1f = StubGLUniform1f;
+ interface->fUniform1i = StubGLUniform1i;
+ interface->fUniform1fv = StubGLUniform1fv;
+ interface->fUniform1iv = StubGLUniform1iv;
+ interface->fUniform2f = StubGLUniform2f;
+ interface->fUniform2i = StubGLUniform2i;
+ interface->fUniform2fv = StubGLUniform2fv;
+ interface->fUniform2iv = StubGLUniform2iv;
+ interface->fUniform3f = StubGLUniform3f;
+ interface->fUniform3i = StubGLUniform3i;
+ interface->fUniform3fv = StubGLUniform3fv;
+ interface->fUniform3iv = StubGLUniform3iv;
+ interface->fUniform4f = StubGLUniform4f;
+ interface->fUniform4i = StubGLUniform4i;
+ interface->fUniform4fv = StubGLUniform4fv;
+ interface->fUniform4iv = StubGLUniform4iv;
+ interface->fUniformMatrix2fv = StubGLUniformMatrix2fv;
+ interface->fUniformMatrix3fv = StubGLUniformMatrix3fv;
+ interface->fUniformMatrix4fv = StubGLUniformMatrix4fv;
+ interface->fUseProgram = StubGLUseProgram;
+ interface->fVertexAttrib4fv = StubGLVertexAttrib4fv;
+ interface->fVertexAttribPointer = StubGLVertexAttribPointer;
+ interface->fViewport = StubGLViewport;
+ interface->fBindFramebuffer = StubGLBindFramebuffer;
+ interface->fBindRenderbuffer = StubGLBindRenderbuffer;
+ interface->fCheckFramebufferStatus = StubGLCheckFramebufferStatus;
+ interface->fDeleteFramebuffers = StubGLDeleteFramebuffers;
+ interface->fDeleteRenderbuffers = StubGLDeleteRenderbuffers;
+ interface->fFramebufferRenderbuffer = StubGLFramebufferRenderbuffer;
+ interface->fFramebufferTexture2D = StubGLFramebufferTexture2D;
+ interface->fGenFramebuffers = StubGLGenFramebuffers;
+ interface->fGenRenderbuffers = StubGLGenRenderbuffers;
+ interface->fGetFramebufferAttachmentParameteriv =
+ StubGLGetFramebufferAttachmentParameteriv;
+ interface->fGetRenderbufferParameteriv = StubGLGetRenderbufferParameteriv;
+ interface->fRenderbufferStorage = StubGLRenderbufferStorage;
+ interface->fRenderbufferStorageMultisample =
+ StubGLRenderbufferStorageMultisample;
+ interface->fBlitFramebuffer = StubGLBlitFramebuffer;
+ interface->fMapBuffer = StubGLMapBuffer;
+ interface->fUnmapBuffer = StubGLUnmapBuffer;
+ interface->fBindFragDataLocationIndexed =
+ StubGLBindFragDataLocationIndexed;
+ return interface;
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_bindings_skia_in_process.h b/ui/gl/gl_bindings_skia_in_process.h
new file mode 100644
index 0000000..5bd356a
--- /dev/null
+++ b/ui/gl/gl_bindings_skia_in_process.h
@@ -0,0 +1,21 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_BINDINGS_SKIA_IN_PROCESS_H_
+#define UI_GL_GL_BINDINGS_SKIA_IN_PROCESS_H_
+#pragma once
+
+#include "ui/gl/gl_export.h"
+
+struct GrGLInterface;
+
+namespace gfx {
+
+// The GPU back-end for skia requires pointers to GL functions. This function
+// creates a binding for skia-gpu to the in-process GL
+GL_EXPORT GrGLInterface* CreateInProcessSkiaGLBinding();
+
+} // namespace gfx
+
+#endif // UI_GL_GL_BINDINGS_SKIA_IN_PROCESS_H_
diff --git a/ui/gl/gl_context.cc b/ui/gl/gl_context.cc
new file mode 100644
index 0000000..8652e25
--- /dev/null
+++ b/ui/gl/gl_context.cc
@@ -0,0 +1,111 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <string>
+
+#include "base/command_line.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/threading/thread_local.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/gl_switches.h"
+
+namespace gfx {
+
+namespace {
+base::LazyInstance<base::ThreadLocalPointer<GLContext> >::Leaky
+ current_context_ = LAZY_INSTANCE_INITIALIZER;
+} // namespace
+
+GLContext::GLContext(GLShareGroup* share_group) : share_group_(share_group) {
+ if (!share_group_.get())
+ share_group_ = new GLShareGroup;
+
+ share_group_->AddContext(this);
+}
+
+GLContext::~GLContext() {
+ share_group_->RemoveContext(this);
+ if (GetCurrent() == this) {
+ SetCurrent(NULL, NULL);
+ }
+}
+
+std::string GLContext::GetExtensions() {
+ DCHECK(IsCurrent(NULL));
+
+ std::string extensions;
+ if (GLSurface::GetCurrent()) {
+ extensions = GLSurface::GetCurrent()->GetExtensions();
+ }
+
+ const char* gl_ext = reinterpret_cast<const char*>(
+ glGetString(GL_EXTENSIONS));
+ if (gl_ext) {
+ extensions += (!extensions.empty() && gl_ext[0]) ? " " : "";
+ extensions += gl_ext;
+ }
+
+ return extensions;
+}
+
+bool GLContext::HasExtension(const char* name) {
+ std::string extensions = GetExtensions();
+ extensions += " ";
+
+ std::string delimited_name(name);
+ delimited_name += " ";
+
+ return extensions.find(delimited_name) != std::string::npos;
+}
+
+GLShareGroup* GLContext::share_group() {
+ return share_group_.get();
+}
+
+bool GLContext::LosesAllContextsOnContextLost() {
+ switch (GetGLImplementation()) {
+ case kGLImplementationDesktopGL:
+ return false;
+ case kGLImplementationEGLGLES2:
+ return true;
+ case kGLImplementationOSMesaGL:
+ case kGLImplementationAppleGL:
+ return false;
+ case kGLImplementationMockGL:
+ return false;
+ default:
+ NOTREACHED();
+ return true;
+ }
+}
+
+GLContext* GLContext::GetCurrent() {
+ return current_context_.Pointer()->Get();
+}
+
+void GLContext::SetCurrent(GLContext* context, GLSurface* surface) {
+ current_context_.Pointer()->Set(context);
+ GLSurface::SetCurrent(surface);
+}
+
+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/gl/gl_context.h b/ui/gl/gl_context.h
new file mode 100644
index 0000000..dc76c00
--- /dev/null
+++ b/ui/gl/gl_context.h
@@ -0,0 +1,95 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_CONTEXT_H_
+#define UI_GL_GL_CONTEXT_H_
+#pragma once
+
+#include <string>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "ui/gl/gl_share_group.h"
+#include "ui/gl/gpu_preference.h"
+
+namespace gfx {
+
+class GLSurface;
+
+// Encapsulates an OpenGL context, hiding platform specific management.
+class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
+ public:
+ explicit GLContext(GLShareGroup* share_group);
+
+ // Initializes the GL context to be compatible with the given surface. The GL
+ // context can be made with other surface's of the same type. The compatible
+ // surface is only needed for certain platforms like WGL, OSMesa and GLX. It
+ // should be specific for all platforms though.
+ virtual bool Initialize(
+ GLSurface* compatible_surface, GpuPreference gpu_preference) = 0;
+
+ // Destroys the GL context.
+ virtual void Destroy() = 0;
+
+ // Makes the GL context and a surface current on the current thread.
+ virtual bool MakeCurrent(GLSurface* surface) = 0;
+
+ // Releases this GL context and surface as current on the current thread.
+ virtual void ReleaseCurrent(GLSurface* surface) = 0;
+
+ // Returns true if this context and surface is current. Pass a null surface
+ // if the current surface is not important.
+ virtual bool IsCurrent(GLSurface* surface) = 0;
+
+ // Get the underlying platform specific GL context "handle".
+ virtual void* GetHandle() = 0;
+
+ // Set swap interval. This context must be current.
+ virtual void SetSwapInterval(int interval) = 0;
+
+ // Returns space separated list of extensions. The context must be current.
+ virtual std::string GetExtensions();
+
+ // Returns whether the current context supports the named extension. The
+ // context must be current.
+ bool HasExtension(const char* name);
+
+ GLShareGroup* share_group();
+
+ // Create a GL context that is compatible with the given surface.
+ // |share_group|, if non-NULL, is a group of contexts which the
+ // internally created OpenGL context shares textures and other resources.
+ static scoped_refptr<GLContext> CreateGLContext(
+ GLShareGroup* share_group,
+ GLSurface* compatible_surface,
+ GpuPreference gpu_preference);
+
+ static bool LosesAllContextsOnContextLost();
+
+ static bool SupportsDualGpus();
+
+ static GLContext* GetCurrent();
+
+ virtual bool WasAllocatedUsingARBRobustness();
+
+ protected:
+ 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:
+ friend class base::RefCounted<GLContext>;
+
+ scoped_refptr<GLShareGroup> share_group_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLContext);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_CONTEXT_H_
diff --git a/ui/gl/gl_context_android.cc b/ui/gl/gl_context_android.cc
new file mode 100644
index 0000000..38d91e8
--- /dev/null
+++ b/ui/gl/gl_context_android.cc
@@ -0,0 +1,34 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_context.h"
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context_egl.h"
+#include "ui/gl/gl_context_stub.h"
+#include "ui/gl/gl_implementation.h"
+
+namespace gfx {
+
+// static
+scoped_refptr<GLContext> GLContext::CreateGLContext(
+ GLShareGroup* share_group,
+ GLSurface* compatible_surface,
+ GpuPreference gpu_preference) {
+ if (GetGLImplementation() == kGLImplementationMockGL)
+ return scoped_refptr<GLContext>(new GLContextStub());
+
+ scoped_refptr<GLContextEGL> context(new GLContextEGL(share_group));
+ if (!context->Initialize(compatible_surface, gpu_preference))
+ return NULL;
+ return context;
+}
+
+bool GLContext::SupportsDualGpus() {
+ return false;
+}
+
+}
diff --git a/ui/gl/gl_context_cgl.cc b/ui/gl/gl_context_cgl.cc
new file mode 100644
index 0000000..790baad
--- /dev/null
+++ b/ui/gl/gl_context_cgl.cc
@@ -0,0 +1,163 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_context_cgl.h"
+
+#include <OpenGL/CGLRenderers.h>
+#include <vector>
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_cgl.h"
+
+namespace gfx {
+
+GLContextCGL::GLContextCGL(GLShareGroup* share_group)
+ : GLContext(share_group),
+ context_(NULL),
+ gpu_preference_(PreferIntegratedGpu) {
+}
+
+bool GLContextCGL::Initialize(GLSurface* compatible_surface,
+ GpuPreference gpu_preference) {
+ DCHECK(compatible_surface);
+
+ GLContextCGL* share_context = share_group() ?
+ static_cast<GLContextCGL*>(share_group()->GetContext()) : NULL;
+ if (SupportsDualGpus()) {
+ // Ensure the GPU preference is compatible with contexts already in the
+ // share group.
+ if (share_context && gpu_preference != share_context->GetGpuPreference())
+ return false;
+ }
+
+ std::vector<CGLPixelFormatAttribute> attribs;
+ bool using_offline_renderer =
+ SupportsDualGpus() && gpu_preference == PreferIntegratedGpu;
+ if (using_offline_renderer) {
+ attribs.push_back(kCGLPFAAllowOfflineRenderers);
+ }
+ if (GetGLImplementation() == kGLImplementationAppleGL) {
+ attribs.push_back(kCGLPFARendererID);
+ attribs.push_back((CGLPixelFormatAttribute) kCGLRendererGenericFloatID);
+ }
+ attribs.push_back((CGLPixelFormatAttribute) 0);
+
+ CGLPixelFormatObj format;
+ GLint num_pixel_formats;
+ if (CGLChoosePixelFormat(&attribs.front(),
+ &format,
+ &num_pixel_formats) != kCGLNoError) {
+ LOG(ERROR) << "Error choosing pixel format.";
+ return false;
+ }
+ if (!format) {
+ LOG(ERROR) << "format == 0.";
+ return false;
+ }
+ DCHECK_NE(num_pixel_formats, 0);
+
+ CGLError res = CGLCreateContext(
+ format,
+ share_context ?
+ static_cast<CGLContextObj>(share_context->GetHandle()) : NULL,
+ reinterpret_cast<CGLContextObj*>(&context_));
+ CGLReleasePixelFormat(format);
+ if (res != kCGLNoError) {
+ LOG(ERROR) << "Error creating context.";
+ Destroy();
+ return false;
+ }
+
+ gpu_preference_ = gpu_preference;
+ return true;
+}
+
+void GLContextCGL::Destroy() {
+ if (context_) {
+ CGLDestroyContext(static_cast<CGLContextObj>(context_));
+ context_ = NULL;
+ }
+}
+
+bool GLContextCGL::MakeCurrent(GLSurface* surface) {
+ DCHECK(context_);
+ if (IsCurrent(surface))
+ return true;
+
+ TRACE_EVENT0("gpu", "GLContextCGL::MakeCurrent");
+
+ if (CGLSetCurrentContext(
+ static_cast<CGLContextObj>(context_)) != kCGLNoError) {
+ LOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+
+ SetCurrent(this, surface);
+ if (!InitializeExtensionBindings()) {
+ ReleaseCurrent(surface);
+ return false;
+ }
+
+ if (!surface->OnMakeCurrent(this)) {
+ LOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+
+ return true;
+}
+
+void GLContextCGL::ReleaseCurrent(GLSurface* surface) {
+ if (!IsCurrent(surface))
+ return;
+
+ SetCurrent(NULL, NULL);
+ CGLSetCurrentContext(NULL);
+}
+
+bool GLContextCGL::IsCurrent(GLSurface* surface) {
+ bool native_context_is_current = CGLGetCurrentContext() == context_;
+
+ // If our context is current then our notion of which GLContext is
+ // current must be correct. On the other hand, third-party code
+ // using OpenGL might change the current context.
+ DCHECK(!native_context_is_current || (GetCurrent() == this));
+
+ if (!native_context_is_current)
+ return false;
+
+ return true;
+}
+
+void* GLContextCGL::GetHandle() {
+ return context_;
+}
+
+void GLContextCGL::SetSwapInterval(int interval) {
+ DCHECK(IsCurrent(NULL));
+ LOG(WARNING) << "GLContex: GLContextCGL::SetSwapInterval is ignored.";
+}
+
+GLContextCGL::~GLContextCGL() {
+ Destroy();
+}
+
+GpuPreference GLContextCGL::GetGpuPreference() {
+ return gpu_preference_;
+}
+
+void GLContextCGL::ForceUseOfDiscreteGPU() {
+ static CGLPixelFormatObj format = NULL;
+ if (format)
+ return;
+ CGLPixelFormatAttribute attribs[1];
+ attribs[0] = static_cast<CGLPixelFormatAttribute>(0);
+ GLint num_pixel_formats = 0;
+ CGLChoosePixelFormat(attribs, &format, &num_pixel_formats);
+ // format is deliberately leaked.
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_context_cgl.h b/ui/gl/gl_context_cgl.h
new file mode 100644
index 0000000..0331568
--- /dev/null
+++ b/ui/gl/gl_context_cgl.h
@@ -0,0 +1,51 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_CONTEXT_CGL_H_
+#define UI_GL_GL_CONTEXT_CGL_H_
+#pragma once
+
+#include "ui/gl/gl_context.h"
+
+namespace gfx {
+
+class GLSurface;
+
+// Encapsulates a CGL OpenGL context.
+class GLContextCGL : public GLContext {
+ public:
+ explicit GLContextCGL(GLShareGroup* share_group);
+
+ // Implement GLContext.
+ virtual bool Initialize(GLSurface* compatible_surface,
+ GpuPreference gpu_preference) OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool MakeCurrent(GLSurface* surface) OVERRIDE;
+ virtual void ReleaseCurrent(GLSurface* surface) OVERRIDE;
+ virtual bool IsCurrent(GLSurface* surface) OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+ virtual void SetSwapInterval(int interval) OVERRIDE;
+
+ protected:
+ virtual ~GLContextCGL();
+
+ private:
+ // Expose ForceUseOfDiscreteGPU only to GLContext implementation.
+ friend class GLContext;
+
+ GpuPreference GetGpuPreference();
+
+ // Helper for dual-GPU support on systems where this is necessary
+ // for stability reasons.
+ static void ForceUseOfDiscreteGPU();
+
+ void* context_;
+ GpuPreference gpu_preference_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLContextCGL);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_CONTEXT_CGL_H_
diff --git a/ui/gl/gl_context_egl.cc b/ui/gl/gl_context_egl.cc
new file mode 100644
index 0000000..fa655a0
--- /dev/null
+++ b/ui/gl/gl_context_egl.cc
@@ -0,0 +1,160 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_context_egl.h"
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "build/build_config.h"
+#include "third_party/angle/include/EGL/egl.h"
+#include "ui/gl/egl_util.h"
+#include "ui/gl/gl_surface.h"
+
+// This header must come after the above third-party include, as
+// it brings in #defines that cause conflicts.
+#include "ui/gl/gl_bindings.h"
+
+#if defined(USE_X11)
+extern "C" {
+#include <X11/Xlib.h>
+}
+#endif
+
+namespace gfx {
+
+std::string GLContextEGL::GetExtensions() {
+ const char* extensions = eglQueryString(display_,
+ EGL_EXTENSIONS);
+ if (!extensions)
+ return GLContext::GetExtensions();
+
+ return GLContext::GetExtensions() + " " + extensions;
+}
+
+GLContextEGL::GLContextEGL(GLShareGroup* share_group)
+ : GLContext(share_group),
+ context_(NULL),
+ display_(NULL),
+ config_(NULL) {
+}
+
+GLContextEGL::~GLContextEGL() {
+ Destroy();
+}
+
+bool GLContextEGL::Initialize(
+ GLSurface* compatible_surface, GpuPreference gpu_preference) {
+ DCHECK(compatible_surface);
+ DCHECK(!context_);
+
+ static const EGLint kContextAttributes[] = {
+ EGL_CONTEXT_CLIENT_VERSION, 2,
+ EGL_NONE
+ };
+
+ display_ = compatible_surface->GetDisplay();
+ config_ = compatible_surface->GetConfig();
+
+ context_ = eglCreateContext(
+ display_,
+ config_,
+ share_group() ? share_group()->GetHandle() : NULL,
+ kContextAttributes);
+ if (!context_) {
+ LOG(ERROR) << "eglCreateContext failed with error "
+ << GetLastEGLErrorString();
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void GLContextEGL::Destroy() {
+ if (context_) {
+ if (!eglDestroyContext(display_, context_)) {
+ LOG(ERROR) << "eglDestroyContext failed with error "
+ << GetLastEGLErrorString();
+ }
+
+ context_ = NULL;
+ }
+}
+
+bool GLContextEGL::MakeCurrent(GLSurface* surface) {
+ DCHECK(context_);
+ if (IsCurrent(surface))
+ return true;
+
+ TRACE_EVENT0("gpu", "GLContextEGL::MakeCurrent");
+
+ if (!eglMakeCurrent(display_,
+ surface->GetHandle(),
+ surface->GetHandle(),
+ context_)) {
+ DVLOG(1) << "eglMakeCurrent failed with error "
+ << GetLastEGLErrorString();
+ return false;
+ }
+
+ SetCurrent(this, surface);
+ if (!InitializeExtensionBindings()) {
+ ReleaseCurrent(surface);
+ return false;
+ }
+
+ if (!surface->OnMakeCurrent(this)) {
+ LOG(ERROR) << "Could not make current.";
+ return false;
+ }
+
+ return true;
+}
+
+void GLContextEGL::ReleaseCurrent(GLSurface* surface) {
+ if (!IsCurrent(surface))
+ return;
+
+ SetCurrent(NULL, NULL);
+ eglMakeCurrent(display_,
+ EGL_NO_SURFACE,
+ EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+}
+
+bool GLContextEGL::IsCurrent(GLSurface* surface) {
+ DCHECK(context_);
+
+ bool native_context_is_current = context_ == eglGetCurrentContext();
+
+ // If our context is current then our notion of which GLContext is
+ // current must be correct. On the other hand, third-party code
+ // using OpenGL might change the current context.
+ DCHECK(!native_context_is_current || (GetCurrent() == this));
+
+ if (!native_context_is_current)
+ return false;
+
+ if (surface) {
+ if (surface->GetHandle() != eglGetCurrentSurface(EGL_DRAW))
+ return false;
+ }
+
+ return true;
+}
+
+void* GLContextEGL::GetHandle() {
+ return context_;
+}
+
+void GLContextEGL::SetSwapInterval(int interval) {
+ DCHECK(IsCurrent(NULL));
+ if (!eglSwapInterval(display_, interval)) {
+ LOG(ERROR) << "eglSwapInterval failed with error "
+ << GetLastEGLErrorString();
+ }
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_context_egl.h b/ui/gl/gl_context_egl.h
new file mode 100644
index 0000000..4e98da8
--- /dev/null
+++ b/ui/gl/gl_context_egl.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_CONTEXT_EGL_H_
+#define UI_GL_GL_CONTEXT_EGL_H_
+#pragma once
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "ui/gl/gl_context.h"
+
+typedef void* EGLContext;
+typedef void* EGLDisplay;
+typedef void* EGLConfig;
+
+namespace gfx {
+
+class GLSurface;
+
+// Encapsulates an EGL OpenGL ES context.
+class GLContextEGL : public GLContext {
+ public:
+ explicit GLContextEGL(GLShareGroup* share_group);
+ virtual ~GLContextEGL();
+
+ // Implement GLContext.
+ virtual bool Initialize(
+ GLSurface* compatible_surface, GpuPreference gpu_preference) OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool MakeCurrent(GLSurface* surface) OVERRIDE;
+ virtual void ReleaseCurrent(GLSurface* surface) OVERRIDE;
+ virtual bool IsCurrent(GLSurface* surface) OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+ virtual void SetSwapInterval(int interval) OVERRIDE;
+ virtual std::string GetExtensions() OVERRIDE;
+
+ private:
+ EGLContext context_;
+ EGLDisplay display_;
+ EGLConfig config_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLContextEGL);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_CONTEXT_EGL_H_
diff --git a/ui/gl/gl_context_glx.cc b/ui/gl/gl_context_glx.cc
new file mode 100644
index 0000000..af94040
--- /dev/null
+++ b/ui/gl/gl_context_glx.cc
@@ -0,0 +1,253 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+extern "C" {
+#include <X11/Xlib.h>
+}
+
+#include "ui/gl/gl_context_glx.h"
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/mesa/MesaLib/include/GL/osmesa.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_glx.h"
+
+namespace gfx {
+
+namespace {
+
+// scoped_ptr functor for XFree(). Use as follows:
+// scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...);
+// where "XVisualInfo" is any X type that is freed with XFree.
+class ScopedPtrXFree {
+ public:
+ void operator()(void* x) const {
+ ::XFree(x);
+ }
+};
+
+} // namespace anonymous
+
+GLContextGLX::GLContextGLX(GLShareGroup* share_group)
+ : GLContext(share_group),
+ context_(NULL),
+ display_(NULL) {
+}
+
+GLContextGLX::~GLContextGLX() {
+ Destroy();
+}
+
+Display* GLContextGLX::display() {
+ return display_;
+}
+
+bool GLContextGLX::Initialize(
+ GLSurface* compatible_surface, GpuPreference gpu_preference) {
+ display_ = static_cast<Display*>(compatible_surface->GetDisplay());
+
+ GLXContext share_handle = static_cast<GLXContext>(
+ share_group() ? share_group()->GetHandle() : NULL);
+
+ if (GLSurfaceGLX::IsCreateContextRobustnessSupported()) {
+ DLOG(INFO) << "GLX_ARB_create_context_robustness supported.";
+
+ std::vector<int> attribs;
+ attribs.push_back(GLX_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB);
+ attribs.push_back(GLX_LOSE_CONTEXT_ON_RESET_ARB);
+ attribs.push_back(0);
+ context_ = glXCreateContextAttribsARB(
+ display_,
+ static_cast<GLXFBConfig>(compatible_surface->GetConfig()),
+ share_handle,
+ True,
+ &attribs.front());
+ if (context_) {
+ DLOG(INFO) << " Successfully allocated "
+ << (compatible_surface->IsOffscreen() ?
+ "offscreen" : "onscreen")
+ << " GL context with LOSE_CONTEXT_ON_RESET_ARB";
+ } else {
+ // TODO(kbr): it is not expected that things will work properly
+ // in this case, since we will likely allocate our offscreen
+ // contexts with this bit set and the onscreen contexts without,
+ // and won't be able to put them in the same share group.
+ // Consider what to do here; force loss of all contexts and
+ // reallocation without ARB_robustness?
+ LOG(ERROR) <<
+ " FAILED to allocate GL context with LOSE_CONTEXT_ON_RESET_ARB";
+ }
+ }
+
+ if (!context_) {
+ // The means by which the context is created depends on whether
+ // the drawable type works reliably with GLX 1.3. If it does not
+ // then fall back to GLX 1.2.
+ if (compatible_surface->IsOffscreen()) {
+ context_ = glXCreateNewContext(
+ display_,
+ static_cast<GLXFBConfig>(compatible_surface->GetConfig()),
+ GLX_RGBA_TYPE,
+ share_handle,
+ True);
+ } else {
+ // Get the visuals for the X drawable.
+ XWindowAttributes attributes;
+ if (!XGetWindowAttributes(
+ display_,
+ reinterpret_cast<GLXDrawable>(compatible_surface->GetHandle()),
+ &attributes)) {
+ LOG(ERROR) << "XGetWindowAttributes failed for window " <<
+ reinterpret_cast<GLXDrawable>(
+ compatible_surface->GetHandle()) << ".";
+ return false;
+ }
+
+ XVisualInfo visual_info_template;
+ visual_info_template.visualid = XVisualIDFromVisual(attributes.visual);
+
+ int visual_info_count = 0;
+ scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info_list(
+ XGetVisualInfo(display_, VisualIDMask,
+ &visual_info_template,
+ &visual_info_count));
+
+ DCHECK(visual_info_list.get());
+ if (visual_info_count == 0) {
+ LOG(ERROR) << "No visual info for visual ID.";
+ return false;
+ }
+
+ // Attempt to create a context with each visual in turn until one works.
+ context_ = glXCreateContext(
+ display_,
+ visual_info_list.get(),
+ share_handle,
+ True);
+ }
+ }
+
+ if (!context_) {
+ LOG(ERROR) << "Couldn't create GL context.";
+ return false;
+ }
+
+ DLOG(INFO) << (compatible_surface->IsOffscreen() ? "Offscreen" : "Onscreen")
+ << " context was "
+ << (glXIsDirect(display_,
+ static_cast<GLXContext>(context_))
+ ? "direct" : "indirect")
+ << ".";
+
+ return true;
+}
+
+void GLContextGLX::Destroy() {
+ if (context_) {
+ glXDestroyContext(display_,
+ static_cast<GLXContext>(context_));
+ context_ = NULL;
+ }
+}
+
+bool GLContextGLX::MakeCurrent(GLSurface* surface) {
+ DCHECK(context_);
+ if (IsCurrent(surface))
+ return true;
+
+ TRACE_EVENT0("gpu", "GLContextGLX::MakeCurrent");
+ if (!glXMakeCurrent(
+ display_,
+ reinterpret_cast<GLXDrawable>(surface->GetHandle()),
+ static_cast<GLXContext>(context_))) {
+ LOG(ERROR) << "Couldn't make context current with X drawable.";
+ Destroy();
+ return false;
+ }
+
+ SetCurrent(this, surface);
+ if (!InitializeExtensionBindings()) {
+ ReleaseCurrent(surface);
+ Destroy();
+ return false;
+ }
+
+ if (!surface->OnMakeCurrent(this)) {
+ LOG(ERROR) << "Could not make current.";
+ ReleaseCurrent(surface);
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void GLContextGLX::ReleaseCurrent(GLSurface* surface) {
+ if (!IsCurrent(surface))
+ return;
+
+ SetCurrent(NULL, NULL);
+ if (!glXMakeCurrent(display_, 0, 0))
+ LOG(ERROR) << "glXMakeCurrent failed in ReleaseCurrent";
+}
+
+bool GLContextGLX::IsCurrent(GLSurface* surface) {
+ bool native_context_is_current =
+ glXGetCurrentContext() == static_cast<GLXContext>(context_);
+
+ // If our context is current then our notion of which GLContext is
+ // current must be correct. On the other hand, third-party code
+ // using OpenGL might change the current context.
+ DCHECK(!native_context_is_current || (GetCurrent() == this));
+
+ if (!native_context_is_current)
+ return false;
+
+ if (surface) {
+ if (glXGetCurrentDrawable() !=
+ reinterpret_cast<GLXDrawable>(surface->GetHandle())) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void* GLContextGLX::GetHandle() {
+ return context_;
+}
+
+void GLContextGLX::SetSwapInterval(int interval) {
+ DCHECK(IsCurrent(NULL));
+ if (HasExtension("GLX_EXT_swap_control") && glXSwapIntervalEXT) {
+ glXSwapIntervalEXT(
+ display_,
+ glXGetCurrentDrawable(),
+ interval);
+ } else {
+ if(interval == 0)
+ LOG(WARNING) <<
+ "Could not disable vsync: driver does not "
+ "support GLX_EXT_swap_control";
+ }
+}
+
+std::string GLContextGLX::GetExtensions() {
+ DCHECK(IsCurrent(NULL));
+ const char* extensions = GLSurfaceGLX::GetGLXExtensions();
+ if (extensions) {
+ return GLContext::GetExtensions() + " " + extensions;
+ }
+
+ return GLContext::GetExtensions();
+}
+
+bool GLContextGLX::WasAllocatedUsingARBRobustness() {
+ return GLSurfaceGLX::IsCreateContextRobustnessSupported();
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_context_glx.h b/ui/gl/gl_context_glx.h
new file mode 100644
index 0000000..60155df
--- /dev/null
+++ b/ui/gl/gl_context_glx.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_CONTEXT_GLX_H_
+#define UI_GL_GL_CONTEXT_GLX_H_
+#pragma once
+
+#include <string>
+
+#include "base/compiler_specific.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gl/gl_context.h"
+
+namespace gfx {
+
+class GLSurface;
+
+// Encapsulates a GLX OpenGL context.
+class GLContextGLX : public GLContext {
+ public:
+ explicit GLContextGLX(GLShareGroup* share_group);
+ virtual ~GLContextGLX();
+
+ Display* display();
+
+ // Implement GLContext.
+ virtual bool Initialize(
+ GLSurface* compatible_surface, GpuPreference gpu_preference) OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool MakeCurrent(GLSurface* surface) OVERRIDE;
+ virtual void ReleaseCurrent(GLSurface* surface) OVERRIDE;
+ virtual bool IsCurrent(GLSurface* surface) OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+ virtual void SetSwapInterval(int interval) OVERRIDE;
+ virtual std::string GetExtensions() OVERRIDE;
+ virtual bool WasAllocatedUsingARBRobustness() OVERRIDE;
+
+ private:
+ void* context_;
+ Display* display_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLContextGLX);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_CONTEXT_GLX_H_
diff --git a/ui/gl/gl_context_linux.cc b/ui/gl/gl_context_linux.cc
new file mode 100644
index 0000000..2b5d16f
--- /dev/null
+++ b/ui/gl/gl_context_linux.cc
@@ -0,0 +1,63 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_context.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/mesa/MesaLib/include/GL/osmesa.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context_egl.h"
+#include "ui/gl/gl_context_glx.h"
+#include "ui/gl/gl_context_osmesa.h"
+#include "ui/gl/gl_context_stub.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/gl_surface_glx.h"
+#include "ui/gl/gl_surface_osmesa.h"
+#include "ui/gl/gl_surface_stub.h"
+
+namespace gfx {
+
+class GLShareGroup;
+
+scoped_refptr<GLContext> GLContext::CreateGLContext(
+ GLShareGroup* share_group,
+ GLSurface* compatible_surface,
+ GpuPreference gpu_preference) {
+ switch (GetGLImplementation()) {
+ case kGLImplementationOSMesaGL: {
+ scoped_refptr<GLContext> context(new GLContextOSMesa(share_group));
+ if (!context->Initialize(compatible_surface, gpu_preference))
+ return NULL;
+
+ return context;
+ }
+ case kGLImplementationDesktopGL: {
+ scoped_refptr<GLContext> context(new GLContextGLX(share_group));
+ if (!context->Initialize(compatible_surface, gpu_preference))
+ return NULL;
+
+ return context;
+ }
+ case kGLImplementationEGLGLES2: {
+ scoped_refptr<GLContext> context(new GLContextEGL(share_group));
+ if (!context->Initialize(compatible_surface, gpu_preference))
+ return NULL;
+
+ return context;
+ }
+ case kGLImplementationMockGL:
+ return new GLContextStub;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+bool GLContext::SupportsDualGpus() {
+ return false;
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_context_mac.mm b/ui/gl/gl_context_mac.mm
new file mode 100644
index 0000000..06829be
--- /dev/null
+++ b/ui/gl/gl_context_mac.mm
@@ -0,0 +1,184 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+#include "base/mac/mac_util.h"
+#include "base/memory/scoped_generic_obj.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/mesa/MesaLib/include/GL/osmesa.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context_cgl.h"
+#include "ui/gl/gl_context_osmesa.h"
+#include "ui/gl/gl_context_stub.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/gl/gl_switches.h"
+
+#if defined(USE_AURA)
+#include "ui/gl/gl_context_nsview.h"
+#endif
+
+namespace {
+
+// ScopedGenericObj functor for CGLDestroyRendererInfo().
+class ScopedDestroyRendererInfo {
+ public:
+ void operator()(CGLRendererInfoObj x) const {
+ CGLDestroyRendererInfo(x);
+ }
+};
+
+} // namespace
+
+namespace gfx {
+
+class GLShareGroup;
+
+scoped_refptr<GLContext> GLContext::CreateGLContext(
+ GLShareGroup* share_group,
+ GLSurface* compatible_surface,
+ GpuPreference gpu_preference) {
+ switch (GetGLImplementation()) {
+ case kGLImplementationDesktopGL:
+ case kGLImplementationAppleGL: {
+ scoped_refptr<GLContext> context;
+#if defined(USE_AURA)
+ if (compatible_surface->IsOffscreen())
+ context = new GLContextCGL(share_group);
+ else
+ context = new GLContextNSView(share_group);
+#else
+ context = new GLContextCGL(share_group);
+#endif // USE_AURA
+ if (!context->Initialize(compatible_surface, gpu_preference))
+ return NULL;
+
+ return context;
+ }
+ case kGLImplementationOSMesaGL: {
+ scoped_refptr<GLContext> context(new GLContextOSMesa(share_group));
+ if (!context->Initialize(compatible_surface, gpu_preference))
+ return NULL;
+
+ return context;
+ }
+ case kGLImplementationMockGL:
+ return new GLContextStub;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+bool GLContext::SupportsDualGpus() {
+ // We need to know the GL implementation in order to correctly
+ // answer whether dual GPUs are supported. This introduces an
+ // initialization cycle with GLSurface::InitializeOneOff() which we
+ // need to break.
+ static bool initialized = false;
+ static bool initializing = false;
+ static bool supports_dual_gpus = false;
+
+ if (initialized) {
+ return supports_dual_gpus;
+ } else {
+ if (!initializing) {
+ initializing = true;
+ if (!GLSurface::InitializeOneOff()) {
+ return false;
+ }
+ }
+ initialized = true;
+ }
+
+ if (!base::mac::IsOSLionOrLater()) {
+ return false;
+ }
+
+ if (GetGLImplementation() != kGLImplementationDesktopGL) {
+ return false;
+ }
+
+ // Enumerate all hardware-accelerated renderers. If we find one
+ // online and one offline, assume we're on a dual-GPU system.
+ GLuint display_mask = static_cast<GLuint>(-1);
+ CGLRendererInfoObj renderer_info = NULL;
+ GLint num_renderers = 0;
+
+ bool found_online = false;
+ bool found_offline = false;
+
+ if (CGLQueryRendererInfo(display_mask,
+ &renderer_info,
+ &num_renderers) != kCGLNoError) {
+ return false;
+ }
+
+ ScopedGenericObj<CGLRendererInfoObj, ScopedDestroyRendererInfo>
+ scoper(renderer_info);
+
+ for (GLint i = 0; i < num_renderers; ++i) {
+ GLint accelerated = 0;
+ if (CGLDescribeRenderer(renderer_info,
+ i,
+ kCGLRPAccelerated,
+ &accelerated) != kCGLNoError) {
+ return false;
+ }
+
+ if (!accelerated)
+ continue;
+
+ GLint online = 0;
+ if (CGLDescribeRenderer(renderer_info,
+ i,
+ kCGLRPOnline,
+ &online) != kCGLNoError) {
+ return false;
+ }
+
+ if (online) {
+ found_online = true;
+ } else {
+ found_offline = true;
+ }
+ }
+
+ if (found_online && found_offline) {
+ // Only switch GPUs dynamically on recent MacBook Pro models.
+ // Otherwise, keep the system on the discrete GPU for the lifetime
+ // of the browser process, since switching back and forth causes
+ // system stability issues. http://crbug.com/113703
+ std::string model;
+ int32 model_major, model_minor;
+ if (!base::mac::ParseModelIdentifier(base::mac::GetModelIdentifier(),
+ &model, &model_major, &model_minor)) {
+ return false;
+ }
+
+ const int kMacBookProFirstDualAMDIntelGPUModel = 8;
+
+ bool forcibly_disable =
+ ((model == "MacBookPro") &&
+ (model_major < kMacBookProFirstDualAMDIntelGPUModel)) ||
+ CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableGpuSwitching) ||
+ // http://crbug.com/127713 : disable dynamic GPU switching on
+ // 10.8 until system stability issues are resolved by Apple.
+ base::mac::IsOSMountainLion();
+
+ if (forcibly_disable) {
+ GLContextCGL::ForceUseOfDiscreteGPU();
+ return false;
+ }
+
+ supports_dual_gpus = true;
+ }
+
+ return supports_dual_gpus;
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_context_nsview.h b/ui/gl/gl_context_nsview.h
new file mode 100644
index 0000000..3c54157f
--- /dev/null
+++ b/ui/gl/gl_context_nsview.h
@@ -0,0 +1,48 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_CONTEXT_NSVIEW_H_
+#define UI_GL_GL_CONTEXT_NSVIEW_H_
+#pragma once
+
+#import <AppKit/NSOpenGL.h>
+
+#include "base/compiler_specific.h"
+#include "base/memory/scoped_nsobject.h"
+#include "ui/gl/gl_context.h"
+
+namespace gfx {
+
+class GLSurface;
+
+// GLContextNSView encapsulates an NSView-based GLContext. This is paired with
+// the GLSurfaceNSView class.
+class GLContextNSView : public GLContext {
+ public:
+ explicit GLContextNSView(GLShareGroup* group);
+ virtual ~GLContextNSView();
+
+ // GLContext:
+ virtual bool Initialize(GLSurface* surface,
+ GpuPreference gpu_preference) OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool MakeCurrent(GLSurface* surface) OVERRIDE;
+ virtual void ReleaseCurrent(GLSurface* surface) OVERRIDE;
+ virtual bool IsCurrent(GLSurface* surface) OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+ virtual void SetSwapInterval(int interval) OVERRIDE;
+
+ // Flush the |context_|. Swaps buffers.
+ void FlushBuffer();
+
+ private:
+ scoped_nsobject<NSOpenGLContext> context_;
+ GpuPreference gpu_preference_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLContextNSView);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_CONTEXT_NSVIEW_H_
diff --git a/ui/gl/gl_context_nsview.mm b/ui/gl/gl_context_nsview.mm
new file mode 100644
index 0000000..898bf01
--- /dev/null
+++ b/ui/gl/gl_context_nsview.mm
@@ -0,0 +1,99 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_context_nsview.h"
+
+#include <vector>
+
+#import <AppKit/NSOpenGL.h>
+#import <AppKit/NSView.h>
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "ui/gl/gl_surface_nsview.h"
+
+namespace gfx {
+
+GLContextNSView::GLContextNSView(GLShareGroup* group)
+ : GLContext(group) {
+}
+
+GLContextNSView::~GLContextNSView() {
+}
+
+bool GLContextNSView::Initialize(GLSurface* surface,
+ GpuPreference gpu_preference) {
+ DCHECK(!context_) << "NSGLContext was previously initialized.";
+ gpu_preference_ = gpu_preference;
+
+ std::vector<NSOpenGLPixelFormatAttribute> attributes;
+ attributes.push_back(NSOpenGLPFAAccelerated);
+ attributes.push_back(NSOpenGLPFADoubleBuffer);
+ attributes.push_back(0);
+
+ scoped_nsobject<NSOpenGLPixelFormat> pixel_format;
+ pixel_format.reset([[NSOpenGLPixelFormat alloc]
+ initWithAttributes:&attributes.front()]);
+ if (!pixel_format) {
+ LOG(ERROR) << "NSOpenGLPixelFormat initWithAttributes failed.";
+ return false;
+ }
+
+ context_.reset([[NSOpenGLContext alloc] initWithFormat:pixel_format
+ shareContext:nil]);
+ if (!context_) {
+ LOG(ERROR) << "NSOpenGLContext initWithFormat failed";
+ return false;
+ }
+
+ return true;
+}
+
+void GLContextNSView::Destroy() {
+ context_.reset(nil);
+}
+
+bool GLContextNSView::MakeCurrent(GLSurface* surface) {
+ TRACE_EVENT0("gpu", "GLContextNSView::MakeCurrent");
+ AcceleratedWidget view =
+ static_cast<AcceleratedWidget>(surface->GetHandle());
+ // Only set the context's view if the view is parented.
+ // I.e. it is a valid drawable.
+ if ([view window])
+ [context_ setView:view];
+ [context_ makeCurrentContext];
+
+ SetCurrent(this, surface);
+
+ if (!surface->OnMakeCurrent(this)) {
+ LOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+
+ return true;
+}
+
+void GLContextNSView::ReleaseCurrent(GLSurface* surface) {
+ [NSOpenGLContext clearCurrentContext];
+}
+
+bool GLContextNSView::IsCurrent(GLSurface* surface) {
+ return context_ == [NSOpenGLContext currentContext];
+}
+
+void* GLContextNSView::GetHandle() {
+ return context_;
+}
+
+void GLContextNSView::SetSwapInterval(int interval) {
+ DCHECK(interval == 0 || interval == 1);
+ GLint swap = interval;
+ [context_ setValues:&swap forParameter:NSOpenGLCPSwapInterval];
+}
+
+void GLContextNSView::FlushBuffer() {
+ [context_ flushBuffer];
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_context_osmesa.cc b/ui/gl/gl_context_osmesa.cc
new file mode 100644
index 0000000..1787ef9
--- /dev/null
+++ b/ui/gl/gl_context_osmesa.cc
@@ -0,0 +1,130 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_context_osmesa.h"
+
+#include <GL/osmesa.h>
+
+#include "base/logging.h"
+#include "ui/gfx/size.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_surface.h"
+
+namespace gfx {
+
+GLContextOSMesa::GLContextOSMesa(GLShareGroup* share_group)
+ : GLContext(share_group),
+ context_(NULL) {
+}
+
+bool GLContextOSMesa::Initialize(GLSurface* compatible_surface,
+ GpuPreference gpu_preference) {
+ DCHECK(!context_);
+
+ OSMesaContext share_handle = static_cast<OSMesaContext>(
+ share_group() ? share_group()->GetHandle() : NULL);
+
+ GLuint format = compatible_surface->GetFormat();
+ DCHECK_NE(format, (unsigned)0);
+ context_ = OSMesaCreateContextExt(format,
+ 0, // depth bits
+ 0, // stencil bits
+ 0, // accum bits
+ share_handle);
+ if (!context_) {
+ LOG(ERROR) << "OSMesaCreateContextExt failed.";
+ return false;
+ }
+
+ return true;
+}
+
+void GLContextOSMesa::Destroy() {
+ if (context_) {
+ OSMesaDestroyContext(static_cast<OSMesaContext>(context_));
+ context_ = NULL;
+ }
+}
+
+bool GLContextOSMesa::MakeCurrent(GLSurface* surface) {
+ DCHECK(context_);
+
+ gfx::Size size = surface->GetSize();
+
+ if (!OSMesaMakeCurrent(context_,
+ surface->GetHandle(),
+ GL_UNSIGNED_BYTE,
+ size.width(),
+ size.height())) {
+ LOG(ERROR) << "OSMesaMakeCurrent failed.";
+ Destroy();
+ return false;
+ }
+
+ // Row 0 is at the top.
+ 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;
+ }
+
+ return true;
+}
+
+void GLContextOSMesa::ReleaseCurrent(GLSurface* surface) {
+ if (!IsCurrent(surface))
+ return;
+
+ SetCurrent(NULL, NULL);
+ OSMesaMakeCurrent(NULL, NULL, GL_UNSIGNED_BYTE, 0, 0);
+}
+
+bool GLContextOSMesa::IsCurrent(GLSurface* surface) {
+ DCHECK(context_);
+
+ bool native_context_is_current =
+ context_ == OSMesaGetCurrentContext();
+
+ // If our context is current then our notion of which GLContext is
+ // current must be correct. On the other hand, third-party code
+ // using OpenGL might change the current context.
+ DCHECK(!native_context_is_current || (GetCurrent() == this));
+
+ if (!native_context_is_current)
+ return false;
+
+ if (surface) {
+ GLint width;
+ GLint height;
+ GLint format;
+ void* buffer = NULL;
+ OSMesaGetColorBuffer(context_, &width, &height, &format, &buffer);
+ if (buffer != surface->GetHandle())
+ return false;
+ }
+
+ return true;
+}
+
+void* GLContextOSMesa::GetHandle() {
+ return context_;
+}
+
+void GLContextOSMesa::SetSwapInterval(int interval) {
+ DCHECK(IsCurrent(NULL));
+ LOG(WARNING) << "GLContextOSMesa::SetSwapInterval is ignored.";
+}
+
+GLContextOSMesa::~GLContextOSMesa() {
+ Destroy();
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_context_osmesa.h b/ui/gl/gl_context_osmesa.h
new file mode 100644
index 0000000..cef3fd9
--- /dev/null
+++ b/ui/gl/gl_context_osmesa.h
@@ -0,0 +1,46 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_CONTEXT_OSMESA_H_
+#define UI_GL_GL_CONTEXT_OSMESA_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "base/compiler_specific.h"
+#include "ui/gl/gl_context.h"
+
+typedef struct osmesa_context* OSMesaContext;
+
+namespace gfx {
+
+class GLShareGroup;
+class GLSurface;
+
+// Encapsulates an OSMesa OpenGL context that uses software rendering.
+class GLContextOSMesa : public GLContext {
+ public:
+ explicit GLContextOSMesa(GLShareGroup* share_group);
+
+ // Implement GLContext.
+ virtual bool Initialize(GLSurface* compatible_surface,
+ GpuPreference gpu_preference) OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool MakeCurrent(GLSurface* surface) OVERRIDE;
+ virtual void ReleaseCurrent(GLSurface* surface) OVERRIDE;
+ virtual bool IsCurrent(GLSurface* surface) OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+ virtual void SetSwapInterval(int interval) OVERRIDE;
+
+ protected:
+ virtual ~GLContextOSMesa();
+
+ private:
+ OSMesaContext context_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLContextOSMesa);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_CONTEXT_OSMESA_H_
diff --git a/ui/gl/gl_context_stub.cc b/ui/gl/gl_context_stub.cc
new file mode 100644
index 0000000..d1364c4
--- /dev/null
+++ b/ui/gl/gl_context_stub.cc
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_context_stub.h"
+
+namespace gfx {
+
+GLContextStub::GLContextStub() : GLContext(NULL) {}
+
+bool GLContextStub::Initialize(
+ GLSurface* compatible_surface, GpuPreference gpu_preference) {
+ return true;
+}
+
+void GLContextStub::Destroy() {}
+
+bool GLContextStub::MakeCurrent(GLSurface* surface) {
+ SetCurrent(this, surface);
+ return true;
+}
+
+void GLContextStub::ReleaseCurrent(GLSurface* surface) {
+}
+
+bool GLContextStub::IsCurrent(GLSurface* surface) {
+ return true;
+}
+
+void* GLContextStub::GetHandle() {
+ return NULL;
+}
+
+void GLContextStub::SetSwapInterval(int interval) {
+}
+
+std::string GLContextStub::GetExtensions() {
+ return std::string();
+}
+
+GLContextStub::~GLContextStub() {}
+
+} // namespace gfx
diff --git a/ui/gl/gl_context_stub.h b/ui/gl/gl_context_stub.h
new file mode 100644
index 0000000..a602f4b
--- /dev/null
+++ b/ui/gl/gl_context_stub.h
@@ -0,0 +1,38 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_CONTEXT_STUB_H_
+#define UI_GL_GL_CONTEXT_STUB_H_
+#pragma once
+
+#include "ui/gl/gl_context.h"
+
+namespace gfx {
+
+// A GLContext that does nothing for unit tests.
+class GL_EXPORT GLContextStub : public GLContext {
+ public:
+ GLContextStub();
+
+ // Implement GLContext.
+ virtual bool Initialize(GLSurface* compatible_surface,
+ GpuPreference gpu_preference) OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool MakeCurrent(GLSurface* surface) OVERRIDE;
+ virtual void ReleaseCurrent(GLSurface* surface) OVERRIDE;
+ virtual bool IsCurrent(GLSurface* surface) OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+ virtual void SetSwapInterval(int interval) OVERRIDE;
+ virtual std::string GetExtensions() OVERRIDE;
+
+ protected:
+ virtual ~GLContextStub();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLContextStub);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_CONTEXT_STUB_H_
diff --git a/ui/gl/gl_context_wgl.cc b/ui/gl/gl_context_wgl.cc
new file mode 100644
index 0000000..e6b8307
--- /dev/null
+++ b/ui/gl/gl_context_wgl.cc
@@ -0,0 +1,141 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// This file implements the GLContextWGL and PbufferGLContext classes.
+
+#include "ui/gl/gl_context_wgl.h"
+
+#include "base/debug/trace_event.h"
+#include "base/logging.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_wgl.h"
+
+namespace gfx {
+
+GLContextWGL::GLContextWGL(GLShareGroup* share_group)
+ : GLContext(share_group),
+ context_(NULL) {
+}
+
+GLContextWGL::~GLContextWGL() {
+ Destroy();
+}
+
+std::string GLContextWGL::GetExtensions() {
+ const char* extensions = NULL;
+ if (wglGetExtensionsStringARB)
+ extensions = wglGetExtensionsStringARB(GLSurfaceWGL::GetDisplayDC());
+ else if (wglGetExtensionsStringEXT)
+ extensions = wglGetExtensionsStringEXT();
+
+ if (extensions)
+ return GLContext::GetExtensions() + " " + extensions;
+
+ return GLContext::GetExtensions();
+}
+
+bool GLContextWGL::Initialize(
+ GLSurface* compatible_surface, GpuPreference gpu_preference) {
+ // Get the handle of another initialized context in the share group _before_
+ // setting context_. Otherwise this context will be considered initialized
+ // and could potentially be returned by GetHandle.
+ HGLRC share_handle = static_cast<HGLRC>(share_group()->GetHandle());
+
+ context_ = wglCreateContext(
+ static_cast<HDC>(compatible_surface->GetHandle()));
+ if (!context_) {
+ LOG(ERROR) << "Failed to create GL context.";
+ Destroy();
+ return false;
+ }
+
+ if (share_handle) {
+ if (!wglShareLists(share_handle, context_)) {
+ LOG(ERROR) << "Could not share GL contexts.";
+ Destroy();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+void GLContextWGL::Destroy() {
+ if (context_) {
+ wglDeleteContext(context_);
+ context_ = NULL;
+ }
+}
+
+bool GLContextWGL::MakeCurrent(GLSurface* surface) {
+ DCHECK(context_);
+ if (IsCurrent(surface))
+ return true;
+
+ TRACE_EVENT0("gpu", "GLContextWGL::MakeCurrent");
+
+ if (!wglMakeCurrent(static_cast<HDC>(surface->GetHandle()), context_)) {
+ LOG(ERROR) << "Unable to make gl context current.";
+ return false;
+ }
+
+ SetCurrent(this, surface);
+ if (!InitializeExtensionBindings()) {
+ ReleaseCurrent(surface);
+ return false;
+ }
+
+ if (!surface->OnMakeCurrent(this)) {
+ LOG(ERROR) << "Could not make current.";
+ return false;
+ }
+
+ return true;
+}
+
+void GLContextWGL::ReleaseCurrent(GLSurface* surface) {
+ if (!IsCurrent(surface))
+ return;
+
+ SetCurrent(NULL, NULL);
+ wglMakeCurrent(NULL, NULL);
+}
+
+bool GLContextWGL::IsCurrent(GLSurface* surface) {
+ bool native_context_is_current =
+ wglGetCurrentContext() == context_;
+
+ // If our context is current then our notion of which GLContext is
+ // current must be correct. On the other hand, third-party code
+ // using OpenGL might change the current context.
+ DCHECK(!native_context_is_current || (GetCurrent() == this));
+
+ if (!native_context_is_current)
+ return false;
+
+ if (surface) {
+ if (wglGetCurrentDC() != surface->GetHandle())
+ return false;
+ }
+
+ return true;
+}
+
+void* GLContextWGL::GetHandle() {
+ return context_;
+}
+
+void GLContextWGL::SetSwapInterval(int interval) {
+ DCHECK(IsCurrent(NULL));
+ if (gfx::g_WGL_EXT_swap_control) {
+ wglSwapIntervalEXT(interval);
+ } else {
+ LOG(WARNING) <<
+ "Could not disable vsync: driver does not "
+ "support WGL_EXT_swap_control";
+ }
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_context_wgl.h b/ui/gl/gl_context_wgl.h
new file mode 100644
index 0000000..1fc6177
--- /dev/null
+++ b/ui/gl/gl_context_wgl.h
@@ -0,0 +1,43 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_CONTEXT_WGL_H_
+#define UI_GL_GL_CONTEXT_WGL_H_
+#pragma once
+
+#include <string>
+
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gl/gl_context.h"
+
+namespace gfx {
+
+class GLSurface;
+
+// This class is a wrapper around a GL context.
+class GLContextWGL : public GLContext {
+ public:
+ explicit GLContextWGL(GLShareGroup* share_group);
+ virtual ~GLContextWGL();
+
+ // Implement GLContext.
+ virtual bool Initialize(
+ GLSurface* compatible_surface, GpuPreference gpu_preference);
+ virtual void Destroy();
+ virtual bool MakeCurrent(GLSurface* surface);
+ virtual void ReleaseCurrent(GLSurface* surface);
+ virtual bool IsCurrent(GLSurface* surface);
+ virtual void* GetHandle();
+ virtual void SetSwapInterval(int interval);
+ virtual std::string GetExtensions();
+
+ private:
+ HGLRC context_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLContextWGL);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_CONTEXT_WGL_H_
diff --git a/ui/gl/gl_context_win.cc b/ui/gl/gl_context_win.cc
new file mode 100644
index 0000000..c42daa9
--- /dev/null
+++ b/ui/gl/gl_context_win.cc
@@ -0,0 +1,61 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_context.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/mesa/MesaLib/include/GL/osmesa.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context_egl.h"
+#include "ui/gl/gl_context_osmesa.h"
+#include "ui/gl/gl_context_stub.h"
+#include "ui/gl/gl_context_wgl.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/gl_surface_osmesa.h"
+#include "ui/gl/gl_surface_stub.h"
+#include "ui/gl/gl_surface_wgl.h"
+
+namespace gfx {
+
+scoped_refptr<GLContext> GLContext::CreateGLContext(
+ GLShareGroup* share_group,
+ GLSurface* compatible_surface,
+ GpuPreference gpu_preference) {
+ switch (GetGLImplementation()) {
+ case kGLImplementationOSMesaGL: {
+ scoped_refptr<GLContext> context(new GLContextOSMesa(share_group));
+ if (!context->Initialize(compatible_surface, gpu_preference))
+ return NULL;
+
+ return context;
+ }
+ case kGLImplementationEGLGLES2: {
+ scoped_refptr<GLContext> context(new GLContextEGL(share_group));
+ if (!context->Initialize(compatible_surface, gpu_preference))
+ return NULL;
+
+ return context;
+ }
+ case kGLImplementationDesktopGL: {
+ scoped_refptr<GLContext> context(new GLContextWGL(share_group));
+ if (!context->Initialize(compatible_surface, gpu_preference))
+ return NULL;
+
+ return context;
+ }
+ case kGLImplementationMockGL:
+ return new GLContextStub;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+bool GLContext::SupportsDualGpus() {
+ return false;
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_export.h b/ui/gl/gl_export.h
new file mode 100644
index 0000000..30e6979
--- /dev/null
+++ b/ui/gl/gl_export.h
@@ -0,0 +1,26 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_EXPORT_H_
+#define UI_GL_GL_EXPORT_H_
+#pragma once
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(GL_IMPLEMENTATION)
+#define GL_EXPORT __declspec(dllexport)
+#else
+#define GL_EXPORT __declspec(dllimport)
+#endif // defined(GL_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#define GL_EXPORT __attribute__((visibility("default")))
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define GL_EXPORT
+#endif
+
+#endif // UI_GL_GL_EXPORT_H_
diff --git a/ui/gl/gl_fence.cc b/ui/gl/gl_fence.cc
new file mode 100644
index 0000000..82cdf30
--- /dev/null
+++ b/ui/gl/gl_fence.cc
@@ -0,0 +1,108 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_fence.h"
+
+#include "base/compiler_specific.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+
+namespace {
+
+class GLFenceNVFence: public gfx::GLFence {
+ public:
+ GLFenceNVFence() {
+ // What if either of these GL calls fails? TestFenceNV will return true.
+ // See spec:
+ // http://www.opengl.org/registry/specs/NV/fence.txt
+ //
+ // What should happen if TestFenceNV is called for a name before SetFenceNV
+ // is called?
+ // We generate an INVALID_OPERATION error, and return TRUE.
+ // This follows the semantics for texture object names before
+ // they are bound, in that they acquire their state upon binding.
+ // We will arbitrarily return TRUE for consistency.
+ glGenFencesNV(1, &fence_);
+ glSetFenceNV(fence_, GL_ALL_COMPLETED_NV);
+ glFlush();
+ }
+
+ virtual bool HasCompleted() OVERRIDE {
+ return IsContextLost() || glTestFenceNV(fence_);
+ }
+
+ private:
+ ~GLFenceNVFence() {
+ glDeleteFencesNV(1, &fence_);
+ }
+
+ GLuint fence_;
+};
+
+class GLFenceARBSync: public gfx::GLFence {
+ public:
+ GLFenceARBSync() {
+ sync_ = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+ glFlush();
+ }
+
+ virtual bool HasCompleted() OVERRIDE {
+ // Handle the case where FenceSync failed.
+ if (!sync_ || IsContextLost())
+ return true;
+
+ GLsizei length = 0;
+ GLsizei value = 0;
+ glGetSynciv(sync_,
+ GL_SYNC_STATUS,
+ 1, // bufSize
+ &length,
+ &value);
+ return length == 1 && value == GL_SIGNALED;
+ }
+
+ private:
+ ~GLFenceARBSync() {
+ glDeleteSync(sync_);
+ }
+
+ GLsync sync_;
+};
+
+} // namespace
+
+namespace gfx {
+
+GLFence::GLFence() {
+}
+
+GLFence::~GLFence() {
+}
+
+// static
+GLFence* GLFence::Create() {
+ if (gfx::g_GL_NV_fence) {
+ return new GLFenceNVFence();
+ } else if (gfx::g_GL_ARB_sync) {
+ return new GLFenceARBSync();
+ } else {
+ return NULL;
+ }
+}
+
+// static
+bool GLFence::IsContextLost() {
+ if (!gfx::g_GL_ARB_robustness)
+ return false;
+
+ if (!gfx::GLContext::GetCurrent() ||
+ !gfx::GLContext::GetCurrent()->
+ WasAllocatedUsingARBRobustness())
+ return false;
+
+ GLenum status = glGetGraphicsResetStatusARB();
+ return status != GL_NO_ERROR;
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_fence.h b/ui/gl/gl_fence.h
new file mode 100644
index 0000000..62a7116
--- /dev/null
+++ b/ui/gl/gl_fence.h
@@ -0,0 +1,31 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_FENCE_H_
+#define UI_GL_GL_FENCE_H_
+#pragma once
+
+#include "base/basictypes.h"
+#include "ui/gl/gl_export.h"
+
+namespace gfx {
+
+class GL_EXPORT GLFence {
+ public:
+ GLFence();
+ virtual ~GLFence();
+
+ static GLFence* Create();
+ virtual bool HasCompleted() = 0;
+
+ protected:
+ static bool IsContextLost();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLFence);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_FENCE_H_
diff --git a/ui/gl/gl_implementation.cc b/ui/gl/gl_implementation.cc
new file mode 100644
index 0000000..0a10f22
--- /dev/null
+++ b/ui/gl/gl_implementation.cc
@@ -0,0 +1,151 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_implementation.h"
+
+#include <algorithm>
+#include <string>
+
+#include "base/at_exit.h"
+#include "base/command_line.h"
+#include "base/logging.h"
+
+namespace gfx {
+
+namespace {
+
+const struct {
+ const char* name;
+ GLImplementation implementation;
+} kGLImplementationNamePairs[] = {
+ { kGLImplementationDesktopName, kGLImplementationDesktopGL },
+ { kGLImplementationOSMesaName, kGLImplementationOSMesaGL },
+#if defined(OS_MACOSX)
+ { kGLImplementationAppleName, kGLImplementationAppleGL },
+#endif
+ { kGLImplementationEGLName, kGLImplementationEGLGLES2 },
+ { kGLImplementationMockName, kGLImplementationMockGL }
+};
+
+typedef std::vector<base::NativeLibrary> LibraryArray;
+
+GLImplementation g_gl_implementation = kGLImplementationNone;
+LibraryArray* g_libraries;
+GLGetProcAddressProc g_get_proc_address;
+
+void CleanupNativeLibraries(void* unused) {
+ if (g_libraries) {
+ for (LibraryArray::iterator it = g_libraries->begin();
+ it != g_libraries->end(); ++it) {
+ base::UnloadNativeLibrary(*it);
+ }
+ delete g_libraries;
+ g_libraries = NULL;
+ }
+}
+
+bool ExportsCoreFunctionsFromGetProcAddress(GLImplementation implementation) {
+ switch (GetGLImplementation()) {
+ case kGLImplementationDesktopGL:
+ case kGLImplementationOSMesaGL:
+ case kGLImplementationAppleGL:
+ case kGLImplementationMockGL:
+ return true;
+ case kGLImplementationEGLGLES2:
+ return false;
+ default:
+ NOTREACHED();
+ return true;
+ }
+}
+
+}
+
+GLImplementation GetNamedGLImplementation(const std::string& name) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kGLImplementationNamePairs); ++i) {
+ if (name == kGLImplementationNamePairs[i].name)
+ return kGLImplementationNamePairs[i].implementation;
+ }
+
+ return kGLImplementationNone;
+}
+
+const char* GetGLImplementationName(GLImplementation implementation) {
+ for (size_t i = 0; i < ARRAYSIZE_UNSAFE(kGLImplementationNamePairs); ++i) {
+ if (implementation == kGLImplementationNamePairs[i].implementation)
+ return kGLImplementationNamePairs[i].name;
+ }
+
+ return "unknown";
+}
+
+void SetGLImplementation(GLImplementation implementation) {
+ g_gl_implementation = implementation;
+}
+
+GLImplementation GetGLImplementation() {
+ return g_gl_implementation;
+}
+
+bool HasDesktopGLFeatures() {
+ return kGLImplementationDesktopGL == g_gl_implementation ||
+ kGLImplementationOSMesaGL == g_gl_implementation ||
+ kGLImplementationAppleGL == g_gl_implementation;
+}
+
+void AddGLNativeLibrary(base::NativeLibrary library) {
+ DCHECK(library);
+
+ if (!g_libraries) {
+ g_libraries = new LibraryArray;
+ base::AtExitManager::RegisterCallback(CleanupNativeLibraries, NULL);
+ }
+
+ g_libraries->push_back(library);
+}
+
+void UnloadGLNativeLibraries() {
+ CleanupNativeLibraries(NULL);
+}
+
+void SetGLGetProcAddressProc(GLGetProcAddressProc proc) {
+ DCHECK(proc);
+ g_get_proc_address = proc;
+}
+
+void* GetGLCoreProcAddress(const char* name) {
+ DCHECK(g_gl_implementation != kGLImplementationNone);
+
+ if (g_libraries) {
+ for (size_t i = 0; i < g_libraries->size(); ++i) {
+ void* proc = base::GetFunctionPointerFromNativeLibrary((*g_libraries)[i],
+ name);
+ if (proc)
+ return proc;
+ }
+ }
+ if (ExportsCoreFunctionsFromGetProcAddress(g_gl_implementation) &&
+ g_get_proc_address) {
+ void* proc = g_get_proc_address(name);
+ if (proc)
+ return proc;
+ }
+
+ 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/gl/gl_implementation.h b/ui/gl/gl_implementation.h
new file mode 100644
index 0000000..9ee1f2d
--- /dev/null
+++ b/ui/gl/gl_implementation.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_IMPLEMENTATION_H_
+#define UI_GL_GL_IMPLEMENTATION_H_
+#pragma once
+
+#include <string>
+#include <vector>
+
+#include "base/native_library.h"
+#include "build/build_config.h"
+#include "ui/gl/gl_export.h"
+#include "ui/gl/gl_switches.h"
+
+namespace gfx {
+
+class GLContext;
+
+// The GL implementation currently in use.
+enum GLImplementation {
+ kGLImplementationNone,
+ kGLImplementationDesktopGL,
+ kGLImplementationOSMesaGL,
+ kGLImplementationAppleGL,
+ kGLImplementationEGLGLES2,
+ kGLImplementationMockGL
+};
+
+void GetAllowedGLImplementations(std::vector<GLImplementation>* impls);
+
+#if defined(OS_WIN)
+typedef void* (WINAPI *GLGetProcAddressProc)(const char* name);
+#else
+typedef void* (*GLGetProcAddressProc)(const char* name);
+#endif
+
+// 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();
+
+void ClearGLBindings();
+
+// Set the current GL implementation.
+void SetGLImplementation(GLImplementation implementation);
+
+// Get the current GL implementation.
+GL_EXPORT GLImplementation GetGLImplementation();
+
+// Does the underlying GL support all features from Desktop GL 2.0 that were
+// removed from the ES 2.0 spec without requiring specific extension strings.
+GL_EXPORT bool HasDesktopGLFeatures();
+
+// Get the GL implementation with a given name.
+GLImplementation GetNamedGLImplementation(const std::string& name);
+
+// Get the name of a GL implementation.
+const char* GetGLImplementationName(GLImplementation implementation);
+
+// Add a native library to those searched for GL entry points.
+void AddGLNativeLibrary(base::NativeLibrary library);
+
+// Unloads all native libraries.
+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.
+void* GetGLProcAddress(const char* name);
+
+} // namespace gfx
+
+#endif // UI_GL_GL_IMPLEMENTATION_H_
diff --git a/ui/gl/gl_implementation_android.cc b/ui/gl/gl_implementation_android.cc
new file mode 100644
index 0000000..254c037
--- /dev/null
+++ b/ui/gl/gl_implementation_android.cc
@@ -0,0 +1,132 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/base_paths.h"
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/native_library.h"
+#include "base/path_service.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+
+namespace gfx {
+
+namespace {
+
+void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) {
+ glClearDepthf(static_cast<GLclampf>(depth));
+}
+
+void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near,
+ GLclampd z_far) {
+ glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far));
+}
+
+base::NativeLibrary LoadLibrary(const FilePath& filename) {
+ std::string error;
+ base::NativeLibrary library = base::LoadNativeLibrary(filename, &error);
+ if (!library) {
+ DVLOG(1) << "Failed to load " << filename.MaybeAsASCII() << ": " << error;
+ return NULL;
+ }
+ return library;
+}
+
+base::NativeLibrary LoadLibrary(const char* filename) {
+ return LoadLibrary(FilePath(filename));
+}
+
+} // namespace anonymous
+
+void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
+ impls->push_back(kGLImplementationEGLGLES2);
+}
+
+bool InitializeGLBindings(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.
+ if (GetGLImplementation() != kGLImplementationNone)
+ return true;
+
+ switch (implementation) {
+ case kGLImplementationEGLGLES2: {
+ base::NativeLibrary gles_library = LoadLibrary("libGLESv2.so");
+ if (!gles_library)
+ return false;
+ base::NativeLibrary egl_library = LoadLibrary("libEGL.so");
+ if (!egl_library) {
+ base::UnloadNativeLibrary(gles_library);
+ return false;
+ }
+
+ GLGetProcAddressProc get_proc_address =
+ reinterpret_cast<GLGetProcAddressProc>(
+ base::GetFunctionPointerFromNativeLibrary(
+ egl_library, "eglGetProcAddress"));
+ if (!get_proc_address) {
+ LOG(ERROR) << "eglGetProcAddress not found.";
+ base::UnloadNativeLibrary(egl_library);
+ base::UnloadNativeLibrary(gles_library);
+ return false;
+ }
+
+ SetGLGetProcAddressProc(get_proc_address);
+ AddGLNativeLibrary(egl_library);
+ AddGLNativeLibrary(gles_library);
+ SetGLImplementation(kGLImplementationEGLGLES2);
+
+ InitializeGLBindingsGL();
+ InitializeGLBindingsEGL();
+
+ // These two functions take single precision float rather than double
+ // precision float parameters in GLES.
+ ::gfx::g_glClearDepth = MarshalClearDepthToClearDepthf;
+ ::gfx::g_glDepthRange = MarshalDepthRangeToDepthRangef;
+ break;
+ }
+ case kGLImplementationMockGL: {
+ SetGLGetProcAddressProc(GetMockGLProcAddress);
+ SetGLImplementation(kGLImplementationMockGL);
+ InitializeGLBindingsGL();
+ break;
+ }
+ default:
+ NOTIMPLEMENTED() << "InitializeGLBindings on Android";
+ return false;
+ }
+
+ return true;
+}
+
+bool InitializeGLExtensionBindings(GLImplementation implementation,
+ GLContext* context) {
+ switch (implementation) {
+ case kGLImplementationEGLGLES2:
+ InitializeGLExtensionBindingsGL(context);
+ InitializeGLExtensionBindingsEGL(context);
+ break;
+ case kGLImplementationMockGL:
+ InitializeGLExtensionBindingsGL(context);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+void InitializeDebugGLBindings() {
+}
+
+void ClearGLBindings() {
+ ClearGLBindingsEGL();
+ ClearGLBindingsGL();
+ SetGLImplementation(kGLImplementationNone);
+
+ UnloadGLNativeLibraries();
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_implementation_linux.cc b/ui/gl/gl_implementation_linux.cc
new file mode 100644
index 0000000..35f68ac
--- /dev/null
+++ b/ui/gl/gl_implementation_linux.cc
@@ -0,0 +1,228 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <vector>
+
+#include "base/base_paths.h"
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/native_library.h"
+#include "base/path_service.h"
+#include "base/threading/thread_restrictions.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_switches.h"
+
+namespace gfx {
+namespace {
+
+// TODO(piman): it should be Desktop GL marshalling from double to float. Today
+// on native GLES, we do float->double->float.
+void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) {
+ glClearDepthf(static_cast<GLclampf>(depth));
+}
+
+void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near,
+ GLclampd z_far) {
+ glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far));
+}
+
+// Load a library, printing an error message on failure.
+base::NativeLibrary LoadLibrary(const FilePath& filename) {
+ std::string error;
+ base::NativeLibrary library = base::LoadNativeLibrary(filename,
+ &error);
+ if (!library) {
+ DVLOG(1) << "Failed to load " << filename.MaybeAsASCII() << ": " << error;
+ return NULL;
+ }
+ return library;
+}
+
+base::NativeLibrary LoadLibrary(const char* filename) {
+ return LoadLibrary(FilePath(filename));
+}
+
+} // namespace anonymous
+
+void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
+ impls->push_back(kGLImplementationDesktopGL);
+ impls->push_back(kGLImplementationEGLGLES2);
+ impls->push_back(kGLImplementationOSMesaGL);
+}
+
+bool InitializeGLBindings(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.
+ if (GetGLImplementation() != kGLImplementationNone)
+ return true;
+
+ // Allow the main thread or another to initialize these bindings
+ // after instituting restrictions on I/O. Going forward they will
+ // likely be used in the browser process on most platforms. The
+ // one-time initialization cost is small, between 2 and 5 ms.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+ switch (implementation) {
+ case kGLImplementationOSMesaGL: {
+ FilePath module_path;
+ if (!PathService::Get(base::DIR_MODULE, &module_path)) {
+ LOG(ERROR) << "PathService::Get failed.";
+ return false;
+ }
+
+ base::NativeLibrary library = LoadLibrary(
+ module_path.Append("libosmesa.so"));
+ if (!library)
+ return false;
+
+ GLGetProcAddressProc get_proc_address =
+ reinterpret_cast<GLGetProcAddressProc>(
+ base::GetFunctionPointerFromNativeLibrary(
+ library, "OSMesaGetProcAddress"));
+ if (!get_proc_address) {
+ LOG(ERROR) << "OSMesaGetProcAddress not found.";
+ base::UnloadNativeLibrary(library);
+ return false;
+ }
+
+ SetGLGetProcAddressProc(get_proc_address);
+ AddGLNativeLibrary(library);
+ SetGLImplementation(kGLImplementationOSMesaGL);
+
+ InitializeGLBindingsGL();
+ InitializeGLBindingsOSMESA();
+ break;
+ }
+ case kGLImplementationDesktopGL: {
+ base::NativeLibrary library = NULL;
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+
+ if (command_line->HasSwitch(switches::kTestGLLib))
+ library = LoadLibrary(command_line->GetSwitchValueASCII(
+ switches::kTestGLLib).c_str());
+
+ if (!library) {
+#if defined(OS_OPENBSD)
+ library = LoadLibrary("libGL.so");
+#else
+ library = LoadLibrary("libGL.so.1");
+#endif
+ }
+
+ if (!library)
+ return false;
+
+ GLGetProcAddressProc get_proc_address =
+ reinterpret_cast<GLGetProcAddressProc>(
+ base::GetFunctionPointerFromNativeLibrary(
+ library, "glXGetProcAddress"));
+ if (!get_proc_address) {
+ LOG(ERROR) << "glxGetProcAddress not found.";
+ base::UnloadNativeLibrary(library);
+ return false;
+ }
+
+ SetGLGetProcAddressProc(get_proc_address);
+ AddGLNativeLibrary(library);
+ SetGLImplementation(kGLImplementationDesktopGL);
+
+ InitializeGLBindingsGL();
+ InitializeGLBindingsGLX();
+ break;
+ }
+ case kGLImplementationEGLGLES2: {
+ base::NativeLibrary gles_library = LoadLibrary("libGLESv2.so.2");
+ if (!gles_library)
+ return false;
+ base::NativeLibrary egl_library = LoadLibrary("libEGL.so.1");
+ if (!egl_library) {
+ base::UnloadNativeLibrary(gles_library);
+ return false;
+ }
+
+ GLGetProcAddressProc get_proc_address =
+ reinterpret_cast<GLGetProcAddressProc>(
+ base::GetFunctionPointerFromNativeLibrary(
+ egl_library, "eglGetProcAddress"));
+ if (!get_proc_address) {
+ LOG(ERROR) << "eglGetProcAddress not found.";
+ base::UnloadNativeLibrary(egl_library);
+ base::UnloadNativeLibrary(gles_library);
+ return false;
+ }
+
+ SetGLGetProcAddressProc(get_proc_address);
+ AddGLNativeLibrary(egl_library);
+ AddGLNativeLibrary(gles_library);
+ SetGLImplementation(kGLImplementationEGLGLES2);
+
+ InitializeGLBindingsGL();
+ InitializeGLBindingsEGL();
+
+ // These two functions take single precision float rather than double
+ // precision float parameters in GLES.
+ ::gfx::g_glClearDepth = MarshalClearDepthToClearDepthf;
+ ::gfx::g_glDepthRange = MarshalDepthRangeToDepthRangef;
+ break;
+ }
+ case kGLImplementationMockGL: {
+ SetGLGetProcAddressProc(GetMockGLProcAddress);
+ SetGLImplementation(kGLImplementationMockGL);
+ InitializeGLBindingsGL();
+ break;
+ }
+ default:
+ return false;
+ }
+
+
+ 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();
+ InitializeDebugGLBindingsGLX();
+ InitializeDebugGLBindingsOSMESA();
+}
+
+void ClearGLBindings() {
+ ClearGLBindingsEGL();
+ ClearGLBindingsGL();
+ ClearGLBindingsGLX();
+ ClearGLBindingsOSMESA();
+ SetGLImplementation(kGLImplementationNone);
+
+ UnloadGLNativeLibraries();
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_implementation_mac.cc b/ui/gl/gl_implementation_mac.cc
new file mode 100644
index 0000000..f05e3eb9
--- /dev/null
+++ b/ui/gl/gl_implementation_mac.cc
@@ -0,0 +1,140 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/base_paths.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/mac/foundation_util.h"
+#include "base/native_library.h"
+#include "base/path_service.h"
+#include "base/threading/thread_restrictions.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+
+namespace gfx {
+namespace {
+const char kOpenGLFrameworkPath[] =
+ "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL";
+} // namespace anonymous
+
+void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
+ impls->push_back(kGLImplementationDesktopGL);
+ impls->push_back(kGLImplementationAppleGL);
+ impls->push_back(kGLImplementationOSMesaGL);
+}
+
+bool InitializeGLBindings(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.
+ if (GetGLImplementation() != kGLImplementationNone)
+ return true;
+
+ // Allow the main thread or another to initialize these bindings
+ // after instituting restrictions on I/O. Going forward they will
+ // likely be used in the browser process on most platforms. The
+ // one-time initialization cost is small, between 2 and 5 ms.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+ switch (implementation) {
+ case kGLImplementationOSMesaGL: {
+ // osmesa.so is located in the build directory. This code path is only
+ // valid in a developer build environment.
+ FilePath exe_path;
+ if (!PathService::Get(base::FILE_EXE, &exe_path)) {
+ LOG(ERROR) << "PathService::Get failed.";
+ return false;
+ }
+ FilePath bundle_path = base::mac::GetAppBundlePath(exe_path);
+ FilePath build_dir_path = bundle_path.DirName();
+ FilePath osmesa_path = build_dir_path.Append("osmesa.so");
+
+ // When using OSMesa, just use OSMesaGetProcAddress to find entry points.
+ base::NativeLibrary library = base::LoadNativeLibrary(osmesa_path, NULL);
+ if (!library) {
+ LOG(ERROR) << "osmesa.so not found at " << osmesa_path.value();
+ return false;
+ }
+
+ GLGetProcAddressProc get_proc_address =
+ reinterpret_cast<GLGetProcAddressProc>(
+ base::GetFunctionPointerFromNativeLibrary(
+ library, "OSMesaGetProcAddress"));
+ if (!get_proc_address) {
+ LOG(ERROR) << "OSMesaGetProcAddress not found.";
+ base::UnloadNativeLibrary(library);
+ return false;
+ }
+
+ SetGLGetProcAddressProc(get_proc_address);
+ AddGLNativeLibrary(library);
+ SetGLImplementation(kGLImplementationOSMesaGL);
+
+ InitializeGLBindingsGL();
+ InitializeGLBindingsOSMESA();
+ break;
+ }
+ case kGLImplementationDesktopGL:
+ case kGLImplementationAppleGL: {
+ base::NativeLibrary library = base::LoadNativeLibrary(
+ FilePath(kOpenGLFrameworkPath), NULL);
+ if (!library) {
+ LOG(ERROR) << "OpenGL framework not found";
+ return false;
+ }
+
+ AddGLNativeLibrary(library);
+ SetGLImplementation(implementation);
+
+ InitializeGLBindingsGL();
+ break;
+ }
+ case kGLImplementationMockGL: {
+ SetGLGetProcAddressProc(GetMockGLProcAddress);
+ SetGLImplementation(kGLImplementationMockGL);
+ InitializeGLBindingsGL();
+ break;
+ }
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+bool InitializeGLExtensionBindings(GLImplementation implementation,
+ GLContext* context) {
+ switch (implementation) {
+ case kGLImplementationOSMesaGL:
+ InitializeGLExtensionBindingsGL(context);
+ InitializeGLExtensionBindingsOSMESA(context);
+ break;
+ case kGLImplementationDesktopGL:
+ case kGLImplementationAppleGL:
+ InitializeGLExtensionBindingsGL(context);
+ break;
+ case kGLImplementationMockGL:
+ InitializeGLExtensionBindingsGL(context);
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+void InitializeDebugGLBindings() {
+ InitializeDebugGLBindingsGL();
+ InitializeDebugGLBindingsOSMESA();
+}
+
+void ClearGLBindings() {
+ ClearGLBindingsGL();
+ ClearGLBindingsOSMESA();
+ SetGLImplementation(kGLImplementationNone);
+
+ UnloadGLNativeLibraries();
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_implementation_win.cc b/ui/gl/gl_implementation_win.cc
new file mode 100644
index 0000000..7625b20
--- /dev/null
+++ b/ui/gl/gl_implementation_win.cc
@@ -0,0 +1,290 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <d3dx9.h>
+
+#include <vector>
+
+#include "base/at_exit.h"
+#include "base/base_paths.h"
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/file_path.h"
+#include "base/logging.h"
+#include "base/native_library.h"
+#include "base/path_service.h"
+#include "base/stringprintf.h"
+#include "base/threading/thread_restrictions.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+
+#if defined(ENABLE_SWIFTSHADER)
+#include "software_renderer.h"
+#endif
+
+namespace gfx {
+
+namespace {
+
+typedef std::vector<base::NativeLibrary> LibraryArray;
+LibraryArray* g_d3dx_libraries;
+
+void GL_BINDING_CALL MarshalClearDepthToClearDepthf(GLclampd depth) {
+ glClearDepthf(static_cast<GLclampf>(depth));
+}
+
+void GL_BINDING_CALL MarshalDepthRangeToDepthRangef(GLclampd z_near,
+ GLclampd z_far) {
+ glDepthRangef(static_cast<GLclampf>(z_near), static_cast<GLclampf>(z_far));
+}
+
+void UnloadD3DXLibraries(void* unused) {
+ if (g_d3dx_libraries) {
+ for (LibraryArray::iterator it = g_d3dx_libraries->begin();
+ it != g_d3dx_libraries->end(); ++it) {
+ base::UnloadNativeLibrary(*it);
+ }
+ delete g_d3dx_libraries;
+ g_d3dx_libraries = NULL;
+ }
+}
+
+bool LoadD3DXLibrary(const FilePath& module_path,
+ const FilePath::StringType& name) {
+ base::NativeLibrary library = base::LoadNativeLibrary(FilePath(name), NULL);
+ if (!library) {
+ library = base::LoadNativeLibrary(module_path.Append(name), NULL);
+ if (!library) {
+ DVLOG(1) << name << " not found.";
+ return false;
+ }
+ }
+
+ if (!g_d3dx_libraries) {
+ g_d3dx_libraries = new LibraryArray;
+ base::AtExitManager::RegisterCallback(UnloadD3DXLibraries, NULL);
+ }
+ g_d3dx_libraries->push_back(library);
+ return true;
+}
+
+} // namespace anonymous
+
+void GetAllowedGLImplementations(std::vector<GLImplementation>* impls) {
+ impls->push_back(kGLImplementationEGLGLES2);
+ impls->push_back(kGLImplementationDesktopGL);
+ impls->push_back(kGLImplementationOSMesaGL);
+}
+
+bool InitializeGLBindings(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.
+ if (GetGLImplementation() != kGLImplementationNone)
+ return true;
+
+ // Allow the main thread or another to initialize these bindings
+ // after instituting restrictions on I/O. Going forward they will
+ // likely be used in the browser process on most platforms. The
+ // one-time initialization cost is small, between 2 and 5 ms.
+ base::ThreadRestrictions::ScopedAllowIO allow_io;
+
+ switch (implementation) {
+ case kGLImplementationOSMesaGL: {
+ FilePath module_path;
+ if (!PathService::Get(base::DIR_MODULE, &module_path)) {
+ LOG(ERROR) << "PathService::Get failed.";
+ return false;
+ }
+
+ base::NativeLibrary library = base::LoadNativeLibrary(
+ module_path.Append(L"osmesa.dll"), NULL);
+ if (!library) {
+ DVLOG(1) << "osmesa.dll not found";
+ return false;
+ }
+
+ GLGetProcAddressProc get_proc_address =
+ reinterpret_cast<GLGetProcAddressProc>(
+ base::GetFunctionPointerFromNativeLibrary(
+ library, "OSMesaGetProcAddress"));
+ if (!get_proc_address) {
+ DLOG(ERROR) << "OSMesaGetProcAddress not found.";
+ base::UnloadNativeLibrary(library);
+ return false;
+ }
+
+ SetGLGetProcAddressProc(get_proc_address);
+ AddGLNativeLibrary(library);
+ SetGLImplementation(kGLImplementationOSMesaGL);
+
+ InitializeGLBindingsGL();
+ InitializeGLBindingsOSMESA();
+ break;
+ }
+ case kGLImplementationEGLGLES2: {
+ FilePath module_path;
+ if (!PathService::Get(base::DIR_MODULE, &module_path))
+ return false;
+
+ // Attempt to load D3DX and its dependencies using the default search path
+ // and if that fails, using an absolute path. This is to ensure these DLLs
+ // are loaded before ANGLE is loaded in case they are not in the default
+ // search path.
+ LoadD3DXLibrary(module_path, base::StringPrintf(L"d3dcompiler_%d.dll",
+ D3DX_SDK_VERSION));
+ LoadD3DXLibrary(module_path, base::StringPrintf(L"d3dx9_%d.dll",
+ D3DX_SDK_VERSION));
+
+ FilePath gles_path;
+ const CommandLine* command_line = CommandLine::ForCurrentProcess();
+ bool using_swift_shader =
+ command_line->GetSwitchValueASCII(switches::kUseGL) == "swiftshader";
+ if (using_swift_shader) {
+ if (!command_line->HasSwitch(switches::kSwiftShaderPath))
+ return false;
+ gles_path =
+ command_line->GetSwitchValuePath(switches::kSwiftShaderPath);
+ // Preload library
+ LoadLibrary(L"ddraw.dll");
+ } else {
+ gles_path = module_path;
+ }
+
+ // Load libglesv2.dll before libegl.dll because the latter is dependent on
+ // the former and if there is another version of libglesv2.dll in the dll
+ // search path, it will get loaded instead.
+ base::NativeLibrary gles_library = base::LoadNativeLibrary(
+ gles_path.Append(L"libglesv2.dll"), NULL);
+ if (!gles_library) {
+ DVLOG(1) << "libglesv2.dll not found";
+ return false;
+ }
+
+ // When using EGL, first try eglGetProcAddress and then Windows
+ // GetProcAddress on both the EGL and GLES2 DLLs.
+ base::NativeLibrary egl_library = base::LoadNativeLibrary(
+ gles_path.Append(L"libegl.dll"), NULL);
+ if (!egl_library) {
+ DVLOG(1) << "libegl.dll not found.";
+ base::UnloadNativeLibrary(gles_library);
+ return false;
+ }
+
+#if defined(ENABLE_SWIFTSHADER)
+ if (using_swift_shader) {
+ SetupSoftwareRenderer(gles_library);
+ }
+#endif
+
+ GLGetProcAddressProc get_proc_address =
+ reinterpret_cast<GLGetProcAddressProc>(
+ base::GetFunctionPointerFromNativeLibrary(
+ egl_library, "eglGetProcAddress"));
+ if (!get_proc_address) {
+ LOG(ERROR) << "eglGetProcAddress not found.";
+ base::UnloadNativeLibrary(egl_library);
+ base::UnloadNativeLibrary(gles_library);
+ return false;
+ }
+
+ SetGLGetProcAddressProc(get_proc_address);
+ AddGLNativeLibrary(egl_library);
+ AddGLNativeLibrary(gles_library);
+ SetGLImplementation(kGLImplementationEGLGLES2);
+
+ InitializeGLBindingsGL();
+ InitializeGLBindingsEGL();
+
+ // These two functions take single precision float rather than double
+ // precision float parameters in GLES.
+ ::gfx::g_glClearDepth = MarshalClearDepthToClearDepthf;
+ ::gfx::g_glDepthRange = MarshalDepthRangeToDepthRangef;
+ break;
+ }
+ case kGLImplementationDesktopGL: {
+ // When using Windows OpenGL, first try wglGetProcAddress and then
+ // Windows GetProcAddress.
+ base::NativeLibrary library = base::LoadNativeLibrary(
+ FilePath(L"opengl32.dll"), NULL);
+ if (!library) {
+ DVLOG(1) << "opengl32.dll not found";
+ return false;
+ }
+
+ GLGetProcAddressProc get_proc_address =
+ reinterpret_cast<GLGetProcAddressProc>(
+ base::GetFunctionPointerFromNativeLibrary(
+ library, "wglGetProcAddress"));
+ if (!get_proc_address) {
+ LOG(ERROR) << "wglGetProcAddress not found.";
+ base::UnloadNativeLibrary(library);
+ return false;
+ }
+
+ SetGLGetProcAddressProc(get_proc_address);
+ AddGLNativeLibrary(library);
+ SetGLImplementation(kGLImplementationDesktopGL);
+
+ InitializeGLBindingsGL();
+ InitializeGLBindingsWGL();
+ break;
+ }
+ case kGLImplementationMockGL: {
+ SetGLGetProcAddressProc(GetMockGLProcAddress);
+ SetGLImplementation(kGLImplementationMockGL);
+ InitializeGLBindingsGL();
+ break;
+ }
+ default:
+ return false;
+ }
+
+ 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();
+ InitializeDebugGLBindingsOSMESA();
+ InitializeDebugGLBindingsWGL();
+}
+
+void ClearGLBindings() {
+ ClearGLBindingsEGL();
+ ClearGLBindingsGL();
+ ClearGLBindingsOSMESA();
+ ClearGLBindingsWGL();
+ SetGLImplementation(kGLImplementationNone);
+
+ UnloadGLNativeLibraries();
+ UnloadD3DXLibraries(NULL);
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_interface.cc b/ui/gl/gl_interface.cc
new file mode 100644
index 0000000..0cb61e7
--- /dev/null
+++ b/ui/gl/gl_interface.cc
@@ -0,0 +1,20 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_interface.h"
+
+namespace gfx {
+
+GLInterface* GLInterface::interface_;
+
+void GLInterface::SetGLInterface(GLInterface* gl_interface) {
+ interface_ = gl_interface;
+}
+
+GLInterface* GLInterface::GetGLInterface() {
+ return interface_;
+}
+
+} // namespace gfx
+
diff --git a/ui/gl/gl_interface.h b/ui/gl/gl_interface.h
new file mode 100644
index 0000000..db120b6
--- /dev/null
+++ b/ui/gl/gl_interface.h
@@ -0,0 +1,640 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_INTERFACE_H_
+#define UI_GL_GL_INTERFACE_H_
+#pragma once
+
+// This file implements glue to a GL interface so we can mock it for unit
+// testing. It has to be Desktop GL, not GLES2 as it is used to test the service
+// side code.
+
+#include "ui/gl/gl_bindings.h"
+
+namespace gfx {
+
+class GL_EXPORT GLInterface {
+ public:
+ virtual ~GLInterface() {}
+
+ static void SetGLInterface(GLInterface* gl_interface);
+
+ static GLInterface* GetGLInterface();
+
+ virtual void ActiveTexture(GLenum texture) = 0;
+
+ virtual void AttachShader(GLuint program,
+ GLuint shader) = 0;
+
+ virtual void BeginQuery(GLenum target, GLuint id) = 0;
+
+ virtual void BeginQueryARB(GLenum target, GLuint id) = 0;
+
+ virtual void BindAttribLocation(GLuint program,
+ GLuint index,
+ const char* name) = 0;
+
+ virtual void BindBuffer(GLenum target, GLuint buffer) = 0;
+
+ virtual void BindFragDataLocationIndexed(GLuint program,
+ GLuint colorNumber,
+ GLuint index,
+ const char* name) = 0;
+
+ virtual void BindFragDataLocation(GLuint program,
+ GLuint colorNumber,
+ const char* name) = 0;
+
+ virtual void BindFramebufferEXT(GLenum target, GLuint framebuffer) = 0;
+
+ virtual void BindRenderbufferEXT(GLenum target, GLuint renderbuffer) = 0;
+
+ virtual void BindTexture(GLenum target, GLuint texture) = 0;
+
+ virtual void BlendColor(GLclampf red,
+ GLclampf green,
+ GLclampf blue,
+ GLclampf alpha) = 0;
+
+ virtual void BlendEquation(GLenum mode) = 0;
+
+ virtual void BlendEquationSeparate(GLenum modeRGB,
+ GLenum modeAlpha) = 0;
+
+ virtual void BlendFunc(GLenum sfactor, GLenum dfactor) = 0;
+
+ virtual void BlendFuncSeparate(GLenum srcRGB,
+ GLenum dstRGB,
+ GLenum srcAlpha,
+ GLenum dstAlpha) = 0;
+
+ virtual void BlitFramebufferANGLE(
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter) = 0;
+
+ virtual void BlitFramebufferEXT(
+ GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1,
+ GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1,
+ GLbitfield mask, GLenum filter) = 0;
+
+ virtual void BufferData(GLenum target,
+ GLsizeiptr size,
+ const void* data,
+ GLenum usage) = 0;
+
+ virtual void BufferSubData(GLenum target,
+ GLintptr offset,
+ GLsizeiptr size,
+ const void* data) = 0;
+
+ virtual GLenum CheckFramebufferStatusEXT(GLenum target) = 0;
+
+ virtual void Clear(GLbitfield mask) = 0;
+
+ virtual void ClearColor(GLclampf red,
+ GLclampf green,
+ GLclampf blue,
+ GLclampf alpha) = 0;
+
+ virtual void ClearDepth(GLclampd depth) = 0;
+
+ virtual void ClearDepthf(GLclampf depth) = 0;
+
+ virtual void ClearStencil(GLint s) = 0;
+
+ virtual void ColorMask(GLboolean red,
+ GLboolean green,
+ GLboolean blue,
+ GLboolean alpha) = 0;
+
+ virtual void CompileShader(GLuint shader) = 0;
+
+ virtual void CompressedTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLsizei width, GLsizei height,
+ GLint border,
+ GLsizei imageSize,
+ const void* data) = 0;
+
+ virtual void CompressedTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format,
+ GLsizei imageSize,
+ const void* data) = 0;
+
+ virtual void CopyTexImage2D(GLenum target,
+ GLint level,
+ GLenum internalformat,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLint border) = 0;
+
+ virtual void CopyTexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset,
+ GLint x, GLint y,
+ GLsizei width, GLsizei height) = 0;
+
+ virtual GLuint CreateProgram() = 0;
+
+ virtual GLuint CreateShader(GLenum type) = 0;
+
+ virtual void CullFace(GLenum mode) = 0;
+
+ virtual void DeleteBuffersARB(GLsizei n, const GLuint* buffers) = 0;
+
+ virtual void DeleteFramebuffersEXT(GLsizei n, const GLuint* framebuffers) = 0;
+
+ virtual void DeleteProgram(GLuint program) = 0;
+
+ virtual void DeleteRenderbuffersEXT(GLsizei n,
+ const GLuint* renderbuffers) = 0;
+
+ virtual void DeleteQueries(GLsizei n, const GLuint* ids) = 0;
+
+ virtual void DeleteQueriesARB(GLsizei n, const GLuint* ids) = 0;
+
+ virtual void DeleteShader(GLuint shader) = 0;
+
+ virtual void DeleteTextures(GLsizei n, const GLuint* textures) = 0;
+
+ virtual void DepthFunc(GLenum func) = 0;
+
+ virtual void DepthMask(GLboolean flag) = 0;
+
+ virtual void DepthRange(GLclampd zNear, GLclampd zFar) = 0;
+
+ virtual void DepthRangef(GLclampf zNear, GLclampf zFar) = 0;
+
+ virtual void DetachShader(GLuint program, GLuint shader) = 0;
+
+ virtual void Disable(GLenum cap) = 0;
+
+ virtual void DisableVertexAttribArray(GLuint index) = 0;
+
+ virtual void DrawArrays(GLenum mode, GLint first, GLsizei count) = 0;
+
+ virtual void DrawBuffer(GLenum mode) = 0;
+
+ virtual void DrawBuffersARB(GLsizei n, const GLenum* bufs) = 0;
+
+ virtual void DrawElements(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void* indices) = 0;
+
+ virtual void EGLImageTargetTexture2DOES(
+ GLenum target, GLeglImageOES image) = 0;
+
+ virtual void EGLImageTargetRenderbufferStorageOES(
+ GLenum target, GLeglImageOES image) = 0;
+
+ virtual void Enable(GLenum cap) = 0;
+
+ virtual void EnableVertexAttribArray(GLuint index) = 0;
+
+ virtual void EndQuery(GLenum target) = 0;
+
+ virtual void EndQueryARB(GLenum target) = 0;
+
+ virtual void Finish() = 0;
+
+ virtual void Flush() = 0;
+
+ virtual void FramebufferRenderbufferEXT(GLenum target,
+ GLenum attachment,
+ GLenum renderbuffertarget,
+ GLuint renderbuffer) = 0;
+
+ virtual void FramebufferTexture2DEXT(GLenum target,
+ GLenum attachment,
+ GLenum textarget,
+ GLuint texture,
+ GLint level) = 0;
+
+ virtual void FrontFace(GLenum mode) = 0;
+
+ virtual void GenBuffersARB(GLsizei n, GLuint* buffers) = 0;
+
+ virtual void GenerateMipmapEXT(GLenum target) = 0;
+
+ virtual void GenFramebuffersEXT(GLsizei n, GLuint* framebuffers) = 0;
+
+ virtual void GenQueries(GLsizei n, GLuint* ids) = 0;
+
+ virtual void GenQueriesARB(GLsizei n, GLuint* ids) = 0;
+
+ virtual void GenRenderbuffersEXT(GLsizei n, GLuint* renderbuffers) = 0;
+
+ virtual void GenTextures(GLsizei n, GLuint* textures) = 0;
+
+ virtual void GetActiveAttrib(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ GLint* size,
+ GLenum* type,
+ char* name) = 0;
+
+ virtual void GetActiveUniform(GLuint program,
+ GLuint index,
+ GLsizei bufsize,
+ GLsizei* length,
+ GLint* size,
+ GLenum* type,
+ char* name) = 0;
+
+ virtual void GetAttachedShaders(GLuint program,
+ GLsizei maxcount,
+ GLsizei* count,
+ GLuint* shaders) = 0;
+
+ virtual GLint GetAttribLocation(GLuint program, const char* name) = 0;
+
+ virtual void GetBooleanv(GLenum pname, GLboolean* params) = 0;
+
+ virtual void GetBufferParameteriv(GLenum target,
+ GLenum pname,
+ GLint* params) = 0;
+
+ virtual GLenum GetError() = 0;
+
+ virtual void GetFloatv(GLenum pname, GLfloat* params) = 0;
+
+ virtual void GetFramebufferAttachmentParameterivEXT(GLenum target,
+ GLenum attachment,
+ GLenum pname,
+ GLint* params) = 0;
+
+ virtual void GetIntegerv(GLenum pname, GLint* params) = 0;
+
+ virtual void GetProgramiv(GLuint program, GLenum pname, GLint* params) = 0;
+
+ // TODO(gman): Implement this
+ virtual void GetProgramInfoLog(GLuint program,
+ GLsizei bufsize,
+ GLsizei* length,
+ char* infolog) = 0;
+
+ virtual void GetQueryiv(GLenum target, GLenum pname, GLint* params) = 0;
+
+ virtual void GetQueryivARB(GLenum target, GLenum pname, GLint* params) = 0;
+
+ virtual void GetQueryObjecti64v(GLuint id, GLenum pname, GLint64* params) = 0;
+
+ virtual void GetQueryObjectiv(GLuint id, GLenum pname, GLint* params) = 0;
+
+ virtual void GetQueryObjectui64v(GLuint id,
+ GLenum pname,
+ GLuint64* params) = 0;
+
+ virtual void GetQueryObjectuiv(GLuint id, GLenum pname, GLuint* params) = 0;
+
+ virtual void GetQueryObjectuivARB(GLuint id,
+ GLenum pname,
+ GLuint* params) = 0;
+
+ virtual void GetRenderbufferParameterivEXT(GLenum target,
+ GLenum pname,
+ GLint* params) = 0;
+
+ virtual void GetShaderiv(GLuint shader, GLenum pname, GLint* params) = 0;
+
+ // TODO(gman): Implement this
+ virtual void GetShaderInfoLog(GLuint shader,
+ GLsizei bufsize,
+ GLsizei* length,
+ char* infolog) = 0;
+
+ virtual void GetShaderPrecisionFormat(GLenum shadertype,
+ GLenum precisiontype,
+ GLint* range,
+ GLint* precision) = 0;
+
+ // TODO(gman): Implement this
+ virtual void GetShaderSource(GLuint shader,
+ GLsizei bufsize,
+ GLsizei* length,
+ char* source) = 0;
+
+ virtual const GLubyte* GetString(GLenum name) = 0;
+
+ virtual void GetTexLevelParameterfv(GLenum target,
+ GLint level,
+ GLenum pname,
+ GLfloat* params) = 0;
+
+ virtual void GetTexLevelParameteriv(GLenum target,
+ GLint level,
+ GLenum pname,
+ GLint* params) = 0;
+
+ virtual void GetTexParameterfv(GLenum target,
+ GLenum pname,
+ GLfloat* params) = 0;
+
+ virtual void GetTexParameteriv(GLenum target,
+ GLenum pname,
+ GLint* params) = 0;
+
+ virtual void GetTranslatedShaderSourceANGLE(GLuint shader,
+ GLsizei bufsize,
+ GLsizei* length,
+ char* source) = 0;
+
+ virtual void GetUniformfv(GLuint program,
+ GLint location,
+ GLfloat* params) = 0;
+
+ virtual void GetUniformiv(GLuint program,
+ GLint location,
+ GLint* params) = 0;
+
+ virtual GLint GetUniformLocation(GLuint program, const char* name) = 0;
+
+ virtual void GetVertexAttribfv(GLuint index,
+ GLenum pname,
+ GLfloat* params) = 0;
+
+ virtual void GetVertexAttribiv(GLuint index,
+ GLenum pname,
+ GLint* params) = 0;
+
+ virtual void GetVertexAttribPointerv(GLuint index,
+ GLenum pname,
+ void** pointer) = 0;
+
+ virtual void Hint(GLenum target, GLenum mode) = 0;
+
+ virtual GLboolean IsBuffer(GLuint buffer) = 0;
+
+ virtual GLboolean IsEnabled(GLenum cap) = 0;
+
+ virtual GLboolean IsFramebufferEXT(GLuint framebuffer) = 0;
+
+ virtual GLboolean IsProgram(GLuint program) = 0;
+
+ virtual GLboolean IsQueryARB(GLuint query) = 0;
+
+ virtual GLboolean IsRenderbufferEXT(GLuint renderbuffer) = 0;
+
+ virtual GLboolean IsShader(GLuint shader) = 0;
+
+ virtual GLboolean IsTexture(GLuint texture) = 0;
+
+ virtual void* MapBuffer(GLenum target, GLenum access) = 0;
+
+ virtual void LineWidth(GLfloat width) = 0;
+
+ virtual void LinkProgram(GLuint program) = 0;
+
+ virtual void PixelStorei(GLenum pname, GLint param) = 0;
+
+ virtual void PolygonOffset(GLfloat factor, GLfloat units) = 0;
+
+ virtual void QueryCounter(GLuint id, GLenum target) = 0;
+
+ virtual void ReadBuffer(GLenum src) = 0;
+
+ virtual void ReadPixels(GLint x, GLint y,
+ GLsizei width, GLsizei height,
+ GLenum format,
+ GLenum type,
+ void* pixels) = 0;
+
+ virtual void ReleaseShaderCompiler(void) = 0;
+
+ virtual void RenderbufferStorageEXT(GLenum target,
+ GLenum internalformat,
+ GLsizei width, GLsizei height) = 0;
+
+ virtual void RenderbufferStorageMultisampleANGLE(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height) = 0;
+
+ virtual void RenderbufferStorageMultisampleEXT(GLenum target,
+ GLsizei samples,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height) = 0;
+
+ virtual void SampleCoverage(GLclampf value, GLboolean invert) = 0;
+
+ virtual void Scissor(GLint x, GLint y, GLsizei width, GLsizei height) = 0;
+
+ virtual void ShaderBinary(GLsizei n,
+ const GLuint* shaders,
+ GLenum binaryformat,
+ const void* binary,
+ GLsizei length) = 0;
+
+ virtual void ShaderSource(GLuint shader,
+ GLsizei count,
+ const char** str,
+ const GLint* length) = 0;
+
+ virtual void StencilFunc(GLenum func, GLint ref, GLuint mask) = 0;
+
+ virtual void StencilFuncSeparate(GLenum face,
+ GLenum func,
+ GLint ref,
+ GLuint mask) = 0;
+
+ virtual void StencilMask(GLuint mask) = 0;
+
+ virtual void StencilMaskSeparate(GLenum face, GLuint mask) = 0;
+
+ virtual void StencilOp(GLenum fail, GLenum zfail, GLenum zpass) = 0;
+
+ virtual void StencilOpSeparate(GLenum face,
+ GLenum fail,
+ GLenum zfail,
+ GLenum zpass) = 0;
+
+ virtual void TexImage2D(GLenum target,
+ GLint level,
+ GLint internalformat,
+ GLsizei width, GLsizei height,
+ GLint border,
+ GLenum format,
+ GLenum type,
+ const void* pixels) = 0;
+
+ virtual void TexParameterf(GLenum target, GLenum pname, GLfloat param) = 0;
+
+ virtual void TexParameterfv(GLenum target,
+ GLenum pname,
+ const GLfloat* params) = 0;
+
+ virtual void TexParameteri(GLenum target, GLenum pname, GLint param) = 0;
+
+ virtual void TexParameteriv(GLenum target,
+ GLenum pname,
+ const GLint* params) = 0;
+
+ virtual void TexStorage2DEXT(GLenum target,
+ GLsizei levels,
+ GLenum internalformat,
+ GLsizei width,
+ GLsizei height) = 0;
+
+ virtual void TexSubImage2D(GLenum target,
+ GLint level,
+ GLint xoffset, GLint yoffset,
+ GLsizei width, GLsizei height,
+ GLenum format,
+ GLenum type,
+ const void* pixels) = 0;
+
+ virtual void Uniform1f(GLint location, GLfloat x) = 0;
+
+ virtual void Uniform1fv(GLint location, GLsizei count, const GLfloat* v) = 0;
+
+ virtual void Uniform1i(GLint location, GLint x) = 0;
+
+ virtual void Uniform1iv(GLint location, GLsizei count, const GLint* v) = 0;
+
+ virtual void Uniform2f(GLint location, GLfloat x, GLfloat y) = 0;
+
+ virtual void Uniform2fv(GLint location, GLsizei count, const GLfloat* v) = 0;
+
+ virtual void Uniform2i(GLint location, GLint x, GLint y) = 0;
+
+ virtual void Uniform2iv(GLint location, GLsizei count, const GLint* v) = 0;
+
+ virtual void Uniform3f(GLint location, GLfloat x, GLfloat y, GLfloat z) = 0;
+
+ virtual void Uniform3fv(GLint location, GLsizei count, const GLfloat* v) = 0;
+
+ virtual void Uniform3i(GLint location, GLint x, GLint y, GLint z) = 0;
+
+ virtual void Uniform3iv(GLint location, GLsizei count, const GLint* v) = 0;
+
+ virtual void Uniform4f(GLint location,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w) = 0;
+
+ virtual void Uniform4fv(GLint location, GLsizei count, const GLfloat* v) = 0;
+
+ virtual void Uniform4i(GLint location,
+ GLint x,
+ GLint y,
+ GLint z,
+ GLint w) = 0;
+
+ virtual void Uniform4iv(GLint location, GLsizei count, const GLint* v) = 0;
+
+ virtual void UniformMatrix2fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat* value) = 0;
+
+ virtual void UniformMatrix3fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat* value) = 0;
+
+ virtual void UniformMatrix4fv(GLint location,
+ GLsizei count,
+ GLboolean transpose,
+ const GLfloat* value) = 0;
+
+ virtual GLboolean UnmapBuffer(GLenum target) = 0;
+
+ virtual void UseProgram(GLuint program) = 0;
+
+ virtual void ValidateProgram(GLuint program) = 0;
+
+ virtual void VertexAttrib1f(GLuint indx, GLfloat x) = 0;
+
+ virtual void VertexAttrib1fv(GLuint indx, const GLfloat* values) = 0;
+
+ virtual void VertexAttrib2f(GLuint indx, GLfloat x, GLfloat y) = 0;
+
+ virtual void VertexAttrib2fv(GLuint indx, const GLfloat* values) = 0;
+
+ virtual void VertexAttrib3f(GLuint indx, GLfloat x, GLfloat y, GLfloat z) = 0;
+
+ virtual void VertexAttrib3fv(GLuint indx, const GLfloat* values) = 0;
+
+ virtual void VertexAttrib4f(GLuint indx,
+ GLfloat x,
+ GLfloat y,
+ GLfloat z,
+ GLfloat w) = 0;
+
+ virtual void VertexAttrib4fv(GLuint indx, const GLfloat* values) = 0;
+
+ virtual void VertexAttribPointer(GLuint indx,
+ GLint size,
+ GLenum type,
+ GLboolean normalized,
+ GLsizei stride,
+ const void* ptr) = 0;
+
+ virtual void Viewport(GLint x, GLint y, GLsizei width, GLsizei height) = 0;
+
+ virtual void SwapBuffers() = 0;
+
+ virtual GLuint GetMaxValueInBufferCHROMIUM(GLuint buffer_id,
+ GLsizei count,
+ GLenum type,
+ GLuint offset) = 0;
+
+ virtual void GenFencesNV(GLsizei n, GLuint *fences) = 0;
+
+ virtual void DeleteFencesNV(GLsizei n, const GLuint *fences) = 0;
+
+ virtual void SetFenceNV(GLuint fence, GLenum condition) = 0;
+
+ virtual GLboolean TestFenceNV(GLuint fence) = 0;
+
+ virtual void FinishFenceNV(GLuint fence) = 0;
+
+ virtual GLboolean IsFenceNV(GLuint fence) = 0;
+
+ virtual void GetFenceivNV(GLuint fence, GLenum pname, GLint *params) = 0;
+
+ virtual void SetSurfaceCHROMIUM(GLuint id) = 0;
+
+ virtual GLenum GetGraphicsResetStatusARB() = 0;
+
+ virtual GLsync FenceSync(GLenum condition, GLbitfield flags) = 0;
+
+ virtual void DeleteSync(GLsync sync) = 0;
+
+ virtual void GetSynciv(GLsync sync,
+ GLenum pname,
+ GLsizei bufSize,
+ GLsizei* length,
+ GLint* values) = 0;
+
+ virtual void DrawArraysInstancedANGLE(GLenum mode,
+ GLint first,
+ GLsizei count,
+ GLsizei primcount) = 0;
+
+ virtual void DrawElementsInstancedANGLE(GLenum mode,
+ GLsizei count,
+ GLenum type,
+ const void* indices,
+ GLsizei primcount) = 0;
+
+ virtual void VertexAttribDivisorANGLE(GLuint index, GLuint divisor) = 0;
+
+ private:
+ static GLInterface* interface_;
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_INTERFACE_H_
diff --git a/ui/gl/gl_share_group.cc b/ui/gl/gl_share_group.cc
new file mode 100644
index 0000000..8ab0cc7
--- /dev/null
+++ b/ui/gl/gl_share_group.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_share_group.h"
+
+#include "ui/gl/gl_context.h"
+
+namespace gfx {
+
+GLShareGroup::GLShareGroup() {
+}
+
+void GLShareGroup::AddContext(GLContext* context) {
+ contexts_.insert(context);
+}
+
+void GLShareGroup::RemoveContext(GLContext* context) {
+ contexts_.erase(context);
+}
+
+void* GLShareGroup::GetHandle() {
+ GLContext* context = GetContext();
+ if (context)
+ return context->GetHandle();
+
+ return NULL;
+}
+
+GLContext* GLShareGroup::GetContext() {
+ for (ContextSet::iterator it = contexts_.begin();
+ it != contexts_.end();
+ ++it) {
+ if ((*it)->GetHandle())
+ return *it;
+ }
+
+ return NULL;
+}
+
+GLShareGroup::~GLShareGroup() {
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_share_group.h b/ui/gl/gl_share_group.h
new file mode 100644
index 0000000..2b39ba5
--- /dev/null
+++ b/ui/gl/gl_share_group.h
@@ -0,0 +1,52 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_SHARE_GROUP_H_
+#define UI_GL_GL_SHARE_GROUP_H_
+#pragma once
+
+#include <set>
+
+#include "base/basictypes.h"
+#include "base/memory/ref_counted.h"
+#include "ui/gl/gl_export.h"
+
+namespace gfx {
+
+class GLContext;
+
+// A group of GL contexts that share an ID namespace.
+class GL_EXPORT GLShareGroup : public base::RefCounted<GLShareGroup> {
+ public:
+ GLShareGroup();
+
+ // These two should only be called from the constructor and destructor of
+ // GLContext.
+ void AddContext(GLContext* context);
+ void RemoveContext(GLContext* context);
+
+ // Returns a handle to any initialized context in the share group or NULL if
+ // there are no initialized contexts in the share group.
+ void* GetHandle();
+
+ // Returns a pointer to any initialized context in the share group
+ // or NULL if there are no initialized contexts in the share group.
+ GLContext* GetContext();
+
+ private:
+ friend class base::RefCounted<GLShareGroup>;
+
+ ~GLShareGroup();
+
+ // References to GLContext are by raw pointer to avoid a reference count
+ // cycle.
+ typedef std::set<GLContext*> ContextSet;
+ ContextSet contexts_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLShareGroup);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_SHARE_GROUP_H_
diff --git a/ui/gl/gl_surface.cc b/ui/gl/gl_surface.cc
new file mode 100644
index 0000000..cc6c3b3
--- /dev/null
+++ b/ui/gl/gl_surface.cc
@@ -0,0 +1,208 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface.h"
+
+#include <algorithm>
+#include <vector>
+
+#include "base/command_line.h"
+#include "base/lazy_instance.h"
+#include "base/logging.h"
+#include "base/threading/thread_local.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_implementation.h"
+
+namespace gfx {
+
+namespace {
+base::LazyInstance<base::ThreadLocalPointer<GLSurface> >::Leaky
+ current_surface_ = LAZY_INSTANCE_INITIALIZER;
+} // namespace
+
+// static
+bool GLSurface::InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ std::vector<GLImplementation> allowed_impls;
+ GetAllowedGLImplementations(&allowed_impls);
+ DCHECK(!allowed_impls.empty());
+
+ // The default implementation is always the first one in list.
+ GLImplementation impl = allowed_impls[0];
+ bool fallback_to_osmesa = false;
+ if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) {
+ std::string requested_implementation_name =
+ CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL);
+ if (requested_implementation_name == "any") {
+ fallback_to_osmesa = true;
+ } else if (requested_implementation_name == "swiftshader") {
+ impl = kGLImplementationEGLGLES2;
+ } else {
+ impl = GetNamedGLImplementation(requested_implementation_name);
+ if (std::find(allowed_impls.begin(),
+ allowed_impls.end(),
+ impl) == allowed_impls.end()) {
+ LOG(ERROR) << "Requested GL implementation is not available.";
+ return false;
+ }
+ }
+ }
+
+ initialized = InitializeGLBindings(impl) && InitializeOneOffInternal();
+ if (!initialized && fallback_to_osmesa) {
+ ClearGLBindings();
+ initialized = InitializeGLBindings(kGLImplementationOSMesaGL) &&
+ InitializeOneOffInternal();
+ }
+
+ if (initialized) {
+ DVLOG(1) << "Using "
+ << GetGLImplementationName(GetGLImplementation())
+ << " GL implementation.";
+ if (CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableGPUServiceLogging))
+ InitializeDebugGLBindings();
+ }
+ return initialized;
+}
+
+GLSurface::GLSurface() {}
+
+bool GLSurface::Initialize()
+{
+ return true;
+}
+
+bool GLSurface::Resize(const gfx::Size& size) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
+std::string GLSurface::GetExtensions() {
+ // Use of GLSurfaceAdapter class means that we can't compare
+ // GetCurrent() and this directly.
+ DCHECK_EQ(GetCurrent()->GetHandle(), GetHandle());
+ return std::string("");
+}
+
+unsigned int GLSurface::GetBackingFrameBufferObject() {
+ return 0;
+}
+
+bool GLSurface::PostSubBuffer(int x, int y, int width, int height) {
+ return false;
+}
+
+bool GLSurface::OnMakeCurrent(GLContext* context) {
+ return true;
+}
+
+void GLSurface::SetBufferAllocation(BufferAllocationState state) {
+}
+
+void* GLSurface::GetShareHandle() {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+void* GLSurface::GetDisplay() {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+void* GLSurface::GetConfig() {
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+unsigned GLSurface::GetFormat() {
+ NOTIMPLEMENTED();
+ return 0;
+}
+
+GLSurface* GLSurface::GetCurrent() {
+ return current_surface_.Pointer()->Get();
+}
+
+GLSurface::~GLSurface() {
+ if (GetCurrent() == this)
+ SetCurrent(NULL);
+}
+
+void GLSurface::SetCurrent(GLSurface* surface) {
+ current_surface_.Pointer()->Set(surface);
+}
+
+GLSurfaceAdapter::GLSurfaceAdapter(GLSurface* surface) : surface_(surface) {}
+
+bool GLSurfaceAdapter::Initialize() {
+ return surface_->Initialize();
+}
+
+void GLSurfaceAdapter::Destroy() {
+ surface_->Destroy();
+}
+
+bool GLSurfaceAdapter::Resize(const gfx::Size& size) {
+ return surface_->Resize(size);
+}
+
+bool GLSurfaceAdapter::IsOffscreen() {
+ return surface_->IsOffscreen();
+}
+
+bool GLSurfaceAdapter::SwapBuffers() {
+ return surface_->SwapBuffers();
+}
+
+bool GLSurfaceAdapter::PostSubBuffer(int x, int y, int width, int height) {
+ return surface_->PostSubBuffer(x, y, width, height);
+}
+
+std::string GLSurfaceAdapter::GetExtensions() {
+ return surface_->GetExtensions();
+}
+
+gfx::Size GLSurfaceAdapter::GetSize() {
+ return surface_->GetSize();
+}
+
+void* GLSurfaceAdapter::GetHandle() {
+ return surface_->GetHandle();
+}
+
+unsigned int GLSurfaceAdapter::GetBackingFrameBufferObject() {
+ return surface_->GetBackingFrameBufferObject();
+}
+
+bool GLSurfaceAdapter::OnMakeCurrent(GLContext* context) {
+ return surface_->OnMakeCurrent(context);
+}
+
+void GLSurfaceAdapter::SetBufferAllocation(BufferAllocationState state) {
+ surface_->SetBufferAllocation(state);
+}
+
+void* GLSurfaceAdapter::GetShareHandle() {
+ return surface_->GetShareHandle();
+}
+
+void* GLSurfaceAdapter::GetDisplay() {
+ return surface_->GetDisplay();
+}
+
+void* GLSurfaceAdapter::GetConfig() {
+ return surface_->GetConfig();
+}
+
+unsigned GLSurfaceAdapter::GetFormat() {
+ return surface_->GetFormat();
+}
+
+GLSurfaceAdapter::~GLSurfaceAdapter() {}
+
+} // namespace gfx
diff --git a/ui/gl/gl_surface.h b/ui/gl/gl_surface.h
new file mode 100644
index 0000000..efa4f23
--- /dev/null
+++ b/ui/gl/gl_surface.h
@@ -0,0 +1,157 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_SURFACE_H_
+#define UI_GL_GL_SURFACE_H_
+#pragma once
+
+#include "base/memory/ref_counted.h"
+#include "build/build_config.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/size.h"
+#include "ui/gl/gl_export.h"
+
+namespace gfx {
+
+class GLContext;
+
+#if defined(OS_ANDROID)
+class AndroidNativeWindow;
+#endif
+
+// Encapsulates a surface that can be rendered to with GL, hiding platform
+// specific management.
+class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> {
+ public:
+ GLSurface();
+
+ // (Re)create the surface. TODO(apatrick): This is an ugly hack to allow the
+ // EGL surface associated to be recreated without destroying the associated
+ // context. The implementation of this function for other GLSurface derived
+ // classes is in a pending changelist.
+ virtual bool Initialize();
+
+ // Destroys the surface.
+ virtual void Destroy() = 0;
+
+ virtual bool Resize(const gfx::Size& size);
+
+ // Returns true if this surface is offscreen.
+ virtual bool IsOffscreen() = 0;
+
+ // Swaps front and back buffers. This has no effect for off-screen
+ // contexts.
+ virtual bool SwapBuffers() = 0;
+
+ // Get the size of the surface.
+ virtual gfx::Size GetSize() = 0;
+
+#if defined(OS_ANDROID)
+ virtual void SetNativeWindow(AndroidNativeWindow* window) { }
+#endif
+
+ // Get the underlying platform specific surface "handle".
+ virtual void* GetHandle() = 0;
+
+ // Returns space separated list of surface specific extensions.
+ // The surface must be current.
+ virtual std::string GetExtensions();
+
+ // Returns the internal frame buffer object name if the surface is backed by
+ // FBO. Otherwise returns 0.
+ virtual unsigned int GetBackingFrameBufferObject();
+
+ // Copy part of the backbuffer to the frontbuffer.
+ virtual bool PostSubBuffer(int x, int y, int width, int height);
+
+ static bool InitializeOneOff();
+
+ // Called after a context is made current with this surface. Returns false
+ // on error.
+ virtual bool OnMakeCurrent(GLContext* context);
+
+ // Used for explicit buffer management. Expect buffers to be destroyed only
+ // when surface is not visible.
+ enum BufferAllocationState {
+ BUFFER_ALLOCATION_FRONT_AND_BACK,
+ BUFFER_ALLOCATION_FRONT_ONLY,
+ BUFFER_ALLOCATION_NONE
+ };
+ virtual void SetBufferAllocation(BufferAllocationState state);
+
+ // Get a handle used to share the surface with another process. Returns null
+ // if this is not possible.
+ virtual void* GetShareHandle();
+
+ // Get the platform specific display on which this surface resides, if
+ // available.
+ virtual void* GetDisplay();
+
+ // Get the platfrom specific configuration for this surface, if available.
+ virtual void* GetConfig();
+
+ // Get the GL pixel format of the surface, if available.
+ virtual unsigned GetFormat();
+
+ // Create a GL surface that renders directly to a view.
+ static scoped_refptr<GLSurface> CreateViewGLSurface(
+ bool software,
+ gfx::AcceleratedWidget window);
+
+ // Create a GL surface used for offscreen rendering.
+ static scoped_refptr<GLSurface> CreateOffscreenGLSurface(
+ bool software,
+ const gfx::Size& size);
+
+ static GLSurface* GetCurrent();
+
+ protected:
+ virtual ~GLSurface();
+ static bool InitializeOneOffInternal();
+ static void SetCurrent(GLSurface* surface);
+
+ private:
+ friend class base::RefCounted<GLSurface>;
+ friend class GLContext;
+
+ DISALLOW_COPY_AND_ASSIGN(GLSurface);
+};
+
+// Implementation of GLSurface that forwards all calls through to another
+// GLSurface.
+class GL_EXPORT GLSurfaceAdapter : public GLSurface {
+ public:
+ explicit GLSurfaceAdapter(GLSurface* surface);
+
+ virtual bool Initialize() OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool Resize(const gfx::Size& size) OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
+ virtual std::string GetExtensions() OVERRIDE;
+ virtual gfx::Size GetSize() OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+ virtual unsigned int GetBackingFrameBufferObject() OVERRIDE;
+ virtual bool OnMakeCurrent(GLContext* context) OVERRIDE;
+ virtual void SetBufferAllocation(BufferAllocationState state) OVERRIDE;
+ virtual void* GetShareHandle() OVERRIDE;
+ virtual void* GetDisplay() OVERRIDE;
+ virtual void* GetConfig() OVERRIDE;
+ virtual unsigned GetFormat() OVERRIDE;
+
+ GLSurface* surface() const { return surface_.get(); }
+
+ protected:
+ virtual ~GLSurfaceAdapter();
+
+ private:
+ scoped_refptr<GLSurface> surface_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLSurfaceAdapter);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_SURFACE_H_
diff --git a/ui/gl/gl_surface_android.cc b/ui/gl/gl_surface_android.cc
new file mode 100644
index 0000000..5500ba0
--- /dev/null
+++ b/ui/gl/gl_surface_android.cc
@@ -0,0 +1,181 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface_android.h"
+
+#include <EGL/egl.h>
+
+#include "base/logging.h"
+#include "base/memory/ref_counted.h"
+#include "ui/gl/android_native_window.h"
+#include "ui/gl/egl_util.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_implementation.h"
+
+namespace gfx {
+
+bool GLSurface::InitializeOneOffInternal() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ switch (GetGLImplementation()) {
+ case kGLImplementationEGLGLES2:
+ if (!GLSurfaceEGL::InitializeOneOff()) {
+ LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
+ return false;
+ }
+ break;
+ default:
+ NOTREACHED();
+ break;
+ }
+
+ initialized = true;
+ return true;
+}
+// static
+scoped_refptr<GLSurface>
+GLSurface::CreateViewGLSurface(bool software, gfx::AcceleratedWidget window) {
+ if (software)
+ return NULL;
+
+ switch (GetGLImplementation()) {
+ case kGLImplementationEGLGLES2: {
+ // window is unused
+ scoped_refptr<AndroidViewSurface> surface(new AndroidViewSurface());
+ if (!surface->Initialize())
+ return NULL;
+ return surface;
+ }
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+// static
+scoped_refptr<GLSurface>
+GLSurface::CreateOffscreenGLSurface(bool software, const gfx::Size& size) {
+ if (software)
+ return NULL;
+
+ switch (GetGLImplementation()) {
+ case kGLImplementationEGLGLES2: {
+ scoped_refptr<PbufferGLSurfaceEGL> surface(
+ new PbufferGLSurfaceEGL(false, size));
+ if (!surface->Initialize())
+ return NULL;
+ return surface;
+ }
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+AndroidViewSurface::AndroidViewSurface()
+ : NativeViewGLSurfaceEGL(false, 0),
+ pbuffer_surface_(new PbufferGLSurfaceEGL(false, Size(1, 1))),
+ window_(NULL) {
+}
+
+AndroidViewSurface::~AndroidViewSurface() {
+}
+
+bool AndroidViewSurface::Initialize() {
+ DCHECK(pbuffer_surface_.get());
+ return pbuffer_surface_->Initialize();
+}
+
+void AndroidViewSurface::Destroy() {
+ if (pbuffer_surface_.get()) {
+ pbuffer_surface_->Destroy();
+ } else {
+ window_ = NULL;
+ }
+ NativeViewGLSurfaceEGL::Destroy();
+}
+
+bool AndroidViewSurface::IsOffscreen() {
+ return false;
+}
+
+bool AndroidViewSurface::SwapBuffers() {
+ if (!pbuffer_surface_.get())
+ return NativeViewGLSurfaceEGL::SwapBuffers();
+ return true;
+}
+
+gfx::Size AndroidViewSurface::GetSize() {
+ if (pbuffer_surface_.get())
+ return pbuffer_surface_->GetSize();
+ else
+ return NativeViewGLSurfaceEGL::GetSize();
+}
+
+EGLSurface AndroidViewSurface::GetHandle() {
+ if (pbuffer_surface_.get())
+ return pbuffer_surface_->GetHandle();
+ else
+ return NativeViewGLSurfaceEGL::GetHandle();
+}
+
+bool AndroidViewSurface::Resize(const gfx::Size& size) {
+ if (pbuffer_surface_.get())
+ return pbuffer_surface_->Resize(size);
+ else if (GetHandle()) {
+ DCHECK(window_ && window_->GetNativeHandle());
+ // Deactivate and restore any currently active context.
+ EGLContext context = eglGetCurrentContext();
+ if (context != EGL_NO_CONTEXT) {
+ eglMakeCurrent(GetDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE,
+ EGL_NO_CONTEXT);
+ }
+ NativeViewGLSurfaceEGL::Destroy();
+ if (CreateWindowSurface(window_)) {
+ if (context != EGL_NO_CONTEXT)
+ eglMakeCurrent(GetDisplay(), GetHandle(), GetHandle(), context);
+ }
+ }
+ return true;
+}
+
+bool AndroidViewSurface::CreateWindowSurface(AndroidNativeWindow* window) {
+ DCHECK(window->GetNativeHandle());
+ window_ = window;
+ EGLSurface surface = eglCreateWindowSurface(GetDisplay(),
+ GetConfig(),
+ window->GetNativeHandle(),
+ NULL);
+ if (surface == EGL_NO_SURFACE) {
+ LOG(ERROR) << "eglCreateWindowSurface failed with error "
+ << GetLastEGLErrorString();
+ Destroy();
+ return false;
+ }
+
+ SetHandle(surface);
+ return true;
+}
+
+void AndroidViewSurface::SetNativeWindow(AndroidNativeWindow* window) {
+ if (window->GetNativeHandle()) {
+ DCHECK(pbuffer_surface_.get());
+ pbuffer_surface_->Destroy();
+ pbuffer_surface_ = NULL;
+
+ CreateWindowSurface(window);
+ } else {
+ DCHECK(GetHandle());
+ NativeViewGLSurfaceEGL::Destroy();
+ window_ = NULL;
+
+ pbuffer_surface_ = new PbufferGLSurfaceEGL(false, Size(1,1));
+ pbuffer_surface_->Initialize();
+ }
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_surface_android.h b/ui/gl/gl_surface_android.h
new file mode 100644
index 0000000..904274e
--- /dev/null
+++ b/ui/gl/gl_surface_android.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_SURFACE_ANDROID_H_
+#define UI_GL_GL_SURFACE_ANDROID_H_
+#pragma once
+
+#include "base/memory/ref_counted.h"
+#include "ui/gl/gl_surface_egl.h"
+
+namespace gfx {
+
+// A view surface. This can be created in the GPU process (default case), or
+// browser process (in-process-gpu), or render process (in-process-webgl). When
+// it is initialized, it always uses a pbuffer EGL surface until the native view
+// is set. The native view is in charge of sharing the GL texture with UI thread
+// in the browser process through SurfaceTexture.
+class AndroidViewSurface : public NativeViewGLSurfaceEGL {
+ public:
+ AndroidViewSurface();
+ virtual ~AndroidViewSurface();
+
+ // Implement GLSurface.
+ virtual bool Initialize() OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool Resize(const gfx::Size& size) OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual gfx::Size GetSize() OVERRIDE;
+ virtual EGLSurface GetHandle() OVERRIDE;
+ virtual void SetNativeWindow(AndroidNativeWindow* window) OVERRIDE;
+
+ private:
+ bool CreateWindowSurface(AndroidNativeWindow* window);
+
+ scoped_refptr<PbufferGLSurfaceEGL> pbuffer_surface_;
+ AndroidNativeWindow* window_;
+
+ DISALLOW_COPY_AND_ASSIGN(AndroidViewSurface);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_SURFACE_ANDROID_H_
diff --git a/ui/gl/gl_surface_cgl.cc b/ui/gl/gl_surface_cgl.cc
new file mode 100644
index 0000000..4f2fba2
--- /dev/null
+++ b/ui/gl/gl_surface_cgl.cc
@@ -0,0 +1,101 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface_cgl.h"
+
+#include <OpenGL/CGLRenderers.h>
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/mac/mac_util.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_implementation.h"
+
+namespace gfx {
+
+namespace {
+CGLPixelFormatObj g_pixel_format;
+}
+
+GLSurfaceCGL::GLSurfaceCGL() {}
+
+bool GLSurfaceCGL::InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ // This is called from the sandbox warmup code on Mac OS X.
+ // GPU-related stuff is very slow without this, probably because
+ // the sandbox prevents loading graphics drivers or some such.
+ std::vector<CGLPixelFormatAttribute> attribs;
+ if (GLContext::SupportsDualGpus()) {
+ // Avoid switching to the discrete GPU just for this pixel
+ // format selection.
+ attribs.push_back(kCGLPFAAllowOfflineRenderers);
+ }
+ if (GetGLImplementation() == kGLImplementationAppleGL) {
+ attribs.push_back(kCGLPFARendererID);
+ attribs.push_back(static_cast<CGLPixelFormatAttribute>(
+ kCGLRendererGenericFloatID));
+ }
+ attribs.push_back(static_cast<CGLPixelFormatAttribute>(0));
+
+ CGLPixelFormatObj format;
+ GLint num_pixel_formats;
+ if (CGLChoosePixelFormat(&attribs.front(),
+ &format,
+ &num_pixel_formats) != kCGLNoError) {
+ LOG(ERROR) << "Error choosing pixel format.";
+ return false;
+ }
+ if (!format) {
+ LOG(ERROR) << "format == 0.";
+ return false;
+ }
+ CGLReleasePixelFormat(format);
+ DCHECK_NE(num_pixel_formats, 0);
+ initialized = true;
+ return true;
+}
+
+void* GLSurfaceCGL::GetPixelFormat() {
+ return g_pixel_format;
+}
+
+GLSurfaceCGL::~GLSurfaceCGL() {}
+
+NoOpGLSurfaceCGL::NoOpGLSurfaceCGL(const gfx::Size& size)
+ : size_(size) {
+}
+
+bool NoOpGLSurfaceCGL::Initialize() {
+ return true;
+}
+
+void NoOpGLSurfaceCGL::Destroy() {
+}
+
+bool NoOpGLSurfaceCGL::IsOffscreen() {
+ return true;
+}
+
+bool NoOpGLSurfaceCGL::SwapBuffers() {
+ NOTREACHED() << "Cannot call SwapBuffers on a NoOpGLSurfaceCGL.";
+ return false;
+}
+
+gfx::Size NoOpGLSurfaceCGL::GetSize() {
+ return size_;
+}
+
+void* NoOpGLSurfaceCGL::GetHandle() {
+ return NULL;
+}
+
+NoOpGLSurfaceCGL::~NoOpGLSurfaceCGL() {
+ Destroy();
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_surface_cgl.h b/ui/gl/gl_surface_cgl.h
new file mode 100644
index 0000000..00886cf
--- /dev/null
+++ b/ui/gl/gl_surface_cgl.h
@@ -0,0 +1,56 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_SURFACE_CGL_H_
+#define UI_GL_GL_SURFACE_CGL_H_
+#pragma once
+
+#include "ui/gfx/size.h"
+#include "ui/gl/gl_surface.h"
+
+namespace gfx {
+
+// Base class for CGL surfaces.
+class GLSurfaceCGL : public GLSurface {
+ public:
+ GLSurfaceCGL();
+
+ static bool InitializeOneOff();
+ static void* GetPixelFormat();
+
+ protected:
+ virtual ~GLSurfaceCGL();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLSurfaceCGL);
+};
+
+// A "no-op" surface. It is not required that a CGLContextObj have an
+// associated drawable (pbuffer or fullscreen context) in order to be
+// made current. Everywhere this surface type is used, we allocate an
+// FBO at the user level as the drawable of the associated context.
+class GL_EXPORT NoOpGLSurfaceCGL : public GLSurfaceCGL {
+ public:
+ explicit NoOpGLSurfaceCGL(const gfx::Size& size);
+
+ // Implement GLSurface.
+ virtual bool Initialize() OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual gfx::Size GetSize() OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+
+ protected:
+ virtual ~NoOpGLSurfaceCGL();
+
+ private:
+ gfx::Size size_;
+
+ DISALLOW_COPY_AND_ASSIGN(NoOpGLSurfaceCGL);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_SURFACE_CGL_H_
diff --git a/ui/gl/gl_surface_egl.cc b/ui/gl/gl_surface_egl.cc
new file mode 100644
index 0000000..f3d3e0f
--- /dev/null
+++ b/ui/gl/gl_surface_egl.cc
@@ -0,0 +1,398 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface_egl.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "build/build_config.h"
+#if !defined(OS_ANDROID)
+#include "third_party/angle/include/EGL/egl.h"
+#include "third_party/angle/include/EGL/eglext.h"
+#endif
+#include "ui/gl/egl_util.h"
+#include "ui/gl/gl_context.h"
+
+#if defined(OS_ANDROID)
+#include <EGL/egl.h>
+#endif
+
+// This header must come after the above third-party include, as
+// it brings in #defines that cause conflicts.
+#include "ui/gl/gl_bindings.h"
+
+#if defined(USE_X11)
+extern "C" {
+#include <X11/Xlib.h>
+}
+#endif
+
+namespace gfx {
+
+namespace {
+EGLConfig g_config;
+EGLDisplay g_display;
+EGLNativeDisplayType g_native_display;
+EGLConfig g_software_config;
+EGLDisplay g_software_display;
+EGLNativeDisplayType g_software_native_display;
+}
+
+GLSurfaceEGL::GLSurfaceEGL() : software_(false) {
+}
+
+GLSurfaceEGL::~GLSurfaceEGL() {
+}
+
+bool GLSurfaceEGL::InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+#if defined(USE_X11)
+ g_native_display = base::MessagePumpForUI::GetDefaultXDisplay();
+#else
+ g_native_display = EGL_DEFAULT_DISPLAY;
+#endif
+ g_display = eglGetDisplay(g_native_display);
+ if (!g_display) {
+ LOG(ERROR) << "eglGetDisplay failed with error " << GetLastEGLErrorString();
+ return false;
+ }
+
+ if (!eglInitialize(g_display, NULL, NULL)) {
+ LOG(ERROR) << "eglInitialize failed with error " << GetLastEGLErrorString();
+ return false;
+ }
+
+ // Choose an EGL configuration.
+ static const EGLint kConfigAttribs[] = {
+ EGL_BUFFER_SIZE, 32,
+ EGL_ALPHA_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_RED_SIZE, 8,
+ EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT,
+ EGL_NONE
+ };
+
+ EGLint num_configs;
+ if (!eglChooseConfig(g_display,
+ kConfigAttribs,
+ NULL,
+ 0,
+ &num_configs)) {
+ LOG(ERROR) << "eglChooseConfig failed failed with error "
+ << GetLastEGLErrorString();
+ return false;
+ }
+
+ if (num_configs == 0) {
+ LOG(ERROR) << "No suitable EGL configs found.";
+ return false;
+ }
+
+ if (!eglChooseConfig(g_display,
+ kConfigAttribs,
+ &g_config,
+ 1,
+ &num_configs)) {
+ LOG(ERROR) << "eglChooseConfig failed with error "
+ << GetLastEGLErrorString();
+ return false;
+ }
+
+ initialized = true;
+
+#if defined(USE_X11) || defined(OS_ANDROID)
+ return true;
+#else
+ g_software_native_display = EGL_SOFTWARE_DISPLAY_ANGLE;
+#endif
+ g_software_display = eglGetDisplay(g_software_native_display);
+ if (!g_software_display) {
+ return true;
+ }
+
+ if (!eglInitialize(g_software_display, NULL, NULL)) {
+ return true;
+ }
+
+ if (!eglChooseConfig(g_software_display,
+ kConfigAttribs,
+ NULL,
+ 0,
+ &num_configs)) {
+ g_software_display = NULL;
+ return true;
+ }
+
+ if (num_configs == 0) {
+ g_software_display = NULL;
+ return true;
+ }
+
+ if (!eglChooseConfig(g_software_display,
+ kConfigAttribs,
+ &g_software_config,
+ 1,
+ &num_configs)) {
+ g_software_display = NULL;
+ return false;
+ }
+
+ return true;
+}
+
+EGLDisplay GLSurfaceEGL::GetDisplay() {
+ return software_ ? g_software_display : g_display;
+}
+
+EGLConfig GLSurfaceEGL::GetConfig() {
+ return software_ ? g_software_config : g_config;
+}
+
+EGLDisplay GLSurfaceEGL::GetHardwareDisplay() {
+ return g_display;
+}
+
+EGLDisplay GLSurfaceEGL::GetSoftwareDisplay() {
+ return g_software_display;
+}
+
+EGLNativeDisplayType GLSurfaceEGL::GetNativeDisplay() {
+ return g_native_display;
+}
+
+NativeViewGLSurfaceEGL::NativeViewGLSurfaceEGL(bool software,
+ gfx::AcceleratedWidget window)
+ : window_(window),
+ surface_(NULL),
+ supports_post_sub_buffer_(false)
+{
+ software_ = software;
+}
+
+NativeViewGLSurfaceEGL::~NativeViewGLSurfaceEGL() {
+ Destroy();
+}
+
+bool NativeViewGLSurfaceEGL::Initialize() {
+#if defined(OS_ANDROID)
+ NOTREACHED();
+ return false;
+#else
+ DCHECK(!surface_);
+
+ if (!GetDisplay()) {
+ LOG(ERROR) << "Trying to create surface with invalid display.";
+ return false;
+ }
+
+ static const EGLint egl_window_attributes_sub_buffer[] = {
+ EGL_POST_SUB_BUFFER_SUPPORTED_NV, EGL_TRUE,
+ EGL_NONE
+ };
+
+ // Create a surface for the native window.
+ surface_ = eglCreateWindowSurface(GetDisplay(),
+ GetConfig(),
+ window_,
+ gfx::g_EGL_NV_post_sub_buffer ?
+ egl_window_attributes_sub_buffer :
+ NULL);
+
+ if (!surface_) {
+ LOG(ERROR) << "eglCreateWindowSurface failed with error "
+ << GetLastEGLErrorString();
+ Destroy();
+ return false;
+ }
+
+ EGLint surfaceVal;
+ EGLBoolean retVal = eglQuerySurface(GetDisplay(),
+ surface_,
+ EGL_POST_SUB_BUFFER_SUPPORTED_NV,
+ &surfaceVal);
+ supports_post_sub_buffer_ = (surfaceVal && retVal) == EGL_TRUE;
+
+ return true;
+#endif
+}
+
+void NativeViewGLSurfaceEGL::Destroy() {
+ if (surface_) {
+ if (!eglDestroySurface(GetDisplay(), surface_)) {
+ LOG(ERROR) << "eglDestroySurface failed with error "
+ << GetLastEGLErrorString();
+ }
+ surface_ = NULL;
+ }
+}
+
+bool NativeViewGLSurfaceEGL::IsOffscreen() {
+ return false;
+}
+
+bool NativeViewGLSurfaceEGL::SwapBuffers() {
+ if (!eglSwapBuffers(GetDisplay(), surface_)) {
+ DVLOG(1) << "eglSwapBuffers failed with error "
+ << GetLastEGLErrorString();
+ return false;
+ }
+
+ return true;
+}
+
+gfx::Size NativeViewGLSurfaceEGL::GetSize() {
+ EGLint width;
+ EGLint height;
+ if (!eglQuerySurface(GetDisplay(), surface_, EGL_WIDTH, &width) ||
+ !eglQuerySurface(GetDisplay(), surface_, EGL_HEIGHT, &height)) {
+ NOTREACHED() << "eglQuerySurface failed with error "
+ << GetLastEGLErrorString();
+ return gfx::Size();
+ }
+
+ return gfx::Size(width, height);
+}
+
+EGLSurface NativeViewGLSurfaceEGL::GetHandle() {
+ return surface_;
+}
+
+std::string NativeViewGLSurfaceEGL::GetExtensions() {
+ std::string extensions = GLSurface::GetExtensions();
+ if (supports_post_sub_buffer_) {
+ extensions += extensions.empty() ? "" : " ";
+ extensions += "GL_CHROMIUM_post_sub_buffer";
+ }
+ return extensions;
+}
+
+bool NativeViewGLSurfaceEGL::PostSubBuffer(
+ int x, int y, int width, int height) {
+ DCHECK(supports_post_sub_buffer_);
+ if (!eglPostSubBufferNV(GetDisplay(), surface_, x, y, width, height)) {
+ DVLOG(1) << "eglPostSubBufferNV failed with error "
+ << GetLastEGLErrorString();
+ return false;
+ }
+ return true;
+}
+
+void NativeViewGLSurfaceEGL::SetHandle(EGLSurface surface) {
+ surface_ = surface;
+}
+
+PbufferGLSurfaceEGL::PbufferGLSurfaceEGL(bool software, const gfx::Size& size)
+ : size_(size),
+ surface_(NULL) {
+ software_ = software;
+}
+
+PbufferGLSurfaceEGL::~PbufferGLSurfaceEGL() {
+ Destroy();
+}
+
+bool PbufferGLSurfaceEGL::Initialize() {
+ DCHECK(!surface_);
+
+ if (!GetDisplay()) {
+ LOG(ERROR) << "Trying to create surface with invalid display.";
+ return false;
+ }
+
+ const EGLint pbuffer_attribs[] = {
+ EGL_WIDTH, size_.width(),
+ EGL_HEIGHT, size_.height(),
+ EGL_NONE
+ };
+
+ surface_ = eglCreatePbufferSurface(GetDisplay(),
+ GetConfig(),
+ pbuffer_attribs);
+ if (!surface_) {
+ LOG(ERROR) << "eglCreatePbufferSurface failed with error "
+ << GetLastEGLErrorString();
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void PbufferGLSurfaceEGL::Destroy() {
+ if (surface_) {
+ if (!eglDestroySurface(GetDisplay(), surface_)) {
+ LOG(ERROR) << "eglDestroySurface failed with error "
+ << GetLastEGLErrorString();
+ }
+ surface_ = NULL;
+ }
+}
+
+bool PbufferGLSurfaceEGL::IsOffscreen() {
+ return true;
+}
+
+bool PbufferGLSurfaceEGL::SwapBuffers() {
+ NOTREACHED() << "Attempted to call SwapBuffers on a PbufferGLSurfaceEGL.";
+ return false;
+}
+
+gfx::Size PbufferGLSurfaceEGL::GetSize() {
+ return size_;
+}
+
+bool PbufferGLSurfaceEGL::Resize(const gfx::Size& size) {
+ if (size == size_)
+ return true;
+
+ GLContext* current_context = GLContext::GetCurrent();
+ bool was_current = current_context && current_context->IsCurrent(this);
+ if (was_current)
+ current_context->ReleaseCurrent(this);
+
+ Destroy();
+
+ size_ = size;
+
+ if (!Initialize())
+ return false;
+
+ if (was_current)
+ return current_context->MakeCurrent(this);
+
+ return true;
+}
+
+EGLSurface PbufferGLSurfaceEGL::GetHandle() {
+ return surface_;
+}
+
+void* PbufferGLSurfaceEGL::GetShareHandle() {
+#if defined(OS_ANDROID)
+ NOTREACHED();
+ return NULL;
+#else
+ const char* extensions = eglQueryString(g_display, EGL_EXTENSIONS);
+ if (!strstr(extensions, "EGL_ANGLE_query_surface_pointer"))
+ return NULL;
+
+ void* handle;
+ if (!eglQuerySurfacePointerANGLE(g_display,
+ GetHandle(),
+ EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE,
+ &handle)) {
+ return NULL;
+ }
+
+ return handle;
+#endif
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_surface_egl.h b/ui/gl/gl_surface_egl.h
new file mode 100644
index 0000000..423ef06
--- /dev/null
+++ b/ui/gl/gl_surface_egl.h
@@ -0,0 +1,106 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_SURFACE_EGL_H_
+#define UI_GL_GL_SURFACE_EGL_H_
+#pragma once
+
+#if defined(OS_WIN)
+#include <windows.h>
+#endif
+
+#include "base/compiler_specific.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/size.h"
+#include "ui/gl/gl_surface.h"
+
+typedef void* EGLConfig;
+typedef void* EGLDisplay;
+typedef void* EGLSurface;
+
+#if defined(OS_ANDROID)
+typedef void* EGLNativeDisplayType;
+#elif defined(OS_WIN)
+typedef HDC EGLNativeDisplayType;
+#else
+typedef struct _XDisplay* EGLNativeDisplayType;
+#endif
+
+namespace gfx {
+
+// Interface for EGL surface.
+class GL_EXPORT GLSurfaceEGL : public GLSurface {
+ public:
+ GLSurfaceEGL();
+ virtual ~GLSurfaceEGL();
+
+ // Implement GLSurface.
+ virtual EGLDisplay GetDisplay() OVERRIDE;
+ virtual EGLConfig GetConfig() OVERRIDE;
+
+ static bool InitializeOneOff();
+ static EGLDisplay GetHardwareDisplay();
+ static EGLDisplay GetSoftwareDisplay();
+ static EGLNativeDisplayType GetNativeDisplay();
+
+ protected:
+ bool software_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLSurfaceEGL);
+};
+
+// Encapsulates an EGL surface bound to a view.
+class NativeViewGLSurfaceEGL : public GLSurfaceEGL {
+ public:
+ NativeViewGLSurfaceEGL(bool software, gfx::AcceleratedWidget window);
+ virtual ~NativeViewGLSurfaceEGL();
+
+ // Implement GLSurface.
+ virtual bool Initialize() OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual gfx::Size GetSize() OVERRIDE;
+ virtual EGLSurface GetHandle() OVERRIDE;
+ virtual std::string GetExtensions() OVERRIDE;
+ virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
+
+ protected:
+ void SetHandle(EGLSurface surface);
+
+ private:
+ gfx::AcceleratedWidget window_;
+ EGLSurface surface_;
+ bool supports_post_sub_buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceEGL);
+};
+
+// Encapsulates a pbuffer EGL surface.
+class GL_EXPORT PbufferGLSurfaceEGL : public GLSurfaceEGL {
+ public:
+ PbufferGLSurfaceEGL(bool software, const gfx::Size& size);
+ virtual ~PbufferGLSurfaceEGL();
+
+ // Implement GLSurface.
+ virtual bool Initialize() OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual gfx::Size GetSize() OVERRIDE;
+ virtual bool Resize(const gfx::Size& size) OVERRIDE;
+ virtual EGLSurface GetHandle() OVERRIDE;
+ virtual void* GetShareHandle() OVERRIDE;
+
+ private:
+ gfx::Size size_;
+ EGLSurface surface_;
+
+ DISALLOW_COPY_AND_ASSIGN(PbufferGLSurfaceEGL);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_SURFACE_EGL_H_
diff --git a/ui/gl/gl_surface_glx.cc b/ui/gl/gl_surface_glx.cc
new file mode 100644
index 0000000..ba8ce92
--- /dev/null
+++ b/ui/gl/gl_surface_glx.cc
@@ -0,0 +1,326 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+extern "C" {
+#include <X11/Xlib.h>
+}
+
+#include "ui/gl/gl_surface_glx.h"
+
+#include "base/basictypes.h"
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "base/process_util.h"
+#include "third_party/mesa/MesaLib/include/GL/osmesa.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+
+namespace gfx {
+
+namespace {
+
+// scoped_ptr functor for XFree(). Use as follows:
+// scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> foo(...);
+// where "XVisualInfo" is any X type that is freed with XFree.
+class ScopedPtrXFree {
+ public:
+ void operator()(void* x) const {
+ ::XFree(x);
+ }
+};
+
+Display* g_display;
+const char* g_glx_extensions = NULL;
+bool g_glx_create_context_robustness_supported = false;
+
+} // namespace anonymous
+
+GLSurfaceGLX::GLSurfaceGLX() {
+}
+
+GLSurfaceGLX::~GLSurfaceGLX() {
+}
+
+bool GLSurfaceGLX::InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ g_display = base::MessagePumpForUI::GetDefaultXDisplay();
+ if (!g_display) {
+ LOG(ERROR) << "XOpenDisplay failed.";
+ return false;
+ }
+
+ int major, minor;
+ if (!glXQueryVersion(g_display, &major, &minor)) {
+ LOG(ERROR) << "glxQueryVersion failed";
+ return false;
+ }
+
+ if (major == 1 && minor < 3) {
+ LOG(ERROR) << "GLX 1.3 or later is required.";
+ return false;
+ }
+
+ g_glx_extensions = glXQueryExtensionsString(g_display, 0);
+ g_glx_create_context_robustness_supported =
+ HasGLXExtension("GLX_ARB_create_context_robustness");
+
+ initialized = true;
+ return true;
+}
+
+// static
+const char* GLSurfaceGLX::GetGLXExtensions() {
+ return g_glx_extensions;
+}
+
+// static
+bool GLSurfaceGLX::HasGLXExtension(const char* name) {
+ DCHECK(name);
+ const char* c_extensions = GetGLXExtensions();
+ if (!c_extensions)
+ return false;
+ std::string extensions(c_extensions);
+ extensions += " ";
+
+ std::string delimited_name(name);
+ delimited_name += " ";
+
+ return extensions.find(delimited_name) != std::string::npos;
+}
+
+// static
+bool GLSurfaceGLX::IsCreateContextRobustnessSupported() {
+ return g_glx_create_context_robustness_supported;
+}
+
+void* GLSurfaceGLX::GetDisplay() {
+ return g_display;
+}
+
+NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window)
+ : window_(window),
+ config_(NULL) {
+}
+
+NativeViewGLSurfaceGLX::NativeViewGLSurfaceGLX()
+ : window_(0),
+ config_(NULL) {
+}
+
+NativeViewGLSurfaceGLX::~NativeViewGLSurfaceGLX() {
+ Destroy();
+}
+
+bool NativeViewGLSurfaceGLX::Initialize() {
+ XWindowAttributes attributes;
+ if (!XGetWindowAttributes(g_display, window_, &attributes)) {
+ LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
+ return false;
+ }
+ size_ = gfx::Size(attributes.width, attributes.height);
+ return true;
+}
+
+void NativeViewGLSurfaceGLX::Destroy() {
+}
+
+bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size) {
+ // On Intel drivers, the frame buffer won't be resize until the next swap. If
+ // we only do PostSubBuffer, then we're stuck in the old size. Force a swap
+ // now.
+ if (gfx::g_GLX_MESA_copy_sub_buffer && size_ != size)
+ SwapBuffers();
+ size_ = size;
+ return true;
+}
+
+bool NativeViewGLSurfaceGLX::IsOffscreen() {
+ return false;
+}
+
+bool NativeViewGLSurfaceGLX::SwapBuffers() {
+ glXSwapBuffers(g_display, window_);
+ return true;
+}
+
+gfx::Size NativeViewGLSurfaceGLX::GetSize() {
+ return size_;
+}
+
+void* NativeViewGLSurfaceGLX::GetHandle() {
+ return reinterpret_cast<void*>(window_);
+}
+
+std::string NativeViewGLSurfaceGLX::GetExtensions() {
+ std::string extensions = GLSurface::GetExtensions();
+ if (g_GLX_MESA_copy_sub_buffer) {
+ extensions += extensions.empty() ? "" : " ";
+ extensions += "GL_CHROMIUM_post_sub_buffer";
+ }
+ return extensions;
+}
+
+void* NativeViewGLSurfaceGLX::GetConfig() {
+ if (!config_) {
+ // This code path is expensive, but we only take it when
+ // attempting to use GLX_ARB_create_context_robustness, in which
+ // case we need a GLXFBConfig for the window in order to create a
+ // context for it.
+ //
+ // TODO(kbr): this is not a reliable code path. On platforms which
+ // support it, we should use glXChooseFBConfig in the browser
+ // process to choose the FBConfig and from there the X Visual to
+ // use when creating the window in the first place. Then we can
+ // pass that FBConfig down rather than attempting to reconstitute
+ // it.
+
+ XWindowAttributes attributes;
+ if (!XGetWindowAttributes(
+ g_display,
+ reinterpret_cast<GLXDrawable>(GetHandle()),
+ &attributes)) {
+ LOG(ERROR) << "XGetWindowAttributes failed for window " <<
+ reinterpret_cast<GLXDrawable>(GetHandle()) << ".";
+ return NULL;
+ }
+
+ int visual_id = XVisualIDFromVisual(attributes.visual);
+
+ int num_elements = 0;
+ scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs(
+ glXGetFBConfigs(g_display,
+ DefaultScreen(g_display),
+ &num_elements));
+ if (!configs.get()) {
+ LOG(ERROR) << "glXGetFBConfigs failed.";
+ return NULL;
+ }
+ if (!num_elements) {
+ LOG(ERROR) << "glXGetFBConfigs returned 0 elements.";
+ return NULL;
+ }
+ bool found = false;
+ int i;
+ for (i = 0; i < num_elements; ++i) {
+ int value;
+ if (glXGetFBConfigAttrib(
+ g_display, configs.get()[i], GLX_VISUAL_ID, &value)) {
+ LOG(ERROR) << "glXGetFBConfigAttrib failed.";
+ return NULL;
+ }
+ if (value == visual_id) {
+ found = true;
+ break;
+ }
+ }
+ if (found) {
+ config_ = configs.get()[i];
+ }
+ }
+
+ return config_;
+}
+
+bool NativeViewGLSurfaceGLX::PostSubBuffer(
+ int x, int y, int width, int height) {
+ DCHECK(g_GLX_MESA_copy_sub_buffer);
+ glXCopySubBufferMESA(g_display, window_, x, y, width, height);
+ return true;
+}
+
+PbufferGLSurfaceGLX::PbufferGLSurfaceGLX(const gfx::Size& size)
+ : size_(size),
+ config_(NULL),
+ pbuffer_(0) {
+}
+
+PbufferGLSurfaceGLX::~PbufferGLSurfaceGLX() {
+ Destroy();
+}
+
+bool PbufferGLSurfaceGLX::Initialize() {
+ DCHECK(!pbuffer_);
+
+ static const int config_attributes[] = {
+ GLX_BUFFER_SIZE, 32,
+ GLX_ALPHA_SIZE, 8,
+ GLX_BLUE_SIZE, 8,
+ GLX_GREEN_SIZE, 8,
+ GLX_RED_SIZE, 8,
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DRAWABLE_TYPE, GLX_PBUFFER_BIT,
+ GLX_DOUBLEBUFFER, False,
+ 0
+ };
+
+ int num_elements = 0;
+ scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> configs(
+ glXChooseFBConfig(g_display,
+ DefaultScreen(g_display),
+ config_attributes,
+ &num_elements));
+ if (!configs.get()) {
+ LOG(ERROR) << "glXChooseFBConfig failed.";
+ return false;
+ }
+ if (!num_elements) {
+ LOG(ERROR) << "glXChooseFBConfig returned 0 elements.";
+ return false;
+ }
+
+ config_ = configs.get()[0];
+
+ const int pbuffer_attributes[] = {
+ GLX_PBUFFER_WIDTH, size_.width(),
+ GLX_PBUFFER_HEIGHT, size_.height(),
+ 0
+ };
+ pbuffer_ = glXCreatePbuffer(g_display,
+ static_cast<GLXFBConfig>(config_),
+ pbuffer_attributes);
+ if (!pbuffer_) {
+ Destroy();
+ LOG(ERROR) << "glXCreatePbuffer failed.";
+ return false;
+ }
+
+ return true;
+}
+
+void PbufferGLSurfaceGLX::Destroy() {
+ if (pbuffer_) {
+ glXDestroyPbuffer(g_display, pbuffer_);
+ pbuffer_ = 0;
+ }
+
+ config_ = NULL;
+}
+
+bool PbufferGLSurfaceGLX::IsOffscreen() {
+ return true;
+}
+
+bool PbufferGLSurfaceGLX::SwapBuffers() {
+ NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
+ return false;
+}
+
+gfx::Size PbufferGLSurfaceGLX::GetSize() {
+ return size_;
+}
+
+void* PbufferGLSurfaceGLX::GetHandle() {
+ return reinterpret_cast<void*>(pbuffer_);
+}
+
+void* PbufferGLSurfaceGLX::GetConfig() {
+ return config_;
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_surface_glx.h b/ui/gl/gl_surface_glx.h
new file mode 100644
index 0000000..ac4655e
--- /dev/null
+++ b/ui/gl/gl_surface_glx.h
@@ -0,0 +1,98 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_SURFACE_GLX_H_
+#define UI_GL_GL_SURFACE_GLX_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/size.h"
+#include "ui/gl/gl_export.h"
+#include "ui/gl/gl_surface.h"
+
+namespace gfx {
+
+// Base class for GLX surfaces.
+class GL_EXPORT GLSurfaceGLX : public GLSurface {
+ public:
+ GLSurfaceGLX();
+ virtual ~GLSurfaceGLX();
+
+ static bool InitializeOneOff();
+
+ // These aren't particularly tied to surfaces, but since we already
+ // have the static InitializeOneOff here, it's easiest to reuse its
+ // initialization guards.
+ static const char* GetGLXExtensions();
+ static bool HasGLXExtension(const char* name);
+ static bool IsCreateContextRobustnessSupported();
+
+ virtual void* GetDisplay() OVERRIDE;
+
+ // Get the FB config that the surface was created with or NULL if it is not
+ // a GLX drawable.
+ virtual void* GetConfig() = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLSurfaceGLX);
+};
+
+// A surface used to render to a view.
+class GL_EXPORT NativeViewGLSurfaceGLX : public GLSurfaceGLX {
+ public:
+ explicit NativeViewGLSurfaceGLX(gfx::AcceleratedWidget window);
+ virtual ~NativeViewGLSurfaceGLX();
+
+ // Implement GLSurfaceGLX.
+ virtual bool Initialize() OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool Resize(const gfx::Size& size) OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual gfx::Size GetSize() OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+ virtual std::string GetExtensions() OVERRIDE;
+ virtual void* GetConfig() OVERRIDE;
+ virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
+
+ protected:
+ NativeViewGLSurfaceGLX();
+
+ gfx::AcceleratedWidget window_;
+
+ private:
+ void* config_;
+ gfx::Size size_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceGLX);
+};
+
+// A surface used to render to an offscreen pbuffer.
+class GL_EXPORT PbufferGLSurfaceGLX : public GLSurfaceGLX {
+ public:
+ explicit PbufferGLSurfaceGLX(const gfx::Size& size);
+ virtual ~PbufferGLSurfaceGLX();
+
+ // Implement GLSurfaceGLX.
+ virtual bool Initialize() OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual gfx::Size GetSize() OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+ virtual void* GetConfig() OVERRIDE;
+
+ private:
+ gfx::Size size_;
+ void* config_;
+ XID pbuffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(PbufferGLSurfaceGLX);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_SURFACE_GLX_H_
diff --git a/ui/gl/gl_surface_linux.cc b/ui/gl/gl_surface_linux.cc
new file mode 100644
index 0000000..a7dbdf0
--- /dev/null
+++ b/ui/gl/gl_surface_linux.cc
@@ -0,0 +1,339 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "base/message_loop.h"
+#include "third_party/mesa/MesaLib/include/GL/osmesa.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/gl_surface_glx.h"
+#include "ui/gl/gl_surface_osmesa.h"
+#include "ui/gl/gl_surface_stub.h"
+
+namespace gfx {
+
+namespace {
+Display* g_osmesa_display;
+} // namespace anonymous
+
+// This OSMesa GL surface can use XLib to swap the contents of the buffer to a
+// view.
+class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa {
+ public:
+ explicit NativeViewGLSurfaceOSMesa(gfx::AcceleratedWidget window);
+ virtual ~NativeViewGLSurfaceOSMesa();
+
+ static bool InitializeOneOff();
+
+ // Implement a subset of GLSurface.
+ virtual bool Initialize() OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool Resize(const gfx::Size& new_size) OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual std::string GetExtensions() OVERRIDE;
+ virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
+
+ private:
+ GC window_graphics_context_;
+ gfx::AcceleratedWidget window_;
+ GC pixmap_graphics_context_;
+ Pixmap pixmap_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa);
+};
+
+bool GLSurface::InitializeOneOffInternal() {
+ switch (GetGLImplementation()) {
+ case kGLImplementationDesktopGL:
+ if (!GLSurfaceGLX::InitializeOneOff()) {
+ LOG(ERROR) << "GLSurfaceGLX::InitializeOneOff failed.";
+ return false;
+ }
+ break;
+ case kGLImplementationOSMesaGL:
+ if (!NativeViewGLSurfaceOSMesa::InitializeOneOff()) {
+ LOG(ERROR) << "NativeViewGLSurfaceOSMesa::InitializeOneOff failed.";
+ return false;
+ }
+ break;
+ case kGLImplementationEGLGLES2:
+ if (!GLSurfaceEGL::InitializeOneOff()) {
+ LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return true;
+}
+
+NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa(
+ gfx::AcceleratedWidget window)
+ : GLSurfaceOSMesa(OSMESA_BGRA, gfx::Size(1, 1)),
+ window_graphics_context_(0),
+ window_(window),
+ pixmap_graphics_context_(0),
+ pixmap_(0) {
+ DCHECK(window);
+}
+
+NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
+ Destroy();
+}
+
+bool NativeViewGLSurfaceOSMesa::InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ g_osmesa_display = base::MessagePumpForUI::GetDefaultXDisplay();
+ if (!g_osmesa_display) {
+ LOG(ERROR) << "XOpenDisplay failed.";
+ return false;
+ }
+
+ initialized = true;
+ return true;
+}
+
+bool NativeViewGLSurfaceOSMesa::Initialize() {
+ if (!GLSurfaceOSMesa::Initialize())
+ return false;
+
+ window_graphics_context_ = XCreateGC(g_osmesa_display,
+ window_,
+ 0,
+ NULL);
+ if (!window_graphics_context_) {
+ LOG(ERROR) << "XCreateGC failed.";
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void NativeViewGLSurfaceOSMesa::Destroy() {
+ if (pixmap_graphics_context_) {
+ XFreeGC(g_osmesa_display, pixmap_graphics_context_);
+ pixmap_graphics_context_ = NULL;
+ }
+
+ if (pixmap_) {
+ XFreePixmap(g_osmesa_display, pixmap_);
+ pixmap_ = 0;
+ }
+
+ if (window_graphics_context_) {
+ XFreeGC(g_osmesa_display, window_graphics_context_);
+ window_graphics_context_ = NULL;
+ }
+}
+
+bool NativeViewGLSurfaceOSMesa::Resize(const gfx::Size& new_size) {
+ if (!GLSurfaceOSMesa::Resize(new_size))
+ return false;
+
+ XWindowAttributes attributes;
+ if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) {
+ LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
+ return false;
+ }
+
+ // Destroy the previous pixmap and graphics context.
+ if (pixmap_graphics_context_) {
+ XFreeGC(g_osmesa_display, pixmap_graphics_context_);
+ pixmap_graphics_context_ = NULL;
+ }
+ if (pixmap_) {
+ XFreePixmap(g_osmesa_display, pixmap_);
+ pixmap_ = 0;
+ }
+
+ // Recreate a pixmap to hold the frame.
+ pixmap_ = XCreatePixmap(g_osmesa_display,
+ window_,
+ new_size.width(),
+ new_size.height(),
+ attributes.depth);
+ if (!pixmap_) {
+ LOG(ERROR) << "XCreatePixmap failed.";
+ return false;
+ }
+
+ // Recreate a graphics context for the pixmap.
+ pixmap_graphics_context_ = XCreateGC(g_osmesa_display, pixmap_, 0, NULL);
+ if (!pixmap_graphics_context_) {
+ LOG(ERROR) << "XCreateGC failed";
+ return false;
+ }
+
+ return true;
+}
+
+bool NativeViewGLSurfaceOSMesa::IsOffscreen() {
+ return false;
+}
+
+bool NativeViewGLSurfaceOSMesa::SwapBuffers() {
+ gfx::Size size = GetSize();
+
+ XWindowAttributes attributes;
+ if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) {
+ LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
+ return false;
+ }
+
+ // Copy the frame into the pixmap.
+ ui::PutARGBImage(g_osmesa_display,
+ attributes.visual,
+ attributes.depth,
+ pixmap_,
+ pixmap_graphics_context_,
+ static_cast<const uint8*>(GetHandle()),
+ size.width(),
+ size.height());
+
+ // Copy the pixmap to the window.
+ XCopyArea(g_osmesa_display,
+ pixmap_,
+ window_,
+ window_graphics_context_,
+ 0, 0,
+ size.width(), size.height(),
+ 0, 0);
+
+ return true;
+}
+
+std::string NativeViewGLSurfaceOSMesa::GetExtensions() {
+ std::string extensions = gfx::GLSurfaceOSMesa::GetExtensions();
+ extensions += extensions.empty() ? "" : " ";
+ extensions += "GL_CHROMIUM_post_sub_buffer";
+ return extensions;
+}
+
+bool NativeViewGLSurfaceOSMesa::PostSubBuffer(
+ int x, int y, int width, int height) {
+ gfx::Size size = GetSize();
+
+ // Move (0,0) from lower-left to upper-left
+ y = size.height() - y - height;
+
+ XWindowAttributes attributes;
+ if (!XGetWindowAttributes(g_osmesa_display, window_, &attributes)) {
+ LOG(ERROR) << "XGetWindowAttributes failed for window " << window_ << ".";
+ return false;
+ }
+
+ // Copy the frame into the pixmap.
+ ui::PutARGBImage(g_osmesa_display,
+ attributes.visual,
+ attributes.depth,
+ pixmap_,
+ pixmap_graphics_context_,
+ static_cast<const uint8*>(GetHandle()),
+ size.width(),
+ size.height(),
+ x, y,
+ x, y,
+ width,
+ height);
+
+ // Copy the pixmap to the window.
+ XCopyArea(g_osmesa_display,
+ pixmap_,
+ window_,
+ window_graphics_context_,
+ x, y,
+ width, height,
+ x, y);
+
+ return true;
+}
+
+scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
+ bool software,
+ gfx::AcceleratedWidget window) {
+ if (software)
+ return NULL;
+
+ switch (GetGLImplementation()) {
+ case kGLImplementationOSMesaGL: {
+ scoped_refptr<GLSurface> surface(
+ new NativeViewGLSurfaceOSMesa(window));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationDesktopGL: {
+ scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceGLX(
+ window));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationEGLGLES2: {
+ scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL(
+ false, window));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationMockGL:
+ return new GLSurfaceStub;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
+ bool software,
+ const gfx::Size& size) {
+ if (software)
+ return NULL;
+
+ switch (GetGLImplementation()) {
+ case kGLImplementationOSMesaGL: {
+ scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
+ size));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationDesktopGL: {
+ scoped_refptr<GLSurface> surface(new PbufferGLSurfaceGLX(size));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationEGLGLES2: {
+ scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(false, size));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationMockGL:
+ return new GLSurfaceStub;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_surface_mac.cc b/ui/gl/gl_surface_mac.cc
new file mode 100644
index 0000000..0431628
--- /dev/null
+++ b/ui/gl/gl_surface_mac.cc
@@ -0,0 +1,95 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/mesa/MesaLib/include/GL/osmesa.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_cgl.h"
+#include "ui/gl/gl_surface_osmesa.h"
+#include "ui/gl/gl_surface_stub.h"
+
+#if defined(USE_AURA)
+#include "ui/gl/gl_surface_nsview.h"
+#endif
+
+namespace gfx {
+
+bool GLSurface::InitializeOneOffInternal() {
+ switch (GetGLImplementation()) {
+ case kGLImplementationDesktopGL:
+ case kGLImplementationAppleGL:
+ if (!GLSurfaceCGL::InitializeOneOff()) {
+ LOG(ERROR) << "GLSurfaceCGL::InitializeOneOff failed.";
+ return false;
+ }
+ break;
+ default:
+ break;
+ }
+ return true;
+}
+
+scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
+ bool software,
+ gfx::AcceleratedWidget window) {
+#if defined(USE_AURA)
+ if (software)
+ return NULL;
+
+ switch (GetGLImplementation()) {
+ case kGLImplementationDesktopGL:
+ case kGLImplementationAppleGL: {
+ scoped_refptr<GLSurface> surface(new GLSurfaceNSView(window));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationMockGL:
+ return new GLSurfaceStub;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+#else
+ return CreateOffscreenGLSurface(software, gfx::Size(1,1));
+#endif
+}
+
+scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
+ bool software,
+ const gfx::Size& size) {
+ if (software)
+ return NULL;
+
+ switch (GetGLImplementation()) {
+ case kGLImplementationOSMesaGL: {
+ scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
+ size));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationDesktopGL:
+ case kGLImplementationAppleGL: {
+ scoped_refptr<GLSurface> surface(new NoOpGLSurfaceCGL(size));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationMockGL:
+ return new GLSurfaceStub;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_surface_nsview.h b/ui/gl/gl_surface_nsview.h
new file mode 100644
index 0000000..440458b
--- /dev/null
+++ b/ui/gl/gl_surface_nsview.h
@@ -0,0 +1,47 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_SURFACE_NSVIEW_H_
+#define UI_GL_GL_SURFACE_NSVIEW_H_
+#pragma once
+
+#include "base/compiler_specific.h"
+#include "ui/gfx/size.h"
+#include "ui/gl/gl_surface.h"
+
+namespace gfx {
+
+class GLContextNSView;
+
+// GLSurfaceNSView provides an implementation of the the GLSurface interface
+// that is backed by an NSView. This interface pairs with the GLContextNSView
+// class, and the NSView is expected to use this context for drawing.
+class GLSurfaceNSView : public GLSurface {
+ public:
+ explicit GLSurfaceNSView(AcceleratedWidget view);
+ virtual ~GLSurfaceNSView();
+
+ // GLSurface:
+ virtual void Destroy() OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual gfx::Size GetSize() OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+
+ // Allow the surface to call back to context when in need of |FlushBuffer|.
+ virtual bool OnMakeCurrent(GLContext* context) OVERRIDE;
+
+ private:
+ // Weak. An |NSView*|.
+ AcceleratedWidget view_;
+
+ // Weak. Associated context.
+ GLContextNSView* context_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLSurfaceNSView);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_SURFACE_NSVIEW_H_
diff --git a/ui/gl/gl_surface_nsview.mm b/ui/gl/gl_surface_nsview.mm
new file mode 100644
index 0000000..ded0719
--- /dev/null
+++ b/ui/gl/gl_surface_nsview.mm
@@ -0,0 +1,47 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface_nsview.h"
+
+#import <AppKit/NSOpenGL.h>
+#import <AppKit/NSView.h>
+
+#include "ui/gl/gl_context_nsview.h"
+
+namespace gfx {
+
+GLSurfaceNSView::GLSurfaceNSView(AcceleratedWidget view)
+ : view_(view),
+ context_(NULL) {
+}
+
+GLSurfaceNSView::~GLSurfaceNSView() {
+}
+
+void GLSurfaceNSView::Destroy() {
+}
+
+bool GLSurfaceNSView::IsOffscreen() {
+ return false;
+}
+
+bool GLSurfaceNSView::SwapBuffers() {
+ context_->FlushBuffer();
+ return true;
+}
+
+gfx::Size GLSurfaceNSView::GetSize() {
+ return gfx::Size(NSSizeToCGSize([view_ bounds].size));
+}
+
+void* GLSurfaceNSView::GetHandle() {
+ return view_;
+}
+
+bool GLSurfaceNSView::OnMakeCurrent(GLContext* context) {
+ context_ = static_cast<GLContextNSView *>(context);
+ return true;
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_surface_osmesa.cc b/ui/gl/gl_surface_osmesa.cc
new file mode 100644
index 0000000..a1fd360
--- /dev/null
+++ b/ui/gl/gl_surface_osmesa.cc
@@ -0,0 +1,82 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/logging.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface_osmesa.h"
+
+namespace gfx {
+
+GLSurfaceOSMesa::GLSurfaceOSMesa(unsigned format, const gfx::Size& size)
+ : format_(format),
+ size_(size) {
+}
+
+bool GLSurfaceOSMesa::Initialize() {
+ return Resize(size_);
+}
+
+void GLSurfaceOSMesa::Destroy() {
+ buffer_.reset();
+}
+
+bool GLSurfaceOSMesa::Resize(const gfx::Size& new_size) {
+ GLContext* current_context = GLContext::GetCurrent();
+ bool was_current = current_context && current_context->IsCurrent(this);
+ if (was_current)
+ current_context->ReleaseCurrent(this);
+
+ // Preserve the old buffer.
+ scoped_array<int32> old_buffer(buffer_.release());
+
+ // Allocate a new one.
+ buffer_.reset(new int32[new_size.GetArea()]);
+ memset(buffer_.get(), 0, new_size.GetArea() * sizeof(buffer_[0]));
+
+ // Copy the old back buffer into the new buffer.
+ if (old_buffer.get()) {
+ int copy_width = std::min(size_.width(), new_size.width());
+ int copy_height = std::min(size_.height(), new_size.height());
+ for (int y = 0; y < copy_height; ++y) {
+ for (int x = 0; x < copy_width; ++x) {
+ buffer_[y * new_size.width() + x] = old_buffer[y * size_.width() + x];
+ }
+ }
+ }
+
+ size_ = new_size;
+
+ if (was_current)
+ return current_context->MakeCurrent(this);
+
+ return true;
+}
+
+bool GLSurfaceOSMesa::IsOffscreen() {
+ return true;
+}
+
+bool GLSurfaceOSMesa::SwapBuffers() {
+ NOTREACHED() << "Should not call SwapBuffers on an GLSurfaceOSMesa.";
+ return false;
+}
+
+gfx::Size GLSurfaceOSMesa::GetSize() {
+ return size_;
+}
+
+void* GLSurfaceOSMesa::GetHandle() {
+ return buffer_.get();
+}
+
+unsigned GLSurfaceOSMesa::GetFormat() {
+ return format_;
+}
+
+GLSurfaceOSMesa::~GLSurfaceOSMesa() {
+ Destroy();
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_surface_osmesa.h b/ui/gl/gl_surface_osmesa.h
new file mode 100644
index 0000000..ab3feec
--- /dev/null
+++ b/ui/gl/gl_surface_osmesa.h
@@ -0,0 +1,45 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_SURFACE_OSMESA_H_
+#define UI_GL_GL_SURFACE_OSMESA_H_
+#pragma once
+
+#include "base/memory/scoped_ptr.h"
+#include "ui/gfx/size.h"
+#include "ui/gl/gl_surface.h"
+
+namespace gfx {
+
+// A surface that the Mesa software renderer draws to. This is actually just a
+// buffer in system memory. GetHandle returns a pointer to the buffer. These
+// surfaces can be resized and resizing preserves the contents.
+class GL_EXPORT GLSurfaceOSMesa : public GLSurface {
+ public:
+ GLSurfaceOSMesa(unsigned format, const gfx::Size& size);
+
+ // Implement GLSurface.
+ virtual bool Initialize() OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool Resize(const gfx::Size& new_size) OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual gfx::Size GetSize() OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+ virtual unsigned GetFormat() OVERRIDE;
+
+ protected:
+ virtual ~GLSurfaceOSMesa();
+
+ private:
+ unsigned format_;
+ gfx::Size size_;
+ scoped_array<int32> buffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(GLSurfaceOSMesa);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_SURFACE_OSMESA_H_
diff --git a/ui/gl/gl_surface_stub.cc b/ui/gl/gl_surface_stub.cc
new file mode 100644
index 0000000..a27d2af
--- /dev/null
+++ b/ui/gl/gl_surface_stub.cc
@@ -0,0 +1,30 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface_stub.h"
+
+namespace gfx {
+
+void GLSurfaceStub::Destroy() {
+}
+
+bool GLSurfaceStub::IsOffscreen() {
+ return false;
+}
+
+bool GLSurfaceStub::SwapBuffers() {
+ return true;
+}
+
+gfx::Size GLSurfaceStub::GetSize() {
+ return size_;
+}
+
+void* GLSurfaceStub::GetHandle() {
+ return NULL;
+}
+
+GLSurfaceStub::~GLSurfaceStub() {}
+
+} // namespace gfx
diff --git a/ui/gl/gl_surface_stub.h b/ui/gl/gl_surface_stub.h
new file mode 100644
index 0000000..86bbd15
--- /dev/null
+++ b/ui/gl/gl_surface_stub.h
@@ -0,0 +1,34 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_SURFACE_STUB_H_
+#define UI_GL_GL_SURFACE_STUB_H_
+#pragma once
+
+#include "ui/gl/gl_surface.h"
+
+namespace gfx {
+
+// A GLSurface that does nothing for unit tests.
+class GL_EXPORT GLSurfaceStub : public GLSurface {
+ public:
+ void SetSize(const gfx::Size& size) { size_ = size; }
+
+ // Implement GLSurface.
+ virtual void Destroy() OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual gfx::Size GetSize() OVERRIDE;
+ virtual void* GetHandle() OVERRIDE;
+
+ protected:
+ virtual ~GLSurfaceStub();
+
+ private:
+ gfx::Size size_;
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_SURFACE_STUB_H_
diff --git a/ui/gl/gl_surface_wgl.cc b/ui/gl/gl_surface_wgl.cc
new file mode 100644
index 0000000..a72c825
--- /dev/null
+++ b/ui/gl/gl_surface_wgl.cc
@@ -0,0 +1,366 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface_wgl.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "ui/gl/gl_bindings.h"
+
+namespace gfx {
+
+namespace {
+const PIXELFORMATDESCRIPTOR kPixelFormatDescriptor = {
+ sizeof(kPixelFormatDescriptor), // Size of structure.
+ 1, // Default version.
+ PFD_DRAW_TO_WINDOW | // Window drawing support.
+ PFD_SUPPORT_OPENGL | // OpenGL support.
+ PFD_DOUBLEBUFFER, // Double buffering support (not stereo).
+ PFD_TYPE_RGBA, // RGBA color mode (not indexed).
+ 24, // 24 bit color mode.
+ 0, 0, 0, 0, 0, 0, // Don't set RGB bits & shifts.
+ 8, 0, // 8 bit alpha
+ 0, // No accumulation buffer.
+ 0, 0, 0, 0, // Ignore accumulation bits.
+ 0, // no z-buffer.
+ 0, // no stencil buffer.
+ 0, // No aux buffer.
+ PFD_MAIN_PLANE, // Main drawing plane (not overlay).
+ 0, // Reserved.
+ 0, 0, 0, // Layer masks ignored.
+};
+
+LRESULT CALLBACK IntermediateWindowProc(HWND window,
+ UINT message,
+ WPARAM w_param,
+ LPARAM l_param) {
+ switch (message) {
+ case WM_ERASEBKGND:
+ // Prevent windows from erasing the background.
+ return 1;
+ case WM_PAINT:
+ // Do not paint anything.
+ PAINTSTRUCT paint;
+ if (BeginPaint(window, &paint))
+ EndPaint(window, &paint);
+ return 0;
+ default:
+ return DefWindowProc(window, message, w_param, l_param);
+ }
+}
+
+class DisplayWGL {
+ public:
+ DisplayWGL()
+ : module_handle_(0),
+ window_class_(0),
+ window_handle_(0),
+ device_context_(0),
+ pixel_format_(0) {
+ }
+
+ ~DisplayWGL() {
+ if (window_handle_)
+ DestroyWindow(window_handle_);
+ if (window_class_)
+ UnregisterClass(reinterpret_cast<wchar_t*>(window_class_),
+ module_handle_);
+ }
+
+ bool Init() {
+ // We must initialize a GL context before we can bind to extension entry
+ // points. This requires the device context for a window.
+ if (!GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT |
+ GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
+ reinterpret_cast<wchar_t*>(IntermediateWindowProc),
+ &module_handle_)) {
+ LOG(ERROR) << "GetModuleHandleEx failed.";
+ return false;
+ }
+
+ WNDCLASS intermediate_class;
+ intermediate_class.style = CS_OWNDC;
+ intermediate_class.lpfnWndProc = IntermediateWindowProc;
+ intermediate_class.cbClsExtra = 0;
+ intermediate_class.cbWndExtra = 0;
+ intermediate_class.hInstance = module_handle_;
+ intermediate_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ intermediate_class.hCursor = LoadCursor(NULL, IDC_ARROW);
+ intermediate_class.hbrBackground = NULL;
+ intermediate_class.lpszMenuName = NULL;
+ intermediate_class.lpszClassName = L"Intermediate GL Window";
+ window_class_ = RegisterClass(&intermediate_class);
+ if (!window_class_) {
+ LOG(ERROR) << "RegisterClass failed.";
+ return false;
+ }
+
+ window_handle_ = CreateWindow(
+ reinterpret_cast<wchar_t*>(window_class_),
+ L"",
+ WS_OVERLAPPEDWINDOW,
+ 0, 0,
+ 100, 100,
+ NULL,
+ NULL,
+ NULL,
+ NULL);
+ if (!window_handle_) {
+ LOG(ERROR) << "CreateWindow failed.";
+ return false;
+ }
+
+ device_context_ = GetDC(window_handle_);
+ pixel_format_ = ChoosePixelFormat(device_context_,
+ &kPixelFormatDescriptor);
+ if (pixel_format_ == 0) {
+ LOG(ERROR) << "Unable to get the pixel format for GL context.";
+ return false;
+ }
+ if (!SetPixelFormat(device_context_,
+ pixel_format_,
+ &kPixelFormatDescriptor)) {
+ LOG(ERROR) << "Unable to set the pixel format for temporary GL context.";
+ return false;
+ }
+
+ return true;
+ }
+
+ ATOM window_class() const { return window_class_; }
+ HDC device_context() const { return device_context_; }
+ int pixel_format() const { return pixel_format_; }
+
+ private:
+ HINSTANCE module_handle_;
+ ATOM window_class_;
+ HWND window_handle_;
+ HDC device_context_;
+ int pixel_format_;
+};
+DisplayWGL* g_display;
+} // namespace
+
+GLSurfaceWGL::GLSurfaceWGL() {
+}
+
+GLSurfaceWGL::~GLSurfaceWGL() {
+}
+
+void* GLSurfaceWGL::GetDisplay() {
+ return GetDisplayDC();
+}
+
+bool GLSurfaceWGL::InitializeOneOff() {
+ static bool initialized = false;
+ if (initialized)
+ return true;
+
+ DCHECK(g_display == NULL);
+ scoped_ptr<DisplayWGL> wgl_display(new DisplayWGL);
+ 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;
+}
+
+HDC GLSurfaceWGL::GetDisplayDC() {
+ return g_display->device_context();
+}
+
+NativeViewGLSurfaceWGL::NativeViewGLSurfaceWGL(gfx::AcceleratedWidget window)
+ : window_(window),
+ child_window_(NULL),
+ device_context_(NULL) {
+ DCHECK(window);
+}
+
+NativeViewGLSurfaceWGL::~NativeViewGLSurfaceWGL() {
+ Destroy();
+}
+
+bool NativeViewGLSurfaceWGL::Initialize() {
+ DCHECK(!device_context_);
+
+ RECT rect;
+ if (!GetClientRect(window_, &rect)) {
+ LOG(ERROR) << "GetClientRect failed.\n";
+ Destroy();
+ return false;
+ }
+
+ // Create a child window. WGL has problems using a window handle owned by
+ // another process.
+ child_window_ = CreateWindow(
+ reinterpret_cast<wchar_t*>(g_display->window_class()),
+ L"",
+ WS_CHILDWINDOW | WS_DISABLED | WS_VISIBLE,
+ 0, 0,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ window_,
+ NULL,
+ NULL,
+ NULL);
+ if (!child_window_) {
+ LOG(ERROR) << "CreateWindow failed.\n";
+ Destroy();
+ return false;
+ }
+
+ // The GL context will render to this window.
+ device_context_ = GetDC(child_window_);
+ if (!device_context_) {
+ LOG(ERROR) << "Unable to get device context for window.";
+ Destroy();
+ return false;
+ }
+
+ if (!SetPixelFormat(device_context_,
+ g_display->pixel_format(),
+ &kPixelFormatDescriptor)) {
+ LOG(ERROR) << "Unable to set the pixel format for GL context.";
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void NativeViewGLSurfaceWGL::Destroy() {
+ if (child_window_ && device_context_)
+ ReleaseDC(child_window_, device_context_);
+
+ if (child_window_)
+ DestroyWindow(child_window_);
+
+ child_window_ = NULL;
+ device_context_ = NULL;
+}
+
+bool NativeViewGLSurfaceWGL::IsOffscreen() {
+ return false;
+}
+
+bool NativeViewGLSurfaceWGL::SwapBuffers() {
+ // Resize the child window to match the parent before swapping. Do not repaint
+ // it as it moves.
+ RECT rect;
+ if (!GetClientRect(window_, &rect))
+ return false;
+ if (!MoveWindow(child_window_,
+ 0, 0,
+ rect.right - rect.left,
+ rect.bottom - rect.top,
+ FALSE)) {
+ return false;
+ }
+
+ DCHECK(device_context_);
+ return ::SwapBuffers(device_context_) == TRUE;
+}
+
+gfx::Size NativeViewGLSurfaceWGL::GetSize() {
+ RECT rect;
+ BOOL result = GetClientRect(child_window_, &rect);
+ DCHECK(result);
+ return gfx::Size(rect.right - rect.left, rect.bottom - rect.top);
+}
+
+void* NativeViewGLSurfaceWGL::GetHandle() {
+ return device_context_;
+}
+
+PbufferGLSurfaceWGL::PbufferGLSurfaceWGL(const gfx::Size& size)
+ : size_(size),
+ device_context_(NULL),
+ pbuffer_(NULL) {
+}
+
+PbufferGLSurfaceWGL::~PbufferGLSurfaceWGL() {
+ Destroy();
+}
+
+bool PbufferGLSurfaceWGL::Initialize() {
+ DCHECK(!device_context_);
+
+ if (!wglCreatePbufferARB) {
+ LOG(ERROR) << "wglCreatePbufferARB not available.";
+ Destroy();
+ return false;
+ }
+
+ const int kNoAttributes[] = { 0 };
+ pbuffer_ = wglCreatePbufferARB(g_display->device_context(),
+ g_display->pixel_format(),
+ size_.width(), size_.height(),
+ kNoAttributes);
+
+ if (!pbuffer_) {
+ LOG(ERROR) << "Unable to create pbuffer.";
+ Destroy();
+ return false;
+ }
+
+ device_context_ = wglGetPbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_));
+ if (!device_context_) {
+ LOG(ERROR) << "Unable to get pbuffer device context.";
+ Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+void PbufferGLSurfaceWGL::Destroy() {
+ if (pbuffer_ && device_context_)
+ wglReleasePbufferDCARB(static_cast<HPBUFFERARB>(pbuffer_), device_context_);
+
+ device_context_ = NULL;
+
+ if (pbuffer_) {
+ wglDestroyPbufferARB(static_cast<HPBUFFERARB>(pbuffer_));
+ pbuffer_ = NULL;
+ }
+}
+
+bool PbufferGLSurfaceWGL::IsOffscreen() {
+ return true;
+}
+
+bool PbufferGLSurfaceWGL::SwapBuffers() {
+ NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer.";
+ return false;
+}
+
+gfx::Size PbufferGLSurfaceWGL::GetSize() {
+ return size_;
+}
+
+void* PbufferGLSurfaceWGL::GetHandle() {
+ return device_context_;
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_surface_wgl.h b/ui/gl/gl_surface_wgl.h
new file mode 100644
index 0000000..6e4f0cd
--- /dev/null
+++ b/ui/gl/gl_surface_wgl.h
@@ -0,0 +1,77 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_SURFACE_WGL_H_
+#define UI_GL_GL_SURFACE_WGL_H_
+#pragma once
+
+#include "ui/gfx/native_widget_types.h"
+#include "ui/gl/gl_surface.h"
+
+namespace gfx {
+
+// Base interface for WGL surfaces.
+class GLSurfaceWGL : public GLSurface {
+ public:
+ GLSurfaceWGL();
+ virtual ~GLSurfaceWGL();
+
+ // Implement GLSurface.
+ virtual void* GetDisplay();
+
+ static bool InitializeOneOff();
+ static HDC GetDisplayDC();
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(GLSurfaceWGL);
+};
+
+// A surface used to render to a view.
+class NativeViewGLSurfaceWGL : public GLSurfaceWGL {
+ public:
+ explicit NativeViewGLSurfaceWGL(gfx::AcceleratedWidget window);
+ virtual ~NativeViewGLSurfaceWGL();
+
+ // Implement GLSurface.
+ virtual bool Initialize();
+ virtual void Destroy();
+ virtual bool IsOffscreen();
+ virtual bool SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+
+ private:
+ gfx::AcceleratedWidget window_;
+ gfx::AcceleratedWidget child_window_;
+ HDC device_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceWGL);
+};
+
+
+// A surface used to render to an offscreen pbuffer.
+class PbufferGLSurfaceWGL : public GLSurfaceWGL {
+ public:
+ explicit PbufferGLSurfaceWGL(const gfx::Size& size);
+ virtual ~PbufferGLSurfaceWGL();
+
+ // Implement GLSurface.
+ virtual bool Initialize();
+ virtual void Destroy();
+ virtual bool IsOffscreen();
+ virtual bool SwapBuffers();
+ virtual gfx::Size GetSize();
+ virtual void* GetHandle();
+
+ private:
+ gfx::Size size_;
+ HDC device_context_;
+ void* pbuffer_;
+
+ DISALLOW_COPY_AND_ASSIGN(PbufferGLSurfaceWGL);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GL_SURFACE_WGL_H_
diff --git a/ui/gl/gl_surface_win.cc b/ui/gl/gl_surface_win.cc
new file mode 100644
index 0000000..ae55568
--- /dev/null
+++ b/ui/gl/gl_surface_win.cc
@@ -0,0 +1,248 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface.h"
+
+#include "base/logging.h"
+#include "base/memory/scoped_ptr.h"
+#include "third_party/mesa/MesaLib/include/GL/osmesa.h"
+#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_egl.h"
+#include "ui/gl/gl_surface_osmesa.h"
+#include "ui/gl/gl_surface_stub.h"
+#include "ui/gl/gl_surface_wgl.h"
+
+namespace gfx {
+
+// This OSMesa GL surface can use GDI to swap the contents of the buffer to a
+// view.
+class NativeViewGLSurfaceOSMesa : public GLSurfaceOSMesa {
+ public:
+ explicit NativeViewGLSurfaceOSMesa(gfx::AcceleratedWidget window);
+ virtual ~NativeViewGLSurfaceOSMesa();
+
+ // Implement subset of GLSurface.
+ virtual bool Initialize() OVERRIDE;
+ virtual void Destroy() OVERRIDE;
+ virtual bool IsOffscreen() OVERRIDE;
+ virtual bool SwapBuffers() OVERRIDE;
+ virtual std::string GetExtensions() OVERRIDE;
+ virtual bool PostSubBuffer(int x, int y, int width, int height) OVERRIDE;
+
+ private:
+ gfx::AcceleratedWidget window_;
+ HDC device_context_;
+
+ DISALLOW_COPY_AND_ASSIGN(NativeViewGLSurfaceOSMesa);
+};
+
+// Helper routine that does one-off initialization like determining the
+// pixel format and initializing the GL bindings.
+bool GLSurface::InitializeOneOffInternal() {
+ switch (GetGLImplementation()) {
+ case kGLImplementationDesktopGL:
+ if (!GLSurfaceWGL::InitializeOneOff()) {
+ LOG(ERROR) << "GLSurfaceWGL::InitializeOneOff failed.";
+ return false;
+ }
+ break;
+ case kGLImplementationEGLGLES2:
+ if (!GLSurfaceEGL::InitializeOneOff()) {
+ LOG(ERROR) << "GLSurfaceEGL::InitializeOneOff failed.";
+ return false;
+ }
+ break;
+ }
+ return true;
+}
+
+NativeViewGLSurfaceOSMesa::NativeViewGLSurfaceOSMesa(
+ gfx::AcceleratedWidget window)
+ : GLSurfaceOSMesa(OSMESA_RGBA, gfx::Size(1, 1)),
+ window_(window),
+ device_context_(NULL) {
+ DCHECK(window);
+}
+
+NativeViewGLSurfaceOSMesa::~NativeViewGLSurfaceOSMesa() {
+ Destroy();
+}
+
+bool NativeViewGLSurfaceOSMesa::Initialize() {
+ if (!GLSurfaceOSMesa::Initialize())
+ return false;
+
+ device_context_ = GetDC(window_);
+ return true;
+}
+
+void NativeViewGLSurfaceOSMesa::Destroy() {
+ if (window_ && device_context_)
+ ReleaseDC(window_, device_context_);
+
+ device_context_ = NULL;
+
+ GLSurfaceOSMesa::Destroy();
+}
+
+bool NativeViewGLSurfaceOSMesa::IsOffscreen() {
+ return false;
+}
+
+bool NativeViewGLSurfaceOSMesa::SwapBuffers() {
+ DCHECK(device_context_);
+
+ gfx::Size size = GetSize();
+
+ // Note: negating the height below causes GDI to treat the bitmap data as row
+ // 0 being at the top.
+ BITMAPV4HEADER info = { sizeof(BITMAPV4HEADER) };
+ info.bV4Width = size.width();
+ info.bV4Height = -size.height();
+ info.bV4Planes = 1;
+ info.bV4BitCount = 32;
+ info.bV4V4Compression = BI_BITFIELDS;
+ info.bV4RedMask = 0x000000FF;
+ info.bV4GreenMask = 0x0000FF00;
+ info.bV4BlueMask = 0x00FF0000;
+ info.bV4AlphaMask = 0xFF000000;
+
+ // Copy the back buffer to the window's device context. Do not check whether
+ // StretchDIBits succeeds or not. It will fail if the window has been
+ // destroyed but it is preferable to allow rendering to silently fail if the
+ // window is destroyed. This is because the primary application of this
+ // class of GLContext is for testing and we do not want every GL related ui /
+ // browser test to become flaky if there is a race condition between GL
+ // context destruction and window destruction.
+ StretchDIBits(device_context_,
+ 0, 0, size.width(), size.height(),
+ 0, 0, size.width(), size.height(),
+ GetHandle(),
+ reinterpret_cast<BITMAPINFO*>(&info),
+ DIB_RGB_COLORS,
+ SRCCOPY);
+
+ return true;
+}
+
+std::string NativeViewGLSurfaceOSMesa::GetExtensions() {
+ std::string extensions = gfx::GLSurfaceOSMesa::GetExtensions();
+ extensions += extensions.empty() ? "" : " ";
+ extensions += "GL_CHROMIUM_post_sub_buffer";
+ return extensions;
+}
+
+bool NativeViewGLSurfaceOSMesa::PostSubBuffer(
+ int x, int y, int width, int height) {
+ DCHECK(device_context_);
+
+ gfx::Size size = GetSize();
+
+ // Note: negating the height below causes GDI to treat the bitmap data as row
+ // 0 being at the top.
+ BITMAPV4HEADER info = { sizeof(BITMAPV4HEADER) };
+ info.bV4Width = size.width();
+ info.bV4Height = -size.height();
+ info.bV4Planes = 1;
+ info.bV4BitCount = 32;
+ info.bV4V4Compression = BI_BITFIELDS;
+ info.bV4RedMask = 0x000000FF;
+ info.bV4GreenMask = 0x0000FF00;
+ info.bV4BlueMask = 0x00FF0000;
+ info.bV4AlphaMask = 0xFF000000;
+
+ // Copy the back buffer to the window's device context. Do not check whether
+ // StretchDIBits succeeds or not. It will fail if the window has been
+ // destroyed but it is preferable to allow rendering to silently fail if the
+ // window is destroyed. This is because the primary application of this
+ // class of GLContext is for testing and we do not want every GL related ui /
+ // browser test to become flaky if there is a race condition between GL
+ // context destruction and window destruction.
+ StretchDIBits(device_context_,
+ x, size.height() - y - height, width, height,
+ x, y, width, height,
+ GetHandle(),
+ reinterpret_cast<BITMAPINFO*>(&info),
+ DIB_RGB_COLORS,
+ SRCCOPY);
+
+ return true;
+}
+
+scoped_refptr<GLSurface> GLSurface::CreateViewGLSurface(
+ bool software,
+ gfx::AcceleratedWidget window) {
+ switch (GetGLImplementation()) {
+ case kGLImplementationOSMesaGL: {
+ scoped_refptr<GLSurface> surface(
+ new NativeViewGLSurfaceOSMesa(window));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationEGLGLES2: {
+ scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceEGL(software,
+ window));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationDesktopGL: {
+ if (software)
+ return NULL;
+ scoped_refptr<GLSurface> surface(new NativeViewGLSurfaceWGL(
+ window));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationMockGL:
+ return new GLSurfaceStub;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+scoped_refptr<GLSurface> GLSurface::CreateOffscreenGLSurface(
+ bool software,
+ const gfx::Size& size) {
+ switch (GetGLImplementation()) {
+ case kGLImplementationOSMesaGL: {
+ scoped_refptr<GLSurface> surface(new GLSurfaceOSMesa(OSMESA_RGBA,
+ size));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationEGLGLES2: {
+ scoped_refptr<GLSurface> surface(new PbufferGLSurfaceEGL(software, size));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationDesktopGL: {
+ if (software)
+ return NULL;
+ scoped_refptr<GLSurface> surface(new PbufferGLSurfaceWGL(size));
+ if (!surface->Initialize())
+ return NULL;
+
+ return surface;
+ }
+ case kGLImplementationMockGL:
+ return new GLSurfaceStub;
+ default:
+ NOTREACHED();
+ return NULL;
+ }
+}
+
+} // namespace gfx
diff --git a/ui/gl/gl_switches.cc b/ui/gl/gl_switches.cc
new file mode 100644
index 0000000..d30c958
--- /dev/null
+++ b/ui/gl/gl_switches.cc
@@ -0,0 +1,55 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_switches.h"
+
+namespace gfx {
+
+const char kGLImplementationDesktopName[] = "desktop";
+const char kGLImplementationOSMesaName[] = "osmesa";
+const char kGLImplementationAppleName[] = "apple";
+const char kGLImplementationEGLName[] = "egl";
+const char kGLImplementationSwiftShaderName[] = "swiftshader";
+const char kGLImplementationMockName[] = "mock";
+
+} // namespace gfx
+
+namespace switches {
+
+// Disable dynamic switching between integrated and discrete GPU on
+// systems that would otherwise support it (currently, only a limited
+// number of MacBook Pros).
+const char kDisableGpuSwitching[] = "disable-gpu-switching";
+
+// Stop the GPU from synchronizing on the vsync before presenting.
+const char kDisableGpuVsync[] = "disable-gpu-vsync";
+
+// Turns on GPU logging (debug build only).
+const char kEnableGPUServiceLogging[] = "enable-gpu-service-logging";
+const char kEnableGPUClientLogging[] = "enable-gpu-client-logging";
+
+// Select which implementation of GL the GPU process should use. Options are:
+// desktop: whatever desktop OpenGL the user has installed (Linux and Mac
+// default).
+// egl: whatever EGL / GLES2 the user has installed (Windows default - actually
+// ANGLE).
+// osmesa: The OSMesa software renderer.
+const char kUseGL[] = "use-gl";
+
+const char kSwiftShaderPath[] = "swiftshader-path";
+
+// Inform Chrome that a GPU context will not be lost in power saving mode,
+// screen saving mode, etc. Note that this flag does not ensure that a GPU
+// context will never be lost in any situations, say, a GPU reset.
+const char kGpuNoContextLost[] = "gpu-no-context-lost";
+
+// Add a delay in milliseconds to the gpu swap buffer completion signal.
+// Simulates a slow GPU.
+const char kGpuSwapDelay[] = "gpu-swap-delay";
+
+// Flag used for Linux tests: for desktop GL bindings, try to load this GL
+// library first, but fall back to regular library if loading fails.
+const char kTestGLLib[] = "test-gl-lib";
+
+} // namespace switches
diff --git a/ui/gl/gl_switches.h b/ui/gl/gl_switches.h
new file mode 100644
index 0000000..ffda704
--- /dev/null
+++ b/ui/gl/gl_switches.h
@@ -0,0 +1,39 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GL_SWITCHES_H_
+#define UI_GL_GL_SWITCHES_H_
+#pragma once
+
+// Defines all the command-line switches used by ui/gl.
+
+#include "ui/gl/gl_export.h"
+
+namespace gfx {
+
+// The GL implementation names that can be passed to --use-gl.
+GL_EXPORT extern const char kGLImplementationDesktopName[];
+GL_EXPORT extern const char kGLImplementationOSMesaName[];
+GL_EXPORT extern const char kGLImplementationAppleName[];
+GL_EXPORT extern const char kGLImplementationEGLName[];
+GL_EXPORT extern const char kGLImplementationSwiftShaderName[];
+extern const char kGLImplementationMockName[];
+
+} // namespace gfx
+
+namespace switches {
+
+GL_EXPORT extern const char kDisableGpuSwitching[];
+GL_EXPORT extern const char kDisableGpuVsync[];
+GL_EXPORT extern const char kEnableGPUServiceLogging[];
+GL_EXPORT extern const char kEnableGPUClientLogging[];
+GL_EXPORT extern const char kGpuNoContextLost[];
+GL_EXPORT extern const char kGpuSwapDelay[];
+GL_EXPORT extern const char kUseGL[];
+GL_EXPORT extern const char kSwiftShaderPath[];
+GL_EXPORT extern const char kTestGLLib[];
+
+} // namespace switches
+
+#endif // UI_GL_GL_SWITCHES_H_
diff --git a/ui/gl/gpu_preference.h b/ui/gl/gpu_preference.h
new file mode 100644
index 0000000..54f814a
--- /dev/null
+++ b/ui/gl/gpu_preference.h
@@ -0,0 +1,25 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_GPU_PREFERENCE_H_
+#define UI_GL_GPU_PREFERENCE_H_
+#pragma once
+
+namespace gfx {
+
+// On dual-GPU systems, expresses a preference for using the integrated
+// or discrete GPU. On systems that have dual-GPU support (see
+// GLContext::SupportsDualGpus), resource sharing only works between
+// contexts that are created with the same GPU preference.
+//
+// This API will likely need to be adjusted as the functionality is
+// implemented on more operating systems.
+enum GpuPreference {
+ PreferIntegratedGpu,
+ PreferDiscreteGpu
+};
+
+} // namespace gfx
+
+#endif // UI_GL_GPU_PREFERENCE_H_
diff --git a/ui/gl/scoped_make_current.cc b/ui/gl/scoped_make_current.cc
new file mode 100644
index 0000000..54dac6d
--- /dev/null
+++ b/ui/gl/scoped_make_current.cc
@@ -0,0 +1,36 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/scoped_make_current.h"
+
+#include "base/logging.h"
+
+namespace gfx {
+
+ScopedMakeCurrent::ScopedMakeCurrent(GLContext* context, GLSurface* surface)
+ : previous_context_(GLContext::GetCurrent())
+ , previous_surface_(GLSurface::GetCurrent())
+ , context_(context)
+ , surface_(surface)
+ , succeeded_(false) {
+ DCHECK(context);
+ DCHECK(surface);
+ succeeded_ = context->MakeCurrent(surface);
+}
+
+ScopedMakeCurrent::~ScopedMakeCurrent() {
+ if (previous_context_.get()) {
+ DCHECK(previous_surface_.get());
+ previous_context_->MakeCurrent(previous_surface_.get());
+ } else {
+ context_->ReleaseCurrent(surface_.get());
+ }
+}
+
+bool ScopedMakeCurrent::Succeeded() {
+ return succeeded_;
+}
+
+} // namespace gfx
+
diff --git a/ui/gl/scoped_make_current.h b/ui/gl/scoped_make_current.h
new file mode 100644
index 0000000..3c336f3
--- /dev/null
+++ b/ui/gl/scoped_make_current.h
@@ -0,0 +1,33 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_GL_SCOPED_MAKE_CURRENT_H_
+#define UI_GL_SCOPED_MAKE_CURRENT_H_
+#pragma once
+
+#include "ui/gl/gl_context.h"
+#include "ui/gl/gl_surface.h"
+
+namespace gfx {
+
+class GL_EXPORT ScopedMakeCurrent {
+ public:
+ explicit ScopedMakeCurrent(GLContext* context, GLSurface* surface);
+ ~ScopedMakeCurrent();
+
+ bool Succeeded();
+
+ private:
+ scoped_refptr<GLContext> previous_context_;
+ scoped_refptr<GLSurface> previous_surface_;
+ scoped_refptr<GLContext> context_;
+ scoped_refptr<GLSurface> surface_;
+ bool succeeded_;
+
+ DISALLOW_COPY_AND_ASSIGN(ScopedMakeCurrent);
+};
+
+} // namespace gfx
+
+#endif // UI_GL_SCOPED_MAKE_CURRENT_H_