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