1706f2543Smrg/*
2706f2543Smrg * Xephyr - A kdrive X server thats runs in a host X window.
3706f2543Smrg *          Authored by Matthew Allum <mallum@openedhand.com>
4706f2543Smrg *
5706f2543Smrg * Copyright © 2007 OpenedHand Ltd
6706f2543Smrg *
7706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
8706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
9706f2543Smrg * the above copyright notice appear in all copies and that both that
10706f2543Smrg * copyright notice and this permission notice appear in supporting
11706f2543Smrg * documentation, and that the name of OpenedHand Ltd not be used in
12706f2543Smrg * advertising or publicity pertaining to distribution of the software without
13706f2543Smrg * specific, written prior permission. OpenedHand Ltd makes no
14706f2543Smrg * representations about the suitability of this software for any purpose.  It
15706f2543Smrg * is provided "as is" without express or implied warranty.
16706f2543Smrg *
17706f2543Smrg * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19706f2543Smrg * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
24706f2543Smrg *
25706f2543Smrg * Authors:
26706f2543Smrg *    Dodji Seketeli <dodji@openedhand.com>
27706f2543Smrg */
28706f2543Smrg#ifdef HAVE_CONFIG_H
29706f2543Smrg#include <kdrive-config.h>
30706f2543Smrg#endif
31706f2543Smrg
32706f2543Smrg#include "extnsionst.h"
33706f2543Smrg#include "ephyrglxext.h"
34706f2543Smrg#include "ephyrhostglx.h"
35706f2543Smrg#define _HAVE_XALLOC_DECLS
36706f2543Smrg#include "ephyrlog.h"
37706f2543Smrg#include <GL/glxproto.h>
38706f2543Smrg#include "glx/glxserver.h"
39706f2543Smrg#include "glx/indirect_table.h"
40706f2543Smrg#include "glx/indirect_util.h"
41706f2543Smrg#include "glx/unpack.h"
42706f2543Smrg#include "hostx.h"
43706f2543Smrg
44706f2543Smrg
45706f2543Smrg#ifndef TRUE
46706f2543Smrg#define TRUE 1
47706f2543Smrg#endif
48706f2543Smrg
49706f2543Smrg#ifndef FALSE
50706f2543Smrg#define FALSE 0
51706f2543Smrg#endif
52706f2543Smrg
53706f2543Smrg
54706f2543Smrgint ephyrGLXQueryVersion (__GLXclientState *cl, GLbyte *pc) ;
55706f2543Smrgint ephyrGLXQueryVersionSwap (__GLXclientState *cl, GLbyte *pc) ;
56706f2543Smrgint ephyrGLXGetVisualConfigs (__GLXclientState *cl, GLbyte *pc) ;
57706f2543Smrgint ephyrGLXGetVisualConfigsSwap (__GLXclientState *cl, GLbyte *pc) ;
58706f2543Smrgint ephyrGLXClientInfo(__GLXclientState *cl, GLbyte *pc) ;
59706f2543Smrgint ephyrGLXClientInfoSwap(__GLXclientState *cl, GLbyte *pc) ;
60706f2543Smrgint ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) ;
61706f2543Smrgint ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) ;
62706f2543Smrgint ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc);
63706f2543Smrgint ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc);
64706f2543Smrgint ephyrGLXCreateContext (__GLXclientState *a_cl, GLbyte *a_pc);
65706f2543Smrgint ephyrGLXCreateContextSwap (__GLXclientState *a_cl, GLbyte *a_pc);
66706f2543Smrgint ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) ;
67706f2543Smrgint ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
68706f2543Smrgint ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) ;
69706f2543Smrgint ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
70706f2543Smrgint ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) ;
71706f2543Smrgint ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
72706f2543Smrgint ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) ;
73706f2543Smrgint ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
74706f2543Smrgint ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) ;
75706f2543Smrgint ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
76706f2543Smrg
77706f2543SmrgBool
78706f2543SmrgephyrHijackGLXExtension (void)
79706f2543Smrg{
80706f2543Smrg    const void *(*dispatch_functions)[2];
81706f2543Smrg
82706f2543Smrg    if (!hostx_has_glx ()) {
83706f2543Smrg        EPHYR_LOG ("host X does not have GLX\n") ;
84706f2543Smrg        return FALSE ;
85706f2543Smrg    }
86706f2543Smrg    EPHYR_LOG ("host X does have GLX\n") ;
87706f2543Smrg
88706f2543Smrg    if (!Single_dispatch_info.dispatch_functions) {
89706f2543Smrg        EPHYR_LOG_ERROR ("could not get dispatch functions table\n") ;
90706f2543Smrg        return FALSE ;
91706f2543Smrg    }
92706f2543Smrg    /*
93706f2543Smrg     * hijack some single entry point dispatch functions
94706f2543Smrg     */
95706f2543Smrg    dispatch_functions = Single_dispatch_info.dispatch_functions ;
96706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (dispatch_functions, FALSE) ;
97706f2543Smrg
98706f2543Smrg    dispatch_functions[X_GLXQueryVersion][0] = ephyrGLXQueryVersion ;
99706f2543Smrg    dispatch_functions[X_GLXQueryVersion][1] = ephyrGLXQueryVersionSwap ;
100706f2543Smrg
101706f2543Smrg    dispatch_functions[X_GLXGetVisualConfigs][0] = ephyrGLXGetVisualConfigs ;
102706f2543Smrg    dispatch_functions[X_GLXGetVisualConfigs][1] = ephyrGLXGetVisualConfigsSwap ;
103706f2543Smrg    dispatch_functions[X_GLXClientInfo][0] = ephyrGLXClientInfo ;
104706f2543Smrg    dispatch_functions[X_GLXClientInfo][1] = ephyrGLXClientInfoSwap ;
105706f2543Smrg
106706f2543Smrg    dispatch_functions[X_GLXQueryServerString][0] = ephyrGLXQueryServerString ;
107706f2543Smrg    dispatch_functions[X_GLXQueryServerString][1] =
108706f2543Smrg                                                ephyrGLXQueryServerStringSwap ;
109706f2543Smrg
110706f2543Smrg    dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext ;
111706f2543Smrg    dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap ;
112706f2543Smrg
113706f2543Smrg    dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext ;
114706f2543Smrg    dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap ;
115706f2543Smrg
116706f2543Smrg    dispatch_functions[X_GLXMakeCurrent][0] = ephyrGLXMakeCurrent ;
117706f2543Smrg    dispatch_functions[X_GLXMakeCurrent][1] = ephyrGLXMakeCurrentSwap ;
118706f2543Smrg
119706f2543Smrg    dispatch_functions[X_GLXIsDirect][0] = ephyrGLXIsDirect ;
120706f2543Smrg    dispatch_functions[X_GLXIsDirect][1] = ephyrGLXIsDirectSwap ;
121706f2543Smrg
122706f2543Smrg    dispatch_functions[73][0] = ephyrGLXGetString ;
123706f2543Smrg    dispatch_functions[73][1] = ephyrGLXGetStringSwap ;
124706f2543Smrg
125706f2543Smrg    dispatch_functions[61][0] = ephyrGLXGetIntegerv ;
126706f2543Smrg    dispatch_functions[61][1] = ephyrGLXGetIntegervSwap ;
127706f2543Smrg
128706f2543Smrg    /*
129706f2543Smrg     * hijack some vendor priv entry point dispatch functions
130706f2543Smrg     */
131706f2543Smrg    dispatch_functions = VendorPriv_dispatch_info.dispatch_functions ;
132706f2543Smrg    dispatch_functions[92][0] = ephyrGLXGetFBConfigsSGIX;
133706f2543Smrg    dispatch_functions[92][1] = ephyrGLXGetFBConfigsSGIXSwap;
134706f2543Smrg    EPHYR_LOG ("hijacked glx entry points to forward requests to host X\n") ;
135706f2543Smrg
136706f2543Smrg    return TRUE ;
137706f2543Smrg}
138706f2543Smrg
139706f2543Smrg/*********************
140706f2543Smrg * implementation of
141706f2543Smrg * hijacked GLX entry
142706f2543Smrg * points
143706f2543Smrg ********************/
144706f2543Smrg
145706f2543Smrgint
146706f2543SmrgephyrGLXQueryVersion(__GLXclientState *a_cl, GLbyte *a_pc)
147706f2543Smrg{
148706f2543Smrg    ClientPtr client = a_cl->client;
149706f2543Smrg    xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc;
150706f2543Smrg    xGLXQueryVersionReply reply;
151706f2543Smrg    int major, minor;
152706f2543Smrg    int res = BadImplementation ;
153706f2543Smrg
154706f2543Smrg    EPHYR_LOG ("enter\n") ;
155706f2543Smrg
156706f2543Smrg    major = req->majorVersion ;
157706f2543Smrg    minor = req->minorVersion ;
158706f2543Smrg
159706f2543Smrg    if (!ephyrHostGLXQueryVersion (&major, &minor)) {
160706f2543Smrg        EPHYR_LOG_ERROR ("ephyrHostGLXQueryVersion() failed\n") ;
161706f2543Smrg        goto out ;
162706f2543Smrg    }
163706f2543Smrg    EPHYR_LOG ("major:%d, minor:%d\n",
164706f2543Smrg                major, minor);
165706f2543Smrg    reply.majorVersion = major ;
166706f2543Smrg    reply.minorVersion = minor ;
167706f2543Smrg    reply.length = 0 ;
168706f2543Smrg    reply.type = X_Reply ;
169706f2543Smrg    reply.sequenceNumber = client->sequence ;
170706f2543Smrg
171706f2543Smrg    if (client->swapped) {
172706f2543Smrg        __glXSwapQueryVersionReply(client, &reply);
173706f2543Smrg    } else {
174706f2543Smrg        WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply);
175706f2543Smrg    }
176706f2543Smrg
177706f2543Smrg    res = Success ;
178706f2543Smrgout:
179706f2543Smrg    EPHYR_LOG ("leave\n") ;
180706f2543Smrg    return res;
181706f2543Smrg}
182706f2543Smrg
183706f2543Smrgint
184706f2543SmrgephyrGLXQueryVersionSwap (__GLXclientState *a_cl, GLbyte *a_pc)
185706f2543Smrg{
186706f2543Smrg    xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc;
187706f2543Smrg    __GLX_DECLARE_SWAP_VARIABLES;
188706f2543Smrg
189706f2543Smrg    __GLX_SWAP_SHORT (&req->length);
190706f2543Smrg    __GLX_SWAP_INT (&req->majorVersion);
191706f2543Smrg    __GLX_SWAP_INT (&req->minorVersion);
192706f2543Smrg    return ephyrGLXQueryVersion (a_cl, a_pc) ;
193706f2543Smrg}
194706f2543Smrg
195706f2543Smrgstatic int
196706f2543SmrgephyrGLXGetVisualConfigsReal (__GLXclientState *a_cl,
197706f2543Smrg                              GLbyte *a_pc,
198706f2543Smrg                              Bool a_do_swap)
199706f2543Smrg{
200706f2543Smrg    xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) a_pc;
201706f2543Smrg    ClientPtr client = a_cl->client;
202706f2543Smrg    xGLXGetVisualConfigsReply reply;
203706f2543Smrg    int32_t *props_buf=NULL, num_visuals=0,
204706f2543Smrg            num_props=0, res=BadImplementation, i=0,
205706f2543Smrg            props_per_visual_size=0,
206706f2543Smrg            props_buf_size=0;
207706f2543Smrg    __GLX_DECLARE_SWAP_VARIABLES;
208706f2543Smrg    __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
209706f2543Smrg
210706f2543Smrg    EPHYR_LOG ("enter\n") ;
211706f2543Smrg
212706f2543Smrg    if (!ephyrHostGLXGetVisualConfigs (req->screen,
213706f2543Smrg                                       &num_visuals,
214706f2543Smrg                                       &num_props,
215706f2543Smrg                                       &props_buf_size,
216706f2543Smrg                                       &props_buf)) {
217706f2543Smrg        EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ;
218706f2543Smrg        goto out ;
219706f2543Smrg    }
220706f2543Smrg    EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ;
221706f2543Smrg
222706f2543Smrg    reply.numVisuals = num_visuals;
223706f2543Smrg    reply.numProps = num_props;
224706f2543Smrg    reply.length = (num_visuals *__GLX_SIZE_CARD32 * num_props) >> 2;
225706f2543Smrg    reply.type = X_Reply;
226706f2543Smrg    reply.sequenceNumber = client->sequence;
227706f2543Smrg
228706f2543Smrg    if (a_do_swap) {
229706f2543Smrg        __GLX_SWAP_SHORT(&reply.sequenceNumber);
230706f2543Smrg        __GLX_SWAP_INT(&reply.length);
231706f2543Smrg        __GLX_SWAP_INT(&reply.numVisuals);
232706f2543Smrg        __GLX_SWAP_INT(&reply.numProps);
233706f2543Smrg        __GLX_SWAP_INT_ARRAY (props_buf, num_props) ;
234706f2543Smrg    }
235706f2543Smrg    WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply);
236706f2543Smrg    props_per_visual_size = props_buf_size/num_visuals ;
237706f2543Smrg    for (i=0; i < num_visuals; i++) {
238706f2543Smrg        WriteToClient (client,
239706f2543Smrg                       props_per_visual_size,
240706f2543Smrg                       (char*)props_buf +i*props_per_visual_size);
241706f2543Smrg    }
242706f2543Smrg    res = Success ;
243706f2543Smrg
244706f2543Smrgout:
245706f2543Smrg    EPHYR_LOG ("leave\n") ;
246706f2543Smrg    free(props_buf) ;
247706f2543Smrg    props_buf = NULL ;
248706f2543Smrg
249706f2543Smrg    return res ;
250706f2543Smrg}
251706f2543Smrg
252706f2543Smrgstatic int
253706f2543SmrgephyrGLXGetFBConfigsSGIXReal (__GLXclientState *a_cl,
254706f2543Smrg                              GLbyte *a_pc,
255706f2543Smrg                              Bool a_do_swap)
256706f2543Smrg{
257706f2543Smrg    xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *)a_pc;
258706f2543Smrg    ClientPtr client = a_cl->client;
259706f2543Smrg    xGLXGetVisualConfigsReply reply;
260706f2543Smrg    int32_t *props_buf=NULL, num_visuals=0,
261706f2543Smrg            num_props=0, res=BadImplementation, i=0,
262706f2543Smrg            props_per_visual_size=0,
263706f2543Smrg            props_buf_size=0;
264706f2543Smrg    __GLX_DECLARE_SWAP_VARIABLES;
265706f2543Smrg    __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
266706f2543Smrg
267706f2543Smrg    EPHYR_LOG ("enter\n") ;
268706f2543Smrg
269706f2543Smrg    if (!ephyrHostGLXVendorPrivGetFBConfigsSGIX (req->screen,
270706f2543Smrg                                                 &num_visuals,
271706f2543Smrg                                                 &num_props,
272706f2543Smrg                                                 &props_buf_size,
273706f2543Smrg                                                 &props_buf)) {
274706f2543Smrg        EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ;
275706f2543Smrg        goto out ;
276706f2543Smrg    }
277706f2543Smrg    EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ;
278706f2543Smrg
279706f2543Smrg    reply.numVisuals = num_visuals;
280706f2543Smrg    reply.numProps = num_props;
281706f2543Smrg    reply.length = props_buf_size >> 2;
282706f2543Smrg    reply.type = X_Reply;
283706f2543Smrg    reply.sequenceNumber = client->sequence;
284706f2543Smrg
285706f2543Smrg    if (a_do_swap) {
286706f2543Smrg        __GLX_SWAP_SHORT(&reply.sequenceNumber);
287706f2543Smrg        __GLX_SWAP_INT(&reply.length);
288706f2543Smrg        __GLX_SWAP_INT(&reply.numVisuals);
289706f2543Smrg        __GLX_SWAP_INT(&reply.numProps);
290706f2543Smrg        __GLX_SWAP_INT_ARRAY (props_buf, num_props) ;
291706f2543Smrg    }
292706f2543Smrg    WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply);
293706f2543Smrg    props_per_visual_size = props_buf_size/num_visuals ;
294706f2543Smrg    for (i=0; i < num_visuals; i++) {
295706f2543Smrg        WriteToClient (client,
296706f2543Smrg                       props_per_visual_size,
297706f2543Smrg                       &((char*)props_buf)[i*props_per_visual_size]);
298706f2543Smrg    }
299706f2543Smrg    res = Success ;
300706f2543Smrg
301706f2543Smrgout:
302706f2543Smrg    EPHYR_LOG ("leave\n") ;
303706f2543Smrg    free(props_buf) ;
304706f2543Smrg    props_buf = NULL ;
305706f2543Smrg
306706f2543Smrg    return res ;
307706f2543Smrg}
308706f2543Smrg
309706f2543Smrgint
310706f2543SmrgephyrGLXGetVisualConfigs (__GLXclientState *a_cl, GLbyte *a_pc)
311706f2543Smrg{
312706f2543Smrg    return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, FALSE) ;
313706f2543Smrg}
314706f2543Smrg
315706f2543Smrgint
316706f2543SmrgephyrGLXGetVisualConfigsSwap (__GLXclientState *a_cl, GLbyte *a_pc)
317706f2543Smrg{
318706f2543Smrg    return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, TRUE) ;
319706f2543Smrg}
320706f2543Smrg
321706f2543Smrg
322706f2543Smrgint
323706f2543SmrgephyrGLXClientInfo(__GLXclientState *a_cl, GLbyte *a_pc)
324706f2543Smrg{
325706f2543Smrg    int res=BadImplementation ;
326706f2543Smrg    xGLXClientInfoReq *req = (xGLXClientInfoReq *) a_pc;
327706f2543Smrg
328706f2543Smrg    EPHYR_LOG ("enter\n") ;
329706f2543Smrg    if (!ephyrHostGLXSendClientInfo (req->major, req->minor, (char*)req+1)) {
330706f2543Smrg        EPHYR_LOG_ERROR ("failed to send client info to host\n") ;
331706f2543Smrg        goto out ;
332706f2543Smrg    }
333706f2543Smrg    res = Success ;
334706f2543Smrg
335706f2543Smrgout:
336706f2543Smrg    EPHYR_LOG ("leave\n") ;
337706f2543Smrg    return res ;
338706f2543Smrg}
339706f2543Smrg
340706f2543Smrgint
341706f2543SmrgephyrGLXClientInfoSwap (__GLXclientState *a_cl, GLbyte *a_pc)
342706f2543Smrg{
343706f2543Smrg    xGLXClientInfoReq *req = (xGLXClientInfoReq *)a_pc;
344706f2543Smrg    __GLX_DECLARE_SWAP_VARIABLES;
345706f2543Smrg
346706f2543Smrg    __GLX_SWAP_SHORT (&req->length);
347706f2543Smrg    __GLX_SWAP_INT (&req->major);
348706f2543Smrg    __GLX_SWAP_INT (&req->minor);
349706f2543Smrg    __GLX_SWAP_INT (&req->numbytes);
350706f2543Smrg
351706f2543Smrg    return ephyrGLXClientInfo (a_cl, a_pc) ;
352706f2543Smrg}
353706f2543Smrg
354706f2543Smrgint
355706f2543SmrgephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc)
356706f2543Smrg{
357706f2543Smrg    int res = BadImplementation ;
358706f2543Smrg    ClientPtr client = a_cl->client;
359706f2543Smrg    xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) a_pc;
360706f2543Smrg    xGLXQueryServerStringReply reply;
361706f2543Smrg    char *server_string=NULL, *buf=NULL;
362706f2543Smrg    int length=0 ;
363706f2543Smrg
364706f2543Smrg    EPHYR_LOG ("enter\n") ;
365706f2543Smrg    if (!ephyrHostGLXGetStringFromServer (req->screen,
366706f2543Smrg                                          req->name,
367706f2543Smrg                                          EPHYR_HOST_GLX_QueryServerString,
368706f2543Smrg                                          &server_string)) {
369706f2543Smrg        EPHYR_LOG_ERROR ("failed to query string from host\n") ;
370706f2543Smrg        goto out ;
371706f2543Smrg    }
372706f2543Smrg    EPHYR_LOG ("string: %s\n", server_string) ;
373706f2543Smrg    length= strlen (server_string) + 1;
374706f2543Smrg    reply.type = X_Reply ;
375706f2543Smrg    reply.sequenceNumber = client->sequence ;
376706f2543Smrg    reply.length = __GLX_PAD (length) >> 2 ;
377706f2543Smrg    reply.n = length ;
378706f2543Smrg    buf = calloc(reply.length << 2, 1);
379706f2543Smrg    if (!buf) {
380706f2543Smrg        EPHYR_LOG_ERROR ("failed to allocate string\n;");
381706f2543Smrg        return BadAlloc;
382706f2543Smrg    }
383706f2543Smrg    memcpy (buf, server_string, length);
384706f2543Smrg
385706f2543Smrg    WriteToClient(client, sz_xGLXQueryServerStringReply, (char*)&reply);
386706f2543Smrg    WriteToClient(client, (int)(reply.length << 2), server_string);
387706f2543Smrg
388706f2543Smrg    res = Success ;
389706f2543Smrg
390706f2543Smrgout:
391706f2543Smrg    EPHYR_LOG ("leave\n") ;
392706f2543Smrg    free(server_string) ;
393706f2543Smrg    server_string = NULL;
394706f2543Smrg
395706f2543Smrg    free(buf);
396706f2543Smrg    buf = NULL;
397706f2543Smrg
398706f2543Smrg    return res ;
399706f2543Smrg}
400706f2543Smrg
401706f2543Smrgint
402706f2543SmrgephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc)
403706f2543Smrg{
404706f2543Smrg    EPHYR_LOG_ERROR ("not yet implemented\n") ;
405706f2543Smrg    return BadImplementation ;
406706f2543Smrg}
407706f2543Smrg
408706f2543Smrg
409706f2543Smrgint
410706f2543SmrgephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc)
411706f2543Smrg{
412706f2543Smrg    return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, FALSE) ;
413706f2543Smrg}
414706f2543Smrg
415706f2543Smrgint
416706f2543SmrgephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc)
417706f2543Smrg{
418706f2543Smrg    return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, TRUE) ;
419706f2543Smrg}
420706f2543Smrg
421706f2543Smrgstatic int
422706f2543SmrgephyrGLXCreateContextReal (xGLXCreateContextReq *a_req, Bool a_do_swap)
423706f2543Smrg{
424706f2543Smrg    int res=BadImplementation;
425706f2543Smrg    EphyrHostWindowAttributes host_w_attrs ;
426706f2543Smrg    __GLX_DECLARE_SWAP_VARIABLES;
427706f2543Smrg
428706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (a_req, BadValue) ;
429706f2543Smrg    EPHYR_LOG ("enter\n") ;
430706f2543Smrg
431706f2543Smrg    if (a_do_swap) {
432706f2543Smrg        __GLX_SWAP_SHORT(&a_req->length);
433706f2543Smrg        __GLX_SWAP_INT(&a_req->context);
434706f2543Smrg        __GLX_SWAP_INT(&a_req->visual);
435706f2543Smrg        __GLX_SWAP_INT(&a_req->screen);
436706f2543Smrg        __GLX_SWAP_INT(&a_req->shareList);
437706f2543Smrg    }
438706f2543Smrg
439706f2543Smrg    EPHYR_LOG ("context creation requested. localid:%d, "
440706f2543Smrg               "screen:%d, visual:%d, direct:%d\n",
441706f2543Smrg               (int)a_req->context, (int)a_req->screen,
442706f2543Smrg               (int)a_req->visual, (int)a_req->isDirect) ;
443706f2543Smrg
444706f2543Smrg    memset (&host_w_attrs, 0, sizeof (host_w_attrs)) ;
445706f2543Smrg    if (!hostx_get_window_attributes (hostx_get_window (a_req->screen),
446706f2543Smrg                                      &host_w_attrs)) {
447706f2543Smrg        EPHYR_LOG_ERROR ("failed to get host window attrs\n") ;
448706f2543Smrg        goto out ;
449706f2543Smrg    }
450706f2543Smrg
451706f2543Smrg    EPHYR_LOG ("host window visual id: %d\n", host_w_attrs.visualid) ;
452706f2543Smrg
453706f2543Smrg    if (!ephyrHostGLXCreateContext (a_req->screen,
454706f2543Smrg                                    host_w_attrs.visualid,
455706f2543Smrg                                    a_req->context,
456706f2543Smrg                                    a_req->shareList,
457706f2543Smrg                                    a_req->isDirect)) {
458706f2543Smrg        EPHYR_LOG_ERROR ("ephyrHostGLXCreateContext() failed\n") ;
459706f2543Smrg        goto out ;
460706f2543Smrg    }
461706f2543Smrg    res = Success;
462706f2543Smrgout:
463706f2543Smrg    EPHYR_LOG ("leave\n") ;
464706f2543Smrg    return res ;
465706f2543Smrg}
466706f2543Smrg
467706f2543Smrgint
468706f2543SmrgephyrGLXCreateContext (__GLXclientState *cl, GLbyte *pc)
469706f2543Smrg{
470706f2543Smrg    xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc;
471706f2543Smrg
472706f2543Smrg    return ephyrGLXCreateContextReal (req, FALSE) ;
473706f2543Smrg}
474706f2543Smrg
475706f2543Smrgint ephyrGLXCreateContextSwap (__GLXclientState *cl, GLbyte *pc)
476706f2543Smrg{
477706f2543Smrg    xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc;
478706f2543Smrg    return ephyrGLXCreateContextReal (req, TRUE) ;
479706f2543Smrg}
480706f2543Smrg
481706f2543Smrgstatic int
482706f2543SmrgephyrGLXDestroyContextReal (__GLXclientState *a_cl,
483706f2543Smrg                            GLbyte *a_pc,
484706f2543Smrg                            Bool a_do_swap)
485706f2543Smrg{
486706f2543Smrg    int res=BadImplementation;
487706f2543Smrg    ClientPtr client = a_cl->client;
488706f2543Smrg    xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) a_pc;
489706f2543Smrg
490706f2543Smrg    EPHYR_LOG ("enter. id:%d\n", (int)req->context) ;
491706f2543Smrg    if (!ephyrHostDestroyContext (req->context)) {
492706f2543Smrg        EPHYR_LOG_ERROR ("ephyrHostDestroyContext() failed\n") ;
493706f2543Smrg        client->errorValue = req->context ;
494706f2543Smrg        goto out ;
495706f2543Smrg    }
496706f2543Smrg    res = Success ;
497706f2543Smrg
498706f2543Smrgout:
499706f2543Smrg    EPHYR_LOG ("leave\n") ;
500706f2543Smrg    return res ;
501706f2543Smrg}
502706f2543Smrg
503706f2543Smrgint
504706f2543SmrgephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc)
505706f2543Smrg{
506706f2543Smrg    return ephyrGLXDestroyContextReal (a_cl, a_pc, FALSE) ;
507706f2543Smrg}
508706f2543Smrg
509706f2543Smrgint
510706f2543SmrgephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc)
511706f2543Smrg{
512706f2543Smrg    return ephyrGLXDestroyContextReal (a_cl, a_pc, TRUE) ;
513706f2543Smrg}
514706f2543Smrg
515706f2543Smrgstatic int
516706f2543SmrgephyrGLXMakeCurrentReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
517706f2543Smrg{
518706f2543Smrg    int res=BadImplementation;
519706f2543Smrg    xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc;
520706f2543Smrg    xGLXMakeCurrentReply reply ;
521706f2543Smrg    DrawablePtr drawable=NULL;
522706f2543Smrg    int rc=0;
523706f2543Smrg
524706f2543Smrg    EPHYR_LOG ("enter\n") ;
525706f2543Smrg    rc = dixLookupDrawable (&drawable,
526706f2543Smrg                            req->drawable,
527706f2543Smrg                            a_cl->client,
528706f2543Smrg                            0,
529706f2543Smrg                            DixReadAccess);
530706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (drawable, BadValue) ;
531706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (drawable->pScreen, BadValue) ;
532706f2543Smrg    EPHYR_LOG ("screen nummber requested:%d\n",
533706f2543Smrg               drawable->pScreen->myNum) ;
534706f2543Smrg
535706f2543Smrg    memset (&reply, 0, sizeof (reply)) ;
536706f2543Smrg    if (!ephyrHostGLXMakeCurrent (hostx_get_window (drawable->pScreen->myNum),
537706f2543Smrg                                  req->context,
538706f2543Smrg                                  req->oldContextTag,
539706f2543Smrg                                  (int*)&reply.contextTag)) {
540706f2543Smrg        EPHYR_LOG_ERROR ("ephyrHostGLXMakeCurrent() failed\n") ;
541706f2543Smrg        goto out;
542706f2543Smrg    }
543706f2543Smrg    reply.length = 0;
544706f2543Smrg    reply.type = X_Reply;
545706f2543Smrg    reply.sequenceNumber = a_cl->client->sequence;
546706f2543Smrg    if (a_do_swap) {
547706f2543Smrg        __GLX_DECLARE_SWAP_VARIABLES;
548706f2543Smrg        __GLX_SWAP_SHORT(&reply.sequenceNumber);
549706f2543Smrg        __GLX_SWAP_INT(&reply.length);
550706f2543Smrg        __GLX_SWAP_INT(&reply.contextTag);
551706f2543Smrg    }
552706f2543Smrg    WriteToClient(a_cl->client, sz_xGLXMakeCurrentReply, (char *)&reply);
553706f2543Smrg
554706f2543Smrg    res = Success ;
555706f2543Smrgout:
556706f2543Smrg    EPHYR_LOG ("leave\n") ;
557706f2543Smrg    return res ;
558706f2543Smrg}
559706f2543Smrg
560706f2543Smrgint
561706f2543SmrgephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc)
562706f2543Smrg{
563706f2543Smrg    return ephyrGLXMakeCurrentReal (a_cl, a_pc, FALSE) ;
564706f2543Smrg}
565706f2543Smrg
566706f2543Smrgint
567706f2543SmrgephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc)
568706f2543Smrg{
569706f2543Smrg    return ephyrGLXMakeCurrentReal (a_cl, a_pc, TRUE) ;
570706f2543Smrg}
571706f2543Smrg
572706f2543Smrgstatic int
573706f2543SmrgephyrGLXGetStringReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
574706f2543Smrg{
575706f2543Smrg    ClientPtr client=NULL ;
576706f2543Smrg    int context_tag=0, name=0, res=BadImplementation, length=0 ;
577706f2543Smrg    char *string=NULL;
578706f2543Smrg    __GLX_DECLARE_SWAP_VARIABLES;
579706f2543Smrg
580706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, BadValue) ;
581706f2543Smrg
582706f2543Smrg    EPHYR_LOG ("enter\n") ;
583706f2543Smrg
584706f2543Smrg    client = a_cl->client ;
585706f2543Smrg
586706f2543Smrg    if (a_do_swap) {
587706f2543Smrg        __GLX_SWAP_INT (a_pc + 4);
588706f2543Smrg        __GLX_SWAP_INT (a_pc + __GLX_SINGLE_HDR_SIZE);
589706f2543Smrg    }
590706f2543Smrg    context_tag = __GLX_GET_SINGLE_CONTEXT_TAG (a_pc) ;
591706f2543Smrg    a_pc += __GLX_SINGLE_HDR_SIZE;
592706f2543Smrg    name = *(GLenum*)(a_pc + 0);
593706f2543Smrg    EPHYR_LOG ("context_tag:%d, name:%d\n", context_tag, name) ;
594706f2543Smrg    if (!ephyrHostGLXGetStringFromServer (context_tag,
595706f2543Smrg                                          name,
596706f2543Smrg                                          EPHYR_HOST_GLX_GetString,
597706f2543Smrg                                          &string)) {
598706f2543Smrg        EPHYR_LOG_ERROR ("failed to get string from server\n") ;
599706f2543Smrg        goto out ;
600706f2543Smrg    }
601706f2543Smrg    if (string) {
602706f2543Smrg        length = strlen (string) + 1;
603706f2543Smrg        EPHYR_LOG ("got string:'%s', size:%d\n", string, length) ;
604706f2543Smrg    } else {
605706f2543Smrg        EPHYR_LOG ("got string: string (null)\n") ;
606706f2543Smrg    }
607706f2543Smrg    __GLX_BEGIN_REPLY (length);
608706f2543Smrg    __GLX_PUT_SIZE (length);
609706f2543Smrg    __GLX_SEND_HEADER ();
610706f2543Smrg    if (a_do_swap) {
611706f2543Smrg        __GLX_SWAP_REPLY_SIZE ();
612706f2543Smrg        __GLX_SWAP_REPLY_HEADER ();
613706f2543Smrg    }
614706f2543Smrg    WriteToClient (client, length, (char *)string);
615706f2543Smrg
616706f2543Smrg    res = Success ;
617706f2543Smrgout:
618706f2543Smrg    EPHYR_LOG ("leave\n") ;
619706f2543Smrg    return res ;
620706f2543Smrg}
621706f2543Smrg
622706f2543Smrgint
623706f2543SmrgephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc)
624706f2543Smrg{
625706f2543Smrg    return ephyrGLXGetStringReal (a_cl, a_pc, FALSE) ;
626706f2543Smrg}
627706f2543Smrg
628706f2543Smrgint
629706f2543SmrgephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc)
630706f2543Smrg{
631706f2543Smrg    return ephyrGLXGetStringReal (a_cl, a_pc, TRUE) ;
632706f2543Smrg}
633706f2543Smrg
634706f2543Smrgstatic int
635706f2543SmrgephyrGLXGetIntegervReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
636706f2543Smrg{
637706f2543Smrg    int res=BadImplementation;
638706f2543Smrg    xGLXSingleReq * const req = (xGLXSingleReq *) a_pc;
639706f2543Smrg    GLenum int_name ;
640706f2543Smrg    int value=0 ;
641706f2543Smrg    GLint answer_buf_room[200];
642706f2543Smrg    GLint *buf=NULL ;
643706f2543Smrg
644706f2543Smrg    EPHYR_LOG ("enter\n") ;
645706f2543Smrg
646706f2543Smrg    a_pc += __GLX_SINGLE_HDR_SIZE;
647706f2543Smrg
648706f2543Smrg    int_name = *(GLenum*) (a_pc+0) ;
649706f2543Smrg    if (!ephyrHostGetIntegerValue (req->contextTag, int_name, &value)) {
650706f2543Smrg        EPHYR_LOG_ERROR ("ephyrHostGetIntegerValue() failed\n") ;
651706f2543Smrg        goto out ;
652706f2543Smrg    }
653706f2543Smrg    buf = __glXGetAnswerBuffer (a_cl, sizeof (value),
654706f2543Smrg                                answer_buf_room,
655706f2543Smrg                                sizeof (answer_buf_room),
656706f2543Smrg                                4) ;
657706f2543Smrg
658706f2543Smrg    if (!buf) {
659706f2543Smrg        EPHYR_LOG_ERROR ("failed to allocate reply buffer\n") ;
660706f2543Smrg        res = BadAlloc ;
661706f2543Smrg        goto out ;
662706f2543Smrg    }
663706f2543Smrg    __glXSendReply (a_cl->client, buf, 1, sizeof (value), GL_FALSE, 0) ;
664706f2543Smrg    res = Success ;
665706f2543Smrg
666706f2543Smrgout:
667706f2543Smrg    EPHYR_LOG ("leave\n") ;
668706f2543Smrg    return res ;
669706f2543Smrg}
670706f2543Smrg
671706f2543Smrgint
672706f2543SmrgephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc)
673706f2543Smrg{
674706f2543Smrg    return ephyrGLXGetIntegervReal (a_cl, a_pc, FALSE) ;
675706f2543Smrg}
676706f2543Smrg
677706f2543Smrgint
678706f2543SmrgephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc)
679706f2543Smrg{
680706f2543Smrg    return ephyrGLXGetIntegervReal (a_cl, a_pc, TRUE) ;
681706f2543Smrg}
682706f2543Smrg
683706f2543Smrgstatic int
684706f2543SmrgephyrGLXIsDirectReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
685706f2543Smrg{
686706f2543Smrg    int res=BadImplementation;
687706f2543Smrg    ClientPtr client = a_cl->client;
688706f2543Smrg    xGLXIsDirectReq *req = (xGLXIsDirectReq *) a_pc;
689706f2543Smrg    xGLXIsDirectReply reply;
690706f2543Smrg    int is_direct=0 ;
691706f2543Smrg
692706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, FALSE) ;
693706f2543Smrg
694706f2543Smrg    EPHYR_LOG ("enter\n") ;
695706f2543Smrg
696706f2543Smrg    memset (&reply, 0, sizeof (reply)) ;
697706f2543Smrg    if (!ephyrHostIsContextDirect (req->context, (int*)&is_direct)) {
698706f2543Smrg        EPHYR_LOG_ERROR ("ephyrHostIsContextDirect() failed\n") ;
699706f2543Smrg        goto out ;
700706f2543Smrg    }
701706f2543Smrg    reply.isDirect = is_direct ;
702706f2543Smrg    reply.length = 0;
703706f2543Smrg    reply.type = X_Reply;
704706f2543Smrg    reply.sequenceNumber = client->sequence;
705706f2543Smrg    WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply);
706706f2543Smrg    res = Success ;
707706f2543Smrg
708706f2543Smrgout:
709706f2543Smrg    EPHYR_LOG ("leave\n") ;
710706f2543Smrg    return res ;
711706f2543Smrg}
712706f2543Smrg
713706f2543Smrgint
714706f2543SmrgephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc)
715706f2543Smrg{
716706f2543Smrg    return ephyrGLXIsDirectReal (a_cl, a_pc, FALSE) ;
717706f2543Smrg}
718706f2543Smrg
719706f2543Smrgint
720706f2543SmrgephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc)
721706f2543Smrg{
722706f2543Smrg    return ephyrGLXIsDirectReal (a_cl, a_pc, TRUE) ;
723706f2543Smrg}
724