# New Ticket Created by Geoffrey Broadwell # Please include the string: [perl #54238] # in the subject line of all future correspondence about this issue. # <URL: http://rt.perl.org/rt3/Ticket/Display.html?id=54238 >
The attached patch for OpenGL.pir and triangle.pir makes the following changes: 1. Expand/improve comments and POD docs 2. Add leading underscore to private OpenGL.pir routines 3. Add _export_all_functions_to(namespace) function in OpenGL.pir 4. Use native export rather than manual get_global ops in triangle.pir Nothing other than these two files is affected, so I'm hoping this can be committed quickly. In particular, there are NO changes to configure or build in this patch; I'm keeping those separate (and probably will end up delaying them until after the next monthly release). -'f
=== runtime/parrot/library/OpenGL.pir ================================================================== --- runtime/parrot/library/OpenGL.pir (revision 5183) +++ runtime/parrot/library/OpenGL.pir (local) @@ -4,15 +4,66 @@ =head1 SYNOPSIS -TBD +This covers only the basic OpenGL and GLUT initialization. +For more, look in F<examples/opengl/>. + # Include OpenGL constants + .include 'opengl_defines.pasm' + + .sub main :main + .param pmc argv + + # Load OpenGL libary and a helper library for calling glutInit + load_bytecode 'library/OpenGL.pbc' + load_bytecode 'library/NCI/call_toolkit_init.pbc' + + # Import all OpenGL/GLU/GLUT functions + .local pmc import_gl_to, my_namespace + import_gl_to = get_global ['OpenGL'], '_export_all_functions_to' + my_namespace = get_namespace + + import_gl_to(my_namespace) + + # Initialize GLUT + .local pmc call_toolkit_init + call_toolkit_init = get_global ['NCI'], 'call_toolkit_init' + + .const .Sub glutInit = 'glutInit' + argv = call_toolkit_init(glutInit, argv) + + # Set display mode, create GLUT window, save window handle + .local int mode + mode = .GLUT_DOUBLE | .GLUT_RGBA + glutInitDisplayMode(mode) + + .local pmc window + window = new 'Integer' + window = glutCreateWindow('My Window Title') + set_global 'glut_window', window + + # Set up GLUT callbacks + .const .Sub draw = 'draw' + .const .Sub idle = 'idle' + .const .Sub keyboard = 'keyboard' + glutcbDisplayFunc (draw) + glutcbIdleFunc (idle) + glutcbKeyboardFunc(keyboard) + + # Enter the GLUT main loop + glutMainLoop() + .end + =head1 DESCRIPTION This library is a straightforward Parrot NCI wrapper for OpenGL, GLU, and GLUT. It is still a work in progress; work will generally start with the oldest, most widely supported functions and progress to the most recently -standardized calls. +standardized calls. Generally you will find programming GLUT in PIR to be +similar to GLUT in C, with the exception of the renaming of C<glut*Func> +to C<glutcb*Func> to work around some current Parrot limitations. +The following sections describe other differences from OpenGL in C. + =head2 Initialization The initialization routines are mostly for internal use only. They @@ -57,29 +108,29 @@ libnames = new 'ResizableStringArray' push libnames, 'libGL' push libnames, '/System/Library/Frameworks/OpenGL.framework/OpenGL' - libgl = load_lib_with_fallbacks('GL', libnames) - set_global 'libgl', libgl + libgl = _load_lib_with_fallbacks('GL', libnames) + set_global '_libgl', libgl libnames = new 'ResizableStringArray' push libnames, 'libGLU' push libnames, '/System/Library/Frameworks/OpenGL.framework/OpenGL' - libglu = load_lib_with_fallbacks('GLU', libnames) - set_global 'libglu', libglu + libglu = _load_lib_with_fallbacks('GLU', libnames) + set_global '_libglu', libglu libnames = new 'ResizableStringArray' push libnames, 'libglut' push libnames, '/System/Library/Frameworks/GLUT.framework/GLUT' - libglut = load_lib_with_fallbacks('GLUT', libnames) - set_global 'libglut', libglut + libglut = _load_lib_with_fallbacks('GLUT', libnames) + set_global '_libglut', libglut libnames = new 'ResizableStringArray' push libnames, 'libglutcb' - libglutcb = load_lib_with_fallbacks('GLUTCB', libnames) - set_global 'libglutcb', libglutcb + libglutcb = _load_lib_with_fallbacks('GLUTCB', libnames) + set_global '_libglutcb', libglutcb .end -=item load_lib_with_fallbacks(string friendly_name, pmc fallback_list) +=item _load_lib_with_fallbacks(string friendly_name, pmc fallback_list) This function is more generally useful than just for this module -- it implements the search for a particular libary that may appear under any @@ -91,7 +142,7 @@ =cut -.sub load_lib_with_fallbacks +.sub _load_lib_with_fallbacks .param string friendly_name .param pmc fallback_list @@ -130,24 +181,24 @@ namespace = get_namespace .local pmc libgl, libglu, libglut, libglutcb - libgl = get_global 'libgl' - libglu = get_global 'libglu' - libglut = get_global 'libglut' - libglutcb = get_global 'libglutcb' + libgl = get_global '_libgl' + libglu = get_global '_libglu' + libglut = get_global '_libglut' + libglutcb = get_global '_libglutcb' .local pmc gl_funcs, glu_funcs, glut_funcs, glutcb_funcs - gl_funcs = gl_func_list() - glu_funcs = glu_func_list() - glut_funcs = glut_func_list() - glutcb_funcs = glutcb_func_list() + gl_funcs = _gl_func_list() + glu_funcs = _glu_func_list() + glut_funcs = _glut_func_list() + glutcb_funcs = _glutcb_func_list() - wrap_nci_list(namespace, libgl, gl_funcs) - wrap_nci_list(namespace, libglu, glu_funcs) - wrap_nci_list(namespace, libglut, glut_funcs) - wrap_nci_list(namespace, libglutcb, glutcb_funcs) + _wrap_nci_list(namespace, libgl, gl_funcs) + _wrap_nci_list(namespace, libglu, glu_funcs) + _wrap_nci_list(namespace, libglut, glut_funcs) + _wrap_nci_list(namespace, libglutcb, glutcb_funcs) .end -.sub gl_func_list +.sub _gl_func_list .local pmc gl_funcs gl_funcs = new 'ResizableStringArray' push gl_funcs, 'glBegin' @@ -168,14 +219,14 @@ .return (gl_funcs) .end -.sub glu_func_list +.sub _glu_func_list .local pmc glu_funcs glu_funcs = new 'ResizableStringArray' .return (glu_funcs) .end -.sub glut_func_list +.sub _glut_func_list .local pmc glut_funcs glut_funcs = new 'ResizableStringArray' push glut_funcs, 'glutInit' @@ -196,7 +247,7 @@ .return (glut_funcs) .end -.sub glutcb_func_list +.sub _glutcb_func_list .local pmc glutcb_funcs glutcb_funcs = new 'ResizableStringArray' push glutcb_funcs, 'glutcbCloseFunc' @@ -262,7 +313,7 @@ .end -=item wrap_nci_list(pmc namespace, pmc library, pmc nci_list) +=item _wrap_nci_list(pmc namespace, pmc library, pmc nci_list) Create NCI wrappers for every C<library> entry point in C<nci_list>, and store the results in C<namespace> . The list should consist of @@ -270,7 +321,7 @@ =cut -.sub wrap_nci_list +.sub _wrap_nci_list .param pmc namespace .param pmc library .param pmc nci_list @@ -296,6 +347,54 @@ .end +=back + +=head2 Symbol Export + +These routines allow OpenGL symbols to exported to other namespaces to more +directly replicate the normal OpenGL coding style. Most calling programs +will want to use at least one of these, probably immediately after loading +this library. + +=over 4 + +=item _export_all_functions_to(pmc namespace) + +Export all OpenGL/GLU/GLUT functions to the target C<namespace>. + +=cut + +.sub _export_all_functions_to + .param pmc namespace + + .local pmc gl_namespace + gl_namespace = get_namespace + + .local pmc iterator, export_list + .local string symbol, tag + iterator = new 'Iterator', gl_namespace + export_list = new 'ResizableStringArray' + + # Collect all symbols in the OpenGL namespace starting with 'gl' + symbol_loop: + unless iterator goto symbol_end + symbol = shift iterator + tag = substr symbol, 0, 2 + unless tag == 'gl' goto symbol_loop + push export_list, symbol + goto symbol_loop + symbol_end: + + # Export them all to the requested namespace + gl_namespace.export_to(namespace, export_list) +.end + + +=back + +=cut + + # Local Variables: # mode: pir # fill-column: 100 === examples/opengl/triangle.pir ================================================================== --- examples/opengl/triangle.pir (revision 5183) +++ examples/opengl/triangle.pir (local) @@ -27,34 +27,35 @@ .sub main :main .param pmc argv + # Load OpenGL libary and a helper library for calling glutInit load_bytecode 'library/OpenGL.pbc' load_bytecode 'library/NCI/call_toolkit_init.pbc' - .local pmc glutInit, glutInitDisplayMode, glutCreateWindow, glutMainLoop - .local pmc glutcbDisplayFunc, glutcbIdleFunc - .local pmc glutcbKeyboardFunc, glutcbSpecialFunc + # Import all OpenGL/GLU/GLUT functions + .local pmc import_gl_to, my_namespace + import_gl_to = get_global ['OpenGL'], '_export_all_functions_to' + my_namespace = get_namespace + + import_gl_to(my_namespace) + + # Initialize GLUT .local pmc call_toolkit_init - glutInit = get_global ['OpenGL'], 'glutInit' - glutInitDisplayMode = get_global ['OpenGL'], 'glutInitDisplayMode' - glutCreateWindow = get_global ['OpenGL'], 'glutCreateWindow' - glutMainLoop = get_global ['OpenGL'], 'glutMainLoop' - glutcbDisplayFunc = get_global ['OpenGL'], 'glutcbDisplayFunc' - glutcbIdleFunc = get_global ['OpenGL'], 'glutcbIdleFunc' - glutcbKeyboardFunc = get_global ['OpenGL'], 'glutcbKeyboardFunc' - glutcbSpecialFunc = get_global ['OpenGL'], 'glutcbSpecialFunc' - call_toolkit_init = get_global ['NCI'], 'call_toolkit_init' + call_toolkit_init = get_global ['NCI'], 'call_toolkit_init' + .const .Sub glutInit = 'glutInit' argv = call_toolkit_init(glutInit, argv) + # Set display mode, create GLUT window, save window handle .local int mode mode = .GLUT_DOUBLE | .GLUT_RGBA glutInitDisplayMode(mode) .local pmc window - window = new Integer + window = new 'Integer' window = glutCreateWindow('Test') set_global 'glut_window', window + # Set up GLUT callbacks .const .Sub draw = 'draw' .const .Sub idle = 'idle' .const .Sub keyboard = 'keyboard' @@ -62,11 +63,13 @@ glutcbIdleFunc (idle) glutcbKeyboardFunc(keyboard) + # Set up global flag for rotating/paused .local pmc rotating rotating = new 'Integer' rotating = 1 set_global 'rotating', rotating + # Set up global time to allow constant rotation speed regardless of FPS .local pmc prev_time .local num now now = time @@ -74,23 +77,11 @@ prev_time = now set_global 'prev_time', prev_time + # Enter the GLUT main loop glutMainLoop() .end .sub draw - .local pmc glClear, glFlush - .local pmc glBegin, glEnd - .local pmc glColor3f, glVertex3f - glClear = get_global ['OpenGL'], 'glClear' - glFlush = get_global ['OpenGL'], 'glFlush' - glBegin = get_global ['OpenGL'], 'glBegin' - glEnd = get_global ['OpenGL'], 'glEnd' - glColor3f = get_global ['OpenGL'], 'glColor3f' - glVertex3f = get_global ['OpenGL'], 'glVertex3f' - - .local pmc glutSwapBuffers - glutSwapBuffers = get_global ['OpenGL'], 'glutSwapBuffers' - .local int buffers buffers = .GL_COLOR_BUFFER_BIT | .GL_DEPTH_BUFFER_BIT glClear(buffers) @@ -99,24 +90,19 @@ glColor3f(1, 0, 0) glVertex3f(-.5, -.5, 0) + glColor3f(0, 1, 0) glVertex3f( .5, -.5, 0) + glColor3f(0, 0, 1) glVertex3f(0 , .5, 0) glEnd() - glFlush() - glutSwapBuffers() .end .sub idle - .local pmc glutPostRedisplay - .local pmc glRotatef - glutPostRedisplay = get_global ['OpenGL'], 'glutPostRedisplay' - glRotatef = get_global ['OpenGL'], 'glRotatef' - .local pmc prev_time .local num prev, now, dt prev_time = get_global 'prev_time' @@ -147,17 +133,16 @@ if key == 113 goto quit goto toggle_rotation quit: - .local pmc glutDestroyWindow, glut_window - glutDestroyWindow = get_global ['OpenGL'], 'glutDestroyWindow' - glut_window = get_global 'glut_window' + .local pmc glut_window + glut_window = get_global 'glut_window' glutDestroyWindow(glut_window) end # For all other keys, just toggle rotation toggle_rotation: .local pmc rotating - rotating = get_global 'rotating' - rotating = not rotating + rotating = get_global 'rotating' + rotating = not rotating .end