sung pushed a commit to branch master.
commit 3074280217f47b2cfd01708160aa2d83ddcb4de6
Author: Sung W. Park <[email protected]>
Date: Mon Jul 22 18:52:32 2013 +0900
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.
---
.../evas/engines/gl_common/evas_gl_common.h | 2 +
.../evas/engines/gl_common/evas_gl_context.c | 64 ++++++++++++++++++++++
src/modules/evas/engines/gl_x11/evas_engine.c | 45 ++++++++++++++-
3 files changed, 110 insertions(+), 1 deletion(-)
diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h
b/src/modules/evas/engines/gl_common/evas_gl_common.h
index 1f4f1fa..def6425 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_common.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_common.h
@@ -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);
diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c
b/src/modules/evas/engines/gl_common/evas_gl_context.c
index 777397a..d1b2c7e 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_context.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_context.c
@@ -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)
{
diff --git a/src/modules/evas/engines/gl_x11/evas_engine.c
b/src/modules/evas/engines/gl_x11/evas_engine.c
index 0f48b78..2bf934c 100644
--- a/src/modules/evas/engines/gl_x11/evas_engine.c
+++ b/src/modules/evas/engines/gl_x11/evas_engine.c
@@ -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);
}
--
------------------------------------------------------------------------------
See everything from the browser to the database with AppDynamics
Get end-to-end visibility with application monitoring from AppDynamics
Isolate bottlenecks and diagnose root cause in seconds.
Start your free trial of AppDynamics Pro today!
http://pubads.g.doubleclick.net/gampad/clk?id=48808831&iu=/4140/ostg.clktrk