diff options
author | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-28 19:24:49 +0000 |
---|---|---|
committer | backer@chromium.org <backer@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-03-28 19:24:49 +0000 |
commit | 5ae0b28229648b8b5d26624a45f3fffca4e545fd (patch) | |
tree | a97b457285d90a49521a360e7cad015fbd7e2474 /ui | |
parent | 2f4aec1e3e10cac458f44747d650c2336e220554 (diff) | |
download | chromium_src-5ae0b28229648b8b5d26624a45f3fffca4e545fd.zip chromium_src-5ae0b28229648b8b5d26624a45f3fffca4e545fd.tar.gz chromium_src-5ae0b28229648b8b5d26624a45f3fffca4e545fd.tar.bz2 |
Refactor: Move app/gfx/gl ==> ui/gfx/gl
This is the final patch in the sequence. Note that gl.gyp is introduced because dependency checking on the Mac is done on a per file (rather than per target) basis.
BUG=none
TEST=trybots
Review URL: http://codereview.chromium.org/6722026
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@79599 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
29 files changed, 5265 insertions, 10 deletions
diff --git a/ui/gfx/compositor/compositor.gyp b/ui/gfx/compositor/compositor.gyp index d003694..f739b93 100644 --- a/ui/gfx/compositor/compositor.gyp +++ b/ui/gfx/compositor/compositor.gyp @@ -10,7 +10,7 @@ 'msvs_guid': '21CEE0E3-6F4E-4F01-B8C9-F7751CC21AA9', 'dependencies': [ '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/app/app.gyp:app_base', + '<(DEPTH)/ui/gfx/gl/gl.gyp:gl', '<(DEPTH)/ui/ui.gyp:ui_gfx', ], 'sources': [ diff --git a/ui/gfx/compositor/compositor_gl.cc b/ui/gfx/compositor/compositor_gl.cc index 6fa426a..f152ffc 100644 --- a/ui/gfx/compositor/compositor_gl.cc +++ b/ui/gfx/compositor/compositor_gl.cc @@ -4,14 +4,14 @@ #include "ui/gfx/compositor/compositor.h" -#include "app/gfx/gl/gl_context.h" -#include "app/gfx/gl/gl_bindings.h" -#include "app/gfx/gl/gl_implementation.h" #include "base/basictypes.h" #include "base/compiler_specific.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" #include "ui/gfx/transform.h" +#include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_implementation.h" namespace ui { diff --git a/ui/gfx/gl/generate_bindings.py b/ui/gfx/gl/generate_bindings.py new file mode 100644 index 0000000..41038cc --- /dev/null +++ b/ui/gfx/gl/generate_bindings.py @@ -0,0 +1,638 @@ +#!/usr/bin/python +# +# Copyright (c) 2011 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 re +import sys + +GL_FUNCTIONS = [ +['void', ['glActiveTexture'], 'GLenum texture'], +['void', ['glAttachShader'], 'GLuint program, GLuint shader'], +['void', ['glBindAttribLocation'], + 'GLuint program, GLuint index, const char* name'], +['void', ['glBindBuffer'], 'GLenum target, GLuint buffer'], +['void', ['glBindFramebufferEXT', 'glBindFramebuffer'], + 'GLenum target, GLuint framebuffer'], +['void', ['glBindRenderbufferEXT', 'glBindRenderbuffer'], + 'GLenum target, GLuint renderbuffer'], +['void', ['glBindTexture'], 'GLenum target, GLuint texture'], +['void', ['glBlendColor'], + 'GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha'], +['void', ['glBlendEquation'], ' GLenum mode '], +['void', ['glBlendEquationSeparate'], 'GLenum modeRGB, GLenum modeAlpha'], +['void', ['glBlendFunc'], 'GLenum sfactor, GLenum dfactor'], +['void', ['glBlendFuncSeparate'], + 'GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha'], +['void', ['glBlitFramebufferEXT', 'BlitFramebuffer'], + 'GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, ' + 'GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, ' + 'GLbitfield mask, GLenum filter'], +['void', ['glBlitFramebufferANGLE', 'BlitFramebuffer'], + 'GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, ' + 'GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, ' + 'GLbitfield mask, GLenum filter'], +['void', ['glBufferData'], + 'GLenum target, GLsizei size, const void* data, GLenum usage'], +['void', ['glBufferSubData'], + 'GLenum target, GLint offset, GLsizei size, const void* data'], +['GLenum', ['glCheckFramebufferStatusEXT', + 'glCheckFramebufferStatus'], 'GLenum target'], +['void', ['glClear'], 'GLbitfield mask'], +['void', ['glClearColor'], + 'GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha'], +['void', ['glClearDepth'], 'GLclampd depth'], +['void', ['glClearDepthf'], 'GLclampf depth'], +['void', ['glClearStencil'], 'GLint s'], +['void', ['glColorMask'], + 'GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha'], +['void', ['glCompileShader'], 'GLuint shader'], +['void', ['glCompressedTexImage2D'], + 'GLenum target, GLint level, GLenum internalformat, GLsizei width, ' + 'GLsizei height, GLint border, GLsizei imageSize, const void* data'], +['void', ['glCompressedTexSubImage2D'], + 'GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, ' + 'GLsizei height, GLenum format, GLsizei imageSize, const void* data'], +['void', ['glCopyTexImage2D'], + 'GLenum target, GLint level, GLenum internalformat, GLint x, GLint y, ' + 'GLsizei width, GLsizei height, GLint border'], +['void', ['glCopyTexSubImage2D'], 'GLenum target, GLint level, GLint xoffset, ' + 'GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height'], +['GLuint', ['glCreateProgram'], 'void'], +['GLuint', ['glCreateShader'], 'GLenum type'], +['void', ['glCullFace'], 'GLenum mode'], +['void', ['glDeleteBuffersARB', 'glDeleteBuffers'], + 'GLsizei n, const GLuint* buffers'], +['void', ['glDeleteFramebuffersEXT', 'glDeleteFramebuffers'], + 'GLsizei n, const GLuint* framebuffers'], +['void', ['glDeleteProgram'], 'GLuint program'], +['void', ['glDeleteRenderbuffersEXT', 'glDeleteRenderbuffers'], + 'GLsizei n, const GLuint* renderbuffers'], +['void', ['glDeleteShader'], 'GLuint shader'], +['void', ['glDeleteTextures'], 'GLsizei n, const GLuint* textures'], +['void', ['glDepthFunc'], 'GLenum func'], +['void', ['glDepthMask'], 'GLboolean flag'], +['void', ['glDepthRange'], 'GLclampd zNear, GLclampd zFar'], +['void', ['glDepthRangef'], 'GLclampf zNear, GLclampf zFar'], +['void', ['glDetachShader'], 'GLuint program, GLuint shader'], +['void', ['glDisable'], 'GLenum cap'], +['void', ['glDisableVertexAttribArray'], 'GLuint index'], +['void', ['glDrawArrays'], 'GLenum mode, GLint first, GLsizei count'], +['void', ['glDrawElements'], + 'GLenum mode, GLsizei count, GLenum type, const void* indices'], +['void', ['glEnable'], 'GLenum cap'], +['void', ['glEnableVertexAttribArray'], 'GLuint index'], +['void', ['glFinish'], 'void'], +['void', ['glFlush'], 'void'], +['void', ['glFramebufferRenderbufferEXT', 'glFramebufferRenderbuffer'], + 'GLenum target, GLenum attachment, GLenum renderbuffertarget, ' + 'GLuint renderbuffer'], +['void', ['glFramebufferTexture2DEXT', 'glFramebufferTexture2D'], + 'GLenum target, GLenum attachment, GLenum textarget, GLuint texture, ' + 'GLint level'], +['void', ['glFrontFace'], 'GLenum mode'], +['void', ['glGenBuffersARB', 'glGenBuffers'], 'GLsizei n, GLuint* buffers'], +['void', ['glGenerateMipmapEXT', 'glGenerateMipmap'], 'GLenum target'], +['void', ['glGenFramebuffersEXT', 'glGenFramebuffers'], + 'GLsizei n, GLuint* framebuffers'], +['void', ['glGenRenderbuffersEXT', 'glGenRenderbuffers'], + 'GLsizei n, GLuint* renderbuffers'], +['void', ['glGenTextures'], 'GLsizei n, GLuint* textures'], +['void', ['glGetActiveAttrib'], + 'GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, ' + 'GLint* size, GLenum* type, char* name'], +['void', ['glGetActiveUniform'], + 'GLuint program, GLuint index, GLsizei bufsize, GLsizei* length, ' + 'GLint* size, GLenum* type, char* name'], +['void', ['glGetAttachedShaders'], + 'GLuint program, GLsizei maxcount, GLsizei* count, GLuint* shaders'], +['GLint', ['glGetAttribLocation'], 'GLuint program, const char* name'], +['void', ['glGetBooleanv'], 'GLenum pname, GLboolean* params'], +['void', ['glGetBufferParameteriv'], + 'GLenum target, GLenum pname, GLint* params'], +['GLenum', ['glGetError'], 'void'], +['void', ['glGetFloatv'], 'GLenum pname, GLfloat* params'], +['void', ['glGetFramebufferAttachmentParameterivEXT', + 'glGetFramebufferAttachmentParameteriv'], 'GLenum target, ' + 'GLenum attachment, GLenum pname, GLint* params'], +['void', ['glGetIntegerv'], 'GLenum pname, GLint* params'], +['void', ['glGetProgramiv'], 'GLuint program, GLenum pname, GLint* params'], +['void', ['glGetProgramInfoLog'], + 'GLuint program, GLsizei bufsize, GLsizei* length, char* infolog'], +['void', ['glGetRenderbufferParameterivEXT', 'glGetRenderbufferParameteriv'], + 'GLenum target, GLenum pname, GLint* params'], +['void', ['glGetShaderiv'], 'GLuint shader, GLenum pname, GLint* params'], +['void', ['glGetShaderInfoLog'], + 'GLuint shader, GLsizei bufsize, GLsizei* length, char* infolog'], +['void', ['glGetShaderPrecisionFormat'], + 'GLenum shadertype, GLenum precisiontype, GLint* range, GLint* precision'], +['void', ['glGetShaderSource'], + 'GLuint shader, GLsizei bufsize, GLsizei* length, char* source'], +['const GLubyte*', ['glGetString'], 'GLenum name'], +['void', ['glGetTexLevelParameterfv'], + 'GLenum target, GLint level, GLenum pname, GLfloat* params'], +['void', ['glGetTexLevelParameteriv'], + 'GLenum target, GLint level, GLenum pname, GLint* params'], +['void', ['glGetTexParameterfv'], + 'GLenum target, GLenum pname, GLfloat* params'], +['void', ['glGetTexParameteriv'], 'GLenum target, GLenum pname, GLint* params'], +['void', ['glGetUniformfv'], 'GLuint program, GLint location, GLfloat* params'], +['void', ['glGetUniformiv'], 'GLuint program, GLint location, GLint* params'], +['GLint', ['glGetUniformLocation'], 'GLuint program, const char* name'], +['void', ['glGetVertexAttribfv'], + 'GLuint index, GLenum pname, GLfloat* params'], +['void', ['glGetVertexAttribiv'], 'GLuint index, GLenum pname, GLint* params'], +['void', ['glGetVertexAttribPointerv'], + 'GLuint index, GLenum pname, void** pointer'], +['void', ['glHint'], 'GLenum target, GLenum mode'], +['GLboolean', ['glIsBuffer'], 'GLuint buffer'], +['GLboolean', ['glIsEnabled'], 'GLenum cap'], +['GLboolean', ['glIsFramebufferEXT', 'glIsFramebuffer'], + 'GLuint framebuffer'], +['GLboolean', ['glIsProgram'], 'GLuint program'], +['GLboolean', ['glIsRenderbufferEXT', 'glIsRenderbuffer'], + 'GLuint renderbuffer'], +['GLboolean', ['glIsShader'], 'GLuint shader'], +['GLboolean', ['glIsTexture'], 'GLuint texture'], +['void', ['glLineWidth'], 'GLfloat width'], +['void', ['glLinkProgram'], 'GLuint program'], +['void*', ['glMapBuffer'], 'GLenum target, GLenum access'], +['void', ['glPixelStorei'], 'GLenum pname, GLint param'], +['void', ['glPolygonOffset'], 'GLfloat factor, GLfloat units'], +['void', ['glReadPixels'], + 'GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, ' + 'GLenum type, void* pixels'], +['void', ['glReleaseShaderCompiler'], 'void'], +['void', ['glRenderbufferStorageMultisampleEXT', + 'glRenderbufferStorageMultisample'], + 'GLenum target, GLsizei samples, GLenum internalformat, ' + 'GLsizei width, GLsizei height'], +['void', ['glRenderbufferStorageMultisampleANGLE', + 'glRenderbufferStorageMultisample'], + 'GLenum target, GLsizei samples, GLenum internalformat, ' + 'GLsizei width, GLsizei height'], +['void', ['glRenderbufferStorageEXT', 'glRenderbufferStorage'], + 'GLenum target, GLenum internalformat, GLsizei width, GLsizei height'], +['void', ['glSampleCoverage'], 'GLclampf value, GLboolean invert'], +['void', ['glScissor'], 'GLint x, GLint y, GLsizei width, GLsizei height'], +['void', ['glShaderBinary'], + 'GLsizei n, const GLuint* shaders, GLenum binaryformat, ' + 'const void* binary, GLsizei length'], +['void', ['glShaderSource'], + 'GLuint shader, GLsizei count, const char** str, const GLint* length'], +['void', ['glStencilFunc'], 'GLenum func, GLint ref, GLuint mask'], +['void', ['glStencilFuncSeparate'], + 'GLenum face, GLenum func, GLint ref, GLuint mask'], +['void', ['glStencilMask'], 'GLuint mask'], +['void', ['glStencilMaskSeparate'], 'GLenum face, GLuint mask'], +['void', ['glStencilOp'], 'GLenum fail, GLenum zfail, GLenum zpass'], +['void', ['glStencilOpSeparate'], + 'GLenum face, GLenum fail, GLenum zfail, GLenum zpass'], +['void', ['glTexImage2D'], + 'GLenum target, GLint level, GLint internalformat, GLsizei width, ' + 'GLsizei height, GLint border, GLenum format, GLenum type, ' + 'const void* pixels'], +['void', ['glTexParameterf'], 'GLenum target, GLenum pname, GLfloat param'], +['void', ['glTexParameterfv'], + 'GLenum target, GLenum pname, const GLfloat* params'], +['void', ['glTexParameteri'], 'GLenum target, GLenum pname, GLint param'], +['void', ['glTexParameteriv'], + 'GLenum target, GLenum pname, const GLint* params'], +['void', ['glTexSubImage2D'], + 'GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, ' + 'GLsizei height, GLenum format, GLenum type, const void* pixels'], +['void', ['glUniform1f'], 'GLint location, GLfloat x'], +['void', ['glUniform1fv'], 'GLint location, GLsizei count, const GLfloat* v'], +['void', ['glUniform1i'], 'GLint location, GLint x'], +['void', ['glUniform1iv'], 'GLint location, GLsizei count, const GLint* v'], +['void', ['glUniform2f'], 'GLint location, GLfloat x, GLfloat y'], +['void', ['glUniform2fv'], 'GLint location, GLsizei count, const GLfloat* v'], +['void', ['glUniform2i'], 'GLint location, GLint x, GLint y'], +['void', ['glUniform2iv'], 'GLint location, GLsizei count, const GLint* v'], +['void', ['glUniform3f'], 'GLint location, GLfloat x, GLfloat y, GLfloat z'], +['void', ['glUniform3fv'], 'GLint location, GLsizei count, const GLfloat* v'], +['void', ['glUniform3i'], 'GLint location, GLint x, GLint y, GLint z'], +['void', ['glUniform3iv'], 'GLint location, GLsizei count, const GLint* v'], +['void', ['glUniform4f'], + 'GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w'], +['void', ['glUniform4fv'], 'GLint location, GLsizei count, const GLfloat* v'], +['void', ['glUniform4i'], 'GLint location, GLint x, GLint y, GLint z, GLint w'], +['void', ['glUniform4iv'], 'GLint location, GLsizei count, const GLint* v'], +['void', ['glUniformMatrix2fv'], + 'GLint location, GLsizei count, GLboolean transpose, const GLfloat* value'], +['void', ['glUniformMatrix3fv'], + 'GLint location, GLsizei count, GLboolean transpose, const GLfloat* value'], +['void', ['glUniformMatrix4fv'], + 'GLint location, GLsizei count, GLboolean transpose, const GLfloat* value'], +['GLboolean', ['glUnmapBuffer'], 'GLenum target'], +['void', ['glUseProgram'], 'GLuint program'], +['void', ['glValidateProgram'], 'GLuint program'], +['void', ['glVertexAttrib1f'], 'GLuint indx, GLfloat x'], +['void', ['glVertexAttrib1fv'], 'GLuint indx, const GLfloat* values'], +['void', ['glVertexAttrib2f'], 'GLuint indx, GLfloat x, GLfloat y'], +['void', ['glVertexAttrib2fv'], 'GLuint indx, const GLfloat* values'], +['void', ['glVertexAttrib3f'], 'GLuint indx, GLfloat x, GLfloat y, GLfloat z'], +['void', ['glVertexAttrib3fv'], 'GLuint indx, const GLfloat* values'], +['void', ['glVertexAttrib4f'], + 'GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w'], +['void', ['glVertexAttrib4fv'], 'GLuint indx, const GLfloat* values'], +['void', ['glVertexAttribPointer'], + 'GLuint indx, GLint size, GLenum type, GLboolean normalized, ' + 'GLsizei stride, const void* ptr'], +['void', ['glViewport'], 'GLint x, GLint y, GLsizei width, GLsizei height'], +['void', ['glGenFencesNV'], 'GLsizei n, GLuint* fences'], +['void', ['glDeleteFencesNV'], 'GLsizei n, const GLuint* fences'], +['void', ['glSetFenceNV'], 'GLuint fence, GLenum condition'], +['GLboolean', ['glTestFenceNV'], 'GLuint fence'], +['void', ['glFinishFenceNV'], 'GLuint fence'], +['GLboolean', ['glIsFenceNV'], 'GLuint fence'], +['void', ['glGetFenceivNV'], 'GLuint fence, GLenum pname, GLint* params'] +] + +OSMESA_FUNCTIONS = [ +['OSMesaContext', ['OSMesaCreateContext'], + 'GLenum format, OSMesaContext sharelist'], +['OSMesaContext', ['OSMesaCreateContextExt'], + 'GLenum format, GLint depthBits, GLint stencilBits, GLint accumBits, ' + 'OSMesaContext sharelist'], +['void', ['OSMesaDestroyContext'], 'OSMesaContext ctx'], +['GLboolean', ['OSMesaMakeCurrent'], + 'OSMesaContext ctx, void* buffer, GLenum type, GLsizei width, ' + 'GLsizei height'], +['OSMesaContext', ['OSMesaGetCurrentContext'], 'void'], +['void', ['OSMesaPixelStore'], 'GLint pname, GLint value'], +['void', ['OSMesaGetIntegerv'], 'GLint pname, GLint* value'], +['GLboolean', ['OSMesaGetDepthBuffer'], + 'OSMesaContext c, GLint* width, GLint* height, GLint* bytesPerValue, ' + 'void** buffer'], +['GLboolean', ['OSMesaGetColorBuffer'], + 'OSMesaContext c, GLint* width, GLint* height, GLint* format, ' + 'void** buffer'], +['OSMESAproc', ['OSMesaGetProcAddress'], 'const char* funcName'], +['void', ['OSMesaColorClamp'], 'GLboolean enable'], +] + +EGL_FUNCTIONS = [ +['EGLint', ['eglGetError'], 'void'], +['EGLDisplay', ['eglGetDisplay'], 'EGLNativeDisplayType display_id'], +['EGLBoolean', ['eglInitialize'], + 'EGLDisplay dpy, EGLint* major, EGLint* minor'], +['EGLBoolean', ['eglTerminate'], 'EGLDisplay dpy'], +['const char*', ['eglQueryString'], 'EGLDisplay dpy, EGLint name'], +['EGLBoolean', ['eglGetConfigs'], + 'EGLDisplay dpy, EGLConfig* configs, EGLint config_size, ' + 'EGLint* num_config'], +['EGLBoolean', ['eglChooseConfig'], + 'EGLDisplay dpy, const EGLint* attrib_list, EGLConfig* configs, ' + 'EGLint config_size, EGLint* num_config'], +['EGLBoolean', ['eglGetConfigAttrib'], + 'EGLDisplay dpy, EGLConfig config, EGLint attribute, EGLint* value'], +['EGLSurface', ['eglCreateWindowSurface'], + 'EGLDisplay dpy, EGLConfig config, EGLNativeWindowType win, ' + 'const EGLint* attrib_list'], +['EGLSurface', ['eglCreatePbufferSurface'], + 'EGLDisplay dpy, EGLConfig config, const EGLint* attrib_list'], +['EGLSurface', ['eglCreatePixmapSurface'], + 'EGLDisplay dpy, EGLConfig config, EGLNativePixmapType pixmap, ' + 'const EGLint* attrib_list'], +['EGLBoolean', ['eglDestroySurface'], 'EGLDisplay dpy, EGLSurface surface'], +['EGLBoolean', ['eglQuerySurface'], + 'EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint* value'], +['EGLBoolean', ['eglBindAPI'], 'EGLenum api'], +['EGLenum', ['eglQueryAPI'], 'void'], +['EGLBoolean', ['eglWaitClient'], 'void'], +['EGLBoolean', ['eglReleaseThread'], 'void'], +['EGLSurface', ['eglCreatePbufferFromClientBuffer'], + 'EGLDisplay dpy, EGLenum buftype, void* buffer, EGLConfig config, ' + 'const EGLint* attrib_list'], +['EGLBoolean', ['eglSurfaceAttrib'], + 'EGLDisplay dpy, EGLSurface surface, EGLint attribute, EGLint value'], +['EGLBoolean', ['eglBindTexImage'], + 'EGLDisplay dpy, EGLSurface surface, EGLint buffer'], +['EGLBoolean', ['eglReleaseTexImage'], + 'EGLDisplay dpy, EGLSurface surface, EGLint buffer'], +['EGLBoolean', ['eglSwapInterval'], 'EGLDisplay dpy, EGLint interval'], +['EGLContext', ['eglCreateContext'], + 'EGLDisplay dpy, EGLConfig config, EGLContext share_context, ' + 'const EGLint* attrib_list'], +['EGLBoolean', ['eglDestroyContext'], 'EGLDisplay dpy, EGLContext ctx'], +['EGLBoolean', ['eglMakeCurrent'], + 'EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext ctx'], +['EGLContext', ['eglGetCurrentContext'], 'void'], +['EGLSurface', ['eglGetCurrentSurface'], 'EGLint readdraw'], +['EGLDisplay', ['eglGetCurrentDisplay'], 'void'], +['EGLBoolean', ['eglQueryContext'], + 'EGLDisplay dpy, EGLContext ctx, EGLint attribute, EGLint* value'], +['EGLBoolean', ['eglWaitGL'], 'void'], +['EGLBoolean', ['eglWaitNative'], 'EGLint engine'], +['EGLBoolean', ['eglSwapBuffers'], 'EGLDisplay dpy, EGLSurface surface'], +['EGLBoolean', ['eglCopyBuffers'], + 'EGLDisplay dpy, EGLSurface surface, EGLNativePixmapType target'], +['__eglMustCastToProperFunctionPointerType', ['eglGetProcAddress'], + 'const char* procname'], +] + +WGL_FUNCTIONS = [ +['HGLRC', ['wglCreateContext'], 'HDC hdc'], +['HGLRC', ['wglCreateLayerContext'], 'HDC hdc, int iLayerPlane'], +['BOOL', ['wglCopyContext'], 'HGLRC hglrcSrc, HGLRC hglrcDst, UINT mask'], +['BOOL', ['wglDeleteContext'], 'HGLRC hglrc'], +['HGLRC', ['wglGetCurrentContext'], ''], +['HDC', ['wglGetCurrentDC'], ''], +['BOOL', ['wglMakeCurrent'], 'HDC hdc, HGLRC hglrc'], +['BOOL', ['wglShareLists'], 'HGLRC hglrc1, HGLRC hglrc2'], +['BOOL', ['wglSwapIntervalEXT'], 'int interval'], +['BOOL', ['wglSwapLayerBuffers'], 'HDC hdc, UINT fuPlanes'], +['const char*', ['wglGetExtensionsStringARB', 'wglGetExtensionsStringEXT'], + 'HDC hDC'], +['BOOL', ['wglChoosePixelFormatARB'], + 'HDC dc, const int* int_attrib_list, const float* float_attrib_list, ' + 'UINT max_formats, int* formats, UINT* num_formats'], +['HPBUFFERARB', ['wglCreatePbufferARB'], + 'HDC hDC, int iPixelFormat, int iWidth, int iHeight, ' + 'const int* piAttribList'], +['HDC', ['wglGetPbufferDCARB'], 'HPBUFFERARB hPbuffer'], +['int', ['wglReleasePbufferDCARB'], 'HPBUFFERARB hPbuffer, HDC hDC'], +['BOOL', ['wglDestroyPbufferARB'], 'HPBUFFERARB hPbuffer'], +['BOOL', ['wglQueryPbufferARB'], + 'HPBUFFERARB hPbuffer, int iAttribute, int* piValue'], +] + +GLX_FUNCTIONS = [ +['XVisualInfo*', ['glXChooseVisual'], + 'Display* dpy, int screen, int* attribList'], +['GLXContext', ['glXCreateContext'], + 'Display* dpy, XVisualInfo* vis, GLXContext shareList, int direct'], +['void', ['glXDestroyContext'], 'Display* dpy, GLXContext ctx'], +['int', ['glXMakeCurrent'], + 'Display* dpy, GLXDrawable drawable, GLXContext ctx'], +['void', ['glXCopyContext'], + 'Display* dpy, GLXContext src, GLXContext dst, unsigned long mask'], +['void', ['glXSwapBuffers'], 'Display* dpy, GLXDrawable drawable'], +['GLXPixmap', ['glXCreateGLXPixmap'], + 'Display* dpy, XVisualInfo* visual, Pixmap pixmap'], +['void', ['glXDestroyGLXPixmap'], 'Display* dpy, GLXPixmap pixmap'], +['int', ['glXQueryExtension'], 'Display* dpy, int* errorb, int* event'], +['int', ['glXQueryVersion'], 'Display* dpy, int* maj, int* min'], +['int', ['glXIsDirect'], 'Display* dpy, GLXContext ctx'], +['int', ['glXGetConfig'], + 'Display* dpy, XVisualInfo* visual, int attrib, int* value'], +['GLXContext', ['glXGetCurrentContext'], 'void'], +['GLXDrawable', ['glXGetCurrentDrawable'], 'void'], +['void', ['glXWaitGL'], 'void'], +['void', ['glXWaitX'], 'void'], +['void', ['glXUseXFont'], 'Font font, int first, int count, int list'], +['const char*', ['glXQueryExtensionsString'], 'Display* dpy, int screen'], +['const char*', ['glXQueryServerString'], 'Display* dpy, int screen, int name'], +['const char*', ['glXGetClientString'], 'Display* dpy, int name'], +['Display*', ['glXGetCurrentDisplay'], 'void'], +['GLXFBConfig*', ['glXChooseFBConfig'], + 'Display* dpy, int screen, const int* attribList, int* nitems'], +['int', ['glXGetFBConfigAttrib'], + 'Display* dpy, GLXFBConfig config, int attribute, int* value'], +['GLXFBConfig*', ['glXGetFBConfigs'], + 'Display* dpy, int screen, int* nelements'], +['XVisualInfo*', ['glXGetVisualFromFBConfig'], + 'Display* dpy, GLXFBConfig config'], +['GLXWindow', ['glXCreateWindow'], + 'Display* dpy, GLXFBConfig config, Window win, const int* attribList'], +['void', ['glXDestroyWindow'], 'Display* dpy, GLXWindow window'], +['GLXPixmap', ['glXCreatePixmap'], + 'Display* dpy, GLXFBConfig config, Pixmap pixmap, const int* attribList'], +['void', ['glXDestroyPixmap'], 'Display* dpy, GLXPixmap pixmap'], +['GLXPbuffer', ['glXCreatePbuffer'], + 'Display* dpy, GLXFBConfig config, const int* attribList'], +['void', ['glXDestroyPbuffer'], 'Display* dpy, GLXPbuffer pbuf'], +['void', ['glXQueryDrawable'], + 'Display* dpy, GLXDrawable draw, int attribute, unsigned int* value'], +['GLXContext', ['glXCreateNewContext'], + 'Display* dpy, GLXFBConfig config, int renderType, ' + 'GLXContext shareList, int direct'], +['int', ['glXMakeContextCurrent'], + 'Display* dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx'], +['GLXDrawable', ['glXGetCurrentReadDrawable'], 'void'], +['int', ['glXQueryContext'], + 'Display* dpy, GLXContext ctx, int attribute, int* value'], +['void', ['glXSelectEvent'], + 'Display* dpy, GLXDrawable drawable, unsigned long mask'], +['void', ['glXGetSelectedEvent'], + 'Display* dpy, GLXDrawable drawable, unsigned long* mask'], +['void', ['glXSwapIntervalEXT'], + 'Display* dpy, GLXDrawable drawable, int interval'], +] + +FUNCTION_SETS = [ + [GL_FUNCTIONS, 'gl'], + [OSMESA_FUNCTIONS, 'osmesa'], + [EGL_FUNCTIONS, 'egl'], + [WGL_FUNCTIONS, 'wgl'], + [GLX_FUNCTIONS, 'glx'], +] + +def GenerateHeader(file, functions, set_name): + """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('void InitializeGLBindings%s();\n' % set_name.upper()) + file.write('void InitializeDebugGLBindings%s();\n' % set_name.upper()) + + # Write typedefs for function pointer types. Always use the GL name for the + # typedef. + file.write('\n') + for [return_type, names, arguments] in functions: + file.write('typedef %s (GL_BINDING_CALL *%sProc)(%s);\n' % + (return_type, names[0], arguments)) + + # Write declarations for function pointers. Always use the GL name for the + # declaration. + file.write('\n') + for [return_type, names, arguments] in functions: + file.write('extern %sProc g_%s;\n' % (names[0], 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 [return_type, names, arguments] in functions: + file.write('#define %s ::gfx::g_%s\n' % + (names[0], 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): + """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 "ui/gfx/gl/gl_bindings.h"\n') + file.write('#include "ui/gfx/gl/gl_implementation.h"\n') + + # Write definitions of function pointers. + file.write('\n') + file.write('namespace gfx {\n') + file.write('\n') + for [return_type, names, arguments] in functions: + file.write('%sProc g_%s;\n' % (names[0], names[0])) + + file.write('\n') + for [return_type, names, arguments] in functions: + file.write('static %sProc g_debug_%s;\n' % (names[0], names[0])) + + # Write function to initialize the function pointers. + file.write('\n') + file.write('void InitializeGLBindings%s() {\n' % set_name.upper()) + for [return_type, names, arguments] in functions: + for name in names: + file.write(' if (!g_%s)\n' % names[0]) + file.write( + ' g_%s = reinterpret_cast<%sProc>(GetGLProcAddress("%s"));\n' % + (names[0], names[0], name)) + file.write('}\n') + file.write('\n') + + # Write logging wrappers for each function. + file.write('extern "C" {\n') + for [return_type, names, arguments] in functions: + 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 = 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)) + 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)) + 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 function pointers. + file.write('\n') + file.write('void InitializeDebugGLBindings%s() {\n' % set_name.upper()) + for [return_type, names, arguments] in functions: + for name in names: + file.write(' if (!g_debug_%s) {\n' % names[0]) + file.write(' g_debug_%s = g_%s;\n' % (names[0], names[0])) + file.write(' g_%s = Debug_%s;\n' % (names[0], names[0])) + file.write(' }\n') + file.write('}\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/gfx/gl/gl_interface.h"\n') + + file.write('\n') + file.write('namespace gfx {\n') + + # Write function that trampoline into the GLInterface. + for [return_type, names, arguments] in functions: + file.write('\n') + file.write('%s GL_BINDING_CALL Mock_%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) + if argument_names == 'void': + argument_names = '' + function_name = names[0][2:] + if 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 a function to lookup a mock GL function based on its name. + file.write('\n') + file.write('void* GL_BINDING_CALL GetMockGLProcAddress(const char* name) {\n') + for [return_type, names, arguments] in functions: + file.write(' if (strcmp(name, "%s") == 0)\n' % names[0]) + file.write(' return reinterpret_cast<void*>(Mock_%s);\n' % names[0]) + file.write(' return NULL;\n') + file.write('}\n'); + + file.write('\n') + file.write('} // namespace gfx\n') + + +def main(argv): + """This is the main function.""" + + if len(argv) >= 1: + dir = argv[0] + else: + dir = '.' + + for [functions, set_name] in FUNCTION_SETS: + header_file = open( + os.path.join(dir, 'gl_bindings_autogen_%s.h' % set_name), 'wb') + GenerateHeader(header_file, functions, set_name) + header_file.close() + + source_file = open( + os.path.join(dir, 'gl_bindings_autogen_%s.cc' % set_name), 'wb') + GenerateSource(source_file, functions, set_name) + source_file.close() + + source_file = open(os.path.join(dir, 'gl_bindings_autogen_mock.cc'), 'wb') + GenerateMockSource(source_file, GL_FUNCTIONS) + source_file.close() + + +if __name__ == '__main__': + main(sys.argv[1:]) diff --git a/ui/gfx/gl/gl.gyp b/ui/gfx/gl/gl.gyp new file mode 100644 index 0000000..f64804b --- /dev/null +++ b/ui/gfx/gl/gl.gyp @@ -0,0 +1,160 @@ +# Copyright (c) 2011 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. + +{ + 'target_defaults': { + 'sources/': [ + ['exclude', '/(cocoa|gtk|win)/'], + ['exclude', '_(cocoa|gtk|linux|mac|posix|win|x)\\.(cc|mm?)$'], + ['exclude', '/(gtk|win|x11)_[^/]*\\.cc$'], + ], + 'conditions': [ + ['OS=="linux" or OS=="freebsd" or OS=="openbsd"', {'sources/': [ + ['include', '/gtk/'], + ['include', '_(gtk|linux|posix|skia|x)\\.cc$'], + ['include', '/(gtk|x11)_[^/]*\\.cc$'], + ]}], + ['OS=="mac"', {'sources/': [ + ['include', '/cocoa/'], + ['include', '_(cocoa|mac|posix)\\.(cc|mm?)$'], + ]}, { # else: OS != "mac" + 'sources/': [ + ['exclude', '\\.mm?$'], + ], + }], + ['OS=="win"', + {'sources/': [ + ['include', '_(win)\\.cc$'], + ['include', '/win/'], + ['include', '/win_[^/]*\\.cc$'], + ]}], + ], + }, + 'targets': [ + { + 'target_name': 'gl', + 'type': '<(library)', + 'dependencies': [ + '<(DEPTH)/app/app.gyp:app_base', + '<(DEPTH)/base/base.gyp:base', + '<(DEPTH)/skia/skia.gyp:skia', + '<(DEPTH)/ui/ui.gyp:ui_gfx', + ], + 'variables': { + 'gl_binding_output_dir': '<(SHARED_INTERMEDIATE_DIR)/ui/gfx/gl', + }, + 'include_dirs': [ + '<(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.gypi', + 'gl_bindings.h', + 'gl_bindings_skia.cc', + 'gl_bindings_skia.h', + 'gl_context.cc', + 'gl_context.h', + 'gl_context_linux.cc', + 'gl_context_mac.cc', + 'gl_context_osmesa.cc', + 'gl_context_osmesa.h', + 'gl_context_stub.cc', + 'gl_context_stub.h', + 'gl_context_win.cc', + 'gl_implementation.cc', + 'gl_implementation.h', + 'gl_implementation_linux.cc', + 'gl_implementation_mac.cc', + 'gl_implementation_win.cc', + 'gl_interface.cc', + 'gl_interface.h', + 'gl_switches.cc', + 'gl_switches.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', + ], + '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=="linux" or OS=="freebsd" or OS=="openbsd"', { + 'sources': [ + 'gl_context_egl.cc', + 'gl_context_egl.h', + '<(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_glx.cc', + '<(gl_binding_output_dir)/gl_bindings_autogen_glx.h', + ], + 'include_dirs': [ + # We don't use angle, but pull the EGL/GLES headers from there. + '<(DEPTH)/third_party/angle/include', + ], + 'all_dependent_settings': { + 'defines': [ + 'GL_GLEXT_PROTOTYPES', + ], + }, + }], + ['OS=="mac"', { + 'link_settings': { + 'libraries': [ + '$(SDKROOT)/System/Library/Frameworks/OpenGL.framework', + ], + }, + }], + ['OS=="win"', { + 'sources': [ + 'gl_context_egl.cc', + 'gl_context_egl.h', + '<(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_wgl.cc', + '<(gl_binding_output_dir)/gl_bindings_autogen_wgl.h', + ], + 'include_dirs': [ + '<(DEPTH)/third_party/angle/include', + ], + }], + ], + }, + ], +}
\ No newline at end of file diff --git a/ui/gfx/gl/gl_bindings.h b/ui/gfx/gl/gl_bindings.h new file mode 100644 index 0000000..8c16a97 --- /dev/null +++ b/ui/gfx/gl/gl_bindings.h @@ -0,0 +1,98 @@ +// Copyright (c) 2011 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. + +// 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. + +#ifndef UI_GFX_GL_GL_BINDINGS_H_ +#define UI_GFX_GL_GL_BINDINGS_H_ +#pragma once + +#include <GL/gl.h> +#include <GL/glext.h> + +#include "build/build_config.h" +#if defined(OS_WIN) +#include "base/logging.h" +#endif + +// The standard OpenGL native extension headers are also included. +#if defined(OS_WIN) +#include <GL/wglext.h> +#elif defined(OS_LINUX) +#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 + +#elif defined(OS_MACOSX) +#include <OpenGL/OpenGL.h> +#endif + +#if defined(OS_WIN) +#define GL_BINDING_CALL WINAPI +#else +#define GL_BINDING_CALL +#endif + +#if defined(OS_WIN) +#define GL_SERVICE_LOG(args) DLOG(INFO) << args; +#else +#define GL_SERVICE_LOG(args) +#endif + +// Forward declare OSMesa types. +typedef struct osmesa_context *OSMesaContext; +typedef void (*OSMESAproc)(); + +#if defined(OS_WIN) || defined(OS_LINUX) + +// 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 *EGLSurface; +typedef void *EGLClientBuffer; +typedef void (*__eglMustCastToProperFunctionPointerType)(void); + +#if defined(OS_WIN) +typedef HDC EGLNativeDisplayType; +typedef HBITMAP EGLNativePixmapType; +typedef HWND EGLNativeWindowType; +#else +typedef Display *EGLNativeDisplayType; +typedef Pixmap EGLNativePixmapType; +typedef Window EGLNativeWindowType; +#endif + +#endif // OS_WIN || OS_LINUX + +#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(OS_LINUX) +#include "gl_bindings_autogen_egl.h" +#include "gl_bindings_autogen_glx.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_GFX_GL_GL_BINDINGS_H_ diff --git a/ui/gfx/gl/gl_bindings_skia.cc b/ui/gfx/gl/gl_bindings_skia.cc new file mode 100644 index 0000000..4f861aa --- /dev/null +++ b/ui/gfx/gl/gl_bindings_skia.cc @@ -0,0 +1,511 @@ +// Copyright (c) 2011 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/gfx/gl/gl_bindings_skia.h" + +#include "base/logging.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_implementation.h" + +// Skia is built against the headers in gpu\GLES. These functions +// are exported without any call-type modifiers. +#define GR_GL_FUNCTION_TYPE + +#include "third_party/skia/gpu/include/GrGLInterface.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 against the GLES headers, so the interfaces in +// GrGLInterface are __cdecl. + +GLvoid StubGLActiveTexture(GLenum texture) { + glActiveTexture(texture); +} + +GLvoid StubGLAttachShader(GLuint program, GLuint shader) { + glAttachShader(program, shader); +} + +GLvoid StubGLBindAttribLocation(GLuint program, GLuint index, + const char* name) { + glBindAttribLocation(program, index, name); +} + +GLvoid StubGLBindBuffer(GLenum target, GLuint buffer) { + glBindBuffer(target, buffer); +} + +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, GLsizei size, const void* data, + GLenum usage) { + glBufferData(target, size, data, usage); +} + +GLvoid StubGLBufferSubData(GLenum target, GLint offset, GLsizei 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 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 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 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 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); +} + +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 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); +} + +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 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 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 StubGLUniform1fv(GLint location, GLsizei count, const GLfloat* v) { + glUniform1fv(location, count, v); +} + +GLvoid StubGLUniform1i(GLint location, GLint x) { + glUniform1i(location, x); +} + +GLvoid StubGLUniform4fv(GLint location, GLsizei count, const GLfloat* v) { + glUniform4fv(location, count, v); +} + +GLvoid StubGLUniformMatrix3fv(GLint location, GLsizei count, + GLboolean transpose, const GLfloat* value) { + glUniformMatrix3fv(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" + +// Populate |gl_interface| with pointers to the GL implementation used by +// Chrome. +void InitializeGrGLInterface(GrGLInterface* gl_interface) { + + // Propagate the type of GL bindings exported back to skia. + switch (gfx::GetGLImplementation()) { + case gfx::kGLImplementationNone: + NOTREACHED(); + break; + case gfx::kGLImplementationDesktopGL: + gl_interface->fBindingsExported = kDesktop_GrGLBinding; + break; + case gfx::kGLImplementationOSMesaGL: + gl_interface->fBindingsExported = kDesktop_GrGLBinding; + break; + case gfx::kGLImplementationEGLGLES2: + gl_interface->fBindingsExported = kES2_GrGLBinding; + break; + case gfx::kGLImplementationMockGL: + NOTREACHED(); + break; + } + + gl_interface->fClientActiveTexture = NULL; + gl_interface->fColor4ub = NULL; + gl_interface->fColorPointer = NULL; + gl_interface->fDisableClientState = NULL; + gl_interface->fEnableClientState = NULL; + gl_interface->fLoadMatrixf = NULL; + gl_interface->fMatrixMode = NULL; + gl_interface->fPointSize = NULL; + gl_interface->fShadeModel = NULL; + gl_interface->fTexCoordPointer = NULL; + gl_interface->fTexEnvi = NULL; + gl_interface->fVertexPointer = NULL; + + gl_interface->fResolveMultisampleFramebuffer = NULL; + gl_interface->fActiveTexture = StubGLActiveTexture; + gl_interface->fAttachShader = StubGLAttachShader; + gl_interface->fBindAttribLocation = StubGLBindAttribLocation; + gl_interface->fBindBuffer = StubGLBindBuffer; + gl_interface->fBindTexture = StubGLBindTexture; + gl_interface->fBlendColor = StubGLBlendColor; + gl_interface->fBlendFunc = StubGLBlendFunc; + gl_interface->fBufferData = StubGLBufferData; + gl_interface->fBufferSubData = StubGLBufferSubData; + gl_interface->fClear = StubGLClear; + gl_interface->fClearColor = StubGLClearColor; + gl_interface->fClearStencil = StubGLClearStencil; + gl_interface->fColorMask = StubGLColorMask; + gl_interface->fCompileShader = StubGLCompileShader; + gl_interface->fCompressedTexImage2D = StubGLCompressedTexImage2D; + gl_interface->fCreateProgram = StubGLCreateProgram; + gl_interface->fCreateShader = StubGLCreateShader; + gl_interface->fCullFace = StubGLCullFace; + gl_interface->fDeleteBuffers = StubGLDeleteBuffers; + gl_interface->fDeleteProgram = StubGLDeleteProgram; + gl_interface->fDeleteShader = StubGLDeleteShader; + gl_interface->fDeleteTextures = StubGLDeleteTextures; + gl_interface->fDepthMask = StubGLDepthMask; + gl_interface->fDisable = StubGLDisable; + gl_interface->fDisableVertexAttribArray = StubGLDisableVertexAttribArray; + gl_interface->fDrawArrays = StubGLDrawArrays; + gl_interface->fDrawElements = StubGLDrawElements; + gl_interface->fEnable = StubGLEnable; + gl_interface->fEnableVertexAttribArray = StubGLEnableVertexAttribArray; + gl_interface->fFrontFace = StubGLFrontFace; + gl_interface->fGenBuffers = StubGLGenBuffers; + gl_interface->fGenTextures = StubGLGenTextures; + gl_interface->fGetBufferParameteriv = StubGLGetBufferParameteriv; + gl_interface->fGetError = StubGLGetError; + gl_interface->fGetIntegerv = StubGLGetIntegerv; + gl_interface->fGetProgramInfoLog = StubGLGetProgramInfoLog; + gl_interface->fGetProgramiv = StubGLGetProgramiv; + gl_interface->fGetShaderInfoLog = StubGLGetShaderInfoLog; + gl_interface->fGetShaderiv = StubGLGetShaderiv; + gl_interface->fGetString = StubGLGetString; + gl_interface->fGetUniformLocation = StubGLGetUniformLocation; + gl_interface->fLineWidth = StubGLLineWidth; + gl_interface->fLinkProgram = StubGLLinkProgram; + gl_interface->fPixelStorei = StubGLPixelStorei; + gl_interface->fReadPixels = StubGLReadPixels; + gl_interface->fScissor = StubGLScissor; + gl_interface->fShaderSource = StubGLShaderSource; + gl_interface->fStencilFunc = StubGLStencilFunc; + gl_interface->fStencilFuncSeparate = StubGLStencilFuncSeparate; + gl_interface->fStencilMask = StubGLStencilMask; + gl_interface->fStencilMaskSeparate = StubGLStencilMaskSeparate; + gl_interface->fStencilOp = StubGLStencilOp; + gl_interface->fStencilOpSeparate = StubGLStencilOpSeparate; + gl_interface->fTexImage2D = StubGLTexImage2D; + gl_interface->fTexParameteri = StubGLTexParameteri; + gl_interface->fTexSubImage2D = StubGLTexSubImage2D; + gl_interface->fUniform1fv = StubGLUniform1fv; + gl_interface->fUniform1i = StubGLUniform1i; + gl_interface->fUniform4fv = StubGLUniform4fv; + gl_interface->fUniformMatrix3fv = StubGLUniformMatrix3fv; + gl_interface->fUseProgram = StubGLUseProgram; + gl_interface->fVertexAttrib4fv = StubGLVertexAttrib4fv; + gl_interface->fVertexAttribPointer = StubGLVertexAttribPointer; + gl_interface->fViewport = StubGLViewport; + gl_interface->fBindFramebuffer = StubGLBindFramebuffer; + gl_interface->fBindRenderbuffer = StubGLBindRenderbuffer; + gl_interface->fCheckFramebufferStatus = StubGLCheckFramebufferStatus; + gl_interface->fDeleteFramebuffers = StubGLDeleteFramebuffers; + gl_interface->fDeleteRenderbuffers = StubGLDeleteRenderbuffers; + gl_interface->fFramebufferRenderbuffer = StubGLFramebufferRenderbuffer; + gl_interface->fFramebufferTexture2D = StubGLFramebufferTexture2D; + gl_interface->fGenFramebuffers = StubGLGenFramebuffers; + gl_interface->fGenRenderbuffers = StubGLGenRenderbuffers; + gl_interface->fRenderbufferStorage = StubGLRenderBufferStorage; + gl_interface->fRenderbufferStorageMultisample = + StubGLRenderbufferStorageMultisample; + gl_interface->fBlitFramebuffer = StubGLBlitFramebuffer; + gl_interface->fMapBuffer = StubGLMapBuffer; + gl_interface->fUnmapBuffer = StubGLUnmapBuffer; +} + +} // namespace + +namespace gfx { + +void BindSkiaToHostGL() { + static GrGLInterface host_gl_interface; + static bool host_StubGL_initialized = false; + if (!host_StubGL_initialized) { + InitializeGrGLInterface(&host_gl_interface); + GrGLSetGLInterface(&host_gl_interface); + host_StubGL_initialized = true; + } +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_bindings_skia.h b/ui/gfx/gl/gl_bindings_skia.h new file mode 100644 index 0000000..4433c73 --- /dev/null +++ b/ui/gfx/gl/gl_bindings_skia.h @@ -0,0 +1,21 @@ +// Copyright (c) 2011 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_GFX_GL_GL_BINDINGS_SKIA_H_ +#define UI_GFX_GL_GL_BINDINGS_SKIA_H_ +#pragma once + +namespace gfx { + +// The GPU back-end for skia normally makes direct calls to GLES2\gl. Call +// this routine to bind the skia GL implementation to that exported by the +// ui/gfx/gl entry points. +// Note: This override is required to allow the skia gl calls to be correctly +// routed around the command buffers during execution of the DumpRenderTree +// layout tests. +void BindSkiaToHostGL(); + +} + +#endif // UI_GFX_GL_GL_BINDINGS_SKIA_H_ diff --git a/ui/gfx/gl/gl_context.cc b/ui/gfx/gl/gl_context.cc new file mode 100644 index 0000000..769f28c --- /dev/null +++ b/ui/gfx/gl/gl_context.cc @@ -0,0 +1,58 @@ +// Copyright (c) 2011 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/logging.h" +#include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_implementation.h" +#include "ui/gfx/gl/gl_switches.h" + +namespace gfx { + +unsigned int GLContext::GetBackingFrameBufferObject() { + return 0; +} + +std::string GLContext::GetExtensions() { + DCHECK(IsCurrent()); + const char* ext = reinterpret_cast<const char*>(glGetString(GL_EXTENSIONS)); + return std::string(ext ? ext : ""); +} + +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; +} + +bool GLContext::InitializeCommon() { + if (!MakeCurrent()) { + LOG(ERROR) << "MakeCurrent failed."; + return false; + } + + if (!IsOffscreen()) { + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableGpuVsync)) + SetSwapInterval(0); + else + SetSwapInterval(1); + } + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + if (glGetError() != GL_NO_ERROR) { + LOG(ERROR) << "glClear failed."; + return false; + } + + return true; +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_context.h b/ui/gfx/gl/gl_context.h new file mode 100644 index 0000000..67bba0b --- /dev/null +++ b/ui/gfx/gl/gl_context.h @@ -0,0 +1,82 @@ +// Copyright (c) 2011 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_GFX_GL_GL_CONTEXT_H_ +#define UI_GFX_GL_GL_CONTEXT_H_ +#pragma once + +#include <string> + +#include "build/build_config.h" +#include "ui/gfx/native_widget_types.h" +#include "ui/gfx/size.h" + +namespace gfx { + +// Encapsulates an OpenGL context, hiding platform specific management. +class GLContext { + public: + GLContext() {} + virtual ~GLContext() {} + + // Destroys the GL context. + virtual void Destroy() = 0; + + // Makes the GL context current on the current thread. + virtual bool MakeCurrent() = 0; + + // Returns true if this context is current. + virtual bool IsCurrent() = 0; + + // Returns true if this context 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 back buffer. + virtual gfx::Size GetSize() = 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 the internal frame buffer object name if the context is backed by + // FBO. Otherwise returns 0. + virtual unsigned int GetBackingFrameBufferObject(); + + // 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); + + static bool InitializeOneOff(); + +#if !defined(OS_MACOSX) + // Create a GL context that renders directly to a view. + static GLContext* CreateViewGLContext(gfx::PluginWindowHandle window, + bool multisampled); +#endif + + // Create a GL context used for offscreen rendering. It is initially backed by + // a 1x1 pbuffer. Use it to create an FBO to do useful rendering. + // |share_context|, if non-NULL, is a context which the internally created + // OpenGL context shares textures and other resources. + static GLContext* CreateOffscreenGLContext(GLContext* shared_context); + + protected: + bool InitializeCommon(); + + private: + DISALLOW_COPY_AND_ASSIGN(GLContext); +}; + +} // namespace gfx + +#endif // UI_GFX_GL_GL_CONTEXT_H_ diff --git a/ui/gfx/gl/gl_context_egl.cc b/ui/gfx/gl/gl_context_egl.cc new file mode 100644 index 0000000..2b1565f --- /dev/null +++ b/ui/gfx/gl/gl_context_egl.cc @@ -0,0 +1,428 @@ +// Copyright (c) 2011 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 "build/build_config.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "third_party/angle/include/EGL/egl.h" +#include "ui/gfx/gl/gl_context_egl.h" + +// This header must come after the above third-party include, as +// it brings in #defines that cause conflicts. +#include "ui/gfx/gl/gl_bindings.h" + +#if defined(OS_LINUX) +extern "C" { +#include <X11/Xlib.h> +} +#define EGL_HAS_PBUFFERS 1 +#endif + +namespace gfx { + +namespace { + +// The EGL configuration to use. +EGLDisplay g_display; +EGLConfig g_config; + +// 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 anonymous + +SharedEGLSurface::SharedEGLSurface(EGLSurface surface) : surface_(surface) { +} + +SharedEGLSurface::~SharedEGLSurface() { + if (surface_) { + if (!eglDestroySurface(g_display, surface_)) { + LOG(ERROR) << "eglDestroySurface failed with error " + << GetLastEGLErrorString(); + } + } +} + +EGLSurface SharedEGLSurface::egl_surface() const { + return surface_; +} + +bool BaseEGLContext::InitializeOneOff() { + static bool initialized = false; + if (initialized) + return true; + +#ifdef OS_LINUX + EGLNativeDisplayType native_display = XOpenDisplay(NULL); +#else + EGLNativeDisplayType native_display = EGL_DEFAULT_DISPLAY; +#endif + g_display = eglGetDisplay(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_RED_SIZE, 8, + EGL_DEPTH_SIZE, 16, + EGL_STENCIL_SIZE, 8, + EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, +#ifdef EGL_HAS_PBUFFERS + EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_PBUFFER_BIT, +#else + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, +#endif + 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; + } + + scoped_array<EGLConfig> configs(new EGLConfig[num_configs]); + if (!eglChooseConfig(g_display, + kConfigAttribs, + configs.get(), + num_configs, + &num_configs)) { + LOG(ERROR) << "eglChooseConfig failed with error " + << GetLastEGLErrorString(); + return false; + } + + g_config = configs[0]; + + initialized = true; + return true; +} + +EGLDisplay BaseEGLContext::GetDisplay() { + return g_display; +} + +std::string BaseEGLContext::GetExtensions() { + const char* extensions = eglQueryString(g_display, EGL_EXTENSIONS); + if (!extensions) + return GLContext::GetExtensions(); + + return GLContext::GetExtensions() + " " + extensions; +} + +NativeViewEGLContext::NativeViewEGLContext(void* window) + : window_(window), + context_(NULL) +{ +} + +NativeViewEGLContext::~NativeViewEGLContext() { +} + +bool NativeViewEGLContext::Initialize() { + DCHECK(!context_); + + // Create a surface for the native window. + EGLNativeWindowType native_window = + reinterpret_cast<EGLNativeWindowType>(window_); + surface_ = new SharedEGLSurface(eglCreateWindowSurface(g_display, + g_config, + native_window, + NULL)); + + if (!surface_->egl_surface()) { + LOG(ERROR) << "eglCreateWindowSurface failed with error " + << GetLastEGLErrorString(); + Destroy(); + return false; + } + + static const EGLint kContextAttributes[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes); + if (!context_) { + LOG(ERROR) << "eglCreateContext failed with error " + << GetLastEGLErrorString(); + Destroy(); + return false; + } + + if (!MakeCurrent()) { + LOG(ERROR) << "MakeCurrent failed."; + Destroy(); + return false; + } + + if (!InitializeCommon()) { + LOG(ERROR) << "GLContext::InitializeCommon failed."; + Destroy(); + return false; + } + + return true; +} + +void NativeViewEGLContext::Destroy() { + if (context_) { + if (!eglDestroyContext(g_display, context_)) { + LOG(ERROR) << "eglDestroyContext failed with error " + << GetLastEGLErrorString(); + } + + context_ = NULL; + } + + surface_ = NULL; +} + +bool NativeViewEGLContext::MakeCurrent() { + DCHECK(context_); + if (!eglMakeCurrent(g_display, + surface_->egl_surface(), + surface_->egl_surface(), + context_)) { + VLOG(1) << "eglMakeCurrent failed with error " + << GetLastEGLErrorString(); + return false; + } + + return true; +} + +bool NativeViewEGLContext::IsCurrent() { + DCHECK(context_); + return context_ == eglGetCurrentContext(); +} + +bool NativeViewEGLContext::IsOffscreen() { + return false; +} + +bool NativeViewEGLContext::SwapBuffers() { + if (!eglSwapBuffers(g_display, surface_->egl_surface())) { + VLOG(1) << "eglSwapBuffers failed with error " + << GetLastEGLErrorString(); + return false; + } + + return true; +} + +gfx::Size NativeViewEGLContext::GetSize() { +#if defined(OS_WIN) + RECT rect; + if (!GetClientRect(static_cast<HWND>(window_), &rect)) { + DCHECK(false) << "GetClientRect failed."; + return gfx::Size(); + } + + return gfx::Size(rect.right - rect.left, rect.bottom - rect.top); +#else + // TODO(piman): This doesn't work correctly on Windows yet, the size doesn't + // get updated on resize. When it does, we can share the code. + EGLint width; + EGLint height; + if (!eglQuerySurface( + g_display, surface_->egl_surface(), EGL_WIDTH, &width) || + !eglQuerySurface( + g_display, surface_->egl_surface(), EGL_HEIGHT, &height)) { + NOTREACHED() << "eglQuerySurface failed with error " + << GetLastEGLErrorString(); + return gfx::Size(); + } + + return gfx::Size(width, height); +#endif +} + +void* NativeViewEGLContext::GetHandle() { + return context_; +} + +void NativeViewEGLContext::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + if (!eglSwapInterval(g_display, interval)) { + LOG(ERROR) << "eglSwapInterval failed with error " + << GetLastEGLErrorString(); + } +} + +SharedEGLSurface* NativeViewEGLContext::GetSurface() { + return surface_; +} + +SecondaryEGLContext::SecondaryEGLContext() + : context_(NULL) +{ +} + +SecondaryEGLContext::~SecondaryEGLContext() { +} + +bool SecondaryEGLContext::Initialize(GLContext* shared_context) { + DCHECK(!context_); + + static const EGLint kContextAttributes[] = { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }; + + if (shared_context) { + surface_ = static_cast<BaseEGLContext*>(shared_context)->GetSurface(); + + // Create a context. + context_ = eglCreateContext(g_display, + g_config, + shared_context->GetHandle(), + kContextAttributes); + } else { +#ifdef EGL_HAS_PBUFFERS + static const EGLint kPbufferAttribs[] = { + EGL_WIDTH, 1, + EGL_HEIGHT, 1, + EGL_NONE + }; + + surface_ = new SharedEGLSurface(eglCreatePbufferSurface(g_display, + g_config, + kPbufferAttribs)); + if (!surface_->egl_surface()) { + LOG(ERROR) << "eglCreatePbufferSurface failed with error " + << GetLastEGLErrorString(); + Destroy(); + return false; + } + + context_ = eglCreateContext(g_display, g_config, NULL, kContextAttributes); +#else + NOTIMPLEMENTED() << "Offscreen non-shared GLES context"; + return false; +#endif + } + + if (!context_) { + LOG(ERROR) << "eglCreateContext failed with error " + << GetLastEGLErrorString(); + Destroy(); + return false; + } + + return true; +} + +void SecondaryEGLContext::Destroy() { + if (context_) { + if (!eglDestroyContext(g_display, context_)) { + LOG(ERROR) << "eglDestroyContext failed with error " + << GetLastEGLErrorString(); + } + + context_ = NULL; + } + + surface_ = NULL; +} + +bool SecondaryEGLContext::MakeCurrent() { + DCHECK(context_); + if (!eglMakeCurrent(g_display, + surface_->egl_surface(), + surface_->egl_surface(), + context_)) { + VLOG(1) << "eglMakeCurrent failed with error " + << GetLastEGLErrorString(); + return false; + } + + return true; +} + +bool SecondaryEGLContext::IsCurrent() { + DCHECK(context_); + return context_ == eglGetCurrentContext(); +} + +bool SecondaryEGLContext::IsOffscreen() { + return true; +} + +bool SecondaryEGLContext::SwapBuffers() { + NOTREACHED() << "Attempted to call SwapBuffers on a SecondaryEGLContext."; + return false; +} + +gfx::Size SecondaryEGLContext::GetSize() { + NOTREACHED() << "Should not be requesting size of this SecondaryEGLContext."; + return gfx::Size(1, 1); +} + +void* SecondaryEGLContext::GetHandle() { + return context_; +} + +void SecondaryEGLContext::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + NOTREACHED() << "Attempt to call SetSwapInterval on a SecondaryEGLContext."; +} + +SharedEGLSurface* SecondaryEGLContext::GetSurface() { + return surface_; +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_context_egl.h b/ui/gfx/gl/gl_context_egl.h new file mode 100644 index 0000000..4250457 --- /dev/null +++ b/ui/gfx/gl/gl_context_egl.h @@ -0,0 +1,119 @@ +// Copyright (c) 2011 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_GFX_GL_GL_CONTEXT_EGL_H_ +#define UI_GFX_GL_GL_CONTEXT_EGL_H_ +#pragma once + +#include "base/memory/ref_counted.h" +#include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/size.h" + +typedef void* EGLDisplay; +typedef void* EGLContext; +typedef void* EGLSurface; + +namespace gfx { + +// Takes ownership of an EGL surface and reference counts it so it can be shared +// by multiple EGL contexts and destroyed with the last. +class SharedEGLSurface : public base::RefCounted<SharedEGLSurface> { + public: + explicit SharedEGLSurface(EGLSurface surface); + ~SharedEGLSurface(); + + EGLSurface egl_surface() const; + + private: + EGLSurface surface_; + DISALLOW_COPY_AND_ASSIGN(SharedEGLSurface); +}; + +// Interface for EGL contexts. Adds an EGL specific accessor for retreiving +// the surface. +class BaseEGLContext : public GLContext { + public: + BaseEGLContext() {} + virtual ~BaseEGLContext() {} + + static bool InitializeOneOff(); + + static EGLDisplay GetDisplay(); + + // Get the associated EGL surface. + virtual SharedEGLSurface* GetSurface() = 0; + + // Implement GLContext. + virtual std::string GetExtensions(); + + private: + DISALLOW_COPY_AND_ASSIGN(BaseEGLContext); +}; + +// Encapsulates an EGL OpenGL ES context that renders to a view. +class NativeViewEGLContext : public BaseEGLContext { + public: + explicit NativeViewEGLContext(void* window); + virtual ~NativeViewEGLContext(); + + // Initialize an EGL context. + bool Initialize(); + + // Implement GLContext. + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval); + + // Implement BaseEGLContext. + virtual SharedEGLSurface* GetSurface(); + + private: + void* window_; + scoped_refptr<SharedEGLSurface> surface_; + EGLContext context_; + + DISALLOW_COPY_AND_ASSIGN(NativeViewEGLContext); +}; + +// Encapsulates an EGL OpenGL ES context intended for offscreen use. It is +// actually associated with a native window or a pbuffer on supporting platforms +// and will render to it. The caller must bind an FBO to prevent this. +// TODO(apatrick): implement pbuffers in ANGLE and change this to +// PbufferEGLContext and use it on all EGL platforms. +class SecondaryEGLContext : public BaseEGLContext { + public: + SecondaryEGLContext(); + virtual ~SecondaryEGLContext(); + + // Initialize an EGL context that shares a namespace with another. + bool Initialize(GLContext* shared_context); + + // Implement GLContext. + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval); + + // Implement BaseEGLContext. + virtual SharedEGLSurface* GetSurface(); + + private: + scoped_refptr<SharedEGLSurface> surface_; + EGLContext context_; + + DISALLOW_COPY_AND_ASSIGN(SecondaryEGLContext); +}; + +} // namespace gfx + +#endif // UI_GFX_GL_GL_CONTEXT_EGL_H_ diff --git a/ui/gfx/gl/gl_context_linux.cc b/ui/gfx/gl/gl_context_linux.cc new file mode 100644 index 0000000..430bba5 --- /dev/null +++ b/ui/gfx/gl/gl_context_linux.cc @@ -0,0 +1,830 @@ +// Copyright (c) 2011 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 ViewGLContext and PbufferGLContext classes. + +#include "ui/gfx/gl/gl_context.h" + +extern "C" { +#include <X11/Xlib.h> +} + +#include <GL/osmesa.h> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "ui/base/x/x11_util.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_context_egl.h" +#include "ui/gfx/gl/gl_context_osmesa.h" +#include "ui/gfx/gl/gl_context_stub.h" +#include "ui/gfx/gl/gl_implementation.h" + +namespace { + +Display* GetXDisplayHelper() { + static Display* display = NULL; + + if (!display) { + display = XOpenDisplay(NULL); + CHECK(display); + } + + return display; +} + +} // namespace + +namespace gfx { + +typedef GLXContext GLContextHandle; +typedef GLXPbuffer PbufferHandle; + +class BaseLinuxGLContext : public GLContext { + public: + virtual std::string GetExtensions(); +}; + +// This class is a wrapper around a GL context that renders directly to a +// window. +class ViewGLContext : public GLContext { + public: + explicit ViewGLContext(gfx::PluginWindowHandle window) + : window_(window), + context_(NULL) { + DCHECK(window); + } + + // Initializes the GL context. + bool Initialize(bool multisampled); + + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval); + + private: + gfx::PluginWindowHandle window_; + GLContextHandle context_; + + DISALLOW_COPY_AND_ASSIGN(ViewGLContext); +}; + +// This class is a wrapper around a GL context that uses OSMesa to render +// to an offscreen buffer and then blits it to a window. +class OSMesaViewGLContext : public GLContext { + public: + explicit OSMesaViewGLContext(gfx::PluginWindowHandle window) + : window_graphics_context_(0), + window_(window), + pixmap_graphics_context_(0), + pixmap_(0) { + DCHECK(window); + } + + // Initializes the GL context. + bool Initialize(); + + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval); + + private: + bool UpdateSize(); + + GC window_graphics_context_; + gfx::PluginWindowHandle window_; + GC pixmap_graphics_context_; + Pixmap pixmap_; + OSMesaGLContext osmesa_context_; + + DISALLOW_COPY_AND_ASSIGN(OSMesaViewGLContext); +}; + +// This class is a wrapper around a GL context used for offscreen rendering. +// It is initially backed by a 1x1 pbuffer. Use it to create an FBO to do useful +// rendering. +class PbufferGLContext : public GLContext { + public: + explicit PbufferGLContext() + : context_(NULL), + pbuffer_(0) { + } + + // Initializes the GL context. + bool Initialize(GLContext* shared_context); + + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval); + + private: + GLContextHandle context_; + PbufferHandle pbuffer_; + + DISALLOW_COPY_AND_ASSIGN(PbufferGLContext); +}; + +// Backup context if Pbuffers (GLX 1.3) aren't supported. May run slower... +class PixmapGLContext : public GLContext { + public: + explicit PixmapGLContext() + : context_(NULL), + pixmap_(0), + glx_pixmap_(0) { + } + + // Initializes the GL context. + bool Initialize(GLContext* shared_context); + + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval); + + private: + GLContextHandle context_; + Pixmap pixmap_; + GLXPixmap glx_pixmap_; + + DISALLOW_COPY_AND_ASSIGN(PixmapGLContext); +}; + +// 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); + } +}; + +bool GLContext::InitializeOneOff() { + static bool initialized = false; + if (initialized) + return true; + + static const GLImplementation kAllowedGLImplementations[] = { + kGLImplementationDesktopGL, + kGLImplementationEGLGLES2, + kGLImplementationOSMesaGL + }; + + if (!InitializeRequestedGLBindings( + kAllowedGLImplementations, + kAllowedGLImplementations + arraysize(kAllowedGLImplementations), + kGLImplementationDesktopGL)) { + LOG(ERROR) << "InitializeRequestedGLBindings failed."; + return false; + } + + switch (GetGLImplementation()) { + case kGLImplementationDesktopGL: { + // Only check the GLX version if we are in fact using GLX. We might + // actually be using the mock GL implementation. + Display* display = GetXDisplayHelper(); + int major, minor; + if (!glXQueryVersion(display, &major, &minor)) { + LOG(ERROR) << "glxQueryVersion failed"; + return false; + } + + if (major == 1 && minor < 3) { + LOG(WARNING) << "GLX 1.3 or later is recommended."; + } + + break; + } + case kGLImplementationEGLGLES2: + if (!BaseEGLContext::InitializeOneOff()) { + LOG(ERROR) << "BaseEGLContext::InitializeOneOff failed."; + return false; + } + break; + default: + break; + } + + initialized = true; + return true; +} + +std::string BaseLinuxGLContext::GetExtensions() { + Display* display = GetXDisplayHelper(); + const char* extensions = glXQueryExtensionsString(display, 0); + if (extensions) { + return GLContext::GetExtensions() + " " + extensions; + } + + return GLContext::GetExtensions(); +} + +bool ViewGLContext::Initialize(bool multisampled) { + if (multisampled) { + LOG(WARNING) << "Multisampling not implemented."; + } + + Display* display = GetXDisplayHelper(); + XWindowAttributes attributes; + XGetWindowAttributes(display, window_, &attributes); + 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()); + DCHECK_GT(visual_info_count, 0); + context_ = NULL; + for (int i = 0; i < visual_info_count; ++i) { + context_ = glXCreateContext(display, visual_info_list.get() + i, 0, True); + if (context_) + break; + } + if (!context_) { + LOG(ERROR) << "Couldn't create GL context."; + return false; + } + + if (!MakeCurrent()) { + Destroy(); + LOG(ERROR) << "Couldn't make context current for initialization."; + return false; + } + + if (!InitializeCommon()) { + LOG(ERROR) << "GLContext::InitlializeCommon failed."; + Destroy(); + return false; + } + + return true; +} + +void ViewGLContext::Destroy() { + Display* display = GetXDisplayHelper(); + bool result = glXMakeCurrent(display, 0, 0); + + // glXMakeCurrent isn't supposed to fail when unsetting the context, unless + // we have pending draws on an invalid window - which shouldn't be the case + // here. + DCHECK(result); + if (context_) { + glXDestroyContext(display, context_); + context_ = NULL; + } +} + +bool ViewGLContext::MakeCurrent() { + if (IsCurrent()) { + return true; + } + + Display* display = GetXDisplayHelper(); + if (glXMakeCurrent(display, window_, context_) != True) { + glXDestroyContext(display, context_); + context_ = 0; + LOG(ERROR) << "Couldn't make context current."; + return false; + } + + return true; +} + +bool ViewGLContext::IsCurrent() { + return glXGetCurrentDrawable() == window_ && + glXGetCurrentContext() == context_; +} + +bool ViewGLContext::IsOffscreen() { + return false; +} + +bool ViewGLContext::SwapBuffers() { + Display* display = GetXDisplayHelper(); + glXSwapBuffers(display, window_); + return true; +} + +gfx::Size ViewGLContext::GetSize() { + XWindowAttributes attributes; + Display* display = GetXDisplayHelper(); + XGetWindowAttributes(display, window_, &attributes); + return gfx::Size(attributes.width, attributes.height); +} + +void* ViewGLContext::GetHandle() { + return context_; +} + +void ViewGLContext::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + if (HasExtension("GLX_EXT_swap_control") && glXSwapIntervalEXT) { + Display* display = GetXDisplayHelper(); + glXSwapIntervalEXT(display, window_, interval); + } +} + +bool OSMesaViewGLContext::Initialize() { + if (!osmesa_context_.Initialize(OSMESA_BGRA, NULL)) { + LOG(ERROR) << "OSMesaGLContext::Initialize failed."; + Destroy(); + return false; + } + + window_graphics_context_ = XCreateGC(GetXDisplayHelper(), + window_, + 0, + NULL); + if (!window_graphics_context_) { + LOG(ERROR) << "XCreateGC failed."; + Destroy(); + return false; + } + + UpdateSize(); + + return true; +} + +void OSMesaViewGLContext::Destroy() { + osmesa_context_.Destroy(); + + Display* display = GetXDisplayHelper(); + + if (pixmap_graphics_context_) { + XFreeGC(display, pixmap_graphics_context_); + pixmap_graphics_context_ = NULL; + } + + if (pixmap_) { + XFreePixmap(display, pixmap_); + pixmap_ = 0; + } + + if (window_graphics_context_) { + XFreeGC(display, window_graphics_context_); + window_graphics_context_ = NULL; + } +} + +bool OSMesaViewGLContext::MakeCurrent() { + // TODO(apatrick): This is a bit of a hack. The window might have had zero + // size when the context was initialized. Assume it has a valid size when + // MakeCurrent is called and resize the back buffer if necessary. + UpdateSize(); + return osmesa_context_.MakeCurrent(); +} + +bool OSMesaViewGLContext::IsCurrent() { + return osmesa_context_.IsCurrent(); +} + +bool OSMesaViewGLContext::IsOffscreen() { + return false; +} + +bool OSMesaViewGLContext::SwapBuffers() { + // Update the size before blitting so that the blit size is exactly the same + // as the window. + if (!UpdateSize()) { + LOG(ERROR) << "Failed to update size of OSMesaGLContext."; + return false; + } + + gfx::Size size = osmesa_context_.GetSize(); + + Display* display = GetXDisplayHelper(); + + // Copy the frame into the pixmap. + XWindowAttributes attributes; + XGetWindowAttributes(display, window_, &attributes); + ui::PutARGBImage(display, + attributes.visual, + attributes.depth, + pixmap_, + pixmap_graphics_context_, + static_cast<const uint8*>(osmesa_context_.buffer()), + size.width(), + size.height()); + + // Copy the pixmap to the window. + XCopyArea(display, + pixmap_, + window_, + window_graphics_context_, + 0, 0, + size.width(), size.height(), + 0, 0); + + return true; +} + +gfx::Size OSMesaViewGLContext::GetSize() { + return osmesa_context_.GetSize(); +} + +void* OSMesaViewGLContext::GetHandle() { + return osmesa_context_.GetHandle(); +} + +void OSMesaViewGLContext::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + // Fail silently. It is legitimate to set the swap interval on a view context + // but XLib does not have those semantics. +} + +bool OSMesaViewGLContext::UpdateSize() { + // Get the window size. + XWindowAttributes attributes; + Display* display = GetXDisplayHelper(); + XGetWindowAttributes(display, window_, &attributes); + gfx::Size window_size = gfx::Size(std::max(1, attributes.width), + std::max(1, attributes.height)); + + // Early out if the size has not changed. + gfx::Size osmesa_size = osmesa_context_.GetSize(); + if (pixmap_graphics_context_ && pixmap_ && window_size == osmesa_size) + return true; + + // Change osmesa surface size to that of window. + osmesa_context_.Resize(window_size); + + // Destroy the previous pixmap and graphics context. + if (pixmap_graphics_context_) { + XFreeGC(display, pixmap_graphics_context_); + pixmap_graphics_context_ = NULL; + } + if (pixmap_) { + XFreePixmap(display, pixmap_); + pixmap_ = 0; + } + + // Recreate a pixmap to hold the frame. + pixmap_ = XCreatePixmap(display, + window_, + window_size.width(), + window_size.height(), + attributes.depth); + if (!pixmap_) { + LOG(ERROR) << "XCreatePixmap failed."; + return false; + } + + // Recreate a graphics context for the pixmap. + pixmap_graphics_context_ = XCreateGC(display, pixmap_, 0, NULL); + if (!pixmap_graphics_context_) { + LOG(ERROR) << "XCreateGC failed"; + return false; + } + + return true; +} + +GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window, + bool multisampled) { + switch (GetGLImplementation()) { + case kGLImplementationDesktopGL: { + scoped_ptr<ViewGLContext> context(new ViewGLContext(window)); + + if (!context->Initialize(multisampled)) + return NULL; + + return context.release(); + } + case kGLImplementationEGLGLES2: { + scoped_ptr<NativeViewEGLContext> context( + new NativeViewEGLContext(reinterpret_cast<void *>(window))); + if (!context->Initialize()) + return NULL; + + return context.release(); + } + case kGLImplementationOSMesaGL: { + scoped_ptr<OSMesaViewGLContext> context(new OSMesaViewGLContext(window)); + + if (!context->Initialize()) + return NULL; + + return context.release(); + } + case kGLImplementationMockGL: + return new StubGLContext; + default: + NOTREACHED(); + return NULL; + } +} + +bool PbufferGLContext::Initialize(GLContext* shared_context) { + static const int config_attributes[] = { + GLX_DRAWABLE_TYPE, + GLX_PBUFFER_BIT, + GLX_RENDER_TYPE, + GLX_RGBA_BIT, + GLX_DOUBLEBUFFER, + 0, + 0 + }; + + Display* display = GetXDisplayHelper(); + + int nelements = 0; + // TODO(kbr): figure out whether hardcoding screen to 0 is sufficient. + scoped_ptr_malloc<GLXFBConfig, ScopedPtrXFree> config( + glXChooseFBConfig(display, 0, config_attributes, &nelements)); + if (!config.get()) { + LOG(ERROR) << "glXChooseFBConfig failed."; + return false; + } + if (!nelements) { + LOG(ERROR) << "glXChooseFBConfig returned 0 elements."; + return false; + } + + GLContextHandle shared_handle = NULL; + if (shared_context) + shared_handle = static_cast<GLContextHandle>(shared_context->GetHandle()); + + context_ = glXCreateNewContext(display, + config.get()[0], + GLX_RGBA_TYPE, + shared_handle, + True); + if (!context_) { + LOG(ERROR) << "glXCreateNewContext failed."; + return false; + } + static const int pbuffer_attributes[] = { + GLX_PBUFFER_WIDTH, + 1, + GLX_PBUFFER_HEIGHT, + 1, + 0 + }; + pbuffer_ = glXCreatePbuffer(display, + config.get()[0], pbuffer_attributes); + if (!pbuffer_) { + Destroy(); + LOG(ERROR) << "glXCreatePbuffer failed."; + return false; + } + + if (!MakeCurrent()) { + Destroy(); + LOG(ERROR) << "Couldn't make context current for initialization."; + return false; + } + + if (!InitializeCommon()) { + LOG(ERROR) << "GLContext::InitializeCommon failed."; + Destroy(); + return false; + } + + return true; +} + +void PbufferGLContext::Destroy() { + Display* display = GetXDisplayHelper(); + bool result = glXMakeCurrent(display, 0, 0); + // glXMakeCurrent isn't supposed to fail when unsetting the context, unless + // we have pending draws on an invalid window - which shouldn't be the case + // here. + DCHECK(result); + if (context_) { + glXDestroyContext(display, context_); + context_ = NULL; + } + + if (pbuffer_) { + glXDestroyPbuffer(display, pbuffer_); + pbuffer_ = 0; + } +} + +bool PbufferGLContext::MakeCurrent() { + if (IsCurrent()) { + return true; + } + Display* display = GetXDisplayHelper(); + if (glXMakeCurrent(display, pbuffer_, context_) != True) { + glXDestroyContext(display, context_); + context_ = NULL; + LOG(ERROR) << "Couldn't make context current."; + return false; + } + + return true; +} + +bool PbufferGLContext::IsCurrent() { + return glXGetCurrentDrawable() == pbuffer_ && + glXGetCurrentContext() == context_; +} + +bool PbufferGLContext::IsOffscreen() { + return true; +} + +bool PbufferGLContext::SwapBuffers() { + NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer."; + return false; +} + +gfx::Size PbufferGLContext::GetSize() { + NOTREACHED() << "Should not be requesting size of this pbuffer."; + return gfx::Size(1, 1); +} + +void* PbufferGLContext::GetHandle() { + return context_; +} + +void PbufferGLContext::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + NOTREACHED(); +} + +bool PixmapGLContext::Initialize(GLContext* shared_context) { + VLOG(1) << "GL context: using pixmaps."; + + static int attributes[] = { + GLX_RGBA, + 0 + }; + + Display* display = GetXDisplayHelper(); + int screen = DefaultScreen(display); + + scoped_ptr_malloc<XVisualInfo, ScopedPtrXFree> visual_info( + glXChooseVisual(display, screen, attributes)); + + if (!visual_info.get()) { + LOG(ERROR) << "glXChooseVisual failed."; + return false; + } + + GLContextHandle shared_handle = NULL; + if (shared_context) + shared_handle = static_cast<GLContextHandle>(shared_context->GetHandle()); + + context_ = glXCreateContext(display, visual_info.get(), shared_handle, True); + if (!context_) { + LOG(ERROR) << "glXCreateContext failed."; + return false; + } + + pixmap_ = XCreatePixmap(display, RootWindow(display, screen), 1, 1, + visual_info->depth); + if (!pixmap_) { + LOG(ERROR) << "XCreatePixmap failed."; + return false; + } + + glx_pixmap_ = glXCreateGLXPixmap(display, visual_info.get(), pixmap_); + if (!glx_pixmap_) { + LOG(ERROR) << "XCreatePixmap failed."; + return false; + } + + if (!MakeCurrent()) { + Destroy(); + LOG(ERROR) << "Couldn't make context current for initialization."; + return false; + } + + if (!InitializeCommon()) { + LOG(ERROR) << "GLContext::InitializeCommon failed."; + Destroy(); + return false; + } + + return true; +} + +void PixmapGLContext::Destroy() { + Display* display = GetXDisplayHelper(); + bool result = glXMakeCurrent(display, 0, 0); + // glXMakeCurrent isn't supposed to fail when unsetting the context, unless + // we have pending draws on an invalid window - which shouldn't be the case + // here. + DCHECK(result); + if (context_) { + glXDestroyContext(display, context_); + context_ = NULL; + } + + if (glx_pixmap_) { + glXDestroyGLXPixmap(display, glx_pixmap_); + glx_pixmap_ = 0; + } + + if (pixmap_) { + XFreePixmap(display, pixmap_); + pixmap_ = 0; + } +} + +bool PixmapGLContext::MakeCurrent() { + if (IsCurrent()) { + return true; + } + Display* display = GetXDisplayHelper(); + if (glXMakeCurrent(display, glx_pixmap_, context_) != True) { + glXDestroyContext(display, context_); + context_ = NULL; + LOG(ERROR) << "Couldn't make context current."; + return false; + } + + return true; +} + +bool PixmapGLContext::IsCurrent() { + return glXGetCurrentDrawable() == glx_pixmap_ && + glXGetCurrentContext() == context_; +} + +bool PixmapGLContext::IsOffscreen() { + return true; +} + +bool PixmapGLContext::SwapBuffers() { + NOTREACHED() << "Attempted to call SwapBuffers on a pixmap."; + return false; +} + +gfx::Size PixmapGLContext::GetSize() { + NOTREACHED() << "Should not be requesting size of this pixmap."; + return gfx::Size(1, 1); +} + +void* PixmapGLContext::GetHandle() { + return context_; +} + +void PixmapGLContext::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + NOTREACHED(); +} + +GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { + switch (GetGLImplementation()) { + case kGLImplementationDesktopGL: { + scoped_ptr<PbufferGLContext> context(new PbufferGLContext); + if (context->Initialize(shared_context)) + return context.release(); + + scoped_ptr<PixmapGLContext> context_pixmap(new PixmapGLContext); + if (context_pixmap->Initialize(shared_context)) + return context_pixmap.release(); + + return NULL; + } + case kGLImplementationEGLGLES2: { + scoped_ptr<SecondaryEGLContext> context( + new SecondaryEGLContext()); + if (!context->Initialize(shared_context)) + return NULL; + + return context.release(); + } + case kGLImplementationOSMesaGL: { + scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext); + if (!context->Initialize(OSMESA_RGBA, shared_context)) + return NULL; + + return context.release(); + } + case kGLImplementationMockGL: + return new StubGLContext; + default: + NOTREACHED(); + return NULL; + } +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_context_mac.cc b/ui/gfx/gl/gl_context_mac.cc new file mode 100644 index 0000000..10e8bf3 --- /dev/null +++ b/ui/gfx/gl/gl_context_mac.cc @@ -0,0 +1,209 @@ +// Copyright (c) 2011 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 ViewGLContext and PbufferGLContext classes. + +#include "ui/gfx/gl/gl_context.h" + +#include <GL/osmesa.h> +#include <OpenGL/OpenGL.h> + +#include "base/basictypes.h" +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_context_osmesa.h" +#include "ui/gfx/gl/gl_context_stub.h" +#include "ui/gfx/gl/gl_implementation.h" + +namespace gfx { + +typedef CGLContextObj GLContextHandle; +typedef CGLPBufferObj PbufferHandle; + +// This class is a wrapper around a GL context used for offscreen rendering. +// It is initially backed by a 1x1 pbuffer. Use it to create an FBO to do useful +// rendering. +class PbufferGLContext : public GLContext { + public: + PbufferGLContext() + : context_(NULL), + pbuffer_(NULL) { + } + + // Initializes the GL context. + bool Initialize(GLContext* shared_context); + + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval); + + private: + GLContextHandle context_; + PbufferHandle pbuffer_; + + DISALLOW_COPY_AND_ASSIGN(PbufferGLContext); +}; + +bool GLContext::InitializeOneOff() { + static bool initialized = false; + if (initialized) + return true; + + static const GLImplementation kAllowedGLImplementations[] = { + kGLImplementationDesktopGL, + kGLImplementationOSMesaGL + }; + + if (!InitializeRequestedGLBindings( + kAllowedGLImplementations, + kAllowedGLImplementations + arraysize(kAllowedGLImplementations), + kGLImplementationDesktopGL)) { + LOG(ERROR) << "InitializeRequestedGLBindings failed."; + return false; + } + + initialized = true; + return true; +} + +bool PbufferGLContext::Initialize(GLContext* shared_context) { + // Create a 1x1 pbuffer and associated context to bootstrap things. + static const CGLPixelFormatAttribute attribs[] = { + (CGLPixelFormatAttribute) kCGLPFAPBuffer, + (CGLPixelFormatAttribute) 0 + }; + CGLPixelFormatObj pixel_format; + GLint num_pixel_formats; + if (CGLChoosePixelFormat(attribs, + &pixel_format, + &num_pixel_formats) != kCGLNoError) { + LOG(ERROR) << "Error choosing pixel format."; + Destroy(); + return false; + } + if (!pixel_format) { + LOG(ERROR) << "pixel_format == 0."; + return false; + } + + GLContextHandle shared_handle = NULL; + if (shared_context) + shared_handle = static_cast<GLContextHandle>(shared_context->GetHandle()); + + CGLError res = CGLCreateContext(pixel_format, shared_handle, &context_); + CGLDestroyPixelFormat(pixel_format); + if (res != kCGLNoError) { + LOG(ERROR) << "Error creating context."; + Destroy(); + return false; + } + if (CGLCreatePBuffer(1, 1, + GL_TEXTURE_2D, GL_RGBA, + 0, &pbuffer_) != kCGLNoError) { + LOG(ERROR) << "Error creating pbuffer."; + Destroy(); + return false; + } + if (CGLSetPBuffer(context_, pbuffer_, 0, 0, 0) != kCGLNoError) { + LOG(ERROR) << "Error attaching pbuffer to context."; + Destroy(); + return false; + } + + if (!MakeCurrent()) { + Destroy(); + LOG(ERROR) << "Couldn't make context current for initialization."; + return false; + } + + if (!InitializeCommon()) { + LOG(ERROR) << "GLContext::InitializeCommon failed."; + Destroy(); + return false; + } + + return true; +} + +void PbufferGLContext::Destroy() { + if (context_) { + CGLDestroyContext(context_); + context_ = NULL; + } + + if (pbuffer_) { + CGLDestroyPBuffer(pbuffer_); + pbuffer_ = NULL; + } +} + +bool PbufferGLContext::MakeCurrent() { + if (!IsCurrent()) { + if (CGLSetCurrentContext(context_) != kCGLNoError) { + LOG(ERROR) << "Unable to make gl context current."; + return false; + } + } + + return true; +} + +bool PbufferGLContext::IsCurrent() { + return CGLGetCurrentContext() == context_; +} + +bool PbufferGLContext::IsOffscreen() { + return true; +} + +bool PbufferGLContext::SwapBuffers() { + NOTREACHED() << "Cannot call SwapBuffers on a PbufferGLContext."; + return false; +} + +gfx::Size PbufferGLContext::GetSize() { + NOTREACHED() << "Should not be requesting size of a PbufferGLContext."; + return gfx::Size(1, 1); +} + +void* PbufferGLContext::GetHandle() { + return context_; +} + +void PbufferGLContext::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + NOTREACHED() << "Attempt to call SetSwapInterval on a PbufferGLContext."; +} + +GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { + switch (GetGLImplementation()) { + case kGLImplementationDesktopGL: { + scoped_ptr<PbufferGLContext> context(new PbufferGLContext); + if (!context->Initialize(shared_context)) + return NULL; + + return context.release(); + } + case kGLImplementationOSMesaGL: { + scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext); + if (!context->Initialize(OSMESA_RGBA, shared_context)) + return NULL; + + return context.release(); + } + case kGLImplementationMockGL: + return new StubGLContext; + default: + NOTREACHED(); + return NULL; + } +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_context_osmesa.cc b/ui/gfx/gl/gl_context_osmesa.cc new file mode 100644 index 0000000..9d1e802 --- /dev/null +++ b/ui/gfx/gl/gl_context_osmesa.cc @@ -0,0 +1,131 @@ +// Copyright (c) 2011 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 <GL/osmesa.h> + +#include <algorithm> + +#include "base/logging.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_context_osmesa.h" + +namespace gfx { + +OSMesaGLContext::OSMesaGLContext() : context_(NULL) +{ +} + +OSMesaGLContext::~OSMesaGLContext() { +} + +bool OSMesaGLContext::Initialize(GLuint format, GLContext* shared_context) { + DCHECK(!context_); + + size_ = gfx::Size(1, 1); + buffer_.reset(new int32[1]); + + OSMesaContext shared_handle = NULL; + if (shared_context) + shared_handle = static_cast<OSMesaContext>(shared_context->GetHandle()); + + context_ = OSMesaCreateContextExt(format, + 24, // depth bits + 8, // stencil bits + 0, // accum bits + shared_handle); + if (!context_) { + LOG(ERROR) << "OSMesaCreateContextExt failed."; + return false; + } + + if (!MakeCurrent()) { + LOG(ERROR) << "MakeCurrent failed."; + Destroy(); + return false; + } + + // Row 0 is at the top. + OSMesaPixelStore(OSMESA_Y_UP, 0); + + if (!InitializeCommon()) { + LOG(ERROR) << "GLContext::InitializeCommon failed."; + Destroy(); + return false; + } + + return true; +} + +void OSMesaGLContext::Resize(const gfx::Size& new_size) { + if (new_size == size_) + return; + + // Allocate a new back buffer. + scoped_array<int32> new_buffer(new int32[new_size.GetArea()]); + memset(new_buffer.get(), 0, new_size.GetArea() * sizeof(new_buffer[0])); + + // Copy the current back buffer into the new buffer. + 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) { + new_buffer[y * new_size.width() + x] = buffer_[y * size_.width() + x]; + } + } + + buffer_.reset(new_buffer.release()); + size_ = new_size; + + // If this context is current, need to call MakeCurrent again so OSMesa uses + // the new buffer. + if (IsCurrent()) + MakeCurrent(); +} + +void OSMesaGLContext::Destroy() { + if (context_) { + OSMesaDestroyContext(static_cast<OSMesaContext>(context_)); + context_ = NULL; + } + buffer_.reset(); + size_ = gfx::Size(); +} + +bool OSMesaGLContext::MakeCurrent() { + DCHECK(context_); + return OSMesaMakeCurrent(static_cast<OSMesaContext>(context_), + buffer_.get(), + GL_UNSIGNED_BYTE, + size_.width(), size_.height()) == GL_TRUE; + return true; +} + +bool OSMesaGLContext::IsCurrent() { + DCHECK(context_); + return context_ == OSMesaGetCurrentContext(); +} + +bool OSMesaGLContext::IsOffscreen() { + return true; +} + +bool OSMesaGLContext::SwapBuffers() { + NOTREACHED() << "Should not call SwapBuffers on an OSMesaGLContext."; + return false; +} + +gfx::Size OSMesaGLContext::GetSize() { + return size_; +} + +void* OSMesaGLContext::GetHandle() { + return context_; +} + +void OSMesaGLContext::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + NOTREACHED() << "Attempt to call SetSwapInterval on an OSMesaGLContext."; +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_context_osmesa.h b/ui/gfx/gl/gl_context_osmesa.h new file mode 100644 index 0000000..77ca820 --- /dev/null +++ b/ui/gfx/gl/gl_context_osmesa.h @@ -0,0 +1,54 @@ +// Copyright (c) 2011 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_GFX_GL_GL_CONTEXT_OSMESA_H_ +#define UI_GFX_GL_GL_CONTEXT_OSMESA_H_ +#pragma once + +#include "base/memory/scoped_ptr.h" +#include "ui/gfx/gl/gl_context.h" +#include "ui/gfx/size.h" + +typedef struct osmesa_context *OSMesaContext; + +namespace gfx { + +// Encapsulates an OSMesa OpenGL context that uses software rendering. +class OSMesaGLContext : public GLContext { + public: + OSMesaGLContext(); + virtual ~OSMesaGLContext(); + + // Initialize an OSMesa GL context with the default 1 x 1 initial size. + bool Initialize(GLuint format, GLContext* shared_context); + + // Resize the back buffer, preserving the old content. Does nothing if the + // size is unchanged. + void Resize(const gfx::Size& new_size); + + const void* buffer() const { + return buffer_.get(); + } + + // Implement GLContext. + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval); + + private: + gfx::Size size_; + scoped_array<int32> buffer_; + OSMesaContext context_; + + DISALLOW_COPY_AND_ASSIGN(OSMesaGLContext); +}; + +} // namespace gfx + +#endif // UI_GFX_GL_GL_CONTEXT_OSMESA_H_ diff --git a/ui/gfx/gl/gl_context_stub.cc b/ui/gfx/gl/gl_context_stub.cc new file mode 100644 index 0000000..6462f61 --- /dev/null +++ b/ui/gfx/gl/gl_context_stub.cc @@ -0,0 +1,39 @@ +// Copyright (c) 2011 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/gfx/gl/gl_context_stub.h" + +namespace gfx { + +StubGLContext::~StubGLContext() {} + +bool StubGLContext::MakeCurrent() { + return true; +} + +bool StubGLContext::IsCurrent() { + return true; +} + +bool StubGLContext::IsOffscreen() { + return false; +} + +bool StubGLContext::SwapBuffers() { + return true; +} + +gfx::Size StubGLContext::GetSize() { + return size_; +} + +void* StubGLContext::GetHandle() { + return NULL; +} + +std::string StubGLContext::GetExtensions() { + return std::string(); +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_context_stub.h b/ui/gfx/gl/gl_context_stub.h new file mode 100644 index 0000000..03e5cf4 --- /dev/null +++ b/ui/gfx/gl/gl_context_stub.h @@ -0,0 +1,39 @@ +// Copyright (c) 2011 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 StubGLContext. + +#ifndef UI_GFX_GL_GL_CONTEXT_STUB_H_ +#define UI_GFX_GL_GL_CONTEXT_STUB_H_ +#pragma once + +#include "ui/gfx/gl/gl_context.h" + +namespace gfx { + +// A GLContext that does nothing for unit tests. +class StubGLContext : public gfx::GLContext { + public: + virtual ~StubGLContext(); + + void SetSize(const gfx::Size& size) { size_ = size; } + + // Implement GLContext. + virtual void Destroy() {} + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval) {} + virtual std::string GetExtensions(); + + private: + gfx::Size size_; +}; + +} // namespace gfx + +#endif // UI_GFX_GL_GL_CONTEXT_STUB_H_ diff --git a/ui/gfx/gl/gl_context_win.cc b/ui/gfx/gl/gl_context_win.cc new file mode 100644 index 0000000..23f98b2 --- /dev/null +++ b/ui/gfx/gl/gl_context_win.cc @@ -0,0 +1,743 @@ +// Copyright (c) 2011 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 NativeViewGLContext and PbufferGLContext classes. + +#include "ui/gfx/gl/gl_context.h" + +#include <GL/osmesa.h> + +#include <algorithm> + +#include "base/logging.h" +#include "base/memory/scoped_ptr.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_context_egl.h" +#include "ui/gfx/gl/gl_context_osmesa.h" +#include "ui/gfx/gl/gl_context_stub.h" +#include "ui/gfx/gl/gl_implementation.h" + +namespace gfx { + +typedef HGLRC GLContextHandle; +typedef HPBUFFERARB PbufferHandle; + +class BaseWinGLContext : public GLContext { + public: + virtual std::string GetExtensions(); + + virtual HDC GetDC() = 0; +}; + +// This class is a wrapper around a GL context that renders directly to a +// window. +class NativeViewGLContext : public BaseWinGLContext { + public: + explicit NativeViewGLContext(gfx::PluginWindowHandle window) + : window_(window), + device_context_(NULL), + context_(NULL) { + DCHECK(window); + } + + // Initializes the GL context. + bool Initialize(bool multisampled); + + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval); + + virtual HDC GetDC(); + + private: + gfx::PluginWindowHandle window_; + HDC device_context_; + GLContextHandle context_; + + DISALLOW_COPY_AND_ASSIGN(NativeViewGLContext); +}; + +// This class is a wrapper around a GL context that uses OSMesa to render +// to an offscreen buffer and then blits it to a window. +class OSMesaViewGLContext : public GLContext { + public: + explicit OSMesaViewGLContext(gfx::PluginWindowHandle window) + : window_(window), + device_context_(NULL) { + DCHECK(window); + } + + // Initializes the GL context. + bool Initialize(); + + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval); + + private: + void UpdateSize(); + + gfx::PluginWindowHandle window_; + HDC device_context_; + OSMesaGLContext osmesa_context_; + + DISALLOW_COPY_AND_ASSIGN(OSMesaViewGLContext); +}; + +// This class is a wrapper around a GL context used for offscreen rendering. +// It is initially backed by a 1x1 pbuffer. Use it to create an FBO to do useful +// rendering. +class PbufferGLContext : public GLContext { + public: + PbufferGLContext() + : context_(NULL), + device_context_(NULL), + pbuffer_(NULL) { + } + + // Initializes the GL context. + bool Initialize(GLContext* shared_context); + + virtual void Destroy(); + virtual bool MakeCurrent(); + virtual bool IsCurrent(); + virtual bool IsOffscreen(); + virtual bool SwapBuffers(); + virtual gfx::Size GetSize(); + virtual void* GetHandle(); + virtual void SetSwapInterval(int interval); + + virtual HDC GetDC(); + + private: + GLContextHandle context_; + HDC device_context_; + PbufferHandle pbuffer_; + + DISALLOW_COPY_AND_ASSIGN(PbufferGLContext); +}; + +static HWND g_window; +static int g_regular_pixel_format = 0; +static int g_multisampled_pixel_format = 0; + +// When using ANGLE we still need a window for D3D. This context creates the +// D3D device. +static BaseEGLContext* g_default_context; + +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. + 24, // 24 bit z-buffer size. + 8, // 8-bit 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) { + return ::DefWindowProc(window, message, w_param, l_param); +} + +// Helper routine that does one-off initialization like determining the +// pixel format and initializing the GL bindings. +bool GLContext::InitializeOneOff() { + static bool initialized = false; + if (initialized) + return true; + + static const GLImplementation kAllowedGLImplementations[] = { + kGLImplementationEGLGLES2, + kGLImplementationDesktopGL, + kGLImplementationOSMesaGL + }; + + if (!InitializeRequestedGLBindings( + kAllowedGLImplementations, + kAllowedGLImplementations + arraysize(kAllowedGLImplementations), + kGLImplementationEGLGLES2)) { + LOG(ERROR) << "InitializeRequestedGLBindings failed."; + return false; + } + + // We must initialize a GL context before we can determine the multi- + // sampling supported on the current hardware, so we create an intermediate + // window and context here. + HINSTANCE module_handle; + 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_HREDRAW | CS_VREDRAW | 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"; + + ATOM class_registration = ::RegisterClass(&intermediate_class); + if (!class_registration) { + LOG(ERROR) << "RegisterClass failed."; + return false; + } + + g_window = ::CreateWindow( + reinterpret_cast<wchar_t*>(class_registration), + L"", + WS_OVERLAPPEDWINDOW, + 0, 0, + 100, 100, + NULL, + NULL, + NULL, + NULL); + + if (!g_window) { + ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), + module_handle); + LOG(ERROR) << "CreateWindow failed."; + return false; + } + + // Early out if OSMesa offscreen renderer or EGL is present. + switch (GetGLImplementation()) { + case kGLImplementationDesktopGL: { + HDC intermediate_dc = ::GetDC(g_window); + g_regular_pixel_format = ::ChoosePixelFormat(intermediate_dc, + &kPixelFormatDescriptor); + if (g_regular_pixel_format == 0) { + LOG(ERROR) << "Unable to get the pixel format for GL context."; + ::ReleaseDC(g_window, intermediate_dc); + ::DestroyWindow(g_window); + ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), + module_handle); + return false; + } + if (!::SetPixelFormat(intermediate_dc, g_regular_pixel_format, + &kPixelFormatDescriptor)) { + LOG(ERROR) << "Unable to set the pixel format for GL context."; + ::ReleaseDC(g_window, intermediate_dc); + ::DestroyWindow(g_window); + ::UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), + module_handle); + return false; + } + + // Create a temporary GL context to query for multisampled pixel formats. + HGLRC gl_context = wglCreateContext(intermediate_dc); + if (wglMakeCurrent(intermediate_dc, gl_context)) { + // Get bindings to extension functions that cannot be acquired without a + // current context. + InitializeGLBindingsGL(); + InitializeGLBindingsWGL(); + + // If the multi-sample extensions are present, query the api to + // determine the pixel format. + if (wglGetExtensionsStringARB) { + std::string extensions = + std::string(wglGetExtensionsStringARB(intermediate_dc)); + extensions += std::string(" "); + if (extensions.find("WGL_ARB_pixel_format ")) { + int pixel_attributes[] = { + WGL_SAMPLES_ARB, 4, + WGL_DRAW_TO_WINDOW_ARB, GL_TRUE, + WGL_SUPPORT_OPENGL_ARB, GL_TRUE, + WGL_ACCELERATION_ARB, WGL_FULL_ACCELERATION_ARB, + WGL_COLOR_BITS_ARB, 24, + WGL_ALPHA_BITS_ARB, 8, + WGL_DEPTH_BITS_ARB, 24, + WGL_STENCIL_BITS_ARB, 8, + WGL_DOUBLE_BUFFER_ARB, GL_TRUE, + WGL_SAMPLE_BUFFERS_ARB, GL_TRUE, + 0, 0}; + + float pixel_attributes_f[] = {0, 0}; + unsigned int num_formats; + + // Query for the highest sampling rate supported, starting at 4x. + static const int kSampleCount[] = {4, 2}; + static const int kNumSamples = 2; + for (int sample = 0; sample < kNumSamples; ++sample) { + pixel_attributes[1] = kSampleCount[sample]; + if (wglChoosePixelFormatARB(intermediate_dc, + pixel_attributes, + pixel_attributes_f, + 1, + &g_multisampled_pixel_format, + &num_formats)) { + break; + } + } + } + } + } + + wglMakeCurrent(intermediate_dc, NULL); + wglDeleteContext(gl_context); + ReleaseDC(g_window, intermediate_dc); + UnregisterClass(reinterpret_cast<wchar_t*>(class_registration), + module_handle); + break; + } + case kGLImplementationEGLGLES2: + if (!BaseEGLContext::InitializeOneOff()) { + LOG(ERROR) << "BaseEGLContext::InitializeOneOff failed."; + return false; + } + break; + } + + initialized = true; + return true; +} + + +std::string BaseWinGLContext::GetExtensions() { + if (wglGetExtensionsStringARB) { + const char* extensions = wglGetExtensionsStringARB(GetDC()); + if (extensions) { + return GLContext::GetExtensions() + " " + extensions; + } + } + + return GLContext::GetExtensions(); +} + +bool NativeViewGLContext::Initialize(bool multisampled) { + // The GL context will render to this window. + device_context_ = ::GetDC(window_); + + int pixel_format = + multisampled ? g_multisampled_pixel_format : g_regular_pixel_format; + if (!SetPixelFormat(device_context_, + pixel_format, + &kPixelFormatDescriptor)) { + LOG(ERROR) << "Unable to set the pixel format for GL context."; + Destroy(); + return false; + } + + context_ = wglCreateContext(device_context_); + if (!context_) { + LOG(ERROR) << "Failed to create GL context."; + Destroy(); + return false; + } + + if (!MakeCurrent()) { + LOG(ERROR) << "MakeCurrent failed."; + Destroy(); + return false; + } + + if (!InitializeCommon()) { + LOG(ERROR) << "GLContext::InitializeCommon failed."; + Destroy(); + return false; + } + + return true; +} + +void NativeViewGLContext::Destroy() { + if (context_) { + wglDeleteContext(context_); + context_ = NULL; + } + + if (window_ && device_context_) + ReleaseDC(window_, device_context_); + + window_ = NULL; + device_context_ = NULL; +} + +bool NativeViewGLContext::MakeCurrent() { + if (IsCurrent()) { + return true; + } + if (!wglMakeCurrent(device_context_, context_)) { + LOG(ERROR) << "Unable to make gl context current."; + return false; + } + + return true; +} + +bool NativeViewGLContext::IsCurrent() { + return wglGetCurrentDC() == device_context_ && + wglGetCurrentContext() == context_; +} + +bool NativeViewGLContext::IsOffscreen() { + return false; +} + +bool NativeViewGLContext::SwapBuffers() { + DCHECK(device_context_); + return ::SwapBuffers(device_context_) == TRUE; +} + +gfx::Size NativeViewGLContext::GetSize() { + RECT rect; + CHECK(GetClientRect(window_, &rect)); + return gfx::Size(rect.right - rect.left, rect.bottom - rect.top); +} + +void* NativeViewGLContext::GetHandle() { + return context_; +} + +void NativeViewGLContext::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + if (HasExtension("WGL_EXT_swap_control") && wglSwapIntervalEXT) { + wglSwapIntervalEXT(interval); + } +} + +HDC NativeViewGLContext::GetDC() { + return device_context_; +} + +bool OSMesaViewGLContext::Initialize() { + // The GL context will render to this window. + device_context_ = GetDC(window_); + + if (!osmesa_context_.Initialize(OSMESA_RGBA, NULL)) { + LOG(ERROR) << "OSMesaGLContext::Initialize failed."; + Destroy(); + return false; + } + + UpdateSize(); + + return true; +} + +void OSMesaViewGLContext::Destroy() { + osmesa_context_.Destroy(); + + if (window_ && device_context_) + ReleaseDC(window_, device_context_); + + window_ = NULL; + device_context_ = NULL; +} + +bool OSMesaViewGLContext::MakeCurrent() { + // TODO(apatrick): This is a bit of a hack. The window might have had zero + // size when the context was initialized. Assume it has a valid size when + // MakeCurrent is called and resize the back buffer if necessary. + UpdateSize(); + return osmesa_context_.MakeCurrent(); +} + +bool OSMesaViewGLContext::IsCurrent() { + return osmesa_context_.IsCurrent(); +} + +bool OSMesaViewGLContext::IsOffscreen() { + return false; +} + +bool OSMesaViewGLContext::SwapBuffers() { + DCHECK(device_context_); + + // Update the size before blitting so that the blit size is exactly the same + // as the window. + UpdateSize(); + + gfx::Size size = osmesa_context_.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(), + osmesa_context_.buffer(), + reinterpret_cast<BITMAPINFO*>(&info), + DIB_RGB_COLORS, + SRCCOPY); + + return true; +} + +gfx::Size OSMesaViewGLContext::GetSize() { + return osmesa_context_.GetSize(); +} + +void* OSMesaViewGLContext::GetHandle() { + return osmesa_context_.GetHandle(); +} + +void OSMesaViewGLContext::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + // Fail silently. It is legitimate to set the swap interval on a view context + // but GDI does not have those semantics. +} + +void OSMesaViewGLContext::UpdateSize() { + // Change back buffer size to that of window. If window handle is invalid, do + // not change the back buffer size. + RECT rect; + if (!GetClientRect(window_, &rect)) + return; + + gfx::Size window_size = gfx::Size( + std::max(1, static_cast<int>(rect.right - rect.left)), + std::max(1, static_cast<int>(rect.bottom - rect.top))); + osmesa_context_.Resize(window_size); +} + +GLContext* GLContext::CreateViewGLContext(gfx::PluginWindowHandle window, + bool multisampled) { + switch (GetGLImplementation()) { + case kGLImplementationOSMesaGL: { + scoped_ptr<OSMesaViewGLContext> context(new OSMesaViewGLContext(window)); + if (!context->Initialize()) + return NULL; + + return context.release(); + } + case kGLImplementationEGLGLES2: { + scoped_ptr<NativeViewEGLContext> context( + new NativeViewEGLContext(window)); + if (!context->Initialize()) + return NULL; + + return context.release(); + } + case kGLImplementationDesktopGL: { + scoped_ptr<NativeViewGLContext> context(new NativeViewGLContext(window)); + if (!context->Initialize(multisampled)) + return NULL; + + return context.release(); + } + case kGLImplementationMockGL: + return new StubGLContext; + default: + NOTREACHED(); + return NULL; + } +} + +bool PbufferGLContext::Initialize(GLContext* shared_context) { + // Create a device context compatible with the primary display. + HDC display_device_context = ::CreateDC(L"DISPLAY", NULL, NULL, NULL); + + // Create a 1 x 1 pbuffer suitable for use with the device. This is just + // a stepping stone towards creating a frame buffer object. It doesn't + // matter what size it is. + if (!wglCreatePbufferARB) { + LOG(ERROR) << "wglCreatePbufferARB not available."; + Destroy(); + return false; + } + const int kNoAttributes[] = { 0 }; + pbuffer_ = wglCreatePbufferARB(display_device_context, + g_regular_pixel_format, + 1, 1, + kNoAttributes); + ::DeleteDC(display_device_context); + if (!pbuffer_) { + LOG(ERROR) << "Unable to create pbuffer."; + Destroy(); + return false; + } + + device_context_ = wglGetPbufferDCARB(pbuffer_); + if (!device_context_) { + LOG(ERROR) << "Unable to get pbuffer device context."; + Destroy(); + return false; + } + + context_ = wglCreateContext(device_context_); + if (!context_) { + LOG(ERROR) << "Failed to create GL context."; + Destroy(); + return false; + } + + if (shared_context) { + if (!wglShareLists( + static_cast<GLContextHandle>(shared_context->GetHandle()), context_)) { + LOG(ERROR) << "Could not share GL contexts."; + Destroy(); + return false; + } + } + + if (!MakeCurrent()) { + LOG(ERROR) << "MakeCurrent failed."; + Destroy(); + return false; + } + + if (!InitializeCommon()) { + LOG(ERROR) << "GLContext::InitializeCommon failed."; + Destroy(); + return false; + } + + return true; +} + +void PbufferGLContext::Destroy() { + if (context_) { + wglDeleteContext(context_); + context_ = NULL; + } + + if (pbuffer_ && device_context_) + wglReleasePbufferDCARB(pbuffer_, device_context_); + + device_context_ = NULL; + + if (pbuffer_) { + wglDestroyPbufferARB(pbuffer_); + pbuffer_ = NULL; + } +} + +bool PbufferGLContext::MakeCurrent() { + if (IsCurrent()) { + return true; + } + if (!wglMakeCurrent(device_context_, context_)) { + LOG(ERROR) << "Unable to make gl context current."; + return false; + } + + return true; +} + +bool PbufferGLContext::IsCurrent() { + return wglGetCurrentDC() == device_context_ && + wglGetCurrentContext() == context_; +} + +bool PbufferGLContext::IsOffscreen() { + return true; +} + +bool PbufferGLContext::SwapBuffers() { + NOTREACHED() << "Attempted to call SwapBuffers on a pbuffer."; + return false; +} + +gfx::Size PbufferGLContext::GetSize() { + NOTREACHED() << "Should not be requesting size of this pbuffer."; + return gfx::Size(1, 1); +} + +void* PbufferGLContext::GetHandle() { + return context_; +} + +void PbufferGLContext::SetSwapInterval(int interval) { + DCHECK(IsCurrent()); + NOTREACHED() << "Attempt to call SetSwapInterval on a PbufferGLContext."; +} + +HDC PbufferGLContext::GetDC() { + return device_context_; +} + +GLContext* GLContext::CreateOffscreenGLContext(GLContext* shared_context) { + switch (GetGLImplementation()) { + case kGLImplementationOSMesaGL: { + scoped_ptr<OSMesaGLContext> context(new OSMesaGLContext); + if (!context->Initialize(OSMESA_RGBA, shared_context)) + return NULL; + + return context.release(); + } + case kGLImplementationEGLGLES2: { + if (!shared_context) { + if (!g_default_context) { + scoped_ptr<NativeViewEGLContext> default_context( + new NativeViewEGLContext(g_window)); + if (!default_context->Initialize()) + return NULL; + + g_default_context = default_context.release(); + } + shared_context = g_default_context; + } + + scoped_ptr<SecondaryEGLContext> context( + new SecondaryEGLContext()); + if (!context->Initialize(shared_context)) + return NULL; + + return context.release(); + } + case kGLImplementationDesktopGL: { + scoped_ptr<PbufferGLContext> context(new PbufferGLContext); + if (!context->Initialize(shared_context)) + return NULL; + + return context.release(); + } + case kGLImplementationMockGL: + return new StubGLContext; + default: + NOTREACHED(); + return NULL; + } +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_implementation.cc b/ui/gfx/gl/gl_implementation.cc new file mode 100644 index 0000000..b38b2647 --- /dev/null +++ b/ui/gfx/gl/gl_implementation.cc @@ -0,0 +1,147 @@ +// Copyright (c) 2011 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/gfx/gl/gl_implementation.h" + +#include <algorithm> +#include <string> + +#include "base/at_exit.h" +#include "base/command_line.h" +#include "base/logging.h" +#include "ui/gfx/gl/gl_switches.h" + +namespace gfx { + +const char kGLImplementationDesktopName[] = "desktop"; +const char kGLImplementationOSMesaName[] = "osmesa"; +const char kGLImplementationEGLName[] = "egl"; +const char kGLImplementationMockName[] = "mock"; + +namespace { + +const struct { + const char* name; + GLImplementation implementation; +} kGLImplementationNamePairs[] = { + { kGLImplementationDesktopName, kGLImplementationDesktopGL }, + { kGLImplementationOSMesaName, kGLImplementationOSMesaGL }, + { 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; + } +} +} + +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"; +} + +bool InitializeRequestedGLBindings( + const GLImplementation* allowed_implementations_begin, + const GLImplementation* allowed_implementations_end, + GLImplementation default_implementation) { + if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUseGL)) { + std::string requested_implementation_name = + CommandLine::ForCurrentProcess()->GetSwitchValueASCII(switches::kUseGL); + GLImplementation requested_implementation = + GetNamedGLImplementation(requested_implementation_name); + if (std::find(allowed_implementations_begin, + allowed_implementations_end, + requested_implementation) == allowed_implementations_end) { + LOG(ERROR) << "Requested GL implementation is not available."; + return false; + } + + InitializeGLBindings(requested_implementation); + } else { + InitializeGLBindings(default_implementation); + } + + if (GetGLImplementation() == kGLImplementationNone) { + LOG(ERROR) << "Could not initialize GL."; + return false; + } else { + LOG(INFO) << "Using " + << GetGLImplementationName(GetGLImplementation()) + << " GL implementation."; + return true; + } +} + +void SetGLImplementation(GLImplementation implementation) { + g_gl_implementation = implementation; +} + +GLImplementation GetGLImplementation() { + return 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 SetGLGetProcAddressProc(GLGetProcAddressProc proc) { + DCHECK(proc); + g_get_proc_address = proc; +} + +void* GetGLProcAddress(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 (g_get_proc_address) { + void* proc = g_get_proc_address(name); + if (proc) + return proc; + } + + return NULL; +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_implementation.h b/ui/gfx/gl/gl_implementation.h new file mode 100644 index 0000000..f357b31 --- /dev/null +++ b/ui/gfx/gl/gl_implementation.h @@ -0,0 +1,74 @@ +// Copyright (c) 2011 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_GFX_GL_GL_IMPLEMENTATION_H_ +#define UI_GFX_GL_GL_IMPLEMENTATION_H_ +#pragma once + +#include <string> + +#include "base/native_library.h" +#include "build/build_config.h" + +namespace gfx { + +// The GL implementation currently in use. +enum GLImplementation { + kGLImplementationNone, + kGLImplementationDesktopGL, + kGLImplementationOSMesaGL, + kGLImplementationEGLGLES2, + kGLImplementationMockGL +}; + +// The GL implementation names that can be passed to --use-gl. +extern const char kGLImplementationDesktopName[]; +extern const char kGLImplementationOSMesaName[]; +extern const char kGLImplementationEGLName[]; +extern const char kGLImplementationMockName[]; + +#if defined(OS_WIN) +typedef void* (WINAPI *GLGetProcAddressProc)(const char* name); +#else +typedef void* (*GLGetProcAddressProc)(const char* name); +#endif + +// Initialize a particular GL implementation. +bool InitializeGLBindings(GLImplementation implementation); + +// Initialize Debug logging wrappers for GL bindings. +void InitializeDebugGLBindings(); + +// Set the current GL implementation. +void SetGLImplementation(GLImplementation implementation); + +// Get the current GL implementation. +GLImplementation GetGLImplementation(); + +// Get the GL implementation with a given name. +GLImplementation GetNamedGLImplementation(const std::wstring& name); + +// Get the name of a GL implementation. +const char* GetGLImplementationName(GLImplementation implementation); + +// Initialize the preferred GL binding from the given list. The preferred GL +// bindings depend on command line switches passed by the user and which GL +// implementation is the default on a given platform. +bool InitializeRequestedGLBindings( + const GLImplementation* allowed_implementations_begin, + const GLImplementation* allowed_implementations_end, + GLImplementation default_implementation); + +// Add a native library to those searched for GL entry points. +void AddGLNativeLibrary(base::NativeLibrary library); + +// Set an additional function that will be called to find GL entry points. +void SetGLGetProcAddressProc(GLGetProcAddressProc proc); + +// Find an entry point in the current GL implementation. +void* GetGLProcAddress(const char* name); + +} // namespace gfx + +#endif // UI_GFX_GL_GL_IMPLEMENTATION_H_ diff --git a/ui/gfx/gl/gl_implementation_linux.cc b/ui/gfx/gl/gl_implementation_linux.cc new file mode 100644 index 0000000..34069cf --- /dev/null +++ b/ui/gfx/gl/gl_implementation_linux.cc @@ -0,0 +1,160 @@ +// Copyright (c) 2011 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 "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_implementation.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)); +} + +} // namespace anonymous + +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 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("libosmesa.so")); + if (!library) { + VLOG(1) << "libosmesa.so not found"; + 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 = base::LoadNativeLibrary( + FilePath("libGL.so.1")); + if (!library) { + VLOG(1) << "libGL.so.1 not found."; + 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 = base::LoadNativeLibrary( + FilePath("libGLESv2.so")); + if (!gles_library) { + VLOG(1) << "libGLESv2.so not found"; + return false; + } + + base::NativeLibrary egl_library = base::LoadNativeLibrary( + FilePath("libEGL.so")); + if (!egl_library) { + VLOG(1) << "libEGL.so not found"; + 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; +} + +void InitializeDebugGLBindings() { + InitializeDebugGLBindingsEGL(); + InitializeDebugGLBindingsGL(); + InitializeDebugGLBindingsGLX(); + InitializeDebugGLBindingsOSMESA(); +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_implementation_mac.cc b/ui/gfx/gl/gl_implementation_mac.cc new file mode 100644 index 0000000..00ed6bb --- /dev/null +++ b/ui/gfx/gl/gl_implementation_mac.cc @@ -0,0 +1,92 @@ +// Copyright (c) 2011 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/native_library.h" +#include "base/path_service.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_implementation.h" + +namespace gfx { +namespace { +const char kOpenGLFrameworkPath[] = + "/System/Library/Frameworks/OpenGL.framework/Versions/Current/OpenGL"; +} // namespace anonymous + +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 kGLImplementationOSMesaGL: { + FilePath module_path; + if (!PathService::Get(base::DIR_MODULE, &module_path)) { + LOG(ERROR) << "PathService::Get failed."; + return false; + } + + // When using OSMesa, just use OSMesaGetProcAddress to find entry points. + base::NativeLibrary library = base::LoadNativeLibrary( + module_path.Append("osmesa.so")); + if (!library) { + VLOG(1) << "osmesa.so not found"; + 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 = base::LoadNativeLibrary( + FilePath(kOpenGLFrameworkPath)); + if (!library) { + LOG(ERROR) << "OpenGL framework not found"; + return false; + } + + AddGLNativeLibrary(library); + SetGLImplementation(kGLImplementationDesktopGL); + + InitializeGLBindingsGL(); + break; + } + case kGLImplementationMockGL: { + SetGLGetProcAddressProc(GetMockGLProcAddress); + SetGLImplementation(kGLImplementationMockGL); + InitializeGLBindingsGL(); + break; + } + default: + return false; + } + + return true; +} + +void InitializeDebugGLBindings() { + InitializeDebugGLBindingsGL(); + InitializeDebugGLBindingsOSMESA(); +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_implementation_win.cc b/ui/gfx/gl/gl_implementation_win.cc new file mode 100644 index 0000000..ee07cfc --- /dev/null +++ b/ui/gfx/gl/gl_implementation_win.cc @@ -0,0 +1,168 @@ +// Copyright (c) 2011 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/file_path.h" +#include "base/logging.h" +#include "base/native_library.h" +#include "base/path_service.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/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)); +} + +} // namespace anonymous + +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 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")); + if (!library) { + VLOG(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; + + // 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. + base::NativeLibrary gles_library = base::LoadNativeLibrary( + module_path.Append(L"libglesv2.dll")); + if (!gles_library) { + VLOG(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( + module_path.Append(L"libegl.dll")); + if (!egl_library) { + VLOG(1) << "libegl.dll not found."; + 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 kGLImplementationDesktopGL: { + // When using Windows OpenGL, first try wglGetProcAddress and then + // Windows GetProcAddress. + base::NativeLibrary library = base::LoadNativeLibrary( + FilePath(L"opengl32.dll")); + if (!library) { + VLOG(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; +} + +void InitializeDebugGLBindings() { + InitializeDebugGLBindingsEGL(); + InitializeDebugGLBindingsGL(); + InitializeDebugGLBindingsOSMESA(); + InitializeDebugGLBindingsWGL(); +} + +} // namespace gfx diff --git a/ui/gfx/gl/gl_interface.cc b/ui/gfx/gl/gl_interface.cc new file mode 100644 index 0000000..a671973 --- /dev/null +++ b/ui/gfx/gl/gl_interface.cc @@ -0,0 +1,20 @@ +// Copyright (c) 2011 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/gfx/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/gfx/gl/gl_interface.h b/ui/gfx/gl/gl_interface.h new file mode 100644 index 0000000..bbd2b63 --- /dev/null +++ b/ui/gfx/gl/gl_interface.h @@ -0,0 +1,436 @@ +// Copyright (c) 2011 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 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. + +#ifndef UI_GFX_GL_GL_INTERFACE_H_ +#define UI_GFX_GL_GL_INTERFACE_H_ +#pragma once + +#include "ui/gfx/gl/gl_bindings.h" + +namespace gfx { + +class 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 BindAttribLocation( + GLuint program, GLuint index, const char* name) = 0; + + virtual void BindBuffer(GLenum target, GLuint buffer) = 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 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 DrawElements( + GLenum mode, GLsizei count, GLenum type, const void* indices) = 0; + + virtual void Enable(GLenum cap) = 0; + + virtual void EnableVertexAttribArray(GLuint index) = 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 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 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 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 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 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 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; + + private: + static GLInterface* interface_; +}; + +} // namespace gfx + +#endif // UI_GFX_GL_GL_INTERFACE_H_ diff --git a/ui/gfx/surface/accelerated_surface_mac.cc b/ui/gfx/surface/accelerated_surface_mac.cc index 59919f8..4007c03 100644 --- a/ui/gfx/surface/accelerated_surface_mac.cc +++ b/ui/gfx/surface/accelerated_surface_mac.cc @@ -4,10 +4,10 @@ #include "ui/gfx/surface/accelerated_surface_mac.h" -#include "app/gfx/gl/gl_bindings.h" -#include "app/gfx/gl/gl_implementation.h" #include "base/logging.h" #include "base/mac/scoped_cftyperef.h" +#include "ui/gfx/gl/gl_bindings.h" +#include "ui/gfx/gl/gl_implementation.h" #include "ui/gfx/rect.h" #include "ui/gfx/surface/io_surface_support_mac.h" diff --git a/ui/gfx/surface/accelerated_surface_mac.h b/ui/gfx/surface/accelerated_surface_mac.h index 004f49a..8491091 100644 --- a/ui/gfx/surface/accelerated_surface_mac.h +++ b/ui/gfx/surface/accelerated_surface_mac.h @@ -8,12 +8,12 @@ #include <CoreFoundation/CoreFoundation.h> -#include "app/gfx/gl/gl_context.h" #include "base/callback.h" #include "base/mac/scoped_cftyperef.h" #include "base/memory/scoped_ptr.h" #include "ui/gfx/rect.h" #include "ui/gfx/size.h" +#include "ui/gfx/gl/gl_context.h" #include "ui/gfx/surface/transport_dib.h" // Should not include GL headers in a header file. Forward declare these types diff --git a/ui/gfx/surface/surface.gyp b/ui/gfx/surface/surface.gyp index c7d1dca..0cbfe94 100644 --- a/ui/gfx/surface/surface.gyp +++ b/ui/gfx/surface/surface.gyp @@ -38,8 +38,8 @@ 'msvs_guid': '6C99567D-6F02-43B5-BB35-D8E3F8D0D6D2', 'dependencies': [ '<(DEPTH)/base/base.gyp:base', - '<(DEPTH)/app/app.gyp:app_base', '<(DEPTH)/skia/skia.gyp:skia', + '<(DEPTH)/ui/gfx/gl/gl.gyp:gl', '<(DEPTH)/ui/ui.gyp:ui_gfx', ], 'sources': [ diff --git a/ui/ui_gfx.gypi b/ui/ui_gfx.gypi index 4e6d2ee..0fffbec 100644 --- a/ui/ui_gfx.gypi +++ b/ui/ui_gfx.gypi @@ -76,8 +76,6 @@ 'gfx/gfx_paths.h', 'gfx/gfx_module.cc', 'gfx/gfx_module.h', - 'gfx/gl/gl_switches.cc', - 'gfx/gl/gl_switches.h', 'gfx/image.cc', 'gfx/image.h', 'gfx/image_mac.mm', |