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