__GLXextFuncPtr glXGetProcAddressARB (const GLubyte * name) { } __GLXextFuncPtr glXGetProcAddress(const GLubyte *name) { return glXGetProcAddressARB(name); } typedef struct vertex_array_format { struct { GLenum type; GLint size; GLint enabled; } attrib[16]; uint64_t uses; uint64_t total_time; struct vertex_array_format* next; } vertex_array_format; static vertex_array_format* format_list = NULL; static vertex_array_format* vertex_array_get_format() { int a, num_enabled = 0; vertex_array_format* f = (vertex_array_format*) malloc(sizeof(*f)); for(a = 0 ; a < 16 ; a++) { glGetVertexAttribiv(a, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &f->attrib[a].enabled); if (f->attrib[a].enabled) { glGetVertexAttribiv(a, GL_VERTEX_ATTRIB_ARRAY_SIZE, &f->attrib[a].size); glGetVertexAttribiv(a, GL_VERTEX_ATTRIB_ARRAY_TYPE, &f->attrib[a].type); num_enabled++; } else { f->attrib[a].size = 0; f->attrib[a].type = 0; } } if (num_enabled == 0) { GLint save_active_texture; glGetIntegerv(GL_CLIENT_ACTIVE_TEXTURE, &save_active_texture); for(a = 0 ; a < 16 ; a++) { GLenum get_enabled, get_size, get_type; GLint enabled = -1, size = -1, type = -1; switch(a) { case 0: get_enabled = GL_VERTEX_ARRAY; get_size = GL_VERTEX_ARRAY_SIZE; get_type = GL_VERTEX_ARRAY_TYPE; break; case 1: get_enabled = GL_NORMAL_ARRAY; size = 3; get_type = GL_NORMAL_ARRAY_TYPE; break; case 2: get_enabled = GL_COLOR_ARRAY; get_size = GL_COLOR_ARRAY_SIZE; get_type = GL_COLOR_ARRAY_TYPE; break; case 3: get_enabled = GL_INDEX_ARRAY; size = 1; get_type = GL_INDEX_ARRAY_TYPE; break; case 4: get_enabled = GL_EDGE_FLAG_ARRAY; size = 1; type = GL_UNSIGNED_BYTE; break; case 5: get_enabled = GL_FOG_COORD_ARRAY; size = 1; get_type = GL_FOG_COORD_ARRAY_TYPE; break; case 6: get_enabled = GL_SECONDARY_COLOR_ARRAY; size = 1; get_type = GL_FOG_COORD_ARRAY_TYPE; break; case 7: enabled = 0; size = 0; type = 0; break; case 8: get_enabled = GL_TEXTURE_COORD_ARRAY; get_size = GL_TEXTURE_COORD_ARRAY_SIZE; type = GL_TEXTURE_COORD_ARRAY_TYPE; break; case 9: get_enabled = GL_TEXTURE_COORD_ARRAY; get_size = GL_TEXTURE_COORD_ARRAY_SIZE; type = GL_TEXTURE_COORD_ARRAY_TYPE; break; case 10: get_enabled = GL_TEXTURE_COORD_ARRAY; get_size = GL_TEXTURE_COORD_ARRAY_SIZE; type = GL_TEXTURE_COORD_ARRAY_TYPE; break; case 11: get_enabled = GL_TEXTURE_COORD_ARRAY; get_size = GL_TEXTURE_COORD_ARRAY_SIZE; type = GL_TEXTURE_COORD_ARRAY_TYPE; break; case 12: get_enabled = GL_TEXTURE_COORD_ARRAY; get_size = GL_TEXTURE_COORD_ARRAY_SIZE; type = GL_TEXTURE_COORD_ARRAY_TYPE; break; case 13: get_enabled = GL_TEXTURE_COORD_ARRAY; get_size = GL_TEXTURE_COORD_ARRAY_SIZE; type = GL_TEXTURE_COORD_ARRAY_TYPE; break; case 14: get_enabled = GL_TEXTURE_COORD_ARRAY; get_size = GL_TEXTURE_COORD_ARRAY_SIZE; type = GL_TEXTURE_COORD_ARRAY_TYPE; break; case 15: get_enabled = GL_TEXTURE_COORD_ARRAY; get_size = GL_TEXTURE_COORD_ARRAY_SIZE; type = GL_TEXTURE_COORD_ARRAY_TYPE; break; } if (a>=8) { glClientActiveTexture(GL_TEXTURE0+a-8); } if (enabled == -1) enabled = glIsEnabled(get_enabled); if (size == -1) glGetIntegerv(get_size, &size); if (type == -1) glGetIntegerv(get_type, &type); f->attrib[a].enabled = enabled; f->attrib[a].size = size; f->attrib[a].type = type; } glClientActiveTexture(save_active_texture); } f->uses = 0; f->total_time = 0; f->next = NULL; return f; } static vertex_array_format* vertex_array_find_format(vertex_array_format* to_find) { vertex_array_format* f = format_list; while(f) { if(! memcmp(&f->attrib, &to_find->attrib, sizeof(f->attrib) ) ) { free(to_find); return f; } f = f->next; } // not found allocate new to_find->next = format_list; format_list = to_find; return to_find; } static void vertex_array_add(int num_elements, uint64_t time) { vertex_array_format *f, *g; f = vertex_array_get_format(); g = vertex_array_find_format(f); g->uses += num_elements; g->total_time += time; } static void (*rtld_fini_func)(void); static int compare(const void* a, const void* b) { int v1 = *(int*)(a); int v2 = *(int*)(b); return total_time[v1]uses; f = f->next; } f = format_list; while(f) { int a; for(a = 0 ; a < 16 ; a++) { if (f->attrib[a].enabled) { char type_name[4]; gl_type(f->attrib[a].type, type_name); printf("%d%s ",f->attrib[a].size,type_name); } else printf(" "); } printf("%10.5f\t%7.3f\t %d\n",f->total_time/(float)f->uses, f->uses*100.0/total_uses, f->uses); f = f->next; } } } /* Modify the __start function by overiding this function */ int __libc_start_main(int(*main_fct)(int, char **), int argc, char ** ubp_av,void (*init) (void), void (*fini) (void), void (*rtld_fini) (void),void (* stack_end)) { int (*func)(int(*)(int, char **), int, char **, void (*) (void), void (*) (void), void (*) (void), void(*)); func = dlsym(((void *) -1l), "__libc_start_main"); static int loaded=0; if (loaded) return; loaded=1; /* open library (NOTE: you may need to change this filename!) */ void* lib_handle_libGL = NULL; char* libGL_places[] = { "/usr/lib64/libGL.so.1", "/usr/lib64/mesa/libGL.so.1", "/usr/lib64/libGL.so", "/usr/lib/libGL.so.1", "/usr/lib/mesa/libGL.so.1", "/usr/lib/libGL.so", NULL }; int i = 0; while(!lib_handle_libGL && libGL_places[i]) { lib_handle_libGL = dlopen(libGL_places[i], RTLD_LAZY); i++; } if (!lib_handle_libGL){perror("Can't find host libGL");exit(0);} /* get the host getprocaddress function */ lib_glXGetProcAddressARB = dlsym(lib_handle_libGL, "glXGetProcAddressARB"); memset(total_time, 0, sizeof(total_time)); memset(total_time, 0, sizeof(total_calls)); functable_init(); // int r= func(main_fct, argc, ubp_av, init, fini, rtld_fini, stack_end); rtld_fini_func = rtld_fini; int r= func(main_fct, argc, ubp_av, init, fini, exit_func, stack_end); return r; }