def _postprocessEvent(event, logDir): # Process the render surface if there is one if "render_surface_width" in event.sensorData and "render_surface_height" in event.sensorData: try: _processRenderSurface(logDir, event.sensorData) except Exception, e: Log.error("Unable to load render surface for event %s(%d): %s" % (event.name, event.seq, e))
def _processRenderSurface(logDir, attributes): def attr(name): return attributes[name] w, h = attr("render_surface_width"), attr("render_surface_height") redMask = attr("red_mask") greenMask = attr("green_mask") blueMask = attr("blue_mask") alphaMask = attr("alpha_mask") depthMask = attr("depth_mask") stencilMask = attr("stencil_mask") isLinear = attr("is_linear") isPremultiplied = attr("is_premultiplied") # Convert the color buffer if "color_buffer" in attributes: fileName = attr("color_buffer") if not os.path.exists(fileName): fileName = os.path.join(logDir, fileName) fileNameOut = fileName.rsplit(".", 1)[0] + ".png" # Only do the conversion if the image doesn't already exist # or if the source file is newer. if fileName.endswith(".dat") and \ (not os.path.exists(fileNameOut) or \ (os.path.exists(fileName) and os.path.getmtime(fileName) > os.path.getmtime(fileNameOut)) ): stride = attr("color_stride") f = open(fileName, "rb") data = f.read(stride * h) f.close() if len(data) != h * stride or not data: Log.error("Invalid color buffer data size: %d" % len(data)) return colorBuffer = Graphics.decodeImageData(data, (w, h), stride, redMask, greenMask, blueMask, alphaMask, isLinear, isPremultiplied) colorBuffer = colorBuffer.convert("RGBA") colorBuffer.save(fileNameOut) # We can remove the original file now os.unlink(fileName) # Replace the original file name with the decoded file attributes["color_buffer"] = fileNameOut # Eat the render surface attributes since they are of little use further down the road #for attrName in ["red_mask", "green_mask", "blue_mask", "alpha_mask", # "depth_mask", "stencil_mask", "color_stride", # "is_linear", "is_premultiplied", "color_data_type", # "depth_data_type", "stencil_data_type"]: # if attrName in attributes: # del attributes[attrName] for bufferName in ["depth_buffer", "stencil_buffer"]: if bufferName in attributes and not os.path.exists(attributes[bufferName]): # Fill in the full buffer file name attributes[bufferName] = os.path.join(logDir, attr(bufferName))
def collectItem(self, targetPath, item): Tools.makePath(targetPath) path = self.config.getRelativePath(item) if not os.path.exists(path): Log.error("Project file '%s' not found." % path) return if not int(item.attrs.get("copy", 1)): return path name = os.path.basename(path) shutil.copyfile(path, os.path.join(targetPath, name)) return name
def generate(templates, namespace, outputFile = sys.stdout): """ Process a list of templates and write the result to a file object. @param templates: A list of templates to process @param namespace: A dictionary of objects that the templates may access @param outputFile: Output file object. """ def processTemplate(inputFile, outputFile, searchList): t = Template(file = inputFile, searchList = searchList) outputFile.write(str(t)) def process(templateName): processTemplate(open(templateName), outputFile, namespace) for template in templates: try: process(template) except Exception, e: Log.error("Exception while processing template '%s': %s" % (template, e)) raise
def getAvailablePluginModules(pluginPath = None): """ Determine the available plugin modules on the system. @returns a list of found plugins """ if pluginPath is None: pluginPath = Resource.getPath("plugins", required = True) if pluginPath is None: return [] if not pluginPath in sys.path: sys.path.append(pluginPath) plugins = [] for name in os.listdir(pluginPath): try: if os.path.isfile(os.path.join(pluginPath, name, "__init__.py")): plugins.append(__import__(name)) except ImportError, e: Log.error("Unable to load plugin %s: %s" % (name, e))
def getAvailablePluginModules(pluginPath=None): """ Determine the available plugin modules on the system. @returns a list of found plugins """ if pluginPath is None: pluginPath = Resource.getPath("plugins", required=True) if pluginPath is None: return [] if not pluginPath in sys.path: sys.path.append(pluginPath) plugins = [] for name in os.listdir(pluginPath): try: if os.path.isfile(os.path.join(pluginPath, name, "__init__.py")): plugins.append(__import__(name)) except ImportError, e: Log.error("Unable to load plugin %s: %s" % (name, e))
def generate(templates, namespace, outputFile=sys.stdout): """ Process a list of templates and write the result to a file object. @param templates: A list of templates to process @param namespace: A dictionary of objects that the templates may access @param outputFile: Output file object. """ def processTemplate(inputFile, outputFile, searchList): t = Template(file=inputFile, searchList=searchList) outputFile.write(str(t)) def process(templateName): processTemplate(open(templateName), outputFile, namespace) for template in templates: try: process(template) except Exception, e: Log.error("Exception while processing template '%s': %s" % (template, e)) raise
def reportError(self, msg): for line in str(msg).rstrip().split("\n"): Log.error(line)
def fail(reason): Log.error(reason) sys.exit(1)
def _processRenderSurface(logDir, attributes): def attr(name): return attributes[name] w, h = attr("render_surface_width"), attr("render_surface_height") redMask = attr("red_mask") greenMask = attr("green_mask") blueMask = attr("blue_mask") alphaMask = attr("alpha_mask") depthMask = attr("depth_mask") stencilMask = attr("stencil_mask") isLinear = attr("is_linear") isPremultiplied = attr("is_premultiplied") # Convert the color buffer if "color_buffer" in attributes: fileName = attr("color_buffer") if not os.path.exists(fileName): fileName = os.path.join(logDir, fileName) fileNameOut = fileName.rsplit(".", 1)[0] + ".png" # Only do the conversion if the image doesn't already exist # or if the source file is newer. if fileName.endswith(".dat") and \ (not os.path.exists(fileNameOut) or \ (os.path.exists(fileName) and os.path.getmtime(fileName) > os.path.getmtime(fileNameOut)) ): stride = attr("color_stride") f = open(fileName, "rb") data = f.read(stride * h) f.close() if len(data) != h * stride or not data: Log.error("Invalid color buffer data size: %d" % len(data)) return colorBuffer = Graphics.decodeImageData(data, (w, h), stride, redMask, greenMask, blueMask, alphaMask, isLinear, isPremultiplied) colorBuffer = colorBuffer.convert("RGBA") colorBuffer.save(fileNameOut) # We can remove the original file now os.unlink(fileName) # Replace the original file name with the decoded file attributes["color_buffer"] = fileNameOut # Eat the render surface attributes since they are of little use further down the road #for attrName in ["red_mask", "green_mask", "blue_mask", "alpha_mask", # "depth_mask", "stencil_mask", "color_stride", # "is_linear", "is_premultiplied", "color_data_type", # "depth_data_type", "stencil_data_type"]: # if attrName in attributes: # del attributes[attrName] for bufferName in ["depth_buffer", "stencil_buffer"]: if bufferName in attributes and not os.path.exists( attributes[bufferName]): # Fill in the full buffer file name attributes[bufferName] = os.path.join(logDir, attr(bufferName))
def fail(self, reason): msg = "Target '%s' failed: %s" % (self.name, reason) Log.error(msg) raise RuntimeError(msg)
def prepare(self): # Shorthand for various objects config = self.config lib = self.library # Parse the sources for fileName in config.get("apiheaders", []): Log.notice("Parsing functions from '%s'." % fileName) source = self.parserTool.readSource(fileName) newLib = Parser.parseSource(source) for f in newLib.functions.values(): f.headerName = fileName for f in newLib.functions.values(): Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join(["%s %s" % (t.type, p) for p, t in f.parameters.items()]))) if not newLib.functions: Log.warn("No new functions found.") else: Log.notice("%d functions found." % len(newLib.functions)) lib.merge(newLib) # Load the hooks self.parserTool.loadHooks() def parseBool(s): return bool(int(s)) # Read the typemap for typeDecl, mapping in self.config.types.items(): attrs = self.config.types[typeDecl].attrs name, type = Parser.parseVariableDeclaration(typeDecl + " dummy") assert name == "dummy" # If this is a class mapping, create the class if it doesn't already exist if mapping == "object": if not mapping in self.library.classes: cls = Library.Class(type) if "namespace" in attrs: cls.namespacePath = attrs["namespace"].split(".") self.library.classes[type] = cls # Patch the default decoration hint into all matching types if "decorationhint" in attrs: for function in self.library.functions.values(): for t in [p.type for p in function.parameters.values()] + [function.type]: if t == type: t.decorationHint = attrs["decorationhint"] self.library.typeMap[type] = str(mapping) # Patch in some function-specific attributes for function in config.functions.keys(): if not function in lib.functions: self.fail("Attributes specified for non-existent function '%s'." % function) attrs = config.functions[function].attrs if "terminator" in attrs: lib.functions[function].isTerminator = parseBool(attrs["terminator"]) if "generate" in attrs: lib.functions[function].generate = parseBool(attrs["generate"]) if "runtimestate" in attrs: lib.functions[function].runtimeStateTracking = parseBool(attrs["runtimestate"]) if "framemarker" in attrs: lib.functions[function].isFrameMarker = parseBool(attrs["framemarker"]) if "staticlinkage" in attrs: lib.functions[function].staticLinkage = parseBool(attrs["staticlinkage"]) if "rendercall" in attrs: lib.functions[function].isRenderCall = parseBool(attrs["rendercall"]) if "passthrough" in attrs: lib.functions[function].passthrough = parseBool(attrs["passthrough"]) if not isinstance(config.functions[function], Config.Group): self.fail("Syntax error: State map definition for function '%s' is missing braces." % function) # Argument to state mapping reservedNames = ["@return", "@modify", "@set", "@get", "@copy"] funcAttrs = attrs for arg, parameter in config.functions[function].items(): # Check that this is a valid parameter if not arg in reservedNames and not arg in lib.functions[function].parameters: self.fail("State mapping for nonexistent parameter '%s' of function '%s' specified." % (arg, function)) if arg in ["@copy"] and parseBool(funcAttrs.get("runtimestate", "0")): Log.warn("Function %s state relation %s not implemented for runtime state tracking." % (function, arg)) # Read the parameter-specific attributes attrs = config.functions[function][arg].attrs if "decoration" in attrs: lib.functions[function].parameters[arg].decoration = attrs["decoration"] if "decorationhint" in attrs: lib.functions[function].parameters[arg].decorationHint = attrs["decorationhint"] if "out" in attrs: lib.functions[function].parameters[arg].isOut = parseBool(attrs["out"]) if "object_class" in attrs: # Create a function-local type so that this parameter type is an object only for this function if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # Override the type's name so that it will refer to the new object class # while still using the original C type under the hood newType = copy.deepcopy(type) newType.isObject = True newType.name = attrs["object_class"] if arg == "@return": lib.functions[function].type = newType else: lib.functions[function].parameters[arg].type = newType # Check that this class exists classType = Library.Type(attrs["object_class"]) if not classType in self.library.classes: self.fail("Undefined object class '%s'." % classType) # Do we have a meta type? if "metatype" in config.functions[function][arg]: metaGroup = config.functions[function][arg].metatype try: metaType = Library.MetaType(metaGroup.attrs["class"]) except KeyError: self.fail("Meta type for parameter '%s' does not define class." % arg) # Is this an array parameter? if metaType.name == "array": metaType.values["size"] = Library.MetaValue("size", metaGroup.attrs.get("size", 1)) if "type" in metaGroup.attrs: metaType.values["type"] = Library.MetaValue("type", metaGroup.attrs["type"]) if metaGroup.attrs["type"] == "object": if not "object_class" in metaGroup.attrs: self.fail("Required metatype attribute object_class missing") metaType.values["object_class"] = Library.MetaValue("object_class", metaGroup.attrs["object_class"]) # How about an image parameter? elif metaType.name == "image": metaType.values["stride"] = Library.MetaValue("stride", metaGroup.attrs.get("stride", "width")) metaType.values["height"] = Library.MetaValue("height", metaGroup.attrs.get("height", "height")) metaType.values["components"] = Library.MetaValue("components", metaGroup.attrs.get("components", "1")) metaType.values["type"] = Library.MetaValue("type", metaGroup.attrs.get("type", "byte")) else: self.fail("Unknown meta type class '%s'." % metaclass) Log.debug("Meta type: %s.%s: %s" % (function, arg, metaType.name)) # Get the conditions for different meta values if isinstance(metaGroup, Config.List): for item in metaGroup: predicate = item.attrs["condition"] predicateValue = item.attrs["value"] result = item.attrs["result"] metaType.values[item].addPredicate(predicate, predicateValue, result) Log.debug("Meta type condition: If %s is %s, then %s = %s" % (predicate, predicateValue, item, result)) elif isinstance(metaGroup, Config.Group): Log.error("Meta type variations for parameter '%s' represented in a group instead of a list." % arg) # Record the meta type lib.functions[function].parameters[arg].metaType = metaType # Is this a short-hand state mapping? try: path = parameter.split(".") except AttributeError: # Try the expanded form of a nested attribute set try: path = (config.functions[function][arg].state).split(".") except AttributeError: path = [] # Check that we even have a state structure if path and not "state" in config: Log.warn("State structure not defined.") continue # Parse special state mapping relations relation = None checkPaths = [] if arg == "@copy": relation = Library.StateRelationCopy(attrs["src"].split("."), attrs["dest"].split(".")) checkPaths = [relation.sourcePath, relation.destPath] elif arg == "@get": relation = Library.StateRelationGet(path) checkPaths = [relation.path] elif arg == "@set": relation = Library.StateRelationSet(path) checkPaths = [relation.path] elif arg == "@modify": relation = Library.StateRelationModify(path) checkPaths = [relation.path] # Empty mapping? elif not "".join(path): continue if relation: for path in checkPaths: if traverseStatePath(config, path) is None: self.fail("Relation state path '%s' for function '%s' does not exist." % (".".join(path), function)) Log.debug("State relation: %s %s" % (function, relation)) lib.functions[function].stateRelations.append(relation) continue Log.debug("State mapping: %s.%s -> %s" % (function, arg, ".".join(path))) # Determine the parameter type type = None if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # If this is a runtime mapping, check that the parameter is of a supported type if lib.functions[function].runtimeStateTracking and type and \ lib.getNativeType(type) in ["float", "double"]: self.fail("Values of type '%s' can not be saved to the runtime state tree" % type) continue node = traverseStatePath(config, path) if node is None: self.fail("State path '%s' for function '%s' does not exist." % (".".join(path), function)) # Save the mapping if arg == "@return": lib.functions[function].retStateRelation = Library.StateRelationSet(path) else: lib.functions[function].parameters[arg].stateRelation = Library.StateRelationSet(path)
def prepare(self): # Shorthand for various objects config = self.config lib = self.library # Parse the sources for fileName in config.get("apiheaders", []): Log.notice("Parsing functions from '%s'." % fileName) source = self.parserTool.readSource(fileName) newLib = Parser.parseSource(source) for f in newLib.functions.values(): f.headerName = fileName for f in newLib.functions.values(): Log.debug("%s %s(%s)" % (f.type, f.name, ", ".join( ["%s %s" % (t.type, p) for p, t in f.parameters.items()]))) if not newLib.functions: Log.warn("No new functions found.") else: Log.notice("%d functions found." % len(newLib.functions)) lib.merge(newLib) # Load the hooks self.parserTool.loadHooks() def parseBool(s): return bool(int(s)) # Read the typemap for typeDecl, mapping in self.config.types.items(): attrs = self.config.types[typeDecl].attrs name, type = Parser.parseVariableDeclaration(typeDecl + " dummy") assert name == "dummy" # If this is a class mapping, create the class if it doesn't already exist if mapping == "object": if not mapping in self.library.classes: cls = Library.Class(type) if "namespace" in attrs: cls.namespacePath = attrs["namespace"].split(".") self.library.classes[type] = cls # Patch the default decoration hint into all matching types if "decorationhint" in attrs: for function in self.library.functions.values(): for t in [p.type for p in function.parameters.values() ] + [function.type]: if t == type: t.decorationHint = attrs["decorationhint"] self.library.typeMap[type] = str(mapping) # Patch in some function-specific attributes for function in config.functions.keys(): if not function in lib.functions: self.fail( "Attributes specified for non-existent function '%s'." % function) attrs = config.functions[function].attrs if "terminator" in attrs: lib.functions[function].isTerminator = parseBool( attrs["terminator"]) if "generate" in attrs: lib.functions[function].generate = parseBool(attrs["generate"]) if "runtimestate" in attrs: lib.functions[function].runtimeStateTracking = parseBool( attrs["runtimestate"]) if "framemarker" in attrs: lib.functions[function].isFrameMarker = parseBool( attrs["framemarker"]) if "staticlinkage" in attrs: lib.functions[function].staticLinkage = parseBool( attrs["staticlinkage"]) if "rendercall" in attrs: lib.functions[function].isRenderCall = parseBool( attrs["rendercall"]) if "passthrough" in attrs: lib.functions[function].passthrough = parseBool( attrs["passthrough"]) if not isinstance(config.functions[function], Config.Group): self.fail( "Syntax error: State map definition for function '%s' is missing braces." % function) # Argument to state mapping reservedNames = ["@return", "@modify", "@set", "@get", "@copy"] funcAttrs = attrs for arg, parameter in config.functions[function].items(): # Check that this is a valid parameter if not arg in reservedNames and not arg in lib.functions[ function].parameters: self.fail( "State mapping for nonexistent parameter '%s' of function '%s' specified." % (arg, function)) if arg in ["@copy"] and parseBool( funcAttrs.get("runtimestate", "0")): Log.warn( "Function %s state relation %s not implemented for runtime state tracking." % (function, arg)) # Read the parameter-specific attributes attrs = config.functions[function][arg].attrs if "decoration" in attrs: lib.functions[function].parameters[arg].decoration = attrs[ "decoration"] if "decorationhint" in attrs: lib.functions[function].parameters[ arg].decorationHint = attrs["decorationhint"] if "out" in attrs: lib.functions[function].parameters[arg].isOut = parseBool( attrs["out"]) if "object_class" in attrs: # Create a function-local type so that this parameter type is an object only for this function if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # Override the type's name so that it will refer to the new object class # while still using the original C type under the hood newType = copy.deepcopy(type) newType.isObject = True newType.name = attrs["object_class"] if arg == "@return": lib.functions[function].type = newType else: lib.functions[function].parameters[arg].type = newType # Check that this class exists classType = Library.Type(attrs["object_class"]) if not classType in self.library.classes: self.fail("Undefined object class '%s'." % classType) # Do we have a meta type? if "metatype" in config.functions[function][arg]: metaGroup = config.functions[function][arg].metatype try: metaType = Library.MetaType(metaGroup.attrs["class"]) except KeyError: self.fail( "Meta type for parameter '%s' does not define class." % arg) # Is this an array parameter? if metaType.name == "array": metaType.values["size"] = Library.MetaValue( "size", metaGroup.attrs.get("size", 1)) if "type" in metaGroup.attrs: metaType.values["type"] = Library.MetaValue( "type", metaGroup.attrs["type"]) if metaGroup.attrs["type"] == "object": if not "object_class" in metaGroup.attrs: self.fail( "Required metatype attribute object_class missing" ) metaType.values[ "object_class"] = Library.MetaValue( "object_class", metaGroup.attrs["object_class"]) # How about an image parameter? elif metaType.name == "image": metaType.values["stride"] = Library.MetaValue( "stride", metaGroup.attrs.get("stride", "width")) metaType.values["height"] = Library.MetaValue( "height", metaGroup.attrs.get("height", "height")) metaType.values["components"] = Library.MetaValue( "components", metaGroup.attrs.get("components", "1")) metaType.values["type"] = Library.MetaValue( "type", metaGroup.attrs.get("type", "byte")) else: self.fail("Unknown meta type class '%s'." % metaclass) Log.debug("Meta type: %s.%s: %s" % (function, arg, metaType.name)) # Get the conditions for different meta values if isinstance(metaGroup, Config.List): for item in metaGroup: predicate = item.attrs["condition"] predicateValue = item.attrs["value"] result = item.attrs["result"] metaType.values[item].addPredicate( predicate, predicateValue, result) Log.debug( "Meta type condition: If %s is %s, then %s = %s" % (predicate, predicateValue, item, result)) elif isinstance(metaGroup, Config.Group): Log.error( "Meta type variations for parameter '%s' represented in a group instead of a list." % arg) # Record the meta type lib.functions[function].parameters[arg].metaType = metaType # Is this a short-hand state mapping? try: path = parameter.split(".") except AttributeError: # Try the expanded form of a nested attribute set try: path = ( config.functions[function][arg].state).split(".") except AttributeError: path = [] # Check that we even have a state structure if path and not "state" in config: Log.warn("State structure not defined.") continue # Parse special state mapping relations relation = None checkPaths = [] if arg == "@copy": relation = Library.StateRelationCopy( attrs["src"].split("."), attrs["dest"].split(".")) checkPaths = [relation.sourcePath, relation.destPath] elif arg == "@get": relation = Library.StateRelationGet(path) checkPaths = [relation.path] elif arg == "@set": relation = Library.StateRelationSet(path) checkPaths = [relation.path] elif arg == "@modify": relation = Library.StateRelationModify(path) checkPaths = [relation.path] # Empty mapping? elif not "".join(path): continue if relation: for path in checkPaths: if traverseStatePath(config, path) is None: self.fail( "Relation state path '%s' for function '%s' does not exist." % (".".join(path), function)) Log.debug("State relation: %s %s" % (function, relation)) lib.functions[function].stateRelations.append(relation) continue Log.debug("State mapping: %s.%s -> %s" % (function, arg, ".".join(path))) # Determine the parameter type type = None if arg == "@return": type = lib.functions[function].type else: type = lib.functions[function].parameters[arg].type # If this is a runtime mapping, check that the parameter is of a supported type if lib.functions[function].runtimeStateTracking and type and \ lib.getNativeType(type) in ["float", "double"]: self.fail( "Values of type '%s' can not be saved to the runtime state tree" % type) continue node = traverseStatePath(config, path) if node is None: self.fail( "State path '%s' for function '%s' does not exist." % (".".join(path), function)) # Save the mapping if arg == "@return": lib.functions[ function].retStateRelation = Library.StateRelationSet( path) else: lib.functions[function].parameters[ arg].stateRelation = Library.StateRelationSet(path)