PageRenderTime 50ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/src/third_party/mesa/MesaLib/src/gallium/tests/python/retrace/interpreter.py

https://bitbucket.org/kennethendfinger/chromium
Python | 729 lines | 523 code | 161 blank | 45 comment | 75 complexity | 85c5869066e13ae456058d6ee650c3e6 MD5 | raw file
Possible License(s): AGPL-3.0, GPL-3.0, LGPL-2.1, CC-BY-SA-3.0, BSD-2-Clause, CC-BY-3.0, AGPL-1.0, Unlicense, 0BSD, MPL-2.0, LGPL-2.0, Apache-2.0, GPL-2.0, LGPL-3.0, BSD-3-Clause, MPL-2.0-no-copyleft-exception, MIT
  1. #!/usr/bin/env python
  2. ##########################################################################
  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. ##########################################################################
  28. import sys
  29. import struct
  30. import gallium
  31. import model
  32. import parse as parser
  33. try:
  34. from struct import unpack_from
  35. except ImportError:
  36. def unpack_from(fmt, buf, offset=0):
  37. size = struct.calcsize(fmt)
  38. return struct.unpack(fmt, buf[offset:offset + size])
  39. def make_image(ctx, surface, x=None, y=None, w=None, h=None):
  40. if x is None:
  41. x = 0
  42. if y is None:
  43. y = 0
  44. if w is None:
  45. w = surface.width - x
  46. if h is None:
  47. h = surface.height - y
  48. data = ctx.surface_read_rgba8(surface, x, y, surface.width, surface.height)
  49. import Image
  50. outimage = Image.fromstring('RGBA', (w, h), data, "raw", 'RGBA', 0, 1)
  51. return outimage
  52. def save_image(ctx, filename, surface, x=None, y=None, w=None, h=None):
  53. outimage = make_image(ctx, surface, x, y, w, h)
  54. outimage.save(filename, "PNG")
  55. def show_image(ctx, surface, title, x=None, y=None, w=None, h=None):
  56. outimage = make_image(ctx, surface, x, y, w, h)
  57. import Tkinter as tk
  58. from PIL import Image, ImageTk
  59. root = tk.Tk()
  60. root.title(title)
  61. image1 = ImageTk.PhotoImage(outimage)
  62. w = image1.width()
  63. h = image1.height()
  64. x = 100
  65. y = 100
  66. root.geometry("%dx%d+%d+%d" % (w, h, x, y))
  67. panel1 = tk.Label(root, image=image1)
  68. panel1.pack(side='top', fill='both', expand='yes')
  69. panel1.image = image1
  70. root.mainloop()
  71. class Struct:
  72. """C-like struct"""
  73. # A basic Python class can pass as a C-like structure
  74. pass
  75. struct_factories = {
  76. "pipe_blend_color": gallium.BlendColor,
  77. "pipe_blend_state": gallium.Blend,
  78. #"pipe_clip_state": gallium.Clip,
  79. #"pipe_buffer": gallium.Buffer,
  80. "pipe_depth_state": gallium.Depth,
  81. "pipe_stencil_state": gallium.Stencil,
  82. "pipe_alpha_state": gallium.Alpha,
  83. "pipe_depth_stencil_alpha_state": gallium.DepthStencilAlpha,
  84. #"pipe_framebuffer_state": gallium.Framebuffer,
  85. "pipe_poly_stipple": gallium.PolyStipple,
  86. "pipe_rasterizer_state": gallium.Rasterizer,
  87. "pipe_sampler_state": gallium.Sampler,
  88. "pipe_scissor_state": gallium.Scissor,
  89. #"pipe_shader_state": gallium.Shader,
  90. #"pipe_vertex_buffer": gallium.VertexBuffer,
  91. "pipe_vertex_element": gallium.VertexElement,
  92. "pipe_viewport_state": gallium.Viewport,
  93. #"pipe_texture": gallium.Texture,
  94. 'pipe_subresource': gallium.pipe_subresource,
  95. 'pipe_box': gallium.pipe_box,
  96. }
  97. member_array_factories = {
  98. #"pipe_rasterizer_state": {"sprite_coord_mode": gallium.ByteArray},
  99. "pipe_poly_stipple": {"stipple": gallium.UnsignedArray},
  100. "pipe_viewport_state": {"scale": gallium.FloatArray, "translate": gallium.FloatArray},
  101. #"pipe_clip_state": {"ucp": gallium.FloatArray},
  102. "pipe_depth_stencil_alpha_state": {"stencil": gallium.StencilArray},
  103. "pipe_blend_color": {"color": gallium.FloatArray},
  104. "pipe_sampler_state": {"border_color": gallium.FloatArray},
  105. }
  106. class Translator(model.Visitor):
  107. """Translate model arguments into regular Python objects"""
  108. def __init__(self, interpreter):
  109. self.interpreter = interpreter
  110. self.result = None
  111. def visit(self, node):
  112. self.result = None
  113. node.visit(self)
  114. return self.result
  115. def visit_literal(self, node):
  116. self.result = node.value
  117. def visit_named_constant(self, node):
  118. # lookup the named constant in the gallium module
  119. self.result = getattr(gallium, node.name)
  120. def visit_array(self, node):
  121. array = []
  122. for element in node.elements:
  123. array.append(self.visit(element))
  124. self.result = array
  125. def visit_struct(self, node):
  126. struct_factory = struct_factories.get(node.name, Struct)
  127. struct = struct_factory()
  128. for member_name, member_node in node.members:
  129. member_value = self.visit(member_node)
  130. try:
  131. array_factory = member_array_factories[node.name][member_name]
  132. except KeyError:
  133. pass
  134. else:
  135. assert isinstance(member_value, list)
  136. array = array_factory(len(member_value))
  137. for i in range(len(member_value)):
  138. array[i] = member_value[i]
  139. member_value = array
  140. #print node.name, member_name, member_value
  141. assert isinstance(struct, Struct) or hasattr(struct, member_name)
  142. setattr(struct, member_name, member_value)
  143. self.result = struct
  144. def visit_pointer(self, node):
  145. self.result = self.interpreter.lookup_object(node.address)
  146. class Object:
  147. def __init__(self, interpreter, real):
  148. self.interpreter = interpreter
  149. self.real = real
  150. class Global(Object):
  151. def __init__(self, interpreter, real):
  152. self.interpreter = interpreter
  153. self.real = real
  154. def pipe_screen_create(self):
  155. real = gallium.Device()
  156. return Screen(self.interpreter, real)
  157. def pipe_context_create(self, screen):
  158. context = screen.real.context_create()
  159. return Context(self.interpreter, context)
  160. class Transfer:
  161. def __init__(self, resource, usage, subresource, box):
  162. self.resource = resource
  163. self.usage = usage
  164. self.subresource = subresource
  165. self.box = box
  166. class Screen(Object):
  167. def __init__(self, interpreter, real):
  168. Object.__init__(self, interpreter, real)
  169. self.context = self.real.context_create()
  170. def destroy(self):
  171. pass
  172. def get_name(self):
  173. pass
  174. def get_vendor(self):
  175. pass
  176. def get_param(self, param):
  177. pass
  178. def get_paramf(self, param):
  179. pass
  180. def context_create(self):
  181. context = self.real.context_create()
  182. return Context(self.interpreter, context)
  183. def is_format_supported(self, format, target, sample_count, bind, geom_flags):
  184. return self.real.is_format_supported(format, target, sample_count, bind, geom_flags)
  185. def resource_create(self, templat):
  186. return self.real.resource_create(
  187. format = templat.format,
  188. width = templat.width,
  189. height = templat.height,
  190. depth = templat.depth,
  191. last_level = templat.last_level,
  192. target = templat.target,
  193. bind = templat.bind,
  194. )
  195. def texture_destroy(self, texture):
  196. self.interpreter.unregister_object(texture)
  197. def texture_release(self, surface):
  198. pass
  199. def get_tex_surface(self, texture, face, level, zslice, usage):
  200. if texture is None:
  201. return None
  202. return texture.get_surface(face, level, zslice)
  203. def tex_surface_destroy(self, surface):
  204. self.interpreter.unregister_object(surface)
  205. def tex_surface_release(self, surface):
  206. pass
  207. def user_buffer_create(self, data, size, usage):
  208. bind = usage
  209. # We don't really care to distinguish between user and regular buffers
  210. buffer = self.real.buffer_create(size, bind)
  211. assert size == len(data)
  212. self.context.buffer_write(buffer, data)
  213. return buffer
  214. def buffer_create(self, alignment, usage, size):
  215. return self.real.buffer_create(size, alignment, usage)
  216. def buffer_destroy(self, buffer):
  217. pass
  218. def fence_finish(self, fence, flags):
  219. pass
  220. def fence_reference(self, dst, src):
  221. pass
  222. def flush_frontbuffer(self, surface):
  223. pass
  224. class Context(Object):
  225. def __init__(self, interpreter, real):
  226. Object.__init__(self, interpreter, real)
  227. self.cbufs = []
  228. self.zsbuf = None
  229. self.vbufs = []
  230. self.velems = []
  231. self.dirty = False
  232. def destroy(self):
  233. pass
  234. def create_blend_state(self, state):
  235. if isinstance(state, str):
  236. state = gallium.Blend(state)
  237. sys.stdout.write('\t%s\n' % state)
  238. return state
  239. def bind_blend_state(self, state):
  240. if state is not None:
  241. self.real.set_blend(state)
  242. def delete_blend_state(self, state):
  243. pass
  244. def create_sampler_state(self, state):
  245. return state
  246. def delete_sampler_state(self, state):
  247. pass
  248. def bind_vertex_sampler_states(self, num_states, states):
  249. for i in range(num_states):
  250. self.real.set_vertex_sampler(i, states[i])
  251. def bind_fragment_sampler_states(self, num_states, states):
  252. for i in range(num_states):
  253. self.real.set_fragment_sampler(i, states[i])
  254. def create_rasterizer_state(self, state):
  255. return state
  256. def bind_rasterizer_state(self, state):
  257. if state is not None:
  258. self.real.set_rasterizer(state)
  259. def delete_rasterizer_state(self, state):
  260. pass
  261. def create_depth_stencil_alpha_state(self, state):
  262. return state
  263. def bind_depth_stencil_alpha_state(self, state):
  264. if state is not None:
  265. self.real.set_depth_stencil_alpha(state)
  266. def delete_depth_stencil_alpha_state(self, state):
  267. pass
  268. def create_fs_state(self, state):
  269. tokens = str(state.tokens)
  270. shader = gallium.Shader(tokens)
  271. return shader
  272. create_vs_state = create_fs_state
  273. def bind_fs_state(self, state):
  274. self.real.set_fragment_shader(state)
  275. def bind_vs_state(self, state):
  276. self.real.set_vertex_shader(state)
  277. def delete_fs_state(self, state):
  278. pass
  279. delete_vs_state = delete_fs_state
  280. def set_blend_color(self, state):
  281. self.real.set_blend_color(state)
  282. def set_stencil_ref(self, state):
  283. self.real.set_stencil_ref(state)
  284. def set_clip_state(self, state):
  285. _state = gallium.Clip()
  286. _state.nr = state.nr
  287. if state.nr:
  288. # FIXME
  289. ucp = gallium.FloatArray(gallium.PIPE_MAX_CLIP_PLANES*4)
  290. for i in range(len(state.ucp)):
  291. for j in range(len(state.ucp[i])):
  292. ucp[i*4 + j] = state.ucp[i][j]
  293. _state.ucp = ucp
  294. self.real.set_clip(_state)
  295. def dump_constant_buffer(self, buffer):
  296. if not self.interpreter.verbosity(2):
  297. return
  298. data = self.real.buffer_read(buffer)
  299. format = '4f'
  300. index = 0
  301. for offset in range(0, len(data), struct.calcsize(format)):
  302. x, y, z, w = unpack_from(format, data, offset)
  303. sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w))
  304. index += 1
  305. sys.stdout.flush()
  306. def set_constant_buffer(self, shader, index, buffer):
  307. if buffer is not None:
  308. self.real.set_constant_buffer(shader, index, buffer)
  309. self.dump_constant_buffer(buffer)
  310. def set_framebuffer_state(self, state):
  311. _state = gallium.Framebuffer()
  312. _state.width = state.width
  313. _state.height = state.height
  314. _state.nr_cbufs = state.nr_cbufs
  315. for i in range(len(state.cbufs)):
  316. _state.set_cbuf(i, state.cbufs[i])
  317. _state.set_zsbuf(state.zsbuf)
  318. self.real.set_framebuffer(_state)
  319. self.cbufs = state.cbufs
  320. self.zsbuf = state.zsbuf
  321. def set_polygon_stipple(self, state):
  322. self.real.set_polygon_stipple(state)
  323. def set_scissor_state(self, state):
  324. self.real.set_scissor(state)
  325. def set_viewport_state(self, state):
  326. self.real.set_viewport(state)
  327. def create_sampler_view(self, texture, templ):
  328. return self.real.create_sampler_view(texture,
  329. format = templ.format,
  330. first_level = templ.first_level,
  331. last_level = templ.last_level,
  332. swizzle_r = templ.swizzle_r,
  333. swizzle_g = templ.swizzle_r,
  334. swizzle_b = templ.swizzle_g,
  335. swizzle_a = templ.swizzle_a)
  336. def sampler_view_destroy(self, view):
  337. pass
  338. def set_fragment_sampler_views(self, num, views):
  339. for i in range(num):
  340. self.real.set_fragment_sampler_view(i, views[i])
  341. def set_vertex_sampler_views(self, num, views):
  342. for i in range(num):
  343. self.real.set_vertex_sampler_view(i, views[i])
  344. def set_vertex_buffers(self, num_buffers, buffers):
  345. self.vbufs = buffers[0:num_buffers]
  346. for i in range(num_buffers):
  347. vbuf = buffers[i]
  348. self.real.set_vertex_buffer(
  349. i,
  350. stride = vbuf.stride,
  351. max_index = vbuf.max_index,
  352. buffer_offset = vbuf.buffer_offset,
  353. buffer = vbuf.buffer,
  354. )
  355. def create_vertex_elements_state(self, num_elements, elements):
  356. return elements[0:num_elements]
  357. def bind_vertex_elements_state(self, state):
  358. if state is None:
  359. self.real.set_vertex_elements(0)
  360. return
  361. elements = state
  362. num_elements = len(elements)
  363. self.velems = elements
  364. for i in range(num_elements):
  365. self.real.set_vertex_element(i, elements[i])
  366. self.real.set_vertex_elements(num_elements)
  367. def delete_vertex_elements_state(self, state):
  368. pass
  369. def dump_vertices(self, start, count):
  370. if not self.interpreter.verbosity(2):
  371. return
  372. for index in range(start, start + count):
  373. if index >= start + 16:
  374. sys.stdout.write('\t...\n')
  375. break
  376. sys.stdout.write('\t{\n')
  377. for velem in self.velems:
  378. vbuf = self.vbufs[velem.vertex_buffer_index]
  379. offset = vbuf.buffer_offset + velem.src_offset + vbuf.stride*index
  380. format = {
  381. gallium.PIPE_FORMAT_R32_FLOAT: 'f',
  382. gallium.PIPE_FORMAT_R32G32_FLOAT: '2f',
  383. gallium.PIPE_FORMAT_R32G32B32_FLOAT: '3f',
  384. gallium.PIPE_FORMAT_R32G32B32A32_FLOAT: '4f',
  385. gallium.PIPE_FORMAT_A8R8G8B8_UNORM: '4B',
  386. gallium.PIPE_FORMAT_R8G8B8A8_UNORM: '4B',
  387. gallium.PIPE_FORMAT_B8G8R8A8_UNORM: '4B',
  388. gallium.PIPE_FORMAT_R16G16B16_SNORM: '3h',
  389. }[velem.src_format]
  390. data = self.real.buffer_read(vbuf.buffer)
  391. values = unpack_from(format, data, offset)
  392. sys.stdout.write('\t\t{' + ', '.join(map(str, values)) + '},\n')
  393. sys.stdout.write('\t},\n')
  394. sys.stdout.flush()
  395. def dump_indices(self, ibuf, isize, ibias, start, count):
  396. if not self.interpreter.verbosity(2):
  397. return
  398. format = {
  399. 1: 'B',
  400. 2: 'H',
  401. 4: 'I',
  402. }[isize]
  403. assert struct.calcsize(format) == isize
  404. data = self.real.buffer_read(ibuf)
  405. maxindex, minindex = 0, 0xffffffff
  406. sys.stdout.write('\t{\n')
  407. for i in range(start, start + count):
  408. if i >= start + 16 and not self.interpreter.verbosity(3):
  409. sys.stdout.write('\t...\n')
  410. break
  411. offset = i*isize
  412. index, = unpack_from(format, data, offset)
  413. sys.stdout.write('\t\t%u,\n' % index)
  414. minindex = min(minindex, index)
  415. maxindex = max(maxindex, index)
  416. sys.stdout.write('\t},\n')
  417. sys.stdout.flush()
  418. return minindex + ibias, maxindex + ibias
  419. def draw_arrays(self, mode, start, count):
  420. self.dump_vertices(start, count)
  421. self.real.draw_arrays(mode, start, count)
  422. self._set_dirty()
  423. def draw_elements(self, indexBuffer, indexSize, indexBias, mode, start, count):
  424. if self.interpreter.verbosity(2):
  425. minindex, maxindex = self.dump_indices(indexBuffer, indexSize, indexBias, start, count)
  426. self.dump_vertices(minindex, maxindex - minindex)
  427. self.real.draw_elements(indexBuffer, indexSize, indexBias, mode, start, count)
  428. self._set_dirty()
  429. def draw_range_elements(self, indexBuffer, indexSize, indexBias, minIndex, maxIndex, mode, start, count):
  430. if self.interpreter.verbosity(2):
  431. minindex, maxindex = self.dump_indices(indexBuffer, indexSize, indexBias, start, count)
  432. minindex = min(minindex, minIndex)
  433. maxindex = min(maxindex, maxIndex)
  434. self.dump_vertices(minindex, maxindex - minindex)
  435. self.real.draw_range_elements(indexBuffer, indexSize, indexBias, minIndex, maxIndex, mode, start, count)
  436. self._set_dirty()
  437. def resource_copy_region(self, dst, subdst, dstx, dsty, dstz, src, subsrc, srcx, srcy, srcz, width, height):
  438. if dst is not None and src is not None:
  439. if self.interpreter.options.all:
  440. self.interpreter.present(self.real, src, 'resource_copy_src', srcx, srcy, width, height)
  441. self.real.resource_copy_region(dst, subdst, dstx, dsty, dstx, src, subsrc, srcx, srcy, srcz, width, height)
  442. flags = 0
  443. self.flush(flags)
  444. if self.interpreter.options.all:
  445. self.interpreter.present(self.real, dst, 'resource_copy_dst', dstx, dsty, width, height)
  446. def is_resource_referenced(self, texture, face, level):
  447. #return self.real.is_resource_referenced(format, texture, face, level)
  448. pass
  449. def buffer_write(self, buffer, data, size, offset=0):
  450. assert size == len(data)
  451. self.buffer_write(buffer, data)
  452. def surface_write(self, surface, data, stride, size):
  453. if surface is None:
  454. return
  455. # assert surface.nblocksy * stride == size
  456. surface.put_tile_raw(0, 0, surface.width, surface.height, data, stride)
  457. def get_transfer(self, texture, sr, usage, box):
  458. if texture is None:
  459. return None
  460. transfer = Transfer(texture, sr, usage, box)
  461. if transfer and usage & gallium.PIPE_TRANSFER_READ:
  462. if self.interpreter.options.all:
  463. surface = texture.get_surface(sr.face, sr.level, box.z)
  464. self.interpreter.present(self.real, transfer.surface, 'transf_read', box.x, box.y, box.w, box.h)
  465. return transfer
  466. def tex_transfer_destroy(self, transfer):
  467. self.interpreter.unregister_object(transfer)
  468. def transfer_inline_write(self, resource, sr, usage, box, stride, slice_stride, data):
  469. self.real.transfer_inline_write(resource, sr, usage, box, data, stride, slice_stride)
  470. def _set_dirty(self):
  471. if self.interpreter.options.step:
  472. self._present()
  473. else:
  474. self.dirty = True
  475. def flush(self, flags):
  476. self.real.flush(flags)
  477. if self.dirty:
  478. if flags & gallium.PIPE_FLUSH_FRAME:
  479. self._present()
  480. self.dirty = False
  481. return None
  482. def clear(self, buffers, rgba, depth, stencil):
  483. _rgba = gallium.FloatArray(4)
  484. for i in range(4):
  485. _rgba[i] = rgba[i]
  486. self.real.clear(buffers, _rgba, depth, stencil)
  487. def _present(self):
  488. self.real.flush()
  489. if self.cbufs and self.cbufs[0]:
  490. self.interpreter.present(self.real, self.cbufs[0], "cbuf")
  491. if self.zsbuf:
  492. if self.interpreter.options.all:
  493. self.interpreter.present(self.real, self.zsbuf, "zsbuf")
  494. class Interpreter(parser.TraceDumper):
  495. ignore_calls = set((
  496. ('pipe_screen', 'is_format_supported'),
  497. ('pipe_screen', 'get_param'),
  498. ('pipe_screen', 'get_paramf'),
  499. ))
  500. def __init__(self, stream, options):
  501. parser.TraceDumper.__init__(self, stream)
  502. self.options = options
  503. self.objects = {}
  504. self.result = None
  505. self.globl = Global(self, None)
  506. self.call_no = None
  507. def register_object(self, address, object):
  508. self.objects[address] = object
  509. def unregister_object(self, object):
  510. # FIXME:
  511. pass
  512. def lookup_object(self, address):
  513. return self.objects[address]
  514. def interpret(self, trace):
  515. for call in trace.calls:
  516. self.interpret_call(call)
  517. def handle_call(self, call):
  518. if self.options.stop and call.no > self.options.stop:
  519. sys.exit(0)
  520. if (call.klass, call.method) in self.ignore_calls:
  521. return
  522. self.call_no = call.no
  523. if self.verbosity(1):
  524. parser.TraceDumper.handle_call(self, call)
  525. sys.stdout.flush()
  526. args = [(str(name), self.interpret_arg(arg)) for name, arg in call.args]
  527. if call.klass:
  528. name, obj = args[0]
  529. args = args[1:]
  530. else:
  531. obj = self.globl
  532. method = getattr(obj, call.method)
  533. ret = method(**dict(args))
  534. if call.ret and isinstance(call.ret, model.Pointer):
  535. if ret is None:
  536. sys.stderr.write('warning: NULL returned\n')
  537. self.register_object(call.ret.address, ret)
  538. self.call_no = None
  539. def interpret_arg(self, node):
  540. translator = Translator(self)
  541. return translator.visit(node)
  542. def verbosity(self, level):
  543. return self.options.verbosity >= level
  544. def present(self, ctx, surface, description, x=None, y=None, w=None, h=None):
  545. if self.call_no < self.options.start:
  546. return
  547. if self.options.images:
  548. filename = '%04u_%s.png' % (self.call_no, description)
  549. save_image(ctx, filename, surface, x, y, w, h)
  550. else:
  551. title = '%u. %s' % (self.call_no, description)
  552. show_image(ctx, surface, title, x, y, w, h)
  553. class Main(parser.Main):
  554. def get_optparser(self):
  555. optparser = parser.Main.get_optparser(self)
  556. optparser.add_option("-q", "--quiet", action="store_const", const=0, dest="verbosity", help="no messages")
  557. optparser.add_option("-v", "--verbose", action="count", dest="verbosity", default=1, help="increase verbosity level")
  558. optparser.add_option("-i", "--images", action="store_true", dest="images", default=False, help="save images instead of showing them")
  559. optparser.add_option("-a", "--all", action="store_true", dest="all", default=False, help="show depth, stencil, and transfers")
  560. optparser.add_option("-s", "--step", action="store_true", dest="step", default=False, help="step trhough every draw")
  561. optparser.add_option("-f", "--from", action="store", type="int", dest="start", default=0, help="from call no")
  562. optparser.add_option("-t", "--to", action="store", type="int", dest="stop", default=0, help="until call no")
  563. return optparser
  564. def process_arg(self, stream, options):
  565. parser = Interpreter(stream, options)
  566. parser.parse()
  567. if __name__ == '__main__':
  568. Main().main()