summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMike Blumenkrantz <zmike@samsung.com>2014-01-10 02:26:06 -0500
committerMike Blumenkrantz <zmike@samsung.com>2014-01-11 14:58:43 -0500
commit09092b4675c907381db1c353c54044edcd3808bf (patch)
tree2dc8cd75631cb474d737ffb9b210a90856ab700a
parent3e89295c73f9ffc432a8c03168b5779439918ff9 (diff)
downloadefl-devs/discomfitor/present.tar.gz
ecore-x now supports XPRESENTdevs/discomfitor/present
-rw-r--r--configure.ac24
-rw-r--r--src/Makefile_Ecore_X.am2
-rw-r--r--src/lib/ecore_x/Ecore_X.h78
-rw-r--r--src/lib/ecore_x/xcb/ecore_xcb_events.c16
-rw-r--r--src/lib/ecore_x/xcb/ecore_xcb_extensions.c3
-rw-r--r--src/lib/ecore_x/xcb/ecore_xcb_present.c194
-rw-r--r--src/lib/ecore_x/xcb/ecore_xcb_private.h5
-rw-r--r--src/lib/ecore_x/xlib/ecore_x.c5
-rw-r--r--src/lib/ecore_x/xlib/ecore_x_events.c22
-rw-r--r--src/lib/ecore_x/xlib/ecore_x_present.c169
-rw-r--r--src/lib/ecore_x/xlib/ecore_x_private.h9
11 files changed, 514 insertions, 13 deletions
diff --git a/configure.ac b/configure.ac
index 8f991867f3..62ed2c5682 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2697,6 +2697,17 @@ AC_ARG_ENABLE([gesture],
],
[want_gesture="no"])
+AC_ARG_ENABLE([xpresent],
+ [AC_HELP_STRING([--enable-xpresent], [enable X11 XPresent extension support])],
+ [
+ if test "x${enableval}" = "xyes" ; then
+ want_xpresent="yes"
+ else
+ want_xpresent="no"
+ fi
+ ],
+ [want_xpresent="no"])
+
AC_ARG_ENABLE([xinput2],
[AC_HELP_STRING([--disable-xinput2], [disable X11 XInput v2.x support])],
[
@@ -2861,6 +2872,11 @@ if test "x${want_x11_xlib}" = "xyes" ; then
ECORE_CHECK_X_EXTENSION([Xtest], [XTest.h], [Xtst], [XTestFakeKeyEvent])
ECORE_CHECK_X_EXTENSION([Xss], [scrnsaver.h], [Xss], [XScreenSaverSelectInput])
+ if test "${want_xpresent}" = "yes"; then
+ ECORE_CHECK_X_EXTENSION([Xpresent], [Xpresent.h], [Xpresent], [XPresentQueryExtension])
+ fi
+ EFL_ADD_FEATURE([ECORE_X], [xpresent])
+
if test "${want_gesture}" = "yes"; then
ECORE_CHECK_X_EXTENSION([Xgesture], [gesture.h], [Xgesture], [XGestureQueryExtension])
fi
@@ -2888,7 +2904,7 @@ fi
if test "${want_x11_xcb}" = "yes"; then
dnl note: added pixman-1 as ecore_xcb_region uses that
EFL_DEPEND_PKG([ECORE_X], [ECORE_X_XCB],
- [x11-xcb xcb xcb-shm xcb-event xcb-icccm >= 0.3.8 xcb-util >= 0.3.8 xcb-image xcb-keysyms >= 0.3.8 xcb-composite xcb-damage xcb-dpms xcb-randr xcb-render xcb-screensaver xcb-shape xcb-sync xcb-xfixes xcb-xinerama xcb-xprint xcb-xtest xcb-renderutil pixman-1])
+ [x11-xcb xcb xcb-shm xcb-event xcb-icccm >= 0.3.8 xcb-util >= 0.3.8 xcb-image xcb-keysyms >= 0.3.8 xcb-composite xcb-present xcb-damage xcb-dpms xcb-randr xcb-render xcb-screensaver xcb-shape xcb-sync xcb-xfixes xcb-xinerama xcb-xprint xcb-xtest xcb-renderutil pixman-1])
dnl TODO: remove these ifdefs from code!
AC_DEFINE([ECORE_XCB_COMPOSITE], [1], [Build support for XCB composite])
@@ -2905,6 +2921,12 @@ dnl TODO: remove these ifdefs from code!
AC_DEFINE([ECORE_XCB_XTEST], [1], [Build support for XCB xtest])
AC_DEFINE([ECORE_XCB_CURSOR], [1], [Build support for XCB cursor])
+ EFL_OPTIONAL_DEPEND_PKG([ECORE_X], [${want_xpresent}], [ECORE_XCB_XPRESENT],
+ [xcb-present])
+ AC_DEFINE_IF([ECORE_XCB_XPRESENT], [test "${want_xpresent}" = "yes"],
+ [1], [Build support for XCB Present])
+ EFL_ADD_FEATURE([ECORE_X], [xpresent])
+
EFL_OPTIONAL_DEPEND_PKG([ECORE_X], [${want_gesture}], [ECORE_XCB_GESTURE],
[xcb-gesture])
AC_DEFINE_IF([ECORE_XCB_XGESTURE], [test "${want_gesture}" = "yes"],
diff --git a/src/Makefile_Ecore_X.am b/src/Makefile_Ecore_X.am
index d0c6e85b14..0b6d390e17 100644
--- a/src/Makefile_Ecore_X.am
+++ b/src/Makefile_Ecore_X.am
@@ -38,6 +38,7 @@ lib/ecore_x/xcb/ecore_xcb_input.c \
lib/ecore_x/xcb/ecore_xcb_gesture.c \
lib/ecore_x/xcb/ecore_xcb_mwm.c \
lib/ecore_x/xcb/ecore_xcb_pixmap.c \
+lib/ecore_x/xcb/ecore_xcb_present.c \
lib/ecore_x/xcb/ecore_xcb_region.c \
lib/ecore_x/xcb/ecore_xcb_selection.c \
lib/ecore_x/xcb/ecore_xcb_textlist.c \
@@ -75,6 +76,7 @@ lib/ecore_x/xlib/ecore_x_window.c \
lib/ecore_x/xlib/ecore_x_window_prop.c \
lib/ecore_x/xlib/ecore_x_window_shape.c \
lib/ecore_x/xlib/ecore_x_pixmap.c \
+lib/ecore_x/xlib/ecore_x_present.c \
lib/ecore_x/xlib/ecore_x_gc.c \
lib/ecore_x/xlib/ecore_x_xinerama.c \
lib/ecore_x/xlib/ecore_x_screensaver.c \
diff --git a/src/lib/ecore_x/Ecore_X.h b/src/lib/ecore_x/Ecore_X.h
index f7c0e7708b..6dbed60c76 100644
--- a/src/lib/ecore_x/Ecore_X.h
+++ b/src/lib/ecore_x/Ecore_X.h
@@ -94,6 +94,7 @@ typedef void Ecore_X_Connection;
typedef void Ecore_X_Screen;
typedef Ecore_X_ID Ecore_X_Sync_Counter;
typedef Ecore_X_ID Ecore_X_Sync_Alarm;
+typedef Ecore_X_ID Ecore_X_Sync_Fence; /**< @since 1.9 */
typedef void Ecore_X_XRegion;
typedef Ecore_X_ID Ecore_X_Randr_Output;
@@ -489,12 +490,18 @@ typedef struct _Ecore_X_Event_Startup_Sequence Ecore_X_Event_Startup
typedef struct _Ecore_X_Event_Generic Ecore_X_Event_Generic;
+
+typedef struct Ecore_X_Event_Present_Configure Ecore_X_Event_Present_Configure; /**< @since 1.9 */
+typedef struct Ecore_X_Event_Present_Complete Ecore_X_Event_Present_Complete; /**< @since 1.9 */
+typedef struct Ecore_X_Event_Present_Idle Ecore_X_Event_Present_Idle; /**< @since 1.9 */
+
typedef struct _Ecore_X_Randr_Screen_Size Ecore_X_Randr_Screen_Size;
typedef struct _Ecore_X_Randr_Screen_Size_MM Ecore_X_Randr_Screen_Size_MM;
typedef struct _Ecore_X_Randr_Crtc_Info Ecore_X_Randr_Crtc_Info; /**< @since 1.8 */
typedef struct _Ecore_X_Xdnd_Position Ecore_X_Xdnd_Position;
+
struct _Ecore_X_Event_Mouse_In
{
int modifiers;
@@ -1053,6 +1060,59 @@ struct _Ecore_X_Event_Generic
void *data;
};
+typedef enum Ecore_X_Present_Event_Mask
+{
+ ECORE_X_PRESENT_EVENT_MASK_NO_EVENT = 0,
+ ECORE_X_PRESENT_EVENT_MASK_CONFIGURE_NOTIFY = 1,
+ ECORE_X_PRESENT_EVENT_MASK_COMPLETE_NOTIFY = 2,
+ ECORE_X_PRESENT_EVENT_MASK_IDLE_NOTIFY = 4,
+} Ecore_X_Present_Event_Mask; /**< @since 1.9 */
+
+typedef struct Ecore_X_Present
+{
+ Ecore_X_Window win;
+ unsigned int serial;
+} Ecore_X_Present; /**< @since 1.9 */
+
+struct Ecore_X_Event_Present_Configure
+{
+ Ecore_X_Window win;
+
+ int x, y;
+ unsigned int width, height;
+ int off_x, off_y;
+ int pixmap_width, pixmap_height;
+ long pixmap_flags;
+}; /**< @since 1.9 */
+
+typedef enum
+{
+ ECORE_X_PRESENT_COMPLETE_MODE_COPY,
+ ECORE_X_PRESENT_COMPLETE_MODE_FLIP,
+ ECORE_X_PRESENT_COMPLETE_MODE_SKIP,
+} Ecore_X_Present_Complete_Mode;
+
+struct Ecore_X_Event_Present_Complete
+{
+ Ecore_X_Window win;
+
+ unsigned int serial; // value provided when generating request
+ unsigned long long ust; // system time of presentation
+ unsigned long long msc; // frame count at time of presentation
+ Eina_Bool kind : 1; /* 0 for PresentCompleteKindPixmap (PresentPixmap completion),
+ 1 for PresentCompleteKindNotifyMsc (PresentNotifyMSC completion) */
+ Ecore_X_Present_Complete_Mode mode;
+}; /**< @since 1.9 */
+
+struct Ecore_X_Event_Present_Idle
+{
+ Ecore_X_Window win;
+
+ unsigned int serial;
+ Ecore_X_Pixmap pixmap;
+ Ecore_X_Sync_Fence idle_fence;
+}; /**< @since 1.9 */
+
EAPI extern int ECORE_X_EVENT_ANY; /**< low level event dependent on
backend in use, if Xlib will be XEvent, if XCB will be xcb_generic_event_t.
@warning avoid using it.
@@ -1118,6 +1178,10 @@ EAPI extern int ECORE_X_EVENT_XKB_NEWKBD_NOTIFY; /** @since 1.7 */
EAPI extern int ECORE_X_EVENT_GENERIC;
+EAPI extern int ECORE_X_EVENT_PRESENT_CONFIGURE; /**< @since 1.9 */
+EAPI extern int ECORE_X_EVENT_PRESENT_COMPLETE; /**< @since 1.9 */
+EAPI extern int ECORE_X_EVENT_PRESENT_IDLE; /**< @since 1.9 */
+
EAPI extern int ECORE_X_EVENT_XDND_ENTER;
EAPI extern int ECORE_X_EVENT_XDND_POSITION;
EAPI extern int ECORE_X_EVENT_XDND_STATUS;
@@ -2356,6 +2420,20 @@ EAPI void ecore_x_composite_window_events_enable(Ecore_X_Window wi
EAPI Ecore_X_Window ecore_x_composite_render_window_enable(Ecore_X_Window root);
EAPI void ecore_x_composite_render_window_disable(Ecore_X_Window root);
+/* XPresent Extension Support */
+/** @since 1.9 */
+EAPI void ecore_x_present_select_events(Ecore_X_Window win, unsigned int events);
+/** @since 1.9 */
+EAPI void ecore_x_present_notify_msc(Ecore_X_Window win, unsigned int serial, unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder);
+/** @since 1.9 */
+EAPI void ecore_x_present_pixmap(Ecore_X_Window win, Ecore_X_Pixmap pixmap, unsigned int serial, Ecore_X_Region valid,
+ Ecore_X_Region update, int x_off, int y_off, Ecore_X_Randr_Crtc target_crtc,
+ Ecore_X_Sync_Fence wait_fence, Ecore_X_Sync_Fence idle_fence, unsigned int options,
+ unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder,
+ Ecore_X_Present *notifies, int num_notifies);
+/** @since 1.9 */
+EAPI Eina_Bool ecore_x_present_exists(void);
+
/* XDamage Extension Support */
typedef Ecore_X_ID Ecore_X_Damage;
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_events.c b/src/lib/ecore_x/xcb/ecore_xcb_events.c
index 7f76d7a741..adee7ce0ba 100644
--- a/src/lib/ecore_x/xcb/ecore_xcb_events.c
+++ b/src/lib/ecore_x/xcb/ecore_xcb_events.c
@@ -18,6 +18,9 @@
# ifdef ECORE_XCB_XFIXES
# include <xcb/xfixes.h>
# endif
+# ifdef ECORE_XCB_XPRESENT
+# include <xcb/present.h>
+# endif
# ifdef ECORE_XCB_XGESTURE
# include <xcb/gesture.h>
# endif
@@ -184,6 +187,10 @@ EAPI int ECORE_X_EVENT_XKB_STATE_NOTIFY = 0;
EAPI int ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = 0;
EAPI int ECORE_X_EVENT_GENERIC = 0;
+EAPI int ECORE_X_EVENT_PRESENT_CONFIGURE = 0;
+EAPI int ECORE_X_EVENT_PRESENT_COMPLETE = 0;
+EAPI int ECORE_X_EVENT_PRESENT_IDLE = 0;
+
EAPI int ECORE_X_RAW_BUTTON_PRESS = 0;
EAPI int ECORE_X_RAW_BUTTON_RELEASE = 0;
EAPI int ECORE_X_RAW_MOTION = 0;
@@ -253,6 +260,10 @@ _ecore_xcb_events_init(void)
ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = ecore_event_type_new();
ECORE_X_EVENT_GENERIC = ecore_event_type_new();
+ ECORE_X_EVENT_PRESENT_CONFIGURE = ecore_event_type_new();
+ ECORE_X_EVENT_PRESENT_COMPLETE = ecore_event_type_new();
+ ECORE_X_EVENT_PRESENT_IDLE = ecore_event_type_new();
+
ECORE_X_RAW_BUTTON_PRESS = ecore_event_type_new();
ECORE_X_RAW_BUTTON_RELEASE = ecore_event_type_new();
ECORE_X_RAW_MOTION = ecore_event_type_new();
@@ -2303,6 +2314,11 @@ _ecore_xcb_event_handle_generic_event(xcb_generic_event_t *event)
// FIXME: should we generate generic events as WELL as input events?
// return;
}
+ else if (ev->pad0 == _ecore_xcb_event_xpresent)
+ {
+ _ecore_xcb_event_handle_present_event((xcb_ge_event_t*)event);
+ return;
+ }
if (!(e = calloc(1, sizeof(Ecore_X_Event_Generic))))
return;
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_extensions.c b/src/lib/ecore_x/xcb/ecore_xcb_extensions.c
index 40c10ac05b..2e3577bf1c 100644
--- a/src/lib/ecore_x/xcb/ecore_xcb_extensions.c
+++ b/src/lib/ecore_x/xcb/ecore_xcb_extensions.c
@@ -64,6 +64,8 @@ _ecore_xcb_extensions_init(void)
_ecore_xcb_gesture_init();
#endif
+ _ecore_xcb_present_init();
+
/* #ifdef ECORE_XCB_DRI */
/* _ecore_xcb_dri_init(); */
/* #endif */
@@ -135,6 +137,7 @@ _ecore_xcb_extensions_finalize(void)
_ecore_xcb_gesture_finalize();
#endif
+ _ecore_xcb_present_finalize();
/* #ifdef ECORE_XCB_DRI */
/* _ecore_xcb_dri_finalize(); */
/* #endif */
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_present.c b/src/lib/ecore_x/xcb/ecore_xcb_present.c
new file mode 100644
index 0000000000..b5b426ba28
--- /dev/null
+++ b/src/lib/ecore_x/xcb/ecore_xcb_present.c
@@ -0,0 +1,194 @@
+#include "ecore_xcb_private.h"
+# ifdef ECORE_XCB_XPRESENT
+# include <xcb/present.h>
+# endif
+
+/* local variables */
+static Eina_Bool _xpresent_avail = EINA_FALSE;
+
+/* external variables */
+int _ecore_xcb_event_xpresent = -1;
+
+void
+_ecore_xcb_xpresent_init(void)
+{
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+#ifdef ECORE_XCB_XPRESENT
+ xcb_prefetch_extension_data(_ecore_xcb_conn, &xcb_present_id);
+#endif
+}
+
+void
+_ecore_xcb_xpresent_finalize(void)
+{
+#ifdef ECORE_XCB_XPRESENT
+ const xcb_query_extension_reply_t *ext_reply;
+#endif
+
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+
+#ifdef ECORE_XCB_XPRESENT
+ ext_reply = xcb_get_extension_data(_ecore_xcb_conn, &xcb_present_id);
+ if ((ext_reply) && (ext_reply->present))
+ {
+ xcb_present_query_version_cookie_t cookie;
+ xcb_present_query_version_reply_t *reply;
+
+ cookie =
+ xcb_present_query_version_unchecked(_ecore_xcb_conn,
+ XCB_PRESENT_MAJOR_VERSION,
+ XCB_PRESENT_MINOR_VERSION);
+ reply = xcb_present_query_version_reply(_ecore_xcb_conn, cookie, NULL);
+ if (reply)
+ {
+ _xpresent_avail = EINA_TRUE;
+ free(reply);
+ }
+
+ if (_xpresent_avail)
+ _ecore_xcb_event_xpresent = ext_reply->first_event;
+ }
+#endif
+}
+
+#ifdef ECORE_XCB_XPRESENT
+#define SET(X) e->X = ev->X
+
+static void
+_present_configure(xcb_present_configure_notify_event_t *ev)
+{
+ Ecore_X_Event_Present_Configure *e;
+
+ e = calloc(1, sizeof(Ecore_X_Event_Present_Configure));
+ if (!e) return;
+
+ e->win = ev->window;
+ SET(x), SET(y);
+ SET(width), SET(height);
+ SET(off_x), SET(off_y);
+ SET(pixmap_width), SET(pixmap_height);
+ SET(pixmap_flags);
+
+ ecore_event_add(ECORE_X_EVENT_PRESENT_CONFIGURE, e, NULL, NULL);
+}
+
+static void
+_present_complete(xcb_present_complete_notify_event_t *ev)
+{
+ unsigned int mode[] =
+ {
+ [XCB_PRESENT_COMPLETE_MODE_COPY] = ECORE_X_PRESENT_COMPLETE_MODE_COPY,
+ [XCB_PRESENT_COMPLETE_MODE_FLIP] = ECORE_X_PRESENT_COMPLETE_MODE_FLIP,
+ [XCB_PRESENT_COMPLETE_MODE_SKIP] = ECORE_X_PRESENT_COMPLETE_MODE_SKIP,
+ };
+ Ecore_X_Event_Present_Complete *e;
+
+ e = calloc(1, sizeof(Ecore_X_Event_Present_Complete));
+ if (!e) return;
+
+ e->win = ev->window;
+ SET(serial);
+ SET(ust), SET(msc);
+ e->kind = (ev->kind == XCB_PRESENT_COMPLETE_KIND_NOTIFY_MSC);
+ e->mode = mode[ev->mode];
+ ecore_event_add(ECORE_X_EVENT_PRESENT_COMPLETE, e, NULL, NULL);
+}
+
+static void
+_present_idle(xcb_present_idle_notify_event_t *ev)
+{
+ Ecore_X_Event_Present_Idle *e;
+
+ e = calloc(1, sizeof(Ecore_X_Event_Present_Idle));
+ if (!e) return;
+
+ e->win = ev->window;
+ SET(serial);
+ SET(pixmap);
+ SET(idle_fence);
+ ecore_event_add(ECORE_X_EVENT_PRESENT_IDLE, e, NULL, NULL);
+}
+#undef SET
+
+void
+_ecore_xcb_event_handle_present_event(xcb_ge_event_t *ev)
+{
+ switch (ev->event_type)
+ {
+ case XCB_PRESENT_EVENT_CONFIGURE_NOTIFY:
+ _present_configure((xcb_present_configure_notify_event_t*)(long)ev->pad1);
+ break;
+ case XCB_PRESENT_EVENT_COMPLETE_NOTIFY:
+ _present_complete((xcb_present_complete_notify_event_t*)(long)ev->pad1);
+ break;
+ case XCB_PRESENT_EVENT_IDLE_NOTIFY:
+ _present_idle((xcb_present_idle_notify_event_t*)(long)ev->pad1);
+ break;
+ default: break;
+ }
+}
+#endif
+
+
+EAPI void
+ecore_x_present_select_events(Ecore_X_Window win, unsigned int events)
+{
+#ifdef ECORE_XCB_XPRESENT
+ xcb_present_select_input(_ecore_xcb_conn, _ecore_xcb_event_xpresent, win, events);
+#else
+ (void)win;
+ (void)events;
+#endif
+}
+
+EAPI void
+ecore_x_present_notify_msc(Ecore_X_Window win, unsigned int serial, unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder)
+{
+#ifdef ECORE_XCB_XPRESENT
+ xcb_present_notify_msc(_ecore_xcb_conn, win, serial, target_msc, divisor, remainder);
+#else
+ (void)win;
+ (void)serial;
+ (void)target_msc;
+ (void)divisor;
+ (void)remainder;
+#endif
+}
+
+EAPI void
+ecore_x_present_pixmap(Ecore_X_Window win, Ecore_X_Pixmap pixmap, unsigned int serial, Ecore_X_Region valid,
+ Ecore_X_Region update, int x_off, int y_off, Ecore_X_Randr_Crtc target_crtc,
+ Ecore_X_Sync_Fence wait_fence, Ecore_X_Sync_Fence idle_fence, unsigned int options,
+ unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder,
+ Ecore_X_Present *notifies, int num_notifies)
+{
+#ifdef ECORE_XCB_XPRESENT
+ xcb_present_pixmap(_ecore_xcb_conn, win, pixmap, serial, valid, update,
+ x_off, y_off, target_crtc, wait_fence, idle_fence, options, target_msc,
+ divisor, remainder, num_notifies, (xcb_present_notify_t*)notifies);
+#else
+ (void)win;
+ (void)pixmap;
+ (void)serial;
+ (void)valid;
+ (void)update;
+ (void)x_off;
+ (void)y_off;
+ (void)target_crtc;
+ (void)wait_fence;
+ (void)idle_fence;
+ (void)options;
+ (void)target_msc;
+ (void)divisor;
+ (void)remainder;
+ (void)notifies;
+ (void)num_notifies;
+#endif
+}
+
+EAPI Eina_Bool
+ecore_x_present_exists(void)
+{
+ return _xpresent_avail;
+}
diff --git a/src/lib/ecore_x/xcb/ecore_xcb_private.h b/src/lib/ecore_x/xcb/ecore_xcb_private.h
index d578a975ca..61452f2385 100644
--- a/src/lib/ecore_x/xcb/ecore_xcb_private.h
+++ b/src/lib/ecore_x/xcb/ecore_xcb_private.h
@@ -278,6 +278,11 @@ void _ecore_xcb_damage_finalize(void);
void _ecore_xcb_composite_init(void);
void _ecore_xcb_composite_finalize(void);
+void _ecore_xcb_present_init(void);
+void _ecore_xcb_present_finalize(void);
+void _ecore_xcb_event_handle_present_event(xcb_ge_event_t *ev);
+extern int _ecore_xcb_event_xpresent;
+
void _ecore_xcb_dpms_init(void);
void _ecore_xcb_dpms_finalize(void);
diff --git a/src/lib/ecore_x/xlib/ecore_x.c b/src/lib/ecore_x/xlib/ecore_x.c
index 501bc7ae92..a9be6b6fc7 100644
--- a/src/lib/ecore_x/xlib/ecore_x.c
+++ b/src/lib/ecore_x/xlib/ecore_x.c
@@ -148,6 +148,10 @@ EAPI int ECORE_X_EVENT_XKB_NEWKBD_NOTIFY = 0;
EAPI int ECORE_X_EVENT_GENERIC = 0;
+EAPI int ECORE_X_EVENT_PRESENT_CONFIGURE = 0;
+EAPI int ECORE_X_EVENT_PRESENT_COMPLETE = 0;
+EAPI int ECORE_X_EVENT_PRESENT_IDLE = 0;
+
EAPI int ECORE_X_MODIFIER_SHIFT = 0;
EAPI int ECORE_X_MODIFIER_CTRL = 0;
EAPI int ECORE_X_MODIFIER_ALT = 0;
@@ -665,6 +669,7 @@ ecore_x_init(const char *name)
_ecore_x_fixes_init();
_ecore_x_damage_init();
_ecore_x_composite_init();
+ _ecore_x_present_init();
_ecore_x_dpms_init();
_ecore_x_randr_init();
_ecore_x_gesture_init();
diff --git a/src/lib/ecore_x/xlib/ecore_x_events.c b/src/lib/ecore_x/xlib/ecore_x_events.c
index ac1e475f2d..467cbcd1a7 100644
--- a/src/lib/ecore_x/xlib/ecore_x_events.c
+++ b/src/lib/ecore_x/xlib/ecore_x_events.c
@@ -2270,7 +2270,6 @@ static void
_ecore_x_event_free_generic_event(void *data,
void *ev)
{
-#ifdef ECORE_XI2
Ecore_X_Event_Generic *e = (Ecore_X_Event_Generic *)ev;
if (data)
@@ -2280,16 +2279,11 @@ _ecore_x_event_free_generic_event(void *data,
free(data);
}
free(e);
-#else
- return;
- data = NULL; ev = NULL;
-#endif /* ifdef ECORE_XI2 */
}
void
_ecore_x_event_handle_generic_event(XEvent *event)
{
-#ifdef ECORE_XI2
XGenericEvent *generic_event;
Ecore_X_Event_Generic *e;
XGenericEventCookie *data;
@@ -2297,6 +2291,14 @@ _ecore_x_event_handle_generic_event(XEvent *event)
LOGFN(__FILE__, __LINE__, __FUNCTION__);
generic_event = (XGenericEvent *)event;
+#ifdef ECORE_XPRESENT
+ if (generic_event->extension == _ecore_x_present_major)
+ {
+ _ecore_x_present_handler(generic_event);
+ return;
+ }
+#endif
+
e = calloc(1, sizeof(Ecore_X_Event_Generic));
if (!e)
return;
@@ -2314,20 +2316,16 @@ _ecore_x_event_handle_generic_event(XEvent *event)
e->extension = generic_event->extension;
e->evtype = generic_event->evtype;
-
+#ifdef ECORE_XI2
if (e->extension == _ecore_x_xi2_opcode)
_ecore_x_input_handler(event);
-
+#endif /* ifdef ECORE_XI2 */
data = malloc(sizeof(XGenericEventCookie));
if (data) memcpy(data, &(event->xcookie), sizeof(XGenericEventCookie));
ecore_event_add(ECORE_X_EVENT_GENERIC,
e,
_ecore_x_event_free_generic_event,
data);
-#else
- return;
- event = NULL;
-#endif /* ifdef ECORE_XI2 */
}
#ifdef ECORE_XGESTURE
diff --git a/src/lib/ecore_x/xlib/ecore_x_present.c b/src/lib/ecore_x/xlib/ecore_x_present.c
new file mode 100644
index 0000000000..9e6a398e4b
--- /dev/null
+++ b/src/lib/ecore_x/xlib/ecore_x_present.c
@@ -0,0 +1,169 @@
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif /* ifdef HAVE_CONFIG_H */
+
+#include <stdlib.h>
+
+#include "ecore_x_private.h"
+#include "Ecore_X.h"
+
+int _ecore_x_present_major = 0;
+static Eina_Bool _ecore_x_present_exists = EINA_FALSE;
+
+void
+_ecore_x_present_init(void)
+{
+ ECORE_X_EVENT_PRESENT_CONFIGURE = ecore_event_type_new();
+ ECORE_X_EVENT_PRESENT_COMPLETE = ecore_event_type_new();
+ ECORE_X_EVENT_PRESENT_IDLE = ecore_event_type_new();
+#ifdef ECORE_XPRESENT
+ LOGFN(__FILE__, __LINE__, __FUNCTION__);
+ _ecore_x_present_exists = XPresentQueryExtension(_ecore_x_disp, &_ecore_x_present_major, NULL, NULL);
+#endif
+}
+
+#ifdef ECORE_XPRESENT
+#define SET(X) e->X = ev->X
+
+static void
+_present_configure(XPresentConfigureNotifyEvent *ev)
+{
+ Ecore_X_Event_Present_Configure *e;
+
+ e = calloc(1, sizeof(Ecore_X_Event_Present_Configure));
+ if (!e) return;
+
+ e->win = ev->window;
+ SET(x), SET(y);
+ SET(width), SET(height);
+ SET(off_x), SET(off_y);
+ SET(pixmap_width), SET(pixmap_height);
+ SET(pixmap_flags);
+
+ ecore_event_add(ECORE_X_EVENT_PRESENT_CONFIGURE, e, NULL, NULL);
+}
+
+static void
+_present_complete(XPresentCompleteNotifyEvent *ev)
+{
+ unsigned int mode[] =
+ {
+ [PresentCompleteModeCopy] = ECORE_X_PRESENT_COMPLETE_MODE_COPY,
+ [PresentCompleteModeFlip] = ECORE_X_PRESENT_COMPLETE_MODE_FLIP,
+ [PresentCompleteModeSkip] = ECORE_X_PRESENT_COMPLETE_MODE_SKIP,
+ };
+ Ecore_X_Event_Present_Complete *e;
+
+ e = calloc(1, sizeof(Ecore_X_Event_Present_Complete));
+ if (!e) return;
+
+ e->win = ev->window;
+ e->serial = ev->serial_number;
+ SET(ust), SET(msc);
+ e->kind = (ev->kind == 1); //libXpresent doesn't expose this...
+ e->mode = mode[ev->mode];
+ ecore_event_add(ECORE_X_EVENT_PRESENT_COMPLETE, e, NULL, NULL);
+}
+
+static void
+_present_idle(XPresentIdleNotifyEvent *ev)
+{
+ Ecore_X_Event_Present_Idle *e;
+
+ e = calloc(1, sizeof(Ecore_X_Event_Present_Idle));
+ if (!e) return;
+
+ e->win = ev->window;
+ e->serial = ev->serial_number;
+ SET(pixmap);
+ SET(idle_fence);
+ ecore_event_add(ECORE_X_EVENT_PRESENT_IDLE, e, NULL, NULL);
+}
+#undef SET
+
+void
+_ecore_x_present_handler(XGenericEvent *ge)
+{
+ XGenericEventCookie *gec = (XGenericEventCookie*)ge;
+
+ if (XGetEventData(_ecore_x_disp, gec))
+ {
+ switch (gec->evtype)
+ {
+ case PresentConfigureNotify:
+ _present_configure(gec->data);
+ break;
+ case PresentCompleteNotify:
+ _present_complete(gec->data);
+ break;
+ case PresentIdleNotify:
+ _present_idle(gec->data);
+ break;
+ default: break;
+ }
+ }
+ XFreeEventData(_ecore_x_disp, gec);
+}
+#endif
+
+EAPI void
+ecore_x_present_select_events(Ecore_X_Window win, unsigned int events)
+{
+#ifdef ECORE_XPRESENT
+ XPresentSelectInput(_ecore_x_disp, win, events);
+#else
+ (void)win;
+ (void)events;
+#endif
+}
+
+EAPI void
+ecore_x_present_notify_msc(Ecore_X_Window win, unsigned int serial, unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder)
+{
+#ifdef ECORE_XPRESENT
+ XPresentNotifyMSC(_ecore_x_disp, win, serial, target_msc, divisor, remainder);
+#else
+ (void)win;
+ (void)serial;
+ (void)target_msc;
+ (void)divisor;
+ (void)remainder;
+#endif
+}
+
+EAPI void
+ecore_x_present_pixmap(Ecore_X_Window win, Ecore_X_Pixmap pixmap, unsigned int serial, Ecore_X_Region valid,
+ Ecore_X_Region update, int x_off, int y_off, Ecore_X_Randr_Crtc target_crtc,
+ Ecore_X_Sync_Fence wait_fence, Ecore_X_Sync_Fence idle_fence, unsigned int options,
+ unsigned long long target_msc, unsigned long long divisor, unsigned long long remainder,
+ Ecore_X_Present *notifies, int num_notifies)
+{
+#ifdef ECORE_XPRESENT
+ XPresentPixmap(_ecore_x_disp, win, pixmap, serial, valid, update,
+ x_off, y_off, target_crtc, wait_fence, idle_fence, options, target_msc,
+ divisor, remainder, (XPresentNotify*)notifies, num_notifies);
+#else
+ (void)win;
+ (void)pixmap;
+ (void)serial;
+ (void)valid;
+ (void)update,
+ (void)x_off;
+ (void)y_off;
+ (void)target_crtc;
+ (void)wait_fence;
+ (void)idle_fence;
+ (void)options;
+ (void)target_msc,
+ (void)divisor;
+ (void)remainder;
+ (void)notifies;
+ (void)num_notifies;
+#endif
+}
+
+EAPI Eina_Bool
+ecore_x_present_exists(void)
+{
+ return _ecore_x_present_exists;
+}
diff --git a/src/lib/ecore_x/xlib/ecore_x_private.h b/src/lib/ecore_x/xlib/ecore_x_private.h
index 815e081238..94a3db88bf 100644
--- a/src/lib/ecore_x/xlib/ecore_x_private.h
+++ b/src/lib/ecore_x/xlib/ecore_x_private.h
@@ -40,6 +40,9 @@
#ifdef ECORE_XCOMPOSITE
#include <X11/extensions/Xcomposite.h>
#endif /* ifdef ECORE_XCOMPOSITE */
+#ifdef ECORE_XPRESENT
+#include <X11/extensions/Xpresent.h>
+#endif /* ifdef ECORE_XPRESENT */
#ifdef ECORE_XDAMAGE
#include <X11/extensions/Xdamage.h>
#endif /* ifdef ECORE_XDAMAGE */
@@ -264,6 +267,10 @@ void _ecore_x_event_handle_xkb(XEvent *xevent);
#endif /* ifdef ECORE_XKB */
void _ecore_x_event_handle_generic_event(XEvent *xevent);
+#ifdef ECORE_XPRESENT
+void _ecore_x_present_handler(XGenericEvent *ge);
+#endif
+
void _ecore_x_selection_data_init(void);
void _ecore_x_selection_shutdown(void);
Ecore_X_Atom _ecore_x_selection_target_atom_get(const char *target);
@@ -308,12 +315,14 @@ int _ecore_x_netwm_startup_info(Ecore_X_Window win,
void _ecore_x_fixes_init(void);
void _ecore_x_damage_init(void);
void _ecore_x_composite_init(void);
+void _ecore_x_present_init(void);
void _ecore_x_dpms_init(void);
void _ecore_x_randr_init(void);
void _ecore_x_gesture_init(void);
void _ecore_x_atoms_init(void);
+extern int _ecore_x_present_major;
extern int _ecore_x_xi2_opcode;
void _ecore_x_events_init(void);