blob: 61e02e87b4d53854235e8c3f7e784e5ae4c4bb32 [file] [log] [blame]
Lionel Ulmerbff705d2000-06-12 01:21:18 +00001#!/usr/bin/perl -w
2
3# This script is called thus :
4#
5# make_opengl path_to_spec_file opengl_version
6#
7# - path_to_spec_file is the path to the directory where the OpenGL
8# spec files are located. These files are part of the OpenGL
9# sample implementation CVS tree and are located in
10# CVS_ROOT/projects/ogl-sample/main/doc/registry/specs.
Lionel Ulmer15a4a772001-03-04 01:05:20 +000011# You can find them on the web at the following URL :
12# http://oss.sgi.com/cgi-bin/cvsweb.cgi/projects/ogl-sample/main/doc/registry/specs/
Lionel Ulmerbff705d2000-06-12 01:21:18 +000013#
14# - opengl_version is the OpenGL version emulated by the library
15# (can be 1.0 to 1.2).
16#
17# This script generates the three following files :
18#
19# - opengl32.spec : the spec file giving all the exported functions
20# of the OpenGL32.DLL library. These functions are the one an
21# application can directly link to (and are all the functions
22# defined in the OpenGL core for the version defined by
23# 'opengl_version').
24#
25# - opengl_norm.c : this file contains the thunks for all OpenGL
26# functions that are defined in 'opengl32.spec'. The corresponding
27# functions NEED to be defined in Linux's libGL or the library
28# won't be able to be linked in.
29#
30# - opengl_ext.c : in this file are stored thunks for ALL possible
31# OpenGL extensions (at least, all the extensions that are defined
32# in the OpenGL extension registry). Contrary to 'opengl_norm.c',
33# you do not need to have these extensions in your libGL to have
34# OpenGL work (as they are resolved at run-time using
35# glXGetProcAddressARB).
36#
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000037# Copyright 2000 Lionel Ulmer
38#
39# This library is free software; you can redistribute it and/or
40# modify it under the terms of the GNU Lesser General Public
41# License as published by the Free Software Foundation; either
42# version 2.1 of the License, or (at your option) any later version.
43#
44# This library is distributed in the hope that it will be useful,
45# but WITHOUT ANY WARRANTY; without even the implied warranty of
46# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
47# Lesser General Public License for more details.
48#
49# You should have received a copy of the GNU Lesser General Public
50# License along with this library; if not, write to the Free Software
51# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
52#
Lionel Ulmerbff705d2000-06-12 01:21:18 +000053
54#
Lionel Ulmer15a4a772001-03-04 01:05:20 +000055# Files to generate
Lionel Ulmerbff705d2000-06-12 01:21:18 +000056#
Lionel Ulmer15a4a772001-03-04 01:05:20 +000057$spec_file = "opengl32.spec";
58$norm_file = "opengl_norm.c";
59$ext_file = "opengl_ext.c";
Lionel Ulmerbff705d2000-06-12 01:21:18 +000060
Lionel Ulmer15a4a772001-03-04 01:05:20 +000061# Set to 0 for removing the ENTER / LEAVE GL calls
62$gen_thread_safe = 1;
63# Prefix used for the local variables
64$ext_prefix = "func_";
65# If set to 1, generate TRACEs for each OpenGL function
66$gen_traces = 1;
Lionel Ulmerbff705d2000-06-12 01:21:18 +000067
Lionel Ulmer15a4a772001-03-04 01:05:20 +000068#
69# List of categories to put in the 'opengl_norm.c' file
70#
Alexandre Julliard7cae5582002-06-01 02:55:48 +000071%cat_1_0 = ( "display-list" => 1,
72 "drawing" => 1,
73 "drawing-control" => 1,
74 "feedback" => 1,
75 "framebuf" => 1,
76 "misc" => 1,
77 "modeling" => 1,
78 "pixel-op" => 1,
79 "pixel-rw" => 1,
80 "state-req" => 1,
Lionel Ulmer15a4a772001-03-04 01:05:20 +000081 "xform" => 1 );
Alexandre Julliard7cae5582002-06-01 02:55:48 +000082%cat_1_1 = ( %cat_1_0,
Lionel Ulmer15a4a772001-03-04 01:05:20 +000083 "1_1" => 1 );
Alexandre Julliard7cae5582002-06-01 02:55:48 +000084%cat_1_2 = ( %cat_1_1,
Lionel Ulmer8def4002003-07-08 21:07:03 +000085 "VERSION_1_2" => 1 );
Lionel Ulmer0e999e32004-03-02 20:54:17 +000086%cat_1_3 = ( %cat_1_2,
87 "VERSION_1_3" => 1 );
88%cat_1_4 = ( %cat_1_3,
89 "VERSION_1_4" => 1 );
90%cat_1_5 = ( %cat_1_4,
91 "VERSION_1_5" => 1 );
Lionel Ulmer15a4a772001-03-04 01:05:20 +000092
93%norm_categories = ();
94
95#
96# This hash table gives the conversion between OpenGL types and what
97# is used by the TRACE printfs
98#
Alexandre Julliard7cae5582002-06-01 02:55:48 +000099%debug_conv =
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000100 ("GLbitfield" => "%d",
101 "GLboolean" => "%d",
102 "GLbyte" => "%d",
103 "GLclampd" => "%f",
104 "GLclampf" => "%f",
105 "GLdouble" => "%f",
106 "GLenum" => "%d",
107 "GLfloat" => "%f",
108 "GLint" => "%d",
109 "GLshort" => "%d",
110 "GLsizei" => "%d",
111 "GLstring" => "%s",
112 "GLubyte" => "%d",
113 "GLuint" => "%d",
114 "GLushort" => "%d",
Lionel Ulmer9ac8ba12003-06-13 16:31:17 +0000115 "GLhalfNV" => "%d",
116 "GLintptrARB" => "%d",
117 "GLsizeiptrARB" => "%d",
Lionel Ulmer0e999e32004-03-02 20:54:17 +0000118 "GLintptr" => "%d",
119 "GLsizeiptr" => "%d",
120 "GLhandleARB" => "%d",
121 "GLcharARB" => "%c",
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000122 "GLvoid" => "(void)",
123 "_GLfuncptr" => "%p");
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000124
125#
126# This hash table gives the conversion between OpenGL types and what
127# is used in the .spec file
128#
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000129%arg_conv =
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000130 ("GLbitfield" => [ "long", 4 ],
131 "GLboolean" => [ "long", 4 ],
132 "GLbyte" => [ "long", 4 ],
133 "GLclampd" => [ "double", 8 ],
134 "GLclampf" => [ "long", 4 ],
135 "GLdouble" => [ "double", 8 ],
136 "GLenum" => [ "long", 4 ],
137 "GLfloat" => [ "long", 4 ],
138 "GLint" => [ "long", 4 ],
139 "GLshort" => [ "long", 4 ],
140 "GLsizei" => [ "long", 4 ],
141 "GLstring" => [ "str", 4 ],
142 "GLubyte" => [ "long", 4 ],
143 "GLuint" => [ "long", 4 ],
144 "GLushort" => [ "long", 4 ],
Lionel Ulmer9ac8ba12003-06-13 16:31:17 +0000145 "GLhalfNV" => [ "long", 4 ],
146 "GLintptrARB" => [ "long", 4 ],
147 "GLsizeiptrARB" => [ "long", 4 ],
Lionel Ulmer0e999e32004-03-02 20:54:17 +0000148 "GLhandleARB" => [ "long", 4 ],
149 "GLcharARB" => [ "long", 4 ],
150 "GLintptr" => [ "long", 4 ],
151 "GLsizeiptr" => [ "long", 4 ],
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000152 "GLvoid" => [ "void", 4 ],
153 "_GLfuncptr" => [ "ptr", 4 ]);
154
155#
Lionel Ulmer334aacd2003-06-20 21:29:28 +0000156# Used to convert some types
157#
158sub ConvertType {
159 my ($type) = @_;
160
161 %hash = ( "GLstring" => "const GLubyte *",
162 "GLintptrARB" => "ptrdiff_t",
163 "GLsizeiptrARB" => "ptrdiff_t",
Lionel Ulmer0e999e32004-03-02 20:54:17 +0000164 "GLintptr" => "ptrdiff_t",
165 "GLsizeiptr" => "ptrdiff_t",
166 "GLhandleARB" => "unsigned int",
167 "GLcharARB" => "char",
Lionel Ulmer334aacd2003-06-20 21:29:28 +0000168 "GLhalfNV" => "unsigned short" );
169
Christian Costa8bbabd12004-04-14 23:58:33 +0000170 foreach $org (reverse(sort(keys %hash))) {
Lionel Ulmer334aacd2003-06-20 21:29:28 +0000171 if ($type =~ /$org/) {
172 ($before, $after) = ($type =~ /^(.*)$org(.*)$/);
173 return "$before$hash{$org}$after";
174 }
175 }
176 return $type;
177}
178
179#
Lionel Ulmer0e999e32004-03-02 20:54:17 +0000180# Used to convert some variable names
181#
182sub ConvertVarName {
183 my ($type) = @_;
184
185 %hash = ( "near" => "nearParam",
186 "far" => "farParam" );
187
188 foreach $org (keys %hash) {
189 if ($type =~ /$org/) {
190 ($before, $after) = ($type =~ /^(.*)$org(.*)$/);
191 return "$before$hash{$org}$after";
192 }
193 }
194 return $type;
195}
196
197#
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000198# This functions generates the thunk for a given function.
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000199#
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000200sub GenerateThunk {
201 my ($func_ref, $comment, $prefix, $thread_safe) = @_;
202 my ($ret) = ("");
203 my ($call_arg) = ("");
204 my ($trace_arg) = ("");
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000205
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000206 # If for opengl_norm.c, generate a nice heading otherwise Patrik won't be happy :-)
Lionel Ulmer7fc3a3b2001-07-31 00:08:05 +0000207 # Patrik says: Well I would be even happier if a (OPENGL32.@) was added as well. Done. :-)
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000208 if ($comment eq 1) {
209 $ret = $ret . "/***********************************************************************\n";
Lionel Ulmer7fc3a3b2001-07-31 00:08:05 +0000210 $ret = $ret . " * " . $func_ref->[0] . " (OPENGL32.@)\n";
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000211 $ret = $ret . " */\n";
212 }
Lionel Ulmer334aacd2003-06-20 21:29:28 +0000213 $ret = $ret . ConvertType($func_ref->[1]) . " WINAPI wine_" . $func_ref->[0] . "( ";
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000214 for ($i = 0; $i <= $#{@{$func_ref->[2]}}; $i++) {
Lionel Ulmer0e999e32004-03-02 20:54:17 +0000215 ## Quick debug code :-)
216 ## print $func_ref->[2]->[$i]->[1] . "\n";
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000217 $type = $func_ref->[2]->[$i]->[0];
Lionel Ulmer0e999e32004-03-02 20:54:17 +0000218 $name = ConvertVarName($func_ref->[2]->[$i]->[1]);
Lionel Ulmer334aacd2003-06-20 21:29:28 +0000219 $ret = $ret . ConvertType($type) . " $name";
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000220 $call_arg = $call_arg . "$name";
221 if ($type =~ /\*/) {
222 $trace_arg = $trace_arg . "%p";
223 } else {
224 $trace_arg = $trace_arg . $debug_conv{$type};
225 }
226 if ($i != $#{@{$func_ref->[2]}}) {
227 $ret = $ret . ", ";
228 $call_arg = $call_arg . ", ";
229 $trace_arg = $trace_arg . ", ";
230 } else {
231 $ret = $ret . " ";
232 $call_arg = $call_arg . " ";
233 }
234 }
235 $ret = $ret . ") {\n";
236 if ($func_ref->[1] ne "void") {
Lionel Ulmer334aacd2003-06-20 21:29:28 +0000237 $ret = $ret . " " . ConvertType($func_ref->[1]) . " ret_value;\n";
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000238 }
239 if ($gen_traces) {
240 $ret = $ret . " TRACE(\"(" . $trace_arg . ")\\n\"";
241 if ($trace_arg ne "") {
242 $ret = $ret . ", " . $call_arg;
243 }
244 $ret = $ret . ");\n";
245 }
246 if ($thread_safe) {
247 $ret = $ret . " ENTER_GL();\n";
248 }
249 $ret = $ret . " ";
250 if ($func_ref->[1] ne "void") {
251 $ret = $ret . "ret_value = ";
252 }
253 $ret = $ret . $prefix . $func_ref->[0] . "( " . $call_arg . ");\n";
254 if ($thread_safe) {
255 $ret = $ret . " LEAVE_GL();\n";
256 }
257 if ($func_ref->[1] ne "void") {
258 $ret = $ret . " return ret_value;\n"
259 }
260 $ret = $ret . "}\n";
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000261
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000262 # Return this string....
263 $ret;
264}
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000265
266#
267# Extract and checks the number of arguments
268#
269if ($#ARGV != 1) {
270 die "Usage : make_opengl OpenGL_registry_location OpenGL_version.\n";
271}
272$registry_path = shift @ARGV;
273$version = shift @ARGV;
274if ($version eq "1.0") {
275 %norm_categories = %cat_1_0;
276} elsif ($version eq "1.1") {
277 %norm_categories = %cat_1_1;
278} elsif ($version eq "1.2") {
279 %norm_categories = %cat_1_2;
Lionel Ulmer0e999e32004-03-02 20:54:17 +0000280} elsif ($version eq "1.3") {
281 %norm_categories = %cat_1_3;
282} elsif ($version eq "1.4") {
283 %norm_categories = %cat_1_4;
284} elsif ($version eq "1.5") {
285 %norm_categories = %cat_1_5;
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000286} else {
Lionel Ulmer0e999e32004-03-02 20:54:17 +0000287 die "Incorrect OpenGL version.\n";
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000288}
289
290#
291# Open the registry files
292#
293open(TYPES, $registry_path . "/gl.tm") || die "Could not open 'gl.tm'. Please check your path the the registry files.\n";
294open(REGISTRY, $registry_path . "/gl.spec") || die "Could not open 'gl.spec'. Please check your path the the registry files.\n";
295
296#
297# First, create a mapping between the pseudo types used in the spec file
298# and OpenGL types using the 'gl.tm' file.
299#
300%pseudo_to_opengl = ();
301while ($line = <TYPES>) {
Lionel Ulmer9ac8ba12003-06-13 16:31:17 +0000302 if ($line !~ /\w*\#/) {
303 ($pseudo, $opengl) = ($line =~ /(\w*),\*,\*,\s*(.*),\*,\*/);
304 $pseudo_to_opengl{$pseudo} = $opengl;
305 }
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000306}
307# This is to override the 'void' -> '*' bogus conversion
308$pseudo_to_opengl{"void"} = "void";
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000309# This is a bug in the spec file...
310$pseudo_to_opengl{"FfdTargetSGIX"} = "GLint";
311$pseudo_to_opengl{"FfdMaskSGIX"} = "GLint";
312$pseudo_to_opengl{"IglooFunctionSelectSGIX"} = "GLint";
313$pseudo_to_opengl{"IglooParameterSGIX"} = "GLint";
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000314
315#
316# Then, create the list of all OpenGL functions using the 'gl.spec'
317# file. This will create two hash-tables, one with all the function
318# whose category matches the one listed in '@norm_categories', the other
319# with all other functions.
320#
321# An element of the hash table is a reference to an array with these
322# elements :
323#
324# - function name
325#
326# - return type
327#
328# - reference to an array giving the list of arguments (an empty array
329# for a 'void' function).
330#
331# The list of arguments is itself an array of reference to arrays. Each
332# of these arrays represents the argument type and the argument name.
333#
334# An example :
335#
336# void glBitmap( GLsizei width, GLsizei height,
337# GLfloat xorig, GLfloat yorig,
338# GLfloat xmove, GLfloat ymove,
339# const GLubyte *bitmap );
340#
341# Would give something like that :
342#
343# [ "glBitmap",
344# "void",
345# [ [ "GLsizei", "width" ],
346# [ "GLsizei", "height" ],
347# [ "GLfloat", "xorig" ],
348# [ "GLfloat", "yorig" ],
349# [ "GLfloat", "xmove" ],
350# [ "GLfloat", "ymove" ],
351# [ "GLubyte *", "bitmap"] ] ];
352#
353%norm_functions = ();
Lionel Ulmer4ed280f2003-03-04 02:17:04 +0000354
355#
356# This stores various extensions NOT part of the GL extension registry but still
357# implemented by most OpenGL libraries out there...
358#
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000359%ext_functions =
Lionel Ulmer4ed280f2003-03-04 02:17:04 +0000360 ( "glDeleteBufferRegion" => [ "glDeleteBufferRegion", "void", [ [ "GLenum", "region" ] ], "glDeleteBufferRegion" ],
361 "glReadBufferRegion" => [ "glReadBufferRegion", "void", [ [ "GLenum", "region" ],
362 [ "GLint", "x" ],
363 [ "GLint", "y" ],
364 [ "GLsizei", "width" ],
365 [ "GLsizei", "height" ] ], "glReadBufferRegion" ],
366 "glDrawBufferRegion" => [ "glDrawBufferRegion", "void", [ [ "GLenum", "region" ],
367 [ "GLint", "x" ],
368 [ "GLint", "y" ],
369 [ "GLsizei", "width" ],
370 [ "GLsizei", "height" ],
371 [ "GLint", "xDest" ],
372 [ "GLint", "yDest" ] ], "glDrawBufferRegion" ],
373 "glBufferRegionEnabled" => [ "glBufferRegionEnabled", "GLuint", [ ], "glBufferRegionEnabled" ],
374 "glNewBufferRegion" => [ "glNewBufferRegion", "GLuint", [ [ "GLenum", "type" ] ], "glNewBufferRegion" ],
375 "glMTexCoord2fSGIS" => [ "glMTexCoord2fSGIS", "void", [ [ "GLenum", "target" ],
Alexandre Julliardc4a336a2002-03-20 00:58:40 +0000376 [ "GLfloat", "s" ],
377 [ "GLfloat", "t" ] ], "glMTexCoord2fSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000378 "glMTexCoord2fvSGIS" => [ "glMTexCoord2fvSGIS", "void", [ [ "GLenum", "target" ],
Alexandre Julliardc4a336a2002-03-20 00:58:40 +0000379 [ "GLfloat *", "v" ] ], "glMTexCoord2fvSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000380 "glMultiTexCoord1dSGIS" => [ "glMultiTexCoord1dSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000381 [ "GLdouble", "s" ] ], "glMultiTexCoord1dSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000382 "glMultiTexCoord1dvSGIS" => [ "glMultiTexCoord1dvSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000383 [ "GLdouble *", "v" ] ], "glMultiTexCoord1dvSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000384 "glMultiTexCoord1fSGIS" => [ "glMultiTexCoord1fSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000385 [ "GLfloat", "s" ] ], "glMultiTexCoord1fSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000386 "glMultiTexCoord1fvSGIS" => [ "glMultiTexCoord1fvSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000387 [ "const GLfloat *", "v" ] ], "glMultiTexCoord1fvSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000388 "glMultiTexCoord1iSGIS" => [ "glMultiTexCoord1iSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000389 [ "GLint", "s" ] ], "glMultiTexCoord1iSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000390 "glMultiTexCoord1ivSGIS" => [ "glMultiTexCoord1ivSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000391 [ "GLint *", "v" ] ], "glMultiTexCoord1ivSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000392 "glMultiTexCoord1sSGIS" => [ "glMultiTexCoord1sSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000393 [ "GLshort", "s" ] ], "glMultiTexCoord1sSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000394 "glMultiTexCoord1svSGIS" => [ "glMultiTexCoord1svSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000395 [ "GLshort *", "v" ] ], "glMultiTexCoord1svSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000396 "glMultiTexCoord2dSGIS" => [ "glMultiTexCoord2dSGIS", "void", [ [ "GLenum", "target" ],
397 [ "GLdouble", "s"],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000398 [ "GLdouble", "t" ] ], "glMultiTexCoord2dSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000399 "glMultiTexCoord2dvSGIS" => [ "glMultiTexCoord2dvSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000400 [ "GLdouble *", "v" ] ], "glMultiTexCoord2dvSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000401 "glMultiTexCoord2fSGIS" => [ "glMultiTexCoord2fSGIS", "void", [ [ "GLenum", "target" ],
402 [ "GLfloat", "s" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000403 [ "GLfloat", "t" ] ], "glMultiTexCoord2fSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000404 "glMultiTexCoord2fvSGIS" => [ "glMultiTexCoord2fvSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000405 [ "GLfloat *", "v" ] ], "glMultiTexCoord2fvSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000406 "glMultiTexCoord2iSGIS" => [ "glMultiTexCoord2iSGIS", "void", [ [ "GLenum", "target" ],
407 [ "GLint", "s" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000408 [ "GLint", "t" ] ], "glMultiTexCoord2iSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000409 "glMultiTexCoord2ivSGIS" => [ "glMultiTexCoord2ivSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000410 [ "GLint *", "v" ] ], "glMultiTexCoord2ivSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000411 "glMultiTexCoord2sSGIS" => [ "glMultiTexCoord2sSGIS", "void", [ [ "GLenum", "target" ],
412 [ "GLshort", "s" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000413 [ "GLshort", "t" ] ], "glMultiTexCoord2sSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000414 "glMultiTexCoord2svSGIS" => [ "glMultiTexCoord2svSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000415 [ "GLshort *", "v" ] ], "glMultiTexCoord2svSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000416 "glMultiTexCoord3dSGIS" => [ "glMultiTexCoord3dSGIS", "void", [ [ "GLenum", "target" ],
417 [ "GLdouble", "s" ],
418 [ "GLdouble", "t" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000419 [ "GLdouble", "r" ] ], "glMultiTexCoord3dSGIS" ],
420 "glMultiTexCoord3dvSGIS" => [ "glMultiTexCoord3dvSGIS", "void", [ [ "GLenum", "target" ],
421 [ "GLdouble *", "v" ] ], "glMultiTexCoord3dvSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000422 "glMultiTexCoord3fSGIS" => [ "glMultiTexCoord3fSGIS", "void", [ [ "GLenum", "target" ],
423 [ "GLfloat", "s" ],
424 [ "GLfloat", "t" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000425 [ "GLfloat", "r" ] ], "glMultiTexCoord3fSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000426 "glMultiTexCoord3fvSGIS" => [ "glMultiTexCoord3fvSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000427 [ "GLfloat *", "v" ] ], "glMultiTexCoord3fvSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000428 "glMultiTexCoord3iSGIS" => [ "glMultiTexCoord3iSGIS", "void", [ [ "GLenum", "target" ],
429 [ "GLint", "s" ],
430 [ "GLint", "t" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000431 [ "GLint", "r" ] ], "glMultiTexCoord3iSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000432 "glMultiTexCoord3ivSGIS" => [ "glMultiTexCoord3ivSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000433 [ "GLint *", "v" ] ], "glMultiTexCoord3ivSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000434 "glMultiTexCoord3sSGIS" => [ "glMultiTexCoord3sSGIS", "void", [ [ "GLenum", "target" ],
435 [ "GLshort", "s" ],
436 [ "GLshort", "t" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000437 [ "GLshort", "r" ] ], "glMultiTexCoord3sSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000438 "glMultiTexCoord3svSGIS" => [ "glMultiTexCoord3svSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000439 [ "GLshort *", "v" ] ], "glMultiTexCoord3svSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000440 "glMultiTexCoord4dSGIS" => [ "glMultiTexCoord4dSGIS", "void", [ [ "GLenum", "target" ],
441 [ "GLdouble", "s" ],
442 [ "GLdouble", "t" ],
443 [ "GLdouble", "r" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000444 [ "GLdouble", "q" ] ], "glMultiTexCoord4dSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000445 "glMultiTexCoord4dvSGIS" => [ "glMultiTexCoord4dvSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000446 [ "GLdouble *", "v" ] ], "glMultiTexCoord4dvSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000447 "glMultiTexCoord4fSGIS" => [ "glMultiTexCoord4fSGIS", "void", [ [ "GLenum", "target" ],
448 [ "GLfloat", "s" ],
449 [ "GLfloat", "t" ],
450 [ "GLfloat", "r" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000451 [ "GLfloat", "q" ] ], "glMultiTexCoord4fSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000452 "glMultiTexCoord4fvSGIS" => [ "glMultiTexCoord4fvSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000453 [ "GLfloat *", "v" ] ], "glMultiTexCoord4fvSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000454 "glMultiTexCoord4iSGIS" => [ "glMultiTexCoord4iSGIS", "void", [ [ "GLenum", "target" ],
455 [ "GLint", "s" ],
456 [ "GLint", "t" ],
457 [ "GLint", "r" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000458 [ "GLint", "q" ] ], "glMultiTexCoord4iSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000459 "glMultiTexCoord4ivSGIS" => [ "glMultiTexCoord4ivSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000460 [ "GLint *", "v" ] ], "glMultiTexCoord4ivSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000461 "glMultiTexCoord4sSGIS" => [ "glMultiTexCoord4sSGIS", "void", [ [ "GLenum", "target" ],
462 [ "GLshort", "s" ],
463 [ "GLshort", "t" ],
464 [ "GLshort", "r" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000465 [ "GLshort", "q" ] ], "glMultiTexCoord4sSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000466 "glMultiTexCoord4svSGIS" => [ "glMultiTexCoord4svSGIS", "void", [ [ "GLenum", "target" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000467 [ "GLshort *", "v" ] ], "glMultiTexCoord4svSGIS" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000468 "glMultiTexCoordPointerSGIS" => [ "glMultiTexCoordPointerSGIS", "void", [ [ "GLenum", "target" ],
469 [ "GLint", "size" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000470 [ "GLenum", "type" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000471 [ "GLsizei", "stride" ],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000472 [ "GLvoid *", "pointer" ] ], "glMultiTexCoordPointerSGIS" ],
473 "glSelectTextureSGIS" => [ "glSelectTextureSGIS", "void", [ [ "GLenum", "target" ] ], "glSelectTextureSGIS" ],
474 "glSelectTextureCoordSetSGIS" => [ "glSelectTextureCoordSetSGIS", "void", [ [ "GLenum", "target" ] ], "glSelectTextureCoordSetSGIS" ],
475 "wglAllocateMemoryNV" => [ "wglAllocateMemoryNV", "void *", [ [ "GLsizei", "size" ],
476 [ "GLfloat", "readfreq" ],
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000477 [ "GLfloat", "writefreq"],
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000478 [ "GLfloat", "priority" ] ], "glXAllocateMemoryNV" ],
Christian Costa8bbabd12004-04-14 23:58:33 +0000479 "wglFreeMemoryNV" => [ "wglFreeMemoryNV", "void", [ [ "GLvoid *", "pointer" ] ], "glXFreeMemoryNV" ],
480 "glDeleteObjectBufferATI" => [ "glDeleteObjectBufferATI", "void", [ [ "GLuint", "buffer" ] ], "glDeleteObjectBufferATI" ]
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000481 );
Lionel Ulmer7fc3a3b2001-07-31 00:08:05 +0000482
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000483
484while ($line = <REGISTRY>) {
485 if ($line =~ /^\w*\(.*\)/) {
486 # Get the function name (NOTE: the 'gl' prefix needs to be added later)
487 ($funcname, $args) = ($line =~ /^(\w*)\((.*)\)/);
488 # and the argument names
489 @arg_names = split /\s*,\s*/, $args;
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000490
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000491 # After get :
492 # - the return type
493 # - the argument types
494 # - the category the function belongs
495 %arg_types = ();
496 $category = "";
497 $ret_type = "";
498 while (1) {
499 $line = <REGISTRY>;
500 unless (defined($line)) {
501 last;
502 } elsif ($line =~ /^\s*$/) {
503 if (($category eq "") || ($ret_type eq "")) {
504 die "Missing 'category' line in function $funcname.\n";
505 }
506 last;
507 } elsif ($line =~ /\t*return\t*(\w*)/) {
508 ($ret_type) = ($line =~ /\t*return\s*(\w*)/);
509 $ret_type = $pseudo_to_opengl{$ret_type};
510 unless (defined($ret_type)) {
511 die "Unsupported return type in function $funcname\n";
512 }
513 } elsif ($line =~ /^\t*category/) {
514 ($category) = ($line =~ /^\t*category\s*([\w-]*)/);
515 } elsif ($line =~ /^\t*param/) {
516 ($name, $base_type, $ext) = ($line =~ /\t*param\s*(\w*)\s*(\w*) (.*)/);
517 $ptr = 0;
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000518 unless (defined($name)) {
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000519 chomp $line;
520 die "Broken spec file line $line in function $funcname\n";
521 }
522
523 if ($ext =~ /array/) {
524 # This is a pointer
525 $ptr = 1;
526 } elsif ($ext =~ /value/) {
527 # And this a 'normal' value
528 $ptr = 0;
529 } else {
530 chomp $line;
531 die "Unsupported type : $line in function $funcname\n";
532 }
533 # Get the 'real' type and append a '*' in case of a pointer
534 $type = $pseudo_to_opengl{$base_type};
535 unless (defined($type)) {
536 chomp $line;
537 die "Unsupported return type in function $funcname for type $base_type (line $line)\n";
538 }
539 if ($ptr) {
540 $type = $type . "*";
541 }
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000542
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000543 $arg_types{$name} = $type;
544 }
545 }
546
547 # Now, build the argument reference
548 $arg_ref = [ ];
549 for ($i = 0; $i <= $#arg_names; $i++) {
550 unless (defined($arg_types{$arg_names[$i]})) {
551 print "@arg_names\n";
552 foreach (sort keys %arg_types) {
553 print "$_ => $arg_types{$_}\n";
554 }
555 die "Undefined type for $arg_names[$i] in function $funcname\n";
556 }
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000557
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000558 push @$arg_ref, [ $arg_types{$arg_names[$i]}, $arg_names[$i] ];
559 }
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000560 $func_ref = [ "gl" . $funcname,
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000561 $ret_type,
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000562 $arg_ref,
563 "gl" . $funcname ];
Alexandre Julliard7cae5582002-06-01 02:55:48 +0000564
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000565 # Now, put in one or the other hash table
566 if ($norm_categories{$category}) {
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000567 $norm_functions{"gl" . $funcname} = $func_ref;
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000568 } else {
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000569 $ext_functions{"gl" . $funcname} = $func_ref;
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000570 }
571 }
572}
573
574#
575# Clean up the input files
576#
577close(TYPES);
578close(REGISTRY);
579
580#
581# Now, generate the output files. First, the spec file.
582#
583open(SPEC, ">" . $spec_file);
584
Lionel Ulmer5a96cbf2003-04-14 21:34:11 +0000585print SPEC "@ stdcall wglCreateContext(long)
586@ stdcall wglCreateLayerContext(long long)
587@ stdcall wglCopyContext(long long long)
588@ stdcall wglDeleteContext(long)
589@ stdcall wglDescribeLayerPlane(long long long long ptr)
590@ stdcall wglGetCurrentContext()
591@ stdcall wglGetCurrentDC()
Lionel Ulmer5a96cbf2003-04-14 21:34:11 +0000592@ stdcall wglGetLayerPaletteEntries(long long long long ptr)
593@ stdcall wglGetProcAddress(str)
594@ stdcall wglMakeCurrent(long long)
595@ stdcall wglRealizeLayerPalette(long long long)
596@ stdcall wglSetLayerPaletteEntries(long long long long ptr)
597@ stdcall wglShareLists(long long)
598@ stdcall wglSwapLayerBuffers(long long)
599@ stdcall wglUseFontBitmapsA(long long long long)
600@ stdcall wglUseFontOutlinesA(long long long long long long long ptr)
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000601@ stub glGetLevelParameterfv
602@ stub glGetLevelParameteriv
Lionel Ulmerb945bfd2004-01-06 00:36:13 +0000603@ stdcall wglUseFontBitmapsW(long long long long)
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000604@ stub wglUseFontOutlinesW
Lionel Ulmer55d4f932003-02-11 22:13:54 +0000605@ stub wglGetDefaultProcAddress
Lionel Ulmer5a96cbf2003-04-14 21:34:11 +0000606@ stdcall wglChoosePixelFormat(long ptr) gdi32.ChoosePixelFormat
607@ stdcall wglDescribePixelFormat(long long long ptr) gdi32.DescribePixelFormat
608@ stdcall wglGetPixelFormat(long) gdi32.GetPixelFormat
609@ stdcall wglSetPixelFormat(long long ptr) gdi32.SetPixelFormat
610@ stdcall wglSwapBuffers(long) gdi32.SwapBuffers
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000611";
612
613foreach (sort keys %norm_functions) {
614 $func_name = $norm_functions{$_}->[0];
615 print SPEC "@ stdcall $func_name( ";
616 for ($i = 0; $i <= $#{@{$norm_functions{$_}->[2]}}; $i++) {
617 $type = $norm_functions{$_}->[2]->[$i]->[0];
618 if ($type =~ /\*/) {
619 print SPEC "ptr ";
620 } elsif (defined($arg_conv{$type})) {
621 print SPEC "$@$arg_conv{$type}[0] ";
622 } else {
623 die "No convertion for GL type $type...\n";
624 }
625 }
626 print SPEC ") wine_$func_name\n";
627}
628close(SPEC);
629
630#
631# After the spec file, the opengl_norm.c file
632#
633open(NORM, ">" . $norm_file);
634print NORM "
635/* Auto-generated file... Do not edit ! */
636
637#include \"config.h\"
Alexandre Julliard2c40e292002-09-25 00:29:56 +0000638#include \"opengl_ext.h\"
Alexandre Julliardc4a336a2002-03-20 00:58:40 +0000639#include \"wine/debug.h\"
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000640
Alexandre Julliardc4a336a2002-03-20 00:58:40 +0000641WINE_DEFAULT_DEBUG_CHANNEL(opengl);
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000642";
643foreach (sort keys %norm_functions) {
644 $string = GenerateThunk($norm_functions{$_}, 1, "", $gen_thread_safe);
645
Alexandre Julliardc8173ec2003-07-11 03:51:38 +0000646 print NORM "\n$string";
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000647}
648close(NORM);
649
650#
651# Finally, more complex, the opengl_ext.c file
652#
653open(EXT, ">" . $ext_file);
654print EXT "
655/* Auto-generated file... Do not edit ! */
656
657#include \"config.h\"
Alexandre Julliard2c40e292002-09-25 00:29:56 +0000658#include \"opengl_ext.h\"
Alexandre Julliardc4a336a2002-03-20 00:58:40 +0000659#include \"wine/debug.h\"
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000660
Alexandre Julliardc4a336a2002-03-20 00:58:40 +0000661WINE_DEFAULT_DEBUG_CHANNEL(opengl);
Lionel Ulmer15a4a772001-03-04 01:05:20 +0000662
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000663";
664
665# First, generate the function pointers
666foreach (sort keys %ext_functions) {
667 $func_ref = $ext_functions{$_};
Lionel Ulmer0e999e32004-03-02 20:54:17 +0000668 print EXT ConvertType($func_ref->[1]) . " (*" . $ext_prefix . $func_ref->[0] . ")( ";
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000669 for ($i = 0; $i <= $#{@{$func_ref->[2]}}; $i++) {
Lionel Ulmer334aacd2003-06-20 21:29:28 +0000670 $type = ConvertType($func_ref->[2]->[$i]->[0]);
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000671 print EXT "$type";
672 if ($i != $#{@{$func_ref->[2]}}) {
673 print EXT ", ";
674 } else {
675 print EXT " ";
676 }
677 }
678 print EXT ") = (void *) 0xdeadbeef;\n";
679}
680
681# Then, the function prototypes
682print EXT "\n\n/* The function prototypes */\n";
683foreach (sort keys %ext_functions) {
684 $func_ref = $ext_functions{$_};
Lionel Ulmer0e999e32004-03-02 20:54:17 +0000685 print EXT ConvertType($func_ref->[1]) . " WINAPI " . "wine_" . $func_ref->[0] . "( ";
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000686 for ($i = 0; $i <= $#{@{$func_ref->[2]}}; $i++) {
Lionel Ulmer334aacd2003-06-20 21:29:28 +0000687 $type = ConvertType($func_ref->[2]->[$i]->[0]);
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000688 print EXT "$type";
689 if ($i != $#{@{$func_ref->[2]}}) {
690 print EXT ", ";
691 } else {
692 print EXT " ";
693 }
694 }
695 print EXT ");\n";
696}
697
698# Then the table giving the string <-> function correspondance */
699print EXT "\n\n/* The table giving the correspondance between names and functions */\n";
700@tmp = keys %ext_functions;
701print EXT "int extension_registry_size = " . ($#tmp + 1) . ";\n";
702print EXT "OpenGL_extension extension_registry[" . ($#tmp + 1) . "] = {\n";
703$i = 0;
704foreach (sort keys %ext_functions) {
705 $func_ref = $ext_functions{$_};
Lionel Ulmerce3ab0e2002-01-02 21:43:19 +0000706 print EXT " { \"" . $func_ref->[0] . "\", \"" . $func_ref->[3] . "\", (void *) wine_" . $func_ref->[0] . ", (void **) (&" . $ext_prefix . $func_ref->[0] . ") }";
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000707 if ($i != $#tmp) {
708 print EXT ",";
709 }
710 $i++;
711 print EXT "\n";
712}
713print EXT "};\n";
714
715# And, finally, the thunks themselves....
Alexandre Julliardc8173ec2003-07-11 03:51:38 +0000716print EXT "\n/* The thunks themselves....*/";
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000717foreach (sort keys %ext_functions) {
718 $string = GenerateThunk($ext_functions{$_}, 0, $ext_prefix, $gen_thread_safe);
719
Alexandre Julliardc8173ec2003-07-11 03:51:38 +0000720 print EXT "\n$string";
Lionel Ulmerbff705d2000-06-12 01:21:18 +0000721}
722close(EXT);