/* * 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. * * Authors: * Dodji Seketeli <dodji@openedhand.com> */ #ifdef HAVE_CONFIG_H #include <kdrive-config.h> #endif #include "extnsionst.h" #include "ephyrglxext.h" #include "ephyrhostglx.h" #define _HAVE_XALLOC_DECLS #include "ephyrlog.h" #include <GL/glxproto.h> #include "glx/glxserver.h" #include "glx/indirect_table.h" #include "glx/indirect_util.h" #include "glx/unpack.h" #include "hostx.h" #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif int ephyrGLXQueryVersion (__GLXclientState *cl, GLbyte *pc) ; int ephyrGLXQueryVersionSwap (__GLXclientState *cl, GLbyte *pc) ; int ephyrGLXGetVisualConfigs (__GLXclientState *cl, GLbyte *pc) ; int ephyrGLXGetVisualConfigsSwap (__GLXclientState *cl, GLbyte *pc) ; int ephyrGLXClientInfo(__GLXclientState *cl, GLbyte *pc) ; int ephyrGLXClientInfoSwap(__GLXclientState *cl, GLbyte *pc) ; int ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc); int ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc); int ephyrGLXCreateContext (__GLXclientState *a_cl, GLbyte *a_pc); int ephyrGLXCreateContextSwap (__GLXclientState *a_cl, GLbyte *a_pc); int ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) ; int ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) ; Bool ephyrHijackGLXExtension (void) { const void *(*dispatch_functions)[2]; if (!hostx_has_glx ()) { EPHYR_LOG ("host X does not have GLX\n") ; return FALSE ; } EPHYR_LOG ("host X does have GLX\n") ; if (!Single_dispatch_info.dispatch_functions) { EPHYR_LOG_ERROR ("could not get dispatch functions table\n") ; return FALSE ; } /* * hijack some single entry point dispatch functions */ dispatch_functions = Single_dispatch_info.dispatch_functions ; EPHYR_RETURN_VAL_IF_FAIL (dispatch_functions, FALSE) ; dispatch_functions[X_GLXQueryVersion][0] = ephyrGLXQueryVersion ; dispatch_functions[X_GLXQueryVersion][1] = ephyrGLXQueryVersionSwap ; dispatch_functions[X_GLXGetVisualConfigs][0] = ephyrGLXGetVisualConfigs ; dispatch_functions[X_GLXGetVisualConfigs][1] = ephyrGLXGetVisualConfigsSwap ; dispatch_functions[X_GLXClientInfo][0] = ephyrGLXClientInfo ; dispatch_functions[X_GLXClientInfo][1] = ephyrGLXClientInfoSwap ; dispatch_functions[X_GLXQueryServerString][0] = ephyrGLXQueryServerString ; dispatch_functions[X_GLXQueryServerString][1] = ephyrGLXQueryServerStringSwap ; dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext ; dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap ; dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext ; dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap ; dispatch_functions[X_GLXMakeCurrent][0] = ephyrGLXMakeCurrent ; dispatch_functions[X_GLXMakeCurrent][1] = ephyrGLXMakeCurrentSwap ; dispatch_functions[X_GLXIsDirect][0] = ephyrGLXIsDirect ; dispatch_functions[X_GLXIsDirect][1] = ephyrGLXIsDirectSwap ; dispatch_functions[73][0] = ephyrGLXGetString ; dispatch_functions[73][1] = ephyrGLXGetStringSwap ; dispatch_functions[61][0] = ephyrGLXGetIntegerv ; dispatch_functions[61][1] = ephyrGLXGetIntegervSwap ; /* * hijack some vendor priv entry point dispatch functions */ dispatch_functions = VendorPriv_dispatch_info.dispatch_functions ; dispatch_functions[92][0] = ephyrGLXGetFBConfigsSGIX; dispatch_functions[92][1] = ephyrGLXGetFBConfigsSGIXSwap; EPHYR_LOG ("hijacked glx entry points to forward requests to host X\n") ; return TRUE ; } /********************* * implementation of * hijacked GLX entry * points ********************/ int ephyrGLXQueryVersion(__GLXclientState *a_cl, GLbyte *a_pc) { ClientPtr client = a_cl->client; xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; xGLXQueryVersionReply reply; int major, minor; int res = BadImplementation ; EPHYR_LOG ("enter\n") ; major = req->majorVersion ; minor = req->minorVersion ; if (!ephyrHostGLXQueryVersion (&major, &minor)) { EPHYR_LOG_ERROR ("ephyrHostGLXQueryVersion() failed\n") ; goto out ; } EPHYR_LOG ("major:%d, minor:%d\n", major, minor); reply.majorVersion = major ; reply.minorVersion = minor ; reply.length = 0 ; reply.type = X_Reply ; reply.sequenceNumber = client->sequence ; if (client->swapped) { __glXSwapQueryVersionReply(client, &reply); } else { WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply); } res = Success ; out: EPHYR_LOG ("leave\n") ; return res; } int ephyrGLXQueryVersionSwap (__GLXclientState *a_cl, GLbyte *a_pc) { xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc; __GLX_DECLARE_SWAP_VARIABLES; __GLX_SWAP_SHORT (&req->length); __GLX_SWAP_INT (&req->majorVersion); __GLX_SWAP_INT (&req->minorVersion); return ephyrGLXQueryVersion (a_cl, a_pc) ; } static int ephyrGLXGetVisualConfigsReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) { xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) a_pc; ClientPtr client = a_cl->client; xGLXGetVisualConfigsReply reply; int32_t *props_buf=NULL, num_visuals=0, num_props=0, res=BadImplementation, i=0, props_per_visual_size=0, props_buf_size=0; __GLX_DECLARE_SWAP_VARIABLES; __GLX_DECLARE_SWAP_ARRAY_VARIABLES; EPHYR_LOG ("enter\n") ; if (!ephyrHostGLXGetVisualConfigs (req->screen, &num_visuals, &num_props, &props_buf_size, &props_buf)) { EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ; goto out ; } EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ; reply.numVisuals = num_visuals; reply.numProps = num_props; reply.length = (num_visuals *__GLX_SIZE_CARD32 * num_props) >> 2; reply.type = X_Reply; reply.sequenceNumber = client->sequence; if (a_do_swap) { __GLX_SWAP_SHORT(&reply.sequenceNumber); __GLX_SWAP_INT(&reply.length); __GLX_SWAP_INT(&reply.numVisuals); __GLX_SWAP_INT(&reply.numProps); __GLX_SWAP_INT_ARRAY (props_buf, num_props) ; } WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply); props_per_visual_size = props_buf_size/num_visuals ; for (i=0; i < num_visuals; i++) { WriteToClient (client, props_per_visual_size, (char*)props_buf +i*props_per_visual_size); } res = Success ; out: EPHYR_LOG ("leave\n") ; free(props_buf) ; props_buf = NULL ; return res ; } static int ephyrGLXGetFBConfigsSGIXReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) { xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *)a_pc; ClientPtr client = a_cl->client; xGLXGetVisualConfigsReply reply; int32_t *props_buf=NULL, num_visuals=0, num_props=0, res=BadImplementation, i=0, props_per_visual_size=0, props_buf_size=0; __GLX_DECLARE_SWAP_VARIABLES; __GLX_DECLARE_SWAP_ARRAY_VARIABLES; EPHYR_LOG ("enter\n") ; if (!ephyrHostGLXVendorPrivGetFBConfigsSGIX (req->screen, &num_visuals, &num_props, &props_buf_size, &props_buf)) { EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ; goto out ; } EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ; reply.numVisuals = num_visuals; reply.numProps = num_props; reply.length = props_buf_size >> 2; reply.type = X_Reply; reply.sequenceNumber = client->sequence; if (a_do_swap) { __GLX_SWAP_SHORT(&reply.sequenceNumber); __GLX_SWAP_INT(&reply.length); __GLX_SWAP_INT(&reply.numVisuals); __GLX_SWAP_INT(&reply.numProps); __GLX_SWAP_INT_ARRAY (props_buf, num_props) ; } WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply); props_per_visual_size = props_buf_size/num_visuals ; for (i=0; i < num_visuals; i++) { WriteToClient (client, props_per_visual_size, &((char*)props_buf)[i*props_per_visual_size]); } res = Success ; out: EPHYR_LOG ("leave\n") ; free(props_buf) ; props_buf = NULL ; return res ; } int ephyrGLXGetVisualConfigs (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, FALSE) ; } int ephyrGLXGetVisualConfigsSwap (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, TRUE) ; } int ephyrGLXClientInfo(__GLXclientState *a_cl, GLbyte *a_pc) { int res=BadImplementation ; xGLXClientInfoReq *req = (xGLXClientInfoReq *) a_pc; EPHYR_LOG ("enter\n") ; if (!ephyrHostGLXSendClientInfo (req->major, req->minor, (char*)req+1)) { EPHYR_LOG_ERROR ("failed to send client info to host\n") ; goto out ; } res = Success ; out: EPHYR_LOG ("leave\n") ; return res ; } int ephyrGLXClientInfoSwap (__GLXclientState *a_cl, GLbyte *a_pc) { xGLXClientInfoReq *req = (xGLXClientInfoReq *)a_pc; __GLX_DECLARE_SWAP_VARIABLES; __GLX_SWAP_SHORT (&req->length); __GLX_SWAP_INT (&req->major); __GLX_SWAP_INT (&req->minor); __GLX_SWAP_INT (&req->numbytes); return ephyrGLXClientInfo (a_cl, a_pc) ; } int ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) { int res = BadImplementation ; ClientPtr client = a_cl->client; xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) a_pc; xGLXQueryServerStringReply reply; char *server_string=NULL, *buf=NULL; int length=0 ; EPHYR_LOG ("enter\n") ; if (!ephyrHostGLXGetStringFromServer (req->screen, req->name, EPHYR_HOST_GLX_QueryServerString, &server_string)) { EPHYR_LOG_ERROR ("failed to query string from host\n") ; goto out ; } EPHYR_LOG ("string: %s\n", server_string) ; length= strlen (server_string) + 1; reply.type = X_Reply ; reply.sequenceNumber = client->sequence ; reply.length = __GLX_PAD (length) >> 2 ; reply.n = length ; buf = calloc(reply.length << 2, 1); if (!buf) { EPHYR_LOG_ERROR ("failed to allocate string\n;"); return BadAlloc; } memcpy (buf, server_string, length); WriteToClient(client, sz_xGLXQueryServerStringReply, (char*)&reply); WriteToClient(client, (int)(reply.length << 2), server_string); res = Success ; out: EPHYR_LOG ("leave\n") ; free(server_string) ; server_string = NULL; free(buf); buf = NULL; return res ; } int ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) { EPHYR_LOG_ERROR ("not yet implemented\n") ; return BadImplementation ; } int ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, FALSE) ; } int ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, TRUE) ; } static int ephyrGLXCreateContextReal (xGLXCreateContextReq *a_req, Bool a_do_swap) { int res=BadImplementation; EphyrHostWindowAttributes host_w_attrs ; __GLX_DECLARE_SWAP_VARIABLES; EPHYR_RETURN_VAL_IF_FAIL (a_req, BadValue) ; EPHYR_LOG ("enter\n") ; if (a_do_swap) { __GLX_SWAP_SHORT(&a_req->length); __GLX_SWAP_INT(&a_req->context); __GLX_SWAP_INT(&a_req->visual); __GLX_SWAP_INT(&a_req->screen); __GLX_SWAP_INT(&a_req->shareList); } EPHYR_LOG ("context creation requested. localid:%d, " "screen:%d, visual:%d, direct:%d\n", (int)a_req->context, (int)a_req->screen, (int)a_req->visual, (int)a_req->isDirect) ; memset (&host_w_attrs, 0, sizeof (host_w_attrs)) ; if (!hostx_get_window_attributes (hostx_get_window (a_req->screen), &host_w_attrs)) { EPHYR_LOG_ERROR ("failed to get host window attrs\n") ; goto out ; } EPHYR_LOG ("host window visual id: %d\n", host_w_attrs.visualid) ; if (!ephyrHostGLXCreateContext (a_req->screen, host_w_attrs.visualid, a_req->context, a_req->shareList, a_req->isDirect)) { EPHYR_LOG_ERROR ("ephyrHostGLXCreateContext() failed\n") ; goto out ; } res = Success; out: EPHYR_LOG ("leave\n") ; return res ; } int ephyrGLXCreateContext (__GLXclientState *cl, GLbyte *pc) { xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; return ephyrGLXCreateContextReal (req, FALSE) ; } int ephyrGLXCreateContextSwap (__GLXclientState *cl, GLbyte *pc) { xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc; return ephyrGLXCreateContextReal (req, TRUE) ; } static int ephyrGLXDestroyContextReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) { int res=BadImplementation; ClientPtr client = a_cl->client; xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) a_pc; EPHYR_LOG ("enter. id:%d\n", (int)req->context) ; if (!ephyrHostDestroyContext (req->context)) { EPHYR_LOG_ERROR ("ephyrHostDestroyContext() failed\n") ; client->errorValue = req->context ; goto out ; } res = Success ; out: EPHYR_LOG ("leave\n") ; return res ; } int ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXDestroyContextReal (a_cl, a_pc, FALSE) ; } int ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXDestroyContextReal (a_cl, a_pc, TRUE) ; } static int ephyrGLXMakeCurrentReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) { int res=BadImplementation; xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc; xGLXMakeCurrentReply reply ; DrawablePtr drawable=NULL; int rc=0; EPHYR_LOG ("enter\n") ; rc = dixLookupDrawable (&drawable, req->drawable, a_cl->client, 0, DixReadAccess); EPHYR_RETURN_VAL_IF_FAIL (drawable, BadValue) ; EPHYR_RETURN_VAL_IF_FAIL (drawable->pScreen, BadValue) ; EPHYR_LOG ("screen nummber requested:%d\n", drawable->pScreen->myNum) ; memset (&reply, 0, sizeof (reply)) ; if (!ephyrHostGLXMakeCurrent (hostx_get_window (drawable->pScreen->myNum), req->context, req->oldContextTag, (int*)&reply.contextTag)) { EPHYR_LOG_ERROR ("ephyrHostGLXMakeCurrent() failed\n") ; goto out; } reply.length = 0; reply.type = X_Reply; reply.sequenceNumber = a_cl->client->sequence; if (a_do_swap) { __GLX_DECLARE_SWAP_VARIABLES; __GLX_SWAP_SHORT(&reply.sequenceNumber); __GLX_SWAP_INT(&reply.length); __GLX_SWAP_INT(&reply.contextTag); } WriteToClient(a_cl->client, sz_xGLXMakeCurrentReply, (char *)&reply); res = Success ; out: EPHYR_LOG ("leave\n") ; return res ; } int ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXMakeCurrentReal (a_cl, a_pc, FALSE) ; } int ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXMakeCurrentReal (a_cl, a_pc, TRUE) ; } static int ephyrGLXGetStringReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) { ClientPtr client=NULL ; int context_tag=0, name=0, res=BadImplementation, length=0 ; char *string=NULL; __GLX_DECLARE_SWAP_VARIABLES; EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, BadValue) ; EPHYR_LOG ("enter\n") ; client = a_cl->client ; if (a_do_swap) { __GLX_SWAP_INT (a_pc + 4); __GLX_SWAP_INT (a_pc + __GLX_SINGLE_HDR_SIZE); } context_tag = __GLX_GET_SINGLE_CONTEXT_TAG (a_pc) ; a_pc += __GLX_SINGLE_HDR_SIZE; name = *(GLenum*)(a_pc + 0); EPHYR_LOG ("context_tag:%d, name:%d\n", context_tag, name) ; if (!ephyrHostGLXGetStringFromServer (context_tag, name, EPHYR_HOST_GLX_GetString, &string)) { EPHYR_LOG_ERROR ("failed to get string from server\n") ; goto out ; } if (string) { length = strlen (string) + 1; EPHYR_LOG ("got string:'%s', size:%d\n", string, length) ; } else { EPHYR_LOG ("got string: string (null)\n") ; } __GLX_BEGIN_REPLY (length); __GLX_PUT_SIZE (length); __GLX_SEND_HEADER (); if (a_do_swap) { __GLX_SWAP_REPLY_SIZE (); __GLX_SWAP_REPLY_HEADER (); } WriteToClient (client, length, (char *)string); res = Success ; out: EPHYR_LOG ("leave\n") ; return res ; } int ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXGetStringReal (a_cl, a_pc, FALSE) ; } int ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXGetStringReal (a_cl, a_pc, TRUE) ; } static int ephyrGLXGetIntegervReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) { int res=BadImplementation; xGLXSingleReq * const req = (xGLXSingleReq *) a_pc; GLenum int_name ; int value=0 ; GLint answer_buf_room[200]; GLint *buf=NULL ; EPHYR_LOG ("enter\n") ; a_pc += __GLX_SINGLE_HDR_SIZE; int_name = *(GLenum*) (a_pc+0) ; if (!ephyrHostGetIntegerValue (req->contextTag, int_name, &value)) { EPHYR_LOG_ERROR ("ephyrHostGetIntegerValue() failed\n") ; goto out ; } buf = __glXGetAnswerBuffer (a_cl, sizeof (value), answer_buf_room, sizeof (answer_buf_room), 4) ; if (!buf) { EPHYR_LOG_ERROR ("failed to allocate reply buffer\n") ; res = BadAlloc ; goto out ; } __glXSendReply (a_cl->client, buf, 1, sizeof (value), GL_FALSE, 0) ; res = Success ; out: EPHYR_LOG ("leave\n") ; return res ; } int ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXGetIntegervReal (a_cl, a_pc, FALSE) ; } int ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXGetIntegervReal (a_cl, a_pc, TRUE) ; } static int ephyrGLXIsDirectReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap) { int res=BadImplementation; ClientPtr client = a_cl->client; xGLXIsDirectReq *req = (xGLXIsDirectReq *) a_pc; xGLXIsDirectReply reply; int is_direct=0 ; EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, FALSE) ; EPHYR_LOG ("enter\n") ; memset (&reply, 0, sizeof (reply)) ; if (!ephyrHostIsContextDirect (req->context, (int*)&is_direct)) { EPHYR_LOG_ERROR ("ephyrHostIsContextDirect() failed\n") ; goto out ; } reply.isDirect = is_direct ; reply.length = 0; reply.type = X_Reply; reply.sequenceNumber = client->sequence; WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply); res = Success ; out: EPHYR_LOG ("leave\n") ; return res ; } int ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXIsDirectReal (a_cl, a_pc, FALSE) ; } int ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) { return ephyrGLXIsDirectReal (a_cl, a_pc, TRUE) ; }