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 = [ ...@@ -1213,8 +1213,11 @@ _PEPPER_INTERFACES = [
{'name': 'DrawBuffers', 'dev': True}, {'name': 'DrawBuffers', 'dev': True},
] ]
# This table specifies types and other special data for the commands that # A function info object specifies the type and other special data for the
# will be generated. # 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". # 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) { ...@@ -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))) 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(" if (data_size > immediate_data_size) {\n")
file.Write(" return error::kOutOfBounds;\n") file.Write(" return error::kOutOfBounds;\n")
file.Write(" }\n") file.Write(" }\n")
...@@ -5099,7 +5102,7 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs%(arg_index)d_%(value_index)d) { ...@@ -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))) 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(" if (data_size > immediate_data_size) {\n")
file.Write(" return error::kOutOfBounds;\n") file.Write(" return error::kOutOfBounds;\n")
file.Write(" }\n") file.Write(" }\n")
...@@ -5773,18 +5776,6 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs) { ...@@ -5773,18 +5776,6 @@ TEST_P(%(test_name)s, %(name)sInvalidArgs) {
"""Overrriden from TypeHandler.""" """Overrriden from TypeHandler."""
pass 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): class Argument(object):
"""A class that represents a function argument.""" """A class that represents a function argument."""
...@@ -5960,7 +5951,7 @@ class SizeArgument(Argument): ...@@ -5960,7 +5951,7 @@ class SizeArgument(Argument):
def GetNumInvalidValues(self, func): def GetNumInvalidValues(self, func):
"""overridden from Argument.""" """overridden from Argument."""
if func.is_immediate: if func.IsImmediate():
return 0 return 0
return 1 return 1
...@@ -6389,35 +6380,102 @@ class ResourceIdZeroArgument(Argument): ...@@ -6389,35 +6380,102 @@ class ResourceIdZeroArgument(Argument):
class Function(object): class Function(object):
"""A class that represents a function.""" """A class that represents a function."""
def __init__(self, original_name, name, info, return_type, original_args, type_handlers = {
args_for_cmds, cmd_args, init_args, num_pointer_args): '': 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.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.info = info
self.type_handler = info.type_handler self.type_handler = self.type_handlers[info['type']]
self.return_type = return_type self.can_auto_generate = (self.num_pointer_args == 0 and
self.original_args = original_args info['return_type'] == "void")
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.InitFunction() 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): def IsType(self, type_name):
"""Returns true if function is a certain type.""" """Returns true if function is a certain type."""
return self.info.type == type_name return self.info['type'] == type_name
def InitFunction(self): 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) 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.""" """Returns a value from the function info for this function."""
if hasattr(self.info, name): if name in self.info:
return getattr(self.info, name) return self.info[name]
return None return default
def GetValidArg(self, index): def GetValidArg(self, index):
"""Gets a valid arg from the function info if one exists.""" """Gets a valid arg from the function info if one exists."""
...@@ -6428,7 +6486,7 @@ class Function(object): ...@@ -6428,7 +6486,7 @@ class Function(object):
def AddInfo(self, name, value): def AddInfo(self, name, value):
"""Adds an info.""" """Adds an info."""
setattr(self.info, name, value) self.info[name] = value
def IsCoreGLFunction(self): def IsCoreGLFunction(self):
return (not self.GetInfo('extension') and return (not self.GetInfo('extension') and
...@@ -6570,11 +6628,10 @@ class Function(object): ...@@ -6570,11 +6628,10 @@ class Function(object):
def WriteCmdFlag(self, file): def WriteCmdFlag(self, file):
"""Writes the cmd cmd_flags constant.""" """Writes the cmd cmd_flags constant."""
flags = [] flags = []
trace_level = 3 # By default trace only at the highest level # By default trace only at the highest level 3.
if hasattr(self.info, 'trace_level'): trace_level = int(self.GetInfo('trace_level', default = 3))
if (self.info.trace_level < 0) or (self.info.trace_level > 3): if trace_level not in xrange(0, 4):
raise KeyError("Unhandled trace_level: %d" % self.info.trace_level) raise KeyError("Unhandled trace_level: %d" % trace_level)
trace_level = self.info.trace_level
flags.append('CMD_FLAG_SET_TRACE_LEVEL(%d)' % trace_level) flags.append('CMD_FLAG_SET_TRACE_LEVEL(%d)' % trace_level)
...@@ -6728,36 +6785,34 @@ class ImmediateFunction(Function): ...@@ -6728,36 +6785,34 @@ class ImmediateFunction(Function):
"""A class that represnets an immediate function command.""" """A class that represnets an immediate function command."""
def __init__(self, func): def __init__(self, func):
new_args = [] Function.__init__(
for arg in func.GetOriginalArgs(): 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() new_arg = arg.GetImmediateVersion()
if new_arg: 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 = [] new_args_for_cmds = []
for arg in func.args_for_cmds: for arg in self.args_for_cmds:
new_arg = arg.GetImmediateVersion() new_arg = arg.GetImmediateVersion()
if new_arg: if new_arg:
new_args_for_cmds.append(new_arg) new_args_for_cmds.append(new_arg)
new_arg.AddCmdArgs(cmd_args)
new_init_args = [] self.args_for_cmds = new_args_for_cmds
for arg in new_args_for_cmds:
arg.AddInitArgs(new_init_args)
Function.__init__( Function.InitFunction(self)
self,
func.original_name, def IsImmediate(self):
"%sImmediate" % func.name, return True
func.info,
func.return_type,
new_args,
new_args_for_cmds,
cmd_args,
new_init_args,
0)
self.is_immediate = True
def WriteCommandDescription(self, file): def WriteCommandDescription(self, file):
"""Overridden from Function""" """Overridden from Function"""
...@@ -6813,39 +6868,31 @@ class BucketFunction(Function): ...@@ -6813,39 +6868,31 @@ class BucketFunction(Function):
"""A class that represnets a bucket version of a function command.""" """A class that represnets a bucket version of a function command."""
def __init__(self, func): def __init__(self, func):
new_args = [] Function.__init__(
for arg in func.GetOriginalArgs(): 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() new_arg = arg.GetBucketVersion()
if new_arg: 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 = [] new_args_for_cmds = []
for arg in func.args_for_cmds: for arg in self.args_for_cmds:
new_arg = arg.GetBucketVersion() new_arg = arg.GetBucketVersion()
if new_arg: if new_arg:
new_args_for_cmds.append(new_arg) new_args_for_cmds.append(new_arg)
new_arg.AddCmdArgs(cmd_args)
new_init_args = [] self.args_for_cmds = new_args_for_cmds
for arg in new_args_for_cmds:
arg.AddInitArgs(new_init_args)
Function.__init__( Function.InitFunction(self)
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
def WriteCommandDescription(self, file): def WriteCommandDescription(self, file):
"""Overridden from Function""" """Overridden from Function"""
...@@ -6919,45 +6966,9 @@ class GLGenerator(object): ...@@ -6919,45 +6966,9 @@ class GLGenerator(object):
self.functions = [] self.functions = []
self.verbose = verbose self.verbose = verbose
self.errors = 0 self.errors = 0
self._function_info = {}
self._empty_type_handler = TypeHandler()
self._empty_function_info = FunctionInfo({}, self._empty_type_handler)
self.pepper_interfaces = [] self.pepper_interfaces = []
self.interface_info = {} 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: for interface in _PEPPER_INTERFACES:
interface = PepperInterface(interface) interface = PepperInterface(interface)
self.pepper_interfaces.append(interface) self.pepper_interfaces.append(interface)
...@@ -6967,20 +6978,17 @@ class GLGenerator(object): ...@@ -6967,20 +6978,17 @@ class GLGenerator(object):
"""Adds a function.""" """Adds a function."""
self.functions.append(func) 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): def GetFunctionInfo(self, name):
"""Gets a type info for the given function name.""" """Gets a type info for the given function name."""
if name in self._function_info: if name in _FUNCTION_INFO:
return self._function_info[name] func_info = _FUNCTION_INFO[name].copy()
return self._empty_function_info else:
func_info = {}
if not 'type' in func_info:
func_info['type'] = ''
return func_info
def Log(self, msg): def Log(self, msg):
"""Prints something if verbose is true.""" """Prints something if verbose is true."""
...@@ -7008,22 +7016,6 @@ class GLGenerator(object): ...@@ -7008,22 +7016,6 @@ class GLGenerator(object):
file.Write("} // namespace gpu\n") file.Write("} // namespace gpu\n")
file.Write("\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): def ParseGLH(self, filename):
"""Parses the cmd_buffer_functions.txt file and extracts the functions""" """Parses the cmd_buffer_functions.txt file and extracts the functions"""
f = open(filename, "r") f = open(filename, "r")
...@@ -7034,29 +7026,26 @@ class GLGenerator(object): ...@@ -7034,29 +7026,26 @@ class GLGenerator(object):
if match: if match:
func_name = match.group(2)[2:] func_name = match.group(2)[2:]
func_info = self.GetFunctionInfo(func_name) func_info = self.GetFunctionInfo(func_name)
if func_info.type != 'Noop': if func_info['type'] == 'Noop':
return_type = match.group(1).strip() continue
arg_string = match.group(3)
(args, num_pointer_args, is_gl_enum) = self.ParseArgs(arg_string) parsed_func_info = {
# comment in to find out which functions use bare enums. 'original_name': func_name,
# if is_gl_enum: 'original_args': match.group(3),
# self.Log("%s uses bare GLenum" % func_name) 'return_type': match.group(1).strip(),
args_for_cmds = args }
if hasattr(func_info, 'cmd_args'):
(args_for_cmds, num_pointer_args, is_gl_enum) = ( for k in parsed_func_info.keys():
self.ParseArgs(getattr(func_info, 'cmd_args'))) if not k in func_info:
cmd_args = [] func_info[k] = parsed_func_info[k]
for arg in args_for_cmds:
arg.AddCmdArgs(cmd_args) f = Function(func_name, func_info)
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)
self.original_functions.append(f) 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') gen_cmd = f.GetInfo('gen_cmd')
if gen_cmd == True or gen_cmd == None: if gen_cmd == True or gen_cmd == None:
self.AddFunction(f) self.AddFunction(f)
...@@ -7073,7 +7062,7 @@ class GLGenerator(object): ...@@ -7073,7 +7062,7 @@ class GLGenerator(object):
self.Log("Non Auto Generated Functions: %d" % len(funcs)) self.Log("Non Auto Generated Functions: %d" % len(funcs))
for f in 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): def WriteCommandIds(self, filename):
"""Writes the command buffer format""" """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