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