1 /*
2  * (C) Copyright IBM Corporation 2004
3  * All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the "Software"),
7  * to deal in the Software without restriction, including without limitation
8  * on the rights to use, copy, modify, merge, publish, distribute, sub
9  * license, and/or sell copies of the Software, and to permit persons to whom
10  * the Software is furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice (including the next
13  * paragraph) shall be included in all copies or substantial portions of the
14  * Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19  * IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  * DEALINGS IN THE SOFTWARE.
23  */
24 
25 /**
26  * \file glx_query.c
27  * Generic utility functions to query internal data from the server.
28  *
29  * \author Ian Romanick <idr@us.ibm.com>
30  */
31 
32 #include "glxclient.h"
33 
34 #if defined(USE_XCB)
35 # include <X11/Xlib-xcb.h>
36 # include <xcb/xcb.h>
37 # include <xcb/glx.h>
38 #endif
39 
40 #ifdef USE_XCB
41 
42 /**
43  * Exchange a protocol request for glXQueryServerString.
44  */
45 char *
__glXQueryServerString(Display * dpy,int opcode,CARD32 screen,CARD32 name)46 __glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name)
47 {
48    xcb_connection_t *c = XGetXCBConnection(dpy);
49    xcb_glx_query_server_string_reply_t *reply =
50       xcb_glx_query_server_string_reply(c,
51                                         xcb_glx_query_server_string(c,
52                                                                     screen,
53                                                                     name),
54                                         NULL);
55 
56    /* The spec doesn't mention this, but the Xorg server replies with
57     * a string already terminated with '\0'. */
58    uint32_t len = xcb_glx_query_server_string_string_length(reply);
59    char *buf = Xmalloc(len);
60    memcpy(buf, xcb_glx_query_server_string_string(reply), len);
61    free(reply);
62 
63    return buf;
64 }
65 
66 /**
67  * Exchange a protocol request for glGetString.
68  */
69 char *
__glXGetString(Display * dpy,int opcode,CARD32 contextTag,CARD32 name)70 __glXGetString(Display * dpy, int opcode, CARD32 contextTag, CARD32 name)
71 {
72    xcb_connection_t *c = XGetXCBConnection(dpy);
73    xcb_glx_get_string_reply_t *reply = xcb_glx_get_string_reply(c,
74                                                                 xcb_glx_get_string
75                                                                 (c,
76                                                                  contextTag,
77                                                                  name),
78                                                                 NULL);
79 
80    /* The spec doesn't mention this, but the Xorg server replies with
81     * a string already terminated with '\0'. */
82    uint32_t len = xcb_glx_get_string_string_length(reply);
83    char *buf = Xmalloc(len);
84    memcpy(buf, xcb_glx_get_string_string(reply), len);
85    free(reply);
86 
87    return buf;
88 }
89 
90 #else
91 
92 /**
93  * GLX protocol structure for the ficticious "GXLGenericGetString" request.
94  *
95  * This is a non-existant protocol packet.  It just so happens that all of
96  * the real protocol packets used to request a string from the server have
97  * an identical binary layout.  The only difference between them is the
98  * meaning of the \c for_whom field and the value of the \c glxCode.
99  */
100 typedef struct GLXGenericGetString
101 {
102    CARD8 reqType;
103    CARD8 glxCode;
104    CARD16 length B16;
105    CARD32 for_whom B32;
106    CARD32 name B32;
107 } xGLXGenericGetStringReq;
108 
109 /* These defines are only needed to make the GetReq macro happy.
110  */
111 #define sz_xGLXGenericGetStringReq 12
112 #define X_GLXGenericGetString 0
113 
114 /**
115  * Query the Server GLX string.
116  * This routine will allocate the necessay space for the string.
117  */
118 static char *
__glXGetStringFromServer(Display * dpy,int opcode,CARD32 glxCode,CARD32 for_whom,CARD32 name)119 __glXGetStringFromServer(Display * dpy, int opcode, CARD32 glxCode,
120                          CARD32 for_whom, CARD32 name)
121 {
122    xGLXGenericGetStringReq *req;
123    xGLXSingleReply reply;
124    int length;
125    int numbytes;
126    char *buf;
127 
128 
129    LockDisplay(dpy);
130 
131 
132    /* All of the GLX protocol requests for getting a string from the server
133     * look the same.  The exact meaning of the for_whom field is usually
134     * either the screen number (for glXQueryServerString) or the context tag
135     * (for GLXSingle).
136     */
137 
138    GetReq(GLXGenericGetString, req);
139    req->reqType = opcode;
140    req->glxCode = glxCode;
141    req->for_whom = for_whom;
142    req->name = name;
143 
144    _XReply(dpy, (xReply *) & reply, 0, False);
145 
146    length = reply.length * 4;
147    numbytes = reply.size;
148 
149    buf = (char *) Xmalloc(numbytes);
150    if (buf != NULL) {
151       _XRead(dpy, buf, numbytes);
152       length -= numbytes;
153    }
154 
155    _XEatData(dpy, length);
156 
157    UnlockDisplay(dpy);
158    SyncHandle();
159 
160    return buf;
161 }
162 
163 char *
__glXQueryServerString(Display * dpy,int opcode,CARD32 screen,CARD32 name)164 __glXQueryServerString(Display * dpy, int opcode, CARD32 screen, CARD32 name)
165 {
166    return __glXGetStringFromServer(dpy, opcode,
167                                    X_GLXQueryServerString, screen, name);
168 }
169 
170 char *
__glXGetString(Display * dpy,int opcode,CARD32 contextTag,CARD32 name)171 __glXGetString(Display * dpy, int opcode, CARD32 contextTag, CARD32 name)
172 {
173    return __glXGetStringFromServer(dpy, opcode, X_GLsop_GetString,
174                                    contextTag, name);
175 }
176 
177 #endif /* USE_XCB */
178