aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael Antognolli <antognolli@gmail.com>2013-01-28 19:13:46 +0000
committerRafael Antognolli <antognolli@gmail.com>2013-01-28 19:13:46 +0000
commit1210067fbeb21bdce34ec710e66749de981a1617 (patch)
treefdd4464005c233e481eb97f4cd721d114b2b0c99
parent003b7f12d8010ccca9abde6fbbc5344a476e5003 (diff)
downloadefl-1210067fbeb21bdce34ec710e66749de981a1617.tar.gz
efl-1210067fbeb21bdce34ec710e66749de981a1617.tar.xz
efl-1210067fbeb21bdce34ec710e66749de981a1617.zip
ecore_evas/wayland_egl: Only render if last frame has been presented.
This avoids blocking in eglSwapBuffers and has the side effect of avoiding doing unnecessary work - painting where a frame won't be presented. We do this by using the event that the wayland compositor will send us to tell us that the frame has been presented. Due to the fact that evas_render_updates() could do no work and not cause a eglSwapBuffers we must always have a frame callback listener setup. Original patch by: Rob Bradford <rob@linux.intel.com> (I just adjusted the patch to the single efl tree) SVN revision: 83387
-rw-r--r--ChangeLog5
-rw-r--r--NEWS1
-rw-r--r--src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c27
-rw-r--r--src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c105
4 files changed, 110 insertions, 28 deletions
diff --git a/ChangeLog b/ChangeLog
index a9e7833e3..47f89f6bf 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -380,3 +380,8 @@
2013-01-28 Daniel Willmann <d.willmann@samsung.com>
* Use ecore_audio in edje-multisense
+
+2013-01-28 Rafael Antognolli <antognolli@gmail.com>
+
+ * Ecore_Evas wayland-egl only renders now if last frame has
+ been presented.
diff --git a/NEWS b/NEWS
index ee96a2a36..378155683 100644
--- a/NEWS
+++ b/NEWS
@@ -86,6 +86,7 @@ Improvements:
* edje entry: remove ecore_imf_context_reset, cursor update in mouse move event because it's useless.
* edje entry: move ecore_imf_context_cursor_position_set from mouse down event to mouse up event.
* Use ecore_audio in edje-multisense
+ * Ecore_Evas wayland-egl only renders now if last frame has been presented.
Fixes:
* Fix PPC (big endian) image codec bug.
diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
index c0cc37dd3..72ec92b5f 100644
--- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
+++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
@@ -723,33 +723,6 @@ _ecore_evas_wl_common_pre_render(Ecore_Evas *ee)
return rend;
}
-int
-_ecore_evas_wl_common_render_updates(Ecore_Evas *ee)
-{
- int rend = 0;
- Eina_List *updates = NULL;
- Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
-
- LOGFN(__FILE__, __LINE__, __FUNCTION__);
-
- if ((updates = evas_render_updates(ee->evas)))
- {
- Eina_List *l = NULL;
- Eina_Rectangle *r;
-
- EINA_LIST_FOREACH(updates, l, r)
- ecore_wl_window_damage(wdata->win,
- r->x, r->y, r->w, r->h);
-
- ecore_wl_flush();
-
- evas_render_updates_free(updates);
- rend = 1;
- }
-
- return rend;
-}
-
void
_ecore_evas_wl_common_post_render(Ecore_Evas *ee)
{
diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c
index b79766018..df7eeb0c3 100644
--- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c
+++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_egl.c
@@ -10,6 +10,7 @@
/* local function prototypes */
+static int _ecore_evas_wl_render(Ecore_Evas *ee);
static void _ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h);
static void _ecore_evas_wl_show(Ecore_Evas *ee);
static void _ecore_evas_wl_hide(Ecore_Evas *ee);
@@ -72,7 +73,7 @@ static Ecore_Evas_Engine_Func _ecore_wl_engine_func =
NULL, // modal set
NULL, // demand attention set
NULL, // focus skip set
- _ecore_evas_wl_common_render,
+ _ecore_evas_wl_render,
_ecore_evas_wl_common_screen_geometry_get,
_ecore_evas_wl_common_screen_dpi_get
};
@@ -228,6 +229,108 @@ ecore_evas_wayland_egl_new_internal(const char *disp_name, unsigned int parent,
return NULL;
}
+static void
+_ecore_evas_wl_frame_complete (void *data, struct wl_callback *callback, uint32_t time EINA_UNUSED);
+
+static const struct wl_callback_listener frame_listener = {
+ _ecore_evas_wl_frame_complete,
+};
+
+static void
+_ecore_evas_wl_frame_complete (void *data, struct wl_callback *callback, uint32_t time EINA_UNUSED)
+{
+ Ecore_Evas *ee = data;
+ Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
+
+ wdata->win->frame_callback = NULL;
+ wdata->win->frame_pending = EINA_FALSE;
+ wl_callback_destroy(callback);
+
+ wdata->win->frame_callback =
+ wl_surface_frame(wdata->win->surface);
+
+ wl_callback_add_listener(wdata->win->frame_callback,
+ &frame_listener, ee);
+}
+
+int
+_ecore_evas_wl_render_updates(Ecore_Evas *ee)
+{
+ int rend = 0;
+ Eina_List *updates = NULL;
+ Ecore_Evas_Engine_Wl_Data *wdata = ee->engine.data;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ /* eglSwapBuffers is ultimately called by evas_render_updates() if
+ * there is some update to make. So we must pre-emptively create a
+ * frame callback handler. We make sure we always have one of these in
+ * available to track if the event is presented.
+ *
+ * This frame callback will be fired when the frame has been presented
+ * and we can safely call eglSwapBuffers without it blocking. Whether
+ * to render or not is handled by the frame_pending boolean which is
+ * reset on the frame callback event.
+ */
+ if (!wdata->win->frame_pending)
+ {
+ /* FIXME - ideally have an evas_changed_get to return the value
+ * of evas->changed to avoid creating this callback and
+ * destroying it again
+ */
+
+ if (!wdata->win->frame_callback)
+ {
+ wdata->win->frame_callback =
+ wl_surface_frame(wdata->win->surface);
+
+ wl_callback_add_listener(wdata->win->frame_callback,
+ &frame_listener, ee);
+ }
+
+ if ((updates = evas_render_updates(ee->evas)))
+ {
+ Eina_List *l = NULL;
+ Eina_Rectangle *r;
+
+ EINA_LIST_FOREACH(updates, l, r)
+ ecore_wl_window_damage(wdata->win,
+ r->x, r->y, r->w, r->h);
+
+ ecore_wl_flush();
+
+ evas_render_updates_free(updates);
+
+ wdata->win->frame_pending = EINA_TRUE;
+
+ rend = 1;
+ }
+ }
+
+ return rend;
+}
+
+static int
+_ecore_evas_wl_render(Ecore_Evas *ee)
+{
+ int rend = 0;
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+ if (!ee) return 0;
+ if (!ee->visible)
+ {
+ evas_norender(ee->evas);
+ return 0;
+ }
+
+ rend = _ecore_evas_wl_common_pre_render(ee);
+ rend |= _ecore_evas_wl_render_updates(ee);
+ _ecore_evas_wl_common_post_render(ee);
+
+ return rend;
+}
+
static void
_ecore_evas_wl_resize(Ecore_Evas *ee, int w, int h)
{