• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
2
3# (C) Copyright IBM Corporation 2004, 2005
4# All Rights Reserved.
5# Copyright (c) 2015 Intel Corporation
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the "Software"),
9# to deal in the Software without restriction, including without limitation
10# on the rights to use, copy, modify, merge, publish, distribute, sub
11# license, and/or sell copies of the Software, and to permit persons to whom
12# the Software is furnished to do so, subject to the following conditions:
13#
14# The above copyright notice and this permission notice (including the next
15# paragraph) shall be included in all copies or substantial portions of the
16# Software.
17#
18# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
21# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
23# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
24# IN THE SOFTWARE.
25#
26# Authors:
27#    Ian Romanick <idr@us.ibm.com>
28#    Jeremy Kolb <jkolb@brandeis.edu>
29
30import argparse
31
32import gl_XML, glX_XML, glX_proto_common, license
33import copy, string
34
35def convertStringForXCB(str):
36    tmp = ""
37    special = [ "ARB" ]
38    i = 0
39    while i < len(str):
40        if str[i:i+3] in special:
41            tmp = '%s_%s' % (tmp, string.lower(str[i:i+3]))
42            i = i + 2;
43        elif str[i].isupper():
44            tmp = '%s_%s' % (tmp, string.lower(str[i]))
45        else:
46            tmp = '%s%s' % (tmp, str[i])
47        i += 1
48    return tmp
49
50def hash_pixel_function(func):
51    """Generate a 'unique' key for a pixel function.  The key is based on
52    the parameters written in the command packet.  This includes any
53    padding that might be added for the original function and the 'NULL
54    image' flag."""
55
56
57    h = ""
58    hash_pre = ""
59    hash_suf = ""
60    for param in func.parameterIterateGlxSend():
61        if param.is_image():
62            [dim, junk, junk, junk, junk] = param.get_dimensions()
63
64            d = (dim + 1) & ~1
65            hash_pre = "%uD%uD_" % (d - 1, d)
66
67            if param.img_null_flag:
68                hash_suf = "_NF"
69
70        h += "%u" % (param.size())
71
72        if func.pad_after(param):
73            h += "4"
74
75
76    n = func.name.replace("%uD" % (dim), "")
77    n = "__glx_%s_%uD%uD" % (n, d - 1, d)
78
79    h = hash_pre + h + hash_suf
80    return [h, n]
81
82
83class glx_pixel_function_stub(glX_XML.glx_function):
84    """Dummy class used to generate pixel "utility" functions that are
85    shared by multiple dimension image functions.  For example, these
86    objects are used to generate shared functions used to send GLX
87    protocol for TexImage1D and TexImage2D, TexSubImage1D and
88    TexSubImage2D, etc."""
89
90    def __init__(self, func, name):
91        # The parameters to the utility function are the same as the
92        # parameters to the real function except for the added "pad"
93        # parameters.
94
95        self.name = name
96        self.images = []
97        self.parameters = []
98        self.parameters_by_name = {}
99        for _p in func.parameterIterator():
100            p = copy.copy(_p)
101            self.parameters.append(p)
102            self.parameters_by_name[ p.name ] = p
103
104
105            if p.is_image():
106                self.images.append(p)
107                p.height = "height"
108
109                if p.img_yoff == None:
110                    p.img_yoff = "yoffset"
111
112                if p.depth:
113                    if p.extent == None:
114                        p.extent = "extent"
115
116                    if p.img_woff == None:
117                        p.img_woff = "woffset"
118
119
120            pad_name = func.pad_after(p)
121            if pad_name:
122                pad = copy.copy(p)
123                pad.name = pad_name
124                self.parameters.append(pad)
125                self.parameters_by_name[ pad.name ] = pad
126
127
128        self.return_type = func.return_type
129
130        self.glx_rop = ~0
131        self.glx_sop = 0
132        self.glx_vendorpriv = 0
133
134        self.glx_doubles_in_order = func.glx_doubles_in_order
135
136        self.vectorequiv = None
137        self.output = None
138        self.can_be_large = func.can_be_large
139        self.reply_always_array = func.reply_always_array
140        self.dimensions_in_reply = func.dimensions_in_reply
141        self.img_reset = None
142
143        self.server_handcode = 0
144        self.client_handcode = 0
145        self.ignore = 0
146
147        self.count_parameter_list = func.count_parameter_list
148        self.counter_list = func.counter_list
149        self.offsets_calculated = 0
150        return
151
152
153class PrintGlxProtoStubs(glX_proto_common.glx_print_proto):
154    def __init__(self):
155        glX_proto_common.glx_print_proto.__init__(self)
156        self.name = "glX_proto_send.py (from Mesa)"
157        self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004, 2005", "IBM")
158
159
160        self.last_category = ""
161        self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32]
162        self.pixel_stubs = {}
163        self.debug = 0
164        return
165
166    def printRealHeader(self):
167        print ''
168        print '#include <GL/gl.h>'
169        print '#include "indirect.h"'
170        print '#include "glxclient.h"'
171        print '#include "indirect_size.h"'
172        print '#include "glapi.h"'
173        print '#include <GL/glxproto.h>'
174        print '#include <X11/Xlib-xcb.h>'
175        print '#include <xcb/xcb.h>'
176        print '#include <xcb/glx.h>'
177        print '#include <limits.h>'
178
179        print ''
180        self.printFastcall()
181        self.printNoinline()
182        print ''
183
184        print 'static _X_INLINE int safe_add(int a, int b)'
185        print '{'
186        print '    if (a < 0 || b < 0) return -1;'
187        print '    if (INT_MAX - a < b) return -1;'
188        print '    return a + b;'
189        print '}'
190        print 'static _X_INLINE int safe_mul(int a, int b)'
191        print '{'
192        print '    if (a < 0 || b < 0) return -1;'
193        print '    if (a == 0 || b == 0) return 0;'
194        print '    if (a > INT_MAX / b) return -1;'
195        print '    return a * b;'
196        print '}'
197        print 'static _X_INLINE int safe_pad(int a)'
198        print '{'
199        print '    int ret;'
200        print '    if (a < 0) return -1;'
201        print '    if ((ret = safe_add(a, 3)) < 0) return -1;'
202        print '    return ret & (GLuint)~3;'
203        print '}'
204        print ''
205
206        print '#ifndef __GNUC__'
207        print '#  define __builtin_expect(x, y) x'
208        print '#endif'
209        print ''
210        print '/* If the size and opcode values are known at compile-time, this will, on'
211        print ' * x86 at least, emit them with a single instruction.'
212        print ' */'
213        print '#define emit_header(dest, op, size)            \\'
214        print '    do { union { short s[2]; int i; } temp;    \\'
215        print '         temp.s[0] = (size); temp.s[1] = (op); \\'
216        print '         *((int *)(dest)) = temp.i; } while(0)'
217        print ''
218        print """NOINLINE CARD32
219__glXReadReply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array )
220{
221    xGLXSingleReply reply;
222
223    (void) _XReply(dpy, (xReply *) & reply, 0, False);
224    if (size != 0) {
225        if ((reply.length > 0) || reply_is_always_array) {
226            const GLint bytes = (reply_is_always_array)
227              ? (4 * reply.length) : (reply.size * size);
228            const GLint extra = 4 - (bytes & 3);
229
230            _XRead(dpy, dest, bytes);
231            if ( extra < 4 ) {
232                _XEatData(dpy, extra);
233            }
234        }
235        else {
236            (void) memcpy( dest, &(reply.pad3), size);
237        }
238    }
239
240    return reply.retval;
241}
242
243NOINLINE void
244__glXReadPixelReply( Display *dpy, struct glx_context * gc, unsigned max_dim,
245    GLint width, GLint height, GLint depth, GLenum format, GLenum type,
246    void * dest, GLboolean dimensions_in_reply )
247{
248    xGLXSingleReply reply;
249    GLint size;
250
251    (void) _XReply(dpy, (xReply *) & reply, 0, False);
252
253    if ( dimensions_in_reply ) {
254        width  = reply.pad3;
255        height = reply.pad4;
256        depth  = reply.pad5;
257
258	if ((height == 0) || (max_dim < 2)) { height = 1; }
259	if ((depth  == 0) || (max_dim < 3)) { depth  = 1; }
260    }
261
262    size = reply.length * 4;
263    if (size != 0) {
264        void * buf = malloc( size );
265
266        if ( buf == NULL ) {
267            _XEatData(dpy, size);
268            __glXSetError(gc, GL_OUT_OF_MEMORY);
269        }
270        else {
271            const GLint extra = 4 - (size & 3);
272
273            _XRead(dpy, buf, size);
274            if ( extra < 4 ) {
275                _XEatData(dpy, extra);
276            }
277
278            __glEmptyImage(gc, 3, width, height, depth, format, type,
279                           buf, dest);
280            free(buf);
281        }
282    }
283}
284
285#define X_GLXSingle 0
286
287NOINLINE FASTCALL GLubyte *
288__glXSetupSingleRequest( struct glx_context * gc, GLint sop, GLint cmdlen )
289{
290    xGLXSingleReq * req;
291    Display * const dpy = gc->currentDpy;
292
293    (void) __glXFlushRenderBuffer(gc, gc->pc);
294    LockDisplay(dpy);
295    GetReqExtra(GLXSingle, cmdlen, req);
296    req->reqType = gc->majorOpcode;
297    req->contextTag = gc->currentContextTag;
298    req->glxCode = sop;
299    return (GLubyte *)(req) + sz_xGLXSingleReq;
300}
301
302NOINLINE FASTCALL GLubyte *
303__glXSetupVendorRequest( struct glx_context * gc, GLint code, GLint vop, GLint cmdlen )
304{
305    xGLXVendorPrivateReq * req;
306    Display * const dpy = gc->currentDpy;
307
308    (void) __glXFlushRenderBuffer(gc, gc->pc);
309    LockDisplay(dpy);
310    GetReqExtra(GLXVendorPrivate, cmdlen, req);
311    req->reqType = gc->majorOpcode;
312    req->glxCode = code;
313    req->vendorCode = vop;
314    req->contextTag = gc->currentContextTag;
315    return (GLubyte *)(req) + sz_xGLXVendorPrivateReq;
316}
317
318const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 };
319
320#define zero                        (__glXDefaultPixelStore+0)
321#define one                         (__glXDefaultPixelStore+8)
322#define default_pixel_store_1D      (__glXDefaultPixelStore+4)
323#define default_pixel_store_1D_size 20
324#define default_pixel_store_2D      (__glXDefaultPixelStore+4)
325#define default_pixel_store_2D_size 20
326#define default_pixel_store_3D      (__glXDefaultPixelStore+0)
327#define default_pixel_store_3D_size 36
328#define default_pixel_store_4D      (__glXDefaultPixelStore+0)
329#define default_pixel_store_4D_size 36
330"""
331
332        for size in self.generic_sizes:
333            self.print_generic_function(size)
334        return
335
336
337    def printBody(self, api):
338
339        self.pixel_stubs = {}
340        generated_stubs = []
341
342        for func in api.functionIterateGlx():
343            if func.client_handcode: continue
344
345            # If the function is a pixel function with a certain
346            # GLX protocol signature, create a fake stub function
347            # for it.  For example, create a single stub function
348            # that is used to implement both glTexImage1D and
349            # glTexImage2D.
350
351            if func.glx_rop != 0:
352                do_it = 0
353                for image in func.get_images():
354                    if image.img_pad_dimensions:
355                        do_it = 1
356                        break
357
358
359                if do_it:
360                    [h, n] = hash_pixel_function(func)
361
362
363                    self.pixel_stubs[ func.name ] = n
364                    if h not in generated_stubs:
365                        generated_stubs.append(h)
366
367                        fake_func = glx_pixel_function_stub( func, n )
368                        self.printFunction(fake_func, fake_func.name)
369
370
371            self.printFunction(func, func.name)
372            if func.glx_sop and func.glx_vendorpriv:
373                self.printFunction(func, func.glx_vendorpriv_names[0])
374
375        self.printGetProcAddress(api)
376        return
377
378    def printGetProcAddress(self, api):
379        procs = {}
380        for func in api.functionIterateGlx():
381            for n in func.entry_points:
382                if func.has_different_protocol(n):
383                    procs[n] = func.static_glx_name(n)
384
385        print """
386#ifdef GLX_SHARED_GLAPI
387
388static const struct proc_pair
389{
390   const char *name;
391   _glapi_proc proc;
392} proc_pairs[%d] = {""" % len(procs)
393        names = procs.keys()
394        names.sort()
395        for i in xrange(len(names)):
396            comma = ',' if i < len(names) - 1 else ''
397            print '   { "%s", (_glapi_proc) gl%s }%s' % (names[i], procs[names[i]], comma)
398        print """};
399
400static int
401__indirect_get_proc_compare(const void *key, const void *memb)
402{
403   const struct proc_pair *pair = (const struct proc_pair *) memb;
404   return strcmp((const char *) key, pair->name);
405}
406
407_glapi_proc
408__indirect_get_proc_address(const char *name)
409{
410   const struct proc_pair *pair;
411
412   /* skip "gl" */
413   name += 2;
414
415   pair = (const struct proc_pair *) bsearch((const void *) name,
416      (const void *) proc_pairs, ARRAY_SIZE(proc_pairs), sizeof(proc_pairs[0]),
417      __indirect_get_proc_compare);
418
419   return (pair) ? pair->proc : NULL;
420}
421
422#endif /* GLX_SHARED_GLAPI */
423"""
424        return
425
426
427    def printFunction(self, func, name):
428        footer = '}\n'
429        if func.glx_rop == ~0:
430            print 'static %s' % (func.return_type)
431            print '%s( unsigned opcode, unsigned dim, %s )' % (func.name, func.get_parameter_string())
432            print '{'
433        else:
434            if func.has_different_protocol(name):
435                if func.return_type == "void":
436                    ret_string = ''
437                else:
438                    ret_string = "return "
439
440                func_name = func.static_glx_name(name)
441                print '#define %s %d' % (func.opcode_vendor_name(name), func.glx_vendorpriv)
442                print '%s gl%s(%s)' % (func.return_type, func_name, func.get_parameter_string())
443                print '{'
444                print '    struct glx_context * const gc = __glXGetCurrentContext();'
445                print ''
446                print '#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)'
447                print '    if (gc->isDirect) {'
448                print '        const _glapi_proc *const disp_table = (_glapi_proc *)GET_DISPATCH();'
449                print '        PFNGL%sPROC p =' % (name.upper())
450                print '            (PFNGL%sPROC) disp_table[%d];' % (name.upper(), func.offset)
451                print '    %sp(%s);' % (ret_string, func.get_called_parameter_string())
452                print '    } else'
453                print '#endif'
454                print '    {'
455
456                footer = '}\n}\n'
457            else:
458                print '#define %s %d' % (func.opcode_name(), func.opcode_value())
459
460                print '%s __indirect_gl%s(%s)' % (func.return_type, name, func.get_parameter_string())
461                print '{'
462
463
464        if func.glx_rop != 0 or func.vectorequiv != None:
465            if len(func.images):
466                self.printPixelFunction(func)
467            else:
468                self.printRenderFunction(func)
469        elif func.glx_sop != 0 or func.glx_vendorpriv != 0:
470            self.printSingleFunction(func, name)
471            pass
472        else:
473            print "/* Missing GLX protocol for %s. */" % (name)
474
475        print footer
476        return
477
478
479    def print_generic_function(self, n):
480        size = (n + 3) & ~3
481        print """static FASTCALL NOINLINE void
482generic_%u_byte( GLint rop, const void * ptr )
483{
484    struct glx_context * const gc = __glXGetCurrentContext();
485    const GLuint cmdlen = %u;
486
487    emit_header(gc->pc, rop, cmdlen);
488    (void) memcpy((void *)(gc->pc + 4), ptr, %u);
489    gc->pc += cmdlen;
490    if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }
491}
492""" % (n, size + 4, size)
493        return
494
495
496    def common_emit_one_arg(self, p, pc, adjust, extra_offset):
497        if p.is_array():
498            src_ptr = p.name
499        else:
500            src_ptr = "&" + p.name
501
502        if p.is_padding:
503            print '(void) memset((void *)(%s + %u), 0, %s);' \
504                % (pc, p.offset + adjust, p.size_string() )
505        elif not extra_offset:
506            print '(void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \
507                % (pc, p.offset + adjust, src_ptr, p.size_string() )
508        else:
509            print '(void) memcpy((void *)(%s + %u + %s), (void *)(%s), %s);' \
510                % (pc, p.offset + adjust, extra_offset, src_ptr, p.size_string() )
511
512    def common_emit_args(self, f, pc, adjust, skip_vla):
513        extra_offset = None
514
515        for p in f.parameterIterateGlxSend( not skip_vla ):
516            if p.name != f.img_reset:
517                self.common_emit_one_arg(p, pc, adjust, extra_offset)
518
519                if p.is_variable_length():
520                    temp = p.size_string()
521                    if extra_offset:
522                        extra_offset += " + %s" % (temp)
523                    else:
524                        extra_offset = temp
525
526        return
527
528
529    def pixel_emit_args(self, f, pc, large):
530        """Emit the arguments for a pixel function.  This differs from
531        common_emit_args in that pixel functions may require padding
532        be inserted (i.e., for the missing width field for
533        TexImage1D), and they may also require a 'NULL image' flag
534        be inserted before the image data."""
535
536        if large:
537            adjust = 8
538        else:
539            adjust = 4
540
541        for param in f.parameterIterateGlxSend():
542            if not param.is_image():
543                self.common_emit_one_arg(param, pc, adjust, None)
544
545                if f.pad_after(param):
546                    print '(void) memcpy((void *)(%s + %u), zero, 4);' % (pc, (param.offset + param.size()) + adjust)
547
548            else:
549                [dim, width, height, depth, extent] = param.get_dimensions()
550                if f.glx_rop == ~0:
551                    dim_str = "dim"
552                else:
553                    dim_str = str(dim)
554
555                if param.is_padding:
556                    print '(void) memset((void *)(%s + %u), 0, %s);' \
557                    % (pc, (param.offset - 4) + adjust, param.size_string() )
558
559                if param.img_null_flag:
560                    if large:
561                        print '(void) memcpy((void *)(%s + %u), zero, 4);' % (pc, (param.offset - 4) + adjust)
562                    else:
563                        print '(void) memcpy((void *)(%s + %u), (void *)((%s == NULL) ? one : zero), 4);' % (pc, (param.offset - 4) + adjust, param.name)
564
565
566                pixHeaderPtr = "%s + %u" % (pc, adjust)
567                pcPtr = "%s + %u" % (pc, param.offset + adjust)
568
569                if not large:
570                    if param.img_send_null:
571                        condition = '(compsize > 0) && (%s != NULL)' % (param.name)
572                    else:
573                        condition = 'compsize > 0'
574
575                    print 'if (%s) {' % (condition)
576                    print '    gc->fillImage(gc, %s, %s, %s, %s, %s, %s, %s, %s, %s);' % (dim_str, width, height, depth, param.img_format, param.img_type, param.name, pcPtr, pixHeaderPtr)
577                    print '} else {'
578                    print '    (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (pixHeaderPtr, dim, dim)
579                    print '}'
580                else:
581                    print '__glXSendLargeImage(gc, compsize, %s, %s, %s, %s, %s, %s, %s, %s, %s);' % (dim_str, width, height, depth, param.img_format, param.img_type, param.name, pcPtr, pixHeaderPtr)
582
583        return
584
585
586    def large_emit_begin(self, f, op_name = None):
587        if not op_name:
588            op_name = f.opcode_real_name()
589
590        print 'const GLint op = %s;' % (op_name)
591        print 'const GLuint cmdlenLarge = cmdlen + 4;'
592        print 'GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);'
593        print '(void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);'
594        print '(void) memcpy((void *)(pc + 4), (void *)(&op), 4);'
595        return
596
597
598    def common_func_print_just_start(self, f, name):
599        print '    struct glx_context * const gc = __glXGetCurrentContext();'
600
601        # The only reason that single and vendor private commands need
602        # a variable called 'dpy' is because they use the SyncHandle
603        # macro.  For whatever brain-dead reason, that macro is hard-
604        # coded to use a variable called 'dpy' instead of taking a
605        # parameter.
606
607        # FIXME Simplify the logic related to skip_condition and
608        # FIXME condition_list in this function.  Basically, remove
609        # FIXME skip_condition, and just append the "dpy != NULL" type
610        # FIXME condition to condition_list from the start.  The only
611        # FIXME reason it's done in this confusing way now is to
612        # FIXME minimize the diffs in the generated code.
613
614        if not f.glx_rop:
615            for p in f.parameterIterateOutputs():
616                if p.is_image() and (p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP"):
617                    print '    const __GLXattribute * const state = gc->client_state_private;'
618                    break
619
620            print '    Display * const dpy = gc->currentDpy;'
621            skip_condition = "dpy != NULL"
622        elif f.can_be_large:
623            skip_condition = "gc->currentDpy != NULL"
624        else:
625            skip_condition = None
626
627
628        if f.return_type != 'void':
629            print '    %s retval = (%s) 0;' % (f.return_type, f.return_type)
630
631
632        if name != None and name not in f.glx_vendorpriv_names:
633            print '#ifndef USE_XCB'
634        self.emit_packet_size_calculation(f, 0)
635        if name != None and name not in f.glx_vendorpriv_names:
636            print '#endif'
637
638        if f.command_variable_length() != "":
639            print "    if (0%s < 0) {" % f.command_variable_length()
640            print "        __glXSetError(gc, GL_INVALID_VALUE);"
641            if f.return_type != 'void':
642                print "        return 0;"
643            else:
644                print "        return;"
645            print "    }"
646
647        condition_list = []
648        for p in f.parameterIterateCounters():
649            condition_list.append( "%s >= 0" % (p.name) )
650            # 'counter' parameters cannot be negative
651            print "    if (%s < 0) {" % p.name
652            print "        __glXSetError(gc, GL_INVALID_VALUE);"
653            if f.return_type != 'void':
654                print "        return 0;"
655            else:
656                print "        return;"
657            print "    }"
658
659        if skip_condition:
660            condition_list.append( skip_condition )
661
662        if len( condition_list ) > 0:
663            if len( condition_list ) > 1:
664                skip_condition = "(%s)" % (string.join( condition_list, ") && (" ))
665            else:
666                skip_condition = "%s" % (condition_list.pop(0))
667
668            print '    if (__builtin_expect(%s, 1)) {' % (skip_condition)
669            return 1
670        else:
671            return 0
672
673
674    def printSingleFunction(self, f, name):
675        self.common_func_print_just_start(f, name)
676
677        if self.debug:
678            print '        printf( "Enter %%s...\\n", "gl%s" );' % (f.name)
679
680        if name not in f.glx_vendorpriv_names:
681
682            # XCB specific:
683            print '#ifdef USE_XCB'
684            if self.debug:
685                print '        printf("\\tUsing XCB.\\n");'
686            print '        xcb_connection_t *c = XGetXCBConnection(dpy);'
687            print '        (void) __glXFlushRenderBuffer(gc, gc->pc);'
688            xcb_name = 'xcb_glx%s' % convertStringForXCB(name)
689
690            iparams=[]
691            extra_iparams = []
692            output = None
693            for p in f.parameterIterator():
694                if p.is_output:
695                    output = p
696
697                    if p.is_image():
698                        if p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP":
699                            extra_iparams.append("state->storePack.swapEndian")
700                        else:
701                            extra_iparams.append("0")
702
703                        # Hardcode this in.  lsb_first param (apparently always GL_FALSE)
704                        # also present in GetPolygonStipple, but taken care of above.
705                        if xcb_name == "xcb_glx_read_pixels":
706                            extra_iparams.append("0")
707                else:
708                    iparams.append(p.name)
709
710
711            xcb_request = '%s(%s)' % (xcb_name, ", ".join(["c", "gc->currentContextTag"] + iparams + extra_iparams))
712
713            if f.needs_reply():
714                print '        %s_reply_t *reply = %s_reply(c, %s, NULL);' % (xcb_name, xcb_name, xcb_request)
715                if output:
716                    if output.is_image():
717                        [dim, w, h, d, junk] = output.get_dimensions()
718                        if f.dimensions_in_reply:
719                            w = "reply->width"
720                            h = "reply->height"
721                            d = "reply->depth"
722                            if dim < 2:
723                                h = "1"
724                            else:
725                                print '        if (%s == 0) { %s = 1; }' % (h, h)
726                            if dim < 3:
727                                d = "1"
728                            else:
729                                print '        if (%s == 0) { %s = 1; }' % (d, d)
730
731                        print '        __glEmptyImage(gc, 3, %s, %s, %s, %s, %s, %s_data(reply), %s);' % (w, h, d, output.img_format, output.img_type, xcb_name, output.name)
732                    else:
733                        if f.reply_always_array:
734                            print '        (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
735                        else:
736                            print '        /* the XXX_data_length() xcb function name is misleading, it returns the number */'
737                            print '        /* of elements, not the length of the data part. A single element is embedded. */'
738                            print '        if (%s_data_length(reply) == 1)' % (xcb_name)
739                            print '            (void)memcpy(%s, &reply->datum, sizeof(reply->datum));' % (output.name)
740                            print '        else'
741                            print '            (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
742
743                if f.return_type != 'void':
744                    print '        retval = reply->ret_val;'
745                print '        free(reply);'
746            else:
747                print '        ' + xcb_request + ';'
748            print '#else'
749            # End of XCB specific.
750
751
752        if f.parameters != []:
753            pc_decl = "GLubyte const * pc ="
754        else:
755            pc_decl = "(void)"
756
757        if name in f.glx_vendorpriv_names:
758            print '        %s __glXSetupVendorRequest(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_vendor_name(name))
759        else:
760            print '        %s __glXSetupSingleRequest(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
761
762        self.common_emit_args(f, "pc", 0, 0)
763
764        images = f.get_images()
765
766        for img in images:
767            if img.is_output:
768                o = f.command_fixed_length() - 4
769                print '        *(int32_t *)(pc + %u) = 0;' % (o)
770                if img.img_format != "GL_COLOR_INDEX" or img.img_type != "GL_BITMAP":
771                    print '        * (int8_t *)(pc + %u) = state->storePack.swapEndian;' % (o)
772
773                if f.img_reset:
774                    print '        * (int8_t *)(pc + %u) = %s;' % (o + 1, f.img_reset)
775
776
777        return_name = ''
778        if f.needs_reply():
779            if f.return_type != 'void':
780                return_name = " retval"
781                return_str = " retval = (%s)" % (f.return_type)
782            else:
783                return_str = " (void)"
784
785            got_reply = 0
786
787            for p in f.parameterIterateOutputs():
788                if p.is_image():
789                    [dim, w, h, d, junk] = p.get_dimensions()
790                    if f.dimensions_in_reply:
791                        print "        __glXReadPixelReply(dpy, gc, %u, 0, 0, 0, %s, %s, %s, GL_TRUE);" % (dim, p.img_format, p.img_type, p.name)
792                    else:
793                        print "        __glXReadPixelReply(dpy, gc, %u, %s, %s, %s, %s, %s, %s, GL_FALSE);" % (dim, w, h, d, p.img_format, p.img_type, p.name)
794
795                    got_reply = 1
796                else:
797                    if f.reply_always_array:
798                        aa = "GL_TRUE"
799                    else:
800                        aa = "GL_FALSE"
801
802                    # gl_parameter.size() returns the size
803                    # of the entire data item.  If the
804                    # item is a fixed-size array, this is
805                    # the size of the whole array.  This
806                    # is not what __glXReadReply wants. It
807                    # wants the size of a single data
808                    # element in the reply packet.
809                    # Dividing by the array size (1 for
810                    # non-arrays) gives us this.
811
812                    s = p.size() / p.get_element_count()
813                    print "       %s __glXReadReply(dpy, %s, %s, %s);" % (return_str, s, p.name, aa)
814                    got_reply = 1
815
816
817            # If a reply wasn't read to fill an output parameter,
818            # read a NULL reply to get the return value.
819
820            if not got_reply:
821                print "       %s __glXReadReply(dpy, 0, NULL, GL_FALSE);" % (return_str)
822
823
824        elif self.debug:
825            # Only emit the extra glFinish call for functions
826            # that don't already require a reply from the server.
827            print '        __indirect_glFinish();'
828
829        if self.debug:
830            print '        printf( "Exit %%s.\\n", "gl%s" );' % (name)
831
832
833        print '        UnlockDisplay(dpy); SyncHandle();'
834
835        if name not in f.glx_vendorpriv_names:
836            print '#endif /* USE_XCB */'
837
838        print '    }'
839        print '    return%s;' % (return_name)
840        return
841
842
843    def printPixelFunction(self, f):
844        if self.pixel_stubs.has_key( f.name ):
845            # Normally gl_function::get_parameter_string could be
846            # used.  However, this call needs to have the missing
847            # dimensions (e.g., a fake height value for
848            # glTexImage1D) added in.
849
850            p_string = ""
851            for param in f.parameterIterateGlxSend():
852                if param.is_padding:
853                    continue
854
855                p_string += ", " + param.name
856
857                if param.is_image():
858                    [dim, junk, junk, junk, junk] = param.get_dimensions()
859
860                if f.pad_after(param):
861                    p_string += ", 1"
862
863            print '    %s(%s, %u%s );' % (self.pixel_stubs[f.name] , f.opcode_name(), dim, p_string)
864            return
865
866
867        if self.common_func_print_just_start(f, None):
868            trailer = "    }"
869        else:
870            trailer = None
871
872
873        if f.can_be_large:
874            print 'if (cmdlen <= gc->maxSmallRenderCommandSize) {'
875            print '    if ( (gc->pc + cmdlen) > gc->bufEnd ) {'
876            print '        (void) __glXFlushRenderBuffer(gc, gc->pc);'
877            print '    }'
878
879        if f.glx_rop == ~0:
880            opcode = "opcode"
881        else:
882            opcode = f.opcode_real_name()
883
884        print 'emit_header(gc->pc, %s, cmdlen);' % (opcode)
885
886        self.pixel_emit_args( f, "gc->pc", 0 )
887        print 'gc->pc += cmdlen;'
888        print 'if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }'
889
890        if f.can_be_large:
891            print '}'
892            print 'else {'
893
894            self.large_emit_begin(f, opcode)
895            self.pixel_emit_args(f, "pc", 1)
896
897            print '}'
898
899        if trailer: print trailer
900        return
901
902
903    def printRenderFunction(self, f):
904        # There is a class of GL functions that take a single pointer
905        # as a parameter.  This pointer points to a fixed-size chunk
906        # of data, and the protocol for this functions is very
907        # regular.  Since they are so regular and there are so many
908        # of them, special case them with generic functions.  On
909        # x86, this saves about 26KB in the libGL.so binary.
910
911        if f.variable_length_parameter() == None and len(f.parameters) == 1:
912            p = f.parameters[0]
913            if p.is_pointer():
914                cmdlen = f.command_fixed_length()
915                if cmdlen in self.generic_sizes:
916                    print '    generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
917                    return
918
919        if self.common_func_print_just_start(f, None):
920            trailer = "    }"
921        else:
922            trailer = None
923
924        if self.debug:
925            print 'printf( "Enter %%s...\\n", "gl%s" );' % (f.name)
926
927        if f.can_be_large:
928            print 'if (cmdlen <= gc->maxSmallRenderCommandSize) {'
929            print '    if ( (gc->pc + cmdlen) > gc->bufEnd ) {'
930            print '        (void) __glXFlushRenderBuffer(gc, gc->pc);'
931            print '    }'
932
933        print 'emit_header(gc->pc, %s, cmdlen);' % (f.opcode_real_name())
934
935        self.common_emit_args(f, "gc->pc", 4, 0)
936        print 'gc->pc += cmdlen;'
937        print 'if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }'
938
939        if f.can_be_large:
940            print '}'
941            print 'else {'
942
943            self.large_emit_begin(f)
944            self.common_emit_args(f, "pc", 8, 1)
945
946            p = f.variable_length_parameter()
947            print '    __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (p.offset + 8, p.name, p.size_string())
948            print '}'
949
950        if self.debug:
951            print '__indirect_glFinish();'
952            print 'printf( "Exit %%s.\\n", "gl%s" );' % (f.name)
953
954        if trailer: print trailer
955        return
956
957
958class PrintGlxProtoInit_c(gl_XML.gl_print_base):
959    def __init__(self):
960        gl_XML.gl_print_base.__init__(self)
961
962        self.name = "glX_proto_send.py (from Mesa)"
963        self.license = license.bsd_license_template % ( \
964"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
965(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
966        return
967
968
969    def printRealHeader(self):
970        print """/**
971 * \\file indirect_init.c
972 * Initialize indirect rendering dispatch table.
973 *
974 * \\author Kevin E. Martin <kevin@precisioninsight.com>
975 * \\author Brian Paul <brian@precisioninsight.com>
976 * \\author Ian Romanick <idr@us.ibm.com>
977 */
978
979#include "indirect_init.h"
980#include "indirect.h"
981#include "glapi.h"
982#include <assert.h>
983
984#ifndef GLX_USE_APPLEGL
985
986/**
987 * No-op function used to initialize functions that have no GLX protocol
988 * support.
989 */
990static int NoOp(void)
991{
992    return 0;
993}
994
995/**
996 * Create and initialize a new GL dispatch table.  The table is initialized
997 * with GLX indirect rendering protocol functions.
998 */
999struct _glapi_table * __glXNewIndirectAPI( void )
1000{
1001    _glapi_proc *table;
1002    unsigned entries;
1003    unsigned i;
1004    int o;
1005
1006    entries = _glapi_get_dispatch_table_size();
1007    table = malloc(entries * sizeof(_glapi_proc));
1008    if (table == NULL)
1009        return NULL;
1010
1011    /* first, set all entries to point to no-op functions */
1012    for (i = 0; i < entries; i++) {
1013       table[i] = (_glapi_proc) NoOp;
1014    }
1015
1016    /* now, initialize the entries we understand */"""
1017
1018    def printRealFooter(self):
1019        print """
1020    return (struct _glapi_table *) table;
1021}
1022
1023#endif
1024"""
1025        return
1026
1027
1028    def printBody(self, api):
1029        for [name, number] in api.categoryIterate():
1030            if number != None:
1031                preamble = '\n    /* %3u. %s */\n' % (int(number), name)
1032            else:
1033                preamble = '\n    /* %s */\n' % (name)
1034
1035            for func in api.functionIterateByCategory(name):
1036                if func.client_supported_for_indirect():
1037                    if preamble:
1038                        print preamble
1039                        preamble = None
1040
1041                    if func.is_abi():
1042                        print '    table[{offset}] = (_glapi_proc) __indirect_gl{name};'.format(name = func.name, offset = func.offset)
1043                    else:
1044                        print '    o = _glapi_get_proc_offset("gl{0}");'.format(func.name)
1045                        print '    assert(o > 0);'
1046                        print '    table[o] = (_glapi_proc) __indirect_gl{0};'.format(func.name)
1047
1048        return
1049
1050
1051class PrintGlxProtoInit_h(gl_XML.gl_print_base):
1052    def __init__(self):
1053        gl_XML.gl_print_base.__init__(self)
1054
1055        self.name = "glX_proto_send.py (from Mesa)"
1056        self.license = license.bsd_license_template % ( \
1057"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
1058(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
1059        self.header_tag = "_INDIRECT_H_"
1060
1061        self.last_category = ""
1062        return
1063
1064
1065    def printRealHeader(self):
1066        print """/**
1067 * \\file
1068 * Prototypes for indirect rendering functions.
1069 *
1070 * \\author Kevin E. Martin <kevin@precisioninsight.com>
1071 * \\author Ian Romanick <idr@us.ibm.com>
1072 */
1073"""
1074        self.printFastcall()
1075        self.printNoinline()
1076
1077        print """
1078#include <X11/Xfuncproto.h>
1079#include "glxclient.h"
1080
1081extern _X_HIDDEN NOINLINE CARD32 __glXReadReply( Display *dpy, size_t size,
1082    void * dest, GLboolean reply_is_always_array );
1083
1084extern _X_HIDDEN NOINLINE void __glXReadPixelReply( Display *dpy,
1085    struct glx_context * gc, unsigned max_dim, GLint width, GLint height,
1086    GLint depth, GLenum format, GLenum type, void * dest,
1087    GLboolean dimensions_in_reply );
1088
1089extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupSingleRequest(
1090    struct glx_context * gc, GLint sop, GLint cmdlen );
1091
1092extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupVendorRequest(
1093    struct glx_context * gc, GLint code, GLint vop, GLint cmdlen );
1094"""
1095
1096
1097    def printBody(self, api):
1098        for func in api.functionIterateGlx():
1099            params = func.get_parameter_string()
1100
1101            print 'extern _X_HIDDEN %s __indirect_gl%s(%s);' % (func.return_type, func.name, params)
1102
1103            for n in func.entry_points:
1104                if func.has_different_protocol(n):
1105                    asdf = func.static_glx_name(n)
1106                    if asdf not in func.static_entry_points:
1107                        print 'extern _X_HIDDEN %s gl%s(%s);' % (func.return_type, asdf, params)
1108                        # give it a easy-to-remember name
1109                        if func.client_handcode:
1110                            print '#define gl_dispatch_stub_%s gl%s' % (n, asdf)
1111                    else:
1112                        print 'GLAPI %s GLAPIENTRY gl%s(%s);' % (func.return_type, asdf, params)
1113
1114                    break
1115
1116        print ''
1117        print '#ifdef GLX_SHARED_GLAPI'
1118        print 'extern _X_HIDDEN void (*__indirect_get_proc_address(const char *name))(void);'
1119        print '#endif'
1120
1121
1122def _parser():
1123    """Parse input and returned a parsed namespace."""
1124    parser = argparse.ArgumentParser()
1125    parser.add_argument('-f',
1126                        default='gl_API.xml',
1127                        dest='filename',
1128                        help='An XML file describing an API')
1129    parser.add_argument('-m',
1130                        required=True,
1131                        dest='mode',
1132                        choices=frozenset(['proto', 'init_c', 'init_h']),
1133                        help='which file to generate')
1134    parser.add_argument('-d',
1135                        action='store_true',
1136                        dest='debug',
1137                        help='turn debug mode on.')
1138    return parser.parse_args()
1139
1140
1141def main():
1142    """Main function."""
1143    args = _parser()
1144
1145    if args.mode == "proto":
1146        printer = PrintGlxProtoStubs()
1147    elif args.mode == "init_c":
1148        printer = PrintGlxProtoInit_c()
1149    elif args.mode == "init_h":
1150        printer = PrintGlxProtoInit_h()
1151
1152    printer.debug = args.debug
1153    api = gl_XML.parse_GL_API(args.filename, glX_XML.glx_item_factory())
1154
1155    printer.Print( api )
1156
1157
1158if __name__ == '__main__':
1159    main()
1160