Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/python | 1 #!/usr/bin/python |
| 2 # | 2 # |
| 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| 4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
| 5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
| 6 | 6 |
| 7 """code generator for GL/GLES extension wrangler.""" | 7 """code generator for GL/GLES extension wrangler.""" |
| 8 | 8 |
| 9 import os | 9 import os |
| 10 import collections | |
| 10 import re | 11 import re |
| 11 import sys | 12 import sys |
| 12 | 13 |
| 13 GL_FUNCTIONS = [ | 14 GL_FUNCTIONS = [ |
| 14 ['void', ['glActiveTexture'], 'GLenum texture'], | 15 ['void', ['glActiveTexture'], 'GLenum texture'], |
| 15 ['void', ['glAttachShader'], 'GLuint program, GLuint shader'], | 16 ['void', ['glAttachShader'], 'GLuint program, GLuint shader'], |
| 16 ['void', ['glBeginQuery'], 'GLenum target, GLuint id'], | 17 ['void', ['glBeginQuery'], 'GLenum target, GLuint id'], |
| 17 ['void', ['glBindAttribLocation'], | 18 ['void', ['glBindAttribLocation'], |
| 18 'GLuint program, GLuint index, const char* name'], | 19 'GLuint program, GLuint index, const char* name'], |
| 19 ['void', ['glBindBuffer'], 'GLenum target, GLuint buffer'], | 20 ['void', ['glBindBuffer'], 'GLenum target, GLuint buffer'], |
| 20 ['void', ['glBindFragDataLocation'], | 21 ['void', ['glBindFragDataLocation'], |
| 21 'GLuint program, GLuint colorNumber, const char* name'], | 22 'GLuint program, GLuint colorNumber, const char* name'], |
| 22 ['void', ['glBindFragDataLocationIndexedARB'], | 23 ['void', ['glBindFragDataLocationIndexed'], |
| 23 'GLuint program, GLuint colorNumber, GLuint index, const char* name'], | 24 'GLuint program, GLuint colorNumber, GLuint index, const char* name'], |
| 24 ['void', ['glBindFramebufferEXT', 'glBindFramebuffer'], | 25 ['void', ['glBindFramebufferEXT', 'glBindFramebuffer'], |
| 25 'GLenum target, GLuint framebuffer'], | 26 'GLenum target, GLuint framebuffer'], |
| 26 ['void', ['glBindRenderbufferEXT', 'glBindRenderbuffer'], | 27 ['void', ['glBindRenderbufferEXT', 'glBindRenderbuffer'], |
| 27 'GLenum target, GLuint renderbuffer'], | 28 'GLenum target, GLuint renderbuffer'], |
| 28 ['void', ['glBindTexture'], 'GLenum target, GLuint texture'], | 29 ['void', ['glBindTexture'], 'GLenum target, GLuint texture'], |
| 29 ['void', ['glBlendColor'], | 30 ['void', ['glBlendColor'], |
| 30 'GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha'], | 31 'GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha'], |
| 31 ['void', ['glBlendEquation'], ' GLenum mode '], | 32 ['void', ['glBlendEquation'], ' GLenum mode '], |
| 32 ['void', ['glBlendEquationSeparate'], 'GLenum modeRGB, GLenum modeAlpha'], | 33 ['void', ['glBlendEquationSeparate'], 'GLenum modeRGB, GLenum modeAlpha'], |
| 33 ['void', ['glBlendFunc'], 'GLenum sfactor, GLenum dfactor'], | 34 ['void', ['glBlendFunc'], 'GLenum sfactor, GLenum dfactor'], |
| 34 ['void', ['glBlendFuncSeparate'], | 35 ['void', ['glBlendFuncSeparate'], |
| 35 'GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha'], | 36 'GLenum srcRGB, GLenum dstRGB, GLenum srcAlpha, GLenum dstAlpha'], |
| 36 ['void', ['glBlitFramebufferEXT', 'BlitFramebuffer'], | 37 ['void', ['glBlitFramebufferEXT', 'glBlitFramebuffer'], |
| 37 'GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, ' | 38 'GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, ' |
| 38 'GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, ' | 39 'GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, ' |
| 39 'GLbitfield mask, GLenum filter'], | 40 'GLbitfield mask, GLenum filter'], |
| 40 ['void', ['glBlitFramebufferANGLE', 'BlitFramebuffer'], | 41 ['void', ['glBlitFramebufferANGLE', 'glBlitFramebuffer'], |
| 41 'GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, ' | 42 'GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, ' |
| 42 'GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, ' | 43 'GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, ' |
| 43 'GLbitfield mask, GLenum filter'], | 44 'GLbitfield mask, GLenum filter'], |
| 44 ['void', ['glBufferData'], | 45 ['void', ['glBufferData'], |
| 45 'GLenum target, GLsizei size, const void* data, GLenum usage'], | 46 'GLenum target, GLsizei size, const void* data, GLenum usage'], |
| 46 ['void', ['glBufferSubData'], | 47 ['void', ['glBufferSubData'], |
| 47 'GLenum target, GLint offset, GLsizei size, const void* data'], | 48 'GLenum target, GLint offset, GLsizei size, const void* data'], |
| 48 ['GLenum', ['glCheckFramebufferStatusEXT', | 49 ['GLenum', ['glCheckFramebufferStatusEXT', |
| 49 'glCheckFramebufferStatus'], 'GLenum target'], | 50 'glCheckFramebufferStatus'], 'GLenum target'], |
| 50 ['void', ['glClear'], 'GLbitfield mask'], | 51 ['void', ['glClear'], 'GLbitfield mask'], |
| (...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 174 ['GLboolean', ['glIsEnabled'], 'GLenum cap'], | 175 ['GLboolean', ['glIsEnabled'], 'GLenum cap'], |
| 175 ['GLboolean', ['glIsFramebufferEXT', 'glIsFramebuffer'], | 176 ['GLboolean', ['glIsFramebufferEXT', 'glIsFramebuffer'], |
| 176 'GLuint framebuffer'], | 177 'GLuint framebuffer'], |
| 177 ['GLboolean', ['glIsProgram'], 'GLuint program'], | 178 ['GLboolean', ['glIsProgram'], 'GLuint program'], |
| 178 ['GLboolean', ['glIsRenderbufferEXT', 'glIsRenderbuffer'], | 179 ['GLboolean', ['glIsRenderbufferEXT', 'glIsRenderbuffer'], |
| 179 'GLuint renderbuffer'], | 180 'GLuint renderbuffer'], |
| 180 ['GLboolean', ['glIsShader'], 'GLuint shader'], | 181 ['GLboolean', ['glIsShader'], 'GLuint shader'], |
| 181 ['GLboolean', ['glIsTexture'], 'GLuint texture'], | 182 ['GLboolean', ['glIsTexture'], 'GLuint texture'], |
| 182 ['void', ['glLineWidth'], 'GLfloat width'], | 183 ['void', ['glLineWidth'], 'GLfloat width'], |
| 183 ['void', ['glLinkProgram'], 'GLuint program'], | 184 ['void', ['glLinkProgram'], 'GLuint program'], |
| 184 ['void*', ['glMapBuffer'], 'GLenum target, GLenum access'], | 185 ['void*', ['glMapBuffer', 'glMapBufferOES'], 'GLenum target, GLenum access'], |
| 185 ['void', ['glPixelStorei'], 'GLenum pname, GLint param'], | 186 ['void', ['glPixelStorei'], 'GLenum pname, GLint param'], |
| 186 ['void', ['glPolygonOffset'], 'GLfloat factor, GLfloat units'], | 187 ['void', ['glPolygonOffset'], 'GLfloat factor, GLfloat units'], |
| 187 ['void', ['glQueryCounter'], 'GLuint id, GLenum target'], | 188 ['void', ['glQueryCounter'], 'GLuint id, GLenum target'], |
| 188 ['void', ['glReadBuffer'], 'GLenum src'], | 189 ['void', ['glReadBuffer'], 'GLenum src'], |
| 189 ['void', ['glReadPixels'], | 190 ['void', ['glReadPixels'], |
| 190 'GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, ' | 191 'GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, ' |
| 191 'GLenum type, void* pixels'], | 192 'GLenum type, void* pixels'], |
| 192 ['void', ['glReleaseShaderCompiler'], 'void'], | 193 ['void', ['glReleaseShaderCompiler'], 'void'], |
| 193 ['void', ['glRenderbufferStorageMultisampleEXT', | 194 ['void', ['glRenderbufferStorageMultisampleEXT', |
| 194 'glRenderbufferStorageMultisample'], | 195 'glRenderbufferStorageMultisample'], |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 244 'GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w'], | 245 'GLint location, GLfloat x, GLfloat y, GLfloat z, GLfloat w'], |
| 245 ['void', ['glUniform4fv'], 'GLint location, GLsizei count, const GLfloat* v'], | 246 ['void', ['glUniform4fv'], 'GLint location, GLsizei count, const GLfloat* v'], |
| 246 ['void', ['glUniform4i'], 'GLint location, GLint x, GLint y, GLint z, GLint w'], | 247 ['void', ['glUniform4i'], 'GLint location, GLint x, GLint y, GLint z, GLint w'], |
| 247 ['void', ['glUniform4iv'], 'GLint location, GLsizei count, const GLint* v'], | 248 ['void', ['glUniform4iv'], 'GLint location, GLsizei count, const GLint* v'], |
| 248 ['void', ['glUniformMatrix2fv'], | 249 ['void', ['glUniformMatrix2fv'], |
| 249 'GLint location, GLsizei count, GLboolean transpose, const GLfloat* value'], | 250 'GLint location, GLsizei count, GLboolean transpose, const GLfloat* value'], |
| 250 ['void', ['glUniformMatrix3fv'], | 251 ['void', ['glUniformMatrix3fv'], |
| 251 'GLint location, GLsizei count, GLboolean transpose, const GLfloat* value'], | 252 'GLint location, GLsizei count, GLboolean transpose, const GLfloat* value'], |
| 252 ['void', ['glUniformMatrix4fv'], | 253 ['void', ['glUniformMatrix4fv'], |
| 253 'GLint location, GLsizei count, GLboolean transpose, const GLfloat* value'], | 254 'GLint location, GLsizei count, GLboolean transpose, const GLfloat* value'], |
| 254 ['GLboolean', ['glUnmapBuffer'], 'GLenum target'], | 255 ['GLboolean', ['glUnmapBuffer', 'glUnmapBufferOES'], 'GLenum target'], |
| 255 ['void', ['glUseProgram'], 'GLuint program'], | 256 ['void', ['glUseProgram'], 'GLuint program'], |
| 256 ['void', ['glValidateProgram'], 'GLuint program'], | 257 ['void', ['glValidateProgram'], 'GLuint program'], |
| 257 ['void', ['glVertexAttrib1f'], 'GLuint indx, GLfloat x'], | 258 ['void', ['glVertexAttrib1f'], 'GLuint indx, GLfloat x'], |
| 258 ['void', ['glVertexAttrib1fv'], 'GLuint indx, const GLfloat* values'], | 259 ['void', ['glVertexAttrib1fv'], 'GLuint indx, const GLfloat* values'], |
| 259 ['void', ['glVertexAttrib2f'], 'GLuint indx, GLfloat x, GLfloat y'], | 260 ['void', ['glVertexAttrib2f'], 'GLuint indx, GLfloat x, GLfloat y'], |
| 260 ['void', ['glVertexAttrib2fv'], 'GLuint indx, const GLfloat* values'], | 261 ['void', ['glVertexAttrib2fv'], 'GLuint indx, const GLfloat* values'], |
| 261 ['void', ['glVertexAttrib3f'], 'GLuint indx, GLfloat x, GLfloat y, GLfloat z'], | 262 ['void', ['glVertexAttrib3f'], 'GLuint indx, GLfloat x, GLfloat y, GLfloat z'], |
| 262 ['void', ['glVertexAttrib3fv'], 'GLuint indx, const GLfloat* values'], | 263 ['void', ['glVertexAttrib3fv'], 'GLuint indx, const GLfloat* values'], |
| 263 ['void', ['glVertexAttrib4f'], | 264 ['void', ['glVertexAttrib4f'], |
| 264 'GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w'], | 265 'GLuint indx, GLfloat x, GLfloat y, GLfloat z, GLfloat w'], |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 456 ['void', ['glXSwapIntervalEXT'], | 457 ['void', ['glXSwapIntervalEXT'], |
| 457 'Display* dpy, GLXDrawable drawable, int interval'], | 458 'Display* dpy, GLXDrawable drawable, int interval'], |
| 458 ['GLXFBConfig', ['glXGetFBConfigFromVisualSGIX'], | 459 ['GLXFBConfig', ['glXGetFBConfigFromVisualSGIX'], |
| 459 'Display* dpy, XVisualInfo* visualInfo'], | 460 'Display* dpy, XVisualInfo* visualInfo'], |
| 460 ['GLXContext', ['glXCreateContextAttribsARB'], | 461 ['GLXContext', ['glXCreateContextAttribsARB'], |
| 461 'Display* dpy, GLXFBConfig config, GLXContext share_context, int direct, ' | 462 'Display* dpy, GLXFBConfig config, GLXContext share_context, int direct, ' |
| 462 'const int* attrib_list'], | 463 'const int* attrib_list'], |
| 463 ] | 464 ] |
| 464 | 465 |
| 465 FUNCTION_SETS = [ | 466 FUNCTION_SETS = [ |
| 466 [GL_FUNCTIONS, 'gl'], | 467 [GL_FUNCTIONS, 'gl', ['../../../third_party/mesa/MesaLib/include/GL/glext.h', |
| 467 [OSMESA_FUNCTIONS, 'osmesa'], | 468 '../../../gpu/GLES2/gl2ext.h']], |
| 468 [EGL_FUNCTIONS, 'egl'], | 469 [OSMESA_FUNCTIONS, 'osmesa', []], |
| 469 [WGL_FUNCTIONS, 'wgl'], | 470 [EGL_FUNCTIONS, 'egl', ['../../../gpu/EGL/eglext.h']], |
| 470 [GLX_FUNCTIONS, 'glx'], | 471 [WGL_FUNCTIONS, 'wgl', [ |
| 472 '../../../third_party/mesa/MesaLib/include/GL/wglext.h']], | |
| 473 [GLX_FUNCTIONS, 'glx', [ | |
| 474 '../../../third_party/mesa/MesaLib/include/GL/glxext.h']], | |
| 471 ] | 475 ] |
| 472 | 476 |
| 473 def GenerateHeader(file, functions, set_name): | 477 def GenerateHeader(file, functions, set_name): |
| 474 """Generates gl_binding_autogen_x.h""" | 478 """Generates gl_binding_autogen_x.h""" |
| 475 | 479 |
| 476 # Write file header. | 480 # Write file header. |
| 477 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n ') | 481 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n ') |
| 478 file.write('// Use of this source code is governed by a BSD-style license that can be\n') | 482 file.write('// Use of this source code is governed by a BSD-style license that can be\n') |
| 479 file.write('// found in the LICENSE file.\n') | 483 file.write('// found in the LICENSE file.\n') |
| 480 file.write('\n') | 484 file.write('\n') |
| 481 file.write('// This file is automatically generated.\n') | 485 file.write('// This file is automatically generated.\n') |
| 482 file.write('\n') | 486 file.write('\n') |
| 483 file.write('#ifndef UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % set_name.upper()) | 487 file.write('#ifndef UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % set_name.upper()) |
| 484 file.write('#define UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % set_name.upper()) | 488 file.write('#define UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % set_name.upper()) |
| 485 | 489 |
| 486 # Write prototype for initialization function. | 490 # Write prototype for initialization function. |
| 487 file.write('\n') | 491 file.write('\n') |
| 488 file.write('namespace gfx {\n') | 492 file.write('namespace gfx {\n') |
| 489 file.write('\n') | 493 file.write('\n') |
| 494 file.write('class GLContext;\n') | |
| 495 file.write('\n') | |
| 490 file.write('void InitializeGLBindings%s();\n' % set_name.upper()) | 496 file.write('void InitializeGLBindings%s();\n' % set_name.upper()) |
| 497 file.write('void InitializeGLExtensionBindings%s(GLContext* context);\n' % | |
| 498 set_name.upper()) | |
| 491 file.write('void InitializeDebugGLBindings%s();\n' % set_name.upper()) | 499 file.write('void InitializeDebugGLBindings%s();\n' % set_name.upper()) |
| 492 | 500 |
| 493 # Write typedefs for function pointer types. Always use the GL name for the | 501 # Write typedefs for function pointer types. Always use the GL name for the |
| 494 # typedef. | 502 # typedef. |
| 495 file.write('\n') | 503 file.write('\n') |
| 496 for [return_type, names, arguments] in functions: | 504 for [return_type, names, arguments] in functions: |
| 497 file.write('typedef %s (GL_BINDING_CALL *%sProc)(%s);\n' % | 505 file.write('typedef %s (GL_BINDING_CALL *%sProc)(%s);\n' % |
| 498 (return_type, names[0], arguments)) | 506 (return_type, names[0], arguments)) |
| 499 | 507 |
| 500 # Write declarations for function pointers. Always use the GL name for the | 508 # Write declarations for function pointers. Always use the GL name for the |
| 501 # declaration. | 509 # declaration. |
| 502 file.write('\n') | 510 file.write('\n') |
| 503 for [return_type, names, arguments] in functions: | 511 for [return_type, names, arguments] in functions: |
| 504 file.write('GL_EXPORT extern %sProc g_%s;\n' % (names[0], names[0])) | 512 file.write('GL_EXPORT extern %sProc g_%s;\n' % (names[0], names[0])) |
| 505 file.write('\n') | 513 file.write('\n') |
| 506 file.write( '} // namespace gfx\n') | 514 file.write( '} // namespace gfx\n') |
| 507 | 515 |
| 508 # Write macros to invoke function pointers. Always use the GL name for the | 516 # Write macros to invoke function pointers. Always use the GL name for the |
| 509 # macro. | 517 # macro. |
| 510 file.write('\n') | 518 file.write('\n') |
| 511 for [return_type, names, arguments] in functions: | 519 for [return_type, names, arguments] in functions: |
| 512 file.write('#define %s ::gfx::g_%s\n' % | 520 file.write('#define %s ::gfx::g_%s\n' % |
| 513 (names[0], names[0])) | 521 (names[0], names[0])) |
| 514 | 522 |
| 515 file.write('\n') | 523 file.write('\n') |
| 516 file.write('#endif // UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % | 524 file.write('#endif // UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % |
| 517 set_name.upper()) | 525 set_name.upper()) |
| 518 | 526 |
| 519 | 527 |
| 520 def GenerateSource(file, functions, set_name): | 528 def GenerateSource(file, functions, set_name, used_extension_functions): |
| 521 """Generates gl_binding_autogen_x.cc""" | 529 """Generates gl_binding_autogen_x.cc""" |
| 522 | 530 |
| 523 # Write file header. | 531 # Write file header. |
| 524 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n ') | 532 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n ') |
| 525 file.write('// Use of this source code is governed by a BSD-style license that can be\n') | 533 file.write('// Use of this source code is governed by a BSD-style license that can be\n') |
| 526 file.write('// found in the LICENSE file.\n') | 534 file.write('// found in the LICENSE file.\n') |
| 527 file.write('\n') | 535 file.write('\n') |
| 528 file.write('// This file is automatically generated.\n') | 536 file.write('// This file is automatically generated.\n') |
| 529 file.write('\n') | 537 file.write('\n') |
| 530 file.write('#include "ui/gfx/gl/gl_bindings.h"\n') | 538 file.write('#include "ui/gfx/gl/gl_bindings.h"\n') |
| 539 file.write('#include "ui/gfx/gl/gl_context.h"\n') | |
| 531 file.write('#include "ui/gfx/gl/gl_implementation.h"\n') | 540 file.write('#include "ui/gfx/gl/gl_implementation.h"\n') |
| 532 | 541 |
| 533 # Write definitions of function pointers. | 542 # Write definitions of function pointers. |
| 534 file.write('\n') | 543 file.write('\n') |
| 535 file.write('namespace gfx {\n') | 544 file.write('namespace gfx {\n') |
| 536 file.write('\n') | 545 file.write('\n') |
| 546 file.write('static bool g_debugBindingsInitialized;\n') | |
| 547 file.write('static void UpdateDebugGLExtensionBindings();\n') | |
| 548 file.write('\n') | |
| 537 for [return_type, names, arguments] in functions: | 549 for [return_type, names, arguments] in functions: |
| 538 file.write('%sProc g_%s;\n' % (names[0], names[0])) | 550 file.write('%sProc g_%s;\n' % (names[0], names[0])) |
| 539 | 551 |
| 540 file.write('\n') | 552 file.write('\n') |
| 541 for [return_type, names, arguments] in functions: | 553 for [return_type, names, arguments] in functions: |
| 542 file.write('static %sProc g_debug_%s;\n' % (names[0], names[0])) | 554 file.write('static %sProc g_debug_%s;\n' % (names[0], names[0])) |
| 543 | 555 |
| 544 # Write function to initialize the function pointers. | 556 # Write function to initialize the core function pointers. The code assumes |
| 557 # any non-NULL pointer returned by GetGLCoreProcAddress() is valid, although | |
| 558 # it may be overwritten by an extension function pointer later. | |
| 545 file.write('\n') | 559 file.write('\n') |
| 546 file.write('void InitializeGLBindings%s() {\n' % set_name.upper()) | 560 file.write('void InitializeGLBindings%s() {\n' % set_name.upper()) |
| 547 for [return_type, names, arguments] in functions: | 561 for [return_type, names, arguments] in functions: |
| 548 for name in names: | 562 for i, name in enumerate(names): |
| 549 file.write(' if (!g_%s)\n' % names[0]) | 563 if i: |
| 564 file.write(' if (!g_%s)\n ' % names[0]) | |
| 550 file.write( | 565 file.write( |
| 551 ' g_%s = reinterpret_cast<%sProc>(GetGLProcAddress("%s"));\n' % | 566 ' g_%s = reinterpret_cast<%sProc>(GetGLCoreProcAddress("%s"));\n' % |
| 552 (names[0], names[0], name)) | 567 (names[0], names[0], name)) |
| 553 file.write('}\n') | 568 file.write('}\n') |
| 554 file.write('\n') | 569 file.write('\n') |
| 555 | 570 |
| 571 # Write function to initialize the extension function pointers. This function | |
| 572 # uses a current context to query which extensions are actually supported. | |
| 573 file.write('void InitializeGLExtensionBindings%s(GLContext* context) {\n' % | |
| 574 set_name.upper()) | |
| 575 file.write(' DCHECK(context && context->IsCurrent(NULL));\n') | |
| 576 for extension, ext_functions in used_extension_functions: | |
| 577 file.write(' if (context->HasExtension("%s")) {\n' % extension) | |
| 578 queried_entry_points = set() | |
| 579 for entry_point_name, function_name in ext_functions: | |
| 580 # Replace the pointer unconditionally unless this extension has several | |
| 581 # alternatives for the same entry point (e.g., | |
| 582 # GL_ARB_blend_func_extended). | |
| 583 if entry_point_name in queried_entry_points: | |
| 584 file.write(' if (!g_%s)\n ' % entry_point_name) | |
| 585 file.write( | |
| 586 ' g_%s = reinterpret_cast<%sProc>(GetGLProcAddress("%s"));\n' % | |
| 587 (entry_point_name, entry_point_name, function_name)) | |
| 588 queried_entry_points.add(entry_point_name) | |
| 589 file.write(' }\n') | |
| 590 file.write(' if (g_debugBindingsInitialized)\n') | |
| 591 file.write(' UpdateDebugGLExtensionBindings();\n') | |
| 592 file.write('}\n') | |
| 593 file.write('\n') | |
| 594 | |
| 556 # Write logging wrappers for each function. | 595 # Write logging wrappers for each function. |
| 557 file.write('extern "C" {\n') | 596 file.write('extern "C" {\n') |
| 558 for [return_type, names, arguments] in functions: | 597 for [return_type, names, arguments] in functions: |
| 559 file.write('\n') | 598 file.write('\n') |
| 560 file.write('static %s GL_BINDING_CALL Debug_%s(%s) {\n' % | 599 file.write('static %s GL_BINDING_CALL Debug_%s(%s) {\n' % |
| 561 (return_type, names[0], arguments)) | 600 (return_type, names[0], arguments)) |
| 562 argument_names = re.sub(r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2', | 601 argument_names = re.sub(r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2', |
| 563 arguments) | 602 arguments) |
| 564 argument_names = re.sub(r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2', | 603 argument_names = re.sub(r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2', |
| 565 argument_names) | 604 argument_names) |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 588 else: | 627 else: |
| 589 file.write(' GL_SERVICE_LOG("%s" << "(" %s << ")");\n' % | 628 file.write(' GL_SERVICE_LOG("%s" << "(" %s << ")");\n' % |
| 590 (function_name, log_argument_names)) | 629 (function_name, log_argument_names)) |
| 591 file.write(' %s result = g_debug_%s(%s);\n' % | 630 file.write(' %s result = g_debug_%s(%s);\n' % |
| 592 (return_type, function_name, argument_names)) | 631 (return_type, function_name, argument_names)) |
| 593 file.write(' GL_SERVICE_LOG("GL_RESULT: " << result);\n'); | 632 file.write(' GL_SERVICE_LOG("GL_RESULT: " << result);\n'); |
| 594 file.write(' return result;\n') | 633 file.write(' return result;\n') |
| 595 file.write('}\n') | 634 file.write('}\n') |
| 596 file.write('} // extern "C"\n') | 635 file.write('} // extern "C"\n') |
| 597 | 636 |
| 598 # Write function to initialize the function pointers. | 637 # Write function to initialize the debug function pointers. |
| 599 file.write('\n') | 638 file.write('\n') |
| 600 file.write('void InitializeDebugGLBindings%s() {\n' % set_name.upper()) | 639 file.write('void InitializeDebugGLBindings%s() {\n' % set_name.upper()) |
| 601 for [return_type, names, arguments] in functions: | 640 for [return_type, names, arguments] in functions: |
| 602 for name in names: | 641 file.write(' if (!g_debug_%s) {\n' % names[0]) |
| 603 file.write(' if (!g_debug_%s) {\n' % names[0]) | 642 file.write(' g_debug_%s = g_%s;\n' % (names[0], names[0])) |
| 604 file.write(' g_debug_%s = g_%s;\n' % (names[0], names[0])) | 643 file.write(' g_%s = Debug_%s;\n' % (names[0], names[0])) |
| 605 file.write(' g_%s = Debug_%s;\n' % (names[0], names[0])) | 644 file.write(' }\n') |
| 645 file.write(' g_debugBindingsInitialized = true;\n') | |
| 646 file.write('}\n') | |
| 647 | |
| 648 # Write function to update the debug function pointers to extension functions | |
| 649 # after the extensions have been initialized. | |
| 650 file.write('\n') | |
| 651 file.write('static void UpdateDebugGLExtensionBindings() {\n') | |
| 652 for extension, ext_functions in used_extension_functions: | |
| 653 for name, _ in ext_functions: | |
| 654 file.write(' if (g_debug_%s != g_%s &&\n' % (name, name)) | |
| 655 file.write(' g_%s != Debug_%s) {\n' % (name, name)) | |
| 656 file.write(' g_debug_%s = g_%s;\n' % (name, name)) | |
| 657 file.write(' g_%s = Debug_%s;\n' % (name, name)) | |
| 606 file.write(' }\n') | 658 file.write(' }\n') |
| 607 file.write('}\n') | 659 file.write('}\n') |
| 608 file.write('\n') | |
| 609 | 660 |
| 610 file.write( '} // namespace gfx\n') | 661 file.write('} // namespace gfx\n') |
| 611 | 662 |
| 612 | 663 |
| 613 def GenerateMockSource(file, functions): | 664 def GenerateMockSource(file, functions): |
| 614 """Generates functions that invoke a mock GLInterface""" | 665 """Generates functions that invoke a mock GLInterface""" |
| 615 | 666 |
| 616 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n ') | 667 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n ') |
| 617 file.write('// Use of this source code is governed by a BSD-style license that can be\n') | 668 file.write('// Use of this source code is governed by a BSD-style license that can be\n') |
| 618 file.write('// found in the LICENSE file.\n') | 669 file.write('// found in the LICENSE file.\n') |
| 619 file.write('\n') | 670 file.write('\n') |
| 620 file.write('// This file is automatically generated.\n') | 671 file.write('// This file is automatically generated.\n') |
| (...skipping 16 matching lines...) Expand all Loading... | |
| 637 argument_names = '' | 688 argument_names = '' |
| 638 function_name = names[0][2:] | 689 function_name = names[0][2:] |
| 639 if return_type == 'void': | 690 if return_type == 'void': |
| 640 file.write(' GLInterface::GetGLInterface()->%s(%s);\n' % | 691 file.write(' GLInterface::GetGLInterface()->%s(%s);\n' % |
| 641 (function_name, argument_names)) | 692 (function_name, argument_names)) |
| 642 else: | 693 else: |
| 643 file.write(' return GLInterface::GetGLInterface()->%s(%s);\n' % | 694 file.write(' return GLInterface::GetGLInterface()->%s(%s);\n' % |
| 644 (function_name, argument_names)) | 695 (function_name, argument_names)) |
| 645 file.write('}\n') | 696 file.write('}\n') |
| 646 | 697 |
| 698 # Write an 'invalid' function to catch code calling through uninitialized | |
| 699 # function pointers or trying to interpret the return value of | |
| 700 # GLProcAddress(). | |
| 701 file.write('\n') | |
| 702 file.write('static void MockInvalidFunction() {\n') | |
| 703 file.write(' DCHECK(0);\n') | |
|
apatrick_chromium
2011/10/26 18:29:11
This could be NOTREACHED()
Sami
2011/10/27 13:46:06
Done.
| |
| 704 file.write('}\n') | |
| 705 | |
| 647 # Write a function to lookup a mock GL function based on its name. | 706 # Write a function to lookup a mock GL function based on its name. |
| 648 file.write('\n') | 707 file.write('\n') |
| 649 file.write('void* GL_BINDING_CALL GetMockGLProcAddress(const char* name) {\n') | 708 file.write('void* GL_BINDING_CALL GetMockGLProcAddress(const char* name) {\n') |
| 650 for [return_type, names, arguments] in functions: | 709 for [return_type, names, arguments] in functions: |
| 651 file.write(' if (strcmp(name, "%s") == 0)\n' % names[0]) | 710 file.write(' if (strcmp(name, "%s") == 0)\n' % names[0]) |
| 652 file.write(' return reinterpret_cast<void*>(Mock_%s);\n' % names[0]) | 711 file.write(' return reinterpret_cast<void*>(Mock_%s);\n' % names[0]) |
| 653 file.write(' return NULL;\n') | 712 # Always return a non-NULL pointer like some EGL implementations do. |
| 713 file.write(' return reinterpret_cast<void*>(&MockInvalidFunction);\n') | |
| 654 file.write('}\n'); | 714 file.write('}\n'); |
| 655 | 715 |
| 656 file.write('\n') | 716 file.write('\n') |
| 657 file.write('} // namespace gfx\n') | 717 file.write('} // namespace gfx\n') |
| 658 | 718 |
| 719 def ParseExtensionFunctionsFromHeader(header_file): | |
| 720 """Parse a C extension header file and return a map from extension names to | |
| 721 a list of functions. | |
| 722 | |
| 723 Args: | |
| 724 header_file: Line-iterable C header file. | |
| 725 Returns: | |
| 726 Map of extension name => functions. | |
| 727 """ | |
| 728 extension_start = re.compile(r'#define ([A-Z]+_[A-Z]+_[a-zA-Z]\w+) 1') | |
| 729 extension_function = re.compile(r'.+\s+([a-z]+\w+)\s*\(.+\);') | |
| 730 typedef = re.compile(r'typedef .*') | |
| 731 macro_start = re.compile(r'^#(if|ifdef|ifndef).*') | |
| 732 macro_end = re.compile(r'^#endif.*') | |
| 733 macro_depth = 0 | |
| 734 current_extension = None | |
| 735 current_extension_depth = 0 | |
| 736 extensions = collections.defaultdict(lambda: []) | |
| 737 for line in header_file: | |
| 738 if macro_start.match(line): | |
| 739 macro_depth += 1 | |
| 740 elif macro_end.match(line): | |
| 741 macro_depth -= 1 | |
| 742 if macro_depth < current_extension_depth: | |
| 743 current_extension = None | |
| 744 match = extension_start.match(line) | |
| 745 if match: | |
| 746 current_extension = match.group(1) | |
| 747 current_extension_depth = macro_depth | |
| 748 assert current_extension not in extensions, \ | |
| 749 "Duplicate extension: " + current_extension | |
| 750 match = extension_function.match(line) | |
| 751 if match and current_extension and not typedef.match(line): | |
| 752 extensions[current_extension].append(match.group(1)) | |
| 753 return extensions | |
| 754 | |
| 755 def GetExtensionFunctions(extension_headers): | |
| 756 """Parse extension functions from a list of header files. | |
| 757 | |
| 758 Args: | |
| 759 extension_headers: List of header file names. | |
| 760 Returns: | |
| 761 Map of extension name => list of functions. | |
| 762 """ | |
| 763 extensions = {} | |
| 764 for header in extension_headers: | |
| 765 extensions.update(ParseExtensionFunctionsFromHeader(open(header))) | |
| 766 return extensions | |
| 767 | |
| 768 def GetFunctionToExtensionMap(extensions): | |
| 769 """Construct map from a function names to extensions which define the | |
| 770 function. | |
| 771 | |
| 772 Args: | |
| 773 extensions: Map of extension name => functions. | |
| 774 Returns: | |
| 775 Map of function name => extension name. | |
| 776 """ | |
| 777 function_to_extension = {} | |
| 778 for extension, functions in extensions.items(): | |
| 779 for function in functions: | |
| 780 assert function not in function_to_extension, \ | |
| 781 "Duplicate function: " + function | |
| 782 function_to_extension[function] = extension | |
| 783 return function_to_extension | |
| 784 | |
| 785 def LooksLikeExtensionFunction(function): | |
| 786 """Heuristic to see if a function name is consistent with extension function | |
| 787 naming.""" | |
| 788 vendor = re.match(r'\w+?([A-Z][A-Z]+)$', function) | |
| 789 return vendor is not None and not vendor.group(1) in ['GL', 'API', 'DC'] | |
| 790 | |
| 791 def GetUsedExtensionFunctions(functions, extension_headers): | |
| 792 """Determine which functions belong to extensions. | |
| 793 | |
| 794 Args: | |
| 795 functions: List of (return type, function names, arguments). | |
| 796 extension_headers: List of header file names. | |
| 797 Returns: | |
| 798 List of (extension name, [function name alternatives]) sorted with least | |
| 799 preferred extensions first. | |
| 800 """ | |
| 801 # Parse known extensions. | |
| 802 extensions = GetExtensionFunctions(extension_headers) | |
| 803 functions_to_extensions = GetFunctionToExtensionMap(extensions) | |
| 804 | |
| 805 # Collect all used extension functions. | |
| 806 used_extension_functions = collections.defaultdict(lambda: []) | |
| 807 for [return_type, names, arguments] in functions: | |
| 808 for name in names: | |
| 809 # Make sure we know about all extension functions. | |
| 810 if (LooksLikeExtensionFunction(name) and | |
| 811 not name in functions_to_extensions): | |
| 812 raise RuntimeError('%s looks like an extension function but does not ' | |
| 813 'belong to any of the known extensions.' % name) | |
| 814 if name in functions_to_extensions: | |
| 815 extension = functions_to_extensions[name] | |
| 816 used_extension_functions[extension].append((names[0], name)) | |
| 817 | |
| 818 def ExtensionSortKey(name): | |
| 819 # Prefer ratified extensions and EXTs. | |
| 820 preferences = ['_ARB_', '_OES_', '_EXT_', ''] | |
| 821 for i, category in enumerate(preferences): | |
| 822 if category in name: | |
| 823 return -i | |
| 824 used_extension_functions = sorted(used_extension_functions.items(), | |
| 825 key = lambda item: ExtensionSortKey(item[0])) | |
| 826 return used_extension_functions | |
| 659 | 827 |
| 660 def main(argv): | 828 def main(argv): |
| 661 """This is the main function.""" | 829 """This is the main function.""" |
| 662 | 830 |
| 663 if len(argv) >= 1: | 831 if len(argv) >= 1: |
| 664 dir = argv[0] | 832 dir = argv[0] |
| 665 else: | 833 else: |
| 666 dir = '.' | 834 dir = '.' |
| 667 | 835 |
| 668 for [functions, set_name] in FUNCTION_SETS: | 836 for [functions, set_name, extension_headers] in FUNCTION_SETS: |
| 669 header_file = open( | 837 header_file = open( |
| 670 os.path.join(dir, 'gl_bindings_autogen_%s.h' % set_name), 'wb') | 838 os.path.join(dir, 'gl_bindings_autogen_%s.h' % set_name), 'wb') |
| 671 GenerateHeader(header_file, functions, set_name) | 839 GenerateHeader(header_file, functions, set_name) |
| 672 header_file.close() | 840 header_file.close() |
| 673 | 841 |
| 674 source_file = open( | 842 source_file = open( |
| 675 os.path.join(dir, 'gl_bindings_autogen_%s.cc' % set_name), 'wb') | 843 os.path.join(dir, 'gl_bindings_autogen_%s.cc' % set_name), 'wb') |
| 676 GenerateSource(source_file, functions, set_name) | 844 used_extension_functions = GetUsedExtensionFunctions( |
| 845 functions, extension_headers) | |
| 846 GenerateSource(source_file, functions, set_name, used_extension_functions) | |
| 677 source_file.close() | 847 source_file.close() |
| 678 | 848 |
| 679 source_file = open(os.path.join(dir, 'gl_bindings_autogen_mock.cc'), 'wb') | 849 source_file = open(os.path.join(dir, 'gl_bindings_autogen_mock.cc'), 'wb') |
| 680 GenerateMockSource(source_file, GL_FUNCTIONS) | 850 GenerateMockSource(source_file, GL_FUNCTIONS) |
| 681 source_file.close() | 851 source_file.close() |
| 682 | 852 |
| 683 | 853 |
| 684 if __name__ == '__main__': | 854 if __name__ == '__main__': |
| 685 main(sys.argv[1:]) | 855 main(sys.argv[1:]) |
| OLD | NEW |