overlay: Add a X11 window backend
authorChris Wilson <chris@chris-wilson.co.uk>
Sun, 18 Aug 2013 20:10:26 +0000 (21:10 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Sun, 18 Aug 2013 20:10:26 +0000 (21:10 +0100)
Useful for remote hosts.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
configure.ac
overlay/Makefile.am
overlay/overlay.c
overlay/overlay.h
overlay/x11/x11-window.c [new file with mode: 0644]

index d6c4cc6..1c8e84b 100644 (file)
@@ -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])
index ee34fb3..09f273c 100644 (file)
@@ -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
index 519bf20..b9247b8 100644 (file)
@@ -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);
index 3b72098..05bb6af 100644 (file)
@@ -1,3 +1,7 @@
+#ifdef HAVE_CONFIG_H
+#include"config.h"
+#endif
+
 #include <cairo.h>
 
 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 (file)
index 0000000..0bce9a1
--- /dev/null
@@ -0,0 +1,186 @@
+#include <X11/Xlib.h>
+#include <cairo.h>
+#include <cairo-xlib.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdbool.h>
+#include <string.h>
+#include <unistd.h>
+
+#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;
+}