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