1418 lines
42 KiB
C
1418 lines
42 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
|
|
|
|
#include <string.h>
|
|
|
|
#include <X11/X.h>
|
|
#include <X11/Xproto.h>
|
|
#define _XF86DRI_SERVER_
|
|
#include <X11/dri/xf86dri.h>
|
|
#include <X11/dri/xf86driproto.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"
|
|
#include "protocol-versions.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 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 DevPrivateKeyRec ephyrDRIWindowKeyRec;
|
|
#define ephyrDRIWindowKey (&ephyrDRIWindowKeyRec)
|
|
static DevPrivateKeyRec ephyrDRIScreenKeyRec;
|
|
#define ephyrDRIScreenKey (&ephyrDRIScreenKeyRec)
|
|
|
|
#define GET_EPHYR_DRI_WINDOW_PRIV(win) ((EphyrDRIWindowPrivPtr) \
|
|
dixLookupPrivate(&(win)->devPrivates, ephyrDRIWindowKey))
|
|
#define GET_EPHYR_DRI_SCREEN_PRIV(screen) ((EphyrDRIScreenPrivPtr) \
|
|
dixLookupPrivate(&(screen)->devPrivates, ephyrDRIScreenKey))
|
|
|
|
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:%p\n", 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) ;
|
|
free(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: %p\n", 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: %p\n", 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: %p\n", 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 = calloc(RegionNumRects (&a_win->clipList),
|
|
sizeof (EphyrRect)) ;
|
|
for (i=0; i < RegionNumRects (&a_win->clipList); i++) {
|
|
memmove (&rects[i],
|
|
&RegionRects (&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,
|
|
RegionNumRects (&a_win->clipList)) ;
|
|
is_ok = TRUE ;
|
|
|
|
out:
|
|
free(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 = calloc(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 = realloc(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
|
|
*/
|
|
free(screen->visuals) ;
|
|
screen->visuals = new_visuals ;
|
|
screen->numVisuals++ ;
|
|
new_visuals = NULL ;
|
|
|
|
is_ok = TRUE ;
|
|
out:
|
|
free(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;
|
|
}
|
|
|
|
|
|
static int
|
|
ProcXF86DRIQueryVersion (register ClientPtr client)
|
|
{
|
|
xXF86DRIQueryVersionReply rep;
|
|
register int n;
|
|
REQUEST_SIZE_MATCH(xXF86DRIQueryVersionReq);
|
|
|
|
EPHYR_LOG ("enter\n") ;
|
|
|
|
rep.type = X_Reply;
|
|
rep.length = 0;
|
|
rep.sequenceNumber = client->sequence;
|
|
rep.majorVersion = SERVER_XF86DRI_MAJOR_VERSION;
|
|
rep.minorVersion = SERVER_XF86DRI_MINOR_VERSION;
|
|
rep.patchVersion = SERVER_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 Success;
|
|
}
|
|
|
|
static int
|
|
ProcXF86DRIQueryDirectRenderingCapable (register ClientPtr client)
|
|
{
|
|
xXF86DRIQueryDirectRenderingCapableReply rep;
|
|
Bool isCapable;
|
|
register int n;
|
|
REQUEST(xXF86DRIQueryDirectRenderingCapableReq);
|
|
REQUEST_SIZE_MATCH(xXF86DRIQueryDirectRenderingCapableReq);
|
|
|
|
EPHYR_LOG ("enter\n") ;
|
|
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 Success;
|
|
}
|
|
|
|
static int
|
|
ProcXF86DRIOpenConnection (register ClientPtr client)
|
|
{
|
|
xXF86DRIOpenConnectionReply rep;
|
|
drm_handle_t hSAREA;
|
|
char* busIdString = NULL;
|
|
REQUEST(xXF86DRIOpenConnectionReq);
|
|
REQUEST_SIZE_MATCH(xXF86DRIOpenConnectionReq);
|
|
|
|
EPHYR_LOG ("enter\n") ;
|
|
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 = bytes_to_int32(SIZEOF(xXF86DRIOpenConnectionReply) - SIZEOF(xGenericReply) +
|
|
pad_to_int32(rep.busIdStringLength));
|
|
|
|
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);
|
|
free(busIdString);
|
|
EPHYR_LOG ("leave\n") ;
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXF86DRIAuthConnection (register ClientPtr client)
|
|
{
|
|
xXF86DRIAuthConnectionReply rep;
|
|
REQUEST(xXF86DRIAuthConnectionReq);
|
|
REQUEST_SIZE_MATCH(xXF86DRIAuthConnectionReq);
|
|
|
|
EPHYR_LOG ("enter\n") ;
|
|
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 Success;
|
|
}
|
|
|
|
static int
|
|
ProcXF86DRICloseConnection (register ClientPtr client)
|
|
{
|
|
REQUEST(xXF86DRICloseConnectionReq);
|
|
REQUEST_SIZE_MATCH(xXF86DRICloseConnectionReq);
|
|
EPHYR_LOG ("enter\n") ;
|
|
if (stuff->screen >= screenInfo.numScreens) {
|
|
client->errorValue = stuff->screen;
|
|
return BadValue;
|
|
}
|
|
|
|
/*
|
|
DRICloseConnection( screenInfo.screens[stuff->screen]);
|
|
*/
|
|
|
|
EPHYR_LOG ("leave\n") ;
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXF86DRIGetClientDriverName (register ClientPtr client)
|
|
{
|
|
xXF86DRIGetClientDriverNameReply rep;
|
|
char* clientDriverName;
|
|
REQUEST(xXF86DRIGetClientDriverNameReq);
|
|
REQUEST_SIZE_MATCH(xXF86DRIGetClientDriverNameReq);
|
|
|
|
EPHYR_LOG ("enter\n") ;
|
|
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 = bytes_to_int32(SIZEOF(xXF86DRIGetClientDriverNameReply) -
|
|
SIZEOF(xGenericReply) +
|
|
pad_to_int32(rep.clientDriverNameLength));
|
|
|
|
WriteToClient(client,
|
|
sizeof(xXF86DRIGetClientDriverNameReply), (char *)&rep);
|
|
if (rep.clientDriverNameLength)
|
|
WriteToClient(client,
|
|
rep.clientDriverNameLength,
|
|
clientDriverName);
|
|
EPHYR_LOG ("leave\n") ;
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXF86DRICreateContext (register ClientPtr client)
|
|
{
|
|
xXF86DRICreateContextReply rep;
|
|
ScreenPtr pScreen;
|
|
VisualPtr visual;
|
|
int i=0;
|
|
unsigned long context_id=0;
|
|
REQUEST(xXF86DRICreateContextReq);
|
|
REQUEST_SIZE_MATCH(xXF86DRICreateContextReq);
|
|
|
|
EPHYR_LOG ("enter\n") ;
|
|
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 Success;
|
|
}
|
|
|
|
static int
|
|
ProcXF86DRIDestroyContext (register ClientPtr client)
|
|
{
|
|
REQUEST(xXF86DRIDestroyContextReq);
|
|
REQUEST_SIZE_MATCH(xXF86DRIDestroyContextReq);
|
|
EPHYR_LOG ("enter\n") ;
|
|
|
|
if (stuff->screen >= screenInfo.numScreens) {
|
|
client->errorValue = stuff->screen;
|
|
return BadValue;
|
|
}
|
|
|
|
if (!ephyrDRIDestroyContext (stuff->screen, stuff->context)) {
|
|
return BadValue;
|
|
}
|
|
|
|
EPHYR_LOG ("leave\n") ;
|
|
return Success;
|
|
}
|
|
|
|
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):(%p, %d)\n", 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 (%p, %d)\n",
|
|
(*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 '%p'\n", 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;
|
|
REQUEST(xXF86DRICreateDrawableReq);
|
|
REQUEST_SIZE_MATCH(xXF86DRICreateDrawableReq);
|
|
|
|
EPHYR_LOG ("enter\n") ;
|
|
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 %p\n", drawable) ;
|
|
window = (WindowPtr)drawable;
|
|
if (findWindowPairFromLocal (window, &pair) && pair) {
|
|
remote_win = pair->remote ;
|
|
EPHYR_LOG ("found window '%p' paire with remote '%d'\n",
|
|
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 = calloc(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 '%p' with remote '%d'\n",
|
|
window, remote_win) ;
|
|
}
|
|
|
|
WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep);
|
|
EPHYR_LOG ("leave\n") ;
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXF86DRIDestroyDrawable (register ClientPtr client)
|
|
{
|
|
DrawablePtr drawable=NULL;
|
|
WindowPtr window=NULL;
|
|
EphyrWindowPair *pair=NULL;
|
|
int rc=0;
|
|
REQUEST(xXF86DRIDestroyDrawableReq);
|
|
REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq);
|
|
|
|
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 Success;
|
|
}
|
|
|
|
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;
|
|
REQUEST(xXF86DRIGetDrawableInfoReq);
|
|
REQUEST_SIZE_MATCH(xXF86DRIGetDrawableInfoReq);
|
|
|
|
EPHYR_LOG ("enter\n") ;
|
|
memset (&rep, 0, sizeof (rep)) ;
|
|
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 < RegionNumRects (&window->clipList); i++) {
|
|
EPHYR_LOG ("x1:%d, y1:%d, x2:%d, y2:%d\n",
|
|
RegionRects (&window->clipList)[i].x1,
|
|
RegionRects (&window->clipList)[i].y1,
|
|
RegionRects (&window->clipList)[i].x2,
|
|
RegionRects (&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 = bytes_to_int32(rep.length);
|
|
|
|
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);
|
|
}
|
|
free(clipRects);
|
|
clipRects = NULL ;
|
|
|
|
EPHYR_LOG ("leave\n") ;
|
|
|
|
return Success;
|
|
}
|
|
|
|
static int
|
|
ProcXF86DRIGetDeviceInfo (register ClientPtr client)
|
|
{
|
|
xXF86DRIGetDeviceInfoReply rep;
|
|
drm_handle_t hFrameBuffer;
|
|
void *pDevPrivate;
|
|
REQUEST(xXF86DRIGetDeviceInfoReq);
|
|
REQUEST_SIZE_MATCH(xXF86DRIGetDeviceInfoReq);
|
|
|
|
EPHYR_LOG ("enter\n") ;
|
|
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 = bytes_to_int32(SIZEOF(xXF86DRIGetDeviceInfoReply) -
|
|
SIZEOF(xGenericReply) +
|
|
pad_to_int32(rep.devPrivateSize));
|
|
}
|
|
|
|
WriteToClient(client, sizeof(xXF86DRIGetDeviceInfoReply), (char *)&rep);
|
|
if (rep.length) {
|
|
WriteToClient(client, rep.devPrivateSize, (char *)pDevPrivate);
|
|
}
|
|
EPHYR_LOG ("leave\n") ;
|
|
return Success;
|
|
}
|
|
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
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, "DRIEvents");
|
|
if (!EventType) {
|
|
EPHYR_LOG_ERROR ("failed to register DRI event resource type\n") ;
|
|
goto out ;
|
|
}
|
|
#endif
|
|
|
|
if ((extEntry = AddExtension(XF86DRINAME,
|
|
XF86DRINumberEvents,
|
|
XF86DRINumberErrors,
|
|
ProcXF86DRIDispatch,
|
|
SProcXF86DRIDispatch,
|
|
NULL,
|
|
StandardMinorOpcode))) {
|
|
DRIReqCode = (unsigned char)extEntry->base;
|
|
DRIErrorBase = extEntry->errorBase;
|
|
} else {
|
|
EPHYR_LOG_ERROR ("failed to register DRI extension\n") ;
|
|
goto out ;
|
|
}
|
|
if (!dixRegisterPrivateKey(&ephyrDRIScreenKeyRec, PRIVATE_SCREEN, 0))
|
|
goto out ;
|
|
if (!dixRegisterPrivateKey(&ephyrDRIWindowKeyRec, PRIVATE_WINDOW, 0))
|
|
goto out ;
|
|
screen_priv = calloc(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 ;
|
|
}
|