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

Tiago Vignatti tiago.vignatti at nokia.com
Fri Sep 24 08:05:03 PDT 2010


On Tue, Sep 21, 2010 at 07:51:21AM +0200, ext Feng, Haitao wrote:
> 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

I think you can remove all references to this macro in the patch.

Also, the same argument that I gave for the patch #3 maybe is valid in this
patch: is there a real reason to not fallback silently to software when
off-screen rendering is not possible? Who would want to not execute with
off-screen just for fun? :)

  Tiago


More information about the xorg-devel mailing list