xserver: Branch 'master' - 6 commits

Keith Packard keithp at kemper.freedesktop.org
Thu Mar 6 11:43:28 PST 2014


 configure.ac                       |   14 +
 glamor/Makefile.am                 |    1 
 glamor/glamor.c                    |   21 +-
 glamor/glamor.h                    |   64 ++++---
 glamor/glamor_egl.c                |   97 ++++++++++
 glamor/glamor_eglmodule.c          |    3 
 glamor/glamor_xv.c                 |   19 --
 hw/kdrive/ephyr/Makefile.am        |   20 ++
 hw/kdrive/ephyr/ephyr.c            |   45 +++--
 hw/kdrive/ephyr/ephyr.h            |   14 +
 hw/kdrive/ephyr/ephyr_glamor_glx.c |  331 +++++++++++++++++++++++++++++++++++++
 hw/kdrive/ephyr/ephyr_glamor_glx.h |   73 ++++++++
 hw/kdrive/ephyr/ephyrinit.c        |   14 +
 hw/kdrive/ephyr/hostx.c            |  126 +++++++++++++-
 hw/xfree86/Makefile.am             |    7 
 hw/xfree86/glamor_egl/Makefile.am  |   43 ++++
 include/dix-config.h.in            |    3 
 17 files changed, 827 insertions(+), 68 deletions(-)

New commits:
commit da08316605b26830b4d8f8fb2d9e69471cdc80ab
Author: Eric Anholt <eric at anholt.net>
Date:   Tue Dec 31 00:07:42 2013 -0800

    glamor: Add support for DRI3.
    
    The render-nodes case is untested.
    
    v2: Add a flag for wayland to suppress the native DRI3 support.
        Wayland isn't running as a master itself, so it can't do the auth
        on its own and has to ask the compositor to do it for us.  Dropped
        XXX about randr provider -- the conclusion from discussion with
        keithp was that if the driver's dri3_open for a provider on a
        different screen, that's a core dri3 bug.
    v3: Don't put quite so much under GLAMOR_NO_DRI3, and add a comment
        explaining what this is about.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor.h b/glamor/glamor.h
index 041004e..e12f497 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -67,10 +67,12 @@ typedef enum glamor_pixmap_type {
 #define GLAMOR_USE_SCREEN		(1 << 1)
 #define GLAMOR_USE_PICTURE_SCREEN 	(1 << 2)
 #define GLAMOR_USE_EGL_SCREEN		(1 << 3)
+#define GLAMOR_NO_DRI3			(1 << 4)
 #define GLAMOR_VALID_FLAGS      (GLAMOR_INVERTED_Y_AXIS  		\
 				 | GLAMOR_USE_SCREEN 			\
                                  | GLAMOR_USE_PICTURE_SCREEN		\
-				 | GLAMOR_USE_EGL_SCREEN)
+				 | GLAMOR_USE_EGL_SCREEN                \
+                                 | GLAMOR_NO_DRI3)
 
 /* @glamor_init: Initialize glamor internal data structure.
  *
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 56d8913..05e6bd0 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -50,6 +50,7 @@
 
 #include "glamor.h"
 #include "glamor_priv.h"
+#include "dri3.h"
 
 static const char glamor_name[] = "glamor";
 
@@ -68,6 +69,7 @@ struct glamor_egl_screen_private {
     EGLDisplay display;
     EGLContext context;
     EGLint major, minor;
+    char *device_path;
 
     CreateScreenResourcesProcPtr CreateScreenResources;
     CloseScreenProcPtr CloseScreen;
@@ -627,10 +629,67 @@ glamor_egl_has_extension(struct glamor_egl_screen_private *glamor_egl,
     return FALSE;
 }
 
+static int
+glamor_dri3_open(ScreenPtr screen,
+                 RRProviderPtr provider,
+                 int *fdp)
+{
+    ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    struct glamor_egl_screen_private *glamor_egl =
+        glamor_egl_get_screen_private(scrn);
+    int fd;
+    drm_magic_t magic;
+
+    fd = open(glamor_egl->device_path, O_RDWR|O_CLOEXEC);
+    if (fd < 0)
+        return BadAlloc;
+
+    /* Before FD passing in the X protocol with DRI3 (and increased
+     * security of rendering with per-process address spaces on the
+     * GPU), the kernel had to come up with a way to have the server
+     * decide which clients got to access the GPU, which was done by
+     * each client getting a unique (magic) number from the kernel,
+     * passing it to the server, and the server then telling the
+     * kernel which clients were authenticated for using the device.
+     *
+     * Now that we have FD passing, the server can just set up the
+     * authentication on its own and hand the prepared FD off to the
+     * client.
+     */
+    if (drmGetMagic(fd, &magic) < 0) {
+        if (errno == EACCES) {
+            /* Assume that we're on a render node, and the fd is
+             * already as authenticated as it should be.
+             */
+            *fdp = fd;
+            return Success;
+        } else {
+            close(fd);
+            return BadMatch;
+        }
+    }
+
+    if (drmAuthMagic(glamor_egl->fd, magic) < 0) {
+        close(fd);
+        return BadMatch;
+    }
+
+    *fdp = fd;
+    return Success;
+}
+
+static dri3_screen_info_rec glamor_dri3_info = {
+    .version = 0,
+    .open = glamor_dri3_open,
+    .pixmap_from_fd = glamor_pixmap_from_fd,
+    .fd_from_pixmap = glamor_fd_from_pixmap,
+};
+
 void
 glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
 {
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
+    glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
     struct glamor_egl_screen_private *glamor_egl =
         glamor_egl_get_screen_private(scrn);
 
@@ -642,6 +701,30 @@ glamor_egl_screen_init(ScreenPtr screen, struct glamor_context *glamor_ctx)
 
     glamor_ctx->get_context = glamor_egl_get_context;
     glamor_ctx->put_context = glamor_egl_put_context;
+
+    if (glamor_egl->dri3_capable) {
+        /* Tell the core that we have the interfaces for import/export
+         * of pixmaps.
+         */
+        glamor_enable_dri3(screen);
+
+        /* If the driver wants to do its own auth dance (e.g. Xwayland
+         * on pre-3.15 kernels that don't have render nodes and thus
+         * has the wayland compositor as a master), then it needs us
+         * to stay out of the way and let it init DRI3 on its own.
+         */
+        if (!(glamor_priv->flags & GLAMOR_NO_DRI3)) {
+            /* To do DRI3 device FD generation, we need to open a new fd
+             * to the same device we were handed in originally.
+             */
+            glamor_egl->device_path = drmGetDeviceNameFromFd(glamor_egl->fd);
+
+            if (!dri3_screen_init(screen, &glamor_dri3_info)) {
+                xf86DrvMsg(scrn->scrnIndex, X_ERROR,
+                           "Failed to initialize DRI3.\n");
+            }
+        }
+    }
 }
 
 static void
@@ -658,6 +741,8 @@ glamor_egl_free_screen(ScrnInfoPtr scrn)
         if (glamor_egl->gbm)
             gbm_device_destroy(glamor_egl->gbm);
 #endif
+        free(glamor_egl->device_path);
+
         scrn->FreeScreen = glamor_egl->saved_free_screen;
         free(glamor_egl);
         scrn->FreeScreen(scrn);
diff --git a/hw/xfree86/glamor_egl/Makefile.am b/hw/xfree86/glamor_egl/Makefile.am
index bb1b511..85e1c0c 100644
--- a/hw/xfree86/glamor_egl/Makefile.am
+++ b/hw/xfree86/glamor_egl/Makefile.am
@@ -36,5 +36,8 @@ libglamoregl_la_LIBADD = \
 	$(top_builddir)/glamor/libglamor.la \
 	$()
 
-AM_CPPFLAGS = $(XORG_INCS)
+AM_CPPFLAGS = $(XORG_INCS) \
+	-I$(top_srcdir)/dri3 \
+	$()
+
 AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_CFLAGS) $(GBM_CFLAGS)
commit fb4a1e6ef6f80a7670e92cab2bc490d4afd80a9b
Author: Eric Anholt <eric at anholt.net>
Date:   Mon Dec 30 18:49:46 2013 -0800

    glamor: Rename the DRI-related pixmap functions.
    
    There was confusion over whether they should have egl in the name, and
    they had DRI3 in the name even though they're useful to have without
    DRI3.
    
    v2: Just rename glamor_name_from_pixmap for now -- I'd accidentally
        conflict-resolved in adding new parameters from a later commit.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/glamor.c b/glamor/glamor.c
index 85fd560..fa753bb 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -567,16 +567,16 @@ glamor_enable_dri3(ScreenPtr screen)
 }
 
 Bool
-glamor_is_dri3_support_enabled(ScreenPtr screen)
+glamor_supports_pixmap_import_export(ScreenPtr screen)
 {
     glamor_screen_private *glamor_priv = glamor_get_screen_private(screen);
 
     return glamor_priv->dri3_enabled;
 }
 
-int
-glamor_dri3_fd_from_pixmap(ScreenPtr screen,
-                           PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
+_X_EXPORT int
+glamor_fd_from_pixmap(ScreenPtr screen,
+                      PixmapPtr pixmap, CARD16 *stride, CARD32 *size)
 {
     glamor_pixmap_private *pixmap_priv;
     glamor_screen_private *glamor_priv =
@@ -600,7 +600,7 @@ glamor_dri3_fd_from_pixmap(ScreenPtr screen,
 }
 
 int
-glamor_dri3_name_from_pixmap(PixmapPtr pixmap)
+glamor_name_from_pixmap(PixmapPtr pixmap)
 {
     glamor_pixmap_private *pixmap_priv;
     glamor_screen_private *glamor_priv =
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 89e7d80..041004e 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -173,21 +173,23 @@ extern _X_EXPORT int glamor_egl_dri3_fd_name_from_tex(ScreenPtr, PixmapPtr,
                                                       unsigned int, Bool,
                                                       CARD16 *, CARD32 *);
 
-/* @glamor_is_dri3_support_enabled: Returns if DRI3 support is enabled.
+/* @glamor_supports_pixmap_import_export: Returns whether
+ * glamor_fd_from_pixmap(), glamor_name_from_pixmap(), and
+ * glamor_pixmap_from_fd() are supported.
  *
  * @screen: Current screen pointer.
  *
- * To have DRI3 support enabled, glamor and glamor_egl need to be initialized,
- * and glamor_egl_init_textured_pixmap need to be called. glamor also
- * has to be compiled with gbm support.
- * The EGL layer need to have the following extensions working:
+ * To have DRI3 support enabled, glamor and glamor_egl need to be
+ * initialized. glamor also has to be compiled with gbm support.
+ *
+ * The EGL layer needs to have the following extensions working:
+ *
  * .EGL_KHR_gl_texture_2D_image
  * .EGL_EXT_image_dma_buf_import
- * If DRI3 support is not enabled, the following helpers will return an error.
  * */
-extern _X_EXPORT Bool glamor_is_dri3_support_enabled(ScreenPtr screen);
+extern _X_EXPORT Bool glamor_supports_pixmap_import_export(ScreenPtr screen);
 
-/* @glamor_dri3_fd_from_pixmap: DRI3 helper to get a dma-buf fd from a pixmap.
+/* @glamor_fd_from_pixmap: Get a dma-buf fd from a pixmap.
  *
  * @screen: Current screen pointer.
  * @pixmap: The pixmap from which we want the fd.
@@ -198,22 +200,25 @@ extern _X_EXPORT Bool glamor_is_dri3_support_enabled(ScreenPtr screen);
  * content.
  * Returns the fd on success, -1 on error.
  * */
-extern _X_EXPORT int glamor_dri3_fd_from_pixmap(ScreenPtr screen,
-                                                PixmapPtr pixmap,
-                                                CARD16 *stride, CARD32 *size);
+extern _X_EXPORT int glamor_fd_from_pixmap(ScreenPtr screen,
+                                           PixmapPtr pixmap,
+                                           CARD16 *stride, CARD32 *size);
 
-/* @glamor_dri3_name_from_pixmap: helper to get an gem name from a pixmap.
+/**
+ * @glamor_name_from_pixmap: Gets a gem name from a pixmap.
  *
  * @pixmap: The pixmap from which we want the gem name.
  *
- * the pixmap and the buffer associated by the gem name will share the same
- * content. This function can be used by the DDX to support DRI2, but needs
- * glamor DRI3 support to be activated.
+ * the pixmap and the buffer associated by the gem name will share the
+ * same content. This function can be used by the DDX to support DRI2,
+ * and needs the same set of buffer export GL extensions as DRI3
+ * support.
+ *
  * Returns the name on success, -1 on error.
  * */
-extern _X_EXPORT int glamor_dri3_name_from_pixmap(PixmapPtr pixmap);
+extern _X_EXPORT int glamor_name_from_pixmap(PixmapPtr pixmap);
 
-/* @glamor_egl_dri3_pixmap_from_fd: DRI3 helper to get a pixmap from a dma-buf fd.
+/* @glamor_pixmap_from_fd: Creates a pixmap to wrap a dma-buf fd.
  *
  * @screen: Current screen pointer.
  * @fd: The dma-buf fd to import.
@@ -225,13 +230,13 @@ extern _X_EXPORT int glamor_dri3_name_from_pixmap(PixmapPtr pixmap);
  *
  * Returns a valid pixmap if the import succeeded, else NULL.
  * */
-extern _X_EXPORT PixmapPtr glamor_egl_dri3_pixmap_from_fd(ScreenPtr screen,
-                                                          int fd,
-                                                          CARD16 width,
-                                                          CARD16 height,
-                                                          CARD16 stride,
-                                                          CARD8 depth,
-                                                          CARD8 bpp);
+extern _X_EXPORT PixmapPtr glamor_pixmap_from_fd(ScreenPtr screen,
+                                                 int fd,
+                                                 CARD16 width,
+                                                 CARD16 height,
+                                                 CARD16 stride,
+                                                 CARD8 depth,
+                                                 CARD8 bpp);
 
 #ifdef GLAMOR_FOR_XORG
 
diff --git a/glamor/glamor_egl.c b/glamor/glamor_egl.c
index 9dcba71..56d8913 100644
--- a/glamor/glamor_egl.c
+++ b/glamor/glamor_egl.c
@@ -453,12 +453,12 @@ glamor_egl_dri3_fd_name_from_tex(ScreenPtr screen,
 #endif
 }
 
-PixmapPtr
-glamor_egl_dri3_pixmap_from_fd(ScreenPtr screen,
-                               int fd,
-                               CARD16 width,
-                               CARD16 height,
-                               CARD16 stride, CARD8 depth, CARD8 bpp)
+_X_EXPORT PixmapPtr
+glamor_pixmap_from_fd(ScreenPtr screen,
+                      int fd,
+                      CARD16 width,
+                      CARD16 height,
+                      CARD16 stride, CARD8 depth, CARD8 bpp)
 {
 #ifdef GLAMOR_HAS_GBM
     ScrnInfoPtr scrn = xf86ScreenToScrn(screen);
commit 2d20f75b60276508424997d9fa8c5b97d8f1d92b
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 22:19:07 2013 -0800

    xorg: Connect up the glamor XV code, xorg DDX-only for now.
    
    Porting this code to be non-xorg-dependent is going to take
    significant hacking, so just dump it in the glamoregl module for the
    moment, so I can hack on it while regression testing.
    
    v2: Fix compiler warnings by adding #include dix-config.h at the top,
        don't try to auto-init (I'll try to fix the xv ABI later).
    v3: Fix last minute breakage of having reintroduced xf86ScrnToScreen
        (one of the compat macros).  Just use the drawable's pScreen instead.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/glamor/Makefile.am b/glamor/Makefile.am
index 12a57c4..77492bc 100644
--- a/glamor/Makefile.am
+++ b/glamor/Makefile.am
@@ -37,7 +37,6 @@ libglamor_la_SOURCES = \
 	glamor_window.c\
 	glamor_fbo.c\
 	glamor_compositerects.c\
-	glamor_xv.c\
 	glamor_utils.h\
 	glamor.h
 
diff --git a/glamor/glamor.h b/glamor/glamor.h
index 08ffd26..89e7d80 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -35,6 +35,9 @@
 #include <picturestr.h>
 #include <fb.h>
 #include <fbpict.h>
+#ifdef GLAMOR_FOR_XORG
+#include <xf86xv.h>
+#endif
 
 struct glamor_context;
 
@@ -434,7 +437,7 @@ extern _X_EXPORT Bool glamor_poly_line_nf(DrawablePtr pDrawable, GCPtr pGC,
 extern _X_EXPORT Bool glamor_poly_lines_nf(DrawablePtr drawable, GCPtr gc,
                                            int mode, int n, DDXPointPtr points);
 
-#if 0
+#ifdef GLAMOR_FOR_XORG
 extern _X_EXPORT XF86VideoAdaptorPtr glamor_xv_init(ScreenPtr pScreen,
                                                     int num_texture_ports);
 #endif
diff --git a/glamor/glamor_eglmodule.c b/glamor/glamor_eglmodule.c
index fb5b855..d7e1836 100644
--- a/glamor/glamor_eglmodule.c
+++ b/glamor/glamor_eglmodule.c
@@ -41,7 +41,7 @@ static XF86ModuleVersionInfo VersRec = {
     MODINFOSTRING1,
     MODINFOSTRING2,
     XORG_VERSION_CURRENT,
-    0, 5, 1, /* version */
+    1, 0, 0, /* version */
     ABI_CLASS_ANSIC,            /* Only need the ansic layer */
     ABI_ANSIC_VERSION,
     MOD_CLASS_NONE,
diff --git a/glamor/glamor_xv.c b/glamor/glamor_xv.c
index dc39476..fb90457 100644
--- a/glamor/glamor_xv.c
+++ b/glamor/glamor_xv.c
@@ -32,10 +32,14 @@
  * Xv acceleration implementation
  */
 
-#include "glamor_priv.h"
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
 
-#ifdef GLAMOR_XV
 #include "xf86xv.h"
+#define GLAMOR_FOR_XORG
+#include "glamor_priv.h"
+
 #include <X11/extensions/Xv.h>
 #include "fourcc.h"
 /* Reference color space transform data */
@@ -430,7 +434,7 @@ glamor_xv_put_image(ScrnInfoPtr pScrn,
                     Bool sync,
                     RegionPtr clipBoxes, void *data, DrawablePtr pDrawable)
 {
-    ScreenPtr screen = xf86ScrnToScreen(pScrn);
+    ScreenPtr screen = pDrawable->pScreen;
     glamor_port_private *port_priv = (glamor_port_private *) data;
     INT32 x1, x2, y1, y2;
     int srcPitch, srcPitch2;
@@ -614,12 +618,3 @@ glamor_xv_init(ScreenPtr screen, int num_texture_ports)
     }
     return adapt;
 }
-#else
-#if 0
-XF86VideoAdaptorPtr
-glamor_xv_init(ScreenPtr screen, int num_texture_ports)
-{
-    return NULL;
-}
-#endif
-#endif
diff --git a/hw/xfree86/glamor_egl/Makefile.am b/hw/xfree86/glamor_egl/Makefile.am
index 827e033..bb1b511 100644
--- a/hw/xfree86/glamor_egl/Makefile.am
+++ b/hw/xfree86/glamor_egl/Makefile.am
@@ -24,6 +24,7 @@ module_LTLIBRARIES = libglamoregl.la
 libglamoregl_la_SOURCES = \
 	$(top_srcdir)/glamor/glamor_egl.c \
 	$(top_srcdir)/glamor/glamor_eglmodule.c \
+	$(top_srcdir)/glamor/glamor_xv.c \
 	$()
 
 libglamoregl_la_LDFLAGS = \
commit 8d1cca30638f8a12c09efee27e9dedd90322b40e
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 27 16:44:15 2013 -0800

    xorg: Build a glamor_egl module.
    
    This is not exposing the API we want long term, but it should get
    existing DDX drivers up and running while we massage the API into
    shape.
    
    v2: Use LIBADD instead of LDFLAGS to fix deps on libglamor.la, and use
        version 0.5.1 (the point it was forked from the external repo).
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/configure.ac b/configure.ac
index 5934950..74819bf 100644
--- a/configure.ac
+++ b/configure.ac
@@ -806,6 +806,8 @@ LIBAPPLEWM="applewm >= 1.4"
 LIBDMX="dmx >= 1.0.99.1"
 LIBDRI="dri >= 7.8.0"
 LIBDRM="libdrm >= 2.3.0"
+LIBEGL="egl"
+LIBGBM="gbm >= 9"
 LIBGL="gl >= 7.1.0"
 LIBXEXT="xext >= 1.0.99.4"
 LIBXFONT="xfont >= 1.4.2"
@@ -2070,7 +2072,15 @@ AM_CONDITIONAL([GLAMOR], [test "x$GLAMOR" = xyes])
 if test "x$GLAMOR" = xyes; then
 	AC_DEFINE(GLAMOR, 1, [Build glamor])
 	PKG_CHECK_MODULES([GLAMOR], [epoxy])
+
+	PKG_CHECK_MODULES(GBM, "$LIBGBM", [GBM=yes], [GBM=no])
+	if test "x$GBM" = xyes; then
+		AC_DEFINE(GLAMOR_HAS_GBM, 1,
+			  [Build glamor with GBM-based EGL support])
+	fi
+
 fi
+AM_CONDITIONAL([GLAMOR_EGL], [test "x$GBM" = xyes])
 
 dnl XWin DDX
 
@@ -2479,6 +2489,7 @@ hw/xfree86/exa/Makefile
 hw/xfree86/exa/man/Makefile
 hw/xfree86/fbdevhw/Makefile
 hw/xfree86/fbdevhw/man/Makefile
+hw/xfree86/glamor_egl/Makefile
 hw/xfree86/i2c/Makefile
 hw/xfree86/int10/Makefile
 hw/xfree86/loader/Makefile
diff --git a/glamor/glamor_eglmodule.c b/glamor/glamor_eglmodule.c
index 5ddd602..fb5b855 100644
--- a/glamor/glamor_eglmodule.c
+++ b/glamor/glamor_eglmodule.c
@@ -30,6 +30,7 @@
 #include "dix-config.h"
 
 #include <xorg-server.h>
+#include <xf86.h>
 #define GLAMOR_FOR_XORG
 #include <xf86Module.h>
 #include "glamor.h"
@@ -40,7 +41,7 @@ static XF86ModuleVersionInfo VersRec = {
     MODINFOSTRING1,
     MODINFOSTRING2,
     XORG_VERSION_CURRENT,
-    PACKAGE_VERSION_MAJOR, PACKAGE_VERSION_MINOR, PACKAGE_VERSION_PATCHLEVEL,
+    0, 5, 1, /* version */
     ABI_CLASS_ANSIC,            /* Only need the ansic layer */
     ABI_ANSIC_VERSION,
     MOD_CLASS_NONE,
diff --git a/hw/xfree86/Makefile.am b/hw/xfree86/Makefile.am
index 9672904..73e1b4c 100644
--- a/hw/xfree86/Makefile.am
+++ b/hw/xfree86/Makefile.am
@@ -14,6 +14,10 @@ DRI3_BUILDDIR = $(top_builddir)/dri3
 DRI3_LIB = $(DRI3_BUILDDIR)/libdri3.la
 endif
 
+if GLAMOR_EGL
+GLAMOR_EGL_SUBDIR = glamor_egl
+endif
+
 if XF86UTILS
 XF86UTILS_SUBDIR = utils
 endif
@@ -33,7 +37,8 @@ endif
 SUBDIRS = common ddc x86emu $(INT10_SUBDIR) os-support parser \
 	  ramdac $(VGAHW_SUBDIR) loader modes $(DRI_SUBDIR) \
 	  $(DRI2_SUBDIR) . $(VBE_SUBDIR) i2c dixmods \
-	  fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man
+	  fbdevhw shadowfb exa $(XF86UTILS_SUBDIR) doc man \
+	  $(GLAMOR_EGL_SUBDIR)
 
 DIST_SUBDIRS = common ddc i2c x86emu int10 fbdevhw os-support \
                parser ramdac shadowfb vbe vgahw \
diff --git a/hw/xfree86/glamor_egl/Makefile.am b/hw/xfree86/glamor_egl/Makefile.am
new file mode 100644
index 0000000..827e033
--- /dev/null
+++ b/hw/xfree86/glamor_egl/Makefile.am
@@ -0,0 +1,39 @@
+# Copyright © 2013 Intel Corporation
+#
+# Permission is hereby granted, free of charge, to any person obtaining a
+# copy of this software and associated documentation files (the "Software"),
+# to deal in the Software without restriction, including without limitation
+# the rights to use, copy, modify, merge, publish, distribute, sublicense,
+# and/or sell copies of the Software, and to permit persons to whom the
+# Software is furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice (including the next
+# paragraph) shall be included in all copies or substantial portions of the
+# Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+# IN THE SOFTWARE.
+
+module_LTLIBRARIES = libglamoregl.la
+
+libglamoregl_la_SOURCES = \
+	$(top_srcdir)/glamor/glamor_egl.c \
+	$(top_srcdir)/glamor/glamor_eglmodule.c \
+	$()
+
+libglamoregl_la_LDFLAGS = \
+	-avoid-version \
+	$(GBM_LIBS) \
+	$()
+
+libglamoregl_la_LIBADD = \
+	$(top_builddir)/glamor/libglamor.la \
+	$()
+
+AM_CPPFLAGS = $(XORG_INCS)
+AM_CFLAGS = $(DIX_CFLAGS) $(XORG_CFLAGS) $(GLAMOR_CFLAGS) $(GBM_CFLAGS)
diff --git a/include/dix-config.h.in b/include/dix-config.h.in
index 7c77956..754e81e 100644
--- a/include/dix-config.h.in
+++ b/include/dix-config.h.in
@@ -481,4 +481,7 @@
 /* Build GLAMOR */
 #undef GLAMOR
 
+/* Build glamor's GBM-based EGL support */
+#undef GLAMOR_HAS_GBM
+
 #endif /* _DIX_CONFIG_H_ */
commit fa2e78788327c41bfd45b3de3c71bf9c26dcc85e
Author: Eric Anholt <eric at anholt.net>
Date:   Fri Dec 20 10:41:43 2013 -0800

    xephyr: Pass incoming XCB events to the Xlib event filter.
    
    This is the same thing that Qt ended up doing to get DRI2's event
    mangling to happen despite using an XCB event loop.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index 75a6fcb..def50d8 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -1223,6 +1223,9 @@ ephyrPoll(void)
             break;
         }
 
+        if (ephyr_glamor)
+            ephyr_glamor_process_event(xev);
+
         free(xev);
     }
 }
diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.c b/hw/kdrive/ephyr/ephyr_glamor_glx.c
index a937c1a..d56907f 100644
--- a/hw/kdrive/ephyr/ephyr_glamor_glx.c
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.c
@@ -29,12 +29,17 @@
 
 #include <stdlib.h>
 #include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#undef Xcalloc
+#undef Xrealloc
+#undef Xfree
 #include <X11/Xlib-xcb.h>
 #include <xcb/xcb_aux.h>
 #include <pixman.h>
 #include <epoxy/glx.h>
 #include "ephyr_glamor_glx.h"
 #include "os.h"
+#include <X11/Xproto.h>
 
 /** @{
  *
@@ -218,6 +223,40 @@ ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
     glXSwapBuffers(dpy, glamor->glx_win);
 }
 
+/**
+ * Xlib-based handling of xcb events for glamor.
+ *
+ * We need to let the Xlib event filtering run on the event so that
+ * Mesa's dri2_glx.c userspace event mangling gets run, and we
+ * correctly get our invalidate events propagated into the driver.
+ */
+void
+ephyr_glamor_process_event(xcb_generic_event_t *xev)
+{
+
+    uint32_t response_type = xev->response_type & 0x7f;
+    /* Note the types on wire_to_event: there's an Xlib XEvent (with
+     * the broken types) that it returns, and a protocol xEvent that
+     * it inspects.
+     */
+    Bool (*wire_to_event)(Display *dpy, XEvent *ret, xEvent *event);
+
+    XLockDisplay(dpy);
+    /* Set the event handler to NULL to get access to the current one. */
+    wire_to_event = XESetWireToEvent(dpy, response_type, NULL);
+    if (wire_to_event) {
+        XEvent processed_event;
+
+        /* OK they had an event handler.  Plug it back in, and call
+         * through to it.
+         */
+        XESetWireToEvent(dpy, response_type, wire_to_event);
+        xev->sequence = LastKnownRequestProcessed(dpy);
+        wire_to_event(dpy, &processed_event, (xEvent *)xev);
+    }
+    XUnlockDisplay(dpy);
+}
+
 struct ephyr_glamor *
 ephyr_glamor_glx_screen_init(xcb_window_t win)
 {
diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.h b/hw/kdrive/ephyr/ephyr_glamor_glx.h
index 950beff..8995e1e 100644
--- a/hw/kdrive/ephyr/ephyr_glamor_glx.h
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.h
@@ -53,10 +53,21 @@ ephyr_glamor_glx_screen_fini(struct ephyr_glamor *glamor);
 void
 ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
                               struct pixman_region16 *damage);
-#else
+
+void
+ephyr_glamor_process_event(xcb_generic_event_t *xev);
+
+#else /* !GLAMOR */
+
 static inline void
 ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
                               struct pixman_region16 *damage)
 {
 }
-#endif
+
+static inline void
+ephyr_glamor_process_event(xcb_generic_event_t *xev)
+{
+}
+
+#endif /* !GLAMOR */
commit 9fe052d90cca90fdf750d3a45b151be2ac7f0ebd
Author: Eric Anholt <eric at anholt.net>
Date:   Wed Dec 18 13:24:14 2013 -0800

    xephyr: Build support for rendering with glamor using a -glamor option.
    
    v2: Avoid making the Ximage for the screen that we'll never use, and
        drive the screen pixmap creation for glamor ourselves.
    
    Signed-off-by: Eric Anholt <eric at anholt.net>
    Reviewed-by: Keith Packard <keithp at keithp.com> (v1)
    Reviewed-by: Adam Jackson <ajax at redhat.com>

diff --git a/configure.ac b/configure.ac
index 0fb2fc3..5934950 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2319,6 +2319,9 @@ if test "$KDRIVE" = yes; then
     if test "x$DRI" = xyes && test "x$GLX" = xyes; then
         XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS libdrm xcb-glx xcb-xf86dri > 1.6"
     fi
+    if test "x$GLAMOR" = xyes; then
+        XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS x11-xcb"
+    fi
 
     if test "x$XEPHYR" = xauto; then
         PKG_CHECK_MODULES(XEPHYR, $XEPHYR_REQUIRED_LIBS, [XEPHYR="yes"], [XEPHYR="no"])
diff --git a/glamor/glamor.c b/glamor/glamor.c
index 7d8228c..85fd560 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -123,6 +123,17 @@ glamor_set_screen_pixmap(PixmapPtr screen_pixmap, PixmapPtr *back_pixmap)
     glamor_priv->back_pixmap = back_pixmap;
 }
 
+uint32_t
+glamor_get_pixmap_texture(PixmapPtr pixmap)
+{
+    glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap);
+
+    if (pixmap_priv->type != GLAMOR_TEXTURE_ONLY)
+        return 0;
+
+    return pixmap_priv->base.fbo->tex;
+}
+
 PixmapPtr
 glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth,
                      unsigned int usage)
diff --git a/glamor/glamor.h b/glamor/glamor.h
index eec6872..08ffd26 100644
--- a/glamor/glamor.h
+++ b/glamor/glamor.h
@@ -124,6 +124,8 @@ extern _X_EXPORT Bool glamor_close_screen(ScreenPtr screen);
 extern _X_EXPORT void glamor_set_screen_pixmap(PixmapPtr screen_pixmap,
                                                PixmapPtr *back_pixmap);
 
+extern _X_EXPORT uint32_t glamor_get_pixmap_texture(PixmapPtr pixmap);
+
 /* @glamor_glyphs_init: Initialize glyphs internal data structures.
  *
  * @pScreen: Current screen pointer.
diff --git a/hw/kdrive/ephyr/Makefile.am b/hw/kdrive/ephyr/Makefile.am
index 6b790fd..040993c 100644
--- a/hw/kdrive/ephyr/Makefile.am
+++ b/hw/kdrive/ephyr/Makefile.am
@@ -27,12 +27,20 @@ AM_CPPFLAGS = 			\
 	@XEPHYR_INCS@		\
 	@XEPHYR_CFLAGS@		\
 	-I$(top_srcdir)		\
+	-I$(top_srcdir)/glamor	\
 	-I$(top_srcdir)/exa
 
 if XV
 XV_SRCS = ephyrvideo.c
 endif
 
+if GLAMOR
+GLAMOR_SRCS = \
+	ephyr_glamor_glx.c \
+	ephyr_glamor_glx.h \
+	()
+endif
+
 if DRI
 DRI_SRCS =			\
 	ephyrdriext.c		\
@@ -59,14 +67,24 @@ Xephyr_SOURCES = \
 	hostx.h \
 	$(XV_SRCS) \
 	$(DRI_SRCS) \
+	$(GLAMOR_SRCS) \
 	$()
 
+if GLAMOR
+AM_CPPFLAGS += $(XLIB_CFLAGS)
+XEPHYR_GLAMOR_LIB = \
+	$(top_builddir)/glamor/libglamor.la \
+	$(top_builddir)/glamor/libglamor_egl_stubs.la \
+	$()
+endif
+
 Xephyr_LDADD = 						\
 	$(top_builddir)/exa/libexa.la			\
+	$(XEPHYR_GLAMOR_LIB)				\
 	@KDRIVE_LIBS@					\
 	@XEPHYR_LIBS@
 
-Xephyr_DEPENDENCIES = @KDRIVE_LOCAL_LIBS@
+Xephyr_DEPENDENCIES = @KDRIVE_LOCAL_LIBS@ $(XEPHYR_GLAMOR_LIB)
 
 Xephyr_LDFLAGS = $(LD_EXPORT_SYMBOLS_FLAG)
 
diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index 9681273..75a6fcb 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -43,9 +43,15 @@
 #include "ephyrglxext.h"
 #endif                          /* XF86DRI */
 
+#ifdef GLAMOR
+#include "glamor.h"
+#endif
+#include "ephyr_glamor_glx.h"
+
 #include "xkbsrv.h"
 
 extern int KdTsPhyScreen;
+extern Bool ephyr_glamor;
 
 KdKeyboardInfo *ephyrKbd;
 KdPointerInfo *ephyrMouse;
@@ -326,15 +332,19 @@ ephyrInternalDamageRedisplay(ScreenPtr pScreen)
         int nbox;
         BoxPtr pbox;
 
-        nbox = RegionNumRects(pRegion);
-        pbox = RegionRects(pRegion);
-
-        while (nbox--) {
-            hostx_paint_rect(screen,
-                             pbox->x1, pbox->y1,
-                             pbox->x1, pbox->y1,
-                             pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
-            pbox++;
+        if (ephyr_glamor) {
+            ephyr_glamor_damage_redisplay(scrpriv->glamor, pRegion);
+        } else {
+            nbox = RegionNumRects(pRegion);
+            pbox = RegionRects(pRegion);
+
+            while (nbox--) {
+                hostx_paint_rect(screen,
+                                 pbox->x1, pbox->y1,
+                                 pbox->x1, pbox->y1,
+                                 pbox->x2 - pbox->x1, pbox->y2 - pbox->y1);
+                pbox++;
+            }
         }
         DamageEmpty(scrpriv->pDamage);
     }
@@ -662,6 +672,7 @@ ephyrInitScreen(ScreenPtr pScreen)
     return TRUE;
 }
 
+
 Bool
 ephyrFinishInitScreen(ScreenPtr pScreen)
 {
@@ -679,6 +690,12 @@ ephyrFinishInitScreen(ScreenPtr pScreen)
     return TRUE;
 }
 
+/**
+ * Called by kdrive after calling down the
+ * pScreen->CreateScreenResources() chain, this gives us a chance to
+ * make any pixmaps after the screen and all extensions have been
+ * initialized.
+ */
 Bool
 ephyrCreateResources(ScreenPtr pScreen)
 {
@@ -693,8 +710,13 @@ ephyrCreateResources(ScreenPtr pScreen)
         return KdShadowSet(pScreen,
                            scrpriv->randr,
                            ephyrShadowUpdate, ephyrWindowLinear);
-    else
+    else {
+#ifdef GLAMOR
+        if (ephyr_glamor)
+            ephyr_glamor_create_screen_resources(pScreen);
+#endif
         return ephyrSetInternalDamage(pScreen);
+    }
 }
 
 void
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h
index 73fdb59..34ce460 100644
--- a/hw/kdrive/ephyr/ephyr.h
+++ b/hw/kdrive/ephyr/ephyr.h
@@ -80,6 +80,12 @@ typedef struct _ephyrScrPriv {
 
     KdScreenInfo *screen;
     int mynum;                  /* Screen number */
+
+    /**
+     * Per-screen Xlib-using state for glamor (private to
+     * ephyr_glamor_glx.c)
+     */
+    struct ephyr_glamor *glamor;
 } EphyrScrPriv;
 
 extern KdCardFuncs ephyrFuncs;
@@ -203,6 +209,14 @@ void
 void
  ephyrDrawFini(ScreenPtr pScreen);
 
+/* hostx.c glamor support */
+Bool ephyr_glamor_init(ScreenPtr pScreen);
+Bool ephyr_glamor_create_screen_resources(ScreenPtr pScreen);
+void ephyr_glamor_enable(ScreenPtr pScreen);
+void ephyr_glamor_disable(ScreenPtr pScreen);
+void ephyr_glamor_fini(ScreenPtr pScreen);
+void ephyr_glamor_host_paint_rect(ScreenPtr pScreen);
+
 /*ephyvideo.c*/
 
 Bool ephyrInitVideo(ScreenPtr pScreen);
diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.c b/hw/kdrive/ephyr/ephyr_glamor_glx.c
new file mode 100644
index 0000000..a937c1a
--- /dev/null
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.c
@@ -0,0 +1,292 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/** @file ephyr_glamor_glx.c
+ *
+ * Separate file for hiding Xlib and GLX-using parts of xephyr from
+ * the rest of the server-struct-aware build.
+ */
+
+#include <stdlib.h>
+#include <X11/Xlib.h>
+#include <X11/Xlib-xcb.h>
+#include <xcb/xcb_aux.h>
+#include <pixman.h>
+#include <epoxy/glx.h>
+#include "ephyr_glamor_glx.h"
+#include "os.h"
+
+/** @{
+ *
+ * global state for Xephyr with glamor.
+ *
+ * Xephyr can render with multiple windows, but all the windows have
+ * to be on the same X connection and all have to have the same
+ * visual.
+ */
+static Display *dpy;
+static XVisualInfo *visual_info;
+static GLXFBConfig fb_config;
+/** @} */
+
+/**
+ * Per-screen state for Xephyr with glamor.
+ */
+struct ephyr_glamor {
+    GLXContext ctx;
+    Window win;
+    GLXWindow glx_win;
+
+    GLuint tex;
+
+    GLuint texture_shader;
+    GLuint texture_shader_position_loc;
+    GLuint texture_shader_texcoord_loc;
+};
+
+static GLint
+ephyr_glamor_compile_glsl_prog(GLenum type, const char *source)
+{
+    GLint ok;
+    GLint prog;
+
+    prog = glCreateShader(type);
+    glShaderSource(prog, 1, (const GLchar **) &source, NULL);
+    glCompileShader(prog);
+    glGetShaderiv(prog, GL_COMPILE_STATUS, &ok);
+    if (!ok) {
+        GLchar *info;
+        GLint size;
+
+        glGetShaderiv(prog, GL_INFO_LOG_LENGTH, &size);
+        info = malloc(size);
+        if (info) {
+            glGetShaderInfoLog(prog, size, NULL, info);
+            ErrorF("Failed to compile %s: %s\n",
+                   type == GL_FRAGMENT_SHADER ? "FS" : "VS", info);
+            ErrorF("Program source:\n%s", source);
+            free(info);
+        }
+        else
+            ErrorF("Failed to get shader compilation info.\n");
+        FatalError("GLSL compile failure\n");
+    }
+
+    return prog;
+}
+
+static GLuint
+ephyr_glamor_build_glsl_prog(GLuint vs, GLuint fs)
+{
+    GLint ok;
+    GLuint prog;
+
+    prog = glCreateProgram();
+    glAttachShader(prog, vs);
+    glAttachShader(prog, fs);
+
+    glLinkProgram(prog);
+    glGetProgramiv(prog, GL_LINK_STATUS, &ok);
+    if (!ok) {
+        GLchar *info;
+        GLint size;
+
+        glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size);
+        info = malloc(size);
+
+        glGetProgramInfoLog(prog, size, NULL, info);
+        ErrorF("Failed to link: %s\n", info);
+        FatalError("GLSL link failure\n");
+    }
+
+    return prog;
+}
+
+static void
+ephyr_glamor_setup_texturing_shader(struct ephyr_glamor *glamor)
+{
+    const char *vs_source =
+        "attribute vec2 texcoord;\n"
+        "attribute vec2 position;\n"
+        "varying vec2 t;\n"
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    t = texcoord;\n"
+        "    gl_Position = vec4(position, 0, 1);\n"
+        "}\n";
+
+    const char *fs_source =
+        "varying vec2 t;\n"
+        "uniform sampler2D s; /* initially 0 */\n"
+        "\n"
+        "void main()\n"
+        "{\n"
+        "    gl_FragColor = texture2D(s, t);\n"
+        "}\n";
+
+    GLuint fs, vs, prog;
+
+    vs = ephyr_glamor_compile_glsl_prog(GL_VERTEX_SHADER, vs_source);
+    fs = ephyr_glamor_compile_glsl_prog(GL_FRAGMENT_SHADER, fs_source);
+    prog = ephyr_glamor_build_glsl_prog(vs, fs);
+
+    glamor->texture_shader = prog;
+    glamor->texture_shader_position_loc = glGetAttribLocation(prog, "position");
+    assert(glamor->texture_shader_position_loc != -1);
+    glamor->texture_shader_texcoord_loc = glGetAttribLocation(prog, "texcoord");
+    assert(glamor->texture_shader_texcoord_loc != -1);
+}
+
+xcb_connection_t *
+ephyr_glamor_connect(void)
+{
+    dpy = XOpenDisplay(NULL);
+    if (!dpy)
+        return NULL;
+
+    XSetEventQueueOwner(dpy, XCBOwnsEventQueue);
+
+    return XGetXCBConnection(dpy);
+}
+
+void
+ephyr_glamor_set_texture(struct ephyr_glamor *glamor, uint32_t tex)
+{
+    glamor->tex = tex;
+}
+
+void
+ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
+                              struct pixman_region16 *damage)
+{
+    /* Redraw the whole screen, since glXSwapBuffers leaves the back
+     * buffer undefined.
+     */
+    static const float position[] = {
+        -1, -1,
+         1, -1,
+         1,  1,
+        -1,  1,
+    };
+    static const float texcoords[] = {
+        0, 1,
+        1, 1,
+        1, 0,
+        0, 0,
+    };
+
+    glXMakeCurrent(dpy, glamor->glx_win, glamor->ctx);
+
+    glBindFramebuffer(GL_FRAMEBUFFER, 0);
+    glUseProgram(glamor->texture_shader);
+
+    glVertexAttribPointer(glamor->texture_shader_position_loc,
+                          2, GL_FLOAT, FALSE, 0, position);
+    glVertexAttribPointer(glamor->texture_shader_texcoord_loc,
+                          2, GL_FLOAT, FALSE, 0, texcoords);
+    glEnableVertexAttribArray(glamor->texture_shader_position_loc);
+    glEnableVertexAttribArray(glamor->texture_shader_texcoord_loc);
+
+    glActiveTexture(GL_TEXTURE0);
+    glBindTexture(GL_TEXTURE_2D, glamor->tex);
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+    glDisableVertexAttribArray(glamor->texture_shader_position_loc);
+    glDisableVertexAttribArray(glamor->texture_shader_texcoord_loc);
+
+    glXSwapBuffers(dpy, glamor->glx_win);
+}
+
+struct ephyr_glamor *
+ephyr_glamor_glx_screen_init(xcb_window_t win)
+{
+    GLXContext ctx;
+    struct ephyr_glamor *glamor;
+    GLXWindow glx_win;
+
+    glamor = calloc(1, sizeof(struct ephyr_glamor));
+    if (!glamor) {
+        FatalError("malloc");
+        return NULL;
+    }
+
+    glx_win = glXCreateWindow(dpy, fb_config, win, NULL);
+
+    ctx = glXCreateContext(dpy, visual_info, NULL, True);
+    if (ctx == NULL)
+        FatalError("glXCreateContext failed\n");
+
+    if (!glXMakeCurrent(dpy, glx_win, ctx))
+        FatalError("glXMakeCurrent failed\n");
+
+    glamor->ctx = ctx;
+    glamor->win = win;
+    glamor->glx_win = glx_win;
+    ephyr_glamor_setup_texturing_shader(glamor);
+
+    return glamor;
+}
+
+void
+ephyr_glamor_glx_screen_fini(struct ephyr_glamor *glamor)
+{
+    glXMakeCurrent(dpy, None, NULL);
+    glXDestroyContext(dpy, glamor->ctx);
+    glXDestroyWindow(dpy, glamor->glx_win);
+
+    free(glamor);
+}
+
+xcb_visualtype_t *
+ephyr_glamor_get_visual(void)
+{
+    xcb_screen_t *xscreen =
+        xcb_aux_get_screen(XGetXCBConnection(dpy), DefaultScreen(dpy));
+    int attribs[] = {
+        GLX_RENDER_TYPE, GLX_RGBA_BIT,
+        GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+        GLX_RED_SIZE, 1,
+        GLX_GREEN_SIZE, 1,
+        GLX_BLUE_SIZE, 1,
+        GLX_DOUBLEBUFFER, 1,
+        None
+    };
+    int event_base = 0, error_base = 0, nelements;
+    GLXFBConfig *fbconfigs;
+
+    if (!glXQueryExtension (dpy, &error_base, &event_base))
+        FatalError("Couldn't find GLX extension\n");
+
+    fbconfigs = glXChooseFBConfig(dpy, DefaultScreen(dpy), attribs, &nelements);
+    if (!nelements)
+        FatalError("Couldn't choose an FBConfig\n");
+    fb_config = fbconfigs[0];
+    free(fbconfigs);
+
+    visual_info = glXGetVisualFromFBConfig(dpy, fb_config);
+    if (visual_info == NULL)
+        FatalError("Couldn't get RGB visual\n");
+
+    return xcb_aux_find_visual_by_id(xscreen, visual_info->visualid);
+}
diff --git a/hw/kdrive/ephyr/ephyr_glamor_glx.h b/hw/kdrive/ephyr/ephyr_glamor_glx.h
new file mode 100644
index 0000000..950beff
--- /dev/null
+++ b/hw/kdrive/ephyr/ephyr_glamor_glx.h
@@ -0,0 +1,62 @@
+/*
+ * Copyright © 2013 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+
+/**
+ * ephyr_glamor_glx.h
+ *
+ * Prototypes exposed by ephyr_glamor_glx.c, without including any
+ * server headers.
+ */
+
+#include <xcb/xcb.h>
+#include "dix-config.h"
+
+struct ephyr_glamor;
+struct pixman_region16;
+
+xcb_connection_t *
+ephyr_glamor_connect(void);
+
+void
+ephyr_glamor_set_texture(struct ephyr_glamor *ephyr_glamor, uint32_t tex);
+
+xcb_visualtype_t *
+ephyr_glamor_get_visual(void);
+
+struct ephyr_glamor *
+ephyr_glamor_glx_screen_init(xcb_window_t win);
+
+void
+ephyr_glamor_glx_screen_fini(struct ephyr_glamor *glamor);
+
+#ifdef GLAMOR
+void
+ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
+                              struct pixman_region16 *damage);
+#else
+static inline void
+ephyr_glamor_damage_redisplay(struct ephyr_glamor *glamor,
+                              struct pixman_region16 *damage)
+{
+}
+#endif
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
index 3230e70..807e717 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -35,6 +35,7 @@ extern Bool EphyrWantGrayScale;
 extern Bool EphyrWantResize;
 extern Bool kdHasPointer;
 extern Bool kdHasKbd;
+extern Bool ephyr_glamor;
 
 #ifdef GLXEXT
 extern Bool ephyrNoDRI;
@@ -138,6 +139,9 @@ ddxUseMsg(void)
     ErrorF("-fullscreen          Attempt to run Xephyr fullscreen\n");
     ErrorF("-grayscale           Simulate 8bit grayscale\n");
     ErrorF("-resizeable          Make Xephyr windows resizeable\n");
+#ifdef GLAMOR
+    ErrorF("-glamor              Enable 2D acceleration using glamor\n");
+#endif
     ErrorF
         ("-fakexa              Simulate acceleration using software rendering\n");
     ErrorF("-verbosity <level>   Set log verbosity level\n");
@@ -241,6 +245,16 @@ ddxProcessArgument(int argc, char **argv, int i)
         EphyrWantResize = 1;
         return 1;
     }
+#ifdef GLAMOR
+    else if (!strcmp (argv[i], "-glamor")) {
+        ephyr_glamor = TRUE;
+        ephyrFuncs.initAccel = ephyr_glamor_init;
+        ephyrFuncs.enableAccel = ephyr_glamor_enable;
+        ephyrFuncs.disableAccel = ephyr_glamor_disable;
+        ephyrFuncs.finiAccel = ephyr_glamor_fini;
+        return 1;
+    }
+#endif
     else if (!strcmp(argv[i], "-fakexa")) {
         ephyrFuncs.initAccel = ephyrDrawInit;
         ephyrFuncs.enableAccel = ephyrDrawEnable;
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 44ad8e2..19c2ed2 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -36,6 +36,7 @@
 #include <string.h>             /* for memset */
 #include <errno.h>
 #include <time.h>
+#include <err.h>
 
 #include <sys/ipc.h>
 #include <sys/shm.h>
@@ -54,6 +55,11 @@
 #include <xcb/xf86dri.h>
 #include <xcb/glx.h>
 #endif /* XF86DRI */
+#ifdef GLAMOR
+#include <epoxy/gl.h>
+#include "glamor.h"
+#include "ephyr_glamor_glx.h"
+#endif
 #include "ephyrlog.h"
 #include "ephyr.h"
 
@@ -90,6 +96,7 @@ extern Bool EphyrWantResize;
 char *ephyrResName = NULL;
 int ephyrResNameFromCmd = 0;
 char *ephyrTitle = NULL;
+Bool ephyr_glamor = FALSE;
 
 static void
  hostx_set_fullscreen_hint(void);
@@ -302,7 +309,10 @@ hostx_init(void)
         | XCB_EVENT_MASK_STRUCTURE_NOTIFY;
 
     EPHYR_DBG("mark");
-    HostX.conn = xcb_connect(NULL, &HostX.screen);
+    if (ephyr_glamor)
+        HostX.conn = ephyr_glamor_connect();
+    else
+        HostX.conn = xcb_connect(NULL, &HostX.screen);
     if (xcb_connection_has_error(HostX.conn)) {
         fprintf(stderr, "\nXephyr cannot open host display. Is DISPLAY set?\n");
         exit(1);
@@ -312,7 +322,11 @@ hostx_init(void)
     HostX.winroot = xscreen->root;
     HostX.gc = xcb_generate_id(HostX.conn);
     HostX.depth = xscreen->root_depth;
-    HostX.visual  = xcb_aux_find_visual_by_id(xscreen, xscreen->root_visual);
+    if (ephyr_glamor) {
+        HostX.visual = ephyr_glamor_get_visual();
+    } else {
+        HostX.visual = xcb_aux_find_visual_by_id(xscreen,xscreen->root_visual);
+    }
 
     xcb_create_gc(HostX.conn, HostX.gc, HostX.winroot, 0, NULL);
     cookie_WINDOW_STATE = xcb_intern_atom(HostX.conn, FALSE,
@@ -642,7 +656,7 @@ hostx_screen_init(KdScreenInfo *screen,
         }
     }
 
-    if (HostX.have_shm) {
+    if (!ephyr_glamor && HostX.have_shm) {
         scrpriv->ximg = xcb_image_create_native(HostX.conn,
                                                 width,
                                                 buffer_height,
@@ -677,7 +691,7 @@ hostx_screen_init(KdScreenInfo *screen,
         }
     }
 
-    if (!shm_success) {
+    if (!ephyr_glamor && !shm_success) {
         EPHYR_DBG("Creating image %dx%d for screen scrpriv=%p\n",
                   width, buffer_height, scrpriv);
         scrpriv->ximg = xcb_image_create_native(HostX.conn,
@@ -711,7 +725,11 @@ hostx_screen_init(KdScreenInfo *screen,
     scrpriv->win_width = width;
     scrpriv->win_height = height;
 
-    if (host_depth_matches_server(scrpriv)) {
+    if (ephyr_glamor) {
+        *bytes_per_line = 0;
+        *bits_per_pixel = 0;
+        return NULL;
+    } else if (host_depth_matches_server(scrpriv)) {
         *bytes_per_line = scrpriv->ximg->stride;
         *bits_per_pixel = scrpriv->ximg->bpp;
 
@@ -742,6 +760,21 @@ hostx_paint_rect(KdScreenInfo *screen,
 
     EPHYR_DBG("painting in screen %d\n", scrpriv->mynum);
 
+    if (ephyr_glamor) {
+        BoxRec box;
+        RegionRec region;
+
+        box.x1 = dx;
+        box.y1 = dy;
+        box.x2 = dx + width;
+        box.y2 = dy + height;
+
+        RegionInit(&region, &box, 1);
+        ephyr_glamor_damage_redisplay(scrpriv->glamor, &region);
+        RegionUninit(&region);
+        return;
+    }
+
     /*
      *  Copy the image data updated by the shadow layer
      *  on to the window
@@ -1170,3 +1203,86 @@ hostx_get_resource_id_peer(int a_local_resource_id, int *a_remote_resource_id)
 }
 
 #endif                          /* XF86DRI */
+
+#ifdef GLAMOR
+Bool
+ephyr_glamor_init(ScreenPtr screen)
+{
+    KdScreenPriv(screen);
+    KdScreenInfo *kd_screen = pScreenPriv->screen;
+    EphyrScrPriv *scrpriv = kd_screen->driver;
+
+    scrpriv->glamor = ephyr_glamor_glx_screen_init(scrpriv->win);
+
+    glamor_init(screen,
+                GLAMOR_USE_SCREEN |
+                GLAMOR_USE_PICTURE_SCREEN |
+                GLAMOR_INVERTED_Y_AXIS);
+
+    return TRUE;
+}
+
+Bool
+ephyr_glamor_create_screen_resources(ScreenPtr pScreen)
+{
+    KdScreenPriv(pScreen);
+    KdScreenInfo *kd_screen = pScreenPriv->screen;
+    EphyrScrPriv *scrpriv = kd_screen->driver;
+    PixmapPtr screen_pixmap;
+    uint32_t tex;
+
+    if (!ephyr_glamor)
+        return TRUE;
+
+    if (!glamor_glyphs_init(pScreen))
+        return FALSE;
+
+    /* kdrive's fbSetupScreen() told mi to have
+     * miCreateScreenResources() (which is called before this) make a
+     * scratch pixmap wrapping ephyr-glamor's NULL
+     * KdScreenInfo->fb.framebuffer.
+     *
+     * We want a real (texture-based) screen pixmap at this point.
+     * This is what glamor will render into, and we'll then texture
+     * out of that into the host's window to present the results.
+     *
+     * Thus, delete the current screen pixmap, and put a fresh one in.
+     */
+    screen_pixmap = pScreen->GetScreenPixmap(pScreen);
+    pScreen->DestroyPixmap(screen_pixmap);
+
+    screen_pixmap = pScreen->CreatePixmap(pScreen,
+                                          pScreen->width,
+                                          pScreen->height,
+                                          pScreen->rootDepth, 0);
+    pScreen->SetScreenPixmap(screen_pixmap);
+
+    /* Tell the GLX code what to GL texture to read from. */
+    tex = glamor_get_pixmap_texture(screen_pixmap);
+    ephyr_glamor_set_texture(scrpriv->glamor, tex);
+
+    return TRUE;
+}
+
+void
+ephyr_glamor_enable(ScreenPtr screen)
+{
+}
+
+void
+ephyr_glamor_disable(ScreenPtr screen)
+{
+}
+
+void
+ephyr_glamor_fini(ScreenPtr screen)
+{
+    KdScreenPriv(screen);
+    KdScreenInfo *kd_screen = pScreenPriv->screen;
+    EphyrScrPriv *scrpriv = kd_screen->driver;
+
+    glamor_fini(screen);
+    ephyr_glamor_glx_screen_fini(scrpriv->glamor);
+    scrpriv->glamor = NULL;
+}
+#endif


More information about the xorg-commit mailing list