[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, ®);
+ REGION_COPY (screen, ®, &pair->local->clipList);
+ pGC->pCompositeClip = ®
+ pGC->ops->PutImage((DrawablePtr)pair->local, pGC, depth, 0, 0, width, height, 0, ZPixmap, data);
+ DamageRegionAppend((DrawablePtr)pair->local, ®);
+ DamageRegionProcessPending((DrawablePtr)pair->local);
+ REGION_UNINIT (screen, ®);
+ }
+}
+#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