ephyrhostglx.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 * a lots of the content of this file has been adapted from the mesa source
26 * code.
27 * Authors:
28 *    Dodji Seketeli <dodji@openedhand.com>
29 */
30#ifdef HAVE_CONFIG_H
31#include <kdrive-config.h>
32#endif
33
34/*
35 * including some server headers (like kdrive-config.h)
36 * might define the macro _XSERVER64
37 * on 64 bits machines. That macro must _NOT_ be defined for Xlib
38 * client code, otherwise bad things happen.
39 * So let's undef that macro if necessary.
40 */
41#ifdef _XSERVER64
42#undef _XSERVER64
43#endif
44
45#include <X11/Xlibint.h>
46#include <GL/glx.h>
47#include <GL/internal/glcore.h>
48#include <GL/glxproto.h>
49#include <GL/glxint.h>
50#include "ephyrhostglx.h"
51#define _HAVE_XALLOC_DECLS
52#include "ephyrlog.h"
53#include "hostx.h"
54
55enum VisualConfRequestType {
56    EPHYR_GET_FB_CONFIG,
57    EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX,
58    EPHYR_GET_VISUAL_CONFIGS
59
60};
61
62static Bool ephyrHostGLXGetVisualConfigsInternal
63                                        (enum VisualConfRequestType a_type,
64                                         int32_t a_screen,
65                                         int32_t *a_num_visuals,
66                                         int32_t *a_num_props,
67                                         int32_t *a_props_buf_size,
68                                         int32_t **a_props_buf);
69Bool
70ephyrHostGLXGetMajorOpcode (int *a_opcode)
71{
72    Bool is_ok=FALSE ;
73    Display *dpy=hostx_get_display () ;
74    static int opcode ;
75    int first_event_return=0, first_error_return=0;
76
77    EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ;
78    EPHYR_LOG ("enter\n") ;
79    if (!opcode) {
80        if (!XQueryExtension (dpy, GLX_EXTENSION_NAME, &opcode,
81                              &first_event_return, &first_error_return)) {
82            EPHYR_LOG_ERROR ("XQueryExtension() failed\n") ;
83            goto out ;
84        }
85    }
86    *a_opcode = opcode ;
87    is_ok = TRUE ;
88out:
89    EPHYR_LOG ("release\n") ;
90    return is_ok ;
91}
92
93Bool
94ephyrHostGLXQueryVersion (int *a_major, int *a_minor)
95{
96    Bool is_ok = FALSE ;
97    Display *dpy = hostx_get_display () ;
98    int major_opcode=0;
99    xGLXQueryVersionReq *req=NULL;
100    xGLXQueryVersionReply reply;
101
102    EPHYR_RETURN_VAL_IF_FAIL (a_major && a_minor, FALSE) ;
103    EPHYR_LOG ("enter\n") ;
104
105    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
106        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
107        goto out ;
108    }
109    EPHYR_LOG ("major opcode: %d\n", major_opcode) ;
110
111    /* Send the glXQueryVersion request */
112    memset (&reply, 0, sizeof (reply)) ;
113    LockDisplay (dpy);
114    GetReq (GLXQueryVersion, req);
115    req->reqType = major_opcode;
116    req->glxCode = X_GLXQueryVersion;
117    req->majorVersion = 2;
118    req->minorVersion = 1;
119    _XReply(dpy, (xReply*) &reply, 0, False);
120    UnlockDisplay (dpy);
121    SyncHandle ();
122
123    *a_major = reply.majorVersion ;
124    *a_minor = reply.minorVersion ;
125
126    EPHYR_LOG ("major:%d, minor:%d\n", *a_major, *a_minor) ;
127
128    is_ok = TRUE ;
129out:
130    EPHYR_LOG ("leave\n") ;
131    return is_ok ;
132}
133
134/**
135 * GLX protocol structure for the ficticious "GXLGenericGetString" request.
136 *
137 * This is a non-existant protocol packet.  It just so happens that all of
138 * the real protocol packets used to request a string from the server have
139 * an identical binary layout.  The only difference between them is the
140 * meaning of the \c for_whom field and the value of the \c glxCode.
141 * (this has been copied from the mesa source code)
142 */
143typedef struct GLXGenericGetString {
144    CARD8 reqType;
145    CARD8 glxCode;
146    CARD16 length B16;
147    CARD32 for_whom B32;
148    CARD32 name B32;
149} xGLXGenericGetStringReq;
150
151/* These defines are only needed to make the GetReq macro happy.
152 */
153#define sz_xGLXGenericGetStringReq 12
154#define X_GLXGenericGetString 0
155
156Bool
157ephyrHostGLXGetStringFromServer (int a_screen_number,
158                                 int a_string_name,
159                                 enum EphyrHostGLXGetStringOps a_op,
160                                 char **a_string)
161{
162    Bool is_ok=FALSE ;
163    Display *dpy = hostx_get_display () ;
164    int default_screen = DefaultScreen (dpy);
165    xGLXGenericGetStringReq *req=NULL;
166    xGLXSingleReply reply;
167    int length=0, numbytes=0, major_opcode=0, get_string_op=0;
168
169    EPHYR_RETURN_VAL_IF_FAIL (dpy && a_string, FALSE) ;
170
171    EPHYR_LOG ("enter\n") ;
172    switch (a_op) {
173        case EPHYR_HOST_GLX_QueryServerString:
174            get_string_op = X_GLXQueryServerString;
175            break ;
176        case EPHYR_HOST_GLX_GetString:
177            get_string_op = X_GLsop_GetString;
178            EPHYR_LOG ("Going to glXGetString. strname:%#x, ctxttag:%d\n",
179                       a_string_name, a_screen_number) ;
180            break ;
181        default:
182            EPHYR_LOG_ERROR ("unknown EphyrHostGLXGetStringOp:%d\n", a_op) ;
183            goto out ;
184    }
185
186    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
187        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
188        goto out ;
189    }
190    EPHYR_LOG ("major opcode: %d\n", major_opcode) ;
191
192    LockDisplay (dpy);
193
194    /* All of the GLX protocol requests for getting a string from the server
195     * look the same.  The exact meaning of the a_for_whom field is usually
196     * either the screen number (for glXQueryServerString) or the context tag
197     * (for GLXSingle).
198     */
199    GetReq (GLXGenericGetString, req);
200    req->reqType = major_opcode;
201    req->glxCode = get_string_op;
202    req->for_whom = default_screen;
203    req->name = a_string_name;
204
205    _XReply (dpy, (xReply *)&reply, 0, False);
206
207    length = reply.length * 4;
208    if (!length) {
209        numbytes = 0;
210    } else {
211        numbytes = reply.size;
212    }
213    EPHYR_LOG ("going to get a string of size:%d\n", numbytes) ;
214
215    *a_string = (char *) Xmalloc (numbytes +1);
216    if (!a_string) {
217        EPHYR_LOG_ERROR ("allocation failed\n") ;
218        goto out;
219    }
220
221    memset (*a_string, 0, numbytes+1) ;
222    if (_XRead (dpy, *a_string, numbytes)) {
223        UnlockDisplay (dpy);
224        SyncHandle ();
225        EPHYR_LOG_ERROR ("read failed\n") ;
226        goto out ;
227    }
228    length -= numbytes;
229    _XEatData (dpy, length) ;
230    UnlockDisplay (dpy);
231    SyncHandle ();
232    EPHYR_LOG ("strname:%#x, strvalue:'%s', strlen:%d\n",
233               a_string_name, *a_string, numbytes) ;
234
235    is_ok = TRUE ;
236out:
237    EPHYR_LOG ("leave\n") ;
238    return is_ok ;
239}
240
241static Bool
242ephyrHostGLXGetVisualConfigsInternal (enum VisualConfRequestType a_type,
243                                      int32_t a_screen,
244                                      int32_t *a_num_visuals,
245                                      int32_t *a_num_props,
246                                      int32_t *a_props_buf_size,
247                                      int32_t **a_props_buf)
248{
249    Bool is_ok = FALSE ;
250    Display *dpy = hostx_get_display () ;
251    xGLXGetVisualConfigsReq *req;
252    xGLXGetFBConfigsReq *fb_req;
253    xGLXVendorPrivateWithReplyReq *vpreq;
254    xGLXGetFBConfigsSGIXReq *sgi_req;
255    xGLXGetVisualConfigsReply reply;
256    char *server_glx_version=NULL,
257         *server_glx_extensions=NULL ;
258    int j=0,
259        screens=0,
260        major_opcode=0,
261        num_props=0,
262        num_visuals=0,
263        props_buf_size=0,
264        props_per_visual_size=0;
265    int32_t *props_buf=NULL;
266
267    EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ;
268
269    screens = ScreenCount (dpy);
270    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
271        EPHYR_LOG_ERROR ("failed to get opcode\n") ;
272        goto out ;
273    }
274
275    LockDisplay(dpy);
276    switch (a_type) {
277        case EPHYR_GET_FB_CONFIG:
278        GetReq(GLXGetFBConfigs,fb_req);
279        fb_req->reqType = major_opcode;
280        fb_req->glxCode = X_GLXGetFBConfigs;
281        fb_req->screen = DefaultScreen (dpy);
282        break;
283
284        case EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX:
285        GetReqExtra(GLXVendorPrivateWithReply,
286                    sz_xGLXGetFBConfigsSGIXReq
287                         -
288                    sz_xGLXVendorPrivateWithReplyReq,
289                    vpreq);
290        sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
291        sgi_req->reqType = major_opcode;
292        sgi_req->glxCode = X_GLXVendorPrivateWithReply;
293        sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
294        sgi_req->screen = DefaultScreen (dpy);
295        break;
296
297        case EPHYR_GET_VISUAL_CONFIGS:
298        GetReq(GLXGetVisualConfigs,req);
299        req->reqType = major_opcode;
300        req->glxCode = X_GLXGetVisualConfigs;
301        req->screen = DefaultScreen (dpy);
302        break;
303    }
304
305    if (!_XReply(dpy, (xReply*) &reply, 0, False)) {
306        EPHYR_LOG_ERROR ("unknown error\n") ;
307        UnlockDisplay(dpy);
308        goto out ;
309    }
310   if (!reply.numVisuals) {
311        EPHYR_LOG_ERROR ("screen does not support GL rendering\n") ;
312        UnlockDisplay(dpy);
313        goto out ;
314    }
315   num_visuals = reply.numVisuals ;
316
317    /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for
318     * FIXME: FBconfigs?
319     */
320    /* Check number of properties */
321    num_props = reply.numProps;
322    if ((num_props < __GLX_MIN_CONFIG_PROPS) ||
323        (num_props > __GLX_MAX_CONFIG_PROPS)) {
324        /* Huh?  Not in protocol defined limits.  Punt */
325        EPHYR_LOG_ERROR ("got a bad reply to request\n") ;
326        UnlockDisplay(dpy);
327        goto out ;
328    }
329
330    if (a_type != EPHYR_GET_VISUAL_CONFIGS) {
331        num_props *= 2;
332    }
333    props_per_visual_size = num_props * __GLX_SIZE_INT32;
334    props_buf_size = props_per_visual_size * reply.numVisuals;
335    props_buf = malloc (props_buf_size) ;
336    for (j = 0; j < reply.numVisuals; j++) {
337        if (_XRead (dpy,
338                    &((char*)props_buf)[j*props_per_visual_size],
339                    props_per_visual_size) != Success) {
340            EPHYR_LOG_ERROR ("read failed\n") ;
341        }
342    }
343    UnlockDisplay(dpy);
344
345    *a_num_visuals = num_visuals ;
346    *a_num_props = reply.numProps ;
347    *a_props_buf_size = props_buf_size ;
348    *a_props_buf = props_buf ;
349    is_ok = TRUE ;
350
351out:
352    if (server_glx_version) {
353        XFree (server_glx_version) ;
354        server_glx_version = NULL ;
355    }
356    if (server_glx_extensions) {
357        XFree (server_glx_extensions) ;
358        server_glx_extensions = NULL ;
359    }
360    SyncHandle () ;
361    return is_ok;
362}
363
364Bool
365ephyrHostGLXGetVisualConfigs (int32_t a_screen,
366                              int32_t *a_num_visuals,
367                              int32_t *a_num_props,
368                              int32_t *a_props_buf_size,
369                              int32_t **a_props_buf)
370{
371    Bool is_ok = FALSE;
372
373    EPHYR_LOG ("enter\n") ;
374    is_ok = ephyrHostGLXGetVisualConfigsInternal (EPHYR_GET_VISUAL_CONFIGS,
375                                                  a_screen,
376                                                  a_num_visuals,
377                                                  a_num_props,
378                                                  a_props_buf_size,
379                                                  a_props_buf) ;
380
381    EPHYR_LOG ("leave:%d\n", is_ok) ;
382    return is_ok;
383}
384
385Bool
386ephyrHostGLXVendorPrivGetFBConfigsSGIX (int a_screen,
387                                        int32_t *a_num_visuals,
388                                        int32_t *a_num_props,
389                                        int32_t *a_props_buf_size,
390                                        int32_t **a_props_buf)
391{
392    Bool is_ok=FALSE ;
393    EPHYR_LOG ("enter\n") ;
394    is_ok = ephyrHostGLXGetVisualConfigsInternal
395                                        (EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX,
396                                         a_screen,
397                                         a_num_visuals,
398                                         a_num_props,
399                                         a_props_buf_size,
400                                         a_props_buf) ;
401    EPHYR_LOG ("leave\n") ;
402    return is_ok ;
403}
404
405Bool
406ephyrHostGLXSendClientInfo (int32_t a_major, int32_t a_minor,
407                            const char* a_extension_list)
408{
409    Bool is_ok = FALSE ;
410    Display *dpy = hostx_get_display () ;
411    xGLXClientInfoReq *req;
412    int size;
413    int32_t major_opcode=0 ;
414
415    EPHYR_RETURN_VAL_IF_FAIL (dpy && a_extension_list, FALSE) ;
416
417    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
418        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
419        goto out ;
420    }
421
422    LockDisplay (dpy);
423
424    GetReq (GLXClientInfo,req);
425    req->reqType = major_opcode;
426    req->glxCode = X_GLXClientInfo;
427    req->major = a_major;
428    req->minor = a_minor;
429
430    size = strlen (a_extension_list) + 1;
431    req->length += bytes_to_int32(size);
432    req->numbytes = size;
433    Data (dpy, a_extension_list, size);
434
435    UnlockDisplay(dpy);
436    SyncHandle();
437
438    is_ok=TRUE ;
439
440out:
441    return is_ok ;
442}
443
444Bool
445ephyrHostGLXCreateContext (int a_screen,
446                           int a_visual_id,
447                           int a_context_id,
448                           int a_share_list_ctxt_id,
449                           Bool a_direct)
450{
451    Bool is_ok = FALSE;
452    Display *dpy = hostx_get_display ();
453    int major_opcode=0, remote_context_id=0;
454    xGLXCreateContextReq *req;
455
456    EPHYR_LOG ("enter. screen:%d, visual:%d, contextid:%d, direct:%d\n",
457               a_screen, a_visual_id, a_context_id, a_direct) ;
458
459    if (!hostx_allocate_resource_id_peer (a_context_id, &remote_context_id)) {
460        EPHYR_LOG_ERROR ("failed to peer the context id %d host X",
461                         remote_context_id) ;
462        goto out ;
463    }
464
465    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
466        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
467        goto out ;
468    }
469
470    LockDisplay (dpy) ;
471
472    /* Send the glXCreateContext request */
473    GetReq(GLXCreateContext,req);
474    req->reqType = major_opcode;
475    req->glxCode = X_GLXCreateContext;
476    req->context = remote_context_id;
477    req->visual = a_visual_id;
478    req->screen = DefaultScreen (dpy);
479    req->shareList = a_share_list_ctxt_id;
480    req->isDirect = a_direct;
481
482    UnlockDisplay (dpy);
483    SyncHandle ();
484
485    is_ok = TRUE ;
486
487out:
488    EPHYR_LOG ("leave\n") ;
489    return is_ok ;
490}
491
492Bool
493ephyrHostDestroyContext (int a_ctxt_id)
494{
495    Bool is_ok=FALSE;
496    Display *dpy=hostx_get_display ();
497    int major_opcode=0, remote_ctxt_id=0 ;
498    xGLXDestroyContextReq *req=NULL;
499
500    EPHYR_LOG ("enter:%d\n", a_ctxt_id) ;
501
502    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
503        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
504        goto out ;
505    }
506    if (!hostx_get_resource_id_peer (a_ctxt_id, &remote_ctxt_id)) {
507        EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ;
508        goto out ;
509    }
510    EPHYR_LOG ("host context id:%d\n", remote_ctxt_id) ;
511
512    LockDisplay (dpy);
513    GetReq (GLXDestroyContext,req);
514    req->reqType = major_opcode;
515    req->glxCode = X_GLXDestroyContext;
516    req->context = remote_ctxt_id;
517    UnlockDisplay (dpy);
518    SyncHandle ();
519
520    is_ok = TRUE ;
521
522out:
523    EPHYR_LOG ("leave\n") ;
524    return is_ok ;
525}
526
527Bool
528ephyrHostGLXMakeCurrent (int a_drawable,
529                         int a_glx_ctxt_id,
530                         int a_old_ctxt_tag,
531                         int *a_ctxt_tag)
532{
533    Bool is_ok=FALSE ;
534    Display *dpy = hostx_get_display () ;
535    int32_t major_opcode=0 ;
536    int remote_glx_ctxt_id=0 ;
537    xGLXMakeCurrentReq *req;
538    xGLXMakeCurrentReply reply;
539
540    EPHYR_RETURN_VAL_IF_FAIL (a_ctxt_tag, FALSE) ;
541
542    EPHYR_LOG ("enter. drawable:%d, context:%d, oldtag:%d\n",
543               a_drawable, a_glx_ctxt_id, a_old_ctxt_tag) ;
544
545    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
546        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
547        goto out ;
548    }
549    if (!hostx_get_resource_id_peer (a_glx_ctxt_id, &remote_glx_ctxt_id)) {
550        EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ;
551        goto out ;
552    }
553
554    LockDisplay (dpy);
555
556    GetReq (GLXMakeCurrent,req);
557    req->reqType = major_opcode;
558    req->glxCode = X_GLXMakeCurrent;
559    req->drawable = a_drawable;
560    req->context = remote_glx_ctxt_id;
561    req->oldContextTag = a_old_ctxt_tag;
562
563    memset (&reply, 0, sizeof (reply)) ;
564    if (!_XReply (dpy, (xReply*)&reply, 0, False)) {
565        EPHYR_LOG_ERROR ("failed to get reply from host\n") ;
566        UnlockDisplay (dpy);
567        SyncHandle ();
568        goto out ;
569    }
570    UnlockDisplay (dpy);
571    SyncHandle ();
572    *a_ctxt_tag = reply.contextTag ;
573    EPHYR_LOG ("context tag:%d\n", *a_ctxt_tag) ;
574    is_ok = TRUE ;
575
576out:
577    EPHYR_LOG ("leave\n") ;
578    return is_ok ;
579}
580
581#define X_GLXSingle 0
582
583#define __EPHYR_GLX_SINGLE_PUT_CHAR(offset,a) \
584    *((INT8 *) (pc + offset)) = a
585
586#define EPHYR_GLX_SINGLE_PUT_SHORT(offset,a) \
587    *((INT16 *) (pc + offset)) = a
588
589#define EPHYR_GLX_SINGLE_PUT_LONG(offset,a) \
590    *((INT32 *) (pc + offset)) = a
591
592#define EPHYR_GLX_SINGLE_PUT_FLOAT(offset,a) \
593    *((FLOAT32 *) (pc + offset)) = a
594
595#define EPHYR_GLX_SINGLE_READ_XREPLY()       \
596    (void) _XReply(dpy, (xReply*) &reply, 0, False)
597
598#define EPHYR_GLX_SINGLE_GET_RETVAL(a,cast) \
599    a = (cast) reply.retval
600
601#define EPHYR_GLX_SINGLE_GET_SIZE(a) \
602    a = (GLint) reply.size
603
604#define EPHYR_GLX_SINGLE_GET_CHAR(p) \
605    *p = *(GLbyte *)&reply.pad3;
606
607#define EPHYR_GLX_SINGLE_GET_SHORT(p) \
608    *p = *(GLshort *)&reply.pad3;
609
610#define EPHYR_GLX_SINGLE_GET_LONG(p) \
611    *p = *(GLint *)&reply.pad3;
612
613#define EPHYR_GLX_SINGLE_GET_FLOAT(p) \
614    *p = *(GLfloat *)&reply.pad3;
615
616Bool
617ephyrHostGetIntegerValue (int a_current_context_tag, int a_int, int *a_val)
618{
619    Bool is_ok=FALSE;
620    Display *dpy = hostx_get_display () ;
621    int major_opcode=0, size=0;
622    xGLXSingleReq *req=NULL;
623    xGLXSingleReply reply;
624    unsigned char* pc=NULL ;
625
626    EPHYR_RETURN_VAL_IF_FAIL (a_val, FALSE) ;
627
628    EPHYR_LOG ("enter\n") ;
629    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
630        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
631        goto out ;
632    }
633    LockDisplay (dpy) ;
634    GetReqExtra (GLXSingle, 4, req) ;
635    req->reqType = major_opcode ;
636    req->glxCode = X_GLsop_GetIntegerv ;
637    req->contextTag = a_current_context_tag;
638    pc = ((unsigned char *)(req) + sz_xGLXSingleReq) ;
639    EPHYR_GLX_SINGLE_PUT_LONG (0, a_int) ;
640    EPHYR_GLX_SINGLE_READ_XREPLY () ;
641    EPHYR_GLX_SINGLE_GET_SIZE (size) ;
642    if (!size) {
643        UnlockDisplay (dpy) ;
644        SyncHandle () ;
645        EPHYR_LOG_ERROR ("X_GLsop_GetIngerv failed\n") ;
646        goto out ;
647    }
648    EPHYR_GLX_SINGLE_GET_LONG (a_val) ;
649    UnlockDisplay (dpy) ;
650    SyncHandle () ;
651    is_ok = TRUE ;
652
653out:
654    EPHYR_LOG ("leave\n") ;
655    return is_ok ;
656}
657
658Bool
659ephyrHostIsContextDirect (int a_ctxt_id,
660                          int *a_is_direct)
661{
662    Bool is_ok=FALSE;
663    Display *dpy = hostx_get_display () ;
664    xGLXIsDirectReq *req=NULL;
665    xGLXIsDirectReply reply;
666    int major_opcode=0, remote_glx_ctxt_id=0;
667
668    EPHYR_LOG ("enter\n") ;
669    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
670        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
671        goto out ;
672    }
673    if (!hostx_get_resource_id_peer (a_ctxt_id, &remote_glx_ctxt_id)) {
674        EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ;
675        goto out ;
676    }
677    memset (&reply, 0, sizeof (reply)) ;
678
679    /* Send the glXIsDirect request */
680    LockDisplay (dpy);
681    GetReq (GLXIsDirect,req);
682    req->reqType = major_opcode;
683    req->glxCode = X_GLXIsDirect;
684    req->context = remote_glx_ctxt_id;
685    if (!_XReply (dpy, (xReply*) &reply, 0, False)) {
686        EPHYR_LOG_ERROR ("fail in reading reply from host\n") ;
687        UnlockDisplay (dpy);
688        SyncHandle ();
689        goto out ;
690    }
691    UnlockDisplay (dpy);
692    SyncHandle ();
693    *a_is_direct = reply.isDirect ;
694    is_ok = TRUE ;
695
696out:
697    EPHYR_LOG ("leave\n") ;
698    return is_ok ;
699}
700