Fixed the XCB implementation when always_array is true, thanks to Ian Romanick for...
[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
28 import gl_XML, glX_XML, glX_proto_common, license
29 import sys, getopt, copy, string
30
31 def hash_pixel_function(func):
32 """Generate a 'unique' key for a pixel function. The key is based on
33 the parameters written in the command packet. This includes any
34 padding that might be added for the original function and the 'NULL
35 image' flag."""
36
37
38 h = ""
39 hash_pre = ""
40 hash_suf = ""
41 for param in func.parameterIterateGlxSend():
42 if param.is_image():
43 [dim, junk, junk, junk, junk] = param.get_dimensions()
44
45 d = (dim + 1) & ~1
46 hash_pre = "%uD%uD_" % (d - 1, d)
47
48 if param.img_null_flag:
49 hash_suf = "_NF"
50
51 h += "%u" % (param.size())
52
53 if func.pad_after(param):
54 h += "4"
55
56
57 n = func.name.replace("%uD" % (dim), "")
58 n = "__glx_%s_%uD%uD" % (n, d - 1, d)
59
60 h = hash_pre + h + hash_suf
61 return [h, n]
62
63
64 class glx_pixel_function_stub(glX_XML.glx_function):
65 """Dummy class used to generate pixel "utility" functions that are
66 shared by multiple dimension image functions. For example, these
67 objects are used to generate shared functions used to send GLX
68 protocol for TexImage1D and TexImage2D, TexSubImage1D and
69 TexSubImage2D, etc."""
70
71 def __init__(self, func, name):
72 # The parameters to the utility function are the same as the
73 # parameters to the real function except for the added "pad"
74 # parameters.
75
76 self.name = name
77 self.images = []
78 self.parameters = []
79 self.parameters_by_name = {}
80 for _p in func.parameterIterator():
81 p = copy.copy(_p)
82 self.parameters.append(p)
83 self.parameters_by_name[ p.name ] = p
84
85
86 if p.is_image():
87 self.images.append(p)
88 p.height = "height"
89
90 if p.img_yoff == None:
91 p.img_yoff = "yoffset"
92
93 if p.depth:
94 if p.extent == None:
95 p.extent = "extent"
96
97 if p.img_woff == None:
98 p.img_woff = "woffset"
99
100
101 pad_name = func.pad_after(p)
102 if pad_name:
103 pad = copy.copy(p)
104 pad.name = pad_name
105 self.parameters.append(pad)
106 self.parameters_by_name[ pad.name ] = pad
107
108
109 self.return_type = func.return_type
110
111 self.glx_rop = ~0
112 self.glx_sop = 0
113 self.glx_vendorpriv = 0
114
115 self.glx_doubles_in_order = func.glx_doubles_in_order
116
117 self.vectorequiv = None
118 self.output = None
119 self.can_be_large = func.can_be_large
120 self.reply_always_array = func.reply_always_array
121 self.dimensions_in_reply = func.dimensions_in_reply
122 self.img_reset = None
123
124 self.server_handcode = 0
125 self.client_handcode = 0
126 self.ignore = 0
127
128 self.count_parameter_list = func.count_parameter_list
129 self.counter_list = func.counter_list
130 self.offsets_calculated = 0
131 return
132
133
134 class PrintGlxProtoStubs(glX_proto_common.glx_print_proto):
135 def __init__(self):
136 glX_proto_common.glx_print_proto.__init__(self)
137 self.name = "glX_proto_send.py (from Mesa)"
138 self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2004, 2005", "IBM")
139
140
141 self.last_category = ""
142 self.generic_sizes = [3, 4, 6, 8, 12, 16, 24, 32]
143 self.pixel_stubs = {}
144 self.debug = 0
145 return
146
147 def printRealHeader(self):
148 print ''
149 print '#include <GL/gl.h>'
150 print '#include "indirect.h"'
151 print '#include "glxclient.h"'
152 print '#include "indirect_size.h"'
153 print '#include <GL/glxproto.h>'
154 print '#ifdef USE_XCB'
155 print '#include <X11/xcl.h>'
156 print '#include <X11/XCB/xcb.h>'
157 print '#include <X11/XCB/glx.h>'
158 print '#endif /* USE_XCB */'
159
160 print ''
161 print '#define __GLX_PAD(n) (((n) + 3) & ~3)'
162 print ''
163 self.printFastcall()
164 self.printNoinline()
165 print ''
166 print '#if !defined __GNUC__ || __GNUC__ < 3'
167 print '# define __builtin_expect(x, y) x'
168 print '#endif'
169 print ''
170 print '/* If the size and opcode values are known at compile-time, this will, on'
171 print ' * x86 at least, emit them with a single instruction.'
172 print ' */'
173 print '#define emit_header(dest, op, size) \\'
174 print ' do { union { short s[2]; int i; } temp; \\'
175 print ' temp.s[0] = (size); temp.s[1] = (op); \\'
176 print ' *((int *)(dest)) = temp.i; } while(0)'
177 print ''
178 print """NOINLINE CARD32
179 __glXReadReply( Display *dpy, size_t size, void * dest, GLboolean reply_is_always_array )
180 {
181 xGLXSingleReply reply;
182
183 (void) _XReply(dpy, (xReply *) & reply, 0, False);
184 if (size != 0) {
185 if ((reply.length > 0) || reply_is_always_array) {
186 const GLint bytes = (reply_is_always_array)
187 ? (4 * reply.length) : (reply.size * size);
188 const GLint extra = 4 - (bytes & 3);
189
190 _XRead(dpy, dest, bytes);
191 if ( extra < 4 ) {
192 _XEatData(dpy, extra);
193 }
194 }
195 else {
196 (void) memcpy( dest, &(reply.pad3), size);
197 }
198 }
199
200 return reply.retval;
201 }
202
203 NOINLINE void
204 __glXReadPixelReply( Display *dpy, __GLXcontext * gc, unsigned max_dim,
205 GLint width, GLint height, GLint depth, GLenum format, GLenum type,
206 void * dest, GLboolean dimensions_in_reply )
207 {
208 xGLXSingleReply reply;
209 GLint size;
210
211 (void) _XReply(dpy, (xReply *) & reply, 0, False);
212
213 if ( dimensions_in_reply ) {
214 width = reply.pad3;
215 height = reply.pad4;
216 depth = reply.pad5;
217
218 if ((height == 0) || (max_dim < 2)) { height = 1; }
219 if ((depth == 0) || (max_dim < 3)) { depth = 1; }
220 }
221
222 size = reply.length * 4;
223 if (size != 0) {
224 void * buf = Xmalloc( size );
225
226 if ( buf == NULL ) {
227 _XEatData(dpy, size);
228 __glXSetError(gc, GL_OUT_OF_MEMORY);
229 }
230 else {
231 const GLint extra = 4 - (size & 3);
232
233 _XRead(dpy, buf, size);
234 if ( extra < 4 ) {
235 _XEatData(dpy, extra);
236 }
237
238 __glEmptyImage(gc, 3, width, height, depth, format, type,
239 buf, dest);
240 Xfree(buf);
241 }
242 }
243 }
244
245 #define X_GLXSingle 0
246
247 NOINLINE FASTCALL GLubyte *
248 __glXSetupSingleRequest( __GLXcontext * gc, GLint sop, GLint cmdlen )
249 {
250 xGLXSingleReq * req;
251 Display * const dpy = gc->currentDpy;
252
253 (void) __glXFlushRenderBuffer(gc, gc->pc);
254 LockDisplay(dpy);
255 GetReqExtra(GLXSingle, cmdlen, req);
256 req->reqType = gc->majorOpcode;
257 req->contextTag = gc->currentContextTag;
258 req->glxCode = sop;
259 return (GLubyte *)(req) + sz_xGLXSingleReq;
260 }
261
262 NOINLINE FASTCALL GLubyte *
263 __glXSetupVendorRequest( __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen )
264 {
265 xGLXVendorPrivateReq * req;
266 Display * const dpy = gc->currentDpy;
267
268 (void) __glXFlushRenderBuffer(gc, gc->pc);
269 LockDisplay(dpy);
270 GetReqExtra(GLXVendorPrivate, cmdlen, req);
271 req->reqType = gc->majorOpcode;
272 req->glxCode = code;
273 req->vendorCode = vop;
274 req->contextTag = gc->currentContextTag;
275 return (GLubyte *)(req) + sz_xGLXVendorPrivateReq;
276 }
277
278 const GLuint __glXDefaultPixelStore[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 1 };
279
280 #define zero (__glXDefaultPixelStore+0)
281 #define one (__glXDefaultPixelStore+8)
282 #define default_pixel_store_1D (__glXDefaultPixelStore+4)
283 #define default_pixel_store_1D_size 20
284 #define default_pixel_store_2D (__glXDefaultPixelStore+4)
285 #define default_pixel_store_2D_size 20
286 #define default_pixel_store_3D (__glXDefaultPixelStore+0)
287 #define default_pixel_store_3D_size 36
288 #define default_pixel_store_4D (__glXDefaultPixelStore+0)
289 #define default_pixel_store_4D_size 36
290 """
291
292 for size in self.generic_sizes:
293 self.print_generic_function(size)
294 return
295
296
297 def printBody(self, api):
298
299 self.pixel_stubs = {}
300 generated_stubs = []
301
302 for func in api.functionIterateGlx():
303 if func.client_handcode: continue
304
305 # If the function is a pixel function with a certain
306 # GLX protocol signature, create a fake stub function
307 # for it. For example, create a single stub function
308 # that is used to implement both glTexImage1D and
309 # glTexImage2D.
310
311 if func.glx_rop != 0:
312 do_it = 0
313 for image in func.get_images():
314 if image.img_pad_dimensions:
315 do_it = 1
316 break
317
318
319 if do_it:
320 [h, n] = hash_pixel_function(func)
321
322
323 self.pixel_stubs[ func.name ] = n
324 if h not in generated_stubs:
325 generated_stubs.append(h)
326
327 fake_func = glx_pixel_function_stub( func, n )
328 self.printFunction( fake_func )
329
330
331 self.printFunction( func )
332
333 return
334
335
336 def printFunction(self, func):
337 if func.glx_rop == ~0:
338 print 'static %s' % (func.return_type)
339 print '%s( unsigned opcode, unsigned dim, %s )' % (func.name, func.get_parameter_string())
340 else:
341 print '#define %s %d' % (func.opcode_name(), func.opcode_value())
342
343 print '%s' % (func.return_type)
344 print '__indirect_gl%s(%s)' % (func.name, func.get_parameter_string())
345
346
347 print '{'
348
349
350 if func.glx_rop != 0 or func.vectorequiv != None:
351 if len(func.images):
352 self.printPixelFunction(func)
353 else:
354 self.printRenderFunction(func)
355 elif func.glx_sop != 0 or func.glx_vendorpriv != 0:
356 self.printSingleFunction(func)
357 pass
358 else:
359 print "/* Missing GLX protocol for %s. */" % (func.name)
360
361 print '}'
362 print ''
363
364 return
365
366
367 def print_generic_function(self, n):
368 size = (n + 3) & ~3
369 print """static FASTCALL NOINLINE void
370 generic_%u_byte( GLint rop, const void * ptr )
371 {
372 __GLXcontext * const gc = __glXGetCurrentContext();
373 const GLuint cmdlen = %u;
374
375 emit_header(gc->pc, rop, cmdlen);
376 (void) memcpy((void *)(gc->pc + 4), ptr, %u);
377 gc->pc += cmdlen;
378 if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }
379 }
380 """ % (n, size + 4, size)
381 return
382
383
384 def common_emit_one_arg(self, p, pc, indent, adjust, extra_offset):
385 if p.is_array():
386 src_ptr = p.name
387 else:
388 src_ptr = "&" + p.name
389
390 if not extra_offset:
391 print '%s (void) memcpy((void *)(%s + %u), (void *)(%s), %s);' \
392 % (indent, pc, p.offset + adjust, src_ptr, p.size_string() )
393 else:
394 print '%s (void) memcpy((void *)(%s + %u + %s), (void *)(%s), %s);' \
395 % (indent, pc, p.offset + adjust, extra_offset, src_ptr, p.size_string() )
396
397 def common_emit_args(self, f, pc, indent, adjust, skip_vla):
398 extra_offset = None
399
400 for p in f.parameterIterateGlxSend( not skip_vla ):
401 if p.name != f.img_reset:
402 self.common_emit_one_arg(p, pc, indent, adjust, extra_offset)
403
404 if p.is_variable_length():
405 temp = p.size_string()
406 if extra_offset:
407 extra_offset += " + %s" % (temp)
408 else:
409 extra_offset = temp
410
411 return
412
413
414 def pixel_emit_args(self, f, pc, indent, large):
415 """Emit the arguments for a pixel function. This differs from
416 common_emit_args in that pixel functions may require padding
417 be inserted (i.e., for the missing width field for
418 TexImage1D), and they may also require a 'NULL image' flag
419 be inserted before the image data."""
420
421 if large:
422 adjust = 8
423 else:
424 adjust = 4
425
426 for param in f.parameterIterateGlxSend():
427 if not param.is_image():
428 self.common_emit_one_arg(param, pc, indent, adjust, None)
429
430 if f.pad_after(param):
431 print '%s (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, (param.offset + param.size()) + adjust)
432
433 else:
434 [dim, width, height, depth, extent] = param.get_dimensions()
435 if f.glx_rop == ~0:
436 dim_str = "dim"
437 else:
438 dim_str = str(dim)
439
440 if param.img_null_flag:
441 if large:
442 print '%s (void) memcpy((void *)(%s + %u), zero, 4);' % (indent, pc, (param.offset - 4) + adjust)
443 else:
444 print '%s (void) memcpy((void *)(%s + %u), (void *)((%s == NULL) ? one : zero), 4);' % (indent, pc, (param.offset - 4) + adjust, param.name)
445
446
447 pixHeaderPtr = "%s + %u" % (pc, adjust)
448 pcPtr = "%s + %u" % (pc, param.offset + adjust)
449
450 if not large:
451 if param.img_send_null:
452 condition = '(compsize > 0) && (%s != NULL)' % (param.name)
453 else:
454 condition = 'compsize > 0'
455
456 print '%s if (%s) {' % (indent, condition)
457 print '%s (*gc->fillImage)(gc, %s, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, dim_str, width, height, depth, param.img_format, param.img_type, param.name, pcPtr, pixHeaderPtr)
458 print '%s }' % (indent)
459 print '%s else {' % (indent)
460 print '%s (void) memcpy( %s, default_pixel_store_%uD, default_pixel_store_%uD_size );' % (indent, pixHeaderPtr, dim, dim)
461 print '%s }' % (indent)
462 else:
463 print '%s __glXSendLargeImage(gc, compsize, %s, %s, %s, %s, %s, %s, %s, %s, %s);' % (indent, dim_str, width, height, depth, param.img_format, param.img_type, param.name, pcPtr, pixHeaderPtr)
464
465 return
466
467
468 def large_emit_begin(self, indent, f, op_name = None):
469 if not op_name:
470 op_name = f.opcode_real_name()
471
472 print '%s const GLint op = %s;' % (indent, op_name)
473 print '%s const GLuint cmdlenLarge = cmdlen + 4;' % (indent)
474 print '%s GLubyte * const pc = __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
475 print '%s (void) memcpy((void *)(pc + 0), (void *)(&cmdlenLarge), 4);' % (indent)
476 print '%s (void) memcpy((void *)(pc + 4), (void *)(&op), 4);' % (indent)
477 return
478
479
480 def common_func_print_just_start(self, f):
481 print ' __GLXcontext * const gc = __glXGetCurrentContext();'
482
483 # The only reason that single and vendor private commands need
484 # a variable called 'dpy' is becuase they use the SyncHandle
485 # macro. For whatever brain-dead reason, that macro is hard-
486 # coded to use a variable called 'dpy' instead of taking a
487 # parameter.
488
489 # FIXME Simplify the logic related to skip_condition and
490 # FIXME condition_list in this function. Basically, remove
491 # FIXME skip_condition, and just append the "dpy != NULL" type
492 # FIXME condition to condition_list from the start. The only
493 # FIXME reason it's done in this confusing way now is to
494 # FIXME minimize the diffs in the generated code.
495
496 if not f.glx_rop:
497 for p in f.parameterIterateOutputs():
498 if p.is_image():
499 print ' const __GLXattribute * const state = gc->client_state_private;'
500 break
501
502 print ' Display * const dpy = gc->currentDpy;'
503 skip_condition = "dpy != NULL"
504 elif f.can_be_large:
505 skip_condition = "gc->currentDpy != NULL"
506 else:
507 skip_condition = None
508
509
510 if f.return_type != 'void':
511 print ' %s retval = (%s) 0;' % (f.return_type, f.return_type)
512
513
514 self.emit_packet_size_calculation(f, 0)
515
516 condition_list = []
517 for p in f.parameterIterateCounters():
518 condition_list.append( "%s >= 0" % (p.name) )
519
520 if skip_condition:
521 condition_list.append( skip_condition )
522
523 if len( condition_list ) > 0:
524 if len( condition_list ) > 1:
525 skip_condition = "(%s)" % (string.join( condition_list, ") && (" ))
526 else:
527 skip_condition = "%s" % (condition_list.pop(0))
528
529 print ' if (__builtin_expect(%s, 1)) {' % (skip_condition)
530 return 1
531 else:
532 return 0
533
534
535 def printSingleFunction(self, f):
536 self.common_func_print_just_start(f)
537
538 if self.debug:
539 print ' printf( "Enter %%s...\\n", "gl%s" );' % (f.name)
540
541 if f.glx_vendorpriv == 0:
542
543 # XCB specific:
544 print '#ifdef USE_XCB'
545 if self.debug:
546 print ' printf("\\tUsing XCB.\\n");'
547 print ' XCBConnection *c = XCBConnectionOfDisplay(dpy);'
548 print ' (void) __glXFlushRenderBuffer(gc, gc->pc);'
549 xcb_name = 'XCBGlx%s' % f.name
550
551 iparams=[]
552 extra_iparams = []
553 output = None
554 for p in f.parameterIterator():
555 if p.is_output:
556 output = p
557
558 if p.is_image():
559 if p.img_format != "GL_COLOR_INDEX" or p.img_type != "GL_BITMAP":
560 extra_iparams.append("state->storePack.swapEndian")
561 else:
562 extra_iparams.append("0")
563
564 # Hardcode this in. lsb_first param (apparently always GL_FALSE)
565 # also present in GetPolygonStipple, but taken care of above.
566 if xcb_name == "XCBGlxReadPixels":
567 extra_iparams.append("0")
568 else:
569 iparams.append(p.name)
570
571
572 xcb_request = '%s(%s)' % (xcb_name, ", ".join(["c", "gc->currentContextTag"] + iparams + extra_iparams))
573
574 if f.needs_reply():
575 print ' %sRep *reply = %sReply(c, %s, NULL);' % (xcb_name, xcb_name, xcb_request)
576 if output and f.reply_always_array:
577 print ' (void)memcpy(%s, %sData(reply), %sDataLength(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
578
579 elif output and not f.reply_always_array:
580 if not output.is_image():
581 print ' if (%sDataLength(reply) == 0)' % (xcb_name)
582 print ' (void)memcpy(%s, &reply->datum, sizeof(reply->datum));' % (output.name)
583 print ' else'
584 print ' (void)memcpy(%s, %sData(reply), %sDataLength(reply) * sizeof(%s));' % (output.name, xcb_name, xcb_name, output.get_base_type_string())
585
586
587 if f.return_type != 'void':
588 print ' retval = reply->ret_val;'
589 print ' free(reply);'
590 else:
591 print ' ' + xcb_request + ';'
592 print '#else'
593 # End of XCB specific.
594
595
596 if f.parameters != []:
597 pc_decl = "GLubyte const * pc ="
598 else:
599 pc_decl = "(void)"
600
601 if f.glx_vendorpriv != 0:
602 print ' %s __glXSetupVendorRequest(gc, %s, %s, cmdlen);' % (pc_decl, f.opcode_real_name(), f.opcode_name())
603 else:
604 print ' %s __glXSetupSingleRequest(gc, %s, cmdlen);' % (pc_decl, f.opcode_name())
605
606 self.common_emit_args(f, "pc", " ", 0, 0)
607
608 images = f.get_images()
609
610 for img in images:
611 if img.is_output:
612 o = f.command_fixed_length() - 4
613 print ' *(int32_t *)(pc + %u) = 0;' % (o)
614 if img.img_format != "GL_COLOR_INDEX" or img.img_type != "GL_BITMAP":
615 print ' * (int8_t *)(pc + %u) = state->storePack.swapEndian;' % (o)
616
617 if f.img_reset:
618 print ' * (int8_t *)(pc + %u) = %s;' % (o + 1, f.img_reset)
619
620
621 return_name = ''
622 if f.needs_reply():
623 if f.return_type != 'void':
624 return_name = " retval"
625 return_str = " retval = (%s)" % (f.return_type)
626 else:
627 return_str = " (void)"
628
629 got_reply = 0
630
631 for p in f.parameterIterateOutputs():
632 if p.is_image():
633 [dim, w, h, d, junk] = p.get_dimensions()
634 if f.dimensions_in_reply:
635 print " __glXReadPixelReply(dpy, gc, %u, 0, 0, 0, %s, %s, %s, GL_TRUE);" % (dim, p.img_format, p.img_type, p.name)
636 else:
637 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)
638
639 got_reply = 1
640 else:
641 if f.reply_always_array:
642 aa = "GL_TRUE"
643 else:
644 aa = "GL_FALSE"
645
646 # gl_parameter.size() returns the size
647 # of the entire data item. If the
648 # item is a fixed-size array, this is
649 # the size of the whole array. This
650 # is not what __glXReadReply wants. It
651 # wants the size of a single data
652 # element in the reply packet.
653 # Dividing by the array size (1 for
654 # non-arrays) gives us this.
655
656 s = p.size() / p.get_element_count()
657 print " %s __glXReadReply(dpy, %s, %s, %s);" % (return_str, s, p.name, aa)
658 got_reply = 1
659
660
661 # If a reply wasn't read to fill an output parameter,
662 # read a NULL reply to get the return value.
663
664 if not got_reply:
665 print " %s __glXReadReply(dpy, 0, NULL, GL_FALSE);" % (return_str)
666
667
668 elif self.debug:
669 # Only emit the extra glFinish call for functions
670 # that don't already require a reply from the server.
671 print ' __indirect_glFinish();'
672
673 if self.debug:
674 print ' printf( "Exit %%s.\\n", "gl%s" );' % (f.name)
675
676
677 print ' UnlockDisplay(dpy); SyncHandle();'
678
679 if f.glx_vendorpriv == 0:
680 print '#endif /* USE_XCB */'
681
682 print ' }'
683 print ' return%s;' % (return_name)
684 return
685
686
687 def printPixelFunction(self, f):
688 if self.pixel_stubs.has_key( f.name ):
689 # Normally gl_function::get_parameter_string could be
690 # used. However, this call needs to have the missing
691 # dimensions (e.g., a fake height value for
692 # glTexImage1D) added in.
693
694 p_string = ""
695 for param in f.parameterIterateGlxSend():
696 p_string += ", " + param.name
697
698 if param.is_image():
699 [dim, junk, junk, junk, junk] = param.get_dimensions()
700
701 if f.pad_after(param):
702 p_string += ", 1"
703
704 print ' %s(%s, %u%s );' % (self.pixel_stubs[f.name] , f.opcode_name(), dim, p_string)
705 return
706
707
708 if self.common_func_print_just_start(f):
709 indent = " "
710 trailer = " }"
711 else:
712 indent = ""
713 trailer = None
714
715
716 if f.can_be_large:
717 print '%s if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
718 print '%s if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
719 print '%s (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
720 print '%s }' % (indent)
721 indent += " "
722
723 if f.glx_rop == ~0:
724 opcode = "opcode"
725 else:
726 opcode = f.opcode_real_name()
727
728 print '%s emit_header(gc->pc, %s, cmdlen);' % (indent, opcode)
729
730 self.pixel_emit_args( f, "gc->pc", indent, 0 )
731 print '%s gc->pc += cmdlen;' % (indent)
732 print '%s if (gc->pc > gc->limit) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
733
734 if f.can_be_large:
735 print '%s}' % (indent)
736 print '%selse {' % (indent)
737
738 self.large_emit_begin(indent, f, opcode)
739 self.pixel_emit_args( f, "pc", indent, 1 )
740
741 print '%s}' % (indent)
742
743 if trailer: print trailer
744 return
745
746
747 def printRenderFunction(self, f):
748 # There is a class of GL functions that take a single pointer
749 # as a parameter. This pointer points to a fixed-size chunk
750 # of data, and the protocol for this functions is very
751 # regular. Since they are so regular and there are so many
752 # of them, special case them with generic functions. On
753 # x86, this saves about 26KB in the libGL.so binary.
754
755 if f.variable_length_parameter() == None and len(f.parameters) == 1:
756 p = f.parameters[0]
757 if p.is_pointer():
758 cmdlen = f.command_fixed_length()
759 if cmdlen in self.generic_sizes:
760 print ' generic_%u_byte( %s, %s );' % (cmdlen, f.opcode_real_name(), p.name)
761 return
762
763 if self.common_func_print_just_start(f):
764 indent = " "
765 trailer = " }"
766 else:
767 indent = ""
768 trailer = None
769
770 if self.debug:
771 print '%s printf( "Enter %%s...\\n", "gl%s" );' % (indent, f.name)
772
773 if f.can_be_large:
774 print '%s if (cmdlen <= gc->maxSmallRenderCommandSize) {' % (indent)
775 print '%s if ( (gc->pc + cmdlen) > gc->bufEnd ) {' % (indent)
776 print '%s (void) __glXFlushRenderBuffer(gc, gc->pc);' % (indent)
777 print '%s }' % (indent)
778 indent += " "
779
780 print '%s emit_header(gc->pc, %s, cmdlen);' % (indent, f.opcode_real_name())
781
782 self.common_emit_args(f, "gc->pc", indent, 4, 0)
783 print '%s gc->pc += cmdlen;' % (indent)
784 print '%s if (__builtin_expect(gc->pc > gc->limit, 0)) { (void) __glXFlushRenderBuffer(gc, gc->pc); }' % (indent)
785
786 if f.can_be_large:
787 print '%s}' % (indent)
788 print '%selse {' % (indent)
789
790 self.large_emit_begin(indent, f)
791 self.common_emit_args(f, "pc", indent, 8, 1)
792
793 p = f.variable_length_parameter()
794 print '%s __glXSendLargeCommand(gc, pc, %u, %s, %s);' % (indent, p.offset + 8, p.name, p.size_string())
795 print '%s}' % (indent)
796
797 if self.debug:
798 print '%s __indirect_glFinish();' % (indent)
799 print '%s printf( "Exit %%s.\\n", "gl%s" );' % (indent, f.name)
800
801 if trailer: print trailer
802 return
803
804
805 class PrintGlxProtoInit_c(gl_XML.gl_print_base):
806 def __init__(self):
807 gl_XML.gl_print_base.__init__(self)
808
809 self.name = "glX_proto_send.py (from Mesa)"
810 self.license = license.bsd_license_template % ( \
811 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
812 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
813 return
814
815
816 def printRealHeader(self):
817 print """/**
818 * \\file indirect_init.c
819 * Initialize indirect rendering dispatch table.
820 *
821 * \\author Kevin E. Martin <kevin@precisioninsight.com>
822 * \\author Brian Paul <brian@precisioninsight.com>
823 * \\author Ian Romanick <idr@us.ibm.com>
824 */
825
826 #include "indirect_init.h"
827 #include "indirect.h"
828 #include "glapi.h"
829
830
831 /**
832 * No-op function used to initialize functions that have no GLX protocol
833 * support.
834 */
835 static int NoOp(void)
836 {
837 return 0;
838 }
839
840 /**
841 * Create and initialize a new GL dispatch table. The table is initialized
842 * with GLX indirect rendering protocol functions.
843 */
844 __GLapi * __glXNewIndirectAPI( void )
845 {
846 __GLapi *glAPI;
847 GLuint entries;
848
849 entries = _glapi_get_dispatch_table_size();
850 glAPI = (__GLapi *) Xmalloc(entries * sizeof(void *));
851
852 /* first, set all entries to point to no-op functions */
853 {
854 int i;
855 void **dispatch = (void **) glAPI;
856 for (i = 0; i < entries; i++) {
857 dispatch[i] = (void *) NoOp;
858 }
859 }
860
861 /* now, initialize the entries we understand */"""
862
863 def printRealFooter(self):
864 print """
865 return glAPI;
866 }
867 """
868 return
869
870
871 def printCategory(self, category_group, show_num):
872 cat_keys = category_group.keys()
873 cat_keys.sort()
874 for cat_num in cat_keys:
875 first = 1
876 for offset in category_group[ cat_num ]:
877 [cat_name, func_name] = category_group[ cat_num ][ offset ]
878
879 if first:
880 print ''
881 if show_num:
882 print ' /* % 3u. %s */' % (cat_num, cat_name)
883 else:
884 print ' /* %s */' % (cat_name)
885 print ''
886 first = 0
887
888 print ' glAPI->%s = __indirect_gl%s;' % (func_name, func_name)
889
890
891 def printBody(self, api):
892 core_categories = {}
893 arb_categories = {}
894 other_categories = {}
895 next_unnum = 1000
896
897 for func in api.functionIterateGlx():
898 [cat, num] = api.get_category_for_name( func.name )
899
900 # There are three groups of "categories" that we
901 # care about here. We want to separate the core GL
902 # version categories from extensions. We also want to
903 # separate the ARB extensions from the non-ARB
904 # extensions.
905 #
906 # This is done by first trying to convert the category
907 # name to a floating point number. All core GL
908 # versions are of the form "N.M" where both N and M
909 # are integers. If the cast to float fails, an
910 # exception will be thrown. Once down that path,
911 # we can look at the start of the extension string.
912 # If it begins with "GL_ARB_", it's an ARB extension.
913 #
914 # Once the categories are separated, the are ordered
915 # by number. The un-numbered non-ARB extensions
916 # (e.g., GL_INGR_blend_func_separate) are assigned
917 # arbitrary numbers starting at 1000.
918 #
919 # FIXME In order to maintain repeatability, the
920 # FIXME unnumbered extensions should be put in their
921 # FIXME own dictionary and ordered by name (since they
922 # FIXME have no number).
923
924 try:
925 num = float(cat)
926 if not core_categories.has_key( num ):
927 core_categories[ num ] = {}
928
929 core_categories[ num ][ func.offset ] = [cat, func.name]
930
931 except Exception, e:
932 if not num:
933 num = next_unnum
934 next_unnum += 1
935 else:
936 num = int(num)
937
938 if cat.startswith( "GL_ARB_" ):
939 if not arb_categories.has_key( num ):
940 arb_categories[ num ] = {}
941
942 arb_categories[ num ][ func.offset ] = [cat, func.name]
943 else:
944 if not other_categories.has_key( num ):
945 other_categories[ num ] = {}
946
947 other_categories[ num ][ func.offset ] = [cat, func.name]
948
949 self.printCategory( core_categories, 0 )
950 self.printCategory( arb_categories, 1 )
951 self.printCategory( other_categories, 1 )
952 return
953
954
955 class PrintGlxProtoInit_h(gl_XML.gl_print_base):
956 def __init__(self):
957 gl_XML.gl_print_base.__init__(self)
958
959 self.name = "glX_proto_send.py (from Mesa)"
960 self.license = license.bsd_license_template % ( \
961 """Copyright 1998-1999 Precision Insight, Inc., Cedar Park, Texas.
962 (C) Copyright IBM Corporation 2004""", "PRECISION INSIGHT, IBM")
963 self.header_tag = "_INDIRECT_H_"
964
965 self.last_category = ""
966 return
967
968
969 def printRealHeader(self):
970 print """/**
971 * \\file
972 * Prototypes for indirect rendering functions.
973 *
974 * \\author Kevin E. Martin <kevin@precisioninsight.com>
975 * \\author Ian Romanick <idr@us.ibm.com>
976 */
977 """
978 self.printVisibility( "HIDDEN", "hidden" )
979 self.printFastcall()
980 self.printNoinline()
981
982 print """
983 #include "glxclient.h"
984
985 extern HIDDEN NOINLINE CARD32 __glXReadReply( Display *dpy, size_t size,
986 void * dest, GLboolean reply_is_always_array );
987
988 extern HIDDEN NOINLINE void __glXReadPixelReply( Display *dpy,
989 __GLXcontext * gc, unsigned max_dim, GLint width, GLint height,
990 GLint depth, GLenum format, GLenum type, void * dest,
991 GLboolean dimensions_in_reply );
992
993 extern HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupSingleRequest(
994 __GLXcontext * gc, GLint sop, GLint cmdlen );
995
996 extern HIDDEN NOINLINE FASTCALL GLubyte * __glXSetupVendorRequest(
997 __GLXcontext * gc, GLint code, GLint vop, GLint cmdlen );
998 """
999
1000
1001 def printBody(self, api):
1002 for func in api.functionIterateGlx():
1003 print 'extern HIDDEN %s __indirect_gl%s(%s);' % (func.return_type, func.name, func.get_parameter_string())
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 )