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 * a lots of the content of this file has been adapted from the mesa source
26706f2543Smrg * code.
27706f2543Smrg * Authors:
28706f2543Smrg *    Dodji Seketeli <dodji@openedhand.com>
29706f2543Smrg */
30706f2543Smrg#ifdef HAVE_CONFIG_H
31706f2543Smrg#include <kdrive-config.h>
32706f2543Smrg#endif
33706f2543Smrg
34706f2543Smrg/*
35706f2543Smrg * including some server headers (like kdrive-config.h)
36706f2543Smrg * might define the macro _XSERVER64
37706f2543Smrg * on 64 bits machines. That macro must _NOT_ be defined for Xlib
38706f2543Smrg * client code, otherwise bad things happen.
39706f2543Smrg * So let's undef that macro if necessary.
40706f2543Smrg */
41706f2543Smrg#ifdef _XSERVER64
42706f2543Smrg#undef _XSERVER64
43706f2543Smrg#endif
44706f2543Smrg
45706f2543Smrg#include <X11/Xlibint.h>
46706f2543Smrg#include <GL/glx.h>
47706f2543Smrg#include <GL/internal/glcore.h>
48706f2543Smrg#include <GL/glxproto.h>
49706f2543Smrg#include <GL/glxint.h>
50706f2543Smrg#include "ephyrhostglx.h"
51706f2543Smrg#define _HAVE_XALLOC_DECLS
52706f2543Smrg#include "ephyrlog.h"
53706f2543Smrg#include "hostx.h"
54706f2543Smrg
55706f2543Smrgenum VisualConfRequestType {
56706f2543Smrg    EPHYR_GET_FB_CONFIG,
57706f2543Smrg    EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX,
58706f2543Smrg    EPHYR_GET_VISUAL_CONFIGS
59706f2543Smrg
60706f2543Smrg};
61706f2543Smrg
62706f2543Smrgstatic Bool ephyrHostGLXGetVisualConfigsInternal
63706f2543Smrg                                        (enum VisualConfRequestType a_type,
64706f2543Smrg                                         int32_t a_screen,
65706f2543Smrg                                         int32_t *a_num_visuals,
66706f2543Smrg                                         int32_t *a_num_props,
67706f2543Smrg                                         int32_t *a_props_buf_size,
68706f2543Smrg                                         int32_t **a_props_buf);
69706f2543SmrgBool
70706f2543SmrgephyrHostGLXGetMajorOpcode (int *a_opcode)
71706f2543Smrg{
72706f2543Smrg    Bool is_ok=FALSE ;
73706f2543Smrg    Display *dpy=hostx_get_display () ;
74706f2543Smrg    static int opcode ;
75706f2543Smrg    int first_event_return=0, first_error_return=0;
76706f2543Smrg
77706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ;
78706f2543Smrg    EPHYR_LOG ("enter\n") ;
79706f2543Smrg    if (!opcode) {
80706f2543Smrg        if (!XQueryExtension (dpy, GLX_EXTENSION_NAME, &opcode,
81706f2543Smrg                              &first_event_return, &first_error_return)) {
82706f2543Smrg            EPHYR_LOG_ERROR ("XQueryExtension() failed\n") ;
83706f2543Smrg            goto out ;
84706f2543Smrg        }
85706f2543Smrg    }
86706f2543Smrg    *a_opcode = opcode ;
87706f2543Smrg    is_ok = TRUE ;
88706f2543Smrgout:
89706f2543Smrg    EPHYR_LOG ("release\n") ;
90706f2543Smrg    return is_ok ;
91706f2543Smrg}
92706f2543Smrg
93706f2543SmrgBool
94706f2543SmrgephyrHostGLXQueryVersion (int *a_major, int *a_minor)
95706f2543Smrg{
96706f2543Smrg    Bool is_ok = FALSE ;
97706f2543Smrg    Display *dpy = hostx_get_display () ;
98706f2543Smrg    int major_opcode=0;
99706f2543Smrg    xGLXQueryVersionReq *req=NULL;
100706f2543Smrg    xGLXQueryVersionReply reply;
101706f2543Smrg
102706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (a_major && a_minor, FALSE) ;
103706f2543Smrg    EPHYR_LOG ("enter\n") ;
104706f2543Smrg
105706f2543Smrg    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
106706f2543Smrg        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
107706f2543Smrg        goto out ;
108706f2543Smrg    }
109706f2543Smrg    EPHYR_LOG ("major opcode: %d\n", major_opcode) ;
110706f2543Smrg
111706f2543Smrg    /* Send the glXQueryVersion request */
112706f2543Smrg    memset (&reply, 0, sizeof (reply)) ;
113706f2543Smrg    LockDisplay (dpy);
114706f2543Smrg    GetReq (GLXQueryVersion, req);
115706f2543Smrg    req->reqType = major_opcode;
116706f2543Smrg    req->glxCode = X_GLXQueryVersion;
117706f2543Smrg    req->majorVersion = 2;
118706f2543Smrg    req->minorVersion = 1;
119706f2543Smrg    _XReply(dpy, (xReply*) &reply, 0, False);
120706f2543Smrg    UnlockDisplay (dpy);
121706f2543Smrg    SyncHandle ();
122706f2543Smrg
123706f2543Smrg    *a_major = reply.majorVersion ;
124706f2543Smrg    *a_minor = reply.minorVersion ;
125706f2543Smrg
126706f2543Smrg    EPHYR_LOG ("major:%d, minor:%d\n", *a_major, *a_minor) ;
127706f2543Smrg
128706f2543Smrg    is_ok = TRUE ;
129706f2543Smrgout:
130706f2543Smrg    EPHYR_LOG ("leave\n") ;
131706f2543Smrg    return is_ok ;
132706f2543Smrg}
133706f2543Smrg
134706f2543Smrg/**
135706f2543Smrg * GLX protocol structure for the ficticious "GXLGenericGetString" request.
136706f2543Smrg *
137706f2543Smrg * This is a non-existant protocol packet.  It just so happens that all of
138706f2543Smrg * the real protocol packets used to request a string from the server have
139706f2543Smrg * an identical binary layout.  The only difference between them is the
140706f2543Smrg * meaning of the \c for_whom field and the value of the \c glxCode.
141706f2543Smrg * (this has been copied from the mesa source code)
142706f2543Smrg */
143706f2543Smrgtypedef struct GLXGenericGetString {
144706f2543Smrg    CARD8 reqType;
145706f2543Smrg    CARD8 glxCode;
146706f2543Smrg    CARD16 length B16;
147706f2543Smrg    CARD32 for_whom B32;
148706f2543Smrg    CARD32 name B32;
149706f2543Smrg} xGLXGenericGetStringReq;
150706f2543Smrg
151706f2543Smrg/* These defines are only needed to make the GetReq macro happy.
152706f2543Smrg */
153706f2543Smrg#define sz_xGLXGenericGetStringReq 12
154706f2543Smrg#define X_GLXGenericGetString 0
155706f2543Smrg
156706f2543SmrgBool
157706f2543SmrgephyrHostGLXGetStringFromServer (int a_screen_number,
158706f2543Smrg                                 int a_string_name,
159706f2543Smrg                                 enum EphyrHostGLXGetStringOps a_op,
160706f2543Smrg                                 char **a_string)
161706f2543Smrg{
162706f2543Smrg    Bool is_ok=FALSE ;
163706f2543Smrg    Display *dpy = hostx_get_display () ;
164706f2543Smrg    int default_screen = DefaultScreen (dpy);
165706f2543Smrg    xGLXGenericGetStringReq *req=NULL;
166706f2543Smrg    xGLXSingleReply reply;
167706f2543Smrg    int length=0, numbytes=0, major_opcode=0, get_string_op=0;
168706f2543Smrg
169706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (dpy && a_string, FALSE) ;
170706f2543Smrg
171706f2543Smrg    EPHYR_LOG ("enter\n") ;
172706f2543Smrg    switch (a_op) {
173706f2543Smrg        case EPHYR_HOST_GLX_QueryServerString:
174706f2543Smrg            get_string_op = X_GLXQueryServerString;
175706f2543Smrg            break ;
176706f2543Smrg        case EPHYR_HOST_GLX_GetString:
177706f2543Smrg            get_string_op = X_GLsop_GetString;
178706f2543Smrg            EPHYR_LOG ("Going to glXGetString. strname:%#x, ctxttag:%d\n",
179706f2543Smrg                       a_string_name, a_screen_number) ;
180706f2543Smrg            break ;
181706f2543Smrg        default:
182706f2543Smrg            EPHYR_LOG_ERROR ("unknown EphyrHostGLXGetStringOp:%d\n", a_op) ;
183706f2543Smrg            goto out ;
184706f2543Smrg    }
185706f2543Smrg
186706f2543Smrg    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
187706f2543Smrg        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
188706f2543Smrg        goto out ;
189706f2543Smrg    }
190706f2543Smrg    EPHYR_LOG ("major opcode: %d\n", major_opcode) ;
191706f2543Smrg
192706f2543Smrg    LockDisplay (dpy);
193706f2543Smrg
194706f2543Smrg    /* All of the GLX protocol requests for getting a string from the server
195706f2543Smrg     * look the same.  The exact meaning of the a_for_whom field is usually
196706f2543Smrg     * either the screen number (for glXQueryServerString) or the context tag
197706f2543Smrg     * (for GLXSingle).
198706f2543Smrg     */
199706f2543Smrg    GetReq (GLXGenericGetString, req);
200706f2543Smrg    req->reqType = major_opcode;
201706f2543Smrg    req->glxCode = get_string_op;
202706f2543Smrg    req->for_whom = default_screen;
203706f2543Smrg    req->name = a_string_name;
204706f2543Smrg
205706f2543Smrg    _XReply (dpy, (xReply *)&reply, 0, False);
206706f2543Smrg
207706f2543Smrg    length = reply.length * 4;
208706f2543Smrg    if (!length) {
209706f2543Smrg        numbytes = 0;
210706f2543Smrg    } else {
211706f2543Smrg        numbytes = reply.size;
212706f2543Smrg    }
213706f2543Smrg    EPHYR_LOG ("going to get a string of size:%d\n", numbytes) ;
214706f2543Smrg
215706f2543Smrg    *a_string = (char *) Xmalloc (numbytes +1);
216706f2543Smrg    if (!a_string) {
217706f2543Smrg        EPHYR_LOG_ERROR ("allocation failed\n") ;
218706f2543Smrg        goto out;
219706f2543Smrg    }
220706f2543Smrg
221706f2543Smrg    memset (*a_string, 0, numbytes+1) ;
222706f2543Smrg    if (_XRead (dpy, *a_string, numbytes)) {
223706f2543Smrg        UnlockDisplay (dpy);
224706f2543Smrg        SyncHandle ();
225706f2543Smrg        EPHYR_LOG_ERROR ("read failed\n") ;
226706f2543Smrg        goto out ;
227706f2543Smrg    }
228706f2543Smrg    length -= numbytes;
229706f2543Smrg    _XEatData (dpy, length) ;
230706f2543Smrg    UnlockDisplay (dpy);
231706f2543Smrg    SyncHandle ();
232706f2543Smrg    EPHYR_LOG ("strname:%#x, strvalue:'%s', strlen:%d\n",
233706f2543Smrg               a_string_name, *a_string, numbytes) ;
234706f2543Smrg
235706f2543Smrg    is_ok = TRUE ;
236706f2543Smrgout:
237706f2543Smrg    EPHYR_LOG ("leave\n") ;
238706f2543Smrg    return is_ok ;
239706f2543Smrg}
240706f2543Smrg
241706f2543Smrgstatic Bool
242706f2543SmrgephyrHostGLXGetVisualConfigsInternal (enum VisualConfRequestType a_type,
243706f2543Smrg                                      int32_t a_screen,
244706f2543Smrg                                      int32_t *a_num_visuals,
245706f2543Smrg                                      int32_t *a_num_props,
246706f2543Smrg                                      int32_t *a_props_buf_size,
247706f2543Smrg                                      int32_t **a_props_buf)
248706f2543Smrg{
249706f2543Smrg    Bool is_ok = FALSE ;
250706f2543Smrg    Display *dpy = hostx_get_display () ;
251706f2543Smrg    xGLXGetVisualConfigsReq *req;
252706f2543Smrg    xGLXGetFBConfigsReq *fb_req;
253706f2543Smrg    xGLXVendorPrivateWithReplyReq *vpreq;
254706f2543Smrg    xGLXGetFBConfigsSGIXReq *sgi_req;
255706f2543Smrg    xGLXGetVisualConfigsReply reply;
256706f2543Smrg    char *server_glx_version=NULL,
257706f2543Smrg         *server_glx_extensions=NULL ;
258706f2543Smrg    int j=0,
259706f2543Smrg        screens=0,
260706f2543Smrg        major_opcode=0,
261706f2543Smrg        num_props=0,
262706f2543Smrg        num_visuals=0,
263706f2543Smrg        props_buf_size=0,
264706f2543Smrg        props_per_visual_size=0;
265706f2543Smrg    int32_t *props_buf=NULL;
266706f2543Smrg
267706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (dpy, FALSE) ;
268706f2543Smrg
269706f2543Smrg    screens = ScreenCount (dpy);
270706f2543Smrg    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
271706f2543Smrg        EPHYR_LOG_ERROR ("failed to get opcode\n") ;
272706f2543Smrg        goto out ;
273706f2543Smrg    }
274706f2543Smrg
275706f2543Smrg    LockDisplay(dpy);
276706f2543Smrg    switch (a_type) {
277706f2543Smrg        case EPHYR_GET_FB_CONFIG:
278706f2543Smrg        GetReq(GLXGetFBConfigs,fb_req);
279706f2543Smrg        fb_req->reqType = major_opcode;
280706f2543Smrg        fb_req->glxCode = X_GLXGetFBConfigs;
281706f2543Smrg        fb_req->screen = DefaultScreen (dpy);
282706f2543Smrg        break;
283706f2543Smrg
284706f2543Smrg        case EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX:
285706f2543Smrg        GetReqExtra(GLXVendorPrivateWithReply,
286706f2543Smrg                    sz_xGLXGetFBConfigsSGIXReq
287706f2543Smrg                         -
288706f2543Smrg                    sz_xGLXVendorPrivateWithReplyReq,
289706f2543Smrg                    vpreq);
290706f2543Smrg        sgi_req = (xGLXGetFBConfigsSGIXReq *) vpreq;
291706f2543Smrg        sgi_req->reqType = major_opcode;
292706f2543Smrg        sgi_req->glxCode = X_GLXVendorPrivateWithReply;
293706f2543Smrg        sgi_req->vendorCode = X_GLXvop_GetFBConfigsSGIX;
294706f2543Smrg        sgi_req->screen = DefaultScreen (dpy);
295706f2543Smrg        break;
296706f2543Smrg
297706f2543Smrg        case EPHYR_GET_VISUAL_CONFIGS:
298706f2543Smrg        GetReq(GLXGetVisualConfigs,req);
299706f2543Smrg        req->reqType = major_opcode;
300706f2543Smrg        req->glxCode = X_GLXGetVisualConfigs;
301706f2543Smrg        req->screen = DefaultScreen (dpy);
302706f2543Smrg        break;
303706f2543Smrg    }
304706f2543Smrg
305706f2543Smrg    if (!_XReply(dpy, (xReply*) &reply, 0, False)) {
306706f2543Smrg        EPHYR_LOG_ERROR ("unknown error\n") ;
307706f2543Smrg        UnlockDisplay(dpy);
308706f2543Smrg        goto out ;
309706f2543Smrg    }
310706f2543Smrg   if (!reply.numVisuals) {
311706f2543Smrg        EPHYR_LOG_ERROR ("screen does not support GL rendering\n") ;
312706f2543Smrg        UnlockDisplay(dpy);
313706f2543Smrg        goto out ;
314706f2543Smrg    }
315706f2543Smrg   num_visuals = reply.numVisuals ;
316706f2543Smrg
317706f2543Smrg    /* FIXME: Is the __GLX_MIN_CONFIG_PROPS test correct for
318706f2543Smrg     * FIXME: FBconfigs?
319706f2543Smrg     */
320706f2543Smrg    /* Check number of properties */
321706f2543Smrg    num_props = reply.numProps;
322706f2543Smrg    if ((num_props < __GLX_MIN_CONFIG_PROPS) ||
323706f2543Smrg        (num_props > __GLX_MAX_CONFIG_PROPS)) {
324706f2543Smrg        /* Huh?  Not in protocol defined limits.  Punt */
325706f2543Smrg        EPHYR_LOG_ERROR ("got a bad reply to request\n") ;
326706f2543Smrg        UnlockDisplay(dpy);
327706f2543Smrg        goto out ;
328706f2543Smrg    }
329706f2543Smrg
330706f2543Smrg    if (a_type != EPHYR_GET_VISUAL_CONFIGS) {
331706f2543Smrg        num_props *= 2;
332706f2543Smrg    }
333706f2543Smrg    props_per_visual_size = num_props * __GLX_SIZE_INT32;
334706f2543Smrg    props_buf_size = props_per_visual_size * reply.numVisuals;
335706f2543Smrg    props_buf = malloc (props_buf_size) ;
336706f2543Smrg    for (j = 0; j < reply.numVisuals; j++) {
337706f2543Smrg        if (_XRead (dpy,
338706f2543Smrg                    &((char*)props_buf)[j*props_per_visual_size],
339706f2543Smrg                    props_per_visual_size) != Success) {
340706f2543Smrg            EPHYR_LOG_ERROR ("read failed\n") ;
341706f2543Smrg        }
342706f2543Smrg    }
343706f2543Smrg    UnlockDisplay(dpy);
344706f2543Smrg
345706f2543Smrg    *a_num_visuals = num_visuals ;
346706f2543Smrg    *a_num_props = reply.numProps ;
347706f2543Smrg    *a_props_buf_size = props_buf_size ;
348706f2543Smrg    *a_props_buf = props_buf ;
349706f2543Smrg    is_ok = TRUE ;
350706f2543Smrg
351706f2543Smrgout:
352706f2543Smrg    if (server_glx_version) {
353706f2543Smrg        XFree (server_glx_version) ;
354706f2543Smrg        server_glx_version = NULL ;
355706f2543Smrg    }
356706f2543Smrg    if (server_glx_extensions) {
357706f2543Smrg        XFree (server_glx_extensions) ;
358706f2543Smrg        server_glx_extensions = NULL ;
359706f2543Smrg    }
360706f2543Smrg    SyncHandle () ;
361706f2543Smrg    return is_ok;
362706f2543Smrg}
363706f2543Smrg
364706f2543SmrgBool
365706f2543SmrgephyrHostGLXGetVisualConfigs (int32_t a_screen,
366706f2543Smrg                              int32_t *a_num_visuals,
367706f2543Smrg                              int32_t *a_num_props,
368706f2543Smrg                              int32_t *a_props_buf_size,
369706f2543Smrg                              int32_t **a_props_buf)
370706f2543Smrg{
371706f2543Smrg    Bool is_ok = FALSE;
372706f2543Smrg
373706f2543Smrg    EPHYR_LOG ("enter\n") ;
374706f2543Smrg    is_ok = ephyrHostGLXGetVisualConfigsInternal (EPHYR_GET_VISUAL_CONFIGS,
375706f2543Smrg                                                  a_screen,
376706f2543Smrg                                                  a_num_visuals,
377706f2543Smrg                                                  a_num_props,
378706f2543Smrg                                                  a_props_buf_size,
379706f2543Smrg                                                  a_props_buf) ;
380706f2543Smrg
381706f2543Smrg    EPHYR_LOG ("leave:%d\n", is_ok) ;
382706f2543Smrg    return is_ok;
383706f2543Smrg}
384706f2543Smrg
385706f2543SmrgBool
386706f2543SmrgephyrHostGLXVendorPrivGetFBConfigsSGIX (int a_screen,
387706f2543Smrg                                        int32_t *a_num_visuals,
388706f2543Smrg                                        int32_t *a_num_props,
389706f2543Smrg                                        int32_t *a_props_buf_size,
390706f2543Smrg                                        int32_t **a_props_buf)
391706f2543Smrg{
392706f2543Smrg    Bool is_ok=FALSE ;
393706f2543Smrg    EPHYR_LOG ("enter\n") ;
394706f2543Smrg    is_ok = ephyrHostGLXGetVisualConfigsInternal
395706f2543Smrg                                        (EPHYR_VENDOR_PRIV_GET_FB_CONFIG_SGIX,
396706f2543Smrg                                         a_screen,
397706f2543Smrg                                         a_num_visuals,
398706f2543Smrg                                         a_num_props,
399706f2543Smrg                                         a_props_buf_size,
400706f2543Smrg                                         a_props_buf) ;
401706f2543Smrg    EPHYR_LOG ("leave\n") ;
402706f2543Smrg    return is_ok ;
403706f2543Smrg}
404706f2543Smrg
405706f2543SmrgBool
406706f2543SmrgephyrHostGLXSendClientInfo (int32_t a_major, int32_t a_minor,
407706f2543Smrg                            const char* a_extension_list)
408706f2543Smrg{
409706f2543Smrg    Bool is_ok = FALSE ;
410706f2543Smrg    Display *dpy = hostx_get_display () ;
411706f2543Smrg    xGLXClientInfoReq *req;
412706f2543Smrg    int size;
413706f2543Smrg    int32_t major_opcode=0 ;
414706f2543Smrg
415706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (dpy && a_extension_list, FALSE) ;
416706f2543Smrg
417706f2543Smrg    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
418706f2543Smrg        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
419706f2543Smrg        goto out ;
420706f2543Smrg    }
421706f2543Smrg
422706f2543Smrg    LockDisplay (dpy);
423706f2543Smrg
424706f2543Smrg    GetReq (GLXClientInfo,req);
425706f2543Smrg    req->reqType = major_opcode;
426706f2543Smrg    req->glxCode = X_GLXClientInfo;
427706f2543Smrg    req->major = a_major;
428706f2543Smrg    req->minor = a_minor;
429706f2543Smrg
430706f2543Smrg    size = strlen (a_extension_list) + 1;
431706f2543Smrg    req->length += bytes_to_int32(size);
432706f2543Smrg    req->numbytes = size;
433706f2543Smrg    Data (dpy, a_extension_list, size);
434706f2543Smrg
435706f2543Smrg    UnlockDisplay(dpy);
436706f2543Smrg    SyncHandle();
437706f2543Smrg
438706f2543Smrg    is_ok=TRUE ;
439706f2543Smrg
440706f2543Smrgout:
441706f2543Smrg    return is_ok ;
442706f2543Smrg}
443706f2543Smrg
444706f2543SmrgBool
445706f2543SmrgephyrHostGLXCreateContext (int a_screen,
446706f2543Smrg                           int a_visual_id,
447706f2543Smrg                           int a_context_id,
448706f2543Smrg                           int a_share_list_ctxt_id,
449706f2543Smrg                           Bool a_direct)
450706f2543Smrg{
451706f2543Smrg    Bool is_ok = FALSE;
452706f2543Smrg    Display *dpy = hostx_get_display ();
453706f2543Smrg    int major_opcode=0, remote_context_id=0;
454706f2543Smrg    xGLXCreateContextReq *req;
455706f2543Smrg
456706f2543Smrg    EPHYR_LOG ("enter. screen:%d, visual:%d, contextid:%d, direct:%d\n",
457706f2543Smrg               a_screen, a_visual_id, a_context_id, a_direct) ;
458706f2543Smrg
459706f2543Smrg    if (!hostx_allocate_resource_id_peer (a_context_id, &remote_context_id)) {
460706f2543Smrg        EPHYR_LOG_ERROR ("failed to peer the context id %d host X",
461706f2543Smrg                         remote_context_id) ;
462706f2543Smrg        goto out ;
463706f2543Smrg    }
464706f2543Smrg
465706f2543Smrg    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
466706f2543Smrg        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
467706f2543Smrg        goto out ;
468706f2543Smrg    }
469706f2543Smrg
470706f2543Smrg    LockDisplay (dpy) ;
471706f2543Smrg
472706f2543Smrg    /* Send the glXCreateContext request */
473706f2543Smrg    GetReq(GLXCreateContext,req);
474706f2543Smrg    req->reqType = major_opcode;
475706f2543Smrg    req->glxCode = X_GLXCreateContext;
476706f2543Smrg    req->context = remote_context_id;
477706f2543Smrg    req->visual = a_visual_id;
478706f2543Smrg    req->screen = DefaultScreen (dpy);
479706f2543Smrg    req->shareList = a_share_list_ctxt_id;
480706f2543Smrg    req->isDirect = a_direct;
481706f2543Smrg
482706f2543Smrg    UnlockDisplay (dpy);
483706f2543Smrg    SyncHandle ();
484706f2543Smrg
485706f2543Smrg    is_ok = TRUE ;
486706f2543Smrg
487706f2543Smrgout:
488706f2543Smrg    EPHYR_LOG ("leave\n") ;
489706f2543Smrg    return is_ok ;
490706f2543Smrg}
491706f2543Smrg
492706f2543SmrgBool
493706f2543SmrgephyrHostDestroyContext (int a_ctxt_id)
494706f2543Smrg{
495706f2543Smrg    Bool is_ok=FALSE;
496706f2543Smrg    Display *dpy=hostx_get_display ();
497706f2543Smrg    int major_opcode=0, remote_ctxt_id=0 ;
498706f2543Smrg    xGLXDestroyContextReq *req=NULL;
499706f2543Smrg
500706f2543Smrg    EPHYR_LOG ("enter:%d\n", a_ctxt_id) ;
501706f2543Smrg
502706f2543Smrg    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
503706f2543Smrg        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
504706f2543Smrg        goto out ;
505706f2543Smrg    }
506706f2543Smrg    if (!hostx_get_resource_id_peer (a_ctxt_id, &remote_ctxt_id)) {
507706f2543Smrg        EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ;
508706f2543Smrg        goto out ;
509706f2543Smrg    }
510706f2543Smrg    EPHYR_LOG ("host context id:%d\n", remote_ctxt_id) ;
511706f2543Smrg
512706f2543Smrg    LockDisplay (dpy);
513706f2543Smrg    GetReq (GLXDestroyContext,req);
514706f2543Smrg    req->reqType = major_opcode;
515706f2543Smrg    req->glxCode = X_GLXDestroyContext;
516706f2543Smrg    req->context = remote_ctxt_id;
517706f2543Smrg    UnlockDisplay (dpy);
518706f2543Smrg    SyncHandle ();
519706f2543Smrg
520706f2543Smrg    is_ok = TRUE ;
521706f2543Smrg
522706f2543Smrgout:
523706f2543Smrg    EPHYR_LOG ("leave\n") ;
524706f2543Smrg    return is_ok ;
525706f2543Smrg}
526706f2543Smrg
527706f2543SmrgBool
528706f2543SmrgephyrHostGLXMakeCurrent (int a_drawable,
529706f2543Smrg                         int a_glx_ctxt_id,
530706f2543Smrg                         int a_old_ctxt_tag,
531706f2543Smrg                         int *a_ctxt_tag)
532706f2543Smrg{
533706f2543Smrg    Bool is_ok=FALSE ;
534706f2543Smrg    Display *dpy = hostx_get_display () ;
535706f2543Smrg    int32_t major_opcode=0 ;
536706f2543Smrg    int remote_glx_ctxt_id=0 ;
537706f2543Smrg    xGLXMakeCurrentReq *req;
538706f2543Smrg    xGLXMakeCurrentReply reply;
539706f2543Smrg
540706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (a_ctxt_tag, FALSE) ;
541706f2543Smrg
542706f2543Smrg    EPHYR_LOG ("enter. drawable:%d, context:%d, oldtag:%d\n",
543706f2543Smrg               a_drawable, a_glx_ctxt_id, a_old_ctxt_tag) ;
544706f2543Smrg
545706f2543Smrg    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
546706f2543Smrg        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
547706f2543Smrg        goto out ;
548706f2543Smrg    }
549706f2543Smrg    if (!hostx_get_resource_id_peer (a_glx_ctxt_id, &remote_glx_ctxt_id)) {
550706f2543Smrg        EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ;
551706f2543Smrg        goto out ;
552706f2543Smrg    }
553706f2543Smrg
554706f2543Smrg    LockDisplay (dpy);
555706f2543Smrg
556706f2543Smrg    GetReq (GLXMakeCurrent,req);
557706f2543Smrg    req->reqType = major_opcode;
558706f2543Smrg    req->glxCode = X_GLXMakeCurrent;
559706f2543Smrg    req->drawable = a_drawable;
560706f2543Smrg    req->context = remote_glx_ctxt_id;
561706f2543Smrg    req->oldContextTag = a_old_ctxt_tag;
562706f2543Smrg
563706f2543Smrg    memset (&reply, 0, sizeof (reply)) ;
564706f2543Smrg    if (!_XReply (dpy, (xReply*)&reply, 0, False)) {
565706f2543Smrg        EPHYR_LOG_ERROR ("failed to get reply from host\n") ;
566706f2543Smrg        UnlockDisplay (dpy);
567706f2543Smrg        SyncHandle ();
568706f2543Smrg        goto out ;
569706f2543Smrg    }
570706f2543Smrg    UnlockDisplay (dpy);
571706f2543Smrg    SyncHandle ();
572706f2543Smrg    *a_ctxt_tag = reply.contextTag ;
573706f2543Smrg    EPHYR_LOG ("context tag:%d\n", *a_ctxt_tag) ;
574706f2543Smrg    is_ok = TRUE ;
575706f2543Smrg
576706f2543Smrgout:
577706f2543Smrg    EPHYR_LOG ("leave\n") ;
578706f2543Smrg    return is_ok ;
579706f2543Smrg}
580706f2543Smrg
581706f2543Smrg#define X_GLXSingle 0
582706f2543Smrg
583706f2543Smrg#define __EPHYR_GLX_SINGLE_PUT_CHAR(offset,a) \
584706f2543Smrg    *((INT8 *) (pc + offset)) = a
585706f2543Smrg
586706f2543Smrg#define EPHYR_GLX_SINGLE_PUT_SHORT(offset,a) \
587706f2543Smrg    *((INT16 *) (pc + offset)) = a
588706f2543Smrg
589706f2543Smrg#define EPHYR_GLX_SINGLE_PUT_LONG(offset,a) \
590706f2543Smrg    *((INT32 *) (pc + offset)) = a
591706f2543Smrg
592706f2543Smrg#define EPHYR_GLX_SINGLE_PUT_FLOAT(offset,a) \
593706f2543Smrg    *((FLOAT32 *) (pc + offset)) = a
594706f2543Smrg
595706f2543Smrg#define EPHYR_GLX_SINGLE_READ_XREPLY()       \
596706f2543Smrg    (void) _XReply(dpy, (xReply*) &reply, 0, False)
597706f2543Smrg
598706f2543Smrg#define EPHYR_GLX_SINGLE_GET_RETVAL(a,cast) \
599706f2543Smrg    a = (cast) reply.retval
600706f2543Smrg
601706f2543Smrg#define EPHYR_GLX_SINGLE_GET_SIZE(a) \
602706f2543Smrg    a = (GLint) reply.size
603706f2543Smrg
604706f2543Smrg#define EPHYR_GLX_SINGLE_GET_CHAR(p) \
605706f2543Smrg    *p = *(GLbyte *)&reply.pad3;
606706f2543Smrg
607706f2543Smrg#define EPHYR_GLX_SINGLE_GET_SHORT(p) \
608706f2543Smrg    *p = *(GLshort *)&reply.pad3;
609706f2543Smrg
610706f2543Smrg#define EPHYR_GLX_SINGLE_GET_LONG(p) \
611706f2543Smrg    *p = *(GLint *)&reply.pad3;
612706f2543Smrg
613706f2543Smrg#define EPHYR_GLX_SINGLE_GET_FLOAT(p) \
614706f2543Smrg    *p = *(GLfloat *)&reply.pad3;
615706f2543Smrg
616706f2543SmrgBool
617706f2543SmrgephyrHostGetIntegerValue (int a_current_context_tag, int a_int, int *a_val)
618706f2543Smrg{
619706f2543Smrg    Bool is_ok=FALSE;
620706f2543Smrg    Display *dpy = hostx_get_display () ;
621706f2543Smrg    int major_opcode=0, size=0;
622706f2543Smrg    xGLXSingleReq *req=NULL;
623706f2543Smrg    xGLXSingleReply reply;
624706f2543Smrg    unsigned char* pc=NULL ;
625706f2543Smrg
626706f2543Smrg    EPHYR_RETURN_VAL_IF_FAIL (a_val, FALSE) ;
627706f2543Smrg
628706f2543Smrg    EPHYR_LOG ("enter\n") ;
629706f2543Smrg    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
630706f2543Smrg        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
631706f2543Smrg        goto out ;
632706f2543Smrg    }
633706f2543Smrg    LockDisplay (dpy) ;
634706f2543Smrg    GetReqExtra (GLXSingle, 4, req) ;
635706f2543Smrg    req->reqType = major_opcode ;
636706f2543Smrg    req->glxCode = X_GLsop_GetIntegerv ;
637706f2543Smrg    req->contextTag = a_current_context_tag;
638706f2543Smrg    pc = ((unsigned char *)(req) + sz_xGLXSingleReq) ;
639706f2543Smrg    EPHYR_GLX_SINGLE_PUT_LONG (0, a_int) ;
640706f2543Smrg    EPHYR_GLX_SINGLE_READ_XREPLY () ;
641706f2543Smrg    EPHYR_GLX_SINGLE_GET_SIZE (size) ;
642706f2543Smrg    if (!size) {
643706f2543Smrg        UnlockDisplay (dpy) ;
644706f2543Smrg        SyncHandle () ;
645706f2543Smrg        EPHYR_LOG_ERROR ("X_GLsop_GetIngerv failed\n") ;
646706f2543Smrg        goto out ;
647706f2543Smrg    }
648706f2543Smrg    EPHYR_GLX_SINGLE_GET_LONG (a_val) ;
649706f2543Smrg    UnlockDisplay (dpy) ;
650706f2543Smrg    SyncHandle () ;
651706f2543Smrg    is_ok = TRUE ;
652706f2543Smrg
653706f2543Smrgout:
654706f2543Smrg    EPHYR_LOG ("leave\n") ;
655706f2543Smrg    return is_ok ;
656706f2543Smrg}
657706f2543Smrg
658706f2543SmrgBool
659706f2543SmrgephyrHostIsContextDirect (int a_ctxt_id,
660706f2543Smrg                          int *a_is_direct)
661706f2543Smrg{
662706f2543Smrg    Bool is_ok=FALSE;
663706f2543Smrg    Display *dpy = hostx_get_display () ;
664706f2543Smrg    xGLXIsDirectReq *req=NULL;
665706f2543Smrg    xGLXIsDirectReply reply;
666706f2543Smrg    int major_opcode=0, remote_glx_ctxt_id=0;
667706f2543Smrg
668706f2543Smrg    EPHYR_LOG ("enter\n") ;
669706f2543Smrg    if (!ephyrHostGLXGetMajorOpcode (&major_opcode)) {
670706f2543Smrg        EPHYR_LOG_ERROR ("failed to get major opcode\n") ;
671706f2543Smrg        goto out ;
672706f2543Smrg    }
673706f2543Smrg    if (!hostx_get_resource_id_peer (a_ctxt_id, &remote_glx_ctxt_id)) {
674706f2543Smrg        EPHYR_LOG_ERROR ("failed to get remote glx ctxt id\n") ;
675706f2543Smrg        goto out ;
676706f2543Smrg    }
677706f2543Smrg    memset (&reply, 0, sizeof (reply)) ;
678706f2543Smrg
679706f2543Smrg    /* Send the glXIsDirect request */
680706f2543Smrg    LockDisplay (dpy);
681706f2543Smrg    GetReq (GLXIsDirect,req);
682706f2543Smrg    req->reqType = major_opcode;
683706f2543Smrg    req->glxCode = X_GLXIsDirect;
684706f2543Smrg    req->context = remote_glx_ctxt_id;
685706f2543Smrg    if (!_XReply (dpy, (xReply*) &reply, 0, False)) {
686706f2543Smrg        EPHYR_LOG_ERROR ("fail in reading reply from host\n") ;
687706f2543Smrg        UnlockDisplay (dpy);
688706f2543Smrg        SyncHandle ();
689706f2543Smrg        goto out ;
690706f2543Smrg    }
691706f2543Smrg    UnlockDisplay (dpy);
692706f2543Smrg    SyncHandle ();
693706f2543Smrg    *a_is_direct = reply.isDirect ;
694706f2543Smrg    is_ok = TRUE ;
695706f2543Smrg
696706f2543Smrgout:
697706f2543Smrg    EPHYR_LOG ("leave\n") ;
698706f2543Smrg    return is_ok ;
699706f2543Smrg}
700