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
51static boolean
52stw_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
277struct attrib_match_info
278{
279   int attribute;
280   int weight;
281   BOOL exact;
282};
283
284static 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
326struct stw_pixelformat_score
327{
328   int points;
329   uint index;
330};
331
332
333static BOOL
334score_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
391WINGDIAPI BOOL APIENTRY
392wglChoosePixelFormatARB(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
481WINGDIAPI BOOL APIENTRY
482wglGetPixelFormatAttribfvARB(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
501WINGDIAPI BOOL APIENTRY
502wglGetPixelFormatAttribivARB(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