stw_pixelformat.c revision 59e6e765426a5877db7446e1e34bb7edd3dc1f74
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
42struct 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
59struct 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
72static const struct stw_pf_color_info
73stw_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
89static const struct stw_pf_depth_info
90stw_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
102static const boolean
103stw_pf_doublebuffer[] = {
104   FALSE,
105   TRUE,
106};
107
108
109const unsigned
110stw_pf_multisample[] = {
111   0,
112   4
113};
114
115
116static void
117stw_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
207void
208stw_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, 0))
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, 0))
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
252uint
253stw_pixelformat_get_count( void )
254{
255   return stw_dev->pixelformat_count;
256}
257
258uint
259stw_pixelformat_get_extended_count( void )
260{
261   return stw_dev->pixelformat_extended_count;
262}
263
264const struct stw_pixelformat_info *
265stw_pixelformat_get_info( uint index )
266{
267   assert( index < stw_dev->pixelformat_extended_count );
268
269   return &stw_dev->pixelformats[index];
270}
271
272
273LONG APIENTRY
274DrvDescribePixelFormat(
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
304BOOL APIENTRY
305DrvDescribeLayerPlane(
306   HDC hdc,
307   INT iPixelFormat,
308   INT iLayerPlane,
309   UINT nBytes,
310   LPLAYERPLANEDESCRIPTOR plpd )
311{
312   assert(0);
313   return FALSE;
314}
315
316int APIENTRY
317DrvGetLayerPaletteEntries(
318   HDC hdc,
319   INT iLayerPlane,
320   INT iStart,
321   INT cEntries,
322   COLORREF *pcr )
323{
324   assert(0);
325   return 0;
326}
327
328int APIENTRY
329DrvSetLayerPaletteEntries(
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
340BOOL APIENTRY
341DrvRealizeLayerPalette(
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 */
353int 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}
402