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