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