Evas: adding image dump debug feature for gl_x11 backend

Added a feature to dump out a png image before calling SwapBuffers.
To turn on the feature, use the following env vars.

EVAS_GL_SWAP_BUFFER_DEBUG_DIR="dir_name" sets the name of the directory
that the files will be output to and enables the debug mode.

EVAS_GL_SWAP_BUFFER_DEBUG_ALWAYS=1 will enable the writing of the
files every frame.  This in effect turns on the swap_buffer_debug
variable, which can be set on or off in gdb for debugging.  This will
allow dumping of certain frames without having to dump out a ton of
files to track down one frame.
This commit is contained in:
Sung W. Park 2013-07-22 18:52:32 +09:00
parent 79851b4762
commit 3074280217
3 changed files with 110 additions and 1 deletions

View File

@ -747,6 +747,8 @@ void evas_gl_common_poly_draw(Evas_Engine_GL_Context *gc, Evas_GL_P
void evas_gl_common_line_draw(Evas_Engine_GL_Context *gc, int x1, int y1, int x2, int y2);
int evas_gl_common_buffer_dump(Evas_Engine_GL_Context *gc, const char* dname, const char* fname, int frame);
extern void (*glsym_glGenFramebuffers) (GLsizei a, GLuint *b);
extern void (*glsym_glBindFramebuffer) (GLenum a, GLuint b);
extern void (*glsym_glFramebufferTexture2D) (GLenum a, GLenum b, GLenum c, GLuint d, GLint e);

View File

@ -3185,6 +3185,70 @@ shader_array_flush(Evas_Engine_GL_Context *gc)
gc->havestuff = EINA_FALSE;
}
int
evas_gl_common_buffer_dump(Evas_Engine_GL_Context *gc, const char* dname, const char* buf_name, int frame)
{
RGBA_Image *im = NULL;
DATA32 *data1, *data2;
char fname[100];
int ok = 0;
sprintf(fname, "./%s/evas_win_%s-fc_%03d.png", dname, buf_name, frame);
data1 = (DATA32 *)malloc(gc->w * gc->h * sizeof(DATA32));
data2 = (DATA32 *)malloc(gc->w * gc->h * sizeof(DATA32));
if ((!data1) || (!data2)) goto finish;
glReadPixels(0, 0, gc->w, gc->h, GL_RGBA,
GL_UNSIGNED_BYTE, (unsigned char*)data1);
// Flip the Y and change from RGBA TO BGRA
int i, j;
for (j = 0; j < gc->h; j++)
for (i = 0; i < gc->w; i++)
{
DATA32 d;
int idx1 = (j * gc->w) + i;
int idx2 = ((gc->h - 1) - j) * gc->w + i;
d = data1[idx1];
data2[idx2] = ((d & 0x000000ff) << 16) +
((d & 0x00ff0000) >> 16) +
((d & 0xff00ff00));
}
evas_common_convert_argb_premul(data2, gc->w * gc->h);
im = (RGBA_Image*) evas_cache_image_data(evas_common_image_cache_get(),
gc->w,
gc->h,
(DATA32 *)data2,
1,
EVAS_COLORSPACE_ARGB8888);
if (im)
{
im->image.data = data2;
if (im->image.data)
{
ok = evas_common_save_image_to_file(im, fname, NULL, 0, 0);
if (!ok) ERR("Error Saving file.");
}
evas_cache_image_drop(&im->cache_entry);
}
finish:
if (data1) free(data1);
if (data2) free(data2);
if (im) evas_cache_image_drop(&im->cache_entry);
if (ok) return 1;
else return 0;
}
Eina_Bool
evas_gl_common_module_open(void)
{

View File

@ -26,6 +26,8 @@ enum {
static int partial_render_debug = -1;
static int partial_rect_union_mode = -1;
static int swap_buffer_debug_mode = -1;
static int swap_buffer_debug = 0;
enum {
MODE_FULL,
@ -52,6 +54,7 @@ struct _Render_Engine
int vsync;
int lost_back;
int prev_age;
int frame_cnt;
Eina_Bool evgl_initted : 1;
struct {
@ -1472,6 +1475,8 @@ static void
eng_output_flush(void *data, Evas_Render_Mode render_mode)
{
Render_Engine *re;
static char *dname = NULL;
re = (Render_Engine *)data;
if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) goto end;
@ -1482,7 +1487,42 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode)
re->win->draw.drew = 0;
eng_window_use(re->win);
evas_gl_common_context_done(re->win->gl_context);
// Save contents of the framebuffer to a file
if (swap_buffer_debug_mode == -1)
{
if ((dname = getenv("EVAS_GL_SWAP_BUFFER_DEBUG_DIR")))
{
int stat;
// Create a directory with 0775 permission
stat = mkdir(dname, S_IRWXU|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
if ((!stat) || errno == EEXIST) swap_buffer_debug_mode = 1;
}
else
swap_buffer_debug_mode = 0;
}
if (swap_buffer_debug_mode == 1)
{
// Set this env var to dump files every frame
// Or set the global var in gdb to 1|0 to turn it on and off
if (getenv("EVAS_GL_SWAP_BUFFER_DEBUG_ALWAYS"))
swap_buffer_debug = 1;
if (swap_buffer_debug)
{
char fname[100];
int ret = 0;
sprintf(fname, "%p", (void*)re->win);
ret = evas_gl_common_buffer_dump(re->win->gl_context,
(const char*)dname,
(const char*)fname,
re->frame_cnt);
if (!ret) swap_buffer_debug_mode = 0;
}
}
#ifdef GL_GLES
if (!re->vsync)
{
@ -1552,6 +1592,7 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode)
}
else
eglSwapBuffers(re->win->egl_disp, re->win->egl_surface[0]);
//xx if (!safe_native) eglWaitGL();
if (re->info->callback.post_swap)
{
@ -1615,6 +1656,8 @@ eng_output_flush(void *data, Evas_Render_Mode render_mode)
re->rects = NULL;
}
re->frame_cnt++;
end:
evas_gl_preload_render_unlock(eng_preload_make_current, re);
}