utils.c revision 447cdd536fe4539b724e8a7024659e3f4cd724d1
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 38#if !defined( DRI_NEW_INTERFACE_ONLY ) 39#include "xf86dri.h" /* For XF86DRIQueryVersion prototype. */ 40#endif 41 42#if defined(USE_X86_ASM) 43#include "x86/common_x86_asm.h" 44#endif 45 46#if defined(USE_PPC_ASM) 47#include "ppc/common_ppc_features.h" 48#endif 49 50unsigned 51driParseDebugString( const char * debug, 52 const struct dri_debug_control * control ) 53{ 54 unsigned flag; 55 56 57 flag = 0; 58 if ( debug != NULL ) { 59 while( control->string != NULL ) { 60 if ( !strcmp( debug, "all" ) || 61 strstr( debug, control->string ) != NULL ) { 62 flag |= control->flag; 63 } 64 65 control++; 66 } 67 } 68 69 return flag; 70} 71 72 73 74/** 75 * Create the \c GL_RENDERER string for DRI drivers. 76 * 77 * Almost all DRI drivers use a \c GL_RENDERER string of the form: 78 * 79 * "Mesa DRI <chip> <driver date> <AGP speed) <CPU information>" 80 * 81 * Using the supplied chip name, driver data, and AGP speed, this function 82 * creates the string. 83 * 84 * \param buffer Buffer to hold the \c GL_RENDERER string. 85 * \param hardware_name Name of the hardware. 86 * \param driver_date Driver date. 87 * \param agp_mode AGP mode (speed). 88 * 89 * \returns 90 * The length of the string stored in \c buffer. This does \b not include 91 * the terminating \c NUL character. 92 */ 93unsigned 94driGetRendererString( char * buffer, const char * hardware_name, 95 const char * driver_date, GLuint agp_mode ) 96{ 97#define MAX_INFO 4 98 const char * cpu[MAX_INFO]; 99 unsigned next = 0; 100 unsigned i; 101 unsigned offset; 102 103 104 offset = sprintf( buffer, "Mesa DRI %s %s", hardware_name, driver_date ); 105 106 /* Append any AGP-specific information. 107 */ 108 switch ( agp_mode ) { 109 case 1: 110 case 2: 111 case 4: 112 case 8: 113 offset += sprintf( & buffer[ offset ], " AGP %ux", agp_mode ); 114 break; 115 116 default: 117 break; 118 } 119 120 /* Append any CPU-specific information. 121 */ 122#ifdef USE_X86_ASM 123 if ( _mesa_x86_cpu_features ) { 124 cpu[next] = " x86"; 125 next++; 126 } 127# ifdef USE_MMX_ASM 128 if ( cpu_has_mmx ) { 129 cpu[next] = (cpu_has_mmxext) ? "/MMX+" : "/MMX"; 130 next++; 131 } 132# endif 133# ifdef USE_3DNOW_ASM 134 if ( cpu_has_3dnow ) { 135 cpu[next] = (cpu_has_3dnowext) ? "/3DNow!+" : "/3DNow!"; 136 next++; 137 } 138# endif 139# ifdef USE_SSE_ASM 140 if ( cpu_has_xmm ) { 141 cpu[next] = (cpu_has_xmm2) ? "/SSE2" : "/SSE"; 142 next++; 143 } 144# endif 145 146#elif defined(USE_SPARC_ASM) 147 148 cpu[0] = " SPARC"; 149 next = 1; 150 151#elif defined(USE_PPC_ASM) 152 if ( _mesa_ppc_cpu_features ) { 153 cpu[next] = (cpu_has_64) ? " PowerPC 64" : " PowerPC"; 154 next++; 155 } 156 157# ifdef USE_VMX_ASM 158 if ( cpu_has_vmx ) { 159 cpu[next] = "/Altivec"; 160 next++; 161 } 162# endif 163 164 if ( ! cpu_has_fpu ) { 165 cpu[next] = "/No FPU"; 166 next++; 167 } 168#endif 169 170 for ( i = 0 ; i < next ; i++ ) { 171 const size_t len = strlen( cpu[i] ); 172 173 strncpy( & buffer[ offset ], cpu[i], len ); 174 offset += len; 175 } 176 177 return offset; 178} 179 180 181 182 183void driInitExtensions( GLcontext * ctx, 184 const char * const extensions_to_enable[], 185 GLboolean enable_imaging ) 186{ 187 unsigned i; 188 189 if ( enable_imaging ) { 190 _mesa_enable_imaging_extensions( ctx ); 191 } 192 193 for ( i = 0 ; extensions_to_enable[i] != NULL ; i++ ) { 194 _mesa_enable_extension( ctx, extensions_to_enable[i] ); 195 } 196} 197 198 199 200 201#ifndef DRI_NEW_INTERFACE_ONLY 202/** 203 * Utility function used by drivers to test the verions of other components. 204 * 205 * \deprecated 206 * All drivers using the new interface should use \c driCheckDriDdxVersions2 207 * instead. This function is implemented using a call that is not available 208 * to drivers using the new interface. Furthermore, the information gained 209 * by this call (the DRI and DDX version information) is already provided to 210 * the driver via the new interface. 211 */ 212GLboolean 213driCheckDriDdxDrmVersions(__DRIscreenPrivate *sPriv, 214 const char * driver_name, 215 int dri_major, int dri_minor, 216 int ddx_major, int ddx_minor, 217 int drm_major, int drm_minor) 218{ 219 static const char format[] = "%s DRI driver expected %s version %d.%d.x " 220 "but got version %d.%d.%d"; 221 int major, minor, patch; 222 223 /* Check the DRI version */ 224 if (XF86DRIQueryVersion(sPriv->display, &major, &minor, &patch)) { 225 if (major != dri_major || minor < dri_minor) { 226 __driUtilMessage(format, driver_name, "DRI", dri_major, dri_minor, 227 major, minor, patch); 228 return GL_FALSE; 229 } 230 } 231 232 /* Check that the DDX driver version is compatible */ 233 if (sPriv->ddxMajor != ddx_major || sPriv->ddxMinor < ddx_minor) { 234 __driUtilMessage(format, driver_name, "DDX", ddx_major, ddx_minor, 235 sPriv->ddxMajor, sPriv->ddxMinor, sPriv->ddxPatch); 236 return GL_FALSE; 237 } 238 239 /* Check that the DRM driver version is compatible */ 240 if (sPriv->drmMajor != drm_major || sPriv->drmMinor < drm_minor) { 241 __driUtilMessage(format, driver_name, "DRM", drm_major, drm_minor, 242 sPriv->drmMajor, sPriv->drmMinor, sPriv->drmPatch); 243 return GL_FALSE; 244 } 245 246 return GL_TRUE; 247} 248#endif /* DRI_NEW_INTERFACE_ONLY */ 249 250/** 251 * Utility function used by drivers to test the verions of other components. 252 * 253 * If one of the version requirements is not met, a message is logged using 254 * \c __driUtilMessage. 255 * 256 * \param driver_name Name of the driver. Used in error messages. 257 * \param driActual Actual DRI version supplied __driCreateNewScreen. 258 * \param driExpected Minimum DRI version required by the driver. 259 * \param ddxActual Actual DDX version supplied __driCreateNewScreen. 260 * \param ddxExpected Minimum DDX version required by the driver. 261 * \param drmActual Actual DRM version supplied __driCreateNewScreen. 262 * \param drmExpected Minimum DRM version required by the driver. 263 * 264 * \returns \c GL_TRUE if all version requirements are met. Otherwise, 265 * \c GL_FALSE is returned. 266 * 267 * \sa __driCreateNewScreen, driCheckDriDdxDrmVersions, __driUtilMessage 268 */ 269GLboolean 270driCheckDriDdxDrmVersions2(const char * driver_name, 271 const __DRIversion * driActual, 272 const __DRIversion * driExpected, 273 const __DRIversion * ddxActual, 274 const __DRIversion * ddxExpected, 275 const __DRIversion * drmActual, 276 const __DRIversion * drmExpected) 277{ 278 static const char format[] = "%s DRI driver expected %s version %d.%d.x " 279 "but got version %d.%d.%d"; 280 281 282 /* Check the DRI version */ 283 if ( (driActual->major != driExpected->major) 284 || (driActual->minor < driExpected->minor) ) { 285 __driUtilMessage(format, driver_name, "DRI", 286 driExpected->major, driExpected->minor, 287 driActual->major, driActual->minor, driActual->patch); 288 return GL_FALSE; 289 } 290 291 /* Check that the DDX driver version is compatible */ 292 if ( (ddxActual->major != ddxExpected->major) 293 || (ddxActual->minor < ddxExpected->minor) ) { 294 __driUtilMessage(format, driver_name, "DDX", 295 ddxExpected->major, ddxExpected->minor, 296 ddxActual->major, ddxActual->minor, ddxActual->patch); 297 return GL_FALSE; 298 } 299 300 /* Check that the DRM driver version is compatible */ 301 if ( (drmActual->major != drmExpected->major) 302 || (drmActual->minor < drmExpected->minor) ) { 303 __driUtilMessage(format, driver_name, "DRM", 304 drmExpected->major, drmExpected->minor, 305 drmActual->major, drmActual->minor, drmActual->patch); 306 return GL_FALSE; 307 } 308 309 return GL_TRUE; 310} 311 312 313GLboolean driClipRectToFramebuffer( const GLframebuffer *buffer, 314 GLint *x, GLint *y, 315 GLsizei *width, GLsizei *height ) 316{ 317 /* left clipping */ 318 if (*x < buffer->_Xmin) { 319 *width -= (buffer->_Xmin - *x); 320 *x = buffer->_Xmin; 321 } 322 323 /* right clipping */ 324 if (*x + *width > buffer->_Xmax) 325 *width -= (*x + *width - buffer->_Xmax - 1); 326 327 if (*width <= 0) 328 return GL_FALSE; 329 330 /* bottom clipping */ 331 if (*y < buffer->_Ymin) { 332 *height -= (buffer->_Ymin - *y); 333 *y = buffer->_Ymin; 334 } 335 336 /* top clipping */ 337 if (*y + *height > buffer->_Ymax) 338 *height -= (*y + *height - buffer->_Ymax - 1); 339 340 if (*height <= 0) 341 return GL_FALSE; 342 343 return GL_TRUE; 344} 345 346 347 348/** 349 * Creates a set of \c __GLcontextModes that a driver will expose. 350 * 351 * A set of \c __GLcontextModes will be created based on the supplied 352 * parameters. The number of modes processed will be 2 * 353 * \c num_depth_stencil_bits * \c num_db_modes. 354 * 355 * For the most part, data is just copied from \c depth_bits, \c stencil_bits, 356 * \c db_modes, and \c visType into each \c __GLcontextModes element. 357 * However, the meanings of \c fb_format and \c fb_type require further 358 * explanation. The \c fb_format specifies which color components are in 359 * each pixel and what the default order is. For example, \c GL_RGB specifies 360 * that red, green, blue are available and red is in the "most significant" 361 * position and blue is in the "least significant". The \c fb_type specifies 362 * the bit sizes of each component and the actual ordering. For example, if 363 * \c GL_UNSIGNED_SHORT_5_6_5_REV is specified with \c GL_RGB, bits [15:11] 364 * are the blue value, bits [10:5] are the green value, and bits [4:0] are 365 * the red value. 366 * 367 * One sublte issue is the combination of \c GL_RGB or \c GL_BGR and either 368 * of the \c GL_UNSIGNED_INT_8_8_8_8 modes. The resulting mask values in the 369 * \c __GLcontextModes structure is \b identical to the \c GL_RGBA or 370 * \c GL_BGRA case, except the \c alphaMask is zero. This means that, as 371 * far as this routine is concerned, \c GL_RGB with \c GL_UNSIGNED_INT_8_8_8_8 372 * still uses 32-bits. 373 * 374 * If in doubt, look at the tables used in the function. 375 * 376 * \param ptr_to_modes Pointer to a pointer to a linked list of 377 * \c __GLcontextModes. Upon completion, a pointer to 378 * the next element to be process will be stored here. 379 * If the function fails and returns \c GL_FALSE, this 380 * value will be unmodified, but some elements in the 381 * linked list may be modified. 382 * \param fb_format Format of the framebuffer. Currently only \c GL_RGB, 383 * \c GL_RGBA, \c GL_BGR, and \c GL_BGRA are supported. 384 * \param fb_type Type of the pixels in the framebuffer. Currently only 385 * \c GL_UNSIGNED_SHORT_5_6_5, 386 * \c GL_UNSIGNED_SHORT_5_6_5_REV, 387 * \c GL_UNSIGNED_INT_8_8_8_8, and 388 * \c GL_UNSIGNED_INT_8_8_8_8_REV are supported. 389 * \param depth_bits Array of depth buffer sizes to be exposed. 390 * \param stencil_bits Array of stencil buffer sizes to be exposed. 391 * \param num_depth_stencil_bits Number of entries in both \c depth_bits and 392 * \c stencil_bits. 393 * \param db_modes Array of buffer swap modes. If an element has a 394 * value of \c GLX_NONE, then it represents a 395 * single-buffered mode. Other valid values are 396 * \c GLX_SWAP_EXCHANGE_OML, \c GLX_SWAP_COPY_OML, and 397 * \c GLX_SWAP_UNDEFINED_OML. See the 398 * GLX_OML_swap_method extension spec for more details. 399 * \param num_db_modes Number of entries in \c db_modes. 400 * \param visType GLX visual type. Usually either \c GLX_TRUE_COLOR or 401 * \c GLX_DIRECT_COLOR. 402 * 403 * \returns 404 * \c GL_TRUE on success or \c GL_FALSE on failure. Currently the only 405 * cause of failure is a bad parameter (i.e., unsupported \c fb_format or 406 * \c fb_type). 407 * 408 * \todo 409 * There is currently no way to support packed RGB modes (i.e., modes with 410 * exactly 3 bytes per pixel) or floating-point modes. This could probably 411 * be done by creating some new, private enums with clever names likes 412 * \c GL_UNSIGNED_3BYTE_8_8_8, \c GL_4FLOAT_32_32_32_32, 413 * \c GL_4HALF_16_16_16_16, etc. We can cross that bridge when we come to it. 414 */ 415GLboolean 416driFillInModes( __GLcontextModes ** ptr_to_modes, 417 GLenum fb_format, GLenum fb_type, 418 const uint8_t * depth_bits, const uint8_t * stencil_bits, 419 unsigned num_depth_stencil_bits, 420 const GLenum * db_modes, unsigned num_db_modes, 421 int visType ) 422{ 423 static const uint8_t bits_table[3][4] = { 424 /* R G B A */ 425 { 5, 6, 5, 0 }, /* Any GL_UNSIGNED_SHORT_5_6_5 */ 426 { 8, 8, 8, 0 }, /* Any RGB with any GL_UNSIGNED_INT_8_8_8_8 */ 427 { 8, 8, 8, 8 } /* Any RGBA with any GL_UNSIGNED_INT_8_8_8_8 */ 428 }; 429 430 /* The following arrays are all indexed by the fb_type masked with 0x07. 431 * Given the four supported fb_type values, this results in valid array 432 * indices of 3, 4, 5, and 7. 433 */ 434 static const uint32_t masks_table_rgb[8][4] = { 435 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 436 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 437 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 438 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ 439 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ 440 { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x00000000 }, /* 8_8_8_8 */ 441 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 442 { 0x000000FF, 0x0000FF00, 0x00FF0000, 0x00000000 } /* 8_8_8_8_REV */ 443 }; 444 445 static const uint32_t masks_table_rgba[8][4] = { 446 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 447 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 448 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 449 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5 */ 450 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5_REV */ 451 { 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF }, /* 8_8_8_8 */ 452 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 453 { 0x000000FF, 0x0000FF00, 0x00FF0000, 0xFF000000 }, /* 8_8_8_8_REV */ 454 }; 455 456 static const uint32_t masks_table_bgr[8][4] = { 457 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 458 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 459 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 460 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ 461 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ 462 { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x00000000 }, /* 8_8_8_8 */ 463 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 464 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0x00000000 }, /* 8_8_8_8_REV */ 465 }; 466 467 static const uint32_t masks_table_bgra[8][4] = { 468 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 469 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 470 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 471 { 0x0000001F, 0x000007E0, 0x0000F800, 0x00000000 }, /* 5_6_5 */ 472 { 0x0000F800, 0x000007E0, 0x0000001F, 0x00000000 }, /* 5_6_5_REV */ 473 { 0x0000FF00, 0x00FF0000, 0xFF000000, 0x000000FF }, /* 8_8_8_8 */ 474 { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 475 { 0x00FF0000, 0x0000FF00, 0x000000FF, 0xFF000000 }, /* 8_8_8_8_REV */ 476 }; 477 478 static const uint8_t bytes_per_pixel[8] = { 479 0, 0, 0, 2, 2, 4, 0, 4 480 }; 481 482 const uint8_t * bits; 483 const uint32_t * masks; 484 const int index = fb_type & 0x07; 485 __GLcontextModes * modes = *ptr_to_modes; 486 unsigned i; 487 unsigned j; 488 unsigned k; 489 490 491 if ( bytes_per_pixel[ index ] == 0 ) { 492 fprintf( stderr, "[%s:%u] Framebuffer type 0x%04x has 0 bytes per pixel.\n", 493 __func__, __LINE__, fb_type ); 494 return GL_FALSE; 495 } 496 497 498 /* Valid types are GL_UNSIGNED_SHORT_5_6_5 and GL_UNSIGNED_INT_8_8_8_8 and 499 * the _REV versions. 500 * 501 * Valid formats are GL_RGBA, GL_RGB, and GL_BGRA. 502 */ 503 504 switch ( fb_format ) { 505 case GL_RGB: 506 bits = (bytes_per_pixel[ index ] == 2) 507 ? bits_table[0] : bits_table[1]; 508 masks = masks_table_rgb[ index ]; 509 break; 510 511 case GL_RGBA: 512 bits = (bytes_per_pixel[ index ] == 2) 513 ? bits_table[0] : bits_table[2]; 514 masks = masks_table_rgba[ index ]; 515 break; 516 517 case GL_BGR: 518 bits = (bytes_per_pixel[ index ] == 2) 519 ? bits_table[0] : bits_table[1]; 520 masks = masks_table_bgr[ index ]; 521 break; 522 523 case GL_BGRA: 524 bits = (bytes_per_pixel[ index ] == 2) 525 ? bits_table[0] : bits_table[2]; 526 masks = masks_table_bgra[ index ]; 527 break; 528 529 default: 530 fprintf( stderr, "[%s:%u] Framebuffer format 0x%04x is not GL_RGB, GL_RGBA, GL_BGR, or GL_BGRA.\n", 531 __func__, __LINE__, fb_format ); 532 return GL_FALSE; 533 } 534 535 536 for ( k = 0 ; k < num_depth_stencil_bits ; k++ ) { 537 for ( i = 0 ; i < num_db_modes ; i++ ) { 538 for ( j = 0 ; j < 2 ; j++ ) { 539 540 modes->redBits = bits[0]; 541 modes->greenBits = bits[1]; 542 modes->blueBits = bits[2]; 543 modes->alphaBits = bits[3]; 544 modes->redMask = masks[0]; 545 modes->greenMask = masks[1]; 546 modes->blueMask = masks[2]; 547 modes->alphaMask = masks[3]; 548 modes->rgbBits = modes->redBits + modes->greenBits 549 + modes->blueBits + modes->alphaBits; 550 551 modes->accumRedBits = 16 * j; 552 modes->accumGreenBits = 16 * j; 553 modes->accumBlueBits = 16 * j; 554 modes->accumAlphaBits = (masks[3] != 0) ? 16 * j : 0; 555 modes->visualRating = (j == 0) ? GLX_NONE : GLX_SLOW_CONFIG; 556 557 modes->stencilBits = stencil_bits[k]; 558 modes->depthBits = depth_bits[k]; 559 560 modes->visualType = visType; 561 modes->renderType = GLX_RGBA_BIT; 562 modes->drawableType = GLX_WINDOW_BIT; 563 modes->rgbMode = GL_TRUE; 564 565 if ( db_modes[i] == GLX_NONE ) { 566 modes->doubleBufferMode = GL_FALSE; 567 } 568 else { 569 modes->doubleBufferMode = GL_TRUE; 570 modes->swapMethod = db_modes[i]; 571 } 572 573 modes = modes->next; 574 } 575 } 576 } 577 578 *ptr_to_modes = modes; 579 return GL_TRUE; 580} 581