Commit 03644191 authored by kkinnunen@nvidia.com's avatar kkinnunen@nvidia.com

Clarify function info object usage in the command buffer generator

Before, the Function objects (roughly corresponding to the commands
being generated) would construct itself based on the function info
object, parsed properties and many argument lists. The argument lists
themselves were also constructed out of function info object and the
parsed properties.

Try to clarify this by following changes.

Define that function info object is first parsed from the
cmd_buffer_functions.txt file.

Then the function info is possibly augmented by the optional object
for the function info object table (_FUNCTION_INFO).

Function objects are created solely on the function info
object. Function constructor parses the function info object and
constructs the needed properties, such as function type handlers,
argument arrays and return value types.

Function provides simple initialization function that the immediate and
bucket subclasses can use to construct specialized versions of the
command buffer command argument lists.

Review URL: https://codereview.chromium.org/276873002

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@270051 0039d316-1c4b-4281-b951-d872f2087c98
parent dca94c76
......@@ -1213,8 +1213,11 @@ _PEPPER_INTERFACES = [
{'name': 'DrawBuffers', 'dev': True},
]
# This table specifies types and other special data for the commands that
# will be generated.
# A function info object specifies the type and other special data for the
# command that will be generated. A base function info object is generated by
# parsing the "cmd_buffer_functions.txt", one for each function in the
# file. These function info objects can be augmented and their values can be
# overridden by adding an object to the table below.
#
# Must match function names specified in "cmd_buffer_functions.txt".
#
......@@ -4831,7 +4834,7 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
}
"""
file.Write(code % (self.GetArrayType(func), self.GetArrayCount(func)))
if func.is_immediate:
if func.IsImmediate():
file.Write(" if (data_size > immediate_data_size) {\n")
file.Write(" return error::kOutOfBounds;\n")
file.Write(" }\n")
......@@ -5099,7 +5102,7 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) {
}
"""
file.Write(code % (self.GetArrayType(func), self.GetArrayCount(func)))
if func.is_immediate:
if func.IsImmediate():
file.Write(" if (data_size > immediate_data_size) {\n")
file.Write(" return error::kOutOfBounds;\n")
file.Write(" }\n")
......@@ -5773,18 +5776,6 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs) {
"""Overrriden from TypeHandler."""
pass
class FunctionInfo(object):
"""Holds info about a function."""
def __init__(self, info, type_handler):
for key in info:
setattr(self, key, info[key])
self.type_handler = type_handler
if not 'type' in info:
self.type = ''
class Argument(object):
"""A class that represents a function argument."""
......@@ -5960,7 +5951,7 @@ class SizeArgument(Argument):
def GetNumInvalidValues(self, func):
"""overridden from Argument."""
if func.is_immediate:
if func.IsImmediate():
return 0
return 1
......@@ -6389,35 +6380,102 @@ class ResourceIdZeroArgument(Argument):
class Function(object):
"""A class that represents a function."""
def __init__(self, original_name, name, info, return_type, original_args,
args_for_cmds, cmd_args, init_args, num_pointer_args):
type_handlers = {
'': TypeHandler(),
'Bind': BindHandler(),
'Create': CreateHandler(),
'Custom': CustomHandler(),
'Data': DataHandler(),
'Delete': DeleteHandler(),
'DELn': DELnHandler(),
'GENn': GENnHandler(),
'GETn': GETnHandler(),
'GLchar': GLcharHandler(),
'GLcharN': GLcharNHandler(),
'HandWritten': HandWrittenHandler(),
'Is': IsHandler(),
'Manual': ManualHandler(),
'PUT': PUTHandler(),
'PUTn': PUTnHandler(),
'PUTXn': PUTXnHandler(),
'StateSet': StateSetHandler(),
'StateSetRGBAlpha': StateSetRGBAlphaHandler(),
'StateSetFrontBack': StateSetFrontBackHandler(),
'StateSetFrontBackSeparate': StateSetFrontBackSeparateHandler(),
'StateSetNamedParameter': StateSetNamedParameter(),
'STRn': STRnHandler(),
'Todo': TodoHandler(),
}
def __init__(self, name, info):
self.name = name
self.original_name = original_name
self.original_name = info['original_name']
self.original_args = self.ParseArgs(info['original_args'])
if 'cmd_args' in info:
self.args_for_cmds = self.ParseArgs(info['cmd_args'])
else:
self.args_for_cmds = self.original_args[:]
self.return_type = info['return_type']
if self.return_type != 'void':
self.return_arg = CreateArg(info['return_type'] + " result")
else:
self.return_arg = None
self.num_pointer_args = sum(
[1 for arg in self.args_for_cmds if arg.IsPointer()])
self.info = info
self.type_handler = info.type_handler
self.return_type = return_type
self.original_args = original_args
self.num_pointer_args = num_pointer_args
self.can_auto_generate = num_pointer_args == 0 and return_type == "void"
self.cmd_args = cmd_args
self.init_args = init_args
self.type_handler = self.type_handlers[info['type']]
self.can_auto_generate = (self.num_pointer_args == 0 and
info['return_type'] == "void")
self.InitFunction()
self.args_for_cmds = args_for_cmds
self.is_immediate = False
def ParseArgs(self, arg_string):
"""Parses a function arg string."""
args = []
parts = arg_string.split(',')
for arg_string in parts:
arg = CreateArg(arg_string)
if arg:
args.append(arg)
return args
def IsType(self, type_name):
"""Returns true if function is a certain type."""
return self.info.type == type_name
return self.info['type'] == type_name
def InitFunction(self):
"""Calls the init function for the type handler."""
"""Creates command args and calls the init function for the type handler.
Creates argument lists for command buffer commands, eg. self.cmd_args and
self.init_args.
Calls the type function initialization.
Override to create different kind of command buffer command argument lists.
"""
self.cmd_args = []
for arg in self.args_for_cmds:
arg.AddCmdArgs(self.cmd_args)
self.init_args = []
for arg in self.args_for_cmds:
arg.AddInitArgs(self.init_args)
if self.return_arg:
self.init_args.append(self.return_arg)
self.type_handler.InitFunction(self)
def GetInfo(self, name):
def IsImmediate(self):
"""Returns whether the function is immediate data function or not."""
return False
def GetInfo(self, name, default = None):
"""Returns a value from the function info for this function."""
if hasattr(self.info, name):
return getattr(self.info, name)
return None
if name in self.info:
return self.info[name]
return default
def GetValidArg(self, index):
"""Gets a valid arg from the function info if one exists."""
......@@ -6428,7 +6486,7 @@ class Function(object):
def AddInfo(self, name, value):
"""Adds an info."""
setattr(self.info, name, value)
self.info[name] = value
def IsCoreGLFunction(self):
return (not self.GetInfo('extension') and
......@@ -6570,11 +6628,10 @@ class Function(object):
def WriteCmdFlag(self, file):
"""Writes the cmd cmd_flags constant."""
flags = []
trace_level = 3 # By default trace only at the highest level
if hasattr(self.info, 'trace_level'):
if (self.info.trace_level < 0) or (self.info.trace_level > 3):
raise KeyError("Unhandled trace_level: %d" % self.info.trace_level)
trace_level = self.info.trace_level
# By default trace only at the highest level 3.
trace_level = int(self.GetInfo('trace_level', default = 3))
if trace_level not in xrange(0, 4):
raise KeyError("Unhandled trace_level: %d" % trace_level)
flags.append('CMD_FLAG_SET_TRACE_LEVEL(%d)' % trace_level)
......@@ -6728,36 +6785,34 @@ class ImmediateFunction(Function):
"""A class that represnets an immediate function command."""
def __init__(self, func):
new_args = []
for arg in func.GetOriginalArgs():
Function.__init__(
self,
"%sImmediate" % func.name,
func.info)
def InitFunction(self):
# Override args in original_args and args_for_cmds with immediate versions
# of the args.
new_original_args = []
for arg in self.original_args:
new_arg = arg.GetImmediateVersion()
if new_arg:
new_args.append(new_arg)
new_original_args.append(new_arg)
self.original_args = new_original_args
cmd_args = []
new_args_for_cmds = []
for arg in func.args_for_cmds:
for arg in self.args_for_cmds:
new_arg = arg.GetImmediateVersion()
if new_arg:
new_args_for_cmds.append(new_arg)
new_arg.AddCmdArgs(cmd_args)
new_init_args = []
for arg in new_args_for_cmds:
arg.AddInitArgs(new_init_args)
self.args_for_cmds = new_args_for_cmds
Function.__init__(
self,
func.original_name,
"%sImmediate" % func.name,
func.info,
func.return_type,
new_args,
new_args_for_cmds,
cmd_args,
new_init_args,
0)
self.is_immediate = True
Function.InitFunction(self)
def IsImmediate(self):
return True
def WriteCommandDescription(self, file):
"""Overridden from Function"""
......@@ -6813,39 +6868,31 @@ class BucketFunction(Function):
"""A class that represnets a bucket version of a function command."""
def __init__(self, func):
new_args = []
for arg in func.GetOriginalArgs():
Function.__init__(
self,
"%sBucket" % func.name,
func.info)
def InitFunction(self):
# Override args in original_args and args_for_cmds with bucket versions
# of the args.
new_original_args = []
for arg in self.original_args:
new_arg = arg.GetBucketVersion()
if new_arg:
new_args.append(new_arg)
new_original_args.append(new_arg)
self.original_args = new_original_args
cmd_args = []
new_args_for_cmds = []
for arg in func.args_for_cmds:
for arg in self.args_for_cmds:
new_arg = arg.GetBucketVersion()
if new_arg:
new_args_for_cmds.append(new_arg)
new_arg.AddCmdArgs(cmd_args)
new_init_args = []
for arg in new_args_for_cmds:
arg.AddInitArgs(new_init_args)
self.args_for_cmds = new_args_for_cmds
Function.__init__(
self,
func.original_name,
"%sBucket" % func.name,
func.info,
func.return_type,
new_args,
new_args_for_cmds,
cmd_args,
new_init_args,
0)
# def InitFunction(self):
# """Overridden from Function"""
# pass
Function.InitFunction(self)
def WriteCommandDescription(self, file):
"""Overridden from Function"""
......@@ -6919,45 +6966,9 @@ class GLGenerator(object):
self.functions = []
self.verbose = verbose
self.errors = 0
self._function_info = {}
self._empty_type_handler = TypeHandler()
self._empty_function_info = FunctionInfo({}, self._empty_type_handler)
self.pepper_interfaces = []
self.interface_info = {}
self._type_handlers = {
'Bind': BindHandler(),
'Create': CreateHandler(),
'Custom': CustomHandler(),
'Data': DataHandler(),
'Delete': DeleteHandler(),
'DELn': DELnHandler(),
'GENn': GENnHandler(),
'GETn': GETnHandler(),
'GLchar': GLcharHandler(),
'GLcharN': GLcharNHandler(),
'HandWritten': HandWrittenHandler(),
'Is': IsHandler(),
'Manual': ManualHandler(),
'PUT': PUTHandler(),
'PUTn': PUTnHandler(),
'PUTXn': PUTXnHandler(),
'StateSet': StateSetHandler(),
'StateSetRGBAlpha': StateSetRGBAlphaHandler(),
'StateSetFrontBack': StateSetFrontBackHandler(),
'StateSetFrontBackSeparate': StateSetFrontBackSeparateHandler(),
'StateSetNamedParameter': StateSetNamedParameter(),
'STRn': STRnHandler(),
'Todo': TodoHandler(),
}
for func_name in _FUNCTION_INFO:
info = _FUNCTION_INFO[func_name]
type = ''
if 'type' in info:
type = info['type']
self._function_info[func_name] = FunctionInfo(info,
self.GetTypeHandler(type))
for interface in _PEPPER_INTERFACES:
interface = PepperInterface(interface)
self.pepper_interfaces.append(interface)
......@@ -6967,20 +6978,17 @@ class GLGenerator(object):
"""Adds a function."""
self.functions.append(func)
def GetTypeHandler(self, name):
"""Gets a type info for the given type."""
if len(name):
if name in self._type_handlers:
return self._type_handlers[name]
else:
raise KeyError("no such type handler: %s" % name)
return self._empty_type_handler
def GetFunctionInfo(self, name):
"""Gets a type info for the given function name."""
if name in self._function_info:
return self._function_info[name]
return self._empty_function_info
if name in _FUNCTION_INFO:
func_info = _FUNCTION_INFO[name].copy()
else:
func_info = {}
if not 'type' in func_info:
func_info['type'] = ''
return func_info
def Log(self, msg):
"""Prints something if verbose is true."""
......@@ -7008,22 +7016,6 @@ class GLGenerator(object):
file.Write("} // namespace gpu\n")
file.Write("\n")
def ParseArgs(self, arg_string):
"""Parses a function arg string."""
args = []
num_pointer_args = 0
parts = arg_string.split(',')
is_gl_enum = False
for arg_string in parts:
if arg_string.startswith('GLenum '):
is_gl_enum = True
arg = CreateArg(arg_string)
if arg:
args.append(arg)
if arg.IsPointer():
num_pointer_args += 1
return (args, num_pointer_args, is_gl_enum)
def ParseGLH(self, filename):
"""Parses the cmd_buffer_functions.txt file and extracts the functions"""
f = open(filename, "r")
......@@ -7034,29 +7026,26 @@ class GLGenerator(object):
if match:
func_name = match.group(2)[2:]
func_info = self.GetFunctionInfo(func_name)
if func_info.type != 'Noop':
return_type = match.group(1).strip()
arg_string = match.group(3)
(args, num_pointer_args, is_gl_enum) = self.ParseArgs(arg_string)
# comment in to find out which functions use bare enums.
# if is_gl_enum:
# self.Log("%s uses bare GLenum" % func_name)
args_for_cmds = args
if hasattr(func_info, 'cmd_args'):
(args_for_cmds, num_pointer_args, is_gl_enum) = (
self.ParseArgs(getattr(func_info, 'cmd_args')))
cmd_args = []
for arg in args_for_cmds:
arg.AddCmdArgs(cmd_args)
init_args = []
for arg in args_for_cmds:
arg.AddInitArgs(init_args)
return_arg = CreateArg(return_type + " result")
if return_arg:
init_args.append(return_arg)
f = Function(func_name, func_name, func_info, return_type, args,
args_for_cmds, cmd_args, init_args, num_pointer_args)
if func_info['type'] == 'Noop':
continue
parsed_func_info = {
'original_name': func_name,
'original_args': match.group(3),
'return_type': match.group(1).strip(),
}
for k in parsed_func_info.keys():
if not k in func_info:
func_info[k] = parsed_func_info[k]
f = Function(func_name, func_info)
self.original_functions.append(f)
#for arg in f.GetOriginalArgs():
# if not isinstance(arg, EnumArgument) and arg.type == 'GLenum':
# self.Log("%s uses bare GLenum %s." % (func_name, arg.name))
gen_cmd = f.GetInfo('gen_cmd')
if gen_cmd == True or gen_cmd == None:
self.AddFunction(f)
......@@ -7073,7 +7062,7 @@ class GLGenerator(object):
self.Log("Non Auto Generated Functions: %d" % len(funcs))
for f in funcs:
self.Log(" %-10s %-20s gl%s" % (f.info.type, f.return_type, f.name))
self.Log(" %-10s %-20s gl%s" % (f.info['type'], f.return_type, f.name))
def WriteCommandIds(self, filename):
"""Writes the command buffer format"""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment