1 /*
2 * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3 * Copyright (C) 1991-2000 Silicon Graphics, Inc. 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 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9 * and/or sell copies of the Software, and to permit persons to whom the
10 * Software is furnished to do so, subject to the following conditions:
11 *
12 * The above copyright notice including the dates of first publication and
13 * either this permission notice or a reference to
14 * http://oss.sgi.com/projects/FreeB/
15 * shall be included in all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20 * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22 * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 *
25 * Except as contained in this notice, the name of Silicon Graphics, Inc.
26 * shall not be used in advertising or otherwise to promote the sale, use or
27 * other dealings in this Software without prior written authorization from
28 * Silicon Graphics, Inc.
29 */
30
31 #ifdef HAVE_DMX_CONFIG_H
32 #include <dmx-config.h>
33 #endif
34
35 #include "dmx.h"
36 #include "dmxlog.h"
37
38 #include "glxserver.h"
39
40 #include <windowstr.h>
41
42 #include "glxfbconfig.h"
43
44 #ifdef PANORAMIX
45 #include "panoramiXsrv.h"
46 #endif
47
48 __GLXscreenInfo *__glXActiveScreens;
49 GLint __glXNumActiveScreens;
50
51 __GLXFBConfig **__glXFBConfigs;
52 int __glXNumFBConfigs;
53
54 static char GLXServerVendorName[] = "SGI DMX/glxProxy";
55 static char GLXServerVersion[64];
56 static char GLXServerExtensions[] =
57 "GLX_EXT_visual_info "
58 "GLX_EXT_visual_rating "
59 "GLX_EXT_import_context "
60 "GLX_SGIX_fbconfig " "GLX_SGI_make_current_read " "GLX_SGI_swap_control ";
61
62 static char ExtensionsString[1024];
63
64 static void
CalcServerVersionAndExtensions(void)65 CalcServerVersionAndExtensions(void)
66 {
67 int s;
68 char **be_extensions;
69 char *ext;
70 char *denied_extensions;
71
72 /*
73 * set the server glx version to be the minimum version
74 * supported by all back-end servers
75 */
76 __glXVersionMajor = 0;
77 __glXVersionMinor = 0;
78 for (s = 0; s < __glXNumActiveScreens; s++) {
79 DMXScreenInfo *dmxScreen = &dmxScreens[s];
80 Display *dpy = dmxScreen->beDisplay;
81 xGLXQueryVersionReq *req;
82 xGLXQueryVersionReply reply;
83
84 /* Send the glXQueryVersion request */
85 LockDisplay(dpy);
86 GetReq(GLXQueryVersion, req);
87 req->reqType = dmxScreen->glxMajorOpcode;
88 req->glxCode = X_GLXQueryVersion;
89 req->majorVersion = GLX_SERVER_MAJOR_VERSION;
90 req->minorVersion = GLX_SERVER_MINOR_VERSION;
91 _XReply(dpy, (xReply *) &reply, 0, False);
92 UnlockDisplay(dpy);
93 SyncHandle();
94
95 if (s == 0) {
96 __glXVersionMajor = reply.majorVersion;
97 __glXVersionMinor = reply.minorVersion;
98 }
99 else {
100 if (reply.majorVersion < __glXVersionMajor) {
101 __glXVersionMajor = reply.majorVersion;
102 __glXVersionMinor = reply.minorVersion;
103 }
104 else if ((reply.majorVersion == __glXVersionMajor) &&
105 (reply.minorVersion < __glXVersionMinor)) {
106 __glXVersionMinor = reply.minorVersion;
107 }
108 }
109
110 }
111
112 if (GLX_SERVER_MAJOR_VERSION < __glXVersionMajor) {
113 __glXVersionMajor = GLX_SERVER_MAJOR_VERSION;
114 __glXVersionMinor = GLX_SERVER_MINOR_VERSION;
115 }
116 else if ((GLX_SERVER_MAJOR_VERSION == __glXVersionMajor) &&
117 (GLX_SERVER_MINOR_VERSION < __glXVersionMinor)) {
118 __glXVersionMinor = GLX_SERVER_MINOR_VERSION;
119 }
120
121 snprintf(GLXServerVersion, sizeof(GLXServerVersion),
122 "%d.%d DMX %d back-end server(s)",
123 __glXVersionMajor, __glXVersionMinor, __glXNumActiveScreens);
124 /*
125 * set the ExtensionsString to the minimum extensions string
126 */
127 ExtensionsString[0] = '\0';
128
129 /*
130 * read extensions strings of all back-end servers
131 */
132 be_extensions = xallocarray(__glXNumActiveScreens, sizeof(char *));
133 if (!be_extensions)
134 return;
135
136 for (s = 0; s < __glXNumActiveScreens; s++) {
137 DMXScreenInfo *dmxScreen = &dmxScreens[s];
138 Display *dpy = dmxScreen->beDisplay;
139 xGLXQueryServerStringReq *req;
140 xGLXQueryServerStringReply reply;
141 int length, numbytes;
142
143 /* Send the glXQueryServerString request */
144 LockDisplay(dpy);
145 GetReq(GLXQueryServerString, req);
146 req->reqType = dmxScreen->glxMajorOpcode;
147 req->glxCode = X_GLXQueryServerString;
148 req->screen = DefaultScreen(dpy);
149 req->name = GLX_EXTENSIONS;
150 _XReply(dpy, (xReply *) &reply, 0, False);
151
152 length = (int) reply.length;
153 numbytes = (int) reply.n;
154 be_extensions[s] = (char *) malloc(numbytes);
155 if (!be_extensions[s]) {
156 /* Throw data on the floor */
157 _XEatDataWords(dpy, length);
158 }
159 else {
160 _XReadPad(dpy, (char *) be_extensions[s], numbytes);
161 }
162 UnlockDisplay(dpy);
163 SyncHandle();
164 }
165
166 /*
167 * extensions string will include only extensions that our
168 * server supports as well as all back-end servers supports.
169 * extensions that are in the DMX_DENY_EXTENSIONS string will
170 * not be supported.
171 */
172 denied_extensions = getenv("DMX_DENY_GLX_EXTENSIONS");
173 ext = strtok(GLXServerExtensions, " ");
174 while (ext) {
175 int supported = 1;
176
177 if (denied_extensions && strstr(denied_extensions, ext)) {
178 supported = 0;
179 }
180 else {
181 for (s = 0; s < __glXNumActiveScreens && supported; s++) {
182 if (!strstr(be_extensions[s], ext)) {
183 supported = 0;
184 }
185 }
186 }
187
188 if (supported) {
189 strcat(ExtensionsString, ext);
190 strcat(ExtensionsString, " ");
191 }
192
193 ext = strtok(NULL, " ");
194 }
195
196 /*
197 * release temporary storage
198 */
199 for (s = 0; s < __glXNumActiveScreens; s++) {
200 free(be_extensions[s]);
201 }
202 free(be_extensions);
203
204 if (dmxGLXSwapGroupSupport) {
205 if (!denied_extensions ||
206 !strstr(denied_extensions, "GLX_SGIX_swap_group")) {
207 strcat(ExtensionsString, "GLX_SGIX_swap_group");
208 if (!denied_extensions ||
209 !strstr(denied_extensions, "GLX_SGIX_swap_barrier")) {
210 strcat(ExtensionsString, " GLX_SGIX_swap_barrier");
211 }
212 }
213 }
214
215 }
216
217 void
__glXScreenInit(GLint numscreens)218 __glXScreenInit(GLint numscreens)
219 {
220 int s;
221 int c;
222 DMXScreenInfo *dmxScreen0 = &dmxScreens[0];
223
224 __glXNumActiveScreens = numscreens;
225
226 CalcServerVersionAndExtensions();
227
228 __glXFBConfigs = NULL;
229 __glXNumFBConfigs = 0;
230
231 if ((__glXVersionMajor == 1 && __glXVersionMinor >= 3) ||
232 (__glXVersionMajor > 1) ||
233 (strstr(ExtensionsString, "GLX_SGIX_fbconfig"))) {
234
235 /*
236 // Initialize FBConfig info.
237 // find the set of FBConfigs that are present on all back-end
238 // servers - only those configs will be supported
239 */
240 __glXFBConfigs =
241 xallocarray(dmxScreen0->numFBConfigs * (numscreens + 1),
242 sizeof(__GLXFBConfig *));
243 __glXNumFBConfigs = 0;
244
245 for (c = 0; c < dmxScreen0->numFBConfigs; c++) {
246 __GLXFBConfig *cfg = NULL;
247
248 if (numscreens > 1) {
249 for (s = 1; s < numscreens; s++) {
250 DMXScreenInfo *dmxScreen = &dmxScreens[s];
251
252 cfg = FindMatchingFBConfig(&dmxScreen0->fbconfigs[c],
253 dmxScreen->fbconfigs,
254 dmxScreen->numFBConfigs);
255 __glXFBConfigs[__glXNumFBConfigs * (numscreens + 1) + s +
256 1] = cfg;
257 if (!cfg) {
258 dmxLog(dmxInfo,
259 "screen0 FBConfig 0x%x is missing on screen#%d\n",
260 dmxScreen0->fbconfigs[c].id, s);
261 break;
262 }
263 else {
264 dmxLog(dmxInfo,
265 "screen0 FBConfig 0x%x matched to 0x%x on screen#%d\n",
266 dmxScreen0->fbconfigs[c].id, cfg->id, s);
267 }
268 }
269 }
270 else {
271 cfg = &dmxScreen0->fbconfigs[c];
272 }
273
274 if (cfg) {
275
276 /* filter out overlay visuals */
277 if (cfg->level == 0) {
278 __GLXFBConfig *proxy_cfg;
279
280 __glXFBConfigs[__glXNumFBConfigs * (numscreens + 1) + 1] =
281 &dmxScreen0->fbconfigs[c];
282
283 proxy_cfg = malloc(sizeof(__GLXFBConfig));
284 memcpy(proxy_cfg, cfg, sizeof(__GLXFBConfig));
285 proxy_cfg->id = FakeClientID(0);
286 /* visual will be associated later in __glXGetFBConfigs */
287 proxy_cfg->associatedVisualId = (unsigned int) -1;
288
289 __glXFBConfigs[__glXNumFBConfigs * (numscreens + 1) + 0] =
290 proxy_cfg;
291
292 __glXNumFBConfigs++;
293 }
294
295 }
296
297 }
298
299 }
300
301 }
302
303 void
__glXScreenReset(void)304 __glXScreenReset(void)
305 {
306 __glXNumActiveScreens = 0;
307 }
308
309 char *
__glXGetServerString(unsigned int name)310 __glXGetServerString(unsigned int name)
311 {
312 char *ret = NULL;
313
314 switch (name) {
315
316 case GLX_VENDOR:
317 ret = GLXServerVendorName;
318 break;
319
320 case GLX_VERSION:
321 ret = GLXServerVersion;
322 break;
323
324 case GLX_EXTENSIONS:
325 ret = ExtensionsString;
326 break;
327
328 default:
329 break;
330 }
331
332 return ret;
333
334 }
335
336 int
glxIsExtensionSupported(const char * ext)337 glxIsExtensionSupported(const char *ext)
338 {
339 return (strstr(ExtensionsString, ext) != NULL);
340 }
341