summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGwanglim Lee <gl77.lee@samsung.com>2015-04-10 01:11:07 +0900
committerGwanglim Lee <gl77.lee@samsung.com>2015-04-10 01:11:07 +0900
commit9309a9feef7d0d174bea16e702eff621e29afa50 (patch)
tree39e8d02ba641143ce7f844c332bfc13c699f0402
parenteaca0b233acdf750543ccdfbed07c22aecbb5d2d (diff)
downloadefl-9309a9feef7d0d174bea16e702eff621e29afa50.tar.gz
ecore_evas_drm: improve drm page flip event handling
Change-Id: I5f0cda91b905c2f3e6057a3a1f81948ec2a8bc88
-rw-r--r--src/lib/ecore_drm/Ecore_Drm.h26
-rw-r--r--src/lib/ecore_drm/ecore_drm.c4
-rw-r--r--src/lib/ecore_drm/ecore_drm_device.c57
-rw-r--r--src/lib/ecore_drm/ecore_drm_tty.c1
-rw-r--r--src/modules/ecore_evas/engines/drm/ecore_evas_drm.c95
-rw-r--r--src/modules/evas/engines/drm/evas_drm.c27
-rw-r--r--src/modules/evas/engines/gl_drm/Evas_Engine_GL_Drm.h7
-rw-r--r--src/modules/evas/engines/gl_drm/evas_drm.c19
-rw-r--r--src/modules/evas/engines/gl_drm/evas_engine.c6
-rw-r--r--src/modules/evas/engines/gl_drm/evas_engine.h5
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