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