devilhorns pushed a commit to branch master. http://git.enlightenment.org/core/efl.git/commit/?id=c403035e1d571b6b5a9137c92578723b810f44e5
commit c403035e1d571b6b5a9137c92578723b810f44e5 Author: Chris Michael <cp.mich...@samsung.com> Date: Mon Mar 10 10:02:31 2014 +0000 ecore-evas-drm: Add initial code to make ecore_evas render using drm NB: This is still a work-in-progress and not complete yet Signed-off-by: Chris Michael <cp.mich...@samsung.com> --- .../ecore_evas/engines/drm/ecore_evas_drm.c | 335 +++++++++++++++++++-- 1 file changed, 318 insertions(+), 17 deletions(-) diff --git a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c index 4cf2370..78dc495 100644 --- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c +++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c @@ -14,10 +14,10 @@ #include "ecore_evas_private.h" #include "ecore_evas_drm.h" -#ifdef BUILD_ECORE_EVAS_DRM +//#ifdef BUILD_ECORE_EVAS_DRM # include <Evas_Engine_Drm.h> # include <Ecore_Drm.h> -#endif +//#endif /* local structures */ typedef struct _Ecore_Evas_Engine_Data_Drm Ecore_Evas_Engine_Data_Drm; @@ -32,17 +32,27 @@ static int _ecore_evas_drm_init(void); static int _ecore_evas_drm_shutdown(void); static Ecore_Evas_Interface_Drm *_ecore_evas_drm_interface_new(void); +static void _ecore_evas_drm_free(Ecore_Evas *ee); +static void _ecore_evas_drm_delete_request_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func); +static void _ecore_evas_drm_resize(Ecore_Evas *ee, int w, int h); +static void _ecore_evas_drm_show(Ecore_Evas *ee); +static void _ecore_evas_drm_hide(Ecore_Evas *ee); +static int _ecore_evas_drm_render(Ecore_Evas *ee); +static void _ecore_evas_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event); +static int _ecore_evas_drm_render_updates_process(Ecore_Evas *ee, Eina_List *updates); + /* local variables */ static int _ecore_evas_init_count = 0; +static Ecore_Drm_Device *dev = NULL; static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func = { - NULL, //void (*fn_free) (Ecore_Evas *ee); + _ecore_evas_drm_free, NULL, //void (*fn_callback_resize_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); NULL, //void (*fn_callback_move_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); NULL, //void (*fn_callback_show_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); NULL, //void (*fn_callback_hide_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); - NULL, //void (*fn_callback_delete_request_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); + _ecore_evas_drm_delete_request_set, NULL, //void (*fn_callback_destroy_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); NULL, //void (*fn_callback_focus_in_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); NULL, //void (*fn_callback_focus_out_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); @@ -54,12 +64,12 @@ static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func = NULL, //void (*fn_callback_post_render_set) (Ecore_Evas *ee, Ecore_Evas_Event_Cb func); NULL, //void (*fn_move) (Ecore_Evas *ee, int x, int y); NULL, //void (*fn_managed_move) (Ecore_Evas *ee, int x, int y); - NULL, //void (*fn_resize) (Ecore_Evas *ee, int w, int h); + _ecore_evas_drm_resize, NULL, //void (*fn_move_resize) (Ecore_Evas *ee, int x, int y, int w, int h); NULL, //void (*fn_rotation_set) (Ecore_Evas *ee, int rot, int resize); NULL, //void (*fn_shaped_set) (Ecore_Evas *ee, int shaped); - NULL, //void (*fn_show) (Ecore_Evas *ee); - NULL, //void (*fn_hide) (Ecore_Evas *ee); + _ecore_evas_drm_show, + _ecore_evas_drm_hide, NULL, //void (*fn_raise) (Ecore_Evas *ee); NULL, //void (*fn_lower) (Ecore_Evas *ee); NULL, //void (*fn_activate) (Ecore_Evas *ee); @@ -93,7 +103,8 @@ static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func = NULL, //void (*fn_demands_attention_set) (Ecore_Evas *ee, Eina_Bool on); NULL, //void (*fn_focus_skip_set) (Ecore_Evas *ee, Eina_Bool on); - NULL, //int (*fn_render) (Ecore_Evas *ee); + _ecore_evas_drm_render, + NULL, //void (*fn_screen_geometry_get) (const Ecore_Evas *ee, int *x, int *y, int *w, int *h); NULL, //void (*fn_screen_dpi_get) (const Ecore_Evas *ee, int *xdpi, int *ydpi); NULL, //void (*fn_msg_parent_send) (Ecore_Evas *ee, int maj, int min, void *data, int size); @@ -114,6 +125,8 @@ EAPI Ecore_Evas * ecore_evas_drm_new_internal(const char *device, unsigned int parent, int x, int y, int w, int h) { Ecore_Evas *ee; + Evas_Engine_Info_Drm *einfo; + Ecore_Evas_Interface_Drm *iface; int method; /* try to find the evas drm engine */ @@ -123,41 +136,329 @@ ecore_evas_drm_new_internal(const char *device, unsigned int parent, int x, int return NULL; } + /* try to init drm */ + if (_ecore_evas_drm_init() < 1) return NULL; + /* try to allocate space for new ecore_evas */ if (!(ee = calloc(1, sizeof(Ecore_Evas)))) { ERR("Failed to allocate space for new Ecore_Evas"); - return NULL; + goto ee_err; } ECORE_MAGIC_SET(ee, ECORE_MAGIC_EVAS); - /* try to init drm */ + ee->engine.func = (Ecore_Evas_Engine_Func *)&_ecore_evas_drm_engine_func; + + iface = _ecore_evas_drm_interface_new(); + ee->engine.ifaces = eina_list_append(ee->engine.ifaces, iface); + + /* set some engine properties */ + ee->driver = "drm"; + if (device) ee->name = strdup(device); + + if (w < 1) w = 1; + if (h < 1) h = 1; + + ee->x = ee->req.x = x; + ee->y = ee->req.y = y; + ee->w = ee->req.w = w; + ee->h = ee->req.h = h; + + ee->prop.max.w = 32767; + ee->prop.max.h = 32767; + ee->prop.layer = 4; + ee->prop.request_pos = 0; + ee->prop.sticky = 0; + ee->alpha = EINA_FALSE; + + ee->can_async_render = 1; + if (getenv("ECORE_EVAS_FORCE_SYNC_RENDER")) + ee->can_async_render = 0; + + /* try to initialize evas */ + ee->evas = evas_new(); + evas_data_attach_set(ee->evas, ee); + evas_output_method_set(ee->evas, method); + + /* FIXME: Support initial rotation ?? */ + evas_output_size_set(ee->evas, w, h); + evas_output_viewport_set(ee->evas, 0, 0, w, h); + + if (ee->can_async_render) + evas_event_callback_add(ee->evas, EVAS_CALLBACK_RENDER_POST, + _ecore_evas_drm_render_updates, ee); + + if ((einfo = (Evas_Engine_Info_Drm *)evas_engine_info_get(ee->evas))) + { + einfo->info.depth = 32; // FIXME + einfo->info.destination_alpha = ee->alpha; + einfo->info.rotation = ee->rotation; + einfo->info.vsync = EINA_FALSE; + einfo->info.use_hw_accel = EINA_FALSE; + einfo->info.fd = ecore_drm_device_fd_get(dev); + einfo->info.tty = ecore_drm_tty_get(dev); + + if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) + { + ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver); + goto eng_err; + } + } + else + { + ERR("Failed to get Evas Engine Info for '%s'", ee->driver); + goto eng_err; + } + + _ecore_evas_register(ee); + ecore_evas_input_event_register(ee); return ee; + +eng_err: + ecore_evas_free(ee); +ee_err: + _ecore_evas_drm_shutdown(); + return NULL; } /* local functions */ static int _ecore_evas_drm_init(void) { - _ecore_evas_init_count++; - if (_ecore_evas_init_count > 1) return _ecore_evas_init_count; + if (++_ecore_evas_init_count != 1) return _ecore_evas_init_count; + + /* try to init ecore_drm */ + if (!ecore_drm_init()) + { + ERR("Could not initialize Ecore_Drm"); + return --_ecore_evas_init_count; + } + + /* try to find the device */ + if (!(dev = ecore_drm_device_find(NULL, NULL))) + { + ERR("Could not find default drm device"); + goto dev_err; + } + + /* try to open the graphics card */ + if (!ecore_drm_device_open(dev)) + { + ERR("Could not open drm device"); + goto dev_open_err; + } + + /* try to open the tty */ + if (!ecore_drm_tty_open(dev, NULL)) + { + ERR("Could not open tty: %m"); + goto tty_open_err; + } + + /* FIXME: Init egl/software renderer here ?? */ + + /* try to create sprites */ + if (!ecore_drm_sprites_create(dev)) + { + ERR("Could not create sprites: %m"); + goto sprite_err; + } + + /* try to create outputs */ + if (!ecore_drm_outputs_create(dev)) + { + ERR("Could not create outputs: %m"); + goto output_err; + } + + /* try to create inputs */ + if (!ecore_drm_inputs_create(dev)) + { + ERR("Could not create inputs: %m"); + goto output_err; + } ecore_event_evas_init(); return _ecore_evas_init_count; + +output_err: + ecore_drm_sprites_destroy(dev); +sprite_err: + ecore_drm_tty_close(dev); +tty_open_err: + ecore_drm_device_close(dev); +dev_open_err: + ecore_drm_device_free(dev); +dev_err: + ecore_drm_shutdown(); + return --_ecore_evas_init_count; } static int _ecore_evas_drm_shutdown(void) { - _ecore_evas_init_count--; - if (_ecore_evas_init_count == 0) + if (--_ecore_evas_init_count != 0) return _ecore_evas_init_count; + + ecore_drm_sprites_destroy(dev); + /* NB: No need to free outputs here. Is done in device free */ + ecore_drm_inputs_destroy(dev); + ecore_drm_tty_close(dev); + ecore_drm_device_close(dev); + ecore_drm_device_free(dev); + ecore_drm_shutdown(); + + ecore_event_evas_shutdown(); + + return _ecore_evas_init_count; +} + +static Ecore_Evas_Interface_Drm * +_ecore_evas_drm_interface_new(void) +{ + Ecore_Evas_Interface_Drm *iface; + + if (!(iface = calloc(1, sizeof(Ecore_Evas_Interface_Drm)))) + return NULL; + + iface->base.name = "drm"; + iface->base.version = 1; + + /* iface->pixmap_visual_get; */ + /* iface->pixmap_colormap_get; */ + /* iface->pixmap_depth_get; */ + + return iface; +} + +/* local ecore_evas functions */ +static void +_ecore_evas_drm_free(Ecore_Evas *ee) +{ + ecore_evas_input_event_unregister(ee); + _ecore_evas_drm_shutdown(); +} + +static void +_ecore_evas_drm_delete_request_set(Ecore_Evas *ee, Ecore_Evas_Event_Cb func) +{ + ee->func.fn_delete_request = func; +} + +static void +_ecore_evas_drm_resize(Ecore_Evas *ee, int w, int h) +{ + ee->req.w = w; + ee->req.h = h; + if ((ee->w == w) && (ee->h == h)) return; + ee->w = w; + ee->h = h; + evas_output_size_set(ee->evas, w, h); + evas_output_viewport_set(ee->evas, 0, 0, w, h); + if (ee->func.fn_resize) ee->func.fn_resize(ee); +} + +static void +_ecore_evas_drm_show(Ecore_Evas *ee) +{ + if ((!ee) || (ee->visible)) return; + evas_damage_rectangle_add(ee->evas, 0, 0, ee->w, ee->h); + ee->visible = 1; + if (ee->func.fn_show) ee->func.fn_show(ee); +} + +static void +_ecore_evas_drm_hide(Ecore_Evas *ee) +{ + if ((!ee) || (!ee->visible)) return; + evas_sync(ee->evas); + ee->visible = 0; + ee->should_be_visible = 0; + if (ee->func.fn_hide) ee->func.fn_hide(ee); +} + +static int +_ecore_evas_drm_render(Ecore_Evas *ee) +{ + int rend = 0; + Eina_List *l; + Ecore_Evas *ee2; + + if (ee->in_async_render) return 0; + + if (!ee->visible) { - ecore_event_evas_shutdown(); + evas_norender(ee->evas); + return 0; } - if (_ecore_evas_init_count < 0) _ecore_evas_init_count = 0; - return _ecore_evas_init_count; + EINA_LIST_FOREACH(ee->sub_ecore_evas, l, ee2) + { + if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2); + if (ee2->engine.func->fn_render) + rend |= ee2->engine.func->fn_render(ee2); + if (ee2->func.fn_post_render) ee2->func.fn_post_render(ee2); + } + + if (ee->func.fn_pre_render) ee->func.fn_pre_render(ee); + + if (!ee->can_async_render) + { + Eina_List *updates; + + updates = evas_render_updates(ee->evas); + rend = _ecore_evas_drm_render_updates_process(ee, updates); + evas_render_updates_free(updates); + } + else if (evas_render_async(ee->evas)) + { + ee->in_async_render = EINA_TRUE; + rend = 1; + } + + return rend; +} + +static void +_ecore_evas_drm_render_updates(void *data, Evas *evas EINA_UNUSED, void *event) +{ + Evas_Event_Render_Post *ev; + Ecore_Evas *ee; + + if (!(ev = event)) return; + if (!(ee = data)) return; + + ee->in_async_render = EINA_FALSE; + + _ecore_evas_drm_render_updates_process(ee, ev->updated_area); + + /* TODO: handle delayed changes */ +} + +static int +_ecore_evas_drm_render_updates_process(Ecore_Evas *ee, Eina_List *updates) +{ + int rend = 0; + + if ((ee->visible) && (updates)) + { + Eina_List *l = NULL; + Eina_Rectangle *r; + + EINA_LIST_FOREACH(updates, l, r) + { + /* TODO */ + } + + _ecore_evas_idle_timeout_update(ee); + rend = 1; + } + else + evas_norender(ee->evas); + + if (ee->func.fn_post_render) ee->func.fn_post_render(ee); + + return rend; } --