forked from enlightenment/efl
311 lines
10 KiB
C
311 lines
10 KiB
C
#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;
|
|
int load_error;
|
|
|
|
if (o->cur->scene == scene) return;
|
|
|
|
evas_object_async_block(obj);
|
|
_evas_image_init_set(NULL, NULL, eo_obj, obj, o, &lo);
|
|
o->engine_data = ENFN->image_mmap(ENC, o->cur->f, o->cur->key, &load_error, &lo);
|
|
o->load_error = _evas_load_error_to_efl_gfx_image_load_error(load_error);
|
|
_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(const 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_Rw_Slice
|
|
_efl_canvas_scene3d_efl_gfx_buffer_buffer_map(Eo *eo_obj, void *_pd EINA_UNUSED,
|
|
Efl_Gfx_Buffer_Access_Mode mode,
|
|
const Eina_Rect *region,
|
|
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;
|
|
Eina_Rw_Slice slice = {};
|
|
int x, y, w, h;
|
|
size_t len = 0;
|
|
|
|
if (!o->cur->scene)
|
|
{
|
|
ERR("invalid scene data");
|
|
return slice;
|
|
}
|
|
if (mode & EFL_GFX_BUFFER_ACCESS_MODE_WRITE)
|
|
{
|
|
ERR("invalid map access mode");
|
|
return slice;
|
|
}
|
|
if (cspace != EFL_GFX_COLORSPACE_ARGB8888)
|
|
{
|
|
ERR("invalid map colorspace. Only ARGB is supported");
|
|
return slice;
|
|
}
|
|
|
|
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 (region)
|
|
{
|
|
x = region->x;
|
|
y = region->y;
|
|
w = region->w;
|
|
h = region->h;
|
|
}
|
|
else
|
|
{
|
|
x = y = 0;
|
|
w = width;
|
|
h = height;
|
|
}
|
|
|
|
if ((x < 0) || (y < 0) || (w <= 0) || (h <= 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 slice;
|
|
}
|
|
|
|
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 slice;
|
|
}
|
|
else
|
|
return slice;
|
|
|
|
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 slice;
|
|
}
|
|
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"
|