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