utils.c revision 429a08384c2ea66d446e46beb28e33ee3b764d52
1/* 2 * (C) Copyright IBM Corporation 2002, 2004 3 * 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 * on the rights to use, copy, modify, merge, publish, distribute, sub 9 * license, and/or sell copies of the Software, and to permit persons to whom 10 * the Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 * VA LINUX SYSTEM, IBM AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22 * USE OR OTHER DEALINGS IN THE SOFTWARE. 23 */ 24 25/** 26 * \file utils.c 27 * Utility functions for DRI drivers. 28 * 29 * \author Ian Romanick <idr@us.ibm.com> 30 */ 31 32#include <string.h> 33#include <stdlib.h> 34#include "mtypes.h" 35#include "extensions.h" 36#include "utils.h" 37#include "dispatch.h" 38 39int driDispatchRemapTable[ driDispatchRemapTable_size ]; 40 41#if defined(USE_X86_ASM) 42#include "x86/common_x86_asm.h" 43#endif 44 45#if defined(USE_PPC_ASM) 46#include "ppc/common_ppc_features.h" 47#endif 48 49unsigned 50driParseDebugString( const char * debug, 51 const struct dri_debug_control * control ) 52{ 53 unsigned flag; 54 55 56 flag = 0; 57 if ( debug != NULL ) { 58 while( control->string != NULL ) { 59 if ( !strcmp( debug, "all" ) || 60 strstr( debug, control->string ) != NULL ) { 61 flag |= control->flag; 62 } 63 64 control++; 65 } 66 } 67 68 return flag; 69} 70 71 72 73/** 74 * Create the \c GL_RENDERER string for DRI drivers. 75 * 76 * Almost all DRI drivers use a \c GL_RENDERER string of the form: 77 * 78 * "Mesa DRI <chip> <driver date> <AGP speed) <CPU information>" 79 * 80 * Using the supplied chip name, driver data, and AGP speed, this function 81 * creates the string. 82 * 83 * \param buffer Buffer to hold the \c GL_RENDERER string. 84 * \param hardware_name Name of the hardware. 85 * \param driver_date Driver date. 86 * \param agp_mode AGP mode (speed). 87 * 88 * \returns 89 * The length of the string stored in \c buffer. This does \b not include 90 * the terminating \c NUL character. 91 */ 92unsigned 93driGetRendererString( char * buffer, const char * hardware_name, 94 const char * driver_date, GLuint agp_mode ) 95{ 96#define MAX_INFO 4 97 const char * cpu[MAX_INFO]; 98 unsigned next = 0; 99 unsigned i; 100 unsigned offset; 101 102 103 offset = sprintf( buffer, "Mesa DRI %s %s", hardware_name, driver_date ); 104 105 /* Append any AGP-specific information. 106 */ 107 switch ( agp_mode ) { 108 case 1: 109 case 2: 110 case 4: 111 case 8: 112 offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode ); 113 break; 114 115 default: 116 break; 117 } 118 119 /* Append any CPU-specific information. 120 */ 121#ifdef USE_X86_ASM 122 if ( _mesa_x86_cpu_features ) { 123 cpu[next] = " x86"; 124 next++; 125 } 126# ifdef USE_MMX_ASM 127 if ( cpu_has_mmx ) { 128 cpu[next] = (cpu_has_mmxext) ? "/MMX+" : "/MMX"; 129 next++; 130 } 131# endif 132# ifdef USE_3DNOW_ASM 133 if ( cpu_has_3dnow ) { 134 cpu[next] = (cpu_has_3dnowext) ? "/3DNow!+" : "/3DNow!"; 135 next++; 136 } 137# endif 138# ifdef USE_SSE_ASM 139 if ( cpu_has_xmm ) { 140 cpu[next] = (cpu_has_xmm2) ? "/SSE2" : "/SSE"; 141 next++; 142 } 143# endif 144 145#elif defined(USE_SPARC_ASM) 146 147 cpu[0] = " SPARC"; 148 next = 1; 149 150#elif defined(USE_PPC_ASM) 151 if ( _mesa_ppc_cpu_features ) { 152 cpu[next] = (cpu_has_64) ? " PowerPC 64" : " PowerPC"; 153 next++; 154 } 155 156# ifdef USE_VMX_ASM 157 if ( cpu_has_vmx ) { 158 cpu[next] = "/Altivec"; 159 next++; 160 } 161# endif 162 163 if ( ! cpu_has_fpu ) { 164 cpu[next] = "/No FPU"; 165 next++; 166 } 167#endif 168 169 for ( i = 0 ; i < next ; i++ ) { 170 const size_t len = strlen( cpu[i] ); 171 172 strncpy( & buffer[ offset ], cpu[i], len ); 173 offset += len; 174 } 175 176 return offset; 177} 178 179 180 181 182#define need_GL_ARB_multisample 183#define need_GL_ARB_transpose_matrix 184#define need_GL_ARB_window_pos 185#define need_GL_EXT_compiled_vertex_array 186#define need_GL_EXT_polygon_offset 187#define need_GL_EXT_texture_object 188#define need_GL_EXT_vertex_array 189#define need_GL_MESA_window_pos 190 191/* These are needed in *all* drivers because Mesa internally implements 192 * certain functionality in terms of functions provided by these extensions. 193 * For example, glBlendFunc is implemented by calling glBlendFuncSeparateEXT. 194 */ 195#define need_GL_EXT_blend_func_separate 196#define need_GL_NV_vertex_program 197 198#include "extension_helper.h" 199 200static const struct dri_extension all_mesa_extensions[] = { 201 { "GL_ARB_multisample", GL_ARB_multisample_functions }, 202 { "GL_ARB_transpose_matrix", GL_ARB_transpose_matrix_functions }, 203 { "GL_ARB_window_pos", GL_ARB_window_pos_functions }, 204 { "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions }, 205 { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions }, 206 { "GL_EXT_polygon_offset", GL_EXT_polygon_offset_functions }, 207 { "GL_EXT_texture_object", GL_EXT_texture_object_functions }, 208 { "GL_EXT_vertex_array", GL_EXT_vertex_array_functions }, 209 { "GL_MESA_window_pos", GL_MESA_window_pos_functions }, 210 { "GL_NV_vertex_program", GL_NV_vertex_program_functions }, 211 { NULL, NULL } 212}; 213 214 215/** 216 * Enable extensions supported by the driver. 217 * 218 * \bug 219 * ARB_imaging isn't handled properly. In Mesa, enabling ARB_imaging also 220 * enables all the sub-extensions that are folded into it. This means that 221 * we need to add entry-points (via \c driInitSingleExtension) for those 222 * new functions here. 223 */ 224void driInitExtensions( GLcontext * ctx, 225 const struct dri_extension * extensions_to_enable, 226 GLboolean enable_imaging ) 227{ 228 static int first_time = 1; 229 unsigned i; 230 231 if ( first_time ) { 232 for ( i = 0 ; i < driDispatchRemapTable_size ; i++ ) { 233 driDispatchRemapTable[i] = -1; 234 } 235 236 first_time = 0; 237 driInitExtensions( ctx, all_mesa_extensions, GL_FALSE ); 238 } 239 240 if ( (ctx != NULL) && enable_imaging ) { 241 _mesa_enable_imaging_extensions( ctx ); 242 } 243 244 for ( i = 0 ; extensions_to_enable[i].name != NULL ; i++ ) { 245 driInitSingleExtension( ctx, & extensions_to_enable[i] ); 246 } 247} 248 249 250 251 252/** 253 * Enable and add dispatch functions for a single extension 254 * 255 * \param ctx Context where extension is to be enabled. 256 * \param ext Extension that is to be enabled. 257 * 258 * \sa driInitExtensions, _mesa_enable_extension, _glapi_add_entrypoint 259 * 260 * \todo 261 * Determine if it would be better to use \c strlen instead of the hardcoded 262 * for-loops. 263 */ 264void driInitSingleExtension( GLcontext * ctx, 265 const struct dri_extension * ext ) 266{ 267 unsigned i; 268 269 270 if ( ext->functions != NULL ) { 271 for ( i = 0 ; ext->functions[i].strings != NULL ; i++ ) { 272 const char * functions[16]; 273 const char * parameter_signature; 274 const char * str = ext->functions[i].strings; 275 unsigned j; 276 unsigned offset; 277 278 279 /* Separate the parameter signature from the rest of the string. 280 * If the parameter signature is empty (i.e., the string starts 281 * with a NUL character), then the function has a void parameter 282 * list. 283 */ 284 parameter_signature = str; 285 while ( str[0] != '\0' ) { 286 str++; 287 } 288 str++; 289 290 291 /* Divide the string into the substrings that name each 292 * entry-point for the function. 293 */ 294 for ( j = 0 ; j < 16 ; j++ ) { 295 if ( str[0] == '\0' ) { 296 functions[j] = NULL; 297 break; 298 } 299 300 functions[j] = str; 301 302 while ( str[0] != '\0' ) { 303 str++; 304 } 305 str++; 306 } 307 308 309 /* Add each entry-point to the dispatch table. 310 */ 311 offset = _glapi_add_dispatch( functions, parameter_signature ); 312 if (offset == -1) { 313 fprintf(stderr, "DISPATCH ERROR! _glapi_add_dispatch failed " 314 "to add %s!\n", functions[0]); 315 } 316 else if (ext->functions[i].remap_index != -1) { 317 driDispatchRemapTable[ ext->functions[i].remap_index ] = 318 offset; 319 } 320 else if (ext->functions[i].offset != offset) { 321 fprintf(stderr, "DISPATCH ERROR! %s -> %u != %u\n", 322 functions[0], offset, ext->functions[i].offset); 323 } 324 } 325 } 326 327 if ( ctx != NULL ) { 328 _mesa_enable_extension( ctx, ext->name ); 329 } 330} 331 332 333/** 334 * Utility function used by drivers to test the verions of other components. 335 * 336 * If one of the version requirements is not met, a message is logged using 337 * \c __driUtilMessage. 338 * 339 * \param driver_name Name of the driver. Used in error messages. 340 * \param driActual Actual DRI version supplied __driCreateNewScreen. 341 * \param driExpected Minimum DRI version required by the driver. 342 * \param ddxActual Actual DDX version supplied __driCreateNewScreen. 343 * \param ddxExpected Minimum DDX minor and range of DDX major version required by the driver. 344 * \param drmActual Actual DRM version supplied __driCreateNewScreen. 345 * \param drmExpected Minimum DRM version required by the driver. 346 * 347 * \returns \c GL_TRUE if all version requirements are met. Otherwise, 348 * \c GL_FALSE is returned. 349 * 350 * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2, __driUtilMessage 351 * 352 * \todo 353 * Now that the old \c driCheckDriDdxDrmVersions function is gone, this 354 * function and \c driCheckDriDdxDrmVersions2 should be renamed. 355 */ 356GLboolean 357driCheckDriDdxDrmVersions3(const char * driver_name, 358 const __DRIversion * driActual, 359 const __DRIversion * driExpected, 360 const __DRIversion * ddxActual, 361 const __DRIutilversion2 * ddxExpected, 362 const __DRIversion * drmActual, 363 const __DRIversion * drmExpected) 364{ 365 static const char format[] = "%s DRI driver expected %s version %d.%d.x " 366 "but got version %d.%d.%d\n"; 367 static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x " 368 "but got version %d.%d.%d\n"; 369 370 371 /* Check the DRI version */ 372 if ( (driActual->major != driExpected->major) 373 || (driActual->minor < driExpected->minor) ) { 374 fprintf(stderr, format, driver_name, "DRI", 375 driExpected->major, driExpected->minor, 376 driActual->major, driActual->minor, driActual->patch); 377 return GL_FALSE; 378 } 379 380 /* Check that the DDX driver version is compatible */ 381 /* for miniglx we pass in -1 so we can ignore the DDX version */ 382 if ( (ddxActual->major != -1) && ((ddxActual->major < ddxExpected->major_min) 383 || (ddxActual->major > ddxExpected->major_max) 384 || (ddxActual->minor < ddxExpected->minor)) ) { 385 fprintf(stderr, format2, driver_name, "DDX", 386 ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor, 387 ddxActual->major, ddxActual->minor, ddxActual->patch); 388 return GL_FALSE; 389 } 390 391 /* Check that the DRM driver version is compatible */ 392 if ( (drmActual->major != drmExpected->major) 393 || (drmActual->minor < drmExpected->minor) ) { 394 fprintf(stderr, format, driver_name, "DRM", 395 drmExpected->major, drmExpected->minor, 396 drmActual->major, drmActual->minor, drmActual->patch); 397 return GL_FALSE; 398 } 399 400 return GL_TRUE; 401} 402 403GLboolean 404driCheckDriDdxDrmVersions2(const char * driver_name, 405 const __DRIversion * driActual, 406 const __DRIversion * driExpected, 407 const __DRIversion * ddxActual, 408 const __DRIversion * ddxExpected, 409 const __DRIversion * drmActual, 410 const __DRIversion * drmExpected) 411{ 412 __DRIutilversion2 ddx_expected; 413 ddx_expected.major_min = ddxExpected->major; 414 ddx_expected.major_max = ddxExpected->major; 415 ddx_expected.minor = ddxExpected->minor; 416 ddx_expected.patch = ddxExpected->patch; 417 return driCheckDriDdxDrmVersions3(driver_name, driActual, 418 driExpected, ddxActual, & ddx_expected, 419 drmActual, drmExpected); 420} 421 422 423 424GLint 425driIntersectArea( drm_clip_rect_t rect1, drm_clip_rect_t rect2 ) 426{ 427 if (rect2.x1 > rect1.x1) rect1.x1 = rect2.x1; 428 if (rect2.x2 < rect1.x2) rect1.x2 = rect2.x2; 429 if (rect2.y1 > rect1.y1) rect1.y1 = rect2.y1; 430 if (rect2.y2 < rect1.y2) rect1.y2 = rect2.y2; 431 432 if (rect1.x1 > rect1.x2 || rect1.y1 > rect1.y2) return 0; 433 434 return (rect1.x2 - rect1.x1) * (rect1.y2 - rect1.y1); 435} 436 437GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer, 438 GLint *x, GLint *y, 439 GLsizei *width, GLsizei *height ) 440{ 441 /* left clipping */ 442 if (*x < buffer->_Xmin) { 443 *width -= (buffer->_Xmin - *x); 444 *x = buffer->_Xmin; 445 } 446 447 /* right clipping */ 448 if (*x + *width > buffer->_Xmax) 449 *width -= (*x + *width - buffer->_Xmax - 1); 450 451 if (*width <= 0) 452 return GL_FALSE; 453 454 /* bottom clipping */ 455 if (*y < buffer->_Ymin) { 456 *height -= (buffer->_Ymin - *y); 457 *y = buffer->_Ymin; 458 } 459 460 /* top clipping */ 461 if (*y + *height > buffer->_Ymax) 462 *height -= (*y + *height - buffer->_Ymax - 1); 463 464 if (*height <= 0) 465 return GL_FALSE; 466 467 return GL_TRUE; 468} 469 470 471 472/** 473 * Creates a set of \c __GLcontextModes that a driver will expose. 474 * 475 * A set of \c __GLcontextModes will be created based on the supplied 476 * parameters. The number of modes processed will be 2 * 477 * \c num_depth_stencil_bits * \c num_db_modes. 478 * 479 * For the most part, data is just copied from \c depth_bits, \c stencil_bits, 480 * \c db_modes, and \c visType into each \c __GLcontextModes element. 481 * However, the meanings of \c fb_format and \c fb_type require further 482 * explanation. The \c fb_format specifies which color components are in 483 * each pixel and what the default order is. For example, \c GL_RGB specifies 484 * that red, green, blue are available and red is in the "most significant" 485 * position and blue is in the "least significant". The \c fb_type specifies 486 * the bit sizes of each component and the actual ordering. For example, if 487 * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11] 488 * are the blue value, bits [10:5] are the green value, and bits [4:0] are 489 * the red value. 490 * 491 * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either 492 * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the 493 * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or 494 * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as 495 * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8 496 * still uses 32-bits. 497 * 498 * If in doubt, look at the tables used in the function. 499 * 500 * \param ptr_to_modes Pointer to a pointer to a linked list of 501 * \c __GLcontextModes. Upon completion, a pointer to 502 * the next element to be process will be stored here. 503 * If the function fails and returns \c GL_FALSE, this 504 * value will be unmodified, but some elements in the 505 * linked list may be modified. 506 * \param fb_format Format of the framebuffer. Currently only \c GL_RGB, 507 * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported. 508 * \param fb_type Type of the pixels in the framebuffer. Currently only 509 * \c GL_UNSIGNED_SHORT_5_6_5, 510 * \c GL_UNSIGNED_SHORT_5_6_5_REV, 511 * \c GL_UNSIGNED_INT_8_8_8_8, and 512 * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported. 513 * \param depth_bits Array of depth buffer sizes to be exposed. 514 * \param stencil_bits Array of stencil buffer sizes to be exposed. 515 * \param num_depth_stencil_bits Number of entries in both \c depth_bits and 516 * \c stencil_bits. 517 * \param db_modes Array of buffer swap modes. If an element has a 518 * value of \c GLX_NONE, then it represents a 519 * single-buffered mode. Other valid values are 520 * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and 521 * \c GLX_SWAP_UNDEFINED_OML. See the 522 * GLX_OML_swap_method extension spec for more details. 523 * \param num_db_modes Number of entries in \c db_modes. 524 * \param msaa_samples Array of msaa sample count. 0 represents a visual 525 * without a multisample buffer. 526 * \param num_msaa_modes Number of entries in \c msaa_samples. 527 * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or 528 * \c GLX_DIRECT_COLOR. 529 * 530 * \returns 531 * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only 532 * cause of failure is a bad parameter (i.e., unsupported \c fb_format or 533 * \c fb_type). 534 * 535 * \todo 536 * There is currently no way to support packed RGB modes (i.e., modes with 537 * exactly 3 bytes per pixel) or floating-point modes. This could probably 538 * be done by creating some new, private enums with clever names likes 539 * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32, 540 * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it. 541 */ 542GLboolean 543driFillInModes( __GLcontextModes ** ptr_to_modes, 544 GLenum fb_format, GLenum fb_type, 545 const uint8_t * depth_bits, const uint8_t * stencil_bits, 546 unsigned num_depth_stencil_bits, 547 const GLenum * db_modes, unsigned num_db_modes, 548 const u_int8_t * msaa_samples, unsigned num_msaa_modes, 549 int visType ) 550{ 551 static const uint8_t bits_table[3][4] = { 552 /* R G B A */ 553 { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */ 554 { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */ 555 { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */ 556 }; 557 558 /* The following arrays are all indexed by the fb_type masked with 0x07. 559 * Given the four supported fb_type values, this results in valid array 560 * indices of 3, 4, 5, and 7. 561 */ 562 static const uint32_t masks_table_rgb[8][4] = { 563 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 564 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 565 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 566 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ 567 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ 568 { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8 */ 569 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 570 { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 } /* 8_8_8_8_REV */ 571 }; 572 573 static const uint32_t masks_table_rgba[8][4] = { 574 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 575 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 576 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 577 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ 578 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ 579 { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8 */ 580 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 581 { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */ 582 }; 583 584 static const uint32_t masks_table_bgr[8][4] = { 585 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 586 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 587 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 588 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ 589 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ 590 { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8 */ 591 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 592 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */ 593 }; 594 595 static const uint32_t masks_table_bgra[8][4] = { 596 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 597 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 598 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 599 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ 600 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ 601 { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8 */ 602 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 603 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */ 604 }; 605 606 static const uint8_t bytes_per_pixel[8] = { 607 0, 0, 0, 2, 2, 4, 0, 4 608 }; 609 610 const uint8_t * bits; 611 const uint32_t * masks; 612 const int index = fb_type & 0x07; 613 __GLcontextModes * modes = *ptr_to_modes; 614 unsigned i, j, k, h; 615 616 617 if ( bytes_per_pixel[ index ] == 0 ) { 618 fprintf( stderr, "[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.\n", 619 __FUNCTION__, __LINE__, fb_type ); 620 return GL_FALSE; 621 } 622 623 624 /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and 625 * the _REV versions. 626 * 627 * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA. 628 */ 629 630 switch ( fb_format ) { 631 case GL_RGB: 632 bits = (bytes_per_pixel[ index ] == 2) 633 ? bits_table[0] : bits_table[1]; 634 masks = masks_table_rgb[ index ]; 635 break; 636 637 case GL_RGBA: 638 bits = (bytes_per_pixel[ index ] == 2) 639 ? bits_table[0] : bits_table[2]; 640 masks = masks_table_rgba[ index ]; 641 break; 642 643 case GL_BGR: 644 bits = (bytes_per_pixel[ index ] == 2) 645 ? bits_table[0] : bits_table[1]; 646 masks = masks_table_bgr[ index ]; 647 break; 648 649 case GL_BGRA: 650 bits = (bytes_per_pixel[ index ] == 2) 651 ? bits_table[0] : bits_table[2]; 652 masks = masks_table_bgra[ index ]; 653 break; 654 655 default: 656 fprintf( stderr, "[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.\n", 657 __FUNCTION__, __LINE__, fb_format ); 658 return GL_FALSE; 659 } 660 661 662 for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) { 663 for ( i = 0 ; i < num_db_modes ; i++ ) { 664 for ( h = 0 ; h < num_msaa_modes; h++ ) { 665 for ( j = 0 ; j < 2 ; j++ ) { 666 667 modes->redBits = bits[0]; 668 modes->greenBits = bits[1]; 669 modes->blueBits = bits[2]; 670 modes->alphaBits = bits[3]; 671 modes->redMask = masks[0]; 672 modes->greenMask = masks[1]; 673 modes->blueMask = masks[2]; 674 modes->alphaMask = masks[3]; 675 modes->rgbBits = modes->redBits + modes->greenBits 676 + modes->blueBits + modes->alphaBits; 677 678 modes->accumRedBits = 16 * j; 679 modes->accumGreenBits = 16 * j; 680 modes->accumBlueBits = 16 * j; 681 modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0; 682 modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG; 683 684 modes->stencilBits = stencil_bits[k]; 685 modes->depthBits = depth_bits[k]; 686 687 modes->visualType = visType; 688 modes->renderType = GLX_RGBA_BIT; 689 modes->drawableType = GLX_WINDOW_BIT; 690 modes->rgbMode = GL_TRUE; 691 692 if ( db_modes[i] == GLX_NONE ) { 693 modes->doubleBufferMode = GL_FALSE; 694 } 695 else { 696 modes->doubleBufferMode = GL_TRUE; 697 modes->swapMethod = db_modes[i]; 698 } 699 700 modes->samples = msaa_samples[h]; 701 modes->sampleBuffers = modes->samples ? 1 : 0; 702 703 modes->haveAccumBuffer = ((modes->accumRedBits + 704 modes->accumGreenBits + 705 modes->accumBlueBits + 706 modes->accumAlphaBits) > 0); 707 modes->haveDepthBuffer = (modes->depthBits > 0); 708 modes->haveStencilBuffer = (modes->stencilBits > 0); 709 710 modes = modes->next; 711 } 712 } 713 } 714 } 715 716 *ptr_to_modes = modes; 717 return GL_TRUE; 718} 719