1 /**************************************************************************
2 *
3 * Copyright (C) 2018 Collabora Ltd
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the "Software"),
7 * to deal in the Software without restriction, including without limitation
8 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included
13 * in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
16 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
21 * OTHER DEALINGS IN THE SOFTWARE.
22 *
23 **************************************************************************/
24
25 #include "vrend_debug.h"
26 #include "vrend_renderer.h"
27 #include "util/u_debug.h"
28 #include <stdlib.h>
29 #include <stdio.h>
30
31 static const char *command_names[VIRGL_MAX_COMMANDS] = {
32 "NOP",
33 "CREATE_OBJECT",
34 "BIND_OBJECT",
35 "DESTROY_OBJECT",
36 "SET_VIEWPORT_STATE",
37 "SET_FRAMEBUFFER_STATE",
38 "SET_VERTEX_BUFFERS",
39 "CLEAR",
40 "DRAW_VBO",
41 "RESOURCE_INLINE_WRITE",
42 "SET_SAMPLER_VIEWS",
43 "SET_INDEX_BUFFER",
44 "SET_CONSTANT_BUFFER",
45 "SET_STENCIL_REF",
46 "SET_BLEND_COLOR",
47 "SET_SCISSOR_STATE",
48 "BLIT",
49 "RESOURCE_COPY_REGION",
50 "BIND_SAMPLER_STATES",
51 "BEGIN_QUERY",
52 "END_QUERY",
53 "GET_QUERY_RESULT",
54 "SET_POLYGON_STIPPLE",
55 "SET_CLIP_STATE",
56 "SET_SAMPLE_MASK",
57 "SET_STREAMOUT_TARGETS",
58 "SET_RENDER_CONDITION",
59 "SET_UNIFORM_BUFFER",
60 "SET_SUB_CTX",
61 "CREATE_SUB_CTX",
62 "DESTROY_SUB_CTX",
63 "BIND_SHADER",
64 "SET_TESS_STATE",
65 "SET_MIN_SAMPLES",
66 "SET_SHADER_BUFFERS",
67 "SET_SHADER_IMAGES",
68 "MEMORY_BARRIER",
69 "LAUNCH_GRID",
70 "SET_FRAMEBUFFER_STATE_NO_ATTACH",
71 "TEXTURE_BARRIER",
72 "SET_ATOMIC_BUFFERS",
73 "SET_DEBUG_FLAGS",
74 "GET_QBO_RESULT",
75 "TRANSFER3D",
76 "END_TRANSFERS",
77 "COPY_TRANSFER3D",
78 "TWEAK"
79 };
80
81 static const char *object_type_names[VIRGL_MAX_OBJECTS] = {
82 "NULL",
83 "BLEND",
84 "RASTERIZER",
85 "DSA",
86 "SHADER",
87 "VERTEX_ELEMENTS",
88 "SAMPLER_VIEW",
89 "SAMPLER_STATE",
90 "SURFACE",
91 "QUERY",
92 "STREAMOUT_TARGET"
93 };
94
vrend_get_comand_name(enum virgl_context_cmd cmd)95 const char *vrend_get_comand_name(enum virgl_context_cmd cmd)
96 {
97 if (cmd < VIRGL_MAX_COMMANDS)
98 return command_names[cmd];
99 return "UNKNOWN";
100 }
101
vrend_get_object_type_name(enum virgl_object_type obj)102 extern const char *vrend_get_object_type_name(enum virgl_object_type obj)
103 {
104 if (obj < VIRGL_MAX_OBJECTS)
105 return object_type_names[obj];
106 return "UNKNOWN";
107 }
108
109 static const struct debug_named_value vrend_debug_options[] = {
110 {"tgsi", dbg_shader_tgsi, "Print TGSI"},
111 {"glsl", dbg_shader_glsl, "Print GLSL shaders created from TGSI"},
112 {"shader", dbg_shader, "Print TGSI and created GLSL shaders"},
113 {"stream", dbg_shader_streamout, "Print shader streamout"},
114 {"cmd", dbg_cmd, "Print incoming commands"},
115 {"obj", dbg_object, "Print object creation"},
116 {"blit", dbg_blit, "Debug blit code path"},
117 {"copyres", dbg_copy_resource, "Debug copy resource code path"},
118 {"feat", dbg_features, "Log features found"},
119 {"tex", dbg_tex, "Log texture operations"},
120 {"caller", dbg_caller, "Log who is creating the context"},
121 {"tweak", dbg_tweak, "Log tweaks"},
122 {"query", dbg_query, "Log queries"},
123 {"gles", dbg_gles, "GLES host specific debug"},
124 {"all", dbg_all, "Enable all debugging output"},
125 {"guestallow", dbg_allow_guest_override, "Allow the guest to override the debug flags"},
126 {"khr", dbg_khr, "Enable debug via KHR_debug extension"},
127 DEBUG_NAMED_VALUE_END
128 };
129
130 static uint64_t vrend_debug_flags = 0;
131 static int vrend_debug_flags_initalized = 0;
132
vrend_get_debug_flags(const char * flagstring)133 int vrend_get_debug_flags(const char *flagstring)
134 {
135 int retval;
136 char buf[1024] = "";
137
138 /* Unfortunately the available function to scan the flags take the string
139 * from the environment. The alternative to using setenv would be to
140 * duplicate code or to change the gallium/util intefaces and diverge more
141 * from mesa. So just stick to the environment variable. */
142 snprintf(buf, 1024, "VREND_TEMP_DEBUG_STRING_%d", getpid());
143 setenv(buf, flagstring, 1);
144
145 retval = (int)debug_get_flags_option(buf,
146 vrend_debug_options, 0);
147 unsetenv(buf);
148 return retval;
149 }
150
vrend_init_debug_flags()151 void vrend_init_debug_flags()
152 {
153 if (!vrend_debug_flags_initalized) {
154 vrend_debug_flags_initalized = 1;
155 vrend_debug_flags = debug_get_flags_option("VREND_DEBUG",
156 vrend_debug_options, 0);
157 }
158 }
159
vrend_debug(struct vrend_context * ctx,enum virgl_debug_flags flag)160 unsigned vrend_debug(struct vrend_context *ctx, enum virgl_debug_flags flag)
161 {
162 return (vrend_debug_flags & flag) || vrend_context_has_debug_flag(ctx, flag);
163 }
164
vrend_debug_add_flag(enum virgl_debug_flags flag)165 void vrend_debug_add_flag(enum virgl_debug_flags flag)
166 {
167 vrend_debug_flags |= flag;
168 }
169
vrend_debug_can_override(void)170 int vrend_debug_can_override(void)
171 {
172 return vrend_debug_flags & dbg_allow_guest_override;
173 }
174
175 static
vrend_default_debug_callback(const char * fmt,va_list va)176 void vrend_default_debug_callback(const char *fmt, va_list va)
177 {
178 static FILE* fp = NULL;
179 if (NULL == fp) {
180 const char* log = getenv("VIRGL_LOG_FILE");
181 if (log) {
182 char *log_prefix = strdup(log);
183 char *log_suffix = strstr(log_prefix, "%PID%");
184 if (log_suffix) {
185 *log_suffix = 0;
186 log_suffix += 5;
187 int len = strlen(log) + 32;
188 char *name = malloc(len);
189 snprintf(name, len, "%s%d%s", log_prefix, getpid(), log_suffix);
190 fp = fopen(name, "a");
191 free(name);
192 } else {
193 fp = fopen(log, "a");
194 }
195 free(log_prefix);
196 if (NULL == fp) {
197 fprintf(stderr, "Can't open %s\n", log);
198 fp = stderr;
199 }
200 } else {
201 fp = stderr;
202 }
203 }
204 vfprintf(fp, fmt, va);
205 fflush(fp);
206 }
207
208 static virgl_debug_callback_type debug_callback = vrend_default_debug_callback;
209
vrend_printf(const char * fmt,...)210 void vrend_printf(const char *fmt, ...)
211 {
212 if (debug_callback) {
213 va_list va;
214 va_start(va, fmt);
215 debug_callback(fmt, va);
216 va_end(va);
217 }
218 }
219
vrend_set_debug_callback(virgl_debug_callback_type cb)220 virgl_debug_callback_type vrend_set_debug_callback(virgl_debug_callback_type cb)
221 {
222 virgl_debug_callback_type retval = debug_callback;
223 debug_callback = cb;
224 return retval;
225 }
226
227