python/retrace: Cope with null constant buffers.
[mesa.git] / src / gallium / state_trackers / python / retrace / interpreter.py
index 708937119f00bf581f75aed9b4103de5edebd71a..348f2e436831e89186895fc4a140e06ebf36de63 100755 (executable)
@@ -32,7 +32,7 @@ import struct
 
 import gallium
 import model
-import parser
+import parse as parser
 
 
 try:
@@ -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
@@ -286,6 +294,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,17 +305,29 @@ 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):
-        return Transfer(texture.get_surface(face, level, zslice), x, y, w, h)
+        if texture is None:
+            return None
+        transfer = Transfer(texture.get_surface(face, level, zslice), x, y, w, h)
+        if transfer and usage & gallium.PIPE_TRANSFER_READ:
+            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)
 
     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)
+        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
@@ -434,9 +456,10 @@ 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:
+        if buffer is not None and buffer.buffer is not None:
             self.real.set_constant_buffer(shader, index, buffer.buffer)
 
             self.dump_constant_buffer(buffer.buffer)
@@ -515,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):
@@ -542,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
 
@@ -569,6 +594,28 @@ 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:
+            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)
+        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()
@@ -594,6 +641,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):
@@ -627,6 +677,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
@@ -635,6 +687,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] 
         
@@ -648,6 +701,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
@@ -659,13 +714,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):
@@ -675,7 +733,10 @@ 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")
         return optparser
 
     def process_arg(self, stream, options):