1449 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1449 lines
		
	
	
		
			44 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * Xephyr - A kdrive X server thats runs in a host X window.
 | |
|  *          Authored by Matthew Allum <mallum@openedhand.com>
 | |
|  * 
 | |
|  * Copyright © 2007 OpenedHand Ltd 
 | |
|  *
 | |
|  * Permission to use, copy, modify, distribute, and sell this software and its
 | |
|  * documentation for any purpose is hereby granted without fee, provided that
 | |
|  * the above copyright notice appear in all copies and that both that
 | |
|  * copyright notice and this permission notice appear in supporting
 | |
|  * documentation, and that the name of OpenedHand Ltd not be used in
 | |
|  * advertising or publicity pertaining to distribution of the software without
 | |
|  * specific, written prior permission. OpenedHand Ltd makes no
 | |
|  * representations about the suitability of this software for any purpose.  It
 | |
|  * is provided "as is" without express or implied warranty.
 | |
|  *
 | |
|  * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
 | |
|  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
 | |
|  * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR
 | |
|  * CONSEQUENTIAL 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
 | |
|  * PERFORMANCE OF THIS SOFTWARE.
 | |
|  *
 | |
|  * This file is heavily copied from hw/xfree86/dri/xf86dri.c
 | |
|  *
 | |
|  * Authors:
 | |
|  *    Dodji Seketeli <dodji@openedhand.com>
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_CONFIG_H
 | |
| #include <kdrive-config.h>
 | |
| #endif
 | |
| 
 | |
| #ifdef XEPHYR_DRI
 | |
| 
 | |
| #include <string.h>
 | |
| 
 | |
| #define NEED_REPLIES
 | |
| #define NEED_EVENTS
 | |
| #include <X11/X.h>
 | |
| #include <X11/Xproto.h>
 | |
| #define _XF86DRI_SERVER_
 | |
| #include <X11/dri/xf86dri.h>
 | |
| #include <X11/dri/xf86dristr.h>
 | |
| #include "misc.h"
 | |
| #include "dixstruct.h"
 | |
| #include "extnsionst.h"
 | |
| #include "colormapst.h"
 | |
| #include "cursorstr.h"
 | |
| #include "scrnintstr.h"
 | |
| #include "windowstr.h"
 | |
| #include "servermd.h"
 | |
| #include "swaprep.h"
 | |
| #include "ephyrdri.h"
 | |
| #include "ephyrdriext.h"
 | |
| #include "hostx.h"
 | |
| #define _HAVE_XALLOC_DECLS
 | |
| #include "ephyrlog.h"
 | |
| 
 | |
| typedef struct {
 | |
|     WindowPtr local ;
 | |
|     int remote ;
 | |
| } EphyrWindowPair;
 | |
| 
 | |
| typedef struct {
 | |
|     int foo;
 | |
| } EphyrDRIWindowPrivRec;
 | |
| typedef EphyrDRIWindowPrivRec* EphyrDRIWindowPrivPtr;
 | |
| 
 | |
| typedef struct {
 | |
|     CreateWindowProcPtr CreateWindow ;
 | |
|     DestroyWindowProcPtr DestroyWindow ;
 | |
|     MoveWindowProcPtr MoveWindow ;
 | |
|     PositionWindowProcPtr PositionWindow ;
 | |
|     ClipNotifyProcPtr ClipNotify ;
 | |
| } EphyrDRIScreenPrivRec;
 | |
| typedef EphyrDRIScreenPrivRec* EphyrDRIScreenPrivPtr;
 | |
| 
 | |
| static int DRIErrorBase;
 | |
| 
 | |
| static DISPATCH_PROC(ProcXF86DRIQueryVersion);
 | |
| static DISPATCH_PROC(ProcXF86DRIQueryDirectRenderingCapable);
 | |
| static DISPATCH_PROC(ProcXF86DRIOpenConnection);
 | |
| static DISPATCH_PROC(ProcXF86DRICloseConnection);
 | |
| static DISPATCH_PROC(ProcXF86DRIGetClientDriverName);
 | |
| static DISPATCH_PROC(ProcXF86DRICreateContext);
 | |
| static DISPATCH_PROC(ProcXF86DRIDestroyContext);
 | |
| static DISPATCH_PROC(ProcXF86DRICreateDrawable);
 | |
| static DISPATCH_PROC(ProcXF86DRIDestroyDrawable);
 | |
| static DISPATCH_PROC(ProcXF86DRIGetDrawableInfo);
 | |
| static DISPATCH_PROC(ProcXF86DRIGetDeviceInfo);
 | |
| static DISPATCH_PROC(ProcXF86DRIDispatch);
 | |
| static DISPATCH_PROC(ProcXF86DRIAuthConnection);
 | |
| 
 | |
| static DISPATCH_PROC(SProcXF86DRIQueryVersion);
 | |
| static DISPATCH_PROC(SProcXF86DRIQueryDirectRenderingCapable);
 | |
| static DISPATCH_PROC(SProcXF86DRIDispatch);
 | |
| 
 | |
| static void XF86DRIResetProc(ExtensionEntry* extEntry);
 | |
| 
 | |
| static Bool ephyrDRIScreenInit (ScreenPtr a_screen) ;
 | |
| static Bool ephyrDRICreateWindow (WindowPtr a_win) ;
 | |
| static Bool ephyrDRIDestroyWindow (WindowPtr a_win) ;
 | |
| static void ephyrDRIMoveWindow (WindowPtr a_win,
 | |
|                                 int a_x, int a_y,
 | |
|                                 WindowPtr a_siblings,
 | |
|                                 VTKind a_kind);
 | |
| static Bool ephyrDRIPositionWindow (WindowPtr a_win,
 | |
|                                     int x, int y) ;
 | |
| static void ephyrDRIClipNotify (WindowPtr a_win,
 | |
|                                 int a_x, int a_y) ;
 | |
| 
 | |
| static Bool EphyrMirrorHostVisuals (ScreenPtr a_screen) ;
 | |
| static Bool destroyHostPeerWindow (const WindowPtr a_win) ;
 | |
| static Bool findWindowPairFromLocal (WindowPtr a_local,
 | |
|                                      EphyrWindowPair **a_pair);
 | |
| 
 | |
| static unsigned char DRIReqCode = 0;
 | |
| 
 | |
| static int ephyrDRIGeneration=-1 ;
 | |
| static int ephyrDRIWindowIndex=-1 ;
 | |
| static int ephyrDRIScreenIndex=-1 ;
 | |
| 
 | |
| #define GET_EPHYR_DRI_WINDOW_PRIV(win) \
 | |
|     ((EphyrDRIWindowPrivPtr)((win)->devPrivates[ephyrDRIWindowIndex].ptr))
 | |
| #define GET_EPHYR_DRI_SCREEN_PRIV(screen) \
 | |
|     ((EphyrDRIScreenPrivPtr)((screen)->devPrivates[ephyrDRIScreenIndex].ptr))
 | |
| 
 | |
| 
 | |
| Bool
 | |
| ephyrDRIExtensionInit (ScreenPtr a_screen)
 | |
| {
 | |
|     Bool is_ok=FALSE ;
 | |
|     ExtensionEntry* extEntry=NULL;
 | |
|     EphyrDRIScreenPrivPtr screen_priv=NULL ;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     if (!hostx_has_dri ()) {
 | |
|         EPHYR_LOG ("host does not have DRI extension\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     EPHYR_LOG ("host X does have DRI extension\n") ;
 | |
|     if (!hostx_has_xshape ()) {
 | |
|         EPHYR_LOG ("host does not have XShape extension\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     EPHYR_LOG ("host X does have XShape extension\n") ;
 | |
| 
 | |
| #ifdef XF86DRI_EVENTS
 | |
|     EventType = CreateNewResourceType (XF86DRIFreeEvents);
 | |
| #endif
 | |
| 
 | |
|     if ((extEntry = AddExtension(XF86DRINAME,
 | |
| 				 XF86DRINumberEvents,
 | |
| 				 XF86DRINumberErrors,
 | |
| 				 ProcXF86DRIDispatch,
 | |
| 				 SProcXF86DRIDispatch,
 | |
| 				 XF86DRIResetProc,
 | |
| 				 StandardMinorOpcode))) {
 | |
| 	DRIReqCode = (unsigned char)extEntry->base;
 | |
| 	DRIErrorBase = extEntry->errorBase;
 | |
|     } else {
 | |
|         EPHYR_LOG_ERROR ("failed to register DRI extension\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     if (ephyrDRIGeneration != serverGeneration) {
 | |
|         ephyrDRIScreenIndex = AllocateScreenPrivateIndex () ;
 | |
|         if (ephyrDRIScreenIndex < 0) {
 | |
|             EPHYR_LOG_ERROR ("failed to allocate screen priv index\n") ;
 | |
|             goto out ;
 | |
|         }
 | |
|     }
 | |
|     screen_priv = xcalloc (1, sizeof (EphyrDRIScreenPrivRec)) ;
 | |
|     if (!screen_priv) {
 | |
|         EPHYR_LOG_ERROR ("failed to allocate screen_priv\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     a_screen->devPrivates[ephyrDRIScreenIndex].ptr = screen_priv;
 | |
| 
 | |
|     if (!ephyrDRIScreenInit (a_screen)) {
 | |
|         EPHYR_LOG_ERROR ("ephyrDRIScreenInit() failed\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     EphyrMirrorHostVisuals (a_screen) ;
 | |
|     if (ephyrDRIGeneration != serverGeneration) {
 | |
|         ephyrDRIGeneration = serverGeneration ;
 | |
|     }
 | |
|     is_ok=TRUE ;
 | |
| out:
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return is_ok ;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| ephyrDRIScreenInit (ScreenPtr a_screen)
 | |
| {
 | |
|     Bool is_ok=FALSE ;
 | |
|     EphyrDRIScreenPrivPtr screen_priv=NULL ;
 | |
| 
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (a_screen, FALSE) ;
 | |
| 
 | |
|     screen_priv=GET_EPHYR_DRI_SCREEN_PRIV (a_screen) ;
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (screen_priv, FALSE) ;
 | |
| 
 | |
|     if (ephyrDRIGeneration != serverGeneration) {
 | |
|         ephyrDRIWindowIndex = AllocateWindowPrivateIndex () ;
 | |
|         if (ephyrDRIWindowIndex < 0) {
 | |
|             EPHYR_LOG_ERROR ("failed to allocate window priv index\n") ;
 | |
|             goto out ;
 | |
|         }
 | |
|     }
 | |
|     if (!AllocateWindowPrivate (a_screen, ephyrDRIWindowIndex, 0)) {
 | |
|         EPHYR_LOG_ERROR ("failed to allocate window privates\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     screen_priv->CreateWindow = a_screen->CreateWindow ;
 | |
|     screen_priv->DestroyWindow = a_screen->DestroyWindow ;
 | |
|     screen_priv->MoveWindow = a_screen->MoveWindow ;
 | |
|     screen_priv->PositionWindow = a_screen->PositionWindow ;
 | |
|     screen_priv->ClipNotify = a_screen->ClipNotify ;
 | |
| 
 | |
|     a_screen->CreateWindow = ephyrDRICreateWindow ;
 | |
|     a_screen->DestroyWindow = ephyrDRIDestroyWindow ;
 | |
|     a_screen->MoveWindow = ephyrDRIMoveWindow ;
 | |
|     a_screen->PositionWindow = ephyrDRIPositionWindow ;
 | |
|     a_screen->ClipNotify = ephyrDRIClipNotify ;
 | |
| 
 | |
|     is_ok = TRUE ;
 | |
| out:
 | |
|     return is_ok ;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| ephyrDRICreateWindow (WindowPtr a_win)
 | |
| {
 | |
|     Bool is_ok=FALSE ;
 | |
|     ScreenPtr screen=NULL ;
 | |
|     EphyrDRIScreenPrivPtr screen_priv =NULL;
 | |
| 
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ;
 | |
|     screen = a_win->drawable.pScreen ;
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ;
 | |
|     screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ;
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (screen_priv
 | |
|                               && screen_priv->CreateWindow,
 | |
|                               FALSE) ;
 | |
| 
 | |
|     EPHYR_LOG ("enter. win:%#x\n",
 | |
|                (unsigned int)a_win) ;
 | |
| 
 | |
|     screen->CreateWindow = screen_priv->CreateWindow ;
 | |
|     is_ok = (*screen->CreateWindow) (a_win) ;
 | |
|     screen->CreateWindow = ephyrDRICreateWindow ;
 | |
| 
 | |
|     if (is_ok) {
 | |
|         a_win->devPrivates[ephyrDRIWindowIndex].ptr = NULL ;
 | |
|     }
 | |
|     return is_ok ;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| ephyrDRIDestroyWindow (WindowPtr a_win)
 | |
| {
 | |
|     Bool is_ok=FALSE ;
 | |
|     ScreenPtr screen=NULL ;
 | |
|     EphyrDRIScreenPrivPtr screen_priv =NULL;
 | |
| 
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ;
 | |
|     screen = a_win->drawable.pScreen ;
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ;
 | |
|     screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ;
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (screen_priv
 | |
|                               && screen_priv->DestroyWindow,
 | |
|                               FALSE) ;
 | |
| 
 | |
|     screen->DestroyWindow = screen_priv->DestroyWindow ;
 | |
|     if (screen->DestroyWindow) {
 | |
|         is_ok = (*screen->DestroyWindow) (a_win) ;
 | |
|     }
 | |
|     screen->DestroyWindow = ephyrDRIDestroyWindow ;
 | |
| 
 | |
|     if (is_ok) {
 | |
|         EphyrDRIWindowPrivPtr win_priv=GET_EPHYR_DRI_WINDOW_PRIV (a_win) ;
 | |
|         if (win_priv) {
 | |
|             destroyHostPeerWindow (a_win) ;
 | |
|             xfree (win_priv) ;
 | |
|             a_win->devPrivates[ephyrDRIWindowIndex].ptr = NULL ;
 | |
|             EPHYR_LOG ("destroyed the remote peer window\n") ;
 | |
|         }
 | |
|     }
 | |
|     return is_ok ;
 | |
| }
 | |
| 
 | |
| static void
 | |
| ephyrDRIMoveWindow (WindowPtr a_win,
 | |
|                     int a_x, int a_y,
 | |
|                     WindowPtr a_siblings,
 | |
|                     VTKind a_kind)
 | |
| {
 | |
|     Bool is_ok=FALSE ;
 | |
|     ScreenPtr screen=NULL ;
 | |
|     EphyrDRIScreenPrivPtr screen_priv =NULL;
 | |
|     EphyrDRIWindowPrivPtr win_priv=NULL ;
 | |
|     EphyrWindowPair *pair=NULL ;
 | |
|     EphyrBox geo;
 | |
|     int x=0,y=0;/*coords relative to parent window*/
 | |
| 
 | |
|     EPHYR_RETURN_IF_FAIL (a_win) ;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     screen = a_win->drawable.pScreen ;
 | |
|     EPHYR_RETURN_IF_FAIL (screen) ;
 | |
|     screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ;
 | |
|     EPHYR_RETURN_IF_FAIL (screen_priv
 | |
|                           && screen_priv->MoveWindow) ;
 | |
| 
 | |
|     screen->MoveWindow = screen_priv->MoveWindow ;
 | |
|     if (screen->MoveWindow) {
 | |
|         (*screen->MoveWindow) (a_win, a_x, a_y, a_siblings, a_kind) ;
 | |
|     }
 | |
|     screen->MoveWindow = ephyrDRIMoveWindow ;
 | |
| 
 | |
|     EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ;
 | |
|     if (!a_win->parent) {
 | |
|         EPHYR_LOG ("cannot move root window\n") ;
 | |
|         is_ok = TRUE ;
 | |
|         goto out ;
 | |
|     }
 | |
|     win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ;
 | |
|     if (!win_priv) {
 | |
|         EPHYR_LOG ("not a DRI peered window\n") ;
 | |
|         is_ok = TRUE ;
 | |
|         goto out ;
 | |
|     }
 | |
|     if (!findWindowPairFromLocal (a_win, &pair) || !pair) {
 | |
|         EPHYR_LOG_ERROR ("failed to get window pair\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     /*compute position relative to parent window*/
 | |
|     x = a_win->drawable.x - a_win->parent->drawable.x ;
 | |
|     y = a_win->drawable.y - a_win->parent->drawable.y ;
 | |
|     /*set the geometry to pass to hostx_set_window_geometry*/
 | |
|     memset (&geo, 0, sizeof (geo)) ;
 | |
|     geo.x = x ;
 | |
|     geo.y = y ;
 | |
|     geo.width = a_win->drawable.width ;
 | |
|     geo.height = a_win->drawable.height ;
 | |
|     hostx_set_window_geometry (pair->remote, &geo) ;
 | |
|     is_ok = TRUE ;
 | |
| 
 | |
| out:
 | |
|     EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ;
 | |
|     /*do cleanup here*/
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| ephyrDRIPositionWindow (WindowPtr a_win,
 | |
|                         int a_x, int a_y)
 | |
| {
 | |
|     Bool is_ok=FALSE ;
 | |
|     ScreenPtr screen=NULL ;
 | |
|     EphyrDRIScreenPrivPtr screen_priv =NULL;
 | |
|     EphyrDRIWindowPrivPtr win_priv=NULL ;
 | |
|     EphyrWindowPair *pair=NULL ;
 | |
|     EphyrBox geo;
 | |
| 
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     screen = a_win->drawable.pScreen ;
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ;
 | |
|     screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ;
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (screen_priv
 | |
|                               && screen_priv->PositionWindow,
 | |
|                               FALSE) ;
 | |
| 
 | |
|     screen->PositionWindow = screen_priv->PositionWindow ;
 | |
|     if (screen->PositionWindow) {
 | |
|         (*screen->PositionWindow) (a_win, a_x, a_y) ;
 | |
|     }
 | |
|     screen->PositionWindow = ephyrDRIPositionWindow ;
 | |
| 
 | |
|     EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ;
 | |
|     win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ;
 | |
|     if (!win_priv) {
 | |
|         EPHYR_LOG ("not a DRI peered window\n") ;
 | |
|         is_ok = TRUE ;
 | |
|         goto out ;
 | |
|     }
 | |
|     if (!findWindowPairFromLocal (a_win, &pair) || !pair) {
 | |
|         EPHYR_LOG_ERROR ("failed to get window pair\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     /*set the geometry to pass to hostx_set_window_geometry*/
 | |
|     memset (&geo, 0, sizeof (geo)) ;
 | |
|     geo.x = a_x ;
 | |
|     geo.y = a_y ;
 | |
|     geo.width = a_win->drawable.width ;
 | |
|     geo.height = a_win->drawable.height ;
 | |
|     hostx_set_window_geometry (pair->remote, &geo) ;
 | |
|     is_ok = TRUE ;
 | |
| 
 | |
| out:
 | |
|     EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ;
 | |
|     /*do cleanup here*/
 | |
|     return is_ok ;
 | |
| }
 | |
| 
 | |
| static void
 | |
| ephyrDRIClipNotify (WindowPtr a_win,
 | |
|                     int a_x, int a_y)
 | |
| {
 | |
|     Bool is_ok=FALSE ;
 | |
|     ScreenPtr screen=NULL ;
 | |
|     EphyrDRIScreenPrivPtr screen_priv =NULL;
 | |
|     EphyrDRIWindowPrivPtr win_priv=NULL ;
 | |
|     EphyrWindowPair *pair=NULL ;
 | |
|     EphyrRect *rects=NULL;
 | |
|     int i=0 ;
 | |
| 
 | |
|     EPHYR_RETURN_IF_FAIL (a_win) ;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     screen = a_win->drawable.pScreen ;
 | |
|     EPHYR_RETURN_IF_FAIL (screen) ;
 | |
|     screen_priv = GET_EPHYR_DRI_SCREEN_PRIV (screen) ;
 | |
|     EPHYR_RETURN_IF_FAIL (screen_priv && screen_priv->ClipNotify) ;
 | |
| 
 | |
|     screen->ClipNotify = screen_priv->ClipNotify ;
 | |
|     if (screen->ClipNotify) {
 | |
|         (*screen->ClipNotify) (a_win, a_x, a_y) ;
 | |
|     }
 | |
|     screen->ClipNotify = ephyrDRIClipNotify ;
 | |
| 
 | |
|     EPHYR_LOG ("window: %#x\n", (unsigned int)a_win) ;
 | |
|     win_priv = GET_EPHYR_DRI_WINDOW_PRIV (a_win) ;
 | |
|     if (!win_priv) {
 | |
|         EPHYR_LOG ("not a DRI peered window\n") ;
 | |
|         is_ok = TRUE ;
 | |
|         goto out ;
 | |
|     }
 | |
|     if (!findWindowPairFromLocal (a_win, &pair) || !pair) {
 | |
|         EPHYR_LOG_ERROR ("failed to get window pair\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     rects = xcalloc (REGION_NUM_RECTS (&a_win->clipList),
 | |
|                      sizeof (EphyrRect)) ;
 | |
|     for (i=0; i < REGION_NUM_RECTS (&a_win->clipList); i++) {
 | |
|         memmove (&rects[i],
 | |
|                  ®ION_RECTS (&a_win->clipList)[i],
 | |
|                  sizeof (EphyrRect)) ;
 | |
|         rects[i].x1 -= a_win->drawable.x;
 | |
|         rects[i].x2 -= a_win->drawable.x;
 | |
|         rects[i].y1 -= a_win->drawable.y;
 | |
|         rects[i].y2 -= a_win->drawable.y;
 | |
|     }
 | |
|     /*
 | |
|      * push the clipping region of this window
 | |
|      * to the peer window in the host
 | |
|      */
 | |
|     is_ok = hostx_set_window_bounding_rectangles
 | |
|                                 (pair->remote,
 | |
|                                  rects,
 | |
|                                  REGION_NUM_RECTS (&a_win->clipList)) ;
 | |
|     is_ok = TRUE ;
 | |
| 
 | |
| out:
 | |
|     if (rects) {
 | |
|         xfree (rects) ;
 | |
|         rects = NULL ;
 | |
|     }
 | |
|     EPHYR_LOG ("leave. is_ok:%d\n", is_ok) ;
 | |
|     /*do cleanup here*/
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Duplicates a visual of a_screen
 | |
|  * In screen a_screen, for depth a_depth, find a visual which
 | |
|  * bitsPerRGBValue and colormap size equal
 | |
|  * a_bits_per_rgb_values and a_colormap_entries.
 | |
|  * The ID of that duplicated visual is set to a_new_id.
 | |
|  * That duplicated visual is then added to the list of visuals
 | |
|  * of the screen.
 | |
|  */
 | |
| static Bool
 | |
| EphyrDuplicateVisual (unsigned int a_screen,
 | |
|                       short a_depth,
 | |
|                       short a_class,
 | |
|                       short a_bits_per_rgb_values,
 | |
|                       short a_colormap_entries,
 | |
|                       unsigned int a_red_mask,
 | |
|                       unsigned int a_green_mask,
 | |
|                       unsigned int a_blue_mask,
 | |
|                       unsigned int a_new_id)
 | |
| {
 | |
|     Bool is_ok = FALSE, found_visual=FALSE, found_depth=FALSE ;
 | |
|     ScreenPtr screen=NULL ;
 | |
|     VisualRec new_visual, *new_visuals=NULL ;
 | |
|     int i=0 ;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ; 
 | |
|     if (a_screen > screenInfo.numScreens) {
 | |
|         EPHYR_LOG_ERROR ("bad screen number\n") ;
 | |
|         goto out;
 | |
|     }
 | |
|     memset (&new_visual, 0, sizeof (VisualRec)) ;
 | |
| 
 | |
|     /*get the screen pointed to by a_screen*/
 | |
|     screen = screenInfo.screens[a_screen] ;
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (screen, FALSE) ;
 | |
| 
 | |
|     /*
 | |
|      * In that screen, first look for an existing visual that has the
 | |
|      * same characteristics as those passed in parameter
 | |
|      * to this function and copy it.
 | |
|      */
 | |
|     for (i=0; i < screen->numVisuals; i++) {
 | |
|         if (screen->visuals[i].bitsPerRGBValue == a_bits_per_rgb_values &&
 | |
|             screen->visuals[i].ColormapEntries == a_colormap_entries ) {
 | |
|             /*copy the visual found*/
 | |
|             memcpy (&new_visual, &screen->visuals[i], sizeof (new_visual)) ;
 | |
|             new_visual.vid = a_new_id ;
 | |
|             new_visual.class = a_class ;
 | |
|             new_visual.redMask = a_red_mask ;
 | |
|             new_visual.greenMask = a_green_mask ;
 | |
|             new_visual.blueMask = a_blue_mask ;
 | |
|             found_visual = TRUE ;
 | |
|             EPHYR_LOG ("found a visual that matches visual id: %d\n",
 | |
|                        a_new_id) ;
 | |
|             break;
 | |
|         }
 | |
|     }
 | |
|     if (!found_visual) {
 | |
|         EPHYR_LOG ("did not find any visual matching %d\n", a_new_id) ;
 | |
|         goto out ;
 | |
|     }
 | |
|     /*
 | |
|      * be prepare to extend screen->visuals to add new_visual to it
 | |
|      */
 | |
|     new_visuals = xcalloc (screen->numVisuals+1, sizeof (VisualRec)) ;
 | |
|     memmove (new_visuals,
 | |
|              screen->visuals,
 | |
|              screen->numVisuals*sizeof (VisualRec)) ;
 | |
|     memmove (&new_visuals[screen->numVisuals],
 | |
|              &new_visual,
 | |
|              sizeof (VisualRec)) ;
 | |
|     /*
 | |
|      * Now, in that same screen, update the screen->allowedDepths member.
 | |
|      * In that array, each element represents the visuals applicable to
 | |
|      * a given depth. So we need to add an entry matching the new visual
 | |
|      * that we are going to add to screen->visuals
 | |
|      */
 | |
|     for (i=0; i<screen->numDepths; i++) {
 | |
|         VisualID *vids=NULL;
 | |
|         DepthPtr cur_depth=NULL ;
 | |
|         /*find the entry matching a_depth*/
 | |
|         if (screen->allowedDepths[i].depth != a_depth)
 | |
|             continue ;
 | |
|         cur_depth = &screen->allowedDepths[i];
 | |
|         /*
 | |
|          * extend the list of visual IDs in that entry,
 | |
|          * so to add a_new_id in there.
 | |
|          */
 | |
|         vids = xrealloc (cur_depth->vids,
 | |
|                          (cur_depth->numVids+1)*sizeof (VisualID));
 | |
|         if (!vids) {
 | |
|             EPHYR_LOG_ERROR ("failed to realloc numids\n") ;
 | |
|             goto out ;
 | |
|         }
 | |
|         vids[cur_depth->numVids] = a_new_id ;
 | |
|         /*
 | |
|          * Okay now commit our change.
 | |
|          * Do really update screen->allowedDepths[i]
 | |
|          */
 | |
|         cur_depth->numVids++ ;
 | |
|         cur_depth->vids = vids ;
 | |
|         found_depth=TRUE;
 | |
|     }
 | |
|     if (!found_depth) {
 | |
|         EPHYR_LOG_ERROR ("failed to update screen[%d]->allowedDepth\n",
 | |
|                          a_screen) ;
 | |
|         goto out ;
 | |
|     }
 | |
|     /*
 | |
|      * Commit our change to screen->visuals
 | |
|      */
 | |
|     xfree (screen->visuals) ;
 | |
|     screen->visuals = new_visuals ;
 | |
|     screen->numVisuals++ ;
 | |
|     new_visuals = NULL ;
 | |
| 
 | |
|     is_ok = TRUE ;
 | |
| out:
 | |
|     if (new_visuals) {
 | |
|         xfree (new_visuals) ;
 | |
|         new_visuals = NULL ;
 | |
|     }
 | |
|     EPHYR_LOG ("leave\n") ; 
 | |
|     return is_ok ;
 | |
| }
 | |
| 
 | |
| /**
 | |
|  * Duplicates the visuals of the host X server.
 | |
|  * This is necessary to have visuals that have the same
 | |
|  * ID as those of the host X. It is important to have that for
 | |
|  * GLX.
 | |
|  */
 | |
| static Bool
 | |
| EphyrMirrorHostVisuals (ScreenPtr a_screen)
 | |
| {
 | |
|     Bool is_ok=FALSE;
 | |
|     EphyrHostVisualInfo  *visuals=NULL;
 | |
|     int nb_visuals=0, i=0;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     if (!hostx_get_visuals_info (&visuals, &nb_visuals)) {
 | |
|         EPHYR_LOG_ERROR ("failed to get host visuals\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     for (i=0; i<nb_visuals; i++) {
 | |
|         if (!EphyrDuplicateVisual (a_screen->myNum,
 | |
|                                    visuals[i].depth,
 | |
|                                    visuals[i].class,
 | |
|                                    visuals[i].bits_per_rgb,
 | |
|                                    visuals[i].colormap_size,
 | |
|                                    visuals[i].red_mask,
 | |
|                                    visuals[i].green_mask,
 | |
|                                    visuals[i].blue_mask,
 | |
|                                    visuals[i].visualid)) {
 | |
|             EPHYR_LOG_ERROR ("failed to duplicate host visual %d\n",
 | |
|                              (int)visuals[i].visualid) ;
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     is_ok = TRUE ;
 | |
| out:
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return is_ok;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| static void
 | |
| XF86DRIResetProc (
 | |
|     ExtensionEntry* extEntry
 | |
| )
 | |
| {
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRIQueryVersion (register ClientPtr client)
 | |
| {
 | |
|     xXF86DRIQueryVersionReply rep;
 | |
|     register int n;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq);
 | |
|     rep.type = X_Reply;
 | |
|     rep.length = 0;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
|     rep.majorVersion = XF86DRI_MAJOR_VERSION;
 | |
|     rep.minorVersion = XF86DRI_MINOR_VERSION;
 | |
|     rep.patchVersion = XF86DRI_PATCH_VERSION;
 | |
|     if (client->swapped) {
 | |
|     	swaps(&rep.sequenceNumber, n);
 | |
|     	swapl(&rep.length, n);
 | |
| 	swaps(&rep.majorVersion, n);
 | |
| 	swaps(&rep.minorVersion, n);
 | |
| 	swapl(&rep.patchVersion, n);
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xXF86DRIQueryVersionReply), (char *)&rep);
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client)
 | |
| {
 | |
|     xXF86DRIQueryDirectRenderingCapableReply	rep;
 | |
|     Bool isCapable;
 | |
|     register int n;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
 | |
|     REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq);
 | |
|     if (stuff->screen >= screenInfo.numScreens) {
 | |
| 	client->errorValue = stuff->screen;
 | |
| 	return BadValue;
 | |
|     }
 | |
| 
 | |
|     rep.type = X_Reply;
 | |
|     rep.length = 0;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
| 
 | |
|     if (!ephyrDRIQueryDirectRenderingCapable (stuff->screen, &isCapable)) {
 | |
|         return BadValue;
 | |
|     }
 | |
|     rep.isCapable = isCapable;
 | |
| 
 | |
|     if (!LocalClient(client) || client->swapped)
 | |
| 	rep.isCapable = 0;
 | |
| 
 | |
|     if (client->swapped) {
 | |
|     	swaps(&rep.sequenceNumber, n);
 | |
|     	swapl(&rep.length, n);
 | |
|     }
 | |
| 
 | |
|     WriteToClient(client, sizeof(xXF86DRIQueryDirectRenderingCapableReply), (char *)&rep);
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
| 
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRIOpenConnection (register ClientPtr client)
 | |
| {
 | |
|     xXF86DRIOpenConnectionReply rep;
 | |
|     drm_handle_t			hSAREA;
 | |
|     char*			busIdString;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     REQUEST(xXF86DRIOpenConnectionReq);
 | |
|     REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq);
 | |
|     if (stuff->screen >= screenInfo.numScreens) {
 | |
| 	client->errorValue = stuff->screen;
 | |
| 	return BadValue;
 | |
|     }
 | |
| 
 | |
|     if (!ephyrDRIOpenConnection(stuff->screen,
 | |
|                                 &hSAREA,
 | |
|                                 &busIdString)) {
 | |
|         return BadValue;
 | |
|     }
 | |
| 
 | |
|     rep.type = X_Reply;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
|     rep.busIdStringLength = 0;
 | |
|     if (busIdString)
 | |
| 	rep.busIdStringLength = strlen(busIdString);
 | |
|     rep.length = (SIZEOF(xXF86DRIOpenConnectionReply) - SIZEOF(xGenericReply) +
 | |
|                   ((rep.busIdStringLength + 3) & ~3)) >> 2;
 | |
| 
 | |
|     rep.hSAREALow  = (CARD32)(hSAREA & 0xffffffff);
 | |
| #if defined(LONG64) && !defined(__linux__)
 | |
|     rep.hSAREAHigh = (CARD32)(hSAREA >> 32);
 | |
| #else
 | |
|     rep.hSAREAHigh = 0;
 | |
| #endif
 | |
| 
 | |
|     WriteToClient(client, sizeof(xXF86DRIOpenConnectionReply), (char *)&rep);
 | |
|     if (rep.busIdStringLength)
 | |
|         WriteToClient(client, rep.busIdStringLength, busIdString);
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRIAuthConnection  (register ClientPtr client)
 | |
| {
 | |
|     xXF86DRIAuthConnectionReply rep;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     REQUEST(xXF86DRIAuthConnectionReq);
 | |
|     REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq);
 | |
|     if (stuff->screen >= screenInfo.numScreens) {
 | |
| 	client->errorValue = stuff->screen;
 | |
| 	return BadValue;
 | |
|     }
 | |
| 
 | |
|     rep.type = X_Reply;
 | |
|     rep.length = 0;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
|     rep.authenticated = 1;
 | |
| 
 | |
|     if (!ephyrDRIAuthConnection (stuff->screen, stuff->magic)) {
 | |
|         ErrorF("Failed to authenticate %lu\n", (unsigned long)stuff->magic);
 | |
|         rep.authenticated = 0;
 | |
|     }
 | |
|     WriteToClient(client, sizeof(xXF86DRIAuthConnectionReply), (char *)&rep);
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRICloseConnection (register ClientPtr client)
 | |
| {
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     REQUEST(xXF86DRICloseConnectionReq);
 | |
|     REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq);
 | |
|     if (stuff->screen >= screenInfo.numScreens) {
 | |
|         client->errorValue = stuff->screen;
 | |
|         return BadValue;
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|     DRICloseConnection( screenInfo.screens[stuff->screen]);
 | |
|     */
 | |
| 
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRIGetClientDriverName (register ClientPtr client)
 | |
| {
 | |
|     xXF86DRIGetClientDriverNameReply	rep;
 | |
|     char* clientDriverName;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     REQUEST(xXF86DRIGetClientDriverNameReq);
 | |
|     REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq);
 | |
|     if (stuff->screen >= screenInfo.numScreens) {
 | |
| 	client->errorValue = stuff->screen;
 | |
| 	return BadValue;
 | |
|     }
 | |
| 
 | |
|     ephyrDRIGetClientDriverName (stuff->screen,
 | |
|                                  (int *)&rep.ddxDriverMajorVersion,
 | |
|                                  (int *)&rep.ddxDriverMinorVersion,
 | |
|                                  (int *)&rep.ddxDriverPatchVersion,
 | |
|                                  &clientDriverName);
 | |
| 
 | |
|     rep.type = X_Reply;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
|     rep.clientDriverNameLength = 0;
 | |
|     if (clientDriverName)
 | |
| 	rep.clientDriverNameLength = strlen(clientDriverName);
 | |
|     rep.length = (SIZEOF(xXF86DRIGetClientDriverNameReply) - 
 | |
| 			SIZEOF(xGenericReply) +
 | |
| 			((rep.clientDriverNameLength + 3) & ~3)) >> 2;
 | |
| 
 | |
|     WriteToClient(client, 
 | |
| 	sizeof(xXF86DRIGetClientDriverNameReply), (char *)&rep);
 | |
|     if (rep.clientDriverNameLength)
 | |
| 	WriteToClient(client, 
 | |
|                       rep.clientDriverNameLength, 
 | |
|                       clientDriverName);
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRICreateContext (register ClientPtr client)
 | |
| {
 | |
|     xXF86DRICreateContextReply	rep;
 | |
|     ScreenPtr pScreen;
 | |
|     VisualPtr visual;
 | |
|     int i=0;
 | |
|     unsigned long context_id=0;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     REQUEST(xXF86DRICreateContextReq);
 | |
|     REQUEST_SIZE_MATCH(xXF86DRICreateContextReq);
 | |
|     if (stuff->screen >= screenInfo.numScreens) {
 | |
| 	client->errorValue = stuff->screen;
 | |
| 	return BadValue;
 | |
|     }
 | |
| 
 | |
|     rep.type = X_Reply;
 | |
|     rep.length = 0;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
| 
 | |
|     pScreen = screenInfo.screens[stuff->screen];
 | |
|     visual = pScreen->visuals;
 | |
| 
 | |
|     /* Find the requested X visual */
 | |
|     for (i = 0; i < pScreen->numVisuals; i++, visual++)
 | |
| 	if (visual->vid == stuff->visual)
 | |
| 	    break;
 | |
|     if (i == pScreen->numVisuals) {
 | |
| 	/* No visual found */
 | |
| 	return BadValue;
 | |
|     }
 | |
| 
 | |
|     context_id = stuff->context ;
 | |
|     if (!ephyrDRICreateContext (stuff->screen,
 | |
|                                 stuff->visual,
 | |
|                                 &context_id,
 | |
|                                 (drm_context_t *)&rep.hHWContext)) {
 | |
|         return BadValue;
 | |
|     }
 | |
| 
 | |
|     WriteToClient(client, sizeof(xXF86DRICreateContextReply), (char *)&rep);
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRIDestroyContext (register ClientPtr client)
 | |
| {
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
| 
 | |
|     REQUEST(xXF86DRIDestroyContextReq);
 | |
|     REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq);
 | |
|     if (stuff->screen >= screenInfo.numScreens) {
 | |
|         client->errorValue = stuff->screen;
 | |
|         return BadValue;
 | |
|     }
 | |
| 
 | |
|    if (!ephyrDRIDestroyContext (stuff->screen, stuff->context)) {
 | |
|        return BadValue;
 | |
|    }
 | |
| 
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| getWindowVisual (const WindowPtr a_win,
 | |
|                  VisualPtr *a_visual)
 | |
| {
 | |
|     int i=0, visual_id=0 ;
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (a_win
 | |
|                               && a_win->drawable.pScreen
 | |
|                               && a_win->drawable.pScreen->visuals,
 | |
|                               FALSE) ;
 | |
| 
 | |
|     visual_id = wVisual (a_win) ;
 | |
|     for (i=0; i < a_win->drawable.pScreen->numVisuals; i++) {
 | |
|         if (a_win->drawable.pScreen->visuals[i].vid == visual_id) {
 | |
|             *a_visual = &a_win->drawable.pScreen->visuals[i] ;
 | |
|             return TRUE ;
 | |
|         }
 | |
|     }
 | |
|     return FALSE ;
 | |
| }
 | |
| 
 | |
| 
 | |
| #define NUM_WINDOW_PAIRS 256
 | |
| static EphyrWindowPair window_pairs[NUM_WINDOW_PAIRS] ;
 | |
| 
 | |
| static Bool
 | |
| appendWindowPairToList (WindowPtr a_local,
 | |
|                         int a_remote)
 | |
| {
 | |
|     int i=0 ;
 | |
| 
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (a_local, FALSE) ;
 | |
| 
 | |
|     EPHYR_LOG ("(local,remote):(%#x, %d)\n", (unsigned int)a_local, a_remote) ;
 | |
| 
 | |
|     for (i=0; i < NUM_WINDOW_PAIRS; i++) {
 | |
|         if (window_pairs[i].local == NULL) {
 | |
|             window_pairs[i].local = a_local ;
 | |
|             window_pairs[i].remote = a_remote ;
 | |
|             return TRUE ;
 | |
|         }
 | |
|     }
 | |
|     return FALSE ;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| findWindowPairFromLocal (WindowPtr a_local,
 | |
|                          EphyrWindowPair **a_pair)
 | |
| {
 | |
|     int i=0 ;
 | |
| 
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (a_pair && a_local, FALSE) ;
 | |
| 
 | |
|     for (i=0; i < NUM_WINDOW_PAIRS; i++) {
 | |
|         if (window_pairs[i].local == a_local) {
 | |
|             *a_pair = &window_pairs[i] ;
 | |
|             EPHYR_LOG ("found (%#x, %d)\n",
 | |
|                        (unsigned int)(*a_pair)->local,
 | |
|                        (*a_pair)->remote) ;
 | |
|             return TRUE ;
 | |
|         }
 | |
|     }
 | |
|     return FALSE ;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| createHostPeerWindow (const WindowPtr a_win,
 | |
|                       int *a_peer_win)
 | |
| {
 | |
|     Bool is_ok=FALSE ;
 | |
|     VisualPtr visual=NULL;
 | |
|     EphyrBox geo ;
 | |
| 
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (a_win && a_peer_win, FALSE) ;
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (a_win->drawable.pScreen,
 | |
|                               FALSE) ;
 | |
| 
 | |
|     EPHYR_LOG ("enter. a_win '%#x'\n", (unsigned int)a_win) ;
 | |
|     if (!getWindowVisual (a_win, &visual)) {
 | |
|         EPHYR_LOG_ERROR ("failed to get window visual\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     if (!visual) {
 | |
|         EPHYR_LOG_ERROR ("failed to create visual\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     memset (&geo, 0, sizeof (geo)) ;
 | |
|     geo.x = a_win->drawable.x ;
 | |
|     geo.y = a_win->drawable.y ;
 | |
|     geo.width = a_win->drawable.width ;
 | |
|     geo.height = a_win->drawable.height ;
 | |
|     if (!hostx_create_window (a_win->drawable.pScreen->myNum,
 | |
|                               &geo, visual->vid, a_peer_win)) {
 | |
|         EPHYR_LOG_ERROR ("failed to create host peer window\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     if (!appendWindowPairToList (a_win, *a_peer_win)) {
 | |
|         EPHYR_LOG_ERROR ("failed to append window to pair list\n") ;
 | |
|         goto out ;
 | |
|     }
 | |
|     is_ok = TRUE ;
 | |
| out:
 | |
|     EPHYR_LOG ("leave:remote win%d\n", *a_peer_win) ;
 | |
|     return is_ok ;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| destroyHostPeerWindow (const WindowPtr a_win)
 | |
| {
 | |
|     Bool is_ok = FALSE ;
 | |
|     EphyrWindowPair *pair=NULL ;
 | |
|     EPHYR_RETURN_VAL_IF_FAIL (a_win, FALSE) ;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
| 
 | |
|     if (!findWindowPairFromLocal (a_win, &pair) || !pair) {
 | |
|         EPHYR_LOG_ERROR ("failed to find peer to local window\n") ;
 | |
|         goto out;
 | |
|     }
 | |
|     hostx_destroy_window (pair->remote) ;
 | |
|     is_ok = TRUE ;
 | |
| 
 | |
| out:
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return is_ok;
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRICreateDrawable (ClientPtr client)
 | |
| {
 | |
|     xXF86DRICreateDrawableReply	rep;
 | |
|     DrawablePtr drawable=NULL;
 | |
|     WindowPtr window=NULL ;
 | |
|     EphyrWindowPair *pair=NULL ;
 | |
|     EphyrDRIWindowPrivPtr win_priv=NULL;
 | |
|     int rc=0, remote_win=0;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     REQUEST(xXF86DRICreateDrawableReq);
 | |
|     REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq);
 | |
|     if (stuff->screen >= screenInfo.numScreens) {
 | |
|         client->errorValue = stuff->screen;
 | |
|         return BadValue;
 | |
|     }
 | |
| 
 | |
|     rep.type = X_Reply;
 | |
|     rep.length = 0;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
| 
 | |
|     rc = dixLookupDrawable (&drawable, stuff->drawable, client, 0,
 | |
|                             DixReadAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
|     if (drawable->type != DRAWABLE_WINDOW) {
 | |
|         EPHYR_LOG_ERROR ("non drawable windows are not yet supported\n") ;
 | |
|         return BadImplementation ;
 | |
|     }
 | |
|     EPHYR_LOG ("lookedup drawable %#x\n", (unsigned int)drawable) ;
 | |
|     window = (WindowPtr)drawable;
 | |
|     if (findWindowPairFromLocal (window, &pair) && pair) {
 | |
|         remote_win = pair->remote ;
 | |
|         EPHYR_LOG ("found window '%#x' paire with remote '%d'\n",
 | |
|                    (unsigned int)window, remote_win) ;
 | |
|     } else if (!createHostPeerWindow (window, &remote_win)) {
 | |
|         EPHYR_LOG_ERROR ("failed to create host peer window\n") ;
 | |
|         return BadAlloc ;
 | |
|     }
 | |
| 
 | |
|     if (!ephyrDRICreateDrawable (stuff->screen,
 | |
|                                  remote_win,
 | |
|                                  (drm_drawable_t *)&rep.hHWDrawable)) {
 | |
|         EPHYR_LOG_ERROR ("failed to create dri drawable\n") ;
 | |
|         return BadValue;
 | |
|     }
 | |
| 
 | |
|     win_priv = GET_EPHYR_DRI_WINDOW_PRIV (window) ;
 | |
|     if (!win_priv) {
 | |
|         win_priv = xcalloc (1, sizeof (EphyrDRIWindowPrivRec)) ;
 | |
|         if (!win_priv) {
 | |
|             EPHYR_LOG_ERROR ("failed to allocate window private\n") ;
 | |
|             return BadAlloc ;
 | |
|         }
 | |
|         window->devPrivates[ephyrDRIWindowIndex].ptr = win_priv ;
 | |
|         EPHYR_LOG ("paired window '%#x' with remote '%d'\n",
 | |
|                    (unsigned int)window, remote_win) ;
 | |
|     }
 | |
| 
 | |
|     WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep);
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRIDestroyDrawable (register ClientPtr client)
 | |
| {
 | |
|     REQUEST(xXF86DRIDestroyDrawableReq);
 | |
|     DrawablePtr drawable=NULL;
 | |
|     WindowPtr window=NULL;
 | |
|     EphyrWindowPair *pair=NULL;
 | |
|     REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq);
 | |
|     int rc=0;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     if (stuff->screen >= screenInfo.numScreens) {
 | |
|         client->errorValue = stuff->screen;
 | |
|         return BadValue;
 | |
|     }
 | |
| 
 | |
|     rc = dixLookupDrawable(&drawable,
 | |
|                            stuff->drawable,
 | |
|                            client,
 | |
|                            0,
 | |
|                            DixReadAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
|     if (drawable->type != DRAWABLE_WINDOW) {
 | |
|         EPHYR_LOG_ERROR ("non drawable windows are not yet supported\n") ;
 | |
|         return BadImplementation ;
 | |
|     }
 | |
|     window = (WindowPtr)drawable;
 | |
|     if (!findWindowPairFromLocal (window, &pair) && pair) {
 | |
|         EPHYR_LOG_ERROR ("failed to find pair window\n") ;
 | |
|         return BadImplementation;
 | |
|     }
 | |
|     if (!ephyrDRIDestroyDrawable(stuff->screen,
 | |
|                                  pair->remote/*drawable in host x*/)) {
 | |
|         EPHYR_LOG_ERROR ("failed to destroy dri drawable\n") ;
 | |
|         return BadImplementation;
 | |
|     }
 | |
|     pair->local=NULL ;
 | |
|     pair->remote=0;
 | |
| 
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRIGetDrawableInfo (register ClientPtr client)
 | |
| {
 | |
|     xXF86DRIGetDrawableInfoReply rep;
 | |
|     DrawablePtr drawable;
 | |
|     WindowPtr window=NULL;
 | |
|     EphyrWindowPair *pair=NULL;
 | |
|     int X=0, Y=0, W=0, H=0, backX=0, backY=0, rc=0, i=0;
 | |
|     drm_clip_rect_t *clipRects=NULL;
 | |
|     drm_clip_rect_t *backClipRects=NULL;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     memset (&rep, 0, sizeof (rep)) ;
 | |
|     REQUEST(xXF86DRIGetDrawableInfoReq);
 | |
|     REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq);
 | |
|     if (stuff->screen >= screenInfo.numScreens) {
 | |
|         client->errorValue = stuff->screen;
 | |
|         return BadValue;
 | |
|     }
 | |
| 
 | |
|     rep.type = X_Reply;
 | |
|     rep.length = 0;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
| 
 | |
|     rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0,
 | |
|                            DixReadAccess);
 | |
|     if (rc != Success || !drawable) {
 | |
|         EPHYR_LOG_ERROR ("could not get drawable\n") ;
 | |
|         return rc;
 | |
|     }
 | |
| 
 | |
|     if (drawable->type != DRAWABLE_WINDOW) {
 | |
|         EPHYR_LOG_ERROR ("non windows type drawables are not yes supported\n") ;
 | |
|         return BadImplementation ;
 | |
|     }
 | |
|     window = (WindowPtr)drawable ;
 | |
|     memset (&pair, 0, sizeof (pair)) ;
 | |
|     if (!findWindowPairFromLocal (window, &pair) || !pair) {
 | |
|         EPHYR_LOG_ERROR ("failed to find remote peer drawable\n") ;
 | |
|         return BadMatch ;
 | |
|     }
 | |
|     EPHYR_LOG ("clip list of xephyr gl drawable:\n") ;
 | |
|     for (i=0; i < REGION_NUM_RECTS (&window->clipList); i++) {
 | |
|         EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n",
 | |
|                    REGION_RECTS (&window->clipList)[i].x1,
 | |
|                    REGION_RECTS (&window->clipList)[i].y1,
 | |
|                    REGION_RECTS (&window->clipList)[i].x2,
 | |
|                    REGION_RECTS (&window->clipList)[i].y2) ;
 | |
|     }
 | |
| 
 | |
|     if (!ephyrDRIGetDrawableInfo (stuff->screen,
 | |
|                                   pair->remote/*the drawable in hostx*/,
 | |
|                                   (unsigned int*)&rep.drawableTableIndex,
 | |
|                                   (unsigned int*)&rep.drawableTableStamp,
 | |
|                                   (int*)&X,
 | |
|                                   (int*)&Y,
 | |
|                                   (int*)&W,
 | |
|                                   (int*)&H,
 | |
|                                   (int*)&rep.numClipRects,
 | |
|                                   &clipRects,
 | |
|                                   &backX,
 | |
|                                   &backY,
 | |
|                                   (int*)&rep.numBackClipRects,
 | |
|                                   &backClipRects)) {
 | |
|         return BadValue;
 | |
|     }
 | |
|     EPHYR_LOG ("num clip rects:%d, num back clip rects:%d\n",
 | |
|                (int)rep.numClipRects, (int)rep.numBackClipRects) ;
 | |
| 
 | |
|     rep.drawableX = X;
 | |
|     rep.drawableY = Y;
 | |
|     rep.drawableWidth = W;
 | |
|     rep.drawableHeight = H;
 | |
|     rep.length = (SIZEOF(xXF86DRIGetDrawableInfoReply) -
 | |
|                   SIZEOF(xGenericReply));
 | |
| 
 | |
|     rep.backX = backX;
 | |
|     rep.backY = backY;
 | |
| 
 | |
| 
 | |
|     if (rep.numClipRects) {
 | |
|         if (clipRects) {
 | |
|             ScreenPtr pScreen = screenInfo.screens[stuff->screen];
 | |
|             int i=0;
 | |
|             EPHYR_LOG ("clip list of host gl drawable:\n") ;
 | |
|             for (i = 0; i < rep.numClipRects; i++) {
 | |
|                 clipRects[i].x1 = max (clipRects[i].x1, 0);
 | |
|                 clipRects[i].y1 = max (clipRects[i].y1, 0);
 | |
|                 clipRects[i].x2 = min (clipRects[i].x2,
 | |
|                                        pScreen->width + clipRects[i].x1) ;
 | |
|                 clipRects[i].y2 = min (clipRects[i].y2,
 | |
|                                        pScreen->width + clipRects[i].y1) ;
 | |
| 
 | |
|                 EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n",
 | |
|                            clipRects[i].x1, clipRects[i].y1,
 | |
|                            clipRects[i].x2, clipRects[i].y2) ;
 | |
|             }
 | |
|         } else {
 | |
|             rep.numClipRects = 0;
 | |
|         }
 | |
|     } else {
 | |
|         EPHYR_LOG ("got zero host gl drawable clipping rects\n") ;
 | |
|     }
 | |
|     rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects;
 | |
|     backClipRects = clipRects ;
 | |
|     rep.numBackClipRects = rep.numClipRects ;
 | |
|     if (rep.numBackClipRects)
 | |
|         rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects;
 | |
|     EPHYR_LOG ("num host clip rects:%d\n", (int)rep.numClipRects) ;
 | |
|     EPHYR_LOG ("num host back clip rects:%d\n", (int)rep.numBackClipRects) ;
 | |
| 
 | |
|     rep.length = ((rep.length + 3) & ~3) >> 2;
 | |
| 
 | |
|     WriteToClient(client, sizeof(xXF86DRIGetDrawableInfoReply), (char *)&rep);
 | |
| 
 | |
|     if (rep.numClipRects) {
 | |
|         WriteToClient(client,
 | |
|                       sizeof(drm_clip_rect_t) * rep.numClipRects,
 | |
|                       (char *)clipRects);
 | |
|     }
 | |
| 
 | |
|     if (rep.numBackClipRects) {
 | |
|         WriteToClient(client,
 | |
|                       sizeof(drm_clip_rect_t) * rep.numBackClipRects,
 | |
|                       (char *)backClipRects);
 | |
|     }
 | |
|     if (clipRects) {
 | |
|         xfree(clipRects);
 | |
|         clipRects = NULL ;
 | |
|     }
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
| 
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRIGetDeviceInfo (register ClientPtr client)
 | |
| {
 | |
|     xXF86DRIGetDeviceInfoReply	rep;
 | |
|     drm_handle_t hFrameBuffer;
 | |
|     void *pDevPrivate;
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     REQUEST(xXF86DRIGetDeviceInfoReq);
 | |
|     REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq);
 | |
|     if (stuff->screen >= screenInfo.numScreens) {
 | |
|         client->errorValue = stuff->screen;
 | |
|         return BadValue;
 | |
|     }
 | |
| 
 | |
|     rep.type = X_Reply;
 | |
|     rep.length = 0;
 | |
|     rep.sequenceNumber = client->sequence;
 | |
| 
 | |
|     if (!ephyrDRIGetDeviceInfo (stuff->screen,
 | |
|                 &hFrameBuffer,
 | |
|                 (int*)&rep.framebufferOrigin,
 | |
|                 (int*)&rep.framebufferSize,
 | |
|                 (int*)&rep.framebufferStride,
 | |
|                 (int*)&rep.devPrivateSize,
 | |
|                 &pDevPrivate)) {
 | |
|         return BadValue;
 | |
|     }
 | |
| 
 | |
|     rep.hFrameBufferLow  = (CARD32)(hFrameBuffer & 0xffffffff);
 | |
| #if defined(LONG64) && !defined(__linux__)
 | |
|     rep.hFrameBufferHigh = (CARD32)(hFrameBuffer >> 32);
 | |
| #else
 | |
|     rep.hFrameBufferHigh = 0;
 | |
| #endif
 | |
| 
 | |
|     rep.length = 0;
 | |
|     if (rep.devPrivateSize) {
 | |
|         rep.length = (SIZEOF(xXF86DRIGetDeviceInfoReply) - 
 | |
|                 SIZEOF(xGenericReply) +
 | |
|                 ((rep.devPrivateSize + 3) & ~3)) >> 2;
 | |
|     }
 | |
| 
 | |
|     WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep);
 | |
|     if (rep.length) {
 | |
|         WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate);
 | |
|     }
 | |
|     EPHYR_LOG ("leave\n") ;
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| ProcXF86DRIDispatch (register ClientPtr	client)
 | |
| {
 | |
|     REQUEST(xReq);
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
| 
 | |
|     switch (stuff->data)
 | |
|     {
 | |
|         case X_XF86DRIQueryVersion: {
 | |
|                 EPHYR_LOG ("leave\n") ;
 | |
|                 return ProcXF86DRIQueryVersion(client);
 | |
|         }
 | |
|         case X_XF86DRIQueryDirectRenderingCapable: {
 | |
|                 EPHYR_LOG ("leave\n") ;
 | |
|                 return ProcXF86DRIQueryDirectRenderingCapable(client);
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     if (!LocalClient(client))
 | |
|         return DRIErrorBase + XF86DRIClientNotLocal;
 | |
| 
 | |
|     switch (stuff->data)
 | |
|     {
 | |
|         case X_XF86DRIOpenConnection: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return ProcXF86DRIOpenConnection(client);
 | |
|         }
 | |
|         case X_XF86DRICloseConnection: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return ProcXF86DRICloseConnection(client);
 | |
|         }
 | |
|         case X_XF86DRIGetClientDriverName: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return ProcXF86DRIGetClientDriverName(client);
 | |
|         }
 | |
|         case X_XF86DRICreateContext: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return ProcXF86DRICreateContext(client);
 | |
|         }
 | |
|         case X_XF86DRIDestroyContext: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return ProcXF86DRIDestroyContext(client);
 | |
|         }
 | |
|         case X_XF86DRICreateDrawable: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return ProcXF86DRICreateDrawable(client);
 | |
|         }
 | |
|         case X_XF86DRIDestroyDrawable: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return ProcXF86DRIDestroyDrawable(client);
 | |
|         }
 | |
|         case X_XF86DRIGetDrawableInfo: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return ProcXF86DRIGetDrawableInfo(client);
 | |
|         }
 | |
|         case X_XF86DRIGetDeviceInfo: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return ProcXF86DRIGetDeviceInfo(client);
 | |
|         }
 | |
|         case X_XF86DRIAuthConnection: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return ProcXF86DRIAuthConnection(client);
 | |
|         }
 | |
|             /* {Open,Close}FullScreen are deprecated now */
 | |
|         default: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return BadRequest;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcXF86DRIQueryVersion (register ClientPtr	client)
 | |
| {
 | |
|     register int n;
 | |
|     REQUEST(xXF86DRIQueryVersionReq);
 | |
|     swaps(&stuff->length, n);
 | |
|     return ProcXF86DRIQueryVersion(client);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client)
 | |
| {
 | |
|     register int n;
 | |
|     REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
 | |
|     swaps(&stuff->length, n);
 | |
|     swapl(&stuff->screen, n);
 | |
|     return ProcXF86DRIQueryDirectRenderingCapable(client);
 | |
| }
 | |
| 
 | |
| static int
 | |
| SProcXF86DRIDispatch (register ClientPtr client)
 | |
| {
 | |
|     REQUEST(xReq);
 | |
| 
 | |
|     EPHYR_LOG ("enter\n") ;
 | |
|     /*
 | |
|      * Only local clients are allowed DRI access, but remote clients still need
 | |
|      * these requests to find out cleanly.
 | |
|      */
 | |
|     switch (stuff->data)
 | |
|     {
 | |
|         case X_XF86DRIQueryVersion: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return SProcXF86DRIQueryVersion(client);
 | |
|         }
 | |
|         case X_XF86DRIQueryDirectRenderingCapable: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return SProcXF86DRIQueryDirectRenderingCapable(client);
 | |
|         }
 | |
|         default: {
 | |
|             EPHYR_LOG ("leave\n") ;
 | |
|             return DRIErrorBase + XF86DRIClientNotLocal;
 | |
|         }
 | |
|     }
 | |
| }
 | |
| 
 | |
| #endif /*XEPHYR_DRI*/
 |