Merge commit 'origin/master' into gallium-0.2
[mesa.git] / src / gallium / state_trackers / python / retrace / interpreter.py
1 #!/usr/bin/env python
2 #############################################################################
3 #
4 # Copyright 2008 Tungsten Graphics, Inc.
5 #
6 # This program is free software: you can redistribute it and/or modify it
7 # under the terms of the GNU Lesser General Public License as published
8 # by the Free Software Foundation, either version 3 of the License, or
9 # (at your option) any later version.
10 #
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU Lesser General Public License for more details.
15 #
16 # You should have received a copy of the GNU Lesser General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
18 #
19 #############################################################################
20
21
22 import sys
23 import gallium
24 import model
25 import parser
26
27
28 def make_image(surface):
29 pixels = gallium.FloatArray(surface.height*surface.width*4)
30 surface.get_tile_rgba(0, 0, surface.width, surface.height, pixels)
31
32 import Image
33 outimage = Image.new(
34 mode='RGB',
35 size=(surface.width, surface.height),
36 color=(0,0,0))
37 outpixels = outimage.load()
38 for y in range(0, surface.height):
39 for x in range(0, surface.width):
40 offset = (y*surface.width + x)*4
41 r, g, b, a = [int(pixels[offset + ch]*255) for ch in range(4)]
42 outpixels[x, y] = r, g, b
43 return outimage
44
45 def save_image(filename, surface):
46 outimage = make_image(surface)
47 outimage.save(filename, "PNG")
48
49 def show_image(surface):
50 outimage = make_image(surface)
51
52 import Tkinter as tk
53 from PIL import Image, ImageTk
54 root = tk.Tk()
55
56 root.title('background image')
57
58 image1 = ImageTk.PhotoImage(outimage)
59 w = image1.width()
60 h = image1.height()
61 x = 100
62 y = 100
63 root.geometry("%dx%d+%d+%d" % (w, h, x, y))
64 panel1 = tk.Label(root, image=image1)
65 panel1.pack(side='top', fill='both', expand='yes')
66 panel1.image = image1
67 root.mainloop()
68
69
70
71
72 class Struct:
73 """C-like struct"""
74
75 # A basic Python class can pass as a C-like structure
76 pass
77
78
79 struct_factories = {
80 "pipe_blend_color": gallium.BlendColor,
81 "pipe_blend_state": gallium.Blend,
82 #"pipe_clip_state": gallium.Clip,
83 #"pipe_constant_buffer": gallium.ConstantBuffer,
84 "pipe_depth_state": gallium.Depth,
85 "pipe_stencil_state": gallium.Stencil,
86 "pipe_alpha_state": gallium.Alpha,
87 "pipe_depth_stencil_alpha_state": gallium.DepthStencilAlpha,
88 "pipe_format_block": gallium.FormatBlock,
89 #"pipe_framebuffer_state": gallium.Framebuffer,
90 "pipe_poly_stipple": gallium.PolyStipple,
91 "pipe_rasterizer_state": gallium.Rasterizer,
92 "pipe_sampler_state": gallium.Sampler,
93 "pipe_scissor_state": gallium.Scissor,
94 #"pipe_shader_state": gallium.Shader,
95 #"pipe_vertex_buffer": gallium.VertexBuffer,
96 "pipe_vertex_element": gallium.VertexElement,
97 "pipe_viewport_state": gallium.Viewport,
98 #"pipe_texture": gallium.Texture,
99 }
100
101
102 member_array_factories = {
103 "pipe_rasterizer_state": {"sprite_coord_mode": gallium.ByteArray},
104 "pipe_poly_stipple": {"stipple": gallium.UnsignedArray},
105 "pipe_viewport_state": {"scale": gallium.FloatArray, "translate": gallium.FloatArray},
106 #"pipe_clip_state": {"ucp": gallium.FloatArray},
107 "pipe_depth_stencil_alpha_state": {"stencil": gallium.StencilArray},
108 "pipe_blend_color": {"color": gallium.FloatArray},
109 "pipe_sampler_state": {"border_color": gallium.FloatArray},
110 }
111
112
113 class Translator(model.Visitor):
114 """Translate model arguments into regular Python objects"""
115
116 def __init__(self, interpreter):
117 self.interpreter = interpreter
118 self.result = None
119
120 def visit(self, node):
121 self.result = None
122 node.visit(self)
123 return self.result
124
125 def visit_literal(self, node):
126 self.result = node.value
127
128 def visit_named_constant(self, node):
129 # lookup the named constant in the gallium module
130 self.result = getattr(gallium, node.name)
131
132 def visit_array(self, node):
133 array = []
134 for element in node.elements:
135 array.append(self.visit(element))
136 self.result = array
137
138 def visit_struct(self, node):
139 struct_factory = struct_factories.get(node.name, Struct)
140 struct = struct_factory()
141 for member_name, member_node in node.members:
142 member_value = self.visit(member_node)
143 try:
144 array_factory = member_array_factories[node.name][member_name]
145 except KeyError:
146 pass
147 else:
148 assert isinstance(member_value, list)
149 array = array_factory(len(member_value))
150 for i in range(len(member_value)):
151 array[i] = member_value[i]
152 member_value = array
153 #print node.name, member_name, member_value
154 assert isinstance(struct, Struct) or hasattr(struct, member_name)
155 setattr(struct, member_name, member_value)
156 self.result = struct
157
158 def visit_pointer(self, node):
159 self.result = self.interpreter.lookup_object(node.address)
160
161
162 class Object:
163
164 def __init__(self, interpreter, real):
165 self.interpreter = interpreter
166 self.real = real
167
168
169 class Global(Object):
170
171 def __init__(self, interpreter, real):
172 self.interpreter = interpreter
173 self.real = real
174
175 def pipe_winsys_create(self):
176 return Winsys(self.interpreter, gallium.Device())
177
178 def pipe_screen_create(self, winsys):
179 return Screen(self.interpreter, winsys.real)
180
181 def pipe_context_create(self, screen):
182 context = screen.real.context_create()
183 return Context(self.interpreter, context)
184
185
186 class Winsys(Object):
187
188 def __init__(self, interpreter, real):
189 self.interpreter = interpreter
190 self.real = real
191
192 def get_name(self):
193 pass
194
195 def user_buffer_create(self, data, size):
196 # We don't really care to distinguish between user and regular buffers
197 buffer = self.real.buffer_create(size,
198 4,
199 gallium.PIPE_BUFFER_USAGE_CPU_READ |
200 gallium.PIPE_BUFFER_USAGE_CPU_WRITE )
201 buffer.write(data, size)
202 return buffer
203
204 def buffer_create(self, alignment, usage, size):
205 return self.real.buffer_create(size, alignment, usage)
206
207 def buffer_destroy(self, buffer):
208 pass
209
210 def buffer_write(self, buffer, data, size):
211 buffer.write(data, size)
212
213 def fence_finish(self, fence, flags):
214 pass
215
216 def fence_reference(self, dst, src):
217 pass
218
219 def flush_frontbuffer(self, surface):
220 pass
221
222 def surface_alloc(self):
223 return None
224
225 def surface_release(self, surface):
226 pass
227
228
229 class Screen(Object):
230
231 def get_name(self):
232 pass
233
234 def get_vendor(self):
235 pass
236
237 def get_param(self, param):
238 pass
239
240 def get_paramf(self, param):
241 pass
242
243 def is_format_supported(self, format, target, tex_usage, geom_flags):
244 return self.real.is_format_supported(format, target, tex_usage, geom_flags)
245
246 def texture_create(self, template):
247 return self.real.texture_create(
248 format = template.format,
249 width = template.width[0],
250 height = template.height[0],
251 depth = template.depth[0],
252 last_level = template.last_level,
253 target = template.target,
254 tex_usage = template.tex_usage,
255 )
256
257 def texture_destroy(self, texture):
258 self.interpreter.unregister_object(texture)
259
260 def texture_release(self, surface):
261 pass
262
263 def get_tex_surface(self, texture, face, level, zslice, usage):
264 return texture.get_surface(face, level, zslice, usage)
265
266 def tex_surface_destroy(self, surface):
267 self.interpreter.unregister_object(surface)
268
269 def tex_surface_release(self, surface):
270 pass
271
272 def surface_write(self, surface, data, stride, size):
273 assert surface.nblocksy * stride == size
274 surface.put_tile_raw(0, 0, surface.width, surface.height, data, stride)
275
276
277 class Context(Object):
278
279 def __init__(self, interpreter, real):
280 Object.__init__(self, interpreter, real)
281 self.cbufs = []
282 self.zsbuf = None
283
284 def destroy(self):
285 pass
286
287 def create_blend_state(self, state):
288 return state
289
290 def bind_blend_state(self, state):
291 if state is not None:
292 self.real.set_blend(state)
293
294 def delete_blend_state(self, state):
295 pass
296
297 def create_sampler_state(self, state):
298 return state
299
300 def delete_sampler_state(self, state):
301 pass
302
303 def bind_sampler_states(self, n, states):
304 for i in range(n):
305 self.real.set_sampler(i, states[i])
306
307 def create_rasterizer_state(self, state):
308 return state
309
310 def bind_rasterizer_state(self, state):
311 if state is not None:
312 self.real.set_rasterizer(state)
313
314 def delete_rasterizer_state(self, state):
315 pass
316
317 def create_depth_stencil_alpha_state(self, state):
318 return state
319
320 def bind_depth_stencil_alpha_state(self, state):
321 if state is not None:
322 self.real.set_depth_stencil_alpha(state)
323
324 def delete_depth_stencil_alpha_state(self, state):
325 pass
326
327 def create_fs_state(self, state):
328 tokens = str(state.tokens)
329 shader = gallium.Shader(tokens)
330 return shader
331
332 create_vs_state = create_fs_state
333
334 def bind_fs_state(self, state):
335 self.real.set_fragment_shader(state)
336
337 def bind_vs_state(self, state):
338 self.real.set_vertex_shader(state)
339
340 def delete_fs_state(self, state):
341 pass
342
343 delete_vs_state = delete_fs_state
344
345 def set_blend_color(self, state):
346 self.real.set_blend_color(state)
347
348 def set_clip_state(self, state):
349 _state = gallium.Clip()
350 _state.nr = state.nr
351 if state.nr:
352 # FIXME
353 ucp = gallium.FloatArray(gallium.PIPE_MAX_CLIP_PLANES*4)
354 for i in range(len(state.ucp)):
355 for j in range(len(state.ucp[i])):
356 ucp[i*4 + j] = state.ucp[i][j]
357 _state.ucp = ucp
358 self.real.set_clip(_state)
359
360 def set_constant_buffer(self, shader, index, state):
361 if state is not None:
362 self.real.set_constant_buffer(shader, index, state.buffer)
363
364 def set_framebuffer_state(self, state):
365 _state = gallium.Framebuffer()
366 _state.width = state.width
367 _state.height = state.height
368 _state.num_cbufs = state.num_cbufs
369 for i in range(len(state.cbufs)):
370 _state.set_cbuf(i, state.cbufs[i])
371 _state.set_zsbuf(state.zsbuf)
372 self.real.set_framebuffer(_state)
373
374 self.cbufs = state.cbufs
375 self.zsbuf = state.zsbuf
376
377 def set_polygon_stipple(self, state):
378 self.real.set_polygon_stipple(state)
379
380 def set_scissor_state(self, state):
381 self.real.set_scissor(state)
382
383 def set_viewport_state(self, state):
384 self.real.set_viewport(state)
385
386 def set_sampler_textures(self, n, textures):
387 for i in range(n):
388 self.real.set_sampler_texture(i, textures[i])
389
390 def set_vertex_buffers(self, n, vbufs):
391 for i in range(n):
392 vbuf = vbufs[i]
393 self.real.set_vertex_buffer(
394 i,
395 pitch = vbuf.pitch,
396 max_index = vbuf.max_index,
397 buffer_offset = vbuf.buffer_offset,
398 buffer = vbuf.buffer,
399 )
400
401 def set_vertex_elements(self, n, elements):
402 for i in range(n):
403 self.real.set_vertex_element(i, elements[i])
404 self.real.set_vertex_elements(n)
405
406 def set_edgeflags(self, bitfield):
407 # FIXME
408 pass
409
410 def draw_arrays(self, mode, start, count):
411 self.real.draw_arrays(mode, start, count)
412
413 def draw_elements(self, indexBuffer, indexSize, mode, start, count):
414 self.real.draw_elements(indexBuffer, indexSize, mode, start, count)
415
416 def draw_range_elements(self, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count):
417 self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count)
418
419 def flush(self, flags):
420 self.real.flush(flags)
421 if flags & gallium.PIPE_FLUSH_FRAME:
422 self._update()
423 return None
424
425 def clear(self, surface, value):
426 self.real.surface_clear(surface, value)
427
428 def _update(self):
429 self.real.flush()
430
431 if self.cbufs and self.cbufs[0]:
432 show_image(self.cbufs[0])
433
434
435 class Interpreter(parser.TraceParser):
436
437 def __init__(self, stream):
438 parser.TraceParser.__init__(self, stream)
439 self.objects = {}
440 self.result = None
441 self.globl = Global(self, None)
442
443 def register_object(self, address, object):
444 self.objects[address] = object
445
446 def unregister_object(self, object):
447 # FIXME:
448 pass
449
450 def lookup_object(self, address):
451 return self.objects[address]
452
453 def interpret(self, trace):
454 for call in trace.calls:
455 self.interpret_call(call)
456
457 def handle_call(self, call):
458 sys.stderr.write("%s\n" % call)
459
460 args = [self.interpret_arg(arg) for name, arg in call.args]
461
462 if call.klass:
463 obj = args[0]
464 args = args[1:]
465 else:
466 obj = self.globl
467
468 method = getattr(obj, call.method)
469 ret = method(*args)
470
471 if call.ret and isinstance(call.ret, model.Pointer):
472 self.register_object(call.ret.address, ret)
473
474 def interpret_arg(self, node):
475 translator = Translator(self)
476 return translator.visit(node)
477
478
479 if __name__ == '__main__':
480 parser.main(Interpreter)