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 |