glxscreens.c revision 4642e01f
14642e01fSmrg/*
24642e01fSmrg * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
34642e01fSmrg * Copyright (C) 1991-2000 Silicon Graphics, Inc. All Rights Reserved.
44642e01fSmrg *
54642e01fSmrg * Permission is hereby granted, free of charge, to any person obtaining a
64642e01fSmrg * copy of this software and associated documentation files (the "Software"),
74642e01fSmrg * to deal in the Software without restriction, including without limitation
84642e01fSmrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
94642e01fSmrg * and/or sell copies of the Software, and to permit persons to whom the
104642e01fSmrg * Software is furnished to do so, subject to the following conditions:
114642e01fSmrg *
124642e01fSmrg * The above copyright notice including the dates of first publication and
134642e01fSmrg * either this permission notice or a reference to
144642e01fSmrg * http://oss.sgi.com/projects/FreeB/
154642e01fSmrg * shall be included in all copies or substantial portions of the Software.
164642e01fSmrg *
174642e01fSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
184642e01fSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
194642e01fSmrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
204642e01fSmrg * SILICON GRAPHICS, INC. BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
214642e01fSmrg * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
224642e01fSmrg * OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
234642e01fSmrg * SOFTWARE.
244642e01fSmrg *
254642e01fSmrg * Except as contained in this notice, the name of Silicon Graphics, Inc.
264642e01fSmrg * shall not be used in advertising or otherwise to promote the sale, use or
274642e01fSmrg * other dealings in this Software without prior written authorization from
284642e01fSmrg * Silicon Graphics, Inc.
294642e01fSmrg */
304642e01fSmrg
314642e01fSmrg#ifdef HAVE_DIX_CONFIG_H
324642e01fSmrg#include <dix-config.h>
334642e01fSmrg#endif
344642e01fSmrg
354642e01fSmrg#include <GL/glxtokens.h>
364642e01fSmrg#include <string.h>
374642e01fSmrg#include <windowstr.h>
384642e01fSmrg#include <os.h>
394642e01fSmrg#include <colormapst.h>
404642e01fSmrg
414642e01fSmrg#include "privates.h"
424642e01fSmrg#include "glxserver.h"
434642e01fSmrg#include "glxutil.h"
444642e01fSmrg#include "glxext.h"
454642e01fSmrg
464642e01fSmrgstatic int glxScreenPrivateKeyIndex;
474642e01fSmrgstatic DevPrivateKey glxScreenPrivateKey = &glxScreenPrivateKeyIndex;
484642e01fSmrg
494642e01fSmrgconst char GLServerVersion[] = "1.4";
504642e01fSmrgstatic const char GLServerExtensions[] =
514642e01fSmrg			"GL_ARB_depth_texture "
524642e01fSmrg			"GL_ARB_draw_buffers "
534642e01fSmrg			"GL_ARB_fragment_program "
544642e01fSmrg			"GL_ARB_fragment_program_shadow "
554642e01fSmrg			"GL_ARB_imaging "
564642e01fSmrg			"GL_ARB_multisample "
574642e01fSmrg			"GL_ARB_multitexture "
584642e01fSmrg			"GL_ARB_occlusion_query "
594642e01fSmrg			"GL_ARB_point_parameters "
604642e01fSmrg			"GL_ARB_point_sprite "
614642e01fSmrg			"GL_ARB_shadow "
624642e01fSmrg			"GL_ARB_shadow_ambient "
634642e01fSmrg			"GL_ARB_texture_border_clamp "
644642e01fSmrg			"GL_ARB_texture_compression "
654642e01fSmrg			"GL_ARB_texture_cube_map "
664642e01fSmrg			"GL_ARB_texture_env_add "
674642e01fSmrg			"GL_ARB_texture_env_combine "
684642e01fSmrg			"GL_ARB_texture_env_crossbar "
694642e01fSmrg			"GL_ARB_texture_env_dot3 "
704642e01fSmrg			"GL_ARB_texture_mirrored_repeat "
714642e01fSmrg			"GL_ARB_texture_non_power_of_two "
724642e01fSmrg			"GL_ARB_transpose_matrix "
734642e01fSmrg			"GL_ARB_vertex_program "
744642e01fSmrg			"GL_ARB_window_pos "
754642e01fSmrg			"GL_EXT_abgr "
764642e01fSmrg			"GL_EXT_bgra "
774642e01fSmrg 			"GL_EXT_blend_color "
784642e01fSmrg			"GL_EXT_blend_equation_separate "
794642e01fSmrg			"GL_EXT_blend_func_separate "
804642e01fSmrg			"GL_EXT_blend_logic_op "
814642e01fSmrg 			"GL_EXT_blend_minmax "
824642e01fSmrg 			"GL_EXT_blend_subtract "
834642e01fSmrg			"GL_EXT_clip_volume_hint "
844642e01fSmrg			"GL_EXT_copy_texture "
854642e01fSmrg			"GL_EXT_draw_range_elements "
864642e01fSmrg			"GL_EXT_fog_coord "
874642e01fSmrg			"GL_EXT_framebuffer_object "
884642e01fSmrg			"GL_EXT_multi_draw_arrays "
894642e01fSmrg			"GL_EXT_packed_pixels "
904642e01fSmrg			"GL_EXT_paletted_texture "
914642e01fSmrg			"GL_EXT_point_parameters "
924642e01fSmrg			"GL_EXT_polygon_offset "
934642e01fSmrg			"GL_EXT_rescale_normal "
944642e01fSmrg			"GL_EXT_secondary_color "
954642e01fSmrg			"GL_EXT_separate_specular_color "
964642e01fSmrg			"GL_EXT_shadow_funcs "
974642e01fSmrg			"GL_EXT_shared_texture_palette "
984642e01fSmrg 			"GL_EXT_stencil_two_side "
994642e01fSmrg			"GL_EXT_stencil_wrap "
1004642e01fSmrg			"GL_EXT_subtexture "
1014642e01fSmrg			"GL_EXT_texture "
1024642e01fSmrg			"GL_EXT_texture3D "
1034642e01fSmrg			"GL_EXT_texture_compression_dxt1 "
1044642e01fSmrg			"GL_EXT_texture_compression_s3tc "
1054642e01fSmrg			"GL_EXT_texture_edge_clamp "
1064642e01fSmrg 			"GL_EXT_texture_env_add "
1074642e01fSmrg 			"GL_EXT_texture_env_combine "
1084642e01fSmrg 			"GL_EXT_texture_env_dot3 "
1094642e01fSmrg 			"GL_EXT_texture_filter_anisotropic "
1104642e01fSmrg			"GL_EXT_texture_lod "
1114642e01fSmrg 			"GL_EXT_texture_lod_bias "
1124642e01fSmrg 			"GL_EXT_texture_mirror_clamp "
1134642e01fSmrg			"GL_EXT_texture_object "
1144642e01fSmrg			"GL_EXT_texture_rectangle "
1154642e01fSmrg			"GL_EXT_vertex_array "
1164642e01fSmrg			"GL_3DFX_texture_compression_FXT1 "
1174642e01fSmrg			"GL_APPLE_packed_pixels "
1184642e01fSmrg			"GL_ATI_draw_buffers "
1194642e01fSmrg			"GL_ATI_texture_env_combine3 "
1204642e01fSmrg			"GL_ATI_texture_mirror_once "
1214642e01fSmrg 			"GL_HP_occlusion_test "
1224642e01fSmrg			"GL_IBM_texture_mirrored_repeat "
1234642e01fSmrg			"GL_INGR_blend_func_separate "
1244642e01fSmrg			"GL_MESA_pack_invert "
1254642e01fSmrg			"GL_MESA_ycbcr_texture "
1264642e01fSmrg			"GL_NV_blend_square "
1274642e01fSmrg			"GL_NV_depth_clamp "
1284642e01fSmrg			"GL_NV_fog_distance "
1294642e01fSmrg			"GL_NV_fragment_program "
1304642e01fSmrg			"GL_NV_fragment_program_option "
1314642e01fSmrg			"GL_NV_fragment_program2 "
1324642e01fSmrg			"GL_NV_light_max_exponent "
1334642e01fSmrg			"GL_NV_multisample_filter_hint "
1344642e01fSmrg			"GL_NV_point_sprite "
1354642e01fSmrg			"GL_NV_texgen_reflection "
1364642e01fSmrg			"GL_NV_texture_compression_vtc "
1374642e01fSmrg			"GL_NV_texture_env_combine4 "
1384642e01fSmrg			"GL_NV_texture_expand_normal "
1394642e01fSmrg			"GL_NV_texture_rectangle "
1404642e01fSmrg			"GL_NV_vertex_program "
1414642e01fSmrg			"GL_NV_vertex_program1_1 "
1424642e01fSmrg			"GL_NV_vertex_program2 "
1434642e01fSmrg			"GL_NV_vertex_program2_option "
1444642e01fSmrg			"GL_NV_vertex_program3 "
1454642e01fSmrg			"GL_OES_compressed_paletted_texture "
1464642e01fSmrg			"GL_SGI_color_matrix "
1474642e01fSmrg			"GL_SGI_color_table "
1484642e01fSmrg			"GL_SGIS_generate_mipmap "
1494642e01fSmrg			"GL_SGIS_multisample "
1504642e01fSmrg			"GL_SGIS_point_parameters "
1514642e01fSmrg			"GL_SGIS_texture_border_clamp "
1524642e01fSmrg			"GL_SGIS_texture_edge_clamp "
1534642e01fSmrg			"GL_SGIS_texture_lod "
1544642e01fSmrg			"GL_SGIX_depth_texture "
1554642e01fSmrg			"GL_SGIX_shadow "
1564642e01fSmrg			"GL_SGIX_shadow_ambient "
1574642e01fSmrg			"GL_SUN_slice_accum "
1584642e01fSmrg			;
1594642e01fSmrg
1604642e01fSmrg/*
1614642e01fSmrg** We have made the simplifying assuption that the same extensions are
1624642e01fSmrg** supported across all screens in a multi-screen system.
1634642e01fSmrg*/
1644642e01fSmrgstatic char GLXServerVendorName[] = "SGI";
1654642e01fSmrgstatic char GLXServerVersion[] = "1.2";
1664642e01fSmrgstatic char GLXServerExtensions[] =
1674642e01fSmrg			"GLX_ARB_multisample "
1684642e01fSmrg			"GLX_EXT_visual_info "
1694642e01fSmrg			"GLX_EXT_visual_rating "
1704642e01fSmrg			"GLX_EXT_import_context "
1714642e01fSmrg                        "GLX_EXT_texture_from_pixmap "
1724642e01fSmrg			"GLX_OML_swap_method "
1734642e01fSmrg			"GLX_SGI_make_current_read "
1744642e01fSmrg#ifndef __APPLE__
1754642e01fSmrg			"GLX_SGIS_multisample "
1764642e01fSmrg                        "GLX_SGIX_hyperpipe "
1774642e01fSmrg                        "GLX_SGIX_swap_barrier "
1784642e01fSmrg#endif
1794642e01fSmrg			"GLX_SGIX_fbconfig "
1804642e01fSmrg			"GLX_MESA_copy_sub_buffer "
1814642e01fSmrg			;
1824642e01fSmrg
1834642e01fSmrg/*
1844642e01fSmrg * If your DDX driver wants to register support for swap barriers or hyperpipe
1854642e01fSmrg * topology, it should call __glXHyperpipeInit() or __glXSwapBarrierInit()
1864642e01fSmrg * with a dispatch table of functions to handle the requests.   In the XFree86
1874642e01fSmrg * DDX, for example, you would call these near the bottom of the driver's
1884642e01fSmrg * ScreenInit method, after DRI has been initialized.
1894642e01fSmrg *
1904642e01fSmrg * This should be replaced with a better method when we teach the server how
1914642e01fSmrg * to load DRI drivers.
1924642e01fSmrg */
1934642e01fSmrg
1944642e01fSmrgvoid __glXHyperpipeInit(int screen, __GLXHyperpipeExtensionFuncs *funcs)
1954642e01fSmrg{
1964642e01fSmrg    __GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
1974642e01fSmrg
1984642e01fSmrg    pGlxScreen->hyperpipeFuncs = funcs;
1994642e01fSmrg}
2004642e01fSmrg
2014642e01fSmrgvoid __glXSwapBarrierInit(int screen, __GLXSwapBarrierExtensionFuncs *funcs)
2024642e01fSmrg{
2034642e01fSmrg    __GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]);
2044642e01fSmrg
2054642e01fSmrg    pGlxScreen->swapBarrierFuncs = funcs;
2064642e01fSmrg}
2074642e01fSmrg
2084642e01fSmrgstatic Bool
2094642e01fSmrgglxCloseScreen (int index, ScreenPtr pScreen)
2104642e01fSmrg{
2114642e01fSmrg    __GLXscreen *pGlxScreen = glxGetScreen(pScreen);
2124642e01fSmrg
2134642e01fSmrg    pScreen->CloseScreen = pGlxScreen->CloseScreen;
2144642e01fSmrg
2154642e01fSmrg    pGlxScreen->destroy(pGlxScreen);
2164642e01fSmrg
2174642e01fSmrg    return pScreen->CloseScreen(index, pScreen);
2184642e01fSmrg}
2194642e01fSmrg
2204642e01fSmrg__GLXscreen *
2214642e01fSmrgglxGetScreen(ScreenPtr pScreen)
2224642e01fSmrg{
2234642e01fSmrg    return dixLookupPrivate(&pScreen->devPrivates, glxScreenPrivateKey);
2244642e01fSmrg}
2254642e01fSmrg
2264642e01fSmrgvoid GlxSetVisualConfigs(int nconfigs,
2274642e01fSmrg                         __GLXvisualConfig *configs, void **privates)
2284642e01fSmrg{
2294642e01fSmrg    /* We keep this stub around for the DDX drivers that still
2304642e01fSmrg     * call it. */
2314642e01fSmrg}
2324642e01fSmrg
2334642e01fSmrgGLint glxConvertToXVisualType(int visualType)
2344642e01fSmrg{
2354642e01fSmrg    static const int x_visual_types[] = {
2364642e01fSmrg	TrueColor,   DirectColor,
2374642e01fSmrg	PseudoColor, StaticColor,
2384642e01fSmrg	GrayScale,   StaticGray
2394642e01fSmrg    };
2404642e01fSmrg
2414642e01fSmrg    return ( (unsigned) (visualType - GLX_TRUE_COLOR) < 6 )
2424642e01fSmrg	? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1;
2434642e01fSmrg}
2444642e01fSmrg
2454642e01fSmrg/* This code inspired by composite/compinit.c.  We could move this to
2464642e01fSmrg * mi/ and share it with composite.*/
2474642e01fSmrg
2484642e01fSmrgstatic VisualPtr
2494642e01fSmrgAddScreenVisuals(ScreenPtr pScreen, int count, int d)
2504642e01fSmrg{
2514642e01fSmrg    XID		*installedCmaps, *vids, vid;
2524642e01fSmrg    int		 numInstalledCmaps, numVisuals, i, j;
2534642e01fSmrg    VisualPtr	 visuals;
2544642e01fSmrg    ColormapPtr	 installedCmap;
2554642e01fSmrg    DepthPtr	 depth;
2564642e01fSmrg
2574642e01fSmrg    depth = NULL;
2584642e01fSmrg    for (i = 0; i < pScreen->numDepths; i++) {
2594642e01fSmrg	if (pScreen->allowedDepths[i].depth == d) {
2604642e01fSmrg	    depth = &pScreen->allowedDepths[i];
2614642e01fSmrg	    break;
2624642e01fSmrg	}
2634642e01fSmrg    }
2644642e01fSmrg    if (depth == NULL)
2654642e01fSmrg	return NULL;
2664642e01fSmrg
2674642e01fSmrg    /* Find the installed colormaps */
2684642e01fSmrg    installedCmaps = xalloc (pScreen->maxInstalledCmaps * sizeof (XID));
2694642e01fSmrg    if (!installedCmaps)
2704642e01fSmrg	return NULL;
2714642e01fSmrg
2724642e01fSmrg    numInstalledCmaps = pScreen->ListInstalledColormaps(pScreen, installedCmaps);
2734642e01fSmrg
2744642e01fSmrg    /* realloc the visual array to fit the new one in place */
2754642e01fSmrg    numVisuals = pScreen->numVisuals;
2764642e01fSmrg    visuals = xrealloc(pScreen->visuals, (numVisuals + count) * sizeof(VisualRec));
2774642e01fSmrg    if (!visuals) {
2784642e01fSmrg	xfree(installedCmaps);
2794642e01fSmrg	return NULL;
2804642e01fSmrg    }
2814642e01fSmrg
2824642e01fSmrg    vids = xrealloc(depth->vids, (depth->numVids + count) * sizeof(XID));
2834642e01fSmrg    if (vids == NULL) {
2844642e01fSmrg	xfree(installedCmaps);
2854642e01fSmrg	xfree(visuals);
2864642e01fSmrg	return NULL;
2874642e01fSmrg    }
2884642e01fSmrg
2894642e01fSmrg    /*
2904642e01fSmrg     * Fix up any existing installed colormaps -- we'll assume that
2914642e01fSmrg     * the only ones created so far have been installed.  If this
2924642e01fSmrg     * isn't true, we'll have to walk the resource database looking
2934642e01fSmrg     * for all colormaps.
2944642e01fSmrg     */
2954642e01fSmrg    for (i = 0; i < numInstalledCmaps; i++) {
2964642e01fSmrg	installedCmap = LookupIDByType (installedCmaps[i], RT_COLORMAP);
2974642e01fSmrg	if (!installedCmap)
2984642e01fSmrg	    continue;
2994642e01fSmrg	j = installedCmap->pVisual - pScreen->visuals;
3004642e01fSmrg	installedCmap->pVisual = &visuals[j];
3014642e01fSmrg    }
3024642e01fSmrg
3034642e01fSmrg    xfree(installedCmaps);
3044642e01fSmrg
3054642e01fSmrg    for (i = 0; i < count; i++) {
3064642e01fSmrg	vid = FakeClientID(0);
3074642e01fSmrg	visuals[pScreen->numVisuals + i].vid = vid;
3084642e01fSmrg	vids[depth->numVids + i] = vid;
3094642e01fSmrg    }
3104642e01fSmrg
3114642e01fSmrg    pScreen->visuals = visuals;
3124642e01fSmrg    pScreen->numVisuals += count;
3134642e01fSmrg    depth->vids = vids;
3144642e01fSmrg    depth->numVids += count;
3154642e01fSmrg
3164642e01fSmrg    /* Return a pointer to the first of the added visuals. */
3174642e01fSmrg    return pScreen->visuals + pScreen->numVisuals - count;
3184642e01fSmrg}
3194642e01fSmrg
3204642e01fSmrgstatic int
3214642e01fSmrgfindFirstSet(unsigned int v)
3224642e01fSmrg{
3234642e01fSmrg    int i;
3244642e01fSmrg
3254642e01fSmrg    for (i = 0; i < 32; i++)
3264642e01fSmrg	if (v & (1 << i))
3274642e01fSmrg	    return i;
3284642e01fSmrg
3294642e01fSmrg    return -1;
3304642e01fSmrg}
3314642e01fSmrg
3324642e01fSmrgstatic void
3334642e01fSmrginitGlxVisual(VisualPtr visual, __GLXconfig *config)
3344642e01fSmrg{
3354642e01fSmrg    int maxBits;
3364642e01fSmrg    maxBits = max(config->redBits, max(config->greenBits, config->blueBits));
3374642e01fSmrg
3384642e01fSmrg    config->visualID = visual->vid;
3394642e01fSmrg    visual->class = glxConvertToXVisualType(config->visualType);
3404642e01fSmrg    visual->bitsPerRGBValue = maxBits;
3414642e01fSmrg    visual->ColormapEntries = 1 << maxBits;
3424642e01fSmrg    visual->nplanes = config->redBits + config->greenBits + config->blueBits;
3434642e01fSmrg
3444642e01fSmrg    visual->redMask = config->redMask;
3454642e01fSmrg    visual->greenMask = config->greenMask;
3464642e01fSmrg    visual->blueMask = config->blueMask;
3474642e01fSmrg    visual->offsetRed = findFirstSet(config->redMask);
3484642e01fSmrg    visual->offsetGreen = findFirstSet(config->greenMask);
3494642e01fSmrg    visual->offsetBlue = findFirstSet(config->blueMask);
3504642e01fSmrg}
3514642e01fSmrg
3524642e01fSmrgstatic __GLXconfig *
3534642e01fSmrgpickFBConfig(__GLXscreen *pGlxScreen, VisualPtr visual)
3544642e01fSmrg{
3554642e01fSmrg    __GLXconfig *best = NULL, *config;
3564642e01fSmrg    int best_score = 0;
3574642e01fSmrg
3584642e01fSmrg    for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
3594642e01fSmrg	int score = 0;
3604642e01fSmrg
3614642e01fSmrg	if (config->redMask != visual->redMask ||
3624642e01fSmrg	    config->greenMask != visual->greenMask ||
3634642e01fSmrg	    config->blueMask != visual->blueMask)
3644642e01fSmrg	    continue;
3654642e01fSmrg	if (config->visualRating != GLX_NONE)
3664642e01fSmrg	    continue;
3674642e01fSmrg	if (glxConvertToXVisualType(config->visualType) != visual->class)
3684642e01fSmrg	    continue;
3694642e01fSmrg	/* If it's the 32-bit RGBA visual, demand a 32-bit fbconfig. */
3704642e01fSmrg	if (visual->nplanes == 32 && config->rgbBits != 32)
3714642e01fSmrg	    continue;
3724642e01fSmrg	/* Can't use the same FBconfig for multiple X visuals.  I think. */
3734642e01fSmrg	if (config->visualID != 0)
3744642e01fSmrg	    continue;
3754642e01fSmrg
3764642e01fSmrg	if (config->doubleBufferMode > 0)
3774642e01fSmrg	    score += 8;
3784642e01fSmrg	if (config->depthBits > 0)
3794642e01fSmrg	    score += 4;
3804642e01fSmrg	if (config->stencilBits > 0)
3814642e01fSmrg	    score += 2;
3824642e01fSmrg	if (config->alphaBits > 0)
3834642e01fSmrg	    score++;
3844642e01fSmrg
3854642e01fSmrg	if (score > best_score) {
3864642e01fSmrg	    best = config;
3874642e01fSmrg	    best_score = score;
3884642e01fSmrg	}
3894642e01fSmrg    }
3904642e01fSmrg
3914642e01fSmrg    return best;
3924642e01fSmrg}
3934642e01fSmrg
3944642e01fSmrgvoid __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen)
3954642e01fSmrg{
3964642e01fSmrg    __GLXconfig *m;
3974642e01fSmrg    __GLXconfig *config;
3984642e01fSmrg    int i;
3994642e01fSmrg
4004642e01fSmrg    pGlxScreen->pScreen       = pScreen;
4014642e01fSmrg    pGlxScreen->GLextensions  = xstrdup(GLServerExtensions);
4024642e01fSmrg    pGlxScreen->GLXvendor     = xstrdup(GLXServerVendorName);
4034642e01fSmrg    pGlxScreen->GLXversion    = xstrdup(GLXServerVersion);
4044642e01fSmrg    pGlxScreen->GLXextensions = xstrdup(GLXServerExtensions);
4054642e01fSmrg
4064642e01fSmrg    pGlxScreen->CloseScreen = pScreen->CloseScreen;
4074642e01fSmrg    pScreen->CloseScreen = glxCloseScreen;
4084642e01fSmrg
4094642e01fSmrg    i = 0;
4104642e01fSmrg    for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) {
4114642e01fSmrg	m->fbconfigID = FakeClientID(0);
4124642e01fSmrg	m->visualID = 0;
4134642e01fSmrg	i++;
4144642e01fSmrg    }
4154642e01fSmrg    pGlxScreen->numFBConfigs = i;
4164642e01fSmrg
4174642e01fSmrg    pGlxScreen->visuals =
4184642e01fSmrg	xcalloc(pGlxScreen->numFBConfigs, sizeof (__GLXconfig *));
4194642e01fSmrg
4204642e01fSmrg    /* First, try to choose featureful FBconfigs for the existing X visuals.
4214642e01fSmrg     * Note that if multiple X visuals end up with the same FBconfig being
4224642e01fSmrg     * chosen, the later X visuals don't get GLX visuals (because we want to
4234642e01fSmrg     * prioritize the root visual being GLX).
4244642e01fSmrg     */
4254642e01fSmrg    for (i = 0; i < pScreen->numVisuals; i++) {
4264642e01fSmrg	VisualPtr visual = &pScreen->visuals[i];
4274642e01fSmrg
4284642e01fSmrg	config = pickFBConfig(pGlxScreen, visual);
4294642e01fSmrg	if (config) {
4304642e01fSmrg	    pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
4314642e01fSmrg	    config->visualID = visual->vid;
4324642e01fSmrg	}
4334642e01fSmrg    }
4344642e01fSmrg
4354642e01fSmrg    /* Then, add new visuals corresponding to all FBconfigs that didn't have
4364642e01fSmrg     * an existing, appropriate visual.
4374642e01fSmrg     */
4384642e01fSmrg    for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
4394642e01fSmrg	int depth;
4404642e01fSmrg
4414642e01fSmrg	VisualPtr visual;
4424642e01fSmrg
4434642e01fSmrg	if (config->visualID != 0)
4444642e01fSmrg	    continue;
4454642e01fSmrg
4464642e01fSmrg	/* Only count RGB bits and not alpha, as we're not trying to create
4474642e01fSmrg	 * visuals for compositing (that's what the 32-bit composite visual
4484642e01fSmrg	 * set up above is for.
4494642e01fSmrg	 */
4504642e01fSmrg	depth = config->redBits + config->greenBits + config->blueBits;
4514642e01fSmrg
4524642e01fSmrg	/* Make sure that our FBconfig's depth can actually be displayed
4534642e01fSmrg	 * (corresponds to an existing visual).
4544642e01fSmrg	 */
4554642e01fSmrg	for (i = 0; i < pScreen->numVisuals; i++) {
4564642e01fSmrg	    if (depth == pScreen->visuals[i].nplanes)
4574642e01fSmrg		break;
4584642e01fSmrg	}
4594642e01fSmrg	if (i == pScreen->numVisuals)
4604642e01fSmrg	    continue;
4614642e01fSmrg
4624642e01fSmrg	/* Create a new X visual for our FBconfig. */
4634642e01fSmrg	visual = AddScreenVisuals(pScreen, 1, depth);
4644642e01fSmrg	if (visual == NULL)
4654642e01fSmrg	    continue;
4664642e01fSmrg
4674642e01fSmrg	pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
4684642e01fSmrg	initGlxVisual(visual, config);
4694642e01fSmrg    }
4704642e01fSmrg
4714642e01fSmrg    dixSetPrivate(&pScreen->devPrivates, glxScreenPrivateKey, pGlxScreen);
4724642e01fSmrg}
4734642e01fSmrg
4744642e01fSmrgvoid __glXScreenDestroy(__GLXscreen *screen)
4754642e01fSmrg{
4764642e01fSmrg    xfree(screen->GLXvendor);
4774642e01fSmrg    xfree(screen->GLXversion);
4784642e01fSmrg    xfree(screen->GLXextensions);
4794642e01fSmrg    xfree(screen->GLextensions);
4804642e01fSmrg}
481