Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/angle
Path: blob/main_old/src/tests/restricted_traces/gen_restricted_traces.py
1693 views
1
#!/usr/bin/python3
2
#
3
# Copyright 2020 The ANGLE Project Authors. All rights reserved.
4
# Use of this source code is governed by a BSD-style license that can be
5
# found in the LICENSE file.
6
#
7
# gen_restricted_traces.py:
8
# Generates integration code for the restricted trace tests.
9
10
import getpass
11
import glob
12
import fnmatch
13
import json
14
import os
15
import sys
16
17
GNI_TEMPLATE = """\
18
# GENERATED FILE - DO NOT EDIT.
19
# Generated by {script_name} using data from {data_source_name}
20
#
21
# Copyright 2020 The ANGLE Project Authors. All rights reserved.
22
# Use of this source code is governed by a BSD-style license that can be
23
# found in the LICENSE file.
24
#
25
# A list of all restricted trace tests, paired with their context.
26
# Can be consumed by tests/BUILD.gn.
27
28
angle_restricted_traces = [
29
{test_list}
30
]
31
"""
32
33
HEADER_TEMPLATE = """\
34
// GENERATED FILE - DO NOT EDIT.
35
// Generated by {script_name} using data from {data_source_name}
36
//
37
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
38
// Use of this source code is governed by a BSD-style license that can be
39
// found in the LICENSE file.
40
//
41
// {filename}: Types and enumerations for trace tests.
42
43
#ifndef ANGLE_RESTRICTED_TRACES_AUTOGEN_H_
44
#define ANGLE_RESTRICTED_TRACES_AUTOGEN_H_
45
46
#include <cstdint>
47
#include <vector>
48
#include <KHR/khrplatform.h>
49
#include <EGL/egl.h>
50
51
#include "restricted_traces_export.h"
52
53
namespace trace_angle
54
{{
55
using GenericProc = void (*)();
56
using LoadProc = GenericProc(KHRONOS_APIENTRY *)(const char *);
57
ANGLE_TRACE_LOADER_EXPORT void LoadEGL(LoadProc loadProc);
58
ANGLE_TRACE_LOADER_EXPORT void LoadGLES(LoadProc loadProc);
59
}} // namespace trace_angle
60
61
namespace angle
62
{{
63
enum class RestrictedTraceID
64
{{
65
{trace_ids}, InvalidEnum, EnumCount = InvalidEnum
66
}};
67
68
static constexpr size_t kTraceInfoMaxNameLen = 32;
69
70
static constexpr uint32_t kDefaultReplayContextClientMajorVersion = 3;
71
static constexpr uint32_t kDefaultReplayContextClientMinorVersion = 1;
72
static constexpr uint32_t kDefaultReplayDrawSurfaceColorSpace = EGL_COLORSPACE_LINEAR;
73
74
struct TraceInfo
75
{{
76
uint32_t contextClientMajorVersion;
77
uint32_t contextClientMinorVersion;
78
uint32_t startFrame;
79
uint32_t endFrame;
80
uint32_t drawSurfaceWidth;
81
uint32_t drawSurfaceHeight;
82
uint32_t drawSurfaceColorSpace;
83
char name[kTraceInfoMaxNameLen];
84
}};
85
86
ANGLE_TRACE_EXPORT const TraceInfo &GetTraceInfo(RestrictedTraceID traceID);
87
}} // namespace angle
88
89
#endif // ANGLE_RESTRICTED_TRACES_AUTOGEN_H_
90
"""
91
92
SOURCE_TEMPLATE = """\
93
// GENERATED FILE - DO NOT EDIT.
94
// Generated by {script_name} using data from {data_source_name}
95
//
96
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
97
// Use of this source code is governed by a BSD-style license that can be
98
// found in the LICENSE file.
99
//
100
// {filename}: Types and enumerations for trace tests.
101
102
#include "{filename}.h"
103
104
#include "common/PackedEnums.h"
105
#include "common/system_utils.h"
106
107
{trace_includes}
108
109
namespace angle
110
{{
111
namespace
112
{{
113
constexpr angle::PackedEnumMap<RestrictedTraceID, TraceInfo> kTraceInfos = {{
114
{trace_infos}
115
}};
116
}}
117
118
const TraceInfo &GetTraceInfo(RestrictedTraceID traceID)
119
{{
120
return kTraceInfos[traceID];
121
}}
122
}} // namespace angle
123
"""
124
125
CIPD_TRACE_PREFIX = 'angle/traces'
126
EXPERIMENTAL_CIPD_PREFIX = 'experimental/google.com/%s/angle/traces'
127
DEPS_PATH = '../../../DEPS'
128
DEPS_START = '# === ANGLE Restricted Trace Generated Code Start ==='
129
DEPS_END = '# === ANGLE Restricted Trace Generated Code End ==='
130
DEPS_TEMPLATE = """\
131
'src/tests/restricted_traces/{trace}': {{
132
'packages': [
133
{{
134
'package': '{trace_prefix}/{trace}',
135
'version': 'version:{version}',
136
}},
137
],
138
'dep_type': 'cipd',
139
'condition': 'checkout_angle_restricted_traces',
140
}},
141
"""
142
143
144
def reject_duplicate_keys(pairs):
145
found_keys = {}
146
for key, value in pairs:
147
if key in found_keys:
148
raise ValueError("duplicate key: %r" % (key,))
149
else:
150
found_keys[key] = value
151
return found_keys
152
153
154
# TODO(http://anglebug.com/5878): Revert back to non-autogen'ed file names for the angledata.gz.
155
def get_angledata_filename(trace):
156
angledata_files = glob.glob('%s/%s*angledata.gz' % (trace, trace))
157
assert len(angledata_files) == 1, "Trace '%s' has %d angledata.gz files" % (
158
trace, len(angledata_files))
159
return angledata_files[0].replace('\\', '/')
160
161
162
def gen_gni(traces, gni_file, format_args):
163
test_list = []
164
for trace in traces:
165
context = get_context(trace)
166
angledata_file = get_angledata_filename(trace)
167
with open('%s/%s_capture_context%s_files.txt' % (trace, trace, context)) as f:
168
files = f.readlines()
169
f.close()
170
files = ['"%s/%s"' % (trace, file.strip()) for file in files]
171
test_list += ['["%s", %s, [%s], "%s"]' % (trace, context, ','.join(files), angledata_file)]
172
173
format_args['test_list'] = ',\n'.join(test_list)
174
gni_data = GNI_TEMPLATE.format(**format_args)
175
with open(gni_file, "w") as out_file:
176
out_file.write(gni_data)
177
return True
178
179
180
def contains_string(trace, string):
181
"""Determines if the trace contains a string"""
182
for file in os.listdir(trace):
183
if fnmatch.fnmatch(file, '*.h'):
184
with open(os.path.join(trace, file)) as f:
185
if string in f.read():
186
return True
187
return False
188
189
190
def contains_context_version(trace):
191
"""Determines if the trace contains the major/minor context version"""
192
return contains_string(trace, 'kReplayContextClientMajorVersion')
193
194
195
def contains_colorspace(trace):
196
"""Determines if the trace contains an EGL surface color space"""
197
return contains_string(trace, 'kReplayDrawSurfaceColorSpace')
198
199
200
def get_trace_info(trace):
201
# Some traces don't contain major/minor version, so use defaults
202
info = []
203
if contains_context_version(trace):
204
info += [
205
f"{trace}::kReplayContextClientMajorVersion",
206
f"{trace}::kReplayContextClientMinorVersion"
207
]
208
else:
209
info += [
210
"kDefaultReplayContextClientMajorVersion", "kDefaultReplayContextClientMinorVersion"
211
]
212
213
info += [
214
f"{trace}::kReplayFrameStart", f"{trace}::kReplayFrameEnd",
215
f"{trace}::kReplayDrawSurfaceWidth", f"{trace}::kReplayDrawSurfaceHeight"
216
]
217
218
if contains_colorspace(trace):
219
info += [f"{trace}::kReplayDrawSurfaceColorSpace"]
220
else:
221
info += ["kDefaultReplayDrawSurfaceColorSpace"]
222
223
info += [f"\"{trace}\""]
224
225
return ", ".join(info)
226
227
228
def get_context(trace):
229
"""Returns the context number used by trace txt file"""
230
for file in os.listdir(trace):
231
# Load up the only header present for each trace
232
if fnmatch.fnmatch(file, '*.txt'):
233
# Strip the extension to isolate the context by scanning
234
# for numbers leading up to the last one, i.e.:
235
# app_capture_context123_files.txt
236
# ^^
237
# start---||---end
238
start = len(file) - 11
239
end = start + 1
240
while file[start - 1].isdigit():
241
start -= 1
242
context = file[start:end]
243
assert context.isnumeric(), "Failed to find trace context number"
244
return context
245
246
247
def get_header_name(trace):
248
return "%s/%s_capture_context%s.h" % (trace, trace, get_context(trace))
249
250
251
def get_source_name(trace):
252
return "%s/%s_capture_context%s.cpp" % (trace, trace, get_context(trace))
253
254
255
def gen_header(header_file, format_args):
256
header_data = HEADER_TEMPLATE.format(**format_args)
257
with open(header_file, "w") as out_file:
258
out_file.write(header_data)
259
return True
260
261
262
def gen_source(source_file, format_args):
263
source_data = SOURCE_TEMPLATE.format(**format_args)
264
with open(source_file, "w") as out_file:
265
out_file.write(source_data)
266
return True
267
268
269
def gen_git_ignore(traces):
270
ignores = ['%s/' % trace for trace in traces]
271
with open('.gitignore', 'w') as out_file:
272
out_file.write('\n'.join(sorted(ignores)))
273
return True
274
275
276
def read_json(json_file):
277
with open(json_file) as map_file:
278
return json.loads(map_file.read(), object_pairs_hook=reject_duplicate_keys)
279
280
281
def update_deps(trace_pairs):
282
# Generate substitution string
283
replacement = ""
284
for (trace, version) in trace_pairs:
285
if 'x' in version:
286
version = version.strip('x')
287
trace_prefix = EXPERIMENTAL_CIPD_PREFIX % getpass.getuser()
288
else:
289
trace_prefix = CIPD_TRACE_PREFIX
290
sub = {'trace': trace, 'version': version, 'trace_prefix': trace_prefix}
291
replacement += DEPS_TEMPLATE.format(**sub)
292
293
# Update DEPS to download CIPD dependencies
294
new_deps = ""
295
with open(DEPS_PATH) as f:
296
in_deps = False
297
for line in f:
298
if in_deps:
299
if DEPS_END in line:
300
new_deps += replacement
301
new_deps += line
302
in_deps = False
303
else:
304
if DEPS_START in line:
305
new_deps += line
306
in_deps = True
307
else:
308
new_deps += line
309
f.close()
310
311
with open(DEPS_PATH, 'w') as f:
312
f.write(new_deps)
313
f.close()
314
315
return True
316
317
318
def main():
319
json_file = 'restricted_traces.json'
320
gni_file = 'restricted_traces_autogen.gni'
321
header_file = 'restricted_traces_autogen.h'
322
source_file = 'restricted_traces_autogen.cpp'
323
324
json_data = read_json(json_file)
325
if 'traces' not in json_data:
326
print('Trace data missing traces key.')
327
return 1
328
trace_pairs = [trace.split(' ') for trace in json_data['traces']]
329
traces = [trace_pair[0] for trace_pair in trace_pairs]
330
331
# auto_script parameters.
332
if len(sys.argv) > 1:
333
inputs = [json_file]
334
335
# Note: we do not include DEPS in the list of outputs to simplify the integration.
336
# Otherwise we'd continually need to regenerate on any roll.
337
outputs = [gni_file, header_file, source_file, '.gitignore']
338
339
if sys.argv[1] == 'inputs':
340
print(','.join(inputs))
341
elif sys.argv[1] == 'outputs':
342
print(','.join(outputs))
343
else:
344
print('Invalid script parameters.')
345
return 1
346
return 0
347
348
format_args = {
349
"script_name": os.path.basename(__file__),
350
"data_source_name": json_file,
351
}
352
353
if not gen_gni(traces, gni_file, format_args):
354
print('.gni file generation failed.')
355
return 1
356
357
includes = ["#include \"%s\"" % get_header_name(trace) for trace in traces]
358
trace_infos = [
359
"{RestrictedTraceID::%s, {%s}}" % (trace, get_trace_info(trace)) for trace in traces
360
]
361
362
format_args["filename"] = "restricted_traces_autogen"
363
format_args["trace_ids"] = ",\n".join(traces)
364
format_args["trace_includes"] = "\n".join(includes)
365
format_args["trace_infos"] = ",\n".join(trace_infos)
366
if not gen_header(header_file, format_args):
367
print('.h file generation failed.')
368
return 1
369
370
if not gen_source(source_file, format_args):
371
print('.cpp file generation failed.')
372
return 1
373
374
if not gen_git_ignore(traces):
375
print('.gitignore file generation failed')
376
return 1
377
378
if not update_deps(trace_pairs):
379
print('DEPS file update failed')
380
return 1
381
382
return 0
383
384
385
if __name__ == '__main__':
386
sys.exit(main())
387
388