[PATCH 2/3] Enable off-screen rendering feature for Xephyr

Feng, Haitao haitao.feng at intel.com
Mon Sep 20 22:51:21 PDT 2010


Hi,

This patch will enable off-screen rendering feature for Xephyr.

Basically on Xephyr host side, I use XCompositeRedirect to do the off-screen
rendering after creating a host peer window. And when glSwapBuffer happens in
Xephyr clients, I will copy the host peer window contents into Xephyr and
register a damage to let the Xephyr clients redraw the content.

This feature could be disabled by -noosr.

Thanks
-Haitao 

Signed-off-by: Haitao Feng <haitao.feng at intel.com>
---
 configure.ac                   |    3 ++
 hw/kdrive/ephyr/dri2.h         |   10 +------
 hw/kdrive/ephyr/dri2buffer.h   |   45 ++++++++++++++++++++++++++++++
 hw/kdrive/ephyr/ephyr.c        |   45 ++++++++++++++++++++++++++++++
 hw/kdrive/ephyr/ephyrdri2.c    |    1 +
 hw/kdrive/ephyr/ephyrdri2.h    |    3 +-
 hw/kdrive/ephyr/ephyrdri2ext.c |   38 +++++++++++++++++++++++--
 hw/kdrive/ephyr/ephyrdri2ext.h |   10 ++++++
 hw/kdrive/ephyr/ephyrinit.c    |    8 +++++
 hw/kdrive/ephyr/hostx.c        |   60 +++++++++++++++++++++++++++++++++++++++-
 hw/kdrive/ephyr/hostx.h        |    7 ++++
 11 files changed, 216 insertions(+), 14 deletions(-)
 create mode 100644 hw/kdrive/ephyr/dri2buffer.h

diff --git a/configure.ac b/configure.ac
index 95f7a76..daea4e0 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2069,6 +2069,9 @@ if test "$KDRIVE" = yes; then
     if test "x$DRI" = xyes && test "x$GLX" = xyes; then
         XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS $LIBGL libdrm"
     fi
+    if test "x$DRI2" = xyes && test "x$GLX" = xyes; then
+        XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS $LIBGL xcomposite"
+    fi
 
     PKG_CHECK_MODULES(XEPHYR, $XEPHYR_REQUIRED_LIBS, [xephyr="yes"], [xephyr="no"])
     if test "x$XEPHYR" = xauto; then
diff --git a/hw/kdrive/ephyr/dri2.h b/hw/kdrive/ephyr/dri2.h
index 9db77f4..1d32cad 100644
--- a/hw/kdrive/ephyr/dri2.h
+++ b/hw/kdrive/ephyr/dri2.h
@@ -36,15 +36,7 @@
 #include <X11/extensions/Xfixes.h>
 #include <X11/extensions/dri2tokens.h>
 #include <xf86drm.h>
-
-typedef struct
-{
-   unsigned int attachment;
-   unsigned int name;
-   unsigned int pitch;
-   unsigned int cpp;
-   unsigned int flags;
-} DRI2Buffer;
+#include "dri2buffer.h"
 
 extern Bool
 DRI2QueryExtension(Display * display, int *eventBase, int *errorBase);
diff --git a/hw/kdrive/ephyr/dri2buffer.h b/hw/kdrive/ephyr/dri2buffer.h
new file mode 100644
index 0000000..ab219c2
--- /dev/null
+++ b/hw/kdrive/ephyr/dri2buffer.h
@@ -0,0 +1,45 @@
+/*
+ * Copyright © 2007,2008 Red Hat, Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Soft-
+ * ware"), to deal in the Software without restriction, including without
+ * limitation the rights to use, copy, modify, merge, publish, distribute,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, provided that the above copyright
+ * notice(s) and this permission notice appear in all copies of the Soft-
+ * ware and that both the above copyright notice(s) and this permission
+ * notice appear in supporting documentation.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL-
+ * ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF THIRD PARTY
+ * RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR HOLDERS INCLUDED IN
+ * THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL INDIRECT OR CONSE-
+ * QUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFOR-
+ * MANCE OF THIS SOFTWARE.
+ *
+ * Except as contained in this notice, the name of a copyright holder shall
+ * not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization of
+ * the copyright holder.
+ *
+ * Authors:
+ *   Kristian Høgsberg (krh at redhat.com)
+ */
+
+#ifndef _DRI2BUFFER_H_
+#define _DRI2BUFFER_H_
+
+typedef struct
+{
+   unsigned int attachment;
+   unsigned int name;
+   unsigned int pitch;
+   unsigned int cpp;
+   unsigned int flags;
+} DRI2Buffer;
+
+#endif
diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index e4252ee..47bd82d 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -55,6 +55,7 @@ KdPointerInfo *ephyrMouse;
 EphyrKeySyms ephyrKeySyms;
 Bool ephyrNoDRI=FALSE ;
 Bool ephyrNoDRI2=FALSE ;
+Bool ephyrNoOSR=FALSE ;
 Bool ephyrNoXV=FALSE ;
 
 static int mouseState = 0;
@@ -663,6 +664,7 @@ ephyrInitScreen (ScreenPtr pScreen)
   if (!ephyrNoDRI) {
     ephyrDRIExtensionInit (pScreen) ;
     ephyrHijackGLXExtension () ;
+    ephyrNoOSR = TRUE ;
   }
 #endif
 
@@ -675,6 +677,9 @@ ephyrInitScreen (ScreenPtr pScreen)
   if (ephyrNoDRI && !ephyrNoDRI2) {
     ephyrDRI2ExtensionInit (pScreen) ;
     ephyrHijackGLXExtension () ;
+    if (!ephyrNoOSR && !hostx_has_composite ()) {
+        ephyrNoOSR = TRUE ;
+    }
   }
 #endif
 
@@ -900,6 +905,46 @@ ephyrExposePairedWindow (int a_remote)
 }
 #endif /* XF86DRI */
 
+#ifdef OFFSCREEN_RENDERING
+void
+ephyrPaintPairedLocalWindow (int a_remote, int depth, char *data, int sx, int sy, int width, int height)
+{
+    EphyrDRI2WindowPair *pair = NULL;
+    RegionRec reg;
+    ScreenPtr screen;
+    GCPtr pGC;
+    XID gcval = FALSE;
+    int status;
+
+    if (!findDRI2WindowPairFromRemote (a_remote, &pair)) {
+        EPHYR_LOG ("did not find a pair for this window\n");
+        return;
+    }
+
+    screen = pair->local->drawable.pScreen;
+
+    pGC = pair->gc;
+    if (!pGC) {
+        pGC = CreateGC((DrawablePtr)pair->local,
+                   GCGraphicsExposures, &gcval,
+                   &status, (XID)0, serverClient);
+        pair->gc = pGC;
+    }
+    if (pGC) {
+        FbGCPrivPtr pPriv = fbGetGCPrivate(pGC);
+        pPriv->pm = FB_ALLONES;
+
+        REGION_NULL (screen, &reg);
+        REGION_COPY (screen, &reg, &pair->local->clipList);
+        pGC->pCompositeClip = &reg;
+        pGC->ops->PutImage((DrawablePtr)pair->local, pGC, depth, 0, 0, width, height, 0, ZPixmap, data);
+        DamageRegionAppend((DrawablePtr)pair->local, &reg);
+        DamageRegionProcessPending((DrawablePtr)pair->local);
+        REGION_UNINIT (screen, &reg);
+    }
+}
+#endif
+
 void
 ephyrPoll(void)
 {
diff --git a/hw/kdrive/ephyr/ephyrdri2.c b/hw/kdrive/ephyr/ephyrdri2.c
index c8508b9..ec0ec75 100644
--- a/hw/kdrive/ephyr/ephyrdri2.c
+++ b/hw/kdrive/ephyr/ephyrdri2.c
@@ -39,6 +39,7 @@
 #include "ephyrlog.h"
 #include "dixstruct.h"
 #include "pixmapstr.h"
+#include "dri2.h"
 #include "ephyrdri2.h"
 
 #ifndef TRUE
diff --git a/hw/kdrive/ephyr/ephyrdri2.h b/hw/kdrive/ephyr/ephyrdri2.h
index 7132261..50419cc 100644
--- a/hw/kdrive/ephyr/ephyrdri2.h
+++ b/hw/kdrive/ephyr/ephyrdri2.h
@@ -30,7 +30,8 @@
 #define __EPHYRDRI2_H__
 
 #include <X11/extensions/dri2tokens.h>
-#include "dri2.h"
+#include <xf86drm.h>
+#include "dri2buffer.h"
 #include "ephyrdri2ext.h"
 
 void ephyrDRI2CloseScreen(ScreenPtr pScreen);
diff --git a/hw/kdrive/ephyr/ephyrdri2ext.c b/hw/kdrive/ephyr/ephyrdri2ext.c
index cb1ae16..2d61808 100644
--- a/hw/kdrive/ephyr/ephyrdri2ext.c
+++ b/hw/kdrive/ephyr/ephyrdri2ext.c
@@ -55,14 +55,15 @@
 #include "ephyrlog.h"
 
 #include "ephyrdri2ext.h"
+#include "gcstruct.h"
 
 #include <X11/extensions/dri2proto.h>
 #include "ephyrdri2.h"
-#include <X11/extensions/xfixeswire.h>
-#include <X11/Xlib.h>
 
+extern Bool   ephyrNoOSR;
 extern RESTYPE    RegionResType;
 extern int    XFixesErrorBase;
+
 #define VERIFY_REGION(pRegion, rid, client, mode)           \
     do {                                \
     int err;                            \
@@ -271,6 +272,7 @@ ephyrDRI2DestroyWindow (WindowPtr a_win)
     Bool is_ok=FALSE ;
     ScreenPtr screen=NULL ;
     EphyrDRI2ScreenPrivPtr screen_priv =NULL;
+    EphyrDRI2WindowPrivPtr win_priv;
 
     EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ;
     screen = a_win->drawable.pScreen ;
@@ -280,6 +282,22 @@ ephyrDRI2DestroyWindow (WindowPtr a_win)
                               && screen_priv->DestroyWindow,
                               FALSE) ;
 
+#ifdef OFFSCREEN_RENDERING
+    if (!ephyrNoOSR) {
+        win_priv=GET_EPHYR_DRI2_WINDOW_PRIV (a_win) ;
+        if (win_priv) {
+            EphyrDRI2WindowPair *pair=NULL ;
+            findWindowPairFromLocal (a_win, &pair);
+            if (pair) {
+                GCPtr pGC = pair->gc;
+                if (pGC){
+                    (*pGC->funcs->DestroyGC)(pGC); 
+                }
+            }
+        }
+    }
+#endif
+
     screen->DestroyWindow = screen_priv->DestroyWindow ;
     if (screen->DestroyWindow) {
         is_ok = (*screen->DestroyWindow) (a_win) ;
@@ -287,7 +305,7 @@ ephyrDRI2DestroyWindow (WindowPtr a_win)
     screen->DestroyWindow = ephyrDRI2DestroyWindow ;
 
     if (is_ok) {
-        EphyrDRI2WindowPrivPtr win_priv=GET_EPHYR_DRI2_WINDOW_PRIV (a_win) ;
+        win_priv=GET_EPHYR_DRI2_WINDOW_PRIV (a_win) ;
         if (win_priv) {
             destroyHostPeerWindow (a_win) ;
             free (win_priv) ;
@@ -682,6 +700,9 @@ appendWindowPairToList (WindowPtr a_local,
         if (window_pairs[i].local == NULL) {
             window_pairs[i].local = a_local ;
             window_pairs[i].remote = a_remote ;
+#ifdef OFFSCREEN_RENDERING
+            window_pairs[i].gc = 0;
+#endif
             return TRUE ;
         }
     }
@@ -792,6 +813,9 @@ destroyHostPeerWindow (const WindowPtr a_win)
     hostx_destroy_window (pair->remote) ;
     pair->local  = NULL;
     pair->remote = 0;
+#ifdef OFFSCREEN_RENDERING
+    pair->gc = 0;
+#endif
     is_ok = TRUE ;
 
 out:
@@ -1117,6 +1141,14 @@ ProcDRI2CopyRegion(ClientPtr client)
     if (status != Success)
         return status;
 
+#ifdef OFFSCREEN_RENDERING
+    if (!ephyrNoOSR) {
+        int width  = pRegion->extents.x2 - pRegion->extents.x1;
+        int height = pRegion->extents.y2 - pRegion->extents.y1;
+        hostx_copy_region(stuff->drawable, pair->remote, width, height, pDrawable->x, pDrawable->y);
+    }
+#endif
+
     /* CopyRegion needs to be a round trip to make sure the X server
      * queues the swap buffer rendering commands before the DRI client
      * continues rendering.  The reply has a bitmask to signal the
diff --git a/hw/kdrive/ephyr/ephyrdri2ext.h b/hw/kdrive/ephyr/ephyrdri2ext.h
index b0b5ea9..154e3c8 100644
--- a/hw/kdrive/ephyr/ephyrdri2ext.h
+++ b/hw/kdrive/ephyr/ephyrdri2ext.h
@@ -29,15 +29,25 @@
 #ifndef __EPHYRDRI2EXT_H__
 #define __EPHYRDRI2EXT_H__
 
+#define OFFSCREEN_RENDERING 1
+
 #include "window.h"
 
+#ifdef OFFSCREEN_RENDERING
+#include "gc.h"
+#endif
+
 typedef struct {
     WindowPtr local ;
     int remote ;
+#ifdef OFFSCREEN_RENDERING
+    GCPtr gc;
+#endif
 } EphyrDRI2WindowPair;
 
 Bool ephyrDRI2ExtensionInit (ScreenPtr a_screen) ;
 Bool findDRI2WindowPairFromRemote (int a_remote,
         EphyrDRI2WindowPair **a_pair);
+void ephyrPaintPairedLocalWindow (int a_remote, int depth, char *data, int sx, int sy, int width, int height);
 
 #endif /*__EPHYRDRIEXT_H__*/
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
index 19d18c1..07e6c65 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -37,6 +37,7 @@ extern Bool   kdHasKbd;
 #ifdef GLXEXT
 extern Bool   ephyrNoDRI;
 extern Bool   ephyrNoDRI2;
+extern Bool   ephyrNoOSR;
 extern Bool noGlxVisualInit;
 #endif
 extern Bool   ephyrNoXV;
@@ -122,6 +123,7 @@ ddxUseMsg (void)
 #ifdef GLXEXT
   ErrorF("-nodri               do not use DRI\n");
   ErrorF("-nodri2              do not use DRI2\n");
+  ErrorF("-noosr               do not use off-screen rendering\n");
 #endif
   ErrorF("-noxv                do not use XV\n");
   ErrorF("-name [name]         define the name in the WM_CLASS property\n");
@@ -257,6 +259,12 @@ ddxProcessArgument (int argc, char **argv, int i)
        EPHYR_LOG ("no direct rendering enabled\n") ;
        return 1 ;
    }
+  else if (!strcmp (argv[i], "-noosr"))
+   {
+       ephyrNoOSR = TRUE ;
+       EPHYR_LOG ("no off-screen rendering enabled\n") ;
+       return 1 ;
+   }
 #endif
   else if (!strcmp (argv[i], "-noxv"))
    {
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 79e407e..884e108 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -62,6 +62,16 @@
 #endif /* XF86DRI */
 #include "ephyrlog.h"
 
+#ifdef DRI2
+#include "ephyrdri2ext.h"
+#endif
+
+#ifdef OFFSCREEN_RENDERING
+#include <X11/extensions/Xcomposite.h>
+extern Bool ephyrNoOSR;
+#endif
+
+
 #ifdef XF86DRI
 extern Bool XF86DRIQueryExtension (Display *dpy,
                                    int *event_basep,
@@ -1170,6 +1180,27 @@ out:
 
 }
 
+#ifdef OFFSCREEN_RENDERING
+int
+hostx_copy_region (XID drawable,
+                       int remote,
+                       int width,
+                       int height,
+                       int sx,
+                       int sy)
+{
+    Display *dpy = hostx_get_display () ;
+    XImage *img = XGetImage(dpy, remote, 0, 0, width, height, 0xffffffff, ZPixmap);
+
+    if (img){
+        ephyrPaintPairedLocalWindow(remote, img->depth, img->data, sx, sy, width, height);
+        XDestroyImage(img);
+    }
+
+    return 0;
+}
+#endif
+
 int
 hostx_create_window (int a_screen_number,
                      EphyrBox *a_geometry,
@@ -1211,6 +1242,13 @@ hostx_create_window (int a_screen_number,
                        |KeyPressMask
                        |KeyReleaseMask
                        |ExposureMask;
+
+#ifdef OFFSCREEN_RENDERING
+    if (!ephyrNoOSR) {
+        attrs.event_mask = 0;
+    }
+#endif
+
     winmask = CWColormap|CWEventMask;
 
     win = XCreateWindow (dpy, hostx_get_window (a_screen_number),
@@ -1230,6 +1268,12 @@ hostx_create_window (int a_screen_number,
     XFlush (dpy) ;
     XMapWindow (dpy, win) ;
     *a_host_peer = win ;
+
+#ifdef OFFSCREEN_RENDERING
+    if (!ephyrNoOSR) {
+        XCompositeRedirectWindow (dpy, win, CompositeRedirectManual);
+    }
+#endif
     is_ok = TRUE ;
 out:
     EPHYR_LOG ("leave\n") ;
@@ -1461,7 +1505,6 @@ hostx_has_dri2 (void)
     int event_base=0, error_base=0 ;
     Display *dpy=hostx_get_display () ;
 
-
     if (!dpy)
         return FALSE ;
     if (!DRI2QueryExtension (dpy,
@@ -1472,4 +1515,19 @@ hostx_has_dri2 (void)
     return TRUE ;
 }
 
+int
+hostx_has_composite (void)
+{
+    int composite_opcode=0, composite_event=0, composite_error=0 ;
+    Display *dpy=hostx_get_display () ;
+
+    if (!dpy)
+        return FALSE ;
+    if (!XQueryExtension (dpy, COMPOSITE_NAME, &composite_opcode,
+              &composite_event, &composite_error)) {
+        return FALSE ;
+    }
+    return TRUE ;
+}
+
 #endif /* DRI2 */
diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h
index 6a59a53..fc529c2 100644
--- a/hw/kdrive/ephyr/hostx.h
+++ b/hw/kdrive/ephyr/hostx.h
@@ -265,6 +265,13 @@ int hostx_has_dri (void) ;
 
 #if defined(DRI2)
 int hostx_has_dri2 (void) ;
+int hostx_copy_region (XID drawable,
+                       int remote,
+                       int width,
+                       int height,
+                       int sx,
+                       int sy);
+int hostx_has_composite (void) ;
 #endif
 
 #endif /*_XLIBS_STUFF_H_*/
-- 
1.6.1.3



More information about the xorg-devel mailing list