3bbfe7b179
Tested by at least ajacoutot@, dcoppa@ & jasper@
855 lines
26 KiB
C
855 lines
26 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 <xcb/glx.h>
|
|
#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 ephyrGLXCreateNewContext(__GLXclientState * a_cl, GLbyte * a_pc);
|
|
int ephyrGLXCreateNewContextSwap(__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 ephyrGLXMakeCurrentReadSGI(__GLXclientState * a_cl, GLbyte * a_pc);
|
|
int ephyrGLXMakeCurrentReadSGISwap(__GLXclientState * a_cl, GLbyte * a_pc);
|
|
int ephyrGLXMakeContextCurrent(__GLXclientState * a_cl, GLbyte * a_pc);
|
|
int ephyrGLXMakeContextCurrentSwap(__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 (!host_has_extension(&xcb_glx_id)) {
|
|
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_GLXCreateNewContext][0] = ephyrGLXCreateNewContext;
|
|
dispatch_functions[X_GLXCreateNewContext][1] = ephyrGLXCreateNewContextSwap;
|
|
|
|
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;
|
|
|
|
dispatch_functions[X_GLXMakeContextCurrent][0] =
|
|
ephyrGLXMakeContextCurrent;
|
|
dispatch_functions[X_GLXMakeContextCurrent][1] =
|
|
ephyrGLXMakeContextCurrentSwap;
|
|
|
|
/*
|
|
* 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;
|
|
|
|
dispatch_functions[89][0] = ephyrGLXMakeCurrentReadSGI;
|
|
dispatch_functions[89][1] = ephyrGLXMakeCurrentReadSGISwap;
|
|
|
|
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 = (xGLXQueryVersionReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.length = 0,
|
|
.majorVersion = major,
|
|
.minorVersion = minor
|
|
};
|
|
|
|
if (client->swapped) {
|
|
__glXSwapQueryVersionReply(client, &reply);
|
|
}
|
|
else {
|
|
WriteToClient(client, sz_xGLXQueryVersionReply, &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 = (xGLXGetVisualConfigsReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.length = (num_visuals * __GLX_SIZE_CARD32 * num_props) >> 2,
|
|
.numVisuals = num_visuals,
|
|
.numProps = num_props
|
|
};
|
|
|
|
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, &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 = (xGLXGetVisualConfigsReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.length = props_buf_size >> 2,
|
|
.numVisuals = num_visuals,
|
|
.numProps = num_props
|
|
};
|
|
|
|
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, &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;
|
|
int length = 0;
|
|
|
|
EPHYR_LOG("enter\n");
|
|
if (!ephyrHostGLXQueryServerString(req->screen,
|
|
req->name,
|
|
&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 = (xGLXQueryServerStringReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.length = __GLX_PAD(length) >> 2,
|
|
.n = length
|
|
};
|
|
|
|
WriteToClient(client, sz_xGLXQueryServerStringReply, &reply);
|
|
WriteToClient(client, (int) (reply.length << 2), server_string);
|
|
|
|
res = Success;
|
|
|
|
out:
|
|
EPHYR_LOG("leave\n");
|
|
free(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);
|
|
}
|
|
|
|
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, 0,
|
|
a_req->isDirect, X_GLXCreateContext)) {
|
|
EPHYR_LOG_ERROR("ephyrHostGLXCreateContext() failed\n");
|
|
goto out;
|
|
}
|
|
res = Success;
|
|
out:
|
|
EPHYR_LOG("leave\n");
|
|
return res;
|
|
}
|
|
|
|
static int
|
|
ephyrGLXCreateNewContextReal(xGLXCreateNewContextReq * a_req, Bool a_do_swap)
|
|
{
|
|
int res = BadImplementation;
|
|
|
|
__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->fbconfig);
|
|
__GLX_SWAP_INT(&a_req->screen);
|
|
__GLX_SWAP_INT(&a_req->renderType);
|
|
__GLX_SWAP_INT(&a_req->shareList);
|
|
}
|
|
|
|
EPHYR_LOG("context creation requested. localid:%d, "
|
|
"screen:%d, fbconfig:%d, renderType:%d, direct:%d\n",
|
|
(int) a_req->context, (int) a_req->screen,
|
|
(int) a_req->fbconfig, (int) a_req->renderType,
|
|
(int) a_req->isDirect);
|
|
|
|
if (!ephyrHostGLXCreateContext(a_req->screen,
|
|
a_req->fbconfig,
|
|
a_req->context,
|
|
a_req->shareList, a_req->renderType,
|
|
a_req->isDirect, X_GLXCreateNewContext)) {
|
|
EPHYR_LOG_ERROR("ephyrHostGLXCreateNewContext() 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);
|
|
}
|
|
|
|
int
|
|
ephyrGLXCreateNewContext(__GLXclientState * cl, GLbyte * pc)
|
|
{
|
|
xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc;
|
|
|
|
return ephyrGLXCreateNewContextReal(req, FALSE);
|
|
}
|
|
|
|
int
|
|
ephyrGLXCreateNewContextSwap(__GLXclientState * cl, GLbyte * pc)
|
|
{
|
|
xGLXCreateNewContextReq *req = (xGLXCreateNewContextReq *) pc;
|
|
|
|
return ephyrGLXCreateNewContextReal(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, GLXDrawable write,
|
|
GLXDrawable read, GLXContextTag ctx,
|
|
GLXContextTag old_ctx, Bool a_do_swap)
|
|
{
|
|
int res = BadImplementation;
|
|
xGLXMakeCurrentReply reply;
|
|
DrawablePtr drawableR = NULL, drawableW = NULL;
|
|
GLXContextTag new_ctx = 0;
|
|
|
|
EPHYR_LOG("enter\n");
|
|
res = dixLookupDrawable(&drawableW, write, a_cl->client, 0, DixReadAccess);
|
|
EPHYR_RETURN_VAL_IF_FAIL(drawableW, BadValue);
|
|
EPHYR_RETURN_VAL_IF_FAIL(drawableW->pScreen, BadValue);
|
|
EPHYR_LOG("screen nummber requested:%d\n", drawableW->pScreen->myNum);
|
|
|
|
if (read != write) {
|
|
res = dixLookupDrawable(&drawableR, read, a_cl->client, 0,
|
|
DixReadAccess);
|
|
EPHYR_RETURN_VAL_IF_FAIL(drawableR, BadValue);
|
|
EPHYR_RETURN_VAL_IF_FAIL(drawableR->pScreen, BadValue);
|
|
}
|
|
else {
|
|
drawableR = drawableW;
|
|
}
|
|
|
|
if (!ephyrHostGLXMakeCurrent(hostx_get_window(drawableW->pScreen->myNum),
|
|
hostx_get_window(drawableR->pScreen->myNum),
|
|
ctx, old_ctx, (int *) &new_ctx)) {
|
|
EPHYR_LOG_ERROR("ephyrHostGLXMakeCurrent() failed\n");
|
|
goto out;
|
|
}
|
|
reply = (xGLXMakeCurrentReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = a_cl->client->sequence,
|
|
.length = 0,
|
|
.contextTag = new_ctx
|
|
};
|
|
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, &reply);
|
|
|
|
res = Success;
|
|
out:
|
|
EPHYR_LOG("leave\n");
|
|
return res;
|
|
}
|
|
|
|
int
|
|
ephyrGLXMakeCurrent(__GLXclientState * a_cl, GLbyte * a_pc)
|
|
{
|
|
xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc;
|
|
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->drawable,
|
|
req->context, req->oldContextTag, FALSE);
|
|
}
|
|
|
|
int
|
|
ephyrGLXMakeCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc)
|
|
{
|
|
xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc;
|
|
__GLX_DECLARE_SWAP_VARIABLES;
|
|
|
|
__GLX_SWAP_INT(&req->drawable);
|
|
__GLX_SWAP_INT(&req->context);
|
|
__GLX_SWAP_INT(&req->oldContextTag);
|
|
|
|
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->drawable,
|
|
req->context, req->oldContextTag, TRUE);
|
|
}
|
|
|
|
int
|
|
ephyrGLXMakeCurrentReadSGI(__GLXclientState * a_cl, GLbyte * a_pc)
|
|
{
|
|
xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) a_pc;
|
|
|
|
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readable,
|
|
req->context, req->oldContextTag, FALSE);
|
|
}
|
|
|
|
int
|
|
ephyrGLXMakeCurrentReadSGISwap(__GLXclientState * a_cl, GLbyte * a_pc)
|
|
{
|
|
xGLXMakeCurrentReadSGIReq *req = (xGLXMakeCurrentReadSGIReq *) a_pc;
|
|
__GLX_DECLARE_SWAP_VARIABLES;
|
|
|
|
__GLX_SWAP_INT(&req->drawable);
|
|
__GLX_SWAP_INT(&req->readable);
|
|
__GLX_SWAP_INT(&req->context);
|
|
__GLX_SWAP_INT(&req->oldContextTag);
|
|
|
|
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readable,
|
|
req->context, req->oldContextTag, TRUE);
|
|
}
|
|
|
|
int
|
|
ephyrGLXMakeContextCurrent(__GLXclientState * a_cl, GLbyte * a_pc)
|
|
{
|
|
xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) a_pc;
|
|
|
|
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readdrawable,
|
|
req->context, req->oldContextTag, FALSE);
|
|
}
|
|
|
|
int
|
|
ephyrGLXMakeContextCurrentSwap(__GLXclientState * a_cl, GLbyte * a_pc)
|
|
{
|
|
xGLXMakeContextCurrentReq *req = (xGLXMakeContextCurrentReq *) a_pc;
|
|
__GLX_DECLARE_SWAP_VARIABLES;
|
|
|
|
__GLX_SWAP_INT(&req->drawable);
|
|
__GLX_SWAP_INT(&req->readdrawable);
|
|
__GLX_SWAP_INT(&req->context);
|
|
__GLX_SWAP_INT(&req->oldContextTag);
|
|
|
|
return ephyrGLXMakeCurrentReal(a_cl, req->drawable, req->readdrawable,
|
|
req->context, req->oldContextTag, 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 (!ephyrHostGLXGetString(context_tag, name, &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, 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");
|
|
|
|
if (!ephyrHostIsContextDirect(req->context, (int *) &is_direct)) {
|
|
EPHYR_LOG_ERROR("ephyrHostIsContextDirect() failed\n");
|
|
goto out;
|
|
}
|
|
reply = (xGLXIsDirectReply) {
|
|
.type = X_Reply,
|
|
.sequenceNumber = client->sequence,
|
|
.length = 0,
|
|
.isDirect = is_direct
|
|
};
|
|
|
|
WriteToClient(client, sz_xGLXIsDirectReply, &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);
|
|
}
|