From 34e4780c8e9c429a835c8be9c512cfe239241298 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sun, 18 Aug 2013 21:10:26 +0100 Subject: [PATCH] overlay: Add a X11 window backend Useful for remote hosts. Signed-off-by: Chris Wilson --- configure.ac | 15 +++- overlay/Makefile.am | 15 ++++ overlay/overlay.c | 4 + overlay/overlay.h | 15 ++++ overlay/x11/x11-window.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 232 insertions(+), 3 deletions(-) create mode 100644 overlay/x11/x11-window.c diff --git a/configure.ac b/configure.ac index d6c4cc6..1c8e84b 100644 --- a/configure.ac +++ b/configure.ac @@ -72,9 +72,18 @@ AC_SUBST(ASSEMBLER_WARN_CFLAGS) PKG_CHECK_MODULES(DRM, [libdrm_intel >= 2.4.45 libdrm]) PKG_CHECK_MODULES(PCIACCESS, [pciaccess >= 0.10]) -PKG_CHECK_MODULES(OVERLAY, [xv x11 xext], enable_overlay=yes, enable_overlay=no) - -AM_CONDITIONAL(BUILD_OVERLAY, [test "x$enable_overlay" = xyes]) +PKG_CHECK_MODULES(OVERLAY_XVLIB, [xv x11 xext], enable_overlay_xvlib=yes, enable_overlay_xvlib=no) +PKG_CHECK_MODULES(OVERLAY_XLIB, [cairo-xlib], enable_overlay_xlib=yes, enable_overlay_xlib=no) + +AM_CONDITIONAL(BUILD_OVERLAY_XVLIB, [test "x$enable_overlay_xvlib" = xyes]) +AM_CONDITIONAL(BUILD_OVERLAY_XLIB, [test "x$enable_overlay_xlib" = xyes]) +AM_CONDITIONAL(BUILD_OVERLAY, [test "x$enable_overlay_xlib" = xyes -o "x$enable_overlay_xvlib"]) +if test x$enable_overlay_xvlib = xyes; then + AC_DEFINE(HAVE_OVERLAY_XVLIB, 1, [Enable XV backend]) +fi +if test x$enable_overlay_xlib = xyes; then + AC_DEFINE(HAVE_OVERLAY_XLIB, 1, [Enable X backend]) +fi # for testdisplay PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0]) diff --git a/overlay/Makefile.am b/overlay/Makefile.am index ee34fb3..09f273c 100644 --- a/overlay/Makefile.am +++ b/overlay/Makefile.am @@ -23,11 +23,26 @@ intel_gpu_overlay_SOURCES = \ gpu-freq.c \ igfx.h \ igfx.c \ + $(NULL) + +if BUILD_OVERLAY_XLIB +AM_CFLAGS += $(OVERLAY_XLIB_CFLAGS) +LDADD += $(OVERLAY_XLIB_LIBS) +intel_gpu_overlay_SOURCES += \ + x11/x11-window.c \ + $(NULL) +endif + +if BUILD_OVERLAY_XVLIB +AM_CFLAGS += $(OVERLAY_XVLIB_CFLAGS) +LDADD += $(OVERLAY_XVLIB_LIBS) +intel_gpu_overlay_SOURCES += \ x11/dri2.c \ x11/dri2.h \ x11/rgb2yuv.c \ x11/rgb2yuv.h \ x11/x11-overlay.c \ $(NULL) +endif EXTRA_DIST=README diff --git a/overlay/overlay.c b/overlay/overlay.c index 519bf20..b9247b8 100644 --- a/overlay/overlay.c +++ b/overlay/overlay.c @@ -23,6 +23,8 @@ static void overlay_show(cairo_surface_t *surface) { struct overlay *overlay; + cairo_surface_flush(surface); + overlay = cairo_surface_get_user_data(surface, &overlay_key); if (overlay == NULL) return; @@ -511,6 +513,8 @@ int main(int argc, char **argv) ctx.height = 236; ctx.surface = x11_overlay_create(POS_TOP_RIGHT, &ctx.width, &ctx.height); if (ctx.surface == NULL) + ctx.surface = x11_window_create(POS_TOP_RIGHT, &ctx.width, &ctx.height); + if (ctx.surface == NULL) return ENOMEM; init_gpu_top(&ctx, &ctx.gpu_top); diff --git a/overlay/overlay.h b/overlay/overlay.h index 3b72098..05bb6af 100644 --- a/overlay/overlay.h +++ b/overlay/overlay.h @@ -1,3 +1,7 @@ +#ifdef HAVE_CONFIG_H +#include"config.h" +#endif + #include enum position { @@ -33,5 +37,16 @@ struct overlay { extern const cairo_user_data_key_t overlay_key; +#ifdef HAVE_OVERLAY_XVLIB cairo_surface_t *x11_overlay_create(enum position pos, int *width, int *height); void x11_overlay_stop(void); +#else +static inline cairo_surface_t *x11_overlay_create(enum position pos, int *width, int *height) { return NULL; } +static inline void x11_overlay_stop(void) { } +#endif + +#ifdef HAVE_OVERLAY_XLIB +cairo_surface_t *x11_window_create(enum position pos, int *width, int *height); +#else +static inline cairo_surface_t *x11_window_create(enum position pos, int *width, int *height) { return NULL; } +#endif diff --git a/overlay/x11/x11-window.c b/overlay/x11/x11-window.c new file mode 100644 index 0000000..0bce9a1 --- /dev/null +++ b/overlay/x11/x11-window.c @@ -0,0 +1,186 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../overlay.h" + +struct x11_window { + struct overlay base; + Display *dpy; + Window win; + int width, height; + int visible; +}; + +static inline struct x11_window *to_x11_window(struct overlay *o) +{ + return (struct x11_window *)o; +} + +static int noop(Display *dpy, XErrorEvent *event) +{ + return 0; +} + +static void x11_window_show(struct overlay *overlay) +{ + struct x11_window *priv = to_x11_window(overlay); + + if (!priv->visible) { + XMapWindow(priv->dpy, priv->win); + priv->visible = true; + } + + XFlush(priv->dpy); +} + +static void x11_window_position(struct overlay *overlay, + enum position p) +{ + struct x11_window *priv = to_x11_window(overlay); + Screen *scr = ScreenOfDisplay(priv->dpy, DefaultScreen(priv->dpy)); + int x, y; + + switch (p & 7) { + default: + case 0: x = 0; break; + case 1: x = (scr->width - priv->width)/2; break; + case 2: x = scr->width - priv->width; break; + } + + switch ((p >> 4) & 7) { + default: + case 0: y = 0; break; + case 1: y = (scr->height - priv->height)/2; break; + case 2: y = scr->height - priv->height; break; + } + + if (priv->visible) { + XMoveWindow(priv->dpy, priv->win, x, y); + XFlush(priv->dpy); + } +} + +static void x11_window_hide(struct overlay *overlay) +{ + struct x11_window *priv = to_x11_window(overlay); + if (priv->visible) { + XUnmapWindow(priv->dpy, priv->win); + XFlush(priv->dpy); + priv->visible = false; + } +} + +static void x11_window_destroy(void *data) +{ + struct x11_window *priv = data; + XDestroyWindow(priv->dpy, priv->win); + XCloseDisplay(priv->dpy); + free(priv); +} + +cairo_surface_t * +x11_window_create(enum position position, int *width, int *height) +{ + Display *dpy; + Screen *scr; + Window win; + int screen; + cairo_surface_t *surface; + XSetWindowAttributes attr; + struct x11_window *priv; + int x, y, w, h; + + dpy = XOpenDisplay(NULL); + if (dpy == NULL) + return NULL; + + screen = DefaultScreen(dpy); + scr = XScreenOfDisplay(dpy, screen); + + XSetErrorHandler(noop); + + if (*width == -1) { + w = scr->width; + switch (position & 7) { + default: + case 0: + case 2: w >>= 1; break; + } + } else if (*width > scr->width) { + w = scr->width; + } else + w = *width; + + if (*height == -1) { + h = scr->height; + switch ((position >> 4) & 7) { + default: + case 0: + case 2: h >>= 1; break; + } + } else if (*height > scr->height) + h = scr->height; + else + h = *height; + + switch (position & 7) { + default: + case 0: x = 0; break; + case 1: x = (scr->width - w)/2; break; + case 2: x = scr->width - w; break; + } + + switch ((position >> 4) & 7) { + default: + case 0: y = 0; break; + case 1: y = (scr->height - h)/2; break; + case 2: y = scr->height - h; break; + } + + attr.override_redirect = True; + win = XCreateWindow(dpy, DefaultRootWindow(dpy), + x, y, w, h, 0, + DefaultDepth(dpy, screen), + InputOutput, + DefaultVisual(dpy, screen), + CWOverrideRedirect, &attr); + + surface = cairo_xlib_surface_create(dpy, win, DefaultVisual (dpy, screen), w, h); + if (cairo_surface_status(surface)) + goto err_win; + + priv = malloc(sizeof(*priv)); + if (priv == NULL) + goto err_surface; + + priv->base.surface = surface; + priv->base.show = x11_window_show; + priv->base.position = x11_window_position; + priv->base.hide = x11_window_hide; + + priv->dpy = dpy; + priv->win = win; + priv->visible = false; + + priv->width = w; + priv->height = h; + + cairo_surface_set_user_data(surface, &overlay_key, priv, x11_window_destroy); + + *width = w; + *height = h; + return surface; + +err_surface: + cairo_surface_destroy(surface); +err_win: + XDestroyWindow(dpy, win); + XCloseDisplay(dpy); + return NULL; +} -- 2.7.4