glxscreens.c revision 4642e01f
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 46static int glxScreenPrivateKeyIndex; 47static DevPrivateKey glxScreenPrivateKey = &glxScreenPrivateKeyIndex; 48 49const char GLServerVersion[] = "1.4"; 50static const char GLServerExtensions[] = 51 "GL_ARB_depth_texture " 52 "GL_ARB_draw_buffers " 53 "GL_ARB_fragment_program " 54 "GL_ARB_fragment_program_shadow " 55 "GL_ARB_imaging " 56 "GL_ARB_multisample " 57 "GL_ARB_multitexture " 58 "GL_ARB_occlusion_query " 59 "GL_ARB_point_parameters " 60 "GL_ARB_point_sprite " 61 "GL_ARB_shadow " 62 "GL_ARB_shadow_ambient " 63 "GL_ARB_texture_border_clamp " 64 "GL_ARB_texture_compression " 65 "GL_ARB_texture_cube_map " 66 "GL_ARB_texture_env_add " 67 "GL_ARB_texture_env_combine " 68 "GL_ARB_texture_env_crossbar " 69 "GL_ARB_texture_env_dot3 " 70 "GL_ARB_texture_mirrored_repeat " 71 "GL_ARB_texture_non_power_of_two " 72 "GL_ARB_transpose_matrix " 73 "GL_ARB_vertex_program " 74 "GL_ARB_window_pos " 75 "GL_EXT_abgr " 76 "GL_EXT_bgra " 77 "GL_EXT_blend_color " 78 "GL_EXT_blend_equation_separate " 79 "GL_EXT_blend_func_separate " 80 "GL_EXT_blend_logic_op " 81 "GL_EXT_blend_minmax " 82 "GL_EXT_blend_subtract " 83 "GL_EXT_clip_volume_hint " 84 "GL_EXT_copy_texture " 85 "GL_EXT_draw_range_elements " 86 "GL_EXT_fog_coord " 87 "GL_EXT_framebuffer_object " 88 "GL_EXT_multi_draw_arrays " 89 "GL_EXT_packed_pixels " 90 "GL_EXT_paletted_texture " 91 "GL_EXT_point_parameters " 92 "GL_EXT_polygon_offset " 93 "GL_EXT_rescale_normal " 94 "GL_EXT_secondary_color " 95 "GL_EXT_separate_specular_color " 96 "GL_EXT_shadow_funcs " 97 "GL_EXT_shared_texture_palette " 98 "GL_EXT_stencil_two_side " 99 "GL_EXT_stencil_wrap " 100 "GL_EXT_subtexture " 101 "GL_EXT_texture " 102 "GL_EXT_texture3D " 103 "GL_EXT_texture_compression_dxt1 " 104 "GL_EXT_texture_compression_s3tc " 105 "GL_EXT_texture_edge_clamp " 106 "GL_EXT_texture_env_add " 107 "GL_EXT_texture_env_combine " 108 "GL_EXT_texture_env_dot3 " 109 "GL_EXT_texture_filter_anisotropic " 110 "GL_EXT_texture_lod " 111 "GL_EXT_texture_lod_bias " 112 "GL_EXT_texture_mirror_clamp " 113 "GL_EXT_texture_object " 114 "GL_EXT_texture_rectangle " 115 "GL_EXT_vertex_array " 116 "GL_3DFX_texture_compression_FXT1 " 117 "GL_APPLE_packed_pixels " 118 "GL_ATI_draw_buffers " 119 "GL_ATI_texture_env_combine3 " 120 "GL_ATI_texture_mirror_once " 121 "GL_HP_occlusion_test " 122 "GL_IBM_texture_mirrored_repeat " 123 "GL_INGR_blend_func_separate " 124 "GL_MESA_pack_invert " 125 "GL_MESA_ycbcr_texture " 126 "GL_NV_blend_square " 127 "GL_NV_depth_clamp " 128 "GL_NV_fog_distance " 129 "GL_NV_fragment_program " 130 "GL_NV_fragment_program_option " 131 "GL_NV_fragment_program2 " 132 "GL_NV_light_max_exponent " 133 "GL_NV_multisample_filter_hint " 134 "GL_NV_point_sprite " 135 "GL_NV_texgen_reflection " 136 "GL_NV_texture_compression_vtc " 137 "GL_NV_texture_env_combine4 " 138 "GL_NV_texture_expand_normal " 139 "GL_NV_texture_rectangle " 140 "GL_NV_vertex_program " 141 "GL_NV_vertex_program1_1 " 142 "GL_NV_vertex_program2 " 143 "GL_NV_vertex_program2_option " 144 "GL_NV_vertex_program3 " 145 "GL_OES_compressed_paletted_texture " 146 "GL_SGI_color_matrix " 147 "GL_SGI_color_table " 148 "GL_SGIS_generate_mipmap " 149 "GL_SGIS_multisample " 150 "GL_SGIS_point_parameters " 151 "GL_SGIS_texture_border_clamp " 152 "GL_SGIS_texture_edge_clamp " 153 "GL_SGIS_texture_lod " 154 "GL_SGIX_depth_texture " 155 "GL_SGIX_shadow " 156 "GL_SGIX_shadow_ambient " 157 "GL_SUN_slice_accum " 158 ; 159 160/* 161** We have made the simplifying assuption that the same extensions are 162** supported across all screens in a multi-screen system. 163*/ 164static char GLXServerVendorName[] = "SGI"; 165static char GLXServerVersion[] = "1.2"; 166static char GLXServerExtensions[] = 167 "GLX_ARB_multisample " 168 "GLX_EXT_visual_info " 169 "GLX_EXT_visual_rating " 170 "GLX_EXT_import_context " 171 "GLX_EXT_texture_from_pixmap " 172 "GLX_OML_swap_method " 173 "GLX_SGI_make_current_read " 174#ifndef __APPLE__ 175 "GLX_SGIS_multisample " 176 "GLX_SGIX_hyperpipe " 177 "GLX_SGIX_swap_barrier " 178#endif 179 "GLX_SGIX_fbconfig " 180 "GLX_MESA_copy_sub_buffer " 181 ; 182 183/* 184 * If your DDX driver wants to register support for swap barriers or hyperpipe 185 * topology, it should call __glXHyperpipeInit() or __glXSwapBarrierInit() 186 * with a dispatch table of functions to handle the requests. In the XFree86 187 * DDX, for example, you would call these near the bottom of the driver's 188 * ScreenInit method, after DRI has been initialized. 189 * 190 * This should be replaced with a better method when we teach the server how 191 * to load DRI drivers. 192 */ 193 194void __glXHyperpipeInit(int screen, __GLXHyperpipeExtensionFuncs *funcs) 195{ 196 __GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]); 197 198 pGlxScreen->hyperpipeFuncs = funcs; 199} 200 201void __glXSwapBarrierInit(int screen, __GLXSwapBarrierExtensionFuncs *funcs) 202{ 203 __GLXscreen *pGlxScreen = glxGetScreen(screenInfo.screens[screen]); 204 205 pGlxScreen->swapBarrierFuncs = funcs; 206} 207 208static Bool 209glxCloseScreen (int index, ScreenPtr pScreen) 210{ 211 __GLXscreen *pGlxScreen = glxGetScreen(pScreen); 212 213 pScreen->CloseScreen = pGlxScreen->CloseScreen; 214 215 pGlxScreen->destroy(pGlxScreen); 216 217 return pScreen->CloseScreen(index, pScreen); 218} 219 220__GLXscreen * 221glxGetScreen(ScreenPtr pScreen) 222{ 223 return dixLookupPrivate(&pScreen->devPrivates, glxScreenPrivateKey); 224} 225 226void GlxSetVisualConfigs(int nconfigs, 227 __GLXvisualConfig *configs, void **privates) 228{ 229 /* We keep this stub around for the DDX drivers that still 230 * call it. */ 231} 232 233GLint glxConvertToXVisualType(int visualType) 234{ 235 static const int x_visual_types[] = { 236 TrueColor, DirectColor, 237 PseudoColor, StaticColor, 238 GrayScale, StaticGray 239 }; 240 241 return ( (unsigned) (visualType - GLX_TRUE_COLOR) < 6 ) 242 ? x_visual_types[ visualType - GLX_TRUE_COLOR ] : -1; 243} 244 245/* This code inspired by composite/compinit.c. We could move this to 246 * mi/ and share it with composite.*/ 247 248static VisualPtr 249AddScreenVisuals(ScreenPtr pScreen, int count, int d) 250{ 251 XID *installedCmaps, *vids, vid; 252 int numInstalledCmaps, numVisuals, i, j; 253 VisualPtr visuals; 254 ColormapPtr installedCmap; 255 DepthPtr depth; 256 257 depth = NULL; 258 for (i = 0; i < pScreen->numDepths; i++) { 259 if (pScreen->allowedDepths[i].depth == d) { 260 depth = &pScreen->allowedDepths[i]; 261 break; 262 } 263 } 264 if (depth == NULL) 265 return NULL; 266 267 /* Find the installed colormaps */ 268 installedCmaps = xalloc (pScreen->maxInstalledCmaps * sizeof (XID)); 269 if (!installedCmaps) 270 return NULL; 271 272 numInstalledCmaps = pScreen->ListInstalledColormaps(pScreen, installedCmaps); 273 274 /* realloc the visual array to fit the new one in place */ 275 numVisuals = pScreen->numVisuals; 276 visuals = xrealloc(pScreen->visuals, (numVisuals + count) * sizeof(VisualRec)); 277 if (!visuals) { 278 xfree(installedCmaps); 279 return NULL; 280 } 281 282 vids = xrealloc(depth->vids, (depth->numVids + count) * sizeof(XID)); 283 if (vids == NULL) { 284 xfree(installedCmaps); 285 xfree(visuals); 286 return NULL; 287 } 288 289 /* 290 * Fix up any existing installed colormaps -- we'll assume that 291 * the only ones created so far have been installed. If this 292 * isn't true, we'll have to walk the resource database looking 293 * for all colormaps. 294 */ 295 for (i = 0; i < numInstalledCmaps; i++) { 296 installedCmap = LookupIDByType (installedCmaps[i], RT_COLORMAP); 297 if (!installedCmap) 298 continue; 299 j = installedCmap->pVisual - pScreen->visuals; 300 installedCmap->pVisual = &visuals[j]; 301 } 302 303 xfree(installedCmaps); 304 305 for (i = 0; i < count; i++) { 306 vid = FakeClientID(0); 307 visuals[pScreen->numVisuals + i].vid = vid; 308 vids[depth->numVids + i] = vid; 309 } 310 311 pScreen->visuals = visuals; 312 pScreen->numVisuals += count; 313 depth->vids = vids; 314 depth->numVids += count; 315 316 /* Return a pointer to the first of the added visuals. */ 317 return pScreen->visuals + pScreen->numVisuals - count; 318} 319 320static int 321findFirstSet(unsigned int v) 322{ 323 int i; 324 325 for (i = 0; i < 32; i++) 326 if (v & (1 << i)) 327 return i; 328 329 return -1; 330} 331 332static void 333initGlxVisual(VisualPtr visual, __GLXconfig *config) 334{ 335 int maxBits; 336 maxBits = max(config->redBits, max(config->greenBits, config->blueBits)); 337 338 config->visualID = visual->vid; 339 visual->class = glxConvertToXVisualType(config->visualType); 340 visual->bitsPerRGBValue = maxBits; 341 visual->ColormapEntries = 1 << maxBits; 342 visual->nplanes = config->redBits + config->greenBits + config->blueBits; 343 344 visual->redMask = config->redMask; 345 visual->greenMask = config->greenMask; 346 visual->blueMask = config->blueMask; 347 visual->offsetRed = findFirstSet(config->redMask); 348 visual->offsetGreen = findFirstSet(config->greenMask); 349 visual->offsetBlue = findFirstSet(config->blueMask); 350} 351 352static __GLXconfig * 353pickFBConfig(__GLXscreen *pGlxScreen, VisualPtr visual) 354{ 355 __GLXconfig *best = NULL, *config; 356 int best_score = 0; 357 358 for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) { 359 int score = 0; 360 361 if (config->redMask != visual->redMask || 362 config->greenMask != visual->greenMask || 363 config->blueMask != visual->blueMask) 364 continue; 365 if (config->visualRating != GLX_NONE) 366 continue; 367 if (glxConvertToXVisualType(config->visualType) != visual->class) 368 continue; 369 /* If it's the 32-bit RGBA visual, demand a 32-bit fbconfig. */ 370 if (visual->nplanes == 32 && config->rgbBits != 32) 371 continue; 372 /* Can't use the same FBconfig for multiple X visuals. I think. */ 373 if (config->visualID != 0) 374 continue; 375 376 if (config->doubleBufferMode > 0) 377 score += 8; 378 if (config->depthBits > 0) 379 score += 4; 380 if (config->stencilBits > 0) 381 score += 2; 382 if (config->alphaBits > 0) 383 score++; 384 385 if (score > best_score) { 386 best = config; 387 best_score = score; 388 } 389 } 390 391 return best; 392} 393 394void __glXScreenInit(__GLXscreen *pGlxScreen, ScreenPtr pScreen) 395{ 396 __GLXconfig *m; 397 __GLXconfig *config; 398 int i; 399 400 pGlxScreen->pScreen = pScreen; 401 pGlxScreen->GLextensions = xstrdup(GLServerExtensions); 402 pGlxScreen->GLXvendor = xstrdup(GLXServerVendorName); 403 pGlxScreen->GLXversion = xstrdup(GLXServerVersion); 404 pGlxScreen->GLXextensions = xstrdup(GLXServerExtensions); 405 406 pGlxScreen->CloseScreen = pScreen->CloseScreen; 407 pScreen->CloseScreen = glxCloseScreen; 408 409 i = 0; 410 for (m = pGlxScreen->fbconfigs; m != NULL; m = m->next) { 411 m->fbconfigID = FakeClientID(0); 412 m->visualID = 0; 413 i++; 414 } 415 pGlxScreen->numFBConfigs = i; 416 417 pGlxScreen->visuals = 418 xcalloc(pGlxScreen->numFBConfigs, sizeof (__GLXconfig *)); 419 420 /* First, try to choose featureful FBconfigs for the existing X visuals. 421 * Note that if multiple X visuals end up with the same FBconfig being 422 * chosen, the later X visuals don't get GLX visuals (because we want to 423 * prioritize the root visual being GLX). 424 */ 425 for (i = 0; i < pScreen->numVisuals; i++) { 426 VisualPtr visual = &pScreen->visuals[i]; 427 428 config = pickFBConfig(pGlxScreen, visual); 429 if (config) { 430 pGlxScreen->visuals[pGlxScreen->numVisuals++] = config; 431 config->visualID = visual->vid; 432 } 433 } 434 435 /* Then, add new visuals corresponding to all FBconfigs that didn't have 436 * an existing, appropriate visual. 437 */ 438 for (config = pGlxScreen->fbconfigs; config != NULL; config = config->next) { 439 int depth; 440 441 VisualPtr visual; 442 443 if (config->visualID != 0) 444 continue; 445 446 /* Only count RGB bits and not alpha, as we're not trying to create 447 * visuals for compositing (that's what the 32-bit composite visual 448 * set up above is for. 449 */ 450 depth = config->redBits + config->greenBits + config->blueBits; 451 452 /* Make sure that our FBconfig's depth can actually be displayed 453 * (corresponds to an existing visual). 454 */ 455 for (i = 0; i < pScreen->numVisuals; i++) { 456 if (depth == pScreen->visuals[i].nplanes) 457 break; 458 } 459 if (i == pScreen->numVisuals) 460 continue; 461 462 /* Create a new X visual for our FBconfig. */ 463 visual = AddScreenVisuals(pScreen, 1, depth); 464 if (visual == NULL) 465 continue; 466 467 pGlxScreen->visuals[pGlxScreen->numVisuals++] = config; 468 initGlxVisual(visual, config); 469 } 470 471 dixSetPrivate(&pScreen->devPrivates, glxScreenPrivateKey, pGlxScreen); 472} 473 474void __glXScreenDestroy(__GLXscreen *screen) 475{ 476 xfree(screen->GLXvendor); 477 xfree(screen->GLXversion); 478 xfree(screen->GLXextensions); 479 xfree(screen->GLextensions); 480} 481