1bf215546Sopenharmony_ci
2bf215546Sopenharmony_ci# (C) Copyright IBM Corporation 2004, 2005
3bf215546Sopenharmony_ci# All Rights Reserved.
4bf215546Sopenharmony_ci#
5bf215546Sopenharmony_ci# Permission is hereby granted, free of charge, to any person obtaining a
6bf215546Sopenharmony_ci# copy of this software and associated documentation files (the "Software"),
7bf215546Sopenharmony_ci# to deal in the Software without restriction, including without limitation
8bf215546Sopenharmony_ci# on the rights to use, copy, modify, merge, publish, distribute, sub
9bf215546Sopenharmony_ci# license, and/or sell copies of the Software, and to permit persons to whom
10bf215546Sopenharmony_ci# the Software is furnished to do so, subject to the following conditions:
11bf215546Sopenharmony_ci#
12bf215546Sopenharmony_ci# The above copyright notice and this permission notice (including the next
13bf215546Sopenharmony_ci# paragraph) shall be included in all copies or substantial portions of the
14bf215546Sopenharmony_ci# Software.
15bf215546Sopenharmony_ci#
16bf215546Sopenharmony_ci# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17bf215546Sopenharmony_ci# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20bf215546Sopenharmony_ci# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21bf215546Sopenharmony_ci# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22bf215546Sopenharmony_ci# IN THE SOFTWARE.
23bf215546Sopenharmony_ci#
24bf215546Sopenharmony_ci# Authors:
25bf215546Sopenharmony_ci#    Ian Romanick <idr@us.ibm.com>
26bf215546Sopenharmony_ci
27bf215546Sopenharmony_ciimport gl_XML
28bf215546Sopenharmony_ciimport license
29bf215546Sopenharmony_ciimport sys, getopt, string
30bf215546Sopenharmony_ci
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ciclass glx_item_factory(gl_XML.gl_item_factory):
33bf215546Sopenharmony_ci    """Factory to create GLX protocol oriented objects derived from gl_item."""
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_ci    def create_function(self, element, context):
36bf215546Sopenharmony_ci        return glx_function(element, context)
37bf215546Sopenharmony_ci
38bf215546Sopenharmony_ci    def create_enum(self, element, context, category):
39bf215546Sopenharmony_ci        return glx_enum(element, context, category)
40bf215546Sopenharmony_ci
41bf215546Sopenharmony_ci    def create_api(self):
42bf215546Sopenharmony_ci        return glx_api(self)
43bf215546Sopenharmony_ci
44bf215546Sopenharmony_ci
45bf215546Sopenharmony_ciclass glx_enum(gl_XML.gl_enum):
46bf215546Sopenharmony_ci    def __init__(self, element, context, category):
47bf215546Sopenharmony_ci        gl_XML.gl_enum.__init__(self, element, context, category)
48bf215546Sopenharmony_ci
49bf215546Sopenharmony_ci        self.functions = {}
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_ci        for child in element:
52bf215546Sopenharmony_ci            if child.tag == "size":
53bf215546Sopenharmony_ci                n = child.get( "name" )
54bf215546Sopenharmony_ci                c = child.get( "count" )
55bf215546Sopenharmony_ci                m = child.get( "mode", "set" )
56bf215546Sopenharmony_ci
57bf215546Sopenharmony_ci                if not c:
58bf215546Sopenharmony_ci                    c = self.default_count
59bf215546Sopenharmony_ci                else:
60bf215546Sopenharmony_ci                    c = int(c)
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_ci                if m == "get":
63bf215546Sopenharmony_ci                    mode = 0
64bf215546Sopenharmony_ci                else:
65bf215546Sopenharmony_ci                    mode = 1
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci                if n not in self.functions:
68bf215546Sopenharmony_ci                    self.functions[ n ] = [c, mode]
69bf215546Sopenharmony_ci
70bf215546Sopenharmony_ci        return
71bf215546Sopenharmony_ci
72bf215546Sopenharmony_ci
73bf215546Sopenharmony_ciclass glx_function(gl_XML.gl_function):
74bf215546Sopenharmony_ci    def __init__(self, element, context):
75bf215546Sopenharmony_ci        self.glx_rop = 0
76bf215546Sopenharmony_ci        self.glx_sop = 0
77bf215546Sopenharmony_ci        self.glx_vendorpriv = 0
78bf215546Sopenharmony_ci
79bf215546Sopenharmony_ci        self.glx_vendorpriv_names = []
80bf215546Sopenharmony_ci
81bf215546Sopenharmony_ci        # If this is set to true, it means that GLdouble parameters should be
82bf215546Sopenharmony_ci        # written to the GLX protocol packet in the order they appear in the
83bf215546Sopenharmony_ci        # prototype.  This is different from the "classic" ordering.  In the
84bf215546Sopenharmony_ci        # classic ordering GLdoubles are written to the protocol packet first,
85bf215546Sopenharmony_ci        # followed by non-doubles.  NV_vertex_program was the first extension
86bf215546Sopenharmony_ci        # to break with this tradition.
87bf215546Sopenharmony_ci
88bf215546Sopenharmony_ci        self.glx_doubles_in_order = 0
89bf215546Sopenharmony_ci
90bf215546Sopenharmony_ci        self.vectorequiv = None
91bf215546Sopenharmony_ci        self.output = None
92bf215546Sopenharmony_ci        self.can_be_large = 0
93bf215546Sopenharmony_ci        self.reply_always_array = 0
94bf215546Sopenharmony_ci        self.dimensions_in_reply = 0
95bf215546Sopenharmony_ci        self.img_reset = None
96bf215546Sopenharmony_ci
97bf215546Sopenharmony_ci        self.server_handcode = 0
98bf215546Sopenharmony_ci        self.client_handcode = 0
99bf215546Sopenharmony_ci        self.ignore = 0
100bf215546Sopenharmony_ci
101bf215546Sopenharmony_ci        self.count_parameter_list = []
102bf215546Sopenharmony_ci        self.counter_list = []
103bf215546Sopenharmony_ci        self.parameters_by_name = {}
104bf215546Sopenharmony_ci        self.offsets_calculated = 0
105bf215546Sopenharmony_ci
106bf215546Sopenharmony_ci        gl_XML.gl_function.__init__(self, element, context)
107bf215546Sopenharmony_ci        return
108bf215546Sopenharmony_ci
109bf215546Sopenharmony_ci
110bf215546Sopenharmony_ci    def process_element(self, element):
111bf215546Sopenharmony_ci        gl_XML.gl_function.process_element(self, element)
112bf215546Sopenharmony_ci
113bf215546Sopenharmony_ci        # If the function already has a vector equivalent set, don't
114bf215546Sopenharmony_ci        # set it again.  This can happen if an alias to a function
115bf215546Sopenharmony_ci        # appears after the function that it aliases.
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci        if not self.vectorequiv:
118bf215546Sopenharmony_ci            self.vectorequiv = element.get("vectorequiv")
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci
121bf215546Sopenharmony_ci        name = element.get("name")
122bf215546Sopenharmony_ci        if name == self.name:
123bf215546Sopenharmony_ci            for param in self.parameters:
124bf215546Sopenharmony_ci                self.parameters_by_name[ param.name ] = param
125bf215546Sopenharmony_ci
126bf215546Sopenharmony_ci                if len(param.count_parameter_list):
127bf215546Sopenharmony_ci                    self.count_parameter_list.extend( param.count_parameter_list )
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_ci                if param.counter and param.counter not in self.counter_list:
130bf215546Sopenharmony_ci                    self.counter_list.append(param.counter)
131bf215546Sopenharmony_ci
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci        for child in element:
134bf215546Sopenharmony_ci            if child.tag == "glx":
135bf215546Sopenharmony_ci                rop = child.get( 'rop' )
136bf215546Sopenharmony_ci                sop = child.get( 'sop' )
137bf215546Sopenharmony_ci                vop = child.get( 'vendorpriv' )
138bf215546Sopenharmony_ci
139bf215546Sopenharmony_ci                if rop:
140bf215546Sopenharmony_ci                    self.glx_rop = int(rop)
141bf215546Sopenharmony_ci
142bf215546Sopenharmony_ci                if sop:
143bf215546Sopenharmony_ci                    self.glx_sop = int(sop)
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_ci                if vop:
146bf215546Sopenharmony_ci                    self.glx_vendorpriv = int(vop)
147bf215546Sopenharmony_ci                    self.glx_vendorpriv_names.append(name)
148bf215546Sopenharmony_ci
149bf215546Sopenharmony_ci                self.img_reset = child.get( 'img_reset' )
150bf215546Sopenharmony_ci
151bf215546Sopenharmony_ci                # The 'handcode' attribute can be one of 'true',
152bf215546Sopenharmony_ci                # 'false', 'client', or 'server'.
153bf215546Sopenharmony_ci
154bf215546Sopenharmony_ci                handcode = child.get( 'handcode', 'false' )
155bf215546Sopenharmony_ci                if handcode == "false":
156bf215546Sopenharmony_ci                    self.server_handcode = 0
157bf215546Sopenharmony_ci                    self.client_handcode = 0
158bf215546Sopenharmony_ci                elif handcode == "true":
159bf215546Sopenharmony_ci                    self.server_handcode = 1
160bf215546Sopenharmony_ci                    self.client_handcode = 1
161bf215546Sopenharmony_ci                elif handcode == "client":
162bf215546Sopenharmony_ci                    self.server_handcode = 0
163bf215546Sopenharmony_ci                    self.client_handcode = 1
164bf215546Sopenharmony_ci                elif handcode == "server":
165bf215546Sopenharmony_ci                    self.server_handcode = 1
166bf215546Sopenharmony_ci                    self.client_handcode = 0
167bf215546Sopenharmony_ci                else:
168bf215546Sopenharmony_ci                    raise RuntimeError('Invalid handcode mode "%s" in function "%s".' % (handcode, self.name))
169bf215546Sopenharmony_ci
170bf215546Sopenharmony_ci                self.ignore               = gl_XML.is_attr_true( child, 'ignore' )
171bf215546Sopenharmony_ci                self.can_be_large         = gl_XML.is_attr_true( child, 'large' )
172bf215546Sopenharmony_ci                self.glx_doubles_in_order = gl_XML.is_attr_true( child, 'doubles_in_order' )
173bf215546Sopenharmony_ci                self.reply_always_array   = gl_XML.is_attr_true( child, 'always_array' )
174bf215546Sopenharmony_ci                self.dimensions_in_reply  = gl_XML.is_attr_true( child, 'dimensions_in_reply' )
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci
177bf215546Sopenharmony_ci        # Do some validation of the GLX protocol information.  As
178bf215546Sopenharmony_ci        # new tests are discovered, they should be added here.
179bf215546Sopenharmony_ci
180bf215546Sopenharmony_ci        for param in self.parameters:
181bf215546Sopenharmony_ci            if param.is_output and self.glx_rop != 0:
182bf215546Sopenharmony_ci                raise RuntimeError("Render / RenderLarge commands cannot have outputs (%s)." % (self.name))
183bf215546Sopenharmony_ci
184bf215546Sopenharmony_ci        return
185bf215546Sopenharmony_ci
186bf215546Sopenharmony_ci
187bf215546Sopenharmony_ci    def has_variable_size_request(self):
188bf215546Sopenharmony_ci        """Determine if the GLX request packet is variable sized.
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci        The GLX request packet is variable sized in several common
191bf215546Sopenharmony_ci        situations.
192bf215546Sopenharmony_ci
193bf215546Sopenharmony_ci        1. The function has a non-output parameter that is counted
194bf215546Sopenharmony_ci           by another parameter (e.g., the 'textures' parameter of
195bf215546Sopenharmony_ci           glDeleteTextures).
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci        2. The function has a non-output parameter whose count is
198bf215546Sopenharmony_ci           determined by another parameter that is an enum (e.g., the
199bf215546Sopenharmony_ci           'params' parameter of glLightfv).
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci        3. The function has a non-output parameter that is an
202bf215546Sopenharmony_ci           image.
203bf215546Sopenharmony_ci
204bf215546Sopenharmony_ci        4. The function must be hand-coded on the server.
205bf215546Sopenharmony_ci        """
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci        if self.glx_rop == 0:
208bf215546Sopenharmony_ci            return 0
209bf215546Sopenharmony_ci
210bf215546Sopenharmony_ci        if self.server_handcode or self.images:
211bf215546Sopenharmony_ci            return 1
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci        for param in self.parameters:
214bf215546Sopenharmony_ci            if not param.is_output:
215bf215546Sopenharmony_ci                if param.counter or len(param.count_parameter_list):
216bf215546Sopenharmony_ci                    return 1
217bf215546Sopenharmony_ci
218bf215546Sopenharmony_ci        return 0
219bf215546Sopenharmony_ci
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci    def variable_length_parameter(self):
222bf215546Sopenharmony_ci        for param in self.parameters:
223bf215546Sopenharmony_ci            if not param.is_output:
224bf215546Sopenharmony_ci                if param.counter or len(param.count_parameter_list):
225bf215546Sopenharmony_ci                    return param
226bf215546Sopenharmony_ci
227bf215546Sopenharmony_ci        return None
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci
230bf215546Sopenharmony_ci    def calculate_offsets(self):
231bf215546Sopenharmony_ci        if not self.offsets_calculated:
232bf215546Sopenharmony_ci            # Calculate the offset of the first function parameter
233bf215546Sopenharmony_ci            # in the GLX command packet.  This byte offset is
234bf215546Sopenharmony_ci            # measured from the end of the Render / RenderLarge
235bf215546Sopenharmony_ci            # header.  The offset for all non-pixel commends is
236bf215546Sopenharmony_ci            # zero.  The offset for pixel commands depends on the
237bf215546Sopenharmony_ci            # number of dimensions of the pixel data.
238bf215546Sopenharmony_ci
239bf215546Sopenharmony_ci            if len(self.images) and not self.images[0].is_output:
240bf215546Sopenharmony_ci                [dim, junk, junk, junk, junk] = self.images[0].get_dimensions()
241bf215546Sopenharmony_ci
242bf215546Sopenharmony_ci                # The base size is the size of the pixel pack info
243bf215546Sopenharmony_ci                # header used by images with the specified number
244bf215546Sopenharmony_ci                # of dimensions.
245bf215546Sopenharmony_ci
246bf215546Sopenharmony_ci                if dim <=  2:
247bf215546Sopenharmony_ci                    offset = 20
248bf215546Sopenharmony_ci                elif dim <= 4:
249bf215546Sopenharmony_ci                    offset = 36
250bf215546Sopenharmony_ci                else:
251bf215546Sopenharmony_ci                    raise RuntimeError('Invalid number of dimensions %u for parameter "%s" in function "%s".' % (dim, self.image.name, self.name))
252bf215546Sopenharmony_ci            else:
253bf215546Sopenharmony_ci                offset = 0
254bf215546Sopenharmony_ci
255bf215546Sopenharmony_ci            for param in self.parameterIterateGlxSend():
256bf215546Sopenharmony_ci                if param.img_null_flag:
257bf215546Sopenharmony_ci                    offset += 4
258bf215546Sopenharmony_ci
259bf215546Sopenharmony_ci                if param.name != self.img_reset:
260bf215546Sopenharmony_ci                    param.offset = offset
261bf215546Sopenharmony_ci                    if not param.is_variable_length() and not param.is_client_only:
262bf215546Sopenharmony_ci                        offset += param.size()
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ci                if self.pad_after( param ):
265bf215546Sopenharmony_ci                    offset += 4
266bf215546Sopenharmony_ci
267bf215546Sopenharmony_ci
268bf215546Sopenharmony_ci            self.offsets_calculated = 1
269bf215546Sopenharmony_ci        return
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_ci
272bf215546Sopenharmony_ci    def offset_of(self, param_name):
273bf215546Sopenharmony_ci        self.calculate_offsets()
274bf215546Sopenharmony_ci        return self.parameters_by_name[ param_name ].offset
275bf215546Sopenharmony_ci
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci    def parameterIterateGlxSend(self, include_variable_parameters = 1):
278bf215546Sopenharmony_ci        """Create an iterator for parameters in GLX request order."""
279bf215546Sopenharmony_ci
280bf215546Sopenharmony_ci        # The parameter lists are usually quite short, so it's easier
281bf215546Sopenharmony_ci        # (i.e., less code) to just generate a new list with the
282bf215546Sopenharmony_ci        # required elements than it is to create a new iterator class.
283bf215546Sopenharmony_ci
284bf215546Sopenharmony_ci        temp = [ [],  [], [] ]
285bf215546Sopenharmony_ci        for param in self.parameters:
286bf215546Sopenharmony_ci            if param.is_output: continue
287bf215546Sopenharmony_ci
288bf215546Sopenharmony_ci            if param.is_variable_length():
289bf215546Sopenharmony_ci                temp[2].append( param )
290bf215546Sopenharmony_ci            elif not self.glx_doubles_in_order and param.is_64_bit():
291bf215546Sopenharmony_ci                temp[0].append( param )
292bf215546Sopenharmony_ci            else:
293bf215546Sopenharmony_ci                temp[1].append( param )
294bf215546Sopenharmony_ci
295bf215546Sopenharmony_ci        parameters = temp[0]
296bf215546Sopenharmony_ci        parameters.extend( temp[1] )
297bf215546Sopenharmony_ci        if include_variable_parameters:
298bf215546Sopenharmony_ci            parameters.extend( temp[2] )
299bf215546Sopenharmony_ci        return iter(parameters)
300bf215546Sopenharmony_ci
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_ci    def parameterIterateCounters(self):
303bf215546Sopenharmony_ci        temp = []
304bf215546Sopenharmony_ci        for name in self.counter_list:
305bf215546Sopenharmony_ci            temp.append( self.parameters_by_name[ name ] )
306bf215546Sopenharmony_ci
307bf215546Sopenharmony_ci        return iter(temp)
308bf215546Sopenharmony_ci
309bf215546Sopenharmony_ci
310bf215546Sopenharmony_ci    def parameterIterateOutputs(self):
311bf215546Sopenharmony_ci        temp = []
312bf215546Sopenharmony_ci        for p in self.parameters:
313bf215546Sopenharmony_ci            if p.is_output:
314bf215546Sopenharmony_ci                temp.append( p )
315bf215546Sopenharmony_ci
316bf215546Sopenharmony_ci        return temp
317bf215546Sopenharmony_ci
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci    def command_fixed_length(self):
320bf215546Sopenharmony_ci        """Return the length, in bytes as an integer, of the
321bf215546Sopenharmony_ci        fixed-size portion of the command."""
322bf215546Sopenharmony_ci
323bf215546Sopenharmony_ci        if len(self.parameters) == 0:
324bf215546Sopenharmony_ci            return 0
325bf215546Sopenharmony_ci
326bf215546Sopenharmony_ci        self.calculate_offsets()
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci        size = 0
329bf215546Sopenharmony_ci        for param in self.parameterIterateGlxSend(0):
330bf215546Sopenharmony_ci            if param.name != self.img_reset and not param.is_client_only:
331bf215546Sopenharmony_ci                if size == 0:
332bf215546Sopenharmony_ci                    size = param.offset + param.size()
333bf215546Sopenharmony_ci                else:
334bf215546Sopenharmony_ci                    size += param.size()
335bf215546Sopenharmony_ci
336bf215546Sopenharmony_ci                if self.pad_after( param ):
337bf215546Sopenharmony_ci                    size += 4
338bf215546Sopenharmony_ci
339bf215546Sopenharmony_ci        for param in self.images:
340bf215546Sopenharmony_ci            if param.img_null_flag or param.is_output:
341bf215546Sopenharmony_ci                size += 4
342bf215546Sopenharmony_ci
343bf215546Sopenharmony_ci        return size
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_ci
346bf215546Sopenharmony_ci    def command_variable_length(self):
347bf215546Sopenharmony_ci        """Return the length, as a string, of the variable-sized
348bf215546Sopenharmony_ci        portion of the command."""
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci        size_string = ""
351bf215546Sopenharmony_ci        for p in self.parameterIterateGlxSend():
352bf215546Sopenharmony_ci            if (not p.is_output) and (p.is_variable_length() or p.is_image()):
353bf215546Sopenharmony_ci                # FIXME Replace the 1 in the size_string call
354bf215546Sopenharmony_ci                # FIXME w/0 to eliminate some un-needed parnes
355bf215546Sopenharmony_ci                # FIXME This would already be done, but it
356bf215546Sopenharmony_ci                # FIXME adds some extra diffs to the generated
357bf215546Sopenharmony_ci                # FIXME code.
358bf215546Sopenharmony_ci
359bf215546Sopenharmony_ci                size_string = size_string + " + safe_pad(%s)" % (p.size_string(1))
360bf215546Sopenharmony_ci
361bf215546Sopenharmony_ci        return size_string
362bf215546Sopenharmony_ci
363bf215546Sopenharmony_ci
364bf215546Sopenharmony_ci    def command_length(self):
365bf215546Sopenharmony_ci        size = self.command_fixed_length()
366bf215546Sopenharmony_ci
367bf215546Sopenharmony_ci        if self.glx_rop != 0:
368bf215546Sopenharmony_ci            size += 4
369bf215546Sopenharmony_ci
370bf215546Sopenharmony_ci        size = ((size + 3) & ~3)
371bf215546Sopenharmony_ci        return "%u%s" % (size, self.command_variable_length())
372bf215546Sopenharmony_ci
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci    def opcode_real_value(self):
375bf215546Sopenharmony_ci        """Get the true numeric value of the GLX opcode
376bf215546Sopenharmony_ci
377bf215546Sopenharmony_ci        Behaves similarly to opcode_value, except for
378bf215546Sopenharmony_ci        X_GLXVendorPrivate and X_GLXVendorPrivateWithReply commands.
379bf215546Sopenharmony_ci        In these cases the value for the GLX opcode field (i.e.,
380bf215546Sopenharmony_ci        16 for X_GLXVendorPrivate or 17 for
381bf215546Sopenharmony_ci        X_GLXVendorPrivateWithReply) is returned.  For other 'single'
382bf215546Sopenharmony_ci        commands, the opcode for the command (e.g., 101 for
383bf215546Sopenharmony_ci        X_GLsop_NewList) is returned."""
384bf215546Sopenharmony_ci
385bf215546Sopenharmony_ci        if self.glx_vendorpriv != 0:
386bf215546Sopenharmony_ci            if self.needs_reply():
387bf215546Sopenharmony_ci                return 17
388bf215546Sopenharmony_ci            else:
389bf215546Sopenharmony_ci                return 16
390bf215546Sopenharmony_ci        else:
391bf215546Sopenharmony_ci            return self.opcode_value()
392bf215546Sopenharmony_ci
393bf215546Sopenharmony_ci
394bf215546Sopenharmony_ci    def opcode_value(self):
395bf215546Sopenharmony_ci        """Get the unique protocol opcode for the glXFunction"""
396bf215546Sopenharmony_ci
397bf215546Sopenharmony_ci        if (self.glx_rop == 0) and self.vectorequiv:
398bf215546Sopenharmony_ci            equiv = self.context.functions_by_name[ self.vectorequiv ]
399bf215546Sopenharmony_ci            self.glx_rop = equiv.glx_rop
400bf215546Sopenharmony_ci
401bf215546Sopenharmony_ci
402bf215546Sopenharmony_ci        if self.glx_rop != 0:
403bf215546Sopenharmony_ci            return self.glx_rop
404bf215546Sopenharmony_ci        elif self.glx_sop != 0:
405bf215546Sopenharmony_ci            return self.glx_sop
406bf215546Sopenharmony_ci        elif self.glx_vendorpriv != 0:
407bf215546Sopenharmony_ci            return self.glx_vendorpriv
408bf215546Sopenharmony_ci        else:
409bf215546Sopenharmony_ci            return -1
410bf215546Sopenharmony_ci
411bf215546Sopenharmony_ci
412bf215546Sopenharmony_ci    def opcode_rop_basename(self):
413bf215546Sopenharmony_ci        """Return either the name to be used for GLX protocol enum.
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_ci        Returns either the name of the function or the name of the
416bf215546Sopenharmony_ci        name of the equivalent vector (e.g., glVertex3fv for
417bf215546Sopenharmony_ci        glVertex3f) function."""
418bf215546Sopenharmony_ci
419bf215546Sopenharmony_ci        if self.vectorequiv == None:
420bf215546Sopenharmony_ci            return self.name
421bf215546Sopenharmony_ci        else:
422bf215546Sopenharmony_ci            return self.vectorequiv
423bf215546Sopenharmony_ci
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_ci    def opcode_name(self):
426bf215546Sopenharmony_ci        """Get the unique protocol enum name for the glXFunction"""
427bf215546Sopenharmony_ci
428bf215546Sopenharmony_ci        if (self.glx_rop == 0) and self.vectorequiv:
429bf215546Sopenharmony_ci            equiv = self.context.functions_by_name[ self.vectorequiv ]
430bf215546Sopenharmony_ci            self.glx_rop = equiv.glx_rop
431bf215546Sopenharmony_ci            self.glx_doubles_in_order = equiv.glx_doubles_in_order
432bf215546Sopenharmony_ci
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci        if self.glx_rop != 0:
435bf215546Sopenharmony_ci            return "X_GLrop_%s" % (self.opcode_rop_basename())
436bf215546Sopenharmony_ci        elif self.glx_sop != 0:
437bf215546Sopenharmony_ci            return "X_GLsop_%s" % (self.name)
438bf215546Sopenharmony_ci        elif self.glx_vendorpriv != 0:
439bf215546Sopenharmony_ci            return "X_GLvop_%s" % (self.name)
440bf215546Sopenharmony_ci        else:
441bf215546Sopenharmony_ci            raise RuntimeError('Function "%s" has no opcode.' % (self.name))
442bf215546Sopenharmony_ci
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci    def opcode_vendor_name(self, name):
445bf215546Sopenharmony_ci        if name in self.glx_vendorpriv_names:
446bf215546Sopenharmony_ci            return "X_GLvop_%s" % (name)
447bf215546Sopenharmony_ci        else:
448bf215546Sopenharmony_ci            raise RuntimeError('Function "%s" has no VendorPrivate opcode.' % (name))
449bf215546Sopenharmony_ci
450bf215546Sopenharmony_ci
451bf215546Sopenharmony_ci    def opcode_real_name(self):
452bf215546Sopenharmony_ci        """Get the true protocol enum name for the GLX opcode
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ci        Behaves similarly to opcode_name, except for
455bf215546Sopenharmony_ci        X_GLXVendorPrivate and X_GLXVendorPrivateWithReply commands.
456bf215546Sopenharmony_ci        In these cases the string 'X_GLXVendorPrivate' or
457bf215546Sopenharmony_ci        'X_GLXVendorPrivateWithReply' is returned.  For other
458bf215546Sopenharmony_ci        single or render commands 'X_GLsop' or 'X_GLrop' plus the
459bf215546Sopenharmony_ci        name of the function returned."""
460bf215546Sopenharmony_ci
461bf215546Sopenharmony_ci        if self.glx_vendorpriv != 0:
462bf215546Sopenharmony_ci            if self.needs_reply():
463bf215546Sopenharmony_ci                return "X_GLXVendorPrivateWithReply"
464bf215546Sopenharmony_ci            else:
465bf215546Sopenharmony_ci                return "X_GLXVendorPrivate"
466bf215546Sopenharmony_ci        else:
467bf215546Sopenharmony_ci            return self.opcode_name()
468bf215546Sopenharmony_ci
469bf215546Sopenharmony_ci
470bf215546Sopenharmony_ci    def needs_reply(self):
471bf215546Sopenharmony_ci        try:
472bf215546Sopenharmony_ci            x = self._needs_reply
473bf215546Sopenharmony_ci        except Exception:
474bf215546Sopenharmony_ci            x = 0
475bf215546Sopenharmony_ci            if self.return_type != 'void':
476bf215546Sopenharmony_ci                x = 1
477bf215546Sopenharmony_ci
478bf215546Sopenharmony_ci            for param in self.parameters:
479bf215546Sopenharmony_ci                if param.is_output:
480bf215546Sopenharmony_ci                    x = 1
481bf215546Sopenharmony_ci                    break
482bf215546Sopenharmony_ci
483bf215546Sopenharmony_ci            self._needs_reply = x
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci        return x
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci    def pad_after(self, p):
489bf215546Sopenharmony_ci        """Returns the name of the field inserted after the
490bf215546Sopenharmony_ci        specified field to pad out the command header."""
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci        for image in self.images:
493bf215546Sopenharmony_ci            if image.img_pad_dimensions:
494bf215546Sopenharmony_ci                if not image.height:
495bf215546Sopenharmony_ci                    if p.name == image.width:
496bf215546Sopenharmony_ci                        return "height"
497bf215546Sopenharmony_ci                    elif p.name == image.img_xoff:
498bf215546Sopenharmony_ci                        return "yoffset"
499bf215546Sopenharmony_ci                elif not image.extent:
500bf215546Sopenharmony_ci                    if p.name == image.depth:
501bf215546Sopenharmony_ci                        # Should this be "size4d"?
502bf215546Sopenharmony_ci                        return "extent"
503bf215546Sopenharmony_ci                    elif p.name == image.img_zoff:
504bf215546Sopenharmony_ci                        return "woffset"
505bf215546Sopenharmony_ci
506bf215546Sopenharmony_ci        return None
507bf215546Sopenharmony_ci
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci    def has_different_protocol(self, name):
510bf215546Sopenharmony_ci        """Returns true if the named version of the function uses different protocol from the other versions.
511bf215546Sopenharmony_ci
512bf215546Sopenharmony_ci        Some functions, such as glDeleteTextures and
513bf215546Sopenharmony_ci        glDeleteTexturesEXT are functionally identical, but have
514bf215546Sopenharmony_ci        different protocol.  This function returns true if the
515bf215546Sopenharmony_ci        named function is an alias name and that named version uses
516bf215546Sopenharmony_ci        different protocol from the function that is aliased.
517bf215546Sopenharmony_ci        """
518bf215546Sopenharmony_ci
519bf215546Sopenharmony_ci        return (name in self.glx_vendorpriv_names) and self.glx_sop
520bf215546Sopenharmony_ci
521bf215546Sopenharmony_ci
522bf215546Sopenharmony_ci    def static_glx_name(self, name):
523bf215546Sopenharmony_ci        if self.has_different_protocol(name):
524bf215546Sopenharmony_ci            for n in self.glx_vendorpriv_names:
525bf215546Sopenharmony_ci                if n in self.static_entry_points:
526bf215546Sopenharmony_ci                    return n
527bf215546Sopenharmony_ci
528bf215546Sopenharmony_ci        return self.static_name(name)
529bf215546Sopenharmony_ci
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci    def client_supported_for_indirect(self):
532bf215546Sopenharmony_ci        """Returns true if the function is supported on the client
533bf215546Sopenharmony_ci        side for indirect rendering."""
534bf215546Sopenharmony_ci
535bf215546Sopenharmony_ci        return not self.ignore and (self.offset != -1) and (self.glx_rop or self.glx_sop or self.glx_vendorpriv or self.vectorequiv or self.client_handcode)
536bf215546Sopenharmony_ci
537bf215546Sopenharmony_ci
538bf215546Sopenharmony_ciclass glx_function_iterator(object):
539bf215546Sopenharmony_ci    """Class to iterate over a list of glXFunctions"""
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci    def __init__(self, context):
542bf215546Sopenharmony_ci        self.iterator = context.functionIterateByOffset()
543bf215546Sopenharmony_ci        return
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ci
546bf215546Sopenharmony_ci    def __iter__(self):
547bf215546Sopenharmony_ci        return self
548bf215546Sopenharmony_ci
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci    def __next__(self):
551bf215546Sopenharmony_ci        while True:
552bf215546Sopenharmony_ci            f = next(self.iterator)
553bf215546Sopenharmony_ci
554bf215546Sopenharmony_ci            if f.client_supported_for_indirect():
555bf215546Sopenharmony_ci                return f
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci    next = __next__
558bf215546Sopenharmony_ci
559bf215546Sopenharmony_ci
560bf215546Sopenharmony_ciclass glx_api(gl_XML.gl_api):
561bf215546Sopenharmony_ci    def functionIterateGlx(self):
562bf215546Sopenharmony_ci        return glx_function_iterator(self)
563bf215546Sopenharmony_ci
564