ephyrglxext.c revision 706f2543
1/*
2 * Xephyr - A kdrive X server thats runs in a host X window.
3 *          Authored by Matthew Allum <mallum@openedhand.com>
4 *
5 * Copyright © 2007 OpenedHand Ltd
6 *
7 * Permission to use, copy, modify, distribute, and sell this software and its
8 * documentation for any purpose is hereby granted without fee, provided that
9 * the above copyright notice appear in all copies and that both that
10 * copyright notice and this permission notice appear in supporting
11 * documentation, and that the name of OpenedHand Ltd not be used in
12 * advertising or publicity pertaining to distribution of the software without
13 * specific, written prior permission. OpenedHand Ltd makes no
14 * representations about the suitability of this software for any purpose.  It
15 * is provided "as is" without express or implied warranty.
16 *
17 * OpenedHand Ltd DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
18 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
19 * EVENT SHALL OpenedHand Ltd BE LIABLE FOR ANY SPECIAL, INDIRECT OR
20 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
21 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
22 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23 * PERFORMANCE OF THIS SOFTWARE.
24 *
25 * Authors:
26 *    Dodji Seketeli <dodji@openedhand.com>
27 */
28#ifdef HAVE_CONFIG_H
29#include <kdrive-config.h>
30#endif
31
32#include "extnsionst.h"
33#include "ephyrglxext.h"
34#include "ephyrhostglx.h"
35#define _HAVE_XALLOC_DECLS
36#include "ephyrlog.h"
37#include <GL/glxproto.h>
38#include "glx/glxserver.h"
39#include "glx/indirect_table.h"
40#include "glx/indirect_util.h"
41#include "glx/unpack.h"
42#include "hostx.h"
43
44
45#ifndef TRUE
46#define TRUE 1
47#endif
48
49#ifndef FALSE
50#define FALSE 0
51#endif
52
53
54int ephyrGLXQueryVersion (__GLXclientState *cl, GLbyte *pc) ;
55int ephyrGLXQueryVersionSwap (__GLXclientState *cl, GLbyte *pc) ;
56int ephyrGLXGetVisualConfigs (__GLXclientState *cl, GLbyte *pc) ;
57int ephyrGLXGetVisualConfigsSwap (__GLXclientState *cl, GLbyte *pc) ;
58int ephyrGLXClientInfo(__GLXclientState *cl, GLbyte *pc) ;
59int ephyrGLXClientInfoSwap(__GLXclientState *cl, GLbyte *pc) ;
60int ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) ;
61int ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) ;
62int ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc);
63int ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc);
64int ephyrGLXCreateContext (__GLXclientState *a_cl, GLbyte *a_pc);
65int ephyrGLXCreateContextSwap (__GLXclientState *a_cl, GLbyte *a_pc);
66int ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) ;
67int ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
68int ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) ;
69int ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
70int ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) ;
71int ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
72int ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) ;
73int ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
74int ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) ;
75int ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
76
77Bool
78ephyrHijackGLXExtension (void)
79{
80    const void *(*dispatch_functions)[2];
81
82    if (!hostx_has_glx ()) {
83        EPHYR_LOG ("host X does not have GLX\n") ;
84        return FALSE ;
85    }
86    EPHYR_LOG ("host X does have GLX\n") ;
87
88    if (!Single_dispatch_info.dispatch_functions) {
89        EPHYR_LOG_ERROR ("could not get dispatch functions table\n") ;
90        return FALSE ;
91    }
92    /*
93     * hijack some single entry point dispatch functions
94     */
95    dispatch_functions = Single_dispatch_info.dispatch_functions ;
96    EPHYR_RETURN_VAL_IF_FAIL (dispatch_functions, FALSE) ;
97
98    dispatch_functions[X_GLXQueryVersion][0] = ephyrGLXQueryVersion ;
99    dispatch_functions[X_GLXQueryVersion][1] = ephyrGLXQueryVersionSwap ;
100
101    dispatch_functions[X_GLXGetVisualConfigs][0] = ephyrGLXGetVisualConfigs ;
102    dispatch_functions[X_GLXGetVisualConfigs][1] = ephyrGLXGetVisualConfigsSwap ;
103    dispatch_functions[X_GLXClientInfo][0] = ephyrGLXClientInfo ;
104    dispatch_functions[X_GLXClientInfo][1] = ephyrGLXClientInfoSwap ;
105
106    dispatch_functions[X_GLXQueryServerString][0] = ephyrGLXQueryServerString ;
107    dispatch_functions[X_GLXQueryServerString][1] =
108                                                ephyrGLXQueryServerStringSwap ;
109
110    dispatch_functions[X_GLXCreateContext][0] = ephyrGLXCreateContext ;
111    dispatch_functions[X_GLXCreateContext][1] = ephyrGLXCreateContextSwap ;
112
113    dispatch_functions[X_GLXDestroyContext][0] = ephyrGLXDestroyContext ;
114    dispatch_functions[X_GLXDestroyContext][1] = ephyrGLXDestroyContextSwap ;
115
116    dispatch_functions[X_GLXMakeCurrent][0] = ephyrGLXMakeCurrent ;
117    dispatch_functions[X_GLXMakeCurrent][1] = ephyrGLXMakeCurrentSwap ;
118
119    dispatch_functions[X_GLXIsDirect][0] = ephyrGLXIsDirect ;
120    dispatch_functions[X_GLXIsDirect][1] = ephyrGLXIsDirectSwap ;
121
122    dispatch_functions[73][0] = ephyrGLXGetString ;
123    dispatch_functions[73][1] = ephyrGLXGetStringSwap ;
124
125    dispatch_functions[61][0] = ephyrGLXGetIntegerv ;
126    dispatch_functions[61][1] = ephyrGLXGetIntegervSwap ;
127
128    /*
129     * hijack some vendor priv entry point dispatch functions
130     */
131    dispatch_functions = VendorPriv_dispatch_info.dispatch_functions ;
132    dispatch_functions[92][0] = ephyrGLXGetFBConfigsSGIX;
133    dispatch_functions[92][1] = ephyrGLXGetFBConfigsSGIXSwap;
134    EPHYR_LOG ("hijacked glx entry points to forward requests to host X\n") ;
135
136    return TRUE ;
137}
138
139/*********************
140 * implementation of
141 * hijacked GLX entry
142 * points
143 ********************/
144
145int
146ephyrGLXQueryVersion(__GLXclientState *a_cl, GLbyte *a_pc)
147{
148    ClientPtr client = a_cl->client;
149    xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc;
150    xGLXQueryVersionReply reply;
151    int major, minor;
152    int res = BadImplementation ;
153
154    EPHYR_LOG ("enter\n") ;
155
156    major = req->majorVersion ;
157    minor = req->minorVersion ;
158
159    if (!ephyrHostGLXQueryVersion (&major, &minor)) {
160        EPHYR_LOG_ERROR ("ephyrHostGLXQueryVersion() failed\n") ;
161        goto out ;
162    }
163    EPHYR_LOG ("major:%d, minor:%d\n",
164                major, minor);
165    reply.majorVersion = major ;
166    reply.minorVersion = minor ;
167    reply.length = 0 ;
168    reply.type = X_Reply ;
169    reply.sequenceNumber = client->sequence ;
170
171    if (client->swapped) {
172        __glXSwapQueryVersionReply(client, &reply);
173    } else {
174        WriteToClient(client, sz_xGLXQueryVersionReply, (char *)&reply);
175    }
176
177    res = Success ;
178out:
179    EPHYR_LOG ("leave\n") ;
180    return res;
181}
182
183int
184ephyrGLXQueryVersionSwap (__GLXclientState *a_cl, GLbyte *a_pc)
185{
186    xGLXQueryVersionReq *req = (xGLXQueryVersionReq *) a_pc;
187    __GLX_DECLARE_SWAP_VARIABLES;
188
189    __GLX_SWAP_SHORT (&req->length);
190    __GLX_SWAP_INT (&req->majorVersion);
191    __GLX_SWAP_INT (&req->minorVersion);
192    return ephyrGLXQueryVersion (a_cl, a_pc) ;
193}
194
195static int
196ephyrGLXGetVisualConfigsReal (__GLXclientState *a_cl,
197                              GLbyte *a_pc,
198                              Bool a_do_swap)
199{
200    xGLXGetVisualConfigsReq *req = (xGLXGetVisualConfigsReq *) a_pc;
201    ClientPtr client = a_cl->client;
202    xGLXGetVisualConfigsReply reply;
203    int32_t *props_buf=NULL, num_visuals=0,
204            num_props=0, res=BadImplementation, i=0,
205            props_per_visual_size=0,
206            props_buf_size=0;
207    __GLX_DECLARE_SWAP_VARIABLES;
208    __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
209
210    EPHYR_LOG ("enter\n") ;
211
212    if (!ephyrHostGLXGetVisualConfigs (req->screen,
213                                       &num_visuals,
214                                       &num_props,
215                                       &props_buf_size,
216                                       &props_buf)) {
217        EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ;
218        goto out ;
219    }
220    EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ;
221
222    reply.numVisuals = num_visuals;
223    reply.numProps = num_props;
224    reply.length = (num_visuals *__GLX_SIZE_CARD32 * num_props) >> 2;
225    reply.type = X_Reply;
226    reply.sequenceNumber = client->sequence;
227
228    if (a_do_swap) {
229        __GLX_SWAP_SHORT(&reply.sequenceNumber);
230        __GLX_SWAP_INT(&reply.length);
231        __GLX_SWAP_INT(&reply.numVisuals);
232        __GLX_SWAP_INT(&reply.numProps);
233        __GLX_SWAP_INT_ARRAY (props_buf, num_props) ;
234    }
235    WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply);
236    props_per_visual_size = props_buf_size/num_visuals ;
237    for (i=0; i < num_visuals; i++) {
238        WriteToClient (client,
239                       props_per_visual_size,
240                       (char*)props_buf +i*props_per_visual_size);
241    }
242    res = Success ;
243
244out:
245    EPHYR_LOG ("leave\n") ;
246    free(props_buf) ;
247    props_buf = NULL ;
248
249    return res ;
250}
251
252static int
253ephyrGLXGetFBConfigsSGIXReal (__GLXclientState *a_cl,
254                              GLbyte *a_pc,
255                              Bool a_do_swap)
256{
257    xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *)a_pc;
258    ClientPtr client = a_cl->client;
259    xGLXGetVisualConfigsReply reply;
260    int32_t *props_buf=NULL, num_visuals=0,
261            num_props=0, res=BadImplementation, i=0,
262            props_per_visual_size=0,
263            props_buf_size=0;
264    __GLX_DECLARE_SWAP_VARIABLES;
265    __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
266
267    EPHYR_LOG ("enter\n") ;
268
269    if (!ephyrHostGLXVendorPrivGetFBConfigsSGIX (req->screen,
270                                                 &num_visuals,
271                                                 &num_props,
272                                                 &props_buf_size,
273                                                 &props_buf)) {
274        EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ;
275        goto out ;
276    }
277    EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ;
278
279    reply.numVisuals = num_visuals;
280    reply.numProps = num_props;
281    reply.length = props_buf_size >> 2;
282    reply.type = X_Reply;
283    reply.sequenceNumber = client->sequence;
284
285    if (a_do_swap) {
286        __GLX_SWAP_SHORT(&reply.sequenceNumber);
287        __GLX_SWAP_INT(&reply.length);
288        __GLX_SWAP_INT(&reply.numVisuals);
289        __GLX_SWAP_INT(&reply.numProps);
290        __GLX_SWAP_INT_ARRAY (props_buf, num_props) ;
291    }
292    WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply);
293    props_per_visual_size = props_buf_size/num_visuals ;
294    for (i=0; i < num_visuals; i++) {
295        WriteToClient (client,
296                       props_per_visual_size,
297                       &((char*)props_buf)[i*props_per_visual_size]);
298    }
299    res = Success ;
300
301out:
302    EPHYR_LOG ("leave\n") ;
303    free(props_buf) ;
304    props_buf = NULL ;
305
306    return res ;
307}
308
309int
310ephyrGLXGetVisualConfigs (__GLXclientState *a_cl, GLbyte *a_pc)
311{
312    return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, FALSE) ;
313}
314
315int
316ephyrGLXGetVisualConfigsSwap (__GLXclientState *a_cl, GLbyte *a_pc)
317{
318    return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, TRUE) ;
319}
320
321
322int
323ephyrGLXClientInfo(__GLXclientState *a_cl, GLbyte *a_pc)
324{
325    int res=BadImplementation ;
326    xGLXClientInfoReq *req = (xGLXClientInfoReq *) a_pc;
327
328    EPHYR_LOG ("enter\n") ;
329    if (!ephyrHostGLXSendClientInfo (req->major, req->minor, (char*)req+1)) {
330        EPHYR_LOG_ERROR ("failed to send client info to host\n") ;
331        goto out ;
332    }
333    res = Success ;
334
335out:
336    EPHYR_LOG ("leave\n") ;
337    return res ;
338}
339
340int
341ephyrGLXClientInfoSwap (__GLXclientState *a_cl, GLbyte *a_pc)
342{
343    xGLXClientInfoReq *req = (xGLXClientInfoReq *)a_pc;
344    __GLX_DECLARE_SWAP_VARIABLES;
345
346    __GLX_SWAP_SHORT (&req->length);
347    __GLX_SWAP_INT (&req->major);
348    __GLX_SWAP_INT (&req->minor);
349    __GLX_SWAP_INT (&req->numbytes);
350
351    return ephyrGLXClientInfo (a_cl, a_pc) ;
352}
353
354int
355ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc)
356{
357    int res = BadImplementation ;
358    ClientPtr client = a_cl->client;
359    xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) a_pc;
360    xGLXQueryServerStringReply reply;
361    char *server_string=NULL, *buf=NULL;
362    int length=0 ;
363
364    EPHYR_LOG ("enter\n") ;
365    if (!ephyrHostGLXGetStringFromServer (req->screen,
366                                          req->name,
367                                          EPHYR_HOST_GLX_QueryServerString,
368                                          &server_string)) {
369        EPHYR_LOG_ERROR ("failed to query string from host\n") ;
370        goto out ;
371    }
372    EPHYR_LOG ("string: %s\n", server_string) ;
373    length= strlen (server_string) + 1;
374    reply.type = X_Reply ;
375    reply.sequenceNumber = client->sequence ;
376    reply.length = __GLX_PAD (length) >> 2 ;
377    reply.n = length ;
378    buf = calloc(reply.length << 2, 1);
379    if (!buf) {
380        EPHYR_LOG_ERROR ("failed to allocate string\n;");
381        return BadAlloc;
382    }
383    memcpy (buf, server_string, length);
384
385    WriteToClient(client, sz_xGLXQueryServerStringReply, (char*)&reply);
386    WriteToClient(client, (int)(reply.length << 2), server_string);
387
388    res = Success ;
389
390out:
391    EPHYR_LOG ("leave\n") ;
392    free(server_string) ;
393    server_string = NULL;
394
395    free(buf);
396    buf = NULL;
397
398    return res ;
399}
400
401int
402ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc)
403{
404    EPHYR_LOG_ERROR ("not yet implemented\n") ;
405    return BadImplementation ;
406}
407
408
409int
410ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc)
411{
412    return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, FALSE) ;
413}
414
415int
416ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc)
417{
418    return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, TRUE) ;
419}
420
421static int
422ephyrGLXCreateContextReal (xGLXCreateContextReq *a_req, Bool a_do_swap)
423{
424    int res=BadImplementation;
425    EphyrHostWindowAttributes host_w_attrs ;
426    __GLX_DECLARE_SWAP_VARIABLES;
427
428    EPHYR_RETURN_VAL_IF_FAIL (a_req, BadValue) ;
429    EPHYR_LOG ("enter\n") ;
430
431    if (a_do_swap) {
432        __GLX_SWAP_SHORT(&a_req->length);
433        __GLX_SWAP_INT(&a_req->context);
434        __GLX_SWAP_INT(&a_req->visual);
435        __GLX_SWAP_INT(&a_req->screen);
436        __GLX_SWAP_INT(&a_req->shareList);
437    }
438
439    EPHYR_LOG ("context creation requested. localid:%d, "
440               "screen:%d, visual:%d, direct:%d\n",
441               (int)a_req->context, (int)a_req->screen,
442               (int)a_req->visual, (int)a_req->isDirect) ;
443
444    memset (&host_w_attrs, 0, sizeof (host_w_attrs)) ;
445    if (!hostx_get_window_attributes (hostx_get_window (a_req->screen),
446                                      &host_w_attrs)) {
447        EPHYR_LOG_ERROR ("failed to get host window attrs\n") ;
448        goto out ;
449    }
450
451    EPHYR_LOG ("host window visual id: %d\n", host_w_attrs.visualid) ;
452
453    if (!ephyrHostGLXCreateContext (a_req->screen,
454                                    host_w_attrs.visualid,
455                                    a_req->context,
456                                    a_req->shareList,
457                                    a_req->isDirect)) {
458        EPHYR_LOG_ERROR ("ephyrHostGLXCreateContext() failed\n") ;
459        goto out ;
460    }
461    res = Success;
462out:
463    EPHYR_LOG ("leave\n") ;
464    return res ;
465}
466
467int
468ephyrGLXCreateContext (__GLXclientState *cl, GLbyte *pc)
469{
470    xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc;
471
472    return ephyrGLXCreateContextReal (req, FALSE) ;
473}
474
475int ephyrGLXCreateContextSwap (__GLXclientState *cl, GLbyte *pc)
476{
477    xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc;
478    return ephyrGLXCreateContextReal (req, TRUE) ;
479}
480
481static int
482ephyrGLXDestroyContextReal (__GLXclientState *a_cl,
483                            GLbyte *a_pc,
484                            Bool a_do_swap)
485{
486    int res=BadImplementation;
487    ClientPtr client = a_cl->client;
488    xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) a_pc;
489
490    EPHYR_LOG ("enter. id:%d\n", (int)req->context) ;
491    if (!ephyrHostDestroyContext (req->context)) {
492        EPHYR_LOG_ERROR ("ephyrHostDestroyContext() failed\n") ;
493        client->errorValue = req->context ;
494        goto out ;
495    }
496    res = Success ;
497
498out:
499    EPHYR_LOG ("leave\n") ;
500    return res ;
501}
502
503int
504ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc)
505{
506    return ephyrGLXDestroyContextReal (a_cl, a_pc, FALSE) ;
507}
508
509int
510ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc)
511{
512    return ephyrGLXDestroyContextReal (a_cl, a_pc, TRUE) ;
513}
514
515static int
516ephyrGLXMakeCurrentReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
517{
518    int res=BadImplementation;
519    xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc;
520    xGLXMakeCurrentReply reply ;
521    DrawablePtr drawable=NULL;
522    int rc=0;
523
524    EPHYR_LOG ("enter\n") ;
525    rc = dixLookupDrawable (&drawable,
526                            req->drawable,
527                            a_cl->client,
528                            0,
529                            DixReadAccess);
530    EPHYR_RETURN_VAL_IF_FAIL (drawable, BadValue) ;
531    EPHYR_RETURN_VAL_IF_FAIL (drawable->pScreen, BadValue) ;
532    EPHYR_LOG ("screen nummber requested:%d\n",
533               drawable->pScreen->myNum) ;
534
535    memset (&reply, 0, sizeof (reply)) ;
536    if (!ephyrHostGLXMakeCurrent (hostx_get_window (drawable->pScreen->myNum),
537                                  req->context,
538                                  req->oldContextTag,
539                                  (int*)&reply.contextTag)) {
540        EPHYR_LOG_ERROR ("ephyrHostGLXMakeCurrent() failed\n") ;
541        goto out;
542    }
543    reply.length = 0;
544    reply.type = X_Reply;
545    reply.sequenceNumber = a_cl->client->sequence;
546    if (a_do_swap) {
547        __GLX_DECLARE_SWAP_VARIABLES;
548        __GLX_SWAP_SHORT(&reply.sequenceNumber);
549        __GLX_SWAP_INT(&reply.length);
550        __GLX_SWAP_INT(&reply.contextTag);
551    }
552    WriteToClient(a_cl->client, sz_xGLXMakeCurrentReply, (char *)&reply);
553
554    res = Success ;
555out:
556    EPHYR_LOG ("leave\n") ;
557    return res ;
558}
559
560int
561ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc)
562{
563    return ephyrGLXMakeCurrentReal (a_cl, a_pc, FALSE) ;
564}
565
566int
567ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc)
568{
569    return ephyrGLXMakeCurrentReal (a_cl, a_pc, TRUE) ;
570}
571
572static int
573ephyrGLXGetStringReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
574{
575    ClientPtr client=NULL ;
576    int context_tag=0, name=0, res=BadImplementation, length=0 ;
577    char *string=NULL;
578    __GLX_DECLARE_SWAP_VARIABLES;
579
580    EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, BadValue) ;
581
582    EPHYR_LOG ("enter\n") ;
583
584    client = a_cl->client ;
585
586    if (a_do_swap) {
587        __GLX_SWAP_INT (a_pc + 4);
588        __GLX_SWAP_INT (a_pc + __GLX_SINGLE_HDR_SIZE);
589    }
590    context_tag = __GLX_GET_SINGLE_CONTEXT_TAG (a_pc) ;
591    a_pc += __GLX_SINGLE_HDR_SIZE;
592    name = *(GLenum*)(a_pc + 0);
593    EPHYR_LOG ("context_tag:%d, name:%d\n", context_tag, name) ;
594    if (!ephyrHostGLXGetStringFromServer (context_tag,
595                                          name,
596                                          EPHYR_HOST_GLX_GetString,
597                                          &string)) {
598        EPHYR_LOG_ERROR ("failed to get string from server\n") ;
599        goto out ;
600    }
601    if (string) {
602        length = strlen (string) + 1;
603        EPHYR_LOG ("got string:'%s', size:%d\n", string, length) ;
604    } else {
605        EPHYR_LOG ("got string: string (null)\n") ;
606    }
607    __GLX_BEGIN_REPLY (length);
608    __GLX_PUT_SIZE (length);
609    __GLX_SEND_HEADER ();
610    if (a_do_swap) {
611        __GLX_SWAP_REPLY_SIZE ();
612        __GLX_SWAP_REPLY_HEADER ();
613    }
614    WriteToClient (client, length, (char *)string);
615
616    res = Success ;
617out:
618    EPHYR_LOG ("leave\n") ;
619    return res ;
620}
621
622int
623ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc)
624{
625    return ephyrGLXGetStringReal (a_cl, a_pc, FALSE) ;
626}
627
628int
629ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc)
630{
631    return ephyrGLXGetStringReal (a_cl, a_pc, TRUE) ;
632}
633
634static int
635ephyrGLXGetIntegervReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
636{
637    int res=BadImplementation;
638    xGLXSingleReq * const req = (xGLXSingleReq *) a_pc;
639    GLenum int_name ;
640    int value=0 ;
641    GLint answer_buf_room[200];
642    GLint *buf=NULL ;
643
644    EPHYR_LOG ("enter\n") ;
645
646    a_pc += __GLX_SINGLE_HDR_SIZE;
647
648    int_name = *(GLenum*) (a_pc+0) ;
649    if (!ephyrHostGetIntegerValue (req->contextTag, int_name, &value)) {
650        EPHYR_LOG_ERROR ("ephyrHostGetIntegerValue() failed\n") ;
651        goto out ;
652    }
653    buf = __glXGetAnswerBuffer (a_cl, sizeof (value),
654                                answer_buf_room,
655                                sizeof (answer_buf_room),
656                                4) ;
657
658    if (!buf) {
659        EPHYR_LOG_ERROR ("failed to allocate reply buffer\n") ;
660        res = BadAlloc ;
661        goto out ;
662    }
663    __glXSendReply (a_cl->client, buf, 1, sizeof (value), GL_FALSE, 0) ;
664    res = Success ;
665
666out:
667    EPHYR_LOG ("leave\n") ;
668    return res ;
669}
670
671int
672ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc)
673{
674    return ephyrGLXGetIntegervReal (a_cl, a_pc, FALSE) ;
675}
676
677int
678ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc)
679{
680    return ephyrGLXGetIntegervReal (a_cl, a_pc, TRUE) ;
681}
682
683static int
684ephyrGLXIsDirectReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
685{
686    int res=BadImplementation;
687    ClientPtr client = a_cl->client;
688    xGLXIsDirectReq *req = (xGLXIsDirectReq *) a_pc;
689    xGLXIsDirectReply reply;
690    int is_direct=0 ;
691
692    EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, FALSE) ;
693
694    EPHYR_LOG ("enter\n") ;
695
696    memset (&reply, 0, sizeof (reply)) ;
697    if (!ephyrHostIsContextDirect (req->context, (int*)&is_direct)) {
698        EPHYR_LOG_ERROR ("ephyrHostIsContextDirect() failed\n") ;
699        goto out ;
700    }
701    reply.isDirect = is_direct ;
702    reply.length = 0;
703    reply.type = X_Reply;
704    reply.sequenceNumber = client->sequence;
705    WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply);
706    res = Success ;
707
708out:
709    EPHYR_LOG ("leave\n") ;
710    return res ;
711}
712
713int
714ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc)
715{
716    return ephyrGLXIsDirectReal (a_cl, a_pc, FALSE) ;
717}
718
719int
720ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc)
721{
722    return ephyrGLXIsDirectReal (a_cl, a_pc, TRUE) ;
723}
724