342 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			342 lines
		
	
	
		
			10 KiB
		
	
	
	
		
			C
		
	
	
	
| /*
 | |
|  * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
 | |
|  * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
 | |
|  *
 | |
|  * Permission is hereby granted, free of charge, to any person obtaining a
 | |
|  * copy of this software and associated documentation files (the "Software"),
 | |
|  * to deal in the Software without restriction, including without limitation
 | |
|  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
 | |
|  * and/or sell copies of the Software, and to permit persons to whom the
 | |
|  * Software is furnished to do so, subject to the following conditions:
 | |
|  *
 | |
|  * The above copyright notice including the dates of first publication and
 | |
|  * either this permission notice or a reference to
 | |
|  * http://oss.sgi.com/projects/FreeB/
 | |
|  * shall be included in all copies or substantial portions of the Software.
 | |
|  *
 | |
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
 | |
|  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 | |
|  * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 | |
|  * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
 | |
|  * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 | |
|  * SOFTWARE.
 | |
|  *
 | |
|  * Except as contained in this notice, the name of Silicon Graphics, Inc.
 | |
|  * shall not be used in advertising or otherwise to promote the sale, use or
 | |
|  * other dealings in this Software without prior written authorization from
 | |
|  * Silicon Graphics, Inc.
 | |
|  */
 | |
| 
 | |
| #ifdef HAVE_DMX_CONFIG_H
 | |
| #include <dmx-config.h>
 | |
| #endif
 | |
| 
 | |
| #include "dmx.h"
 | |
| #include "dmxlog.h"
 | |
| 
 | |
| #include "glxserver.h"
 | |
| 
 | |
| #include <windowstr.h>
 | |
| 
 | |
| #include "glxfbconfig.h"
 | |
| 
 | |
| #ifdef PANORAMIX
 | |
| #include "panoramiXsrv.h"
 | |
| #endif
 | |
| 
 | |
| __GLXscreenInfo *__glXActiveScreens;
 | |
| GLint __glXNumActiveScreens;
 | |
| 
 | |
| __GLXFBConfig **__glXFBConfigs;
 | |
| int __glXNumFBConfigs;
 | |
| 
 | |
| static char GLXServerVendorName[] = "SGI DMX/glxProxy";
 | |
| static char GLXServerVersion[64];
 | |
| static char GLXServerExtensions[] =
 | |
|     "GLX_EXT_visual_info "
 | |
|     "GLX_EXT_visual_rating "
 | |
|     "GLX_EXT_import_context "
 | |
|     "GLX_SGIX_fbconfig " "GLX_SGI_make_current_read " "GLX_SGI_swap_control ";
 | |
| 
 | |
| static char ExtensionsString[1024];
 | |
| 
 | |
| static void
 | |
| CalcServerVersionAndExtensions(void)
 | |
| {
 | |
|     int s;
 | |
|     xGLXQueryVersionReq *req;
 | |
|     xGLXQueryVersionReply reply;
 | |
|     char **be_extensions;
 | |
|     char *ext;
 | |
|     char *denied_extensions;
 | |
| 
 | |
|     /*
 | |
|      * set the server glx version to be the minimum version
 | |
|      * supported by all back-end servers
 | |
|      */
 | |
|     __glXVersionMajor = 0;
 | |
|     __glXVersionMinor = 0;
 | |
|     for (s = 0; s < __glXNumActiveScreens; s++) {
 | |
|         DMXScreenInfo *dmxScreen = &dmxScreens[s];
 | |
|         Display *dpy = dmxScreen->beDisplay;
 | |
| 
 | |
|         /* Send the glXQueryVersion request */
 | |
|         LockDisplay(dpy);
 | |
|         GetReq(GLXQueryVersion, req);
 | |
|         req->reqType = dmxScreen->glxMajorOpcode;
 | |
|         req->glxCode = X_GLXQueryVersion;
 | |
|         req->majorVersion = GLX_SERVER_MAJOR_VERSION;
 | |
|         req->minorVersion = GLX_SERVER_MINOR_VERSION;
 | |
|         _XReply(dpy, (xReply *) &reply, 0, False);
 | |
|         UnlockDisplay(dpy);
 | |
|         SyncHandle();
 | |
| 
 | |
|         if (s == 0) {
 | |
|             __glXVersionMajor = reply.majorVersion;
 | |
|             __glXVersionMinor = reply.minorVersion;
 | |
|         }
 | |
|         else {
 | |
|             if (reply.majorVersion < __glXVersionMajor) {
 | |
|                 __glXVersionMajor = reply.majorVersion;
 | |
|                 __glXVersionMinor = reply.minorVersion;
 | |
|             }
 | |
|             else if ((reply.majorVersion == __glXVersionMajor) &&
 | |
|                      (reply.minorVersion < __glXVersionMinor)) {
 | |
|                 __glXVersionMinor = reply.minorVersion;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|     }
 | |
| 
 | |
|     if (GLX_SERVER_MAJOR_VERSION < __glXVersionMajor) {
 | |
|         __glXVersionMajor = GLX_SERVER_MAJOR_VERSION;
 | |
|         __glXVersionMinor = GLX_SERVER_MINOR_VERSION;
 | |
|     }
 | |
|     else if ((GLX_SERVER_MAJOR_VERSION == __glXVersionMajor) &&
 | |
|              (GLX_SERVER_MINOR_VERSION < __glXVersionMinor)) {
 | |
|         __glXVersionMinor = GLX_SERVER_MINOR_VERSION;
 | |
|     }
 | |
| 
 | |
|     snprintf(GLXServerVersion, sizeof(GLXServerVersion),
 | |
|              "%d.%d DMX %d back-end server(s)",
 | |
|              __glXVersionMajor, __glXVersionMinor, __glXNumActiveScreens);
 | |
|     /*
 | |
|      * set the ExtensionsString to the minimum extensions string
 | |
|      */
 | |
|     ExtensionsString[0] = '\0';
 | |
| 
 | |
|     /*
 | |
|      * read extensions strings of all back-end servers
 | |
|      */
 | |
|     be_extensions = (char **) malloc(__glXNumActiveScreens * sizeof(char *));
 | |
|     if (!be_extensions)
 | |
|         return;
 | |
| 
 | |
|     for (s = 0; s < __glXNumActiveScreens; s++) {
 | |
|         DMXScreenInfo *dmxScreen = &dmxScreens[s];
 | |
|         Display *dpy = dmxScreen->beDisplay;
 | |
|         xGLXQueryServerStringReq *req;
 | |
|         xGLXQueryServerStringReply reply;
 | |
|         int length, numbytes;
 | |
| 
 | |
|         /* Send the glXQueryServerString request */
 | |
|         LockDisplay(dpy);
 | |
|         GetReq(GLXQueryServerString, req);
 | |
|         req->reqType = dmxScreen->glxMajorOpcode;
 | |
|         req->glxCode = X_GLXQueryServerString;
 | |
|         req->screen = DefaultScreen(dpy);
 | |
|         req->name = GLX_EXTENSIONS;
 | |
|         _XReply(dpy, (xReply *) &reply, 0, False);
 | |
| 
 | |
|         length = (int) reply.length;
 | |
|         numbytes = (int) reply.n;
 | |
|         be_extensions[s] = (char *) malloc(numbytes);
 | |
|         if (!be_extensions[s]) {
 | |
|             /* Throw data on the floor */
 | |
|             _XEatDataWords(dpy, length);
 | |
|         }
 | |
|         else {
 | |
|             _XReadPad(dpy, (char *) be_extensions[s], numbytes);
 | |
|         }
 | |
|         UnlockDisplay(dpy);
 | |
|         SyncHandle();
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * extensions string will include only extensions that our
 | |
|      * server supports as well as all back-end servers supports.
 | |
|      * extensions that are in the DMX_DENY_EXTENSIONS string will
 | |
|      * not be supported.
 | |
|      */
 | |
|     denied_extensions = getenv("DMX_DENY_GLX_EXTENSIONS");
 | |
|     ext = strtok(GLXServerExtensions, " ");
 | |
|     while (ext) {
 | |
|         int supported = 1;
 | |
| 
 | |
|         if (denied_extensions && strstr(denied_extensions, ext)) {
 | |
|             supported = 0;
 | |
|         }
 | |
|         else {
 | |
|             for (s = 0; s < __glXNumActiveScreens && supported; s++) {
 | |
|                 if (!strstr(be_extensions[s], ext)) {
 | |
|                     supported = 0;
 | |
|                 }
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         if (supported) {
 | |
|             strcat(ExtensionsString, ext);
 | |
|             strcat(ExtensionsString, " ");
 | |
|         }
 | |
| 
 | |
|         ext = strtok(NULL, " ");
 | |
|     }
 | |
| 
 | |
|     /*
 | |
|      * release temporary storage
 | |
|      */
 | |
|     for (s = 0; s < __glXNumActiveScreens; s++) {
 | |
|         free(be_extensions[s]);
 | |
|     }
 | |
|     free(be_extensions);
 | |
| 
 | |
|     if (dmxGLXSwapGroupSupport) {
 | |
|         if (!denied_extensions ||
 | |
|             !strstr(denied_extensions, "GLX_SGIX_swap_group")) {
 | |
|             strcat(ExtensionsString, "GLX_SGIX_swap_group");
 | |
|             if (!denied_extensions ||
 | |
|                 !strstr(denied_extensions, "GLX_SGIX_swap_barrier")) {
 | |
|                 strcat(ExtensionsString, " GLX_SGIX_swap_barrier");
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| void
 | |
| __glXScreenInit(GLint numscreens)
 | |
| {
 | |
|     int s;
 | |
|     int c;
 | |
|     DMXScreenInfo *dmxScreen0 = &dmxScreens[0];
 | |
| 
 | |
|     __glXNumActiveScreens = numscreens;
 | |
| 
 | |
|     CalcServerVersionAndExtensions();
 | |
| 
 | |
|     __glXFBConfigs = NULL;
 | |
|     __glXNumFBConfigs = 0;
 | |
| 
 | |
|     if ((__glXVersionMajor == 1 && __glXVersionMinor >= 3) ||
 | |
|         (__glXVersionMajor > 1) ||
 | |
|         (strstr(ExtensionsString, "GLX_SGIX_fbconfig"))) {
 | |
| 
 | |
|         /*
 | |
|            // Initialize FBConfig info.
 | |
|            // find the set of FBConfigs that are present on all back-end
 | |
|            // servers - only those configs will be supported
 | |
|          */
 | |
|         __glXFBConfigs = (__GLXFBConfig **) malloc(dmxScreen0->numFBConfigs *
 | |
|                                                    (numscreens +
 | |
|                                                     1) *
 | |
|                                                    sizeof(__GLXFBConfig *));
 | |
|         __glXNumFBConfigs = 0;
 | |
| 
 | |
|         for (c = 0; c < dmxScreen0->numFBConfigs; c++) {
 | |
|             __GLXFBConfig *cfg = NULL;
 | |
| 
 | |
|             if (numscreens > 1) {
 | |
|                 for (s = 1; s < numscreens; s++) {
 | |
|                     DMXScreenInfo *dmxScreen = &dmxScreens[s];
 | |
| 
 | |
|                     cfg = FindMatchingFBConfig(&dmxScreen0->fbconfigs[c],
 | |
|                                                dmxScreen->fbconfigs,
 | |
|                                                dmxScreen->numFBConfigs);
 | |
|                     __glXFBConfigs[__glXNumFBConfigs * (numscreens + 1) + s +
 | |
|                                    1] = cfg;
 | |
|                     if (!cfg) {
 | |
|                         dmxLog(dmxInfo,
 | |
|                                "screen0 FBConfig 0x%x is missing on screen#%d\n",
 | |
|                                dmxScreen0->fbconfigs[c].id, s);
 | |
|                         break;
 | |
|                     }
 | |
|                     else {
 | |
|                         dmxLog(dmxInfo,
 | |
|                                "screen0 FBConfig 0x%x matched to  0x%x on screen#%d\n",
 | |
|                                dmxScreen0->fbconfigs[c].id, cfg->id, s);
 | |
|                     }
 | |
|                 }
 | |
|             }
 | |
|             else {
 | |
|                 cfg = &dmxScreen0->fbconfigs[c];
 | |
|             }
 | |
| 
 | |
|             if (cfg) {
 | |
| 
 | |
|                 /* filter out overlay visuals */
 | |
|                 if (cfg->level == 0) {
 | |
|                     __GLXFBConfig *proxy_cfg;
 | |
| 
 | |
|                     __glXFBConfigs[__glXNumFBConfigs * (numscreens + 1) + 1] =
 | |
|                         &dmxScreen0->fbconfigs[c];
 | |
| 
 | |
|                     proxy_cfg = malloc(sizeof(__GLXFBConfig));
 | |
|                     memcpy(proxy_cfg, cfg, sizeof(__GLXFBConfig));
 | |
|                     proxy_cfg->id = FakeClientID(0);
 | |
|                     /* visual will be associated later in __glXGetFBConfigs */
 | |
|                     proxy_cfg->associatedVisualId = (unsigned int) -1;
 | |
| 
 | |
|                     __glXFBConfigs[__glXNumFBConfigs * (numscreens + 1) + 0] =
 | |
|                         proxy_cfg;
 | |
| 
 | |
|                     __glXNumFBConfigs++;
 | |
|                 }
 | |
| 
 | |
|             }
 | |
| 
 | |
|         }
 | |
| 
 | |
|     }
 | |
| 
 | |
| }
 | |
| 
 | |
| void
 | |
| __glXScreenReset(void)
 | |
| {
 | |
|     __glXNumActiveScreens = 0;
 | |
| }
 | |
| 
 | |
| char *
 | |
| __glXGetServerString(unsigned int name)
 | |
| {
 | |
|     char *ret = NULL;
 | |
| 
 | |
|     switch (name) {
 | |
| 
 | |
|     case GLX_VENDOR:
 | |
|         ret = GLXServerVendorName;
 | |
|         break;
 | |
| 
 | |
|     case GLX_VERSION:
 | |
|         ret = GLXServerVersion;
 | |
|         break;
 | |
| 
 | |
|     case GLX_EXTENSIONS:
 | |
|         ret = ExtensionsString;
 | |
|         break;
 | |
| 
 | |
|     default:
 | |
|         break;
 | |
|     }
 | |
| 
 | |
|     return ret;
 | |
| 
 | |
| }
 | |
| 
 | |
| int
 | |
| glxIsExtensionSupported(char *ext)
 | |
| {
 | |
|     return (strstr(ExtensionsString, ext) != NULL);
 | |
| }
 |