nikawhite pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=7e0601c98027a710e273fc2abe1dc2278a54a093

commit 7e0601c98027a710e273fc2abe1dc2278a54a093
Author: Oleksandr Shcherbina <o.shcherb...@samsung.com>
Date:   Fri Jun 3 14:22:33 2016 +0300

    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
---
 src/lib/evas/canvas/efl_canvas_scene3d.c           | 73 ++++++++++++++++++++++
 src/lib/evas/canvas/efl_canvas_scene3d.eo          |  6 +-
 src/lib/evas/include/evas_private.h                |  3 +-
 src/modules/evas/engines/gl_common/evas_gl_3d.c    | 47 ++++++++++++++
 .../evas/engines/gl_common/evas_gl_3d_common.h     |  5 +-
 src/modules/evas/engines/gl_generic/evas_engine.c  | 15 ++++-
 .../evas/engines/software_generic/evas_engine.c    |  2 +
 7 files changed, 146 insertions(+), 5 deletions(-)

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

-- 


Reply via email to