Add coding style guide.
[platform/core/uifw/coregl.git] / src / modules / tracepath / coregl_tracepath.c
1 #include "coregl_tracepath.h"
2
3 #include <stdlib.h>
4 #include <string.h>
5 #include <sys/time.h>
6
7 #include <sys/types.h>
8 #include <unistd.h>
9
10 #include <dlfcn.h>
11 static int         api_gl_version;
12
13
14 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST)     RET_TYPE (*_orig_tracepath_##FUNC_NAME) PARAM_LIST = NULL;
15 #include "../../headers/sym.h"
16 #undef _COREGL_SYMBOL
17
18 #define TIMEVAL_INIT            { 0, 0 }
19
20 struct _Trace_Data {
21         char                         name[MAX_TRACE_NAME_LENGTH];
22         struct _Trace_Data          *next;
23 };
24
25 struct _Apicall_Data {
26         struct _Trace_Data          trace_data;
27
28         int                          call_count;
29         int                          last_call_count;
30         struct timeval              elapsed_time;
31         struct timeval              elapsed_time_max;
32         struct timeval              last_elapsed_time;
33         struct timeval              total_elapsed_time;
34         struct timeval              last_total_elapsed_time;
35         struct timeval              last_time;
36
37         int                          traced;
38 };
39
40 struct _Memuse_Data {
41         struct _Trace_Data          trace_data;
42
43         int                          memsize;
44         int                          alloc_count;
45         int                          remove_count;
46 };
47
48 struct _Surface_Data {
49         struct _Trace_Data          trace_data;
50
51         GLDisplay                    display;
52         GLSurface                    surface;
53         GLContext                    context;
54         GLint                        fbo;
55         GLint                        tex;
56         GLint                        rb;
57         int                          dump_count;
58         GLint                        tex_w;
59         GLint                        tex_h;
60         GLint                        tex_format;
61 };
62
63 typedef struct _GLGlueFakeContext {
64         GLuint gl_num_draw_buffers[1];
65         GLuint gl_num_tex_units[1];
66         GLuint gl_num_vertex_attribs[1];
67         GLuint gl_num_transform_feedback_separate_attribs[1];
68         GLuint gl_num_uniform_buffer_bindings[1];
69 } GLGlueFakeContext;
70
71 GLGlueFakeContext initial_fake_ctx_real;
72 GLGlueFakeContext *initial_fake_ctx = &initial_fake_ctx_real;
73
74 struct timeval     initial_time = TIMEVAL_INIT;
75 struct timeval     last_initial_time = TIMEVAL_INIT;
76
77 struct timeval     last_trace_time = TIMEVAL_INIT;
78 struct timeval     other_elapsed_time = TIMEVAL_INIT;
79 struct timeval     traced_other_elapsed_time = TIMEVAL_INIT;
80
81 Mutex               mtd_access_mutex = MUTEX_INITIALIZER;
82 Memuse_Data       **mtd_table;
83
84 Mutex               std_access_mutex = MUTEX_INITIALIZER;
85 Surface_Data      **std_table;
86
87 static void
88 _state_get_texture_states(GLenum pname, GLint *params)
89 {
90         GLuint cur_active_tex = 0;
91
92         AST(initial_fake_ctx != NULL);
93
94         _orig_tracepath_glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *)&cur_active_tex);
95         int i;
96         for (i = 0; i < initial_fake_ctx->gl_num_tex_units[0]; i++) {
97                 _orig_tracepath_glActiveTexture(GL_TEXTURE0 + i);
98                 _orig_tracepath_glGetIntegerv(pname, (GLint *)&params[i]);
99         }
100         _orig_tracepath_glActiveTexture(cur_active_tex);
101 }
102
103 static void
104 _state_get_draw_buffers(GLenum *params)
105 {
106         AST(initial_fake_ctx != NULL);
107
108         int i;
109         for (i = 0; i < initial_fake_ctx->gl_num_draw_buffers[0]; i++) {
110                 _orig_tracepath_glGetIntegerv(GL_DRAW_BUFFER0 + i, (GLint *)&params[i]);
111         }
112 }
113
114 static void
115 _state_get_transform_feedback_buffer_bindings(GLuint *params)
116 {
117         AST(initial_fake_ctx != NULL);
118
119         int i;
120         for (i = 0; i < initial_fake_ctx->gl_num_transform_feedback_separate_attribs[0];
121              i++) {
122                 _orig_tracepath_glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, i,
123                                                 (GLint *)&params[i]);
124         }
125 }
126
127 static void
128 _state_get_transform_feedback_buffer_bindings_offset(GLintptr *params)
129 {
130         AST(initial_fake_ctx != NULL);
131
132         int i;
133         for (i = 0; i < initial_fake_ctx->gl_num_transform_feedback_separate_attribs[0];
134              i++) {
135                 _orig_tracepath_glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_START, i,
136                                                 (GLint *)&params[i]);
137         }
138 }
139
140 static void
141 _state_get_transform_feedback_buffer_bindings_size(GLsizeiptr *params)
142 {
143         AST(initial_fake_ctx != NULL);
144
145         int i;
146         for (i = 0; i < initial_fake_ctx->gl_num_transform_feedback_separate_attribs[0];
147              i++) {
148                 _orig_tracepath_glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, i,
149                                                 (GLint *)&params[i]);
150         }
151 }
152
153 static void
154 _state_get_uniform_buffer_bindings(GLuint *params)
155 {
156         AST(initial_fake_ctx != NULL);
157
158         int i;
159         for (i = 0; i < initial_fake_ctx->gl_num_uniform_buffer_bindings[0]; i++) {
160 /////////////////////////////////////////////////////////////////////////////////
161 // XXXX : AVOID SEGFAULT in ADRENO
162                 ((GLint *)params)[i] = 0;
163 //              _orig_tracepath_glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, i, (GLint *)&params[i]);
164 /////////////////////////////////////////////////////////////////////////////////
165         }
166 }
167
168 static void
169 _state_get_uniform_buffer_bindings_offset(GLintptr *params)
170 {
171         AST(initial_fake_ctx != NULL);
172
173         int i;
174         for (i = 0; i < initial_fake_ctx->gl_num_uniform_buffer_bindings[0]; i++) {
175                 _orig_tracepath_glGetIntegeri_v(GL_UNIFORM_BUFFER_START, i,
176                                                 (GLint *)&params[i]);
177         }
178 }
179
180 static void
181 _state_get_uniform_buffer_bindings_size(GLsizeiptr *params)
182 {
183         AST(initial_fake_ctx != NULL);
184
185         int i;
186         for (i = 0; i < initial_fake_ctx->gl_num_uniform_buffer_bindings[0]; i++) {
187                 _orig_tracepath_glGetIntegeri_v(GL_UNIFORM_BUFFER_SIZE, i, (GLint *)&params[i]);
188         }
189 }
190
191 void
192 init_modules_tracepath()
193 {
194         {
195                 const char *output_file = NULL;
196                 output_file = get_env_setting("COREGL_LOG_FILE");
197                 if (strlen(output_file) > 0) {
198                         trace_fp = fopen(output_file, "w");
199                 }
200         }
201
202 #ifdef COREGL_TRACEPATH_TRACE_APICALL_INFO
203         trace_api_flag = atoi(get_env_setting("COREGL_TRACE_API"));
204         trace_api_all_flag = atoi(get_env_setting("COREGL_TRACE_API_ALL"));
205         trace_api_frame_flag = atoi(get_env_setting("COREGL_TRACE_API_FRAME"));
206 #endif
207 #ifdef COREGL_TRACEPATH_TRACE_MEMUSE_INFO
208         trace_mem_flag = atoi(get_env_setting("COREGL_TRACE_MEM"));
209         trace_mem_all_flag = atoi(get_env_setting("COREGL_TRACE_MEM_ALL"));
210 #endif
211 #ifdef COREGL_TRACEPATH_TRACE_SURFACE_INFO
212         trace_surface_flag = atoi(get_env_setting("COREGL_TRACE_SURFACE"));
213         trace_surface_sequence_sort_flag = atoi(
214                         get_env_setting("COREGL_TRACE_SURFACE_SEQUENCE_SORT"));
215         trace_surface_print_only_flag = atoi(
216                                                 get_env_setting("COREGL_TRACE_SURFACE_PRINT_ONLY"));
217
218         {
219                 // COREGL_TRACE_SURFACE_FILTER_PERIOD=40~60
220                 char tmp[64 + 1] = { 0 }, *tmpp = NULL;
221                 strncpy(tmp, get_env_setting("COREGL_TRACE_SURFACE_FILTER_PERIOD"), 64);
222                 for (tmpp = &tmp[0]; ; tmpp++) {
223                         if (*tmpp == 0x00) break;
224                         if (*tmpp == '~') {
225                                 *tmpp = 0x00;
226                                 trace_surface_filter_period_begin = atoi(tmp);
227                                 trace_surface_filter_period_end = atoi(tmpp + 1);
228                                 break;
229                         }
230                 }
231         }
232
233         {
234                 // COREGL_TRACE_SURFACE_FILTER_TYPE=EGL|FBO
235                 char tmp[64 + 1] = { 0 };
236                 strncpy(tmp, get_env_setting("COREGL_TRACE_SURFACE_FILTER_TYPE"), 64);
237                 if (strcmp(tmp, "EGL") == 0) trace_surface_filter_type = 1;
238                 if (strcmp(tmp, "FBO") == 0) trace_surface_filter_type = 2;
239         }
240
241         {
242                 // COREGL_TRACE_SURFACE_FILTER_HANDLE=0x3234
243                 char tmp[64 + 1] = { 0 }, *tmpp = NULL;
244                 strncpy(tmp, get_env_setting("COREGL_TRACE_SURFACE_FILTER_HANDLE"), 64);
245                 if (tmp[0] == '0' && tmp[1] == 'x') {
246                         for (tmpp = &tmp[2]; ; tmpp++) {
247                                 if (*tmpp == 0x00) break;
248                                 trace_surface_filter_handle *= 16;
249                                 switch (*tmpp) {
250                                 case '1' :
251                                         trace_surface_filter_handle += 1;
252                                         break;
253                                 case '2' :
254                                         trace_surface_filter_handle += 2;
255                                         break;
256                                 case '3' :
257                                         trace_surface_filter_handle += 3;
258                                         break;
259                                 case '4' :
260                                         trace_surface_filter_handle += 4;
261                                         break;
262                                 case '5' :
263                                         trace_surface_filter_handle += 5;
264                                         break;
265                                 case '6' :
266                                         trace_surface_filter_handle += 6;
267                                         break;
268                                 case '7' :
269                                         trace_surface_filter_handle += 7;
270                                         break;
271                                 case '8' :
272                                         trace_surface_filter_handle += 8;
273                                         break;
274                                 case '9' :
275                                         trace_surface_filter_handle += 9;
276                                         break;
277                                 case 'A' :
278                                 case 'a' :
279                                         trace_surface_filter_handle += 10;
280                                         break;
281                                 case 'B' :
282                                 case 'b' :
283                                         trace_surface_filter_handle += 11;
284                                         break;
285                                 case 'C' :
286                                 case 'c' :
287                                         trace_surface_filter_handle += 12;
288                                         break;
289                                 case 'D' :
290                                 case 'd' :
291                                         trace_surface_filter_handle += 13;
292                                         break;
293                                 case 'E' :
294                                 case 'e' :
295                                         trace_surface_filter_handle += 14;
296                                         break;
297                                 case 'F' :
298                                 case 'f' :
299                                         trace_surface_filter_handle += 15;
300                                         break;
301                                 }
302                         }
303                 } else {
304                         trace_surface_filter_handle = atoi(tmp);
305                 }
306         }
307
308         {
309                 // COREGL_TRACE_SURFACE_FILTER_SIZE=640x480
310                 char tmp[64 + 1] = { 0 }, *tmpp = NULL;
311                 strncpy(tmp, get_env_setting("COREGL_TRACE_SURFACE_FILTER_SIZE"), 64);
312                 for (tmpp = &tmp[0]; ; tmpp++) {
313                         if (*tmpp == 0x00) break;
314                         if (*tmpp == 'x') {
315                                 *tmpp = 0x00;
316                                 trace_surface_filter_size_w = atoi(tmp);
317                                 trace_surface_filter_size_h = atoi(tmpp + 1);
318                                 break;
319                         }
320                 }
321         }
322
323 #endif
324 #ifdef COREGL_TRACEPATH_TRACE_CONTEXT_INFO
325         trace_ctx_flag = atoi(get_env_setting("COREGL_TRACE_CTX"));
326         trace_ctx_force_flag = atoi(get_env_setting("COREGL_TRACE_CTX_FORCE"));
327 #endif
328 #ifdef COREGL_TRACEPATH_TRACE_STATE_INFO
329         trace_state_flag = atoi(get_env_setting("COREGL_TRACE_STATE"));
330 #endif
331
332         if (USE_TRACEPATH) {
333                 COREGL_LOG("[CoreGL] \E[40;32;1m<Trace> \E[40;37;1m: ");
334
335                 if (trace_api_flag == 1) {
336                         COREGL_LOG("\E[40;31;1m(API)\E[0m ");
337                         if (trace_api_all_flag == 1) COREGL_LOG("\E[40;31;1m(API-ALL)\E[0m ");
338                         if (trace_api_frame_flag == 1) COREGL_LOG("\E[40;31;1m(API-FRAME)\E[0m ");
339                 }
340                 if (trace_ctx_flag == 1) {
341                         COREGL_LOG("\E[40;33;1m(CONTEXT)\E[0m ");
342                         if (trace_ctx_force_flag == 1) COREGL_LOG("\E[40;33;1m(CONTEXT-FORCE)\E[0m ");
343                 }
344                 if (trace_state_flag == 1) COREGL_LOG("\E[40;36;1m(STATE)\E[0m ");
345                 if (trace_mem_flag == 1) {
346                         COREGL_LOG("\E[40;35;1m(MEM)\E[0m ");
347                         if (trace_mem_all_flag == 1) COREGL_LOG("\E[40;35;1m(MEM-ALL)\E[0m ");
348                 }
349                 if (trace_surface_flag == 1) {
350                         COREGL_LOG("\E[40;36;1m(SURFACE)\E[0m ");
351                         if (trace_surface_sequence_sort_flag == 1)
352                                 COREGL_LOG("\E[40;36;1m(SURFACE-SEQUENCE SORT)\E[0m ");
353                         if (trace_surface_print_only_flag == 1)
354                                 COREGL_LOG("\E[40;36;1m(PRINT ONLY)\E[0m ");
355                         if (trace_surface_filter_period_begin != 0 ||
356                             trace_surface_filter_period_end != 0)
357                                 COREGL_LOG("\E[40;36;1m(SURFACE-PERIOD:%d~%d)\E[0m ",
358                                            trace_surface_filter_period_begin, trace_surface_filter_period_end);
359                         if (trace_surface_filter_type == 1)
360                                 COREGL_LOG("\E[40;36;1m(SURFACE-TYPE:EGL)\E[0m ");
361                         if (trace_surface_filter_type == 2)
362                                 COREGL_LOG("\E[40;36;1m(SURFACE-TYPE:FBO)\E[0m ");
363                         if (trace_surface_filter_handle != 0)
364                                 COREGL_LOG("\E[40;36;1m(SURFACE-HANDLE:0x%x(%d))\E[0m ",
365                                            trace_surface_filter_handle, trace_surface_filter_handle);
366                         if (trace_surface_filter_size_w > 0 && trace_surface_filter_size_h > 0)
367                                 COREGL_LOG("\E[40;36;1m(SURFACE-SIZE:%dx%d)\E[0m ", trace_surface_filter_size_w,
368                                            trace_surface_filter_size_h);
369                 }
370
371                 COREGL_LOG("\E[40;37;1menabled\E[0m\n");
372         }
373 }
374
375 void
376 deinit_modules_tracepath()
377 {
378 }
379
380 void
381 init_modules_tstate_tracepath(GLThreadState *tstate)
382 {
383         MY_MODULE_TSTATE *tstate_mt = NULL;
384
385         tstate_mt = (MY_MODULE_TSTATE *)calloc(1, sizeof(MY_MODULE_TSTATE));
386
387
388         tstate->module_data[MY_MODULE_ID] = tstate_mt;
389 }
390
391 void
392 deinit_modules_tstate_tracepath(GLThreadState *tstate)
393 {
394         if (tstate->module_data[MY_MODULE_ID] != NULL) {
395                 free(tstate->module_data[MY_MODULE_ID]);
396                 tstate->module_data[MY_MODULE_ID] = NULL;
397         }
398 }
399
400 void
401 tracepath_apply_overrides()
402 {
403         if (USE_TRACEPATH) {
404                 tracepath_apply_overrides_egl(1);
405                 tracepath_apply_overrides_gl(1);
406         }
407 }
408
409 void
410 tracepath_apply_overrides_egl(int enable)
411 {
412 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST)     COREGL_INIT_ORIGINAL(_orig_tracepath_, FUNC_NAME);
413 # include "../../headers/sym_egl.h"
414 #undef _COREGL_SYMBOL
415
416 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST)     COREGL_OVERRIDE(tracepath_, FUNC_NAME);
417 # include "../../headers/sym_egl.h"
418 #undef _COREGL_SYMBOL
419 }
420
421 void
422 tracepath_apply_overrides_gl(int enable)
423 {
424 #define _COREGL_START_API(version) api_gl_version = version;
425 #define _COREGL_END_API(version) api_gl_version = COREGL_GLAPI_2;
426 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST)     \
427         if(api_gl_version <= driver_gl_version) COREGL_INIT_ORIGINAL(_orig_tracepath_, FUNC_NAME);
428 # include "../../headers/sym_gl.h"
429 #undef _COREGL_SYMBOL
430
431 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST) \
432         if(api_gl_version <= driver_gl_version) COREGL_OVERRIDE(tracepath_, FUNC_NAME);
433 # include "../../headers/sym_gl.h"
434 #undef _COREGL_SYMBOL
435 #undef _COREGL_START_API
436 #undef _COREGL_END_API
437 }
438
439 #undef OVERRIDE
440
441 void
442 tracepath_dump_context_states(int force_output)
443 {
444         static struct timeval tv_last = { 0, 0 };
445
446         if (unlikely(trace_state_flag != 1)) return;
447
448         _sym_glGetIntegerv(GL_MAX_DRAW_BUFFERS,
449                            (GLint *)initial_fake_ctx->gl_num_draw_buffers);
450         _sym_glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS,
451                            (GLint *)initial_fake_ctx->gl_num_tex_units);
452         _sym_glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,
453                            (GLint *)initial_fake_ctx->gl_num_vertex_attribs);
454         _sym_glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
455                            (GLint *)initial_fake_ctx->gl_num_transform_feedback_separate_attribs);
456         _sym_glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
457                            (GLint *)initial_fake_ctx->gl_num_uniform_buffer_bindings);
458
459         if (!force_output) {
460                 struct timeval tv_now = { 0, 0 };
461                 AST(gettimeofday(&tv_now, NULL) == 0);
462                 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC) {
463                         goto finish;
464                 }
465                 tv_last = tv_now;
466         }
467
468         TRACE("\n");
469         TRACE("\E[0;40;34m===================================================================================================================\E[0m\n");
470         TRACE("\E[40;32;1m  State info \E[1;37;1m: <PID = %d> (CURRENT BINDED CONTEXT)\E[0m\n",
471               getpid());
472         TRACE("\E[0;40;34m===================================================================================================================\E[0m\n");
473
474 #define PRINTF_CHAR_GLenum "0x%8X"
475 #define PRINTF_CHAR_GLboolean "%10d"
476 #define PRINTF_CHAR_GLint "%10d"
477 #define PRINTF_CHAR_GLsizei "%10u"
478 #define PRINTF_CHAR_GLuint "%10u"
479 #define PRINTF_CHAR_GLuintmask "0x%8X"
480 #define PRINTF_CHAR_GLintptr "%10ld"
481 #define PRINTF_CHAR_GLsizeiptr "%10ld"
482
483 #define PRINTF_CHAR_GLclampf "%10.6f"
484 #define PRINTF_CHAR_GLfloat "%10.6f"
485
486 #define PRINTF_CHAR_GLvoidptr "%10p"
487
488 #define PRINTF_CHAR(type) PRINTF_CHAR_##type
489
490 #define INITIAL_CTX initial_fake_ctx
491
492 #define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT)  \
493    { \
494       TYPE valuedata[SIZE]; \
495       TYPE *value = NULL; \
496       value = valuedata; GET_STMT; value = valuedata; \
497       TRACE("\E[40;37;1m %-30.30s : (\E[0m ", #NAME); \
498       for (int i = 0; i < SIZE; i++) \
499       { \
500          if (i > 0) { \
501             if (i % 4 == 0) \
502                TRACE("\n %-30.30s     ", "");\
503             else \
504                TRACE(", "); \
505          } \
506          TRACE("["PRINTF_CHAR(TYPE)"]", value[i]); \
507       } \
508       TRACE(" \E[40;37;1m)\E[0m\n"); \
509    }
510 # include "../fastpath/coregl_fastpath_state.h"
511 #undef GLUE_STATE
512
513         TRACE("\E[0;40;34m===================================================================================================================\E[0m\n");
514         TRACE("\n");
515
516         TRACE_END();
517
518 finish:
519         return;
520 }
521
522
523 static inline void
524 _add_timeval_period(struct timeval *tv_dst, struct timeval tv_now,
525                     struct timeval tv_old)
526 {
527         tv_dst->tv_sec += tv_now.tv_sec - tv_old.tv_sec;
528         tv_dst->tv_usec += 1000000 + (tv_now.tv_usec - tv_old.tv_usec);
529         tv_dst->tv_sec += (tv_dst->tv_usec / 1000000) - 1;
530         tv_dst->tv_usec = tv_dst->tv_usec % 1000000;
531 }
532
533 static inline void
534 _add_timeval(struct timeval *tv_dst, struct timeval tv_src)
535 {
536         tv_dst->tv_sec += tv_src.tv_sec;
537         tv_dst->tv_usec += tv_src.tv_usec;
538         if (tv_dst->tv_usec > 1000000) {
539                 tv_dst->tv_usec -= 1000000;
540                 tv_dst->tv_sec++;
541         } else if (tv_dst->tv_usec < 0) {
542                 tv_dst->tv_usec += 1000000;
543                 tv_dst->tv_sec--;
544         }
545 }
546
547 static inline double
548 _get_timeval_period(struct timeval time_now, struct timeval time_old)
549 {
550         return ((time_now.tv_sec - time_old.tv_sec) * 1000) + ((
551                                 time_now.tv_usec - time_old.tv_usec) / 1000.0);
552 }
553
554 static inline double
555 _get_timeval(struct timeval time)
556 {
557         return (time.tv_sec * 1000) + (time.tv_usec / 1000.0);
558 }
559
560 static unsigned short
561 _generate_hash_short(const char *string)
562 {
563         unsigned short hash = 0;
564         int i;
565
566         for (i = 0; i < strlen(string); i++) {
567                 hash = 253 * hash + string[i];
568         }
569         return (hash ^ (hash >> 8)) % MAX_TRACE_TABLE_SIZE;
570 }
571
572 static Trace_Data *
573 _get_trace_data(Trace_Data **ftd_table, size_t td_size, const char *name)
574 {
575         Trace_Data *ret = NULL;
576         Trace_Data *current = NULL;
577         Trace_Data *prev = NULL;
578         unsigned short hash = 0;
579
580         AST(strlen(name) < MAX_TRACE_NAME_LENGTH);
581
582         hash = _generate_hash_short(name);
583
584         current = ftd_table[hash];
585
586         while (current != NULL && current->next != NULL) {
587                 if (strcmp(current->name, name) == 0)
588                         break;
589                 prev = current;
590                 current = current->next;
591         }
592
593         if (current != NULL) {
594                 ret = current;
595         } else {
596                 Trace_Data *newitm = NULL;
597                 newitm = (Trace_Data *)calloc(1, td_size);
598                 strcpy(newitm->name, name);
599                 newitm->next = NULL;
600
601                 if (prev != NULL) {
602                         prev->next = newitm;
603                 } else {
604                         ftd_table[hash] = newitm;
605                 }
606                 ret = newitm;
607         }
608
609         goto finish;
610
611 finish:
612         return ret;
613 }
614
615 void
616 tracepath_mem_trace_add(const char *desc, int alloc_size)
617 {
618         Memuse_Data *mtd = NULL;
619
620         if (trace_mem_flag == 1) {
621                 AST(mutex_lock(&mtd_access_mutex) == 1);
622
623                 if (mtd_table == NULL) {
624                         mtd_table = (Memuse_Data **)calloc(1,
625                                                            sizeof(Memuse_Data *) * MAX_TRACE_TABLE_SIZE);
626                 }
627
628                 mtd = (Memuse_Data *)_get_trace_data((Trace_Data **)mtd_table,
629                                                      sizeof(Memuse_Data), desc);
630
631                 AST(mtd != NULL);
632
633                 mtd->alloc_count++;
634
635                 if (mtd->memsize == 0)
636                         mtd->memsize = alloc_size;
637
638                 AST(mtd->memsize == alloc_size);
639
640                 AST(mutex_unlock(&mtd_access_mutex) == 1);
641
642                 if (trace_mem_all_flag == 1)
643                         _COREGL_TRACE_MEM_OUTPUT(1);
644         }
645
646 }
647
648 void
649 tracepath_mem_trace_remove(const char *desc, int alloc_size)
650 {
651         Memuse_Data *mtd = NULL;
652
653         if (trace_mem_flag == 1) {
654                 AST(mutex_lock(&mtd_access_mutex) == 1);
655
656                 if (mtd_table == NULL) {
657                         mtd_table = (Memuse_Data **)calloc(1,
658                                                            sizeof(Memuse_Data *) * MAX_TRACE_TABLE_SIZE);
659                 }
660
661                 mtd = (Memuse_Data *)_get_trace_data((Trace_Data **)mtd_table,
662                                                      sizeof(Memuse_Data), desc);
663
664                 AST(mtd != NULL);
665                 AST(mtd->memsize == alloc_size);
666
667                 AST(mtd->alloc_count > mtd->remove_count);
668                 mtd->remove_count++;
669
670                 AST(mutex_unlock(&mtd_access_mutex) == 1);
671
672                 if (trace_mem_all_flag == 1)
673                         _COREGL_TRACE_MEM_OUTPUT(1);
674         }
675 }
676
677 void *
678 tracepath_api_trace_begin(const char *funcname, void *hint,
679                           int trace_total_time)
680 {
681         Apicall_Data *ftd = NULL;
682         struct timeval t = TIMEVAL_INIT;
683
684         if (trace_api_flag == 1) {
685                 AST(gettimeofday(&t, NULL) == 0);
686
687                 ftd = (Apicall_Data *)hint;
688
689                 if (ftd == NULL) {
690                         MY_MODULE_TSTATE *tstate = NULL;
691                         GET_MY_TSTATE(tstate, get_current_thread_state());
692
693                         if (tstate == NULL) {
694                                 init_new_thread_state();
695
696                                 GET_MY_TSTATE(tstate, get_current_thread_state());
697                                 AST(tstate != NULL);
698                         }
699
700                         if (tstate->ftd_table == NULL) {
701                                 tstate->ftd_table = (Apicall_Data **)calloc(1,
702                                                     sizeof(Apicall_Data *) * MAX_TRACE_TABLE_SIZE);
703                         }
704
705                         ftd = (Apicall_Data *)_get_trace_data((Trace_Data **)tstate->ftd_table,
706                                                               sizeof(Apicall_Data), funcname);
707                 }
708
709                 AST(ftd != NULL);
710
711                 ftd->call_count++;
712                 AST(ftd->last_time.tv_sec == 0);
713
714                 AST(gettimeofday(&ftd->last_time, NULL) == 0);
715
716                 if (initial_time.tv_sec == 0) {
717                         initial_time = ftd->last_time;
718                         last_initial_time = ftd->last_time;
719                 }
720
721                 if (trace_total_time == 1) {
722                         if (last_trace_time.tv_sec != 0) {
723                                 _add_timeval_period(&other_elapsed_time, t, last_trace_time);
724                                 last_trace_time.tv_sec = 0;
725                         }
726                 }
727
728         }
729
730         return ftd;
731 }
732
733 void *
734 tracepath_api_trace_end(const char *funcname, void *hint, int trace_total_time)
735 {
736         Apicall_Data *ftd = NULL;
737         struct timeval t = TIMEVAL_INIT;
738
739         if (trace_api_flag == 1) {
740                 MY_MODULE_TSTATE *tstate = NULL;
741                 struct timeval elapsed_time = TIMEVAL_INIT;
742
743                 AST(gettimeofday(&t, NULL) == 0);
744
745                 ftd = (Apicall_Data *)hint;
746
747                 if (ftd == NULL) {
748                         GET_MY_TSTATE(tstate, get_current_thread_state());
749
750                         if (tstate == NULL) {
751                                 init_new_thread_state();
752
753                                 GET_MY_TSTATE(tstate, get_current_thread_state());
754                                 AST(tstate != NULL);
755                         }
756
757                         AST(tstate != NULL);
758                         AST(tstate->ftd_table != NULL);
759
760                         ftd = (Apicall_Data *)_get_trace_data((Trace_Data **)tstate->ftd_table,
761                                                               sizeof(Apicall_Data), funcname);
762                 }
763
764                 AST(ftd != NULL);
765
766                 _add_timeval_period(&elapsed_time, t, ftd->last_time);
767
768                 _add_timeval(&ftd->elapsed_time, elapsed_time);
769
770                 if (elapsed_time.tv_sec >= ftd->elapsed_time_max.tv_sec &&
771                     elapsed_time.tv_usec > ftd->elapsed_time_max.tv_usec) {
772                         ftd->elapsed_time_max.tv_sec = elapsed_time.tv_sec;
773                         ftd->elapsed_time_max.tv_usec = elapsed_time.tv_usec;
774                 }
775
776                 ftd->last_time.tv_sec = 0;
777
778                 if (trace_total_time == 1) {
779                         _add_timeval(&ftd->total_elapsed_time, elapsed_time);
780
781                         AST(gettimeofday(&last_trace_time, NULL) == 0);
782
783                         if (initial_time.tv_sec == 0) {
784                                 initial_time = t;
785                                 last_initial_time = t;
786                         }
787                 }
788
789         }
790
791
792         return ftd;
793 }
794
795 void
796 tracepath_api_trace_output(int force_output)
797 {
798         static struct timeval tv_last = TIMEVAL_INIT;
799         struct timeval total_now = TIMEVAL_INIT;
800         GLThreadState *tstate = NULL;
801         MY_MODULE_TSTATE *tstate_tm = NULL;
802         Apicall_Data **ftd_table = NULL;
803
804         double total_elapsed_time = 0.0;
805         double total_elapsed_time_period = 0.0;
806         double total_opengl_elapsed_time = 0.0;
807         double total_opengl_elapsed_time_period = 0.0;
808         double total_other_elapsed_time = 0.0;
809         double total_other_elapsed_time_period = 0.0;
810
811         double swaps_per_sec = 0.0;
812
813         int i;
814
815         if (trace_api_flag != 1) {
816                 goto finish;
817         }
818
819         if (!force_output) {
820                 struct timeval tv_now = TIMEVAL_INIT;
821                 AST(gettimeofday(&tv_now, NULL) == 0);
822                 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC) {
823                         goto finish;
824                 }
825                 tv_last = tv_now;
826         }
827
828         AST(gettimeofday(&total_now, NULL) == 0);
829
830         total_elapsed_time = _get_timeval_period(total_now, initial_time);
831         total_elapsed_time_period = _get_timeval_period(total_now, last_initial_time);
832         last_initial_time = total_now;
833
834         total_other_elapsed_time = _get_timeval(other_elapsed_time);
835         total_other_elapsed_time_period = _get_timeval_period(other_elapsed_time,
836                                           traced_other_elapsed_time);
837         traced_other_elapsed_time = other_elapsed_time;
838
839         tstate = get_current_thread_state();
840
841         if (tstate == NULL) {
842                 init_new_thread_state();
843
844                 tstate = get_current_thread_state();
845                 AST(tstate != NULL);
846         }
847
848         GET_MY_TSTATE(tstate_tm, tstate);
849         if (tstate_tm == NULL) goto finish;
850
851         ftd_table = tstate_tm->ftd_table;
852         if (ftd_table == NULL) goto finish;
853
854         {
855                 static Apicall_Data *trace_hint_swap = NULL;
856                 if (trace_hint_swap == NULL)
857                         trace_hint_swap = (Apicall_Data *)_get_trace_data((Trace_Data **)ftd_table,
858                                           sizeof(Apicall_Data), "tracepath_eglSwapBuffers");
859
860                 if (trace_hint_swap != NULL && total_elapsed_time_period > 0) {
861                         swaps_per_sec = (trace_hint_swap->call_count -
862                                          trace_hint_swap->last_call_count) / (total_elapsed_time_period / 1000);
863                 }
864         }
865
866
867         TRACE("\n");
868         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
869         TRACE("\E[40;32;1m  API call info \E[1;37;1m: <PID = %d> Thread ID = 0x%x  [Swaps per Second(P) = %7.2f]\E[0m\n",
870               getpid(), tstate->thread_id, swaps_per_sec);
871         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
872
873         // highlighted
874         for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
875                 if (ftd_table[i] != NULL) {
876                         Apicall_Data *current = ftd_table[i];
877
878                         while (current != NULL) {
879                                 double elapsed_time = _get_timeval(current->elapsed_time);
880                                 double elapsed_time_per_call = elapsed_time / current->call_count;
881
882                                 total_opengl_elapsed_time += _get_timeval(current->total_elapsed_time);
883                                 total_opengl_elapsed_time_period += _get_timeval(current->total_elapsed_time) -
884                                                                     _get_timeval(current->last_total_elapsed_time);
885
886                                 current->traced = 0;
887
888                                 if (current->call_count > current->last_call_count) {
889                                         double elapsed_time_period = _get_timeval_period(current->elapsed_time,
890                                                                      current->last_elapsed_time);
891                                         double elapsed_time_max = _get_timeval(current->elapsed_time_max);
892                                         double elapsed_time_per_call_period = elapsed_time_period /
893                                                                               (current->call_count - current->last_call_count);
894                                         char *fname = current->trace_data.name;
895
896                                         if (!strncmp(fname, "tracepath_", 10))
897                                                 fname = &current->trace_data.name[10];
898
899                                         if (elapsed_time_per_call_period >= 0.01 ||
900                                             current->call_count - current->last_call_count > 1000) {
901                                                 TRACE("\E[40;37;1m %-39.39s : %10d call(s), %9.3f ms/API, %9.2f ms(MAX), %9.3f ms/API(P)\E[0m\n",
902                                                       fname, current->call_count, elapsed_time_per_call, elapsed_time_max,
903                                                       elapsed_time_per_call_period);
904                                                 current->traced = 1;
905                                         }
906                                 }
907                                 current = (Apicall_Data *)current->trace_data.next;
908                         }
909                 }
910         }
911
912         {
913                 int fp_env = 0;
914                 fp_env = atoi(get_env_setting("COREGL_TRACE_API_ALL"));
915                 if (fp_env == 1) {
916                         // other
917                         for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
918                                 if (ftd_table[i] != NULL) {
919                                         Apicall_Data *current = ftd_table[i];
920
921                                         while (current != NULL) {
922                                                 if (current->traced == 0 && current->call_count > 0) {
923                                                         double elapsed_time = _get_timeval(current->elapsed_time);
924                                                         double elapsed_time_per_call = elapsed_time / current->call_count;
925                                                         double elapsed_time_max = _get_timeval(current->elapsed_time_max);
926                                                         char *fname = current->trace_data.name;
927
928                                                         if (!strncmp(fname, "tracepath_", 10))
929                                                                 fname = &current->trace_data.name[10];
930
931                                                         TRACE(" %-39.39s : %10d call(s), %9.3f ms/API, %9.2f ms(MAX)\n",
932                                                               fname, current->call_count, elapsed_time_per_call, elapsed_time_max);
933                                                 }
934                                                 current = (Apicall_Data *)current->trace_data.next;
935                                         }
936                                 }
937                         }
938                 }
939         }
940
941         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
942
943         if (trace_api_frame_flag == 0) {
944                 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
945                       "TOTAL elapsed Time",
946                       total_elapsed_time,
947                       100.0,
948                       total_elapsed_time_period,
949                       100.0);
950
951
952                 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
953                       "OpenGL elapsed Time",
954                       total_opengl_elapsed_time,
955                       total_opengl_elapsed_time * 100.0 / total_elapsed_time,
956                       total_opengl_elapsed_time_period,
957                       total_opengl_elapsed_time_period * 100.0 / total_elapsed_time_period);
958
959                 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
960                       "Out of OpenGL elapsed time",
961                       total_other_elapsed_time,
962                       total_other_elapsed_time * 100.0 / total_elapsed_time,
963                       total_other_elapsed_time_period,
964                       total_other_elapsed_time_period * 100.0 / total_elapsed_time_period);
965
966                 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
967                       "CoreGL API tracing overhead",
968                       total_elapsed_time - total_opengl_elapsed_time - total_other_elapsed_time,
969                       (total_elapsed_time - total_opengl_elapsed_time - total_other_elapsed_time) *
970                       100.0 / total_elapsed_time,
971                       total_elapsed_time_period - total_opengl_elapsed_time_period -
972                       total_other_elapsed_time_period,
973                       (total_elapsed_time_period - total_opengl_elapsed_time_period -
974                        total_other_elapsed_time_period) * 100.0 / total_elapsed_time_period);
975
976                 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
977         }
978         TRACE("\n");
979
980         for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
981                 if (ftd_table[i] != NULL) {
982                         Apicall_Data *current = ftd_table[i];
983
984                         while (current != NULL) {
985                                 current->last_call_count = current->call_count;
986                                 current->last_elapsed_time = current->elapsed_time;
987                                 current->last_total_elapsed_time = current->total_elapsed_time;
988                                 current = (Apicall_Data *)current->trace_data.next;
989                         }
990                 }
991         }
992
993         TRACE_END();
994
995         goto finish;
996
997 finish:
998         return;
999 }
1000
1001 void
1002 tracepath_api_trace_reset_frame()
1003 {
1004         GLThreadState *tstate = NULL;
1005         MY_MODULE_TSTATE *tstate_tm = NULL;
1006         Apicall_Data **ftd_table = NULL;
1007
1008         int i;
1009
1010         if (trace_api_flag != 1) {
1011                 goto finish;
1012         }
1013
1014         tstate = get_current_thread_state();
1015
1016         if (tstate == NULL) {
1017                 init_new_thread_state();
1018
1019                 tstate = get_current_thread_state();
1020                 AST(tstate != NULL);
1021         }
1022
1023         GET_MY_TSTATE(tstate_tm, tstate);
1024         if (tstate_tm == NULL) goto finish;
1025
1026         ftd_table = tstate_tm->ftd_table;
1027         if (ftd_table == NULL) goto finish;
1028
1029         for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1030                 if (ftd_table[i] != NULL) {
1031                         Apicall_Data *current = ftd_table[i];
1032
1033                         while (current != NULL) {
1034                                 current->call_count = 0;
1035                                 current->last_call_count = 0;
1036                                 current->elapsed_time.tv_sec = 0;
1037                                 current->elapsed_time.tv_usec = 0;
1038                                 current->last_elapsed_time.tv_sec = 0;
1039                                 current->last_elapsed_time.tv_usec = 0;
1040                                 current->last_total_elapsed_time.tv_sec = 0;
1041                                 current->last_total_elapsed_time.tv_usec = 0;
1042                                 current->total_elapsed_time.tv_sec = 0;
1043                                 current->total_elapsed_time.tv_usec = 0;
1044                                 current = (Apicall_Data *)current->trace_data.next;
1045                         }
1046                 }
1047         }
1048         AST(gettimeofday(&last_initial_time, NULL) == 0);
1049
1050 finish:
1051         return;
1052
1053 }
1054
1055 void
1056 tracepath_mem_trace_output(int force_output)
1057 {
1058         static struct timeval tv_last = TIMEVAL_INIT;
1059
1060         int i;
1061
1062         if (trace_mem_flag != 1) {
1063                 goto finish;
1064         }
1065
1066         if (!force_output) {
1067                 struct timeval tv_now = TIMEVAL_INIT;
1068                 AST(gettimeofday(&tv_now, NULL) == 0);
1069                 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC) {
1070                         goto finish;
1071                 }
1072                 tv_last = tv_now;
1073         }
1074
1075         TRACE("\n");
1076         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
1077         TRACE("\E[40;32;1m  Memory usage info \E[1;37;1m: <PID = %d>\E[0m\n", getpid());
1078         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
1079
1080         if (mtd_table != NULL) {
1081                 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1082                         if (mtd_table[i] != NULL) {
1083                                 Memuse_Data *current = mtd_table[i];
1084
1085                                 while (current != NULL) {
1086                                         int obj_count = current->alloc_count - current->remove_count;
1087                                         if (obj_count > 0) {
1088                                                 TRACE("\E[40;37;1m %-46.46s : %12d byte(s)(E), %9d object(s) [%9d+/%9d-]\E[0m\n",
1089                                                       current->trace_data.name, current->memsize, obj_count, current->alloc_count,
1090                                                       current->remove_count);
1091                                         }
1092                                         current = (Memuse_Data *)current->trace_data.next;
1093                                 }
1094                         }
1095                 }
1096
1097                 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1098                         if (mtd_table[i] != NULL) {
1099                                 Memuse_Data *current = mtd_table[i];
1100
1101                                 while (current != NULL) {
1102                                         int obj_count = current->alloc_count - current->remove_count;
1103                                         if (obj_count == 0) {
1104                                                 TRACE(" %-46.46s : %12d byte(s)(E), %9d object(s) [%9d+/%9d-]\n",
1105                                                       current->trace_data.name, current->memsize, obj_count, current->alloc_count,
1106                                                       current->remove_count);
1107                                         }
1108                                         current = (Memuse_Data *)current->trace_data.next;
1109                                 }
1110                         }
1111                 }
1112         }
1113
1114         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
1115         TRACE("\n");
1116
1117         TRACE_END();
1118
1119         goto finish;
1120
1121 finish:
1122         return;
1123 }
1124
1125 #include <png.h>
1126
1127 void *png_lib_handle = NULL;
1128
1129 png_structp (*dl_png_create_write_struct) (png_const_charp user_png_ver,
1130                 png_voidp error_ptr,
1131                 png_error_ptr error_fn,
1132                 png_error_ptr warn_fn);
1133
1134
1135 void (*dl_png_destroy_write_struct) (png_structpp png_ptr_ptr,
1136                                      png_infopp info_ptr_ptr);
1137
1138
1139 png_infop (*dl_png_create_info_struct) (png_structp png_ptr);
1140
1141 void (*dl_png_init_io) (png_structp png_ptr,
1142                         png_FILE_p fp);
1143
1144
1145 void (*dl_png_set_IHDR) (png_structp png_ptr,
1146                          png_infop info_ptr,
1147                          png_uint_32 width,
1148                          png_uint_32 height,
1149                          int bit_depth,
1150                          int color_type,
1151                          int interlace_method,
1152                          int compression_method,
1153                          int filter_method);
1154
1155 void (*dl_png_set_bKGD) (png_structp png_ptr,
1156                          png_infop info_ptr,
1157                          png_color_16p background);
1158
1159 void (*dl_png_set_bgr) (png_structp png_ptr);
1160
1161 void (*dl_png_write_info) (png_structp png_ptr,
1162                            png_infop info_ptr);
1163
1164 void (*dl_png_write_image) (png_structp png_ptr,
1165                             png_bytepp image);
1166
1167 void (*dl_png_write_end) (png_structp png_ptr,
1168                           png_infop info_ptr);
1169
1170 static void
1171 _dump_surface(int force_output, int type, const char *position,
1172               Surface_Data *sdata)
1173 {
1174         static int alldumpcount = 0;
1175         unsigned char *data = NULL;
1176         EGLint width = -1, height = -1, channel = -1;
1177         char name[200];
1178         FILE *write_fd = NULL;
1179         png_struct *png = NULL;
1180         png_info *info = NULL;
1181         png_byte **rows = NULL;
1182         GLenum ret_value = _COREGL_INT_INIT_VALUE;
1183
1184         if (!png_lib_handle) {
1185                 png_lib_handle = dlopen("libpng16.so.16", RTLD_NOW);
1186
1187                 dl_png_create_write_struct = dlsym(png_lib_handle, "png_create_write_struct");
1188                 dl_png_destroy_write_struct = dlsym(png_lib_handle, "png_destroy_write_struct");
1189                 dl_png_create_info_struct = dlsym(png_lib_handle, "png_create_info_struct");
1190
1191                 dl_png_init_io = dlsym(png_lib_handle, "png_init_io");
1192
1193                 dl_png_set_IHDR = dlsym(png_lib_handle, "png_set_IHDR");
1194                 dl_png_set_bKGD = dlsym(png_lib_handle, "png_set_bKGD");
1195                 dl_png_set_bgr = dlsym(png_lib_handle, "png_set_bgr");
1196
1197                 dl_png_write_info = dlsym(png_lib_handle, "png_write_info");
1198                 dl_png_write_image = dlsym(png_lib_handle, "png_write_image");
1199                 dl_png_write_end = dlsym(png_lib_handle, "png_write_end");
1200         }
1201
1202         {
1203                 if (!png_lib_handle ||
1204                     dl_png_create_write_struct == NULL ||
1205                     dl_png_destroy_write_struct == NULL ||
1206                     dl_png_create_info_struct == NULL ||
1207                     dl_png_init_io == NULL ||
1208                     dl_png_set_IHDR == NULL ||
1209                     dl_png_set_bKGD == NULL ||
1210                     dl_png_set_bgr == NULL ||
1211                     dl_png_write_info == NULL ||
1212                     dl_png_write_image == NULL ||
1213                     dl_png_write_end == NULL) {
1214                         COREGL_ERR("Can't trace surface : Failed to use libpng (recommend : 1.2.50-3.4)");
1215                         goto finish;
1216                 }
1217
1218                 if (trace_surface_sequence_sort_flag == 1)
1219                         sprintf(name, "[%d (%06d)%p-%p] %s %04d (%s).png", getpid(), alldumpcount,
1220                                 sdata->display, sdata->context, sdata->trace_data.name, sdata->dump_count,
1221                                 position);
1222                 else
1223                         sprintf(name, "[%d %p-%p] %s %04d (%s).png", getpid(), sdata->display,
1224                                 sdata->context, sdata->trace_data.name, sdata->dump_count, position);
1225
1226                 if (!strncmp(sdata->trace_data.name, "EGL", 3) && type != 2) {
1227                         // EGL
1228                         if (trace_surface_filter_type != 0 &&
1229                             trace_surface_filter_type != 1) goto finish;;
1230
1231                         if (trace_surface_filter_handle != 0 &&
1232                             trace_surface_filter_handle != (int)sdata->surface) goto finish;
1233
1234                         EGLConfig eglconfig;
1235                         GLint asize, rsize, gsize, bsize;
1236                         _orig_tracepath_eglQuerySurface(sdata->display, sdata->surface, EGL_WIDTH,
1237                                                         &width);
1238                         _orig_tracepath_eglQuerySurface(sdata->display, sdata->surface, EGL_HEIGHT,
1239                                                         &height);
1240                         _orig_tracepath_eglQuerySurface(sdata->display, sdata->surface, EGL_CONFIG_ID,
1241                                                         (GLint *)&eglconfig);
1242                         _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_ALPHA_SIZE,
1243                                                            &asize);
1244                         _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_RED_SIZE,
1245                                                            &rsize);
1246                         _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_GREEN_SIZE,
1247                                                            &gsize);
1248                         _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_BLUE_SIZE,
1249                                                            &bsize);
1250                         channel = 4;
1251                         if (asize == 0) channel = 3;
1252                         if (bsize == 0) channel = 2;
1253                         if (gsize == 0) channel = 1;
1254                         if (rsize == 0) channel = 0;
1255
1256                         if (channel == 2) channel = 3;
1257                         if (width <= 0 || height <= 0 || channel <= 0) goto finish;
1258                         if (trace_surface_filter_size_w > 0 && trace_surface_filter_size_h > 0 &&
1259                             (trace_surface_filter_size_w != width || trace_surface_filter_size_h != height))
1260                                 goto finish;
1261
1262                         if ((trace_surface_filter_period_begin > 0 ||
1263                              trace_surface_filter_period_end > 0) &&
1264                             (trace_surface_filter_period_begin > alldumpcount ||
1265                              trace_surface_filter_period_end < alldumpcount)) {
1266                                 alldumpcount++;
1267                                 sdata->dump_count++;
1268                                 goto finish;
1269                         }
1270
1271                         if (channel == 3) channel = 4;
1272
1273                         TRACE("\E[40;31;1m[[TRACE SURFACE]] : '%s' is dumped (%dx%dx%d).\E[0m\n", name,
1274                               width, height, channel);
1275                         if (trace_surface_print_only_flag == 1 && force_output == 0) {
1276                                 alldumpcount++;
1277                                 sdata->dump_count++;
1278                                 goto finish;
1279                         }
1280
1281                         data = (unsigned char *)calloc(1,
1282                                                        width * height * channel * sizeof(unsigned char));
1283                         if (data == NULL) {
1284                                 COREGL_ERR("Can't trace surface : Failed to allocate memory");
1285                                 goto finish;
1286                         }
1287
1288                         GLint oldfb;
1289                         _orig_tracepath_glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldfb);
1290                         _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, 0);
1291
1292                         switch (channel) {
1293                         case 4:
1294                                 _orig_tracepath_glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
1295                                                              data);
1296                                 break;
1297                                 //case 3: _orig_tracepath_glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data); break;
1298                         case 1:
1299                                 _orig_tracepath_glReadPixels(0, 0, width, height, GL_ALPHA, GL_UNSIGNED_BYTE,
1300                                                              data);
1301                                 break;
1302                         }
1303
1304                         _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, oldfb);
1305                 }
1306                 if (!strncmp(sdata->trace_data.name, "FBO", 3) && type != 1) {
1307                         // FBO
1308                         if (sdata->fbo == 0) goto finish;
1309
1310                         if (trace_surface_filter_type != 0 &&
1311                             trace_surface_filter_type != 2) goto finish;
1312
1313                         if (trace_surface_filter_handle != 0 &&
1314                             trace_surface_filter_handle != sdata->tex &&
1315                             trace_surface_filter_handle != sdata->rb) goto finish;
1316
1317                         GLint oldfb;
1318                         _orig_tracepath_glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldfb);
1319                         _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, sdata->fbo);
1320
1321                         if (driver_gl_version >= 2)
1322                                 ret_value = _orig_tracepath_glCheckFramebufferStatus(GL_FRAMEBUFFER);
1323                         else
1324                                 ret_value = _orig_tracepath_glCheckFramebufferStatusOES(GL_FRAMEBUFFER);
1325                         if (ret_value == GL_FRAMEBUFFER_COMPLETE) {
1326                                 _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, oldfb);
1327                                 width = sdata->tex_w;
1328                                 height = sdata->tex_h;
1329                                 channel = sdata->tex_format;
1330
1331                                 if (channel == 2) channel = 3;
1332                                 if (width <= 0 || height <= 0 || channel <= 0) goto finish;
1333                                 if (trace_surface_filter_size_w > 0 && trace_surface_filter_size_h > 0 &&
1334                                     (trace_surface_filter_size_w != width || trace_surface_filter_size_h != height))
1335                                         goto finish;
1336
1337                                 if ((trace_surface_filter_period_begin > 0 ||
1338                                      trace_surface_filter_period_end > 0) &&
1339                                     (trace_surface_filter_period_begin > alldumpcount ||
1340                                      trace_surface_filter_period_end < alldumpcount)) {
1341                                         alldumpcount++;
1342                                         sdata->dump_count++;
1343                                         goto finish;
1344                                 }
1345
1346                                 TRACE("\E[40;31;1m[[TRACE SURFACE]] : '%s' is dumped (%dx%dx%d).\E[0m\n", name,
1347                                       width, height, channel);
1348                                 if (trace_surface_print_only_flag == 1 && force_output == 0) {
1349                                         alldumpcount++;
1350                                         sdata->dump_count++;
1351                                         goto finish;
1352                                 }
1353
1354                                 if (channel == 3) channel = 4;
1355
1356                                 data = (unsigned char *)calloc(1,
1357                                                                width * height * channel * sizeof(unsigned char));
1358                                 if (data == NULL) {
1359                                         COREGL_ERR("Can't trace surface : Failed to allocate memory");
1360                                         goto finish;
1361                                 }
1362
1363                                 _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, sdata->fbo);
1364                                 int atttype = _COREGL_INT_INIT_VALUE;
1365                                 if (driver_gl_version >= 2)
1366                                         _orig_tracepath_glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
1367                                                         GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &atttype);
1368                                 else
1369                                         _orig_tracepath_glGetFramebufferAttachmentParameterivOES(GL_FRAMEBUFFER,
1370                                                         GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &atttype);
1371                                 AST(atttype != sdata->tex);
1372                                 int attname = _COREGL_INT_INIT_VALUE;
1373                                 if (driver_gl_version >= 2)
1374                                         _orig_tracepath_glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
1375                                                         GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attname);
1376                                 else
1377                                         _orig_tracepath_glGetFramebufferAttachmentParameterivOES(GL_FRAMEBUFFER,
1378                                                         GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attname);
1379                                 switch (atttype) {
1380                                 case GL_TEXTURE:
1381                                         AST(attname == sdata->tex);
1382                                         break;
1383                                 case GL_RENDERBUFFER:
1384                                         AST(attname == sdata->rb);
1385                                         break;
1386                                 }
1387
1388                                 switch (channel) {
1389                                 case 4:
1390                                         _orig_tracepath_glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
1391                                                                      data);
1392                                         break;
1393                                         //case 3: _orig_tracepath_glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data); break;
1394                                 case 1:
1395                                         _orig_tracepath_glReadPixels(0, 0, width, height, GL_ALPHA, GL_UNSIGNED_BYTE,
1396                                                                      data);
1397                                         break;
1398                                 }
1399                         }
1400                         _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, oldfb);
1401                 }
1402
1403
1404
1405                 if (data == NULL) goto finish;
1406
1407                 unlink(name);
1408                 write_fd = fopen(name, "wb");
1409
1410                 if (write_fd == NULL) {
1411                         COREGL_ERR("Can't trace surface : Failed to create png file");
1412                         goto finish;
1413                 }
1414
1415                 rows = (png_byte **)malloc(height * sizeof(png_byte *));
1416                 if (rows == NULL) {
1417                         COREGL_ERR("Can't trace surface : Failed to allocate memory");
1418                         goto finish;
1419                 }
1420
1421                 for (int i = 0; i < height; i++) {
1422                         rows[i] = data + (height - i - 1) * (width * channel);
1423                 }
1424
1425                 png = dl_png_create_write_struct(PNG_LIBPNG_VER_STRING,
1426                                                  NULL,
1427                                                  NULL,
1428                                                  NULL);
1429                 if (png == NULL) {
1430                         COREGL_ERR("Can't trace surface : Failed to create write structure of png file");
1431                         goto finish;
1432                 }
1433
1434                 info = dl_png_create_info_struct(png);
1435                 if (info == NULL) {
1436                         COREGL_ERR("Can't trace surface : Failed to create info structure of png file");
1437                         goto finish;
1438                 }
1439
1440                 dl_png_init_io(png, write_fd);
1441
1442                 switch (channel) {
1443                 case 4:
1444                         dl_png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
1445                                         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1446                         break;
1447                         //case 3: dl_png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); break;
1448                 case 1:
1449                         dl_png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_GRAY,
1450                                         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1451                         break;
1452                 }
1453
1454                 dl_png_write_info(png, info);
1455
1456                 dl_png_write_image(png, rows);
1457
1458                 dl_png_write_end(png, info);
1459
1460                 dl_png_destroy_write_struct(&png, &info);
1461
1462                 alldumpcount++;
1463                 sdata->dump_count++;
1464         }
1465
1466         goto finish;
1467
1468 finish:
1469         if (data != NULL) {
1470                 free(data);
1471                 data = NULL;
1472         }
1473         if (write_fd != NULL) {
1474                 fclose(write_fd);
1475                 write_fd = NULL;
1476         }
1477         if (rows != NULL) {
1478                 free(rows);
1479                 rows = NULL;
1480         }
1481         if (png != NULL) {
1482                 if (info != NULL) {
1483                         dl_png_destroy_write_struct(&png, &info);
1484                         info = NULL;
1485                 } else
1486                         dl_png_destroy_write_struct(&png, NULL);
1487                 png = NULL;
1488         }
1489 }
1490
1491 void
1492 tracepath_surface_trace_add(const char *desc, GLDisplay dpy, GLContext ctx,
1493                             GLSurface surf, GLint fbo, GLint tex, GLint rb, GLint tex_w, GLint tex_h,
1494                             GLint tex_format, const char *dump)
1495 {
1496         Surface_Data *std = NULL;
1497
1498         if (trace_surface_flag == 1) {
1499                 AST(mutex_lock(&std_access_mutex) == 1);
1500
1501                 if (std_table == NULL) {
1502                         std_table = (Surface_Data **)calloc(1,
1503                                                             sizeof(Surface_Data *) * MAX_TRACE_TABLE_SIZE);
1504                 }
1505
1506                 std = (Surface_Data *)_get_trace_data((Trace_Data **)std_table,
1507                                                       sizeof(Surface_Data), desc);
1508
1509                 AST(std != NULL);
1510
1511                 if (dump != NULL) {
1512                         _dump_surface(0, 0, dump, std);
1513                 }
1514
1515                 std->display = dpy;
1516                 std->surface = surf;
1517                 std->context = ctx;
1518                 if (fbo >= 0) std->fbo = fbo;
1519                 std->tex = tex;
1520                 std->rb = rb;
1521                 if (tex_w >= 0) std->tex_w = tex_w;
1522                 if (tex_h >= 0) std->tex_h = tex_h;
1523                 if (tex_format >= 0) std->tex_format = tex_format;
1524
1525                 AST(mutex_unlock(&std_access_mutex) == 1);
1526
1527         }
1528
1529 }
1530
1531 void
1532 tracepath_surface_trace(int force_output, int type, const char *position)
1533 {
1534         int i;
1535
1536         if (trace_surface_flag != 1) {
1537                 goto finish;
1538         }
1539
1540         AST(mutex_lock(&std_access_mutex) == 1);
1541
1542         if (std_table != NULL) {
1543                 EGLDisplay olddpy = _orig_tracepath_eglGetCurrentDisplay();
1544                 EGLContext oldctx = _orig_tracepath_eglGetCurrentContext();
1545                 EGLSurface oldsurf_read = _orig_tracepath_eglGetCurrentSurface(EGL_READ);
1546                 EGLSurface oldsurf_draw = _orig_tracepath_eglGetCurrentSurface(EGL_DRAW);
1547
1548                 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1549                         if (std_table[i] != NULL) {
1550                                 Surface_Data *current = std_table[i];
1551
1552                                 while (current != NULL) {
1553                                         if (current->surface != EGL_NO_SURFACE && current->display != EGL_NO_DISPLAY &&
1554                                             current->context != EGL_NO_CONTEXT) {
1555                                                 if (_orig_tracepath_eglMakeCurrent(current->display, current->surface,
1556                                                                                    current->surface, current->context) == EGL_TRUE) {
1557                                                         _dump_surface(force_output, type, position, current);
1558                                                 }
1559                                         }
1560
1561                                         current = (Surface_Data *)current->trace_data.next;
1562                                 }
1563                         }
1564                 }
1565                 _orig_tracepath_eglMakeCurrent(olddpy, oldsurf_read, oldsurf_draw, oldctx);
1566
1567         }
1568
1569         AST(mutex_unlock(&std_access_mutex) == 1);
1570
1571         goto finish;
1572
1573 finish:
1574         return;
1575 }
1576
1577
1578 COREGL_API void
1579 coregl_dump_surface()
1580 {
1581         _COREGL_TRACE_SURFACE(1, 0, "USER CALL");
1582 }
1583