1 /************************************************************************** 2 * 3 * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28 /** 29 * @file 30 * 31 * WGL_ARB_pixel_format extension implementation. 32 * 33 * @sa http://www.opengl.org/registry/specs/ARB/wgl_pixel_format.txt 34 */ 35 36 37 #include <windows.h> 38 39 #define WGL_WGLEXT_PROTOTYPES 40 41 #include <GL/gl.h> 42 #include <GL/wglext.h> 43 44 #include "pipe/p_compiler.h" 45 #include "util/u_format.h" 46 #include "util/u_memory.h" 47 #include "stw_device.h" 48 #include "stw_pixelformat.h" 49 50 51 static boolean 52 stw_query_attrib( 53 int iPixelFormat, 54 int iLayerPlane, 55 int attrib, 56 int *pvalue ) 57 { 58 uint count; 59 const struct stw_pixelformat_info *pfi; 60 61 count = stw_pixelformat_get_extended_count(); 62 63 if (attrib == WGL_NUMBER_PIXEL_FORMATS_ARB) { 64 *pvalue = (int) count; 65 return TRUE; 66 } 67 68 pfi = stw_pixelformat_get_info( iPixelFormat ); 69 if (!pfi) { 70 return FALSE; 71 } 72 73 switch (attrib) { 74 case WGL_DRAW_TO_WINDOW_ARB: 75 *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_WINDOW ? TRUE : FALSE; 76 return TRUE; 77 78 case WGL_DRAW_TO_BITMAP_ARB: 79 *pvalue = pfi->pfd.dwFlags & PFD_DRAW_TO_BITMAP ? TRUE : FALSE; 80 return TRUE; 81 82 case WGL_NEED_PALETTE_ARB: 83 *pvalue = pfi->pfd.dwFlags & PFD_NEED_PALETTE ? TRUE : FALSE; 84 return TRUE; 85 86 case WGL_NEED_SYSTEM_PALETTE_ARB: 87 *pvalue = pfi->pfd.dwFlags & PFD_NEED_SYSTEM_PALETTE ? TRUE : FALSE; 88 return TRUE; 89 90 case WGL_SWAP_METHOD_ARB: 91 *pvalue = pfi->pfd.dwFlags & PFD_SWAP_COPY ? WGL_SWAP_COPY_ARB : WGL_SWAP_UNDEFINED_ARB; 92 return TRUE; 93 94 case WGL_SWAP_LAYER_BUFFERS_ARB: 95 *pvalue = FALSE; 96 return TRUE; 97 98 case WGL_NUMBER_OVERLAYS_ARB: 99 *pvalue = 0; 100 return TRUE; 101 102 case WGL_NUMBER_UNDERLAYS_ARB: 103 *pvalue = 0; 104 return TRUE; 105 } 106 107 if (iLayerPlane != 0) 108 return FALSE; 109 110 switch (attrib) { 111 case WGL_ACCELERATION_ARB: 112 *pvalue = WGL_FULL_ACCELERATION_ARB; 113 break; 114 115 case WGL_TRANSPARENT_ARB: 116 *pvalue = FALSE; 117 break; 118 119 case WGL_TRANSPARENT_RED_VALUE_ARB: 120 case WGL_TRANSPARENT_GREEN_VALUE_ARB: 121 case WGL_TRANSPARENT_BLUE_VALUE_ARB: 122 case WGL_TRANSPARENT_ALPHA_VALUE_ARB: 123 case WGL_TRANSPARENT_INDEX_VALUE_ARB: 124 break; 125 126 case WGL_SHARE_DEPTH_ARB: 127 case WGL_SHARE_STENCIL_ARB: 128 case WGL_SHARE_ACCUM_ARB: 129 *pvalue = TRUE; 130 break; 131 132 case WGL_SUPPORT_GDI_ARB: 133 *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_GDI ? TRUE : FALSE; 134 break; 135 136 case WGL_SUPPORT_OPENGL_ARB: 137 *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_OPENGL ? TRUE : FALSE; 138 break; 139 140 case WGL_DOUBLE_BUFFER_ARB: 141 *pvalue = pfi->pfd.dwFlags & PFD_DOUBLEBUFFER ? TRUE : FALSE; 142 break; 143 144 case WGL_STEREO_ARB: 145 *pvalue = pfi->pfd.dwFlags & PFD_STEREO ? TRUE : FALSE; 146 break; 147 148 case WGL_PIXEL_TYPE_ARB: 149 switch (pfi->pfd.iPixelType) { 150 case PFD_TYPE_RGBA: 151 if (util_format_is_float(pfi->stvis.color_format)) { 152 *pvalue = WGL_TYPE_RGBA_FLOAT_ARB; 153 } 154 else { 155 *pvalue = WGL_TYPE_RGBA_ARB; 156 } 157 break; 158 case PFD_TYPE_COLORINDEX: 159 *pvalue = WGL_TYPE_COLORINDEX_ARB; 160 break; 161 default: 162 return FALSE; 163 } 164 break; 165 166 case WGL_COLOR_BITS_ARB: 167 *pvalue = pfi->pfd.cColorBits; 168 break; 169 170 case WGL_RED_BITS_ARB: 171 *pvalue = pfi->pfd.cRedBits; 172 break; 173 174 case WGL_RED_SHIFT_ARB: 175 *pvalue = pfi->pfd.cRedShift; 176 break; 177 178 case WGL_GREEN_BITS_ARB: 179 *pvalue = pfi->pfd.cGreenBits; 180 break; 181 182 case WGL_GREEN_SHIFT_ARB: 183 *pvalue = pfi->pfd.cGreenShift; 184 break; 185 186 case WGL_BLUE_BITS_ARB: 187 *pvalue = pfi->pfd.cBlueBits; 188 break; 189 190 case WGL_BLUE_SHIFT_ARB: 191 *pvalue = pfi->pfd.cBlueShift; 192 break; 193 194 case WGL_ALPHA_BITS_ARB: 195 *pvalue = pfi->pfd.cAlphaBits; 196 break; 197 198 case WGL_ALPHA_SHIFT_ARB: 199 *pvalue = pfi->pfd.cAlphaShift; 200 break; 201 202 case WGL_ACCUM_BITS_ARB: 203 *pvalue = pfi->pfd.cAccumBits; 204 break; 205 206 case WGL_ACCUM_RED_BITS_ARB: 207 *pvalue = pfi->pfd.cAccumRedBits; 208 break; 209 210 case WGL_ACCUM_GREEN_BITS_ARB: 211 *pvalue = pfi->pfd.cAccumGreenBits; 212 break; 213 214 case WGL_ACCUM_BLUE_BITS_ARB: 215 *pvalue = pfi->pfd.cAccumBlueBits; 216 break; 217 218 case WGL_ACCUM_ALPHA_BITS_ARB: 219 *pvalue = pfi->pfd.cAccumAlphaBits; 220 break; 221 222 case WGL_DEPTH_BITS_ARB: 223 *pvalue = pfi->pfd.cDepthBits; 224 break; 225 226 case WGL_STENCIL_BITS_ARB: 227 *pvalue = pfi->pfd.cStencilBits; 228 break; 229 230 case WGL_AUX_BUFFERS_ARB: 231 *pvalue = pfi->pfd.cAuxBuffers; 232 break; 233 234 case WGL_SAMPLE_BUFFERS_ARB: 235 *pvalue = 1; 236 break; 237 238 case WGL_SAMPLES_ARB: 239 *pvalue = pfi->stvis.samples; 240 break; 241 242 243 /* WGL_ARB_pbuffer */ 244 245 case WGL_MAX_PBUFFER_WIDTH_ARB: 246 case WGL_MAX_PBUFFER_HEIGHT_ARB: 247 *pvalue = stw_dev->max_2d_length; 248 break; 249 250 case WGL_MAX_PBUFFER_PIXELS_ARB: 251 *pvalue = stw_dev->max_2d_length * stw_dev->max_2d_length; 252 break; 253 254 case WGL_DRAW_TO_PBUFFER_ARB: 255 *pvalue = 1; 256 break; 257 258 259 default: 260 return FALSE; 261 } 262 263 return TRUE; 264 } 265 266 struct attrib_match_info 267 { 268 int attribute; 269 int weight; 270 BOOL exact; 271 }; 272 273 static const struct attrib_match_info attrib_match[] = { 274 275 /* WGL_ARB_pixel_format */ 276 { WGL_DRAW_TO_WINDOW_ARB, 0, TRUE }, 277 { WGL_DRAW_TO_BITMAP_ARB, 0, TRUE }, 278 { WGL_ACCELERATION_ARB, 0, TRUE }, 279 { WGL_NEED_PALETTE_ARB, 0, TRUE }, 280 { WGL_NEED_SYSTEM_PALETTE_ARB, 0, TRUE }, 281 { WGL_SWAP_LAYER_BUFFERS_ARB, 0, TRUE }, 282 { WGL_SWAP_METHOD_ARB, 0, TRUE }, 283 { WGL_NUMBER_OVERLAYS_ARB, 4, FALSE }, 284 { WGL_NUMBER_UNDERLAYS_ARB, 4, FALSE }, 285 /*{ WGL_SHARE_DEPTH_ARB, 0, TRUE },*/ /* no overlays -- ignore */ 286 /*{ WGL_SHARE_STENCIL_ARB, 0, TRUE },*/ /* no overlays -- ignore */ 287 /*{ WGL_SHARE_ACCUM_ARB, 0, TRUE },*/ /* no overlays -- ignore */ 288 { WGL_SUPPORT_GDI_ARB, 0, TRUE }, 289 { WGL_SUPPORT_OPENGL_ARB, 0, TRUE }, 290 { WGL_DOUBLE_BUFFER_ARB, 0, TRUE }, 291 { WGL_STEREO_ARB, 0, TRUE }, 292 { WGL_PIXEL_TYPE_ARB, 0, TRUE }, 293 { WGL_COLOR_BITS_ARB, 1, FALSE }, 294 { WGL_RED_BITS_ARB, 1, FALSE }, 295 { WGL_GREEN_BITS_ARB, 1, FALSE }, 296 { WGL_BLUE_BITS_ARB, 1, FALSE }, 297 { WGL_ALPHA_BITS_ARB, 1, FALSE }, 298 { WGL_ACCUM_BITS_ARB, 1, FALSE }, 299 { WGL_ACCUM_RED_BITS_ARB, 1, FALSE }, 300 { WGL_ACCUM_GREEN_BITS_ARB, 1, FALSE }, 301 { WGL_ACCUM_BLUE_BITS_ARB, 1, FALSE }, 302 { WGL_ACCUM_ALPHA_BITS_ARB, 1, FALSE }, 303 { WGL_DEPTH_BITS_ARB, 1, FALSE }, 304 { WGL_STENCIL_BITS_ARB, 1, FALSE }, 305 { WGL_AUX_BUFFERS_ARB, 2, FALSE }, 306 307 /* WGL_ARB_multisample */ 308 { WGL_SAMPLE_BUFFERS_ARB, 2, FALSE }, 309 { WGL_SAMPLES_ARB, 2, FALSE } 310 }; 311 312 struct stw_pixelformat_score 313 { 314 int points; 315 uint index; 316 }; 317 318 static BOOL 319 score_pixelformats( 320 struct stw_pixelformat_score *scores, 321 uint count, 322 int attribute, 323 int expected_value ) 324 { 325 uint i; 326 const struct attrib_match_info *ami = NULL; 327 uint index; 328 329 /* Find out if a given attribute should be considered for score calculation. 330 */ 331 for (i = 0; i < sizeof( attrib_match ) / sizeof( attrib_match[0] ); i++) { 332 if (attrib_match[i].attribute == attribute) { 333 ami = &attrib_match[i]; 334 break; 335 } 336 } 337 if (ami == NULL) 338 return TRUE; 339 340 /* Iterate all pixelformats, query the requested attribute and calculate 341 * score points. 342 */ 343 for (index = 0; index < count; index++) { 344 int actual_value; 345 346 if (!stw_query_attrib( index + 1, 0, attribute, &actual_value )) 347 return FALSE; 348 349 if (ami->exact) { 350 /* For an exact match criteria, if the actual and expected values differ, 351 * the score is set to 0 points, effectively removing the pixelformat 352 * from a list of matching pixelformats. 353 */ 354 if (actual_value != expected_value) 355 scores[index].points = 0; 356 } 357 else { 358 /* For a minimum match criteria, if the actual value is smaller than the expected 359 * value, the pixelformat is rejected (score set to 0). However, if the actual 360 * value is bigger, the pixelformat is given a penalty to favour pixelformats that 361 * more closely match the expected values. 362 */ 363 if (actual_value < expected_value) 364 scores[index].points = 0; 365 else if (actual_value > expected_value) 366 scores[index].points -= (actual_value - expected_value) * ami->weight; 367 } 368 } 369 370 return TRUE; 371 } 372 373 WINGDIAPI BOOL APIENTRY 374 wglChoosePixelFormatARB( 375 HDC hdc, 376 const int *piAttribIList, 377 const FLOAT *pfAttribFList, 378 UINT nMaxFormats, 379 int *piFormats, 380 UINT *nNumFormats ) 381 { 382 uint count; 383 struct stw_pixelformat_score *scores; 384 uint i; 385 386 *nNumFormats = 0; 387 388 /* Allocate and initialize pixelformat score table -- better matches 389 * have higher scores. Start with a high score and take out penalty 390 * points for a mismatch when the match does not have to be exact. 391 * Set a score to 0 if there is a mismatch for an exact match criteria. 392 */ 393 count = stw_pixelformat_get_extended_count(); 394 scores = (struct stw_pixelformat_score *) MALLOC( count * sizeof( struct stw_pixelformat_score ) ); 395 if (scores == NULL) 396 return FALSE; 397 for (i = 0; i < count; i++) { 398 scores[i].points = 0x7fffffff; 399 scores[i].index = i; 400 } 401 402 /* Given the attribute list calculate a score for each pixelformat. 403 */ 404 if (piAttribIList != NULL) { 405 while (*piAttribIList != 0) { 406 if (!score_pixelformats( scores, count, piAttribIList[0], piAttribIList[1] )) { 407 FREE( scores ); 408 return FALSE; 409 } 410 piAttribIList += 2; 411 } 412 } 413 if (pfAttribFList != NULL) { 414 while (*pfAttribFList != 0) { 415 if (!score_pixelformats( scores, count, (int) pfAttribFList[0], (int) pfAttribFList[1] )) { 416 FREE( scores ); 417 return FALSE; 418 } 419 pfAttribFList += 2; 420 } 421 } 422 423 /* Bubble-sort the resulting scores. Pixelformats with higher scores go first. 424 * TODO: Find out if there are any patent issues with it. 425 */ 426 if (count > 1) { 427 uint n = count; 428 boolean swapped; 429 430 do { 431 swapped = FALSE; 432 for (i = 1; i < n; i++) { 433 if (scores[i - 1].points < scores[i].points) { 434 struct stw_pixelformat_score score = scores[i - 1]; 435 436 scores[i - 1] = scores[i]; 437 scores[i] = score; 438 swapped = TRUE; 439 } 440 } 441 n--; 442 } 443 while (swapped); 444 } 445 446 /* Return a list of pixelformats that are the best match. 447 * Reject pixelformats with non-positive scores. 448 */ 449 for (i = 0; i < count; i++) { 450 if (scores[i].points > 0) { 451 if (*nNumFormats < nMaxFormats) 452 piFormats[*nNumFormats] = scores[i].index + 1; 453 (*nNumFormats)++; 454 } 455 } 456 457 FREE( scores ); 458 return TRUE; 459 } 460 461 WINGDIAPI BOOL APIENTRY 462 wglGetPixelFormatAttribfvARB( 463 HDC hdc, 464 int iPixelFormat, 465 int iLayerPlane, 466 UINT nAttributes, 467 const int *piAttributes, 468 FLOAT *pfValues ) 469 { 470 UINT i; 471 472 (void) hdc; 473 474 for (i = 0; i < nAttributes; i++) { 475 int value; 476 477 if (!stw_query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &value )) 478 return FALSE; 479 pfValues[i] = (FLOAT) value; 480 } 481 482 return TRUE; 483 } 484 485 WINGDIAPI BOOL APIENTRY 486 wglGetPixelFormatAttribivARB( 487 HDC hdc, 488 int iPixelFormat, 489 int iLayerPlane, 490 UINT nAttributes, 491 const int *piAttributes, 492 int *piValues ) 493 { 494 UINT i; 495 496 (void) hdc; 497 498 for (i = 0; i < nAttributes; i++) { 499 if (!stw_query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &piValues[i] )) 500 return FALSE; 501 } 502 503 return TRUE; 504 } 505