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/format/u_format.h" 46#include "util/u_memory.h" 47#include "stw_device.h" 48#include "stw_pixelformat.h" 49 50 51static boolean 52stw_query_attrib(HDC hdc, 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(hdc); 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 277struct attrib_match_info 278{ 279 int attribute; 280 int weight; 281 BOOL exact; 282}; 283 284static 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 326struct stw_pixelformat_score 327{ 328 int points; 329 uint index; 330}; 331 332 333static BOOL 334score_pixelformats(HDC hdc, 335 struct stw_pixelformat_score *scores, 336 uint count, 337 int attribute, 338 int expected_value) 339{ 340 uint i; 341 const struct attrib_match_info *ami = NULL; 342 uint index; 343 344 /* Find out if a given attribute should be considered for score calculation. 345 */ 346 for (i = 0; i < ARRAY_SIZE(attrib_match); i++) { 347 if (attrib_match[i].attribute == attribute) { 348 ami = &attrib_match[i]; 349 break; 350 } 351 } 352 if (ami == NULL) 353 return TRUE; 354 355 /* Iterate all pixelformats, query the requested attribute and calculate 356 * score points. 357 */ 358 for (index = 0; index < count; index++) { 359 int actual_value; 360 361 if (!stw_query_attrib(hdc, index + 1, 0, attribute, &actual_value)) 362 return FALSE; 363 364 if (ami->exact) { 365 /* For an exact match criteria, if the actual and expected values 366 * differ, the score is set to 0 points, effectively removing the 367 * pixelformat from a list of matching pixelformats. 368 */ 369 if (actual_value != expected_value) 370 scores[index].points = 0; 371 } 372 else { 373 /* For a minimum match criteria, if the actual value is smaller than 374 * the expected value, the pixelformat is rejected (score set to 375 * 0). However, if the actual value is bigger, the pixelformat is 376 * given a penalty to favour pixelformats that more closely match the 377 * expected values. 378 */ 379 if (actual_value < expected_value) 380 scores[index].points = 0; 381 else if (actual_value > expected_value) 382 scores[index].points -= (actual_value - expected_value) 383 * ami->weight; 384 } 385 } 386 387 return TRUE; 388} 389 390 391WINGDIAPI BOOL APIENTRY 392wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList, 393 const FLOAT *pfAttribFList, UINT nMaxFormats, 394 int *piFormats, UINT *nNumFormats) 395{ 396 uint count; 397 struct stw_pixelformat_score *scores; 398 uint i; 399 400 *nNumFormats = 0; 401 402 /* Allocate and initialize pixelformat score table -- better matches 403 * have higher scores. Start with a high score and take out penalty 404 * points for a mismatch when the match does not have to be exact. 405 * Set a score to 0 if there is a mismatch for an exact match criteria. 406 */ 407 count = stw_pixelformat_get_extended_count(hdc); 408 scores = (struct stw_pixelformat_score *) 409 MALLOC(count * sizeof(struct stw_pixelformat_score)); 410 if (scores == NULL) 411 return FALSE; 412 for (i = 0; i < count; i++) { 413 scores[i].points = 0x7fffffff; 414 scores[i].index = i; 415 } 416 417 /* Given the attribute list calculate a score for each pixelformat. 418 */ 419 if (piAttribIList != NULL) { 420 while (*piAttribIList != 0) { 421 if (!score_pixelformats(hdc, scores, count, piAttribIList[0], 422 piAttribIList[1])) { 423 FREE(scores); 424 return FALSE; 425 } 426 piAttribIList += 2; 427 } 428 } 429 if (pfAttribFList != NULL) { 430 while (*pfAttribFList != 0) { 431 if (!score_pixelformats(hdc, scores, count, (int) pfAttribFList[0], 432 (int) pfAttribFList[1])) { 433 FREE(scores); 434 return FALSE; 435 } 436 pfAttribFList += 2; 437 } 438 } 439 440 /* Bubble-sort the resulting scores. Pixelformats with higher scores go 441 * first. TODO: Find out if there are any patent issues with it. 442 */ 443 if (count > 1) { 444 uint n = count; 445 boolean swapped; 446 447 do { 448 swapped = FALSE; 449 for (i = 1; i < n; i++) { 450 if (scores[i - 1].points < scores[i].points) { 451 struct stw_pixelformat_score score = scores[i - 1]; 452 453 scores[i - 1] = scores[i]; 454 scores[i] = score; 455 swapped = TRUE; 456 } 457 } 458 n--; 459 } 460 while (swapped); 461 } 462 463 /* Return a list of pixelformats that are the best match. 464 * Reject pixelformats with non-positive scores. 465 */ 466 for (i = 0; i < count; i++) { 467 if (scores[i].points > 0) { 468 piFormats[*nNumFormats] = scores[i].index + 1; 469 (*nNumFormats)++; 470 if (*nNumFormats >= nMaxFormats) { 471 break; 472 } 473 } 474 } 475 476 FREE(scores); 477 return TRUE; 478} 479 480 481WINGDIAPI BOOL APIENTRY 482wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane, 483 UINT nAttributes, const int *piAttributes, 484 FLOAT *pfValues) 485{ 486 UINT i; 487 488 for (i = 0; i < nAttributes; i++) { 489 int value = 0; 490 491 if (!stw_query_attrib(hdc, iPixelFormat, iLayerPlane, 492 piAttributes[i], &value)) 493 return FALSE; 494 pfValues[i] = (FLOAT) value; 495 } 496 497 return TRUE; 498} 499 500 501WINGDIAPI BOOL APIENTRY 502wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane, 503 UINT nAttributes, const int *piAttributes, 504 int *piValues) 505{ 506 UINT i; 507 508 for (i = 0; i < nAttributes; i++) { 509 if (!stw_query_attrib(hdc, iPixelFormat, iLayerPlane, 510 piAttributes[i], &piValues[i])) 511 return FALSE; 512 } 513 514 return TRUE; 515} 516