Squashed commit of the following:
[profile/ivi/mesa.git] / src / gallium / state_trackers / wgl / stw_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 #include "main/mtypes.h"
29 #include "main/context.h"
30
31 #include "pipe/p_format.h"
32 #include "pipe/p_defines.h"
33 #include "pipe/p_screen.h"
34
35 #include "util/u_format.h"
36 #include "util/u_debug.h"
37
38 #include "stw_icd.h"
39 #include "stw_device.h"
40 #include "stw_pixelformat.h"
41 #include "stw_tls.h"
42
43
44 struct stw_pf_color_info
45 {
46    enum pipe_format format;
47    struct {
48       unsigned char red;
49       unsigned char green;
50       unsigned char blue;
51       unsigned char alpha;
52    } bits;
53    struct {
54       unsigned char red;
55       unsigned char green;
56       unsigned char blue;
57       unsigned char alpha;
58    } shift;
59 };
60
61 struct stw_pf_depth_info
62 {
63    enum pipe_format format;
64    struct {
65       unsigned char depth;
66       unsigned char stencil;
67    } bits;
68 };
69
70
71 /* NOTE: order matters, since in otherwise equal circumstances the first
72  * format listed will get chosen */
73
74 static const struct stw_pf_color_info
75 stw_pf_color[] = {
76    /* no-alpha */
77    { PIPE_FORMAT_B8G8R8X8_UNORM,    { 8,  8,  8,  0}, {16,  8,  0,  0} },
78    { PIPE_FORMAT_X8R8G8B8_UNORM,    { 8,  8,  8,  0}, { 8, 16, 24,  0} },
79    { PIPE_FORMAT_B5G6R5_UNORM,      { 5,  6,  5,  0}, {11,  5,  0,  0} },
80    /* alpha */
81    { PIPE_FORMAT_B8G8R8A8_UNORM,    { 8,  8,  8,  8}, {16,  8,  0, 24} },
82    { PIPE_FORMAT_A8R8G8B8_UNORM,    { 8,  8,  8,  8}, { 8, 16, 24,  0} },
83 #if 0
84    { PIPE_FORMAT_R10G10B10A2_UNORM, {10, 10, 10,  2}, { 0, 10, 20, 30} },
85 #endif
86    { PIPE_FORMAT_B5G5R5A1_UNORM,    { 5,  5,  5,  1}, {10,  5,  0, 15} },
87    { PIPE_FORMAT_B4G4R4A4_UNORM,    { 4,  4,  4,  4}, {16,  4,  0, 12} }
88 };
89
90
91 static const struct stw_pf_depth_info 
92 stw_pf_depth_stencil[] = {
93    /* pure depth */
94    { PIPE_FORMAT_Z32_UNORM,   {32, 0} },
95    { PIPE_FORMAT_X8Z24_UNORM, {24, 0} },
96    { PIPE_FORMAT_Z24X8_UNORM, {24, 0} },
97    { PIPE_FORMAT_Z16_UNORM,   {16, 0} },
98    /* combined depth-stencil */
99    { PIPE_FORMAT_Z24_UNORM_S8_USCALED, {24, 8} },
100    { PIPE_FORMAT_S8_USCALED_Z24_UNORM, {24, 8} }
101 };
102
103
104 static const boolean 
105 stw_pf_doublebuffer[] = {
106    FALSE,
107    TRUE,
108 };
109
110
111 const unsigned 
112 stw_pf_multisample[] = {
113    0,
114    4
115 };
116
117
118 static void
119 stw_pixelformat_add(
120    struct stw_device *stw_dev,
121    const struct stw_pf_color_info *color,
122    const struct stw_pf_depth_info *depth,
123    unsigned accum,
124    boolean doublebuffer,
125    unsigned samples )
126 {
127    boolean extended = FALSE;
128    struct stw_pixelformat_info *pfi;
129    
130    assert(stw_dev->pixelformat_extended_count < STW_MAX_PIXELFORMATS);
131    if(stw_dev->pixelformat_extended_count >= STW_MAX_PIXELFORMATS)
132       return;
133
134    assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 0) == color->bits.red);
135    assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 1) == color->bits.green);
136    assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 2) == color->bits.blue);
137    assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 3) == color->bits.alpha);
138    assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 0) == depth->bits.depth);
139    assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 1) == depth->bits.stencil);
140    
141    pfi = &stw_dev->pixelformats[stw_dev->pixelformat_extended_count];
142    
143    memset(pfi, 0, sizeof *pfi);
144    
145    pfi->color_format = color->format;
146    pfi->depth_stencil_format = depth->format;
147    
148    pfi->pfd.nSize = sizeof pfi->pfd;
149    pfi->pfd.nVersion = 1;
150
151    pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL;
152    
153    /* TODO: also support non-native pixel formats */
154    pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW;
155
156    /* See http://www.opengl.org/pipeline/article/vol003_7/ */
157    pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION;
158
159    if (doublebuffer)
160       pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_COPY;
161    
162    pfi->pfd.iPixelType = PFD_TYPE_RGBA;
163
164    pfi->pfd.cColorBits = color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha;
165    pfi->pfd.cRedBits = color->bits.red;
166    pfi->pfd.cRedShift = color->shift.red;
167    pfi->pfd.cGreenBits = color->bits.green;
168    pfi->pfd.cGreenShift = color->shift.green;
169    pfi->pfd.cBlueBits = color->bits.blue;
170    pfi->pfd.cBlueShift = color->shift.blue;
171    pfi->pfd.cAlphaBits = color->bits.alpha;
172    pfi->pfd.cAlphaShift = color->shift.alpha;
173    pfi->pfd.cAccumBits = 4*accum;
174    pfi->pfd.cAccumRedBits = accum;
175    pfi->pfd.cAccumGreenBits = accum;
176    pfi->pfd.cAccumBlueBits = accum;
177    pfi->pfd.cAccumAlphaBits = accum;
178    pfi->pfd.cDepthBits = depth->bits.depth;
179    pfi->pfd.cStencilBits = depth->bits.stencil;
180    pfi->pfd.cAuxBuffers = 0;
181    pfi->pfd.iLayerType = 0;
182    pfi->pfd.bReserved = 0;
183    pfi->pfd.dwLayerMask = 0;
184    pfi->pfd.dwVisibleMask = 0;
185    pfi->pfd.dwDamageMask = 0;
186
187    if(samples) {
188       pfi->numSampleBuffers = 1;
189       pfi->numSamples = samples;
190       extended = TRUE;
191    }
192    
193    ++stw_dev->pixelformat_extended_count;
194    
195    if(!extended) {
196       ++stw_dev->pixelformat_count;
197       assert(stw_dev->pixelformat_count == stw_dev->pixelformat_extended_count);
198    }
199 }
200
201 void
202 stw_pixelformat_init( void )
203 {
204    struct pipe_screen *screen = stw_dev->screen;
205    unsigned i, j, k, l;
206    
207    assert( !stw_dev->pixelformat_count );
208    assert( !stw_dev->pixelformat_extended_count );
209
210    for(i = 0; i < Elements(stw_pf_multisample); ++i) {
211       unsigned samples = stw_pf_multisample[i];
212       
213       /* FIXME: re-enabled MSAA when we can query it */
214       if(samples)
215          continue;
216
217       for(j = 0; j < Elements(stw_pf_color); ++j) {
218          const struct stw_pf_color_info *color = &stw_pf_color[j];
219          
220          if(!screen->is_format_supported(screen, color->format, PIPE_TEXTURE_2D, 
221                                          PIPE_BIND_RENDER_TARGET |
222                                          PIPE_BIND_DISPLAY_TARGET, 0))
223             continue;
224          
225          for(k = 0; k < Elements(stw_pf_doublebuffer); ++k) {
226             unsigned doublebuffer = stw_pf_doublebuffer[k];
227             
228             for(l = 0; l < Elements(stw_pf_depth_stencil); ++l) {
229                const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[l];
230                
231                if(!screen->is_format_supported(screen, depth->format, PIPE_TEXTURE_2D, 
232                                                PIPE_BIND_DEPTH_STENCIL, 0))
233                   continue;
234
235                stw_pixelformat_add( stw_dev, color, depth,  0, doublebuffer, samples );
236                stw_pixelformat_add( stw_dev, color, depth, 16, doublebuffer, samples );
237             }
238          }
239       }
240    }
241    
242    assert( stw_dev->pixelformat_count <= stw_dev->pixelformat_extended_count );
243    assert( stw_dev->pixelformat_extended_count <= STW_MAX_PIXELFORMATS );
244 }
245
246 uint
247 stw_pixelformat_get_count( void )
248 {
249    return stw_dev->pixelformat_count;
250 }
251
252 uint
253 stw_pixelformat_get_extended_count( void )
254 {
255    return stw_dev->pixelformat_extended_count;
256 }
257
258 const struct stw_pixelformat_info *
259 stw_pixelformat_get_info( uint index )
260 {
261    assert( index < stw_dev->pixelformat_extended_count );
262
263    return &stw_dev->pixelformats[index];
264 }
265
266
267 void
268 stw_pixelformat_visual(GLvisual *visual, 
269                        const struct stw_pixelformat_info *pfi )
270 {
271    memset(visual, 0, sizeof *visual);
272    _mesa_initialize_visual(
273       visual,
274       (pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE,
275       (pfi->pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE,
276       pfi->pfd.cRedBits,
277       pfi->pfd.cGreenBits,
278       pfi->pfd.cBlueBits,
279       pfi->pfd.cAlphaBits,
280       pfi->pfd.cDepthBits,
281       pfi->pfd.cStencilBits,
282       pfi->pfd.cAccumRedBits,
283       pfi->pfd.cAccumGreenBits,
284       pfi->pfd.cAccumBlueBits,
285       pfi->pfd.cAccumAlphaBits,
286       pfi->numSamples );
287 }
288
289
290 LONG APIENTRY
291 DrvDescribePixelFormat(
292    HDC hdc,
293    INT iPixelFormat,
294    ULONG cjpfd,
295    PIXELFORMATDESCRIPTOR *ppfd )
296 {
297    uint count;
298    uint index;
299    const struct stw_pixelformat_info *pfi;
300
301    (void) hdc;
302
303    if (!stw_dev)
304       return 0;
305
306    count = stw_pixelformat_get_extended_count();
307    index = (uint) iPixelFormat - 1;
308
309    if (ppfd == NULL)
310       return count;
311    if (index >= count || cjpfd != sizeof( PIXELFORMATDESCRIPTOR ))
312       return 0;
313
314    pfi = stw_pixelformat_get_info( index );
315    
316    memcpy(ppfd, &pfi->pfd, sizeof( PIXELFORMATDESCRIPTOR ));
317
318    return count;
319 }
320
321 BOOL APIENTRY
322 DrvDescribeLayerPlane(
323    HDC hdc,
324    INT iPixelFormat,
325    INT iLayerPlane,
326    UINT nBytes,
327    LPLAYERPLANEDESCRIPTOR plpd )
328 {
329    assert(0);
330    return FALSE;
331 }
332
333 int APIENTRY
334 DrvGetLayerPaletteEntries(
335    HDC hdc,
336    INT iLayerPlane,
337    INT iStart,
338    INT cEntries,
339    COLORREF *pcr )
340 {
341    assert(0);
342    return 0;
343 }
344
345 int APIENTRY
346 DrvSetLayerPaletteEntries(
347    HDC hdc,
348    INT iLayerPlane,
349    INT iStart,
350    INT cEntries,
351    CONST COLORREF *pcr )
352 {
353    assert(0);
354    return 0;
355 }
356
357 BOOL APIENTRY
358 DrvRealizeLayerPalette(
359    HDC hdc,
360    INT iLayerPlane,
361    BOOL bRealize )
362 {
363    assert(0);
364    return FALSE;
365 }
366
367 /* Only used by the wgl code, but have it here to avoid exporting the
368  * pixelformat.h functionality.
369  */
370 int stw_pixelformat_choose( HDC hdc,
371                             CONST PIXELFORMATDESCRIPTOR *ppfd )
372 {
373    uint count;
374    uint index;
375    uint bestindex;
376    uint bestdelta;
377
378    (void) hdc;
379
380    count = stw_pixelformat_get_count();
381    bestindex = count;
382    bestdelta = ~0U;
383
384    for (index = 0; index < count; index++) {
385       uint delta = 0;
386       const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info( index );
387
388       if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
389           !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) !=
390           !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
391          continue;
392
393       /* FIXME: Take in account individual channel bits */
394       if (ppfd->cColorBits != pfi->pfd.cColorBits)
395          delta += 8;
396
397       if (ppfd->cDepthBits != pfi->pfd.cDepthBits)
398          delta += 4;
399
400       if (ppfd->cStencilBits != pfi->pfd.cStencilBits)
401          delta += 2;
402
403       if (ppfd->cAlphaBits != pfi->pfd.cAlphaBits)
404          delta++;
405
406       if (delta < bestdelta) {
407          bestindex = index;
408          bestdelta = delta;
409          if (bestdelta == 0)
410             break;
411       }
412    }
413
414    if (bestindex == count)
415       return 0;
416
417    return bestindex + 1;
418 }