1 #include "coregl_tracepath.h"
12 static int api_gl_version;
15 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST) RET_TYPE (*_orig_tracepath_##FUNC_NAME) PARAM_LIST = NULL;
16 # include "../headers/sym_gl1.h"
17 # include "../headers/sym_gl2.h"
18 # include "../headers/sym_gl_common.h"
19 # include "../headers/sym_egl.h"
22 #define TIMEVAL_INIT { 0, 0 }
25 char name[MAX_TRACE_NAME_LENGTH];
26 struct _Trace_Data *next;
29 struct _Apicall_Data {
30 struct _Trace_Data trace_data;
34 struct timeval elapsed_time;
35 struct timeval elapsed_time_max;
36 struct timeval last_elapsed_time;
37 struct timeval total_elapsed_time;
38 struct timeval last_total_elapsed_time;
39 struct timeval last_time;
45 struct _Trace_Data trace_data;
52 struct _Surface_Data {
53 struct _Trace_Data trace_data;
70 typedef struct _GLGlueFakeContext {
71 GLuint gl_draw_buffers_num[1];
72 GLuint gl_tex_units_num[1];
73 GLuint gl_vertex_attribs_num[1];
74 GLuint gl_transform_feedback_buffer_binding_num[1];
75 GLuint gl_uniform_buffer_binding_num[1];
76 GLuint gl_shader_storage_buffer_binding_num[1];
77 GLuint gl_atomic_counter_buffer_binding_num[1];
80 GLGlueFakeContext initial_fake_ctx_real;
81 GLGlueFakeContext *initial_fake_ctx = &initial_fake_ctx_real;
83 struct timeval initial_time = TIMEVAL_INIT;
84 struct timeval last_initial_time = TIMEVAL_INIT;
86 struct timeval last_trace_time = TIMEVAL_INIT;
87 struct timeval other_elapsed_time = TIMEVAL_INIT;
88 struct timeval traced_other_elapsed_time = TIMEVAL_INIT;
90 Mutex mtd_access_mutex = MUTEX_INITIALIZER;
91 Memuse_Data **mtd_table;
93 Mutex std_access_mutex = MUTEX_INITIALIZER;
94 Surface_Data **std_table;
96 static int trace_surface_sequence_sort_flag = 0;
97 static int trace_surface_filter_period_begin = 0;
98 static int trace_surface_filter_period_end = 0;
99 static int trace_surface_filter_type = 0;
100 static uintptr_t trace_surface_filter_handle = 0;
101 static int trace_surface_filter_size_w = 0;
102 static int trace_surface_filter_size_h = 0;
103 static int trace_surface_print_only_flag = 0;
106 _state_get_texture_states(GLenum pname, GLint *params)
108 GLuint cur_active_tex = 0;
110 AST(initial_fake_ctx != NULL);
112 _orig_tracepath_glGetIntegerv(GL_ACTIVE_TEXTURE, (GLint *)&cur_active_tex);
114 for (i = 0; i < initial_fake_ctx->gl_tex_units_num[0]; i++) {
115 _orig_tracepath_glActiveTexture(GL_TEXTURE0 + i);
116 _orig_tracepath_glGetIntegerv(pname, (GLint *)¶ms[i]);
118 _orig_tracepath_glActiveTexture(cur_active_tex);
122 _state_get_draw_buffers(GLenum *params)
124 AST(initial_fake_ctx != NULL);
127 for (i = 0; i < initial_fake_ctx->gl_draw_buffers_num[0]; i++) {
128 _orig_tracepath_glGetIntegerv(GL_DRAW_BUFFER0 + i, (GLint *)¶ms[i]);
133 _state_get_transform_feedback_buffer_bindings(GLuint *params)
135 AST(initial_fake_ctx != NULL);
138 for (i = 0; i < initial_fake_ctx->gl_transform_feedback_buffer_binding_num[0];
140 _orig_tracepath_glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_BINDING, i,
141 (GLint *)¶ms[i]);
146 _state_get_transform_feedback_buffer_bindings_offset(GLintptr *params)
148 AST(initial_fake_ctx != NULL);
151 for (i = 0; i < initial_fake_ctx->gl_transform_feedback_buffer_binding_num[0];
153 _orig_tracepath_glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_START, i,
154 (GLint *)¶ms[i]);
159 _state_get_transform_feedback_buffer_bindings_size(GLsizeiptr *params)
161 AST(initial_fake_ctx != NULL);
164 for (i = 0; i < initial_fake_ctx->gl_transform_feedback_buffer_binding_num[0];
166 _orig_tracepath_glGetIntegeri_v(GL_TRANSFORM_FEEDBACK_BUFFER_SIZE, i,
167 (GLint *)¶ms[i]);
172 _state_get_uniform_buffer_bindings(GLuint *params)
174 AST(initial_fake_ctx != NULL);
177 for (i = 0; i < initial_fake_ctx->gl_uniform_buffer_binding_num[0]; i++) {
178 /////////////////////////////////////////////////////////////////////////////////
179 // XXXX : AVOID SEGFAULT in ADRENO
180 ((GLint *)params)[i] = 0;
181 // _orig_tracepath_glGetIntegeri_v(GL_UNIFORM_BUFFER_BINDING, i, (GLint *)¶ms[i]);
182 /////////////////////////////////////////////////////////////////////////////////
187 _state_get_uniform_buffer_bindings_offset(GLintptr *params)
189 AST(initial_fake_ctx != NULL);
192 for (i = 0; i < initial_fake_ctx->gl_uniform_buffer_binding_num[0]; i++) {
193 _orig_tracepath_glGetIntegeri_v(GL_UNIFORM_BUFFER_START, i,
194 (GLint *)¶ms[i]);
199 _state_get_uniform_buffer_bindings_size(GLsizeiptr *params)
201 AST(initial_fake_ctx != NULL);
204 for (i = 0; i < initial_fake_ctx->gl_uniform_buffer_binding_num[0]; i++) {
205 _orig_tracepath_glGetIntegeri_v(GL_UNIFORM_BUFFER_SIZE, i, (GLint *)¶ms[i]);
209 /* shader storage buffer */
211 _state_get_shader_storage_buffer_bindings(GLuint *params)
213 AST(initial_fake_ctx != NULL);
216 for (i = 0; i < initial_fake_ctx->gl_shader_storage_buffer_binding_num[0];
218 _orig_tracepath_glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_BINDING, i,
219 (GLint *)¶ms[i]);
224 _state_get_shader_storage_buffer_bindings_offset(GLintptr *params)
226 AST(initial_fake_ctx != NULL);
229 for (i = 0; i < initial_fake_ctx->gl_shader_storage_buffer_binding_num[0];
231 _orig_tracepath_glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_START, i,
232 (GLint *)¶ms[i]);
237 _state_get_shader_storage_buffer_bindings_size(GLsizeiptr *params)
239 AST(initial_fake_ctx != NULL);
242 for (i = 0; i < initial_fake_ctx->gl_shader_storage_buffer_binding_num[0];
244 _orig_tracepath_glGetIntegeri_v(GL_SHADER_STORAGE_BUFFER_SIZE, i,
245 (GLint *)¶ms[i]);
249 /* atomic counter buffer */
251 _state_get_atomic_counter_buffer_bindings(GLuint *params)
253 AST(initial_fake_ctx != NULL);
256 for (i = 0; i < initial_fake_ctx->gl_atomic_counter_buffer_binding_num[0];
258 _orig_tracepath_glGetIntegeri_v(GL_ATOMIC_COUNTER_BUFFER_BINDING, i,
259 (GLint *)¶ms[i]);
264 _state_get_atomic_counter_buffer_bindings_offset(GLintptr *params)
266 AST(initial_fake_ctx != NULL);
269 for (i = 0; i < initial_fake_ctx->gl_atomic_counter_buffer_binding_num[0];
271 _orig_tracepath_glGetIntegeri_v(GL_ATOMIC_COUNTER_BUFFER_START, i,
272 (GLint *)¶ms[i]);
277 _state_get_atomic_counter_buffer_bindings_size(GLsizeiptr *params)
279 AST(initial_fake_ctx != NULL);
282 for (i = 0; i < initial_fake_ctx->gl_atomic_counter_buffer_binding_num[0];
284 _orig_tracepath_glGetIntegeri_v(GL_ATOMIC_COUNTER_BUFFER_SIZE, i,
285 (GLint *)¶ms[i]);
290 init_modules_tracepath()
293 const char *output_file = NULL;
294 output_file = get_env_setting("COREGL_LOG_FILE");
295 if (strlen(output_file) > 0) {
296 trace_fp = fopen(output_file, "w");
300 #ifdef COREGL_TRACEPATH_TRACE_SURFACE_INFO
301 trace_surface_sequence_sort_flag = atoi(
302 get_env_setting("COREGL_TRACE_SURFACE_SEQUENCE_SORT"));
303 trace_surface_print_only_flag = atoi(
304 get_env_setting("COREGL_TRACE_SURFACE_PRINT_ONLY"));
307 // COREGL_TRACE_SURFACE_FILTER_PERIOD=40~60
308 char tmp[64 + 1] = { 0 }, *tmpp = NULL;
309 strncpy(tmp, get_env_setting("COREGL_TRACE_SURFACE_FILTER_PERIOD"), 64);
310 for (tmpp = &tmp[0]; ; tmpp++) {
311 if (*tmpp == 0x00) break;
314 trace_surface_filter_period_begin = atoi(tmp);
315 trace_surface_filter_period_end = atoi(tmpp + 1);
322 // COREGL_TRACE_SURFACE_FILTER_TYPE=EGL|FBO
323 char tmp[64 + 1] = { 0 };
324 strncpy(tmp, get_env_setting("COREGL_TRACE_SURFACE_FILTER_TYPE"), 64);
325 if (strcmp(tmp, "EGL") == 0) trace_surface_filter_type = 1;
326 if (strcmp(tmp, "FBO") == 0) trace_surface_filter_type = 2;
330 // COREGL_TRACE_SURFACE_FILTER_HANDLE=0x3234
331 char tmp[64 + 1] = { 0 }, *tmpp = NULL;
332 strncpy(tmp, get_env_setting("COREGL_TRACE_SURFACE_FILTER_HANDLE"), 64);
333 if (tmp[0] == '0' && tmp[1] == 'x') {
334 for (tmpp = &tmp[2]; ; tmpp++) {
335 if (*tmpp == 0x00) break;
336 trace_surface_filter_handle *= 16;
339 trace_surface_filter_handle += 1;
342 trace_surface_filter_handle += 2;
345 trace_surface_filter_handle += 3;
348 trace_surface_filter_handle += 4;
351 trace_surface_filter_handle += 5;
354 trace_surface_filter_handle += 6;
357 trace_surface_filter_handle += 7;
360 trace_surface_filter_handle += 8;
363 trace_surface_filter_handle += 9;
367 trace_surface_filter_handle += 10;
371 trace_surface_filter_handle += 11;
375 trace_surface_filter_handle += 12;
379 trace_surface_filter_handle += 13;
383 trace_surface_filter_handle += 14;
387 trace_surface_filter_handle += 15;
392 trace_surface_filter_handle = (uintptr_t)atol(tmp);
397 // COREGL_TRACE_SURFACE_FILTER_SIZE=640x480
398 char tmp[64 + 1] = { 0 }, *tmpp = NULL;
399 strncpy(tmp, get_env_setting("COREGL_TRACE_SURFACE_FILTER_SIZE"), 64);
400 for (tmpp = &tmp[0]; ; tmpp++) {
401 if (*tmpp == 0x00) break;
404 trace_surface_filter_size_w = atoi(tmp);
405 trace_surface_filter_size_h = atoi(tmpp + 1);
414 TRACE("[CoreGL] \E[40;32;1m<Trace> \E[40;37;1m: ");
416 if (get_trace_api_flag() == 1) {
417 TRACE("\E[40;31;1m(API)\E[0m ");
418 if (get_trace_api_all_flag() == 1) TRACE("\E[40;31;1m(API-ALL)\E[0m ");
419 if (get_trace_api_frame_flag() == 1) TRACE("\E[40;31;1m(API-FRAME)\E[0m ");
421 if (get_trace_ctx_flag() == 1) {
422 TRACE("\E[40;33;1m(CONTEXT)\E[0m ");
423 if (get_trace_ctx_force_flag() == 1) TRACE("\E[40;33;1m(CONTEXT-FORCE)\E[0m ");
425 if (get_trace_state_flag() == 1) TRACE("\E[40;36;1m(STATE)\E[0m ");
426 if (get_trace_mem_flag() == 1) {
427 TRACE("\E[40;35;1m(MEM)\E[0m ");
428 if (get_trace_mem_all_flag() == 1) TRACE("\E[40;35;1m(MEM-ALL)\E[0m ");
430 if (get_trace_surface_flag() == 1) {
431 TRACE("\E[40;36;1m(SURFACE)\E[0m ");
432 if (trace_surface_sequence_sort_flag == 1)
433 TRACE("\E[40;36;1m(SURFACE-SEQUENCE SORT)\E[0m ");
434 if (trace_surface_print_only_flag == 1)
435 TRACE("\E[40;36;1m(PRINT ONLY)\E[0m ");
436 if (trace_surface_filter_period_begin != 0 ||
437 trace_surface_filter_period_end != 0)
438 TRACE("\E[40;36;1m(SURFACE-PERIOD:%d~%d)\E[0m ",
439 trace_surface_filter_period_begin, trace_surface_filter_period_end);
440 if (trace_surface_filter_type == 1)
441 TRACE("\E[40;36;1m(SURFACE-TYPE:EGL)\E[0m ");
442 if (trace_surface_filter_type == 2)
443 TRACE("\E[40;36;1m(SURFACE-TYPE:FBO)\E[0m ");
444 if (trace_surface_filter_handle != 0)
445 TRACE("\E[40;36;1m(SURFACE-HANDLE:%p(%ld))\E[0m ",
446 (void *)trace_surface_filter_handle, (long int)trace_surface_filter_handle);
447 if (trace_surface_filter_size_w > 0 && trace_surface_filter_size_h > 0)
448 TRACE("\E[40;36;1m(SURFACE-SIZE:%dx%d)\E[0m ", trace_surface_filter_size_w,
449 trace_surface_filter_size_h);
452 TRACE("\E[40;37;1menabled\E[0m\n");
457 deinit_modules_tracepath()
459 cleanup_current_thread_state();
463 init_modules_tstate_tracepath(GLThreadState *tstate)
465 MY_MODULE_TSTATE *tstate_mt = NULL;
467 tstate_mt = (MY_MODULE_TSTATE *)calloc(1, sizeof(MY_MODULE_TSTATE));
470 tstate->module_data[MY_MODULE_ID] = tstate_mt;
474 deinit_modules_tstate_tracepath(GLThreadState *tstate)
477 Trace_Data *current = NULL, *next = NULL;
478 MY_MODULE_TSTATE *tstate_mt = tstate->module_data[MY_MODULE_ID];
480 if (tstate_mt != NULL) {
481 if(tstate_mt->ftd_table) {
482 for(i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
483 current = (Trace_Data *)tstate_mt->ftd_table[i];
484 tstate_mt->ftd_table[i] = NULL;
487 next = current->next;
495 tstate->module_data[MY_MODULE_ID] = NULL;
500 tracepath_apply_overrides()
503 tracepath_apply_overrides_egl(1);
504 tracepath_apply_overrides_gl(1);
509 tracepath_apply_overrides_egl(int enable)
511 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST) COREGL_INIT_ORIGINAL(_orig_tracepath_, FUNC_NAME);
512 # include "../headers/sym_egl.h"
513 #undef _COREGL_SYMBOL
515 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST) COREGL_OVERRIDE(tracepath_, FUNC_NAME);
516 # include "../headers/sym_egl.h"
517 #undef _COREGL_SYMBOL
521 tracepath_apply_overrides_gl(int enable)
523 #define _COREGL_START_API(version) api_gl_version = version;
524 #define _COREGL_END_API(version) api_gl_version = COREGL_GLAPI_2;
525 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST) \
526 if(api_gl_version <= driver_gl_version) COREGL_INIT_ORIGINAL(_orig_tracepath_, FUNC_NAME);
527 # include "../headers/sym_gl1.h"
528 # include "../headers/sym_gl2.h"
529 # include "../headers/sym_gl_common.h"
530 #undef _COREGL_SYMBOL
532 #define _COREGL_SYMBOL(RET_TYPE, FUNC_NAME, PARAM_LIST) \
533 if(api_gl_version <= driver_gl_version) COREGL_OVERRIDE(tracepath_, FUNC_NAME);
534 # include "../headers/sym_gl1.h"
535 # include "../headers/sym_gl2.h"
536 # include "../headers/sym_gl_common.h"
537 #undef _COREGL_SYMBOL
538 #undef _COREGL_START_API
539 #undef _COREGL_END_API
545 tracepath_dump_context_states(int force_output)
547 static struct timeval tv_last = { 0, 0 };
549 if (unlikely(get_trace_state_flag() != 1)) return;
551 _sym_glGetIntegerv(GL_MAX_DRAW_BUFFERS,
552 (GLint *)initial_fake_ctx->gl_draw_buffers_num);
553 _sym_glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS,
554 (GLint *)initial_fake_ctx->gl_tex_units_num);
555 _sym_glGetIntegerv(GL_MAX_VERTEX_ATTRIBS,
556 (GLint *)initial_fake_ctx->gl_vertex_attribs_num);
557 _sym_glGetIntegerv(GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS,
558 (GLint *)initial_fake_ctx->gl_transform_feedback_buffer_binding_num);
559 _sym_glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS,
560 (GLint *)initial_fake_ctx->gl_uniform_buffer_binding_num);
564 struct timeval tv_now = { 0, 0 };
565 AST(gettimeofday(&tv_now, NULL) == 0);
566 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC) {
573 TRACE("\E[0;40;34m===================================================================================================================\E[0m\n");
574 TRACE("\E[40;32;1m State info \E[1;37;1m: <PID = %d> (CURRENT BINDED CONTEXT)\E[0m\n",
576 TRACE("\E[0;40;34m===================================================================================================================\E[0m\n");
578 #define PRINTF_CHAR_GLenum "0x%8X"
579 #define PRINTF_CHAR_GLboolean "%10d"
580 #define PRINTF_CHAR_GLint "%10d"
581 #define PRINTF_CHAR_GLsizei "%10u"
582 #define PRINTF_CHAR_GLuint "%10u"
583 #define PRINTF_CHAR_GLuintmask "0x%8X"
584 #define PRINTF_CHAR_GLintptr "%10ld"
585 #define PRINTF_CHAR_GLsizeiptr "%10ld"
587 #define PRINTF_CHAR_GLclampf "%10.6f"
588 #define PRINTF_CHAR_GLfloat "%10.6f"
590 #define PRINTF_CHAR_GLvoidptr "%10p"
592 #define PRINTF_CHAR(type) PRINTF_CHAR_##type
594 #define INITIAL_CTX initial_fake_ctx
596 #define GLUE_STATE(TYPE, NAME, SIZE, ARRAY_SIZE, DEFAULT_STMT, GET_STMT) \
598 TYPE valuedata[SIZE]; \
599 TYPE *value = NULL; \
600 value = valuedata; GET_STMT; value = valuedata; \
602 TRACE("\E[40;37;1m %-30.30s : (\E[0m ", #NAME); \
603 for (int i = 0; i < SIZE; i++) \
607 TRACE("\n %-30.30s ", "");\
611 TRACE("["PRINTF_CHAR(TYPE)"]", value[i]); \
613 TRACE(" \E[40;37;1m)\E[0m\n"); \
615 # include "./coregl_fastpath_state.h"
618 TRACE("\E[0;40;34m===================================================================================================================\E[0m\n");
629 _add_timeval_period(struct timeval *tv_dst, struct timeval tv_now,
630 struct timeval tv_old)
632 tv_dst->tv_sec += tv_now.tv_sec - tv_old.tv_sec;
633 tv_dst->tv_usec += 1000000 + (tv_now.tv_usec - tv_old.tv_usec);
634 tv_dst->tv_sec += (tv_dst->tv_usec / 1000000) - 1;
635 tv_dst->tv_usec = tv_dst->tv_usec % 1000000;
639 _add_timeval(struct timeval *tv_dst, struct timeval tv_src)
641 tv_dst->tv_sec += tv_src.tv_sec;
642 tv_dst->tv_usec += tv_src.tv_usec;
643 if (tv_dst->tv_usec > 1000000) {
644 tv_dst->tv_usec -= 1000000;
646 } else if (tv_dst->tv_usec < 0) {
647 tv_dst->tv_usec += 1000000;
653 _get_timeval_period(struct timeval time_now, struct timeval time_old)
655 return ((time_now.tv_sec - time_old.tv_sec) * 1000) + ((
656 time_now.tv_usec - time_old.tv_usec) / 1000.0);
660 _get_timeval(struct timeval time)
662 return (time.tv_sec * 1000) + (time.tv_usec / 1000.0);
665 static unsigned short
666 _generate_hash_short(const char *string)
668 unsigned short hash = 0;
671 for (i = 0; i < strlen(string); i++) {
672 hash = 253 * hash + string[i];
674 return (hash ^ (hash >> 8)) % MAX_TRACE_TABLE_SIZE;
678 _get_trace_data(Trace_Data **ftd_table, size_t td_size, const char *name)
680 Trace_Data *ret = NULL;
681 Trace_Data *current = NULL;
682 Trace_Data *prev = NULL;
683 unsigned short hash = 0;
685 AST(strlen(name) < MAX_TRACE_NAME_LENGTH);
687 hash = _generate_hash_short(name);
689 current = ftd_table[hash];
691 while (current != NULL && current->next != NULL) {
692 if (strcmp(current->name, name) == 0)
695 current = current->next;
698 if (current != NULL) {
701 Trace_Data *newitm = NULL;
702 newitm = (Trace_Data *)calloc(1, td_size);
703 if (newitm == NULL) {
708 strncpy(newitm->name, name,
709 strlen(name) < (sizeof(newitm->name) - 1) ? strlen(name) : (sizeof(
716 ftd_table[hash] = newitm;
728 tracepath_mem_trace_add(const char *desc, int alloc_size)
730 Memuse_Data *mtd = NULL;
732 if (get_trace_mem_flag() == 1) {
733 AST(mutex_lock(&mtd_access_mutex) == 1);
735 if (mtd_table == NULL) {
736 mtd_table = (Memuse_Data **)calloc(1,
737 sizeof(Memuse_Data *) * MAX_TRACE_TABLE_SIZE);
740 mtd = (Memuse_Data *)_get_trace_data((Trace_Data **)mtd_table,
741 sizeof(Memuse_Data), desc);
747 if (mtd->memsize == 0)
748 mtd->memsize = alloc_size;
750 AST(mtd->memsize == alloc_size);
752 AST(mutex_unlock(&mtd_access_mutex) == 1);
754 if (get_trace_mem_all_flag() == 1)
755 _COREGL_TRACE_MEM_OUTPUT(1);
761 tracepath_mem_trace_remove(const char *desc, int alloc_size)
763 Memuse_Data *mtd = NULL;
765 if (get_trace_mem_flag() == 1) {
766 AST(mutex_lock(&mtd_access_mutex) == 1);
768 if (mtd_table == NULL) {
769 mtd_table = (Memuse_Data **)calloc(1,
770 sizeof(Memuse_Data *) * MAX_TRACE_TABLE_SIZE);
773 mtd = (Memuse_Data *)_get_trace_data((Trace_Data **)mtd_table,
774 sizeof(Memuse_Data), desc);
777 AST(mtd->memsize == alloc_size);
779 AST(mtd->alloc_count > mtd->remove_count);
782 AST(mutex_unlock(&mtd_access_mutex) == 1);
784 if (get_trace_mem_all_flag() == 1)
785 _COREGL_TRACE_MEM_OUTPUT(1);
790 tracepath_api_trace_begin(const char *funcname, void *hint,
791 int trace_total_time)
793 Apicall_Data *ftd = NULL;
794 struct timeval t = TIMEVAL_INIT;
796 if (get_trace_api_flag() == 1) {
797 AST(gettimeofday(&t, NULL) == 0);
799 ftd = (Apicall_Data *)hint;
802 MY_MODULE_TSTATE *tstate = NULL;
803 GET_MY_TSTATE(tstate, get_current_thread_state());
805 if (tstate == NULL) {
806 init_new_thread_state();
808 GET_MY_TSTATE(tstate, get_current_thread_state());
814 if (tstate->ftd_table == NULL) {
815 tstate->ftd_table = (Apicall_Data **)calloc(1,
816 sizeof(Apicall_Data *) * MAX_TRACE_TABLE_SIZE);
819 ftd = (Apicall_Data *)_get_trace_data((Trace_Data **)tstate->ftd_table,
820 sizeof(Apicall_Data), funcname);
826 if (ftd) ftd->call_count++;
827 if (ftd) AST(ftd->last_time.tv_sec == 0);
829 if (ftd) AST(gettimeofday(&ftd->last_time, NULL) == 0);
831 if (ftd && initial_time.tv_sec == 0) {
832 initial_time = ftd->last_time;
833 last_initial_time = ftd->last_time;
836 if (trace_total_time == 1) {
837 if (last_trace_time.tv_sec != 0) {
838 _add_timeval_period(&other_elapsed_time, t, last_trace_time);
839 last_trace_time.tv_sec = 0;
849 tracepath_api_trace_end(const char *funcname, void *hint, int trace_total_time)
851 Apicall_Data *ftd = NULL;
852 struct timeval t = TIMEVAL_INIT;
854 if (get_trace_api_flag() == 1) {
855 MY_MODULE_TSTATE *tstate = NULL;
856 struct timeval elapsed_time = TIMEVAL_INIT;
858 AST(gettimeofday(&t, NULL) == 0);
860 ftd = (Apicall_Data *)hint;
863 GET_MY_TSTATE(tstate, get_current_thread_state());
865 if (tstate == NULL) {
866 init_new_thread_state();
868 GET_MY_TSTATE(tstate, get_current_thread_state());
873 AST(tstate && (tstate->ftd_table != NULL));
875 if (tstate && (tstate->ftd_table)) {
876 ftd = (Apicall_Data *)_get_trace_data((Trace_Data **)tstate->ftd_table,
877 sizeof(Apicall_Data), funcname);
883 if (ftd) _add_timeval_period(&elapsed_time, t, ftd->last_time);
885 if (ftd) _add_timeval(&ftd->elapsed_time, elapsed_time);
888 elapsed_time.tv_sec >= ftd->elapsed_time_max.tv_sec &&
889 elapsed_time.tv_usec > ftd->elapsed_time_max.tv_usec) {
890 ftd->elapsed_time_max.tv_sec = elapsed_time.tv_sec;
891 ftd->elapsed_time_max.tv_usec = elapsed_time.tv_usec;
894 if (ftd) ftd->last_time.tv_sec = 0;
896 if (trace_total_time == 1) {
897 if (ftd) _add_timeval(&ftd->total_elapsed_time, elapsed_time);
899 AST(gettimeofday(&last_trace_time, NULL) == 0);
901 if (initial_time.tv_sec == 0) {
903 last_initial_time = t;
913 tracepath_api_trace_output(int force_output)
915 static struct timeval tv_last = TIMEVAL_INIT;
916 struct timeval total_now = TIMEVAL_INIT;
917 GLThreadState *tstate = NULL;
918 MY_MODULE_TSTATE *tstate_tm = NULL;
919 Apicall_Data **ftd_table = NULL;
921 double total_elapsed_time = 0.0;
922 double total_elapsed_time_period = 0.0;
923 double total_opengl_elapsed_time = 0.0;
924 double total_opengl_elapsed_time_period = 0.0;
925 double total_other_elapsed_time = 0.0;
926 double total_other_elapsed_time_period = 0.0;
928 double swaps_per_sec = 0.0;
932 if (get_trace_api_flag() != 1) {
937 struct timeval tv_now = TIMEVAL_INIT;
938 AST(gettimeofday(&tv_now, NULL) == 0);
939 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC) {
945 AST(gettimeofday(&total_now, NULL) == 0);
947 total_elapsed_time = _get_timeval_period(total_now, initial_time);
948 total_elapsed_time_period = _get_timeval_period(total_now, last_initial_time);
949 last_initial_time = total_now;
951 total_other_elapsed_time = _get_timeval(other_elapsed_time);
952 total_other_elapsed_time_period = _get_timeval_period(other_elapsed_time,
953 traced_other_elapsed_time);
954 traced_other_elapsed_time = other_elapsed_time;
956 tstate = get_current_thread_state();
958 if (tstate == NULL) {
959 init_new_thread_state();
961 tstate = get_current_thread_state();
965 GET_MY_TSTATE(tstate_tm, tstate);
966 if (tstate_tm == NULL) goto finish;
968 ftd_table = tstate_tm->ftd_table;
969 if (ftd_table == NULL) goto finish;
972 static Apicall_Data *trace_hint_swap = NULL;
973 if (trace_hint_swap == NULL)
974 trace_hint_swap = (Apicall_Data *)_get_trace_data((Trace_Data **)ftd_table,
975 sizeof(Apicall_Data), "tracepath_eglSwapBuffers");
977 if (trace_hint_swap != NULL && total_elapsed_time_period > 0) {
978 swaps_per_sec = (trace_hint_swap->call_count -
979 trace_hint_swap->last_call_count) / (total_elapsed_time_period / 1000);
985 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
986 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",
987 getpid(), tstate->thread_id, swaps_per_sec);
988 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
991 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
992 if (ftd_table[i] != NULL) {
993 Apicall_Data *current = ftd_table[i];
995 while (current != NULL) {
996 double elapsed_time = _get_timeval(current->elapsed_time);
997 double elapsed_time_per_call = elapsed_time / current->call_count;
999 total_opengl_elapsed_time += _get_timeval(current->total_elapsed_time);
1000 total_opengl_elapsed_time_period += _get_timeval(current->total_elapsed_time) -
1001 _get_timeval(current->last_total_elapsed_time);
1003 current->traced = 0;
1005 if (current->call_count > current->last_call_count) {
1006 double elapsed_time_period = _get_timeval_period(current->elapsed_time,
1007 current->last_elapsed_time);
1008 double elapsed_time_max = _get_timeval(current->elapsed_time_max);
1009 double elapsed_time_per_call_period = elapsed_time_period /
1010 (current->call_count - current->last_call_count);
1011 char *fname = current->trace_data.name;
1013 if (!strncmp(fname, "tracepath_", 10))
1014 fname = ¤t->trace_data.name[10];
1016 if (elapsed_time_per_call_period >= 0.01 ||
1017 current->call_count - current->last_call_count > 1000) {
1018 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",
1019 fname, current->call_count, elapsed_time_per_call, elapsed_time_max,
1020 elapsed_time_per_call_period);
1021 current->traced = 1;
1024 current = (Apicall_Data *)current->trace_data.next;
1031 fp_env = atoi(get_env_setting("COREGL_TRACE_API_ALL"));
1034 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1035 if (ftd_table[i] != NULL) {
1036 Apicall_Data *current = ftd_table[i];
1038 while (current != NULL) {
1039 if (current->traced == 0 && current->call_count > 0) {
1040 double elapsed_time = _get_timeval(current->elapsed_time);
1041 double elapsed_time_per_call = elapsed_time / current->call_count;
1042 double elapsed_time_max = _get_timeval(current->elapsed_time_max);
1043 char *fname = current->trace_data.name;
1045 if (!strncmp(fname, "tracepath_", 10))
1046 fname = ¤t->trace_data.name[10];
1048 TRACE(" %-39.39s : %10d call(s), %9.3f ms/API, %9.2f ms(MAX)\n",
1049 fname, current->call_count, elapsed_time_per_call, elapsed_time_max);
1051 current = (Apicall_Data *)current->trace_data.next;
1058 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
1060 if (get_trace_api_frame_flag() == 0) {
1061 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
1062 "TOTAL elapsed Time",
1065 total_elapsed_time_period,
1069 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
1070 "OpenGL elapsed Time",
1071 total_opengl_elapsed_time,
1072 total_opengl_elapsed_time * 100.0 / total_elapsed_time,
1073 total_opengl_elapsed_time_period,
1074 total_opengl_elapsed_time_period * 100.0 / total_elapsed_time_period);
1076 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
1077 "Out of OpenGL elapsed time",
1078 total_other_elapsed_time,
1079 total_other_elapsed_time * 100.0 / total_elapsed_time,
1080 total_other_elapsed_time_period,
1081 total_other_elapsed_time_period * 100.0 / total_elapsed_time_period);
1083 TRACE("\E[40;36;1m %-39.39s : %13.2f ms[%6.2f%%], %13.2f ms(P)[%6.2f%%]\E[0m\n",
1084 "CoreGL API tracing overhead",
1085 total_elapsed_time - total_opengl_elapsed_time - total_other_elapsed_time,
1086 (total_elapsed_time - total_opengl_elapsed_time - total_other_elapsed_time) *
1087 100.0 / total_elapsed_time,
1088 total_elapsed_time_period - total_opengl_elapsed_time_period -
1089 total_other_elapsed_time_period,
1090 (total_elapsed_time_period - total_opengl_elapsed_time_period -
1091 total_other_elapsed_time_period) * 100.0 / total_elapsed_time_period);
1093 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
1097 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1098 if (ftd_table[i] != NULL) {
1099 Apicall_Data *current = ftd_table[i];
1101 while (current != NULL) {
1102 current->last_call_count = current->call_count;
1103 current->last_elapsed_time = current->elapsed_time;
1104 current->last_total_elapsed_time = current->total_elapsed_time;
1105 current = (Apicall_Data *)current->trace_data.next;
1119 tracepath_api_trace_reset_frame()
1121 GLThreadState *tstate = NULL;
1122 MY_MODULE_TSTATE *tstate_tm = NULL;
1123 Apicall_Data **ftd_table = NULL;
1127 if (get_trace_api_flag() != 1) {
1131 tstate = get_current_thread_state();
1133 if (tstate == NULL) {
1134 init_new_thread_state();
1136 tstate = get_current_thread_state();
1137 AST(tstate != NULL);
1140 GET_MY_TSTATE(tstate_tm, tstate);
1141 if (tstate_tm == NULL) goto finish;
1143 ftd_table = tstate_tm->ftd_table;
1144 if (ftd_table == NULL) goto finish;
1146 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1147 if (ftd_table[i] != NULL) {
1148 Apicall_Data *current = ftd_table[i];
1150 while (current != NULL) {
1151 current->call_count = 0;
1152 current->last_call_count = 0;
1153 current->elapsed_time.tv_sec = 0;
1154 current->elapsed_time.tv_usec = 0;
1155 current->last_elapsed_time.tv_sec = 0;
1156 current->last_elapsed_time.tv_usec = 0;
1157 current->last_total_elapsed_time.tv_sec = 0;
1158 current->last_total_elapsed_time.tv_usec = 0;
1159 current->total_elapsed_time.tv_sec = 0;
1160 current->total_elapsed_time.tv_usec = 0;
1161 current = (Apicall_Data *)current->trace_data.next;
1165 AST(gettimeofday(&last_initial_time, NULL) == 0);
1173 tracepath_mem_trace_output(int force_output)
1175 static struct timeval tv_last = TIMEVAL_INIT;
1179 if (get_trace_mem_flag() != 1) {
1183 if (!force_output) {
1184 struct timeval tv_now = TIMEVAL_INIT;
1185 AST(gettimeofday(&tv_now, NULL) == 0);
1186 if (tv_now.tv_sec - tv_last.tv_sec < _COREGL_TRACE_OUTPUT_INTERVAL_SEC) {
1193 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
1194 TRACE("\E[40;32;1m Memory usage info \E[1;37;1m: <PID = %d>\E[0m\n", getpid());
1195 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
1197 if (mtd_table != NULL) {
1198 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1199 if (mtd_table[i] != NULL) {
1200 Memuse_Data *current = mtd_table[i];
1202 while (current != NULL) {
1203 int obj_count = current->alloc_count - current->remove_count;
1204 if (obj_count > 0) {
1205 TRACE("\E[40;37;1m %-46.46s : %12d byte(s)(E), %9d object(s) [%9d+/%9d-]\E[0m\n",
1206 current->trace_data.name, current->memsize, obj_count, current->alloc_count,
1207 current->remove_count);
1209 current = (Memuse_Data *)current->trace_data.next;
1214 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1215 if (mtd_table[i] != NULL) {
1216 Memuse_Data *current = mtd_table[i];
1218 while (current != NULL) {
1219 int obj_count = current->alloc_count - current->remove_count;
1220 if (obj_count == 0) {
1221 TRACE(" %-46.46s : %12d byte(s)(E), %9d object(s) [%9d+/%9d-]\n",
1222 current->trace_data.name, current->memsize, obj_count, current->alloc_count,
1223 current->remove_count);
1225 current = (Memuse_Data *)current->trace_data.next;
1231 TRACE("\E[40;34m========================================================================================================================\E[0m\n");
1244 void *png_lib_handle;
1245 png_structp (*dl_png_create_write_struct) (png_const_charp user_png_ver,
1246 png_voidp error_ptr,
1247 png_error_ptr error_fn,
1248 png_error_ptr warn_fn);
1249 png_infop (*dl_png_create_info_struct) (png_structp png_ptr);
1250 void (*dl_png_destroy_write_struct) (png_structpp png_ptr_ptr, png_infopp info_ptr_ptr);
1251 void (*dl_png_init_io) (png_structp png_ptr, png_FILE_p fp);
1252 void (*dl_png_set_IHDR) (png_structp png_ptr, png_infop info_ptr, png_uint_32 width,
1253 png_uint_32 height, int bit_depth, int color_type,
1254 int interlace_method, int compression_method, int filter_method);
1255 void (*dl_png_set_bKGD) (png_structp png_ptr, png_infop info_ptr, png_color_16p background);
1256 void (*dl_png_set_bgr) (png_structp png_ptr);
1257 void (*dl_png_write_info) (png_structp png_ptr, png_infop info_ptr);
1258 void (*dl_png_write_image) (png_structp png_ptr, png_bytepp image);
1259 void (*dl_png_write_end) (png_structp png_ptr, png_infop info_ptr);
1263 _dump_surface_egl(Surface_Data *sdata, char name[], unsigned char **data, int *alldumpcount, int force_output)
1265 EGLConfig eglconfig;
1267 GLint asize, rsize, gsize, bsize;
1269 if (trace_surface_filter_type != 0 && trace_surface_filter_type != 1) {
1273 if (trace_surface_filter_handle != 0 &&
1274 trace_surface_filter_handle != (uintptr_t)sdata->surface) {
1278 _orig_tracepath_eglQuerySurface(sdata->display, sdata->surface, EGL_WIDTH, &sdata->width);
1279 _orig_tracepath_eglQuerySurface(sdata->display, sdata->surface, EGL_HEIGHT, &sdata->height);
1280 _orig_tracepath_eglQuerySurface(sdata->display, sdata->surface, EGL_CONFIG_ID, (GLint *)&eglconfig);
1281 _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_ALPHA_SIZE, &asize);
1282 _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_RED_SIZE, &rsize);
1283 _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_GREEN_SIZE, &gsize);
1284 _orig_tracepath_eglGetConfigAttrib(sdata->display, eglconfig, EGL_BLUE_SIZE, &bsize);
1294 if (sdata->width <= 0 || sdata->height <= 0 || sdata->channel <= 0) {
1298 if (trace_surface_filter_size_w > 0 && trace_surface_filter_size_h > 0 &&
1299 (trace_surface_filter_size_w != sdata->width || trace_surface_filter_size_h != sdata->height)) {
1303 if ((trace_surface_filter_period_begin > 0 ||
1304 trace_surface_filter_period_end > 0) &&
1305 (trace_surface_filter_period_begin > *alldumpcount ||
1306 trace_surface_filter_period_end < *alldumpcount)) {
1307 *alldumpcount = *alldumpcount + 1;
1308 sdata->dump_count++;
1312 TRACE("\E[40;31;1m[[TRACE SURFACE]] : '%s' is dumped (%dx%dx%d).\E[0m\n",
1313 name, sdata->width, sdata->height, sdata->channel);
1315 if (trace_surface_print_only_flag == 1 && force_output == 0) {
1316 *alldumpcount = *alldumpcount + 1;
1317 sdata->dump_count++;
1321 *data = (unsigned char *)calloc(1, sdata->width * sdata->height * sdata->channel * sizeof(unsigned char));
1322 if (*data == NULL) {
1323 COREGL_ERR("Can't trace surface : Failed to allocate memory");
1328 _orig_tracepath_glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldfb);
1329 _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, 0);
1331 format = (sdata->channel == 4) ? GL_RGBA : GL_ALPHA;
1332 _orig_tracepath_glReadPixels(0, 0, sdata->width, sdata->height, format, GL_UNSIGNED_BYTE, *data);
1334 _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, oldfb);
1340 _dump_surface_fbo(Surface_Data *sdata, char name[], unsigned char **data, int *alldumpcount, int force_output)
1344 GLenum ret_value = _COREGL_INT_INIT_VALUE;
1346 if (sdata->fbo == 0) {
1350 if (trace_surface_filter_type != 0 && trace_surface_filter_type != 2) {
1354 if (trace_surface_filter_handle != 0 &&
1355 trace_surface_filter_handle != (uintptr_t)sdata->tex &&
1356 trace_surface_filter_handle != (uintptr_t)sdata->rb) {
1360 _orig_tracepath_glGetIntegerv(GL_FRAMEBUFFER_BINDING, &oldfb);
1361 _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, sdata->fbo);
1363 if (driver_gl_version >= 2) {
1364 ret_value = _orig_tracepath_glCheckFramebufferStatus(GL_FRAMEBUFFER);
1367 ret_value = _orig_tracepath_glCheckFramebufferStatusOES(GL_FRAMEBUFFER);
1370 if (ret_value == GL_FRAMEBUFFER_COMPLETE) {
1371 _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, oldfb);
1372 sdata->width = sdata->tex_w;
1373 sdata->height = sdata->tex_h;
1374 sdata->channel = sdata->tex_format;
1376 if (sdata->channel == 2) {
1380 if (sdata->width <= 0 || sdata->height <= 0 || sdata->channel <= 0) {
1384 if (trace_surface_filter_size_w > 0 && trace_surface_filter_size_h > 0 &&
1385 (trace_surface_filter_size_w != sdata->width || trace_surface_filter_size_h != sdata->height)) {
1389 if ((trace_surface_filter_period_begin > 0 ||
1390 trace_surface_filter_period_end > 0) &&
1391 (trace_surface_filter_period_begin > *alldumpcount ||
1392 trace_surface_filter_period_end < *alldumpcount)) {
1393 *alldumpcount = *alldumpcount + 1;
1394 sdata->dump_count++;
1398 TRACE("\E[40;31;1m[[TRACE SURFACE]] : '%s' is dumped (%dx%dx%d).\E[0m\n", name,
1399 sdata->width, sdata->height, sdata->channel);
1400 if (trace_surface_print_only_flag == 1 && force_output == 0) {
1401 *alldumpcount = *alldumpcount + 1;
1402 sdata->dump_count++;
1406 if (sdata->channel == 3) {
1410 *data = (unsigned char *)calloc(1, sdata->width * sdata->height * sdata->channel * sizeof(unsigned char));
1411 if (*data == NULL) {
1412 COREGL_ERR("Can't trace surface : Failed to allocate memory");
1416 _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, sdata->fbo);
1417 int atttype = _COREGL_INT_INIT_VALUE;
1418 if (driver_gl_version >= 2) {
1419 _orig_tracepath_glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
1420 GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &atttype);
1423 _orig_tracepath_glGetFramebufferAttachmentParameterivOES(GL_FRAMEBUFFER,
1424 GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &atttype);
1427 AST(atttype != sdata->tex);
1428 int attname = _COREGL_INT_INIT_VALUE;
1429 if (driver_gl_version >= 2) {
1430 _orig_tracepath_glGetFramebufferAttachmentParameteriv(GL_FRAMEBUFFER,
1431 GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attname);
1434 _orig_tracepath_glGetFramebufferAttachmentParameterivOES(GL_FRAMEBUFFER,
1435 GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &attname);
1440 AST(attname == sdata->tex);
1442 case GL_RENDERBUFFER:
1443 AST(attname == sdata->rb);
1447 format = (sdata->channel == 4) ? GL_RGBA : GL_ALPHA;
1448 _orig_tracepath_glReadPixels(0, 0, sdata->width, sdata->height, format, GL_UNSIGNED_BYTE, *data);
1450 _orig_tracepath_glBindFramebuffer(GL_FRAMEBUFFER, oldfb);
1456 _dump_surface(int force_output, int type, const char *position, Surface_Data *sdata)
1458 static int alldumpcount = 0;
1459 unsigned char *data = NULL;
1461 FILE *write_fd = NULL;
1462 png_struct *png = NULL;
1463 png_info *info = NULL;
1464 png_byte **rows = NULL;
1465 struct png_state state = { NULL };
1467 if (!state.png_lib_handle) {
1468 state.png_lib_handle = dlopen("libpng16.so.16", RTLD_NOW);
1469 state.dl_png_create_write_struct = dlsym(state.png_lib_handle, "png_create_write_struct");
1470 state.dl_png_destroy_write_struct = dlsym(state.png_lib_handle, "png_destroy_write_struct");
1471 state.dl_png_create_info_struct = dlsym(state.png_lib_handle, "png_create_info_struct");
1472 state.dl_png_init_io = dlsym(state.png_lib_handle, "png_init_io");
1473 state.dl_png_set_IHDR = dlsym(state.png_lib_handle, "png_set_IHDR");
1474 state.dl_png_set_bKGD = dlsym(state.png_lib_handle, "png_set_bKGD");
1475 state.dl_png_set_bgr = dlsym(state.png_lib_handle, "png_set_bgr");
1476 state.dl_png_write_info = dlsym(state.png_lib_handle, "png_write_info");
1477 state.dl_png_write_image = dlsym(state.png_lib_handle, "png_write_image");
1478 state.dl_png_write_end = dlsym(state.png_lib_handle, "png_write_end");
1481 if (!state.png_lib_handle ||
1482 state.dl_png_create_write_struct == NULL ||
1483 state.dl_png_destroy_write_struct == NULL ||
1484 state.dl_png_create_info_struct == NULL ||
1485 state.dl_png_init_io == NULL ||
1486 state.dl_png_set_IHDR == NULL ||
1487 state.dl_png_set_bKGD == NULL ||
1488 state.dl_png_set_bgr == NULL ||
1489 state.dl_png_write_info == NULL ||
1490 state.dl_png_write_image == NULL ||
1491 state.dl_png_write_end == NULL) {
1492 COREGL_ERR("Can't trace surface : Failed to use libpng (recommend : 1.2.50-3.4)");
1496 if (trace_surface_sequence_sort_flag == 1) {
1497 snprintf(name, sizeof(name), "[%d (%06d)%p-%p] %s %04d (%s).png", getpid(),
1498 alldumpcount, sdata->display, sdata->context, sdata->trace_data.name,
1499 sdata->dump_count, position);
1502 snprintf(name, sizeof(name), "[%d %p-%p] %s %04d (%s).png", getpid(),
1503 sdata->display, sdata->context, sdata->trace_data.name,
1504 sdata->dump_count, position);
1507 if (!strncmp(sdata->trace_data.name, "EGL", 3) && type != 2) {
1508 if(_dump_surface_egl(sdata, name, &data, &alldumpcount, force_output) == EGL_FALSE) {
1511 } else if (!strncmp(sdata->trace_data.name, "FBO", 3) && type != 1) {
1512 if(_dump_surface_fbo(sdata, name, &data, &alldumpcount, force_output) == EGL_FALSE) {
1518 write_fd = fopen(name, "wb");
1520 if (write_fd == NULL) {
1521 COREGL_ERR("Can't trace surface : Failed to create png file");
1525 rows = (png_byte **)malloc(sdata->height * sizeof(png_byte *));
1527 COREGL_ERR("Can't trace surface : Failed to allocate memory");
1531 for (int i = 0; i < sdata->height; i++) {
1532 rows[i] = data + (sdata->height - i - 1) * (sdata->width * sdata->channel);
1535 png = state.dl_png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
1537 COREGL_ERR("Can't trace surface : Failed to create write structure of png file");
1541 info = state.dl_png_create_info_struct(png);
1543 COREGL_ERR("Can't trace surface : Failed to create info structure of png file");
1547 state.dl_png_init_io(png, write_fd);
1549 int bit_depth = (sdata->channel == 4) ? PNG_COLOR_TYPE_RGB_ALPHA : PNG_COLOR_TYPE_GRAY;
1550 state.dl_png_set_IHDR(png, info, sdata->width, sdata->height, 8, bit_depth,
1551 PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
1553 state.dl_png_write_info(png, info);
1554 state.dl_png_write_image(png, rows);
1555 state.dl_png_write_end(png, info);
1556 state.dl_png_destroy_write_struct(&png, &info);
1559 sdata->dump_count++;
1569 if(state.png_lib_handle != NULL) {
1570 dlclose(state.png_lib_handle);
1571 state.png_lib_handle = NULL;
1574 if (write_fd != NULL) {
1586 if (state.dl_png_destroy_write_struct) {
1587 state.dl_png_destroy_write_struct(&png, &info);
1591 if (state.dl_png_destroy_write_struct) {
1592 state.dl_png_destroy_write_struct(&png, NULL);
1600 tracepath_surface_trace_add(const char *desc, GLDisplay dpy, GLContext ctx,
1601 GLSurface surf, GLint fbo, GLint tex, GLint rb, GLint tex_w, GLint tex_h,
1602 GLint tex_format, const char *dump)
1604 Surface_Data *std = NULL;
1606 if (get_trace_surface_flag() == 1) {
1607 AST(mutex_lock(&std_access_mutex) == 1);
1609 if (std_table == NULL) {
1610 std_table = (Surface_Data **)calloc(1,
1611 sizeof(Surface_Data *) * MAX_TRACE_TABLE_SIZE);
1614 std = (Surface_Data *)_get_trace_data((Trace_Data **)std_table,
1615 sizeof(Surface_Data), desc);
1620 _dump_surface(0, 0, dump, std);
1624 std->surface = surf;
1626 if (fbo >= 0) std->fbo = fbo;
1629 if (tex_w >= 0) std->tex_w = tex_w;
1630 if (tex_h >= 0) std->tex_h = tex_h;
1631 if (tex_format >= 0) std->tex_format = tex_format;
1633 AST(mutex_unlock(&std_access_mutex) == 1);
1640 tracepath_surface_trace(int force_output, int type, const char *position)
1644 if (get_trace_surface_flag() != 1) {
1648 AST(mutex_lock(&std_access_mutex) == 1);
1650 if (std_table != NULL) {
1651 EGLDisplay olddpy = _orig_tracepath_eglGetCurrentDisplay();
1652 EGLContext oldctx = _orig_tracepath_eglGetCurrentContext();
1653 EGLSurface oldsurf_read = _orig_tracepath_eglGetCurrentSurface(EGL_READ);
1654 EGLSurface oldsurf_draw = _orig_tracepath_eglGetCurrentSurface(EGL_DRAW);
1656 for (i = 0; i < MAX_TRACE_TABLE_SIZE; i++) {
1657 if (std_table[i] != NULL) {
1658 Surface_Data *current = std_table[i];
1660 while (current != NULL) {
1661 if (current->surface != EGL_NO_SURFACE && current->display != EGL_NO_DISPLAY &&
1662 current->context != EGL_NO_CONTEXT) {
1663 if (_orig_tracepath_eglMakeCurrent(current->display, current->surface,
1664 current->surface, current->context) == EGL_TRUE) {
1665 _dump_surface(force_output, type, position, current);
1669 current = (Surface_Data *)current->trace_data.next;
1673 _orig_tracepath_eglMakeCurrent(olddpy, oldsurf_read, oldsurf_draw, oldctx);
1677 AST(mutex_unlock(&std_access_mutex) == 1);
1687 coregl_dump_surface()
1689 _COREGL_TRACE_SURFACE(1, 0, "USER CALL");