blob: a34122e0e0f1074d3b1319d00a4122360f43e8d0 [file] [log] [blame]
José Fonseca468c9772008-08-14 11:00:22 +01001#!/usr/bin/env python
José Fonseca9efa6ca2008-11-19 16:23:01 +09002##########################################################################
3#
4# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
5# All Rights Reserved.
6#
7# Permission is hereby granted, free of charge, to any person obtaining a
8# copy of this software and associated documentation files (the
9# "Software"), to deal in the Software without restriction, including
10# without limitation the rights to use, copy, modify, merge, publish,
11# distribute, sub license, and/or sell copies of the Software, and to
12# permit persons to whom the Software is furnished to do so, subject to
13# the following conditions:
14#
15# The above copyright notice and this permission notice (including the
16# next paragraph) shall be included in all copies or substantial portions
17# of the Software.
18#
19# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
20# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
22# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
23# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
24# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
25# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26#
27##########################################################################
José Fonseca468c9772008-08-14 11:00:22 +010028
29
30import sys
José Fonseca59ae12b52008-11-20 01:02:03 +090031import struct
32
José Fonseca468c9772008-08-14 11:00:22 +010033import gallium
34import model
José Fonseca3a618da2009-04-17 10:07:53 +010035import parse as parser
José Fonseca468c9772008-08-14 11:00:22 +010036
37
José Fonseca204526a2009-02-20 15:02:19 +000038try:
39 from struct import unpack_from
40except ImportError:
41 def unpack_from(fmt, buf, offset=0):
42 size = struct.calcsize(fmt)
43 return struct.unpack(fmt, buf[offset:offset + size])
44
45
José Fonseca0ddc3832009-06-11 20:46:07 +010046def make_image(surface, x=None, y=None, w=None, h=None):
47 if x is None:
48 x = 0
49 if y is None:
50 y = 0
51 if w is None:
52 w = surface.width - x
53 if h is None:
54 h = surface.height - y
José Fonseca64893eb2009-12-28 16:39:30 +000055 data = surface.get_tile_rgba8(x, y, surface.width, surface.height)
José Fonseca468c9772008-08-14 11:00:22 +010056
57 import Image
José Fonseca64893eb2009-12-28 16:39:30 +000058 outimage = Image.fromstring('RGBA', (w, h), data, "raw", 'RGBA', 0, 1)
José Fonseca468c9772008-08-14 11:00:22 +010059 return outimage
60
José Fonseca0ddc3832009-06-11 20:46:07 +010061def save_image(filename, surface, x=None, y=None, w=None, h=None):
62 outimage = make_image(surface, x, y, w, h)
José Fonseca468c9772008-08-14 11:00:22 +010063 outimage.save(filename, "PNG")
64
José Fonseca0ddc3832009-06-11 20:46:07 +010065def show_image(surface, title, x=None, y=None, w=None, h=None):
66 outimage = make_image(surface, x, y, w, h)
José Fonseca468c9772008-08-14 11:00:22 +010067
68 import Tkinter as tk
69 from PIL import Image, ImageTk
70 root = tk.Tk()
71
José Fonsecade89c022009-03-25 15:36:51 +000072 root.title(title)
José Fonseca468c9772008-08-14 11:00:22 +010073
74 image1 = ImageTk.PhotoImage(outimage)
75 w = image1.width()
76 h = image1.height()
77 x = 100
78 y = 100
79 root.geometry("%dx%d+%d+%d" % (w, h, x, y))
80 panel1 = tk.Label(root, image=image1)
81 panel1.pack(side='top', fill='both', expand='yes')
82 panel1.image = image1
83 root.mainloop()
84
85
José Fonseca468c9772008-08-14 11:00:22 +010086class Struct:
87 """C-like struct"""
88
89 # A basic Python class can pass as a C-like structure
90 pass
91
92
93struct_factories = {
94 "pipe_blend_color": gallium.BlendColor,
95 "pipe_blend_state": gallium.Blend,
José Fonsecad7f8b952008-08-19 19:12:22 +010096 #"pipe_clip_state": gallium.Clip,
Roland Scheideggerf44b0ff2009-12-23 20:44:06 +010097 #"pipe_buffer": gallium.Buffer,
José Fonseca468c9772008-08-14 11:00:22 +010098 "pipe_depth_state": gallium.Depth,
99 "pipe_stencil_state": gallium.Stencil,
100 "pipe_alpha_state": gallium.Alpha,
101 "pipe_depth_stencil_alpha_state": gallium.DepthStencilAlpha,
José Fonseca468c9772008-08-14 11:00:22 +0100102 #"pipe_framebuffer_state": gallium.Framebuffer,
103 "pipe_poly_stipple": gallium.PolyStipple,
104 "pipe_rasterizer_state": gallium.Rasterizer,
105 "pipe_sampler_state": gallium.Sampler,
106 "pipe_scissor_state": gallium.Scissor,
107 #"pipe_shader_state": gallium.Shader,
108 #"pipe_vertex_buffer": gallium.VertexBuffer,
109 "pipe_vertex_element": gallium.VertexElement,
110 "pipe_viewport_state": gallium.Viewport,
111 #"pipe_texture": gallium.Texture,
112}
113
114
115member_array_factories = {
Roland Scheidegger4a4daa72010-02-03 17:25:14 +0100116 #"pipe_rasterizer_state": {"sprite_coord_mode": gallium.ByteArray},
José Fonseca468c9772008-08-14 11:00:22 +0100117 "pipe_poly_stipple": {"stipple": gallium.UnsignedArray},
118 "pipe_viewport_state": {"scale": gallium.FloatArray, "translate": gallium.FloatArray},
José Fonsecad7f8b952008-08-19 19:12:22 +0100119 #"pipe_clip_state": {"ucp": gallium.FloatArray},
José Fonseca468c9772008-08-14 11:00:22 +0100120 "pipe_depth_stencil_alpha_state": {"stencil": gallium.StencilArray},
José Fonsecac9751522008-08-14 22:03:35 +0100121 "pipe_blend_color": {"color": gallium.FloatArray},
122 "pipe_sampler_state": {"border_color": gallium.FloatArray},
José Fonseca468c9772008-08-14 11:00:22 +0100123}
124
125
126class Translator(model.Visitor):
127 """Translate model arguments into regular Python objects"""
128
129 def __init__(self, interpreter):
130 self.interpreter = interpreter
131 self.result = None
132
133 def visit(self, node):
134 self.result = None
135 node.visit(self)
136 return self.result
137
138 def visit_literal(self, node):
139 self.result = node.value
140
141 def visit_named_constant(self, node):
142 # lookup the named constant in the gallium module
143 self.result = getattr(gallium, node.name)
144
145 def visit_array(self, node):
146 array = []
147 for element in node.elements:
148 array.append(self.visit(element))
149 self.result = array
150
151 def visit_struct(self, node):
152 struct_factory = struct_factories.get(node.name, Struct)
153 struct = struct_factory()
154 for member_name, member_node in node.members:
155 member_value = self.visit(member_node)
156 try:
157 array_factory = member_array_factories[node.name][member_name]
158 except KeyError:
159 pass
160 else:
161 assert isinstance(member_value, list)
162 array = array_factory(len(member_value))
163 for i in range(len(member_value)):
164 array[i] = member_value[i]
165 member_value = array
166 #print node.name, member_name, member_value
167 assert isinstance(struct, Struct) or hasattr(struct, member_name)
168 setattr(struct, member_name, member_value)
169 self.result = struct
170
171 def visit_pointer(self, node):
172 self.result = self.interpreter.lookup_object(node.address)
173
174
175class Object:
176
177 def __init__(self, interpreter, real):
178 self.interpreter = interpreter
179 self.real = real
180
181
182class Global(Object):
183
184 def __init__(self, interpreter, real):
185 self.interpreter = interpreter
186 self.real = real
187
188 def pipe_winsys_create(self):
189 return Winsys(self.interpreter, gallium.Device())
190
José Fonsecac14562d2009-04-08 15:36:17 +0100191 def pipe_screen_create(self, winsys=None):
192 if winsys is None:
193 real = gallium.Device()
194 else:
195 real = winsys.real
196 return Screen(self.interpreter, real)
José Fonseca468c9772008-08-14 11:00:22 +0100197
198 def pipe_context_create(self, screen):
199 context = screen.real.context_create()
200 return Context(self.interpreter, context)
201
202
203class Winsys(Object):
204
205 def __init__(self, interpreter, real):
206 self.interpreter = interpreter
207 self.real = real
208
209 def get_name(self):
210 pass
211
José Fonsecac9751522008-08-14 22:03:35 +0100212 def user_buffer_create(self, data, size):
213 # We don't really care to distinguish between user and regular buffers
214 buffer = self.real.buffer_create(size,
215 4,
216 gallium.PIPE_BUFFER_USAGE_CPU_READ |
217 gallium.PIPE_BUFFER_USAGE_CPU_WRITE )
José Fonseca59ae12b52008-11-20 01:02:03 +0900218 assert size == len(data)
219 buffer.write(data)
José Fonsecac9751522008-08-14 22:03:35 +0100220 return buffer
221
José Fonseca468c9772008-08-14 11:00:22 +0100222 def buffer_create(self, alignment, usage, size):
223 return self.real.buffer_create(size, alignment, usage)
224
225 def buffer_destroy(self, buffer):
226 pass
227
228 def buffer_write(self, buffer, data, size):
José Fonseca59ae12b52008-11-20 01:02:03 +0900229 assert size == len(data)
230 buffer.write(data)
José Fonsecac9751522008-08-14 22:03:35 +0100231
232 def fence_finish(self, fence, flags):
233 pass
234
235 def fence_reference(self, dst, src):
236 pass
237
238 def flush_frontbuffer(self, surface):
239 pass
José Fonseca468c9772008-08-14 11:00:22 +0100240
José Fonsecad7f8b952008-08-19 19:12:22 +0100241 def surface_alloc(self):
242 return None
243
244 def surface_release(self, surface):
245 pass
246
José Fonseca468c9772008-08-14 11:00:22 +0100247
José Fonsecac14562d2009-04-08 15:36:17 +0100248class Transfer:
249
250 def __init__(self, surface, x, y, w, h):
251 self.surface = surface
252 self.x = x
253 self.y = y
254 self.w = w
255 self.h = h
256
257
José Fonseca468c9772008-08-14 11:00:22 +0100258class Screen(Object):
259
José Fonsecad26a43f2008-12-08 17:26:02 +0900260 def destroy(self):
261 pass
262
José Fonseca468c9772008-08-14 11:00:22 +0100263 def get_name(self):
264 pass
265
266 def get_vendor(self):
267 pass
268
269 def get_param(self, param):
270 pass
271
272 def get_paramf(self, param):
273 pass
274
José Fonseca4ab3f0e2010-02-14 12:48:11 +0000275 def context_create(self):
276 context = self.real.context_create()
277 return Context(self.interpreter, context)
278
José Fonseca468c9772008-08-14 11:00:22 +0100279 def is_format_supported(self, format, target, tex_usage, geom_flags):
280 return self.real.is_format_supported(format, target, tex_usage, geom_flags)
281
José Fonsecac14562d2009-04-08 15:36:17 +0100282 def texture_create(self, templat):
José Fonseca468c9772008-08-14 11:00:22 +0100283 return self.real.texture_create(
José Fonsecac14562d2009-04-08 15:36:17 +0100284 format = templat.format,
José Fonseca230a5b52009-12-26 01:14:59 +0000285 width = templat.width,
286 height = templat.height,
287 depth = templat.depth,
José Fonsecac14562d2009-04-08 15:36:17 +0100288 last_level = templat.last_level,
289 target = templat.target,
290 tex_usage = templat.tex_usage,
José Fonseca468c9772008-08-14 11:00:22 +0100291 )
292
José Fonsecad32f51d2008-08-22 03:14:51 +0100293 def texture_destroy(self, texture):
José Fonseca468c9772008-08-14 11:00:22 +0100294 self.interpreter.unregister_object(texture)
295
José Fonsecad32f51d2008-08-22 03:14:51 +0100296 def texture_release(self, surface):
297 pass
298
José Fonseca468c9772008-08-14 11:00:22 +0100299 def get_tex_surface(self, texture, face, level, zslice, usage):
José Fonseca71504c72009-04-08 21:13:57 +0100300 if texture is None:
301 return None
José Fonseca68342f92009-03-30 15:09:18 +0100302 return texture.get_surface(face, level, zslice)
José Fonseca468c9772008-08-14 11:00:22 +0100303
José Fonsecad32f51d2008-08-22 03:14:51 +0100304 def tex_surface_destroy(self, surface):
José Fonseca468c9772008-08-14 11:00:22 +0100305 self.interpreter.unregister_object(surface)
306
José Fonsecad32f51d2008-08-22 03:14:51 +0100307 def tex_surface_release(self, surface):
308 pass
309
José Fonsecac9751522008-08-14 22:03:35 +0100310 def surface_write(self, surface, data, stride, size):
José Fonseca71504c72009-04-08 21:13:57 +0100311 if surface is None:
312 return
Roland Scheideggerdecf6ed2009-11-30 23:02:49 +0100313# assert surface.nblocksy * stride == size
José Fonsecac9751522008-08-14 22:03:35 +0100314 surface.put_tile_raw(0, 0, surface.width, surface.height, data, stride)
José Fonseca468c9772008-08-14 11:00:22 +0100315
José Fonsecac14562d2009-04-08 15:36:17 +0100316 def get_tex_transfer(self, texture, face, level, zslice, usage, x, y, w, h):
José Fonseca71504c72009-04-08 21:13:57 +0100317 if texture is None:
318 return None
José Fonseca0ddc3832009-06-11 20:46:07 +0100319 transfer = Transfer(texture.get_surface(face, level, zslice), x, y, w, h)
José Fonsecaa2e868b2009-11-02 09:47:24 +0000320 if transfer and usage & gallium.PIPE_TRANSFER_READ:
José Fonseca0ddc3832009-06-11 20:46:07 +0100321 if self.interpreter.options.all:
322 self.interpreter.present(transfer.surface, 'transf_read', x, y, w, h)
323 return transfer
José Fonsecac14562d2009-04-08 15:36:17 +0100324
325 def tex_transfer_destroy(self, transfer):
326 self.interpreter.unregister_object(transfer)
327
328 def transfer_write(self, transfer, stride, data, size):
José Fonseca71504c72009-04-08 21:13:57 +0100329 if transfer is None:
330 return
José Fonsecac14562d2009-04-08 15:36:17 +0100331 transfer.surface.put_tile_raw(transfer.x, transfer.y, transfer.w, transfer.h, data, stride)
José Fonseca0ddc3832009-06-11 20:46:07 +0100332 if self.interpreter.options.all:
333 self.interpreter.present(transfer.surface, 'transf_write', transfer.x, transfer.y, transfer.w, transfer.h)
José Fonsecac14562d2009-04-08 15:36:17 +0100334
335 def user_buffer_create(self, data, size):
336 # We don't really care to distinguish between user and regular buffers
337 buffer = self.real.buffer_create(size,
338 4,
339 gallium.PIPE_BUFFER_USAGE_CPU_READ |
340 gallium.PIPE_BUFFER_USAGE_CPU_WRITE )
341 assert size == len(data)
342 buffer.write(data)
343 return buffer
344
345 def buffer_create(self, alignment, usage, size):
346 return self.real.buffer_create(size, alignment, usage)
347
348 def buffer_destroy(self, buffer):
349 pass
350
351 def buffer_write(self, buffer, data, size, offset=0):
352 assert size == len(data)
353 buffer.write(data)
354
355 def fence_finish(self, fence, flags):
356 pass
357
358 def fence_reference(self, dst, src):
359 pass
360
361 def flush_frontbuffer(self, surface):
362 pass
363
José Fonseca468c9772008-08-14 11:00:22 +0100364
365class Context(Object):
366
367 def __init__(self, interpreter, real):
368 Object.__init__(self, interpreter, real)
369 self.cbufs = []
370 self.zsbuf = None
José Fonsecad26a43f2008-12-08 17:26:02 +0900371 self.vbufs = []
372 self.velems = []
José Fonseca059d7f32009-02-20 15:23:33 +0000373 self.dirty = False
José Fonseca468c9772008-08-14 11:00:22 +0100374
José Fonsecad7f8b952008-08-19 19:12:22 +0100375 def destroy(self):
376 pass
377
José Fonseca468c9772008-08-14 11:00:22 +0100378 def create_blend_state(self, state):
379 return state
380
381 def bind_blend_state(self, state):
José Fonsecad7f8b952008-08-19 19:12:22 +0100382 if state is not None:
383 self.real.set_blend(state)
384
385 def delete_blend_state(self, state):
386 pass
387
José Fonseca468c9772008-08-14 11:00:22 +0100388 def create_sampler_state(self, state):
389 return state
390
José Fonsecad7f8b952008-08-19 19:12:22 +0100391 def delete_sampler_state(self, state):
392 pass
393
José Fonseca230a5b52009-12-26 01:14:59 +0000394 def bind_vertex_sampler_states(self, num_states, states):
395 for i in range(num_states):
396 self.real.set_vertex_sampler(i, states[i])
397
Michal Krolee86b1b2009-12-01 08:47:00 +0100398 def bind_fragment_sampler_states(self, num_states, states):
José Fonsecac14562d2009-04-08 15:36:17 +0100399 for i in range(num_states):
José Fonseca230a5b52009-12-26 01:14:59 +0000400 self.real.set_fragment_sampler(i, states[i])
José Fonseca468c9772008-08-14 11:00:22 +0100401
402 def create_rasterizer_state(self, state):
403 return state
404
405 def bind_rasterizer_state(self, state):
José Fonsecad7f8b952008-08-19 19:12:22 +0100406 if state is not None:
407 self.real.set_rasterizer(state)
José Fonseca468c9772008-08-14 11:00:22 +0100408
José Fonsecad7f8b952008-08-19 19:12:22 +0100409 def delete_rasterizer_state(self, state):
410 pass
411
José Fonseca468c9772008-08-14 11:00:22 +0100412 def create_depth_stencil_alpha_state(self, state):
413 return state
414
415 def bind_depth_stencil_alpha_state(self, state):
José Fonsecad7f8b952008-08-19 19:12:22 +0100416 if state is not None:
417 self.real.set_depth_stencil_alpha(state)
418
419 def delete_depth_stencil_alpha_state(self, state):
420 pass
421
José Fonseca468c9772008-08-14 11:00:22 +0100422 def create_fs_state(self, state):
423 tokens = str(state.tokens)
424 shader = gallium.Shader(tokens)
425 return shader
426
427 create_vs_state = create_fs_state
428
429 def bind_fs_state(self, state):
430 self.real.set_fragment_shader(state)
431
432 def bind_vs_state(self, state):
433 self.real.set_vertex_shader(state)
434
José Fonsecad7f8b952008-08-19 19:12:22 +0100435 def delete_fs_state(self, state):
436 pass
Roland Scheidegger903bb042010-02-10 18:46:43 +0100437
José Fonsecad7f8b952008-08-19 19:12:22 +0100438 delete_vs_state = delete_fs_state
Roland Scheidegger903bb042010-02-10 18:46:43 +0100439
José Fonseca468c9772008-08-14 11:00:22 +0100440 def set_blend_color(self, state):
441 self.real.set_blend_color(state)
442
Roland Scheidegger903bb042010-02-10 18:46:43 +0100443 def set_stencil_ref(self, state):
444 self.real.set_stencil_ref(state)
445
José Fonseca468c9772008-08-14 11:00:22 +0100446 def set_clip_state(self, state):
José Fonsecad7f8b952008-08-19 19:12:22 +0100447 _state = gallium.Clip()
448 _state.nr = state.nr
449 if state.nr:
450 # FIXME
451 ucp = gallium.FloatArray(gallium.PIPE_MAX_CLIP_PLANES*4)
452 for i in range(len(state.ucp)):
453 for j in range(len(state.ucp[i])):
454 ucp[i*4 + j] = state.ucp[i][j]
455 _state.ucp = ucp
456 self.real.set_clip(_state)
José Fonseca468c9772008-08-14 11:00:22 +0100457
José Fonsecae92f3312009-02-20 15:14:15 +0000458 def dump_constant_buffer(self, buffer):
José Fonseca9d97c3d2009-03-25 13:31:27 +0000459 if not self.interpreter.verbosity(2):
José Fonsecae92f3312009-02-20 15:14:15 +0000460 return
461
462 data = buffer.read()
463 format = '4f'
464 index = 0
465 for offset in range(0, len(data), struct.calcsize(format)):
466 x, y, z, w = unpack_from(format, data, offset)
467 sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w))
468 index += 1
José Fonseca5807ccb2009-07-16 19:31:36 +0100469 sys.stdout.flush()
José Fonsecae92f3312009-02-20 15:14:15 +0000470
José Fonsecac14562d2009-04-08 15:36:17 +0100471 def set_constant_buffer(self, shader, index, buffer):
Roland Scheideggerf44b0ff2009-12-23 20:44:06 +0100472 if buffer is not None:
473 self.real.set_constant_buffer(shader, index, buffer)
José Fonseca468c9772008-08-14 11:00:22 +0100474
Roland Scheideggerf44b0ff2009-12-23 20:44:06 +0100475 self.dump_constant_buffer(buffer)
José Fonseca59ae12b52008-11-20 01:02:03 +0900476
José Fonseca468c9772008-08-14 11:00:22 +0100477 def set_framebuffer_state(self, state):
478 _state = gallium.Framebuffer()
479 _state.width = state.width
480 _state.height = state.height
José Fonseca53813312009-03-24 21:18:54 +0000481 _state.nr_cbufs = state.nr_cbufs
José Fonseca468c9772008-08-14 11:00:22 +0100482 for i in range(len(state.cbufs)):
483 _state.set_cbuf(i, state.cbufs[i])
484 _state.set_zsbuf(state.zsbuf)
485 self.real.set_framebuffer(_state)
486
487 self.cbufs = state.cbufs
488 self.zsbuf = state.zsbuf
489
490 def set_polygon_stipple(self, state):
491 self.real.set_polygon_stipple(state)
492
493 def set_scissor_state(self, state):
494 self.real.set_scissor(state)
495
496 def set_viewport_state(self, state):
497 self.real.set_viewport(state)
498
Michal Krolee86b1b2009-12-01 08:47:00 +0100499 def set_fragment_sampler_textures(self, num_textures, textures):
José Fonsecac14562d2009-04-08 15:36:17 +0100500 for i in range(num_textures):
José Fonseca230a5b52009-12-26 01:14:59 +0000501 self.real.set_fragment_sampler_texture(i, textures[i])
502
503 def set_vertex_sampler_textures(self, num_textures, textures):
504 for i in range(num_textures):
505 self.real.set_vertex_sampler_texture(i, textures[i])
José Fonseca468c9772008-08-14 11:00:22 +0100506
José Fonsecac14562d2009-04-08 15:36:17 +0100507 def set_vertex_buffers(self, num_buffers, buffers):
508 self.vbufs = buffers[0:num_buffers]
509 for i in range(num_buffers):
510 vbuf = buffers[i]
José Fonseca468c9772008-08-14 11:00:22 +0100511 self.real.set_vertex_buffer(
512 i,
José Fonsecaad5f9752009-03-24 21:21:37 +0000513 stride = vbuf.stride,
José Fonseca468c9772008-08-14 11:00:22 +0100514 max_index = vbuf.max_index,
515 buffer_offset = vbuf.buffer_offset,
516 buffer = vbuf.buffer,
517 )
518
José Fonsecac14562d2009-04-08 15:36:17 +0100519 def set_vertex_elements(self, num_elements, elements):
520 self.velems = elements[0:num_elements]
521 for i in range(num_elements):
José Fonseca468c9772008-08-14 11:00:22 +0100522 self.real.set_vertex_element(i, elements[i])
José Fonsecac14562d2009-04-08 15:36:17 +0100523 self.real.set_vertex_elements(num_elements)
José Fonseca468c9772008-08-14 11:00:22 +0100524
José Fonseca51d96422008-12-09 19:37:25 +0900525 def dump_vertices(self, start, count):
José Fonseca9d97c3d2009-03-25 13:31:27 +0000526 if not self.interpreter.verbosity(2):
José Fonsecae92f3312009-02-20 15:14:15 +0000527 return
528
José Fonsecad26a43f2008-12-08 17:26:02 +0900529 for index in range(start, start + count):
José Fonseca51d96422008-12-09 19:37:25 +0900530 if index >= start + 16:
531 sys.stdout.write('\t...\n')
532 break
José Fonsecad26a43f2008-12-08 17:26:02 +0900533 sys.stdout.write('\t{\n')
534 for velem in self.velems:
535 vbuf = self.vbufs[velem.vertex_buffer_index]
536
José Fonsecaad5f9752009-03-24 21:21:37 +0000537 offset = vbuf.buffer_offset + velem.src_offset + vbuf.stride*index
José Fonsecad26a43f2008-12-08 17:26:02 +0900538 format = {
José Fonseca51d96422008-12-09 19:37:25 +0900539 gallium.PIPE_FORMAT_R32_FLOAT: 'f',
540 gallium.PIPE_FORMAT_R32G32_FLOAT: '2f',
José Fonsecad26a43f2008-12-08 17:26:02 +0900541 gallium.PIPE_FORMAT_R32G32B32_FLOAT: '3f',
José Fonseca51d96422008-12-09 19:37:25 +0900542 gallium.PIPE_FORMAT_R32G32B32A32_FLOAT: '4f',
José Fonsecad26a43f2008-12-08 17:26:02 +0900543 gallium.PIPE_FORMAT_B8G8R8A8_UNORM: '4B',
Zack Rusin8109b6d2010-02-05 19:04:11 -0500544 gallium.PIPE_FORMAT_R8G8B8A8_UNORM: '4B',
545 gallium.PIPE_FORMAT_R16G16B16_SNORM: '3h',
José Fonsecad26a43f2008-12-08 17:26:02 +0900546 }[velem.src_format]
547
548 data = vbuf.buffer.read()
José Fonseca204526a2009-02-20 15:02:19 +0000549 values = unpack_from(format, data, offset)
José Fonsecad26a43f2008-12-08 17:26:02 +0900550 sys.stdout.write('\t\t{' + ', '.join(map(str, values)) + '},\n')
551 assert len(values) == velem.nr_components
552 sys.stdout.write('\t},\n')
José Fonseca5807ccb2009-07-16 19:31:36 +0100553 sys.stdout.flush()
José Fonseca51d96422008-12-09 19:37:25 +0900554
555 def dump_indices(self, ibuf, isize, start, count):
José Fonseca9d97c3d2009-03-25 13:31:27 +0000556 if not self.interpreter.verbosity(2):
José Fonsecae92f3312009-02-20 15:14:15 +0000557 return
558
José Fonseca51d96422008-12-09 19:37:25 +0900559 format = {
560 1: 'B',
561 2: 'H',
562 4: 'I',
563 }[isize]
564
565 assert struct.calcsize(format) == isize
566
567 data = ibuf.read()
568 maxindex, minindex = 0, 0xffffffff
569
570 sys.stdout.write('\t{\n')
571 for i in range(start, start + count):
572 if i >= start + 16:
573 sys.stdout.write('\t...\n')
574 break
575 offset = i*isize
José Fonseca204526a2009-02-20 15:02:19 +0000576 index, = unpack_from(format, data, offset)
José Fonseca51d96422008-12-09 19:37:25 +0900577 sys.stdout.write('\t\t%u,\n' % index)
578 minindex = min(minindex, index)
579 maxindex = max(maxindex, index)
580 sys.stdout.write('\t},\n')
José Fonseca5807ccb2009-07-16 19:31:36 +0100581 sys.stdout.flush()
José Fonseca51d96422008-12-09 19:37:25 +0900582
583 return minindex, maxindex
584
585 def draw_arrays(self, mode, start, count):
586 self.dump_vertices(start, count)
José Fonsecad26a43f2008-12-08 17:26:02 +0900587
José Fonseca468c9772008-08-14 11:00:22 +0100588 self.real.draw_arrays(mode, start, count)
José Fonseca9d97c3d2009-03-25 13:31:27 +0000589 self._set_dirty()
José Fonseca34cffce2008-08-20 14:03:12 +0100590
591 def draw_elements(self, indexBuffer, indexSize, mode, start, count):
José Fonseca9d97c3d2009-03-25 13:31:27 +0000592 if self.interpreter.verbosity(2):
José Fonsecae92f3312009-02-20 15:14:15 +0000593 minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count)
594 self.dump_vertices(minindex, maxindex - minindex)
José Fonseca51d96422008-12-09 19:37:25 +0900595
José Fonseca34cffce2008-08-20 14:03:12 +0100596 self.real.draw_elements(indexBuffer, indexSize, mode, start, count)
José Fonseca9d97c3d2009-03-25 13:31:27 +0000597 self._set_dirty()
José Fonseca34cffce2008-08-20 14:03:12 +0100598
599 def draw_range_elements(self, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count):
José Fonseca9d97c3d2009-03-25 13:31:27 +0000600 if self.interpreter.verbosity(2):
José Fonsecae92f3312009-02-20 15:14:15 +0000601 minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count)
602 minindex = min(minindex, minIndex)
603 maxindex = min(maxindex, maxIndex)
604 self.dump_vertices(minindex, maxindex - minindex)
José Fonseca51d96422008-12-09 19:37:25 +0900605
José Fonseca34cffce2008-08-20 14:03:12 +0100606 self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count)
José Fonseca9d97c3d2009-03-25 13:31:27 +0000607 self._set_dirty()
José Fonseca468c9772008-08-14 11:00:22 +0100608
José Fonseca0474b5c2009-07-15 15:37:27 +0100609 def surface_copy(self, dest, destx, desty, src, srcx, srcy, width, height):
610 if dest is not None and src is not None:
José Fonsecacf7e8fb2009-07-16 19:32:40 +0100611 if self.interpreter.options.all:
612 self.interpreter.present(src, 'surface_copy_src', srcx, srcy, width, height)
José Fonseca0474b5c2009-07-15 15:37:27 +0100613 self.real.surface_copy(dest, destx, desty, src, srcx, srcy, width, height)
José Fonsecacf7e8fb2009-07-16 19:32:40 +0100614 if dest in self.cbufs:
615 self._set_dirty()
616 flags = gallium.PIPE_FLUSH_FRAME
617 else:
618 flags = 0
619 self.flush(flags)
620 if self.interpreter.options.all:
621 self.interpreter.present(dest, 'surface_copy_dest', destx, desty, width, height)
José Fonseca0474b5c2009-07-15 15:37:27 +0100622
José Fonsecae1700002009-06-11 19:24:48 +0100623 def is_texture_referenced(self, texture, face, level):
624 #return self.real.is_texture_referenced(format, texture, face, level)
625 pass
626
627 def is_buffer_referenced(self, buf):
628 #return self.real.is_buffer_referenced(format, buf)
629 pass
630
José Fonseca9d97c3d2009-03-25 13:31:27 +0000631 def _set_dirty(self):
632 if self.interpreter.options.step:
633 self._present()
634 else:
635 self.dirty = True
636
José Fonsecac9751522008-08-14 22:03:35 +0100637 def flush(self, flags):
José Fonseca468c9772008-08-14 11:00:22 +0100638 self.real.flush(flags)
José Fonseca059d7f32009-02-20 15:23:33 +0000639 if self.dirty:
640 if flags & gallium.PIPE_FLUSH_FRAME:
José Fonseca9d97c3d2009-03-25 13:31:27 +0000641 self._present()
José Fonseca059d7f32009-02-20 15:23:33 +0000642 self.dirty = False
José Fonsecac9751522008-08-14 22:03:35 +0100643 return None
José Fonseca468c9772008-08-14 11:00:22 +0100644
Michel Dänzereb168e22009-04-04 19:01:51 +0200645 def clear(self, buffers, rgba, depth, stencil):
José Fonsecac14562d2009-04-08 15:36:17 +0100646 _rgba = gallium.FloatArray(4)
647 for i in range(4):
648 _rgba[i] = rgba[i]
649 self.real.clear(buffers, _rgba, depth, stencil)
José Fonseca468c9772008-08-14 11:00:22 +0100650
José Fonseca9d97c3d2009-03-25 13:31:27 +0000651 def _present(self):
José Fonseca468c9772008-08-14 11:00:22 +0100652 self.real.flush()
653
654 if self.cbufs and self.cbufs[0]:
José Fonseca9d97c3d2009-03-25 13:31:27 +0000655 self.interpreter.present(self.cbufs[0], "cbuf")
José Fonseca0ddc3832009-06-11 20:46:07 +0100656 if self.zsbuf:
657 if self.interpreter.options.all:
658 self.interpreter.present(self.zsbuf, "zsbuf")
José Fonseca468c9772008-08-14 11:00:22 +0100659
660
José Fonseca56ce90c2008-11-19 17:17:06 +0900661class Interpreter(parser.TraceDumper):
José Fonseca468c9772008-08-14 11:00:22 +0100662
José Fonseca03f19bc2008-11-19 20:06:04 +0900663 ignore_calls = set((
664 ('pipe_screen', 'is_format_supported'),
665 ('pipe_screen', 'get_param'),
666 ('pipe_screen', 'get_paramf'),
667 ))
668
José Fonseca9d97c3d2009-03-25 13:31:27 +0000669 def __init__(self, stream, options):
José Fonseca56ce90c2008-11-19 17:17:06 +0900670 parser.TraceDumper.__init__(self, stream)
José Fonseca9d97c3d2009-03-25 13:31:27 +0000671 self.options = options
José Fonseca468c9772008-08-14 11:00:22 +0100672 self.objects = {}
673 self.result = None
674 self.globl = Global(self, None)
José Fonseca710bcc82009-03-25 14:02:49 +0000675 self.call_no = None
José Fonseca468c9772008-08-14 11:00:22 +0100676
677 def register_object(self, address, object):
678 self.objects[address] = object
679
680 def unregister_object(self, object):
681 # FIXME:
682 pass
683
684 def lookup_object(self, address):
685 return self.objects[address]
686
687 def interpret(self, trace):
688 for call in trace.calls:
689 self.interpret_call(call)
690
José Fonseca7f3c3682008-08-22 01:23:48 +0100691 def handle_call(self, call):
José Fonseca2ba98ef2009-07-16 19:34:44 +0100692 if self.options.stop and call.no > self.options.stop:
José Fonseca84e78462009-04-08 16:25:29 +0100693 sys.exit(0)
José Fonseca03f19bc2008-11-19 20:06:04 +0900694
695 if (call.klass, call.method) in self.ignore_calls:
696 return
697
José Fonseca710bcc82009-03-25 14:02:49 +0000698 self.call_no = call.no
699
José Fonseca9d97c3d2009-03-25 13:31:27 +0000700 if self.verbosity(1):
José Fonsecae92f3312009-02-20 15:14:15 +0000701 parser.TraceDumper.handle_call(self, call)
José Fonseca5807ccb2009-07-16 19:31:36 +0100702 sys.stdout.flush()
José Fonseca468c9772008-08-14 11:00:22 +0100703
José Fonsecac14562d2009-04-08 15:36:17 +0100704 args = [(str(name), self.interpret_arg(arg)) for name, arg in call.args]
José Fonseca468c9772008-08-14 11:00:22 +0100705
706 if call.klass:
José Fonsecac14562d2009-04-08 15:36:17 +0100707 name, obj = args[0]
José Fonseca468c9772008-08-14 11:00:22 +0100708 args = args[1:]
709 else:
710 obj = self.globl
711
712 method = getattr(obj, call.method)
José Fonsecac14562d2009-04-08 15:36:17 +0100713 ret = method(**dict(args))
José Fonseca468c9772008-08-14 11:00:22 +0100714
715 if call.ret and isinstance(call.ret, model.Pointer):
José Fonseca71504c72009-04-08 21:13:57 +0100716 if ret is None:
717 sys.stderr.write('warning: NULL returned\n')
José Fonseca468c9772008-08-14 11:00:22 +0100718 self.register_object(call.ret.address, ret)
719
José Fonseca710bcc82009-03-25 14:02:49 +0000720 self.call_no = None
721
José Fonseca468c9772008-08-14 11:00:22 +0100722 def interpret_arg(self, node):
723 translator = Translator(self)
724 return translator.visit(node)
José Fonseca9d97c3d2009-03-25 13:31:27 +0000725
726 def verbosity(self, level):
727 return self.options.verbosity >= level
728
José Fonseca0ddc3832009-06-11 20:46:07 +0100729 def present(self, surface, description, x=None, y=None, w=None, h=None):
José Fonseca84e78462009-04-08 16:25:29 +0100730 if self.call_no < self.options.start:
731 return
732
José Fonseca9d97c3d2009-03-25 13:31:27 +0000733 if self.options.images:
José Fonseca0ddc3832009-06-11 20:46:07 +0100734 filename = '%04u_%s.png' % (self.call_no, description)
735 save_image(filename, surface, x, y, w, h)
José Fonseca9d97c3d2009-03-25 13:31:27 +0000736 else:
José Fonsecade89c022009-03-25 15:36:51 +0000737 title = '%u. %s' % (self.call_no, description)
José Fonseca0ddc3832009-06-11 20:46:07 +0100738 show_image(surface, title, x, y, w, h)
José Fonseca468c9772008-08-14 11:00:22 +0100739
740
José Fonseca9d97c3d2009-03-25 13:31:27 +0000741class Main(parser.Main):
742
743 def get_optparser(self):
744 optparser = parser.Main.get_optparser(self)
745 optparser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbosity", help="no messages")
746 optparser.add_option("-v", "--verbose", action="count", dest="verbosity", default=1, help="increase verbosity level")
747 optparser.add_option("-i", "--images", action="store_true", dest="images", default=False, help="save images instead of showing them")
José Fonseca0ddc3832009-06-11 20:46:07 +0100748 optparser.add_option("-a", "--all", action="store_true", dest="all", default=False, help="show depth, stencil, and transfers")
José Fonseca9d97c3d2009-03-25 13:31:27 +0000749 optparser.add_option("-s", "--step", action="store_true", dest="step", default=False, help="step trhough every draw")
José Fonseca84e78462009-04-08 16:25:29 +0100750 optparser.add_option("-f", "--from", action="store", type="int", dest="start", default=0, help="from call no")
751 optparser.add_option("-t", "--to", action="store", type="int", dest="stop", default=0, help="until call no")
José Fonseca9d97c3d2009-03-25 13:31:27 +0000752 return optparser
753
754 def process_arg(self, stream, options):
755 parser = Interpreter(stream, options)
756 parser.parse()
757
758
José Fonseca468c9772008-08-14 11:00:22 +0100759if __name__ == '__main__':
José Fonseca9d97c3d2009-03-25 13:31:27 +0000760 Main().main()