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;
49GLint __glXNumActiveScreens;
50
51__GLXFBConfig **__glXFBConfigs;
52int            __glXNumFBConfigs;
53
54static char GLXServerVendorName[] = "SGI DMX/glxProxy";
55static char GLXServerVersion[64];
56static char GLXServerExtensions[] =
57            "GLX_EXT_visual_info "
58            "GLX_EXT_visual_rating "
59            "GLX_EXT_import_context "
60	    "GLX_SGIX_fbconfig "
61	    "GLX_SGI_make_current_read "
62	    "GLX_SGI_swap_control "
63            ;
64
65static char ExtensionsString[1024];
66
67static void CalcServerVersionAndExtensions( void )
68{
69   int s;
70   xGLXQueryVersionReq *req;
71   xGLXQueryVersionReply reply;
72   char **be_extensions;
73   char *ext;
74   char *denied_extensions;
75
76   /*
77    * set the server glx version to be the minimum version
78    * supported by all back-end servers
79    */
80   __glXVersionMajor = 0;
81   __glXVersionMinor = 0;
82   for (s=0; s<__glXNumActiveScreens; s++) {
83      DMXScreenInfo *dmxScreen = &dmxScreens[s];
84      Display *dpy = dmxScreen->beDisplay;
85
86      /* Send the glXQueryVersion request */
87      LockDisplay(dpy);
88      GetReq(GLXQueryVersion,req);
89      req->reqType = dmxScreen->glxMajorOpcode;
90      req->glxCode = X_GLXQueryVersion;
91      req->majorVersion = GLX_SERVER_MAJOR_VERSION;
92      req->minorVersion = GLX_SERVER_MINOR_VERSION;
93      _XReply(dpy, (xReply*) &reply, 0, False);
94      UnlockDisplay(dpy);
95      SyncHandle();
96
97      if (s == 0) {
98	 __glXVersionMajor = reply.majorVersion;
99	 __glXVersionMinor = reply.minorVersion;
100      }
101      else {
102	 if (reply.majorVersion < __glXVersionMajor) {
103	    __glXVersionMajor = reply.majorVersion;
104	    __glXVersionMinor = reply.minorVersion;
105	 }
106	 else if ( (reply.majorVersion == __glXVersionMajor) &&
107	           (reply.minorVersion < __glXVersionMinor)  ) {
108	    __glXVersionMinor = reply.minorVersion;
109	 }
110      }
111
112   }
113
114   if (GLX_SERVER_MAJOR_VERSION < __glXVersionMajor) {
115      __glXVersionMajor = GLX_SERVER_MAJOR_VERSION;
116      __glXVersionMinor = GLX_SERVER_MINOR_VERSION;
117   }
118   else if ( (GLX_SERVER_MAJOR_VERSION == __glXVersionMajor) &&
119	     (GLX_SERVER_MINOR_VERSION < __glXVersionMinor)  ) {
120      __glXVersionMinor = GLX_SERVER_MINOR_VERSION;
121   }
122
123   sprintf(GLXServerVersion, "%d.%d DMX %d back-end server(s)",
124              __glXVersionMajor, __glXVersionMinor, __glXNumActiveScreens );
125   /*
126    * set the ExtensionsString to the minimum extensions string
127    */
128   ExtensionsString[0] = '\0';
129
130   /*
131    * read extensions strings of all back-end servers
132    */
133   be_extensions = (char **)malloc( __glXNumActiveScreens * sizeof(char *) );
134   if (!be_extensions)
135      return;
136
137   for (s=0; s<__glXNumActiveScreens; s++) {
138      DMXScreenInfo *dmxScreen = &dmxScreens[s];
139      Display *dpy = dmxScreen->beDisplay;
140      xGLXQueryServerStringReq *req;
141      xGLXQueryServerStringReply reply;
142      int length, numbytes, slop;
143
144      /* Send the glXQueryServerString request */
145      LockDisplay(dpy);
146      GetReq(GLXQueryServerString,req);
147      req->reqType = dmxScreen->glxMajorOpcode;
148      req->glxCode = X_GLXQueryServerString;
149      req->screen = DefaultScreen(dpy);
150      req->name = GLX_EXTENSIONS;
151      _XReply(dpy, (xReply*) &reply, 0, False);
152
153      length = (int)reply.length;
154      numbytes = (int)reply.n;
155      slop = numbytes * __GLX_SIZE_INT8 & 3;
156      be_extensions[s] = (char *)malloc(numbytes);
157      if (!be_extensions[s]) {
158	 /* Throw data on the floor */
159	 _XEatData(dpy, length);
160      } else {
161	 _XRead(dpy, (char *)be_extensions[s], numbytes);
162	 if (slop) _XEatData(dpy,4-slop);
163      }
164      UnlockDisplay(dpy);
165      SyncHandle();
166   }
167
168   /*
169    * extensions string will include only extensions that our
170    * server supports as well as all back-end servers supports.
171    * extensions that are in the DMX_DENY_EXTENSIONS string will
172    * not be supported.
173    */
174   denied_extensions = getenv("DMX_DENY_GLX_EXTENSIONS");
175   ext = strtok(GLXServerExtensions, " ");
176   while( ext ) {
177      int supported = 1;
178
179      if (denied_extensions && strstr(denied_extensions, ext)) {
180	 supported = 0;
181      }
182      else {
183	 for (s=0; s<__glXNumActiveScreens && supported; s++) {
184	    if ( !strstr(be_extensions[s], ext) ) {
185	       supported = 0;
186	    }
187	 }
188      }
189
190      if (supported) {
191	 strcat(ExtensionsString, ext);
192	 strcat(ExtensionsString, " ");
193      }
194
195      ext = strtok(NULL, " ");
196   }
197
198   /*
199    * release temporary storage
200    */
201   for (s=0; s<__glXNumActiveScreens; s++) {
202      free(be_extensions[s]);
203   }
204   free( be_extensions );
205
206   if (dmxGLXSwapGroupSupport) {
207       if (!denied_extensions ||
208	   !strstr(denied_extensions, "GLX_SGIX_swap_group")) {
209	   strcat(ExtensionsString, "GLX_SGIX_swap_group");
210	   if (!denied_extensions ||
211	       !strstr(denied_extensions, "GLX_SGIX_swap_barrier")) {
212	       strcat(ExtensionsString, " GLX_SGIX_swap_barrier");
213	   }
214       }
215   }
216
217}
218
219void __glXScreenInit(GLint numscreens)
220{
221   int s;
222   int c;
223   DMXScreenInfo *dmxScreen0 = &dmxScreens[0];
224    __glXNumActiveScreens = numscreens;
225
226
227   CalcServerVersionAndExtensions();
228
229
230   __glXFBConfigs = NULL;
231   __glXNumFBConfigs = 0;
232
233   if ( (__glXVersionMajor == 1 && __glXVersionMinor >= 3) ||
234        (__glXVersionMajor > 1) ||
235	( strstr(ExtensionsString, "GLX_SGIX_fbconfig") )      ) {
236
237      /*
238      // Initialize FBConfig info.
239      // find the set of FBConfigs that are present on all back-end
240      // servers - only those configs will be supported
241       */
242      __glXFBConfigs = (__GLXFBConfig **)malloc( dmxScreen0->numFBConfigs *
243	                      (numscreens+1) * sizeof(__GLXFBConfig *) );
244      __glXNumFBConfigs = 0;
245
246      for (c=0; c<dmxScreen0->numFBConfigs; c++) {
247	 __GLXFBConfig *cfg = NULL;
248
249	 if (numscreens > 1) {
250	    for (s=1; s<numscreens; s++) {
251	       DMXScreenInfo *dmxScreen = &dmxScreens[s];
252
253	       cfg = FindMatchingFBConfig( &dmxScreen0->fbconfigs[c],
254		                           dmxScreen->fbconfigs,
255		                           dmxScreen->numFBConfigs );
256	       __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + s + 1 ] = cfg;
257	       if (!cfg) {
258		  dmxLog(dmxInfo,"screen0 FBConfig 0x%x is missing on screen#%d\n", dmxScreen0->fbconfigs[c].id, s);
259		  break;
260	       }
261	       else {
262		  dmxLog(dmxInfo,"screen0 FBConfig 0x%x matched to  0x%x on screen#%d\n", dmxScreen0->fbconfigs[c].id, cfg->id, s);
263	       }
264	    }
265         }
266	 else {
267	    cfg = &dmxScreen0->fbconfigs[c];
268	 }
269
270	 if (cfg) {
271
272	    /* filter out overlay visuals */
273	    if (cfg->level == 0) {
274	       __GLXFBConfig *proxy_cfg;
275
276	       __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + 1 ] =
277	               &dmxScreen0->fbconfigs[c];
278
279	       proxy_cfg = malloc( sizeof(__GLXFBConfig) );
280	       memcpy( proxy_cfg, cfg, sizeof(__GLXFBConfig) );
281	       proxy_cfg->id =  FakeClientID(0);
282	       /* visual will be associated later in __glXGetFBConfigs */
283	       proxy_cfg->associatedVisualId =  (unsigned int)-1;
284
285	       __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + 0 ] = proxy_cfg;
286
287	       __glXNumFBConfigs++;
288	    }
289
290	 }
291
292      }
293
294    }
295
296}
297
298void __glXScreenReset(void)
299{
300  __glXNumActiveScreens = 0;
301}
302
303char *__glXGetServerString( unsigned int name )
304{
305   char *ret = NULL;
306
307   switch( name) {
308
309      case GLX_VENDOR:
310	 ret = GLXServerVendorName;
311	 break;
312
313      case GLX_VERSION:
314	 ret = GLXServerVersion;
315	 break;
316
317      case GLX_EXTENSIONS:
318	 ret = ExtensionsString;
319	 break;
320
321      default:
322	 break;
323   }
324
325   return ret;
326
327}
328
329
330__GLXFBConfig *glxLookupFBConfig( GLXFBConfigID id )
331{
332   int i,j;
333
334   for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) {
335      if ( __glXFBConfigs[j]->id == id)
336	 return __glXFBConfigs[j];
337   }
338
339   return NULL;
340}
341
342__GLXFBConfig *glxLookupFBConfigByVID( VisualID vid )
343{
344   int i,j;
345
346   for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) {
347      if ( __glXFBConfigs[j]->associatedVisualId == vid)
348	 return __glXFBConfigs[j];
349   }
350
351   return NULL;
352}
353
354__GLXFBConfig *glxLookupBackEndFBConfig( GLXFBConfigID id, int screen )
355{
356   int i;
357   int j;
358
359   for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) {
360      if ( __glXFBConfigs[j]->id == id)
361	 return __glXFBConfigs[j+screen+1];
362   }
363
364   return NULL;
365
366}
367
368int glxIsExtensionSupported( char *ext )
369{
370   return( strstr(ExtensionsString, ext) != NULL );
371}
372