3 # Copyright (c) 2014, 2016-2017, 2019-2020 Intel Corporation
4 # Copyright (c) 2019 Collabora Ltd
5 # Copyright © 2019-2020 Valve Corporation.
7 # Permission is hereby granted, free of charge, to any person obtaining a
8 # copy of this software and associated documentation files (the "Software"),
9 # to deal in the Software without restriction, including without limitation
10 # the rights to use, copy, modify, merge, publish, distribute, sublicense,
11 # and/or sell copies of the Software, and to permit persons to whom the
12 # Software is furnished to do so, subject to the following conditions:
14 # The above copyright notice and this permission notice shall be included
15 # in all copies or substantial portions of the Software.
17 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 # THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
21 # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
22 # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
23 # OTHER DEALINGS IN THE SOFTWARE.
25 # SPDX-License-Identifier: MIT
28 """ Module providing a GFXReconstruct dump backend for replayer """
36 from packaging
import version
38 from framework
import core
, exceptions
40 from . import DumpBackendError
41 from .abstract
import DumpBackend
, dump_handler
42 from .register
import Registry
46 'GFXReconstructBackend',
50 _MIN_VERSION
= version
.Version('0.9.4')
51 _VERSION_RE
= re
.compile(r
'\s*GFXReconstruct Version\s*([0-9]\.[0-9]\.[0-9])')
53 _TOTAL_FRAMES_RE
= re
.compile(r
'\s*Total frames:\s*([0-9]*)')
56 class GFXReconstructBackend(DumpBackend
):
57 """ replayer's GFXReconstruct dump backend
59 This backend uses GFXReconstruct for replaying its traces.
61 The path to the GFXReconstruct binary is configurable.
63 It also admits configuration for passing extra parameters to
68 def __init__(self
, trace_path
, output_dir
=None, calls
=None, **kwargs
):
69 super(GFXReconstructBackend
, self
).__init
__(trace_path
, output_dir
,
71 extension
= path
.splitext(self
._trace
_path
)[1]
73 if extension
!= '.gfxr':
74 raise exceptions
.PiglitFatalError(
75 'Invalid trace_path: "{}" tried to be dumped '
76 'by the GFXReconstructBackend.\n'.format(self
._trace
_path
))
78 def _get_last_frame_call(self
):
79 gfxrecon_info_bin
= core
.get_option(
80 'PIGLIT_REPLAY_GFXRECON_INFO_BINARY',
81 ('replay', 'gfxrecon-info_bin'),
82 default
='gfxrecon-info')
83 cmd
= [gfxrecon_info_bin
, self
._trace
_path
]
84 ret
= subprocess
.run(cmd
, stdout
=subprocess
.PIPE
, stderr
=sys
.stderr
)
85 lines
= ret
.stdout
.decode(errors
='replace').splitlines()
86 print(ret
.stdout
.decode(errors
='replace'))
88 frames
= re
.search(_TOTAL_FRAMES_RE
, lines
[2])
89 return int(frames
.group(1))
93 def _check_version(self
, gfxrecon_replay_bin
):
94 cmd
= [gfxrecon_replay_bin
, '--version']
95 ret
= subprocess
.run(cmd
, stdout
=subprocess
.PIPE
, stderr
=sys
.stderr
)
96 lines
= ret
.stdout
.decode(errors
='replace').splitlines()
97 print(ret
.stdout
.decode(errors
='replace'))
99 v
= re
.search(_VERSION_RE
, lines
[1])
100 current
= version
.Version(v
.group(1))
102 raise DumpBackendError(
103 '[dump_trace_images] Unable to check the current '
104 'gfxrecon-replay version.')
105 if _MIN_VERSION
> current
:
106 raise DumpBackendError(
107 '[dump_trace_images] The current gfxrecon-replay version '
108 'is {}. Try to update, at least to the {} version.'.format(
109 current
, _MIN_VERSION
))
113 from PIL
import Image
114 outputprefix
= path
.join(self
._output
_dir
,
115 path
.basename(self
._trace
_path
))
116 gfxrecon_replay_bin
= core
.get_option(
117 'PIGLIT_REPLAY_GFXRECON_REPLAY_BINARY',
118 ('replay', 'gfxrecon-replay_bin'),
119 default
='gfxrecon-replay')
120 self
._check
_version
(gfxrecon_replay_bin
)
122 self
._calls
= [str(self
._get
_last
_frame
_call
())]
123 gfxrecon_replay_extra_args
= core
.get_option(
124 'PIGLIT_REPLAY_GFXRECON_REPLAY_EXTRA_ARGS',
125 ('replay', 'gfxrecon-replay_extra_args'),
127 cmd
= ([gfxrecon_replay_bin
] + gfxrecon_replay_extra_args
+
128 ['--screenshots', ','.join(self
._calls
),
129 '--screenshot-dir', self
._output
_dir
,
131 self
._run
_logged
_command
(cmd
, None)
132 for c
in self
._calls
:
133 bmp
= '{}_frame_{}.bmp'.format(path
.join(self
._output
_dir
,
136 outputfile
= '{}-{}.png'.format(outputprefix
, c
)
137 print('Writing: {} to {}'.format(bmp
, outputfile
))
138 Image
.open(bmp
).save(outputfile
)
143 extensions
=['.gfxr'],
144 backend
=GFXReconstructBackend
,