xserver-multidpi/hw/kdrive/ephyr/ephyrglxext.c
Dodji Seketeli 26da625055 proxy the glXGetFBConfigSGIX call
* hw/kdrive/ephyr/ephyrglxext.c:
	  (ephyrGLXGetFBConfigsSGIX): proxy the GLXGetFBConfigsSGIX call.
	  It is a vendor extension to get the visual configs as a list of
	  name/value pairs.
	  (ephyrHijackGLXExtension): hijack the VendorPriv_dispatch_info
	  dispatch table to register our implementation of GLXGetFBConfigsSGIX
	  (ephyrGLXGetFBConfigsSGIXReal): added this where the real
	   implementation of GLXGetFBConfigsSGIX is. It support bytes swapping.
	  (ephyrGLXGetFBConfigsSGIX,ephyrGLXGetFBConfigsSGIXSwap): these are
	  the dispatch entry points. They just call
	  ephyrGLXGetFBConfigsSGIXReal.
	* hw/kdrive/ephyr/ephyrhostglx.c,h: reorganize the proxies to get
	  visual params from the host so that they clearly support the different
	  methods of doing so.
2007-10-02 16:55:15 +02:00

382 lines
12 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 "GL/glx/glxserver.h"
#include "GL/glx/indirect_table.h"
#include "GL/glx/unpack.h"
#ifdef XEPHYR_DRI
#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);
Bool
ephyrHijackGLXExtension (void)
{
const void *(*dispatch_functions)[2];
EPHYR_LOG ("going to hijack some glx entry points ...\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 ;
/*
* 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") ;
if (props_buf) {
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") ;
if (props_buf) {
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 ;
int length=0 ;
EPHYR_LOG ("enter\n") ;
if (!ephyrHostGLXGetStringFromServer (req->screen,
req->name,
&server_string)) {
EPHYR_LOG_ERROR ("failed to query string from host\n") ;
goto out ;
}
EPHYR_LOG ("string: %s", server_string) ;
length= strlen (server_string) + 1;
reply.type = X_Reply ;
reply.sequenceNumber = client->sequence ;
reply.length = __GLX_PAD (length) >> 2 ;
reply.n = length ;
WriteToClient(client, sz_xGLXQueryServerStringReply, (char*)&reply);
WriteToClient(client, (int)length, server_string);
res = Success ;
out:
EPHYR_LOG ("leave\n") ;
if (server_string) {
xfree (server_string) ;
server_string = 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) ;
}
#endif /*XEPHYR_DRI*/