blob: 0fcc506e5fce1fa0d8010a3103076aa5c231ed8f [file] [log] [blame]
Robert Tarasovdf3962b2019-07-28 00:56:25 -07001
2/**************************************************************************
3 *
4 * Copyright 2011 Jose Fonseca
5 * Copyright 2010 VMware, Inc.
6 * All Rights Reserved.
7 *
8 * Permission is hereby granted, free of charge, to any person obtaining a copy
9 * of this software and associated documentation files (the "Software"), to deal
10 * in the Software without restriction, including without limitation the rights
11 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 * copies of the Software, and to permit persons to whom the Software is
13 * furnished to do so, subject to the following conditions:
14 *
15 * The above copyright notice and this permission notice shall be included in
16 * all copies or substantial portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 * THE SOFTWARE.
25 *
26 **************************************************************************/
27
28
29#include <string.h>
30#include <limits.h> // for CHAR_MAX
31#include <getopt.h>
32#ifndef _WIN32
33#include <unistd.h> // for isatty()
34#endif
35
36#include <memory>
37#include <fstream>
38#include <string>
39#include <regex>
40
41#include "cxx_compat.hpp" // for std::to_string, std::make_unique
42
43#include "cli.hpp"
44#include "cli_pager.hpp"
45
46#include "trace_parser.hpp"
47#include "trace_dump_internal.hpp"
48#include "trace_callset.hpp"
49#include "trace_option.hpp"
50
51static trace::CallSet calls(trace::FREQUENCY_ALL);
52
53static const char *synopsis = "Print a trace file information.";
54
55static void
56usage(void)
57{
58 std::cout
59 << "usage: apitrace info [OPTIONS] TRACE_FILE...\n"
60 << synopsis << "\n"
61 "\n"
62 " -h, --help show this help message and exit\n"
63 " --json output in json format\n"
64 "\n"
65 ;
66}
67
68enum {
69 CALLS_OPT = CHAR_MAX + 1,
70 JSON_OPT,
71};
72
73const static char *
74shortOptions = "hv";
75
76const static struct option
77longOptions[] = {
78 {"help", no_argument, 0, 'h'},
79 {"json", no_argument, 0, JSON_OPT},
80 {0, 0, 0, 0}
81};
82
83static int
84parseArrayAttrib(const trace::Array *array_attrib, int attrib, int def_val, int terminator) {
85 for (size_t idx = 0; idx < array_attrib->values.size()/2; ++idx) {
86 int key = array_attrib->values[idx*2]->toSInt();
87 if (terminator == key) break;
88 if (key == attrib) return array_attrib->values[idx*2+1]->toSInt();
89 }
90
91 return def_val;
92}
93
94static int
95command(int argc, char *argv[])
96{
97 std::regex grepRegex;
98 bool json = false;
99
100 int opt;
101 while ((opt = getopt_long(argc, argv, shortOptions, longOptions, NULL)) != -1) {
102 switch (opt) {
103 case 'h':
104 usage();
105 return 0;
106 case JSON_OPT:
107 json = true;
108 break;
109 default:
110 std::cerr << "error: unexpected option `" << (char)opt << "`\n";
111 usage();
112 return 1;
113 }
114 }
115
116 for (int i = optind; i < argc; ++i) {
117 unsigned long frames_count = 0;
118 unsigned int context_version_major = 0, context_version_minor = 0;
119 trace::Parser p;
120
121 if (!p.open(argv[i])) {
122 return 1;
123 }
124
125 trace::Call *call;
126 while ((call = p.parse_call())) {
127 if (call->no > calls.getLast()) {
128 delete call;
129 break;
130 }
131
132 if (context_version_major == 0 && strcmp(call->sig->name, "glXCreateContextAttribsARB") == 0) {
133 if (call->sig->num_args == 5 && strcmp(call->sig->arg_names[4], "attrib_list") == 0 ) {
134 const trace::Array *attribs = call->arg(4).toArray();
135 if (attribs) {
136 context_version_major = parseArrayAttrib(attribs, 0x2091, 0xFFFF, 0);
137 context_version_minor = parseArrayAttrib(attribs, 0x2092, 0xFFFF, 0);
138 } else context_version_major = context_version_minor = 0xFFFF;
139 } else context_version_major = context_version_minor = 0xFFFF;
140 }
141
142 if (call->flags & trace::CALL_FLAG_END_FRAME)
143 ++frames_count;
144
145 delete call;
146 }
147
148 if (json) {
149 printf("{ \"FileVersion\": \"%llu\", \"FramesCount\": \"%lu\", \"ContextVersion\": \"%u.%u\" }\n",
150 p.getVersion(), frames_count, context_version_major, context_version_minor);
151 } else {
152 printf("File version: %llu\nFrames count: %lu\nContext version: %u.%u\n",
153 p.getVersion(), frames_count, context_version_major, context_version_minor);
154 }
155 }
156
157 return 0;
158}
159
160const Command info_command = {
161 "info",
162 synopsis,
163 usage,
164 command
165};