Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/tools/trace/dump_state.py
4561 views
1
#!/usr/bin/env python3
2
##########################################################################
3
#
4
# Copyright 2008-2013, VMware, Inc.
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 VMWARE 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
29
30
import sys
31
import struct
32
import json
33
import binascii
34
import re
35
import copy
36
import argparse
37
38
import model
39
import format
40
import parse as parser
41
42
43
try:
44
from struct import unpack_from
45
except ImportError:
46
def unpack_from(fmt, buf, offset=0):
47
size = struct.calcsize(fmt)
48
return struct.unpack(fmt, buf[offset:offset + size])
49
50
#
51
# Some constants
52
#
53
PIPE_BUFFER = 0
54
PIPE_SHADER_VERTEX = 0
55
PIPE_SHADER_FRAGMENT = 1
56
PIPE_SHADER_GEOMETRY = 2
57
PIPE_SHADER_COMPUTE = 3
58
PIPE_SHADER_TYPES = 4
59
60
61
def serialize(obj):
62
'''JSON serializer function for non-standard Python objects.'''
63
if isinstance(obj, bytearray) or isinstance(obj, bytes):
64
# TODO: Decide on a single way of dumping blobs
65
if False:
66
# Don't dump full blobs, but merely a description of their size and
67
# CRC32 hash.
68
crc32 = binascii.crc32(obj)
69
if crc32 < 0:
70
crc32 += 0x100000000
71
return 'blob(size=%u,crc32=0x%08x)' % (len(obj), crc32)
72
if True:
73
# Dump blobs as an array of 16byte hexadecimals
74
res = []
75
for i in range(0, len(obj), 16):
76
res.append(obj[i : i + 16].hex())
77
return res
78
# Dump blobs as a single hexadecimal string
79
return obj.hex()
80
81
# If the object has a __json__ method, use it.
82
try:
83
method = obj.__json__
84
except AttributeError:
85
raise TypeError(obj)
86
else:
87
return method()
88
89
90
class Struct:
91
"""C-like struct.
92
93
Python doesn't have C structs, but do its dynamic nature, any object is
94
pretty close.
95
"""
96
97
def __json__(self):
98
'''Convert the structure to a standard Python dict, so it can be
99
serialized.'''
100
101
obj = {}
102
for name, value in self.__dict__.items():
103
if not name.startswith('_'):
104
obj[name] = value
105
return obj
106
107
def __repr__(self):
108
return repr(self.__json__())
109
110
111
class Translator(model.Visitor):
112
"""Translate model arguments into regular Python objects"""
113
114
def __init__(self, interpreter):
115
self.interpreter = interpreter
116
self.result = None
117
118
def visit(self, node):
119
self.result = None
120
node.visit(self)
121
return self.result
122
123
def visit_literal(self, node):
124
self.result = node.value
125
126
def visit_blob(self, node):
127
self.result = node
128
129
def visit_named_constant(self, node):
130
self.result = 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 = Struct()
140
for member_name, member_node in node.members:
141
member_name = member_name.replace('.', '_')
142
member_value = self.visit(member_node)
143
setattr(struct, member_name, member_value)
144
self.result = struct
145
146
def visit_pointer(self, node):
147
self.result = self.interpreter.lookup_object(node.address)
148
149
150
class Dispatcher:
151
'''Base class for classes whose methods can dispatch Gallium calls.'''
152
153
def __init__(self, interpreter):
154
self.interpreter = interpreter
155
156
157
class Global(Dispatcher):
158
'''Global name space.
159
160
For calls that are not associated with objects, i.e, functions and not
161
methods.
162
'''
163
164
def pipe_screen_create(self):
165
return Screen(self.interpreter)
166
167
def pipe_context_create(self, screen):
168
return screen.context_create()
169
170
171
class Transfer:
172
'''pipe_transfer'''
173
174
def __init__(self, resource, usage, subresource, box):
175
self.resource = resource
176
self.usage = usage
177
self.subresource = subresource
178
self.box = box
179
180
181
class Screen(Dispatcher):
182
'''pipe_screen'''
183
184
def __init__(self, interpreter):
185
Dispatcher.__init__(self, interpreter)
186
187
def destroy(self):
188
pass
189
190
def context_create(self, priv=None, flags=0):
191
return Context(self.interpreter)
192
193
def is_format_supported(self, format, target, sample_count, bind, geom_flags):
194
pass
195
196
def resource_create(self, templat):
197
resource = templat
198
# Normalize state to avoid spurious differences
199
if resource.nr_samples == 0:
200
resource.nr_samples = 1
201
if resource.target == PIPE_BUFFER:
202
# We will keep track of buffer contents
203
resource.data = bytearray(resource.width)
204
# Ignore format
205
del resource.format
206
return resource
207
208
def resource_destroy(self, resource):
209
self.interpreter.unregister_object(resource)
210
211
def fence_finish(self, fence, timeout=None, ctx=None):
212
pass
213
214
def fence_signalled(self, fence):
215
pass
216
217
def fence_reference(self, dst, src):
218
pass
219
220
def flush_frontbuffer(self, resource):
221
pass
222
223
224
class Context(Dispatcher):
225
'''pipe_context'''
226
227
# Internal methods variable should be prefixed with '_'
228
229
def __init__(self, interpreter):
230
Dispatcher.__init__(self, interpreter)
231
232
# Setup initial state
233
self._state = Struct()
234
self._state.scissors = []
235
self._state.viewports = []
236
self._state.vertex_buffers = []
237
self._state.vertex_elements = []
238
self._state.vs = Struct()
239
self._state.gs = Struct()
240
self._state.fs = Struct()
241
self._state.vs.shader = None
242
self._state.gs.shader = None
243
self._state.fs.shader = None
244
self._state.vs.sampler = []
245
self._state.gs.sampler = []
246
self._state.fs.sampler = []
247
self._state.vs.sampler_views = []
248
self._state.gs.sampler_views = []
249
self._state.fs.sampler_views = []
250
self._state.vs.constant_buffer = []
251
self._state.gs.constant_buffer = []
252
self._state.fs.constant_buffer = []
253
self._state.render_condition_condition = 0
254
self._state.render_condition_mode = 0
255
256
self._draw_no = 0
257
258
def destroy(self):
259
pass
260
261
def create_blend_state(self, state):
262
# Normalize state to avoid spurious differences
263
if not state.logicop_enable:
264
del state.logicop_func
265
if not state.rt[0].blend_enable:
266
del state.rt[0].rgb_src_factor
267
del state.rt[0].rgb_dst_factor
268
del state.rt[0].rgb_func
269
del state.rt[0].alpha_src_factor
270
del state.rt[0].alpha_dst_factor
271
del state.rt[0].alpha_func
272
return state
273
274
def bind_blend_state(self, state):
275
# Normalize state
276
self._state.blend = state
277
278
def delete_blend_state(self, state):
279
pass
280
281
def create_sampler_state(self, state):
282
return state
283
284
def delete_sampler_state(self, state):
285
pass
286
287
def bind_sampler_states(self, shader, start, num_states, states):
288
# FIXME: Handle non-zero start
289
assert start == 0
290
self._get_stage_state(shader).sampler = states
291
292
def bind_vertex_sampler_states(self, num_states, states):
293
# XXX: deprecated method
294
self._state.vs.sampler = states
295
296
def bind_geometry_sampler_states(self, num_states, states):
297
# XXX: deprecated method
298
self._state.gs.sampler = states
299
300
def bind_fragment_sampler_states(self, num_states, states):
301
# XXX: deprecated method
302
self._state.fs.sampler = states
303
304
def create_rasterizer_state(self, state):
305
return state
306
307
def bind_rasterizer_state(self, state):
308
self._state.rasterizer = state
309
310
def delete_rasterizer_state(self, state):
311
pass
312
313
def create_depth_stencil_alpha_state(self, state):
314
# Normalize state to avoid spurious differences
315
if not state.alpha.enabled:
316
del state.alpha.func
317
del state.alpha.ref_value
318
for i in range(2):
319
if not state.stencil[i].enabled:
320
del state.stencil[i].func
321
return state
322
323
def bind_depth_stencil_alpha_state(self, state):
324
self._state.depth_stencil_alpha = state
325
326
def delete_depth_stencil_alpha_state(self, state):
327
pass
328
329
_tokenLabelRE = re.compile('^\s*\d+: ', re.MULTILINE)
330
331
def _create_shader_state(self, state):
332
# Strip the labels from the tokens
333
if state.tokens is not None:
334
state.tokens = self._tokenLabelRE.sub('', state.tokens)
335
return state
336
337
create_vs_state = _create_shader_state
338
create_gs_state = _create_shader_state
339
create_fs_state = _create_shader_state
340
341
def bind_vs_state(self, state):
342
self._state.vs.shader = state
343
344
def bind_gs_state(self, state):
345
self._state.gs.shader = state
346
347
def bind_fs_state(self, state):
348
self._state.fs.shader = state
349
350
def _delete_shader_state(self, state):
351
return state
352
353
delete_vs_state = _delete_shader_state
354
delete_gs_state = _delete_shader_state
355
delete_fs_state = _delete_shader_state
356
357
def set_blend_color(self, state):
358
self._state.blend_color = state
359
360
def set_stencil_ref(self, state):
361
self._state.stencil_ref = state
362
363
def set_clip_state(self, state):
364
self._state.clip = state
365
366
def _dump_constant_buffer(self, buffer):
367
if not self.interpreter.verbosity(2):
368
return
369
370
data = self.real.buffer_read(buffer)
371
format = '4f'
372
index = 0
373
for offset in range(0, len(data), struct.calcsize(format)):
374
x, y, z, w = unpack_from(format, data, offset)
375
sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w))
376
index += 1
377
sys.stdout.flush()
378
379
def _get_stage_state(self, shader):
380
if shader == PIPE_SHADER_VERTEX:
381
return self._state.vs
382
if shader == PIPE_SHADER_GEOMETRY:
383
return self._state.gs
384
if shader == PIPE_SHADER_FRAGMENT:
385
return self._state.fs
386
assert False
387
388
def set_constant_buffer(self, shader, index, constant_buffer):
389
self._update(self._get_stage_state(shader).constant_buffer, index, 1, [constant_buffer])
390
391
def set_framebuffer_state(self, state):
392
self._state.fb = state
393
394
def set_polygon_stipple(self, state):
395
self._state.polygon_stipple = state
396
397
def _update(self, array, start_slot, num_slots, states):
398
if not isinstance(states, list):
399
# XXX: trace is not serializing multiple scissors/viewports properly yet
400
num_slots = 1
401
states = [states]
402
while len(array) < start_slot + num_slots:
403
array.append(None)
404
for i in range(num_slots):
405
array[start_slot + i] = states[i]
406
407
def set_scissor_states(self, start_slot, num_scissors, states):
408
self._update(self._state.scissors, start_slot, num_scissors, states)
409
410
def set_viewport_states(self, start_slot, num_viewports, states):
411
self._update(self._state.viewports, start_slot, num_viewports, states)
412
413
def create_sampler_view(self, resource, templ):
414
templ.resource = resource
415
return templ
416
417
def sampler_view_destroy(self, view):
418
pass
419
420
def set_sampler_views(self, shader, start, num, views):
421
# FIXME: Handle non-zero start
422
assert start == 0
423
self._get_stage_state(shader).sampler_views = views
424
425
def set_fragment_sampler_views(self, num, views):
426
# XXX: deprecated
427
self._state.fs.sampler_views = views
428
429
def set_geometry_sampler_views(self, num, views):
430
# XXX: deprecated
431
self._state.gs.sampler_views = views
432
433
def set_vertex_sampler_views(self, num, views):
434
# XXX: deprecated
435
self._state.vs.sampler_views = views
436
437
def set_vertex_buffers(self, start_slot, num_buffers, buffers):
438
self._update(self._state.vertex_buffers, start_slot, num_buffers, buffers)
439
440
def create_vertex_elements_state(self, num_elements, elements):
441
return elements[0:num_elements]
442
443
def bind_vertex_elements_state(self, state):
444
self._state.vertex_elements = state
445
446
def delete_vertex_elements_state(self, state):
447
pass
448
449
def set_index_buffer(self, ib):
450
self._state.index_buffer = ib
451
452
# Don't dump more than this number of indices/vertices
453
MAX_ELEMENTS = 16
454
455
def _merge_indices(self, info):
456
'''Merge the vertices into our state.'''
457
458
index_size = self._state.index_buffer.index_size
459
460
format = {
461
1: 'B',
462
2: 'H',
463
4: 'I',
464
}[index_size]
465
466
assert struct.calcsize(format) == index_size
467
468
if self._state.index_buffer.buffer is None:
469
# Could happen with index in user memory
470
return 0, 0
471
472
data = self._state.index_buffer.buffer.data
473
max_index, min_index = 0, 0xffffffff
474
475
count = min(info.count, self.MAX_ELEMENTS)
476
indices = []
477
for i in range(info.start, info.start + count):
478
offset = self._state.index_buffer.offset + i*index_size
479
if offset + index_size > len(data):
480
index = 0
481
else:
482
index, = unpack_from(format, data, offset)
483
indices.append(index)
484
min_index = min(min_index, index)
485
max_index = max(max_index, index)
486
487
self._state.indices = indices
488
489
return min_index + info.index_bias, max_index + info.index_bias
490
491
def _merge_vertices(self, start, count):
492
'''Merge the vertices into our state.'''
493
494
count = min(count, self.MAX_ELEMENTS)
495
vertices = []
496
for index in range(start, start + count):
497
if index >= start + 16:
498
sys.stdout.write('\t...\n')
499
break
500
vertex = []
501
for velem in self._state.vertex_elements:
502
vbuf = self._state.vertex_buffers[velem.vertex_buffer_index]
503
resource = vbuf.buffer_resource
504
if resource is None:
505
continue
506
507
data = resource.data
508
509
offset = vbuf.buffer_offset + velem.src_offset + vbuf.stride*index
510
format = {
511
'PIPE_FORMAT_R32_FLOAT': 'f',
512
'PIPE_FORMAT_R32G32_FLOAT': '2f',
513
'PIPE_FORMAT_R32G32B32_FLOAT': '3f',
514
'PIPE_FORMAT_R32G32B32A32_FLOAT': '4f',
515
'PIPE_FORMAT_R32_UINT': 'I',
516
'PIPE_FORMAT_R32G32_UINT': '2I',
517
'PIPE_FORMAT_R32G32B32_UINT': '3I',
518
'PIPE_FORMAT_R32G32B32A32_UINT': '4I',
519
'PIPE_FORMAT_R8_UINT': 'B',
520
'PIPE_FORMAT_R8G8_UINT': '2B',
521
'PIPE_FORMAT_R8G8B8_UINT': '3B',
522
'PIPE_FORMAT_R8G8B8A8_UINT': '4B',
523
'PIPE_FORMAT_A8R8G8B8_UNORM': '4B',
524
'PIPE_FORMAT_R8G8B8A8_UNORM': '4B',
525
'PIPE_FORMAT_B8G8R8A8_UNORM': '4B',
526
'PIPE_FORMAT_R16G16B16_SNORM': '3h',
527
}[velem.src_format]
528
529
data = resource.data
530
attribute = unpack_from(format, data, offset)
531
vertex.append(attribute)
532
533
vertices.append(vertex)
534
535
self._state.vertices = vertices
536
537
def render_condition(self, query, condition = 0, mode = 0):
538
self._state.render_condition_query = query
539
self._state.render_condition_condition = condition
540
self._state.render_condition_mode = mode
541
542
def set_stream_output_targets(self, num_targets, tgs, offsets):
543
self._state.so_targets = tgs
544
self._state.offsets = offsets
545
546
def draw_vbo(self, info):
547
self._draw_no += 1
548
549
if self.interpreter.call_no < self.interpreter.options.call and \
550
self._draw_no < self.interpreter.options.draw:
551
return
552
553
# Merge the all draw state
554
555
self._state.draw = info
556
557
if info.index_size != 0:
558
min_index, max_index = self._merge_indices(info)
559
else:
560
min_index = info.start
561
max_index = info.start + info.count - 1
562
self._merge_vertices(min_index, max_index - min_index + 1)
563
564
self._dump_state()
565
566
_dclRE = re.compile('^DCL\s+(IN|OUT|SAMP|SVIEW)\[([0-9]+)\].*$', re.MULTILINE)
567
568
def _normalize_stage_state(self, stage):
569
570
registers = {}
571
572
if stage.shader is not None and stage.shader.tokens is not None:
573
for mo in self._dclRE.finditer(stage.shader.tokens):
574
file_ = mo.group(1)
575
index = mo.group(2)
576
register = registers.setdefault(file_, set())
577
register.add(int(index))
578
579
if 'SAMP' in registers and 'SVIEW' not in registers:
580
registers['SVIEW'] = registers['SAMP']
581
582
mapping = [
583
#("CONST", "constant_buffer"),
584
("SAMP", "sampler"),
585
("SVIEW", "sampler_views"),
586
]
587
588
for fileName, attrName in mapping:
589
register = registers.setdefault(fileName, set())
590
attr = getattr(stage, attrName)
591
for index in range(len(attr)):
592
if index not in register:
593
attr[index] = None
594
while attr and attr[-1] is None:
595
attr.pop()
596
597
def _dump_state(self):
598
'''Dump our state to JSON and terminate.'''
599
600
state = copy.deepcopy(self._state)
601
602
self._normalize_stage_state(state.vs)
603
self._normalize_stage_state(state.gs)
604
self._normalize_stage_state(state.fs)
605
606
json.dump(
607
obj = state,
608
fp = sys.stdout,
609
default = serialize,
610
sort_keys = True,
611
indent = 4,
612
separators = (',', ': ')
613
)
614
615
sys.exit(0)
616
617
def resource_copy_region(self, dst, dst_level, dstx, dsty, dstz, src, src_level, src_box):
618
if dst.target == PIPE_BUFFER or src.target == PIPE_BUFFER:
619
assert dst.target == PIPE_BUFFER and src.target == PIPE_BUFFER
620
assert dst_level == 0
621
assert dsty == 0
622
assert dstz == 0
623
assert src_level == 0
624
assert src_box.y == 0
625
assert src_box.z == 0
626
assert src_box.height == 1
627
assert src_box.depth == 1
628
dst.data[dstx : dstx + src_box.width] = src.data[src_box.x : src_box.x + src_box.width]
629
pass
630
631
def is_resource_referenced(self, texture, face, level):
632
pass
633
634
def get_transfer(self, texture, sr, usage, box):
635
if texture is None:
636
return None
637
transfer = Transfer(texture, sr, usage, box)
638
return transfer
639
640
def tex_transfer_destroy(self, transfer):
641
self.interpreter.unregister_object(transfer)
642
643
def buffer_subdata(self, resource, usage, data, box=None, offset=None, size=None, level=None, stride=None, layer_stride=None):
644
if box is not None:
645
# XXX trace_context_transfer_unmap generates brokens buffer_subdata
646
assert offset is None
647
assert size is None
648
assert level == 0
649
offset = box.x
650
size = box.width
651
box = None
652
653
if resource is not None and resource.target == PIPE_BUFFER:
654
data = data.getValue()
655
assert len(data) >= size
656
assert offset + size <= len(resource.data)
657
resource.data[offset : offset + size] = data[:size]
658
659
def texture_subdata(self, resource, level, usage, box, data, stride, layer_stride):
660
pass
661
662
def transfer_inline_write(self, resource, level, usage, box, stride, layer_stride, data):
663
if resource is not None and resource.target == PIPE_BUFFER:
664
data = data.getValue()
665
assert len(data) >= box.width
666
assert box.x + box.width <= len(resource.data)
667
resource.data[box.x : box.x + box.width] = data[:box.width]
668
669
def flush(self, flags):
670
# Return a fake fence
671
return self.interpreter.call_no
672
673
def clear(self, buffers, color, depth, stencil, scissor_state=None):
674
pass
675
676
def clear_render_target(self, dst, rgba, dstx, dsty, width, height):
677
pass
678
679
def clear_depth_stencil(self, dst, clear_flags, depth, stencil, dstx, dsty, width, height):
680
pass
681
682
def create_surface(self, resource, surf_tmpl):
683
assert resource is not None
684
surf_tmpl.resource = resource
685
return surf_tmpl
686
687
def surface_destroy(self, surface):
688
self.interpreter.unregister_object(surface)
689
690
def create_query(self, query_type, index):
691
return query_type
692
693
def destroy_query(self, query):
694
pass
695
696
def begin_query(self, query):
697
pass
698
699
def end_query(self, query):
700
pass
701
702
def create_stream_output_target(self, res, buffer_offset, buffer_size):
703
so_target = Struct()
704
so_target.resource = res
705
so_target.offset = buffer_offset
706
so_target.size = buffer_size
707
return so_target
708
709
710
class Interpreter(parser.SimpleTraceDumper):
711
'''Specialization of a trace parser that interprets the calls as it goes
712
along.'''
713
714
ignoredCalls = set((
715
('pipe_screen', 'is_format_supported'),
716
('pipe_screen', 'get_name'),
717
('pipe_screen', 'get_vendor'),
718
('pipe_screen', 'get_param'),
719
('pipe_screen', 'get_paramf'),
720
('pipe_screen', 'get_shader_param'),
721
('pipe_screen', 'get_disk_shader_cache'),
722
('pipe_context', 'clear_render_target'), # XXX workaround trace bugs
723
('pipe_context', 'flush_resource'),
724
))
725
726
def __init__(self, stream, options, formatter):
727
parser.SimpleTraceDumper.__init__(self, stream, options, formatter)
728
self.objects = {}
729
self.result = None
730
self.globl = Global(self)
731
self.call_no = None
732
733
def register_object(self, address, object):
734
self.objects[address] = object
735
736
def unregister_object(self, object):
737
# TODO
738
pass
739
740
def lookup_object(self, address):
741
try:
742
return self.objects[address]
743
except KeyError:
744
# Could happen, e.g., with user memory pointers
745
return address
746
747
def interpret(self, trace):
748
for call in trace.calls:
749
self.interpret_call(call)
750
751
def handle_call(self, call):
752
if (call.klass, call.method) in self.ignoredCalls:
753
return
754
755
self.call_no = call.no
756
757
if self.verbosity(1):
758
# Write the call to stderr (as stdout would corrupt the JSON output)
759
sys.stderr.flush()
760
sys.stdout.flush()
761
parser.TraceDumper.handle_call(self, call)
762
sys.stderr.flush()
763
sys.stdout.flush()
764
765
args = [(str(name), self.interpret_arg(arg)) for name, arg in call.args]
766
767
if call.klass:
768
name, obj = args[0]
769
args = args[1:]
770
else:
771
obj = self.globl
772
773
method = getattr(obj, call.method)
774
ret = method(**dict(args))
775
776
# Keep track of created pointer objects.
777
if call.ret and isinstance(call.ret, model.Pointer):
778
if ret is None:
779
sys.stderr.write('warning: NULL returned\n')
780
self.register_object(call.ret.address, ret)
781
782
self.call_no = None
783
784
def interpret_arg(self, node):
785
translator = Translator(self)
786
return translator.visit(node)
787
788
def verbosity(self, level):
789
return self.options.verbosity >= level
790
791
792
class Main(parser.Main):
793
794
def get_optparser(self):
795
optparser = argparse.ArgumentParser(
796
description="Parse and dump Gallium trace(s) as JSON")
797
798
optparser.add_argument("filename", action="extend", nargs="+",
799
type=str, metavar="filename", help="Gallium trace filename (plain or .gz, .bz2)")
800
801
optparser.add_argument("-v", "--verbose", action="count", default=0, dest="verbosity", help="increase verbosity level")
802
optparser.add_argument("-q", "--quiet", action="store_const", const=0, dest="verbosity", help="no messages")
803
optparser.add_argument("-c", "--call", action="store", type=int, dest="call", default=0xffffffff, help="dump on this call")
804
optparser.add_argument("-d", "--draw", action="store", type=int, dest="draw", default=0xffffffff, help="dump on this draw")
805
return optparser
806
807
def process_arg(self, stream, options):
808
formatter = format.Formatter(sys.stderr)
809
parser = Interpreter(stream, options, formatter)
810
parser.parse()
811
812
813
if __name__ == '__main__':
814
Main().main()
815
816