diff options
author | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
---|---|---|
committer | marha <marha@users.sourceforge.net> | 2009-06-28 22:07:26 +0000 |
commit | 3562e78743202e43aec8727005182a2558117eca (patch) | |
tree | 8f9113a77d12470c5c851a2a8e4cb02e89df7d43 /xorg-server/hw/kdrive/ephyr/ephyrdriext.c | |
download | vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.gz vcxsrv-3562e78743202e43aec8727005182a2558117eca.tar.bz2 vcxsrv-3562e78743202e43aec8727005182a2558117eca.zip |
Checked in the following released items:
xkeyboard-config-1.4.tar.gz
ttf-bitstream-vera-1.10.tar.gz
font-alias-1.0.1.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sun-misc-1.0.0.tar.gz
font-sony-misc-1.0.0.tar.gz
font-schumacher-misc-1.0.0.tar.gz
font-mutt-misc-1.0.0.tar.gz
font-misc-misc-1.0.0.tar.gz
font-misc-meltho-1.0.0.tar.gz
font-micro-misc-1.0.0.tar.gz
font-jis-misc-1.0.0.tar.gz
font-isas-misc-1.0.0.tar.gz
font-dec-misc-1.0.0.tar.gz
font-daewoo-misc-1.0.0.tar.gz
font-cursor-misc-1.0.0.tar.gz
font-arabic-misc-1.0.0.tar.gz
font-winitzki-cyrillic-1.0.0.tar.gz
font-misc-cyrillic-1.0.0.tar.gz
font-cronyx-cyrillic-1.0.0.tar.gz
font-screen-cyrillic-1.0.1.tar.gz
font-xfree86-type1-1.0.1.tar.gz
font-adobe-utopia-type1-1.0.1.tar.gz
font-ibm-type1-1.0.0.tar.gz
font-bitstream-type1-1.0.0.tar.gz
font-bitstream-speedo-1.0.0.tar.gz
font-bh-ttf-1.0.0.tar.gz
font-bh-type1-1.0.0.tar.gz
font-bitstream-100dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-100dpi-1.0.0.tar.gz
font-bh-100dpi-1.0.0.tar.gz
font-adobe-utopia-100dpi-1.0.1.tar.gz
font-adobe-100dpi-1.0.0.tar.gz
font-util-1.0.1.tar.gz
font-bitstream-75dpi-1.0.0.tar.gz
font-bh-lucidatypewriter-75dpi-1.0.0.tar.gz
font-adobe-utopia-75dpi-1.0.1.tar.gz
font-bh-75dpi-1.0.0.tar.gz
bdftopcf-1.0.1.tar.gz
font-adobe-75dpi-1.0.0.tar.gz
mkfontscale-1.0.6.tar.gz
openssl-0.9.8k.tar.gz
bigreqsproto-1.0.2.tar.gz
xtrans-1.2.2.tar.gz
resourceproto-1.0.2.tar.gz
inputproto-1.4.4.tar.gz
compositeproto-0.4.tar.gz
damageproto-1.1.0.tar.gz
zlib-1.2.3.tar.gz
xkbcomp-1.0.5.tar.gz
freetype-2.3.9.tar.gz
pthreads-w32-2-8-0-release.tar.gz
pixman-0.12.0.tar.gz
kbproto-1.0.3.tar.gz
evieext-1.0.2.tar.gz
fixesproto-4.0.tar.gz
recordproto-1.13.2.tar.gz
randrproto-1.2.2.tar.gz
scrnsaverproto-1.1.0.tar.gz
renderproto-0.9.3.tar.gz
xcmiscproto-1.1.2.tar.gz
fontsproto-2.0.2.tar.gz
xextproto-7.0.3.tar.gz
xproto-7.0.14.tar.gz
libXdmcp-1.0.2.tar.gz
libxkbfile-1.0.5.tar.gz
libfontenc-1.0.4.tar.gz
libXfont-1.3.4.tar.gz
libX11-1.1.5.tar.gz
libXau-1.0.4.tar.gz
libxcb-1.1.tar.gz
xorg-server-1.5.3.tar.gz
Diffstat (limited to 'xorg-server/hw/kdrive/ephyr/ephyrdriext.c')
-rw-r--r-- | xorg-server/hw/kdrive/ephyr/ephyrdriext.c | 1443 |
1 files changed, 1443 insertions, 0 deletions
diff --git a/xorg-server/hw/kdrive/ephyr/ephyrdriext.c b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c new file mode 100644 index 000000000..fafe56d1f --- /dev/null +++ b/xorg-server/hw/kdrive/ephyr/ephyrdriext.c @@ -0,0 +1,1443 @@ +/* + * 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 "privates.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 { + 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 DevPrivateKey ephyrDRIWindowKey = &ephyrDRIWindowKey; +static DevPrivateKey ephyrDRIScreenKey = &ephyrDRIScreenKey; + +#define GET_EPHYR_DRI_WINDOW_PRIV(win) ((EphyrDRIWindowPrivPtr) \ + dixLookupPrivate(&(win)->devPrivates, ephyrDRIWindowKey)) +#define GET_EPHYR_DRI_SCREEN_PRIV(screen) ((EphyrDRIScreenPrivPtr) \ + dixLookupPrivate(&(screen)->devPrivates, ephyrDRIScreenKey)) + + +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 ; + } + screen_priv = xcalloc (1, sizeof (EphyrDRIScreenPrivRec)) ; + if (!screen_priv) { + EPHYR_LOG_ERROR ("failed to allocate screen_priv\n") ; + goto out ; + } + dixSetPrivate(&a_screen->devPrivates, ephyrDRIScreenKey, screen_priv); + + if (!ephyrDRIScreenInit (a_screen)) { + EPHYR_LOG_ERROR ("ephyrDRIScreenInit() failed\n") ; + goto out ; + } + EphyrMirrorHostVisuals (a_screen) ; + 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) ; + + 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 ; + + 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) { + dixSetPrivate(&a_win->devPrivates, ephyrDRIWindowKey, 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) ; + dixSetPrivate(&a_win->devPrivates, ephyrDRIWindowKey, 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 ; +} + +Bool +findWindowPairFromRemote (int a_remote, + EphyrWindowPair **a_pair) +{ + int i=0 ; + + EPHYR_RETURN_VAL_IF_FAIL (a_pair, FALSE) ; + + for (i=0; i < NUM_WINDOW_PAIRS; i++) { + if (window_pairs[i].remote == a_remote) { + *a_pair = &window_pairs[i] ; + EPHYR_LOG ("found (%p, %d)\n", + (*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 ; + } + dixSetPrivate(&window->devPrivates, ephyrDRIWindowKey, 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*/ |