utils.c revision 5d5ae371eaeca7e33e638af3aee1ae8e162db0a7
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 "main/mtypes.h" 35#include "main/extensions.h" 36#include "glapi/dispatch.h" 37#include "utils.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_draw_buffers 183#define need_GL_ARB_multisample 184#define need_GL_ARB_texture_compression 185#define need_GL_ARB_transpose_matrix 186#define need_GL_ARB_vertex_buffer_object 187#define need_GL_ARB_window_pos 188#define need_GL_EXT_compiled_vertex_array 189#define need_GL_EXT_multi_draw_arrays 190#define need_GL_EXT_polygon_offset 191#define need_GL_EXT_texture_object 192#define need_GL_EXT_vertex_array 193#define need_GL_IBM_multimode_draw_arrays 194#define need_GL_MESA_window_pos 195 196/* These are needed in *all* drivers because Mesa internally implements 197 * certain functionality in terms of functions provided by these extensions. 198 * For example, glBlendFunc is implemented by calling glBlendFuncSeparateEXT. 199 */ 200#define need_GL_EXT_blend_func_separate 201#define need_GL_NV_vertex_program 202 203#include "extension_helper.h" 204 205static const struct dri_extension all_mesa_extensions[] = { 206 { "GL_ARB_draw_buffers", GL_ARB_draw_buffers_functions }, 207 { "GL_ARB_multisample", GL_ARB_multisample_functions }, 208 { "GL_ARB_texture_compression", GL_ARB_texture_compression_functions }, 209 { "GL_ARB_transpose_matrix", GL_ARB_transpose_matrix_functions }, 210 { "GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions}, 211 { "GL_ARB_window_pos", GL_ARB_window_pos_functions }, 212 { "GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions }, 213 { "GL_EXT_compiled_vertex_array", GL_EXT_compiled_vertex_array_functions }, 214 { "GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions }, 215 { "GL_EXT_polygon_offset", GL_EXT_polygon_offset_functions }, 216 { "GL_EXT_texture_object", GL_EXT_texture_object_functions }, 217 { "GL_EXT_vertex_array", GL_EXT_vertex_array_functions }, 218 { "GL_IBM_multimode_draw_arrays", GL_IBM_multimode_draw_arrays_functions }, 219 { "GL_MESA_window_pos", GL_MESA_window_pos_functions }, 220 { "GL_NV_vertex_program", GL_NV_vertex_program_functions }, 221 { NULL, NULL } 222}; 223 224 225/** 226 * Enable extensions supported by the driver. 227 * 228 * \bug 229 * ARB_imaging isn't handled properly. In Mesa, enabling ARB_imaging also 230 * enables all the sub-extensions that are folded into it. This means that 231 * we need to add entry-points (via \c driInitSingleExtension) for those 232 * new functions here. 233 */ 234void driInitExtensions( GLcontext * ctx, 235 const struct dri_extension * extensions_to_enable, 236 GLboolean enable_imaging ) 237{ 238 static int first_time = 1; 239 unsigned i; 240 241 if ( first_time ) { 242 for ( i = 0 ; i < driDispatchRemapTable_size ; i++ ) { 243 driDispatchRemapTable[i] = -1; 244 } 245 246 first_time = 0; 247 driInitExtensions( ctx, all_mesa_extensions, GL_FALSE ); 248 } 249 250 if ( (ctx != NULL) && enable_imaging ) { 251 _mesa_enable_imaging_extensions( ctx ); 252 } 253 254 for ( i = 0 ; extensions_to_enable[i].name != NULL ; i++ ) { 255 driInitSingleExtension( ctx, & extensions_to_enable[i] ); 256 } 257} 258 259 260 261 262/** 263 * Enable and add dispatch functions for a single extension 264 * 265 * \param ctx Context where extension is to be enabled. 266 * \param ext Extension that is to be enabled. 267 * 268 * \sa driInitExtensions, _mesa_enable_extension, _glapi_add_entrypoint 269 * 270 * \todo 271 * Determine if it would be better to use \c strlen instead of the hardcoded 272 * for-loops. 273 */ 274void driInitSingleExtension( GLcontext * ctx, 275 const struct dri_extension * ext ) 276{ 277 unsigned i; 278 279 280 if ( ext->functions != NULL ) { 281 for ( i = 0 ; ext->functions[i].strings != NULL ; i++ ) { 282 const char * functions[16]; 283 const char * parameter_signature; 284 const char * str = ext->functions[i].strings; 285 unsigned j; 286 unsigned offset; 287 288 289 /* Separate the parameter signature from the rest of the string. 290 * If the parameter signature is empty (i.e., the string starts 291 * with a NUL character), then the function has a void parameter 292 * list. 293 */ 294 parameter_signature = str; 295 while ( str[0] != '\0' ) { 296 str++; 297 } 298 str++; 299 300 301 /* Divide the string into the substrings that name each 302 * entry-point for the function. 303 */ 304 for ( j = 0 ; j < 16 ; j++ ) { 305 if ( str[0] == '\0' ) { 306 functions[j] = NULL; 307 break; 308 } 309 310 functions[j] = str; 311 312 while ( str[0] != '\0' ) { 313 str++; 314 } 315 str++; 316 } 317 318 319 /* Add each entry-point to the dispatch table. 320 */ 321 offset = _glapi_add_dispatch( functions, parameter_signature ); 322 if (offset == -1) { 323#if 0 /* this causes noise with egl */ 324 fprintf(stderr, "DISPATCH ERROR! _glapi_add_dispatch failed " 325 "to add %s!\n", functions[0]); 326#endif 327 } 328 else if (ext->functions[i].remap_index != -1) { 329 driDispatchRemapTable[ ext->functions[i].remap_index ] = 330 offset; 331 } 332 else if (ext->functions[i].offset != offset) { 333 fprintf(stderr, "DISPATCH ERROR! %s -> %u != %u\n", 334 functions[0], offset, ext->functions[i].offset); 335 } 336 } 337 } 338 339 if ( ctx != NULL ) { 340 _mesa_enable_extension( ctx, ext->name ); 341 } 342} 343 344 345/** 346 * Utility function used by drivers to test the verions of other components. 347 * 348 * If one of the version requirements is not met, a message is logged using 349 * \c __driUtilMessage. 350 * 351 * \param driver_name Name of the driver. Used in error messages. 352 * \param driActual Actual DRI version supplied __driCreateNewScreen. 353 * \param driExpected Minimum DRI version required by the driver. 354 * \param ddxActual Actual DDX version supplied __driCreateNewScreen. 355 * \param ddxExpected Minimum DDX minor and range of DDX major version required by the driver. 356 * \param drmActual Actual DRM version supplied __driCreateNewScreen. 357 * \param drmExpected Minimum DRM version required by the driver. 358 * 359 * \returns \c GL_TRUE if all version requirements are met. Otherwise, 360 * \c GL_FALSE is returned. 361 * 362 * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions2, __driUtilMessage 363 * 364 * \todo 365 * Now that the old \c driCheckDriDdxDrmVersions function is gone, this 366 * function and \c driCheckDriDdxDrmVersions2 should be renamed. 367 */ 368GLboolean 369driCheckDriDdxDrmVersions3(const char * driver_name, 370 const __DRIversion * driActual, 371 const __DRIversion * driExpected, 372 const __DRIversion * ddxActual, 373 const __DRIutilversion2 * ddxExpected, 374 const __DRIversion * drmActual, 375 const __DRIversion * drmExpected) 376{ 377 static const char format[] = "%s DRI driver expected %s version %d.%d.x " 378 "but got version %d.%d.%d\n"; 379 static const char format2[] = "%s DRI driver expected %s version %d-%d.%d.x " 380 "but got version %d.%d.%d\n"; 381 382 383 /* Check the DRI version */ 384 if ( (driActual->major != driExpected->major) 385 || (driActual->minor < driExpected->minor) ) { 386 fprintf(stderr, format, driver_name, "DRI", 387 driExpected->major, driExpected->minor, 388 driActual->major, driActual->minor, driActual->patch); 389 return GL_FALSE; 390 } 391 392 /* Check that the DDX driver version is compatible */ 393 /* for miniglx we pass in -1 so we can ignore the DDX version */ 394 if ( (ddxActual->major != -1) && ((ddxActual->major < ddxExpected->major_min) 395 || (ddxActual->major > ddxExpected->major_max) 396 || (ddxActual->minor < ddxExpected->minor)) ) { 397 fprintf(stderr, format2, driver_name, "DDX", 398 ddxExpected->major_min, ddxExpected->major_max, ddxExpected->minor, 399 ddxActual->major, ddxActual->minor, ddxActual->patch); 400 return GL_FALSE; 401 } 402 403 /* Check that the DRM driver version is compatible */ 404 if ( (drmActual->major != drmExpected->major) 405 || (drmActual->minor < drmExpected->minor) ) { 406 fprintf(stderr, format, driver_name, "DRM", 407 drmExpected->major, drmExpected->minor, 408 drmActual->major, drmActual->minor, drmActual->patch); 409 return GL_FALSE; 410 } 411 412 return GL_TRUE; 413} 414 415GLboolean 416driCheckDriDdxDrmVersions2(const char * driver_name, 417 const __DRIversion * driActual, 418 const __DRIversion * driExpected, 419 const __DRIversion * ddxActual, 420 const __DRIversion * ddxExpected, 421 const __DRIversion * drmActual, 422 const __DRIversion * drmExpected) 423{ 424 __DRIutilversion2 ddx_expected; 425 ddx_expected.major_min = ddxExpected->major; 426 ddx_expected.major_max = ddxExpected->major; 427 ddx_expected.minor = ddxExpected->minor; 428 ddx_expected.patch = ddxExpected->patch; 429 return driCheckDriDdxDrmVersions3(driver_name, driActual, 430 driExpected, ddxActual, & ddx_expected, 431 drmActual, drmExpected); 432} 433 434GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer, 435 GLint *x, GLint *y, 436 GLsizei *width, GLsizei *height ) 437{ 438 /* left clipping */ 439 if (*x < buffer->_Xmin) { 440 *width -= (buffer->_Xmin - *x); 441 *x = buffer->_Xmin; 442 } 443 444 /* right clipping */ 445 if (*x + *width > buffer->_Xmax) 446 *width -= (*x + *width - buffer->_Xmax - 1); 447 448 if (*width <= 0) 449 return GL_FALSE; 450 451 /* bottom clipping */ 452 if (*y < buffer->_Ymin) { 453 *height -= (buffer->_Ymin - *y); 454 *y = buffer->_Ymin; 455 } 456 457 /* top clipping */ 458 if (*y + *height > buffer->_Ymax) 459 *height -= (*y + *height - buffer->_Ymax - 1); 460 461 if (*height <= 0) 462 return GL_FALSE; 463 464 return GL_TRUE; 465} 466 467/** 468 * Creates a set of \c __GLcontextModes that a driver will expose. 469 * 470 * A set of \c __GLcontextModes will be created based on the supplied 471 * parameters. The number of modes processed will be 2 * 472 * \c num_depth_stencil_bits * \c num_db_modes. 473 * 474 * For the most part, data is just copied from \c depth_bits, \c stencil_bits, 475 * \c db_modes, and \c visType into each \c __GLcontextModes element. 476 * However, the meanings of \c fb_format and \c fb_type require further 477 * explanation. The \c fb_format specifies which color components are in 478 * each pixel and what the default order is. For example, \c GL_RGB specifies 479 * that red, green, blue are available and red is in the "most significant" 480 * position and blue is in the "least significant". The \c fb_type specifies 481 * the bit sizes of each component and the actual ordering. For example, if 482 * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11] 483 * are the blue value, bits [10:5] are the green value, and bits [4:0] are 484 * the red value. 485 * 486 * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either 487 * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the 488 * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or 489 * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as 490 * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8 491 * still uses 32-bits. 492 * 493 * If in doubt, look at the tables used in the function. 494 * 495 * \param ptr_to_modes Pointer to a pointer to a linked list of 496 * \c __GLcontextModes. Upon completion, a pointer to 497 * the next element to be process will be stored here. 498 * If the function fails and returns \c GL_FALSE, this 499 * value will be unmodified, but some elements in the 500 * linked list may be modified. 501 * \param fb_format Format of the framebuffer. Currently only \c GL_RGB, 502 * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported. 503 * \param fb_type Type of the pixels in the framebuffer. Currently only 504 * \c GL_UNSIGNED_SHORT_5_6_5, 505 * \c GL_UNSIGNED_SHORT_5_6_5_REV, 506 * \c GL_UNSIGNED_INT_8_8_8_8, and 507 * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported. 508 * \param depth_bits Array of depth buffer sizes to be exposed. 509 * \param stencil_bits Array of stencil buffer sizes to be exposed. 510 * \param num_depth_stencil_bits Number of entries in both \c depth_bits and 511 * \c stencil_bits. 512 * \param db_modes Array of buffer swap modes. If an element has a 513 * value of \c GLX_NONE, then it represents a 514 * single-buffered mode. Other valid values are 515 * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and 516 * \c GLX_SWAP_UNDEFINED_OML. See the 517 * GLX_OML_swap_method extension spec for more details. 518 * \param num_db_modes Number of entries in \c db_modes. 519 * \param msaa_samples Array of msaa sample count. 0 represents a visual 520 * without a multisample buffer. 521 * \param num_msaa_modes Number of entries in \c msaa_samples. 522 * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or 523 * \c GLX_DIRECT_COLOR. 524 * 525 * \returns 526 * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only 527 * cause of failure is a bad parameter (i.e., unsupported \c fb_format or 528 * \c fb_type). 529 * 530 * \todo 531 * There is currently no way to support packed RGB modes (i.e., modes with 532 * exactly 3 bytes per pixel) or floating-point modes. This could probably 533 * be done by creating some new, private enums with clever names likes 534 * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32, 535 * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it. 536 */ 537__DRIconfig ** 538driCreateConfigs(GLenum fb_format, GLenum fb_type, 539 const uint8_t * depth_bits, const uint8_t * stencil_bits, 540 unsigned num_depth_stencil_bits, 541 const GLenum * db_modes, unsigned num_db_modes, 542 const u_int8_t * msaa_samples, unsigned num_msaa_modes) 543{ 544 static const uint8_t bits_table[4][4] = { 545 /* R G B A */ 546 { 3, 3, 2, 0 }, /* Any GL_UNSIGNED_BYTE_3_3_2 */ 547 { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */ 548 { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */ 549 { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */ 550 }; 551 552 static const uint32_t masks_table_rgb[6][4] = { 553 { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */ 554 { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */ 555 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ 556 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ 557 { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8 */ 558 { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 } /* 8_8_8_8_REV */ 559 }; 560 561 static const uint32_t masks_table_rgba[6][4] = { 562 { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 3_3_2 */ 563 { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 2_3_3_REV */ 564 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ 565 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ 566 { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8 */ 567 { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */ 568 }; 569 570 static const uint32_t masks_table_bgr[6][4] = { 571 { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */ 572 { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */ 573 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ 574 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ 575 { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8 */ 576 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */ 577 }; 578 579 static const uint32_t masks_table_bgra[6][4] = { 580 { 0x00000007, 0x00000038, 0x000000C0, 0x00000000 }, /* 3_3_2 */ 581 { 0x000000E0, 0x0000001C, 0x00000003, 0x00000000 }, /* 2_3_3_REV */ 582 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ 583 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ 584 { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8 */ 585 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */ 586 }; 587 588 static const uint8_t bytes_per_pixel[6] = { 589 1, /* 3_3_2 */ 590 1, /* 2_3_3_REV */ 591 2, /* 5_6_5 */ 592 2, /* 5_6_5_REV */ 593 4, /* 8_8_8_8 */ 594 4 /* 8_8_8_8_REV */ 595 }; 596 597 const uint8_t * bits; 598 const uint32_t * masks; 599 int index; 600 __DRIconfig **configs, **c; 601 __GLcontextModes *modes; 602 unsigned i, j, k, h; 603 unsigned num_modes; 604 unsigned num_accum_bits = 2; 605 606 switch ( fb_type ) { 607 case GL_UNSIGNED_BYTE_3_3_2: 608 index = 0; 609 break; 610 case GL_UNSIGNED_BYTE_2_3_3_REV: 611 index = 1; 612 break; 613 case GL_UNSIGNED_SHORT_5_6_5: 614 index = 2; 615 break; 616 case GL_UNSIGNED_SHORT_5_6_5_REV: 617 index = 3; 618 break; 619 case GL_UNSIGNED_INT_8_8_8_8: 620 index = 4; 621 break; 622 case GL_UNSIGNED_INT_8_8_8_8_REV: 623 index = 5; 624 break; 625 default: 626 fprintf( stderr, "[%s:%u] Unknown framebuffer type 0x%04x.\n", 627 __FUNCTION__, __LINE__, fb_type ); 628 return NULL; 629 } 630 631 632 /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and 633 * the _REV versions. 634 * 635 * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA. 636 */ 637 638 switch ( fb_format ) { 639 case GL_RGB: 640 masks = masks_table_rgb[ index ]; 641 break; 642 643 case GL_RGBA: 644 masks = masks_table_rgba[ index ]; 645 break; 646 647 case GL_BGR: 648 masks = masks_table_bgr[ index ]; 649 break; 650 651 case GL_BGRA: 652 masks = masks_table_bgra[ index ]; 653 break; 654 655 default: 656 fprintf( stderr, "[%s:%u] Unknown framebuffer format 0x%04x.\n", 657 __FUNCTION__, __LINE__, fb_format ); 658 return NULL; 659 } 660 661 switch ( bytes_per_pixel[ index ] ) { 662 case 1: 663 bits = bits_table[0]; 664 break; 665 case 2: 666 bits = bits_table[1]; 667 break; 668 default: 669 bits = ((fb_format == GL_RGB) || (fb_format == GL_BGR)) 670 ? bits_table[2] 671 : bits_table[3]; 672 break; 673 } 674 675 num_modes = num_depth_stencil_bits * num_db_modes * num_accum_bits * num_msaa_modes; 676 configs = _mesa_calloc((num_modes + 1) * sizeof *configs); 677 if (configs == NULL) 678 return NULL; 679 680 c = configs; 681 for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) { 682 for ( i = 0 ; i < num_db_modes ; i++ ) { 683 for ( h = 0 ; h < num_msaa_modes; h++ ) { 684 for ( j = 0 ; j < num_accum_bits ; j++ ) { 685 *c = _mesa_malloc (sizeof **c); 686 modes = &(*c)->modes; 687 c++; 688 689 memset(modes, 0, sizeof *modes); 690 modes->redBits = bits[0]; 691 modes->greenBits = bits[1]; 692 modes->blueBits = bits[2]; 693 modes->alphaBits = bits[3]; 694 modes->redMask = masks[0]; 695 modes->greenMask = masks[1]; 696 modes->blueMask = masks[2]; 697 modes->alphaMask = masks[3]; 698 modes->rgbBits = modes->redBits + modes->greenBits 699 + modes->blueBits + modes->alphaBits; 700 701 modes->accumRedBits = 16 * j; 702 modes->accumGreenBits = 16 * j; 703 modes->accumBlueBits = 16 * j; 704 modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0; 705 modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG; 706 707 modes->stencilBits = stencil_bits[k]; 708 modes->depthBits = depth_bits[k]; 709 710 modes->transparentPixel = GLX_NONE; 711 modes->transparentRed = GLX_DONT_CARE; 712 modes->transparentGreen = GLX_DONT_CARE; 713 modes->transparentBlue = GLX_DONT_CARE; 714 modes->transparentAlpha = GLX_DONT_CARE; 715 modes->transparentIndex = GLX_DONT_CARE; 716 modes->visualType = GLX_DONT_CARE; 717 modes->renderType = GLX_RGBA_BIT; 718 modes->drawableType = GLX_WINDOW_BIT; 719 modes->rgbMode = GL_TRUE; 720 721 if ( db_modes[i] == GLX_NONE ) { 722 modes->doubleBufferMode = GL_FALSE; 723 } 724 else { 725 modes->doubleBufferMode = GL_TRUE; 726 modes->swapMethod = db_modes[i]; 727 } 728 729 modes->samples = msaa_samples[h]; 730 modes->sampleBuffers = modes->samples ? 1 : 0; 731 732 733 modes->haveAccumBuffer = ((modes->accumRedBits + 734 modes->accumGreenBits + 735 modes->accumBlueBits + 736 modes->accumAlphaBits) > 0); 737 modes->haveDepthBuffer = (modes->depthBits > 0); 738 modes->haveStencilBuffer = (modes->stencilBits > 0); 739 740 modes->bindToTextureRgb = GL_TRUE; 741 modes->bindToTextureRgba = GL_TRUE; 742 modes->bindToMipmapTexture = GL_FALSE; 743 modes->bindToTextureTargets = modes->rgbMode ? 744 __DRI_ATTRIB_TEXTURE_1D_BIT | 745 __DRI_ATTRIB_TEXTURE_2D_BIT | 746 __DRI_ATTRIB_TEXTURE_RECTANGLE_BIT : 747 0; 748 } 749 } 750 } 751 } 752 *c = NULL; 753 754 return configs; 755} 756 757__DRIconfig **driConcatConfigs(__DRIconfig **a, 758 __DRIconfig **b) 759{ 760 __DRIconfig **all; 761 int i, j, index; 762 763 i = 0; 764 while (a[i] != NULL) 765 i++; 766 j = 0; 767 while (b[j] != NULL) 768 j++; 769 770 all = _mesa_malloc((i + j + 1) * sizeof *all); 771 index = 0; 772 for (i = 0; a[i] != NULL; i++) 773 all[index++] = a[i]; 774 for (j = 0; b[j] != NULL; j++) 775 all[index++] = b[j]; 776 all[index++] = NULL; 777 778 _mesa_free(a); 779 _mesa_free(b); 780 781 return all; 782} 783 784#define __ATTRIB(attrib, field) \ 785 { attrib, offsetof(__GLcontextModes, field) } 786 787static const struct { unsigned int attrib, offset; } attribMap[] = { 788 __ATTRIB(__DRI_ATTRIB_BUFFER_SIZE, rgbBits), 789 __ATTRIB(__DRI_ATTRIB_LEVEL, level), 790 __ATTRIB(__DRI_ATTRIB_RED_SIZE, redBits), 791 __ATTRIB(__DRI_ATTRIB_GREEN_SIZE, greenBits), 792 __ATTRIB(__DRI_ATTRIB_BLUE_SIZE, blueBits), 793 __ATTRIB(__DRI_ATTRIB_ALPHA_SIZE, alphaBits), 794 __ATTRIB(__DRI_ATTRIB_DEPTH_SIZE, depthBits), 795 __ATTRIB(__DRI_ATTRIB_STENCIL_SIZE, stencilBits), 796 __ATTRIB(__DRI_ATTRIB_ACCUM_RED_SIZE, accumRedBits), 797 __ATTRIB(__DRI_ATTRIB_ACCUM_GREEN_SIZE, accumGreenBits), 798 __ATTRIB(__DRI_ATTRIB_ACCUM_BLUE_SIZE, accumBlueBits), 799 __ATTRIB(__DRI_ATTRIB_ACCUM_ALPHA_SIZE, accumAlphaBits), 800 __ATTRIB(__DRI_ATTRIB_SAMPLE_BUFFERS, sampleBuffers), 801 __ATTRIB(__DRI_ATTRIB_SAMPLES, samples), 802 __ATTRIB(__DRI_ATTRIB_DOUBLE_BUFFER, doubleBufferMode), 803 __ATTRIB(__DRI_ATTRIB_STEREO, stereoMode), 804 __ATTRIB(__DRI_ATTRIB_AUX_BUFFERS, numAuxBuffers), 805 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_TYPE, transparentPixel), 806 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_INDEX_VALUE, transparentPixel), 807 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_RED_VALUE, transparentRed), 808 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_GREEN_VALUE, transparentGreen), 809 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_BLUE_VALUE, transparentBlue), 810 __ATTRIB(__DRI_ATTRIB_TRANSPARENT_ALPHA_VALUE, transparentAlpha), 811 __ATTRIB(__DRI_ATTRIB_FLOAT_MODE, floatMode), 812 __ATTRIB(__DRI_ATTRIB_RED_MASK, redMask), 813 __ATTRIB(__DRI_ATTRIB_GREEN_MASK, greenMask), 814 __ATTRIB(__DRI_ATTRIB_BLUE_MASK, blueMask), 815 __ATTRIB(__DRI_ATTRIB_ALPHA_MASK, alphaMask), 816 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_WIDTH, maxPbufferWidth), 817 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_HEIGHT, maxPbufferHeight), 818 __ATTRIB(__DRI_ATTRIB_MAX_PBUFFER_PIXELS, maxPbufferPixels), 819 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_WIDTH, optimalPbufferWidth), 820 __ATTRIB(__DRI_ATTRIB_OPTIMAL_PBUFFER_HEIGHT, optimalPbufferHeight), 821 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, swapMethod), 822 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGB, bindToTextureRgb), 823 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_RGBA, bindToTextureRgba), 824 __ATTRIB(__DRI_ATTRIB_BIND_TO_MIPMAP_TEXTURE, bindToMipmapTexture), 825 __ATTRIB(__DRI_ATTRIB_BIND_TO_TEXTURE_TARGETS, bindToTextureTargets), 826 __ATTRIB(__DRI_ATTRIB_YINVERTED, yInverted), 827 828 /* The struct field doesn't matter here, these are handled by the 829 * switch in driGetConfigAttribIndex. We need them in the array 830 * so the iterator includes them though.*/ 831 __ATTRIB(__DRI_ATTRIB_RENDER_TYPE, level), 832 __ATTRIB(__DRI_ATTRIB_CONFIG_CAVEAT, level), 833 __ATTRIB(__DRI_ATTRIB_SWAP_METHOD, level) 834}; 835 836#define ARRAY_SIZE(a) (sizeof (a) / sizeof ((a)[0])) 837 838static int 839driGetConfigAttribIndex(const __DRIconfig *config, 840 unsigned int index, unsigned int *value) 841{ 842 switch (attribMap[index].attrib) { 843 case __DRI_ATTRIB_RENDER_TYPE: 844 if (config->modes.rgbMode) 845 *value = __DRI_ATTRIB_RGBA_BIT; 846 else 847 *value = __DRI_ATTRIB_COLOR_INDEX_BIT; 848 break; 849 case __DRI_ATTRIB_CONFIG_CAVEAT: 850 if (config->modes.visualRating == GLX_NON_CONFORMANT_CONFIG) 851 *value = __DRI_ATTRIB_NON_CONFORMANT_CONFIG; 852 else if (config->modes.visualRating == GLX_SLOW_CONFIG) 853 *value = __DRI_ATTRIB_SLOW_BIT; 854 else 855 *value = 0; 856 break; 857 case __DRI_ATTRIB_SWAP_METHOD: 858 break; 859 860 case __DRI_ATTRIB_FLOAT_MODE: 861 *value = config->modes.floatMode; 862 break; 863 864 default: 865 *value = *(unsigned int *) 866 ((char *) &config->modes + attribMap[index].offset); 867 868 break; 869 } 870 871 return GL_TRUE; 872} 873 874int 875driGetConfigAttrib(const __DRIconfig *config, 876 unsigned int attrib, unsigned int *value) 877{ 878 int i; 879 880 for (i = 0; i < ARRAY_SIZE(attribMap); i++) 881 if (attribMap[i].attrib == attrib) 882 return driGetConfigAttribIndex(config, i, value); 883 884 return GL_FALSE; 885} 886 887int 888driIndexConfigAttrib(const __DRIconfig *config, int index, 889 unsigned int *attrib, unsigned int *value) 890{ 891 if (index >= 0 && index < ARRAY_SIZE(attribMap)) { 892 *attrib = attribMap[index].attrib; 893 return driGetConfigAttribIndex(config, index, value); 894 } 895 896 return GL_FALSE; 897} 898