On Wed, 2008-05-28 at 22:54 +0200, Ron Blaschke wrote: > Geoffrey Broadwell wrote: > > OK, I know what's causing this (no typemap entry for 'wchar_t*', as the > > error indicates). Not sure about best NCI type type to match this to -- > > it really wants to be a native Parrot string with encoding UCS2, I > > believe, but I don't know how to do that off the top of my head, and I > > need to run now. > > > > I'll ruminate on this later -- though if you wanted to try skipping over > > it and see what else goes wrong later on, just put a typemap in > > config/gen/opengl.pm for wchar_t => 'void', and it will just pretend > > wchar_t* is a void buffer. > > Workaround looks good. Build is okay, F<examples/opengl/triangle.pir> > runs fine.
OK, attached is a new patch, incorporating both the path glob fix from earlier today, and the wchar_t => 'void' workaround above. This one looks like a commit candidate -- please test! -'f
diff --git a/MANIFEST b/MANIFEST index b0e3c9d..43c4f52 100644 --- a/MANIFEST +++ b/MANIFEST @@ -296,7 +296,6 @@ config/auto/warnings/test_c.in [] config/gen/call_list.pm [] config/gen/call_list/core.in [] config/gen/call_list/misc.in [] -config/gen/call_list/opengl.in [] config/gen/config_h.pm [] config/gen/config_h/config_h.in [] config/gen/config_h/feature_h.in [] diff --git a/MANIFEST.generated b/MANIFEST.generated index 183fe20..ddfe4cf 100644 --- a/MANIFEST.generated +++ b/MANIFEST.generated @@ -20,6 +20,7 @@ compilers/tge/TGE/Tree.pbc [main] compilers/tge/tgc.pir [main] config/auto/cpu/i386/memcpy_mmx.c [main] config/auto/cpu/i386/memcpy_sse.c [main] +config/gen/call_list/opengl.in [main] config/gen/platform/ansi/dl.c [main] config/gen/platform/ansi/time.c [main] config/gen/platform/darwin/memalign.c [main] @@ -228,6 +229,7 @@ runtime/parrot/library/Getopt/Obj.pbc [main] runtime/parrot/library/MIME/Base64.pbc [main] runtime/parrot/library/NCI/call_toolkit_init.pbc [main] runtime/parrot/library/OpenGL.pbc [main] +runtime/parrot/library/OpenGL_funcs.pir [main] runtime/parrot/library/P6object.pbc [main] runtime/parrot/library/Parrot/Capture_PIR.pbc [main] runtime/parrot/library/Parrot/Coroutine.pbc [main] diff --git a/config/auto/opengl.pm b/config/auto/opengl.pm index 6e69206..eb50b5c 100644 --- a/config/auto/opengl.pm +++ b/config/auto/opengl.pm @@ -1,17 +1,123 @@ # Copyright (C) 2008, The Perl Foundation. # $Id $ + =head1 NAME config/auto/opengl.pm - Probe for OpenGL, GLU, and GLUT libraries + =head1 DESCRIPTION Determines whether the platform supports OpenGL, GLU and GLUT. The optimal result at this time is to find OpenGL 2.1, GLU 1.3, and GLUT API version 4. +You will typically need to install the headers and libraries required for +compiling OpenGL/GLU/GLUT applications as a separate step in addition to +the base development tools for your platform. The following sections detail +the steps needed to add OpenGL support for each platform for which we have +received this information -- details for additional platforms are welcome! + + +=head2 Mac OS X + +You will need to install the F<OpenGL Framework> and the F<GLUT Framework>. +With these in place, everything else should be autodetected. Mac OS X uses +a proprietary GLUT variant that supports more functions than standard +GLUT 3.7, but fewer than F<freeglut>. + + +=head2 Linux + +Linux distributions typically use F<freeglut> +(L<http://freeglut.sourceforge.net/>) for GLUT support, and F<Mesa> +(L<http://www.mesa3d.org/>) for GLU support. Either the Mesa headers +(for open source drivers) or the vendor headers (for closed source drivers) +can be used for core OpenGL/GLX support. Here are the package names for +various distributions; installing each of these will typically pull in a +number of prerequisites as well: + + +=head3 Debian/Ubuntu/etc. + +=over 4 + +=item GLUT + +F<freeglut3-dev> + +=item GLU + +F<libglu1-mesa-dev> + +=item OpenGL/GLX (open source drivers) + +F<libgl1-mesa-dev> + +=item OpenGL/GLX (NVIDIA drivers) + +F<nvidia-glx-dev> + +=back + + +=head3 Fedora/RedHat/CentOS/etc. + +=over 4 + +=item GLUT + +F<freeglut-devel> + +=item GLU + +F<mesa-libGLU-devel> + +=item OpenGL/GLX (open source drivers) + +F<mesa-libGL-devel> + +=item OpenGL/GLX (NVIDIA drivers) + +F<nvidia-devel> (?) + +=back + + +=head2 Windows + +On Windows, Parrot supports three different compiler environments, each of +which has different requirements for OpenGL support: + + +=head3 MSVC + +=over 4 + +=item OpenGL/GLU/WGL + +F<Windows SDK for Windows Server 2008 and .NET Framework 3.5> + +=item GLUT + +F<GLUT for Win32> (L<http://www.xmission.com/~nate/glut.html>) + +=back + + +=head3 MinGW + + XXXX: No details yet + + +=head3 cygwin + + XXXX: No details yet + + =cut + package auto::opengl; use strict; @@ -58,7 +164,7 @@ sub runstep { osname => $osname, cc => $cc, win32_gcc => '-lglut32 -lglu32 -lopengl32', - win32_nongcc => 'glut.lib glu.lib gl.lib', + win32_nongcc => 'opengl32.lib glu32.lib glut32.lib', darwin => '-framework OpenGL -framework GLUT', default => '-lglut -lGLU -lGL', } ); diff --git a/config/gen/call_list/opengl.in b/config/gen/call_list/opengl.in deleted file mode 100644 index 9c21dbf..0000000 --- a/config/gen/call_list/opengl.in +++ /dev/null @@ -1,7 +0,0 @@ -# Used by OpenGL (including GLU and GLUT) -v 3p -v JP -v JPi -v JPii -v fff -v ffff diff --git a/config/gen/makefiles/root.in b/config/gen/makefiles/root.in index 4028b15..c456163 100644 --- a/config/gen/makefiles/root.in +++ b/config/gen/makefiles/root.in @@ -163,6 +163,7 @@ GEN_CONFIGS = \ runtime/parrot/include/config.fpmc \ $(SRC_DIR)/platform.c \ #CONDITIONED_LINE(platform_asm): $(SRC_DIR)/platform_asm.s \ +#CONDITIONED_LINE(has_opengl): config/gen/call_list/opengl.in \ #CONDITIONED_LINE(has_glut): $(SRC_DIR)/glut_callbacks.c \ $(SRC_DIR)/core_pmcs.c \ CFLAGS \ @@ -180,6 +181,7 @@ GEN_CONFIGS = \ GEN_PASM_INCLUDES = \ runtime/parrot/include/signal.pasm \ #CONDITIONED_LINE(has_opengl): runtime/parrot/include/opengl_defines.pasm \ +#CONDITIONED_LINE(has_opengl): runtime/parrot/library/OpenGL_funcs.pir \ @TEMP_gen_pasm_includes@ CONFIGURE_GENERATED_FILES = \ @@ -188,6 +190,7 @@ CONFIGURE_GENERATED_FILES = \ ext/Parrot-Embed/Makefile.PL \ myconfig \ $(GEN_PASM_INCLUDES) \ + $(SRC_DIR)/call_list.txt \ MANIFEST.configure.generated @@ -212,7 +215,6 @@ GEN_HEADERS = \ $(INC_DIR)/pbcversion.h GEN_SOURCES = \ - $(SRC_DIR)/call_list.txt \ $(SRC_DIR)/core_ops.c \ $(SRC_DIR)/nci.c \ $(SRC_DIR)/core_ops_switch.c \ @@ -2167,8 +2169,8 @@ $(LIBNCI_TEST_SO): $(SRC_DIR)/nci_test$(O) # for use by runtime/parrot/library/OpenGL.pir $(LIBGLUTCB_SO): $(LIBPARROT) $(SRC_DIR)/glut_callbacks$(O) - $(LD) $(LD_LOAD_FLAGS) @ncilib_link_extra@ $(LDFLAGS) \ - @[EMAIL PROTECTED]@ $(SRC_DIR)/glut_callbacks$(O) $(C_LIBS) + $(LD) $(LD_LOAD_FLAGS) $(LDFLAGS) \ + @[EMAIL PROTECTED]@ $(SRC_DIR)/glut_callbacks$(O) $(ALL_PARROT_LIBS) # emacs etags # this needs exuberant-ctags diff --git a/config/gen/opengl.pm b/config/gen/opengl.pm index aae7026..d913325 100644 --- a/config/gen/opengl.pm +++ b/config/gen/opengl.pm @@ -13,14 +13,25 @@ Generates several files used by the OpenGL binding. These include: =item F<runtime/parrot/include/opengl_defines.pasm> +=item F<runtime/parrot/library/OpenGL_funcs.pir> + +=item F<config/gen/call_list/opengl.in> + +=item F<src/glut_callbacks.c> + =back +For information about Parrot's OpenGL support on different platforms, and +system libraries/headers that must be installed to enable OpenGL support, +see L<config/auto/opengl.pm>, where this support is detected. + =cut package gen::opengl; use strict; use warnings; +use File::Glob; use base qw(Parrot::Configure::Step); @@ -79,7 +90,205 @@ my @FREEGLUT_CALLBACKS = ( [ 'Mouse Wheel', 'int wheel, int direction, int x, int y' ], ); +my %C_TYPE = ( + GLvoid => 'void', + GLUnurbs => 'void', + GLUquadric => 'void', + GLUtesselator => 'void', + gleGC => 'void', + muiObject => 'void', + SphereMap => 'void', + Display => 'void', + XVisualInfo => 'void', + _CGLContextObject => 'void', + GLXHyperpipeConfigSGIX => 'void', + GLXHyperpipeNetworkSGIX => 'void', + + wchar_t => 'void', + + GLXContext => 'void*', + GLXFBConfig => 'void*', + GLXFBConfigSGIX => 'void*', + CGLContextObj => 'void*', + CGLPixelFormatObj => 'void*', + CGLRendererInfoObj => 'void*', + CGLPBufferObj => 'void*', + + GLchar => 'char', + GLcharARB => 'char', + GLbyte => 'signed char', + GLubyte => 'unsigned char', + GLboolean => 'unsigned char', + + GLshort => 'short', + GLushort => 'unsigned short', + GLhalfARB => 'unsigned short', + GLhalfNV => 'unsigned short', + + Bool => 'int', + Status => 'int', + GLint => 'int', + GLsizei => 'int', + int32_t => 'int', + + GLenum => 'unsigned int', + CGLPixelFormatAttribute => 'unsigned int', + CGLRendererProperty => 'unsigned int', + CGLContextEnable => 'unsigned int', + CGLContextParameter => 'unsigned int', + CGLGlobalOption => 'unsigned int', + CGLError => 'unsigned int', + SphereMapFlags => 'unsigned int', + + GLuint => 'unsigned int', + GLbitfield => 'unsigned int', + GLhandleARB => 'unsigned int', + GLXVideoDeviceNV => 'unsigned int', + + XID => 'unsigned long', + Window => 'unsigned long', + Drawable => 'unsigned long', + Font => 'unsigned long', + Pixmap => 'unsigned long', + Cursor => 'unsigned long', + Colormap => 'unsigned long', + GContext => 'unsigned long', + KeySym => 'unsigned long', + GLXContextID => 'unsigned long', + GLXPixmap => 'unsigned long', + GLXDrawable => 'unsigned long', + GLXPbuffer => 'unsigned long', + GLXWindow => 'unsigned long', + GLXFBConfigID => 'unsigned long', + GLXPbufferSGIX => 'unsigned long', + GLXFBConfigIDSGIX => 'unsigned long', + GLXVideoSourceSGIX => 'unsigned long', + + int64_t => 'long long', + GLint64EXT => 'signed long long', + GLuint64EXT => 'unsigned long long', + + GLfloat => 'float', + GLclampf => 'float', + GLdouble => 'double', + GLclampd => 'double', + gleDouble => 'double', + + GLintptr => 'ptrdiff_t', + GLsizeiptr => 'ptrdiff_t', + GLintptrARB => 'ptrdiff_t', + GLsizeiptrARB => 'ptrdiff_t', +); + +my %NCI_TYPE = ( + void => 'v', + char => 'c', + short => 's', + int => 'i', + long => 'l', + ptrdiff_t => 'l', + # Requires RT 53406 + # longlong => 'L', + float => 'f', + double => 'd', + + 'char*' => 't', + + 'short*' => 'p', + 'int*' => 'p', + 'long*' => 'p', + 'longlong*' => 'p', + 'float*' => 'p', + 'double*' => 'p', + 'void*' => 'p', + + 'char**' => 'p', + 'short**' => 'p', + 'int**' => 'p', + 'long**' => 'p', + 'longlong**' => 'p', + 'float**' => 'p', + 'double**' => 'p', + 'void**' => 'p', + + 'double***' => 'p', +); + +my %OVERRIDE = ( + 'glutInit' => 'v3p', +); + +my @IGNORE = ( + # Most of these are limitations of this module or Parrot NCI + + # Don't handle GetProcAddress type functions yet + 'glutGetProcAddress', + 'glXGetProcAddress', + 'glXGetProcAddressARB', + + # Don't handle this odd create/callback register function yet + 'glutCreateMenu', + + # Don't handle GLU or MUI callbacks yet + 'gluNurbsCallback', + 'gluQuadricCallback', + 'gluTessCallback', + 'muiSetCallback', + 'muiSetNonMUIcallback', + 'handler', + 'callback', + + # Don't handle functions without "namespace" prefixes matching library + 'rot_axis', + 'rot_about_axis', + 'rot_omega', + 'rot_prince', + 'urot_axis', + 'urot_about_axis', + 'urot_omega', + 'urot_prince', + 'uview_direction', + 'uviewpoint', + + # Can't handle longlong until RT 53406 is done + 'glPresentFrameKeyedNV', + 'glPresentFrameDualFillNV', + 'glXSwapBuffersMscOML', + 'glXWaitForMscOML', + 'glXWaitForSbcOML', + + # Can't handle weird data types specified only in proprietary headers + 'glXCreateGLXVideoSourceSGIX', + 'glXAssociateDMPbufferSGIX', + + # Ignore internal GLUT Win32 compatibility hackage + 'exit', +); + +my @SKIP = ( + # Apple CGL OpenGL API conversion macros + 'CGLMacro.h', + + # Internal headers for GLE (OpenGL Extrusions) library + 'extrude.h', + 'segment.h', + + # Rotation math utility functions from GLE + 'gutil.h', + + # Plane math utility functions/macros from GLE + 'intersect.h', + + # MUI (internal?) headers lacking "namespace" identifier prefixes + 'browser.h', + 'gizmo.h', + 'hslider.h', + 'vslider.h', +); + my $MACRO_FILE = 'runtime/parrot/include/opengl_defines.pasm'; +my $FUNCS_FILE = 'runtime/parrot/library/OpenGL_funcs.pir'; +my $SIGS_FILE = 'config/gen/call_list/opengl.in'; my $C_FILE = 'src/glut_callbacks.c'; @@ -87,37 +296,76 @@ sub _init { my $self = shift; return { - description => q{Generating OpenGL bindings}, - result => q{}, + description => q{Generating OpenGL bindings}, + result => q{}, } } sub runstep { - my ( $self, $conf ) = @_; + my ($self, $conf) = @_; - unless ( $conf->data->get('has_opengl') ) { + unless ($conf->data->get('has_opengl')) { $self->set_result('skipped'); return 1; } + my $verbose = $conf->options->get('verbose') || 0; + + my @include_paths_win32 = grep /\S/ => split /;/ => ($ENV{INCLUDE} || ''); + + s{\\}{/}g foreach @include_paths_win32; + my @header_globs = ( + # Default location for most UNIX-like platforms '/usr/include/GL/*.h', + + # Mac OS X '/System/Library/Frameworks/OpenGL.framework/Headers/*.h', '/System/Library/Frameworks/GLUT.framework/Headers/*.h', + + # Windows/MSVC + (map "$_/gl/*.h" => @include_paths_win32), + +# "$ENV{HOME}/src/osx/headers/GLUT/*.h", +# "$ENV{HOME}/src/osx/headers/OpenGL/*.h", +# "$ENV{HOME}/src/osx-10.4/GLUT/*.h", +# "$ENV{HOME}/src/osx-10.4/OpenGL/*.h", +# "$ENV{HOME}/src/cygwin/opengl-1.1.0/GLUI_v2_1_beta/*.h", +# "$ENV{HOME}/src/cygwin/opengl-1.1.0/glut-3.7.3/include/GL/*.h", +# "$ENV{HOME}/src/cygwin/opengl-1.1.0/glut-3.7.3/include/mui/*.h", +# "$ENV{HOME}/src/glut-3.7.6/include/GL/*.h", +# "$ENV{HOME}/src/glut-3.7.6/include/mui/*.h", ); - my @header_files = sort map {glob} @header_globs; + my @header_files = sort map {File::Glob::bsd_glob($_)} @header_globs; + + my %skip = map {($_ => 1)} @SKIP; + @header_files = grep {my ($file) = m{([^/]+)$}; !$skip{$file}} @header_files; - $self->gen_opengl_defines($conf, [EMAIL PROTECTED]); - $self->gen_glut_callbacks($conf); + die "OpenGL enabled and detected, but no OpenGL headers found!" + unless @header_files; + + my $autogen_header = <<'HEADER'; +# DO NOT EDIT THIS FILE. +# +# Any changes made here will be lost. +# +# This file is generated automatically by config/gen/opengl.pm +# using the following files: +# +HEADER + + $autogen_header .= "# $_\n" foreach @header_files; + + $self->gen_opengl_defines ($conf, [EMAIL PROTECTED], $autogen_header, $verbose); + $self->gen_opengl_wrappers($conf, [EMAIL PROTECTED], $autogen_header, $verbose); + $self->gen_glut_callbacks ($conf); return 1; } sub gen_opengl_defines { - my ( $self, $conf, $header_files ) = @_; - - my $verbose = $conf->options->get('verbose'); + my ($self, $conf, $header_files, $autogen_header, $verbose) = @_; my (%defs, @macros); my $max_len = 0; @@ -129,12 +377,13 @@ sub gen_opengl_defines { while (<$header>) { my (@F) = split; next unless @F > 2 and $F[0] eq '#define'; - next unless $F[1] =~ /^(GL(?:X|(?:UT?))?)_/; + next unless $F[1] =~ /^(AGL|CGL|WGL|GLX|MUI|SMAP|TUBE|GL[A-Z]*)_/; + next if $F[1] =~ /\(/; $max_len = length $F[1] if $max_len < length $F[1]; my $api = $1; - if ($F[2] =~ /^GL/) { + if ($F[2] =~ /^(?:[ACW])?GL/) { push @macros, [$api, $F[1], $F[2]]; } elsif ( $F[2] =~ /^0x[0-9a-fA-F]+$/ @@ -149,7 +398,7 @@ sub gen_opengl_defines { foreach my $macro (@macros) { my ($api, $define, $value) = @$macro; - my ($val_api) = $value =~ /^(GL[A-Z]*)_/; + my ($val_api) = $value =~ /^((?:[ACW])?GL[A-Z]*)_/; $defs{$api}{$define} = $defs{$val_api}{$value}; @@ -160,17 +409,7 @@ sub gen_opengl_defines { open my $macros, '>', $MACRO_FILE or die "Could not open macro file '$MACRO_FILE' for write: $!"; - print $macros <<"HEADER"; -# DO NOT EDIT THIS FILE. -# -# Any changes made here will be lost. -# -# This file is generated automatically by config/gen/opengl.pm -# using the following files: -# -HEADER - - print $macros "# $_\n" foreach @$header_files; + print $macros $autogen_header; print $macros "\n\n"; foreach my $api (sort keys %defs) { @@ -187,6 +426,308 @@ HEADER return 1; } +sub gen_opengl_wrappers { + my ($self, $conf, $header_files, $autogen_header, $verbose) = @_; + + my %IGNORE = map {($_ => 1)} @IGNORE; + + my (%pass, %fail, %ignore, %sigs, %funcs); + + # PHASE 1: Parse Headers + foreach my $file (@$header_files) { + open my $header, '<', $file + or die "Could not open header '$file': $!"; + + PROTO: + while (<$header>) { + # Get rid of C comments + s{/\*.*?\*/}{}g; + if (m{/\*}) { + chomp; + $_ .= <$header>; + redo; + } + + # Make sure the entire parameter list is on a single line + next unless /\(/; + unless (/\)/) { + chomp; + $_ .= <$header>; + redo; + } + + # We only care about regular function prototypes + next unless /API/ or /\bextern\b/ or /\bmui[A-Z]/; + next if /^#/; + next if /\btypedef\b/; + + # Save a (space compressed) copy of the source line + # for later error reporting + my $orig = $_; + $orig =~ s/\s+/ /g; + $orig =~ s/ $/\n/; + + # Get rid of junk needed for C, but not for Parrot NCI; + # also do general cleanup to make parsing easier + s/\bAVAILABLE_MAC_OS_X_VERSION_\d+_\d+_AND_LATER\b\s*//; + s/\b__cdecl\b\s*//; + s/\b__stdcall\b\s*//; + s/\b_CRTIMP\b\s*//; + s/\bextern\b\s*//; + s/\bstatic\b\s*//; + s/\bconst\b\s*//g; + s/\benum\b\s*//g; + s/\bstruct\b\s*//g; + s/\b[A-Z]*API[A-Z]*\s*//g; + s/\s*\*\s*/* /g; + s/\* \*/**/g; + s/\s*,\s*/, /g; + s/\s*\(\s*/(/g; + s/\s*\)\s*/)/g; + s/\s+/ /g; + s/\s+$//; + s/^\s+//; + + # Canonicalize types + s/\b(\w+)\b/$C_TYPE{$1} ? $C_TYPE{$1} : $1/eg; + s/\b(?:un)?signed //g; + s/\blong long\b/longlong/g; + + # Parse the function prototype, trying hard to capture name + my ($return, $name, $params) = /^(\w+\**) (\w+)\(([^)]*)\);$/; + ($name) = /^\w+\(?\** (\w+)\)?/ unless defined $name; + + # Is this a function we're ignoring for now or handling elsewhere? + if (defined $name) { + # Callback reg functions handled by gen_*_callbacks() + $pass {$file}++, next if /\bglut[A-Z][a-zA-Z]+Func\b/; + $ignore{$file}++, next if /\bsmap[A-Z][a-zA-Z]+Func\b/; + + # Ignore all library-internal functions + $ignore{$file}++, next if $name =~ /^__/; + $ignore{$file}++, next if $name =~ /_ATEXIT_HACK$/; + + # Miscellaneous ignores + $ignore{$file}++, next if $IGNORE{$name}; + } + + # Successful parse? + unless (defined $return and defined $name and defined $params) { + $fail{$file}++; + $name ||= ''; + warn "In OpenGL header '$file', can't parse canonicalized prototype for '$name':\n $_\nOriginal prototype:\n $orig\n"; + next; + } + + # Figure out what group/library this function belongs to + my ($group) = $name =~ /^(agl|CGL|wgl|glX|mui|smap|gl[a-z]*)/; + + unless ($group) { + $fail{$file}++; + warn "In OpenGL header '$file', found a non-OpenGL function: '$name'\n"; + next; + } + + $group = lc $group; + + # Convert return and param types to NCI signature + my $nci_sig = $OVERRIDE{$name}; + + unless ($nci_sig) { + $params = '' if $params eq 'void'; + my @params = split /, / => $params; + unshift @params, $return; + + foreach my $param (@params) { + 1 while $param =~ s/(\w+\**) (\w+)\s*\[\d*\]/$1* $2/; + $param =~ s/ \w+$// unless $NCI_TYPE{$param}; + unless ($NCI_TYPE{$param}) { + $fail{$file}++; + warn "In OpenGL header '$file', prototype '$name', can't handle type '$param'; original prototype:\n $orig\n"; + next PROTO; + } + $nci_sig .= $NCI_TYPE{$param}; + } + + if ($nci_sig =~ /.v/) { + $fail{$file}++; + warn "In OpenGL header '$file', prototype '$name', there is a void parameter; original prototype:\n $orig\n"; + next PROTO; + } + } + + # Success! Save results. + $pass{$file}++; + $sigs{$nci_sig}++; + push @{$funcs{$group}}, [$name, $nci_sig]; + + print "$group\t$nci_sig\t$return $name($params);\n" if $verbose >= 3; + } + } + + # PHASE 2: Write unique signatures to NCI signatures file + my @sigs = sort keys %sigs; + + open my $sigs, '>', $SIGS_FILE + or die "Could not open NCI signatures file '$SIGS_FILE' for write: $!"; + + print $sigs <<"HEADER"; +# Used by OpenGL (including GLU and GLUT) +# +$autogen_header + +# GLUT callbacks +v JP +v JPi +v JPii + +# Generated signatures +HEADER + + foreach my $nci_sig (@sigs) { + my ($return, $params) = $nci_sig =~ /^(.)(.*)$/; + + print $sigs "$return $params\n"; + } + + close $sigs; + $conf->append_configure_log($SIGS_FILE); + + # PHASE 3: Write function lists for each OpenGL-related library + + open my $funcs, '>', $FUNCS_FILE + or die "Could not open function list file '$FUNCS_FILE' for write: $!"; + + print $funcs $autogen_header; + print $funcs <<'GLUTCB_FUNCS'; + + +.sub _glutcb_func_list + .local pmc glutcb_funcs + glutcb_funcs = new 'ResizableStringArray' + push glutcb_funcs, 'glutcbCloseFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbDisplayFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbIdleFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbMenuDestroyFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbOverlayDisplayFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbWMCloseFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbEntryFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbMenuStateFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbVisibilityFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbWindowStatusFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbButtonBoxFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbDialsFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbMotionFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbPassiveMotionFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbReshapeFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbSpaceballButtonFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbTabletMotionFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbKeyboardFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbKeyboardUpFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbMenuStatusFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbSpaceballMotionFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbSpaceballRotateFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbSpecialFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbSpecialUpFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbMouseFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbMouseWheelFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbTabletButtonFunc' + push glutcb_funcs, 'vJP' + push glutcb_funcs, 'glutcbTimerFunc' + push glutcb_funcs, 'vJPii' + push glutcb_funcs, 'glutcbJoystickFunc' + push glutcb_funcs, 'vJPi' + + .return (glutcb_funcs) +.end +GLUTCB_FUNCS + + foreach my $group (sort keys %funcs) { + my $sub_name = "_${group}_func_list"; + my $list_name = "${group}_funcs"; + + print $funcs <<"SUB_HEADER"; + + +.sub $sub_name + .local pmc $list_name + $list_name = new 'ResizableStringArray' + +SUB_HEADER + + my @funcs = sort {$a->[0] cmp $b->[0]} @{$funcs{$group}}; + foreach my $func (@funcs) { + my ($name, $sig) = @$func; + + print $funcs <<"FUNCTION" + push $list_name, '$name' + push $list_name, '$sig' +FUNCTION + } + print $funcs <<"SUB_FOOTER"; + + .return ($list_name) +.end +SUB_FOOTER + } + + close $funcs; + $conf->append_configure_log($FUNCS_FILE); + + # PHASE 4: Print statistical info on parse results if verbose + if ($verbose) { + print "\nPASS FAIL IGNORE HEADER\n"; + foreach my $file (@$header_files, 'TOTAL') { + my $pass = $pass {$file} || 0; + my $fail = $fail {$file} || 0; + my $ignore = $ignore{$file} || 0; + + printf "%4d %4d %4d %s\n", $pass, $fail, $ignore, $file; + + $pass {TOTAL} += $pass; + $fail {TOTAL} += $fail; + $ignore{TOTAL} += $ignore; + } + + print "\nCOUNT NCI SIGNATURE\n" if $verbose >= 2; + foreach my $nci_sig (@sigs, 'TOTAL') { + printf "%5d %s\n", $sigs{$nci_sig}, $nci_sig if $verbose >= 2; + $sigs{TOTAL} += $sigs{$nci_sig}; + } + + printf "\n===> %d unique signatures successfully translated.\n", + scalar @sigs + } + + return 1; +} + sub gen_glut_callbacks { my ( $self, $conf ) = @_; @@ -251,11 +792,11 @@ sub gen_glut_callbacks { foreach (@callbacks) { $enums .= " $_->{enum},\n"; - $thunks .= " void $_->{thunk}($_->{proto});\n"; - $reg_funcs .= "PARROT_API void $_->{glutcb}(Parrot_Interp, PMC *);\n"; + $thunks .= " void $_->{thunk}($_->{proto});\n"; + $reg_funcs .= "PARROT_DYNEXT_EXPORT void $_->{glutcb}(Parrot_Interp, PMC *);\n"; } - my $header = <<HEADER; + my $header = <<"HEADER"; /* # DO NOT EDIT THIS FILE. # @@ -283,6 +824,8 @@ cannot be used. */ +#define PARROT_IN_EXTENSION + #include <$glut_header> #include "parrot/parrot.h" @@ -306,14 +849,14 @@ typedef struct GLUT_CB_data { GLUT_CB_data callback_data[GLUT_NUM_CALLBACKS]; - int is_safe(Parrot_Interp, PMC *); + int is_safe(Parrot_Interp, PMC *); - void glut_timer_func(int); -PARROT_API void glutcbTimerFunc(Parrot_Interp, PMC *, unsigned int, int); + void glut_timer_func(int); +PARROT_DYNEXT_EXPORT void glutcbTimerFunc(Parrot_Interp, PMC *, unsigned int, int); #if GLUT_API_VERSION >= 4 - void glut_joystick_func(unsigned int, int, int, int); -PARROT_API void glutcbJoystickFunc(Parrot_Interp, PMC *, int); + void glut_joystick_func(unsigned int, int, int, int); +PARROT_DYNEXT_EXPORT void glutcbJoystickFunc(Parrot_Interp, PMC *, int); #endif $thunks @@ -356,7 +899,7 @@ glut_timer_func(int data) Parrot_runops_fromc_args_event(interp, sub, "vi", data); } -PARROT_API +PARROT_DYNEXT_EXPORT void glutcbTimerFunc(PARROT_INTERP, PMC *sub, unsigned int milliseconds, int data) { @@ -391,7 +934,7 @@ glut_joystick_func(unsigned int buttons, int xaxis, int yaxis, int zaxis) Parrot_runops_fromc_args_event(interp, sub, "viiii", buttons, xaxis, yaxis, zaxis); } -PARROT_API +PARROT_DYNEXT_EXPORT void glutcbJoystickFunc(PARROT_INTERP, PMC *sub, int pollinterval) { @@ -431,7 +974,7 @@ $_->{thunk}($_->{params}) Parrot_runops_fromc_args_event(interp, sub, "$_->{sig}"$_->{args}); } -PARROT_API +PARROT_DYNEXT_EXPORT void $_->{glutcb}(PARROT_INTERP, PMC *sub) { @@ -447,7 +990,7 @@ IMPLEMENTATION } - my $footer = <<FOOTER; + my $footer = <<'FOOTER'; /* diff --git a/runtime/parrot/library/OpenGL.pir b/runtime/parrot/library/OpenGL.pir index a45c310..6a06a10 100644 --- a/runtime/parrot/library/OpenGL.pir +++ b/runtime/parrot/library/OpenGL.pir @@ -76,8 +76,7 @@ include: .namespace ['OpenGL'] -.include 'datatypes.pasm' -.include 'iterator.pasm' +.include 'library/OpenGL_funcs.pir' =item _opengl_init() @@ -107,18 +106,21 @@ the known different filenames for each library in turn before giving up. libnames = new 'ResizableStringArray' push libnames, 'libGL' + push libnames, 'opengl32' push libnames, '/System/Library/Frameworks/OpenGL.framework/OpenGL' libgl = _load_lib_with_fallbacks('GL', libnames) set_global '_libgl', libgl libnames = new 'ResizableStringArray' push libnames, 'libGLU' + push libnames, 'glu32' push libnames, '/System/Library/Frameworks/OpenGL.framework/OpenGL' libglu = _load_lib_with_fallbacks('GLU', libnames) set_global '_libglu', libglu libnames = new 'ResizableStringArray' push libnames, 'libglut' + push libnames, 'glut32' push libnames, '/System/Library/Frameworks/GLUT.framework/GLUT' libglut = _load_lib_with_fallbacks('GLUT', libnames) set_global '_libglut', libglut @@ -148,7 +150,6 @@ match can be found on the system. .local pmc list_iter list_iter = new 'Iterator', fallback_list - list_iter = .ITERATE_FROM_START .local string libname .local pmc library @@ -198,120 +199,6 @@ Create NCI wrappers for all GL, GLU, and GLUT functions _wrap_nci_list(namespace, libglutcb, glutcb_funcs) .end -.sub _gl_func_list - .local pmc gl_funcs - gl_funcs = new 'ResizableStringArray' - push gl_funcs, 'glBegin' - push gl_funcs, 'vi' - push gl_funcs, 'glClear' - push gl_funcs, 'vi' - push gl_funcs, 'glColor3f' - push gl_funcs, 'vfff' - push gl_funcs, 'glEnd' - push gl_funcs, 'v' - push gl_funcs, 'glFlush' - push gl_funcs, 'v' - push gl_funcs, 'glVertex3f' - push gl_funcs, 'vfff' - push gl_funcs, 'glRotatef' - push gl_funcs, 'vffff' - - .return (gl_funcs) -.end - -.sub _glu_func_list - .local pmc glu_funcs - glu_funcs = new 'ResizableStringArray' - - .return (glu_funcs) -.end - -.sub _glut_func_list - .local pmc glut_funcs - glut_funcs = new 'ResizableStringArray' - push glut_funcs, 'glutInit' - push glut_funcs, 'v3p' - push glut_funcs, 'glutInitDisplayMode' - push glut_funcs, 'vi' - push glut_funcs, 'glutCreateWindow' - push glut_funcs, 'it' - push glut_funcs, 'glutDestroyWindow' - push glut_funcs, 'vi' - push glut_funcs, 'glutMainLoop' - push glut_funcs, 'v' - push glut_funcs, 'glutPostRedisplay' - push glut_funcs, 'v' - push glut_funcs, 'glutSwapBuffers' - push glut_funcs, 'v' - - .return (glut_funcs) -.end - -.sub _glutcb_func_list - .local pmc glutcb_funcs - glutcb_funcs = new 'ResizableStringArray' - push glutcb_funcs, 'glutcbCloseFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbDisplayFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbIdleFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbMenuDestroyFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbOverlayDisplayFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbWMCloseFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbEntryFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbMenuStateFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbVisibilityFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbWindowStatusFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbButtonBoxFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbDialsFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbMotionFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbPassiveMotionFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbReshapeFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbSpaceballButtonFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbTabletMotionFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbKeyboardFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbKeyboardUpFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbMenuStatusFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbSpaceballMotionFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbSpaceballRotateFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbSpecialFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbSpecialUpFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbMouseFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbMouseWheelFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbTabletButtonFunc' - push glutcb_funcs, 'vJP' - push glutcb_funcs, 'glutcbTimerFunc' - push glutcb_funcs, 'vJPii' - push glutcb_funcs, 'glutcbJoystickFunc' - push glutcb_funcs, 'vJPi' - - .return (glutcb_funcs) -.end - =item _wrap_nci_list(pmc namespace, pmc library, pmc nci_list) @@ -331,7 +218,6 @@ alternating function names and Parrot NCI signatures. .local pmc list_iter list_iter = new 'Iterator', nci_list - list_iter = .ITERATE_FROM_START .local string func_name, signature .local pmc function