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 "privates.h" 42#include "glxserver.h" 43#include "glxutil.h" 44#include "glxext.h" 45#include "protocol-versions.h" 46 47static DevPrivateKeyRec glxScreenPrivateKeyRec; 48#define glxScreenPrivateKey (&glxScreenPrivateKeyRec) 49 50const char GLServerVersion[] = "1.4"; 51static const char GLServerExtensions[] = 52 "GL_ARB_depth_texture " 53 "GL_ARB_draw_buffers " 54 "GL_ARB_fragment_program " 55 "GL_ARB_fragment_program_shadow " 56 "GL_ARB_imaging " 57 "GL_ARB_multisample " 58 "GL_ARB_multitexture " 59 "GL_ARB_occlusion_query " 60 "GL_ARB_point_parameters " 61 "GL_ARB_point_sprite " 62 "GL_ARB_shadow " 63 "GL_ARB_shadow_ambient " 64 "GL_ARB_texture_border_clamp " 65 "GL_ARB_texture_compression " 66 "GL_ARB_texture_cube_map " 67 "GL_ARB_texture_env_add " 68 "GL_ARB_texture_env_combine " 69 "GL_ARB_texture_env_crossbar " 70 "GL_ARB_texture_env_dot3 " 71 "GL_ARB_texture_mirrored_repeat " 72 "GL_ARB_texture_non_power_of_two " 73 "GL_ARB_transpose_matrix " 74 "GL_ARB_vertex_program " 75 "GL_ARB_window_pos " 76 "GL_EXT_abgr " 77 "GL_EXT_bgra " 78 "GL_EXT_blend_color " 79 "GL_EXT_blend_equation_separate " 80 "GL_EXT_blend_func_separate " 81 "GL_EXT_blend_logic_op " 82 "GL_EXT_blend_minmax " 83 "GL_EXT_blend_subtract " 84 "GL_EXT_clip_volume_hint " 85 "GL_EXT_copy_texture " 86 "GL_EXT_draw_range_elements " 87 "GL_EXT_fog_coord " 88 "GL_EXT_framebuffer_object " 89 "GL_EXT_multi_draw_arrays " 90 "GL_EXT_packed_pixels " 91 "GL_EXT_paletted_texture " 92 "GL_EXT_point_parameters " 93 "GL_EXT_polygon_offset " 94 "GL_EXT_rescale_normal " 95 "GL_EXT_secondary_color " 96 "GL_EXT_separate_specular_color " 97 "GL_EXT_shadow_funcs " 98 "GL_EXT_shared_texture_palette " 99 "GL_EXT_stencil_two_side " 100 "GL_EXT_stencil_wrap " 101 "GL_EXT_subtexture " 102 "GL_EXT_texture " 103 "GL_EXT_texture3D " 104 "GL_EXT_texture_compression_dxt1 " 105 "GL_EXT_texture_compression_s3tc " 106 "GL_EXT_texture_edge_clamp " 107 "GL_EXT_texture_env_add " 108 "GL_EXT_texture_env_combine " 109 "GL_EXT_texture_env_dot3 " 110 "GL_EXT_texture_filter_anisotropic " 111 "GL_EXT_texture_lod " 112 "GL_EXT_texture_lod_bias " 113 "GL_EXT_texture_mirror_clamp " 114 "GL_EXT_texture_object " 115 "GL_EXT_texture_rectangle " 116 "GL_EXT_vertex_array " 117 "GL_3DFX_texture_compression_FXT1 " 118 "GL_APPLE_packed_pixels " 119 "GL_ATI_draw_buffers " 120 "GL_ATI_texture_env_combine3 " 121 "GL_ATI_texture_mirror_once " 122 "GL_HP_occlusion_test " 123 "GL_IBM_texture_mirrored_repeat " 124 "GL_INGR_blend_func_separate " 125 "GL_MESA_pack_invert " 126 "GL_MESA_ycbcr_texture " 127 "GL_NV_blend_square " 128 "GL_NV_depth_clamp " 129 "GL_NV_fog_distance " 130 "GL_NV_fragment_program " 131 "GL_NV_fragment_program_option " 132 "GL_NV_fragment_program2 " 133 "GL_NV_light_max_exponent " 134 "GL_NV_multisample_filter_hint " 135 "GL_NV_point_sprite " 136 "GL_NV_texgen_reflection " 137 "GL_NV_texture_compression_vtc " 138 "GL_NV_texture_env_combine4 " 139 "GL_NV_texture_expand_normal " 140 "GL_NV_texture_rectangle " 141 "GL_NV_vertex_program " 142 "GL_NV_vertex_program1_1 " 143 "GL_NV_vertex_program2 " 144 "GL_NV_vertex_program2_option " 145 "GL_NV_vertex_program3 " 146 "GL_OES_compressed_paletted_texture " 147 "GL_SGI_color_matrix " 148 "GL_SGI_color_table " 149 "GL_SGIS_generate_mipmap " 150 "GL_SGIS_multisample " 151 "GL_SGIS_point_parameters " 152 "GL_SGIS_texture_border_clamp " 153 "GL_SGIS_texture_edge_clamp " 154 "GL_SGIS_texture_lod " 155 "GL_SGIX_depth_texture " 156 "GL_SGIX_shadow " 157 "GL_SGIX_shadow_ambient " 158 "GL_SUN_slice_accum " 159 ; 160 161/* 162** We have made the simplifying assuption that the same extensions are 163** supported across all screens in a multi-screen system. 164*/ 165static char GLXServerVendorName[] = "SGI"; 166unsigned glxMajorVersion = SERVER_GLX_MAJOR_VERSION; 167unsigned glxMinorVersion = SERVER_GLX_MINOR_VERSION; 168static char GLXServerExtensions[] = 169 "GLX_ARB_multisample " 170 "GLX_EXT_visual_info " 171 "GLX_EXT_visual_rating " 172 "GLX_EXT_import_context " 173 "GLX_EXT_texture_from_pixmap " 174 "GLX_OML_swap_method " 175 "GLX_SGI_make_current_read " 176#ifndef __APPLE__ 177 "GLX_SGIS_multisample " 178#endif 179 "GLX_SGIX_fbconfig " 180 "GLX_SGIX_pbuffer " 181 "GLX_MESA_copy_sub_buffer " 182 "GLX_INTEL_swap_event" 183 ; 184 185static Bool 186glxCloseScreen (int index, ScreenPtr pScreen) 187{ 188 __GLXscreen *pGlxScreen = glxGetScreen(pScreen); 189 190 pScreen->CloseScreen = pGlxScreen->CloseScreen; 191 192 pGlxScreen->destroy(pGlxScreen); 193 194 return pScreen->CloseScreen(index, pScreen); 195} 196 197__GLXscreen * 198glxGetScreen(ScreenPtr pScreen) 199{ 200 return dixLookupPrivate(&pScreen->devPrivates, glxScreenPrivateKey); 201} 202 203_X_EXPORT void GlxSetVisualConfigs(int nconfigs, 204 void *configs, void **privates) 205{ 206 /* We keep this stub around for the DDX drivers that still 207 * call it. */ 208} 209 210GLint glxConvertToXVisualType(int visualType) 211{ 212 static const int x_visual_types[] = { 213 TrueColor, DirectColor, 214 PseudoColor, StaticColor, 215 GrayScale, StaticGray 216 }; 217 218 return ( (unsigned) (visualType - GLX_TRUE_COLOR) < 6 ) 219 ? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1; 220} 221 222/* This code inspired by composite/compinit.c. We could move this to 223 * mi/ and share it with composite.*/ 224 225static VisualPtr 226AddScreenVisuals(ScreenPtr pScreen, int count, int d) 227{ 228 int i; 229 DepthPtr depth; 230 231 depth = NULL; 232 for (i = 0; i < pScreen->numDepths; i++) { 233 if (pScreen->allowedDepths[i].depth == d) { 234 depth = &pScreen->allowedDepths[i]; 235 break; 236 } 237 } 238 if (depth == NULL) 239 return NULL; 240 241 if (ResizeVisualArray(pScreen, count, depth) == FALSE) 242 return NULL; 243 244 /* Return a pointer to the first of the added visuals. */ 245 return pScreen->visuals + pScreen->numVisuals - count; 246} 247 248static int 249findFirstSet(unsigned int v) 250{ 251 int i; 252 253 for (i = 0; i < 32; i++) 254 if (v & (1 << i)) 255 return i; 256 257 return -1; 258} 259 260static void 261initGlxVisual(VisualPtr visual, __GLXconfig *config) 262{ 263 int maxBits; 264 maxBits = max(config->redBits, max(config->greenBits, config->blueBits)); 265 266 config->visualID = visual->vid; 267 visual->class = glxConvertToXVisualType(config->visualType); 268 visual->bitsPerRGBValue = maxBits; 269 visual->ColormapEntries = 1 << maxBits; 270 visual->nplanes = config->redBits + config->greenBits + config->blueBits; 271 272 visual->redMask = config->redMask; 273 visual->greenMask = config->greenMask; 274 visual->blueMask = config->blueMask; 275 visual->offsetRed = findFirstSet(config->redMask); 276 visual->offsetGreen = findFirstSet(config->greenMask); 277 visual->offsetBlue = findFirstSet(config->blueMask); 278} 279 280static __GLXconfig * 281pickFBConfig(__GLXscreen *pGlxScreen, VisualPtr visual) 282{ 283 __GLXconfig *best = NULL, *config; 284 int best_score = 0; 285 286 for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) { 287 int score = 0; 288 289 if (config->redMask != visual->redMask || 290 config->greenMask != visual->greenMask || 291 config->blueMask != visual->blueMask) 292 continue; 293 if (config->visualRating != GLX_NONE) 294 continue; 295 if (glxConvertToXVisualType(config->visualType) != visual->class) 296 continue; 297 /* If it's the 32-bit RGBA visual, demand a 32-bit fbconfig. */ 298 if (visual->nplanes == 32 && config->rgbBits != 32) 299 continue; 300 /* Can't use the same FBconfig for multiple X visuals. I think. */ 301 if (config->visualID != 0) 302 continue; 303 304 if (config->doubleBufferMode > 0) 305 score += 8; 306 if (config->depthBits > 0) 307 score += 4; 308 if (config->stencilBits > 0) 309 score += 2; 310 if (config->alphaBits > 0) 311 score++; 312 313 if (score > best_score) { 314 best = config; 315 best_score = score; 316 } 317 } 318 319 return best; 320} 321 322void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen) 323{ 324 __GLXconfig *m; 325 __GLXconfig *config; 326 int i; 327 328 if (!dixRegisterPrivateKey(&glxScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) 329 return; 330 331 pGlxScreen->pScreen = pScreen; 332 pGlxScreen->GLextensions = strdup(GLServerExtensions); 333 pGlxScreen->GLXvendor = strdup(GLXServerVendorName); 334 pGlxScreen->GLXextensions = strdup(GLXServerExtensions); 335 336 /* All GLX providers must support all of the functionality required for at 337 * least GLX 1.2. If the provider supports a higher version, the GLXminor 338 * version can be changed in the provider's screen-probe routine. For 339 * most providers, the screen-probe routine is the caller of this 340 * function. 341 */ 342 pGlxScreen->GLXmajor = 1; 343 pGlxScreen->GLXminor = 2; 344 345 pGlxScreen->CloseScreen = pScreen->CloseScreen; 346 pScreen->CloseScreen = glxCloseScreen; 347 348 i = 0; 349 for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) { 350 m->fbconfigID = FakeClientID(0); 351 m->visualID = 0; 352 i++; 353 } 354 pGlxScreen->numFBConfigs = i; 355 356 pGlxScreen->visuals = 357 calloc(pGlxScreen->numFBConfigs, sizeof (__GLXconfig *)); 358 359 /* First, try to choose featureful FBconfigs for the existing X visuals. 360 * Note that if multiple X visuals end up with the same FBconfig being 361 * chosen, the later X visuals don't get GLX visuals (because we want to 362 * prioritize the root visual being GLX). 363 */ 364 for (i = 0; i < pScreen->numVisuals; i++) { 365 VisualPtr visual = &pScreen->visuals[i]; 366 367 config = pickFBConfig(pGlxScreen, visual); 368 if (config) { 369 pGlxScreen->visuals[pGlxScreen->numVisuals++] = config; 370 config->visualID = visual->vid; 371 } 372 } 373 374 /* Then, add new visuals corresponding to all FBconfigs that didn't have 375 * an existing, appropriate visual. 376 */ 377 for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) { 378 int depth; 379 380 VisualPtr visual; 381 382 if (config->visualID != 0) 383 continue; 384 385 /* Only count RGB bits and not alpha, as we're not trying to create 386 * visuals for compositing (that's what the 32-bit composite visual 387 * set up above is for. 388 */ 389 depth = config->redBits + config->greenBits + config->blueBits; 390 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 pGlxScreen->visuals[pGlxScreen->numVisuals++] = config; 414 initGlxVisual(visual, config); 415 } 416 417 dixSetPrivate(&pScreen->devPrivates, glxScreenPrivateKey, pGlxScreen); 418} 419 420void __glXScreenDestroy(__GLXscreen *screen) 421{ 422 free(screen->GLXvendor); 423 free(screen->GLXextensions); 424 free(screen->GLextensions); 425} 426