diff --git a/m4/evas_check_engine.m4 b/m4/evas_check_engine.m4 index 448a210592..4789d4b9f0 100644 --- a/m4/evas_check_engine.m4 +++ b/m4/evas_check_engine.m4 @@ -597,16 +597,23 @@ AC_DEFUN([EVAS_CHECK_ENGINE_DEP_DRM], [ requirement="" -have_dep="yes" +have_dep="no" have_hw_dep="no" evas_engine_[]$1[]_cflags="" evas_engine_[]$1[]_libs="" +PKG_CHECK_EXISTS([libdrm], + [ + have_dep="yes" + requirement="libdrm" + ], [have_dep="no"]) + if test "x${have_dep}" = "xyes" ; then if test "x$3" = "xstatic" ; then requirements_pc_evas="${requirement} ${requirements_pc_evas}" requirements_pc_deps_evas="${requirement} ${requirements_pc_deps_evas}" else + PKG_CHECK_MODULES([DRM], [${requirement}]) evas_engine_[]$1[]_cflags="${DRM_CFLAGS}" evas_engine_[]$1[]_libs="${DRM_LIBS}" fi @@ -636,10 +643,10 @@ else AC_MSG_ERROR([We currently do not support GL DRM without OpenGL ES. Please consider OpenGL ES if you want to use it.]) fi -PKG_CHECK_EXISTS([egl ${gl_library} gbm wayland-client >= REQUIRED_WAYLAND_VERSION], +PKG_CHECK_EXISTS([egl ${gl_library} libdrm gbm wayland-client >= REQUIRED_WAYLAND_VERSION], [ have_dep="yes" - requirement="egl ${gl_library} gbm wayland-client >= REQUIRED_WAYLAND_VERSION" + requirement="egl ${gl_library} libdrm gbm wayland-client >= REQUIRED_WAYLAND_VERSION" ], [have_dep="no"]) diff --git a/src/Makefile_Evas.am b/src/Makefile_Evas.am index daa11b8a86..19fea04991 100644 --- a/src/Makefile_Evas.am +++ b/src/Makefile_Evas.am @@ -1276,7 +1276,6 @@ endif endif if BUILD_ENGINE_DRM -dist_installed_evasmainheaders_DATA += modules/evas/engines/drm/Evas_Engine_Drm.h DRM_SOURCES = \ modules/evas/engines/drm/evas_outbuf.c \ modules/evas/engines/drm/evas_engine.c \ @@ -1301,20 +1300,19 @@ modules_evas_engines_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ -I$(top_srcdir)/src/lib/evas/cserve2 \ -I$(top_srcdir)/src/modules/evas/engines/drm \ @EVAS_CFLAGS@ \ -@ECORE_DRM_CFLAGS@ \ +@ECORE_DRM2_CFLAGS@ \ @evas_engine_drm_cflags@ modules_evas_engines_drm_module_la_LIBADD = \ @USE_EVAS_LIBS@ \ -@USE_ECORE_DRM_LIBS@ \ +@USE_ECORE_DRM2_LIBS@ \ @evas_engine_drm_libs@ -modules_evas_engines_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM_INTERNAL_LIBS@ +modules_evas_engines_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM2_INTERNAL_LIBS@ modules_evas_engines_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ modules_evas_engines_drm_module_la_LIBTOOLFLAGS = --tag=disable-static endif endif if BUILD_ENGINE_GL_DRM -dist_installed_evasmainheaders_DATA += modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h GL_DRM_SOURCES = \ modules/evas/engines/gl_drm/evas_outbuf.c \ modules/evas/engines/gl_drm/evas_engine.c \ @@ -1339,13 +1337,13 @@ modules_evas_engines_gl_drm_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \ -I$(top_srcdir)/src/lib/evas/cserve2 \ -I$(top_srcdir)/src/modules/evas/engines/gl_drm \ @EVAS_CFLAGS@ \ -@ECORE_DRM_CFLAGS@ \ +@ECORE_DRM2_CFLAGS@ \ @evas_engine_gl_drm_cflags@ modules_evas_engines_gl_drm_module_la_LIBADD = \ @USE_EVAS_LIBS@ \ -@USE_ECORE_DRM_LIBS@ \ +@USE_ECORE_DRM2_LIBS@ \ @evas_engine_gl_drm_libs@ -modules_evas_engines_gl_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM_INTERNAL_LIBS@ +modules_evas_engines_gl_drm_module_la_DEPENDENCIES = @USE_EVAS_INTERNAL_LIBS@ @USE_ECORE_DRM2_INTERNAL_LIBS@ modules_evas_engines_gl_drm_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ modules_evas_engines_gl_drm_module_la_LIBTOOLFLAGS = --tag=disable-static endif diff --git a/src/modules/evas/engines/drm/Evas_Engine_Drm.h b/src/modules/evas/engines/drm/Evas_Engine_Drm.h index 136eb919db..457db625e7 100644 --- a/src/modules/evas/engines/drm/Evas_Engine_Drm.h +++ b/src/modules/evas/engines/drm/Evas_Engine_Drm.h @@ -1,11 +1,7 @@ #ifndef _EVAS_ENGINE_DRM_H # define _EVAS_ENGINE_DRM_H -# include - -typedef struct _Evas_Engine_Info_Drm Evas_Engine_Info_Drm; - -struct _Evas_Engine_Info_Drm +typedef struct _Evas_Engine_Info_Drm { /* PRIVATE - don't mess with this baby or evas will poke its tongue out */ /* at you and make nasty noises */ @@ -13,18 +9,17 @@ struct _Evas_Engine_Info_Drm struct { - unsigned int rotation, depth; - Eina_Bool destination_alpha : 1; + int fd; + int depth, bpp; + unsigned int format, rotation; + + void *output; + Eina_Bool alpha : 1; Eina_Bool vsync : 1; - - unsigned int crtc_id, conn_id, buffer_id; - - Eina_Bool use_hw_accel : 1; - Ecore_Drm_Device *dev; } info; /* non-blocking or blocking mode */ Evas_Engine_Render_Mode render_mode; -}; +} Evas_Engine_Info_Drm; #endif diff --git a/src/modules/evas/engines/drm/evas_engine.c b/src/modules/evas/engines/drm/evas_engine.c index 40365a99f1..e3cd01e576 100644 --- a/src/modules/evas/engines/drm/evas_engine.c +++ b/src/modules/evas/engines/drm/evas_engine.c @@ -1,65 +1,57 @@ #include "evas_engine.h" -/* local structures */ -typedef struct _Render_Engine Render_Engine; - -struct _Render_Engine +typedef struct _Render_Engine { Render_Engine_Software_Generic generic; -}; +} Render_Engine; -/* function tables - filled in later (func and parent func) */ static Evas_Func func, pfunc; -/* external variables */ int _evas_engine_drm_log_dom; -/* local functions */ -static void * -_output_setup(Evas_Engine_Info_Drm *info, int w, int h) +static Render_Engine * +_render_engine_setup(Evas_Engine_Info_Drm *info, int w, int h) { - Render_Engine *re = NULL; + Render_Engine *re; Outbuf *ob; - /* try to allocate space for our render engine structure */ - if (!(re = calloc(1, sizeof(Render_Engine)))) - goto on_error; + re = calloc(1, sizeof(Render_Engine)); + if (!re) return NULL; - /* try to create new outbuf */ - if (!(ob = evas_outbuf_setup(info, w, h))) - goto on_error; + ob = _outbuf_setup(info, w, h); + if (!ob) goto err; if (!evas_render_engine_software_generic_init(&re->generic, ob, - evas_outbuf_buffer_state_get, - evas_outbuf_rot_get, - evas_outbuf_reconfigure, NULL, - evas_outbuf_update_region_new, - evas_outbuf_update_region_push, - evas_outbuf_update_region_free, - NULL, evas_outbuf_flush, - evas_outbuf_free, + _outbuf_state_get, + _outbuf_rotation_get, + _outbuf_reconfigure, + NULL, + _outbuf_update_region_new, + _outbuf_update_region_push, + _outbuf_update_region_free, + NULL, + _outbuf_flush, + _outbuf_free, ob->w, ob->h)) - goto on_error; + goto init_err; - /* return the allocated render_engine structure */ return re; - on_error: - if (re) evas_render_engine_software_generic_clean(&re->generic); - +init_err: + evas_render_engine_software_generic_clean(&re->generic); +err: free(re); return NULL; } -/* engine api functions */ static void * eng_info(Evas *evas EINA_UNUSED) { Evas_Engine_Info_Drm *info; /* try to allocate space for our engine info structure */ - if (!(info = calloc(1, sizeof(Evas_Engine_Info_Drm)))) - return NULL; + info = calloc(1, sizeof(Evas_Engine_Info_Drm)); + if (!info) return NULL; /* set some engine default properties */ info->magic.magic = rand(); @@ -74,55 +66,47 @@ eng_info_free(Evas *evas EINA_UNUSED, void *einfo) Evas_Engine_Info_Drm *info; /* free the engine info */ - if ((info = (Evas_Engine_Info_Drm *)einfo)) - free(info); + info = (Evas_Engine_Info_Drm *)einfo; + free(info); } static int eng_setup(Evas *evas, void *einfo) { - Evas_Engine_Info_Drm *info; - Evas_Public_Data *epd; Render_Engine *re; + Evas_Public_Data *epd; + Evas_Engine_Info_Drm *info; - /* try to cast to our engine info structure */ - if (!(info = (Evas_Engine_Info_Drm *)einfo)) return 0; + info = (Evas_Engine_Info_Drm *)einfo; + if (!info) return 0; - /* try to get the evas public data */ - if (!(epd = eo_data_scope_get(evas, EVAS_CANVAS_CLASS))) return 0; + epd = eo_data_scope_get(evas, EVAS_CANVAS_CLASS); + if (!epd) return 0; - /* check for valid engine output */ - if (!(re = epd->engine.data.output)) + re = epd->engine.data.output; + if (!re) { - /* NB: If we have no valid output then assume we have not been - * initialized yet and call any needed common init routines */ evas_common_init(); - /* try to create a new render_engine */ - if (!(re = _output_setup(info, epd->output.w, epd->output.h))) - return 0; + re = _render_engine_setup(info, epd->output.w, epd->output.h); + if (!re) return 0; } else { Outbuf *ob; - /* try to create a new outbuf */ - ob = evas_outbuf_setup(info, epd->output.w, epd->output.h); + ob = _outbuf_setup(info, epd->output.w, epd->output.h); if (!ob) return 0; - /* if we have an existing outbuf, free it */ - evas_render_engine_software_generic_update(&re->generic, ob, + evas_render_engine_software_generic_update(&re->generic, ob, ob->w, ob->h); } - /* reassign engine output */ epd->engine.data.output = re; if (!epd->engine.data.output) return 0; - /* check for valid engine context */ if (!epd->engine.data.context) { - /* create a context if needed */ epd->engine.data.context = epd->engine.func->context_new(epd->engine.data.output); } @@ -135,7 +119,8 @@ eng_output_free(void *data) { Render_Engine *re; - if ((re = data)) + re = data; + if (re) { evas_render_engine_software_generic_clean(&re->generic); free(re); @@ -144,7 +129,6 @@ eng_output_free(void *data) evas_common_shutdown(); } -/* module api functions */ static int module_open(Evas_Module *em) { @@ -165,6 +149,8 @@ module_open(Evas_Module *em) return 0; } + ecore_init(); + /* store parent functions */ func = pfunc; @@ -185,6 +171,8 @@ module_close(Evas_Module *em EINA_UNUSED) { /* unregister the eina log domain for this engine */ eina_log_domain_unregister(_evas_engine_drm_log_dom); + + ecore_shutdown(); } static Evas_Module_Api evas_modapi = diff --git a/src/modules/evas/engines/drm/evas_engine.h b/src/modules/evas/engines/drm/evas_engine.h index d5139117ee..a1925b939e 100644 --- a/src/modules/evas/engines/drm/evas_engine.h +++ b/src/modules/evas/engines/drm/evas_engine.h @@ -6,8 +6,13 @@ # include "evas_private.h" # include "Evas.h" # include "Evas_Engine_Drm.h" +# include +# include +# include +# include +# include -#include "../software_generic/Evas_Engine_Software_Generic.h" +# include "../software_generic/Evas_Engine_Software_Generic.h" extern int _evas_engine_drm_log_dom; @@ -36,35 +41,44 @@ extern int _evas_engine_drm_log_dom; # endif # define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_drm_log_dom, __VA_ARGS__) +typedef struct _Outbuf_Fb +{ + int age; + Ecore_Drm2_Fb *fb; + + Eina_Bool valid : 1; + Eina_Bool drawn : 1; + Eina_Bool busy : 1; +} Outbuf_Fb; + struct _Outbuf { - Evas_Engine_Info_Drm *info; - - int w, h; - int rotation; - unsigned int depth; + int fd, w, h, bpp, rotation; + unsigned int depth, format; struct { - Ecore_Drm_Fb *buffer[4]; - - Eina_List *pending_writes; - - int curr, last, num; + int num; + Outbuf_Fb ofb[4], *current; + Ecore_Drm2_Output *output; + Eina_List *pending; } priv; - Eina_Bool destination_alpha : 1; + drmEventContext ctx; + Ecore_Fd_Handler *hdlr; + + Eina_Bool alpha : 1; Eina_Bool vsync : 1; }; -Outbuf *evas_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h); -void evas_outbuf_free(Outbuf *ob); -void evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth); -Render_Engine_Swap_Mode evas_outbuf_buffer_state_get(Outbuf *ob); -int evas_outbuf_rot_get(Outbuf *ob); -void *evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch); -void evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); -void evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update); -void evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode); +Outbuf *_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h); +void _outbuf_free(Outbuf *ob); +int _outbuf_rotation_get(Outbuf *ob); +void _outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth); +Render_Engine_Swap_Mode _outbuf_state_get(Outbuf *ob); +void *_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch); +void _outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); +void _outbuf_update_region_free(Outbuf *ob, RGBA_Image *update); +void _outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode); #endif diff --git a/src/modules/evas/engines/drm/evas_outbuf.c b/src/modules/evas/engines/drm/evas_outbuf.c index 64b3ba9a52..4c87f2df2f 100644 --- a/src/modules/evas/engines/drm/evas_outbuf.c +++ b/src/modules/evas/engines/drm/evas_outbuf.c @@ -8,183 +8,430 @@ #define GREEN_MASK 0x00ff00 #define BLUE_MASK 0x0000ff -static void -_evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count) +static void _outbuf_tick_schedule(int fd, void *data); + +static Eina_Bool ticking = EINA_FALSE; + +static void +_outbuf_tick_begin(void *data) { - Ecore_Drm_Fb *buff; + Outbuf *ob; - buff = ob->priv.buffer[ob->priv.curr]; + ob = data; + ticking = EINA_TRUE; + if (ob) _outbuf_tick_schedule(ob->fd, ob); +} - /* mark the fb as dirty */ - ecore_drm_fb_dirty(buff, rects, count); +static void +_outbuf_tick_end(void *data EINA_UNUSED) +{ + ticking = EINA_FALSE; +} - /* send this buffer to the crtc */ - ecore_drm_fb_send(ob->info->info.dev, buff, NULL, NULL); +static void +_outbuf_tick_source_set(Outbuf *ob) +{ + if (ob) + { + ecore_animator_custom_source_tick_begin_callback_set + (_outbuf_tick_begin, ob); + ecore_animator_custom_source_tick_end_callback_set + (_outbuf_tick_end, ob); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM); + } + else + { + ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL); + ecore_animator_custom_source_tick_end_callback_set(NULL, NULL); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); + } +} - ob->priv.last = ob->priv.curr; - ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num; +static void +_outbuf_tick_schedule(int fd EINA_UNUSED, void *data) +{ + Outbuf *ob; + Outbuf_Fb *ofb; + + ob = data; + if (!ticking) return; + + ofb = ob->priv.current; + if (!ofb) return; + + drmVBlank vbl = + { + .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, + .request.sequence = 1, + .request.signal = (unsigned long)data, + }; + + if (drmWaitVBlank(fd, &vbl) < 0) + _outbuf_tick_source_set(NULL); +} + +static void +_cb_vblank(int fd, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) +{ + ecore_animator_custom_tick(); + if (ticking) _outbuf_tick_schedule(fd, data); +} + +static void +_cb_pageflip(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) +{ + Outbuf *ob; + Outbuf_Fb *ofb; + Ecore_Drm2_Fb *next; + + ob = data; + + ofb = ob->priv.current; + if (ofb) ofb->busy = EINA_FALSE; + + next = ecore_drm2_output_next_fb_get(ob->priv.output); + if (next) + { + ecore_drm2_output_next_fb_set(ob->priv.output, NULL); + if (ecore_drm2_fb_flip(next, ob->priv.output, ob) < 0) + _outbuf_tick_source_set(NULL); + } +} + +static Eina_Bool +_cb_drm_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) +{ + Outbuf *ob; + int ret; + + ob = data; + ret = drmHandleEvent(ob->fd, &ob->ctx); + if (ret) + { + WRN("drmHandleEvent failed to read an event"); + return EINA_FALSE; + } + + return EINA_TRUE; +} + +static void +_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count) +{ + /* Ecore_Drm2_Plane *plane; */ + Outbuf_Fb *ofb; + + ofb = ob->priv.current; + if (!ofb) return; + + ecore_drm2_fb_dirty(ofb->fb, rects, count); + if (ecore_drm2_fb_flip(ofb->fb, ob->priv.output, ob) < 0) + { + _outbuf_tick_source_set(NULL); + return; + } + + ofb->busy = EINA_TRUE; + ofb->drawn = EINA_TRUE; + ofb->age = 0; + + /* plane = ecore_drm2_plane_find(ob->priv.output, ofb->fb, ob->format); */ + /* if (plane) */ + /* { */ + /* drmVBlank vbl = */ + /* { */ + /* .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, */ + /* .request.sequence = 1, */ + /* }; */ + + /* vbl.request.type |= ecore_drm2_output_vblank_get(ob->priv.output); */ + /* vbl.request.signal = (unsigned long)ofb; */ + + /* ecore_drm2_fb_dirty(ofb->fb, rects, count); */ + + /* if (!ecore_drm2_plane_fb_set(plane, ofb->fb)) */ + /* { */ + /* ERR("Failed to set FB on Plane"); */ + /* return; */ + /* } */ + + /* if (drmWaitVBlank(ob->fd, &vbl) < 0) */ + /* { */ + /* _outbuf_tick_source_set(NULL); */ + /* return; */ + /* } */ + + /* ofb->busy = EINA_TRUE; */ + /* ofb->drawn = EINA_TRUE; */ + /* ofb->age = 0; */ + + /* ob->priv.current = NULL; */ + /* } */ + /* else */ + /* WRN("Could not find a plane for this framebuffer"); */ +} + +static Eina_Bool +_outbuf_fb_create(Outbuf *ob, Outbuf_Fb *ofb) +{ + ofb->fb = + ecore_drm2_fb_create(ob->fd, ob->w, ob->h, + ob->depth, ob->bpp, ob->format); + if (!ofb->fb) return EINA_FALSE; + + ofb->age = 0; + ofb->busy = EINA_FALSE; + ofb->drawn = EINA_FALSE; + ofb->valid = EINA_TRUE; + + return EINA_TRUE; +} + +static void +_outbuf_fb_destroy(Outbuf_Fb *ofb) +{ + ecore_drm2_fb_destroy(ofb->fb); + + memset(ofb, 0, sizeof(*ofb)); + ofb->valid = EINA_FALSE; + ofb->busy = EINA_FALSE; + ofb->drawn = EINA_FALSE; + ofb->age = 0; } Outbuf * -evas_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h) +_outbuf_setup(Evas_Engine_Info_Drm *info, int w, int h) { Outbuf *ob; char *num; int i = 0; - /* try to allocate space for outbuf */ - if (!(ob = calloc(1, sizeof(Outbuf)))) return NULL; + ob = calloc(1, sizeof(Outbuf)); + if (!ob) return NULL; - /* set properties of outbuf */ ob->w = w; ob->h = h; - - ob->info = info; - ob->depth = info->info.depth; + ob->fd = info->info.fd; + ob->alpha = info->info.alpha; ob->rotation = info->info.rotation; - ob->destination_alpha = info->info.destination_alpha; - ob->vsync = info->info.vsync; - /* we must triple-buffer to prevent problems with the page flip handler */ + ob->bpp = info->info.bpp; + ob->depth = info->info.depth; + ob->format = info->info.format; + + ob->priv.output = info->info.output; + ob->priv.num = 3; - /* check for buffer override */ - if ((num = getenv("EVAS_DRM_BUFFERS"))) + num = getenv("EVAS_DRM_BUFFERS"); + if (num) { ob->priv.num = atoi(num); - if (ob->priv.num <= 0) ob->priv.num = 1; + if (ob->priv.num <= 0) ob->priv.num = 3; else if (ob->priv.num > 4) ob->priv.num = 4; } - /* check for vsync override */ - if ((num = getenv("EVAS_DRM_VSYNC"))) - ob->vsync = atoi(num); - - /* try to create buffers */ - for (; i < ob->priv.num; i++) + for (i = 0; i < ob->priv.num; i++) { - ob->priv.buffer[i] = - ecore_drm_fb_create(ob->info->info.dev, ob->w, ob->h); - if (!ob->priv.buffer[i]) + if (!_outbuf_fb_create(ob, &(ob->priv.ofb[i]))) { - ERR("Failed to create buffer %d", i); - break; + WRN("Failed to create framebuffer %d", i); + continue; } - - DBG("Evas Engine Created Dumb Buffer"); - DBG("\tFb: %d", ob->priv.buffer[i]->id); - DBG("\tHandle: %d", ob->priv.buffer[i]->hdl); - DBG("\tStride: %d", ob->priv.buffer[i]->stride); - DBG("\tSize: %d", ob->priv.buffer[i]->size); - DBG("\tW: %d\tH: %d", - ob->priv.buffer[i]->w, ob->priv.buffer[i]->h); } - /* set the front buffer to be the one on the crtc */ - ecore_drm_fb_send(info->info.dev, ob->priv.buffer[0], NULL, NULL); + /* setup vblank handler */ + memset(&ob->ctx, 0, sizeof(ob->ctx)); + ob->ctx.version = DRM_EVENT_CONTEXT_VERSION; + ob->ctx.vblank_handler = _cb_vblank; + ob->ctx.page_flip_handler = _cb_pageflip; + + ob->hdlr = + ecore_main_fd_handler_add(ob->fd, ECORE_FD_READ, _cb_drm_event, ob, + NULL, NULL); + + _outbuf_tick_source_set(ob); return ob; } void -evas_outbuf_free(Outbuf *ob) +_outbuf_free(Outbuf *ob) { int i = 0; - /* destroy the old buffers */ - for (; i < ob->priv.num; i++) - ecore_drm_fb_destroy(ob->priv.buffer[i]); + for (i = 0; i < ob->priv.num; i++) + _outbuf_fb_destroy(&ob->priv.ofb[i]); + + ecore_main_fd_handler_del(ob->hdlr); - /* free allocate space for outbuf */ free(ob); } +int +_outbuf_rotation_get(Outbuf *ob) +{ + return ob->rotation; +} + void -evas_outbuf_reconfigure(Outbuf *ob, int w, int h, int rot, Outbuf_Depth depth) +_outbuf_reconfigure(Outbuf *ob, int w, int h, int rotation, Outbuf_Depth depth) { int i = 0; + unsigned int format = DRM_FORMAT_ARGB8888; - /* check if we are inheriting the old buffer depth */ - if (depth == OUTBUF_DEPTH_INHERIT) depth = ob->depth; + switch (depth) + { + case OUTBUF_DEPTH_RGB_16BPP_565_565_DITHERED: + format = DRM_FORMAT_RGB565; + break; + case OUTBUF_DEPTH_RGB_16BPP_555_555_DITHERED: + format = DRM_FORMAT_RGBX5551; + break; + case OUTBUF_DEPTH_RGB_16BPP_444_444_DITHERED: + format = DRM_FORMAT_RGBX4444; + break; + case OUTBUF_DEPTH_RGB_16BPP_565_444_DITHERED: + format = DRM_FORMAT_RGB565; + break; + case OUTBUF_DEPTH_RGB_32BPP_888_8888: + format = DRM_FORMAT_RGBX8888; + break; + case OUTBUF_DEPTH_ARGB_32BPP_8888_8888: + format = DRM_FORMAT_ARGB8888; + break; + case OUTBUF_DEPTH_BGRA_32BPP_8888_8888: + format = DRM_FORMAT_BGRA8888; + break; + case OUTBUF_DEPTH_BGR_32BPP_888_8888: + format = DRM_FORMAT_BGRX8888; + break; + case OUTBUF_DEPTH_RGB_24BPP_888_888: + format = DRM_FORMAT_RGB888; + break; + case OUTBUF_DEPTH_BGR_24BPP_888_888: + format = DRM_FORMAT_BGR888; + break; + case OUTBUF_DEPTH_INHERIT: + default: + depth = ob->depth; + format = ob->format; + break; + } - /* check for changes */ - if ((ob->w == w) && (ob->h == h) && - (ob->destination_alpha == ob->info->info.destination_alpha) && - (ob->rotation == rot) && - (ob->depth == depth)) + if ((ob->w == w) && (ob->h == h) && (ob->rotation == rotation) && + (ob->depth == depth) && (ob->format == format)) return; - /* set new outbuf properties */ - ob->rotation = rot; ob->depth = depth; - ob->destination_alpha = ob->info->info.destination_alpha; + ob->format = format; + ob->rotation = rotation; - /* handle rotation */ - if ((ob->rotation == 0) || (ob->rotation == 180)) - { - ob->w = w; - ob->h = h; - } - else + ob->w = w; + ob->h = h; + if ((ob->rotation == 90) || (ob->rotation == 270)) { ob->w = h; ob->h = w; } - /* destroy the old buffers */ - for (; i < ob->priv.num; i++) - ecore_drm_fb_destroy(ob->priv.buffer[i]); + for (i = 0; i < ob->priv.num; i++) + _outbuf_fb_destroy(&ob->priv.ofb[i]); for (i = 0; i < ob->priv.num; i++) { - ob->priv.buffer[i] = - ecore_drm_fb_create(ob->info->info.dev, ob->w, ob->h); - if (!ob->priv.buffer[i]) + if (!_outbuf_fb_create(ob, &(ob->priv.ofb[i]))) { - ERR("Failed to create buffer %d", i); - break; + WRN("Failed to create framebuffer %d", i); + continue; } } } -Render_Engine_Swap_Mode -evas_outbuf_buffer_state_get(Outbuf *ob) +static Outbuf_Fb * +_outbuf_fb_wait(Outbuf *ob) { - int delta; + int iter = 0, i = 0; - /* check for valid output buffer */ - if (!ob) return MODE_FULL; - - delta = (ob->priv.last - ob->priv.curr + ob->priv.num) % ob->priv.num; - - /* This is the number of frame since last frame */ - switch (delta) + while (iter++ < 10) { - case 0: - return MODE_COPY; - case 1: - return MODE_DOUBLE; - case 2: - return MODE_TRIPLE; - case 3: - return MODE_QUADRUPLE; - default: - return MODE_FULL; + for (i = 0; i < ob->priv.num; i++) + { + if (ob->priv.ofb[i].busy) continue; + if (ob->priv.ofb[i].valid) return &(ob->priv.ofb[i]); + } + + drmHandleEvent(ob->fd, &ob->ctx); } + + return NULL; +} + +static Eina_Bool +_outbuf_fb_assign(Outbuf *ob) +{ + int i; + + ob->priv.current = _outbuf_fb_wait(ob); + + if (!ob->priv.current) + { + WRN("No Free Buffers. Dropping a frame"); + for (i = 0; i < ob->priv.num; i++) + { + if (ob->priv.ofb[i].valid) + { + ob->priv.ofb[i].age = 0; + ob->priv.ofb[i].drawn = EINA_FALSE; + } + } + + return EINA_FALSE; + } + + for (i = 0; i < ob->priv.num; i++) + { + if ((ob->priv.ofb[i].valid) && (ob->priv.ofb[i].drawn)) + { + ob->priv.ofb[i].age++; + if (ob->priv.ofb[i].age > ob->priv.num) + { + ob->priv.ofb[i].age = 0; + ob->priv.ofb[i].drawn = EINA_FALSE; + } + } + } + + return EINA_TRUE; +} + +Render_Engine_Swap_Mode +_outbuf_state_get(Outbuf *ob) +{ + int age; + + if (!_outbuf_fb_assign(ob)) return MODE_FULL; + + age = ob->priv.current->age; + if (age > ob->priv.num) return MODE_FULL; + else if (age == 1) return MODE_COPY; + else if (age == 2) return MODE_DOUBLE; + else if (age == 3) return MODE_TRIPLE; + else if (age == 4) return MODE_QUADRUPLE; + + return MODE_FULL; } void * -evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch) +_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, int *cy, int *cw, int *ch) { RGBA_Image *img = NULL; if ((w <= 0) || (h <= 0)) return NULL; - /* DBG("Outbuf Region New: %d %d %d %d", x, y, w, h); */ - RECTS_CLIP_TO_RECT(x, y, w, h, 0, 0, ob->w, ob->h); - if ((ob->rotation == 0) && (ob->depth == 32)) + if ((ob->rotation == 0))// && (ob->depth == 32)) { Eina_Rectangle *rect; @@ -204,7 +451,7 @@ evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, i return NULL; } - img->cache_entry.flags.alpha = ob->destination_alpha; + img->cache_entry.flags.alpha = ob->alpha; #ifdef EVAS_CSERVE2 if (evas_cserve2_use_get()) @@ -221,48 +468,52 @@ evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int *cx, i if (ch) *ch = h; /* add this cached image data to pending writes */ - ob->priv.pending_writes = - eina_list_append(ob->priv.pending_writes, img); + ob->priv.pending = + eina_list_append(ob->priv.pending, img); } return img; } -void -evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h) +void +_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h) { Gfx_Func_Convert func = NULL; Eina_Rectangle rect = {0, 0, 0, 0}, pr; DATA32 *src; DATA8 *dst; - Ecore_Drm_Fb *buff; + Ecore_Drm2_Fb *buff; int bpp = 0, bpl = 0; int rx = 0, ry = 0; + int bw = 0, bh = 0; /* check for valid output buffer */ if (!ob) return; /* check for pending writes */ - if (!ob->priv.pending_writes) return; + if (!ob->priv.pending) return; /* check for valid source data */ if (!(src = update->image.data)) return; /* check for valid desination data */ - buff = ob->priv.buffer[ob->priv.curr]; - if (!(dst = buff->mmap)) return; + if (!ob->priv.current) return; + buff = ob->priv.current->fb; + + dst = ecore_drm2_fb_data_get(buff); + if (!dst) return; if ((ob->rotation == 0) || (ob->rotation == 180)) { func = - evas_common_convert_func_get(0, w, h, ob->depth, + evas_common_convert_func_get(0, w, h, ob->bpp, RED_MASK, GREEN_MASK, BLUE_MASK, PAL_MODE_NONE, ob->rotation); } else if ((ob->rotation == 90) || (ob->rotation == 270)) { func = - evas_common_convert_func_get(0, h, w, ob->depth, + evas_common_convert_func_get(0, h, w, ob->bpp, RED_MASK, GREEN_MASK, BLUE_MASK, PAL_MODE_NONE, ob->rotation); } @@ -304,15 +555,18 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int rect.h = w; } - bpp = (ob->depth / 8); - if (bpp <= 0) return; + bpp = ob->bpp / 8; + bw = ob->w; + bh = ob->h; + /* bpp = (ob->depth / 8); */ + /* if (bpp <= 0) return; */ - bpl = buff->stride; + bpl = ecore_drm2_fb_stride_get(buff); if (ob->rotation == 0) { RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, - 0, 0, buff->w, buff->h); + 0, 0, bw, bh); dst += (bpl * rect.y) + (rect.x * bpp); w -= rx; } @@ -320,7 +574,7 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int { pr = rect; RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, - 0, 0, buff->w, buff->h); + 0, 0, bw, bh); rx = pr.w - rect.w; ry = pr.h - rect.h; src += (update->cache_entry.w * ry) + rx; @@ -330,7 +584,7 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int { pr = rect; RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, - 0, 0, buff->w, buff->h); + 0, 0, bw, bh); rx = pr.w - rect.w; ry = pr.h - rect.h; src += ry; w -= ry; @@ -339,7 +593,7 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int { pr = rect; RECTS_CLIP_TO_RECT(rect.x, rect.y, rect.w, rect.h, - 0, 0, buff->w, buff->h); + 0, 0, bw, bh); rx = pr.w - rect.w; ry = pr.h - rect.h; src += (update->cache_entry.w * rx); w -= ry; @@ -352,13 +606,13 @@ evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int } void -evas_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED) +_outbuf_update_region_free(Outbuf *ob EINA_UNUSED, RGBA_Image *update EINA_UNUSED) { - /* evas_cache_image_drop(&update->cache_entry); */ + } void -evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode) +_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode render_mode) { Eina_Rectangle *r; RGBA_Image *img; @@ -367,19 +621,21 @@ evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode if (render_mode == EVAS_RENDER_MODE_ASYNC_INIT) return; /* get number of pending writes */ - n = eina_list_count(ob->priv.pending_writes); + n = eina_list_count(ob->priv.pending); if (n == 0) return; /* allocate rectangles */ - if (!(r = alloca(n * sizeof(Eina_Rectangle)))) return; + r = alloca(n * sizeof(Eina_Rectangle)); + if (!r) return; /* loop the pending writes */ - EINA_LIST_FREE(ob->priv.pending_writes, img) + EINA_LIST_FREE(ob->priv.pending, img) { Eina_Rectangle *rect; int x = 0, y = 0, w = 0, h = 0; - if (!(rect = img->extended_info)) continue; + rect = img->extended_info; + if (!rect) continue; x = rect->x; y = rect->y; w = rect->w; h = rect->h; @@ -430,11 +686,5 @@ evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects EINA_UNUSED, Evas_Render_Mode } /* force a buffer swap */ - _evas_outbuf_buffer_swap(ob, r, n); -} - -int -evas_outbuf_rot_get(Outbuf *ob) -{ - return ob->rotation; + _outbuf_buffer_swap(ob, r, n); } diff --git a/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h b/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h index 71ab60cefc..514aa80c09 100644 --- a/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h +++ b/src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h @@ -1,7 +1,7 @@ #ifndef _EVAS_ENGINE_GL_DRM_H # define _EVAS_ENGINE_GL_DRM_H -# include +# include # include typedef enum _Evas_Engine_Info_GL_Drm_Swap_Mode @@ -26,11 +26,11 @@ struct _Evas_Engine_Info_GL_Drm { struct gbm_device *gbm; + int fd, bpp; unsigned int rotation, depth; - unsigned int crtc_id, conn_id, buffer_id; unsigned int format, flags; - Ecore_Drm_Device *dev; + void *output; Eina_Bool destination_alpha : 1; Eina_Bool vsync : 1; diff --git a/src/modules/evas/engines/gl_drm/evas_engine.c b/src/modules/evas/engines/gl_drm/evas_engine.c index d8d4312aee..29f2e0c533 100644 --- a/src/modules/evas/engines/gl_drm/evas_engine.c +++ b/src/modules/evas/engines/gl_drm/evas_engine.c @@ -118,12 +118,9 @@ static const EVGL_Interface evgl_funcs = Eina_Bool eng_gbm_init(Evas_Engine_Info_GL_Drm *info) { - Ecore_Drm_Device *dev; - if (!info) return EINA_FALSE; - if (!(dev = info->info.dev)) return EINA_FALSE; - if (!(info->info.gbm = gbm_create_device(dev->drm.fd))) + if (!(info->info.gbm = gbm_create_device(info->info.fd))) { ERR("Coult not create gbm device"); return EINA_FALSE; @@ -146,13 +143,6 @@ eng_gbm_shutdown(Evas_Engine_Info_GL_Drm *info) return EINA_TRUE; } -/* local inline functions */ -static inline Outbuf * -eng_get_ob(Render_Engine *re) -{ - return re->generic.software.ob; -} - /* local functions */ static void gl_symbols(void) @@ -362,6 +352,8 @@ evgl_eng_native_window_create(void *data) Render_Engine *re; struct gbm_surface *surface; Evas_Engine_Info_GL_Drm *info; + unsigned int format = GBM_FORMAT_XRGB8888; + unsigned int flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; re = (Render_Engine *)data; if (!re) @@ -377,9 +369,9 @@ evgl_eng_native_window_create(void *data) return NULL; } - surface = gbm_surface_create(info->info.gbm, - eng_get_ob(re)->w, eng_get_ob(re)->h, - info->info.format, info->info.flags); + surface = + gbm_surface_create(info->info.gbm, + eng_get_ob(re)->w, eng_get_ob(re)->h, format, flags); if (!surface) { ERR("Could not create gl drm window"); @@ -786,6 +778,37 @@ _native_cb_free(void *image) free(n); } +static void +_cb_vblank(int fd, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) +{ + evas_outbuf_vblank(data, fd); +} + +static void +_cb_page_flip(int fd, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) +{ + evas_outbuf_page_flip(data, fd); +} + +static Eina_Bool +_cb_drm_event(void *data, Ecore_Fd_Handler *hdlr EINA_UNUSED) +{ + Render_Engine *re; + int ret; + + re = data; + if (!re) return EINA_TRUE; + + ret = drmHandleEvent(re->fd, &re->ctx); + if (ret) + { + ERR("drmHandleEvent failed to read an event: %m"); + return EINA_FALSE; + } + + return EINA_TRUE; +} + /* engine specific override functions */ static void * eng_info(Evas *eo_e EINA_UNUSED) @@ -899,6 +922,17 @@ eng_setup(Evas *evas, void *in) return 0; } + re->fd = info->info.fd; + + memset(&re->ctx, 0, sizeof(re->ctx)); + re->ctx.version = DRM_EVENT_CONTEXT_VERSION; + re->ctx.vblank_handler = _cb_vblank; + re->ctx.page_flip_handler = _cb_page_flip; + + re->hdlr = + ecore_main_fd_handler_add(info->info.fd, ECORE_FD_READ, + _cb_drm_event, re, NULL, NULL); + /* try to create new outbuf */ ob = evas_outbuf_new(info, epd->output.w, epd->output.h, swap_mode); if (!ob) @@ -970,16 +1004,16 @@ eng_setup(Evas *evas, void *in) re->generic.software.ob = NULL; gl_wins--; + if (ob_old) evas_outbuf_free(ob_old); + ob = evas_outbuf_new(info, epd->output.w, epd->output.h, swap_mode); if (!ob) { - if (ob_old) evas_outbuf_free(ob_old); free(re); return 0; } evas_outbuf_use(ob); - if (ob_old) evas_outbuf_free(ob_old); ob->evas = evas; @@ -1439,6 +1473,8 @@ module_open(Evas_Module *em) return 0; } + ecore_init(); + /* store it for later use */ func = pfunc; @@ -1471,6 +1507,8 @@ module_close(Evas_Module *em EINA_UNUSED) /* unregister the eina log domain for this engine */ eina_log_domain_unregister(_evas_engine_gl_drm_log_dom); _evas_engine_gl_drm_log_dom = -1; + + ecore_shutdown(); } static Evas_Module_Api evas_modapi = diff --git a/src/modules/evas/engines/gl_drm/evas_engine.h b/src/modules/evas/engines/gl_drm/evas_engine.h index f45a1995e6..8a51d59c93 100644 --- a/src/modules/evas/engines/gl_drm/evas_engine.h +++ b/src/modules/evas/engines/gl_drm/evas_engine.h @@ -7,6 +7,11 @@ # include "Evas.h" # include "Evas_Engine_GL_Drm.h" +# include +# include +# include +# include + # define EGL_EGLEXT_PROTOTYPES # define GL_GLEXT_PROTOTYPES @@ -64,6 +69,10 @@ typedef struct _Render_Engine Render_Engine; struct _Render_Engine { Render_Engine_GL_Generic generic; + + int fd; + drmEventContext ctx; + Ecore_Fd_Handler *hdlr; }; struct _Context_3D @@ -80,11 +89,10 @@ struct _Outbuf Evas *evas; // used for pre_swap, post_swap - int w, h; - unsigned int rotation, depth; + int fd, w, h, bpp; + unsigned int rotation, depth, format; Render_Engine_Swap_Mode swap_mode; - /* struct gbm_device *gbm; */ struct gbm_surface *surface; struct @@ -98,6 +106,7 @@ struct _Outbuf struct { struct gbm_bo *bo[2]; + Ecore_Drm2_Output *output; } priv; Eina_Bool destination_alpha : 1; @@ -123,6 +132,9 @@ void *evas_outbuf_update_region_new(Outbuf *ob, int x, int y, int w, int h, int void evas_outbuf_update_region_push(Outbuf *ob, RGBA_Image *update, int x, int y, int w, int h); void evas_outbuf_update_region_free(Outbuf *ob, RGBA_Image *update); void evas_outbuf_flush(Outbuf *ob, Tilebuf_Rect *rects, Evas_Render_Mode render_mode); +void evas_outbuf_vblank(void *data, int fd); +void evas_outbuf_page_flip(void *data, int fd); + Evas_Engine_GL_Context* evas_outbuf_gl_context_get(Outbuf *ob); void *evas_outbuf_egl_display_get(Outbuf *ob); Context_3D *evas_outbuf_gl_context_new(Outbuf *ob); @@ -138,6 +150,12 @@ _re_wincheck(Outbuf *ob) return EINA_FALSE; } +static inline Outbuf * +eng_get_ob(Render_Engine *re) +{ + return re->generic.software.ob; +} + extern unsigned int (*glsym_eglSwapBuffersWithDamage)(EGLDisplay a, void *b, const EGLint *d, EGLint c); extern unsigned int (*glsym_eglSetDamageRegionKHR)(EGLDisplay a, EGLSurface b, EGLint *c, EGLint d); diff --git a/src/modules/evas/engines/gl_drm/evas_outbuf.c b/src/modules/evas/engines/gl_drm/evas_outbuf.c index b120216608..ad3f2a0414 100644 --- a/src/modules/evas/engines/gl_drm/evas_outbuf.c +++ b/src/modules/evas/engines/gl_drm/evas_outbuf.c @@ -5,12 +5,86 @@ static Outbuf *_evas_gl_drm_window = NULL; static EGLContext context = EGL_NO_CONTEXT; static int win_count = 0; +static Eina_Bool ticking = EINA_FALSE; #ifdef EGL_MESA_platform_gbm static PFNEGLGETPLATFORMDISPLAYEXTPROC dlsym_eglGetPlatformDisplayEXT = NULL; static PFNEGLCREATEPLATFORMWINDOWSURFACEEXTPROC dlsym_eglCreatePlatformWindowSurfaceEXT = NULL; #endif +static void +_outbuf_tick_schedule(int fd, void *data) +{ + if (!ticking) return; + + drmVBlank vbl = + { + .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, + .request.sequence = 1, + .request.signal = (unsigned long)data, + }; + + drmWaitVBlank(fd, &vbl); +} + +static void +_outbuf_tick_begin(void *data) +{ + Outbuf *ob; + + ob = data; + ticking = EINA_TRUE; + if (ob) _outbuf_tick_schedule(ob->fd, ob); +} + +static void +_outbuf_tick_end(void *data EINA_UNUSED) +{ + ticking = EINA_FALSE; +} + +static void +_outbuf_tick_source_set(Outbuf *ob) +{ + if (ob) + { + ecore_animator_custom_source_tick_begin_callback_set + (_outbuf_tick_begin, ob); + ecore_animator_custom_source_tick_end_callback_set + (_outbuf_tick_end, ob); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_CUSTOM); + } + else + { + ecore_animator_custom_source_tick_begin_callback_set(NULL, NULL); + ecore_animator_custom_source_tick_end_callback_set(NULL, NULL); + ecore_animator_source_set(ECORE_ANIMATOR_SOURCE_TIMER); + } +} + +void +evas_outbuf_vblank(void *data, int fd) +{ + ecore_animator_custom_tick(); + if (ticking) _outbuf_tick_schedule(fd, data); +} + +void +evas_outbuf_page_flip(void *data, int fd EINA_UNUSED) +{ + Outbuf *ob; + Ecore_Drm2_Fb *next; + + ob = data; + next = ecore_drm2_output_next_fb_get(ob->priv.output); + if (next) + { + ecore_drm2_output_next_fb_set(ob->priv.output, NULL); + if (ecore_drm2_fb_flip(next, ob->priv.output, ob) < 0) + _outbuf_tick_source_set(NULL); + } +} + static void _evas_outbuf_gbm_surface_destroy(Outbuf *ob) { @@ -25,63 +99,51 @@ _evas_outbuf_gbm_surface_destroy(Outbuf *ob) static void _evas_outbuf_gbm_surface_create(Outbuf *ob, int w, int h) { + unsigned int format = GBM_FORMAT_XRGB8888; + unsigned int flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING; + if (!ob) return; ob->surface = - gbm_surface_create(ob->info->info.gbm, w, h, - ob->info->info.format, ob->info->info.flags); + gbm_surface_create(ob->info->info.gbm, w, h, format, flags); if (!ob->surface) ERR("Failed to create gbm surface"); } static void -_evas_outbuf_fb_cb_destroy(struct gbm_bo *bo, void *data) +_evas_outbuf_fb_cb_destroy(struct gbm_bo *bo EINA_UNUSED, void *data) { - Ecore_Drm_Fb *fb; + Ecore_Drm2_Fb *fb; fb = data; - if (fb) - { - struct gbm_device *gbm; - - gbm = gbm_bo_get_device(bo); - drmModeRmFB(gbm_device_get_fd(gbm), fb->id); - free(fb); - } + if (fb) ecore_drm2_fb_destroy(fb); } -static Ecore_Drm_Fb * -_evas_outbuf_fb_get(Ecore_Drm_Device *dev, struct gbm_bo *bo) +static Ecore_Drm2_Fb * +_evas_outbuf_fb_get(Outbuf *ob, struct gbm_bo *bo) { - int ret; - Ecore_Drm_Fb *fb; - uint32_t format; - uint32_t handles[4], pitches[4], offsets[4]; + Ecore_Drm2_Fb *fb; + uint32_t format, hdl, stride; + int w, h; fb = gbm_bo_get_user_data(bo); if (fb) return fb; - if (!(fb = calloc(1, sizeof(Ecore_Drm_Fb)))) return NULL; - format = gbm_bo_get_format(bo); + w = gbm_bo_get_width(bo); + h = gbm_bo_get_height(bo); + hdl = gbm_bo_get_handle(bo).u32; + stride = gbm_bo_get_stride(bo); + /* fb->size = fb->stride * fb->h; */ - fb->w = gbm_bo_get_width(bo); - fb->h = gbm_bo_get_height(bo); - fb->hdl = gbm_bo_get_handle(bo).u32; - fb->stride = gbm_bo_get_stride(bo); - fb->size = fb->stride * fb->h; - - handles[0] = fb->hdl; - pitches[0] = fb->stride; - offsets[0] = 0; - - ret = drmModeAddFB2(dev->drm.fd, fb->w, fb->h, format, - handles, pitches, offsets, &(fb->id), 0); - if (ret) - ret = drmModeAddFB(dev->drm.fd, fb->w, fb->h, 24, 32, - fb->stride, fb->hdl, &(fb->id)); - - if (ret) ERR("FAILED TO ADD FB: %m"); + fb = + ecore_drm2_fb_gbm_create(ob->fd, w, h, ob->depth, ob->bpp, + format, hdl, stride); + if (!fb) + { + ERR("Failed to create FBO"); + return NULL; + } gbm_bo_set_user_data(bo, fb, _evas_outbuf_fb_cb_destroy); @@ -91,7 +153,9 @@ _evas_outbuf_fb_get(Ecore_Drm_Device *dev, struct gbm_bo *bo) static void _evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count) { - Ecore_Drm_Fb *fb; + Ecore_Drm2_Fb *fb; + + if (ob->priv.bo[1]) gbm_surface_release_buffer(ob->surface, ob->priv.bo[1]); /* Repulsive hack: Right now we don't actually have a proper way to retire * buffers because the ticker and the flip handler are out of sync, the @@ -106,15 +170,48 @@ _evas_outbuf_buffer_swap(Outbuf *ob, Eina_Rectangle *rects, unsigned int count) ob->priv.bo[0] = gbm_surface_lock_front_buffer(ob->surface); if (!ob->priv.bo[0]) { - WRN("Could not lock front buffer"); + WRN("Could not lock front buffer: %m"); return; } - fb = _evas_outbuf_fb_get(ob->info->info.dev, ob->priv.bo[0]); + + fb = _evas_outbuf_fb_get(ob, ob->priv.bo[0]); if (fb) { - ecore_drm_fb_dirty(fb, rects, count); - ecore_drm_fb_send(ob->info->info.dev, fb, NULL, NULL); + ecore_drm2_fb_dirty(fb, rects, count); + if (ecore_drm2_fb_flip(fb, ob->priv.output, ob) < 0) + _outbuf_tick_source_set(NULL); + + /* Ecore_Drm2_Plane *plane; */ + + /* plane = ecore_drm2_plane_find(ob->priv.output, fb, ob->format); */ + /* if (plane) */ + /* { */ + /* int ret; */ + /* drmVBlank vbl = */ + /* { */ + /* .request.type = DRM_VBLANK_RELATIVE | DRM_VBLANK_EVENT, */ + /* .request.sequence = 1, */ + /* }; */ + + /* vbl.request.type |= ecore_drm2_output_vblank_get(ob->priv.output); */ + /* vbl.request.signal = (unsigned long)ob; */ + + /* ecore_drm2_fb_dirty(fb, rects, count); */ + + /* if (!ecore_drm2_plane_fb_set(plane, fb)) */ + /* { */ + /* ERR("Failed to set FB on Plane"); */ + /* return; */ + /* } */ + + /* ret = drmWaitVBlank(ob->fd, &vbl); */ + /* if (ret) return; */ + /* } */ + /* else */ + /* WRN("NO PLANE FOUND"); */ } + else + WRN("Could not get FBO from Bo"); } static Eina_Bool @@ -253,9 +350,6 @@ _evas_outbuf_egl_setup(Outbuf *ob) return EINA_FALSE; } - DBG("Config Format: %d", format); - DBG("OB Format: %d", ob->info->info.format); - if (format == (int)ob->info->info.format) { ob->egl.config = cfgs[i]; @@ -369,6 +463,11 @@ evas_outbuf_new(Evas_Engine_Info_GL_Drm *info, int w, int h, Render_Engine_Swap_ /* ob->vsync = info->info.vsync; */ ob->swap_mode = swap_mode; + ob->fd = info->info.fd; + ob->bpp = info->info.bpp; + ob->format = info->info.format; + ob->priv.output = info->info.output; + /* if ((num = getenv("EVAS_GL_DRM_VSYNC"))) */ /* ob->vsync = atoi(num); */ @@ -383,6 +482,8 @@ evas_outbuf_new(Evas_Engine_Info_GL_Drm *info, int w, int h, Render_Engine_Swap_ return NULL; } + _outbuf_tick_source_set(ob); + return ob; } @@ -577,9 +678,7 @@ evas_outbuf_buffer_state_get(Outbuf *ob) return swap_mode; } else - { - return MODE_FULL; - } + return MODE_FULL; return ob->swap_mode; }