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
stw_query_attrib(int iPixelFormat,int iLayerPlane,int attrib,int * pvalue)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
score_pixelformats(struct stw_pixelformat_score * scores,uint count,int attribute,int expected_value)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
wglChoosePixelFormatARB(HDC hdc,const int * piAttribIList,const FLOAT * pfAttribFList,UINT nMaxFormats,int * piFormats,UINT * nNumFormats)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
wglGetPixelFormatAttribfvARB(HDC hdc,int iPixelFormat,int iLayerPlane,UINT nAttributes,const int * piAttributes,FLOAT * pfValues)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
wglGetPixelFormatAttribivARB(HDC hdc,int iPixelFormat,int iLayerPlane,UINT nAttributes,const int * piAttributes,int * piValues)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