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_DIX_CONFIG_H 32#include <dix-config.h> 33#endif 34 35#include <GL/glxtokens.h> 36#include <string.h> 37#include <windowstr.h> 38#include <os.h> 39#include <colormapst.h> 40 41#include "extinit.h" 42#include "privates.h" 43#include "glxserver.h" 44#include "glxutil.h" 45#include "glxext.h" 46#include "protocol-versions.h" 47 48#ifdef COMPOSITE 49#include "compositeext.h" 50#endif 51 52static DevPrivateKeyRec glxScreenPrivateKeyRec; 53 54#define glxScreenPrivateKey (&glxScreenPrivateKeyRec) 55 56const char GLServerVersion[] = "1.4"; 57static const char GLServerExtensions[] = 58 "GL_ARB_depth_texture " 59 "GL_ARB_draw_buffers " 60 "GL_ARB_fragment_program " 61 "GL_ARB_fragment_program_shadow " 62 "GL_ARB_imaging " 63 "GL_ARB_multisample " 64 "GL_ARB_multitexture " 65 "GL_ARB_occlusion_query " 66 "GL_ARB_point_parameters " 67 "GL_ARB_point_sprite " 68 "GL_ARB_shadow " 69 "GL_ARB_shadow_ambient " 70 "GL_ARB_texture_border_clamp " 71 "GL_ARB_texture_compression " 72 "GL_ARB_texture_cube_map " 73 "GL_ARB_texture_env_add " 74 "GL_ARB_texture_env_combine " 75 "GL_ARB_texture_env_crossbar " 76 "GL_ARB_texture_env_dot3 " 77 "GL_ARB_texture_mirrored_repeat " 78 "GL_ARB_texture_non_power_of_two " 79 "GL_ARB_transpose_matrix " 80 "GL_ARB_vertex_program " 81 "GL_ARB_window_pos " 82 "GL_EXT_abgr " 83 "GL_EXT_bgra " 84 "GL_EXT_blend_color " 85 "GL_EXT_blend_equation_separate " 86 "GL_EXT_blend_func_separate " 87 "GL_EXT_blend_logic_op " 88 "GL_EXT_blend_minmax " 89 "GL_EXT_blend_subtract " 90 "GL_EXT_clip_volume_hint " 91 "GL_EXT_copy_texture " 92 "GL_EXT_draw_range_elements " 93 "GL_EXT_fog_coord " 94 "GL_EXT_framebuffer_object " 95 "GL_EXT_multi_draw_arrays " 96 "GL_EXT_packed_pixels " 97 "GL_EXT_paletted_texture " 98 "GL_EXT_point_parameters " 99 "GL_EXT_polygon_offset " 100 "GL_EXT_rescale_normal " 101 "GL_EXT_secondary_color " 102 "GL_EXT_separate_specular_color " 103 "GL_EXT_shadow_funcs " 104 "GL_EXT_shared_texture_palette " 105 "GL_EXT_stencil_two_side " 106 "GL_EXT_stencil_wrap " 107 "GL_EXT_subtexture " 108 "GL_EXT_texture " 109 "GL_EXT_texture3D " 110 "GL_EXT_texture_compression_dxt1 " 111 "GL_EXT_texture_compression_s3tc " 112 "GL_EXT_texture_edge_clamp " 113 "GL_EXT_texture_env_add " 114 "GL_EXT_texture_env_combine " 115 "GL_EXT_texture_env_dot3 " 116 "GL_EXT_texture_filter_anisotropic " 117 "GL_EXT_texture_lod " 118 "GL_EXT_texture_lod_bias " 119 "GL_EXT_texture_mirror_clamp " 120 "GL_EXT_texture_object " 121 "GL_EXT_texture_rectangle " 122 "GL_EXT_vertex_array " 123 "GL_3DFX_texture_compression_FXT1 " 124 "GL_APPLE_packed_pixels " 125 "GL_ATI_draw_buffers " 126 "GL_ATI_texture_env_combine3 " 127 "GL_ATI_texture_mirror_once " 128 "GL_HP_occlusion_test " 129 "GL_IBM_texture_mirrored_repeat " 130 "GL_INGR_blend_func_separate " 131 "GL_MESA_pack_invert " 132 "GL_MESA_ycbcr_texture " 133 "GL_NV_blend_square " 134 "GL_NV_depth_clamp " 135 "GL_NV_fog_distance " 136 "GL_NV_fragment_program_option " 137 "GL_NV_fragment_program2 " 138 "GL_NV_light_max_exponent " 139 "GL_NV_multisample_filter_hint " 140 "GL_NV_point_sprite " 141 "GL_NV_texgen_reflection " 142 "GL_NV_texture_compression_vtc " 143 "GL_NV_texture_env_combine4 " 144 "GL_NV_texture_expand_normal " 145 "GL_NV_texture_rectangle " 146 "GL_NV_vertex_program2_option " 147 "GL_NV_vertex_program3 " 148 "GL_OES_compressed_paletted_texture " 149 "GL_SGI_color_matrix " 150 "GL_SGI_color_table " 151 "GL_SGIS_generate_mipmap " 152 "GL_SGIS_multisample " 153 "GL_SGIS_point_parameters " 154 "GL_SGIS_texture_border_clamp " 155 "GL_SGIS_texture_edge_clamp " 156 "GL_SGIS_texture_lod " 157 "GL_SGIX_depth_texture " 158 "GL_SGIX_shadow " 159 "GL_SGIX_shadow_ambient " 160 "GL_SUN_slice_accum "; 161 162static Bool 163glxCloseScreen(ScreenPtr pScreen) 164{ 165 __GLXscreen *pGlxScreen = glxGetScreen(pScreen); 166 167 pScreen->CloseScreen = pGlxScreen->CloseScreen; 168 169 pGlxScreen->destroy(pGlxScreen); 170 171 return pScreen->CloseScreen(pScreen); 172} 173 174__GLXscreen * 175glxGetScreen(ScreenPtr pScreen) 176{ 177 return dixLookupPrivate(&pScreen->devPrivates, glxScreenPrivateKey); 178} 179 180GLint 181glxConvertToXVisualType(int visualType) 182{ 183 static const int x_visual_types[] = { 184 TrueColor, DirectColor, 185 PseudoColor, StaticColor, 186 GrayScale, StaticGray 187 }; 188 189 return ((unsigned) (visualType - GLX_TRUE_COLOR) < 6) 190 ? x_visual_types[visualType - GLX_TRUE_COLOR] : -1; 191} 192 193/* This code inspired by composite/compinit.c. We could move this to 194 * mi/ and share it with composite.*/ 195 196static VisualPtr 197AddScreenVisuals(ScreenPtr pScreen, int count, int d) 198{ 199 int i; 200 DepthPtr depth; 201 202 depth = NULL; 203 for (i = 0; i < pScreen->numDepths; i++) { 204 if (pScreen->allowedDepths[i].depth == d) { 205 depth = &pScreen->allowedDepths[i]; 206 break; 207 } 208 } 209 if (depth == NULL) 210 return NULL; 211 212 if (ResizeVisualArray(pScreen, count, depth) == FALSE) 213 return NULL; 214 215 /* Return a pointer to the first of the added visuals. */ 216 return pScreen->visuals + pScreen->numVisuals - count; 217} 218 219static int 220findFirstSet(unsigned int v) 221{ 222 int i; 223 224 for (i = 0; i < 32; i++) 225 if (v & (1 << i)) 226 return i; 227 228 return -1; 229} 230 231static void 232initGlxVisual(VisualPtr visual, __GLXconfig * config) 233{ 234 int maxBits; 235 236 maxBits = max(config->redBits, max(config->greenBits, config->blueBits)); 237 238 config->visualID = visual->vid; 239 visual->class = glxConvertToXVisualType(config->visualType); 240 visual->bitsPerRGBValue = maxBits; 241 visual->ColormapEntries = 1 << maxBits; 242 visual->nplanes = config->redBits + config->greenBits + config->blueBits; 243 244 visual->redMask = config->redMask; 245 visual->greenMask = config->greenMask; 246 visual->blueMask = config->blueMask; 247 visual->offsetRed = findFirstSet(config->redMask); 248 visual->offsetGreen = findFirstSet(config->greenMask); 249 visual->offsetBlue = findFirstSet(config->blueMask); 250} 251 252static __GLXconfig * 253pickFBConfig(__GLXscreen * pGlxScreen, VisualPtr visual) 254{ 255 __GLXconfig *best = NULL, *config; 256 int best_score = 0; 257 258 for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) { 259 int score = 0; 260 261 if (config->redMask != visual->redMask || 262 config->greenMask != visual->greenMask || 263 config->blueMask != visual->blueMask) 264 continue; 265 if (config->visualRating != GLX_NONE) 266 continue; 267 /* Ignore multisampled configs */ 268 if (config->sampleBuffers) 269 continue; 270 if (glxConvertToXVisualType(config->visualType) != visual->class) 271 continue; 272 /* If it's the 32-bit RGBA visual, demand a 32-bit fbconfig. */ 273 if (visual->nplanes == 32 && config->rgbBits != 32) 274 continue; 275 /* If it's the 32-bit RGBA visual, do not pick sRGB capable config. 276 * This can cause issues with compositors that are not sRGB aware. 277 */ 278 if (visual->nplanes == 32 && config->sRGBCapable == GL_TRUE) 279 continue; 280 /* Can't use the same FBconfig for multiple X visuals. I think. */ 281 if (config->visualID != 0) 282 continue; 283#ifdef COMPOSITE 284 if (!noCompositeExtension) { 285 /* Use only duplicated configs for compIsAlternateVisuals */ 286 if (!!compIsAlternateVisual(pGlxScreen->pScreen, visual->vid) != 287 !!config->duplicatedForComp) 288 continue; 289 } 290#endif 291 /* 292 * If possible, use the same swapmethod for all built-in visual 293 * fbconfigs, to avoid getting the 32-bit composite visual when 294 * requesting, for example, a SWAP_COPY fbconfig. 295 */ 296 if (config->swapMethod == GLX_SWAP_UNDEFINED_OML) 297 score += 32; 298 if (config->swapMethod == GLX_SWAP_EXCHANGE_OML) 299 score += 16; 300 if (config->doubleBufferMode > 0) 301 score += 8; 302 if (config->depthBits > 0) 303 score += 4; 304 if (config->stencilBits > 0) 305 score += 2; 306 if (config->alphaBits > 0) 307 score++; 308 309 if (score > best_score) { 310 best = config; 311 best_score = score; 312 } 313 } 314 315 return best; 316} 317 318void 319__glXScreenInit(__GLXscreen * pGlxScreen, ScreenPtr pScreen) 320{ 321 __GLXconfig *m; 322 __GLXconfig *config; 323 int i; 324 325 if (!dixRegisterPrivateKey(&glxScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 326 return; 327 328 pGlxScreen->pScreen = pScreen; 329 pGlxScreen->GLextensions = strdup(GLServerExtensions); 330 pGlxScreen->GLXextensions = NULL; 331 332 pGlxScreen->CloseScreen = pScreen->CloseScreen; 333 pScreen->CloseScreen = glxCloseScreen; 334 335 i = 0; 336 for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) { 337 m->fbconfigID = FakeClientID(0); 338 m->visualID = 0; 339 i++; 340 } 341 pGlxScreen->numFBConfigs = i; 342 343 pGlxScreen->visuals = 344 calloc(pGlxScreen->numFBConfigs, sizeof(__GLXconfig *)); 345 346 /* First, try to choose featureful FBconfigs for the existing X visuals. 347 * Note that if multiple X visuals end up with the same FBconfig being 348 * chosen, the later X visuals don't get GLX visuals (because we want to 349 * prioritize the root visual being GLX). 350 */ 351 for (i = 0; i < pScreen->numVisuals; i++) { 352 VisualPtr visual = &pScreen->visuals[i]; 353 354 config = pickFBConfig(pGlxScreen, visual); 355 if (config) { 356 pGlxScreen->visuals[pGlxScreen->numVisuals++] = config; 357 config->visualID = visual->vid; 358#ifdef COMPOSITE 359 if (!noCompositeExtension) { 360 if (compIsAlternateVisual(pScreen, visual->vid)) 361 config->visualSelectGroup++; 362 } 363#endif 364 } 365 } 366 367 /* Then, add new visuals corresponding to all FBconfigs that didn't have 368 * an existing, appropriate visual. 369 */ 370 for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) { 371 int depth; 372 373 VisualPtr visual; 374 375 if (config->visualID != 0) 376 continue; 377 378 /* Only count RGB bits and not alpha, as we're not trying to create 379 * visuals for compositing (that's what the 32-bit composite visual 380 * set up above is for. 381 */ 382 depth = config->redBits + config->greenBits + config->blueBits; 383#ifdef COMPOSITE 384 if (!noCompositeExtension) { 385 if (config->duplicatedForComp) { 386 depth += config->alphaBits; 387 config->visualSelectGroup++; 388 } 389 } 390#endif 391 /* Make sure that our FBconfig's depth can actually be displayed 392 * (corresponds to an existing visual). 393 */ 394 for (i = 0; i < pScreen->numVisuals; i++) { 395 if (depth == pScreen->visuals[i].nplanes) 396 break; 397 } 398 /* if it can't, fix up the fbconfig to not advertise window support */ 399 if (i == pScreen->numVisuals) 400 config->drawableType &= ~(GLX_WINDOW_BIT); 401 402 /* fbconfig must support window drawables */ 403 if (!(config->drawableType & GLX_WINDOW_BIT)) { 404 config->visualID = 0; 405 continue; 406 } 407 408 /* Create a new X visual for our FBconfig. */ 409 visual = AddScreenVisuals(pScreen, 1, depth); 410 if (visual == NULL) 411 continue; 412 413#ifdef COMPOSITE 414 if (!noCompositeExtension) { 415 if (config->duplicatedForComp) 416 (void) CompositeRegisterAlternateVisuals(pScreen, &visual->vid, 1); 417 } 418#endif 419 pGlxScreen->visuals[pGlxScreen->numVisuals++] = config; 420 initGlxVisual(visual, config); 421 } 422 423 dixSetPrivate(&pScreen->devPrivates, glxScreenPrivateKey, pGlxScreen); 424 425 if (pGlxScreen->glvnd) 426 __glXEnableExtension(pGlxScreen->glx_enable_bits, "GLX_EXT_libglvnd"); 427 428 i = __glXGetExtensionString(pGlxScreen->glx_enable_bits, NULL); 429 if (i > 0) { 430 pGlxScreen->GLXextensions = xnfalloc(i); 431 (void) __glXGetExtensionString(pGlxScreen->glx_enable_bits, 432 pGlxScreen->GLXextensions); 433 } 434 435} 436 437void 438__glXScreenDestroy(__GLXscreen * screen) 439{ 440 __GLXconfig *config, *next; 441 442 free(screen->glvnd); 443 free(screen->GLXextensions); 444 free(screen->GLextensions); 445 free(screen->visuals); 446 447 for (config = screen->fbconfigs; config != NULL; config = next) { 448 next = config->next; 449 free(config); 450 } 451} 452