make_opengl 24.6 KB
Newer Older
1
#!/usr/bin/perl -w
2
use strict;
3
use XML::LibXML;
4 5 6

# This script is called thus :
#
7 8
#   make_opengl [opengl_version]
#
9
#     - It needs files from the OpenGL extension registry:
10
#
11 12
#       https://raw.github.com/KhronosGroup/OpenGL-Registry/master/xml/gl.xml
#       https://raw.github.com/KhronosGroup/OpenGL-Registry/master/xml/wgl.xml
13
#
14 15 16
#       If they are not found in the current directory the script will
#       attempt to download them from there.
#
17
#     - opengl_version is the OpenGL version emulated by the library
18
#       (can be 1.0 to 1.5). The default is 1.1.
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
#
# This script generates the three following files :
#
#     - opengl32.spec : the spec file giving all the exported functions
#       of the OpenGL32.DLL library. These functions are the one an
#       application can directly link to (and are all the functions
#       defined in the OpenGL core for the version defined by
#       'opengl_version').
#
#     - opengl_norm.c : this file contains the thunks for all OpenGL
#       functions that are defined in 'opengl32.spec'. The corresponding
#       functions NEED to be defined in Linux's libGL or the library
#       won't be able to be linked in.
#
#     - opengl_ext.c : in this file are stored thunks for ALL possible
#       OpenGL extensions (at least, all the extensions that are defined
#       in the OpenGL extension registry). Contrary to 'opengl_norm.c',
#       you do not need to have these extensions in your libGL to have
#       OpenGL work (as they are resolved at run-time using
#       glXGetProcAddressARB).
#
40 41 42
#     - include/wine/wgl_driver.h: definitions for the tables of OpenGL functions.
#
#
43
# Copyright 2000 Lionel Ulmer
44
# Copyright 2012 Alexandre Julliard
45 46 47 48 49 50 51 52 53 54 55 56 57
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
58
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
59
#
60

61 62 63
#
# Files to generate
#
64 65 66
my $spec_file = "opengl32.spec";
my $norm_file = "opengl_norm.c";
my $ext_file  = "opengl_ext.c";
67 68
my $wgl_driver_file = "../../include/wine/wgl_driver.h";
my $wgl_file = "../../include/wine/wgl.h";
69 70

# If set to 1, generate TRACEs for each OpenGL function
71
my $gen_traces = 1;
72 73 74 75

#
# List of categories to put in the 'opengl_norm.c' file
#
76 77 78 79 80 81
my %cat_1_0 = ( "GL_VERSION_1_0" => 1 );
my %cat_1_1 = ( %cat_1_0, "GL_VERSION_1_1" => 1 );
my %cat_1_2 = ( %cat_1_1, "GL_VERSION_1_2" => 1 );
my %cat_1_3 = ( %cat_1_2, "GL_VERSION_1_3" => 1 );
my %cat_1_4 = ( %cat_1_3, "GL_VERSION_1_4" => 1 );
my %cat_1_5 = ( %cat_1_4, "GL_VERSION_1_5" => 1 );
82

83
my %norm_categories = ();
84 85

#
86 87
# This hash table gives the conversion between OpenGL types and
# the .spec type and debug format
88
#
89 90 91 92 93 94 95 96 97 98 99 100
my %arg_types =
    (
     "GLbitfield" =>           [ "long",   "%d" ],
     "GLboolean" =>            [ "long",   "%d" ],
     "GLbyte" =>               [ "long",   "%d" ],
     "GLchar" =>               [ "long",   "%c" ],
     "GLcharARB" =>            [ "long",   "%c" ],
     "GLclampd" =>             [ "double", "%f" ],
     "GLclampf" =>             [ "float",  "%f" ],
     "GLclampx" =>             [ "long",   "%d" ],
     "GLdouble" =>             [ "double", "%f" ],
     "GLeglClientBufferEXT" => [ "ptr",    "%p" ],
101
     "GLeglImageOES" =>        [ "ptr",    "%p" ],
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138
     "GLenum" =>               [ "long",   "%d" ],
     "GLfixed" =>              [ "long",   "%d" ],
     "GLfloat" =>              [ "float",  "%f" ],
     "GLhalfNV" =>             [ "long",   "%d" ],
     "GLhandleARB" =>          [ "long",   "%d" ],
     "GLint" =>                [ "long",   "%d" ],
     "GLint64" =>              [ "int64",  "wine_dbgstr_longlong(%s)" ],
     "GLint64EXT" =>           [ "int64",  "wine_dbgstr_longlong(%s)" ],
     "GLintptr" =>             [ "long",   "%ld" ],
     "GLintptrARB" =>          [ "long",   "%ld" ],
     "GLshort" =>              [ "long",   "%d" ],
     "GLsizei" =>              [ "long",   "%d" ],
     "GLsizeiptr" =>           [ "long",   "%ld" ],
     "GLsizeiptrARB" =>        [ "long",   "%ld" ],
     "GLstring" =>             [ "str",    "wine_dbgstr_a(%s)" ],
     "GLsync" =>               [ "ptr",    "%p" ],
     "GLubyte" =>              [ "long",   "%d" ],
     "GLuint" =>               [ "long",   "%d" ],
     "GLuint64" =>             [ "int64",  "wine_dbgstr_longlong(%s)" ],
     "GLuint64EXT" =>          [ "int64",  "wine_dbgstr_longlong(%s)" ],
     "GLushort" =>             [ "long",   "%d" ],
     "GLvdpauSurfaceNV" =>     [ "long",   "%ld" ],
     "GLDEBUGPROC" =>          [ "ptr",    "%p" ],
     "GLDEBUGPROCARB" =>       [ "ptr",    "%p" ],
     "GLDEBUGPROCAMD" =>       [ "ptr",    "%p" ],
     "GLDEBUGPROCKHR" =>       [ "ptr",    "%p" ],
     "GLVULKANPROCNV" =>       [ "ptr",    "%p" ],
     "HDC" =>                  [ "long",   "%p" ],
     "HGLRC" =>                [ "long",   "%p" ],
     "HPBUFFERARB" =>          [ "long",   "%p" ],
     "HENHMETAFILE" =>         [ "long",   "%p" ],
     "LPGLYPHMETRICSFLOAT" =>  [ "ptr",    "%p" ],
     "LPCSTR" =>               [ "str",    "wine_dbgstr_a(%s)" ],
     "UINT" =>                 [ "long",   "%u" ],
     "DWORD" =>                [ "long",   "%u" ],
     "BOOL" =>                 [ "long",   "%u" ],
     "FLOAT" =>                [ "float",  "%f" ],
139
    );
140

141 142 143 144 145
my %remap_types =
    (
     "HGLRC" => "struct wgl_context *",
     "HPBUFFERARB" => "struct wgl_pbuffer *",
    );
146 147 148 149 150 151 152 153 154 155 156

my %khronos_types =
    (
     "khronos_int8_t" => "signed char",
     "khronos_uint8_t" => "unsigned char",
     "khronos_int16_t" => "short",
     "khronos_uint16_t" => "unsigned short",
     "khronos_int32_t" => "int",
     "khronos_uint32_t" => "unsigned int",
     "khronos_float_t" => "float",
    );
157 158 159
#
# Used to convert some types
#
160 161
sub ConvertType($)
{
162 163 164 165 166 167 168 169
    my $arg = shift;
    my $ret = $arg->textContent();
    my @type = $arg->findnodes("./ptype");

    if (@type)
    {
        my $type = $type[0]->textContent();
        $ret =~ s/$type/$remap_types{$type}/ if defined $remap_types{$type};
170
    }
171
    return $ret;
172 173
}

174 175 176
#
# This functions generates the thunk for a given function.
#
177
sub GenerateThunk($$$)
178
{
179
    my ($name, $func_ref, $prefix) = @_;
180
    my $call_arg = "";
181
    my $trace_call_arg = "";
182
    my $trace_arg = "";
183

184
    my $ret = get_func_proto( "%s WINAPI %s(%s)", $name, $func_ref, 0 );
185 186 187 188 189 190
    foreach my $arg (@{$func_ref->[1]}) {
        my $ptype = get_arg_type( $arg );
        my $pname = get_arg_name( $arg );
        my $param = $arg->textContent();
        $call_arg .= " " . $pname . ",";
        if ($param =~ /\*/ || $param =~ /\[/) {
191
            $trace_arg .= ", %p";
192
            $trace_call_arg .= ", " . $pname;
193 194 195 196
        } elsif (defined $arg_types{$ptype}) {
            my $format = ${$arg_types{$ptype}}[1];
            $trace_arg .= ", " . ($format =~ /^%/ ? $format : "%s");
            $trace_call_arg .= ", " . sprintf $format =~ /^%/ ? "%s" : $format, $pname;
197
        }
198
        else { printf "Unknown type %s in %s\n", $param, $name; }
199
    }
200
    $call_arg =~ s/,$/ /;
201
    $trace_arg =~ s/^, //;
202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217
    $ret .= "\n{\n";
    # special case for functions that take an HDC as first parameter
    if (@{$func_ref->[1]} && get_arg_type( ${$func_ref->[1]}[0] ) eq "HDC")
    {
        my $pname = get_arg_name( ${$func_ref->[1]}[0] );
        $ret .= "  const struct opengl_funcs *funcs = get_dc_funcs( $pname );\n";
        $ret .= "  TRACE( \"($trace_arg)\\n\"$trace_call_arg );\n" if $gen_traces;
        $ret .= "  if (!funcs || !funcs->$prefix.p_$name) return";
        $ret .= " 0" unless is_void_func( $func_ref );
        $ret .= ";\n";
    }
    else
    {
        $ret .= "  const struct opengl_funcs *funcs = NtCurrentTeb()->glTable;\n";
        $ret .= "  TRACE( \"($trace_arg)\\n\"$trace_call_arg );\n" if $gen_traces;
    }
218
    $ret .= "  ";
219 220
    $ret .= "return " unless is_void_func( $func_ref );
    $ret .= "funcs->$prefix.p_$name($call_arg);\n";
221
    $ret .= "}\n\n";
222
    return $ret;
223 224
}

225
sub generate_null_func($$$)
226
{
227
    my ($name, $func_ref, $callconv) = @_;
228 229
    my $ret;

230
    return "" if $name eq "glDebugEntry";
231

232
    $ret = get_func_proto( "static %s$callconv null_%s(%s)", $name, $func_ref, 1 );
233
    $ret .= " {";
234
    if ($name eq "glGetError")
235 236 237
    {
        $ret .= " return GL_INVALID_OPERATION;";
    }
238
    elsif (!is_void_func( $func_ref ))
239 240 241 242 243 244 245
    {
        $ret .= " return 0;";
    }
    $ret .= " }\n";
    return $ret;
}

246 247 248 249 250 251
sub generate_spec_entry($$)
{
    my ($name, $func) = @_;
    my $args=" ";
    foreach my $arg (@{$func->[1]})
    {
252 253 254
        my $ptype = get_arg_type( $arg );
        my $param = $arg->textContent();
        if ($param =~ /[[*]/) {
255
            $args .= "ptr ";
256 257
        } elsif (defined($arg_types{$ptype})) {
            $args .= "$@$arg_types{$ptype}[0] ";
258
        } else {
259
            die "No conversion for func $name type $param\n";
260 261 262 263 264 265
        }
    }
    $args = substr($args,1,-1);
    return "@ stdcall $_($args)";
}

266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
sub is_void_func($)
{
    my $func = shift;
    return 0 if @{$func->[0]->findnodes("./ptype")};
    return $func->[0]->textContent() eq "void ";
}

sub get_arg_type($)
{
    my $p = shift;
    my @type = $p->findnodes("./ptype");
    return @type ? $type[0]->textContent() : "GLint";
}

sub get_arg_name($)
{
    my $p = shift;
    my @name = $p->findnodes("./name");
    return $name[0]->textContent();
}

287
sub get_func_proto($$$$)
288
{
289
    my ($format, $name, $func, $convert_args) = @_;
290
    die "unknown func $name" unless defined $func->[0];
291
    my $proto = $convert_args ? ConvertType( $func->[0] ) : $func->[0]->textContent();
292 293 294
    $proto =~ s/ $//;
    my $args = "";
    foreach my $arg (@{$func->[1]})
295
    {
296
        $args .= " " . ($convert_args ? ConvertType( $arg ) : $arg->textContent()) . ",";
297
    }
298 299 300
    $args =~ s/,$/ /;
    $args ||= "void";
    return sprintf $format, $proto, $name, $args;
301 302
}

303 304 305
#
# Extract and checks the number of arguments
#
306
if (@ARGV > 1) {
307 308
    my $name0=$0;
    $name0=~s%^.*/%%;
309
    die "Usage: $name0 [version]\n";
310
}
311
my $version = $ARGV[0] || "1.1";
312 313 314 315 316 317
if ($version eq "1.0") {
    %norm_categories = %cat_1_0;
} elsif ($version eq "1.1") {
    %norm_categories = %cat_1_1;
} elsif ($version eq "1.2") {
    %norm_categories = %cat_1_2;
318 319 320 321 322 323
} elsif ($version eq "1.3") {
    %norm_categories = %cat_1_3;
} elsif ($version eq "1.4") {
    %norm_categories = %cat_1_4;
} elsif ($version eq "1.5") {
    %norm_categories = %cat_1_5;
324
} else {
325
    die "Incorrect OpenGL version.\n";
326 327
}

328 329 330
#
# Fetch the registry files
#
331
my $url="https://raw.githubusercontent.com/KhronosGroup/OpenGL-Registry";
332
my $commit="03e1bfb87c4664d34dc7822fb591841eec747094";
333 334 335

-f "gl-$commit.xml" || system "wget", "-O", "gl-$commit.xml", "$url/$commit/xml/gl.xml" || die "cannot download gl.xml";
-f "wgl-$commit.xml" || system "wget", "-O", "wgl-$commit.xml", "$url/$commit/xml/wgl.xml" || die "cannot download wgl.xml";
336 337 338


#
339 340
# Then, create the list of all OpenGL functions using the registry
# files. This will create two hash-tables, one with all the function
341 342 343 344 345 346
# whose category matches the one listed in '@norm_categories', the other
# with all other functions.
#
# An element of the hash table is a reference to an array with these
# elements :
#
347
#  - XML node of the function prototype
348
#
349
#  - reference to an array of XML nodes giving the list of arguments (an empty array
350 351
#    for a 'void' function).
#
352 353
my %norm_functions;
my %ext_functions;
354
my %wgl_functions;
355
my %gl_enums;
356
my (%gl_types, @gl_types);  # also use an array to preserve declaration order
357 358 359 360 361 362 363 364 365 366 367 368 369 370

my %supported_wgl_functions =
    (
     "wglCopyContext" => 1,
     "wglCreateContext" => 1,
     "wglDeleteContext" => 1,
     "wglDescribePixelFormat" => 1,
     "wglGetPixelFormat" => 1,
     "wglGetProcAddress" => 1,
     "wglMakeCurrent" => 1,
     "wglSetPixelFormat" => 1,
     "wglShareLists" => 1,
     "wglSwapBuffers" => 1,
    );
371

372 373 374 375 376 377 378 379 380 381 382
my %remapped_wgl_functions =
    (
     "ChoosePixelFormat" => "wglChoosePixelFormat",
     "DescribePixelFormat" => "wglDescribePixelFormat",
     "GetPixelFormat" => "wglGetPixelFormat",
     "GetEnhMetaFilePixelFormat" => 0,
     "SetPixelFormat" => "wglSetPixelFormat",
     "SwapBuffers" => "wglSwapBuffers",
     "wglUseFontBitmaps" => 0,
     "wglUseFontOutlines" => 0,
    );
383

384 385
my @extra_wgl_functions = ( "wglGetDefaultProcAddress" );

386 387 388
my %supported_wgl_extensions =
   (
    "WGL_ARB_create_context" => 1,
389
    "WGL_ARB_create_context_no_error" => 1,
390
    "WGL_ARB_create_context_profile" => 1,
391 392
    "WGL_ARB_extensions_string" => 1,
    "WGL_ARB_make_current_read" => 1,
393
    "WGL_ARB_multisample" => 1,
394 395
    "WGL_ARB_pbuffer" => 1,
    "WGL_ARB_pixel_format" => 1,
396 397
    "WGL_ARB_framebuffer_sRGB" => 1,
    "WGL_ARB_pixel_format_float" => 1,
398
    "WGL_ARB_render_texture" => 1,
399 400
    "WGL_ATI_pixel_format_float" => 1,
    "WGL_EXT_create_context_es2_profile" => 1,
401
    "WGL_EXT_extensions_string" => 1,
402 403
    "WGL_EXT_framebuffer_sRGB" => 1,
    "WGL_EXT_pixel_format_packed_float" => 1,
404
    "WGL_EXT_swap_control" => 1,
405 406 407 408
    "WGL_EXT_swap_control_tear" => 1,
    "WGL_NV_float_buffer" => 1,
    "WGL_NV_render_depth_texture" => 1,
    "WGL_NV_render_texture_rectangle" => 1,
409 410
    "WGL_NV_vertex_array_range" => 1,
    "WGL_WINE_pixel_format_passthrough" => 1,
411
    "WGL_WINE_query_renderer" => 1,
412 413
   );

414 415 416 417 418 419
my %supported_apis =
    (
     "gl" => 1,
    );

sub is_supported_api($)
420
{
421 422 423 424
    my $api = shift;
    foreach my $i (split /\|/, $api)
    {
        return 1 if defined $supported_apis{$i};
425
    }
426
    return 0;
427 428
}

429 430 431 432 433 434
# some functions need a hand-written wrapper
sub needs_wrapper($$)
{
    my %funcs =
        (
         "glDebugEntry" => 1,
435 436 437
         "glDebugMessageCallback" => 1,
         "glDebugMessageCallbackAMD" => 1,
         "glDebugMessageCallbackARB" => 1,
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457
         "glGetIntegerv" => 1,
         "glGetString" => 1,
         "glGetStringi" => 1,
         "wglGetCurrentReadDCARB" => 1,
        );
    my ($name, $func) = @_;

    return 1 if defined $funcs{$name};
    # check if return value needs special handling
    (my $type = $func->[0]->textContent()) =~ s/ $//;
    return 1 if defined $remap_types{$type};
    # check if one of the arguments needs special handling
    foreach (@{$func->[1]})
    {
        $type = get_arg_type( $_ );
        return 1 if defined $remap_types{$type};
    }
    return 0;
}

458
sub parse_file($)
459
{
460
    my $file = shift;
461
    my $xml = XML::LibXML->load_xml( location => $file );
462
    my %functions;
463
    my %enums;
464 465

    # save all functions
466 467 468 469 470 471 472
    foreach my $command ($xml->findnodes("/registry/commands/command"))
    {
        my $proto = @{$command->findnodes("./proto")}[0];
        my $name = @{$command->findnodes("./proto/name")}[0];
        $proto->removeChild( $name );
        my @params = $command->findnodes("./param");
        $functions{$name->textContent()} = [ $proto, \@params ];
473 474
    }

475 476
    # save all enums
    foreach my $enum ($xml->findnodes("/registry/enums/enum"))
477
    {
478
        $enums{$enum->{name}} = $enum->{value};
479 480
    }

481 482 483 484 485 486 487 488 489 490 491
    # save all types
    foreach my $type ($xml->findnodes("/registry/types/type"))
    {
        next if $type->{api};
        my $name = @{$type->findnodes("./name")}[0];
        next unless $name;
        $name = $name->textContent;
        push @gl_types, $name unless $gl_types{$name};
        $gl_types{$name} = $type;
    }

492
    # generate norm functions
493 494 495 496 497 498 499 500 501 502 503
    foreach my $feature ($xml->findnodes("/registry/feature"))
    {
        if ($feature->{api} eq "wgl")
        {
            foreach my $cmd ($feature->findnodes("./require/command"))
            {
                my $name = $cmd->{name};
                if (defined $remapped_wgl_functions{$name})
                {
                    next unless $remapped_wgl_functions{$name};
                    $name = $remapped_wgl_functions{$name};
504
                }
505
                $wgl_functions{$name} = $functions{$cmd->{name}};
506
            }
507 508 509 510
            foreach my $name (@extra_wgl_functions)
            {
                $wgl_functions{$name} = $functions{$name} if defined $functions{$name};
            }
511
        }
512 513 514 515 516
        next unless defined $norm_categories{$feature->{name}};
        foreach my $cmd ($feature->findnodes("./require/command"))
        {
            $norm_functions{$cmd->{name}} = $functions{$cmd->{name}};
        }
517 518 519 520
        foreach my $enum ($feature->findnodes("./require/enum"))
        {
            $gl_enums{$enum->{name}} = $enums{$enum->{name}};
        }
521 522 523
    }

    # generate extension functions from norm functions, if they are newer than the category
524 525 526 527 528
    foreach my $feature ($xml->findnodes("/registry/feature"))
    {
        next if defined $norm_categories{$feature->{name}};
        next unless is_supported_api( $feature->{api} );
        foreach my $cmd ($feature->findnodes("./require/command"))
529
        {
530 531 532
            my $name = $cmd->{name};
            next if $norm_functions{$name} || $ext_functions{$name};
            $ext_functions{$name} = [ $functions{$name}[0], $functions{$name}[1], [ $feature->{name} ] ];
533
        }
534 535 536 537
        foreach my $enum ($feature->findnodes("./require/enum"))
        {
            $gl_enums{$enum->{name}} = $enums{$enum->{name}};
        }
538 539
    }

540
    # generate extension functions
541 542 543 544 545 546 547 548 549
    foreach my $ext ($xml->findnodes("/registry/extensions/extension"))
    {
        if ($ext->{supported} eq "wgl")
        {
            next unless defined $supported_wgl_extensions{$ext->{name}};
            foreach my $cmd ($ext->findnodes("./require/command"))
            {
                my $name = $cmd->{name};
                $ext_functions{$name} = [ $functions{$name}[0], $functions{$name}[1], [ $ext->{name} ] ];
550
            }
551 552 553 554
            foreach my $enum ($ext->findnodes("./require/enum"))
            {
                $gl_enums{$enum->{name}} = $enums{$enum->{name}};
            }
555
            next;
556
        }
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571
        next unless is_supported_api( $ext->{supported} );
        foreach my $req ($ext->findnodes("./require"))
        {
            next unless !$req->{api} || $req->{api} eq "gl";
            foreach my $cmd ($req->findnodes("./command"))
            {
                my $name = $cmd->{name};
                next if $norm_functions{$name};
                if (!$ext_functions{$name})
                {
                    $ext_functions{$name} = [ $functions{$name}[0], $functions{$name}[1], [ $ext->{name} ] ];
                }
                else
                {
                    push @{$ext_functions{$name}->[2]}, $ext->{name};
572 573 574
                }
            }
        }
575 576 577 578
        foreach my $enum ($ext->findnodes("./require/enum"))
        {
            $gl_enums{$enum->{name}} = $enums{$enum->{name}};
        }
579 580
    }
}
581

582 583
parse_file( "gl-$commit.xml" );
parse_file( "wgl-$commit.xml" );
584
parse_file( "winegl.xml" );
585

586 587 588 589
#
# Get the current wgl_driver.h version
#
my $wgl_version = 0;
590
open HEADER, "<$wgl_driver_file" or die "cannot open $wgl_driver_file";
591 592 593 594 595 596 597 598 599 600 601
while (<HEADER>)
{
    next unless /^#define WINE_WGL_DRIVER_VERSION (\d+)/;
    $wgl_version = $1;
    last;
}
close HEADER;

#
# Generate the wgl_driver.h file
#
602 603
open HEADER, ">$wgl_driver_file" or die "cannot create $wgl_driver_file";
print HEADER "/* Automatically generated from http://www.opengl.org/registry files; DO NOT EDIT! */\n\n";
604 605 606 607 608 609 610 611
print HEADER "#ifndef __WINE_WGL_DRIVER_H\n";
print HEADER "#define __WINE_WGL_DRIVER_H\n\n";
print HEADER "#ifndef WINE_GLAPI\n";
print HEADER "#define WINE_GLAPI\n";
print HEADER "#endif\n\n";

printf HEADER "#define WINE_WGL_DRIVER_VERSION %u\n\n", $wgl_version + 1;

612 613
print HEADER "struct wgl_context;\n";
print HEADER "struct wgl_pbuffer;\n\n";
614

615
print HEADER "struct opengl_funcs\n{\n";
616 617 618
print HEADER "    struct\n    {\n";
foreach (sort keys %wgl_functions)
{
619
    next unless defined $supported_wgl_functions{$_};
620
    print HEADER get_func_proto("        %-10s (WINAPI *p_%s)(%s);\n", $_, $wgl_functions{$_}, 1);
621 622 623
}
print HEADER "    } wgl;\n\n";

624 625 626 627
print HEADER "    struct\n    {\n";
foreach (sort keys %norm_functions)
{
    next if $_ eq "glDebugEntry";
628
    print HEADER get_func_proto("        %-10s (WINE_GLAPI *p_%s)(%s);\n", $_, $norm_functions{$_}, 1);
629 630 631 632 633 634
}
print HEADER "    } gl;\n\n";

print HEADER "    struct\n    {\n";
foreach (sort keys %ext_functions)
{
635
    print HEADER get_func_proto("        %-10s (WINE_GLAPI *p_%s)(%s);\n", $_, $ext_functions{$_}, 1);
636 637 638 639 640 641 642 643 644 645 646 647
}
print HEADER "    } ext;\n";
print HEADER "};\n\n";

print HEADER "#define ALL_WGL_FUNCS";
foreach (sort keys %norm_functions)
{
    next if $_ eq "glDebugEntry";
    printf HEADER " \\\n    USE_GL_FUNC(\%s)", $_;
}
print HEADER "\n\n";

648 649
print HEADER "extern struct opengl_funcs * CDECL __wine_get_wgl_driver( HDC hdc, UINT version );\n";
print HEADER "extern BOOL CDECL __wine_set_pixel_format( HWND hwnd, int format );\n\n";
650 651 652
print HEADER "#endif /* __WINE_WGL_DRIVER_H */\n";
close HEADER;

653 654 655
#
# Generate the wgl.h file
#
656 657
open HEADER, ">$wgl_file" or die "cannot create $wgl_file";
print HEADER "/* Automatically generated from http://www.opengl.org/registry files; DO NOT EDIT! */\n\n";
658 659 660 661 662 663 664
print HEADER "#ifndef __WINE_WGL_H\n";
print HEADER "#define __WINE_WGL_H\n\n";

print HEADER "#ifndef GLAPIENTRY\n";
print HEADER "#define GLAPIENTRY __stdcall\n";
print HEADER "#endif\n\n";

665
foreach (@gl_types)
666
{
667 668 669
    my $type = $gl_types{$_}->textContent();
    foreach my $t (keys %khronos_types) { $type =~ s/\s(\Q$t\E)\s/ $khronos_types{$t} /; }
    printf HEADER $type . "\n";
670 671 672 673
}
print HEADER "\n";

my $maxlen = 1;
674 675
foreach (keys %gl_enums) { $maxlen = length($_) if length($_) > $maxlen; }
foreach (sort keys %gl_enums)
676
{
677
    printf HEADER "#define %-*s %s\n", $maxlen, $_, $gl_enums{$_};
678 679 680 681 682
}
print HEADER "\n";

foreach (sort keys %norm_functions)
{
683
    printf HEADER "%s;\n", get_func_proto("%-10s GLAPIENTRY %s(%s)", $_, $norm_functions{$_}, 0);
684 685 686 687 688
}

print HEADER "\n#endif /* __WINE_WGL_H */\n";
close HEADER;

689 690 691
#
# Now, generate the output files. First, the spec file.
#
692
open(SPEC, ">$spec_file") or die "cannot create $spec_file";
693 694

foreach (sort keys %norm_functions) {
695 696 697 698
    printf SPEC "%s\n", generate_spec_entry( $_, $norm_functions{$_} );
}
foreach (sort keys %wgl_functions) {
    printf SPEC "%s\n", generate_spec_entry( $_, $wgl_functions{$_} );
699
}
700

701 702
close(SPEC);

703 704 705 706 707 708 709 710 711 712
my $file_header =
"/* Automatically generated from http://www.opengl.org/registry files; DO NOT EDIT! */\n\n" .
"#include \"config.h\"\n" .
"#include <stdarg.h>\n" .
"#include \"winternl.h\"\n" .
"#include \"opengl_ext.h\"\n" .
"#include \"wine/debug.h\"\n\n";

$file_header .= "WINE_DEFAULT_DEBUG_CHANNEL(opengl);\n\n" if $gen_traces;

713 714 715
#
# After the spec file, the opengl_norm.c file
#
716
open(NORM, ">$norm_file") or die "cannot create $norm_file";
717
print NORM $file_header;
718

719
foreach (sort keys %norm_functions) {
720 721
    next if needs_wrapper( $_, $norm_functions{$_} );
    print NORM GenerateThunk($_, $norm_functions{$_}, "gl");
722
}
723

724
foreach (sort keys %wgl_functions) {
725
    next unless defined $supported_wgl_functions{$_};
726
    print NORM generate_null_func($_, $wgl_functions{$_}, " WINAPI");
727
}
728
foreach (sort keys %norm_functions) {
729
    print NORM generate_null_func($_, $norm_functions{$_}, "");
730
}
731
foreach (sort keys %ext_functions) {
732
    print NORM generate_null_func($_, $ext_functions{$_}, "");
733
}
734

735
print NORM "\nstruct opengl_funcs null_opengl_funcs =\n{\n    {\n";
736 737 738 739 740
foreach (sort keys %wgl_functions)
{
    next unless defined $supported_wgl_functions{$_};
    print NORM "        null_$_,\n";
}
741 742 743 744 745
print NORM "    },\n    {\n";
foreach (sort keys %norm_functions) { print NORM "        null_$_,\n" unless $_ eq "glDebugEntry"; }
print NORM "    },\n    {\n";
foreach (sort keys %ext_functions) { print NORM "        null_$_,\n"; }
print NORM "    }\n};\n";
746

747 748 749 750 751
close(NORM);

#
# Finally, more complex, the opengl_ext.c file
#
752
open(EXT, ">$ext_file") or die "cannot create $ext_file";
753
print EXT $file_header;
754

755 756
# The thunks themselves....
my $count = keys %ext_functions;
757 758
my $wrappers = "";
print EXT "const int extension_registry_size = $count;\n\n";
759
foreach (sort keys %ext_functions) {
760 761 762 763 764 765 766
    if (needs_wrapper( $_, $ext_functions{$_} ))
    {
        $wrappers .= get_func_proto("extern %s WINAPI %s(%s) DECLSPEC_HIDDEN;\n", $_, $ext_functions{$_}, 0);
    }
    else
    {
        print EXT "static " . GenerateThunk($_, $ext_functions{$_}, "ext");
767
    }
768
}
769
print EXT $wrappers;
770

771
# Then the table giving the string <-> function correspondence */
772
print EXT "\nconst OpenGL_extension extension_registry[$count] = {\n";
773
my $i = 0;
774
foreach (sort keys %ext_functions) {
775
    my $func_ref = $ext_functions{$_};
776
    printf EXT "  { \"%s\", \"%s\", %s }", $_, join(" ", sort @{$func_ref->[2]}), $_;
777
    if ($i != $count-1) {
778
        print EXT ",";
779 780 781 782 783 784 785
    }
    $i++;
    print EXT "\n";
}
print EXT "};\n";

close(EXT);