2 ##########################################################################
4 # Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas.
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:
15 # The above copyright notice and this permission notice (including the
16 # next paragraph) shall be included in all copies or substantial portions
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.
27 ##########################################################################
39 from struct
import unpack_from
41 def unpack_from(fmt
, buf
, offset
=0):
42 size
= struct
.calcsize(fmt
)
43 return struct
.unpack(fmt
, buf
[offset
:offset
+ size
])
46 def make_image(surface
):
47 data
= surface
.get_tile_rgba8(0, 0, surface
.width
, surface
.height
)
50 outimage
= Image
.fromstring('RGBA', (surface
.width
, surface
.height
), data
, "raw", 'RGBA', 0, 1)
53 def save_image(filename
, surface
):
54 outimage
= make_image(surface
)
55 outimage
.save(filename
, "PNG")
57 def show_image(surface
):
58 outimage
= make_image(surface
)
61 from PIL
import Image
, ImageTk
64 root
.title('background image')
66 image1
= ImageTk
.PhotoImage(outimage
)
71 root
.geometry("%dx%d+%d+%d" % (w
, h
, x
, y
))
72 panel1
= tk
.Label(root
, image
=image1
)
73 panel1
.pack(side
='top', fill
='both', expand
='yes')
78 # Verbosity level: 0, 1, 2
80 # Dump images to disk instead of showing: True, False
90 # A basic Python class can pass as a C-like structure
95 "pipe_blend_color": gallium
.BlendColor
,
96 "pipe_blend_state": gallium
.Blend
,
97 #"pipe_clip_state": gallium.Clip,
98 #"pipe_constant_buffer": gallium.ConstantBuffer,
99 "pipe_depth_state": gallium
.Depth
,
100 "pipe_stencil_state": gallium
.Stencil
,
101 "pipe_alpha_state": gallium
.Alpha
,
102 "pipe_depth_stencil_alpha_state": gallium
.DepthStencilAlpha
,
103 "pipe_format_block": gallium
.FormatBlock
,
104 #"pipe_framebuffer_state": gallium.Framebuffer,
105 "pipe_poly_stipple": gallium
.PolyStipple
,
106 "pipe_rasterizer_state": gallium
.Rasterizer
,
107 "pipe_sampler_state": gallium
.Sampler
,
108 "pipe_scissor_state": gallium
.Scissor
,
109 #"pipe_shader_state": gallium.Shader,
110 #"pipe_vertex_buffer": gallium.VertexBuffer,
111 "pipe_vertex_element": gallium
.VertexElement
,
112 "pipe_viewport_state": gallium
.Viewport
,
113 #"pipe_texture": gallium.Texture,
117 member_array_factories
= {
118 "pipe_rasterizer_state": {"sprite_coord_mode": gallium
.ByteArray
},
119 "pipe_poly_stipple": {"stipple": gallium
.UnsignedArray
},
120 "pipe_viewport_state": {"scale": gallium
.FloatArray
, "translate": gallium
.FloatArray
},
121 #"pipe_clip_state": {"ucp": gallium.FloatArray},
122 "pipe_depth_stencil_alpha_state": {"stencil": gallium
.StencilArray
},
123 "pipe_blend_color": {"color": gallium
.FloatArray
},
124 "pipe_sampler_state": {"border_color": gallium
.FloatArray
},
128 class Translator(model
.Visitor
):
129 """Translate model arguments into regular Python objects"""
131 def __init__(self
, interpreter
):
132 self
.interpreter
= interpreter
135 def visit(self
, node
):
140 def visit_literal(self
, node
):
141 self
.result
= node
.value
143 def visit_named_constant(self
, node
):
144 # lookup the named constant in the gallium module
145 self
.result
= getattr(gallium
, node
.name
)
147 def visit_array(self
, node
):
149 for element
in node
.elements
:
150 array
.append(self
.visit(element
))
153 def visit_struct(self
, node
):
154 struct_factory
= struct_factories
.get(node
.name
, Struct
)
155 struct
= struct_factory()
156 for member_name
, member_node
in node
.members
:
157 member_value
= self
.visit(member_node
)
159 array_factory
= member_array_factories
[node
.name
][member_name
]
163 assert isinstance(member_value
, list)
164 array
= array_factory(len(member_value
))
165 for i
in range(len(member_value
)):
166 array
[i
] = member_value
[i
]
168 #print node.name, member_name, member_value
169 assert isinstance(struct
, Struct
) or hasattr(struct
, member_name
)
170 setattr(struct
, member_name
, member_value
)
173 def visit_pointer(self
, node
):
174 self
.result
= self
.interpreter
.lookup_object(node
.address
)
179 def __init__(self
, interpreter
, real
):
180 self
.interpreter
= interpreter
184 class Global(Object
):
186 def __init__(self
, interpreter
, real
):
187 self
.interpreter
= interpreter
190 def pipe_winsys_create(self
):
191 return Winsys(self
.interpreter
, gallium
.Device())
193 def pipe_screen_create(self
, winsys
):
194 return Screen(self
.interpreter
, winsys
.real
)
196 def pipe_context_create(self
, screen
):
197 context
= screen
.real
.context_create()
198 return Context(self
.interpreter
, context
)
201 class Winsys(Object
):
203 def __init__(self
, interpreter
, real
):
204 self
.interpreter
= interpreter
210 def user_buffer_create(self
, data
, size
):
211 # We don't really care to distinguish between user and regular buffers
212 buffer = self
.real
.buffer_create(size
,
214 gallium
.PIPE_BUFFER_USAGE_CPU_READ |
215 gallium
.PIPE_BUFFER_USAGE_CPU_WRITE
)
216 assert size
== len(data
)
220 def buffer_create(self
, alignment
, usage
, size
):
221 return self
.real
.buffer_create(size
, alignment
, usage
)
223 def buffer_destroy(self
, buffer):
226 def buffer_write(self
, buffer, data
, size
):
227 assert size
== len(data
)
230 def fence_finish(self
, fence
, flags
):
233 def fence_reference(self
, dst
, src
):
236 def flush_frontbuffer(self
, surface
):
239 def surface_alloc(self
):
242 def surface_release(self
, surface
):
246 class Screen(Object
):
254 def get_vendor(self
):
257 def get_param(self
, param
):
260 def get_paramf(self
, param
):
263 def is_format_supported(self
, format
, target
, tex_usage
, geom_flags
):
264 return self
.real
.is_format_supported(format
, target
, tex_usage
, geom_flags
)
266 def texture_create(self
, template
):
267 return self
.real
.texture_create(
268 format
= template
.format
,
269 width
= template
.width
[0],
270 height
= template
.height
[0],
271 depth
= template
.depth
[0],
272 last_level
= template
.last_level
,
273 target
= template
.target
,
274 tex_usage
= template
.tex_usage
,
277 def texture_destroy(self
, texture
):
278 self
.interpreter
.unregister_object(texture
)
280 def texture_release(self
, surface
):
283 def get_tex_surface(self
, texture
, face
, level
, zslice
, usage
):
284 return texture
.get_surface(face
, level
, zslice
, usage
)
286 def tex_surface_destroy(self
, surface
):
287 self
.interpreter
.unregister_object(surface
)
289 def tex_surface_release(self
, surface
):
292 def surface_write(self
, surface
, data
, stride
, size
):
293 assert surface
.nblocksy
* stride
== size
294 surface
.put_tile_raw(0, 0, surface
.width
, surface
.height
, data
, stride
)
297 class Context(Object
):
299 def __init__(self
, interpreter
, real
):
300 Object
.__init
__(self
, interpreter
, real
)
310 def create_blend_state(self
, state
):
313 def bind_blend_state(self
, state
):
314 if state
is not None:
315 self
.real
.set_blend(state
)
317 def delete_blend_state(self
, state
):
320 def create_sampler_state(self
, state
):
323 def delete_sampler_state(self
, state
):
326 def bind_sampler_states(self
, n
, states
):
328 self
.real
.set_sampler(i
, states
[i
])
330 def create_rasterizer_state(self
, state
):
333 def bind_rasterizer_state(self
, state
):
334 if state
is not None:
335 self
.real
.set_rasterizer(state
)
337 def delete_rasterizer_state(self
, state
):
340 def create_depth_stencil_alpha_state(self
, state
):
343 def bind_depth_stencil_alpha_state(self
, state
):
344 if state
is not None:
345 self
.real
.set_depth_stencil_alpha(state
)
347 def delete_depth_stencil_alpha_state(self
, state
):
350 def create_fs_state(self
, state
):
351 tokens
= str(state
.tokens
)
352 shader
= gallium
.Shader(tokens
)
355 create_vs_state
= create_fs_state
357 def bind_fs_state(self
, state
):
358 self
.real
.set_fragment_shader(state
)
360 def bind_vs_state(self
, state
):
361 self
.real
.set_vertex_shader(state
)
363 def delete_fs_state(self
, state
):
366 delete_vs_state
= delete_fs_state
368 def set_blend_color(self
, state
):
369 self
.real
.set_blend_color(state
)
371 def set_clip_state(self
, state
):
372 _state
= gallium
.Clip()
376 ucp
= gallium
.FloatArray(gallium
.PIPE_MAX_CLIP_PLANES
*4)
377 for i
in range(len(state
.ucp
)):
378 for j
in range(len(state
.ucp
[i
])):
379 ucp
[i
*4 + j
] = state
.ucp
[i
][j
]
381 self
.real
.set_clip(_state
)
383 def dump_constant_buffer(self
, buffer):
390 for offset
in range(0, len(data
), struct
.calcsize(format
)):
391 x
, y
, z
, w
= unpack_from(format
, data
, offset
)
392 sys
.stdout
.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index
, x
, y
, z
, w
))
395 def set_constant_buffer(self
, shader
, index
, state
):
396 if state
is not None:
397 self
.real
.set_constant_buffer(shader
, index
, state
.buffer)
399 self
.dump_constant_buffer(state
.buffer)
401 def set_framebuffer_state(self
, state
):
402 _state
= gallium
.Framebuffer()
403 _state
.width
= state
.width
404 _state
.height
= state
.height
405 _state
.nr_cbufs
= state
.nr_cbufs
406 for i
in range(len(state
.cbufs
)):
407 _state
.set_cbuf(i
, state
.cbufs
[i
])
408 _state
.set_zsbuf(state
.zsbuf
)
409 self
.real
.set_framebuffer(_state
)
411 self
.cbufs
= state
.cbufs
412 self
.zsbuf
= state
.zsbuf
414 def set_polygon_stipple(self
, state
):
415 self
.real
.set_polygon_stipple(state
)
417 def set_scissor_state(self
, state
):
418 self
.real
.set_scissor(state
)
420 def set_viewport_state(self
, state
):
421 self
.real
.set_viewport(state
)
423 def set_sampler_textures(self
, n
, textures
):
425 self
.real
.set_sampler_texture(i
, textures
[i
])
427 def set_vertex_buffers(self
, n
, vbufs
):
428 self
.vbufs
= vbufs
[0:n
]
431 self
.real
.set_vertex_buffer(
433 stride
= vbuf
.stride
,
434 max_index
= vbuf
.max_index
,
435 buffer_offset
= vbuf
.buffer_offset
,
436 buffer = vbuf
.buffer,
439 def set_vertex_elements(self
, n
, elements
):
440 self
.velems
= elements
[0:n
]
442 self
.real
.set_vertex_element(i
, elements
[i
])
443 self
.real
.set_vertex_elements(n
)
445 def set_edgeflags(self
, bitfield
):
449 def dump_vertices(self
, start
, count
):
453 for index
in range(start
, start
+ count
):
454 if index
>= start
+ 16:
455 sys
.stdout
.write('\t...\n')
457 sys
.stdout
.write('\t{\n')
458 for velem
in self
.velems
:
459 vbuf
= self
.vbufs
[velem
.vertex_buffer_index
]
461 offset
= vbuf
.buffer_offset
+ velem
.src_offset
+ vbuf
.stride
*index
463 gallium
.PIPE_FORMAT_R32_FLOAT
: 'f',
464 gallium
.PIPE_FORMAT_R32G32_FLOAT
: '2f',
465 gallium
.PIPE_FORMAT_R32G32B32_FLOAT
: '3f',
466 gallium
.PIPE_FORMAT_R32G32B32A32_FLOAT
: '4f',
467 gallium
.PIPE_FORMAT_B8G8R8A8_UNORM
: '4B',
470 data
= vbuf
.buffer.read()
471 values
= unpack_from(format
, data
, offset
)
472 sys
.stdout
.write('\t\t{' + ', '.join(map(str, values
)) + '},\n')
473 assert len(values
) == velem
.nr_components
474 sys
.stdout
.write('\t},\n')
476 def dump_indices(self
, ibuf
, isize
, start
, count
):
486 assert struct
.calcsize(format
) == isize
489 maxindex
, minindex
= 0, 0xffffffff
491 sys
.stdout
.write('\t{\n')
492 for i
in range(start
, start
+ count
):
494 sys
.stdout
.write('\t...\n')
497 index
, = unpack_from(format
, data
, offset
)
498 sys
.stdout
.write('\t\t%u,\n' % index
)
499 minindex
= min(minindex
, index
)
500 maxindex
= max(maxindex
, index
)
501 sys
.stdout
.write('\t},\n')
503 return minindex
, maxindex
505 def draw_arrays(self
, mode
, start
, count
):
506 self
.dump_vertices(start
, count
)
508 self
.real
.draw_arrays(mode
, start
, count
)
512 def draw_elements(self
, indexBuffer
, indexSize
, mode
, start
, count
):
514 minindex
, maxindex
= self
.dump_indices(indexBuffer
, indexSize
, start
, count
)
515 self
.dump_vertices(minindex
, maxindex
- minindex
)
517 self
.real
.draw_elements(indexBuffer
, indexSize
, mode
, start
, count
)
521 def draw_range_elements(self
, indexBuffer
, indexSize
, minIndex
, maxIndex
, mode
, start
, count
):
523 minindex
, maxindex
= self
.dump_indices(indexBuffer
, indexSize
, start
, count
)
524 minindex
= min(minindex
, minIndex
)
525 maxindex
= min(maxindex
, maxIndex
)
526 self
.dump_vertices(minindex
, maxindex
- minindex
)
528 self
.real
.draw_range_elements(indexBuffer
, indexSize
, minIndex
, maxIndex
, mode
, start
, count
)
532 def flush(self
, flags
):
533 self
.real
.flush(flags
)
535 if flags
& gallium
.PIPE_FLUSH_FRAME
:
540 def clear(self
, surface
, value
):
541 self
.real
.surface_clear(surface
, value
)
546 if self
.cbufs
and self
.cbufs
[0]:
550 filename
= 'cbuf_%04u.png' % image_no
551 save_image(filename
, self
.cbufs
[0])
553 show_image(self
.cbufs
[0])
556 class Interpreter(parser
.TraceDumper
):
559 ('pipe_screen', 'is_format_supported'),
560 ('pipe_screen', 'get_param'),
561 ('pipe_screen', 'get_paramf'),
564 def __init__(self
, stream
):
565 parser
.TraceDumper
.__init
__(self
, stream
)
568 self
.globl
= Global(self
, None)
570 def register_object(self
, address
, object):
571 self
.objects
[address
] = object
573 def unregister_object(self
, object):
577 def lookup_object(self
, address
):
578 return self
.objects
[address
]
580 def interpret(self
, trace
):
581 for call
in trace
.calls
:
582 self
.interpret_call(call
)
584 def handle_call(self
, call
):
586 if (call
.klass
, call
.method
) in self
.ignore_calls
:
590 parser
.TraceDumper
.handle_call(self
, call
)
592 args
= [self
.interpret_arg(arg
) for name
, arg
in call
.args
]
600 method
= getattr(obj
, call
.method
)
603 if call
.ret
and isinstance(call
.ret
, model
.Pointer
):
604 self
.register_object(call
.ret
.address
, ret
)
606 def interpret_arg(self
, node
):
607 translator
= Translator(self
)
608 return translator
.visit(node
)
611 if __name__
== '__main__':
612 parser
.main(Interpreter
)