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