xserver-multidpi/hw/kdrive/ephyr/ephyrdriext.c
Dodji Seketeli 4dd4be99df Xephyr: Make glxinfo work on the ATI R200 free driver.
* hw/kdrive/ephyr/ephyr.c:
	  (EphyrDuplicateVisual): when duplicating the
	  visual, copy the color component masks and the class
	  from the hostX
	  (EphyrMirrorHostVisuals): don't mix blue and green mask.
	* hw/kdrive/ephyr/ephyrdri.c: add more logs.
	  (ephyrDRICreateDrawable): actually implement this.
	  for the moment it creates a DRI drawable for the hostX window,
	  no matter what drawable this call was issued for.
	  (ephyrDRIGetDrawableInfo): actually implemented this.
	  for the moment the drawable info queried for its attrs is the
	  Xephyr main main window.
	* hw/kdrive/ephyr/ephyrdriext.c:
	  (ProcXF86DRIGetDrawableInfo): properly hook this dispatch
	  function to the ephyrDRIGetDrawableInfo() function.
	* hw/kdrive/ephyr/ephyrglxext.c: add a bunch of GLX implementation hooks
	  here. Hijack some of the xserver GLX hooks with them. Still need to
	  properly support byteswapped clients though.
	* hw/kdrive/ephyr/ephyrhostglx.c,h: actually implemented the protocol
	  level forwarding functions used by the GLX entr points in
	  ephyrglxext.c. Here as well, there are a bunch of them, but we are
	  far from having implemented all the GLX calls.
	* hw/kdrive/ephyr/hostx.c,h:
	  (hostx_get_window_attributes): added this new entry point
	  (hostx_allocate_resource_id_peer): added this to keep track of
	   resource IDs peers: one member of the peer is in Xephyr, the other
	   is in host X.
	  (hostx_get_resource_id_peer): ditto.
2007-10-02 16:55:16 +02:00

726 lines
21 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 "servermd.h"
#include "swaprep.h"
#include "ephyrdri.h"
#define _HAVE_XALLOC_DECLS
#include "ephyrlog.h"
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 unsigned char DRIReqCode = 0;
extern void ephyrDRIExtensionInit(void);
void
ephyrDRIExtensionInit(void)
{
ExtensionEntry* extEntry;
EPHYR_LOG ("enter\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;
}
EPHYR_LOG ("leave\n") ;
}
/*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;
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;
}
/*
if (!DRICreateContext( pScreen,
visual,
stuff->context,
(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 (!DRIDestroyContext( screenInfo.screens[stuff->screen],
stuff->context)) {
return BadValue;
}
*/
EPHYR_LOG ("leave\n") ;
return (client->noClientException);
}
static int
ProcXF86DRICreateDrawable (ClientPtr client)
{
xXF86DRICreateDrawableReply rep;
DrawablePtr pDrawable;
int rc;
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 (&pDrawable, stuff->drawable, client, 0,
DixReadAccess);
if (rc != Success)
return rc;
/*TODO: this cannot work. We must properly
* do the mapping between the xephyr drawable and
* the host drawable
*/
if (!ephyrDRICreateDrawable (stuff->screen,
0/*should be host drawableID*/,
(drm_drawable_t *)&rep.hHWDrawable)) {
return BadValue;
}
WriteToClient(client, sizeof(xXF86DRICreateDrawableReply), (char *)&rep);
EPHYR_LOG ("leave\n") ;
return (client->noClientException);
}
static int
ProcXF86DRIDestroyDrawable (register ClientPtr client)
{
REQUEST(xXF86DRIDestroyDrawableReq);
DrawablePtr pDrawable;
REQUEST_SIZE_MATCH(xXF86DRIDestroyDrawableReq);
int rc;
EPHYR_LOG ("enter\n") ;
if (stuff->screen >= screenInfo.numScreens) {
client->errorValue = stuff->screen;
return BadValue;
}
rc = dixLookupDrawable(&pDrawable,
stuff->drawable,
client,
0,
DixReadAccess);
if (rc != Success)
return rc;
if (!ephyrDRIDestroyDrawable(stuff->screen,
0/*should be drawable in host x*/)) {
return BadValue;
}
EPHYR_LOG ("leave\n") ;
return (client->noClientException);
}
static int
ProcXF86DRIGetDrawableInfo (register ClientPtr client)
{
xXF86DRIGetDrawableInfoReply rep;
DrawablePtr drawable;
int X, Y, W, H, backX, backY, rc;
drm_clip_rect_t * pClipRects, *pClippedRects;
drm_clip_rect_t * pBackClipRects;
EPHYR_LOG ("enter\n") ;
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;
/*TODO: this cannot work.
* We must properly do the mapping
* between xephyr drawable and the host drawable
*/
rc = dixLookupDrawable(&drawable, stuff->drawable, client, 0,
DixReadAccess);
if (rc != Success)
return rc;
if (!ephyrDRIGetDrawableInfo (stuff->screen,
drawable/*should be the drawable in hostx*/,
(unsigned int*)&rep.drawableTableIndex,
(unsigned int*)&rep.drawableTableStamp,
(int*)&X,
(int*)&Y,
(int*)&W,
(int*)&H,
(int*)&rep.numClipRects,
&pClipRects,
&backX,
&backY,
(int*)&rep.numBackClipRects,
&pBackClipRects)) {
return BadValue;
}
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.numBackClipRects)
rep.length += sizeof(drm_clip_rect_t) * rep.numBackClipRects;
pClippedRects = pClipRects;
if (rep.numClipRects) {
/* Clip cliprects to screen dimensions (redirected windows) */
pClippedRects = xalloc(rep.numClipRects * sizeof(drm_clip_rect_t));
if (pClippedRects) {
ScreenPtr pScreen = screenInfo.screens[stuff->screen];
int i, j;
for (i = 0, j = 0; i < rep.numClipRects; i++) {
pClippedRects[j].x1 = max(pClipRects[i].x1, 0);
pClippedRects[j].y1 = max(pClipRects[i].y1, 0);
pClippedRects[j].x2 = min(pClipRects[i].x2, pScreen->width);
pClippedRects[j].y2 = min(pClipRects[i].y2, pScreen->height);
if (pClippedRects[j].x1 < pClippedRects[j].x2 &&
pClippedRects[j].y1 < pClippedRects[j].y2) {
j++;
}
}
rep.numClipRects = j;
} else {
rep.numClipRects = 0;
}
rep.length += sizeof(drm_clip_rect_t) * rep.numClipRects;
}
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 *)pClippedRects);
xfree(pClippedRects);
}
if (rep.numBackClipRects) {
WriteToClient(client,
sizeof(drm_clip_rect_t) * rep.numBackClipRects,
(char *)pBackClipRects);
}
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*/