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