# 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