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