Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

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