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