diff options
| author | Ian Romanick <idr@us.ibm.com> | 2006-08-23 20:32:48 +0000 | 
|---|---|---|
| committer | Ian Romanick <idr@us.ibm.com> | 2006-08-23 20:32:48 +0000 | 
| commit | 261a806f9e26347d756bddeae81f4e98325b8e84 (patch) | |
| tree | 40279e4e65d9b1cfd42b7fedd5ea844ad70b247f /src | |
| parent | d21ccb49c078f69030424c31dfe0b70dfe269ba8 (diff) | |
New script and API description file to enable generate of GLX protocol
decode tables in the server.
Diffstat (limited to 'src')
| -rw-r--r-- | src/mesa/glapi/Makefile | 10 | ||||
| -rw-r--r-- | src/mesa/glapi/glX_API.xml | 215 | ||||
| -rw-r--r-- | src/mesa/glapi/glX_server_table.py | 400 | ||||
| -rw-r--r-- | src/mesa/glapi/gl_and_glX_API.xml | 7 | 
4 files changed, 629 insertions, 3 deletions
| diff --git a/src/mesa/glapi/Makefile b/src/mesa/glapi/Makefile index 4eba897e4b..6e8ed1508a 100644 --- a/src/mesa/glapi/Makefile +++ b/src/mesa/glapi/Makefile @@ -27,7 +27,8 @@ SERVER_OUTPUTS = $(GLX_DIR)/indirect_dispatch.c \  	$(GLX_DIR)/indirect_dispatch_swap.c \  	$(GLX_DIR)/indirect_dispatch.h \  	$(GLX_DIR)/indirect_size_get.c \ -	$(GLX_DIR)/indirect_size_get.h +	$(GLX_DIR)/indirect_size_get.h \ +	$(GLX_DIR)/indirect_table.c  COMMON = gl_XML.py license.py gl_API.xml typeexpr.py  COMMON_GLX = $(COMMON) glX_XML.py glX_proto_common.py @@ -88,8 +89,8 @@ $(GLX_DIR)/indirect_dispatch.c: $(COMMON_GLX) glX_proto_recv.py  $(GLX_DIR)/indirect_dispatch_swap.c: $(COMMON_GLX) glX_proto_recv.py  	$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_c -s > $@ -$(GLX_DIR)/indirect_dispatch.h: $(COMMON_GLX) glX_proto_recv.py -	$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_h -s > $@ +$(GLX_DIR)/indirect_dispatch.h: $(COMMON_GLX) glX_proto_recv.py glX_API.xml +	$(PYTHON2) $(PYTHON_FLAGS) glX_proto_recv.py -m dispatch_h -f gl_and_glX_API.xml -s > $@  $(GLX_DIR)/indirect_size_get.h: $(COMMON_GLX) glX_proto_size.py  	$(PYTHON2) $(PYTHON_FLAGS) glX_proto_size.py -m size_h --only-get -h '_INDIRECT_SIZE_GET_H_' > $@ @@ -97,6 +98,9 @@ $(GLX_DIR)/indirect_size_get.h: $(COMMON_GLX) glX_proto_size.py  $(GLX_DIR)/indirect_size_get.c: $(COMMON_GLX) glX_proto_size.py  	$(PYTHON2) $(PYTHON_FLAGS) glX_proto_size.py -m size_c > $@ +$(GLX_DIR)/indirect_table.c: $(COMMON_GLX) glX_server_table.py glX_API.xml +	$(PYTHON2) $(PYTHON_FLAGS) glX_server_table.py -f gl_and_glX_API.xml > $@ +  clean:  	rm -f *~ *.pyo  	rm -f $(OUTPUTS) diff --git a/src/mesa/glapi/glX_API.xml b/src/mesa/glapi/glX_API.xml new file mode 100644 index 0000000000..3f2fbd1163 --- /dev/null +++ b/src/mesa/glapi/glX_API.xml @@ -0,0 +1,215 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<OpenGLAPI> + +<!-- Right now this file is just used to generate the GLX protocol +     decode tables on the server.  The only information that is needed +     for that purpose is the name of the function (or pseudo-function +     in the case of Render of VendorPrivate) and its opcode.  Once +     this file is used for other purposes, additional information will +     need to be added. +  --> + +<category name="1.0" window_system="glX"> +    <function name="Render"> +        <glx sop="1"/> +    </function> + +    <function name="RenderLarge"> +        <glx sop="2"/> +    </function> + +    <function name="CreateContext"> +        <glx sop="3"/> +    </function> + +    <function name="DestroyContext"> +        <glx sop="4"/> +    </function> + +    <function name="MakeCurrent"> +        <glx sop="5"/> +    </function> + +    <function name="IsDirect"> +        <glx sop="6"/> +    </function> + +    <function name="QueryVersion"> +        <glx sop="7"/> +    </function> + +    <function name="WaitGL"> +        <glx sop="8"/> +    </function> + +    <function name="WaitX"> +        <glx sop="9"/> +    </function> + +    <function name="CopyContext"> +        <glx sop="10"/> +    </function> + +    <function name="SwapBuffers"> +        <glx sop="11"/> +    </function> + +    <function name="UseXFont"> +        <glx sop="12"/> +    </function> + +    <function name="CreateGLXPixmap"> +        <glx sop="13"/> +    </function> + +    <function name="GetVisualConfigs"> +        <glx sop="14"/> +    </function> + +    <function name="DestroyGLXPixmap"> +        <glx sop="15"/> +    </function> + +    <function name="VendorPrivate"> +        <glx sop="16"/> +    </function> + +    <function name="VendorPrivateWithReply"> +        <glx sop="17"/> +    </function> + +    <function name="QueryExtensionsString"> +        <glx sop="18"/> +    </function> +</category> + +<category name="1.1" window_system="glX"> +    <function name="QueryServerString"> +        <glx sop="19"/> +    </function> + +    <function name="ClientInfo"> +        <glx sop="20"/> +    </function> +</category> + +<category name="1.3" window_system="glX"> +    <function name="GetFBConfigs"> +        <glx sop="21"/> +    </function> + +    <function name="CreatePixmap"> +        <glx sop="22"/> +    </function> + +    <function name="DestroyPixmap"> +        <glx sop="23"/> +    </function> + +    <function name="CreateNewContext"> +        <glx sop="24"/> +    </function> + +    <function name="QueryContext"> +        <glx sop="25"/> +    </function> + +    <function name="MakeContextCurrent"> +        <glx sop="26"/> +    </function> + +    <function name="CreatePbuffer"> +        <glx sop="27"/> +    </function> + +    <function name="DestroyPbuffer"> +        <glx sop="28"/> +    </function> + +    <function name="GetDrawableAttributes"> +        <glx sop="29"/> +    </function> + +    <function name="ChangeDrawableAttributes"> +        <glx sop="30"/> +    </function> + +    <function name="CreateWindow"> +        <glx sop="31"/> +    </function> + +    <function name="DestroyWindow"> +        <glx sop="32"/> +    </function> +</category> + +<category name="GLX_SGI_make_current_read" number="42" window_system="glX"> +    <function name="MakeCurrentReadSGI"> +<!--        <param name="dpy" type="Display *"/> +	<param name="draw" type="GLXDrawable"/> +	<param name="read" type="GLXDrawable"/> +	<param name="ctx" type="GLXContext"/> --> +        <return type="Bool"/> +        <glx vendorpriv="65537"/> +    </function> +</category> + +<category name="GLX_EXT_import_context" number="47" window_system="glX"> +    <function name="QueryContextInfoEXT"> +        <glx vendorpriv="1024"/> +    </function> +</category> + +<category name="GLX_SGIX_fbconfig" number="49" window_system="glX"> +    <function name="GetFBConfigsSGIX"> +        <glx vendorpriv="65540"/> +    </function> + +    <function name="CreateContextWithConfigSGIX"> +        <glx vendorpriv="65541"/> +    </function> + +    <function name="CreateGLXPixmapWithConfigSGIX"> +        <glx vendorpriv="65542"/> +    </function> +</category> + +<!-- +<category name="GLX_SGIX_pbuffer" number="50" window_system="glX"> +    <function name="CreateGLXPbufferSGIX"> +        <glx vendorpriv="65543"/> +    </function> + +    <function name="DestroyGLXPbufferSGIX"> +        <glx vendorpriv="65544"/> +    </function> + +    <function name="ChangeDrawableAttributesSGIX"> +        <glx vendorpriv="65545"/> +    </function> + +    <function name="GetDrawableAttributesSGIX"> +        <glx vendorpriv="65546"/> +    </function> +</category> +--> + +<category name="GLX_MESA_copy_sub_buffer" number="215"> +    <function name="CopySubBufferMESA"> +        <glx vendorpriv="5154"/> +    </function> +</category> + +<category name="GLX_EXT_texture_from_pixmap"> +    <function name="BindTexImageEXT"> +        <glx vendorpriv="5152"/> +    </function> + +    <function name="ReleaseTexImageEXT"> +        <glx vendorpriv="5153"/> +    </function> +</category> + +</OpenGLAPI> diff --git a/src/mesa/glapi/glX_server_table.py b/src/mesa/glapi/glX_server_table.py new file mode 100644 index 0000000000..2535b48014 --- /dev/null +++ b/src/mesa/glapi/glX_server_table.py @@ -0,0 +1,400 @@ +#!/bin/env python + +# (C) Copyright IBM Corporation 2005, 2006 +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# on the rights to use, copy, modify, merge, publish, distribute, sub +# license, and/or sell copies of the Software, and to permit persons to whom +# the Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL +# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# Authors: +#    Ian Romanick <idr@us.ibm.com> + +import gl_XML, glX_XML, license +import sys, getopt + + +def log2(value): +	for i in range(0, 30): +		p = 1 << i +		if p >= value: +			return i + +	return -1 + + +def round_down_to_power_of_two(n): +	"""Returns the nearest power-of-two less than or equal to n.""" + +	for i in range(30, 0, -1): +		p = 1 << i +		if p <= n: +			return p + +	return -1 + + +class function_table: +	def __init__(self, name, do_size_check): +		self.name_base = name +		self.do_size_check = do_size_check + + +		self.max_bits = 1 +		self.next_opcode_threshold = (1 << self.max_bits) +		self.max_opcode = 0 + +		self.functions = {} +		self.lookup_table = [] +		 +		# Minimum number of opcodes in a leaf node. +		self.min_op_bits = 3 +		self.min_op_count = (1 << self.min_op_bits) +		return + + +	def append(self, opcode, func): +		self.functions[opcode] = func + +		if opcode > self.max_opcode: +			self.max_opcode = opcode + +			if opcode > self.next_opcode_threshold: +				bits = log2(opcode) +				if (1 << bits) <= opcode: +					bits += 1 + +				self.max_bits = bits +				self.next_opcode_threshold = 1 << bits +		return + + +	def divide_group(self, min_opcode, total): +		"""Divide the group starting min_opcode into subgroups. +		Returns a tuple containing the number of bits consumed by +		the node, the list of the children's tuple, and the number +		of entries in the final array used by this node and its +		children, and the depth of the subtree rooted at the node.""" + +		remaining_bits = self.max_bits - total +		next_opcode = min_opcode + (1 << remaining_bits) +		empty_children = 0 +		 +		for M in range(0, remaining_bits): +			op_count = 1 << (remaining_bits - M); +			child_count = 1 << M; + +			empty_children = 0 +			full_children = 0 +			for i in range(min_opcode, next_opcode, op_count): +				used = 0 +				empty = 0 + +				for j in range(i, i + op_count): +					if self.functions.has_key(j): +						used += 1; +					else: +						empty += 1; +						 + +				if empty == op_count: +					empty_children += 1 + +				if used == op_count: +					full_children += 1 + +			if (empty_children > 0) or (full_children == child_count) or (op_count <= self.min_op_count): +				break + + +		# If all the remaining bits are used by this node, as is the +		# case when M is 0 or remaining_bits, the node is a leaf. + +		if (M == 0) or (M == remaining_bits): +			return [remaining_bits, [], 0, 0] +		else: +			children = [] +			count = 1 +			depth = 1 +			all_children_are_nonempty_leaf_nodes = 1 +			for i in range(min_opcode, next_opcode, op_count): +				n = self.divide_group(i, total + M) + +				if not (n[1] == [] and not self.is_empty_leaf(i, n[0])): +					all_children_are_nonempty_leaf_nodes = 0 + +				children.append(n) +				count += n[2] + 1 +				 +				if n[3] >= depth: +					depth = n[3] + 1 + +			# If all of the child nodes are non-empty leaf nodes, pull +			# them up and make this node a leaf. + +			if all_children_are_nonempty_leaf_nodes: +				return [remaining_bits, [], 0, 0] +			else: +				return [M, children, count, depth] + + +	def is_empty_leaf(self, base_opcode, M): +		for op in range(base_opcode, base_opcode + (1 << M)): +			if self.functions.has_key(op): +				return 0 +				break + +		return 1 + + +	def dump_tree(self, node, base_opcode, remaining_bits, base_entry, depth): +		M = node[0] +		children = node[1] +		child_M = remaining_bits - M + + +		# This actually an error condition. +		if children == []: +			return + +		print '    /* [%u] -> opcode range [%u, %u], node depth %u */' % (base_entry, base_opcode, base_opcode + (1 << remaining_bits), depth) +		print '    %u,' % (M) + +		base_entry += (1 << M) + 1 + +		child_index = base_entry +		child_base_opcode = base_opcode +		for child in children: +			if child[1] == []: +				if self.is_empty_leaf(child_base_opcode, child_M): +					print '    EMPTY_LEAF,' +				else: +					# Emit the index of the next dispatch +					# function.  Then add all the +					# dispatch functions for this leaf +					# node to the dispatch function +					# lookup table. + +					print '    LEAF(%u),' % (len(self.lookup_table)) + +					for op in range(child_base_opcode, child_base_opcode + (1 << child_M)): +						if self.functions.has_key(op): +							func = self.functions[op] +							size = func.command_fixed_length() +							if func.has_variable_size_request(): +								size_name = "__glX%sReqSize" % (func.name) +							else: +								size_name = "" + +							temp = [op, "__glXDisp_%s" % (func.name), "__glXDispSwap_%s" % (func.name), size, size_name] +						else: +							temp = [op, "NULL", "NULL", 0, ""] + +						self.lookup_table.append(temp) +			else: +				print '    %u,' % (child_index) +				child_index += child[2] + +			child_base_opcode += 1 << child_M + +		print '' + +		child_index = base_entry +		for child in children: +			if child[1] != []: +				self.dump_tree(child, base_opcode, remaining_bits - M, child_index, depth + 1) +				child_index += child[2] + +			base_opcode += 1 << (remaining_bits - M) + + +	def Print(self): +		# Each dispatch table consists of two data structures. +		# +		# The first structure is an N-way tree where the opcode for +		# the function is the key.  Each node switches on a range of +		# bits from the opcode.  M bits are extracted from the opcde +		# and are used as an index to select one of the N, where +		# N = 2^M, children. +		# +		# The tree is stored as a flat array.  The first value is the +		# number of bits, M, used by the node.  For inner nodes, the +		# following 2^M values are indexes into the array for the +		# child nodes.  For leaf nodes, the followign 2^M values are +		# indexes into the second data structure. +		# +		# If an inner node's child index is 0, the child is an empty +		# leaf node.  That is, none of the opcodes selectable from +		# that child exist.  Since most of the possible opcode space +		# is unused, this allows compact data storage. +		# +		# The second data structure is an array of pairs of function +		# pointers.  Each function contains a pointer to a protocol +		# decode function and a pointer to a byte-swapped protocol +		# decode function.  Elements in this array are selected by the +		# leaf nodes of the first data structure. +		# +		# As the tree is traversed, an accumulator is kept.  This +		# accumulator counts the bits of the opcode consumed by the +		# traversal.  When accumulator + M = B, where B is the +		# maximum number of bits in an opcode, the traversal has +		# reached a leaf node.  The traversal starts with the most +		# significant bits and works down to the least significant +		# bits. +		# +		# Creation of the tree is the most complicated part.  At +		# each node the elements are divided into groups of 2^M +		# elements.  The value of M selected is the smallest possible +		# value where all of the groups are either empty or full, or +		# the groups are a preset minimum size.  If all the children +		# of a node are non-empty leaf nodes, the children are merged +		# to create a single leaf node that replaces the parent. + +		tree = self.divide_group(0, 0) + +		print '/*****************************************************************/' +		print '/* tree depth = %u */' % (tree[3]) +		print 'static const int_fast16_t %s_dispatch_tree[%u] = {' % (self.name_base, tree[2]) +		self.dump_tree(tree, 0, self.max_bits, 0, 1) +		print '};\n' +		 +		# After dumping the tree, dump the function lookup table. +		 +		print 'static const __GLXdispatch%sProcPtr %s_function_table[%u][2] = {' % (self.name_base, self.name_base, len(self.lookup_table)) +		index = 0 +		for func in self.lookup_table: +			opcode = func[0] +			name = func[1] +			name_swap = func[2] +			 +			print '    /* [% 3u] = %5u */ {%s, %s},' % (index, opcode, name, name_swap) +			 +			index += 1 + +		print '};\n' +		 +		if self.do_size_check: +			var_table = [] + +			print 'static const int_fast16_t %s_size_table[%u][2] = {' % (self.name_base, len(self.lookup_table)) +			index = 0 +			var_table = [] +			for func in self.lookup_table: +				opcode = func[0] +				fixed = func[3] +				var = func[4] +				 +				if var != "": +					var_offset = "%u" % (len(var)) +					var_table.append(var) +				else: +					var_offset = "~0" + +				print '    /* [% 3u] = %5u */ {%u, %s},' % (index, opcode, fixed, var_offset) +				index += 1 + +				 +			print '};\n' + + +			print 'static const size_func %s_size_func_table[%u] = {' % (self.name_base, len(var_table)) +			for func in var_table: +				print '   %s,' % (func) +  +			print '};\n' + + +		print 'const struct __glXDispatchInfo %s_dispatch_info = {' % (self.name_base) +		print '    %u,' % (self.max_bits) +		print '    %s_dispatch_tree,' % (self.name_base) +		print '    %s_function_table,' % (self.name_base) +		if self.do_size_check: +			print '    %s_size_table,' % (self.name_base) +			print '    %s_size_func_table' % (self.name_base) +		else: +			print '    NULL,' +			print '    NULL' +		print '};\n' +		return + + +class PrintGlxDispatchTables(gl_XML.gl_print_base): +	def __init__(self): +		gl_XML.gl_print_base.__init__(self) +		self.name = "glX_server_table.py (from Mesa)" +		self.license = license.bsd_license_template % ( "(C) Copyright IBM Corporation 2005, 2006", "IBM") + +		self.rop_functions = function_table("Render", 1) +		self.sop_functions = function_table("Single", 0) +		self.vop_functions = function_table("VendorPriv", 0) +		return + + +	def printRealHeader(self): +		print '#include <inttypes.h>' +		print '#include "glxserver.h"' +		print '#include "glxext.h"' +		print '#include "indirect_dispatch.h"' +		print '#include "indirect_reqsize.h"' +		print '#include "g_disptab.h"' +		print '#include "indirect_table.h"' +		print '' +		return + + +	def printBody(self, api): +		for f in api.functionIterateAll(): +			if not f.ignore and f.vectorequiv == None: +				if f.glx_rop != 0: +					self.rop_functions.append(f.glx_rop, f) +				elif f.glx_sop != 0: +					self.sop_functions.append(f.glx_sop, f) +				elif f.glx_vendorpriv != 0: +					self.vop_functions.append(f.glx_vendorpriv, f) + +		self.sop_functions.Print() +		#self.rop_functions.Print() +		self.vop_functions.Print() +		return + + +if __name__ == '__main__': +	file_name = "gl_API.xml" + +	try: +		(args, trail) = getopt.getopt(sys.argv[1:], "f:m") +	except Exception,e: +		show_usage() + +	mode = "table_c" +	for (arg,val) in args: +		if arg == "-f": +			file_name = val +		elif arg == "-m": +			mode = val + +	if mode == "table_c": +		printer = PrintGlxDispatchTables() +	else: +		show_usage() + + +	api = gl_XML.parse_GL_API( file_name, glX_XML.glx_item_factory() ) + + +	printer.Print( api ) diff --git a/src/mesa/glapi/gl_and_glX_API.xml b/src/mesa/glapi/gl_and_glX_API.xml new file mode 100644 index 0000000000..34c977e9c0 --- /dev/null +++ b/src/mesa/glapi/gl_and_glX_API.xml @@ -0,0 +1,7 @@ +<?xml version="1.0"?> +<!DOCTYPE OpenGLAPI SYSTEM "gl_API.dtd"> + +<OpenGLAPI> +<xi:include href="glX_API.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> +<xi:include href="gl_API.xml" xmlns:xi="http://www.w3.org/2001/XInclude"/> +</OpenGLAPI>
\ No newline at end of file | 
