"Initial commit to Gerrit"
[profile/ivi/cogl.git] / cogl / cogl-pipeline-debug.c
1 /*
2  * Cogl
3  *
4  * An object oriented GL/GLES Abstraction/Utility Layer
5  *
6  * Copyright (C) 2008,2009,2010,2011 Intel Corporation.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library. If not, see
20  * <http://www.gnu.org/licenses/>.
21  *
22  *
23  *
24  * Authors:
25  *   Robert Bragg <robert@linux.intel.com>
26  */
27
28 #ifdef HAVE_CONFIG_H
29 #include "config.h"
30 #endif
31
32 #include "cogl-context-private.h"
33 #include "cogl-pipeline-private.h"
34 #include "cogl-pipeline-layer-private.h"
35 #include "cogl-node-private.h"
36
37 #include <glib.h>
38
39 typedef struct
40 {
41   int parent_id;
42   int *node_id_ptr;
43   GString *graph;
44   int indent;
45 } PrintDebugState;
46
47 static gboolean
48 dump_layer_cb (CoglNode *node, void *user_data)
49 {
50   CoglPipelineLayer *layer = COGL_PIPELINE_LAYER (node);
51   PrintDebugState *state = user_data;
52   int layer_id = *state->node_id_ptr;
53   PrintDebugState state_out;
54   GString *changes_label;
55   gboolean changes = FALSE;
56
57   if (state->parent_id >= 0)
58     g_string_append_printf (state->graph, "%*slayer%p -> layer%p;\n",
59                             state->indent, "",
60                             layer->_parent.parent,
61                             layer);
62
63   g_string_append_printf (state->graph,
64                           "%*slayer%p [label=\"layer=0x%p\\n"
65                           "ref count=%d\" "
66                           "color=\"blue\"];\n",
67                           state->indent, "",
68                           layer,
69                           layer,
70                           COGL_OBJECT (layer)->ref_count);
71
72   changes_label = g_string_new ("");
73   g_string_append_printf (changes_label,
74                           "%*slayer%p -> layer_state%d [weight=100];\n"
75                           "%*slayer_state%d [shape=box label=\"",
76                           state->indent, "",
77                           layer,
78                           layer_id,
79                           state->indent, "",
80                           layer_id);
81
82   if (layer->differences & COGL_PIPELINE_LAYER_STATE_UNIT)
83     {
84       changes = TRUE;
85       g_string_append_printf (changes_label,
86                               "\\lunit=%u\\n",
87                               layer->unit_index);
88     }
89
90   if (layer->differences & COGL_PIPELINE_LAYER_STATE_TEXTURE_DATA)
91     {
92       changes = TRUE;
93       g_string_append_printf (changes_label,
94                               "\\ltexture=%p\\n",
95                               layer->texture);
96     }
97
98   if (changes)
99     {
100       g_string_append_printf (changes_label, "\"];\n");
101       g_string_append (state->graph, changes_label->str);
102       g_string_free (changes_label, TRUE);
103     }
104
105   state_out.parent_id = layer_id;
106
107   state_out.node_id_ptr = state->node_id_ptr;
108   (*state_out.node_id_ptr)++;
109
110   state_out.graph = state->graph;
111   state_out.indent = state->indent + 2;
112
113   _cogl_pipeline_node_foreach_child (COGL_NODE (layer),
114                                      dump_layer_cb,
115                                      &state_out);
116
117   return TRUE;
118 }
119
120 static gboolean
121 dump_layer_ref_cb (CoglPipelineLayer *layer, void *data)
122 {
123   PrintDebugState *state = data;
124   int pipeline_id = *state->node_id_ptr;
125
126   g_string_append_printf (state->graph,
127                           "%*spipeline_state%d -> layer%p;\n",
128                           state->indent, "",
129                           pipeline_id,
130                           layer);
131
132   return TRUE;
133 }
134
135 static gboolean
136 dump_pipeline_cb (CoglNode *node, void *user_data)
137 {
138   CoglPipeline *pipeline = COGL_PIPELINE (node);
139   PrintDebugState *state = user_data;
140   int pipeline_id = *state->node_id_ptr;
141   PrintDebugState state_out;
142   GString *changes_label;
143   gboolean changes = FALSE;
144   gboolean layers = FALSE;
145
146   if (state->parent_id >= 0)
147     g_string_append_printf (state->graph, "%*spipeline%d -> pipeline%d;\n",
148                             state->indent, "",
149                             state->parent_id,
150                             pipeline_id);
151
152   g_string_append_printf (state->graph,
153                           "%*spipeline%d [label=\"pipeline=0x%p\\n"
154                           "ref count=%d\\n"
155                           "breadcrumb=\\\"%s\\\"\" color=\"red\"];\n",
156                           state->indent, "",
157                           pipeline_id,
158                           pipeline,
159                           COGL_OBJECT (pipeline)->ref_count,
160                           pipeline->has_static_breadcrumb ?
161                           pipeline->static_breadcrumb : "NULL");
162
163   changes_label = g_string_new ("");
164   g_string_append_printf (changes_label,
165                           "%*spipeline%d -> pipeline_state%d [weight=100];\n"
166                           "%*spipeline_state%d [shape=box label=\"",
167                           state->indent, "",
168                           pipeline_id,
169                           pipeline_id,
170                           state->indent, "",
171                           pipeline_id);
172
173
174   if (pipeline->differences & COGL_PIPELINE_STATE_COLOR)
175     {
176       changes = TRUE;
177       g_string_append_printf (changes_label,
178                               "\\lcolor=0x%02X%02X%02X%02X\\n",
179                               cogl_color_get_red_byte (&pipeline->color),
180                               cogl_color_get_green_byte (&pipeline->color),
181                               cogl_color_get_blue_byte (&pipeline->color),
182                               cogl_color_get_alpha_byte (&pipeline->color));
183     }
184
185   if (pipeline->differences & COGL_PIPELINE_STATE_BLEND)
186     {
187       const char *blend_enable_name;
188
189       changes = TRUE;
190
191       switch (pipeline->blend_enable)
192         {
193         case COGL_PIPELINE_BLEND_ENABLE_AUTOMATIC:
194           blend_enable_name = "AUTO";
195           break;
196         case COGL_PIPELINE_BLEND_ENABLE_ENABLED:
197           blend_enable_name = "ENABLED";
198           break;
199         case COGL_PIPELINE_BLEND_ENABLE_DISABLED:
200           blend_enable_name = "DISABLED";
201           break;
202         default:
203           blend_enable_name = "UNKNOWN";
204         }
205       g_string_append_printf (changes_label,
206                               "\\lblend=%s\\n",
207                               blend_enable_name);
208     }
209
210   if (pipeline->differences & COGL_PIPELINE_STATE_LAYERS)
211     {
212       changes = TRUE;
213       layers = TRUE;
214       g_string_append_printf (changes_label, "\\ln_layers=%d\\n",
215                               pipeline->n_layers);
216     }
217
218   if (changes)
219     {
220       g_string_append_printf (changes_label, "\"];\n");
221       g_string_append (state->graph, changes_label->str);
222       g_string_free (changes_label, TRUE);
223     }
224
225   if (layers)
226     {
227       g_list_foreach (pipeline->layer_differences,
228                       (GFunc)dump_layer_ref_cb,
229                       state);
230     }
231
232   state_out.parent_id = pipeline_id;
233
234   state_out.node_id_ptr = state->node_id_ptr;
235   (*state_out.node_id_ptr)++;
236
237   state_out.graph = state->graph;
238   state_out.indent = state->indent + 2;
239
240   _cogl_pipeline_node_foreach_child (COGL_NODE (pipeline),
241                                      dump_pipeline_cb,
242                                      &state_out);
243
244   return TRUE;
245 }
246
247 /* This function is just here to be called from GDB so we don't really
248    want to put a declaration in a header and we just add it here to
249    avoid a warning */
250 void
251 _cogl_debug_dump_pipelines_dot_file (const char *filename);
252
253 void
254 _cogl_debug_dump_pipelines_dot_file (const char *filename)
255 {
256   GString *graph;
257   PrintDebugState layer_state;
258   PrintDebugState pipeline_state;
259   int layer_id = 0;
260   int pipeline_id = 0;
261
262   _COGL_GET_CONTEXT (ctx, NO_RETVAL);
263
264   if (!ctx->default_pipeline)
265     return;
266
267   graph = g_string_new ("");
268   g_string_append_printf (graph, "digraph {\n");
269
270   layer_state.graph = graph;
271   layer_state.parent_id = -1;
272   layer_state.node_id_ptr = &layer_id;
273   layer_state.indent = 0;
274   dump_layer_cb ((CoglNode *)ctx->default_layer_0, &layer_state);
275
276   pipeline_state.graph = graph;
277   pipeline_state.parent_id = -1;
278   pipeline_state.node_id_ptr = &pipeline_id;
279   pipeline_state.indent = 0;
280   dump_pipeline_cb ((CoglNode *)ctx->default_pipeline, &pipeline_state);
281
282   g_string_append_printf (graph, "}\n");
283
284   if (filename)
285     g_file_set_contents (filename, graph->str, -1, NULL);
286   else
287     g_print ("%s", graph->str);
288
289   g_string_free (graph, TRUE);
290 }