724 lines
		
	
	
		
			22 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			724 lines
		
	
	
		
			22 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.
 | |
|  *
 | |
|  * 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") ;
 | |
|     xfree (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") ;
 | |
|     xfree (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 = xcalloc (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") ;
 | |
|     xfree (server_string) ;
 | |
|     server_string = NULL;
 | |
| 
 | |
|     xfree (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) ;
 | |
| }
 |