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