• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/python2
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
10import fnmatch
11import json
12import os
13import sys
14
15gni_template = """# GENERATED FILE - DO NOT EDIT.
16# Generated by {script_name} using data from {data_source_name}
17#
18# Copyright 2020 The ANGLE Project Authors. All rights reserved.
19# Use of this source code is governed by a BSD-style license that can be
20# found in the LICENSE file.
21#
22# A list of all restricted trace tests, paired with their context.
23# Can be consumed by tests/BUILD.gn.
24
25angle_restricted_traces = [
26{test_list}
27]
28"""
29
30header_template = """// GENERATED FILE - DO NOT EDIT.
31// Generated by {script_name} using data from {data_source_name}
32//
33// Copyright 2020 The ANGLE Project Authors. All rights reserved.
34// Use of this source code is governed by a BSD-style license that can be
35// found in the LICENSE file.
36//
37// Types and enumerations for trace tests.
38
39#ifndef ANGLE_RESTRICTED_TRACES_H_
40#define ANGLE_RESTRICTED_TRACES_H_
41
42{includes}
43
44namespace angle
45{{
46enum class RestrictedTraceID
47{{
48{trace_ids}, InvalidEnum, EnumCount = InvalidEnum
49}};
50
51using ReplayFunc = void (*)(uint32_t);
52using ResetFunc = void (*)();
53using SetupFunc = void (*)();
54using DecompressFunc = uint8_t *(*)(const std::vector<uint8_t> &);
55using SetBinaryDataDirFunc = void (*)(const char *);
56
57static constexpr size_t kTraceInfoMaxNameLen = 32;
58
59struct TraceInfo
60{{
61    uint32_t startFrame;
62    uint32_t endFrame;
63    char name[kTraceInfoMaxNameLen];
64}};
65
66constexpr angle::PackedEnumMap<RestrictedTraceID, TraceInfo> kTraceInfos = {{
67{trace_infos}
68}};
69
70using DecompressCallback = uint8_t *(*)(const std::vector<uint8_t> &);
71using FramebufferChangeCallback = void(*)(void *userData, GLenum target, GLuint framebuffer);
72
73inline void ReplayFrame(RestrictedTraceID traceID, uint32_t frameIndex)
74{{
75    switch (traceID)
76    {{
77{replay_func_cases}
78        default:
79            fprintf(stderr, "Error in switch.\\n");
80            assert(0);
81            break;
82    }}
83}}
84
85inline void ResetReplay(RestrictedTraceID traceID)
86{{
87    switch (traceID)
88    {{
89{reset_func_cases}
90        default:
91            fprintf(stderr, "Error in switch.\\n");
92            assert(0);
93            break;
94    }}
95}}
96
97inline void SetupReplay(RestrictedTraceID traceID)
98{{
99    switch (traceID)
100    {{
101{setup_func_cases}
102        default:
103            fprintf(stderr, "Error in switch.\\n");
104            assert(0);
105            break;
106    }}
107}}
108
109inline void SetBinaryDataDir(RestrictedTraceID traceID, const char *dataDir)
110{{
111    switch (traceID)
112    {{
113{set_binary_data_dir_cases}
114        default:
115            fprintf(stderr, "Error in switch.\\n");
116            assert(0);
117            break;
118    }}
119}}
120
121inline void SetBinaryDataDecompressCallback(RestrictedTraceID traceID, DecompressCallback callback)
122{{
123    switch (traceID)
124    {{
125{decompress_callback_cases}
126        default:
127            fprintf(stderr, "Error in switch.\\n");
128            assert(0);
129            break;
130    }}
131}}
132
133inline void SetFramebufferChangeCallback(RestrictedTraceID traceID, void *userData, FramebufferChangeCallback callback)
134{{
135    switch (traceID)
136    {{
137{on_fb_change_callback_cases}
138        default:
139            fprintf(stderr, "Error in switch.\\n");
140            assert(0);
141            break;
142    }}
143}}
144}}  // namespace angle
145
146#endif  // ANGLE_RESTRICTED_TRACES_H_
147"""
148
149
150def reject_duplicate_keys(pairs):
151    found_keys = {}
152    for key, value in pairs:
153        if key in found_keys:
154            raise ValueError("duplicate key: %r" % (key,))
155        else:
156            found_keys[key] = value
157    return found_keys
158
159
160def gen_gni(traces, gni_file, format_args):
161    format_args["test_list"] = ",\n".join(
162        ['"%s %s"' % (trace, get_context(trace)) for trace in traces])
163    gni_data = gni_template.format(**format_args)
164    with open(gni_file, "w") as out_file:
165        out_file.write(gni_data)
166    return True
167
168
169def get_trace_info(trace):
170    info = ["%s::kReplayFrameStart", "%s::kReplayFrameEnd", "\"%s\""]
171    return ", ".join([element % trace for element in info])
172
173
174def get_context(trace):
175    "Returns the context number used by trace header file"
176    for file in os.listdir(trace):
177        # Load up the only header present for each trace
178        if fnmatch.fnmatch(file, '*.h'):
179            # Strip the extension to isolate the context
180            context = file[len(file) - 3]
181            assert context.isdigit() == True, "Failed to find trace context number"
182            assert file[len(file) - 4].isdigit() == False, "Context number is higher than 9"
183            return context
184
185
186def get_cases(traces, function, args):
187    funcs = [
188        "case RestrictedTraceID::%s: %s::%s(%s); break;" % (trace, trace, function, args)
189        for trace in traces
190    ]
191    return "\n".join(funcs)
192
193
194def get_header_name(trace):
195    return "%s/%s_capture_context%s.h" % (trace, trace, get_context(trace))
196
197
198def get_sha1_name(trace):
199    return "%s.tar.gz.sha1" % trace
200
201
202def get_cases_with_context(traces, function_start, function_end, args):
203    funcs = [
204        "case RestrictedTraceID::%s: %s::%s%s%s(%s); break;" %
205        (trace, trace, function_start, get_context(trace), function_end, args) for trace in traces
206    ]
207    return "\n".join(funcs)
208
209
210def gen_header(traces, header_file, format_args):
211
212    includes = ["#include \"%s\"" % get_header_name(trace) for trace in traces]
213    trace_infos = [
214        "{RestrictedTraceID::%s, {%s}}" % (trace, get_trace_info(trace)) for trace in traces
215    ]
216
217    format_args["includes"] = "\n".join(includes)
218    format_args["trace_ids"] = ",\n".join(traces)
219    format_args["trace_infos"] = ",\n".join(trace_infos)
220    format_args["replay_func_cases"] = get_cases_with_context(traces, "ReplayContext", "Frame",
221                                                              "frameIndex")
222    format_args["reset_func_cases"] = get_cases_with_context(traces, "ResetContext", "Replay", "")
223    format_args["setup_func_cases"] = get_cases_with_context(traces, "SetupContext", "Replay", "")
224    format_args["set_binary_data_dir_cases"] = get_cases(traces, "SetBinaryDataDir", "dataDir")
225    format_args["decompress_callback_cases"] = get_cases(traces, "SetBinaryDataDecompressCallback",
226                                                         "callback")
227    format_args["on_fb_change_callback_cases"] = get_cases(traces, "SetFramebufferChangeCallback",
228                                                           "userData, callback")
229    header_data = header_template.format(**format_args)
230    with open(header_file, "w") as out_file:
231        out_file.write(header_data)
232    return True
233
234
235def read_json(json_file):
236    with open(json_file) as map_file:
237        return json.loads(map_file.read(), object_pairs_hook=reject_duplicate_keys)
238
239
240def main():
241    json_file = 'restricted_traces.json'
242    gni_file = 'restricted_traces_autogen.gni'
243    header_file = 'restricted_traces_autogen.h'
244
245    json_data = read_json(json_file)
246    if 'traces' not in json_data:
247        print('Trace data missing traces key.')
248        return 1
249    traces = json_data['traces']
250
251    # auto_script parameters.
252    if len(sys.argv) > 1:
253        inputs = [json_file] + [get_sha1_name(trace) for trace in traces]
254        outputs = [gni_file, header_file]
255
256        if sys.argv[1] == 'inputs':
257            print ','.join(inputs)
258        elif sys.argv[1] == 'outputs':
259            print ','.join(outputs)
260        else:
261            print('Invalid script parameters.')
262            return 1
263        return 0
264
265    format_args = {
266        "script_name": __file__,
267        "data_source_name": json_file,
268    }
269
270    if not gen_gni(traces, gni_file, format_args):
271        print('.gni file generation failed.')
272        return 1
273
274    if not gen_header(traces, header_file, format_args):
275        print('.h file generation failed.')
276        return 1
277
278    return 0
279
280
281if __name__ == '__main__':
282    sys.exit(main())
283