[PATCH 6/8] xephyr: Build support for rendering with glamor using a -glamor option.

Eric Anholt eric at anholt.net
Mon Feb 3 10:36:47 PST 2014


Signed-off-by: Eric Anholt <eric at anholt.net>
---
 configure.ac                       |   3 +
 glamor/glamor.c                    |  11 ++
 glamor/glamor.h                    |   2 +
 hw/kdrive/ephyr/Makefile.am        |  20 ++-
 hw/kdrive/ephyr/ephyr.c            |  36 +++--
 hw/kdrive/ephyr/ephyr.h            |  14 ++
 hw/kdrive/ephyr/ephyr_glamor_glx.c | 292 +++++++++++++++++++++++++++++++++++++
 hw/kdrive/ephyr/ephyr_glamor_glx.h |  62 ++++++++
 hw/kdrive/ephyr/ephyrinit.c        |  14 ++
 hw/kdrive/ephyr/hostx.c            |  97 +++++++++++-
 10 files changed, 538 insertions(+), 13 deletions(-)
 create mode 100644 hw/kdrive/ephyr/ephyr_glamor_glx.c
 create mode 100644 hw/kdrive/ephyr/ephyr_glamor_glx.h

diff --git a/configure.ac b/configure.ac
index 5946fe7..ad66f61 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 65fabc2..f1c71ea 100644
--- a/glamor/glamor.c
+++ b/glamor/glamor.c
@@ -140,6 +140,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 da80c95..e799b6e 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)
 {
@@ -693,8 +704,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..f37e1b3 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,
@@ -742,6 +756,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 +1199,67 @@ 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;
+
+    screen_pixmap = pScreen->GetScreenPixmap(pScreen);
+    glamor_set_screen_pixmap(screen_pixmap, NULL);
+    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
-- 
1.9.rc1



More information about the xorg-devel mailing list