1 /*
2 * Cogl
3 *
4 * A Low Level GPU Graphics and Utilities API
5 *
6 * Copyright (C) 2009 Intel Corporation.
7 *
8 * Permission is hereby granted, free of charge, to any person
9 * obtaining a copy of this software and associated documentation
10 * files (the "Software"), to deal in the Software without
11 * restriction, including without limitation the rights to use, copy,
12 * modify, merge, publish, distribute, sublicense, and/or sell copies
13 * of the Software, and to permit persons to whom the Software is
14 * furnished to do so, subject to the following conditions:
15 *
16 * The above copyright notice and this permission notice shall be
17 * included in all copies or substantial portions of the Software.
18 *
19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
23 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
24 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
25 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26 * SOFTWARE.
27 *
28 *
29 */
30
31 #include "cogl-config.h"
32
33 #include <stdlib.h>
34
35 #include "cogl-i18n-private.h"
36 #include "cogl-private.h"
37 #include "cogl-debug.h"
38 #include "cogl1-context.h"
39
40 /* XXX: If you add a debug option, please also add an option
41 * definition to cogl-debug-options.h. This will enable us - for
42 * example - to emit a "help" description for the option.
43 */
44
45 /* NB: Only these options get enabled if COGL_DEBUG=all is
46 * used since they don't affect the behaviour of Cogl they
47 * simply print out verbose information */
48 static const GDebugKey cogl_log_debug_keys[] = {
49 { "object", COGL_DEBUG_OBJECT },
50 { "slicing", COGL_DEBUG_SLICING },
51 { "atlas", COGL_DEBUG_ATLAS },
52 { "blend-strings", COGL_DEBUG_BLEND_STRINGS },
53 { "journal", COGL_DEBUG_JOURNAL },
54 { "batching", COGL_DEBUG_BATCHING },
55 { "matrices", COGL_DEBUG_MATRICES },
56 { "draw", COGL_DEBUG_DRAW },
57 { "opengl", COGL_DEBUG_OPENGL },
58 { "pango", COGL_DEBUG_PANGO },
59 { "show-source", COGL_DEBUG_SHOW_SOURCE},
60 { "framebuffer", COGL_DEBUG_FRAMEBUFFER },
61 { "offscreen", COGL_DEBUG_OFFSCREEN },
62 { "texture-pixmap", COGL_DEBUG_TEXTURE_PIXMAP },
63 { "bitmap", COGL_DEBUG_BITMAP },
64 { "clipping", COGL_DEBUG_CLIPPING },
65 { "winsys", COGL_DEBUG_WINSYS },
66 { "performance", COGL_DEBUG_PERFORMANCE },
67 { "textures", COGL_DEBUG_TEXTURES },
68 };
69 static const int n_cogl_log_debug_keys =
70 G_N_ELEMENTS (cogl_log_debug_keys);
71
72 static const GDebugKey cogl_behavioural_debug_keys[] = {
73 { "rectangles", COGL_DEBUG_RECTANGLES },
74 { "disable-batching", COGL_DEBUG_DISABLE_BATCHING },
75 { "disable-pbos", COGL_DEBUG_DISABLE_PBOS },
76 { "disable-software-transform", COGL_DEBUG_DISABLE_SOFTWARE_TRANSFORM },
77 { "dump-atlas-image", COGL_DEBUG_DUMP_ATLAS_IMAGE },
78 { "disable-atlas", COGL_DEBUG_DISABLE_ATLAS },
79 { "disable-shared-atlas", COGL_DEBUG_DISABLE_SHARED_ATLAS },
80 { "disable-texturing", COGL_DEBUG_DISABLE_TEXTURING},
81 { "disable-blending", COGL_DEBUG_DISABLE_BLENDING},
82 { "wireframe", COGL_DEBUG_WIREFRAME},
83 { "disable-software-clip", COGL_DEBUG_DISABLE_SOFTWARE_CLIP},
84 { "disable-program-caches", COGL_DEBUG_DISABLE_PROGRAM_CACHES},
85 { "disable-fast-read-pixel", COGL_DEBUG_DISABLE_FAST_READ_PIXEL},
86 { "sync-primitive", COGL_DEBUG_SYNC_PRIMITIVE },
87 { "sync-frame", COGL_DEBUG_SYNC_FRAME},
88 { "stencilling", COGL_DEBUG_STENCILLING },
89 };
90 static const int n_cogl_behavioural_debug_keys =
91 G_N_ELEMENTS (cogl_behavioural_debug_keys);
92
93 unsigned long _cogl_debug_flags[COGL_DEBUG_N_LONGS];
94 GHashTable *_cogl_debug_instances;
95
96 static void
_cogl_parse_debug_string_for_keys(const char * value,gboolean enable,const GDebugKey * keys,unsigned int nkeys)97 _cogl_parse_debug_string_for_keys (const char *value,
98 gboolean enable,
99 const GDebugKey *keys,
100 unsigned int nkeys)
101 {
102 int long_num, key_num;
103
104 /* g_parse_debug_string expects the value field in GDebugKey to be a
105 mask in an unsigned int but the flags are stored in an array of
106 multiple longs so we need to build a separate array for each
107 possible unsigned int */
108
109 for (long_num = 0; long_num < COGL_DEBUG_N_LONGS; long_num++)
110 {
111 int int_num;
112
113 for (int_num = 0;
114 int_num < sizeof (unsigned long) / sizeof (unsigned int);
115 int_num++)
116 {
117 GDebugKey keys_for_int[sizeof (unsigned int) * 8];
118 int nkeys_for_int = 0;
119
120 for (key_num = 0; key_num < nkeys; key_num++)
121 {
122 int long_index = COGL_FLAGS_GET_INDEX (keys[key_num].value);
123 int int_index = (keys[key_num].value %
124 (sizeof (unsigned long) * 8) /
125 (sizeof (unsigned int) * 8));
126
127 if (long_index == long_num && int_index == int_num)
128 {
129 keys_for_int[nkeys_for_int] = keys[key_num];
130 keys_for_int[nkeys_for_int].value =
131 COGL_FLAGS_GET_MASK (keys[key_num].value) >>
132 (int_num * sizeof (unsigned int) * 8);
133 nkeys_for_int++;
134 }
135 }
136
137 if (nkeys_for_int > 0)
138 {
139 unsigned long mask =
140 ((unsigned long) g_parse_debug_string (value,
141 keys_for_int,
142 nkeys_for_int)) <<
143 (int_num * sizeof (unsigned int) * 8);
144
145 if (enable)
146 _cogl_debug_flags[long_num] |= mask;
147 else
148 _cogl_debug_flags[long_num] &= ~mask;
149 }
150 }
151 }
152 }
153
154 void
_cogl_parse_debug_string(const char * value,gboolean enable,gboolean ignore_help)155 _cogl_parse_debug_string (const char *value,
156 gboolean enable,
157 gboolean ignore_help)
158 {
159 if (ignore_help && strcmp (value, "help") == 0)
160 return;
161
162 /* We don't want to let g_parse_debug_string handle "all" because
163 * literally enabling all the debug options wouldn't be useful to
164 * anyone; instead the all option enables all non behavioural
165 * options.
166 */
167 if (strcmp (value, "all") == 0 ||
168 strcmp (value, "verbose") == 0)
169 {
170 int i;
171 for (i = 0; i < n_cogl_log_debug_keys; i++)
172 if (enable)
173 COGL_DEBUG_SET_FLAG (cogl_log_debug_keys[i].value);
174 else
175 COGL_DEBUG_CLEAR_FLAG (cogl_log_debug_keys[i].value);
176 }
177 else if (g_ascii_strcasecmp (value, "help") == 0)
178 {
179 g_printerr ("\n\n%28s\n", _("Supported debug values:"));
180 #define OPT(MASK_NAME, GROUP, NAME, NAME_FORMATTED, DESCRIPTION) \
181 g_printerr ("%28s %s\n", NAME ":", DESCRIPTION);
182 #include "cogl-debug-options.h"
183 g_printerr ("\n%28s\n", _("Special debug values:"));
184 OPT (IGNORED, "ignored", "all", "ignored", \
185 N_("Enables all non-behavioural debug options"));
186 OPT (IGNORED, "ignored", "verbose", "ignored", \
187 N_("Enables all non-behavioural debug options"));
188 #undef OPT
189
190 g_printerr ("\n"
191 "%28s\n"
192 " COGL_DISABLE_GL_EXTENSIONS: %s\n"
193 " COGL_OVERRIDE_GL_VERSION: %s\n",
194 _("Additional environment variables:"),
195 _("Comma-separated list of GL extensions to pretend are "
196 "disabled"),
197 _("Override the GL version that Cogl will assume the driver "
198 "supports"));
199 exit (1);
200 }
201 else
202 {
203 _cogl_parse_debug_string_for_keys (value,
204 enable,
205 cogl_log_debug_keys,
206 n_cogl_log_debug_keys);
207 _cogl_parse_debug_string_for_keys (value,
208 enable,
209 cogl_behavioural_debug_keys,
210 n_cogl_behavioural_debug_keys);
211 }
212 }
213
214 #ifdef COGL_ENABLE_DEBUG
215 static gboolean
cogl_arg_debug_cb(const char * key,const char * value,void * user_data)216 cogl_arg_debug_cb (const char *key,
217 const char *value,
218 void *user_data)
219 {
220 _cogl_parse_debug_string (value,
221 TRUE /* enable the flags */,
222 FALSE /* don't ignore help */);
223 return TRUE;
224 }
225
226 static gboolean
cogl_arg_no_debug_cb(const char * key,const char * value,void * user_data)227 cogl_arg_no_debug_cb (const char *key,
228 const char *value,
229 void *user_data)
230 {
231 _cogl_parse_debug_string (value,
232 FALSE, /* disable the flags */
233 TRUE /* ignore help */);
234 return TRUE;
235 }
236 #endif /* COGL_ENABLE_DEBUG */
237
238 static GOptionEntry cogl_args[] = {
239 #ifdef COGL_ENABLE_DEBUG
240 { "cogl-debug", 0, 0, G_OPTION_ARG_CALLBACK, cogl_arg_debug_cb,
241 N_("Cogl debugging flags to set"), "FLAGS" },
242 { "cogl-no-debug", 0, 0, G_OPTION_ARG_CALLBACK, cogl_arg_no_debug_cb,
243 N_("Cogl debugging flags to unset"), "FLAGS" },
244 #endif /* COGL_ENABLE_DEBUG */
245 { NULL, },
246 };
247
248 void
_cogl_debug_check_environment(void)249 _cogl_debug_check_environment (void)
250 {
251 const char *env_string;
252
253 env_string = g_getenv ("COGL_DEBUG");
254 if (env_string != NULL)
255 {
256 _cogl_parse_debug_string (env_string,
257 TRUE /* enable the flags */,
258 FALSE /* don't ignore help */);
259 env_string = NULL;
260 }
261
262 env_string = g_getenv ("COGL_NO_DEBUG");
263 if (env_string != NULL)
264 {
265 _cogl_parse_debug_string (env_string,
266 FALSE /* disable the flags */,
267 FALSE /* don't ignore help */);
268 env_string = NULL;
269 }
270 }
271
272 static gboolean
pre_parse_hook(GOptionContext * context,GOptionGroup * group,void * data,GError ** error)273 pre_parse_hook (GOptionContext *context,
274 GOptionGroup *group,
275 void *data,
276 GError **error)
277 {
278 _cogl_init ();
279
280 return TRUE;
281 }
282
283 /* XXX: GOption based library initialization is not reliable because the
284 * GOption API has no way to represent dependencies between libraries.
285 */
286 GOptionGroup *
cogl_get_option_group(void)287 cogl_get_option_group (void)
288 {
289 GOptionGroup *group;
290
291 group = g_option_group_new ("cogl",
292 _("Cogl Options"),
293 _("Show Cogl options"),
294 NULL, NULL);
295
296 g_option_group_set_parse_hooks (group, pre_parse_hook, NULL);
297 g_option_group_add_entries (group, cogl_args);
298
299 return group;
300 }
301