aboutsummaryrefslogblamecommitdiffstats
path: root/src/lib/evas/canvas/efl_canvas_scene3d.c
blob: 26019404593356bfb3606f32d687428220c2e58d (plain) (tree)
1
2
3
4
5
6
7
8
9
10







                                                                                             

                                                                                         





                                                               
                                                                                            








                                                                 
                                                                                    



                        
                                                      
                                                                                      
                                                                             





                                              
                                                                   







                                                           
                                                   







                                              
                                                      





                                                                          
                                                       











                                                                   
                                                   
                                                                         











                                                                              
                                                              

                                                                          













                                                              





                                                   
                                                                                         
      















                                                                                 
                                                             








                                                                              


                                                                                         






                                                                               
                       




















                                                                                      
                                                                   



                                                                      
                                      



















                                                                              
                                                                             







                                                              
                       
                                                                                




                                                                                   
 
                                                                                    




                                          





                                                     



                                  
                          



                                               
                          



                                                              
                          

      


                                                                             


                                         
                                                                   






                                                                               
                          







                                                                                 

                                                                   



                                                                                             
                            

       
                       
 






                                                            


                                                                                              
                                                                           
 
                    


                    
                                  
#include "evas_image_private.h"
#include "efl_canvas_scene3d.eo.h"

#define MY_CLASS EFL_CANVAS_SCENE3D_CLASS

EOLIAN static void
_efl_canvas_scene3d_scene3d_set(Eo *eo_obj, void *pd EINA_UNUSED, Evas_Canvas3D_Scene *scene)
{
   Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
   Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
   Evas_Image_Load_Opts lo;

   if (o->cur->scene == scene) return;

   evas_object_async_block(obj);
   _evas_image_init_set(NULL, NULL, NULL, eo_obj, obj, o, &lo);
   o->engine_data = ENFN->image_load(ENC, o->cur->u.file, o->cur->key, &o->load_error, &lo);
   _evas_image_done_set(eo_obj, obj, o);

   if (scene) _evas_image_3d_set(eo_obj, scene);
   else _evas_image_3d_unset(eo_obj, obj, o);
}

EOLIAN static Evas_Canvas3D_Scene *
_efl_canvas_scene3d_scene3d_get(Eo *eo_obj, void *pd EINA_UNUSED)
{
   Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
   return o->cur->scene;
}

void
_evas_image_3d_render(Evas *eo_e, Evas_Object *eo_obj,
                      Evas_Object_Protected_Data *obj, Evas_Image_Data *o EINA_UNUSED,
                      Evas_Canvas3D_Scene *scene, void *engine, void *output)
{
   Evas_Public_Data *e;
   Eina_Bool need_native_set = EINA_FALSE;
   Evas_Canvas3D_Scene_Public_Data scene_data;
   Evas_Canvas3D_Scene_Data *pd_scene = NULL;

   pd_scene = efl_data_scope_get(scene, EVAS_CANVAS3D_SCENE_CLASS);

   if ((pd_scene->w == 0) || (pd_scene->h == 0)) return;
   if (!pd_scene->camera_node)
     {
        WRN("Camera has not been set to scene(%p)", scene);
        return;
     }

   e = efl_data_scope_get(eo_e, EVAS_CANVAS_CLASS);

   if (pd_scene->surface)
     {
        int w = 0;
        int h = 0;

        if (e->engine.func->drawable_size_get)
          {
             e->engine.func->drawable_size_get(engine,
                                               pd_scene->surface, &w, &h);
          }
        if ((w != pd_scene->w) || (h != pd_scene->h))
          {
             if (e->engine.func->drawable_free)
               {
                  e->engine.func->drawable_free(engine,
                                                pd_scene->surface);
               }
             pd_scene->surface = NULL;
             need_native_set = EINA_TRUE;
          }
     }
   else
     {
        /* TODO: Hard-coded alpha on. */
        if (e->engine.func->drawable_new)
          {
             pd_scene->surface =
               e->engine.func->drawable_new(engine,
                                            pd_scene->w, pd_scene->h, 1);
          }
        need_native_set = EINA_TRUE;
     }

   EINA_COW_WRITE_BEGIN(evas_object_3d_cow, obj->data_3d, Evas_Object_3D_Data,
                        data)
     {
        if (need_native_set)
          {
             if (e->engine.func->image_drawable_set)
               {
                  data->surface =
                    e->engine.func->image_drawable_set(engine,
                                                       data->surface,
                                                       pd_scene->surface);
               }
          }
        data->w = pd_scene->w;
        data->h = pd_scene->h;
     }
   EINA_COW_WRITE_END(evas_object_3d_cow, obj->data_3d, data);

   evas_canvas3d_scene_data_init(&scene_data);

   scene_data.bg_color = pd_scene->bg_color;
   scene_data.shadows_enabled = pd_scene->shadows_enabled;
   scene_data.camera_node = pd_scene->camera_node;
   scene_data.depth_offset = pd_scene->depth_offset;
   scene_data.depth_constant = pd_scene->depth_constant;
   if (evas_object_anti_alias_get(eo_obj))
     {
        /*Use post processing render*/
        scene_data.post_processing = EINA_TRUE;
        scene_data.color_pick_enabled = EINA_FALSE;
        scene_data.render_to_texture = EINA_TRUE;
        scene_data.post_processing_type = EVAS_CANVAS3D_SHADER_MODE_POST_PROCESSING_FXAA;
     }
   /* Phase 1 - Update scene graph tree. */
   evas_canvas3d_object_update(scene);

   /* Phase 2 - Do frustum culling and get visible model nodes. */
   evas_canvas3d_node_tree_traverse(pd_scene->root_node,
                              EVAS_CANVAS3D_TREE_TRAVERSE_LEVEL_ORDER, EINA_TRUE,
                              evas_canvas3d_node_mesh_collect, &scene_data);

   /* Phase 3 - Collect active light nodes in the scene graph tree. */
   evas_canvas3d_node_tree_traverse(pd_scene->root_node,
                              EVAS_CANVAS3D_TREE_TRAVERSE_ANY_ORDER, EINA_FALSE,
                              evas_canvas3d_node_light_collect, &scene_data);

   /* Phase 5 - Draw the scene. */
   if (e->engine.func->drawable_scene_render)
     {
        e->engine.func->drawable_scene_render(engine, output,
                                              pd_scene->surface, &scene_data);
     }
   /* Clean up temporary resources. */
   evas_canvas3d_scene_data_fini(&scene_data);
}

void
_evas_image_3d_set(Evas_Object *eo_obj, Evas_Canvas3D_Scene *scene)
{
   Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
   Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_CLASS);
   Evas_Canvas3D_Scene_Data *pd_scene = efl_data_scope_get(scene,
                                                    EVAS_CANVAS3D_SCENE_CLASS);
   EINA_COW_WRITE_BEGIN(evas_object_3d_cow, obj->data_3d, Evas_Object_3D_Data,
                        data)
     {
        data->surface = NULL;
        data->w = 0;
        data->h = 0;
        efl_ref(scene);
     }
   EINA_COW_WRITE_END(evas_object_3d_cow, obj->data_3d, data);

   EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
     {
        state_write->scene = scene;
     }
   EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);

   pd_scene->images = eina_list_append(pd_scene->images, eo_obj);
}

void
_evas_image_3d_unset(Evas_Object *eo_obj EINA_UNUSED, Evas_Object_Protected_Data *obj,
                     Evas_Image_Data *o)
{
   Evas_Public_Data *e;

   if (!o->cur->scene) return;

   Evas_Canvas3D_Scene_Data *pd_scene =
      efl_data_scope_get(o->cur->scene, EVAS_CANVAS3D_SCENE_CLASS);

   EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
     {
        pd_scene->images = eina_list_remove(pd_scene->images, eo_obj);
        efl_unref(state_write->scene);
        state_write->scene = NULL;
     }
   EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);

   if (o->cur->defmap)
     {
        EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
          {
             evas_map_free(state_write->defmap);
             state_write->defmap = NULL;
          }
        EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
     }

   EINA_COW_WRITE_BEGIN(evas_object_3d_cow, obj->data_3d, Evas_Object_3D_Data,
                        data)
     {
        e = obj->layer->evas;

        if (data->surface)
          e->engine.func->image_free(_evas_engine_context(e), data->surface);

        data->surface = NULL;
        data->w = 0;
        data->h = 0;
     }
   EINA_COW_WRITE_END(evas_object_3d_cow, obj->data_3d, data);
}

EOLIAN static Eina_Bool
_efl_canvas_scene3d_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
                                              Eina_Rw_Slice *slice,
                                              Efl_Gfx_Buffer_Access_Mode mode,
                                              int x, int y, int w, int h,
                                              Efl_Gfx_Colorspace cspace, int plane,
                                              int *stride)
{
   Evas_Image_Data *o = efl_data_scope_get(eo_obj, EFL_CANVAS_IMAGE_INTERNAL_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;
   size_t len = 0;

   EINA_SAFETY_ON_NULL_RETURN_VAL(slice, EINA_FALSE);

   slice->len = 0;
   slice->mem = NULL;

   if (!o->cur->scene)
     {
        ERR("invalid scene data");
        return EINA_FALSE;
     }
   if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE)
     {
        ERR("invalid map access mode");
        return EINA_FALSE;
     }
   if (cspace != EFL_GFX_COLORSPACE_ARGB8888)
     {
        ERR("invalid map colorspace. Only ARGB is supported");
        return EINA_FALSE;
     }

   pd_parent = efl_data_scope_get(o->cur->scene, EVAS_CANVAS3D_OBJECT_CLASS);
   e = efl_data_scope_get(pd_parent->evas, EVAS_CANVAS_CLASS);
   pd_scene = efl_data_scope_get(o->cur->scene, EVAS_CANVAS3D_SCENE_CLASS);

   if (e->engine.func->drawable_size_get)
      {
         e->engine.func->drawable_size_get(_evas_engine_context(e),
                                           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 EINA_FALSE;
     }

   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)
          {
             len = w * h * sizeof(DATA32); //four component texture
             pixels = malloc(len + sizeof(*slice) + 8);
             e->engine.func->drawable_texture_rendered_pixels_get(ntex, x, y, w, h,
                                                                  pd_scene->surface, pixels);
          }
        else
          return EINA_FALSE;
     }
   else
     return EINA_FALSE;

   if (stride) *stride = w * sizeof(DATA32);
   slice->mem = pixels;
   slice->len = len;
   DBG("map(%p, %d,%d %dx%d plane:%d) -> " EINA_SLICE_FMT,
       eo_obj, x, y, w, h, plane, EINA_SLICE_PRINT(*slice));

   return EINA_TRUE;
}
EOLIAN static Eina_Bool
_efl_canvas_scene3d_efl_gfx_buffer_buffer_unmap(Eo *eo_obj EINA_UNUSED, void *_pd EINA_UNUSED,
                                                const Eina_Rw_Slice *slice)
{
   free(slice->mem);
   return EINA_TRUE;
}

#include "efl_canvas_scene3d.eo.c"