diff options
Diffstat (limited to 'xorg-server/glx/glxscreens.c')
-rw-r--r-- | xorg-server/glx/glxscreens.c | 855 |
1 files changed, 429 insertions, 426 deletions
diff --git a/xorg-server/glx/glxscreens.c b/xorg-server/glx/glxscreens.c index ce513dda7..9eb0f7d55 100644 --- a/xorg-server/glx/glxscreens.c +++ b/xorg-server/glx/glxscreens.c @@ -1,426 +1,429 @@ -/*
- * 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_DIX_CONFIG_H
-#include <dix-config.h>
-#else
-
-#include "glheader.h"
-
-#endif
-
-#include <GL/glxtokens.h>
-#include <string.h>
-#include <windowstr.h>
-#include <os.h>
-#include <colormapst.h>
-
-#include "privates.h"
-#include "glxserver.h"
-#include "glxutil.h"
-#include "glxext.h"
-#include "protocol-versions.h"
-
-static DevPrivateKeyRec glxScreenPrivateKeyRec;
-#define glxScreenPrivateKey (&glxScreenPrivateKeyRec)
-
-const char GLServerVersion[] = "1.4";
-static const char GLServerExtensions[] =
- "GL_ARB_depth_texture "
- "GL_ARB_draw_buffers "
- "GL_ARB_fragment_program "
- "GL_ARB_fragment_program_shadow "
- "GL_ARB_imaging "
- "GL_ARB_multisample "
- "GL_ARB_multitexture "
- "GL_ARB_occlusion_query "
- "GL_ARB_point_parameters "
- "GL_ARB_point_sprite "
- "GL_ARB_shadow "
- "GL_ARB_shadow_ambient "
- "GL_ARB_texture_border_clamp "
- "GL_ARB_texture_compression "
- "GL_ARB_texture_cube_map "
- "GL_ARB_texture_env_add "
- "GL_ARB_texture_env_combine "
- "GL_ARB_texture_env_crossbar "
- "GL_ARB_texture_env_dot3 "
- "GL_ARB_texture_mirrored_repeat "
- "GL_ARB_texture_non_power_of_two "
- "GL_ARB_transpose_matrix "
- "GL_ARB_vertex_program "
- "GL_ARB_window_pos "
- "GL_EXT_abgr "
- "GL_EXT_bgra "
- "GL_EXT_blend_color "
- "GL_EXT_blend_equation_separate "
- "GL_EXT_blend_func_separate "
- "GL_EXT_blend_logic_op "
- "GL_EXT_blend_minmax "
- "GL_EXT_blend_subtract "
- "GL_EXT_clip_volume_hint "
- "GL_EXT_copy_texture "
- "GL_EXT_draw_range_elements "
- "GL_EXT_fog_coord "
- "GL_EXT_framebuffer_object "
- "GL_EXT_multi_draw_arrays "
- "GL_EXT_packed_pixels "
- "GL_EXT_paletted_texture "
- "GL_EXT_point_parameters "
- "GL_EXT_polygon_offset "
- "GL_EXT_rescale_normal "
- "GL_EXT_secondary_color "
- "GL_EXT_separate_specular_color "
- "GL_EXT_shadow_funcs "
- "GL_EXT_shared_texture_palette "
- "GL_EXT_stencil_two_side "
- "GL_EXT_stencil_wrap "
- "GL_EXT_subtexture "
- "GL_EXT_texture "
- "GL_EXT_texture3D "
- "GL_EXT_texture_compression_dxt1 "
- "GL_EXT_texture_compression_s3tc "
- "GL_EXT_texture_edge_clamp "
- "GL_EXT_texture_env_add "
- "GL_EXT_texture_env_combine "
- "GL_EXT_texture_env_dot3 "
- "GL_EXT_texture_filter_anisotropic "
- "GL_EXT_texture_lod "
- "GL_EXT_texture_lod_bias "
- "GL_EXT_texture_mirror_clamp "
- "GL_EXT_texture_object "
- "GL_EXT_texture_rectangle "
- "GL_EXT_vertex_array "
- "GL_3DFX_texture_compression_FXT1 "
- "GL_APPLE_packed_pixels "
- "GL_ATI_draw_buffers "
- "GL_ATI_texture_env_combine3 "
- "GL_ATI_texture_mirror_once "
- "GL_HP_occlusion_test "
- "GL_IBM_texture_mirrored_repeat "
- "GL_INGR_blend_func_separate "
- "GL_MESA_pack_invert "
- "GL_MESA_ycbcr_texture "
- "GL_NV_blend_square "
- "GL_NV_depth_clamp "
- "GL_NV_fog_distance "
- "GL_NV_fragment_program "
- "GL_NV_fragment_program_option "
- "GL_NV_fragment_program2 "
- "GL_NV_light_max_exponent "
- "GL_NV_multisample_filter_hint "
- "GL_NV_point_sprite "
- "GL_NV_texgen_reflection "
- "GL_NV_texture_compression_vtc "
- "GL_NV_texture_env_combine4 "
- "GL_NV_texture_expand_normal "
- "GL_NV_texture_rectangle "
- "GL_NV_vertex_program "
- "GL_NV_vertex_program1_1 "
- "GL_NV_vertex_program2 "
- "GL_NV_vertex_program2_option "
- "GL_NV_vertex_program3 "
- "GL_OES_compressed_paletted_texture "
- "GL_SGI_color_matrix "
- "GL_SGI_color_table "
- "GL_SGIS_generate_mipmap "
- "GL_SGIS_multisample "
- "GL_SGIS_point_parameters "
- "GL_SGIS_texture_border_clamp "
- "GL_SGIS_texture_edge_clamp "
- "GL_SGIS_texture_lod "
- "GL_SGIX_depth_texture "
- "GL_SGIX_shadow "
- "GL_SGIX_shadow_ambient "
- "GL_SUN_slice_accum "
- ;
-
-/*
-** We have made the simplifying assuption that the same extensions are
-** supported across all screens in a multi-screen system.
-*/
-static char GLXServerVendorName[] = "SGI";
-unsigned glxMajorVersion = SERVER_GLX_MAJOR_VERSION;
-unsigned glxMinorVersion = SERVER_GLX_MINOR_VERSION;
-static char GLXServerExtensions[] =
- "GLX_ARB_multisample "
- "GLX_EXT_visual_info "
- "GLX_EXT_visual_rating "
- "GLX_EXT_import_context "
- "GLX_EXT_texture_from_pixmap "
- "GLX_OML_swap_method "
- "GLX_SGI_make_current_read "
-#ifndef __APPLE__
- "GLX_SGIS_multisample "
-#endif
- "GLX_SGIX_fbconfig "
- "GLX_SGIX_pbuffer "
- "GLX_MESA_copy_sub_buffer "
- "GLX_INTEL_swap_event"
- ;
-
-static Bool
-glxCloseScreen (int index, ScreenPtr pScreen)
-{
- __GLXscreen *pGlxScreen = glxGetScreen(pScreen);
-
- pScreen->CloseScreen = pGlxScreen->CloseScreen;
-
- pGlxScreen->destroy(pGlxScreen);
-
- return pScreen->CloseScreen(index, pScreen);
-}
-
-__GLXscreen *
-glxGetScreen(ScreenPtr pScreen)
-{
- return dixLookupPrivate(&pScreen->devPrivates, glxScreenPrivateKey);
-}
-
-_X_EXPORT void GlxSetVisualConfigs(int nconfigs,
- void *configs, void **privates)
-{
- /* We keep this stub around for the DDX drivers that still
- * call it. */
-}
-
-GLint glxConvertToXVisualType(int visualType)
-{
- static const int x_visual_types[] = {
- TrueColor, DirectColor,
- PseudoColor, StaticColor,
- GrayScale, StaticGray
- };
-
- return ( (unsigned) (visualType - GLX_TRUE_COLOR) < 6 )
- ? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1;
-}
-
-/* This code inspired by composite/compinit.c. We could move this to
- * mi/ and share it with composite.*/
-
-static VisualPtr
-AddScreenVisuals(ScreenPtr pScreen, int count, int d)
-{
- int i;
- DepthPtr depth;
-
- depth = NULL;
- for (i = 0; i < pScreen->numDepths; i++) {
- if (pScreen->allowedDepths[i].depth == d) {
- depth = &pScreen->allowedDepths[i];
- break;
- }
- }
- if (depth == NULL)
- return NULL;
-
- if (ResizeVisualArray(pScreen, count, depth) == FALSE)
- return NULL;
-
- /* Return a pointer to the first of the added visuals. */
- return pScreen->visuals + pScreen->numVisuals - count;
-}
-
-static int
-findFirstSet(unsigned int v)
-{
- int i;
-
- for (i = 0; i < 32; i++)
- if (v & (1 << i))
- return i;
-
- return -1;
-}
-
-static void
-initGlxVisual(VisualPtr visual, __GLXconfig *config)
-{
- int maxBits;
- maxBits = max(config->redBits, max(config->greenBits, config->blueBits));
-
- config->visualID = visual->vid;
- visual->class = glxConvertToXVisualType(config->visualType);
- visual->bitsPerRGBValue = maxBits;
- visual->ColormapEntries = 1 << maxBits;
- visual->nplanes = config->redBits + config->greenBits + config->blueBits;
-
- visual->redMask = config->redMask;
- visual->greenMask = config->greenMask;
- visual->blueMask = config->blueMask;
- visual->offsetRed = findFirstSet(config->redMask);
- visual->offsetGreen = findFirstSet(config->greenMask);
- visual->offsetBlue = findFirstSet(config->blueMask);
-}
-
-static __GLXconfig *
-pickFBConfig(__GLXscreen *pGlxScreen, VisualPtr visual)
-{
- __GLXconfig *best = NULL, *config;
- int best_score = 0;
-
- for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
- int score = 0;
-
- if (config->redMask != visual->redMask ||
- config->greenMask != visual->greenMask ||
- config->blueMask != visual->blueMask)
- continue;
- if (config->visualRating != GLX_NONE)
- continue;
- if (glxConvertToXVisualType(config->visualType) != visual->class)
- continue;
- /* If it's the 32-bit RGBA visual, demand a 32-bit fbconfig. */
- if (visual->nplanes == 32 && config->rgbBits != 32)
- continue;
- /* Can't use the same FBconfig for multiple X visuals. I think. */
- if (config->visualID != 0)
- continue;
-
- if (config->doubleBufferMode > 0)
- score += 8;
- if (config->depthBits > 0)
- score += 4;
- if (config->stencilBits > 0)
- score += 2;
- if (config->alphaBits > 0)
- score++;
-
- if (score > best_score) {
- best = config;
- best_score = score;
- }
- }
-
- return best;
-}
-
-void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen)
-{
- __GLXconfig *m;
- __GLXconfig *config;
- int i;
-
- if (!dixRegisterPrivateKey(&glxScreenPrivateKeyRec, PRIVATE_SCREEN, 0))
- return;
-
- pGlxScreen->pScreen = pScreen;
- pGlxScreen->GLextensions = strdup(GLServerExtensions);
- pGlxScreen->GLXvendor = strdup(GLXServerVendorName);
- pGlxScreen->GLXextensions = strdup(GLXServerExtensions);
-
- /* All GLX providers must support all of the functionality required for at
- * least GLX 1.2. If the provider supports a higher version, the GLXminor
- * version can be changed in the provider's screen-probe routine. For
- * most providers, the screen-probe routine is the caller of this
- * function.
- */
- pGlxScreen->GLXmajor = 1;
- pGlxScreen->GLXminor = 2;
-
- pGlxScreen->CloseScreen = pScreen->CloseScreen;
- pScreen->CloseScreen = glxCloseScreen;
-
- i = 0;
- for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) {
- m->fbconfigID = FakeClientID(0);
- m->visualID = 0;
- i++;
- }
- pGlxScreen->numFBConfigs = i;
-
- pGlxScreen->visuals =
- calloc(pGlxScreen->numFBConfigs, sizeof (__GLXconfig *));
-
- /* First, try to choose featureful FBconfigs for the existing X visuals.
- * Note that if multiple X visuals end up with the same FBconfig being
- * chosen, the later X visuals don't get GLX visuals (because we want to
- * prioritize the root visual being GLX).
- */
- for (i = 0; i < pScreen->numVisuals; i++) {
- VisualPtr visual = &pScreen->visuals[i];
-
- config = pickFBConfig(pGlxScreen, visual);
- if (config) {
- pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
- config->visualID = visual->vid;
- }
- }
-
- /* Then, add new visuals corresponding to all FBconfigs that didn't have
- * an existing, appropriate visual.
- */
- for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) {
- int depth;
-
- VisualPtr visual;
-
- if (config->visualID != 0)
- continue;
-
- /* Only count RGB bits and not alpha, as we're not trying to create
- * visuals for compositing (that's what the 32-bit composite visual
- * set up above is for.
- */
- depth = config->redBits + config->greenBits + config->blueBits;
-
- /* Make sure that our FBconfig's depth can actually be displayed
- * (corresponds to an existing visual).
- */
- for (i = 0; i < pScreen->numVisuals; i++) {
- if (depth == pScreen->visuals[i].nplanes)
- break;
- }
- if (i == pScreen->numVisuals)
- continue;
-
- /* Make sure the FBconfig supports window drawables */
- if (!(config->drawableType & GLX_WINDOW_BIT))
- continue;
-
- /* Create a new X visual for our FBconfig. */
- visual = AddScreenVisuals(pScreen, 1, depth);
- if (visual == NULL)
- continue;
-
- pGlxScreen->visuals[pGlxScreen->numVisuals++] = config;
- initGlxVisual(visual, config);
- }
-
- dixSetPrivate(&pScreen->devPrivates, glxScreenPrivateKey, pGlxScreen);
-}
-
-void __glXScreenDestroy(__GLXscreen *screen)
-{
- free(screen->GLXvendor);
- free(screen->GLXextensions);
- free(screen->GLextensions);
-}
+/* + * 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_DIX_CONFIG_H +#include <dix-config.h> +#else + +#include "glheader.h" + +#endif + +#include <GL/glxtokens.h> +#include <string.h> +#include <windowstr.h> +#include <os.h> +#include <colormapst.h> + +#include "privates.h" +#include "glxserver.h" +#include "glxutil.h" +#include "glxext.h" +#include "protocol-versions.h" + +static DevPrivateKeyRec glxScreenPrivateKeyRec; +#define glxScreenPrivateKey (&glxScreenPrivateKeyRec) + +const char GLServerVersion[] = "1.4"; +static const char GLServerExtensions[] = + "GL_ARB_depth_texture " + "GL_ARB_draw_buffers " + "GL_ARB_fragment_program " + "GL_ARB_fragment_program_shadow " + "GL_ARB_imaging " + "GL_ARB_multisample " + "GL_ARB_multitexture " + "GL_ARB_occlusion_query " + "GL_ARB_point_parameters " + "GL_ARB_point_sprite " + "GL_ARB_shadow " + "GL_ARB_shadow_ambient " + "GL_ARB_texture_border_clamp " + "GL_ARB_texture_compression " + "GL_ARB_texture_cube_map " + "GL_ARB_texture_env_add " + "GL_ARB_texture_env_combine " + "GL_ARB_texture_env_crossbar " + "GL_ARB_texture_env_dot3 " + "GL_ARB_texture_mirrored_repeat " + "GL_ARB_texture_non_power_of_two " + "GL_ARB_transpose_matrix " + "GL_ARB_vertex_program " + "GL_ARB_window_pos " + "GL_EXT_abgr " + "GL_EXT_bgra " + "GL_EXT_blend_color " + "GL_EXT_blend_equation_separate " + "GL_EXT_blend_func_separate " + "GL_EXT_blend_logic_op " + "GL_EXT_blend_minmax " + "GL_EXT_blend_subtract " + "GL_EXT_clip_volume_hint " + "GL_EXT_copy_texture " + "GL_EXT_draw_range_elements " + "GL_EXT_fog_coord " + "GL_EXT_framebuffer_object " + "GL_EXT_multi_draw_arrays " + "GL_EXT_packed_pixels " + "GL_EXT_paletted_texture " + "GL_EXT_point_parameters " + "GL_EXT_polygon_offset " + "GL_EXT_rescale_normal " + "GL_EXT_secondary_color " + "GL_EXT_separate_specular_color " + "GL_EXT_shadow_funcs " + "GL_EXT_shared_texture_palette " + "GL_EXT_stencil_two_side " + "GL_EXT_stencil_wrap " + "GL_EXT_subtexture " + "GL_EXT_texture " + "GL_EXT_texture3D " + "GL_EXT_texture_compression_dxt1 " + "GL_EXT_texture_compression_s3tc " + "GL_EXT_texture_edge_clamp " + "GL_EXT_texture_env_add " + "GL_EXT_texture_env_combine " + "GL_EXT_texture_env_dot3 " + "GL_EXT_texture_filter_anisotropic " + "GL_EXT_texture_lod " + "GL_EXT_texture_lod_bias " + "GL_EXT_texture_mirror_clamp " + "GL_EXT_texture_object " + "GL_EXT_texture_rectangle " + "GL_EXT_vertex_array " + "GL_3DFX_texture_compression_FXT1 " + "GL_APPLE_packed_pixels " + "GL_ATI_draw_buffers " + "GL_ATI_texture_env_combine3 " + "GL_ATI_texture_mirror_once " + "GL_HP_occlusion_test " + "GL_IBM_texture_mirrored_repeat " + "GL_INGR_blend_func_separate " + "GL_MESA_pack_invert " + "GL_MESA_ycbcr_texture " + "GL_NV_blend_square " + "GL_NV_depth_clamp " + "GL_NV_fog_distance " + "GL_NV_fragment_program " + "GL_NV_fragment_program_option " + "GL_NV_fragment_program2 " + "GL_NV_light_max_exponent " + "GL_NV_multisample_filter_hint " + "GL_NV_point_sprite " + "GL_NV_texgen_reflection " + "GL_NV_texture_compression_vtc " + "GL_NV_texture_env_combine4 " + "GL_NV_texture_expand_normal " + "GL_NV_texture_rectangle " + "GL_NV_vertex_program " + "GL_NV_vertex_program1_1 " + "GL_NV_vertex_program2 " + "GL_NV_vertex_program2_option " + "GL_NV_vertex_program3 " + "GL_OES_compressed_paletted_texture " + "GL_SGI_color_matrix " + "GL_SGI_color_table " + "GL_SGIS_generate_mipmap " + "GL_SGIS_multisample " + "GL_SGIS_point_parameters " + "GL_SGIS_texture_border_clamp " + "GL_SGIS_texture_edge_clamp " + "GL_SGIS_texture_lod " + "GL_SGIX_depth_texture " + "GL_SGIX_shadow " + "GL_SGIX_shadow_ambient " + "GL_SUN_slice_accum " + ; + +/* +** We have made the simplifying assuption that the same extensions are +** supported across all screens in a multi-screen system. +*/ +static char GLXServerVendorName[] = "SGI"; +unsigned glxMajorVersion = SERVER_GLX_MAJOR_VERSION; +unsigned glxMinorVersion = SERVER_GLX_MINOR_VERSION; +static char GLXServerExtensions[] = + "GLX_ARB_multisample " + "GLX_EXT_visual_info " + "GLX_EXT_visual_rating " + "GLX_EXT_import_context " + "GLX_EXT_texture_from_pixmap " + "GLX_OML_swap_method " + "GLX_SGI_make_current_read " +#ifndef __APPLE__ + "GLX_SGIS_multisample " +#endif + "GLX_SGIX_fbconfig " + "GLX_SGIX_pbuffer " + "GLX_MESA_copy_sub_buffer " + "GLX_INTEL_swap_event" + ; + +static Bool +glxCloseScreen (int index, ScreenPtr pScreen) +{ + __GLXscreen *pGlxScreen = glxGetScreen(pScreen); + + pScreen->CloseScreen = pGlxScreen->CloseScreen; + + pGlxScreen->destroy(pGlxScreen); + + return pScreen->CloseScreen(index, pScreen); +} + +__GLXscreen * +glxGetScreen(ScreenPtr pScreen) +{ + return dixLookupPrivate(&pScreen->devPrivates, glxScreenPrivateKey); +} + +_X_EXPORT void GlxSetVisualConfigs(int nconfigs, + void *configs, void **privates) +{ + /* We keep this stub around for the DDX drivers that still + * call it. */ +} + +GLint glxConvertToXVisualType(int visualType) +{ + static const int x_visual_types[] = { + TrueColor, DirectColor, + PseudoColor, StaticColor, + GrayScale, StaticGray + }; + + return ( (unsigned) (visualType - GLX_TRUE_COLOR) < 6 ) + ? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1; +} + +/* This code inspired by composite/compinit.c. We could move this to + * mi/ and share it with composite.*/ + +static VisualPtr +AddScreenVisuals(ScreenPtr pScreen, int count, int d) +{ + int i; + DepthPtr depth; + + depth = NULL; + for (i = 0; i < pScreen->numDepths; i++) { + if (pScreen->allowedDepths[i].depth == d) { + depth = &pScreen->allowedDepths[i]; + break; + } + } + if (depth == NULL) + return NULL; + + if (ResizeVisualArray(pScreen, count, depth) == FALSE) + return NULL; + + /* Return a pointer to the first of the added visuals. */ + return pScreen->visuals + pScreen->numVisuals - count; +} + +static int +findFirstSet(unsigned int v) +{ + int i; + + for (i = 0; i < 32; i++) + if (v & (1 << i)) + return i; + + return -1; +} + +static void +initGlxVisual(VisualPtr visual, __GLXconfig *config) +{ + int maxBits; + maxBits = max(config->redBits, max(config->greenBits, config->blueBits)); + + config->visualID = visual->vid; + visual->class = glxConvertToXVisualType(config->visualType); + visual->bitsPerRGBValue = maxBits; + visual->ColormapEntries = 1 << maxBits; + visual->nplanes = config->redBits + config->greenBits + config->blueBits; + + visual->redMask = config->redMask; + visual->greenMask = config->greenMask; + visual->blueMask = config->blueMask; + visual->offsetRed = findFirstSet(config->redMask); + visual->offsetGreen = findFirstSet(config->greenMask); + visual->offsetBlue = findFirstSet(config->blueMask); +} + +static __GLXconfig * +pickFBConfig(__GLXscreen *pGlxScreen, VisualPtr visual) +{ + __GLXconfig *best = NULL, *config; + int best_score = 0; + + for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) { + int score = 0; + + if (config->redMask != visual->redMask || + config->greenMask != visual->greenMask || + config->blueMask != visual->blueMask) + continue; + if (config->visualRating != GLX_NONE) + continue; + if (glxConvertToXVisualType(config->visualType) != visual->class) + continue; + /* If it's the 32-bit RGBA visual, demand a 32-bit fbconfig. */ + if (visual->nplanes == 32 && config->rgbBits != 32) + continue; + /* Can't use the same FBconfig for multiple X visuals. I think. */ + if (config->visualID != 0) + continue; + + if (config->doubleBufferMode > 0) + score += 8; + if (config->depthBits > 0) + score += 4; + if (config->stencilBits > 0) + score += 2; + if (config->alphaBits > 0) + score++; + + if (score > best_score) { + best = config; + best_score = score; + } + } + + return best; +} + +void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen) +{ + __GLXconfig *m; + __GLXconfig *config; + int i; + + if (!dixRegisterPrivateKey(&glxScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) + return; + + pGlxScreen->pScreen = pScreen; + pGlxScreen->GLextensions = strdup(GLServerExtensions); + pGlxScreen->GLXvendor = strdup(GLXServerVendorName); + pGlxScreen->GLXextensions = strdup(GLXServerExtensions); + + /* All GLX providers must support all of the functionality required for at + * least GLX 1.2. If the provider supports a higher version, the GLXminor + * version can be changed in the provider's screen-probe routine. For + * most providers, the screen-probe routine is the caller of this + * function. + */ + pGlxScreen->GLXmajor = 1; + pGlxScreen->GLXminor = 2; + + pGlxScreen->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = glxCloseScreen; + + i = 0; + for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) { + m->fbconfigID = FakeClientID(0); + m->visualID = 0; + i++; + } + pGlxScreen->numFBConfigs = i; + + pGlxScreen->visuals = + calloc(pGlxScreen->numFBConfigs, sizeof (__GLXconfig *)); + + /* First, try to choose featureful FBconfigs for the existing X visuals. + * Note that if multiple X visuals end up with the same FBconfig being + * chosen, the later X visuals don't get GLX visuals (because we want to + * prioritize the root visual being GLX). + */ + for (i = 0; i < pScreen->numVisuals; i++) { + VisualPtr visual = &pScreen->visuals[i]; + + config = pickFBConfig(pGlxScreen, visual); + if (config) { + pGlxScreen->visuals[pGlxScreen->numVisuals++] = config; + config->visualID = visual->vid; + } + } + + /* Then, add new visuals corresponding to all FBconfigs that didn't have + * an existing, appropriate visual. + */ + for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) { + int depth; + + VisualPtr visual; + + if (config->visualID != 0) + continue; + + /* Only count RGB bits and not alpha, as we're not trying to create + * visuals for compositing (that's what the 32-bit composite visual + * set up above is for. + */ + depth = config->redBits + config->greenBits + config->blueBits; + + /* Make sure that our FBconfig's depth can actually be displayed + * (corresponds to an existing visual). + */ + for (i = 0; i < pScreen->numVisuals; i++) { + if (depth == pScreen->visuals[i].nplanes) + break; + } + /* if it can't, fix up the fbconfig to not advertise window support */ + if (i == pScreen->numVisuals) + config->drawableType &= ~(GLX_WINDOW_BIT); + + /* fbconfig must support window drawables */ + if (!(config->drawableType & GLX_WINDOW_BIT)) { + config->visualID = 0; + continue; + } + + /* Create a new X visual for our FBconfig. */ + visual = AddScreenVisuals(pScreen, 1, depth); + if (visual == NULL) + continue; + + pGlxScreen->visuals[pGlxScreen->numVisuals++] = config; + initGlxVisual(visual, config); + } + + dixSetPrivate(&pScreen->devPrivates, glxScreenPrivateKey, pGlxScreen); +} + +void __glXScreenDestroy(__GLXscreen *screen) +{ + free(screen->GLXvendor); + free(screen->GLXextensions); + free(screen->GLextensions); +} |