Enable DRI2 based on Dodji Seketeli's DRI work
[xephyr-with-gl-acceleration:xephyr-with-gl-acceleration.git] / xserver / hw / kdrive / ephyr / ephyrglxext.c
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
54 int ephyrGLXQueryVersion (__GLXclientState *cl, GLbyte *pc) ;
55 int ephyrGLXQueryVersionSwap (__GLXclientState *cl, GLbyte *pc) ;
56 int ephyrGLXGetVisualConfigs (__GLXclientState *cl, GLbyte *pc) ;
57 int ephyrGLXGetVisualConfigsSwap (__GLXclientState *cl, GLbyte *pc) ;
58 int ephyrGLXClientInfo(__GLXclientState *cl, GLbyte *pc) ;
59 int ephyrGLXClientInfoSwap(__GLXclientState *cl, GLbyte *pc) ;
60 int ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc) ;
61 int ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc) ;
62 int ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc);
63 int ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc);
64 int ephyrGLXCreateContext (__GLXclientState *a_cl, GLbyte *a_pc);
65 int ephyrGLXCreateContextSwap (__GLXclientState *a_cl, GLbyte *a_pc);
66 int ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc) ;
67 int ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
68 int ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc) ;
69 int ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
70 int ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc) ;
71 int ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
72 int ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc) ;
73 int ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
74 int ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc) ;
75 int ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc) ;
76
77 Bool
78 ephyrHijackGLXExtension (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
145 int
146 ephyrGLXQueryVersion(__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 ;
178 out:
179     EPHYR_LOG ("leave\n") ;
180     return res;
181 }
182
183 int
184 ephyrGLXQueryVersionSwap (__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
195 static int
196 ephyrGLXGetVisualConfigsReal (__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
244 out:
245     EPHYR_LOG ("leave\n") ;
246     if (props_buf) {
247         xfree (props_buf) ;
248         props_buf = NULL ;
249     }
250     return res ;
251 }
252
253 static int
254 ephyrGLXGetFBConfigsSGIXReal (__GLXclientState *a_cl,
255                               GLbyte *a_pc,
256                               Bool a_do_swap)
257 {
258     xGLXGetFBConfigsSGIXReq *req = (xGLXGetFBConfigsSGIXReq *)a_pc;
259     ClientPtr client = a_cl->client;
260     xGLXGetVisualConfigsReply reply;
261     int32_t *props_buf=NULL, num_visuals=0,
262             num_props=0, res=BadImplementation, i=0,
263             props_per_visual_size=0,
264             props_buf_size=0;
265     __GLX_DECLARE_SWAP_VARIABLES;
266     __GLX_DECLARE_SWAP_ARRAY_VARIABLES;
267
268     EPHYR_LOG ("enter\n") ;
269
270     if (!ephyrHostGLXVendorPrivGetFBConfigsSGIX (req->screen,
271                                                  &num_visuals,
272                                                  &num_props,
273                                                  &props_buf_size,
274                                                  &props_buf)) {
275         EPHYR_LOG_ERROR ("ephyrHostGLXGetVisualConfigs() failed\n") ;
276         goto out ;
277     }
278     EPHYR_LOG ("num_visuals:%d, num_props:%d\n", num_visuals, num_props) ;
279
280     reply.numVisuals = num_visuals;
281     reply.numProps = num_props;
282     reply.length = props_buf_size >> 2;
283     reply.type = X_Reply;
284     reply.sequenceNumber = client->sequence;
285
286     if (a_do_swap) {
287         __GLX_SWAP_SHORT(&reply.sequenceNumber);
288         __GLX_SWAP_INT(&reply.length);
289         __GLX_SWAP_INT(&reply.numVisuals);
290         __GLX_SWAP_INT(&reply.numProps);
291         __GLX_SWAP_INT_ARRAY (props_buf, num_props) ;
292     }
293     WriteToClient(client, sz_xGLXGetVisualConfigsReply, (char*)&reply);
294     props_per_visual_size = props_buf_size/num_visuals ;
295     for (i=0; i < num_visuals; i++) {
296         WriteToClient (client,
297                        props_per_visual_size,
298                        &((char*)props_buf)[i*props_per_visual_size]);
299     }
300     res = Success ;
301
302 out:
303     EPHYR_LOG ("leave\n") ;
304     if (props_buf) {
305         xfree (props_buf) ;
306         props_buf = NULL ;
307     }
308     return res ;
309 }
310
311 int
312 ephyrGLXGetVisualConfigs (__GLXclientState *a_cl, GLbyte *a_pc)
313 {
314     return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, FALSE) ;
315 }
316
317 int
318 ephyrGLXGetVisualConfigsSwap (__GLXclientState *a_cl, GLbyte *a_pc)
319 {
320     return ephyrGLXGetVisualConfigsReal (a_cl, a_pc, TRUE) ;
321 }
322
323
324 int
325 ephyrGLXClientInfo(__GLXclientState *a_cl, GLbyte *a_pc)
326 {
327     int res=BadImplementation ;
328     xGLXClientInfoReq *req = (xGLXClientInfoReq *) a_pc;
329
330     EPHYR_LOG ("enter\n") ;
331     if (!ephyrHostGLXSendClientInfo (req->major, req->minor, (char*)req+1)) {
332         EPHYR_LOG_ERROR ("failed to send client info to host\n") ;
333         goto out ;
334     }
335     res = Success ;
336
337 out:
338     EPHYR_LOG ("leave\n") ;
339     return res ;
340 }
341
342 int
343 ephyrGLXClientInfoSwap (__GLXclientState *a_cl, GLbyte *a_pc)
344 {
345     xGLXClientInfoReq *req = (xGLXClientInfoReq *)a_pc;
346     __GLX_DECLARE_SWAP_VARIABLES;
347
348     __GLX_SWAP_SHORT (&req->length);
349     __GLX_SWAP_INT (&req->major);
350     __GLX_SWAP_INT (&req->minor);
351     __GLX_SWAP_INT (&req->numbytes);
352
353     return ephyrGLXClientInfo (a_cl, a_pc) ;
354 }
355
356 int
357 ephyrGLXQueryServerString(__GLXclientState *a_cl, GLbyte *a_pc)
358 {
359     int res = BadImplementation ;
360     ClientPtr client = a_cl->client;
361     xGLXQueryServerStringReq *req = (xGLXQueryServerStringReq *) a_pc;
362     xGLXQueryServerStringReply reply;
363     char *server_string=NULL, *buf=NULL;
364     int length=0 ;
365
366     EPHYR_LOG ("enter\n") ;
367     if (!ephyrHostGLXGetStringFromServer (req->screen,
368                                           req->name,
369                                           EPHYR_HOST_GLX_QueryServerString,
370                                           &server_string)) {
371         EPHYR_LOG_ERROR ("failed to query string from host\n") ;
372         goto out ;
373     }
374     EPHYR_LOG ("string: %s\n", server_string) ;
375     length= strlen (server_string) + 1;
376     reply.type = X_Reply ;
377     reply.sequenceNumber = client->sequence ;
378     reply.length = __GLX_PAD (length) >> 2 ;
379     reply.n = length ;
380     buf = xcalloc (reply.length << 2, 1);
381     if (!buf) {
382         EPHYR_LOG_ERROR ("failed to allocate string\n;");
383         return BadAlloc;
384     }
385     memcpy (buf, server_string, length);
386
387     WriteToClient(client, sz_xGLXQueryServerStringReply, (char*)&reply);
388     WriteToClient(client, (int)(reply.length << 2), server_string);
389
390     res = Success ;
391
392 out:
393     EPHYR_LOG ("leave\n") ;
394     if (server_string) {
395         xfree (server_string) ;
396         server_string = NULL;
397     }
398     if (buf) {
399         xfree (buf);
400         buf = NULL;
401     }
402     return res ;
403 }
404
405 int
406 ephyrGLXQueryServerStringSwap(__GLXclientState *a_cl, GLbyte *a_pc)
407 {
408     EPHYR_LOG_ERROR ("not yet implemented\n") ;
409     return BadImplementation ;
410 }
411
412
413 int
414 ephyrGLXGetFBConfigsSGIX (__GLXclientState *a_cl, GLbyte *a_pc)
415 {
416     return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, FALSE) ;
417 }
418
419 int
420 ephyrGLXGetFBConfigsSGIXSwap (__GLXclientState *a_cl, GLbyte *a_pc)
421 {
422     return ephyrGLXGetFBConfigsSGIXReal (a_cl, a_pc, TRUE) ;
423 }
424
425 static int
426 ephyrGLXCreateContextReal (xGLXCreateContextReq *a_req, Bool a_do_swap)
427 {
428     int res=BadImplementation;
429     EphyrHostWindowAttributes host_w_attrs ;
430     __GLX_DECLARE_SWAP_VARIABLES;
431
432     EPHYR_RETURN_VAL_IF_FAIL (a_req, BadValue) ;
433     EPHYR_LOG ("enter\n") ;
434
435     if (a_do_swap) {
436         __GLX_SWAP_SHORT(&a_req->length);
437         __GLX_SWAP_INT(&a_req->context);
438         __GLX_SWAP_INT(&a_req->visual);
439         __GLX_SWAP_INT(&a_req->screen);
440         __GLX_SWAP_INT(&a_req->shareList);
441     }
442
443     EPHYR_LOG ("context creation requested. localid:%d, "
444                "screen:%d, visual:%d, direct:%d\n",
445                (int)a_req->context, (int)a_req->screen,
446                (int)a_req->visual, (int)a_req->isDirect) ;
447
448     memset (&host_w_attrs, 0, sizeof (host_w_attrs)) ;
449     if (!hostx_get_window_attributes (hostx_get_window (a_req->screen),
450                                       &host_w_attrs)) {
451         EPHYR_LOG_ERROR ("failed to get host window attrs\n") ;
452         goto out ;
453     }
454
455     EPHYR_LOG ("host window visual id: %d\n", host_w_attrs.visualid) ;
456
457     if (!ephyrHostGLXCreateContext (a_req->screen,
458 #if 1
459                                                                         a_req->visual,
460 #else
461                                     host_w_attrs.visualid,
462 #endif
463                                     a_req->context,
464                                     a_req->shareList,
465                                     a_req->isDirect)) {
466         EPHYR_LOG_ERROR ("ephyrHostGLXCreateContext() failed\n") ;
467         goto out ;
468     }
469     res = Success;
470 out:
471     EPHYR_LOG ("leave\n") ;
472     return res ;
473 }
474
475 int
476 ephyrGLXCreateContext (__GLXclientState *cl, GLbyte *pc)
477 {
478     xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc;
479
480     return ephyrGLXCreateContextReal (req, FALSE) ;
481 }
482
483 int ephyrGLXCreateContextSwap (__GLXclientState *cl, GLbyte *pc)
484 {
485     xGLXCreateContextReq *req = (xGLXCreateContextReq *) pc;
486     return ephyrGLXCreateContextReal (req, TRUE) ;
487 }
488
489 static int
490 ephyrGLXDestroyContextReal (__GLXclientState *a_cl,
491                             GLbyte *a_pc,
492                             Bool a_do_swap)
493 {
494     int res=BadImplementation;
495     ClientPtr client = a_cl->client;
496     xGLXDestroyContextReq *req = (xGLXDestroyContextReq *) a_pc;
497
498     EPHYR_LOG ("enter. id:%d\n", (int)req->context) ;
499     if (!ephyrHostDestroyContext (req->context)) {
500         EPHYR_LOG_ERROR ("ephyrHostDestroyContext() failed\n") ;
501         client->errorValue = req->context ;
502         goto out ;
503     }
504     res = Success ;
505
506 out:
507     EPHYR_LOG ("leave\n") ;
508     return res ;
509 }
510
511 int
512 ephyrGLXDestroyContext (__GLXclientState *a_cl, GLbyte *a_pc)
513 {
514     return ephyrGLXDestroyContextReal (a_cl, a_pc, FALSE) ;
515 }
516
517 int
518 ephyrGLXDestroyContextSwap (__GLXclientState *a_cl, GLbyte *a_pc)
519 {
520     return ephyrGLXDestroyContextReal (a_cl, a_pc, TRUE) ;
521 }
522
523 static int
524 ephyrGLXMakeCurrentReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
525 {
526     int res=BadImplementation;
527     xGLXMakeCurrentReq *req = (xGLXMakeCurrentReq *) a_pc;
528     xGLXMakeCurrentReply reply ;
529     DrawablePtr drawable=NULL;
530     int rc=0;
531
532     EPHYR_LOG ("enter\n") ;
533     rc = dixLookupDrawable (&drawable,
534                             req->drawable,
535                             a_cl->client,
536                             0,
537                             DixReadAccess);
538     EPHYR_RETURN_VAL_IF_FAIL (drawable, BadValue) ;
539     EPHYR_RETURN_VAL_IF_FAIL (drawable->pScreen, BadValue) ;
540     EPHYR_LOG ("screen nummber requested:%d\n",
541                drawable->pScreen->myNum) ;
542
543     memset (&reply, 0, sizeof (reply)) ;
544     if (!ephyrHostGLXMakeCurrent (hostx_get_window (drawable->pScreen->myNum),
545                                   req->context,
546                                   req->oldContextTag,
547                                   (int*)&reply.contextTag)) {
548         EPHYR_LOG_ERROR ("ephyrHostGLXMakeCurrent() failed\n") ;
549         goto out;
550     }
551     reply.length = 0;
552     reply.type = X_Reply;
553     reply.sequenceNumber = a_cl->client->sequence;
554     if (a_do_swap) {
555         __GLX_DECLARE_SWAP_VARIABLES;
556         __GLX_SWAP_SHORT(&reply.sequenceNumber);
557         __GLX_SWAP_INT(&reply.length);
558         __GLX_SWAP_INT(&reply.contextTag);
559     }
560     WriteToClient(a_cl->client, sz_xGLXMakeCurrentReply, (char *)&reply);
561
562     res = Success ;
563 out:
564     EPHYR_LOG ("leave\n") ;
565     return res ;
566 }
567
568 int
569 ephyrGLXMakeCurrent (__GLXclientState *a_cl, GLbyte *a_pc)
570 {
571     return ephyrGLXMakeCurrentReal (a_cl, a_pc, FALSE) ;
572 }
573
574 int
575 ephyrGLXMakeCurrentSwap (__GLXclientState *a_cl, GLbyte *a_pc)
576 {
577     return ephyrGLXMakeCurrentReal (a_cl, a_pc, TRUE) ;
578 }
579
580 static int
581 ephyrGLXGetStringReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
582 {
583     ClientPtr client=NULL ;
584     int context_tag=0, name=0, res=BadImplementation, length=0 ;
585     char *string=NULL;
586     __GLX_DECLARE_SWAP_VARIABLES;
587
588     EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, BadValue) ;
589
590     EPHYR_LOG ("enter\n") ;
591
592     client = a_cl->client ;
593
594     if (a_do_swap) {
595         __GLX_SWAP_INT (a_pc + 4);
596         __GLX_SWAP_INT (a_pc + __GLX_SINGLE_HDR_SIZE);
597     }
598     context_tag = __GLX_GET_SINGLE_CONTEXT_TAG (a_pc) ;
599     a_pc += __GLX_SINGLE_HDR_SIZE;
600     name = *(GLenum*)(a_pc + 0);
601     EPHYR_LOG ("context_tag:%d, name:%d\n", context_tag, name) ;
602     if (!ephyrHostGLXGetStringFromServer (context_tag,
603                                           name,
604                                           EPHYR_HOST_GLX_GetString,
605                                           &string)) {
606         EPHYR_LOG_ERROR ("failed to get string from server\n") ;
607         goto out ;
608     }
609     if (string) {
610         length = strlen (string) + 1;
611         EPHYR_LOG ("got string:'%s', size:%d\n", string, length) ;
612     } else {
613         EPHYR_LOG ("got string: string (null)\n") ;
614     }
615     __GLX_BEGIN_REPLY (length);
616     __GLX_PUT_SIZE (length);
617     __GLX_SEND_HEADER ();
618     if (a_do_swap) {
619         __GLX_SWAP_REPLY_SIZE ();
620         __GLX_SWAP_REPLY_HEADER ();
621     }
622     WriteToClient (client, length, (char *)string);
623
624     res = Success ;
625 out:
626     EPHYR_LOG ("leave\n") ;
627     return res ;
628 }
629
630 int
631 ephyrGLXGetString (__GLXclientState *a_cl, GLbyte *a_pc)
632 {
633     return ephyrGLXGetStringReal (a_cl, a_pc, FALSE) ;
634 }
635
636 int
637 ephyrGLXGetStringSwap (__GLXclientState *a_cl, GLbyte *a_pc)
638 {
639     return ephyrGLXGetStringReal (a_cl, a_pc, TRUE) ;
640 }
641
642 static int
643 ephyrGLXGetIntegervReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
644 {
645     int res=BadImplementation;
646     xGLXSingleReq * const req = (xGLXSingleReq *) a_pc;
647     GLenum int_name ;
648     int value=0 ;
649     GLint answer_buf_room[200];
650     GLint *buf=NULL ;
651
652     EPHYR_LOG ("enter\n") ;
653
654     a_pc += __GLX_SINGLE_HDR_SIZE;
655
656     int_name = *(GLenum*) (a_pc+0) ;
657     if (!ephyrHostGetIntegerValue (req->contextTag, int_name, &value)) {
658         EPHYR_LOG_ERROR ("ephyrHostGetIntegerValue() failed\n") ;
659         goto out ;
660     }
661     buf = __glXGetAnswerBuffer (a_cl, sizeof (value),
662                                 answer_buf_room,
663                                 sizeof (answer_buf_room),
664                                 4) ;
665
666     if (!buf) {
667         EPHYR_LOG_ERROR ("failed to allocate reply buffer\n") ;
668         res = BadAlloc ;
669         goto out ;
670     }
671     __glXSendReply (a_cl->client, buf, 1, sizeof (value), GL_FALSE, 0) ;
672     res = Success ;
673
674 out:
675     EPHYR_LOG ("leave\n") ;
676     return res ;
677 }
678
679 int
680 ephyrGLXGetIntegerv (__GLXclientState *a_cl, GLbyte *a_pc)
681 {
682     return ephyrGLXGetIntegervReal (a_cl, a_pc, FALSE) ;
683 }
684
685 int
686 ephyrGLXGetIntegervSwap (__GLXclientState *a_cl, GLbyte *a_pc)
687 {
688     return ephyrGLXGetIntegervReal (a_cl, a_pc, TRUE) ;
689 }
690
691 static int
692 ephyrGLXIsDirectReal (__GLXclientState *a_cl, GLbyte *a_pc, Bool a_do_swap)
693 {
694     int res=BadImplementation;
695     ClientPtr client = a_cl->client;
696     xGLXIsDirectReq *req = (xGLXIsDirectReq *) a_pc;
697     xGLXIsDirectReply reply;
698     int is_direct=0 ;
699
700     EPHYR_RETURN_VAL_IF_FAIL (a_cl && a_pc, FALSE) ;
701
702     EPHYR_LOG ("enter\n") ;
703
704     memset (&reply, 0, sizeof (reply)) ;
705     if (!ephyrHostIsContextDirect (req->context, (int*)&is_direct)) {
706         EPHYR_LOG_ERROR ("ephyrHostIsContextDirect() failed\n") ;
707         goto out ;
708     }
709     reply.isDirect = is_direct ;
710     reply.length = 0;
711     reply.type = X_Reply;
712     reply.sequenceNumber = client->sequence;
713     WriteToClient(client, sz_xGLXIsDirectReply, (char *)&reply);
714     res = Success ;
715
716 out:
717     EPHYR_LOG ("leave\n") ;
718     return res ;
719 }
720
721 int
722 ephyrGLXIsDirect (__GLXclientState *a_cl, GLbyte *a_pc)
723 {
724     return ephyrGLXIsDirectReal (a_cl, a_pc, FALSE) ;
725 }
726
727 int
728 ephyrGLXIsDirectSwap (__GLXclientState *a_cl, GLbyte *a_pc)
729 {
730     return ephyrGLXIsDirectReal (a_cl, a_pc, TRUE) ;
731 }