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