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