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