Replace vulnerable function 'sprintf' to 'snprintf'
[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                 strncpy(newitm->name, name, strlen(newitm->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
701                         if (tstate) {
702                                 if (tstate->ftd_table == NULL) {
703                                         tstate->ftd_table = (Apicall_Data **)calloc(1,
704                                                             sizeof(Apicall_Data *) * MAX_TRACE_TABLE_SIZE);
705                                 }
706
707                                 ftd = (Apicall_Data *)_get_trace_data((Trace_Data **)tstate->ftd_table,
708                                                                       sizeof(Apicall_Data), funcname);
709                         }
710                 }
711
712                 AST(ftd != NULL);
713
714                 ftd->call_count++;
715                 AST(ftd->last_time.tv_sec == 0);
716
717                 AST(gettimeofday(&ftd->last_time, NULL) == 0);
718
719                 if (initial_time.tv_sec == 0) {
720                         initial_time = ftd->last_time;
721                         last_initial_time = ftd->last_time;
722                 }
723
724                 if (trace_total_time == 1) {
725                         if (last_trace_time.tv_sec != 0) {
726                                 _add_timeval_period(&other_elapsed_time, t, last_trace_time);
727                                 last_trace_time.tv_sec = 0;
728                         }
729                 }
730
731         }
732
733         return ftd;
734 }
735
736 void *
737 tracepath_api_trace_end(const char *funcname, void *hint, int trace_total_time)
738 {
739         Apicall_Data *ftd = NULL;
740         struct timeval t = TIMEVAL_INIT;
741
742         if (trace_api_flag == 1) {
743                 MY_MODULE_TSTATE *tstate = NULL;
744                 struct timeval elapsed_time = TIMEVAL_INIT;
745
746                 AST(gettimeofday(&t, NULL) == 0);
747
748                 ftd = (Apicall_Data *)hint;
749
750                 if (ftd == NULL) {
751                         GET_MY_TSTATE(tstate, get_current_thread_state());
752
753                         if (tstate == NULL) {
754                                 init_new_thread_state();
755
756                                 GET_MY_TSTATE(tstate, get_current_thread_state());
757                                 AST(tstate != NULL);
758                         }
759
760                         AST(tstate != NULL);
761                         AST(tstate && (tstate->ftd_table != NULL));
762
763                         if (tstate && (tstate->ftd_table)) {
764                                 ftd = (Apicall_Data *)_get_trace_data((Trace_Data **)tstate->ftd_table,
765                                                                       sizeof(Apicall_Data), funcname);
766                         }
767                 }
768
769                 AST(ftd != NULL);
770
771                 _add_timeval_period(&elapsed_time, t, ftd->last_time);
772
773                 _add_timeval(&ftd->elapsed_time, elapsed_time);
774
775                 if (elapsed_time.tv_sec >= ftd->elapsed_time_max.tv_sec &&
776                     elapsed_time.tv_usec > ftd->elapsed_time_max.tv_usec) {
777                         ftd->elapsed_time_max.tv_sec = elapsed_time.tv_sec;
778                         ftd->elapsed_time_max.tv_usec = elapsed_time.tv_usec;
779                 }
780
781                 ftd->last_time.tv_sec = 0;
782
783                 if (trace_total_time == 1) {
784                         _add_timeval(&ftd->total_elapsed_time, elapsed_time);
785
786                         AST(gettimeofday(&last_trace_time, NULL) == 0);
787
788                         if (initial_time.tv_sec == 0) {
789                                 initial_time = t;
790                                 last_initial_time = t;
791                         }
792                 }
793
794         }
795
796
797         return ftd;
798 }
799
800 void
801 tracepath_api_trace_output(int force_output)
802 {
803         static struct timeval tv_last = TIMEVAL_INIT;
804         struct timeval total_now = TIMEVAL_INIT;
805         GLThreadState *tstate = NULL;
806         MY_MODULE_TSTATE *tstate_tm = NULL;
807         Apicall_Data **ftd_table = NULL;
808
809         double total_elapsed_time = 0.0;
810         double total_elapsed_time_period = 0.0;
811         double total_opengl_elapsed_time = 0.0;
812         double total_opengl_elapsed_time_period = 0.0;
813         double total_other_elapsed_time = 0.0;
814         double total_other_elapsed_time_period = 0.0;
815
816         double swaps_per_sec = 0.0;
817
818         int i;
819
820         if (trace_api_flag != 1) {
821                 goto finish;
822         }
823
824         if (!force_output) {
825                 struct timeval tv_now = TIMEVAL_INIT;
826                 AST(gettimeofday(&tv_now, NULL) == 0);
827                 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC) {
828                         goto finish;
829                 }
830                 tv_last = tv_now;
831         }
832
833         AST(gettimeofday(&total_now, NULL) == 0);
834
835         total_elapsed_time = _get_timeval_period(total_now, initial_time);
836         total_elapsed_time_period = _get_timeval_period(total_now, last_initial_time);
837         last_initial_time = total_now;
838
839         total_other_elapsed_time = _get_timeval(other_elapsed_time);
840         total_other_elapsed_time_period = _get_timeval_period(other_elapsed_time,
841                                           traced_other_elapsed_time);
842         traced_other_elapsed_time = other_elapsed_time;
843
844         tstate = get_current_thread_state();
845
846         if (tstate == NULL) {
847                 init_new_thread_state();
848
849                 tstate = get_current_thread_state();
850                 AST(tstate != NULL);
851         }
852
853         GET_MY_TSTATE(tstate_tm, tstate);
854         if (tstate_tm == NULL) goto finish;
855
856         ftd_table = tstate_tm->ftd_table;
857         if (ftd_table == NULL) goto finish;
858
859         {
860                 static Apicall_Data *trace_hint_swap = NULL;
861                 if (trace_hint_swap == NULL)
862                         trace_hint_swap = (Apicall_Data *)_get_trace_data((Trace_Data **)ftd_table,
863                                           sizeof(Apicall_Data), "tracepath_eglSwapBuffers");
864
865                 if (trace_hint_swap != NULL && total_elapsed_time_period > 0) {
866                         swaps_per_sec = (trace_hint_swap->call_count -
867                                          trace_hint_swap->last_call_count) / (total_elapsed_time_period / 1000);
868                 }
869         }
870
871
872         TRACE("\n");
873         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
874         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",
875               getpid(), tstate->thread_id, swaps_per_sec);
876         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
877
878         // highlighted
879         for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
880                 if (ftd_table[i] != NULL) {
881                         Apicall_Data *current = ftd_table[i];
882
883                         while (current != NULL) {
884                                 double elapsed_time = _get_timeval(current->elapsed_time);
885                                 double elapsed_time_per_call = elapsed_time / current->call_count;
886
887                                 total_opengl_elapsed_time += _get_timeval(current->total_elapsed_time);
888                                 total_opengl_elapsed_time_period += _get_timeval(current->total_elapsed_time) -
889                                                                     _get_timeval(current->last_total_elapsed_time);
890
891                                 current->traced = 0;
892
893                                 if (current->call_count > current->last_call_count) {
894                                         double elapsed_time_period = _get_timeval_period(current->elapsed_time,
895                                                                      current->last_elapsed_time);
896                                         double elapsed_time_max = _get_timeval(current->elapsed_time_max);
897                                         double elapsed_time_per_call_period = elapsed_time_period /
898                                                                               (current->call_count - current->last_call_count);
899                                         char *fname = current->trace_data.name;
900
901                                         if (!strncmp(fname, "tracepath_", 10))
902                                                 fname = &current->trace_data.name[10];
903
904                                         if (elapsed_time_per_call_period >= 0.01 ||
905                                             current->call_count - current->last_call_count > 1000) {
906                                                 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",
907                                                       fname, current->call_count, elapsed_time_per_call, elapsed_time_max,
908                                                       elapsed_time_per_call_period);
909                                                 current->traced = 1;
910                                         }
911                                 }
912                                 current = (Apicall_Data *)current->trace_data.next;
913                         }
914                 }
915         }
916
917         {
918                 int fp_env = 0;
919                 fp_env = atoi(get_env_setting("COREGL_TRACE_API_ALL"));
920                 if (fp_env == 1) {
921                         // other
922                         for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
923                                 if (ftd_table[i] != NULL) {
924                                         Apicall_Data *current = ftd_table[i];
925
926                                         while (current != NULL) {
927                                                 if (current->traced == 0 && current->call_count > 0) {
928                                                         double elapsed_time = _get_timeval(current->elapsed_time);
929                                                         double elapsed_time_per_call = elapsed_time / current->call_count;
930                                                         double elapsed_time_max = _get_timeval(current->elapsed_time_max);
931                                                         char *fname = current->trace_data.name;
932
933                                                         if (!strncmp(fname, "tracepath_", 10))
934                                                                 fname = &current->trace_data.name[10];
935
936                                                         TRACE(" %-39.39s : %10d call(s), %9.3f ms/API, %9.2f ms(MAX)\n",
937                                                               fname, current->call_count, elapsed_time_per_call, elapsed_time_max);
938                                                 }
939                                                 current = (Apicall_Data *)current->trace_data.next;
940                                         }
941                                 }
942                         }
943                 }
944         }
945
946         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
947
948         if (trace_api_frame_flag == 0) {
949                 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
950                       "TOTAL elapsed Time",
951                       total_elapsed_time,
952                       100.0,
953                       total_elapsed_time_period,
954                       100.0);
955
956
957                 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
958                       "OpenGL elapsed Time",
959                       total_opengl_elapsed_time,
960                       total_opengl_elapsed_time * 100.0 / total_elapsed_time,
961                       total_opengl_elapsed_time_period,
962                       total_opengl_elapsed_time_period * 100.0 / total_elapsed_time_period);
963
964                 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
965                       "Out of OpenGL elapsed time",
966                       total_other_elapsed_time,
967                       total_other_elapsed_time * 100.0 / total_elapsed_time,
968                       total_other_elapsed_time_period,
969                       total_other_elapsed_time_period * 100.0 / total_elapsed_time_period);
970
971                 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
972                       "CoreGL API tracing overhead",
973                       total_elapsed_time - total_opengl_elapsed_time - total_other_elapsed_time,
974                       (total_elapsed_time - total_opengl_elapsed_time - total_other_elapsed_time) *
975                       100.0 / total_elapsed_time,
976                       total_elapsed_time_period - total_opengl_elapsed_time_period -
977                       total_other_elapsed_time_period,
978                       (total_elapsed_time_period - total_opengl_elapsed_time_period -
979                        total_other_elapsed_time_period) * 100.0 / total_elapsed_time_period);
980
981                 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
982         }
983         TRACE("\n");
984
985         for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
986                 if (ftd_table[i] != NULL) {
987                         Apicall_Data *current = ftd_table[i];
988
989                         while (current != NULL) {
990                                 current->last_call_count = current->call_count;
991                                 current->last_elapsed_time = current->elapsed_time;
992                                 current->last_total_elapsed_time = current->total_elapsed_time;
993                                 current = (Apicall_Data *)current->trace_data.next;
994                         }
995                 }
996         }
997
998         TRACE_END();
999
1000         goto finish;
1001
1002 finish:
1003         return;
1004 }
1005
1006 void
1007 tracepath_api_trace_reset_frame()
1008 {
1009         GLThreadState *tstate = NULL;
1010         MY_MODULE_TSTATE *tstate_tm = NULL;
1011         Apicall_Data **ftd_table = NULL;
1012
1013         int i;
1014
1015         if (trace_api_flag != 1) {
1016                 goto finish;
1017         }
1018
1019         tstate = get_current_thread_state();
1020
1021         if (tstate == NULL) {
1022                 init_new_thread_state();
1023
1024                 tstate = get_current_thread_state();
1025                 AST(tstate != NULL);
1026         }
1027
1028         GET_MY_TSTATE(tstate_tm, tstate);
1029         if (tstate_tm == NULL) goto finish;
1030
1031         ftd_table = tstate_tm->ftd_table;
1032         if (ftd_table == NULL) goto finish;
1033
1034         for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1035                 if (ftd_table[i] != NULL) {
1036                         Apicall_Data *current = ftd_table[i];
1037
1038                         while (current != NULL) {
1039                                 current->call_count = 0;
1040                                 current->last_call_count = 0;
1041                                 current->elapsed_time.tv_sec = 0;
1042                                 current->elapsed_time.tv_usec = 0;
1043                                 current->last_elapsed_time.tv_sec = 0;
1044                                 current->last_elapsed_time.tv_usec = 0;
1045                                 current->last_total_elapsed_time.tv_sec = 0;
1046                                 current->last_total_elapsed_time.tv_usec = 0;
1047                                 current->total_elapsed_time.tv_sec = 0;
1048                                 current->total_elapsed_time.tv_usec = 0;
1049                                 current = (Apicall_Data *)current->trace_data.next;
1050                         }
1051                 }
1052         }
1053         AST(gettimeofday(&last_initial_time, NULL) == 0);
1054
1055 finish:
1056         return;
1057
1058 }
1059
1060 void
1061 tracepath_mem_trace_output(int force_output)
1062 {
1063         static struct timeval tv_last = TIMEVAL_INIT;
1064
1065         int i;
1066
1067         if (trace_mem_flag != 1) {
1068                 goto finish;
1069         }
1070
1071         if (!force_output) {
1072                 struct timeval tv_now = TIMEVAL_INIT;
1073                 AST(gettimeofday(&tv_now, NULL) == 0);
1074                 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC) {
1075                         goto finish;
1076                 }
1077                 tv_last = tv_now;
1078         }
1079
1080         TRACE("\n");
1081         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
1082         TRACE("\E[40;32;1m  Memory usage info \E[1;37;1m: <PID = %d>\E[0m\n", getpid());
1083         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
1084
1085         if (mtd_table != NULL) {
1086                 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1087                         if (mtd_table[i] != NULL) {
1088                                 Memuse_Data *current = mtd_table[i];
1089
1090                                 while (current != NULL) {
1091                                         int obj_count = current->alloc_count - current->remove_count;
1092                                         if (obj_count > 0) {
1093                                                 TRACE("\E[40;37;1m %-46.46s : %12d byte(s)(E), %9d object(s) [%9d+/%9d-]\E[0m\n",
1094                                                       current->trace_data.name, current->memsize, obj_count, current->alloc_count,
1095                                                       current->remove_count);
1096                                         }
1097                                         current = (Memuse_Data *)current->trace_data.next;
1098                                 }
1099                         }
1100                 }
1101
1102                 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1103                         if (mtd_table[i] != NULL) {
1104                                 Memuse_Data *current = mtd_table[i];
1105
1106                                 while (current != NULL) {
1107                                         int obj_count = current->alloc_count - current->remove_count;
1108                                         if (obj_count == 0) {
1109                                                 TRACE(" %-46.46s : %12d byte(s)(E), %9d object(s) [%9d+/%9d-]\n",
1110                                                       current->trace_data.name, current->memsize, obj_count, current->alloc_count,
1111                                                       current->remove_count);
1112                                         }
1113                                         current = (Memuse_Data *)current->trace_data.next;
1114                                 }
1115                         }
1116                 }
1117         }
1118
1119         TRACE("\E[40;34m========================================================================================================================\E[0m\n");
1120         TRACE("\n");
1121
1122         TRACE_END();
1123
1124         goto finish;
1125
1126 finish:
1127         return;
1128 }
1129
1130 #include <png.h>
1131
1132 void *png_lib_handle = NULL;
1133
1134 png_structp (*dl_png_create_write_struct) (png_const_charp user_png_ver,
1135                 png_voidp error_ptr,
1136                 png_error_ptr error_fn,
1137                 png_error_ptr warn_fn);
1138
1139
1140 void (*dl_png_destroy_write_struct) (png_structpp png_ptr_ptr,
1141                                      png_infopp info_ptr_ptr);
1142
1143
1144 png_infop (*dl_png_create_info_struct) (png_structp png_ptr);
1145
1146 void (*dl_png_init_io) (png_structp png_ptr,
1147                         png_FILE_p fp);
1148
1149
1150 void (*dl_png_set_IHDR) (png_structp png_ptr,
1151                          png_infop info_ptr,
1152                          png_uint_32 width,
1153                          png_uint_32 height,
1154                          int bit_depth,
1155                          int color_type,
1156                          int interlace_method,
1157                          int compression_method,
1158                          int filter_method);
1159
1160 void (*dl_png_set_bKGD) (png_structp png_ptr,
1161                          png_infop info_ptr,
1162                          png_color_16p background);
1163
1164 void (*dl_png_set_bgr) (png_structp png_ptr);
1165
1166 void (*dl_png_write_info) (png_structp png_ptr,
1167                            png_infop info_ptr);
1168
1169 void (*dl_png_write_image) (png_structp png_ptr,
1170                             png_bytepp image);
1171
1172 void (*dl_png_write_end) (png_structp png_ptr,
1173                           png_infop info_ptr);
1174
1175 static void
1176 _dump_surface(int force_output, int type, const char *position,
1177               Surface_Data *sdata)
1178 {
1179         static int alldumpcount = 0;
1180         unsigned char *data = NULL;
1181         EGLint width = -1, height = -1, channel = -1;
1182         char name[200];
1183         FILE *write_fd = NULL;
1184         png_struct *png = NULL;
1185         png_info *info = NULL;
1186         png_byte **rows = NULL;
1187         GLenum ret_value = _COREGL_INT_INIT_VALUE;
1188
1189         if (!png_lib_handle) {
1190                 png_lib_handle = dlopen("libpng16.so.16", RTLD_NOW);
1191
1192                 dl_png_create_write_struct = dlsym(png_lib_handle, "png_create_write_struct");
1193                 dl_png_destroy_write_struct = dlsym(png_lib_handle, "png_destroy_write_struct");
1194                 dl_png_create_info_struct = dlsym(png_lib_handle, "png_create_info_struct");
1195
1196                 dl_png_init_io = dlsym(png_lib_handle, "png_init_io");
1197
1198                 dl_png_set_IHDR = dlsym(png_lib_handle, "png_set_IHDR");
1199                 dl_png_set_bKGD = dlsym(png_lib_handle, "png_set_bKGD");
1200                 dl_png_set_bgr = dlsym(png_lib_handle, "png_set_bgr");
1201
1202                 dl_png_write_info = dlsym(png_lib_handle, "png_write_info");
1203                 dl_png_write_image = dlsym(png_lib_handle, "png_write_image");
1204                 dl_png_write_end = dlsym(png_lib_handle, "png_write_end");
1205         }
1206
1207         {
1208                 if (!png_lib_handle ||
1209                     dl_png_create_write_struct == NULL ||
1210                     dl_png_destroy_write_struct == NULL ||
1211                     dl_png_create_info_struct == NULL ||
1212                     dl_png_init_io == NULL ||
1213                     dl_png_set_IHDR == NULL ||
1214                     dl_png_set_bKGD == NULL ||
1215                     dl_png_set_bgr == NULL ||
1216                     dl_png_write_info == NULL ||
1217                     dl_png_write_image == NULL ||
1218                     dl_png_write_end == NULL) {
1219                         COREGL_ERR("Can't trace surface : Failed to use libpng (recommend : 1.2.50-3.4)");
1220                         goto finish;
1221                 }
1222
1223                 if (trace_surface_sequence_sort_flag == 1)
1224                         snprintf(name, sizeof(name), "[%d (%06d)%p-%p] %s %04d (%s).png", getpid(),
1225                                  alldumpcount,
1226                                  sdata->display, sdata->context, sdata->trace_data.name, sdata->dump_count,
1227                                  position);
1228                 else
1229                         snprintf(name, sizeof(name), "[%d %p-%p] %s %04d (%s).png", getpid(),
1230                                  sdata->display,
1231                                  sdata->context, sdata->trace_data.name, sdata->dump_count, position);
1232
1233                 if (!strncmp(sdata->trace_data.name, "EGL", 3) && type != 2) {
1234                         // EGL
1235                         if (trace_surface_filter_type != 0 &&
1236                             trace_surface_filter_type != 1) goto finish;;
1237
1238                         if (trace_surface_filter_handle != 0 &&
1239                             trace_surface_filter_handle != (int)sdata->surface) goto finish;
1240
1241                         EGLConfig eglconfig;
1242                         GLint asize, rsize, gsize, bsize;
1243                         _orig_tracepath_eglQuerySurface(sdata->display, sdata->surface, EGL_WIDTH,
1244                                                         &width);
1245                         _orig_tracepath_eglQuerySurface(sdata->display, sdata->surface, EGL_HEIGHT,
1246                                                         &height);
1247                         _orig_tracepath_eglQuerySurface(sdata->display, sdata->surface, EGL_CONFIG_ID,
1248                                                         (GLint *)&eglconfig);
1249                         _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_ALPHA_SIZE,
1250                                                            &asize);
1251                         _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_RED_SIZE,
1252                                                            &rsize);
1253                         _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_GREEN_SIZE,
1254                                                            &gsize);
1255                         _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_BLUE_SIZE,
1256                                                            &bsize);
1257                         channel = 4;
1258                         if (asize == 0) channel = 3;
1259                         if (bsize == 0) channel = 2;
1260                         if (gsize == 0) channel = 1;
1261                         if (rsize == 0) channel = 0;
1262
1263                         if (channel == 2) channel = 3;
1264                         if (width <= 0 || height <= 0 || channel <= 0) goto finish;
1265                         if (trace_surface_filter_size_w > 0 && trace_surface_filter_size_h > 0 &&
1266                             (trace_surface_filter_size_w != width || trace_surface_filter_size_h != height))
1267                                 goto finish;
1268
1269                         if ((trace_surface_filter_period_begin > 0 ||
1270                              trace_surface_filter_period_end > 0) &&
1271                             (trace_surface_filter_period_begin > alldumpcount ||
1272                              trace_surface_filter_period_end < alldumpcount)) {
1273                                 alldumpcount++;
1274                                 sdata->dump_count++;
1275                                 goto finish;
1276                         }
1277
1278                         if (channel == 3) channel = 4;
1279
1280                         TRACE("\E[40;31;1m[[TRACE SURFACE]] : '%s' is dumped (%dx%dx%d).\E[0m\n", name,
1281                               width, height, channel);
1282                         if (trace_surface_print_only_flag == 1 && force_output == 0) {
1283                                 alldumpcount++;
1284                                 sdata->dump_count++;
1285                                 goto finish;
1286                         }
1287
1288                         data = (unsigned char *)calloc(1,
1289                                                        width * height * channel * sizeof(unsigned char));
1290                         if (data == NULL) {
1291                                 COREGL_ERR("Can't trace surface : Failed to allocate memory");
1292                                 goto finish;
1293                         }
1294
1295                         GLint oldfb;
1296                         _orig_tracepath_glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldfb);
1297                         _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, 0);
1298
1299                         switch (channel) {
1300                         case 4:
1301                                 _orig_tracepath_glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
1302                                                              data);
1303                                 break;
1304                                 //case 3: _orig_tracepath_glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data); break;
1305                         case 1:
1306                                 _orig_tracepath_glReadPixels(0, 0, width, height, GL_ALPHA, GL_UNSIGNED_BYTE,
1307                                                              data);
1308                                 break;
1309                         }
1310
1311                         _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, oldfb);
1312                 }
1313                 if (!strncmp(sdata->trace_data.name, "FBO", 3) && type != 1) {
1314                         // FBO
1315                         if (sdata->fbo == 0) goto finish;
1316
1317                         if (trace_surface_filter_type != 0 &&
1318                             trace_surface_filter_type != 2) goto finish;
1319
1320                         if (trace_surface_filter_handle != 0 &&
1321                             trace_surface_filter_handle != sdata->tex &&
1322                             trace_surface_filter_handle != sdata->rb) goto finish;
1323
1324                         GLint oldfb;
1325                         _orig_tracepath_glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldfb);
1326                         _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, sdata->fbo);
1327
1328                         if (driver_gl_version >= 2)
1329                                 ret_value = _orig_tracepath_glCheckFramebufferStatus(GL_FRAMEBUFFER);
1330                         else
1331                                 ret_value = _orig_tracepath_glCheckFramebufferStatusOES(GL_FRAMEBUFFER);
1332                         if (ret_value == GL_FRAMEBUFFER_COMPLETE) {
1333                                 _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, oldfb);
1334                                 width = sdata->tex_w;
1335                                 height = sdata->tex_h;
1336                                 channel = sdata->tex_format;
1337
1338                                 if (channel == 2) channel = 3;
1339                                 if (width <= 0 || height <= 0 || channel <= 0) goto finish;
1340                                 if (trace_surface_filter_size_w > 0 && trace_surface_filter_size_h > 0 &&
1341                                     (trace_surface_filter_size_w != width || trace_surface_filter_size_h != height))
1342                                         goto finish;
1343
1344                                 if ((trace_surface_filter_period_begin > 0 ||
1345                                      trace_surface_filter_period_end > 0) &&
1346                                     (trace_surface_filter_period_begin > alldumpcount ||
1347                                      trace_surface_filter_period_end < alldumpcount)) {
1348                                         alldumpcount++;
1349                                         sdata->dump_count++;
1350                                         goto finish;
1351                                 }
1352
1353                                 TRACE("\E[40;31;1m[[TRACE SURFACE]] : '%s' is dumped (%dx%dx%d).\E[0m\n", name,
1354                                       width, height, channel);
1355                                 if (trace_surface_print_only_flag == 1 && force_output == 0) {
1356                                         alldumpcount++;
1357                                         sdata->dump_count++;
1358                                         goto finish;
1359                                 }
1360
1361                                 if (channel == 3) channel = 4;
1362
1363                                 data = (unsigned char *)calloc(1,
1364                                                                width * height * channel * sizeof(unsigned char));
1365                                 if (data == NULL) {
1366                                         COREGL_ERR("Can't trace surface : Failed to allocate memory");
1367                                         goto finish;
1368                                 }
1369
1370                                 _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, sdata->fbo);
1371                                 int atttype = _COREGL_INT_INIT_VALUE;
1372                                 if (driver_gl_version >= 2)
1373                                         _orig_tracepath_glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
1374                                                         GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &atttype);
1375                                 else
1376                                         _orig_tracepath_glGetFramebufferAttachmentParameterivOES(GL_FRAMEBUFFER,
1377                                                         GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &atttype);
1378                                 AST(atttype != sdata->tex);
1379                                 int attname = _COREGL_INT_INIT_VALUE;
1380                                 if (driver_gl_version >= 2)
1381                                         _orig_tracepath_glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
1382                                                         GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attname);
1383                                 else
1384                                         _orig_tracepath_glGetFramebufferAttachmentParameterivOES(GL_FRAMEBUFFER,
1385                                                         GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attname);
1386                                 switch (atttype) {
1387                                 case GL_TEXTURE:
1388                                         AST(attname == sdata->tex);
1389                                         break;
1390                                 case GL_RENDERBUFFER:
1391                                         AST(attname == sdata->rb);
1392                                         break;
1393                                 }
1394
1395                                 switch (channel) {
1396                                 case 4:
1397                                         _orig_tracepath_glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE,
1398                                                                      data);
1399                                         break;
1400                                         //case 3: _orig_tracepath_glReadPixels(0, 0, width, height, GL_RGB, GL_UNSIGNED_BYTE, data); break;
1401                                 case 1:
1402                                         _orig_tracepath_glReadPixels(0, 0, width, height, GL_ALPHA, GL_UNSIGNED_BYTE,
1403                                                                      data);
1404                                         break;
1405                                 }
1406                         }
1407                         _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, oldfb);
1408                 }
1409
1410
1411
1412                 if (data == NULL) goto finish;
1413
1414                 unlink(name);
1415                 write_fd = fopen(name, "wb");
1416
1417                 if (write_fd == NULL) {
1418                         COREGL_ERR("Can't trace surface : Failed to create png file");
1419                         goto finish;
1420                 }
1421
1422                 rows = (png_byte **)malloc(height * sizeof(png_byte *));
1423                 if (rows == NULL) {
1424                         COREGL_ERR("Can't trace surface : Failed to allocate memory");
1425                         goto finish;
1426                 }
1427
1428                 for (int i = 0; i < height; i++) {
1429                         rows[i] = data + (height - i - 1) * (width * channel);
1430                 }
1431
1432                 png = dl_png_create_write_struct(PNG_LIBPNG_VER_STRING,
1433                                                  NULL,
1434                                                  NULL,
1435                                                  NULL);
1436                 if (png == NULL) {
1437                         COREGL_ERR("Can't trace surface : Failed to create write structure of png file");
1438                         goto finish;
1439                 }
1440
1441                 info = dl_png_create_info_struct(png);
1442                 if (info == NULL) {
1443                         COREGL_ERR("Can't trace surface : Failed to create info structure of png file");
1444                         goto finish;
1445                 }
1446
1447                 dl_png_init_io(png, write_fd);
1448
1449                 switch (channel) {
1450                 case 4:
1451                         dl_png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_RGB_ALPHA,
1452                                         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1453                         break;
1454                         //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;
1455                 case 1:
1456                         dl_png_set_IHDR(png, info, width, height, 8, PNG_COLOR_TYPE_GRAY,
1457                                         PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1458                         break;
1459                 }
1460
1461                 dl_png_write_info(png, info);
1462
1463                 dl_png_write_image(png, rows);
1464
1465                 dl_png_write_end(png, info);
1466
1467                 dl_png_destroy_write_struct(&png, &info);
1468
1469                 alldumpcount++;
1470                 sdata->dump_count++;
1471         }
1472
1473         goto finish;
1474
1475 finish:
1476         if (data != NULL) {
1477                 free(data);
1478                 data = NULL;
1479         }
1480         if (write_fd != NULL) {
1481                 fclose(write_fd);
1482                 write_fd = NULL;
1483         }
1484         if (rows != NULL) {
1485                 free(rows);
1486                 rows = NULL;
1487         }
1488         if (png != NULL) {
1489                 if (info != NULL) {
1490                         if (dl_png_destroy_write_struct)
1491                                 dl_png_destroy_write_struct(&png, &info);
1492                         info = NULL;
1493                 } else {
1494                         if (dl_png_destroy_write_struct)
1495                                 dl_png_destroy_write_struct(&png, NULL);
1496                 }
1497                 png = NULL;
1498         }
1499 }
1500
1501 void
1502 tracepath_surface_trace_add(const char *desc, GLDisplay dpy, GLContext ctx,
1503                             GLSurface surf, GLint fbo, GLint tex, GLint rb, GLint tex_w, GLint tex_h,
1504                             GLint tex_format, const char *dump)
1505 {
1506         Surface_Data *std = NULL;
1507
1508         if (trace_surface_flag == 1) {
1509                 AST(mutex_lock(&std_access_mutex) == 1);
1510
1511                 if (std_table == NULL) {
1512                         std_table = (Surface_Data **)calloc(1,
1513                                                             sizeof(Surface_Data *) * MAX_TRACE_TABLE_SIZE);
1514                 }
1515
1516                 std = (Surface_Data *)_get_trace_data((Trace_Data **)std_table,
1517                                                       sizeof(Surface_Data), desc);
1518
1519                 AST(std != NULL);
1520
1521                 if (dump != NULL) {
1522                         _dump_surface(0, 0, dump, std);
1523                 }
1524
1525                 std->display = dpy;
1526                 std->surface = surf;
1527                 std->context = ctx;
1528                 if (fbo >= 0) std->fbo = fbo;
1529                 std->tex = tex;
1530                 std->rb = rb;
1531                 if (tex_w >= 0) std->tex_w = tex_w;
1532                 if (tex_h >= 0) std->tex_h = tex_h;
1533                 if (tex_format >= 0) std->tex_format = tex_format;
1534
1535                 AST(mutex_unlock(&std_access_mutex) == 1);
1536
1537         }
1538
1539 }
1540
1541 void
1542 tracepath_surface_trace(int force_output, int type, const char *position)
1543 {
1544         int i;
1545
1546         if (trace_surface_flag != 1) {
1547                 goto finish;
1548         }
1549
1550         AST(mutex_lock(&std_access_mutex) == 1);
1551
1552         if (std_table != NULL) {
1553                 EGLDisplay olddpy = _orig_tracepath_eglGetCurrentDisplay();
1554                 EGLContext oldctx = _orig_tracepath_eglGetCurrentContext();
1555                 EGLSurface oldsurf_read = _orig_tracepath_eglGetCurrentSurface(EGL_READ);
1556                 EGLSurface oldsurf_draw = _orig_tracepath_eglGetCurrentSurface(EGL_DRAW);
1557
1558                 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1559                         if (std_table[i] != NULL) {
1560                                 Surface_Data *current = std_table[i];
1561
1562                                 while (current != NULL) {
1563                                         if (current->surface != EGL_NO_SURFACE && current->display != EGL_NO_DISPLAY &&
1564                                             current->context != EGL_NO_CONTEXT) {
1565                                                 if (_orig_tracepath_eglMakeCurrent(current->display, current->surface,
1566                                                                                    current->surface, current->context) == EGL_TRUE) {
1567                                                         _dump_surface(force_output, type, position, current);
1568                                                 }
1569                                         }
1570
1571                                         current = (Surface_Data *)current->trace_data.next;
1572                                 }
1573                         }
1574                 }
1575                 _orig_tracepath_eglMakeCurrent(olddpy, oldsurf_read, oldsurf_draw, oldctx);
1576
1577         }
1578
1579         AST(mutex_unlock(&std_access_mutex) == 1);
1580
1581         goto finish;
1582
1583 finish:
1584         return;
1585 }
1586
1587
1588 COREGL_API void
1589 coregl_dump_surface()
1590 {
1591         _COREGL_TRACE_SURFACE(1, 0, "USER CALL");
1592 }
1593