Merge remote branch 'origin/7.8'
[mesa.git] / src / gallium / state_trackers / wgl / stw_ext_pixelformat.c
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_memory.h"
46 #include "stw_pixelformat.h"
47
48
49 static boolean
50 stw_query_attrib(
51 int iPixelFormat,
52 int iLayerPlane,
53 int attrib,
54 int *pvalue )
55 {
56 uint count;
57 uint index;
58 const struct stw_pixelformat_info *pfi;
59
60 count = stw_pixelformat_get_extended_count();
61
62 if (attrib == WGL_NUMBER_PIXEL_FORMATS_ARB) {
63 *pvalue = (int) count;
64 return TRUE;
65 }
66
67 index = (uint) iPixelFormat - 1;
68 if (index >= count)
69 return FALSE;
70
71 pfi = stw_pixelformat_get_info( index );
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 *pvalue = WGL_TYPE_RGBA_ARB;
152 break;
153 case PFD_TYPE_COLORINDEX:
154 *pvalue = WGL_TYPE_COLORINDEX_ARB;
155 break;
156 default:
157 return FALSE;
158 }
159 break;
160
161 case WGL_COLOR_BITS_ARB:
162 *pvalue = pfi->pfd.cColorBits;
163 break;
164
165 case WGL_RED_BITS_ARB:
166 *pvalue = pfi->pfd.cRedBits;
167 break;
168
169 case WGL_RED_SHIFT_ARB:
170 *pvalue = pfi->pfd.cRedShift;
171 break;
172
173 case WGL_GREEN_BITS_ARB:
174 *pvalue = pfi->pfd.cGreenBits;
175 break;
176
177 case WGL_GREEN_SHIFT_ARB:
178 *pvalue = pfi->pfd.cGreenShift;
179 break;
180
181 case WGL_BLUE_BITS_ARB:
182 *pvalue = pfi->pfd.cBlueBits;
183 break;
184
185 case WGL_BLUE_SHIFT_ARB:
186 *pvalue = pfi->pfd.cBlueShift;
187 break;
188
189 case WGL_ALPHA_BITS_ARB:
190 *pvalue = pfi->pfd.cAlphaBits;
191 break;
192
193 case WGL_ALPHA_SHIFT_ARB:
194 *pvalue = pfi->pfd.cAlphaShift;
195 break;
196
197 case WGL_ACCUM_BITS_ARB:
198 *pvalue = pfi->pfd.cAccumBits;
199 break;
200
201 case WGL_ACCUM_RED_BITS_ARB:
202 *pvalue = pfi->pfd.cAccumRedBits;
203 break;
204
205 case WGL_ACCUM_GREEN_BITS_ARB:
206 *pvalue = pfi->pfd.cAccumGreenBits;
207 break;
208
209 case WGL_ACCUM_BLUE_BITS_ARB:
210 *pvalue = pfi->pfd.cAccumBlueBits;
211 break;
212
213 case WGL_ACCUM_ALPHA_BITS_ARB:
214 *pvalue = pfi->pfd.cAccumAlphaBits;
215 break;
216
217 case WGL_DEPTH_BITS_ARB:
218 *pvalue = pfi->pfd.cDepthBits;
219 break;
220
221 case WGL_STENCIL_BITS_ARB:
222 *pvalue = pfi->pfd.cStencilBits;
223 break;
224
225 case WGL_AUX_BUFFERS_ARB:
226 *pvalue = pfi->pfd.cAuxBuffers;
227 break;
228
229 case WGL_SAMPLE_BUFFERS_ARB:
230 *pvalue = 1;
231 break;
232
233 case WGL_SAMPLES_ARB:
234 *pvalue = pfi->stvis.samples;
235 break;
236
237 default:
238 return FALSE;
239 }
240
241 return TRUE;
242 }
243
244 struct attrib_match_info
245 {
246 int attribute;
247 int weight;
248 BOOL exact;
249 };
250
251 static const struct attrib_match_info attrib_match[] = {
252
253 /* WGL_ARB_pixel_format */
254 { WGL_DRAW_TO_WINDOW_ARB, 0, TRUE },
255 { WGL_DRAW_TO_BITMAP_ARB, 0, TRUE },
256 { WGL_ACCELERATION_ARB, 0, TRUE },
257 { WGL_NEED_PALETTE_ARB, 0, TRUE },
258 { WGL_NEED_SYSTEM_PALETTE_ARB, 0, TRUE },
259 { WGL_SWAP_LAYER_BUFFERS_ARB, 0, TRUE },
260 { WGL_SWAP_METHOD_ARB, 0, TRUE },
261 { WGL_NUMBER_OVERLAYS_ARB, 4, FALSE },
262 { WGL_NUMBER_UNDERLAYS_ARB, 4, FALSE },
263 /*{ WGL_SHARE_DEPTH_ARB, 0, TRUE },*/ /* no overlays -- ignore */
264 /*{ WGL_SHARE_STENCIL_ARB, 0, TRUE },*/ /* no overlays -- ignore */
265 /*{ WGL_SHARE_ACCUM_ARB, 0, TRUE },*/ /* no overlays -- ignore */
266 { WGL_SUPPORT_GDI_ARB, 0, TRUE },
267 { WGL_SUPPORT_OPENGL_ARB, 0, TRUE },
268 { WGL_DOUBLE_BUFFER_ARB, 0, TRUE },
269 { WGL_STEREO_ARB, 0, TRUE },
270 { WGL_PIXEL_TYPE_ARB, 0, TRUE },
271 { WGL_COLOR_BITS_ARB, 1, FALSE },
272 { WGL_RED_BITS_ARB, 1, FALSE },
273 { WGL_GREEN_BITS_ARB, 1, FALSE },
274 { WGL_BLUE_BITS_ARB, 1, FALSE },
275 { WGL_ALPHA_BITS_ARB, 1, FALSE },
276 { WGL_ACCUM_BITS_ARB, 1, FALSE },
277 { WGL_ACCUM_RED_BITS_ARB, 1, FALSE },
278 { WGL_ACCUM_GREEN_BITS_ARB, 1, FALSE },
279 { WGL_ACCUM_BLUE_BITS_ARB, 1, FALSE },
280 { WGL_ACCUM_ALPHA_BITS_ARB, 1, FALSE },
281 { WGL_DEPTH_BITS_ARB, 1, FALSE },
282 { WGL_STENCIL_BITS_ARB, 1, FALSE },
283 { WGL_AUX_BUFFERS_ARB, 2, FALSE },
284
285 /* WGL_ARB_multisample */
286 { WGL_SAMPLE_BUFFERS_ARB, 2, FALSE },
287 { WGL_SAMPLES_ARB, 2, FALSE }
288 };
289
290 struct stw_pixelformat_score
291 {
292 int points;
293 uint index;
294 };
295
296 static BOOL
297 score_pixelformats(
298 struct stw_pixelformat_score *scores,
299 uint count,
300 int attribute,
301 int expected_value )
302 {
303 uint i;
304 const struct attrib_match_info *ami = NULL;
305 uint index;
306
307 /* Find out if a given attribute should be considered for score calculation.
308 */
309 for (i = 0; i < sizeof( attrib_match ) / sizeof( attrib_match[0] ); i++) {
310 if (attrib_match[i].attribute == attribute) {
311 ami = &attrib_match[i];
312 break;
313 }
314 }
315 if (ami == NULL)
316 return TRUE;
317
318 /* Iterate all pixelformats, query the requested attribute and calculate
319 * score points.
320 */
321 for (index = 0; index < count; index++) {
322 int actual_value;
323
324 if (!stw_query_attrib( index + 1, 0, attribute, &actual_value ))
325 return FALSE;
326
327 if (ami->exact) {
328 /* For an exact match criteria, if the actual and expected values differ,
329 * the score is set to 0 points, effectively removing the pixelformat
330 * from a list of matching pixelformats.
331 */
332 if (actual_value != expected_value)
333 scores[index].points = 0;
334 }
335 else {
336 /* For a minimum match criteria, if the actual value is smaller than the expected
337 * value, the pixelformat is rejected (score set to 0). However, if the actual
338 * value is bigger, the pixelformat is given a penalty to favour pixelformats that
339 * more closely match the expected values.
340 */
341 if (actual_value < expected_value)
342 scores[index].points = 0;
343 else if (actual_value > expected_value)
344 scores[index].points -= (actual_value - expected_value) * ami->weight;
345 }
346 }
347
348 return TRUE;
349 }
350
351 WINGDIAPI BOOL APIENTRY
352 wglChoosePixelFormatARB(
353 HDC hdc,
354 const int *piAttribIList,
355 const FLOAT *pfAttribFList,
356 UINT nMaxFormats,
357 int *piFormats,
358 UINT *nNumFormats )
359 {
360 uint count;
361 struct stw_pixelformat_score *scores;
362 uint i;
363
364 *nNumFormats = 0;
365
366 /* Allocate and initialize pixelformat score table -- better matches
367 * have higher scores. Start with a high score and take out penalty
368 * points for a mismatch when the match does not have to be exact.
369 * Set a score to 0 if there is a mismatch for an exact match criteria.
370 */
371 count = stw_pixelformat_get_extended_count();
372 scores = (struct stw_pixelformat_score *) MALLOC( count * sizeof( struct stw_pixelformat_score ) );
373 if (scores == NULL)
374 return FALSE;
375 for (i = 0; i < count; i++) {
376 scores[i].points = 0x7fffffff;
377 scores[i].index = i;
378 }
379
380 /* Given the attribute list calculate a score for each pixelformat.
381 */
382 if (piAttribIList != NULL) {
383 while (*piAttribIList != 0) {
384 if (!score_pixelformats( scores, count, piAttribIList[0], piAttribIList[1] )) {
385 FREE( scores );
386 return FALSE;
387 }
388 piAttribIList += 2;
389 }
390 }
391 if (pfAttribFList != NULL) {
392 while (*pfAttribFList != 0) {
393 if (!score_pixelformats( scores, count, (int) pfAttribFList[0], (int) pfAttribFList[1] )) {
394 FREE( scores );
395 return FALSE;
396 }
397 pfAttribFList += 2;
398 }
399 }
400
401 /* Bubble-sort the resulting scores. Pixelformats with higher scores go first.
402 * TODO: Find out if there are any patent issues with it.
403 */
404 if (count > 1) {
405 uint n = count;
406 boolean swapped;
407
408 do {
409 swapped = FALSE;
410 for (i = 1; i < n; i++) {
411 if (scores[i - 1].points < scores[i].points) {
412 struct stw_pixelformat_score score = scores[i - 1];
413
414 scores[i - 1] = scores[i];
415 scores[i] = score;
416 swapped = TRUE;
417 }
418 }
419 n--;
420 }
421 while (swapped);
422 }
423
424 /* Return a list of pixelformats that are the best match.
425 * Reject pixelformats with non-positive scores.
426 */
427 for (i = 0; i < count; i++) {
428 if (scores[i].points > 0) {
429 if (*nNumFormats < nMaxFormats)
430 piFormats[*nNumFormats] = scores[i].index + 1;
431 (*nNumFormats)++;
432 }
433 }
434
435 FREE( scores );
436 return TRUE;
437 }
438
439 WINGDIAPI BOOL APIENTRY
440 wglGetPixelFormatAttribfvARB(
441 HDC hdc,
442 int iPixelFormat,
443 int iLayerPlane,
444 UINT nAttributes,
445 const int *piAttributes,
446 FLOAT *pfValues )
447 {
448 UINT i;
449
450 (void) hdc;
451
452 for (i = 0; i < nAttributes; i++) {
453 int value;
454
455 if (!stw_query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &value ))
456 return FALSE;
457 pfValues[i] = (FLOAT) value;
458 }
459
460 return TRUE;
461 }
462
463 WINGDIAPI BOOL APIENTRY
464 wglGetPixelFormatAttribivARB(
465 HDC hdc,
466 int iPixelFormat,
467 int iLayerPlane,
468 UINT nAttributes,
469 const int *piAttributes,
470 int *piValues )
471 {
472 UINT i;
473
474 (void) hdc;
475
476 for (i = 0; i < nAttributes; i++) {
477 if (!stw_query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &piValues[i] ))
478 return FALSE;
479 }
480
481 return TRUE;
482 }