1 /************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 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 VMWARE 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 if (pfi->pfd.dwFlags & PFD_SWAP_COPY) 92 *pvalue = WGL_SWAP_COPY_ARB; 93 else if (pfi->pfd.dwFlags & PFD_SWAP_EXCHANGE) 94 *pvalue = WGL_SWAP_EXCHANGE_EXT; 95 else 96 *pvalue = WGL_SWAP_UNDEFINED_ARB; 97 return TRUE; 98 99 case WGL_SWAP_LAYER_BUFFERS_ARB: 100 *pvalue = FALSE; 101 return TRUE; 102 103 case WGL_NUMBER_OVERLAYS_ARB: 104 *pvalue = 0; 105 return TRUE; 106 107 case WGL_NUMBER_UNDERLAYS_ARB: 108 *pvalue = 0; 109 return TRUE; 110 111 case WGL_BIND_TO_TEXTURE_RGB_ARB: 112 /* WGL_ARB_render_texture */ 113 *pvalue = pfi->bindToTextureRGB; 114 return TRUE; 115 116 case WGL_BIND_TO_TEXTURE_RGBA_ARB: 117 /* WGL_ARB_render_texture */ 118 *pvalue = pfi->bindToTextureRGBA; 119 return TRUE; 120 } 121 122 if (iLayerPlane != 0) 123 return FALSE; 124 125 switch (attrib) { 126 case WGL_ACCELERATION_ARB: 127 *pvalue = WGL_FULL_ACCELERATION_ARB; 128 break; 129 130 case WGL_TRANSPARENT_ARB: 131 *pvalue = FALSE; 132 break; 133 134 case WGL_TRANSPARENT_RED_VALUE_ARB: 135 case WGL_TRANSPARENT_GREEN_VALUE_ARB: 136 case WGL_TRANSPARENT_BLUE_VALUE_ARB: 137 case WGL_TRANSPARENT_ALPHA_VALUE_ARB: 138 case WGL_TRANSPARENT_INDEX_VALUE_ARB: 139 break; 140 141 case WGL_SHARE_DEPTH_ARB: 142 case WGL_SHARE_STENCIL_ARB: 143 case WGL_SHARE_ACCUM_ARB: 144 *pvalue = TRUE; 145 break; 146 147 case WGL_SUPPORT_GDI_ARB: 148 *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_GDI ? TRUE : FALSE; 149 break; 150 151 case WGL_SUPPORT_OPENGL_ARB: 152 *pvalue = pfi->pfd.dwFlags & PFD_SUPPORT_OPENGL ? TRUE : FALSE; 153 break; 154 155 case WGL_DOUBLE_BUFFER_ARB: 156 *pvalue = pfi->pfd.dwFlags & PFD_DOUBLEBUFFER ? TRUE : FALSE; 157 break; 158 159 case WGL_STEREO_ARB: 160 *pvalue = pfi->pfd.dwFlags & PFD_STEREO ? TRUE : FALSE; 161 break; 162 163 case WGL_PIXEL_TYPE_ARB: 164 switch (pfi->pfd.iPixelType) { 165 case PFD_TYPE_RGBA: 166 if (util_format_is_float(pfi->stvis.color_format)) { 167 *pvalue = WGL_TYPE_RGBA_FLOAT_ARB; 168 } 169 else { 170 *pvalue = WGL_TYPE_RGBA_ARB; 171 } 172 break; 173 case PFD_TYPE_COLORINDEX: 174 *pvalue = WGL_TYPE_COLORINDEX_ARB; 175 break; 176 default: 177 return FALSE; 178 } 179 break; 180 181 case WGL_COLOR_BITS_ARB: 182 *pvalue = pfi->pfd.cColorBits; 183 break; 184 185 case WGL_RED_BITS_ARB: 186 *pvalue = pfi->pfd.cRedBits; 187 break; 188 189 case WGL_RED_SHIFT_ARB: 190 *pvalue = pfi->pfd.cRedShift; 191 break; 192 193 case WGL_GREEN_BITS_ARB: 194 *pvalue = pfi->pfd.cGreenBits; 195 break; 196 197 case WGL_GREEN_SHIFT_ARB: 198 *pvalue = pfi->pfd.cGreenShift; 199 break; 200 201 case WGL_BLUE_BITS_ARB: 202 *pvalue = pfi->pfd.cBlueBits; 203 break; 204 205 case WGL_BLUE_SHIFT_ARB: 206 *pvalue = pfi->pfd.cBlueShift; 207 break; 208 209 case WGL_ALPHA_BITS_ARB: 210 *pvalue = pfi->pfd.cAlphaBits; 211 break; 212 213 case WGL_ALPHA_SHIFT_ARB: 214 *pvalue = pfi->pfd.cAlphaShift; 215 break; 216 217 case WGL_ACCUM_BITS_ARB: 218 *pvalue = pfi->pfd.cAccumBits; 219 break; 220 221 case WGL_ACCUM_RED_BITS_ARB: 222 *pvalue = pfi->pfd.cAccumRedBits; 223 break; 224 225 case WGL_ACCUM_GREEN_BITS_ARB: 226 *pvalue = pfi->pfd.cAccumGreenBits; 227 break; 228 229 case WGL_ACCUM_BLUE_BITS_ARB: 230 *pvalue = pfi->pfd.cAccumBlueBits; 231 break; 232 233 case WGL_ACCUM_ALPHA_BITS_ARB: 234 *pvalue = pfi->pfd.cAccumAlphaBits; 235 break; 236 237 case WGL_DEPTH_BITS_ARB: 238 *pvalue = pfi->pfd.cDepthBits; 239 break; 240 241 case WGL_STENCIL_BITS_ARB: 242 *pvalue = pfi->pfd.cStencilBits; 243 break; 244 245 case WGL_AUX_BUFFERS_ARB: 246 *pvalue = pfi->pfd.cAuxBuffers; 247 break; 248 249 case WGL_SAMPLE_BUFFERS_ARB: 250 *pvalue = (pfi->stvis.samples > 1); 251 break; 252 253 case WGL_SAMPLES_ARB: 254 *pvalue = pfi->stvis.samples; 255 break; 256 257 258 /* WGL_ARB_pbuffer */ 259 260 case WGL_MAX_PBUFFER_WIDTH_ARB: 261 case WGL_MAX_PBUFFER_HEIGHT_ARB: 262 *pvalue = stw_dev->max_2d_length; 263 break; 264 265 case WGL_MAX_PBUFFER_PIXELS_ARB: 266 *pvalue = stw_dev->max_2d_length * stw_dev->max_2d_length; 267 break; 268 269 case WGL_DRAW_TO_PBUFFER_ARB: 270 *pvalue = 1; 271 break; 272 273 274 default: 275 return FALSE; 276 } 277 278 return TRUE; 279 } 280 281 struct attrib_match_info 282 { 283 int attribute; 284 int weight; 285 BOOL exact; 286 }; 287 288 static const struct attrib_match_info attrib_match[] = { 289 290 /* WGL_ARB_pixel_format */ 291 { WGL_DRAW_TO_WINDOW_ARB, 0, TRUE }, 292 { WGL_DRAW_TO_BITMAP_ARB, 0, TRUE }, 293 { WGL_ACCELERATION_ARB, 0, TRUE }, 294 { WGL_NEED_PALETTE_ARB, 0, TRUE }, 295 { WGL_NEED_SYSTEM_PALETTE_ARB, 0, TRUE }, 296 { WGL_SWAP_LAYER_BUFFERS_ARB, 0, TRUE }, 297 { WGL_SWAP_METHOD_ARB, 0, TRUE }, 298 { WGL_NUMBER_OVERLAYS_ARB, 4, FALSE }, 299 { WGL_NUMBER_UNDERLAYS_ARB, 4, FALSE }, 300 /*{ WGL_SHARE_DEPTH_ARB, 0, TRUE },*/ /* no overlays -- ignore */ 301 /*{ WGL_SHARE_STENCIL_ARB, 0, TRUE },*/ /* no overlays -- ignore */ 302 /*{ WGL_SHARE_ACCUM_ARB, 0, TRUE },*/ /* no overlays -- ignore */ 303 { WGL_SUPPORT_GDI_ARB, 0, TRUE }, 304 { WGL_SUPPORT_OPENGL_ARB, 0, TRUE }, 305 { WGL_DOUBLE_BUFFER_ARB, 0, TRUE }, 306 { WGL_STEREO_ARB, 0, TRUE }, 307 { WGL_PIXEL_TYPE_ARB, 0, TRUE }, 308 { WGL_COLOR_BITS_ARB, 1, FALSE }, 309 { WGL_RED_BITS_ARB, 1, FALSE }, 310 { WGL_GREEN_BITS_ARB, 1, FALSE }, 311 { WGL_BLUE_BITS_ARB, 1, FALSE }, 312 { WGL_ALPHA_BITS_ARB, 1, FALSE }, 313 { WGL_ACCUM_BITS_ARB, 1, FALSE }, 314 { WGL_ACCUM_RED_BITS_ARB, 1, FALSE }, 315 { WGL_ACCUM_GREEN_BITS_ARB, 1, FALSE }, 316 { WGL_ACCUM_BLUE_BITS_ARB, 1, FALSE }, 317 { WGL_ACCUM_ALPHA_BITS_ARB, 1, FALSE }, 318 { WGL_DEPTH_BITS_ARB, 1, FALSE }, 319 { WGL_STENCIL_BITS_ARB, 1, FALSE }, 320 { WGL_AUX_BUFFERS_ARB, 2, FALSE }, 321 322 /* WGL_ARB_multisample */ 323 { WGL_SAMPLE_BUFFERS_ARB, 2, FALSE }, 324 { WGL_SAMPLES_ARB, 2, FALSE }, 325 326 /* WGL_ARB_render_texture */ 327 { WGL_BIND_TO_TEXTURE_RGB_ARB, 0, FALSE }, 328 { WGL_BIND_TO_TEXTURE_RGBA_ARB, 0, FALSE }, 329 }; 330 331 struct stw_pixelformat_score 332 { 333 int points; 334 uint index; 335 }; 336 337 static BOOL 338 score_pixelformats( 339 struct stw_pixelformat_score *scores, 340 uint count, 341 int attribute, 342 int expected_value ) 343 { 344 uint i; 345 const struct attrib_match_info *ami = NULL; 346 uint index; 347 348 /* Find out if a given attribute should be considered for score calculation. 349 */ 350 for (i = 0; i < sizeof( attrib_match ) / sizeof( attrib_match[0] ); i++) { 351 if (attrib_match[i].attribute == attribute) { 352 ami = &attrib_match[i]; 353 break; 354 } 355 } 356 if (ami == NULL) 357 return TRUE; 358 359 /* Iterate all pixelformats, query the requested attribute and calculate 360 * score points. 361 */ 362 for (index = 0; index < count; index++) { 363 int actual_value; 364 365 if (!stw_query_attrib( index + 1, 0, attribute, &actual_value )) 366 return FALSE; 367 368 if (ami->exact) { 369 /* For an exact match criteria, if the actual and expected values differ, 370 * the score is set to 0 points, effectively removing the pixelformat 371 * from a list of matching pixelformats. 372 */ 373 if (actual_value != expected_value) 374 scores[index].points = 0; 375 } 376 else { 377 /* For a minimum match criteria, if the actual value is smaller than the expected 378 * value, the pixelformat is rejected (score set to 0). However, if the actual 379 * value is bigger, the pixelformat is given a penalty to favour pixelformats that 380 * more closely match the expected values. 381 */ 382 if (actual_value < expected_value) 383 scores[index].points = 0; 384 else if (actual_value > expected_value) 385 scores[index].points -= (actual_value - expected_value) * ami->weight; 386 } 387 } 388 389 return TRUE; 390 } 391 392 WINGDIAPI BOOL APIENTRY 393 wglChoosePixelFormatARB( 394 HDC hdc, 395 const int *piAttribIList, 396 const FLOAT *pfAttribFList, 397 UINT nMaxFormats, 398 int *piFormats, 399 UINT *nNumFormats ) 400 { 401 uint count; 402 struct stw_pixelformat_score *scores; 403 uint i; 404 405 *nNumFormats = 0; 406 407 /* Allocate and initialize pixelformat score table -- better matches 408 * have higher scores. Start with a high score and take out penalty 409 * points for a mismatch when the match does not have to be exact. 410 * Set a score to 0 if there is a mismatch for an exact match criteria. 411 */ 412 count = stw_pixelformat_get_extended_count(); 413 scores = (struct stw_pixelformat_score *) MALLOC( count * sizeof( struct stw_pixelformat_score ) ); 414 if (scores == NULL) 415 return FALSE; 416 for (i = 0; i < count; i++) { 417 scores[i].points = 0x7fffffff; 418 scores[i].index = i; 419 } 420 421 /* Given the attribute list calculate a score for each pixelformat. 422 */ 423 if (piAttribIList != NULL) { 424 while (*piAttribIList != 0) { 425 if (!score_pixelformats( scores, count, piAttribIList[0], piAttribIList[1] )) { 426 FREE( scores ); 427 return FALSE; 428 } 429 piAttribIList += 2; 430 } 431 } 432 if (pfAttribFList != NULL) { 433 while (*pfAttribFList != 0) { 434 if (!score_pixelformats( scores, count, (int) pfAttribFList[0], (int) pfAttribFList[1] )) { 435 FREE( scores ); 436 return FALSE; 437 } 438 pfAttribFList += 2; 439 } 440 } 441 442 /* Bubble-sort the resulting scores. Pixelformats with higher scores go first. 443 * TODO: Find out if there are any patent issues with it. 444 */ 445 if (count > 1) { 446 uint n = count; 447 boolean swapped; 448 449 do { 450 swapped = FALSE; 451 for (i = 1; i < n; i++) { 452 if (scores[i - 1].points < scores[i].points) { 453 struct stw_pixelformat_score score = scores[i - 1]; 454 455 scores[i - 1] = scores[i]; 456 scores[i] = score; 457 swapped = TRUE; 458 } 459 } 460 n--; 461 } 462 while (swapped); 463 } 464 465 /* Return a list of pixelformats that are the best match. 466 * Reject pixelformats with non-positive scores. 467 */ 468 for (i = 0; i < count; i++) { 469 if (scores[i].points > 0) { 470 piFormats[*nNumFormats] = scores[i].index + 1; 471 (*nNumFormats)++; 472 if (*nNumFormats >= nMaxFormats) { 473 break; 474 } 475 } 476 } 477 478 FREE( scores ); 479 return TRUE; 480 } 481 482 WINGDIAPI BOOL APIENTRY 483 wglGetPixelFormatAttribfvARB( 484 HDC hdc, 485 int iPixelFormat, 486 int iLayerPlane, 487 UINT nAttributes, 488 const int *piAttributes, 489 FLOAT *pfValues ) 490 { 491 UINT i; 492 493 (void) hdc; 494 495 for (i = 0; i < nAttributes; i++) { 496 int value; 497 498 if (!stw_query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &value )) 499 return FALSE; 500 pfValues[i] = (FLOAT) value; 501 } 502 503 return TRUE; 504 } 505 506 WINGDIAPI BOOL APIENTRY 507 wglGetPixelFormatAttribivARB( 508 HDC hdc, 509 int iPixelFormat, 510 int iLayerPlane, 511 UINT nAttributes, 512 const int *piAttributes, 513 int *piValues ) 514 { 515 UINT i; 516 517 (void) hdc; 518 519 for (i = 0; i < nAttributes; i++) { 520 if (!stw_query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &piValues[i] )) 521 return FALSE; 522 } 523 524 return TRUE; 525 } 526