From 468c9775cbc863b024f41fccad3d6bb967e10ea8 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 14 Aug 2008 11:00:22 +0100 Subject: python/retrace: Application capable of replaying gallium traces. At the moment it is capable of replaying trivial/tri kind of apps. See README for status. --- src/gallium/state_trackers/python/retrace/README | 18 + .../state_trackers/python/retrace/interpreter.py | 418 +++++++++++++++++++++ src/gallium/state_trackers/python/retrace/model.py | 151 ++++++++ .../state_trackers/python/retrace/parser.py | 332 ++++++++++++++++ 4 files changed, 919 insertions(+) create mode 100644 src/gallium/state_trackers/python/retrace/README create mode 100755 src/gallium/state_trackers/python/retrace/interpreter.py create mode 100755 src/gallium/state_trackers/python/retrace/model.py create mode 100755 src/gallium/state_trackers/python/retrace/parser.py (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/README b/src/gallium/state_trackers/python/retrace/README new file mode 100644 index 0000000000..c0ad8ae6c1 --- /dev/null +++ b/src/gallium/state_trackers/python/retrace/README @@ -0,0 +1,18 @@ +This is + + +To use it follow the instructions in src/gallium/drivers/trace/README and +src/gallium/state_trackers/python/README, and then do + + python src/gallium/state_trackers/python/samples/retrace/interpreter.py filename.trace + + + + +This is still work in progress: +- not everything is captured/replayed + - surface/textures contents +- any tiny error will result in a crash + +-- +Jose Fonseca diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py new file mode 100755 index 0000000000..ae62bc04a8 --- /dev/null +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -0,0 +1,418 @@ +#!/usr/bin/env python +############################################################################# +# +# Copyright 2008 Tungsten Graphics, Inc. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# +############################################################################# + + +import sys +import gallium +import model +from parser import TraceParser + + +def make_image(surface): + pixels = gallium.FloatArray(surface.height*surface.width*4) + surface.get_tile_rgba(0, 0, surface.width, surface.height, pixels) + + import Image + outimage = Image.new( + mode='RGB', + size=(surface.width, surface.height), + color=(0,0,0)) + outpixels = outimage.load() + for y in range(0, surface.height): + for x in range(0, surface.width): + offset = (y*surface.width + x)*4 + r, g, b, a = [int(pixels[offset + ch]*255) for ch in range(4)] + outpixels[x, y] = r, g, b + return outimage + +def save_image(filename, surface): + outimage = make_image(surface) + outimage.save(filename, "PNG") + +def show_image(surface): + outimage = make_image(surface) + + import Tkinter as tk + from PIL import Image, ImageTk + root = tk.Tk() + + root.title('background image') + + image1 = ImageTk.PhotoImage(outimage) + w = image1.width() + h = image1.height() + x = 100 + y = 100 + root.geometry("%dx%d+%d+%d" % (w, h, x, y)) + panel1 = tk.Label(root, image=image1) + panel1.pack(side='top', fill='both', expand='yes') + panel1.image = image1 + root.mainloop() + + + + +class Struct: + """C-like struct""" + + # A basic Python class can pass as a C-like structure + pass + + +struct_factories = { + "pipe_blend_color": gallium.BlendColor, + "pipe_blend_state": gallium.Blend, + "pipe_clip_state": gallium.Clip, + #"pipe_constant_buffer": gallium.ConstantBuffer, + "pipe_depth_state": gallium.Depth, + "pipe_stencil_state": gallium.Stencil, + "pipe_alpha_state": gallium.Alpha, + "pipe_depth_stencil_alpha_state": gallium.DepthStencilAlpha, + "pipe_format_block": gallium.FormatBlock, + #"pipe_framebuffer_state": gallium.Framebuffer, + "pipe_poly_stipple": gallium.PolyStipple, + "pipe_rasterizer_state": gallium.Rasterizer, + "pipe_sampler_state": gallium.Sampler, + "pipe_scissor_state": gallium.Scissor, + #"pipe_shader_state": gallium.Shader, + #"pipe_vertex_buffer": gallium.VertexBuffer, + "pipe_vertex_element": gallium.VertexElement, + "pipe_viewport_state": gallium.Viewport, + #"pipe_texture": gallium.Texture, +} + + +member_array_factories = { + "pipe_rasterizer_state": {"sprite_coord_mode": gallium.ByteArray}, + "pipe_poly_stipple": {"stipple": gallium.UnsignedArray}, + "pipe_viewport_state": {"scale": gallium.FloatArray, "translate": gallium.FloatArray}, + "pipe_clip_state": {"ucp": gallium.FloatArray}, + "pipe_depth_stencil_alpha_state": {"stencil": gallium.StencilArray}, + "pipe_blend_color": {"color": gallium.FloatArray}, +} + + +class Translator(model.Visitor): + """Translate model arguments into regular Python objects""" + + def __init__(self, interpreter): + self.interpreter = interpreter + self.result = None + + def visit(self, node): + self.result = None + node.visit(self) + return self.result + + def visit_literal(self, node): + self.result = node.value + + def visit_named_constant(self, node): + # lookup the named constant in the gallium module + self.result = getattr(gallium, node.name) + + def visit_array(self, node): + array = [] + for element in node.elements: + array.append(self.visit(element)) + self.result = array + + def visit_struct(self, node): + struct_factory = struct_factories.get(node.name, Struct) + struct = struct_factory() + for member_name, member_node in node.members: + member_value = self.visit(member_node) + try: + array_factory = member_array_factories[node.name][member_name] + except KeyError: + pass + else: + assert isinstance(member_value, list) + array = array_factory(len(member_value)) + for i in range(len(member_value)): + array[i] = member_value[i] + member_value = array + #print node.name, member_name, member_value + assert isinstance(struct, Struct) or hasattr(struct, member_name) + setattr(struct, member_name, member_value) + self.result = struct + + def visit_pointer(self, node): + self.result = self.interpreter.lookup_object(node.address) + + +class Object: + + def __init__(self, interpreter, real): + self.interpreter = interpreter + self.real = real + + +class Global(Object): + + def __init__(self, interpreter, real): + self.interpreter = interpreter + self.real = real + + def pipe_winsys_create(self): + return Winsys(self.interpreter, gallium.Device()) + + def pipe_screen_create(self, winsys): + return Screen(self.interpreter, winsys.real) + + def pipe_context_create(self, screen): + context = screen.real.context_create() + return Context(self.interpreter, context) + + +class Winsys(Object): + + def __init__(self, interpreter, real): + self.interpreter = interpreter + self.real = real + + def get_name(self): + pass + + def buffer_create(self, alignment, usage, size): + return self.real.buffer_create(size, alignment, usage) + + def buffer_destroy(self, buffer): + pass + + def buffer_write(self, buffer, data, size): + buffer.write(data, size) + buffer.write(data, size) + + +class Screen(Object): + + def get_name(self): + pass + + def get_vendor(self): + pass + + def get_param(self, param): + pass + + def get_paramf(self, param): + pass + + def is_format_supported(self, format, target, tex_usage, geom_flags): + return self.real.is_format_supported(format, target, tex_usage, geom_flags) + + def texture_create(self, template): + return self.real.texture_create( + format = template.format, + width = template.width[0], + height = template.height[0], + depth = template.depth[0], + last_level = template.last_level, + target = template.target, + tex_usage = template.tex_usage, + ) + + def texture_release(self, texture): + self.interpreter.unregister_object(texture) + + def get_tex_surface(self, texture, face, level, zslice, usage): + return texture.get_surface(face, level, zslice, usage) + + def tex_surface_release(self, surface): + self.interpreter.unregister_object(surface) + + def surface_map(self, surface, flags): + return None + + def surface_unmap(self, surface): + pass + + +class Context(Object): + + def __init__(self, interpreter, real): + Object.__init__(self, interpreter, real) + self.cbufs = [] + self.zsbuf = None + + def create_blend_state(self, state): + return state + + def bind_blend_state(self, state): + self.real.set_blend(state) + + def create_sampler_state(self, state): + return state + + def bind_sampler_states(self, n, states): + for i in range(n): + self.real.set_sampler(i, states[i]) + + def create_rasterizer_state(self, state): + return state + + def bind_rasterizer_state(self, state): + self.real.set_rasterizer(state) + + def create_depth_stencil_alpha_state(self, state): + return state + + def bind_depth_stencil_alpha_state(self, state): + self.real.set_depth_stencil_alpha(state) + + def create_fs_state(self, state): + tokens = str(state.tokens) + shader = gallium.Shader(tokens) + return shader + + create_vs_state = create_fs_state + + def bind_fs_state(self, state): + self.real.set_fragment_shader(state) + + def bind_vs_state(self, state): + self.real.set_vertex_shader(state) + + def set_blend_color(self, state): + self.real.set_blend_color(state) + + def set_clip_state(self, state): + self.real.set_clip(state) + + def set_constant_buffer(self, shader, index, state): + self.real.set_constant_buffer(shader, index, state.buffer) + + def set_framebuffer_state(self, state): + _state = gallium.Framebuffer() + _state.width = state.width + _state.height = state.height + _state.num_cbufs = state.num_cbufs + for i in range(len(state.cbufs)): + _state.set_cbuf(i, state.cbufs[i]) + _state.set_zsbuf(state.zsbuf) + self.real.set_framebuffer(_state) + + self.cbufs = state.cbufs + self.zsbuf = state.zsbuf + + def set_polygon_stipple(self, state): + self.real.set_polygon_stipple(state) + + def set_scissor_state(self, state): + self.real.set_scissor(state) + + def set_viewport_state(self, state): + self.real.set_viewport(state) + + def set_sampler_textures(self, n, textures): + for i in range(n): + self.real.set_sampler_textures(textures[i]) + + def set_vertex_buffers(self, n, vbufs): + for i in range(n): + vbuf = vbufs[i] + self.real.set_vertex_buffer( + i, + pitch = vbuf.pitch, + max_index = vbuf.max_index, + buffer_offset = vbuf.buffer_offset, + buffer = vbuf.buffer, + ) + + def set_vertex_elements(self, n, elements): + for i in range(n): + self.real.set_vertex_element(i, elements[i]) + self.real.set_vertex_elements(n) + + def set_edgeflags(self, bitfield): + # FIXME + pass + + def draw_arrays(self, mode, start, count): + self.real.draw_arrays(mode, start, count) + self._update() + + def flush(self, flags, fence): + self.real.flush(flags) + + def clear(self, surface, value): + self.real.surface_clear(surface, value) + + def _update(self): + self.real.flush() + + if self.cbufs and self.cbufs[0]: + show_image(self.cbufs[0]) + + +class Interpreter: + + def __init__(self): + self.objects = {} + self.result = None + self.globl = Global(self, None) + + def register_object(self, address, object): + self.objects[address] = object + + def unregister_object(self, object): + # FIXME: + pass + + def lookup_object(self, address): + return self.objects[address] + + def interpret(self, trace): + for call in trace.calls: + self.interpret_call(call) + + def interpret_call(self, call): + sys.stderr.write("%s\n" % call) + + args = [self.interpret_arg(arg) for name, arg in call.args] + + if call.klass: + obj = args[0] + args = args[1:] + else: + obj = self.globl + + method = getattr(obj, call.method) + ret = method(*args) + + if call.ret and isinstance(call.ret, model.Pointer): + self.register_object(call.ret.address, ret) + + def interpret_arg(self, node): + translator = Translator(self) + return translator.visit(node) + + +def main(): + for arg in sys.argv[1:]: + parser = TraceParser(open(arg, 'rt')) + trace = parser.parse() + interpreter = Interpreter() + interpreter.interpret(trace) + + +if __name__ == '__main__': + main() diff --git a/src/gallium/state_trackers/python/retrace/model.py b/src/gallium/state_trackers/python/retrace/model.py new file mode 100755 index 0000000000..c17b5db9f8 --- /dev/null +++ b/src/gallium/state_trackers/python/retrace/model.py @@ -0,0 +1,151 @@ +#!/usr/bin/env python +############################################################################# +# +# Copyright 2008 Tungsten Graphics, Inc. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# +############################################################################# + + +'''Trace data model.''' + + +class Node: + + def visit(self, visitor): + raise NotImplementedError + + +class Literal(Node): + + def __init__(self, value): + self.value = value + + def visit(self, visitor): + visitor.visit_literal(self) + + def __str__(self): + if isinstance(self.value, str) and len(self.value) > 32: + return '...' + else: + return repr(self.value) + + +class NamedConstant(Node): + + def __init__(self, name): + self.name = name + + def visit(self, visitor): + visitor.visit_named_constant(self) + + def __str__(self): + return self.name + + +class Array(Node): + + def __init__(self, elements): + self.elements = elements + + def visit(self, visitor): + visitor.visit_array(self) + + def __str__(self): + return '{' + ', '.join([str(value) for value in self.elements]) + '}' + + +class Struct(Node): + + def __init__(self, name, members): + self.name = name + self.members = members + + def visit(self, visitor): + visitor.visit_struct(self) + + def __str__(self): + return '{' + ', '.join([name + ' = ' + str(value) for name, value in self.members]) + '}' + + +class Pointer(Node): + + def __init__(self, address): + self.address = address + + def visit(self, visitor): + visitor.visit_pointer(self) + + def __str__(self): + return hex(self.address) + + +class Call: + + def __init__(self, klass, method, args, ret): + self.klass = klass + self.method = method + self.args = args + self.ret = ret + + def visit(self, visitor): + visitor.visit_call(self) + + def __str__(self): + s = self.method + if self.klass: + s = self.klass + '::' + s + s += '(' + ', '.join([name + ' = ' + str(value) for name, value in self.args]) + ')' + if self.ret is not None: + s += ' = ' + str(self.ret) + return s + + +class Trace: + + def __init__(self, calls): + self.calls = calls + + def visit(self, visitor): + visitor.visit_trace(self) + + def __str__(self): + return '\n'.join([str(call) for call in self.calls]) + + +class Visitor: + + def visit_literal(self, node): + raise NotImplementedError + + def visit_named_constant(self, node): + raise NotImplementedError + + def visit_array(self, node): + raise NotImplementedError + + def visit_struct(self, node): + raise NotImplementedError + + def visit_pointer(self, node): + raise NotImplementedError + + def visit_call(self, node): + raise NotImplementedError + + def visit_trace(self, node): + raise NotImplementedError + + diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py new file mode 100755 index 0000000000..571d8f6eae --- /dev/null +++ b/src/gallium/state_trackers/python/retrace/parser.py @@ -0,0 +1,332 @@ +#!/usr/bin/env python +############################################################################# +# +# Copyright 2008 Tungsten Graphics, Inc. +# +# This program is free software: you can redistribute it and/or modify it +# under the terms of the GNU Lesser General Public License as published +# by the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public License +# along with this program. If not, see . +# +############################################################################# + + +import sys +import xml.parsers.expat +import binascii + +from model import * + + +ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4) + + +class XmlToken: + + def __init__(self, type, name_or_data, attrs = None, line = None, column = None): + assert type in (ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF) + self.type = type + self.name_or_data = name_or_data + self.attrs = attrs + self.line = line + self.column = column + + def __str__(self): + if self.type == ELEMENT_START: + return '<' + self.name_or_data + ' ...>' + if self.type == ELEMENT_END: + return '' + if self.type == CHARACTER_DATA: + return self.name_or_data + if self.type == EOF: + return 'end of file' + assert 0 + + +class XmlTokenizer: + """Expat based XML tokenizer.""" + + def __init__(self, fp, skip_ws = True): + self.fp = fp + self.tokens = [] + self.index = 0 + self.final = False + self.skip_ws = skip_ws + + self.character_pos = 0, 0 + self.character_data = '' + + self.parser = xml.parsers.expat.ParserCreate() + self.parser.StartElementHandler = self.handle_element_start + self.parser.EndElementHandler = self.handle_element_end + self.parser.CharacterDataHandler = self.handle_character_data + + def handle_element_start(self, name, attributes): + self.finish_character_data() + line, column = self.pos() + token = XmlToken(ELEMENT_START, name, attributes, line, column) + self.tokens.append(token) + + def handle_element_end(self, name): + self.finish_character_data() + line, column = self.pos() + token = XmlToken(ELEMENT_END, name, None, line, column) + self.tokens.append(token) + + def handle_character_data(self, data): + if not self.character_data: + self.character_pos = self.pos() + self.character_data += data + + def finish_character_data(self): + if self.character_data: + if not self.skip_ws or not self.character_data.isspace(): + line, column = self.character_pos + token = XmlToken(CHARACTER_DATA, self.character_data, None, line, column) + self.tokens.append(token) + self.character_data = '' + + def next(self): + size = 16*1024 + while self.index >= len(self.tokens) and not self.final: + self.tokens = [] + self.index = 0 + data = self.fp.read(size) + self.final = len(data) < size + try: + self.parser.Parse(data, self.final) + except xml.parsers.expat.ExpatError, e: + #if e.code == xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS: + if e.code == 3: + pass + else: + raise e + if self.index >= len(self.tokens): + line, column = self.pos() + token = XmlToken(EOF, None, None, line, column) + else: + token = self.tokens[self.index] + self.index += 1 + return token + + def pos(self): + return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber + + +class TokenMismatch(Exception): + + def __init__(self, expected, found): + self.expected = expected + self.found = found + + def __str__(self): + return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found)) + + + +class XmlParser: + """Base XML document parser.""" + + def __init__(self, fp): + self.tokenizer = XmlTokenizer(fp) + self.consume() + + def consume(self): + self.token = self.tokenizer.next() + + def match_element_start(self, name): + return self.token.type == ELEMENT_START and self.token.name_or_data == name + + def match_element_end(self, name): + return self.token.type == ELEMENT_END and self.token.name_or_data == name + + def element_start(self, name): + while self.token.type == CHARACTER_DATA: + self.consume() + if self.token.type != ELEMENT_START: + raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) + if self.token.name_or_data != name: + raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) + attrs = self.token.attrs + self.consume() + return attrs + + def element_end(self, name): + while self.token.type == CHARACTER_DATA: + self.consume() + if self.token.type != ELEMENT_END: + raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) + if self.token.name_or_data != name: + raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) + self.consume() + + def character_data(self, strip = True): + data = '' + while self.token.type == CHARACTER_DATA: + data += self.token.name_or_data + self.consume() + if strip: + data = data.strip() + return data + + +class TraceParser(XmlParser): + + def parse(self): + self.element_start('trace') + calls = [] + while self.token.type not in (ELEMENT_END, EOF): + calls.append(self.parse_call()) + if self.token.type != EOF: + self.element_end('trace') + return Trace(calls) + + def parse_call(self): + attrs = self.element_start('call') + klass = attrs['class'] + method = attrs['method'] + args = [] + ret = None + while self.token.type == ELEMENT_START: + if self.token.name_or_data == 'arg': + arg = self.parse_arg() + args.append(arg) + elif self.token.name_or_data == 'ret': + ret = self.parse_ret() + elif self.token.name_or_data == 'call': + # ignore nested function calls + self.parse_call() + else: + raise TokenMismatch(" or ", self.token) + self.element_end('call') + + return Call(klass, method, args, ret) + + def parse_arg(self): + attrs = self.element_start('arg') + name = attrs['name'] + value = self.parse_value() + self.element_end('arg') + + return name, value + + def parse_ret(self): + attrs = self.element_start('ret') + value = self.parse_value() + self.element_end('ret') + + return value + + def parse_value(self): + expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes') + if self.token.type == ELEMENT_START: + if self.token.name_or_data in expected_tokens: + method = getattr(self, 'parse_' + self.token.name_or_data) + return method() + raise TokenMismatch(" or " .join(expected_tokens), self.token) + + def parse_null(self): + self.element_start('null') + self.element_end('null') + return Literal(None) + + def parse_bool(self): + self.element_start('bool') + value = int(self.character_data()) + self.element_end('bool') + return Literal(value) + + def parse_int(self): + self.element_start('int') + value = int(self.character_data()) + self.element_end('int') + return Literal(value) + + def parse_uint(self): + self.element_start('uint') + value = int(self.character_data()) + self.element_end('uint') + return Literal(value) + + def parse_float(self): + self.element_start('float') + value = float(self.character_data()) + self.element_end('float') + return Literal(value) + + def parse_enum(self): + self.element_start('enum') + name = self.character_data() + self.element_end('enum') + return NamedConstant(name) + + def parse_string(self): + self.element_start('string') + value = self.character_data() + self.element_end('string') + return Literal(value) + + def parse_bytes(self): + self.element_start('bytes') + value = binascii.a2b_hex(self.character_data()) + self.element_end('bytes') + return Literal(value) + + def parse_array(self): + self.element_start('array') + elems = [] + while self.token.type != ELEMENT_END: + elems.append(self.parse_elem()) + self.element_end('array') + return Array(elems) + + def parse_elem(self): + self.element_start('elem') + value = self.parse_value() + self.element_end('elem') + return value + + def parse_struct(self): + attrs = self.element_start('struct') + name = attrs['name'] + members = [] + while self.token.type != ELEMENT_END: + members.append(self.parse_member()) + self.element_end('struct') + return Struct(name, members) + + def parse_member(self): + attrs = self.element_start('member') + name = attrs['name'] + value = self.parse_value() + self.element_end('member') + + return name, value + + def parse_ptr(self): + self.element_start('ptr') + address = self.character_data() + self.element_end('ptr') + + address = int(address, 16) + + return Pointer(address) + + +def main(): + for arg in sys.argv[1:]: + parser = TraceParser(open(arg, 'rt')) + trace = parser.parse() + print trace + + +if __name__ == '__main__': + main() -- cgit v1.2.3 From df3d694851fd99b6ea88c339b5153944824d3d3a Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 14 Aug 2008 11:15:13 +0100 Subject: python/retrace: Commit unsaved changes to the doc. --- src/gallium/state_trackers/python/retrace/README | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/README b/src/gallium/state_trackers/python/retrace/README index c0ad8ae6c1..822cd11404 100644 --- a/src/gallium/state_trackers/python/retrace/README +++ b/src/gallium/state_trackers/python/retrace/README @@ -1,4 +1,5 @@ -This is +This is an application written in python to replay the traces captured by the + trace pipe driver. To use it follow the instructions in src/gallium/drivers/trace/README and @@ -7,8 +8,6 @@ src/gallium/state_trackers/python/README, and then do python src/gallium/state_trackers/python/samples/retrace/interpreter.py filename.trace - - This is still work in progress: - not everything is captured/replayed - surface/textures contents -- cgit v1.2.3 From 14fe0d62ee8cf1dd48ec8d373ee3dcb3fe06fd77 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 14 Aug 2008 14:40:27 +0100 Subject: python/retrace: Keep addresses as strings. To simplify looking up these in the trace. --- src/gallium/state_trackers/python/retrace/model.py | 2 +- src/gallium/state_trackers/python/retrace/parser.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/model.py b/src/gallium/state_trackers/python/retrace/model.py index c17b5db9f8..a17a765914 100755 --- a/src/gallium/state_trackers/python/retrace/model.py +++ b/src/gallium/state_trackers/python/retrace/model.py @@ -89,7 +89,7 @@ class Pointer(Node): visitor.visit_pointer(self) def __str__(self): - return hex(self.address) + return self.address class Call: diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py index 571d8f6eae..9ee47f6e19 100755 --- a/src/gallium/state_trackers/python/retrace/parser.py +++ b/src/gallium/state_trackers/python/retrace/parser.py @@ -316,8 +316,6 @@ class TraceParser(XmlParser): address = self.character_data() self.element_end('ptr') - address = int(address, 16) - return Pointer(address) -- cgit v1.2.3 From c9751522b0ee1908c79f3f9d37b508ac0680bd16 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 14 Aug 2008 22:03:35 +0100 Subject: pyhon/retrace: Retrace surface contents. Now capable of replaying trivial/quad-tex-2d --- .../state_trackers/python/retrace/interpreter.py | 35 ++++++++++++++++------ 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index ae62bc04a8..00b6376623 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -105,7 +105,8 @@ member_array_factories = { "pipe_viewport_state": {"scale": gallium.FloatArray, "translate": gallium.FloatArray}, "pipe_clip_state": {"ucp": gallium.FloatArray}, "pipe_depth_stencil_alpha_state": {"stencil": gallium.StencilArray}, - "pipe_blend_color": {"color": gallium.FloatArray}, + "pipe_blend_color": {"color": gallium.FloatArray}, + "pipe_sampler_state": {"border_color": gallium.FloatArray}, } @@ -191,6 +192,15 @@ class Winsys(Object): def get_name(self): pass + def user_buffer_create(self, data, size): + # We don't really care to distinguish between user and regular buffers + buffer = self.real.buffer_create(size, + 4, + gallium.PIPE_BUFFER_USAGE_CPU_READ | + gallium.PIPE_BUFFER_USAGE_CPU_WRITE ) + buffer.write(data, size) + return buffer + def buffer_create(self, alignment, usage, size): return self.real.buffer_create(size, alignment, usage) @@ -199,7 +209,15 @@ class Winsys(Object): def buffer_write(self, buffer, data, size): buffer.write(data, size) - buffer.write(data, size) + + def fence_finish(self, fence, flags): + pass + + def fence_reference(self, dst, src): + pass + + def flush_frontbuffer(self, surface): + pass class Screen(Object): @@ -239,11 +257,9 @@ class Screen(Object): def tex_surface_release(self, surface): self.interpreter.unregister_object(surface) - def surface_map(self, surface, flags): - return None - - def surface_unmap(self, surface): - pass + def surface_write(self, surface, data, stride, size): + assert surface.nblocksy * stride == size + surface.put_tile_raw(0, 0, surface.width, surface.height, data, stride) class Context(Object): @@ -324,7 +340,7 @@ class Context(Object): def set_sampler_textures(self, n, textures): for i in range(n): - self.real.set_sampler_textures(textures[i]) + self.real.set_sampler_texture(i, textures[i]) def set_vertex_buffers(self, n, vbufs): for i in range(n): @@ -350,8 +366,9 @@ class Context(Object): self.real.draw_arrays(mode, start, count) self._update() - def flush(self, flags, fence): + def flush(self, flags): self.real.flush(flags) + return None def clear(self, surface, value): self.real.surface_clear(surface, value) -- cgit v1.2.3 From 52ecb8f56368180b5dec303d1d77a8d0596aaef7 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 15 Aug 2008 10:33:35 +0100 Subject: python/retrace: Update frame when PIPE_FLUSH_FRAME spotted. --- src/gallium/state_trackers/python/retrace/interpreter.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 00b6376623..fa9a65365c 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -364,10 +364,11 @@ class Context(Object): def draw_arrays(self, mode, start, count): self.real.draw_arrays(mode, start, count) - self._update() def flush(self, flags): self.real.flush(flags) + if flags & gallium.PIPE_FLUSH_FRAME: + self._update() return None def clear(self, surface, value): -- cgit v1.2.3 From 5f1ef11ad2e3016ac4029489d9429d7f93737fe5 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Tue, 19 Aug 2008 18:25:38 +0100 Subject: python/retrace: Trim null chars. They are often left in memory mapped files, and are not part of the XML accept chars anyway. --- src/gallium/state_trackers/python/retrace/parser.py | 1 + 1 file changed, 1 insertion(+) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py index 9ee47f6e19..d02fd7f741 100755 --- a/src/gallium/state_trackers/python/retrace/parser.py +++ b/src/gallium/state_trackers/python/retrace/parser.py @@ -101,6 +101,7 @@ class XmlTokenizer: self.index = 0 data = self.fp.read(size) self.final = len(data) < size + data = data.rstrip('\0') try: self.parser.Parse(data, self.final) except xml.parsers.expat.ExpatError, e: -- cgit v1.2.3 From d7f8b95e097121a8c33332f920115795853d6ad7 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Tue, 19 Aug 2008 19:12:22 +0100 Subject: python/retrace: Add several missing functions. --- .../state_trackers/python/retrace/interpreter.py | 57 ++++++++++++++++++---- 1 file changed, 48 insertions(+), 9 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index fa9a65365c..a7a7341e06 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -79,7 +79,7 @@ class Struct: struct_factories = { "pipe_blend_color": gallium.BlendColor, "pipe_blend_state": gallium.Blend, - "pipe_clip_state": gallium.Clip, + #"pipe_clip_state": gallium.Clip, #"pipe_constant_buffer": gallium.ConstantBuffer, "pipe_depth_state": gallium.Depth, "pipe_stencil_state": gallium.Stencil, @@ -103,7 +103,7 @@ member_array_factories = { "pipe_rasterizer_state": {"sprite_coord_mode": gallium.ByteArray}, "pipe_poly_stipple": {"stipple": gallium.UnsignedArray}, "pipe_viewport_state": {"scale": gallium.FloatArray, "translate": gallium.FloatArray}, - "pipe_clip_state": {"ucp": gallium.FloatArray}, + #"pipe_clip_state": {"ucp": gallium.FloatArray}, "pipe_depth_stencil_alpha_state": {"stencil": gallium.StencilArray}, "pipe_blend_color": {"color": gallium.FloatArray}, "pipe_sampler_state": {"border_color": gallium.FloatArray}, @@ -219,6 +219,12 @@ class Winsys(Object): def flush_frontbuffer(self, surface): pass + def surface_alloc(self): + return None + + def surface_release(self, surface): + pass + class Screen(Object): @@ -269,15 +275,25 @@ class Context(Object): self.cbufs = [] self.zsbuf = None + def destroy(self): + pass + def create_blend_state(self, state): return state def bind_blend_state(self, state): - self.real.set_blend(state) - + if state is not None: + self.real.set_blend(state) + + def delete_blend_state(self, state): + pass + def create_sampler_state(self, state): return state + def delete_sampler_state(self, state): + pass + def bind_sampler_states(self, n, states): for i in range(n): self.real.set_sampler(i, states[i]) @@ -286,14 +302,22 @@ class Context(Object): return state def bind_rasterizer_state(self, state): - self.real.set_rasterizer(state) + if state is not None: + self.real.set_rasterizer(state) + def delete_rasterizer_state(self, state): + pass + def create_depth_stencil_alpha_state(self, state): return state def bind_depth_stencil_alpha_state(self, state): - self.real.set_depth_stencil_alpha(state) - + if state is not None: + self.real.set_depth_stencil_alpha(state) + + def delete_depth_stencil_alpha_state(self, state): + pass + def create_fs_state(self, state): tokens = str(state.tokens) shader = gallium.Shader(tokens) @@ -307,14 +331,29 @@ class Context(Object): def bind_vs_state(self, state): self.real.set_vertex_shader(state) + def delete_fs_state(self, state): + pass + + delete_vs_state = delete_fs_state + def set_blend_color(self, state): self.real.set_blend_color(state) def set_clip_state(self, state): - self.real.set_clip(state) + _state = gallium.Clip() + _state.nr = state.nr + if state.nr: + # FIXME + ucp = gallium.FloatArray(gallium.PIPE_MAX_CLIP_PLANES*4) + for i in range(len(state.ucp)): + for j in range(len(state.ucp[i])): + ucp[i*4 + j] = state.ucp[i][j] + _state.ucp = ucp + self.real.set_clip(_state) def set_constant_buffer(self, shader, index, state): - self.real.set_constant_buffer(shader, index, state.buffer) + if state is not None: + self.real.set_constant_buffer(shader, index, state.buffer) def set_framebuffer_state(self, state): _state = gallium.Framebuffer() -- cgit v1.2.3 From 34cffce33413fe7701975d0d4bd54207bc44cacc Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 20 Aug 2008 14:03:12 +0100 Subject: python/retrace: Retrace draw_elements and draw_range_elements. --- src/gallium/state_trackers/python/retrace/interpreter.py | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index a7a7341e06..7502c096b6 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -403,6 +403,12 @@ class Context(Object): def draw_arrays(self, mode, start, count): self.real.draw_arrays(mode, start, count) + + def draw_elements(self, indexBuffer, indexSize, mode, start, count): + self.real.draw_elements(indexBuffer, indexSize, mode, start, count) + + def draw_range_elements(self, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count): + self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count) def flush(self, flags): self.real.flush(flags) -- cgit v1.2.3 From 10624065b0dc631164d786b2c39f35655e55eadf Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 21 Aug 2008 18:45:43 +0100 Subject: python/retrace: Support gziped traces. --- src/gallium/state_trackers/python/retrace/interpreter.py | 7 ++++++- src/gallium/state_trackers/python/retrace/parser.py | 10 ++++++++-- 2 files changed, 14 insertions(+), 3 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 7502c096b6..f596a54d10 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -471,7 +471,12 @@ class Interpreter: def main(): for arg in sys.argv[1:]: - parser = TraceParser(open(arg, 'rt')) + if arg.endswith('.gz'): + import gzip + stream = gzip.GzipFile(arg, 'rt') + else: + stream = open(arg, 'rt') + parser = TraceParser(stream) trace = parser.parse() interpreter = Interpreter() interpreter.interpret(trace) diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py index d02fd7f741..2ee4d3068d 100755 --- a/src/gallium/state_trackers/python/retrace/parser.py +++ b/src/gallium/state_trackers/python/retrace/parser.py @@ -322,9 +322,15 @@ class TraceParser(XmlParser): def main(): for arg in sys.argv[1:]: - parser = TraceParser(open(arg, 'rt')) + if arg.endswith('.gz'): + import gzip + stream = gzip.GzipFile(arg, 'rt') + else: + stream = open(arg, 'rt') + parser = TraceParser(stream) trace = parser.parse() - print trace + for call in trace.calls: + print call if __name__ == '__main__': -- cgit v1.2.3 From 7f3c3683ce50bad42411547d4b78e03d7f20e498 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 22 Aug 2008 01:23:48 +0100 Subject: python/retrace: Process the trace call-by-call (instead of reading everything into memory). --- .../state_trackers/python/retrace/interpreter.py | 24 +++++--------------- .../state_trackers/python/retrace/parser.py | 26 ++++++++++++++-------- 2 files changed, 23 insertions(+), 27 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index f596a54d10..a2f924f528 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -22,7 +22,7 @@ import sys import gallium import model -from parser import TraceParser +import parser def make_image(surface): @@ -426,9 +426,10 @@ class Context(Object): show_image(self.cbufs[0]) -class Interpreter: +class Interpreter(parser.TraceParser): - def __init__(self): + def __init__(self, stream): + parser.TraceParser.__init__(self, stream) self.objects = {} self.result = None self.globl = Global(self, None) @@ -447,7 +448,7 @@ class Interpreter: for call in trace.calls: self.interpret_call(call) - def interpret_call(self, call): + def handle_call(self, call): sys.stderr.write("%s\n" % call) args = [self.interpret_arg(arg) for name, arg in call.args] @@ -469,18 +470,5 @@ class Interpreter: return translator.visit(node) -def main(): - for arg in sys.argv[1:]: - if arg.endswith('.gz'): - import gzip - stream = gzip.GzipFile(arg, 'rt') - else: - stream = open(arg, 'rt') - parser = TraceParser(stream) - trace = parser.parse() - interpreter = Interpreter() - interpreter.interpret(trace) - - if __name__ == '__main__': - main() + parser.main(Interpreter) diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py index 2ee4d3068d..6bc75ad685 100755 --- a/src/gallium/state_trackers/python/retrace/parser.py +++ b/src/gallium/state_trackers/python/retrace/parser.py @@ -183,12 +183,11 @@ class TraceParser(XmlParser): def parse(self): self.element_start('trace') - calls = [] while self.token.type not in (ELEMENT_END, EOF): - calls.append(self.parse_call()) + call = self.parse_call() + self.handle_call(call) if self.token.type != EOF: self.element_end('trace') - return Trace(calls) def parse_call(self): attrs = self.element_start('call') @@ -319,19 +318,28 @@ class TraceParser(XmlParser): return Pointer(address) + def handle_call(self, call): + + pass + + +class TraceDumper(TraceParser): + + + def handle_call(self, call): + print call + -def main(): +def main(ParserFactory): for arg in sys.argv[1:]: if arg.endswith('.gz'): import gzip stream = gzip.GzipFile(arg, 'rt') else: stream = open(arg, 'rt') - parser = TraceParser(stream) - trace = parser.parse() - for call in trace.calls: - print call + parser = ParserFactory(stream) + parser.parse() if __name__ == '__main__': - main() + main(TraceDumper) -- cgit v1.2.3 From d32f51d4717686d626b0f7ec9a92c3c9af50009f Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 22 Aug 2008 03:14:51 +0100 Subject: python/retrace: Interpret texture/surfaces destructions. --- src/gallium/state_trackers/python/retrace/interpreter.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index a2f924f528..351a6e739b 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -254,15 +254,21 @@ class Screen(Object): tex_usage = template.tex_usage, ) - def texture_release(self, texture): + def texture_destroy(self, texture): self.interpreter.unregister_object(texture) + def texture_release(self, surface): + pass + def get_tex_surface(self, texture, face, level, zslice, usage): return texture.get_surface(face, level, zslice, usage) - def tex_surface_release(self, surface): + def tex_surface_destroy(self, surface): self.interpreter.unregister_object(surface) + def tex_surface_release(self, surface): + pass + def surface_write(self, surface, data, stride, size): assert surface.nblocksy * stride == size surface.put_tile_raw(0, 0, surface.width, surface.height, data, stride) -- cgit v1.2.3 From 9efa6cafea8176eb867bf820ea82a46ad45bfc15 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 19 Nov 2008 16:23:01 +0900 Subject: python/retrace: Use the usual BSD-style license. --- .../state_trackers/python/retrace/interpreter.py | 44 +++++++++++++--------- src/gallium/state_trackers/python/retrace/model.py | 44 +++++++++++++--------- .../state_trackers/python/retrace/parser.py | 44 +++++++++++++--------- 3 files changed, 78 insertions(+), 54 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 351a6e739b..a23f153d2f 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -1,22 +1,30 @@ #!/usr/bin/env python -############################################################################# -# -# Copyright 2008 Tungsten Graphics, Inc. -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . -# -############################################################################# +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# 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 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 TUNGSTEN GRAPHICS 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. +# +########################################################################## import sys diff --git a/src/gallium/state_trackers/python/retrace/model.py b/src/gallium/state_trackers/python/retrace/model.py index a17a765914..9dd928c7e2 100755 --- a/src/gallium/state_trackers/python/retrace/model.py +++ b/src/gallium/state_trackers/python/retrace/model.py @@ -1,22 +1,30 @@ #!/usr/bin/env python -############################################################################# -# -# Copyright 2008 Tungsten Graphics, Inc. -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . -# -############################################################################# +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# 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 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 TUNGSTEN GRAPHICS 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. +# +########################################################################## '''Trace data model.''' diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py index 6bc75ad685..e5e8525dfc 100755 --- a/src/gallium/state_trackers/python/retrace/parser.py +++ b/src/gallium/state_trackers/python/retrace/parser.py @@ -1,22 +1,30 @@ #!/usr/bin/env python -############################################################################# -# -# Copyright 2008 Tungsten Graphics, Inc. -# -# This program is free software: you can redistribute it and/or modify it -# under the terms of the GNU Lesser General Public License as published -# by the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this program. If not, see . -# -############################################################################# +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# 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 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 TUNGSTEN GRAPHICS 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. +# +########################################################################## import sys -- cgit v1.2.3 From 56ce90c8bee057cf69ba653adf57aa401d51c240 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 19 Nov 2008 17:17:06 +0900 Subject: python/retrace: Highlight the trace dump to help to visualize. --- .../state_trackers/python/retrace/format.py | 100 +++++++++++++++++++ .../state_trackers/python/retrace/interpreter.py | 6 +- src/gallium/state_trackers/python/retrace/model.py | 106 +++++++++++++++------ .../state_trackers/python/retrace/parser.py | 8 +- 4 files changed, 185 insertions(+), 35 deletions(-) create mode 100755 src/gallium/state_trackers/python/retrace/format.py (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/format.py b/src/gallium/state_trackers/python/retrace/format.py new file mode 100755 index 0000000000..0bf6baf0b9 --- /dev/null +++ b/src/gallium/state_trackers/python/retrace/format.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# 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 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 TUNGSTEN GRAPHICS 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. +# +########################################################################## + + +class Formatter: + '''Plain formatter''' + + def __init__(self, stream): + self.stream = stream + + def text(self, text): + self.stream.write(text) + + def newline(self): + self.text('\n') + + def function(self, name): + self.text(name) + + def variable(self, name): + self.text(name) + + def literal(self, value): + self.text(str(value)) + + def address(self, addr): + self.text(str(addr)) + + +class AnsiFormatter(Formatter): + '''Formatter for plain-text files which outputs ANSI escape codes. See + http://en.wikipedia.org/wiki/ANSI_escape_code for more information + concerning ANSI escape codes. + ''' + + _csi = '\33[' + + _normal = '0m' + _bold = '1m' + _italic = '3m' + _red = '31m' + _green = '32m' + _blue = '34m' + + def _escape(self, code): + self.text(self._csi + code) + + def function(self, name): + self._escape(self._bold) + Formatter.function(self, name) + self._escape(self._normal) + + def variable(self, name): + self._escape(self._italic) + Formatter.variable(self, name) + self._escape(self._normal) + + def literal(self, value): + self._escape(self._blue) + Formatter.literal(self, value) + self._escape(self._normal) + + def address(self, value): + self._escape(self._green) + Formatter.address(self, value) + self._escape(self._normal) + + + +def DefaultFormatter(stream): + if stream.isatty(): + return AnsiFormatter(stream) + else: + return Formatter(stream) + diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index a23f153d2f..61b3ef2abc 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -440,10 +440,10 @@ class Context(Object): show_image(self.cbufs[0]) -class Interpreter(parser.TraceParser): +class Interpreter(parser.TraceDumper): def __init__(self, stream): - parser.TraceParser.__init__(self, stream) + parser.TraceDumper.__init__(self, stream) self.objects = {} self.result = None self.globl = Global(self, None) @@ -463,7 +463,7 @@ class Interpreter(parser.TraceParser): self.interpret_call(call) def handle_call(self, call): - sys.stderr.write("%s\n" % call) + parser.TraceDumper.handle_call(self, call) args = [self.interpret_arg(arg) for name, arg in call.args] diff --git a/src/gallium/state_trackers/python/retrace/model.py b/src/gallium/state_trackers/python/retrace/model.py index 9dd928c7e2..3889db4e72 100755 --- a/src/gallium/state_trackers/python/retrace/model.py +++ b/src/gallium/state_trackers/python/retrace/model.py @@ -30,11 +30,27 @@ '''Trace data model.''' +import sys +import format + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + + class Node: def visit(self, visitor): raise NotImplementedError + def __str__(self): + stream = StringIO() + formatter = format.DefaultFormatter(stream) + pretty_printer = PrettyPrinter(formatter) + self.visit(pretty_printer) + return stream.getvalue() + class Literal(Node): @@ -43,12 +59,6 @@ class Literal(Node): def visit(self, visitor): visitor.visit_literal(self) - - def __str__(self): - if isinstance(self.value, str) and len(self.value) > 32: - return '...' - else: - return repr(self.value) class NamedConstant(Node): @@ -58,9 +68,6 @@ class NamedConstant(Node): def visit(self, visitor): visitor.visit_named_constant(self) - - def __str__(self): - return self.name class Array(Node): @@ -70,9 +77,6 @@ class Array(Node): def visit(self, visitor): visitor.visit_array(self) - - def __str__(self): - return '{' + ', '.join([str(value) for value in self.elements]) + '}' class Struct(Node): @@ -83,9 +87,6 @@ class Struct(Node): def visit(self, visitor): visitor.visit_struct(self) - - def __str__(self): - return '{' + ', '.join([name + ' = ' + str(value) for name, value in self.members]) + '}' class Pointer(Node): @@ -95,9 +96,6 @@ class Pointer(Node): def visit(self, visitor): visitor.visit_pointer(self) - - def __str__(self): - return self.address class Call: @@ -110,15 +108,6 @@ class Call: def visit(self, visitor): visitor.visit_call(self) - - def __str__(self): - s = self.method - if self.klass: - s = self.klass + '::' + s - s += '(' + ', '.join([name + ' = ' + str(value) for name, value in self.args]) + ')' - if self.ret is not None: - s += ' = ' + str(self.ret) - return s class Trace: @@ -128,9 +117,6 @@ class Trace: def visit(self, visitor): visitor.visit_trace(self) - - def __str__(self): - return '\n'.join([str(call) for call in self.calls]) class Visitor: @@ -155,5 +141,65 @@ class Visitor: def visit_trace(self, node): raise NotImplementedError + + +class PrettyPrinter: + + def __init__(self, formatter): + self.formatter = formatter + + def visit_literal(self, node): + if isinstance(node.value, str) and len(node.value) > 32: + self.formatter.text('...') + else: + self.formatter.literal(repr(node.value)) + + def visit_named_constant(self, node): + self.formatter.literal(node.name) + def visit_array(self, node): + self.formatter.text('{') + sep = '' + for value in node.elements: + self.formatter.text(sep) + value.visit(self) + sep = ', ' + self.formatter.text('}') + + def visit_struct(self, node): + self.formatter.text('{') + sep = '' + for name, value in node.members: + self.formatter.text(sep) + self.formatter.variable(name) + self.formatter.text(' = ') + value.visit(self) + sep = ', ' + self.formatter.text('}') + + def visit_pointer(self, node): + self.formatter.address(node.address) + + def visit_call(self, node): + if node.klass is not None: + self.formatter.function(node.klass + '::' + node.method) + else: + self.formatter.function(node.method) + self.formatter.text('(') + sep = '' + for name, value in node.args: + self.formatter.text(sep) + self.formatter.variable(name) + self.formatter.text(' = ') + value.visit(self) + sep = ', ' + if node.ret is not None: + self.formatter.text(' = ') + node.ret.visit(self) + self.formatter.text(')') + + def visit_trace(self, node): + for call in node.calls: + call.visit(self) + self.formatter.newline() diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py index e5e8525dfc..5205f2d8dd 100755 --- a/src/gallium/state_trackers/python/retrace/parser.py +++ b/src/gallium/state_trackers/python/retrace/parser.py @@ -327,15 +327,19 @@ class TraceParser(XmlParser): return Pointer(address) def handle_call(self, call): - pass class TraceDumper(TraceParser): + def __init__(self, fp): + TraceParser.__init__(self, fp) + self.formatter = format.DefaultFormatter(sys.stdout) + self.pretty_printer = PrettyPrinter(self.formatter) def handle_call(self, call): - print call + call.visit(self.pretty_printer) + self.formatter.newline() def main(ParserFactory): -- cgit v1.2.3 From 03f19bc33d0c2e94bf0ad4ec6e42b708be0c0967 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 19 Nov 2008 20:06:04 +0900 Subject: python/retrace: Ignore irrelevant calls. --- src/gallium/state_trackers/python/retrace/interpreter.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 61b3ef2abc..1918fc9bda 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -442,6 +442,12 @@ class Context(Object): class Interpreter(parser.TraceDumper): + ignore_calls = set(( + ('pipe_screen', 'is_format_supported'), + ('pipe_screen', 'get_param'), + ('pipe_screen', 'get_paramf'), + )) + def __init__(self, stream): parser.TraceDumper.__init__(self, stream) self.objects = {} @@ -463,6 +469,10 @@ class Interpreter(parser.TraceDumper): self.interpret_call(call) def handle_call(self, call): + + if (call.klass, call.method) in self.ignore_calls: + return + parser.TraceDumper.handle_call(self, call) args = [self.interpret_arg(arg) for name, arg in call.args] -- cgit v1.2.3 From 8a9e06257f3a145cddc5e44f841e2f2e81a2cafb Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 19 Nov 2008 20:06:52 +0900 Subject: python/retrace: Fix formatting of shaders. --- src/gallium/state_trackers/python/retrace/model.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/model.py b/src/gallium/state_trackers/python/retrace/model.py index 3889db4e72..ae0f4327d7 100755 --- a/src/gallium/state_trackers/python/retrace/model.py +++ b/src/gallium/state_trackers/python/retrace/model.py @@ -31,6 +31,7 @@ import sys +import string import format try: @@ -149,10 +150,15 @@ class PrettyPrinter: self.formatter = formatter def visit_literal(self, node): - if isinstance(node.value, str) and len(node.value) > 32: - self.formatter.text('...') - else: - self.formatter.literal(repr(node.value)) + if isinstance(node.value, basestring): + if len(node.value) >= 4096 or node.value.strip(string.printable): + self.formatter.text('...') + return + + self.formatter.literal('"' + node.value + '"') + return + + self.formatter.literal(repr(node.value)) def visit_named_constant(self, node): self.formatter.literal(node.name) @@ -193,10 +199,10 @@ class PrettyPrinter: self.formatter.text(' = ') value.visit(self) sep = ', ' + self.formatter.text(')') if node.ret is not None: self.formatter.text(' = ') node.ret.visit(self) - self.formatter.text(')') def visit_trace(self, node): for call in node.calls: -- cgit v1.2.3 From 59ae12b5b14a2bf18c4b566abcdf3211aa5eb4d6 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 20 Nov 2008 01:02:03 +0900 Subject: python/retrace: Dump constants. --- .../state_trackers/python/retrace/interpreter.py | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 1918fc9bda..a7ae4c2625 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -28,6 +28,8 @@ import sys +import struct + import gallium import model import parser @@ -206,7 +208,8 @@ class Winsys(Object): 4, gallium.PIPE_BUFFER_USAGE_CPU_READ | gallium.PIPE_BUFFER_USAGE_CPU_WRITE ) - buffer.write(data, size) + assert size == len(data) + buffer.write(data) return buffer def buffer_create(self, alignment, usage, size): @@ -216,7 +219,8 @@ class Winsys(Object): pass def buffer_write(self, buffer, data, size): - buffer.write(data, size) + assert size == len(data) + buffer.write(data) def fence_finish(self, fence, flags): pass @@ -369,6 +373,15 @@ class Context(Object): if state is not None: self.real.set_constant_buffer(shader, index, state.buffer) + if 1: + data = state.buffer.read() + format = '4f' + index = 0 + for offset in range(0, len(data), struct.calcsize(format)): + x, y, z, w = struct.unpack_from(format, data, offset) + sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w)) + index += 1 + def set_framebuffer_state(self, state): _state = gallium.Framebuffer() _state.width = state.width -- cgit v1.2.3 From d26a43f6c6ba0e1958e3fafc99b5f110b6e3149a Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Mon, 8 Dec 2008 17:26:02 +0900 Subject: python/retrace: Dump vertex buffer contents. --- .../state_trackers/python/retrace/interpreter.py | 24 ++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index a7ae4c2625..63ae54736b 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -240,6 +240,9 @@ class Winsys(Object): class Screen(Object): + def destroy(self): + pass + def get_name(self): pass @@ -292,6 +295,8 @@ class Context(Object): Object.__init__(self, interpreter, real) self.cbufs = [] self.zsbuf = None + self.vbufs = [] + self.velems = [] def destroy(self): pass @@ -409,6 +414,7 @@ class Context(Object): self.real.set_sampler_texture(i, textures[i]) def set_vertex_buffers(self, n, vbufs): + self.vbufs = vbufs[0:n] for i in range(n): vbuf = vbufs[i] self.real.set_vertex_buffer( @@ -420,6 +426,7 @@ class Context(Object): ) def set_vertex_elements(self, n, elements): + self.velems = elements[0:n] for i in range(n): self.real.set_vertex_element(i, elements[i]) self.real.set_vertex_elements(n) @@ -429,6 +436,23 @@ class Context(Object): pass def draw_arrays(self, mode, start, count): + for index in range(start, start + count): + sys.stdout.write('\t{\n') + for velem in self.velems: + vbuf = self.vbufs[velem.vertex_buffer_index] + + offset = vbuf.buffer_offset + velem.src_offset + vbuf.pitch*index + format = { + gallium.PIPE_FORMAT_R32G32B32_FLOAT: '3f', + gallium.PIPE_FORMAT_B8G8R8A8_UNORM: '4B', + }[velem.src_format] + + data = vbuf.buffer.read() + values = struct.unpack_from(format, data, offset) + sys.stdout.write('\t\t{' + ', '.join(map(str, values)) + '},\n') + assert len(values) == velem.nr_components + sys.stdout.write('\t},\n') + self.real.draw_arrays(mode, start, count) def draw_elements(self, indexBuffer, indexSize, mode, start, count): -- cgit v1.2.3 From 51d9642f74c3f418b2f8a56b4b17c94eb91b39d1 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Tue, 9 Dec 2008 19:37:25 +0900 Subject: python/retrace: Dump indices too. --- .../state_trackers/python/retrace/interpreter.py | 45 +++++++++++++++++++++- 1 file changed, 44 insertions(+), 1 deletion(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 63ae54736b..f418f80d7b 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -435,15 +435,21 @@ class Context(Object): # FIXME pass - def draw_arrays(self, mode, start, count): + def dump_vertices(self, start, count): for index in range(start, start + count): + if index >= start + 16: + sys.stdout.write('\t...\n') + break sys.stdout.write('\t{\n') for velem in self.velems: vbuf = self.vbufs[velem.vertex_buffer_index] offset = vbuf.buffer_offset + velem.src_offset + vbuf.pitch*index format = { + gallium.PIPE_FORMAT_R32_FLOAT: 'f', + gallium.PIPE_FORMAT_R32G32_FLOAT: '2f', gallium.PIPE_FORMAT_R32G32B32_FLOAT: '3f', + gallium.PIPE_FORMAT_R32G32B32A32_FLOAT: '4f', gallium.PIPE_FORMAT_B8G8R8A8_UNORM: '4B', }[velem.src_format] @@ -452,13 +458,50 @@ class Context(Object): sys.stdout.write('\t\t{' + ', '.join(map(str, values)) + '},\n') assert len(values) == velem.nr_components sys.stdout.write('\t},\n') + + def dump_indices(self, ibuf, isize, start, count): + format = { + 1: 'B', + 2: 'H', + 4: 'I', + }[isize] + + assert struct.calcsize(format) == isize + + data = ibuf.read() + maxindex, minindex = 0, 0xffffffff + + sys.stdout.write('\t{\n') + for i in range(start, start + count): + if i >= start + 16: + sys.stdout.write('\t...\n') + break + offset = i*isize + index, = struct.unpack_from(format, data, offset) + sys.stdout.write('\t\t%u,\n' % index) + minindex = min(minindex, index) + maxindex = max(maxindex, index) + sys.stdout.write('\t},\n') + + return minindex, maxindex + + def draw_arrays(self, mode, start, count): + self.dump_vertices(start, count) self.real.draw_arrays(mode, start, count) def draw_elements(self, indexBuffer, indexSize, mode, start, count): + minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count) + self.dump_vertices(minindex, maxindex - minindex) + self.real.draw_elements(indexBuffer, indexSize, mode, start, count) def draw_range_elements(self, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count): + minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count) + minindex = min(minindex, minIndex) + maxindex = min(maxindex, maxIndex) + self.dump_vertices(minindex, maxindex - minindex) + self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count) def flush(self, flags): -- cgit v1.2.3 From 204526a6d277265b9872d4681e70c58d57038926 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 20 Feb 2009 15:02:19 +0000 Subject: python/retrace: Cope with python 2.4.x --- src/gallium/state_trackers/python/retrace/interpreter.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index f418f80d7b..181113cae6 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -35,6 +35,14 @@ import model import parser +try: + from struct import unpack_from +except ImportError: + def unpack_from(fmt, buf, offset=0): + size = struct.calcsize(fmt) + return struct.unpack(fmt, buf[offset:offset + size]) + + def make_image(surface): pixels = gallium.FloatArray(surface.height*surface.width*4) surface.get_tile_rgba(0, 0, surface.width, surface.height, pixels) @@ -383,7 +391,7 @@ class Context(Object): format = '4f' index = 0 for offset in range(0, len(data), struct.calcsize(format)): - x, y, z, w = struct.unpack_from(format, data, offset) + x, y, z, w = unpack_from(format, data, offset) sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w)) index += 1 @@ -454,7 +462,7 @@ class Context(Object): }[velem.src_format] data = vbuf.buffer.read() - values = struct.unpack_from(format, data, offset) + values = unpack_from(format, data, offset) sys.stdout.write('\t\t{' + ', '.join(map(str, values)) + '},\n') assert len(values) == velem.nr_components sys.stdout.write('\t},\n') @@ -477,7 +485,7 @@ class Context(Object): sys.stdout.write('\t...\n') break offset = i*isize - index, = struct.unpack_from(format, data, offset) + index, = unpack_from(format, data, offset) sys.stdout.write('\t\t%u,\n' % index) minindex = min(minindex, index) maxindex = max(maxindex, index) -- cgit v1.2.3 From e92f3310fa552b06a17d4f52177fc71e9ad54257 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 20 Feb 2009 15:14:15 +0000 Subject: python/retrace: Verbosity level. --- .../state_trackers/python/retrace/interpreter.py | 45 ++++++++++++++-------- 1 file changed, 30 insertions(+), 15 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 181113cae6..72dafab992 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -85,6 +85,7 @@ def show_image(surface): root.mainloop() +verbose = 1 class Struct: @@ -382,18 +383,23 @@ class Context(Object): _state.ucp = ucp self.real.set_clip(_state) + def dump_constant_buffer(self, buffer): + if verbose < 2: + return + + data = buffer.read() + format = '4f' + index = 0 + for offset in range(0, len(data), struct.calcsize(format)): + x, y, z, w = unpack_from(format, data, offset) + sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w)) + index += 1 + def set_constant_buffer(self, shader, index, state): if state is not None: self.real.set_constant_buffer(shader, index, state.buffer) - if 1: - data = state.buffer.read() - format = '4f' - index = 0 - for offset in range(0, len(data), struct.calcsize(format)): - x, y, z, w = unpack_from(format, data, offset) - sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w)) - index += 1 + self.dump_constant_buffer(state.buffer) def set_framebuffer_state(self, state): _state = gallium.Framebuffer() @@ -444,6 +450,9 @@ class Context(Object): pass def dump_vertices(self, start, count): + if verbose < 2: + return + for index in range(start, start + count): if index >= start + 16: sys.stdout.write('\t...\n') @@ -468,6 +477,9 @@ class Context(Object): sys.stdout.write('\t},\n') def dump_indices(self, ibuf, isize, start, count): + if verbose < 2: + return + format = { 1: 'B', 2: 'H', @@ -499,16 +511,18 @@ class Context(Object): self.real.draw_arrays(mode, start, count) def draw_elements(self, indexBuffer, indexSize, mode, start, count): - minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count) - self.dump_vertices(minindex, maxindex - minindex) + if verbose >= 2: + minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count) + self.dump_vertices(minindex, maxindex - minindex) self.real.draw_elements(indexBuffer, indexSize, mode, start, count) def draw_range_elements(self, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count): - minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count) - minindex = min(minindex, minIndex) - maxindex = min(maxindex, maxIndex) - self.dump_vertices(minindex, maxindex - minindex) + if verbose >= 2: + minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count) + minindex = min(minindex, minIndex) + maxindex = min(maxindex, maxIndex) + self.dump_vertices(minindex, maxindex - minindex) self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count) @@ -561,7 +575,8 @@ class Interpreter(parser.TraceDumper): if (call.klass, call.method) in self.ignore_calls: return - parser.TraceDumper.handle_call(self, call) + if verbose >= 1: + parser.TraceDumper.handle_call(self, call) args = [self.interpret_arg(arg) for name, arg in call.args] -- cgit v1.2.3 From 059d7f3103395917217d376365def36641a51602 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 20 Feb 2009 15:23:33 +0000 Subject: python/interpreter: Don't do unnecessary updates. --- src/gallium/state_trackers/python/retrace/interpreter.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 72dafab992..2a75ee82d5 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -306,6 +306,7 @@ class Context(Object): self.zsbuf = None self.vbufs = [] self.velems = [] + self.dirty = False def destroy(self): pass @@ -509,6 +510,8 @@ class Context(Object): self.dump_vertices(start, count) self.real.draw_arrays(mode, start, count) + + self.dirty = True def draw_elements(self, indexBuffer, indexSize, mode, start, count): if verbose >= 2: @@ -516,6 +519,8 @@ class Context(Object): self.dump_vertices(minindex, maxindex - minindex) self.real.draw_elements(indexBuffer, indexSize, mode, start, count) + + self.dirty = True def draw_range_elements(self, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count): if verbose >= 2: @@ -525,11 +530,15 @@ class Context(Object): self.dump_vertices(minindex, maxindex - minindex) self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count) + + self.dirty = True def flush(self, flags): self.real.flush(flags) - if flags & gallium.PIPE_FLUSH_FRAME: - self._update() + if self.dirty: + if flags & gallium.PIPE_FLUSH_FRAME: + self._update() + self.dirty = False return None def clear(self, surface, value): -- cgit v1.2.3 From 60e35ebf1476c31eb5d7c207ab8e9db77fcad896 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 20 Feb 2009 16:50:02 +0000 Subject: python: More efficient blits from surfaces. C code instead of interpreted python code. --- src/gallium/state_trackers/python/gallium.i | 1 + src/gallium/state_trackers/python/p_texture.i | 44 ++++++++++++++++++++++ .../state_trackers/python/retrace/interpreter.py | 14 +------ src/gallium/state_trackers/python/samples/tri.py | 14 +------ 4 files changed, 49 insertions(+), 24 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/gallium.i b/src/gallium/state_trackers/python/gallium.i index f4c4b36ea7..bd30d9068f 100644 --- a/src/gallium/state_trackers/python/gallium.i +++ b/src/gallium/state_trackers/python/gallium.i @@ -47,6 +47,7 @@ #include "cso_cache/cso_context.h" #include "util/u_draw_quad.h" #include "util/u_tile.h" +#include "util/u_math.h" #include "tgsi/tgsi_text.h" #include "tgsi/tgsi_dump.h" diff --git a/src/gallium/state_trackers/python/p_texture.i b/src/gallium/state_trackers/python/p_texture.i index 08ba0ebe4d..9396522961 100644 --- a/src/gallium/state_trackers/python/p_texture.i +++ b/src/gallium/state_trackers/python/p_texture.i @@ -121,6 +121,50 @@ pipe_put_tile_rgba($self, x, y, w, h, rgba); } + %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); + void + get_tile_rgba8(unsigned x, unsigned y, unsigned w, unsigned h, char **STRING, int *LENGTH) + { + unsigned surface_usage; + float *rgba; + unsigned char *rgba8; + unsigned i, j, k; + + *LENGTH = 0; + *STRING = NULL; + + if (!$self) + return; + + *LENGTH = h*w*4; + *STRING = (char *) malloc(*LENGTH); + if(!*STRING) + return; + + rgba = malloc(w*4*sizeof(float)); + if(!rgba) + return; + + rgba8 = (unsigned char *) *STRING; + + /* XXX: force mappable surface */ + surface_usage = $self->usage; + $self->usage |= PIPE_BUFFER_USAGE_CPU_READ; + + for(j = 0; j < h; ++j) { + pipe_get_tile_rgba($self, + x, y + j, w, 1, + rgba); + for(i = 0; i < w; ++i) + for(k = 0; k <4; ++k) + rgba8[j*w*4 + i*4 + k] = float_to_ubyte(rgba[i*4 + k]); + } + + $self->usage = surface_usage; + + free(rgba); + } + void get_tile_z(unsigned x, unsigned y, unsigned w, unsigned h, unsigned *z) { pipe_get_tile_z($self, x, y, w, h, z); diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 2a75ee82d5..e6999a2211 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -44,20 +44,10 @@ except ImportError: def make_image(surface): - pixels = gallium.FloatArray(surface.height*surface.width*4) - surface.get_tile_rgba(0, 0, surface.width, surface.height, pixels) + data = surface.get_tile_rgba8(0, 0, surface.width, surface.height) import Image - outimage = Image.new( - mode='RGB', - size=(surface.width, surface.height), - color=(0,0,0)) - outpixels = outimage.load() - for y in range(0, surface.height): - for x in range(0, surface.width): - offset = (y*surface.width + x)*4 - r, g, b, a = [int(pixels[offset + ch]*255) for ch in range(4)] - outpixels[x, y] = r, g, b + outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1) return outimage def save_image(filename, surface): diff --git a/src/gallium/state_trackers/python/samples/tri.py b/src/gallium/state_trackers/python/samples/tri.py index 193479f7d6..d3ccb6c2f4 100644 --- a/src/gallium/state_trackers/python/samples/tri.py +++ b/src/gallium/state_trackers/python/samples/tri.py @@ -31,20 +31,10 @@ from gallium import * def make_image(surface): - pixels = FloatArray(surface.height*surface.width*4) - surface.get_tile_rgba(0, 0, surface.width, surface.height, pixels) + data = surface.get_tile_rgba8(0, 0, surface.width, surface.height) import Image - outimage = Image.new( - mode='RGB', - size=(surface.width, surface.height), - color=(0,0,0)) - outpixels = outimage.load() - for y in range(0, surface.height): - for x in range(0, surface.width): - offset = (y*surface.width + x)*4 - r, g, b, a = [int(pixels[offset + ch]*255) for ch in range(4)] - outpixels[x, y] = r, g, b + outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1) return outimage def save_image(filename, surface): -- cgit v1.2.3 From 5381331f97e55db12cce30859a0156c69894f1d2 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Tue, 24 Mar 2009 21:18:54 +0000 Subject: python: s/num_cbufs/nr_cbufs/ --- src/gallium/state_trackers/python/retrace/interpreter.py | 2 +- src/gallium/state_trackers/python/samples/tri.py | 2 +- src/gallium/state_trackers/python/tests/texture.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index e6999a2211..3050904ece 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -396,7 +396,7 @@ class Context(Object): _state = gallium.Framebuffer() _state.width = state.width _state.height = state.height - _state.num_cbufs = state.num_cbufs + _state.nr_cbufs = state.nr_cbufs for i in range(len(state.cbufs)): _state.set_cbuf(i, state.cbufs[i]) _state.set_zsbuf(state.zsbuf) diff --git a/src/gallium/state_trackers/python/samples/tri.py b/src/gallium/state_trackers/python/samples/tri.py index d3ccb6c2f4..ae065c5b9a 100644 --- a/src/gallium/state_trackers/python/samples/tri.py +++ b/src/gallium/state_trackers/python/samples/tri.py @@ -139,7 +139,7 @@ def test(dev): fb = Framebuffer() fb.width = width fb.height = height - fb.num_cbufs = 1 + fb.nr_cbufs = 1 fb.set_cbuf(0, _cbuf) ctx.set_framebuffer(fb) _cbuf.clear_value = 0x00000000 diff --git a/src/gallium/state_trackers/python/tests/texture.py b/src/gallium/state_trackers/python/tests/texture.py index 880a61306c..8cec57e2a6 100644 --- a/src/gallium/state_trackers/python/tests/texture.py +++ b/src/gallium/state_trackers/python/tests/texture.py @@ -234,7 +234,7 @@ class TextureTest(TestCase): fb = Framebuffer() fb.width = width fb.height = height - fb.num_cbufs = 1 + fb.nr_cbufs = 1 fb.set_cbuf(0, cbuf) ctx.set_framebuffer(fb) ctx.surface_clear(cbuf, 0x00000000) -- cgit v1.2.3 From ad5f9752ce7dc7b588a98e0c1ac820a3f918b4d5 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Tue, 24 Mar 2009 21:21:37 +0000 Subject: python: s/pitch/stride/ --- src/gallium/state_trackers/python/p_context.i | 4 ++-- src/gallium/state_trackers/python/retrace/interpreter.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i index 1fdbdf98b2..178ab0e24e 100644 --- a/src/gallium/state_trackers/python/p_context.i +++ b/src/gallium/state_trackers/python/p_context.i @@ -151,7 +151,7 @@ struct st_context { } void set_vertex_buffer(unsigned index, - unsigned pitch, + unsigned stride, unsigned max_index, unsigned buffer_offset, struct st_buffer *buffer) @@ -160,7 +160,7 @@ struct st_context { struct pipe_vertex_buffer state; memset(&state, 0, sizeof(state)); - state.stride = pitch; + state.stride = stride; state.max_index = max_index; state.buffer_offset = buffer_offset; state.buffer = buffer ? buffer->buffer : NULL; diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 3050904ece..6b9587bf2b 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -424,7 +424,7 @@ class Context(Object): vbuf = vbufs[i] self.real.set_vertex_buffer( i, - pitch = vbuf.pitch, + stride = vbuf.stride, max_index = vbuf.max_index, buffer_offset = vbuf.buffer_offset, buffer = vbuf.buffer, @@ -452,7 +452,7 @@ class Context(Object): for velem in self.velems: vbuf = self.vbufs[velem.vertex_buffer_index] - offset = vbuf.buffer_offset + velem.src_offset + vbuf.pitch*index + offset = vbuf.buffer_offset + velem.src_offset + vbuf.stride*index format = { gallium.PIPE_FORMAT_R32_FLOAT: 'f', gallium.PIPE_FORMAT_R32G32_FLOAT: '2f', -- cgit v1.2.3 From a6ad0c86cab0f3044781ece33d3ac0388e238a36 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Tue, 24 Mar 2009 21:35:10 +0000 Subject: python: Allow to dump all images to disk. --- src/gallium/state_trackers/python/retrace/interpreter.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 6b9587bf2b..66d73ed903 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -75,7 +75,13 @@ def show_image(surface): root.mainloop() +# Verbosity level: 0, 1, 2 verbose = 1 +# Dump images to disk instead of showing: True, False +images = False + + +image_no = 0 class Struct: @@ -538,7 +544,13 @@ class Context(Object): self.real.flush() if self.cbufs and self.cbufs[0]: - show_image(self.cbufs[0]) + if images: + global image_no + image_no += 1 + filename = 'cbuf_%04u.png' % image_no + save_image(filename, self.cbufs[0]) + else: + show_image(self.cbufs[0]) class Interpreter(parser.TraceDumper): -- cgit v1.2.3 From 5743483778ffe5b389d10b1651ae1e8951b397ee Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 25 Mar 2009 10:22:05 +0000 Subject: python: Use Ansi escape codes regardless of output is a tty or not. --- src/gallium/state_trackers/python/retrace/format.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/format.py b/src/gallium/state_trackers/python/retrace/format.py index 0bf6baf0b9..d56d72f606 100755 --- a/src/gallium/state_trackers/python/retrace/format.py +++ b/src/gallium/state_trackers/python/retrace/format.py @@ -27,6 +27,9 @@ ########################################################################## +import sys + + class Formatter: '''Plain formatter''' @@ -93,7 +96,7 @@ class AnsiFormatter(Formatter): def DefaultFormatter(stream): - if stream.isatty(): + if sys.platform in ('linux2', 'cygwin'): return AnsiFormatter(stream) else: return Formatter(stream) -- cgit v1.2.3 From 9d97c3d0be9e57226b6a438a90b71f36e0c99269 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 25 Mar 2009 13:31:27 +0000 Subject: python/trace: Control the interpreter from command line options. --- .../state_trackers/python/retrace/interpreter.py | 80 +++++++++++++--------- .../state_trackers/python/retrace/parser.py | 40 ++++++++--- 2 files changed, 80 insertions(+), 40 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 66d73ed903..23038c5c1c 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -75,15 +75,6 @@ def show_image(surface): root.mainloop() -# Verbosity level: 0, 1, 2 -verbose = 1 -# Dump images to disk instead of showing: True, False -images = False - - -image_no = 0 - - class Struct: """C-like struct""" @@ -381,7 +372,7 @@ class Context(Object): self.real.set_clip(_state) def dump_constant_buffer(self, buffer): - if verbose < 2: + if not self.interpreter.verbosity(2): return data = buffer.read() @@ -447,7 +438,7 @@ class Context(Object): pass def dump_vertices(self, start, count): - if verbose < 2: + if not self.interpreter.verbosity(2): return for index in range(start, start + count): @@ -474,7 +465,7 @@ class Context(Object): sys.stdout.write('\t},\n') def dump_indices(self, ibuf, isize, start, count): - if verbose < 2: + if not self.interpreter.verbosity(2): return format = { @@ -506,51 +497,48 @@ class Context(Object): self.dump_vertices(start, count) self.real.draw_arrays(mode, start, count) - - self.dirty = True + self._set_dirty() def draw_elements(self, indexBuffer, indexSize, mode, start, count): - if verbose >= 2: + if self.interpreter.verbosity(2): minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count) self.dump_vertices(minindex, maxindex - minindex) self.real.draw_elements(indexBuffer, indexSize, mode, start, count) - - self.dirty = True + self._set_dirty() def draw_range_elements(self, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count): - if verbose >= 2: + if self.interpreter.verbosity(2): minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count) minindex = min(minindex, minIndex) maxindex = min(maxindex, maxIndex) self.dump_vertices(minindex, maxindex - minindex) self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count) - - self.dirty = True + self._set_dirty() + def _set_dirty(self): + if self.interpreter.options.step: + self._present() + else: + self.dirty = True + def flush(self, flags): self.real.flush(flags) if self.dirty: if flags & gallium.PIPE_FLUSH_FRAME: - self._update() + self._present() self.dirty = False return None def clear(self, surface, value): self.real.surface_clear(surface, value) - def _update(self): + def _present(self): self.real.flush() if self.cbufs and self.cbufs[0]: - if images: - global image_no - image_no += 1 - filename = 'cbuf_%04u.png' % image_no - save_image(filename, self.cbufs[0]) - else: - show_image(self.cbufs[0]) + self.interpreter.present(self.cbufs[0], "cbuf") class Interpreter(parser.TraceDumper): @@ -561,11 +549,13 @@ class Interpreter(parser.TraceDumper): ('pipe_screen', 'get_paramf'), )) - def __init__(self, stream): + def __init__(self, stream, options): parser.TraceDumper.__init__(self, stream) + self.options = options self.objects = {} self.result = None self.globl = Global(self, None) + self.image_no = 0 def register_object(self, address, object): self.objects[address] = object @@ -586,7 +576,7 @@ class Interpreter(parser.TraceDumper): if (call.klass, call.method) in self.ignore_calls: return - if verbose >= 1: + if self.verbosity(1): parser.TraceDumper.handle_call(self, call) args = [self.interpret_arg(arg) for name, arg in call.args] @@ -606,7 +596,33 @@ class Interpreter(parser.TraceDumper): def interpret_arg(self, node): translator = Translator(self) return translator.visit(node) + + def verbosity(self, level): + return self.options.verbosity >= level + + def present(self, surface, description): + if self.options.images: + self.image_no += 1 + filename = '%s_%04u.png' % (description, self.image_no) + save_image(filename, surface) + else: + show_image(surface) +class Main(parser.Main): + + def get_optparser(self): + optparser = parser.Main.get_optparser(self) + optparser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbosity", help="no messages") + optparser.add_option("-v", "--verbose", action="count", dest="verbosity", default=1, help="increase verbosity level") + optparser.add_option("-i", "--images", action="store_true", dest="images", default=False, help="save images instead of showing them") + optparser.add_option("-s", "--step", action="store_true", dest="step", default=False, help="step trhough every draw") + return optparser + + def process_arg(self, stream, options): + parser = Interpreter(stream, options) + parser.parse() + + if __name__ == '__main__': - parser.main(Interpreter) + Main().main() diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py index 5205f2d8dd..db9bcc8226 100755 --- a/src/gallium/state_trackers/python/retrace/parser.py +++ b/src/gallium/state_trackers/python/retrace/parser.py @@ -30,6 +30,7 @@ import sys import xml.parsers.expat import binascii +import optparse from model import * @@ -342,16 +343,39 @@ class TraceDumper(TraceParser): self.formatter.newline() -def main(ParserFactory): - for arg in sys.argv[1:]: - if arg.endswith('.gz'): - import gzip - stream = gzip.GzipFile(arg, 'rt') +class Main: + '''Common main class for all retrace command line utilities.''' + + def __init__(self): + pass + + def main(self): + optparser = self.get_optparser() + (options, args) = optparser.parse_args(sys.argv[1:]) + + if args: + for arg in args: + if arg.endswith('.gz'): + from gzip import GzipFile + stream = GzipFile(arg, 'rt') + elif arg.endswith('.bz2'): + from bz2 import BZ2File + stream = BZ2File(arg, 'rt') + else: + stream = open(arg, 'rt') + self.process_arg(stream, options) else: - stream = open(arg, 'rt') - parser = ParserFactory(stream) + self.process_arg(stream, options) + + def get_optparser(self): + optparser = optparse.OptionParser( + usage="\n\t%prog [options] [traces] ...") + return optparser + + def process_arg(self, stream, options): + parser = TraceDumper(stream) parser.parse() if __name__ == '__main__': - main(TraceDumper) + Main().main() -- cgit v1.2.3 From ecfa99ece1743769bbdb4371cf57229481993e91 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 25 Mar 2009 13:44:32 +0000 Subject: python: Use a sequential number to identify each call. TODO: Modify the trace driver to generate these on the XML file itself. --- src/gallium/state_trackers/python/retrace/model.py | 4 +++- src/gallium/state_trackers/python/retrace/parser.py | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/model.py b/src/gallium/state_trackers/python/retrace/model.py index ae0f4327d7..d4a079fb1e 100755 --- a/src/gallium/state_trackers/python/retrace/model.py +++ b/src/gallium/state_trackers/python/retrace/model.py @@ -101,7 +101,8 @@ class Pointer(Node): class Call: - def __init__(self, klass, method, args, ret): + def __init__(self, no, klass, method, args, ret): + self.no = no self.klass = klass self.method = method self.args = args @@ -187,6 +188,7 @@ class PrettyPrinter: self.formatter.address(node.address) def visit_call(self, node): + self.formatter.text('%s ' % node.no) if node.klass is not None: self.formatter.function(node.klass + '::' + node.method) else: diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py index db9bcc8226..b0f3e8a432 100755 --- a/src/gallium/state_trackers/python/retrace/parser.py +++ b/src/gallium/state_trackers/python/retrace/parser.py @@ -190,6 +190,10 @@ class XmlParser: class TraceParser(XmlParser): + def __init__(self, fp): + XmlParser.__init__(self, fp) + self.last_call_no = 0 + def parse(self): self.element_start('trace') while self.token.type not in (ELEMENT_END, EOF): @@ -200,6 +204,13 @@ class TraceParser(XmlParser): def parse_call(self): attrs = self.element_start('call') + try: + no = int(attrs['no']) + except KeyError: + self.last_call_no += 1 + no = self.last_call_no + else: + self.last_call_no = no klass = attrs['class'] method = attrs['method'] args = [] @@ -217,7 +228,7 @@ class TraceParser(XmlParser): raise TokenMismatch(" or ", self.token) self.element_end('call') - return Call(klass, method, args, ret) + return Call(no, klass, method, args, ret) def parse_arg(self): attrs = self.element_start('arg') -- cgit v1.2.3 From 710bcc8050848766a85420d0425e51008943fc78 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 25 Mar 2009 14:02:49 +0000 Subject: python/retrace: Use the call no when dumping images. To make it easy associate images with the calls. --- src/gallium/state_trackers/python/retrace/interpreter.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 23038c5c1c..6aaea2d65d 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -555,7 +555,7 @@ class Interpreter(parser.TraceDumper): self.objects = {} self.result = None self.globl = Global(self, None) - self.image_no = 0 + self.call_no = None def register_object(self, address, object): self.objects[address] = object @@ -576,6 +576,8 @@ class Interpreter(parser.TraceDumper): if (call.klass, call.method) in self.ignore_calls: return + self.call_no = call.no + if self.verbosity(1): parser.TraceDumper.handle_call(self, call) @@ -593,6 +595,8 @@ class Interpreter(parser.TraceDumper): if call.ret and isinstance(call.ret, model.Pointer): self.register_object(call.ret.address, ret) + self.call_no = None + def interpret_arg(self, node): translator = Translator(self) return translator.visit(node) @@ -602,8 +606,7 @@ class Interpreter(parser.TraceDumper): def present(self, surface, description): if self.options.images: - self.image_no += 1 - filename = '%s_%04u.png' % (description, self.image_no) + filename = '%s_%04u.png' % (description, self.call_no) save_image(filename, surface) else: show_image(surface) -- cgit v1.2.3 From de89c022d5a2e63b52a9ae27ec70b9f5e203d3ed Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 25 Mar 2009 15:36:51 +0000 Subject: python: Show call no in image window. --- src/gallium/state_trackers/python/retrace/interpreter.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 6aaea2d65d..a22314d200 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -54,14 +54,14 @@ def save_image(filename, surface): outimage = make_image(surface) outimage.save(filename, "PNG") -def show_image(surface): +def show_image(surface, title): outimage = make_image(surface) import Tkinter as tk from PIL import Image, ImageTk root = tk.Tk() - root.title('background image') + root.title(title) image1 = ImageTk.PhotoImage(outimage) w = image1.width() @@ -609,7 +609,8 @@ class Interpreter(parser.TraceDumper): filename = '%s_%04u.png' % (description, self.call_no) save_image(filename, surface) else: - show_image(surface) + title = '%u. %s' % (self.call_no, description) + show_image(surface, title) class Main(parser.Main): -- cgit v1.2.3 From 68342f9036d3c94ee50c4cbe5c7b36439eeb6825 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Mon, 30 Mar 2009 15:09:18 +0100 Subject: python: Hide away the surface usage flags. Surfaces are now by definition GPU views. So CPU access flags don't make any sense when creating a surface. For now we are forcing surfaces to be GPU read/write, but that will go away soon. --- src/gallium/state_trackers/python/p_texture.i | 3 ++- src/gallium/state_trackers/python/retrace/interpreter.py | 2 +- src/gallium/state_trackers/python/samples/tri.py | 6 +++--- src/gallium/state_trackers/python/tests/texture.py | 5 ++--- 4 files changed, 8 insertions(+), 8 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/p_texture.i b/src/gallium/state_trackers/python/p_texture.i index b03054adcc..fee9fb0bf8 100644 --- a/src/gallium/state_trackers/python/p_texture.i +++ b/src/gallium/state_trackers/python/p_texture.i @@ -79,8 +79,9 @@ /** Get a surface which is a "view" into a texture */ struct pipe_surface * - get_surface(unsigned face=0, unsigned level=0, unsigned zslice=0, unsigned usage=0 ) + get_surface(unsigned face=0, unsigned level=0, unsigned zslice=0 ) { + const usage = PIPE_BUFFER_USAGE_GPU_READ_WRITE; struct pipe_screen *screen = $self->screen; return screen->get_tex_surface(screen, $self, face, level, zslice, usage); } diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index a22314d200..510adcc242 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -272,7 +272,7 @@ class Screen(Object): pass def get_tex_surface(self, texture, face, level, zslice, usage): - return texture.get_surface(face, level, zslice, usage) + return texture.get_surface(face, level, zslice) def tex_surface_destroy(self, surface): self.interpreter.unregister_object(surface) diff --git a/src/gallium/state_trackers/python/samples/tri.py b/src/gallium/state_trackers/python/samples/tri.py index 9581b307bf..72e94560af 100644 --- a/src/gallium/state_trackers/python/samples/tri.py +++ b/src/gallium/state_trackers/python/samples/tri.py @@ -135,7 +135,7 @@ def test(dev): width, height, tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET, ) - _cbuf = cbuf.get_surface(usage = PIPE_BUFFER_USAGE_GPU_READ|PIPE_BUFFER_USAGE_GPU_WRITE) + _cbuf = cbuf.get_surface() fb = Framebuffer() fb.width = width fb.height = height @@ -205,8 +205,8 @@ def test(dev): ctx.flush() - show_image(cbuf.get_surface(usage = PIPE_BUFFER_USAGE_CPU_READ|PIPE_BUFFER_USAGE_CPU_WRITE)) - #save_image('tri.png', cbuf.get_surface(usage = PIPE_BUFFER_USAGE_CPU_READ|PIPE_BUFFER_USAGE_CPU_WRITE)) + show_image(cbuf.get_surface()) + #save_image('tri.png', cbuf.get_surface()) diff --git a/src/gallium/state_trackers/python/tests/texture.py b/src/gallium/state_trackers/python/tests/texture.py index ce1c66720b..bd95f734fe 100644 --- a/src/gallium/state_trackers/python/tests/texture.py +++ b/src/gallium/state_trackers/python/tests/texture.py @@ -197,7 +197,6 @@ class TextureTest(TestCase): expected_rgba = FloatArray(height*width*4) texture.get_surface( - usage = PIPE_BUFFER_USAGE_CPU_READ|PIPE_BUFFER_USAGE_CPU_WRITE, face = face, level = level, zslice = zslice, @@ -213,7 +212,7 @@ class TextureTest(TestCase): tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET, ) - cbuf = cbuf_tex.get_surface(usage = PIPE_BUFFER_USAGE_GPU_WRITE|PIPE_BUFFER_USAGE_GPU_READ) + cbuf = cbuf_tex.get_surface() fb = Framebuffer() fb.width = width fb.height = height @@ -290,7 +289,7 @@ class TextureTest(TestCase): ctx.flush() - cbuf = cbuf_tex.get_surface(usage = PIPE_BUFFER_USAGE_CPU_READ) + cbuf = cbuf_tex.get_surface() total = h*w different = cbuf.compare_tile_rgba(x, y, w, h, expected_rgba, tol=4.0/256) -- cgit v1.2.3 From eb168e26aa63f11a47d70c4555cae30691a2cd57 Mon Sep 17 00:00:00 2001 From: Michel Dänzer Date: Sat, 4 Apr 2009 19:01:51 +0200 Subject: gallium: Clean up driver clear() interface. Only allows clearing currently bound buffers, but colour and depth/stencil in a single call. --- src/gallium/auxiliary/util/u_clear.h | 60 +++++++ src/gallium/auxiliary/util/u_pack_color.h | 14 +- src/gallium/drivers/i915simple/i915_clear.c | 13 +- src/gallium/drivers/i915simple/i915_context.h | 4 +- src/gallium/drivers/nv10/nv10_clear.c | 8 +- src/gallium/drivers/nv10/nv10_context.h | 5 +- src/gallium/drivers/nv20/nv20_clear.c | 8 +- src/gallium/drivers/nv20/nv20_context.h | 4 +- src/gallium/drivers/nv30/nv30_clear.c | 8 +- src/gallium/drivers/nv30/nv30_context.h | 4 +- src/gallium/drivers/nv40/nv40_clear.c | 8 +- src/gallium/drivers/nv40/nv40_context.h | 4 +- src/gallium/drivers/nv50/nv50_context.h | 4 +- src/gallium/drivers/softpipe/sp_clear.c | 65 +++----- src/gallium/drivers/softpipe/sp_clear.h | 4 +- src/gallium/drivers/trace/tr_context.c | 21 ++- src/gallium/include/pipe/p_context.h | 16 +- src/gallium/include/pipe/p_defines.h | 9 + src/gallium/state_trackers/g3dvl/vl_basic_csc.c | 3 +- src/gallium/state_trackers/python/p_context.i | 41 +---- .../state_trackers/python/retrace/interpreter.py | 4 +- src/gallium/state_trackers/python/samples/tri.py | 8 +- .../tests/regress/vertex-shader/vertex-shader.py | 7 +- .../state_trackers/python/tests/texture_render.py | 7 +- .../state_trackers/python/tests/texture_sample.py | 7 +- src/mesa/state_tracker/st_cb_clear.c | 183 +++++++-------------- 26 files changed, 263 insertions(+), 256 deletions(-) create mode 100644 src/gallium/auxiliary/util/u_clear.h (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/auxiliary/util/u_clear.h b/src/gallium/auxiliary/util/u_clear.h new file mode 100644 index 0000000000..7c16b32cf9 --- /dev/null +++ b/src/gallium/auxiliary/util/u_clear.h @@ -0,0 +1,60 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. 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 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 TUNGSTEN GRAPHICS 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: + * Michel Dänzer + */ + + +#include "pipe/p_context.h" +#include "pipe/p_state.h" +#include "util/u_pack_color.h" + + +/** + * Clear the given buffers to the specified values. + * No masking, no scissor (clear entire buffer). + */ +static INLINE void +util_clear(struct pipe_context *pipe, + struct pipe_framebuffer_state *framebuffer, unsigned buffers, + const float *rgba, double depth, unsigned stencil) +{ + if (buffers & PIPE_CLEAR_COLOR) { + struct pipe_surface *ps = framebuffer->cbufs[0]; + unsigned color; + + util_pack_color(rgba, ps->format, &color); + pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, color); + } + + if (buffers & PIPE_CLEAR_DEPTHSTENCIL) { + struct pipe_surface *ps = framebuffer->zsbuf; + + pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, + util_pack_z_stencil(ps->format, depth, stencil)); + } +} diff --git a/src/gallium/auxiliary/util/u_pack_color.h b/src/gallium/auxiliary/util/u_pack_color.h index e05d032253..4ec7aee192 100644 --- a/src/gallium/auxiliary/util/u_pack_color.h +++ b/src/gallium/auxiliary/util/u_pack_color.h @@ -448,17 +448,19 @@ util_pack_z(enum pipe_format format, double z) static INLINE uint util_pack_z_stencil(enum pipe_format format, double z, uint s) { + unsigned packed = util_pack_z(format, z); + switch (format) { case PIPE_FORMAT_S8Z24_UNORM: - return util_pack_z(format, z) | s << 24; + packed |= s << 24; + break; case PIPE_FORMAT_Z24S8_UNORM: - return util_pack_z(format, z) | s; + packed |= s; default: - debug_print_format("gallium: unhandled format in util_pack_z_stencil()", - format); - assert(0); - return 0; + break; } + + return packed; } diff --git a/src/gallium/drivers/i915simple/i915_clear.c b/src/gallium/drivers/i915simple/i915_clear.c index cde69daacc..90530f2826 100644 --- a/src/gallium/drivers/i915simple/i915_clear.c +++ b/src/gallium/drivers/i915simple/i915_clear.c @@ -25,23 +25,24 @@ * **************************************************************************/ -/* Author: +/* Authors: * Brian Paul */ -#include "pipe/p_defines.h" +#include "util/u_clear.h" #include "i915_context.h" #include "i915_state.h" /** - * Clear the given surface to the specified value. + * Clear the given buffers to the specified values. * No masking, no scissor (clear entire buffer). */ void -i915_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue) +i915_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, + double depth, unsigned stencil) { - pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); + util_clear(pipe, &i915_context(pipe)->framebuffer, buffers, rgba, depth, + stencil); } diff --git a/src/gallium/drivers/i915simple/i915_context.h b/src/gallium/drivers/i915simple/i915_context.h index 3cdabe45f9..b6983ba86e 100644 --- a/src/gallium/drivers/i915simple/i915_context.h +++ b/src/gallium/drivers/i915simple/i915_context.h @@ -314,8 +314,8 @@ void i915_emit_hardware_state(struct i915_context *i915 ); /*********************************************************************** * i915_clear.c: */ -void i915_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue); +void i915_clear( struct pipe_context *pipe, unsigned buffers, const float *rgba, + double depth, unsigned stencil); /*********************************************************************** diff --git a/src/gallium/drivers/nv10/nv10_clear.c b/src/gallium/drivers/nv10/nv10_clear.c index be7e09cf4b..a39a2b5f52 100644 --- a/src/gallium/drivers/nv10/nv10_clear.c +++ b/src/gallium/drivers/nv10/nv10_clear.c @@ -1,12 +1,14 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" +#include "util/u_clear.h" #include "nv10_context.h" void -nv10_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue) +nv10_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil) { - pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); + util_clear(pipe, nv10_context(pipe)->framebuffer, buffers, rgba, depth, + stencil); } diff --git a/src/gallium/drivers/nv10/nv10_context.h b/src/gallium/drivers/nv10/nv10_context.h index f3b56de25a..f1e003c953 100644 --- a/src/gallium/drivers/nv10/nv10_context.h +++ b/src/gallium/drivers/nv10/nv10_context.h @@ -118,8 +118,9 @@ extern void nv10_init_surface_functions(struct nv10_context *nv10); extern void nv10_screen_init_miptree_functions(struct pipe_screen *pscreen); /* nv10_clear.c */ -extern void nv10_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue); +extern void nv10_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil); + /* nv10_draw.c */ extern struct draw_stage *nv10_draw_render_stage(struct nv10_context *nv10); diff --git a/src/gallium/drivers/nv20/nv20_clear.c b/src/gallium/drivers/nv20/nv20_clear.c index 81b6f3e78a..2b4490fa5e 100644 --- a/src/gallium/drivers/nv20/nv20_clear.c +++ b/src/gallium/drivers/nv20/nv20_clear.c @@ -1,12 +1,14 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" +#include "util/u_clear.h" #include "nv20_context.h" void -nv20_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue) +nv20_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil) { - pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); + util_clear(pipe, nv20_context(pipe)->framebuffer, buffers, rgba, depth, + stencil); } diff --git a/src/gallium/drivers/nv20/nv20_context.h b/src/gallium/drivers/nv20/nv20_context.h index 8ad926db20..fc932f1f90 100644 --- a/src/gallium/drivers/nv20/nv20_context.h +++ b/src/gallium/drivers/nv20/nv20_context.h @@ -118,8 +118,8 @@ extern void nv20_init_surface_functions(struct nv20_context *nv20); extern void nv20_screen_init_miptree_functions(struct pipe_screen *pscreen); /* nv20_clear.c */ -extern void nv20_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue); +extern void nv20_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil); /* nv20_draw.c */ extern struct draw_stage *nv20_draw_render_stage(struct nv20_context *nv20); diff --git a/src/gallium/drivers/nv30/nv30_clear.c b/src/gallium/drivers/nv30/nv30_clear.c index 71f413588e..c4ba926664 100644 --- a/src/gallium/drivers/nv30/nv30_clear.c +++ b/src/gallium/drivers/nv30/nv30_clear.c @@ -1,12 +1,14 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" +#include "util/u_clear.h" #include "nv30_context.h" void -nv30_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue) +nv30_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil) { - pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); + util_clear(pipe, &nv30_context(pipe)->framebuffer, buffers, rgba, depth, + stencil); } diff --git a/src/gallium/drivers/nv30/nv30_context.h b/src/gallium/drivers/nv30/nv30_context.h index b933769700..4229c0a0e1 100644 --- a/src/gallium/drivers/nv30/nv30_context.h +++ b/src/gallium/drivers/nv30/nv30_context.h @@ -206,7 +206,7 @@ extern boolean nv30_draw_elements(struct pipe_context *pipe, unsigned count); /* nv30_clear.c */ -extern void nv30_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue); +extern void nv30_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil); #endif diff --git a/src/gallium/drivers/nv40/nv40_clear.c b/src/gallium/drivers/nv40/nv40_clear.c index 2c4e8f01fd..ddf13addf3 100644 --- a/src/gallium/drivers/nv40/nv40_clear.c +++ b/src/gallium/drivers/nv40/nv40_clear.c @@ -1,12 +1,14 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_state.h" +#include "util/u_clear.h" #include "nv40_context.h" void -nv40_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue) +nv40_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil) { - pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); + util_clear(pipe, &nv40_context(pipe)->framebuffer, buffers, rgba, depth, + stencil); } diff --git a/src/gallium/drivers/nv40/nv40_context.h b/src/gallium/drivers/nv40/nv40_context.h index adcfbdd85a..97bc83292d 100644 --- a/src/gallium/drivers/nv40/nv40_context.h +++ b/src/gallium/drivers/nv40/nv40_context.h @@ -227,7 +227,7 @@ extern boolean nv40_draw_elements(struct pipe_context *pipe, unsigned count); /* nv40_clear.c */ -extern void nv40_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue); +extern void nv40_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil); #endif diff --git a/src/gallium/drivers/nv50/nv50_context.h b/src/gallium/drivers/nv50/nv50_context.h index 313e435e7a..7b67a75439 100644 --- a/src/gallium/drivers/nv50/nv50_context.h +++ b/src/gallium/drivers/nv50/nv50_context.h @@ -184,8 +184,8 @@ extern boolean nv50_draw_elements(struct pipe_context *pipe, extern void nv50_vbo_validate(struct nv50_context *nv50); /* nv50_clear.c */ -extern void nv50_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue); +extern void nv50_clear(struct pipe_context *pipe, unsigned buffers, + const float *rgba, double depth, unsigned stencil); /* nv50_program.c */ extern void nv50_vertprog_validate(struct nv50_context *nv50); diff --git a/src/gallium/drivers/softpipe/sp_clear.c b/src/gallium/drivers/softpipe/sp_clear.c index a60c6c4c16..f72c6c63e7 100644 --- a/src/gallium/drivers/softpipe/sp_clear.c +++ b/src/gallium/drivers/softpipe/sp_clear.c @@ -2,6 +2,7 @@ * * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. + * Copyright 2009 VMware, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -27,6 +28,7 @@ /* Author: * Brian Paul + * Michel Dänzer */ @@ -40,34 +42,15 @@ /** - * Convert packed pixel from one format to another. - */ -static unsigned -convert_color(enum pipe_format srcFormat, unsigned srcColor, - enum pipe_format dstFormat) -{ - ubyte r, g, b, a; - unsigned dstColor; - - util_unpack_color_ub(srcFormat, &srcColor, &r, &g, &b, &a); - util_pack_color_ub(r, g, b, a, dstFormat, &dstColor); - - return dstColor; -} - - - -/** - * Clear the given surface to the specified value. + * Clear the given buffers to the specified values. * No masking, no scissor (clear entire buffer). - * Note: when clearing a color buffer, the clearValue is always - * encoded as PIPE_FORMAT_A8R8G8B8_UNORM. */ void -softpipe_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue) +softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, + double depth, unsigned stencil) { struct softpipe_context *softpipe = softpipe_context(pipe); + unsigned cv; uint i; if (softpipe->no_rast) @@ -77,29 +60,29 @@ softpipe_clear(struct pipe_context *pipe, struct pipe_surface *ps, softpipe_update_derived(softpipe); /* not needed?? */ #endif - if (ps == sp_tile_cache_get_surface(softpipe->zsbuf_cache)) { - sp_tile_cache_clear(softpipe->zsbuf_cache, clearValue); -#if TILE_CLEAR_OPTIMIZATION - return; -#endif - } + if (buffers & PIPE_CLEAR_COLOR) { + for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) { + struct pipe_surface *ps = softpipe->framebuffer.cbufs[i]; - for (i = 0; i < softpipe->framebuffer.nr_cbufs; i++) { - if (ps == sp_tile_cache_get_surface(softpipe->cbuf_cache[i])) { - unsigned cv; - if (ps->format != PIPE_FORMAT_A8R8G8B8_UNORM) { - cv = convert_color(PIPE_FORMAT_A8R8G8B8_UNORM, clearValue, - ps->format); - } - else { - cv = clearValue; - } + util_pack_color(rgba, ps->format, &cv); sp_tile_cache_clear(softpipe->cbuf_cache[i], cv); + +#if !TILE_CLEAR_OPTIMIZATION + /* non-cached surface */ + pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv); +#endif } } + if (buffers & PIPE_CLEAR_DEPTHSTENCIL) { + struct pipe_surface *ps = softpipe->framebuffer.zsbuf; + + cv = util_pack_z_stencil(ps->format, depth, stencil); + sp_tile_cache_clear(softpipe->zsbuf_cache, cv); + #if !TILE_CLEAR_OPTIMIZATION - /* non-cached surface */ - pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, clearValue); + /* non-cached surface */ + pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv); #endif + } } diff --git a/src/gallium/drivers/softpipe/sp_clear.h b/src/gallium/drivers/softpipe/sp_clear.h index a8ed1c4ecc..2e450672f5 100644 --- a/src/gallium/drivers/softpipe/sp_clear.h +++ b/src/gallium/drivers/softpipe/sp_clear.h @@ -36,8 +36,8 @@ struct pipe_context; extern void -softpipe_clear(struct pipe_context *pipe, struct pipe_surface *ps, - unsigned clearValue); +softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, + double depth, unsigned stencil); #endif /* SP_CLEAR_H */ diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index b69ed2cb52..6e86a5dfdd 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -973,21 +973,26 @@ trace_context_surface_fill(struct pipe_context *_pipe, static INLINE void trace_context_clear(struct pipe_context *_pipe, - struct pipe_surface *surface, - unsigned clearValue) + unsigned surfaces, + const float *rgba, + double depth, + unsigned stencil) { struct trace_context *tr_ctx = trace_context(_pipe); struct pipe_context *pipe = tr_ctx->pipe; - surface = trace_surface_unwrap(tr_ctx, surface); - trace_dump_call_begin("pipe_context", "clear"); trace_dump_arg(ptr, pipe); - trace_dump_arg(ptr, surface); - trace_dump_arg(uint, clearValue); - - pipe->clear(pipe, surface, clearValue);; + trace_dump_arg(uint, surfaces); + trace_dump_arg(float, rgba[0]); + trace_dump_arg(float, rgba[1]); + trace_dump_arg(float, rgba[2]); + trace_dump_arg(float, rgba[3]); + trace_dump_arg(float, depth); + trace_dump_arg(uint, stencil); + + pipe->clear(pipe, surfaces, rgba, depth, stencil); trace_dump_call_end(); } diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 2452bf3522..29095dcdc3 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -205,12 +205,20 @@ struct pipe_context { unsigned dstx, unsigned dsty, unsigned width, unsigned height, unsigned value); - - void (*clear)(struct pipe_context *pipe, - struct pipe_surface *ps, - unsigned clearValue); /*@}*/ + /** + * Clear the specified set of currently bound buffers to specified values. + * + * buffers is a bitfield of PIPE_CLEAR_* values. + * + * rgba is a pointer to an array of one float for each of r, g, b, a. + */ + void (*clear)(struct pipe_context *pipe, + unsigned buffers, + const float *rgba, + double depth, + unsigned stencil); /** Flush rendering (flags = bitmask of PIPE_FLUSH_x tokens) */ void (*flush)( struct pipe_context *pipe, diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 8e4f253359..81defa445b 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -185,6 +185,15 @@ enum pipe_texture_target { #define PIPE_SURFACE_LAYOUT_LINEAR 0 +/** + * Clear buffer bits + */ +/** All color buffers currently bound */ +#define PIPE_CLEAR_COLOR (1 << 0) +/** Depth/stencil combined */ +#define PIPE_CLEAR_DEPTHSTENCIL (1 << 1) + + /** * Transfer object usage flags */ diff --git a/src/gallium/state_trackers/g3dvl/vl_basic_csc.c b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c index b61b49a2f8..16d4f1e32c 100644 --- a/src/gallium/state_trackers/g3dvl/vl_basic_csc.c +++ b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c @@ -98,7 +98,8 @@ static int vlResizeFrameBuffer ); /* Clear to black, in case video doesn't fill the entire window */ - pipe->clear(pipe, basic_csc->framebuffer.cbufs[0], 0); + pipe->set_framebuffer_state(pipe, &basic_csc->framebuffer); + pipe->clear(pipe, PIPE_CLEAR_COLOR, 0, 0.0f, 0); return 0; } diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i index a0bf063d81..9a3003a56c 100644 --- a/src/gallium/state_trackers/python/p_context.i +++ b/src/gallium/state_trackers/python/p_context.i @@ -308,45 +308,10 @@ error1: pipe_surface_reference(&_dst, NULL); } - void surface_clear(struct st_surface *surface, unsigned value = 0) + void clear(unsigned buffers, const float *rgba, double depth = 0.0f, + unsigned stencil = 0) { - unsigned i; - struct pipe_surface *_surface = NULL; - - if(!surface) - SWIG_exception(SWIG_TypeError, "surface must not be null"); - - for(i = 0; i < $self->framebuffer.nr_cbufs; ++i) { - struct pipe_surface *cbuf = $self->framebuffer.cbufs[i]; - if(cbuf) { - if(cbuf->texture == surface->texture && - cbuf->face == surface->face && - cbuf->level == surface->level && - cbuf->zslice == surface->zslice) { - _surface = cbuf; - break; - } - } - } - - if(!_surface) { - struct pipe_surface *zsbuf = $self->framebuffer.zsbuf; - if(zsbuf) { - if(zsbuf->texture == surface->texture && - zsbuf->face == surface->face && - zsbuf->level == surface->level && - zsbuf->zslice == surface->zslice) { - _surface = zsbuf; - } - } - } - - if(!_surface) - SWIG_exception(SWIG_ValueError, "surface not bound"); - - $self->pipe->clear($self->pipe, _surface, value); - fail: - return; + $self->pipe->clear($self->pipe, buffers, rgba, depth, stencil); } }; diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 510adcc242..d02099389f 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -531,8 +531,8 @@ class Context(Object): self.dirty = False return None - def clear(self, surface, value): - self.real.surface_clear(surface, value) + def clear(self, buffers, rgba, depth, stencil): + self.real.clear(buffers, rgba, depth, stencil) def _present(self): self.real.flush() diff --git a/src/gallium/state_trackers/python/samples/tri.py b/src/gallium/state_trackers/python/samples/tri.py index 4c84d121c4..4b9659861d 100644 --- a/src/gallium/state_trackers/python/samples/tri.py +++ b/src/gallium/state_trackers/python/samples/tri.py @@ -150,8 +150,12 @@ def test(dev): fb.set_cbuf(0, cbuf) fb.set_zsbuf(zbuf) ctx.set_framebuffer(fb) - ctx.surface_clear(cbuf, 0x00000000) - ctx.surface_clear(zbuf, 0xffffffff) + rgba = FloatArray(4); + rgba[0] = 0.0 + rgba[1] = 0.0 + rgba[2] = 0.0 + rgba[3] = 0.0 + ctx.clear(PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL, rgba, 1.0, 0xff) # vertex shader vs = Shader(''' diff --git a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py index 434ac9b3fc..472769f259 100644 --- a/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py +++ b/src/gallium/state_trackers/python/tests/regress/vertex-shader/vertex-shader.py @@ -122,7 +122,12 @@ def test(dev, name): fb.nr_cbufs = 1 fb.set_cbuf(0, cbuf) ctx.set_framebuffer(fb) - ctx.surface_clear(cbuf, 0x80808080) + rgba = FloatArray(4); + rgba[0] = 0.5 + rgba[1] = 0.5 + rgba[2] = 0.5 + rgba[3] = 0.5 + ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0) # vertex shader vs = Shader(file('vert-' + name + '.sh', 'rt').read()) diff --git a/src/gallium/state_trackers/python/tests/texture_render.py b/src/gallium/state_trackers/python/tests/texture_render.py index 580bf65c13..0b76932b6e 100755 --- a/src/gallium/state_trackers/python/tests/texture_render.py +++ b/src/gallium/state_trackers/python/tests/texture_render.py @@ -161,7 +161,12 @@ class TextureTest(TestCase): fb.nr_cbufs = 1 fb.set_cbuf(0, dst_surface) ctx.set_framebuffer(fb) - ctx.surface_clear(dst_surface, 0x00000000) + rgba = FloatArray(4); + rgba[0] = 0.0 + rgba[1] = 0.0 + rgba[2] = 0.0 + rgba[3] = 0.0 + ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0) del fb # vertex shader diff --git a/src/gallium/state_trackers/python/tests/texture_sample.py b/src/gallium/state_trackers/python/tests/texture_sample.py index f5f49f6e51..a382424667 100755 --- a/src/gallium/state_trackers/python/tests/texture_sample.py +++ b/src/gallium/state_trackers/python/tests/texture_sample.py @@ -206,7 +206,12 @@ class TextureTest(TestCase): fb.nr_cbufs = 1 fb.set_cbuf(0, cbuf) ctx.set_framebuffer(fb) - ctx.surface_clear(cbuf, 0x00000000) + rgba = FloatArray(4); + rgba[0] = 0.5 + rgba[1] = 0.5 + rgba[2] = 0.5 + rgba[3] = 0.5 + ctx.clear(PIPE_CLEAR_COLOR, rgba, 0.0, 0) del fb # vertex shader diff --git a/src/mesa/state_tracker/st_cb_clear.c b/src/mesa/state_tracker/st_cb_clear.c index bec32db050..5bdc6a1330 100644 --- a/src/mesa/state_tracker/st_cb_clear.c +++ b/src/mesa/state_tracker/st_cb_clear.c @@ -2,6 +2,7 @@ * * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas. * All Rights Reserved. + * Copyright 2009 VMware, Inc. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the @@ -29,6 +30,7 @@ * Authors: * Keith Whitwell * Brian Paul + * Michel Dänzer */ #include "main/glheader.h" @@ -373,101 +375,6 @@ check_clear_stencil_with_quad(GLcontext *ctx, struct gl_renderbuffer *rb) -static void -clear_color_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) -{ - struct st_renderbuffer *strb = st_renderbuffer(rb); - - if (!strb->surface) - return; - - if (check_clear_color_with_quad( ctx, rb )) { - /* masking or scissoring */ - clear_with_quad(ctx, GL_TRUE, GL_FALSE, GL_FALSE); - } - else { - /* clear whole buffer w/out masking */ - uint clearValue; - /* NOTE: we always pass the clear color as PIPE_FORMAT_A8R8G8B8_UNORM - * at this time! - */ - util_pack_color(ctx->Color.ClearColor, PIPE_FORMAT_A8R8G8B8_UNORM, &clearValue); - ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue); - } -} - - -static void -clear_depth_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) -{ - struct st_renderbuffer *strb = st_renderbuffer(rb); - - if (!strb->surface) - return; - - if (check_clear_depth_with_quad(ctx, rb)) { - /* scissoring or we have a combined depth/stencil buffer */ - clear_with_quad(ctx, GL_FALSE, GL_TRUE, GL_FALSE); - } - else { - /* simple clear of whole buffer */ - uint clearValue = util_pack_z(strb->surface->format, ctx->Depth.Clear); - ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue); - } -} - - -static void -clear_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) -{ - struct st_renderbuffer *strb = st_renderbuffer(rb); - - if (!strb->surface) - return; - - if (check_clear_stencil_with_quad(ctx, rb)) { - /* masking or scissoring or combined depth/stencil buffer */ - clear_with_quad(ctx, GL_FALSE, GL_FALSE, GL_TRUE); - } - else { - /* simple clear of whole buffer */ - GLuint clearValue = ctx->Stencil.Clear; - - switch (strb->surface->format) { - case PIPE_FORMAT_S8Z24_UNORM: - clearValue <<= 24; - break; - default: - ; /* no-op, stencil value is in least significant bits */ - } - - ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue); - } -} - - -static void -clear_depth_stencil_buffer(GLcontext *ctx, struct gl_renderbuffer *rb) -{ - struct st_renderbuffer *strb = st_renderbuffer(rb); - - if (!strb->surface) - return; - - if (check_clear_depth_stencil_with_quad(ctx, rb)) { - /* masking or scissoring */ - clear_with_quad(ctx, GL_FALSE, GL_TRUE, GL_TRUE); - } - else { - /* clear whole buffer w/out masking */ - GLuint clearValue = util_pack_z_stencil(strb->surface->format, - ctx->Depth.Clear, - ctx->Stencil.Clear); - ctx->st->pipe->clear(ctx->st->pipe, strb->surface, clearValue); - } -} - - void st_flush_clear( struct st_context *st ) { /* Release vertex buffer to avoid synchronous rendering if we were @@ -493,51 +400,89 @@ static void st_clear(GLcontext *ctx, GLbitfield mask) = ctx->DrawBuffer->Attachment[BUFFER_DEPTH].Renderbuffer; struct gl_renderbuffer *stencilRb = ctx->DrawBuffer->Attachment[BUFFER_STENCIL].Renderbuffer; - GLbitfield cmask = mask & BUFFER_BITS_COLOR; + GLbitfield quad_buffers = 0; + GLbitfield clear_buffers = 0; + GLuint i; - /* This makes sure the softpipe has the latest scissor, etc values */ + /* This makes sure the pipe has the latest scissor, etc values */ st_validate_state( st ); - /* - * XXX TO-DO: - * If we're going to use clear_with_quad() for any reason, use it to - * clear as many other buffers as possible. - * As it is now, we sometimes call clear_with_quad() three times to clear - * color/depth/stencil individually... - */ + if (mask & BUFFER_BITS_COLOR) { + for (i = 0; i < ctx->DrawBuffer->_NumColorDrawBuffers; i++) { + GLuint b = ctx->DrawBuffer->_ColorDrawBufferIndexes[i]; - if (cmask) { - GLuint b; - for (b = 0; cmask; b++) { - if (cmask & (1 << b)) { + if (mask & (1 << b)) { struct gl_renderbuffer *rb = ctx->DrawBuffer->Attachment[b].Renderbuffer; + struct st_renderbuffer *strb; + assert(rb); - clear_color_buffer(ctx, rb); - cmask &= ~(1 << b); /* turn off bit */ + + strb = st_renderbuffer(rb); + + if (!strb->surface) + continue; + + if (check_clear_color_with_quad( ctx, rb )) + quad_buffers |= PIPE_CLEAR_COLOR; + else + clear_buffers |= PIPE_CLEAR_COLOR; } - assert(b < BUFFER_COUNT); } } - if (mask & BUFFER_BIT_ACCUM) { - st_clear_accum_buffer(ctx, - ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); - } - if ((mask & BUFFER_BITS_DS) == BUFFER_BITS_DS && depthRb == stencilRb) { /* clearing combined depth + stencil */ - clear_depth_stencil_buffer(ctx, depthRb); + struct st_renderbuffer *strb = st_renderbuffer(depthRb); + + if (strb->surface) { + if (check_clear_depth_stencil_with_quad(ctx, depthRb)) + quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + else + clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + } } else { /* separate depth/stencil clears */ if (mask & BUFFER_BIT_DEPTH) { - clear_depth_buffer(ctx, depthRb); + struct st_renderbuffer *strb = st_renderbuffer(depthRb); + + if (strb->surface) { + if (check_clear_depth_with_quad(ctx, depthRb)) + quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + else + clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + } } if (mask & BUFFER_BIT_STENCIL) { - clear_stencil_buffer(ctx, stencilRb); + struct st_renderbuffer *strb = st_renderbuffer(stencilRb); + + if (strb->surface) { + if (check_clear_stencil_with_quad(ctx, stencilRb)) + quad_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + else + clear_buffers |= PIPE_CLEAR_DEPTHSTENCIL; + } } } + + /* + * If we're going to use clear_with_quad() for any reason, use it for + * everything possible. + */ + if (quad_buffers) { + quad_buffers |= clear_buffers; + clear_with_quad(ctx, + quad_buffers & PIPE_CLEAR_COLOR, + mask & BUFFER_BIT_DEPTH, + mask & BUFFER_BIT_STENCIL); + } else if (clear_buffers) + ctx->st->pipe->clear(ctx->st->pipe, clear_buffers, ctx->Color.ClearColor, + ctx->Depth.Clear, ctx->Stencil.Clear); + + if (mask & BUFFER_BIT_ACCUM) + st_clear_accum_buffer(ctx, + ctx->DrawBuffer->Attachment[BUFFER_ACCUM].Renderbuffer); } -- cgit v1.2.3 From c14562d3b1e5d93d5704f3195a7f83fc5c17eddb Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 8 Apr 2009 15:36:17 +0100 Subject: python/retrace: Handle recent traces. Try to keep backwards compatability with old traces as much as possible. --- .../state_trackers/python/retrace/interpreter.py | 115 +++++++++++++++------ 1 file changed, 85 insertions(+), 30 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index d02099389f..708937119f 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -181,8 +181,12 @@ class Global(Object): def pipe_winsys_create(self): return Winsys(self.interpreter, gallium.Device()) - def pipe_screen_create(self, winsys): - return Screen(self.interpreter, winsys.real) + def pipe_screen_create(self, winsys=None): + if winsys is None: + real = gallium.Device() + else: + real = winsys.real + return Screen(self.interpreter, real) def pipe_context_create(self, screen): context = screen.real.context_create() @@ -234,6 +238,16 @@ class Winsys(Object): pass +class Transfer: + + def __init__(self, surface, x, y, w, h): + self.surface = surface + self.x = x + self.y = y + self.w = w + self.h = h + + class Screen(Object): def destroy(self): @@ -254,15 +268,15 @@ class Screen(Object): def is_format_supported(self, format, target, tex_usage, geom_flags): return self.real.is_format_supported(format, target, tex_usage, geom_flags) - def texture_create(self, template): + def texture_create(self, templat): return self.real.texture_create( - format = template.format, - width = template.width[0], - height = template.height[0], - depth = template.depth[0], - last_level = template.last_level, - target = template.target, - tex_usage = template.tex_usage, + format = templat.format, + width = templat.width[0], + height = templat.height[0], + depth = templat.depth[0], + last_level = templat.last_level, + target = templat.target, + tex_usage = templat.tex_usage, ) def texture_destroy(self, texture): @@ -284,6 +298,44 @@ class Screen(Object): assert surface.nblocksy * stride == size surface.put_tile_raw(0, 0, surface.width, surface.height, data, stride) + def get_tex_transfer(self, texture, face, level, zslice, usage, x, y, w, h): + return Transfer(texture.get_surface(face, level, zslice), x, y, w, h) + + def tex_transfer_destroy(self, transfer): + self.interpreter.unregister_object(transfer) + + def transfer_write(self, transfer, stride, data, size): + transfer.surface.put_tile_raw(transfer.x, transfer.y, transfer.w, transfer.h, data, stride) + + def user_buffer_create(self, data, size): + # We don't really care to distinguish between user and regular buffers + buffer = self.real.buffer_create(size, + 4, + gallium.PIPE_BUFFER_USAGE_CPU_READ | + gallium.PIPE_BUFFER_USAGE_CPU_WRITE ) + assert size == len(data) + buffer.write(data) + return buffer + + def buffer_create(self, alignment, usage, size): + return self.real.buffer_create(size, alignment, usage) + + def buffer_destroy(self, buffer): + pass + + def buffer_write(self, buffer, data, size, offset=0): + assert size == len(data) + buffer.write(data) + + def fence_finish(self, fence, flags): + pass + + def fence_reference(self, dst, src): + pass + + def flush_frontbuffer(self, surface): + pass + class Context(Object): @@ -314,8 +366,8 @@ class Context(Object): def delete_sampler_state(self, state): pass - def bind_sampler_states(self, n, states): - for i in range(n): + def bind_sampler_states(self, num_states, states): + for i in range(num_states): self.real.set_sampler(i, states[i]) def create_rasterizer_state(self, state): @@ -383,11 +435,11 @@ class Context(Object): sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w)) index += 1 - def set_constant_buffer(self, shader, index, state): - if state is not None: - self.real.set_constant_buffer(shader, index, state.buffer) + def set_constant_buffer(self, shader, index, buffer): + if buffer is not None: + self.real.set_constant_buffer(shader, index, buffer.buffer) - self.dump_constant_buffer(state.buffer) + self.dump_constant_buffer(buffer.buffer) def set_framebuffer_state(self, state): _state = gallium.Framebuffer() @@ -411,14 +463,14 @@ class Context(Object): def set_viewport_state(self, state): self.real.set_viewport(state) - def set_sampler_textures(self, n, textures): - for i in range(n): + def set_sampler_textures(self, num_textures, textures): + for i in range(num_textures): self.real.set_sampler_texture(i, textures[i]) - def set_vertex_buffers(self, n, vbufs): - self.vbufs = vbufs[0:n] - for i in range(n): - vbuf = vbufs[i] + def set_vertex_buffers(self, num_buffers, buffers): + self.vbufs = buffers[0:num_buffers] + for i in range(num_buffers): + vbuf = buffers[i] self.real.set_vertex_buffer( i, stride = vbuf.stride, @@ -427,11 +479,11 @@ class Context(Object): buffer = vbuf.buffer, ) - def set_vertex_elements(self, n, elements): - self.velems = elements[0:n] - for i in range(n): + def set_vertex_elements(self, num_elements, elements): + self.velems = elements[0:num_elements] + for i in range(num_elements): self.real.set_vertex_element(i, elements[i]) - self.real.set_vertex_elements(n) + self.real.set_vertex_elements(num_elements) def set_edgeflags(self, bitfield): # FIXME @@ -532,7 +584,10 @@ class Context(Object): return None def clear(self, buffers, rgba, depth, stencil): - self.real.clear(buffers, rgba, depth, stencil) + _rgba = gallium.FloatArray(4) + for i in range(4): + _rgba[i] = rgba[i] + self.real.clear(buffers, _rgba, depth, stencil) def _present(self): self.real.flush() @@ -581,16 +636,16 @@ class Interpreter(parser.TraceDumper): if self.verbosity(1): parser.TraceDumper.handle_call(self, call) - args = [self.interpret_arg(arg) for name, arg in call.args] + args = [(str(name), self.interpret_arg(arg)) for name, arg in call.args] if call.klass: - obj = args[0] + name, obj = args[0] args = args[1:] else: obj = self.globl method = getattr(obj, call.method) - ret = method(*args) + ret = method(**dict(args)) if call.ret and isinstance(call.ret, model.Pointer): self.register_object(call.ret.address, ret) -- cgit v1.2.3 From 84e784665aa5b64c11538e90f0ff1482899a1965 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 8 Apr 2009 16:25:29 +0100 Subject: python/retrace: Allow to specify the range of calls of interest. --- src/gallium/state_trackers/python/retrace/interpreter.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 708937119f..0f1c56075a 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -627,6 +627,8 @@ class Interpreter(parser.TraceDumper): self.interpret_call(call) def handle_call(self, call): + if self.options.stop and call.no >= self.options.stop: + sys.exit(0) if (call.klass, call.method) in self.ignore_calls: return @@ -660,6 +662,9 @@ class Interpreter(parser.TraceDumper): return self.options.verbosity >= level def present(self, surface, description): + if self.call_no < self.options.start: + return + if self.options.images: filename = '%s_%04u.png' % (description, self.call_no) save_image(filename, surface) @@ -676,6 +681,8 @@ class Main(parser.Main): optparser.add_option("-v", "--verbose", action="count", dest="verbosity", default=1, help="increase verbosity level") optparser.add_option("-i", "--images", action="store_true", dest="images", default=False, help="save images instead of showing them") optparser.add_option("-s", "--step", action="store_true", dest="step", default=False, help="step trhough every draw") + optparser.add_option("-f", "--from", action="store", type="int", dest="start", default=0, help="from call no") + optparser.add_option("-t", "--to", action="store", type="int", dest="stop", default=0, help="until call no") return optparser def process_arg(self, stream, options): -- cgit v1.2.3 From 4342d6a91f754c9d3e7087ed91b7acf89abbb293 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 8 Apr 2009 21:11:24 +0100 Subject: python/retrace: Use colors on windows console. --- .../state_trackers/python/retrace/format.py | 70 ++++++++++++++++++++++ 1 file changed, 70 insertions(+) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/format.py b/src/gallium/state_trackers/python/retrace/format.py index d56d72f606..a4285bfe07 100755 --- a/src/gallium/state_trackers/python/retrace/format.py +++ b/src/gallium/state_trackers/python/retrace/format.py @@ -94,10 +94,80 @@ class AnsiFormatter(Formatter): self._escape(self._normal) +class WindowsConsoleFormatter(Formatter): + '''Formatter for the Windows Console. See + http://code.activestate.com/recipes/496901/ for more information. + ''' + + STD_INPUT_HANDLE = -10 + STD_OUTPUT_HANDLE = -11 + STD_ERROR_HANDLE = -12 + + FOREGROUND_BLUE = 0x01 + FOREGROUND_GREEN = 0x02 + FOREGROUND_RED = 0x04 + FOREGROUND_INTENSITY = 0x08 + BACKGROUND_BLUE = 0x10 + BACKGROUND_GREEN = 0x20 + BACKGROUND_RED = 0x40 + BACKGROUND_INTENSITY = 0x80 + + _normal = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED + _bold = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY + _italic = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED + _red = FOREGROUND_RED | FOREGROUND_INTENSITY + _green = FOREGROUND_GREEN | FOREGROUND_INTENSITY + _blue = FOREGROUND_BLUE | FOREGROUND_INTENSITY + + def __init__(self, stream): + Formatter.__init__(self, stream) + + if stream is sys.stdin: + nStdHandle = self.STD_INPUT_HANDLE + elif stream is sys.stdout: + nStdHandle = self.STD_OUTPUT_HANDLE + elif stream is sys.stderr: + nStdHandle = self.STD_ERROR_HANDLE + else: + nStdHandle = None + + if nStdHandle: + import ctypes + self.handle = ctypes.windll.kernel32.GetStdHandle(nStdHandle) + else: + self.handle = None + + def _attribute(self, attr): + if self.handle: + import ctypes + ctypes.windll.kernel32.SetConsoleTextAttribute(self.handle, attr) + + def function(self, name): + self._attribute(self._bold) + Formatter.function(self, name) + self._attribute(self._normal) + + def variable(self, name): + self._attribute(self._italic) + Formatter.variable(self, name) + self._attribute(self._normal) + + def literal(self, value): + self._attribute(self._blue) + Formatter.literal(self, value) + self._attribute(self._normal) + + def address(self, value): + self._attribute(self._green) + Formatter.address(self, value) + self._attribute(self._normal) + def DefaultFormatter(stream): if sys.platform in ('linux2', 'cygwin'): return AnsiFormatter(stream) + elif sys.platform in ('win32',): + return WindowsConsoleFormatter(stream) else: return Formatter(stream) -- cgit v1.2.3 From 71504c770086797ef8cf0a57f89565ec3e574ee3 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 8 Apr 2009 21:13:57 +0100 Subject: python/retrace: Try to cope with failures creating textures. --- src/gallium/state_trackers/python/retrace/interpreter.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 0f1c56075a..5ea07724a5 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -286,6 +286,8 @@ class Screen(Object): pass def get_tex_surface(self, texture, face, level, zslice, usage): + if texture is None: + return None return texture.get_surface(face, level, zslice) def tex_surface_destroy(self, surface): @@ -295,16 +297,22 @@ class Screen(Object): pass def surface_write(self, surface, data, stride, size): + if surface is None: + return assert surface.nblocksy * stride == size surface.put_tile_raw(0, 0, surface.width, surface.height, data, stride) def get_tex_transfer(self, texture, face, level, zslice, usage, x, y, w, h): + if texture is None: + return None return Transfer(texture.get_surface(face, level, zslice), x, y, w, h) def tex_transfer_destroy(self, transfer): self.interpreter.unregister_object(transfer) def transfer_write(self, transfer, stride, data, size): + if transfer is None: + return transfer.surface.put_tile_raw(transfer.x, transfer.y, transfer.w, transfer.h, data, stride) def user_buffer_create(self, data, size): @@ -650,6 +658,8 @@ class Interpreter(parser.TraceDumper): ret = method(**dict(args)) if call.ret and isinstance(call.ret, model.Pointer): + if ret is None: + sys.stderr.write('warning: NULL returned\n') self.register_object(call.ret.address, ret) self.call_no = None -- cgit v1.2.3 From 3a618da6e15a6dc4351eb933583569a1ecefc768 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Fri, 17 Apr 2009 10:07:53 +0100 Subject: python/retrace: Rename module as it conflicts with a builtin module. And there is no way to override a builtin module... sigh --- .../state_trackers/python/retrace/interpreter.py | 2 +- src/gallium/state_trackers/python/retrace/parse.py | 392 +++++++++++++++++++++ .../state_trackers/python/retrace/parser.py | 360 +------------------ 3 files changed, 394 insertions(+), 360 deletions(-) create mode 100755 src/gallium/state_trackers/python/retrace/parse.py (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 5ea07724a5..5d4d04498b 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -32,7 +32,7 @@ import struct import gallium import model -import parser +import parse as parser try: diff --git a/src/gallium/state_trackers/python/retrace/parse.py b/src/gallium/state_trackers/python/retrace/parse.py new file mode 100755 index 0000000000..b0f3e8a432 --- /dev/null +++ b/src/gallium/state_trackers/python/retrace/parse.py @@ -0,0 +1,392 @@ +#!/usr/bin/env python +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# 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 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 TUNGSTEN GRAPHICS 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. +# +########################################################################## + + +import sys +import xml.parsers.expat +import binascii +import optparse + +from model import * + + +ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4) + + +class XmlToken: + + def __init__(self, type, name_or_data, attrs = None, line = None, column = None): + assert type in (ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF) + self.type = type + self.name_or_data = name_or_data + self.attrs = attrs + self.line = line + self.column = column + + def __str__(self): + if self.type == ELEMENT_START: + return '<' + self.name_or_data + ' ...>' + if self.type == ELEMENT_END: + return '' + if self.type == CHARACTER_DATA: + return self.name_or_data + if self.type == EOF: + return 'end of file' + assert 0 + + +class XmlTokenizer: + """Expat based XML tokenizer.""" + + def __init__(self, fp, skip_ws = True): + self.fp = fp + self.tokens = [] + self.index = 0 + self.final = False + self.skip_ws = skip_ws + + self.character_pos = 0, 0 + self.character_data = '' + + self.parser = xml.parsers.expat.ParserCreate() + self.parser.StartElementHandler = self.handle_element_start + self.parser.EndElementHandler = self.handle_element_end + self.parser.CharacterDataHandler = self.handle_character_data + + def handle_element_start(self, name, attributes): + self.finish_character_data() + line, column = self.pos() + token = XmlToken(ELEMENT_START, name, attributes, line, column) + self.tokens.append(token) + + def handle_element_end(self, name): + self.finish_character_data() + line, column = self.pos() + token = XmlToken(ELEMENT_END, name, None, line, column) + self.tokens.append(token) + + def handle_character_data(self, data): + if not self.character_data: + self.character_pos = self.pos() + self.character_data += data + + def finish_character_data(self): + if self.character_data: + if not self.skip_ws or not self.character_data.isspace(): + line, column = self.character_pos + token = XmlToken(CHARACTER_DATA, self.character_data, None, line, column) + self.tokens.append(token) + self.character_data = '' + + def next(self): + size = 16*1024 + while self.index >= len(self.tokens) and not self.final: + self.tokens = [] + self.index = 0 + data = self.fp.read(size) + self.final = len(data) < size + data = data.rstrip('\0') + try: + self.parser.Parse(data, self.final) + except xml.parsers.expat.ExpatError, e: + #if e.code == xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS: + if e.code == 3: + pass + else: + raise e + if self.index >= len(self.tokens): + line, column = self.pos() + token = XmlToken(EOF, None, None, line, column) + else: + token = self.tokens[self.index] + self.index += 1 + return token + + def pos(self): + return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber + + +class TokenMismatch(Exception): + + def __init__(self, expected, found): + self.expected = expected + self.found = found + + def __str__(self): + return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found)) + + + +class XmlParser: + """Base XML document parser.""" + + def __init__(self, fp): + self.tokenizer = XmlTokenizer(fp) + self.consume() + + def consume(self): + self.token = self.tokenizer.next() + + def match_element_start(self, name): + return self.token.type == ELEMENT_START and self.token.name_or_data == name + + def match_element_end(self, name): + return self.token.type == ELEMENT_END and self.token.name_or_data == name + + def element_start(self, name): + while self.token.type == CHARACTER_DATA: + self.consume() + if self.token.type != ELEMENT_START: + raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) + if self.token.name_or_data != name: + raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) + attrs = self.token.attrs + self.consume() + return attrs + + def element_end(self, name): + while self.token.type == CHARACTER_DATA: + self.consume() + if self.token.type != ELEMENT_END: + raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) + if self.token.name_or_data != name: + raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) + self.consume() + + def character_data(self, strip = True): + data = '' + while self.token.type == CHARACTER_DATA: + data += self.token.name_or_data + self.consume() + if strip: + data = data.strip() + return data + + +class TraceParser(XmlParser): + + def __init__(self, fp): + XmlParser.__init__(self, fp) + self.last_call_no = 0 + + def parse(self): + self.element_start('trace') + while self.token.type not in (ELEMENT_END, EOF): + call = self.parse_call() + self.handle_call(call) + if self.token.type != EOF: + self.element_end('trace') + + def parse_call(self): + attrs = self.element_start('call') + try: + no = int(attrs['no']) + except KeyError: + self.last_call_no += 1 + no = self.last_call_no + else: + self.last_call_no = no + klass = attrs['class'] + method = attrs['method'] + args = [] + ret = None + while self.token.type == ELEMENT_START: + if self.token.name_or_data == 'arg': + arg = self.parse_arg() + args.append(arg) + elif self.token.name_or_data == 'ret': + ret = self.parse_ret() + elif self.token.name_or_data == 'call': + # ignore nested function calls + self.parse_call() + else: + raise TokenMismatch(" or ", self.token) + self.element_end('call') + + return Call(no, klass, method, args, ret) + + def parse_arg(self): + attrs = self.element_start('arg') + name = attrs['name'] + value = self.parse_value() + self.element_end('arg') + + return name, value + + def parse_ret(self): + attrs = self.element_start('ret') + value = self.parse_value() + self.element_end('ret') + + return value + + def parse_value(self): + expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes') + if self.token.type == ELEMENT_START: + if self.token.name_or_data in expected_tokens: + method = getattr(self, 'parse_' + self.token.name_or_data) + return method() + raise TokenMismatch(" or " .join(expected_tokens), self.token) + + def parse_null(self): + self.element_start('null') + self.element_end('null') + return Literal(None) + + def parse_bool(self): + self.element_start('bool') + value = int(self.character_data()) + self.element_end('bool') + return Literal(value) + + def parse_int(self): + self.element_start('int') + value = int(self.character_data()) + self.element_end('int') + return Literal(value) + + def parse_uint(self): + self.element_start('uint') + value = int(self.character_data()) + self.element_end('uint') + return Literal(value) + + def parse_float(self): + self.element_start('float') + value = float(self.character_data()) + self.element_end('float') + return Literal(value) + + def parse_enum(self): + self.element_start('enum') + name = self.character_data() + self.element_end('enum') + return NamedConstant(name) + + def parse_string(self): + self.element_start('string') + value = self.character_data() + self.element_end('string') + return Literal(value) + + def parse_bytes(self): + self.element_start('bytes') + value = binascii.a2b_hex(self.character_data()) + self.element_end('bytes') + return Literal(value) + + def parse_array(self): + self.element_start('array') + elems = [] + while self.token.type != ELEMENT_END: + elems.append(self.parse_elem()) + self.element_end('array') + return Array(elems) + + def parse_elem(self): + self.element_start('elem') + value = self.parse_value() + self.element_end('elem') + return value + + def parse_struct(self): + attrs = self.element_start('struct') + name = attrs['name'] + members = [] + while self.token.type != ELEMENT_END: + members.append(self.parse_member()) + self.element_end('struct') + return Struct(name, members) + + def parse_member(self): + attrs = self.element_start('member') + name = attrs['name'] + value = self.parse_value() + self.element_end('member') + + return name, value + + def parse_ptr(self): + self.element_start('ptr') + address = self.character_data() + self.element_end('ptr') + + return Pointer(address) + + def handle_call(self, call): + pass + + +class TraceDumper(TraceParser): + + def __init__(self, fp): + TraceParser.__init__(self, fp) + self.formatter = format.DefaultFormatter(sys.stdout) + self.pretty_printer = PrettyPrinter(self.formatter) + + def handle_call(self, call): + call.visit(self.pretty_printer) + self.formatter.newline() + + +class Main: + '''Common main class for all retrace command line utilities.''' + + def __init__(self): + pass + + def main(self): + optparser = self.get_optparser() + (options, args) = optparser.parse_args(sys.argv[1:]) + + if args: + for arg in args: + if arg.endswith('.gz'): + from gzip import GzipFile + stream = GzipFile(arg, 'rt') + elif arg.endswith('.bz2'): + from bz2 import BZ2File + stream = BZ2File(arg, 'rt') + else: + stream = open(arg, 'rt') + self.process_arg(stream, options) + else: + self.process_arg(stream, options) + + def get_optparser(self): + optparser = optparse.OptionParser( + usage="\n\t%prog [options] [traces] ...") + return optparser + + def process_arg(self, stream, options): + parser = TraceDumper(stream) + parser.parse() + + +if __name__ == '__main__': + Main().main() diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py index b0f3e8a432..bd47c9a6b0 100755 --- a/src/gallium/state_trackers/python/retrace/parser.py +++ b/src/gallium/state_trackers/python/retrace/parser.py @@ -27,365 +27,7 @@ ########################################################################## -import sys -import xml.parsers.expat -import binascii -import optparse - -from model import * - - -ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4) - - -class XmlToken: - - def __init__(self, type, name_or_data, attrs = None, line = None, column = None): - assert type in (ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF) - self.type = type - self.name_or_data = name_or_data - self.attrs = attrs - self.line = line - self.column = column - - def __str__(self): - if self.type == ELEMENT_START: - return '<' + self.name_or_data + ' ...>' - if self.type == ELEMENT_END: - return '' - if self.type == CHARACTER_DATA: - return self.name_or_data - if self.type == EOF: - return 'end of file' - assert 0 - - -class XmlTokenizer: - """Expat based XML tokenizer.""" - - def __init__(self, fp, skip_ws = True): - self.fp = fp - self.tokens = [] - self.index = 0 - self.final = False - self.skip_ws = skip_ws - - self.character_pos = 0, 0 - self.character_data = '' - - self.parser = xml.parsers.expat.ParserCreate() - self.parser.StartElementHandler = self.handle_element_start - self.parser.EndElementHandler = self.handle_element_end - self.parser.CharacterDataHandler = self.handle_character_data - - def handle_element_start(self, name, attributes): - self.finish_character_data() - line, column = self.pos() - token = XmlToken(ELEMENT_START, name, attributes, line, column) - self.tokens.append(token) - - def handle_element_end(self, name): - self.finish_character_data() - line, column = self.pos() - token = XmlToken(ELEMENT_END, name, None, line, column) - self.tokens.append(token) - - def handle_character_data(self, data): - if not self.character_data: - self.character_pos = self.pos() - self.character_data += data - - def finish_character_data(self): - if self.character_data: - if not self.skip_ws or not self.character_data.isspace(): - line, column = self.character_pos - token = XmlToken(CHARACTER_DATA, self.character_data, None, line, column) - self.tokens.append(token) - self.character_data = '' - - def next(self): - size = 16*1024 - while self.index >= len(self.tokens) and not self.final: - self.tokens = [] - self.index = 0 - data = self.fp.read(size) - self.final = len(data) < size - data = data.rstrip('\0') - try: - self.parser.Parse(data, self.final) - except xml.parsers.expat.ExpatError, e: - #if e.code == xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS: - if e.code == 3: - pass - else: - raise e - if self.index >= len(self.tokens): - line, column = self.pos() - token = XmlToken(EOF, None, None, line, column) - else: - token = self.tokens[self.index] - self.index += 1 - return token - - def pos(self): - return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber - - -class TokenMismatch(Exception): - - def __init__(self, expected, found): - self.expected = expected - self.found = found - - def __str__(self): - return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found)) - - - -class XmlParser: - """Base XML document parser.""" - - def __init__(self, fp): - self.tokenizer = XmlTokenizer(fp) - self.consume() - - def consume(self): - self.token = self.tokenizer.next() - - def match_element_start(self, name): - return self.token.type == ELEMENT_START and self.token.name_or_data == name - - def match_element_end(self, name): - return self.token.type == ELEMENT_END and self.token.name_or_data == name - - def element_start(self, name): - while self.token.type == CHARACTER_DATA: - self.consume() - if self.token.type != ELEMENT_START: - raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) - if self.token.name_or_data != name: - raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) - attrs = self.token.attrs - self.consume() - return attrs - - def element_end(self, name): - while self.token.type == CHARACTER_DATA: - self.consume() - if self.token.type != ELEMENT_END: - raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) - if self.token.name_or_data != name: - raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) - self.consume() - - def character_data(self, strip = True): - data = '' - while self.token.type == CHARACTER_DATA: - data += self.token.name_or_data - self.consume() - if strip: - data = data.strip() - return data - - -class TraceParser(XmlParser): - - def __init__(self, fp): - XmlParser.__init__(self, fp) - self.last_call_no = 0 - - def parse(self): - self.element_start('trace') - while self.token.type not in (ELEMENT_END, EOF): - call = self.parse_call() - self.handle_call(call) - if self.token.type != EOF: - self.element_end('trace') - - def parse_call(self): - attrs = self.element_start('call') - try: - no = int(attrs['no']) - except KeyError: - self.last_call_no += 1 - no = self.last_call_no - else: - self.last_call_no = no - klass = attrs['class'] - method = attrs['method'] - args = [] - ret = None - while self.token.type == ELEMENT_START: - if self.token.name_or_data == 'arg': - arg = self.parse_arg() - args.append(arg) - elif self.token.name_or_data == 'ret': - ret = self.parse_ret() - elif self.token.name_or_data == 'call': - # ignore nested function calls - self.parse_call() - else: - raise TokenMismatch(" or ", self.token) - self.element_end('call') - - return Call(no, klass, method, args, ret) - - def parse_arg(self): - attrs = self.element_start('arg') - name = attrs['name'] - value = self.parse_value() - self.element_end('arg') - - return name, value - - def parse_ret(self): - attrs = self.element_start('ret') - value = self.parse_value() - self.element_end('ret') - - return value - - def parse_value(self): - expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes') - if self.token.type == ELEMENT_START: - if self.token.name_or_data in expected_tokens: - method = getattr(self, 'parse_' + self.token.name_or_data) - return method() - raise TokenMismatch(" or " .join(expected_tokens), self.token) - - def parse_null(self): - self.element_start('null') - self.element_end('null') - return Literal(None) - - def parse_bool(self): - self.element_start('bool') - value = int(self.character_data()) - self.element_end('bool') - return Literal(value) - - def parse_int(self): - self.element_start('int') - value = int(self.character_data()) - self.element_end('int') - return Literal(value) - - def parse_uint(self): - self.element_start('uint') - value = int(self.character_data()) - self.element_end('uint') - return Literal(value) - - def parse_float(self): - self.element_start('float') - value = float(self.character_data()) - self.element_end('float') - return Literal(value) - - def parse_enum(self): - self.element_start('enum') - name = self.character_data() - self.element_end('enum') - return NamedConstant(name) - - def parse_string(self): - self.element_start('string') - value = self.character_data() - self.element_end('string') - return Literal(value) - - def parse_bytes(self): - self.element_start('bytes') - value = binascii.a2b_hex(self.character_data()) - self.element_end('bytes') - return Literal(value) - - def parse_array(self): - self.element_start('array') - elems = [] - while self.token.type != ELEMENT_END: - elems.append(self.parse_elem()) - self.element_end('array') - return Array(elems) - - def parse_elem(self): - self.element_start('elem') - value = self.parse_value() - self.element_end('elem') - return value - - def parse_struct(self): - attrs = self.element_start('struct') - name = attrs['name'] - members = [] - while self.token.type != ELEMENT_END: - members.append(self.parse_member()) - self.element_end('struct') - return Struct(name, members) - - def parse_member(self): - attrs = self.element_start('member') - name = attrs['name'] - value = self.parse_value() - self.element_end('member') - - return name, value - - def parse_ptr(self): - self.element_start('ptr') - address = self.character_data() - self.element_end('ptr') - - return Pointer(address) - - def handle_call(self, call): - pass - - -class TraceDumper(TraceParser): - - def __init__(self, fp): - TraceParser.__init__(self, fp) - self.formatter = format.DefaultFormatter(sys.stdout) - self.pretty_printer = PrettyPrinter(self.formatter) - - def handle_call(self, call): - call.visit(self.pretty_printer) - self.formatter.newline() - - -class Main: - '''Common main class for all retrace command line utilities.''' - - def __init__(self): - pass - - def main(self): - optparser = self.get_optparser() - (options, args) = optparser.parse_args(sys.argv[1:]) - - if args: - for arg in args: - if arg.endswith('.gz'): - from gzip import GzipFile - stream = GzipFile(arg, 'rt') - elif arg.endswith('.bz2'): - from bz2 import BZ2File - stream = BZ2File(arg, 'rt') - else: - stream = open(arg, 'rt') - self.process_arg(stream, options) - else: - self.process_arg(stream, options) - - def get_optparser(self): - optparser = optparse.OptionParser( - usage="\n\t%prog [options] [traces] ...") - return optparser - - def process_arg(self, stream, options): - parser = TraceDumper(stream) - parser.parse() +from parse import * if __name__ == '__main__': -- cgit v1.2.3 From e1700009b7cfc5f9a136649d7fd6e0f13ae4e7ad Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 11 Jun 2009 19:24:48 +0100 Subject: python/retrace: Interpret is_texture_referenced/is_buffer_referenced. --- src/gallium/state_trackers/python/retrace/interpreter.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 5d4d04498b..7374904554 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -577,6 +577,14 @@ class Context(Object): self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count) self._set_dirty() + def is_texture_referenced(self, texture, face, level): + #return self.real.is_texture_referenced(format, texture, face, level) + pass + + def is_buffer_referenced(self, buf): + #return self.real.is_buffer_referenced(format, buf) + pass + def _set_dirty(self): if self.interpreter.options.step: self._present() -- cgit v1.2.3 From 0ddc38309a4ecbe7db4a9e6055d7855d00e6ab7b Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 11 Jun 2009 20:46:07 +0100 Subject: python/retrace: Show the contents of the depth/stencil and surfaces before/after transfers. --- .../state_trackers/python/retrace/interpreter.py | 38 ++++++++++++++++------ 1 file changed, 28 insertions(+), 10 deletions(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 7374904554..5885e162c2 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -43,19 +43,27 @@ except ImportError: return struct.unpack(fmt, buf[offset:offset + size]) -def make_image(surface): +def make_image(surface, x=None, y=None, w=None, h=None): + if x is None: + x = 0 + if y is None: + y = 0 + if w is None: + w = surface.width - x + if h is None: + h = surface.height - y data = surface.get_tile_rgba8(0, 0, surface.width, surface.height) import Image outimage = Image.fromstring('RGBA', (surface.width, surface.height), data, "raw", 'RGBA', 0, 1) return outimage -def save_image(filename, surface): - outimage = make_image(surface) +def save_image(filename, surface, x=None, y=None, w=None, h=None): + outimage = make_image(surface, x, y, w, h) outimage.save(filename, "PNG") -def show_image(surface, title): - outimage = make_image(surface) +def show_image(surface, title, x=None, y=None, w=None, h=None): + outimage = make_image(surface, x, y, w, h) import Tkinter as tk from PIL import Image, ImageTk @@ -305,7 +313,11 @@ class Screen(Object): def get_tex_transfer(self, texture, face, level, zslice, usage, x, y, w, h): if texture is None: return None - return Transfer(texture.get_surface(face, level, zslice), x, y, w, h) + transfer = Transfer(texture.get_surface(face, level, zslice), x, y, w, h) + if transfer and usage != gallium.PIPE_TRANSFER_WRITE: + if self.interpreter.options.all: + self.interpreter.present(transfer.surface, 'transf_read', x, y, w, h) + return transfer def tex_transfer_destroy(self, transfer): self.interpreter.unregister_object(transfer) @@ -314,6 +326,8 @@ class Screen(Object): if transfer is None: return transfer.surface.put_tile_raw(transfer.x, transfer.y, transfer.w, transfer.h, data, stride) + if self.interpreter.options.all: + self.interpreter.present(transfer.surface, 'transf_write', transfer.x, transfer.y, transfer.w, transfer.h) def user_buffer_create(self, data, size): # We don't really care to distinguish between user and regular buffers @@ -610,6 +624,9 @@ class Context(Object): if self.cbufs and self.cbufs[0]: self.interpreter.present(self.cbufs[0], "cbuf") + if self.zsbuf: + if self.interpreter.options.all: + self.interpreter.present(self.zsbuf, "zsbuf") class Interpreter(parser.TraceDumper): @@ -679,16 +696,16 @@ class Interpreter(parser.TraceDumper): def verbosity(self, level): return self.options.verbosity >= level - def present(self, surface, description): + def present(self, surface, description, x=None, y=None, w=None, h=None): if self.call_no < self.options.start: return if self.options.images: - filename = '%s_%04u.png' % (description, self.call_no) - save_image(filename, surface) + filename = '%04u_%s.png' % (self.call_no, description) + save_image(filename, surface, x, y, w, h) else: title = '%u. %s' % (self.call_no, description) - show_image(surface, title) + show_image(surface, title, x, y, w, h) class Main(parser.Main): @@ -698,6 +715,7 @@ class Main(parser.Main): optparser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbosity", help="no messages") optparser.add_option("-v", "--verbose", action="count", dest="verbosity", default=1, help="increase verbosity level") optparser.add_option("-i", "--images", action="store_true", dest="images", default=False, help="save images instead of showing them") + optparser.add_option("-a", "--all", action="store_true", dest="all", default=False, help="show depth, stencil, and transfers") optparser.add_option("-s", "--step", action="store_true", dest="step", default=False, help="step trhough every draw") optparser.add_option("-f", "--from", action="store", type="int", dest="start", default=0, help="from call no") optparser.add_option("-t", "--to", action="store", type="int", dest="stop", default=0, help="until call no") -- cgit v1.2.3 From 0474b5cb2ac4cefa12e7080aba397013325fb9a6 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Wed, 15 Jul 2009 15:37:27 +0100 Subject: python/retrace: Interpret surface_copy. --- src/gallium/state_trackers/python/retrace/interpreter.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 5885e162c2..e018a6e96b 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -591,6 +591,10 @@ class Context(Object): self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count) self._set_dirty() + def surface_copy(self, dest, destx, desty, src, srcx, srcy, width, height): + if dest is not None and src is not None: + self.real.surface_copy(dest, destx, desty, src, srcx, srcy, width, height) + def is_texture_referenced(self, texture, face, level): #return self.real.is_texture_referenced(format, texture, face, level) pass -- cgit v1.2.3 From 5807ccb41b14890a1cdab4cc06806a9cf6c11ecc Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 16 Jul 2009 19:31:36 +0100 Subject: python/retrace: Flush stdout before calling the pipe driver. So that messages are in sync with stderr. --- src/gallium/state_trackers/python/retrace/interpreter.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index e018a6e96b..69515da218 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -456,6 +456,7 @@ class Context(Object): x, y, z, w = unpack_from(format, data, offset) sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w)) index += 1 + sys.stdout.flush() def set_constant_buffer(self, shader, index, buffer): if buffer is not None: @@ -537,6 +538,7 @@ class Context(Object): sys.stdout.write('\t\t{' + ', '.join(map(str, values)) + '},\n') assert len(values) == velem.nr_components sys.stdout.write('\t},\n') + sys.stdout.flush() def dump_indices(self, ibuf, isize, start, count): if not self.interpreter.verbosity(2): @@ -564,6 +566,7 @@ class Context(Object): minindex = min(minindex, index) maxindex = max(maxindex, index) sys.stdout.write('\t},\n') + sys.stdout.flush() return minindex, maxindex @@ -674,6 +677,7 @@ class Interpreter(parser.TraceDumper): if self.verbosity(1): parser.TraceDumper.handle_call(self, call) + sys.stdout.flush() args = [(str(name), self.interpret_arg(arg)) for name, arg in call.args] -- cgit v1.2.3 From cf7e8fbc2ea2739f1955d83751b631c5444a3c91 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 16 Jul 2009 19:32:40 +0100 Subject: python/retrace: Dump the surface copy contents. --- src/gallium/state_trackers/python/retrace/interpreter.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index 69515da218..bc06429b77 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -596,7 +596,17 @@ class Context(Object): def surface_copy(self, dest, destx, desty, src, srcx, srcy, width, height): if dest is not None and src is not None: + if self.interpreter.options.all: + self.interpreter.present(src, 'surface_copy_src', srcx, srcy, width, height) self.real.surface_copy(dest, destx, desty, src, srcx, srcy, width, height) + if dest in self.cbufs: + self._set_dirty() + flags = gallium.PIPE_FLUSH_FRAME + else: + flags = 0 + self.flush(flags) + if self.interpreter.options.all: + self.interpreter.present(dest, 'surface_copy_dest', destx, desty, width, height) def is_texture_referenced(self, texture, face, level): #return self.real.is_texture_referenced(format, texture, face, level) -- cgit v1.2.3 From 2ba98efdf6653a4cb885d576d2e6f349c69679d4 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Thu, 16 Jul 2009 19:34:44 +0100 Subject: python/retrace: Process the call no passed to --to option inclusively. --- src/gallium/state_trackers/python/retrace/interpreter.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py index bc06429b77..6f0bd6ae52 100755 --- a/src/gallium/state_trackers/python/retrace/interpreter.py +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -677,7 +677,7 @@ class Interpreter(parser.TraceDumper): self.interpret_call(call) def handle_call(self, call): - if self.options.stop and call.no >= self.options.stop: + if self.options.stop and call.no > self.options.stop: sys.exit(0) if (call.klass, call.method) in self.ignore_calls: -- cgit v1.2.3 From cdf56eb68d2718b5702f3d09928da404d745b8e1 Mon Sep 17 00:00:00 2001 From: José Fonseca Date: Sun, 31 May 2009 12:53:22 -0700 Subject: python/retrace: Open bz2 files correctly. --- src/gallium/state_trackers/python/retrace/parse.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/gallium/state_trackers/python/retrace') diff --git a/src/gallium/state_trackers/python/retrace/parse.py b/src/gallium/state_trackers/python/retrace/parse.py index b0f3e8a432..b08d368671 100755 --- a/src/gallium/state_trackers/python/retrace/parse.py +++ b/src/gallium/state_trackers/python/retrace/parse.py @@ -371,7 +371,7 @@ class Main: stream = GzipFile(arg, 'rt') elif arg.endswith('.bz2'): from bz2 import BZ2File - stream = BZ2File(arg, 'rt') + stream = BZ2File(arg, 'rU') else: stream = open(arg, 'rt') self.process_arg(stream, options) -- cgit v1.2.3