xref: /aosp_15_r20/external/mesa3d/src/mapi/glapi/gen/glX_proto_send.py (revision 6104692788411f58d303aa86923a9ff6ecaded22)
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 <[email protected]>
27#    Jeremy Kolb <[email protected]>
28
29import argparse
30
31import gl_XML, glX_XML, glX_proto_common, license
32import copy
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, str[i:i+3].lower())
41            i = i + 2;
42        elif str[i].isupper():
43            tmp = '%s_%s' % (tmp, str[i].lower())
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 "util/glheader.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        return
375
376    def printFunction(self, func, name):
377        footer = '}\n'
378        if func.glx_rop == ~0:
379            print('static %s' % (func.return_type))
380            print('%s( unsigned opcode, unsigned dim, %s )' % (func.name, func.get_parameter_string()))
381            print('{')
382        else:
383            if func.has_different_protocol(name):
384                if func.return_type == "void":
385                    ret_string = ''
386                else:
387                    ret_string = "return "
388
389                func_name = func.static_glx_name(name)
390                print('#define %s %d' % (func.opcode_vendor_name(name), func.glx_vendorpriv))
391                print('%s gl%s(%s)' % (func.return_type, func_name, func.get_parameter_string()))
392                print('{')
393                print('#if defined(GLX_DIRECT_RENDERING) && !defined(GLX_USE_APPLEGL)')
394                print('    if (((struct glx_context *)__glXGetCurrentContext())->isDirect) {')
395                print('        const _glapi_proc *const disp_table = (_glapi_proc *)GET_DISPATCH();')
396                print('        PFNGL%sPROC p =' % (name.upper()))
397                print('            (PFNGL%sPROC) disp_table[%d];' % (name.upper(), func.offset))
398                print('    %sp(%s);' % (ret_string, func.get_called_parameter_string()))
399                print('    } else')
400                print('#endif')
401                print('    {')
402
403                footer = '}\n}\n'
404            else:
405                print('#define %s %d' % (func.opcode_name(), func.opcode_value()))
406
407                print('%s __indirect_gl%s(%s)' % (func.return_type, name, func.get_parameter_string()))
408                print('{')
409
410
411        if func.glx_rop != 0 or func.vectorequiv != None:
412            if len(func.images):
413                self.printPixelFunction(func)
414            else:
415                self.printRenderFunction(func)
416        elif func.glx_sop != 0 or func.glx_vendorpriv != 0:
417            self.printSingleFunction(func, name)
418            pass
419        else:
420            print("/* Missing GLX protocol for %s. */" % (name))
421
422        print(footer)
423        return
424
425
426    def print_generic_function(self, n):
427        size = (n + 3) & ~3
428        print("""static FASTCALL NOINLINE void
429generic_%u_byte( GLint rop, const void * ptr )
430{
431    struct glx_context * const gc = __glXGetCurrentContext();
432    const GLuint cmdlen = %u;
433
434    emit_header(gc->pc, rop, cmdlen);
435    (void) memcpy((void *)(gc->pc + 4), ptr, %u);
436    gc->pc += cmdlen;
437    if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }
438}
439""" % (n, size + 4, size))
440        return
441
442
443    def common_emit_one_arg(self, p, pc, adjust, extra_offset):
444        if p.is_array():
445            src_ptr = p.name
446        else:
447            src_ptr = "&" + p.name
448
449        if p.is_padding:
450            print('(void) memset((void *)(%s + %u), 0, %s);' \
451                % (pc, p.offset + adjust, p.size_string() ))
452        elif not extra_offset:
453            print('(void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \
454                % (pc, p.offset + adjust, src_ptr, p.size_string() ))
455        else:
456            print('(void) memcpy((void *)(%s + %u + %s), (void *)(%s), %s);' \
457                % (pc, p.offset + adjust, extra_offset, src_ptr, p.size_string() ))
458
459    def common_emit_args(self, f, pc, adjust, skip_vla):
460        extra_offset = None
461
462        for p in f.parameterIterateGlxSend( not skip_vla ):
463            if p.name != f.img_reset:
464                self.common_emit_one_arg(p, pc, adjust, extra_offset)
465
466                if p.is_variable_length():
467                    temp = p.size_string()
468                    if extra_offset:
469                        extra_offset += " + %s" % (temp)
470                    else:
471                        extra_offset = temp
472
473        return
474
475
476    def pixel_emit_args(self, f, pc, large):
477        """Emit the arguments for a pixel function.  This differs from
478        common_emit_args in that pixel functions may require padding
479        be inserted (i.e., for the missing width field for
480        TexImage1D), and they may also require a 'NULL image' flag
481        be inserted before the image data."""
482
483        if large:
484            adjust = 8
485        else:
486            adjust = 4
487
488        for param in f.parameterIterateGlxSend():
489            if not param.is_image():
490                self.common_emit_one_arg(param, pc, adjust, None)
491
492                if f.pad_after(param):
493                    print('(void) memcpy((void *)(%s + %u), zero, 4);' % (pc, (param.offset + param.size()) + adjust))
494
495            else:
496                [dim, width, height, depth, extent] = param.get_dimensions()
497                if f.glx_rop == ~0:
498                    dim_str = "dim"
499                else:
500                    dim_str = str(dim)
501
502                if param.is_padding:
503                    print('(void) memset((void *)(%s + %u), 0, %s);' \
504                    % (pc, (param.offset - 4) + adjust, param.size_string() ))
505
506                if param.img_null_flag:
507                    if large:
508                        print('(void) memcpy((void *)(%s + %u), zero, 4);' % (pc, (param.offset - 4) + adjust))
509                    else:
510                        print('(void) memcpy((void *)(%s + %u), (void *)((%s == NULL) ? one : zero), 4);' % (pc, (param.offset - 4) + adjust, param.name))
511
512
513                pixHeaderPtr = "%s + %u" % (pc, adjust)
514                pcPtr = "%s + %u" % (pc, param.offset + adjust)
515
516                if not large:
517                    if param.img_send_null:
518                        condition = '(compsize > 0) && (%s != NULL)' % (param.name)
519                    else:
520                        condition = 'compsize > 0'
521
522                    print('if (%s) {' % (condition))
523                    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))
524                    print('} else {')
525                    print('    (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (pixHeaderPtr, dim, dim))
526                    print('}')
527                else:
528                    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))
529
530        return
531
532
533    def large_emit_begin(self, f, op_name = None):
534        if not op_name:
535            op_name = f.opcode_real_name()
536
537        print('const GLint op = %s;' % (op_name))
538        print('const GLuint cmdlenLarge = cmdlen + 4;')
539        print('GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);')
540        print('(void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);')
541        print('(void) memcpy((void *)(pc + 4), (void *)(&op), 4);')
542        return
543
544
545    def common_func_print_just_start(self, f, name):
546        print('    struct glx_context * const gc = __glXGetCurrentContext();')
547
548        # The only reason that single and vendor private commands need
549        # a variable called 'dpy' is because they use the SyncHandle
550        # macro.  For whatever brain-dead reason, that macro is hard-
551        # coded to use a variable called 'dpy' instead of taking a
552        # parameter.
553
554        # FIXME Simplify the logic related to skip_condition and
555        # FIXME condition_list in this function.  Basically, remove
556        # FIXME skip_condition, and just append the "dpy != NULL" type
557        # FIXME condition to condition_list from the start.  The only
558        # FIXME reason it's done in this confusing way now is to
559        # FIXME minimize the diffs in the generated code.
560
561        if not f.glx_rop:
562            for p in f.parameterIterateOutputs():
563                if p.is_image() and (p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP"):
564                    print('    const __GLXattribute * const state = gc->client_state_private;')
565                    break
566
567            print('    Display * const dpy = gc->currentDpy;')
568            skip_condition = "dpy != NULL"
569        elif f.can_be_large:
570            skip_condition = "gc->currentDpy != NULL"
571        else:
572            skip_condition = None
573
574
575        if f.return_type != 'void':
576            print('    %s retval = (%s) 0;' % (f.return_type, f.return_type))
577
578
579        if name != None and name not in f.glx_vendorpriv_names:
580            print('#ifndef USE_XCB')
581        self.emit_packet_size_calculation(f, 0)
582        if name != None and name not in f.glx_vendorpriv_names:
583            print('#endif')
584
585        if f.command_variable_length() != "":
586            print("    if (0%s < 0) {" % f.command_variable_length())
587            print("        __glXSetError(gc, GL_INVALID_VALUE);")
588            if f.return_type != 'void':
589                print("        return 0;")
590            else:
591                print("        return;")
592            print("    }")
593
594        condition_list = []
595        for p in f.parameterIterateCounters():
596            condition_list.append( "%s >= 0" % (p.name) )
597            # 'counter' parameters cannot be negative
598            print("    if (%s < 0) {" % p.name)
599            print("        __glXSetError(gc, GL_INVALID_VALUE);")
600            if f.return_type != 'void':
601                print("        return 0;")
602            else:
603                print("        return;")
604            print("    }")
605
606        if skip_condition:
607            condition_list.append( skip_condition )
608
609        if len( condition_list ) > 0:
610            if len( condition_list ) > 1:
611                skip_condition = "(%s)" % ") && (".join( condition_list )
612            else:
613                skip_condition = "%s" % (condition_list.pop(0))
614
615            print('    if (__builtin_expect(%s, 1)) {' % (skip_condition))
616            return 1
617        else:
618            return 0
619
620
621    def printSingleFunction(self, f, name):
622        self.common_func_print_just_start(f, name)
623
624        if self.debug:
625            print('        printf( "Enter %%s...\\n", "gl%s" );' % (f.name))
626
627        if name not in f.glx_vendorpriv_names:
628
629            # XCB specific:
630            print('#ifdef USE_XCB')
631            if self.debug:
632                print('        printf("\\tUsing XCB.\\n");')
633            print('        xcb_connection_t *c = XGetXCBConnection(dpy);')
634            print('        (void) __glXFlushRenderBuffer(gc, gc->pc);')
635            xcb_name = 'xcb_glx%s' % convertStringForXCB(name)
636
637            iparams=[]
638            extra_iparams = []
639            output = None
640            for p in f.parameterIterator():
641                if p.is_output:
642                    output = p
643
644                    if p.is_image():
645                        if p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP":
646                            extra_iparams.append("state->storePack.swapEndian")
647                        else:
648                            extra_iparams.append("0")
649
650                        # Hardcode this in.  lsb_first param (apparently always GL_FALSE)
651                        # also present in GetPolygonStipple, but taken care of above.
652                        if xcb_name == "xcb_glx_read_pixels":
653                            extra_iparams.append("0")
654                else:
655                    iparams.append(p.name)
656
657
658            xcb_request = '%s(%s)' % (xcb_name, ", ".join(["c", "gc->currentContextTag"] + iparams + extra_iparams))
659
660            if f.needs_reply():
661                print('        %s_reply_t *reply = %s_reply(c, %s, NULL);' % (xcb_name, xcb_name, xcb_request))
662                if output:
663                    if output.is_image():
664                        [dim, w, h, d, junk] = output.get_dimensions()
665                        if f.dimensions_in_reply:
666                            w = "reply->width"
667                            h = "reply->height"
668                            d = "reply->depth"
669                            if dim < 2:
670                                h = "1"
671                            else:
672                                print('        if (%s == 0) { %s = 1; }' % (h, h))
673                            if dim < 3:
674                                d = "1"
675                            else:
676                                print('        if (%s == 0) { %s = 1; }' % (d, d))
677
678                        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))
679                    else:
680                        if f.reply_always_array:
681                            print('        (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string()))
682                        else:
683                            print('        /* the XXX_data_length() xcb function name is misleading, it returns the number */')
684                            print('        /* of elements, not the length of the data part. A single element is embedded. */')
685                            print('        if (%s_data_length(reply) == 1)' % (xcb_name))
686                            print('            (void)memcpy(%s, &reply->datum, sizeof(reply->datum));' % (output.name))
687                            print('        else')
688                            print('            (void)memcpy(%s, %s_data(reply), %s_data_length(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string()))
689
690                if f.return_type != 'void':
691                    print('        retval = reply->ret_val;')
692                print('        free(reply);')
693            else:
694                print('        ' + xcb_request + ';')
695            print('#else')
696            # End of XCB specific.
697
698
699        if f.parameters != []:
700            pc_decl = "GLubyte const * pc ="
701        else:
702            pc_decl = "(void)"
703
704        if name in f.glx_vendorpriv_names:
705            print('        %s __glXSetupVendorRequest(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_vendor_name(name)))
706        else:
707            print('        %s __glXSetupSingleRequest(gc, %s, cmdlen);' % (pc_decl, f.opcode_name()))
708
709        self.common_emit_args(f, "pc", 0, 0)
710
711        images = f.get_images()
712
713        for img in images:
714            if img.is_output:
715                o = f.command_fixed_length() - 4
716                print('        *(int32_t *)(pc + %u) = 0;' % (o))
717                if img.img_format != "GL_COLOR_INDEX" or img.img_type != "GL_BITMAP":
718                    print('        * (int8_t *)(pc + %u) = state->storePack.swapEndian;' % (o))
719
720                if f.img_reset:
721                    print('        * (int8_t *)(pc + %u) = %s;' % (o + 1, f.img_reset))
722
723
724        return_name = ''
725        if f.needs_reply():
726            if f.return_type != 'void':
727                return_name = " retval"
728                return_str = " retval = (%s)" % (f.return_type)
729            else:
730                return_str = " (void)"
731
732            got_reply = 0
733
734            for p in f.parameterIterateOutputs():
735                if p.is_image():
736                    [dim, w, h, d, junk] = p.get_dimensions()
737                    if f.dimensions_in_reply:
738                        print("        __glXReadPixelReply(dpy, gc, %u, 0, 0, 0, %s, %s, %s, GL_TRUE);" % (dim, p.img_format, p.img_type, p.name))
739                    else:
740                        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))
741
742                    got_reply = 1
743                else:
744                    if f.reply_always_array:
745                        aa = "GL_TRUE"
746                    else:
747                        aa = "GL_FALSE"
748
749                    # gl_parameter.size() returns the size
750                    # of the entire data item.  If the
751                    # item is a fixed-size array, this is
752                    # the size of the whole array.  This
753                    # is not what __glXReadReply wants. It
754                    # wants the size of a single data
755                    # element in the reply packet.
756                    # Dividing by the array size (1 for
757                    # non-arrays) gives us this.
758
759                    s = p.size() // p.get_element_count()
760                    print("       %s __glXReadReply(dpy, %s, %s, %s);" % (return_str, s, p.name, aa))
761                    got_reply = 1
762
763
764            # If a reply wasn't read to fill an output parameter,
765            # read a NULL reply to get the return value.
766
767            if not got_reply:
768                print("       %s __glXReadReply(dpy, 0, NULL, GL_FALSE);" % (return_str))
769
770
771        elif self.debug:
772            # Only emit the extra glFinish call for functions
773            # that don't already require a reply from the server.
774            print('        __indirect_glFinish();')
775
776        if self.debug:
777            print('        printf( "Exit %%s.\\n", "gl%s" );' % (name))
778
779
780        print('        UnlockDisplay(dpy); SyncHandle();')
781
782        if name not in f.glx_vendorpriv_names:
783            print('#endif /* USE_XCB */')
784
785        print('    }')
786        print('    return%s;' % (return_name))
787        return
788
789
790    def printPixelFunction(self, f):
791        if f.name in self.pixel_stubs:
792            # Normally gl_function::get_parameter_string could be
793            # used.  However, this call needs to have the missing
794            # dimensions (e.g., a fake height value for
795            # glTexImage1D) added in.
796
797            p_string = ""
798            for param in f.parameterIterateGlxSend():
799                if param.is_padding:
800                    continue
801
802                p_string += ", " + param.name
803
804                if param.is_image():
805                    [dim, junk, junk, junk, junk] = param.get_dimensions()
806
807                if f.pad_after(param):
808                    p_string += ", 1"
809
810            print('    %s(%s, %u%s );' % (self.pixel_stubs[f.name] , f.opcode_name(), dim, p_string))
811            return
812
813
814        if self.common_func_print_just_start(f, None):
815            trailer = "    }"
816        else:
817            trailer = None
818
819
820        if f.can_be_large:
821            print('if (cmdlen <= gc->maxSmallRenderCommandSize) {')
822            print('    if ( (gc->pc + cmdlen) > gc->bufEnd ) {')
823            print('        (void) __glXFlushRenderBuffer(gc, gc->pc);')
824            print('    }')
825
826        if f.glx_rop == ~0:
827            opcode = "opcode"
828        else:
829            opcode = f.opcode_real_name()
830
831        print('emit_header(gc->pc, %s, cmdlen);' % (opcode))
832
833        self.pixel_emit_args( f, "gc->pc", 0 )
834        print('gc->pc += cmdlen;')
835        print('if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }')
836
837        if f.can_be_large:
838            print('}')
839            print('else {')
840
841            self.large_emit_begin(f, opcode)
842            self.pixel_emit_args(f, "pc", 1)
843
844            print('}')
845
846        if trailer: print(trailer)
847        return
848
849
850    def printRenderFunction(self, f):
851        # There is a class of GL functions that take a single pointer
852        # as a parameter.  This pointer points to a fixed-size chunk
853        # of data, and the protocol for this functions is very
854        # regular.  Since they are so regular and there are so many
855        # of them, special case them with generic functions.  On
856        # x86, this saves about 26KB in the libGL.so binary.
857
858        if f.variable_length_parameter() == None and len(f.parameters) == 1:
859            p = f.parameters[0]
860            if p.is_pointer():
861                cmdlen = f.command_fixed_length()
862                if cmdlen in self.generic_sizes:
863                    print('    generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name))
864                    return
865
866        if self.common_func_print_just_start(f, None):
867            trailer = "    }"
868        else:
869            trailer = None
870
871        if self.debug:
872            print('printf( "Enter %%s...\\n", "gl%s" );' % (f.name))
873
874        if f.can_be_large:
875            print('if (cmdlen <= gc->maxSmallRenderCommandSize) {')
876            print('    if ( (gc->pc + cmdlen) > gc->bufEnd ) {')
877            print('        (void) __glXFlushRenderBuffer(gc, gc->pc);')
878            print('    }')
879
880        print('emit_header(gc->pc, %s, cmdlen);' % (f.opcode_real_name()))
881
882        self.common_emit_args(f, "gc->pc", 4, 0)
883        print('gc->pc += cmdlen;')
884        print('if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }')
885
886        if f.can_be_large:
887            print('}')
888            print('else {')
889
890            self.large_emit_begin(f)
891            self.common_emit_args(f, "pc", 8, 1)
892
893            p = f.variable_length_parameter()
894            print('    __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (p.offset + 8, p.name, p.size_string()))
895            print('}')
896
897        if self.debug:
898            print('__indirect_glFinish();')
899            print('printf( "Exit %%s.\\n", "gl%s" );' % (f.name))
900
901        if trailer: print(trailer)
902        return
903
904
905class PrintGlxProtoInit_c(gl_XML.gl_print_base):
906    def __init__(self):
907        gl_XML.gl_print_base.__init__(self)
908
909        self.name = "glX_proto_send.py (from Mesa)"
910        self.license = license.bsd_license_template % ( \
911"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
912(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
913        return
914
915
916    def printRealHeader(self):
917        print("""/**
918 * \\file indirect_init.c
919 * Initialize indirect rendering dispatch table.
920 *
921 * \\author Kevin E. Martin <[email protected]>
922 * \\author Brian Paul <[email protected]>
923 * \\author Ian Romanick <[email protected]>
924 */
925
926#include "indirect_init.h"
927#include "indirect.h"
928#include "glapi.h"
929#include <assert.h>
930
931#if !defined(GLX_USE_APPLEGL) || defined(GLX_USE_APPLE)
932
933/**
934 * No-op function used to initialize functions that have no GLX protocol
935 * support.
936 */
937static int NoOp(void)
938{
939    return 0;
940}
941
942/**
943 * Create and initialize a new GL dispatch table.  The table is initialized
944 * with GLX indirect rendering protocol functions.
945 */
946struct _glapi_table * __glXNewIndirectAPI( void )
947{
948    _glapi_proc *table;
949    unsigned entries;
950    unsigned i;
951    int o;
952
953    entries = _glapi_get_dispatch_table_size();
954    table = malloc(entries * sizeof(_glapi_proc));
955    if (table == NULL)
956        return NULL;
957
958    /* first, set all entries to point to no-op functions */
959    for (i = 0; i < entries; i++) {
960       table[i] = (_glapi_proc) NoOp;
961    }
962
963    /* now, initialize the entries we understand */""")
964
965    def printRealFooter(self):
966        print("""
967    return (struct _glapi_table *) table;
968}
969
970#endif
971""")
972        return
973
974
975    def printBody(self, api):
976        for [name, number] in api.categoryIterate():
977            if number != None:
978                preamble = '\n    /* %3u. %s */\n' % (int(number), name)
979            else:
980                preamble = '\n    /* %s */\n' % (name)
981
982            for func in api.functionIterateByCategory(name):
983                if func.client_supported_for_indirect():
984                    if preamble:
985                        print(preamble)
986                        preamble = None
987
988                    if func.is_abi():
989                        print('    table[{offset}] = (_glapi_proc) __indirect_gl{name};'.format(name = func.name, offset = func.offset))
990                    else:
991                        print('    o = _glapi_get_proc_offset("gl{0}");'.format(func.name))
992                        print('    assert(o > 0);')
993                        print('    table[o] = (_glapi_proc) __indirect_gl{0};'.format(func.name))
994
995        return
996
997
998class PrintGlxProtoInit_h(gl_XML.gl_print_base):
999    def __init__(self):
1000        gl_XML.gl_print_base.__init__(self)
1001
1002        self.name = "glX_proto_send.py (from Mesa)"
1003        self.license = license.bsd_license_template % ( \
1004"""Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
1005(C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
1006        self.header_tag = "_INDIRECT_H_"
1007
1008        self.last_category = ""
1009        return
1010
1011
1012    def printRealHeader(self):
1013        print("""/**
1014 * \\file
1015 * Prototypes for indirect rendering functions.
1016 *
1017 * \\author Kevin E. Martin <[email protected]>
1018 * \\author Ian Romanick <[email protected]>
1019 */
1020""")
1021        self.printFastcall()
1022        self.printNoinline()
1023
1024        print("""
1025#include <X11/Xfuncproto.h>
1026#include "glxclient.h"
1027
1028extern _X_HIDDEN NOINLINE CARD32 __glXReadReply( Display *dpy, size_t size,
1029    void * dest, GLboolean reply_is_always_array );
1030
1031extern _X_HIDDEN NOINLINE void __glXReadPixelReply( Display *dpy,
1032    struct glx_context * gc, unsigned max_dim, GLint width, GLint height,
1033    GLint depth, GLenum format, GLenum type, void * dest,
1034    GLboolean dimensions_in_reply );
1035
1036extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupSingleRequest(
1037    struct glx_context * gc, GLint sop, GLint cmdlen );
1038
1039extern _X_HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupVendorRequest(
1040    struct glx_context * gc, GLint code, GLint vop, GLint cmdlen );
1041""")
1042
1043
1044    def printBody(self, api):
1045        for func in api.functionIterateGlx():
1046            params = func.get_parameter_string()
1047
1048            print('extern _X_HIDDEN %s __indirect_gl%s(%s);' % (func.return_type, func.name, params))
1049
1050            for n in func.entry_points:
1051                if func.has_different_protocol(n):
1052                    asdf = func.static_glx_name(n)
1053                    if asdf not in func.static_entry_points:
1054                        print('extern _X_HIDDEN %s gl%s(%s);' % (func.return_type, asdf, params))
1055                        # give it a easy-to-remember name
1056                        if func.client_handcode:
1057                            print('#define gl_dispatch_stub_%s gl%s' % (n, asdf))
1058                    else:
1059                        print('GLAPI %s GLAPIENTRY gl%s(%s);' % (func.return_type, asdf, params))
1060
1061                    break
1062
1063        print('')
1064        print('#ifdef GLX_INDIRECT_RENDERING')
1065        print('extern _X_HIDDEN void (*__indirect_get_proc_address(const char *name))(void);')
1066        print('#endif')
1067
1068
1069def _parser():
1070    """Parse input and returned a parsed namespace."""
1071    parser = argparse.ArgumentParser()
1072    parser.add_argument('-f',
1073                        default='gl_API.xml',
1074                        dest='filename',
1075                        help='An XML file describing an API')
1076    parser.add_argument('-m',
1077                        required=True,
1078                        dest='mode',
1079                        choices=frozenset(['proto', 'init_c', 'init_h']),
1080                        help='which file to generate')
1081    parser.add_argument('-d',
1082                        action='store_true',
1083                        dest='debug',
1084                        help='turn debug mode on.')
1085    return parser.parse_args()
1086
1087
1088def main():
1089    """Main function."""
1090    args = _parser()
1091
1092    if args.mode == "proto":
1093        printer = PrintGlxProtoStubs()
1094    elif args.mode == "init_c":
1095        printer = PrintGlxProtoInit_c()
1096    elif args.mode == "init_h":
1097        printer = PrintGlxProtoInit_h()
1098
1099    printer.debug = args.debug
1100    api = gl_XML.parse_GL_API(args.filename, glX_XML.glx_item_factory())
1101
1102    printer.Print( api )
1103
1104
1105if __name__ == '__main__':
1106    main()
1107