1706f2543Smrg/*
2706f2543Smrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
3706f2543Smrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
4706f2543Smrg *
5706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining a
6706f2543Smrg * copy of this software and associated documentation files (the "Software"),
7706f2543Smrg * to deal in the Software without restriction, including without limitation
8706f2543Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
9706f2543Smrg * and/or sell copies of the Software, and to permit persons to whom the
10706f2543Smrg * Software is furnished to do so, subject to the following conditions:
11706f2543Smrg *
12706f2543Smrg * The above copyright notice including the dates of first publication and
13706f2543Smrg * either this permission notice or a reference to
14706f2543Smrg * http://oss.sgi.com/projects/FreeB/
15706f2543Smrg * shall be included in all copies or substantial portions of the Software.
16706f2543Smrg *
17706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18706f2543Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19706f2543Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20706f2543Smrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21706f2543Smrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
22706f2543Smrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23706f2543Smrg * SOFTWARE.
24706f2543Smrg *
25706f2543Smrg * Except as contained in this notice, the name of Silicon Graphics, Inc.
26706f2543Smrg * shall not be used in advertising or otherwise to promote the sale, use or
27706f2543Smrg * other dealings in this Software without prior written authorization from
28706f2543Smrg * Silicon Graphics, Inc.
29706f2543Smrg */
30706f2543Smrg
31706f2543Smrg#ifdef HAVE_DMX_CONFIG_H
32706f2543Smrg#include <dmx-config.h>
33706f2543Smrg#endif
34706f2543Smrg
35706f2543Smrg#include "dmx.h"
36706f2543Smrg#include "dmxlog.h"
37706f2543Smrg
38706f2543Smrg#include "glxserver.h"
39706f2543Smrg
40706f2543Smrg#include <windowstr.h>
41706f2543Smrg
42706f2543Smrg#include "glxfbconfig.h"
43706f2543Smrg
44706f2543Smrg#ifdef PANORAMIX
45706f2543Smrg#include "panoramiXsrv.h"
46706f2543Smrg#endif
47706f2543Smrg
48706f2543Smrg__GLXscreenInfo *__glXActiveScreens;
49706f2543SmrgGLint __glXNumActiveScreens;
50706f2543Smrg
51706f2543Smrg__GLXFBConfig **__glXFBConfigs;
52706f2543Smrgint            __glXNumFBConfigs;
53706f2543Smrg
54706f2543Smrgstatic char GLXServerVendorName[] = "SGI DMX/glxProxy";
55706f2543Smrgstatic char GLXServerVersion[64];
56706f2543Smrgstatic char GLXServerExtensions[] =
57706f2543Smrg            "GLX_EXT_visual_info "
58706f2543Smrg            "GLX_EXT_visual_rating "
59706f2543Smrg            "GLX_EXT_import_context "
60706f2543Smrg	    "GLX_SGIX_fbconfig "
61706f2543Smrg	    "GLX_SGI_make_current_read "
62706f2543Smrg	    "GLX_SGI_swap_control "
63706f2543Smrg            ;
64706f2543Smrg
65706f2543Smrgstatic char ExtensionsString[1024];
66706f2543Smrg
67706f2543Smrgstatic void CalcServerVersionAndExtensions( void )
68706f2543Smrg{
69706f2543Smrg   int s;
70706f2543Smrg   xGLXQueryVersionReq *req;
71706f2543Smrg   xGLXQueryVersionReply reply;
72706f2543Smrg   char **be_extensions;
73706f2543Smrg   char *ext;
74706f2543Smrg   char *denied_extensions;
75706f2543Smrg
76706f2543Smrg   /*
77706f2543Smrg    * set the server glx version to be the minimum version
78706f2543Smrg    * supported by all back-end servers
79706f2543Smrg    */
80706f2543Smrg   __glXVersionMajor = 0;
81706f2543Smrg   __glXVersionMinor = 0;
82706f2543Smrg   for (s=0; s<__glXNumActiveScreens; s++) {
83706f2543Smrg      DMXScreenInfo *dmxScreen = &dmxScreens[s];
84706f2543Smrg      Display *dpy = dmxScreen->beDisplay;
85706f2543Smrg
86706f2543Smrg      /* Send the glXQueryVersion request */
87706f2543Smrg      LockDisplay(dpy);
88706f2543Smrg      GetReq(GLXQueryVersion,req);
89706f2543Smrg      req->reqType = dmxScreen->glxMajorOpcode;
90706f2543Smrg      req->glxCode = X_GLXQueryVersion;
91706f2543Smrg      req->majorVersion = GLX_SERVER_MAJOR_VERSION;
92706f2543Smrg      req->minorVersion = GLX_SERVER_MINOR_VERSION;
93706f2543Smrg      _XReply(dpy, (xReply*) &reply, 0, False);
94706f2543Smrg      UnlockDisplay(dpy);
95706f2543Smrg      SyncHandle();
96706f2543Smrg
97706f2543Smrg      if (s == 0) {
98706f2543Smrg	 __glXVersionMajor = reply.majorVersion;
99706f2543Smrg	 __glXVersionMinor = reply.minorVersion;
100706f2543Smrg      }
101706f2543Smrg      else {
102706f2543Smrg	 if (reply.majorVersion < __glXVersionMajor) {
103706f2543Smrg	    __glXVersionMajor = reply.majorVersion;
104706f2543Smrg	    __glXVersionMinor = reply.minorVersion;
105706f2543Smrg	 }
106706f2543Smrg	 else if ( (reply.majorVersion == __glXVersionMajor) &&
107706f2543Smrg	           (reply.minorVersion < __glXVersionMinor)  ) {
108706f2543Smrg	    __glXVersionMinor = reply.minorVersion;
109706f2543Smrg	 }
110706f2543Smrg      }
111706f2543Smrg
112706f2543Smrg   }
113706f2543Smrg
114706f2543Smrg   if (GLX_SERVER_MAJOR_VERSION < __glXVersionMajor) {
115706f2543Smrg      __glXVersionMajor = GLX_SERVER_MAJOR_VERSION;
116706f2543Smrg      __glXVersionMinor = GLX_SERVER_MINOR_VERSION;
117706f2543Smrg   }
118706f2543Smrg   else if ( (GLX_SERVER_MAJOR_VERSION == __glXVersionMajor) &&
119706f2543Smrg	     (GLX_SERVER_MINOR_VERSION < __glXVersionMinor)  ) {
120706f2543Smrg      __glXVersionMinor = GLX_SERVER_MINOR_VERSION;
121706f2543Smrg   }
122706f2543Smrg
123706f2543Smrg   sprintf(GLXServerVersion, "%d.%d DMX %d back-end server(s)",
124706f2543Smrg              __glXVersionMajor, __glXVersionMinor, __glXNumActiveScreens );
125706f2543Smrg   /*
126706f2543Smrg    * set the ExtensionsString to the minimum extensions string
127706f2543Smrg    */
128706f2543Smrg   ExtensionsString[0] = '\0';
129706f2543Smrg
130706f2543Smrg   /*
131706f2543Smrg    * read extensions strings of all back-end servers
132706f2543Smrg    */
133706f2543Smrg   be_extensions = (char **)malloc( __glXNumActiveScreens * sizeof(char *) );
134706f2543Smrg   if (!be_extensions)
135706f2543Smrg      return;
136706f2543Smrg
137706f2543Smrg   for (s=0; s<__glXNumActiveScreens; s++) {
138706f2543Smrg      DMXScreenInfo *dmxScreen = &dmxScreens[s];
139706f2543Smrg      Display *dpy = dmxScreen->beDisplay;
140706f2543Smrg      xGLXQueryServerStringReq *req;
141706f2543Smrg      xGLXQueryServerStringReply reply;
142706f2543Smrg      int length, numbytes, slop;
143706f2543Smrg
144706f2543Smrg      /* Send the glXQueryServerString request */
145706f2543Smrg      LockDisplay(dpy);
146706f2543Smrg      GetReq(GLXQueryServerString,req);
147706f2543Smrg      req->reqType = dmxScreen->glxMajorOpcode;
148706f2543Smrg      req->glxCode = X_GLXQueryServerString;
149706f2543Smrg      req->screen = DefaultScreen(dpy);
150706f2543Smrg      req->name = GLX_EXTENSIONS;
151706f2543Smrg      _XReply(dpy, (xReply*) &reply, 0, False);
152706f2543Smrg
153706f2543Smrg      length = (int)reply.length;
154706f2543Smrg      numbytes = (int)reply.n;
155706f2543Smrg      slop = numbytes * __GLX_SIZE_INT8 & 3;
156706f2543Smrg      be_extensions[s] = (char *)malloc(numbytes);
157706f2543Smrg      if (!be_extensions[s]) {
158706f2543Smrg	 /* Throw data on the floor */
159706f2543Smrg	 _XEatData(dpy, length);
160706f2543Smrg      } else {
161706f2543Smrg	 _XRead(dpy, (char *)be_extensions[s], numbytes);
162706f2543Smrg	 if (slop) _XEatData(dpy,4-slop);
163706f2543Smrg      }
164706f2543Smrg      UnlockDisplay(dpy);
165706f2543Smrg      SyncHandle();
166706f2543Smrg   }
167706f2543Smrg
168706f2543Smrg   /*
169706f2543Smrg    * extensions string will include only extensions that our
170706f2543Smrg    * server supports as well as all back-end servers supports.
171706f2543Smrg    * extensions that are in the DMX_DENY_EXTENSIONS string will
172706f2543Smrg    * not be supported.
173706f2543Smrg    */
174706f2543Smrg   denied_extensions = getenv("DMX_DENY_GLX_EXTENSIONS");
175706f2543Smrg   ext = strtok(GLXServerExtensions, " ");
176706f2543Smrg   while( ext ) {
177706f2543Smrg      int supported = 1;
178706f2543Smrg
179706f2543Smrg      if (denied_extensions && strstr(denied_extensions, ext)) {
180706f2543Smrg	 supported = 0;
181706f2543Smrg      }
182706f2543Smrg      else {
183706f2543Smrg	 for (s=0; s<__glXNumActiveScreens && supported; s++) {
184706f2543Smrg	    if ( !strstr(be_extensions[s], ext) ) {
185706f2543Smrg	       supported = 0;
186706f2543Smrg	    }
187706f2543Smrg	 }
188706f2543Smrg      }
189706f2543Smrg
190706f2543Smrg      if (supported) {
191706f2543Smrg	 strcat(ExtensionsString, ext);
192706f2543Smrg	 strcat(ExtensionsString, " ");
193706f2543Smrg      }
194706f2543Smrg
195706f2543Smrg      ext = strtok(NULL, " ");
196706f2543Smrg   }
197706f2543Smrg
198706f2543Smrg   /*
199706f2543Smrg    * release temporary storage
200706f2543Smrg    */
201706f2543Smrg   for (s=0; s<__glXNumActiveScreens; s++) {
202706f2543Smrg      free(be_extensions[s]);
203706f2543Smrg   }
204706f2543Smrg   free( be_extensions );
205706f2543Smrg
206706f2543Smrg   if (dmxGLXSwapGroupSupport) {
207706f2543Smrg       if (!denied_extensions ||
208706f2543Smrg	   !strstr(denied_extensions, "GLX_SGIX_swap_group")) {
209706f2543Smrg	   strcat(ExtensionsString, "GLX_SGIX_swap_group");
210706f2543Smrg	   if (!denied_extensions ||
211706f2543Smrg	       !strstr(denied_extensions, "GLX_SGIX_swap_barrier")) {
212706f2543Smrg	       strcat(ExtensionsString, " GLX_SGIX_swap_barrier");
213706f2543Smrg	   }
214706f2543Smrg       }
215706f2543Smrg   }
216706f2543Smrg
217706f2543Smrg}
218706f2543Smrg
219706f2543Smrgvoid __glXScreenInit(GLint numscreens)
220706f2543Smrg{
221706f2543Smrg   int s;
222706f2543Smrg   int c;
223706f2543Smrg   DMXScreenInfo *dmxScreen0 = &dmxScreens[0];
224706f2543Smrg    __glXNumActiveScreens = numscreens;
225706f2543Smrg
226706f2543Smrg
227706f2543Smrg   CalcServerVersionAndExtensions();
228706f2543Smrg
229706f2543Smrg
230706f2543Smrg   __glXFBConfigs = NULL;
231706f2543Smrg   __glXNumFBConfigs = 0;
232706f2543Smrg
233706f2543Smrg   if ( (__glXVersionMajor == 1 && __glXVersionMinor >= 3) ||
234706f2543Smrg        (__glXVersionMajor > 1) ||
235706f2543Smrg	( strstr(ExtensionsString, "GLX_SGIX_fbconfig") )      ) {
236706f2543Smrg
237706f2543Smrg      /*
238706f2543Smrg      // Initialize FBConfig info.
239706f2543Smrg      // find the set of FBConfigs that are present on all back-end
240706f2543Smrg      // servers - only those configs will be supported
241706f2543Smrg       */
242706f2543Smrg      __glXFBConfigs = (__GLXFBConfig **)malloc( dmxScreen0->numFBConfigs *
243706f2543Smrg	                      (numscreens+1) * sizeof(__GLXFBConfig *) );
244706f2543Smrg      __glXNumFBConfigs = 0;
245706f2543Smrg
246706f2543Smrg      for (c=0; c<dmxScreen0->numFBConfigs; c++) {
247706f2543Smrg	 __GLXFBConfig *cfg = NULL;
248706f2543Smrg
249706f2543Smrg	 if (numscreens > 1) {
250706f2543Smrg	    for (s=1; s<numscreens; s++) {
251706f2543Smrg	       DMXScreenInfo *dmxScreen = &dmxScreens[s];
252706f2543Smrg
253706f2543Smrg	       cfg = FindMatchingFBConfig( &dmxScreen0->fbconfigs[c],
254706f2543Smrg		                           dmxScreen->fbconfigs,
255706f2543Smrg		                           dmxScreen->numFBConfigs );
256706f2543Smrg	       __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + s + 1 ] = cfg;
257706f2543Smrg	       if (!cfg) {
258706f2543Smrg		  dmxLog(dmxInfo,"screen0 FBConfig 0x%x is missing on screen#%d\n", dmxScreen0->fbconfigs[c].id, s);
259706f2543Smrg		  break;
260706f2543Smrg	       }
261706f2543Smrg	       else {
262706f2543Smrg		  dmxLog(dmxInfo,"screen0 FBConfig 0x%x matched to  0x%x on screen#%d\n", dmxScreen0->fbconfigs[c].id, cfg->id, s);
263706f2543Smrg	       }
264706f2543Smrg	    }
265706f2543Smrg         }
266706f2543Smrg	 else {
267706f2543Smrg	    cfg = &dmxScreen0->fbconfigs[c];
268706f2543Smrg	 }
269706f2543Smrg
270706f2543Smrg	 if (cfg) {
271706f2543Smrg
272706f2543Smrg	    /* filter out overlay visuals */
273706f2543Smrg	    if (cfg->level == 0) {
274706f2543Smrg	       __GLXFBConfig *proxy_cfg;
275706f2543Smrg
276706f2543Smrg	       __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + 1 ] =
277706f2543Smrg	               &dmxScreen0->fbconfigs[c];
278706f2543Smrg
279706f2543Smrg	       proxy_cfg = malloc( sizeof(__GLXFBConfig) );
280706f2543Smrg	       memcpy( proxy_cfg, cfg, sizeof(__GLXFBConfig) );
281706f2543Smrg	       proxy_cfg->id =  FakeClientID(0);
282706f2543Smrg	       /* visual will be associated later in __glXGetFBConfigs */
283706f2543Smrg	       proxy_cfg->associatedVisualId =  (unsigned int)-1;
284706f2543Smrg
285706f2543Smrg	       __glXFBConfigs[ __glXNumFBConfigs * (numscreens+1) + 0 ] = proxy_cfg;
286706f2543Smrg
287706f2543Smrg	       __glXNumFBConfigs++;
288706f2543Smrg	    }
289706f2543Smrg
290706f2543Smrg	 }
291706f2543Smrg
292706f2543Smrg      }
293706f2543Smrg
294706f2543Smrg    }
295706f2543Smrg
296706f2543Smrg}
297706f2543Smrg
298706f2543Smrgvoid __glXScreenReset(void)
299706f2543Smrg{
300706f2543Smrg  __glXNumActiveScreens = 0;
301706f2543Smrg}
302706f2543Smrg
303706f2543Smrgchar *__glXGetServerString( unsigned int name )
304706f2543Smrg{
305706f2543Smrg   char *ret = NULL;
306706f2543Smrg
307706f2543Smrg   switch( name) {
308706f2543Smrg
309706f2543Smrg      case GLX_VENDOR:
310706f2543Smrg	 ret = GLXServerVendorName;
311706f2543Smrg	 break;
312706f2543Smrg
313706f2543Smrg      case GLX_VERSION:
314706f2543Smrg	 ret = GLXServerVersion;
315706f2543Smrg	 break;
316706f2543Smrg
317706f2543Smrg      case GLX_EXTENSIONS:
318706f2543Smrg	 ret = ExtensionsString;
319706f2543Smrg	 break;
320706f2543Smrg
321706f2543Smrg      default:
322706f2543Smrg	 break;
323706f2543Smrg   }
324706f2543Smrg
325706f2543Smrg   return ret;
326706f2543Smrg
327706f2543Smrg}
328706f2543Smrg
329706f2543Smrg
330706f2543Smrg__GLXFBConfig *glxLookupFBConfig( GLXFBConfigID id )
331706f2543Smrg{
332706f2543Smrg   int i,j;
333706f2543Smrg
334706f2543Smrg   for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) {
335706f2543Smrg      if ( __glXFBConfigs[j]->id == id)
336706f2543Smrg	 return __glXFBConfigs[j];
337706f2543Smrg   }
338706f2543Smrg
339706f2543Smrg   return NULL;
340706f2543Smrg}
341706f2543Smrg
342706f2543Smrg__GLXFBConfig *glxLookupFBConfigByVID( VisualID vid )
343706f2543Smrg{
344706f2543Smrg   int i,j;
345706f2543Smrg
346706f2543Smrg   for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) {
347706f2543Smrg      if ( __glXFBConfigs[j]->associatedVisualId == vid)
348706f2543Smrg	 return __glXFBConfigs[j];
349706f2543Smrg   }
350706f2543Smrg
351706f2543Smrg   return NULL;
352706f2543Smrg}
353706f2543Smrg
354706f2543Smrg__GLXFBConfig *glxLookupBackEndFBConfig( GLXFBConfigID id, int screen )
355706f2543Smrg{
356706f2543Smrg   int i;
357706f2543Smrg   int j;
358706f2543Smrg
359706f2543Smrg   for (i=0, j=0; i<__glXNumFBConfigs; i++,j+=(__glXNumActiveScreens+1) ) {
360706f2543Smrg      if ( __glXFBConfigs[j]->id == id)
361706f2543Smrg	 return __glXFBConfigs[j+screen+1];
362706f2543Smrg   }
363706f2543Smrg
364706f2543Smrg   return NULL;
365706f2543Smrg
366706f2543Smrg}
367706f2543Smrg
368706f2543Smrgint glxIsExtensionSupported( char *ext )
369706f2543Smrg{
370706f2543Smrg   return( strstr(ExtensionsString, ext) != NULL );
371706f2543Smrg}
372