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(int iPixelFormat,int iLayerPlane,int attrib,int * pvalue)52 stw_query_attrib(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();
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(struct stw_pixelformat_score * scores,uint count,int attribute,int expected_value)334 score_pixelformats(struct stw_pixelformat_score *scores,
335                    uint count,
336                    int attribute,
337                    int expected_value)
338 {
339    uint i;
340    const struct attrib_match_info *ami = NULL;
341    uint index;
342 
343    /* Find out if a given attribute should be considered for score calculation.
344     */
345    for (i = 0; i < ARRAY_SIZE(attrib_match); i++) {
346       if (attrib_match[i].attribute == attribute) {
347          ami = &attrib_match[i];
348          break;
349       }
350    }
351    if (ami == NULL)
352       return TRUE;
353 
354    /* Iterate all pixelformats, query the requested attribute and calculate
355     * score points.
356     */
357    for (index = 0; index < count; index++) {
358       int actual_value;
359 
360       if (!stw_query_attrib(index + 1, 0, attribute, &actual_value))
361          return FALSE;
362 
363       if (ami->exact) {
364          /* For an exact match criteria, if the actual and expected values
365           * differ, the score is set to 0 points, effectively removing the
366           * pixelformat from a list of matching pixelformats.
367           */
368          if (actual_value != expected_value)
369             scores[index].points = 0;
370       }
371       else {
372          /* For a minimum match criteria, if the actual value is smaller than
373           * the expected value, the pixelformat is rejected (score set to
374           * 0). However, if the actual value is bigger, the pixelformat is
375           * given a penalty to favour pixelformats that more closely match the
376           * expected values.
377           */
378          if (actual_value < expected_value)
379             scores[index].points = 0;
380          else if (actual_value > expected_value)
381             scores[index].points -= (actual_value - expected_value)
382                * ami->weight;
383       }
384    }
385 
386    return TRUE;
387 }
388 
389 
390 WINGDIAPI BOOL APIENTRY
wglChoosePixelFormatARB(HDC hdc,const int * piAttribIList,const FLOAT * pfAttribFList,UINT nMaxFormats,int * piFormats,UINT * nNumFormats)391 wglChoosePixelFormatARB(HDC hdc, const int *piAttribIList,
392                         const FLOAT *pfAttribFList, UINT nMaxFormats,
393                         int *piFormats, UINT *nNumFormats)
394 {
395    uint count;
396    struct stw_pixelformat_score *scores;
397    uint i;
398 
399    *nNumFormats = 0;
400 
401    /* Allocate and initialize pixelformat score table -- better matches
402     * have higher scores. Start with a high score and take out penalty
403     * points for a mismatch when the match does not have to be exact.
404     * Set a score to 0 if there is a mismatch for an exact match criteria.
405     */
406    count = stw_pixelformat_get_extended_count();
407    scores = (struct stw_pixelformat_score *)
408       MALLOC(count * sizeof(struct stw_pixelformat_score));
409    if (scores == NULL)
410       return FALSE;
411    for (i = 0; i < count; i++) {
412       scores[i].points = 0x7fffffff;
413       scores[i].index = i;
414    }
415 
416    /* Given the attribute list calculate a score for each pixelformat.
417     */
418    if (piAttribIList != NULL) {
419       while (*piAttribIList != 0) {
420          if (!score_pixelformats(scores, count, piAttribIList[0],
421                                  piAttribIList[1])) {
422             FREE(scores);
423             return FALSE;
424          }
425          piAttribIList += 2;
426       }
427    }
428    if (pfAttribFList != NULL) {
429       while (*pfAttribFList != 0) {
430          if (!score_pixelformats(scores, count, (int) pfAttribFList[0],
431                                  (int) pfAttribFList[1])) {
432             FREE(scores);
433             return FALSE;
434          }
435          pfAttribFList += 2;
436       }
437    }
438 
439    /* Bubble-sort the resulting scores. Pixelformats with higher scores go
440     * first.  TODO: Find out if there are any patent issues with it.
441     */
442    if (count > 1) {
443       uint n = count;
444       boolean swapped;
445 
446       do {
447          swapped = FALSE;
448          for (i = 1; i < n; i++) {
449             if (scores[i - 1].points < scores[i].points) {
450                struct stw_pixelformat_score score = scores[i - 1];
451 
452                scores[i - 1] = scores[i];
453                scores[i] = score;
454                swapped = TRUE;
455             }
456          }
457          n--;
458       }
459       while (swapped);
460    }
461 
462    /* Return a list of pixelformats that are the best match.
463     * Reject pixelformats with non-positive scores.
464     */
465    for (i = 0; i < count; i++) {
466       if (scores[i].points > 0) {
467          piFormats[*nNumFormats] = scores[i].index + 1;
468          (*nNumFormats)++;
469          if (*nNumFormats >= nMaxFormats) {
470             break;
471          }
472       }
473    }
474 
475    FREE(scores);
476    return TRUE;
477 }
478 
479 
480 WINGDIAPI BOOL APIENTRY
wglGetPixelFormatAttribfvARB(HDC hdc,int iPixelFormat,int iLayerPlane,UINT nAttributes,const int * piAttributes,FLOAT * pfValues)481 wglGetPixelFormatAttribfvARB(HDC hdc, int iPixelFormat, int iLayerPlane,
482                              UINT nAttributes, const int *piAttributes,
483                              FLOAT *pfValues)
484 {
485    UINT i;
486 
487    (void) hdc;
488 
489    for (i = 0; i < nAttributes; i++) {
490       int value = 0;
491 
492       if (!stw_query_attrib(iPixelFormat, iLayerPlane,
493                              piAttributes[i], &value))
494          return FALSE;
495       pfValues[i] = (FLOAT) value;
496    }
497 
498    return TRUE;
499 }
500 
501 
502 WINGDIAPI BOOL APIENTRY
wglGetPixelFormatAttribivARB(HDC hdc,int iPixelFormat,int iLayerPlane,UINT nAttributes,const int * piAttributes,int * piValues)503 wglGetPixelFormatAttribivARB(HDC hdc, int iPixelFormat, int iLayerPlane,
504                              UINT nAttributes, const int *piAttributes,
505                              int *piValues)
506 {
507    UINT i;
508 
509    (void) hdc;
510 
511    for (i = 0; i < nAttributes; i++) {
512       if (!stw_query_attrib(iPixelFormat, iLayerPlane,
513                             piAttributes[i], &piValues[i]))
514          return FALSE;
515    }
516 
517    return TRUE;
518 }
519