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 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
458 ['void', ['glXSwapIntervalEXT'], | 459 ['void', ['glXSwapIntervalEXT'], |
459 'Display* dpy, GLXDrawable drawable, int interval'], | 460 'Display* dpy, GLXDrawable drawable, int interval'], |
460 ['GLXFBConfig', ['glXGetFBConfigFromVisualSGIX'], | 461 ['GLXFBConfig', ['glXGetFBConfigFromVisualSGIX'], |
461 'Display* dpy, XVisualInfo* visualInfo'], | 462 'Display* dpy, XVisualInfo* visualInfo'], |
462 ['GLXContext', ['glXCreateContextAttribsARB'], | 463 ['GLXContext', ['glXCreateContextAttribsARB'], |
463 'Display* dpy, GLXFBConfig config, GLXContext share_context, int direct, ' | 464 'Display* dpy, GLXFBConfig config, GLXContext share_context, int direct, ' |
464 'const int* attrib_list'], | 465 'const int* attrib_list'], |
465 ] | 466 ] |
466 | 467 |
467 FUNCTION_SETS = [ | 468 FUNCTION_SETS = [ |
468 [GL_FUNCTIONS, 'gl'], | 469 [GL_FUNCTIONS, 'gl', ['../../../third_party/mesa/MesaLib/include/GL/glext.h', |
469 [OSMESA_FUNCTIONS, 'osmesa'], | 470 '../../../gpu/GLES2/gl2ext.h']], |
470 [EGL_FUNCTIONS, 'egl'], | 471 [OSMESA_FUNCTIONS, 'osmesa', []], |
471 [WGL_FUNCTIONS, 'wgl'], | 472 [EGL_FUNCTIONS, 'egl', ['../../../gpu/EGL/eglext.h']], |
472 [GLX_FUNCTIONS, 'glx'], | 473 [WGL_FUNCTIONS, 'wgl', [ |
| 474 '../../../third_party/mesa/MesaLib/include/GL/wglext.h']], |
| 475 [GLX_FUNCTIONS, 'glx', [ |
| 476 '../../../third_party/mesa/MesaLib/include/GL/glxext.h']], |
473 ] | 477 ] |
474 | 478 |
475 def GenerateHeader(file, functions, set_name): | 479 def GenerateHeader(file, functions, set_name): |
476 """Generates gl_binding_autogen_x.h""" | 480 """Generates gl_binding_autogen_x.h""" |
477 | 481 |
478 # Write file header. | 482 # Write file header. |
479 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n
') | 483 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n
') |
480 file.write('// Use of this source code is governed by a BSD-style license that
can be\n') | 484 file.write('// Use of this source code is governed by a BSD-style license that
can be\n') |
481 file.write('// found in the LICENSE file.\n') | 485 file.write('// found in the LICENSE file.\n') |
482 file.write('\n') | 486 file.write('\n') |
483 file.write('// This file is automatically generated.\n') | 487 file.write('// This file is automatically generated.\n') |
484 file.write('\n') | 488 file.write('\n') |
485 file.write('#ifndef UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % set_name.upper()) | 489 file.write('#ifndef UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % set_name.upper()) |
486 file.write('#define UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % set_name.upper()) | 490 file.write('#define UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % set_name.upper()) |
487 | 491 |
488 # Write prototype for initialization function. | 492 # Write prototype for initialization function. |
489 file.write('\n') | 493 file.write('\n') |
490 file.write('namespace gfx {\n') | 494 file.write('namespace gfx {\n') |
491 file.write('\n') | 495 file.write('\n') |
| 496 file.write('class GLContext;\n') |
| 497 file.write('\n') |
492 file.write('void InitializeGLBindings%s();\n' % set_name.upper()) | 498 file.write('void InitializeGLBindings%s();\n' % set_name.upper()) |
| 499 file.write('void InitializeGLExtensionBindings%s(GLContext* context);\n' % |
| 500 set_name.upper()) |
493 file.write('void InitializeDebugGLBindings%s();\n' % set_name.upper()) | 501 file.write('void InitializeDebugGLBindings%s();\n' % set_name.upper()) |
494 | 502 |
495 # Write typedefs for function pointer types. Always use the GL name for the | 503 # Write typedefs for function pointer types. Always use the GL name for the |
496 # typedef. | 504 # typedef. |
497 file.write('\n') | 505 file.write('\n') |
498 for [return_type, names, arguments] in functions: | 506 for [return_type, names, arguments] in functions: |
499 file.write('typedef %s (GL_BINDING_CALL *%sProc)(%s);\n' % | 507 file.write('typedef %s (GL_BINDING_CALL *%sProc)(%s);\n' % |
500 (return_type, names[0], arguments)) | 508 (return_type, names[0], arguments)) |
501 | 509 |
502 # Write declarations for function pointers. Always use the GL name for the | 510 # Write declarations for function pointers. Always use the GL name for the |
503 # declaration. | 511 # declaration. |
504 file.write('\n') | 512 file.write('\n') |
505 for [return_type, names, arguments] in functions: | 513 for [return_type, names, arguments] in functions: |
506 file.write('GL_EXPORT extern %sProc g_%s;\n' % (names[0], names[0])) | 514 file.write('GL_EXPORT extern %sProc g_%s;\n' % (names[0], names[0])) |
507 file.write('\n') | 515 file.write('\n') |
508 file.write( '} // namespace gfx\n') | 516 file.write( '} // namespace gfx\n') |
509 | 517 |
510 # Write macros to invoke function pointers. Always use the GL name for the | 518 # Write macros to invoke function pointers. Always use the GL name for the |
511 # macro. | 519 # macro. |
512 file.write('\n') | 520 file.write('\n') |
513 for [return_type, names, arguments] in functions: | 521 for [return_type, names, arguments] in functions: |
514 file.write('#define %s ::gfx::g_%s\n' % | 522 file.write('#define %s ::gfx::g_%s\n' % |
515 (names[0], names[0])) | 523 (names[0], names[0])) |
516 | 524 |
517 file.write('\n') | 525 file.write('\n') |
518 file.write('#endif // UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % | 526 file.write('#endif // UI_GFX_GL_GL_BINDINGS_AUTOGEN_%s_H_\n' % |
519 set_name.upper()) | 527 set_name.upper()) |
520 | 528 |
521 | 529 |
522 def GenerateSource(file, functions, set_name): | 530 def GenerateSource(file, functions, set_name, used_extension_functions): |
523 """Generates gl_binding_autogen_x.cc""" | 531 """Generates gl_binding_autogen_x.cc""" |
524 | 532 |
525 # Write file header. | 533 # Write file header. |
526 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n
') | 534 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n
') |
527 file.write('// Use of this source code is governed by a BSD-style license that
can be\n') | 535 file.write('// Use of this source code is governed by a BSD-style license that
can be\n') |
528 file.write('// found in the LICENSE file.\n') | 536 file.write('// found in the LICENSE file.\n') |
529 file.write('\n') | 537 file.write('\n') |
530 file.write('// This file is automatically generated.\n') | 538 file.write('// This file is automatically generated.\n') |
531 file.write('\n') | 539 file.write('\n') |
532 file.write('#include "ui/gfx/gl/gl_bindings.h"\n') | 540 file.write('#include "ui/gfx/gl/gl_bindings.h"\n') |
| 541 file.write('#include "ui/gfx/gl/gl_context.h"\n') |
533 file.write('#include "ui/gfx/gl/gl_implementation.h"\n') | 542 file.write('#include "ui/gfx/gl/gl_implementation.h"\n') |
534 | 543 |
535 # Write definitions of function pointers. | 544 # Write definitions of function pointers. |
536 file.write('\n') | 545 file.write('\n') |
537 file.write('namespace gfx {\n') | 546 file.write('namespace gfx {\n') |
538 file.write('\n') | 547 file.write('\n') |
| 548 file.write('static bool g_debugBindingsInitialized;\n') |
| 549 file.write('static void UpdateDebugGLExtensionBindings();\n') |
| 550 file.write('\n') |
539 for [return_type, names, arguments] in functions: | 551 for [return_type, names, arguments] in functions: |
540 file.write('%sProc g_%s;\n' % (names[0], names[0])) | 552 file.write('%sProc g_%s;\n' % (names[0], names[0])) |
541 | 553 |
542 file.write('\n') | 554 file.write('\n') |
543 for [return_type, names, arguments] in functions: | 555 for [return_type, names, arguments] in functions: |
544 file.write('static %sProc g_debug_%s;\n' % (names[0], names[0])) | 556 file.write('static %sProc g_debug_%s;\n' % (names[0], names[0])) |
545 | 557 |
546 # Write function to initialize the function pointers. | 558 # Write function to initialize the core function pointers. The code assumes |
| 559 # any non-NULL pointer returned by GetGLCoreProcAddress() is valid, although |
| 560 # it may be overwritten by an extension function pointer later. |
547 file.write('\n') | 561 file.write('\n') |
548 file.write('void InitializeGLBindings%s() {\n' % set_name.upper()) | 562 file.write('void InitializeGLBindings%s() {\n' % set_name.upper()) |
549 for [return_type, names, arguments] in functions: | 563 for [return_type, names, arguments] in functions: |
550 for name in names: | 564 for i, name in enumerate(names): |
551 file.write(' if (!g_%s)\n' % names[0]) | 565 if i: |
| 566 file.write(' if (!g_%s)\n ' % names[0]) |
552 file.write( | 567 file.write( |
553 ' g_%s = reinterpret_cast<%sProc>(GetGLProcAddress("%s"));\n' % | 568 ' g_%s = reinterpret_cast<%sProc>(GetGLCoreProcAddress("%s"));\n' % |
554 (names[0], names[0], name)) | 569 (names[0], names[0], name)) |
555 file.write('}\n') | 570 file.write('}\n') |
556 file.write('\n') | 571 file.write('\n') |
557 | 572 |
| 573 # Write function to initialize the extension function pointers. This function |
| 574 # uses a current context to query which extensions are actually supported. |
| 575 file.write('void InitializeGLExtensionBindings%s(GLContext* context) {\n' % |
| 576 set_name.upper()) |
| 577 file.write(' DCHECK(context && context->IsCurrent(NULL));\n') |
| 578 for extension, ext_functions in used_extension_functions: |
| 579 file.write(' if (context->HasExtension("%s")) {\n' % extension) |
| 580 queried_entry_points = set() |
| 581 for entry_point_name, function_name in ext_functions: |
| 582 # Replace the pointer unconditionally unless this extension has several |
| 583 # alternatives for the same entry point (e.g., |
| 584 # GL_ARB_blend_func_extended). |
| 585 if entry_point_name in queried_entry_points: |
| 586 file.write(' if (!g_%s)\n ' % entry_point_name) |
| 587 file.write( |
| 588 ' g_%s = reinterpret_cast<%sProc>(GetGLProcAddress("%s"));\n' % |
| 589 (entry_point_name, entry_point_name, function_name)) |
| 590 queried_entry_points.add(entry_point_name) |
| 591 file.write(' }\n') |
| 592 file.write(' if (g_debugBindingsInitialized)\n') |
| 593 file.write(' UpdateDebugGLExtensionBindings();\n') |
| 594 file.write('}\n') |
| 595 file.write('\n') |
| 596 |
558 # Write logging wrappers for each function. | 597 # Write logging wrappers for each function. |
559 file.write('extern "C" {\n') | 598 file.write('extern "C" {\n') |
560 for [return_type, names, arguments] in functions: | 599 for [return_type, names, arguments] in functions: |
561 file.write('\n') | 600 file.write('\n') |
562 file.write('static %s GL_BINDING_CALL Debug_%s(%s) {\n' % | 601 file.write('static %s GL_BINDING_CALL Debug_%s(%s) {\n' % |
563 (return_type, names[0], arguments)) | 602 (return_type, names[0], 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 arguments) | 604 arguments) |
566 argument_names = re.sub(r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2', | 605 argument_names = re.sub(r'(const )?[a-zA-Z0-9_]+\** ([a-zA-Z0-9_]+)', r'\2', |
567 argument_names) | 606 argument_names) |
(...skipping 22 matching lines...) Expand all Loading... |
590 else: | 629 else: |
591 file.write(' GL_SERVICE_LOG("%s" << "(" %s << ")");\n' % | 630 file.write(' GL_SERVICE_LOG("%s" << "(" %s << ")");\n' % |
592 (function_name, log_argument_names)) | 631 (function_name, log_argument_names)) |
593 file.write(' %s result = g_debug_%s(%s);\n' % | 632 file.write(' %s result = g_debug_%s(%s);\n' % |
594 (return_type, function_name, argument_names)) | 633 (return_type, function_name, argument_names)) |
595 file.write(' GL_SERVICE_LOG("GL_RESULT: " << result);\n'); | 634 file.write(' GL_SERVICE_LOG("GL_RESULT: " << result);\n'); |
596 file.write(' return result;\n') | 635 file.write(' return result;\n') |
597 file.write('}\n') | 636 file.write('}\n') |
598 file.write('} // extern "C"\n') | 637 file.write('} // extern "C"\n') |
599 | 638 |
600 # Write function to initialize the function pointers. | 639 # Write function to initialize the debug function pointers. |
601 file.write('\n') | 640 file.write('\n') |
602 file.write('void InitializeDebugGLBindings%s() {\n' % set_name.upper()) | 641 file.write('void InitializeDebugGLBindings%s() {\n' % set_name.upper()) |
603 for [return_type, names, arguments] in functions: | 642 for [return_type, names, arguments] in functions: |
604 for name in names: | 643 file.write(' if (!g_debug_%s) {\n' % names[0]) |
605 file.write(' if (!g_debug_%s) {\n' % names[0]) | 644 file.write(' g_debug_%s = g_%s;\n' % (names[0], names[0])) |
606 file.write(' g_debug_%s = g_%s;\n' % (names[0], names[0])) | 645 file.write(' g_%s = Debug_%s;\n' % (names[0], names[0])) |
607 file.write(' g_%s = Debug_%s;\n' % (names[0], names[0])) | 646 file.write(' }\n') |
| 647 file.write(' g_debugBindingsInitialized = true;\n') |
| 648 file.write('}\n') |
| 649 |
| 650 # Write function to update the debug function pointers to extension functions |
| 651 # after the extensions have been initialized. |
| 652 file.write('\n') |
| 653 file.write('static void UpdateDebugGLExtensionBindings() {\n') |
| 654 for extension, ext_functions in used_extension_functions: |
| 655 for name, _ in ext_functions: |
| 656 file.write(' if (g_debug_%s != g_%s &&\n' % (name, name)) |
| 657 file.write(' g_%s != Debug_%s) {\n' % (name, name)) |
| 658 file.write(' g_debug_%s = g_%s;\n' % (name, name)) |
| 659 file.write(' g_%s = Debug_%s;\n' % (name, name)) |
608 file.write(' }\n') | 660 file.write(' }\n') |
609 file.write('}\n') | 661 file.write('}\n') |
610 file.write('\n') | |
611 | 662 |
612 file.write( '} // namespace gfx\n') | 663 file.write('} // namespace gfx\n') |
613 | 664 |
614 | 665 |
615 def GenerateMockSource(file, functions): | 666 def GenerateMockSource(file, functions): |
616 """Generates functions that invoke a mock GLInterface""" | 667 """Generates functions that invoke a mock GLInterface""" |
617 | 668 |
618 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n
') | 669 file.write('// Copyright (c) 2011 The Chromium Authors. All rights reserved.\n
') |
619 file.write('// Use of this source code is governed by a BSD-style license that
can be\n') | 670 file.write('// Use of this source code is governed by a BSD-style license that
can be\n') |
620 file.write('// found in the LICENSE file.\n') | 671 file.write('// found in the LICENSE file.\n') |
621 file.write('\n') | 672 file.write('\n') |
622 file.write('// This file is automatically generated.\n') | 673 file.write('// This file is automatically generated.\n') |
(...skipping 16 matching lines...) Expand all Loading... |
639 argument_names = '' | 690 argument_names = '' |
640 function_name = names[0][2:] | 691 function_name = names[0][2:] |
641 if return_type == 'void': | 692 if return_type == 'void': |
642 file.write(' GLInterface::GetGLInterface()->%s(%s);\n' % | 693 file.write(' GLInterface::GetGLInterface()->%s(%s);\n' % |
643 (function_name, argument_names)) | 694 (function_name, argument_names)) |
644 else: | 695 else: |
645 file.write(' return GLInterface::GetGLInterface()->%s(%s);\n' % | 696 file.write(' return GLInterface::GetGLInterface()->%s(%s);\n' % |
646 (function_name, argument_names)) | 697 (function_name, argument_names)) |
647 file.write('}\n') | 698 file.write('}\n') |
648 | 699 |
| 700 # Write an 'invalid' function to catch code calling through uninitialized |
| 701 # function pointers or trying to interpret the return value of |
| 702 # GLProcAddress(). |
| 703 file.write('\n') |
| 704 file.write('static void MockInvalidFunction() {\n') |
| 705 file.write(' NOTREACHED();\n') |
| 706 file.write('}\n') |
| 707 |
649 # Write a function to lookup a mock GL function based on its name. | 708 # Write a function to lookup a mock GL function based on its name. |
650 file.write('\n') | 709 file.write('\n') |
651 file.write('void* GL_BINDING_CALL GetMockGLProcAddress(const char* name) {\n') | 710 file.write('void* GL_BINDING_CALL GetMockGLProcAddress(const char* name) {\n') |
652 for [return_type, names, arguments] in functions: | 711 for [return_type, names, arguments] in functions: |
653 file.write(' if (strcmp(name, "%s") == 0)\n' % names[0]) | 712 file.write(' if (strcmp(name, "%s") == 0)\n' % names[0]) |
654 file.write(' return reinterpret_cast<void*>(Mock_%s);\n' % names[0]) | 713 file.write(' return reinterpret_cast<void*>(Mock_%s);\n' % names[0]) |
655 file.write(' return NULL;\n') | 714 # Always return a non-NULL pointer like some EGL implementations do. |
| 715 file.write(' return reinterpret_cast<void*>(&MockInvalidFunction);\n') |
656 file.write('}\n'); | 716 file.write('}\n'); |
657 | 717 |
658 file.write('\n') | 718 file.write('\n') |
659 file.write('} // namespace gfx\n') | 719 file.write('} // namespace gfx\n') |
660 | 720 |
| 721 def ParseExtensionFunctionsFromHeader(header_file): |
| 722 """Parse a C extension header file and return a map from extension names to |
| 723 a list of functions. |
| 724 |
| 725 Args: |
| 726 header_file: Line-iterable C header file. |
| 727 Returns: |
| 728 Map of extension name => functions. |
| 729 """ |
| 730 extension_start = re.compile(r'#define ([A-Z]+_[A-Z]+_[a-zA-Z]\w+) 1') |
| 731 extension_function = re.compile(r'.+\s+([a-z]+\w+)\s*\(.+\);') |
| 732 typedef = re.compile(r'typedef .*') |
| 733 macro_start = re.compile(r'^#(if|ifdef|ifndef).*') |
| 734 macro_end = re.compile(r'^#endif.*') |
| 735 macro_depth = 0 |
| 736 current_extension = None |
| 737 current_extension_depth = 0 |
| 738 extensions = collections.defaultdict(lambda: []) |
| 739 for line in header_file: |
| 740 if macro_start.match(line): |
| 741 macro_depth += 1 |
| 742 elif macro_end.match(line): |
| 743 macro_depth -= 1 |
| 744 if macro_depth < current_extension_depth: |
| 745 current_extension = None |
| 746 match = extension_start.match(line) |
| 747 if match: |
| 748 current_extension = match.group(1) |
| 749 current_extension_depth = macro_depth |
| 750 assert current_extension not in extensions, \ |
| 751 "Duplicate extension: " + current_extension |
| 752 match = extension_function.match(line) |
| 753 if match and current_extension and not typedef.match(line): |
| 754 extensions[current_extension].append(match.group(1)) |
| 755 return extensions |
| 756 |
| 757 def GetExtensionFunctions(extension_headers): |
| 758 """Parse extension functions from a list of header files. |
| 759 |
| 760 Args: |
| 761 extension_headers: List of header file names. |
| 762 Returns: |
| 763 Map of extension name => list of functions. |
| 764 """ |
| 765 extensions = {} |
| 766 for header in extension_headers: |
| 767 extensions.update(ParseExtensionFunctionsFromHeader(open(header))) |
| 768 return extensions |
| 769 |
| 770 def GetFunctionToExtensionMap(extensions): |
| 771 """Construct map from a function names to extensions which define the |
| 772 function. |
| 773 |
| 774 Args: |
| 775 extensions: Map of extension name => functions. |
| 776 Returns: |
| 777 Map of function name => extension name. |
| 778 """ |
| 779 function_to_extension = {} |
| 780 for extension, functions in extensions.items(): |
| 781 for function in functions: |
| 782 assert function not in function_to_extension, \ |
| 783 "Duplicate function: " + function |
| 784 function_to_extension[function] = extension |
| 785 return function_to_extension |
| 786 |
| 787 def LooksLikeExtensionFunction(function): |
| 788 """Heuristic to see if a function name is consistent with extension function |
| 789 naming.""" |
| 790 vendor = re.match(r'\w+?([A-Z][A-Z]+)$', function) |
| 791 return vendor is not None and not vendor.group(1) in ['GL', 'API', 'DC'] |
| 792 |
| 793 def GetUsedExtensionFunctions(functions, extension_headers): |
| 794 """Determine which functions belong to extensions. |
| 795 |
| 796 Args: |
| 797 functions: List of (return type, function names, arguments). |
| 798 extension_headers: List of header file names. |
| 799 Returns: |
| 800 List of (extension name, [function name alternatives]) sorted with least |
| 801 preferred extensions first. |
| 802 """ |
| 803 # Parse known extensions. |
| 804 extensions = GetExtensionFunctions(extension_headers) |
| 805 functions_to_extensions = GetFunctionToExtensionMap(extensions) |
| 806 |
| 807 # Collect all used extension functions. |
| 808 used_extension_functions = collections.defaultdict(lambda: []) |
| 809 for [return_type, names, arguments] in functions: |
| 810 for name in names: |
| 811 # Make sure we know about all extension functions. |
| 812 if (LooksLikeExtensionFunction(name) and |
| 813 not name in functions_to_extensions): |
| 814 raise RuntimeError('%s looks like an extension function but does not ' |
| 815 'belong to any of the known extensions.' % name) |
| 816 if name in functions_to_extensions: |
| 817 extension = functions_to_extensions[name] |
| 818 used_extension_functions[extension].append((names[0], name)) |
| 819 |
| 820 def ExtensionSortKey(name): |
| 821 # Prefer ratified extensions and EXTs. |
| 822 preferences = ['_ARB_', '_OES_', '_EXT_', ''] |
| 823 for i, category in enumerate(preferences): |
| 824 if category in name: |
| 825 return -i |
| 826 used_extension_functions = sorted(used_extension_functions.items(), |
| 827 key = lambda item: ExtensionSortKey(item[0])) |
| 828 return used_extension_functions |
661 | 829 |
662 def main(argv): | 830 def main(argv): |
663 """This is the main function.""" | 831 """This is the main function.""" |
664 | 832 |
665 if len(argv) >= 1: | 833 if len(argv) >= 1: |
666 dir = argv[0] | 834 dir = argv[0] |
667 else: | 835 else: |
668 dir = '.' | 836 dir = '.' |
669 | 837 |
670 for [functions, set_name] in FUNCTION_SETS: | 838 for [functions, set_name, extension_headers] in FUNCTION_SETS: |
671 header_file = open( | 839 header_file = open( |
672 os.path.join(dir, 'gl_bindings_autogen_%s.h' % set_name), 'wb') | 840 os.path.join(dir, 'gl_bindings_autogen_%s.h' % set_name), 'wb') |
673 GenerateHeader(header_file, functions, set_name) | 841 GenerateHeader(header_file, functions, set_name) |
674 header_file.close() | 842 header_file.close() |
675 | 843 |
676 source_file = open( | 844 source_file = open( |
677 os.path.join(dir, 'gl_bindings_autogen_%s.cc' % set_name), 'wb') | 845 os.path.join(dir, 'gl_bindings_autogen_%s.cc' % set_name), 'wb') |
678 GenerateSource(source_file, functions, set_name) | 846 used_extension_functions = GetUsedExtensionFunctions( |
| 847 functions, extension_headers) |
| 848 GenerateSource(source_file, functions, set_name, used_extension_functions) |
679 source_file.close() | 849 source_file.close() |
680 | 850 |
681 source_file = open(os.path.join(dir, 'gl_bindings_autogen_mock.cc'), 'wb') | 851 source_file = open(os.path.join(dir, 'gl_bindings_autogen_mock.cc'), 'wb') |
682 GenerateMockSource(source_file, GL_FUNCTIONS) | 852 GenerateMockSource(source_file, GL_FUNCTIONS) |
683 source_file.close() | 853 source_file.close() |
684 | 854 |
685 | 855 |
686 if __name__ == '__main__': | 856 if __name__ == '__main__': |
687 main(sys.argv[1:]) | 857 main(sys.argv[1:]) |
OLD | NEW |