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