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 
51 static boolean
stw_query_attrib(HDC hdc,int iPixelFormat,int iLayerPlane,int attrib,int * pvalue)52 stw_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 
277 struct attrib_match_info
278 {
279    int attribute;
280    int weight;
281    BOOL exact;
282 };
283 
284 static 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 
326 struct stw_pixelformat_score
327 {
328    int points;
329    uint index;
330 };
331 
332 
333 static BOOL
score_pixelformats(HDC hdc,struct stw_pixelformat_score * scores,uint count,int attribute,int expected_value)334 score_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 
391 WINGDIAPI BOOL APIENTRY
wglChoosePixelFormatARB(HDC hdc,const int * piAttribIList,const FLOAT * pfAttribFList,UINT nMaxFormats,int * piFormats,UINT * nNumFormats)392 wglChoosePixelFormatARB(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 
481 WINGDIAPI BOOL APIENTRY
wglGetPixelFormatAttribfvARB(HDC hdc,int iPixelFormat,int iLayerPlane,UINT nAttributes,const int * piAttributes,FLOAT * pfValues)482 wglGetPixelFormatAttribfvARB(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 
501 WINGDIAPI BOOL APIENTRY
wglGetPixelFormatAttribivARB(HDC hdc,int iPixelFormat,int iLayerPlane,UINT nAttributes,const int * piAttributes,int * piValues)502 wglGetPixelFormatAttribivARB(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