From: Oleksandr Shcherbina Date: Fri, 3 Jun 2016 11:22:33 +0000 (+0300) Subject: evas: Get pixels from rendered 3D scene X-Git-Tag: upstream/1.20.0~6011 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=7e0601c98027a710e273fc2abe1dc2278a54a093;p=platform%2Fupstream%2Fefl.git evas: Get pixels from rendered 3D scene Summary: Implemented interface Efl.Gfx.Buffer functions bufer_map/unmap for Efl.Canvas3D.Scene. Added function e3d_drawable_texture_rendered_pixels_get to module evas_gl_3d to getting pixels from FBO. Added wrappers for functions e3d_drawable_texture_rendered_pixels_get and e3d_drawable_texture_id_get to have possibility call it through engine functions. Reviewers: cedric, Hermet, raster, jpeg Reviewed By: jpeg Subscribers: jpeg Differential Revision: https://phab.enlightenment.org/D3978 --- diff --git a/src/lib/evas/canvas/efl_canvas_scene3d.c b/src/lib/evas/canvas/efl_canvas_scene3d.c index d0623fe..c8ce097 100644 --- a/src/lib/evas/canvas/efl_canvas_scene3d.c +++ b/src/lib/evas/canvas/efl_canvas_scene3d.c @@ -208,4 +208,77 @@ _evas_image_3d_unset(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data EINA_COW_WRITE_END(evas_object_3d_cow, obj->data_3d, data); } +EOLIAN static void * +_efl_canvas_scene3d_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED, + int *length EINA_UNUSED, + Efl_Gfx_Buffer_Access_Mode mode, + int x, int y, int w, int h, + Efl_Gfx_Colorspace cspace, int *stride EINA_UNUSED) +{ + Evas_Image_Data *o = eo_data_scope_get(eo_obj, EVAS_IMAGE_CLASS); + Evas_Public_Data *e; + Evas_Canvas3D_Object_Data *pd_parent; + Evas_Canvas3D_Scene_Data *pd_scene; + int width = -1, height = -1, ntex = -1; + unsigned char *pixels = NULL; + + if (!o->cur->scene) + { + ERR("invalid scene data"); + return NULL; + } + if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE) + { + ERR("invalid map access mode"); + return NULL; + } + if (cspace != EFL_GFX_COLORSPACE_ARGB8888) + { + ERR("invalid map colorspace. Only ARGB is supported"); + return NULL; + } + + pd_parent = eo_data_scope_get(o->cur->scene, EVAS_CANVAS3D_OBJECT_CLASS); + e = eo_data_scope_get(pd_parent->evas, EVAS_CANVAS_CLASS); + pd_scene = eo_data_scope_get(o->cur->scene, EVAS_CANVAS3D_SCENE_CLASS); + + if (e->engine.func->drawable_size_get) + { + e->engine.func->drawable_size_get(e->engine.data.output, + pd_scene->surface, &width, &height); + } + + if ((x < 0) || (y < 0) || ((x + w) > width) || ((y + h) > height)) + { + ERR("Invalid map dimensions : %dx%d +%d,%d. Image is %dx%d.", + w, h, x, y, width, height); + return NULL; + } + + if (e->engine.func->drawable_texture_target_id_get) + { + ntex = e->engine.func->drawable_texture_target_id_get(pd_scene->surface); + + if (e->engine.func->drawable_texture_rendered_pixels_get) + { + pixels = malloc(w * h * sizeof(DATA32)); //four component texture + e->engine.func->drawable_texture_rendered_pixels_get(ntex, x, y, w, h, + pd_scene->surface, pixels); + } + else + return NULL; + } + else + return NULL; + + return pixels; +} +EOLIAN static Eina_Bool +_efl_canvas_scene3d_efl_gfx_buffer_buffer_unmap(Eo *eo_obj EINA_UNUSED, void *_pd EINA_UNUSED, + void *data, int length EINA_UNUSED) +{ + free(data); + return EINA_TRUE; +} + #include "efl_canvas_scene3d.eo.c" diff --git a/src/lib/evas/canvas/efl_canvas_scene3d.eo b/src/lib/evas/canvas/efl_canvas_scene3d.eo index b157587..4df2239 100644 --- a/src/lib/evas/canvas/efl_canvas_scene3d.eo +++ b/src/lib/evas/canvas/efl_canvas_scene3d.eo @@ -1,4 +1,4 @@ -class Efl.Canvas.Scene3d (Evas.Image) +class Efl.Canvas.Scene3d (Evas.Image, Efl.Gfx.Buffer) { [[A UI view for EFL Canvas 3D.]] data: null; @@ -15,4 +15,8 @@ class Efl.Canvas.Scene3d (Evas.Image) } } } + implements { + Efl.Gfx.Buffer.buffer_map; + Efl.Gfx.Buffer.buffer_unmap; + } } diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h index 9fc022d..fd34248 100644 --- a/src/lib/evas/include/evas_private.h +++ b/src/lib/evas/include/evas_private.h @@ -1464,11 +1464,12 @@ struct _Evas_Func void (*drawable_free) (void *data, void *drawable); void (*drawable_size_get) (void *data, void *drawable, int *w, int *h); void *(*image_drawable_set) (void *data, void *image, void *drawable); - + void (*drawable_texture_rendered_pixels_get) (unsigned int tex, int x, int y, int w, int h, void *drawable EINA_UNUSED, void *data); void (*drawable_scene_render) (void *data, void *drawable, void *scene_data); Eina_Bool (*drawable_scene_render_to_texture) (void *data, void *drawable, void *scene_data); int (*drawable_texture_color_pick_id_get) (void *drawable); + int (*drawable_texture_target_id_get) (void *drawable); void (*drawable_texture_pixel_color_get) (unsigned int tex EINA_UNUSED, int x, int y, Evas_Color *color, void *drawable); void *(*texture_new) (void *data, Eina_Bool use_atlas); diff --git a/src/modules/evas/engines/gl_common/evas_gl_3d.c b/src/modules/evas/engines/gl_common/evas_gl_3d.c index b3beb5c..404750a 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_3d.c +++ b/src/modules/evas/engines/gl_common/evas_gl_3d.c @@ -1440,6 +1440,53 @@ e3d_drawable_texture_pixel_color_get(GLuint tex EINA_UNUSED, int x, int y, glBindFramebuffer(GL_FRAMEBUFFER, d->fbo); } + +void +e3d_drawable_texture_rendered_pixels_get(GLuint tex EINA_UNUSED, int x, int y, int w, int h, + void *drawable EINA_UNUSED, void *data) +{ + DATA32 *buffer = (DATA32 *)data; + DATA32 *datarowup = NULL, *datarowlow = NULL; + DATA32 pixel; + int i, j, width = 0, up, bellow; + + glReadPixels(x, y, w, h, GL_RGBA, GL_UNSIGNED_BYTE, (GLubyte *)buffer); + + /*Due to returned pixels buffer filled as from the + bottom left of the screen going up to the top right*/ + datarowup = malloc(w * sizeof(DATA32)); + datarowlow = malloc(w * sizeof(DATA32)); + + if (!datarowup || !datarowlow) + { + ERR("Not enough memory"); + return; + } + for (j = 0; j < h / 2; j++) + { + bellow = h * w - width; + up = w + width; + + for (i = w; i >= 0; i--) + { + pixel = buffer[bellow]; + datarowlow[i] = ((pixel & 0x000000ff) << 16) + + ((pixel & 0x00ff0000) >> 16) + + ((pixel & 0xff00ff00)); + pixel = buffer[up]; + datarowup[i] = ((pixel & 0x000000ff) << 16) + + ((pixel & 0x00ff0000) >> 16) + + ((pixel & 0xff00ff00)); + bellow--; + up--; + } + memcpy(buffer + width, datarowlow, w * sizeof(DATA32)); + width += w; + memcpy(buffer + (h * w - width), datarowup, w * sizeof(DATA32)); + } + free(datarowup); + free(datarowlow); +} #undef CHECK_LOD_DISTANCE #undef RENDER_MESH_NODE_ITERATE_BEGIN #undef RENDER_MESH_NODE_ITERATE_END diff --git a/src/modules/evas/engines/gl_common/evas_gl_3d_common.h b/src/modules/evas/engines/gl_common/evas_gl_3d_common.h index d59fd7e..6f01d1a 100644 --- a/src/modules/evas/engines/gl_common/evas_gl_3d_common.h +++ b/src/modules/evas/engines/gl_common/evas_gl_3d_common.h @@ -31,9 +31,10 @@ Eina_Bool e3d_drawable_scene_render_to_texture(E3D_Drawable *drawable void e3d_drawable_size_get(E3D_Drawable *drawable, int *w, int *h); GLuint e3d_drawable_texture_id_get(E3D_Drawable *drawable); GLuint e3d_drawable_texture_color_pick_id_get(E3D_Drawable *drawable); -void e3d_drawable_texture_pixel_color_get(GLuint tex EINA_UNUSED, int x, int y, Evas_Color *color, void *drawable); +void e3d_drawable_texture_pixel_color_get(GLuint tex EINA_UNUSED, int x, int y, Evas_Color *color, void *drawable); GLenum e3d_drawable_format_get(E3D_Drawable *drawable); - +void e3d_drawable_texture_rendered_pixels_get(GLuint tex EINA_UNUSED, int x, int y, int w, int h, + void *drawable EINA_UNUSED, void *data); /* Renderer */ E3D_Renderer *e3d_renderer_new(void); void e3d_renderer_free(E3D_Renderer *renderer); diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c index ca8d839..8fae432 100644 --- a/src/modules/evas/engines/gl_generic/evas_engine.c +++ b/src/modules/evas/engines/gl_generic/evas_engine.c @@ -2368,6 +2368,12 @@ eng_drawable_scene_render(void *data, void *drawable, void *scene_data) } static int +eng_drawable_texture_target_id_get(void *drawable) +{ + return e3d_drawable_texture_id_get((E3D_Drawable *)drawable); +} + +static int eng_drawable_texture_color_pick_id_get(void *drawable) { return e3d_drawable_texture_color_pick_id_get((E3D_Drawable *)drawable); @@ -2397,6 +2403,12 @@ eng_drawable_scene_render_to_texture(void *data, void *drawable, void *scene_dat return e3d_drawable_scene_render_to_texture((E3D_Drawable *)drawable, renderer, scene_data); } +static void +eng_drawable_texture_rendered_pixels_get(GLuint tex EINA_UNUSED, int x, int y, + int w, int h, void *drawable EINA_UNUSED, void *data) +{ + e3d_drawable_texture_rendered_pixels_get(tex, x, y, w, h, drawable, data); +} static void * eng_texture_new(void *data EINA_UNUSED, Eina_Bool use_atlas) { @@ -2921,9 +2933,10 @@ module_open(Evas_Module *em) ORD(drawable_scene_render); ORD(drawable_texture_color_pick_id_get); + ORD(drawable_texture_target_id_get); ORD(drawable_texture_pixel_color_get); ORD(drawable_scene_render_to_texture); - + ORD(drawable_texture_rendered_pixels_get); ORD(texture_new); ORD(texture_free); ORD(texture_size_get); diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c index f67e694..399430c 100644 --- a/src/modules/evas/engines/software_generic/evas_engine.c +++ b/src/modules/evas/engines/software_generic/evas_engine.c @@ -4524,7 +4524,9 @@ static Evas_Func func = NULL, // eng_drawable_scene_render NULL, // eng_drawable_scene_render_to_texture NULL, // eng_drawable_texture_color_pick_id_get + NULL, // end_drawable_texture_target_id_get NULL, // eng_drawable_texture_pixel_color_get + NULL, // end_drawable_texture_rendered_pixels_get NULL, // eng_texture_new NULL, // eng_texture_free NULL, // eng_texture_size_get