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