diff options
author | Gwanglim Lee <gl77.lee@samsung.com> | 2015-04-10 01:11:07 +0900 |
---|---|---|
committer | Gwanglim Lee <gl77.lee@samsung.com> | 2015-04-10 01:11:07 +0900 |
commit | 9309a9feef7d0d174bea16e702eff621e29afa50 (patch) | |
tree | 39e8d02ba641143ce7f844c332bfc13c699f0402 | |
parent | eaca0b233acdf750543ccdfbed07c22aecbb5d2d (diff) | |
download | efl-9309a9feef7d0d174bea16e702eff621e29afa50.tar.gz |
ecore_evas_drm: improve drm page flip event handling
Change-Id: I5f0cda91b905c2f3e6057a3a1f81948ec2a8bc88
-rw-r--r-- | src/lib/ecore_drm/Ecore_Drm.h | 26 | ||||
-rw-r--r-- | src/lib/ecore_drm/ecore_drm.c | 4 | ||||
-rw-r--r-- | src/lib/ecore_drm/ecore_drm_device.c | 57 | ||||
-rw-r--r-- | src/lib/ecore_drm/ecore_drm_tty.c | 1 | ||||
-rw-r--r-- | src/modules/ecore_evas/engines/drm/ecore_evas_drm.c | 95 | ||||
-rw-r--r-- | src/modules/evas/engines/drm/evas_drm.c | 27 | ||||
-rw-r--r-- | src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h | 7 | ||||
-rw-r--r-- | src/modules/evas/engines/gl_drm/evas_drm.c | 19 | ||||
-rw-r--r-- | src/modules/evas/engines/gl_drm/evas_engine.c | 6 | ||||
-rw-r--r-- | src/modules/evas/engines/gl_drm/evas_engine.h | 5 |
10 files changed, 176 insertions, 71 deletions
diff --git a/src/lib/ecore_drm/Ecore_Drm.h b/src/lib/ecore_drm/Ecore_Drm.h index f2f3699fec..e34a3121de 100644 --- a/src/lib/ecore_drm/Ecore_Drm.h +++ b/src/lib/ecore_drm/Ecore_Drm.h @@ -116,6 +116,24 @@ struct _Ecore_Drm_Event_Activate Eina_Bool active; }; +struct _Ecore_Drm_Event_Page_Flip +{ + int fd; + unsigned int sequence; + unsigned int sec; + unsigned int usec; + void *data; +}; + +struct _Ecore_Drm_Event_Vblank +{ + int fd; + unsigned int sequence; + unsigned int sec; + unsigned int usec; + void *data; +}; + /* opaque structure to represent a drm device */ typedef struct _Ecore_Drm_Device Ecore_Drm_Device; @@ -140,7 +158,15 @@ typedef struct _Ecore_Drm_Sprite Ecore_Drm_Sprite; /* sturcture to inform drm activation state */ typedef struct _Ecore_Drm_Event_Activate Ecore_Drm_Event_Activate; +/* sturcture to inform drm page flip */ +typedef struct _Ecore_Drm_Event_Page_Flip Ecore_Drm_Event_Page_Flip; + +/* sturcture to inform drm vblank */ +typedef struct _Ecore_Drm_Event_Vblank Ecore_Drm_Event_Vblank; + EAPI extern int ECORE_DRM_EVENT_ACTIVATE; +EAPI extern int ECORE_DRM_EVENT_PAGE_FLIP; +EAPI extern int ECORE_DRM_EVENT_VBLANK; /** * @file diff --git a/src/lib/ecore_drm/ecore_drm.c b/src/lib/ecore_drm/ecore_drm.c index 81a6fa9500..9ca2b80d23 100644 --- a/src/lib/ecore_drm/ecore_drm.c +++ b/src/lib/ecore_drm/ecore_drm.c @@ -12,6 +12,8 @@ static int _ecore_drm_init_count = 0; int _ecore_drm_log_dom = -1; EAPI int ECORE_DRM_EVENT_ACTIVATE = 0; +EAPI int ECORE_DRM_EVENT_PAGE_FLIP = 0; +EAPI int ECORE_DRM_EVENT_VBLANK = 0; static void _ecore_drm_event_activate_free(void *data EINA_UNUSED, void *event) @@ -89,6 +91,8 @@ ecore_drm_init(void) if (!eeze_init()) goto eeze_err; ECORE_DRM_EVENT_ACTIVATE = ecore_event_type_new(); + ECORE_DRM_EVENT_PAGE_FLIP = ecore_event_type_new(); + ECORE_DRM_EVENT_VBLANK = ecore_event_type_new(); /* return init count */ return _ecore_drm_init_count; diff --git a/src/lib/ecore_drm/ecore_drm_device.c b/src/lib/ecore_drm/ecore_drm_device.c index c2f0d02adc..41f75850ff 100644 --- a/src/lib/ecore_drm/ecore_drm_device.c +++ b/src/lib/ecore_drm/ecore_drm_device.c @@ -10,41 +10,35 @@ static Eina_List *drm_devices; static void _ecore_drm_device_cb_page_flip(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) { - Ecore_Drm_Output *output; - - DBG("Drm Page Flip Event"); - - if (!(output = data)) return; - - if (output->pending_flip) - { - ecore_drm_output_fb_release(output, output->current); - output->current = output->next; - output->next = NULL; - } - - output->pending_flip = EINA_FALSE; - if (!output->pending_vblank) ecore_drm_output_repaint(output); + Ecore_Drm_Event_Page_Flip *e; + + e = calloc(1, sizeof(Ecore_Drm_Event_Page_Flip)); + if (!e) + return; + + e->fd = fd; + e->sequence = frame; + e->sec = sec; + e->usec = usec; + e->data = data; + ecore_event_add(ECORE_DRM_EVENT_PAGE_FLIP, e, NULL, NULL); } static void _ecore_drm_device_cb_vblank(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) { - Ecore_Drm_Sprite *sprite; - Ecore_Drm_Output *output; - - DBG("Drm VBlank Event"); - - if (!(sprite = data)) return; - - output = sprite->output; - output->pending_vblank = EINA_FALSE; - - ecore_drm_output_fb_release(output, sprite->current_fb); - sprite->current_fb = sprite->next_fb; - sprite->next_fb = NULL; - - if (!output->pending_flip) _ecore_drm_output_frame_finish(output); + Ecore_Drm_Event_Vblank *e; + + e = calloc(1, sizeof(Ecore_Drm_Event_Vblank)); + if (!e) + return; + + e->fd = fd; + e->sequence = frame; + e->sec = sec; + e->usec = usec; + e->data = data; + ecore_event_add(ECORE_DRM_EVENT_VBLANK, e, NULL, NULL); } static Eina_Bool @@ -303,9 +297,6 @@ ecore_drm_device_open(Ecore_Drm_Device *dev) ecore_main_fd_handler_add(dev->drm.fd, ECORE_FD_READ, _ecore_drm_device_cb_event, dev, NULL, NULL); - dev->drm.idler = - ecore_idle_enterer_add(_ecore_drm_device_cb_idle, dev); - return EINA_TRUE; } diff --git a/src/lib/ecore_drm/ecore_drm_tty.c b/src/lib/ecore_drm/ecore_drm_tty.c index f9ea64c305..979047847b 100644 --- a/src/lib/ecore_drm/ecore_drm_tty.c +++ b/src/lib/ecore_drm/ecore_drm_tty.c @@ -66,7 +66,6 @@ _ecore_drm_tty_setup(Ecore_Drm_Device *dev) if (kmode != KD_TEXT) { WRN("Virtual Terminal already in KD_GRAPHICS mode"); - return EINA_FALSE; } if (ioctl(dev->tty.fd, VT_ACTIVATE, minor(st.st_rdev)) < 0) 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 afb747c15d..c7019a0e16 100644 --- a/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c +++ b/src/modules/ecore_evas/engines/drm/ecore_evas_drm.c @@ -26,6 +26,13 @@ typedef struct _Ecore_Evas_Engine_Drm_Data Ecore_Evas_Engine_Drm_Data; struct _Ecore_Evas_Engine_Drm_Data { int w, h; + struct + { + void (*flip) (int fd, unsigned int seq, unsigned int sec, unsigned int usec, void *data); + void (*vblank) (int fd, unsigned int seq, unsigned int sec, unsigned int usec, void *data); + } func; + int wait_for_flip_done; + int need_render; }; /* local function prototypes */ @@ -72,9 +79,13 @@ static int _ecore_evas_drm_render_updates_process(Ecore_Evas *ee, Eina_List *upd static void _ecore_evas_drm_screen_geometry_get(const Ecore_Evas *ee EINA_UNUSED, int *x, int *y, int *w, int *h); static void _ecore_evas_drm_pointer_xy_get(const Ecore_Evas *ee, Evas_Coord *x, Evas_Coord *y); +static Eina_Bool _ecore_evas_drm_event_page_flip(void *data, int type, void *event); +static Eina_Bool _ecore_evas_drm_event_vblank(void *data, int type, void *event); + /* local variables */ static int _ecore_evas_init_count = 0; static Ecore_Drm_Device *dev = NULL; +static Ecore_Event_Handler *_ecore_evas_event_handlers[2]; static Ecore_Evas_Engine_Func _ecore_evas_drm_engine_func = { @@ -280,6 +291,14 @@ ecore_evas_drm_new_internal(const char *device, unsigned int parent EINA_UNUSED, (ecore_time_get() * 1000.0) & 0xffffffff), NULL); + _ecore_evas_event_handlers[0] = + ecore_event_handler_add(ECORE_DRM_EVENT_PAGE_FLIP, + _ecore_evas_drm_event_page_flip, ee); + + _ecore_evas_event_handlers[1] = + ecore_event_handler_add(ECORE_DRM_EVENT_VBLANK, + _ecore_evas_drm_event_vblank, ee); + return ee; eng_err: @@ -411,6 +430,10 @@ ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUS gbm_surface_create(einfo->info.gbm, w, h, format, flags); } + /* setting up drm event handler of evas gl_drm engine */ + if (einfo->func.flip) edata->func.flip = einfo->func.flip; + if (einfo->func.vblank) edata->func.vblank = einfo->func.vblank; + if (!evas_engine_info_set(ee->evas, (Evas_Engine_Info *)einfo)) { ERR("evas_engine_info_set() for engine '%s' failed.", ee->driver); @@ -440,6 +463,14 @@ ecore_evas_gl_drm_new_internal(const char *device, unsigned int parent EINA_UNUS (ecore_time_get() * 1000.0) & 0xffffffff), NULL); + _ecore_evas_event_handlers[0] = + ecore_event_handler_add(ECORE_DRM_EVENT_PAGE_FLIP, + _ecore_evas_drm_event_page_flip, ee); + + _ecore_evas_event_handlers[1] = + ecore_event_handler_add(ECORE_DRM_EVENT_VBLANK, + _ecore_evas_drm_event_vblank, ee); + return ee; eng_err: @@ -534,8 +565,16 @@ dev_err: static int _ecore_evas_drm_shutdown(void) { + unsigned int i; + if (--_ecore_evas_init_count != 0) return _ecore_evas_init_count; + for (i = 0; i < sizeof(_ecore_evas_event_handlers) / sizeof(Ecore_Event_Handler*); i++) + { + if (_ecore_evas_event_handlers[i]) + ecore_event_handler_del(_ecore_evas_event_handlers[i]); + } + ecore_drm_inputs_destroy(dev); /* NB: No need to free outputs here. Is done in device free */ ecore_drm_sprites_destroy(dev); @@ -549,6 +588,50 @@ _ecore_evas_drm_shutdown(void) return _ecore_evas_init_count; } +static Eina_Bool +_ecore_evas_drm_event_page_flip(void *data, int type EINA_UNUSED, void *event) +{ + Ecore_Evas *ee; + Ecore_Drm_Event_Page_Flip *e; + Ecore_Evas_Engine_Drm_Data *edata; + + e = event; + ee = data; + edata = ee->engine.data; + + if (edata->func.flip) + edata->func.flip(e->fd, e->sequence, e->sec, e->usec, e->data); + + if (edata->wait_for_flip_done) + { + edata->wait_for_flip_done = 0; + if (edata->need_render) + { + _ecore_evas_drm_render(ee); + edata->need_render = 0; + } + } + + return ECORE_CALLBACK_PASS_ON; +} + +static Eina_Bool +_ecore_evas_drm_event_vblank(void *data, int type EINA_UNUSED, void *event) +{ + Ecore_Evas *ee; + Ecore_Drm_Event_Vblank *e; + Ecore_Evas_Engine_Drm_Data *edata; + + e = event; + ee = data; + edata = ee->engine.data; + + if (edata->func.vblank) + edata->func.vblank(e->fd, e->sequence, e->sec, e->usec, e->data); + + return ECORE_CALLBACK_PASS_ON; +} + static Ecore_Evas_Interface_Drm * _ecore_evas_drm_interface_new(void) { @@ -944,6 +1027,9 @@ _ecore_evas_drm_render(Ecore_Evas *ee) Eina_List *l; Ecore_Evas *ee2; + Ecore_Evas_Engine_Drm_Data *edata; + edata = ee->engine.data; + if (ee->in_async_render) return 0; if (!ee->visible) @@ -952,6 +1038,12 @@ _ecore_evas_drm_render(Ecore_Evas *ee) return 0; } + if (edata->wait_for_flip_done) + { + edata->need_render = 1; + return 0; + } + EINA_LIST_FOREACH(ee->sub_ecore_evas, l, ee2) { if (ee2->func.fn_pre_render) ee2->func.fn_pre_render(ee2); @@ -969,6 +1061,9 @@ _ecore_evas_drm_render(Ecore_Evas *ee) updates = evas_render_updates(ee->evas); rend = _ecore_evas_drm_render_updates_process(ee, updates); evas_render_updates_free(updates); + + if (rend) + edata->wait_for_flip_done = 1; } else if (evas_render_async(ee->evas)) { diff --git a/src/modules/evas/engines/drm/evas_drm.c b/src/modules/evas/engines/drm/evas_drm.c index f4c35360c0..5d19edcf81 100644 --- a/src/modules/evas/engines/drm/evas_drm.c +++ b/src/modules/evas/engines/drm/evas_drm.c @@ -13,21 +13,6 @@ _evas_drm_crtc_buffer_get(int fd, int crtc_id) return id; } -static void -_evas_drm_outbuf_page_flip(int fd EINA_UNUSED, unsigned int seq EINA_UNUSED, unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED, void *data) -{ - Outbuf *ob; - - /* get the output buffer from data */ - if (!(ob = data)) return; - - /* DBG("Page Flip Event"); */ - - ob->priv.pending_flip = EINA_FALSE; - ob->priv.last = ob->priv.curr; - ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num; -} - /* static void */ /* _evas_drm_outbuf_vblank(int fd EINA_UNUSED, unsigned int frame EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) */ /* { */ @@ -105,12 +90,6 @@ evas_drm_outbuf_setup(Outbuf *ob) /* check for valid Output buffer */ if ((!ob) || (ob->priv.fd < 0)) return EINA_FALSE; - /* setup drmHandleEvent context */ - memset(&ob->priv.ctx, 0, sizeof(ob->priv.ctx)); - ob->priv.ctx.version = DRM_EVENT_CONTEXT_VERSION; - ob->priv.ctx.page_flip_handler = _evas_drm_outbuf_page_flip; - /* ob->priv.ctx.vblank_handler = _evas_drm_outbuf_vblank; */ - /* try to get drm resources */ if (!(res = drmModeGetResources(ob->priv.fd))) { @@ -367,10 +346,8 @@ evas_drm_framebuffer_send(Outbuf *ob, Buffer *buffer) return EINA_FALSE; } - ob->priv.pending_flip = EINA_TRUE; - - while (ob->priv.pending_flip) - drmHandleEvent(ob->priv.fd, &ob->priv.ctx); + ob->priv.last = ob->priv.curr; + ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num; } else { 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 92069b61e0..c7cb7391b5 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 @@ -33,6 +33,13 @@ struct _Evas_Engine_Info_GL_Drm void *data; } callback; + struct + { + /* functions for handling drm events */ + void (*flip) (int fd, unsigned int seq, unsigned int sec, unsigned int usec, void *data); + void (*vblank) (int fd, unsigned int seq, unsigned int sec, unsigned int usec, void *data); + } func; + /* non-blocking or blocking mode */ Evas_Engine_Render_Mode render_mode; diff --git a/src/modules/evas/engines/gl_drm/evas_drm.c b/src/modules/evas/engines/gl_drm/evas_drm.c index 22d92e3bae..32b76aaa8e 100644 --- a/src/modules/evas/engines/gl_drm/evas_drm.c +++ b/src/modules/evas/engines/gl_drm/evas_drm.c @@ -70,8 +70,8 @@ _evas_drm_crtc_buffer_get(int fd, int crtc_id) return id; } -static void -_evas_drm_outbuf_page_flip(int fd EINA_UNUSED, unsigned int seq EINA_UNUSED, unsigned int tv_sec EINA_UNUSED, unsigned int tv_usec EINA_UNUSED, void *data) +void +evas_drm_outbuf_event_flip(int fd EINA_UNUSED, unsigned int seq EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) { Outbuf *ob; Buffer *buff; @@ -86,6 +86,13 @@ _evas_drm_outbuf_page_flip(int fd EINA_UNUSED, unsigned int seq EINA_UNUSED, uns ob->priv.curr = (ob->priv.curr + 1) % ob->priv.num; } +void +evas_drm_outbuf_event_vblank(int fd EINA_UNUSED, unsigned int seq EINA_UNUSED, unsigned int sec EINA_UNUSED, unsigned int usec EINA_UNUSED, void *data) +{ + /* do nothing */ + ; +} + static Eina_Bool _evas_drm_outbuf_planes_setup(Outbuf *ob, drmModePlaneResPtr pres) { @@ -191,11 +198,6 @@ evas_drm_outbuf_setup(Outbuf *ob) /* check for valid Output buffer */ if ((!ob) || (ob->priv.fd < 0)) return EINA_FALSE; - /* setup drmHandleEvent context */ - memset(&ob->priv.ctx, 0, sizeof(ob->priv.ctx)); - ob->priv.ctx.version = DRM_EVENT_CONTEXT_VERSION; - ob->priv.ctx.page_flip_handler = _evas_drm_outbuf_page_flip; - /* try to get drm resources */ if (!(res = drmModeGetResources(ob->priv.fd))) { @@ -365,9 +367,6 @@ evas_drm_framebuffer_send(Outbuf *ob, Buffer *buffer) } ob->priv.pending_flip = EINA_TRUE; - - while (ob->priv.pending_flip) - drmHandleEvent(ob->priv.fd, &ob->priv.ctx); } else { diff --git a/src/modules/evas/engines/gl_drm/evas_engine.c b/src/modules/evas/engines/gl_drm/evas_engine.c index 4c6bf7452b..89e3a7c8d3 100644 --- a/src/modules/evas/engines/gl_drm/evas_engine.c +++ b/src/modules/evas/engines/gl_drm/evas_engine.c @@ -541,6 +541,12 @@ eng_info(Evas *eo_e EINA_UNUSED) info->magic.magic = rand(); info->render_mode = EVAS_RENDER_MODE_BLOCKING; + /* setup drm page flip done and vblank event handlers. + * then these will be called when drm event occurrs. + */ + info->func.flip = evas_drm_outbuf_event_flip; + info->func.vblank = evas_drm_outbuf_event_vblank; + return info; } diff --git a/src/modules/evas/engines/gl_drm/evas_engine.h b/src/modules/evas/engines/gl_drm/evas_engine.h index 622f83203a..43b3f6e115 100644 --- a/src/modules/evas/engines/gl_drm/evas_engine.h +++ b/src/modules/evas/engines/gl_drm/evas_engine.h @@ -63,7 +63,7 @@ extern Evas_GL_Preload_Render_Call glsym_evas_gl_preload_render_unlock; # endif # define CRI(...) EINA_LOG_DOM_CRIT(_evas_engine_gl_drm_log_dom, __VA_ARGS__) -# define NUM_BUFFERS 2 +# define NUM_BUFFERS 4 typedef struct _Buffer Buffer; typedef struct _Plane Plane; @@ -127,7 +127,6 @@ struct _Outbuf Buffer buffer[NUM_BUFFERS]; int curr, num; drmModeModeInfo mode; - drmEventContext ctx; Eina_List *pending_writes; Eina_List *planes; Eina_Bool pending_flip : 1; @@ -183,4 +182,6 @@ Eina_Bool evas_drm_gbm_shutdown(Evas_Engine_Info_GL_Drm *info); Eina_Bool evas_drm_outbuf_setup(Outbuf *ob); void evas_drm_outbuf_framebuffer_set(Outbuf *ob, Buffer *buffer); Eina_Bool evas_drm_framebuffer_send(Outbuf *ob, Buffer *buffer); +void evas_drm_outbuf_event_flip(int fd, unsigned int seq, unsigned int sec, unsigned int usec, void *data); +void evas_drm_outbuf_event_vblank(int fd, unsigned int seq, unsigned int sec, unsigned int usec, void *data); #endif |