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