# 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
 
 

Reply via email to