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.f...@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 (k...@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 _______________________________________________ xorg-devel@lists.x.org: X.Org development Archives: http://lists.x.org/archives/xorg-devel Info: http://lists.x.org/mailman/listinfo/xorg-devel