stw_pixelformat.c revision 5706d7fcaf3c3238c652593d5669b9f793c6cdce
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
44struct 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
61struct 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
74static const struct stw_pf_color_info
75stw_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
91static const struct stw_pf_depth_info
92stw_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_Z24S8_UNORM, {24, 8} },
100   { PIPE_FORMAT_S8Z24_UNORM, {24, 8} }
101};
102
103
104static const boolean
105stw_pf_doublebuffer[] = {
106   FALSE,
107   TRUE,
108};
109
110
111const unsigned
112stw_pf_multisample[] = {
113   0,
114   4
115};
116
117
118static void
119stw_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
201void
202stw_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_TEXTURE_USAGE_RENDER_TARGET |
222                                         PIPE_TEXTURE_USAGE_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_TEXTURE_USAGE_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
246uint
247stw_pixelformat_get_count( void )
248{
249   return stw_dev->pixelformat_count;
250}
251
252uint
253stw_pixelformat_get_extended_count( void )
254{
255   return stw_dev->pixelformat_extended_count;
256}
257
258const struct stw_pixelformat_info *
259stw_pixelformat_get_info( uint index )
260{
261   assert( index < stw_dev->pixelformat_extended_count );
262
263   return &stw_dev->pixelformats[index];
264}
265
266
267void
268stw_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.iPixelType == PFD_TYPE_RGBA) ? GL_TRUE : GL_FALSE,
275      (pfi->pfd.dwFlags & PFD_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE,
276      (pfi->pfd.dwFlags & PFD_STEREO) ? GL_TRUE : GL_FALSE,
277      pfi->pfd.cRedBits,
278      pfi->pfd.cGreenBits,
279      pfi->pfd.cBlueBits,
280      pfi->pfd.cAlphaBits,
281      (pfi->pfd.iPixelType == PFD_TYPE_COLORINDEX) ? pfi->pfd.cColorBits : 0,
282      pfi->pfd.cDepthBits,
283      pfi->pfd.cStencilBits,
284      pfi->pfd.cAccumRedBits,
285      pfi->pfd.cAccumGreenBits,
286      pfi->pfd.cAccumBlueBits,
287      pfi->pfd.cAccumAlphaBits,
288      pfi->numSamples );
289}
290
291
292LONG APIENTRY
293DrvDescribePixelFormat(
294   HDC hdc,
295   INT iPixelFormat,
296   ULONG cjpfd,
297   PIXELFORMATDESCRIPTOR *ppfd )
298{
299   uint count;
300   uint index;
301   const struct stw_pixelformat_info *pfi;
302
303   (void) hdc;
304
305   if (!stw_dev)
306      return 0;
307
308   count = stw_pixelformat_get_extended_count();
309   index = (uint) iPixelFormat - 1;
310
311   if (ppfd == NULL)
312      return count;
313   if (index >= count || cjpfd != sizeof( PIXELFORMATDESCRIPTOR ))
314      return 0;
315
316   pfi = stw_pixelformat_get_info( index );
317
318   memcpy(ppfd, &pfi->pfd, sizeof( PIXELFORMATDESCRIPTOR ));
319
320   return count;
321}
322
323BOOL APIENTRY
324DrvDescribeLayerPlane(
325   HDC hdc,
326   INT iPixelFormat,
327   INT iLayerPlane,
328   UINT nBytes,
329   LPLAYERPLANEDESCRIPTOR plpd )
330{
331   assert(0);
332   return FALSE;
333}
334
335int APIENTRY
336DrvGetLayerPaletteEntries(
337   HDC hdc,
338   INT iLayerPlane,
339   INT iStart,
340   INT cEntries,
341   COLORREF *pcr )
342{
343   assert(0);
344   return 0;
345}
346
347int APIENTRY
348DrvSetLayerPaletteEntries(
349   HDC hdc,
350   INT iLayerPlane,
351   INT iStart,
352   INT cEntries,
353   CONST COLORREF *pcr )
354{
355   assert(0);
356   return 0;
357}
358
359BOOL APIENTRY
360DrvRealizeLayerPalette(
361   HDC hdc,
362   INT iLayerPlane,
363   BOOL bRealize )
364{
365   assert(0);
366   return FALSE;
367}
368
369/* Only used by the wgl code, but have it here to avoid exporting the
370 * pixelformat.h functionality.
371 */
372int stw_pixelformat_choose( HDC hdc,
373                            CONST PIXELFORMATDESCRIPTOR *ppfd )
374{
375   uint count;
376   uint index;
377   uint bestindex;
378   uint bestdelta;
379
380   (void) hdc;
381
382   count = stw_pixelformat_get_count();
383   bestindex = count;
384   bestdelta = ~0U;
385
386   for (index = 0; index < count; index++) {
387      uint delta = 0;
388      const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info( index );
389
390      if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
391          !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) !=
392          !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
393         continue;
394
395      /* FIXME: Take in account individual channel bits */
396      if (ppfd->cColorBits != pfi->pfd.cColorBits)
397         delta += 8;
398
399      if (ppfd->cDepthBits != pfi->pfd.cDepthBits)
400         delta += 4;
401
402      if (ppfd->cStencilBits != pfi->pfd.cStencilBits)
403         delta += 2;
404
405      if (ppfd->cAlphaBits != pfi->pfd.cAlphaBits)
406         delta++;
407
408      if (delta < bestdelta) {
409         bestindex = index;
410         bestdelta = delta;
411         if (bestdelta == 0)
412            break;
413      }
414   }
415
416   if (bestindex == count)
417      return 0;
418
419   return bestindex + 1;
420}
421