stw_pixelformat.c revision 9646762261d976d34bee8c8b1dcda9656cec655c
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
88static const struct stw_pf_color_info
89stw_pf_color_extended[] = {
90    { PIPE_FORMAT_R32G32B32A32_FLOAT, { 32,  32, 32,  32}, { 0,  32, 64, 96} }
91};
92
93static const struct stw_pf_depth_info
94stw_pf_depth_stencil[] = {
95   /* pure depth */
96   { PIPE_FORMAT_Z32_UNORM,   {32, 0} },
97   { PIPE_FORMAT_X8Z24_UNORM, {24, 0} },
98   { PIPE_FORMAT_Z24X8_UNORM, {24, 0} },
99   { PIPE_FORMAT_Z16_UNORM,   {16, 0} },
100   /* combined depth-stencil */
101   { PIPE_FORMAT_Z24_UNORM_S8_UINT, {24, 8} },
102   { PIPE_FORMAT_S8_UINT_Z24_UNORM, {24, 8} }
103};
104
105
106static const boolean
107stw_pf_doublebuffer[] = {
108   FALSE,
109   TRUE,
110};
111
112
113const unsigned
114stw_pf_multisample[] = {
115   0,
116   4
117};
118
119
120static void
121stw_pixelformat_add(
122   struct stw_device *stw_dev,
123   boolean extended,
124   const struct stw_pf_color_info *color,
125   const struct stw_pf_depth_info *depth,
126   unsigned accum,
127   boolean doublebuffer,
128   unsigned samples )
129{
130   struct stw_pixelformat_info *pfi;
131
132   assert(stw_dev->pixelformat_extended_count < STW_MAX_PIXELFORMATS);
133   if(stw_dev->pixelformat_extended_count >= STW_MAX_PIXELFORMATS)
134      return;
135
136   assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 0) == color->bits.red);
137   assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 1) == color->bits.green);
138   assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 2) == color->bits.blue);
139   assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 3) == color->bits.alpha);
140   assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 0) == depth->bits.depth);
141   assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 1) == depth->bits.stencil);
142
143   pfi = &stw_dev->pixelformats[stw_dev->pixelformat_extended_count];
144
145   memset(pfi, 0, sizeof *pfi);
146
147   pfi->pfd.nSize = sizeof pfi->pfd;
148   pfi->pfd.nVersion = 1;
149
150   pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL;
151
152   /* TODO: also support non-native pixel formats */
153   if (!extended) {
154      pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW;
155   }
156
157   /* See http://www.opengl.org/pipeline/article/vol003_7/ */
158   pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION;
159
160   if (doublebuffer)
161      pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_COPY;
162
163   pfi->pfd.iPixelType = PFD_TYPE_RGBA;
164
165   pfi->pfd.cColorBits = color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha;
166   pfi->pfd.cRedBits = color->bits.red;
167   pfi->pfd.cRedShift = color->shift.red;
168   pfi->pfd.cGreenBits = color->bits.green;
169   pfi->pfd.cGreenShift = color->shift.green;
170   pfi->pfd.cBlueBits = color->bits.blue;
171   pfi->pfd.cBlueShift = color->shift.blue;
172   pfi->pfd.cAlphaBits = color->bits.alpha;
173   pfi->pfd.cAlphaShift = color->shift.alpha;
174   pfi->pfd.cAccumBits = 4*accum;
175   pfi->pfd.cAccumRedBits = accum;
176   pfi->pfd.cAccumGreenBits = accum;
177   pfi->pfd.cAccumBlueBits = accum;
178   pfi->pfd.cAccumAlphaBits = accum;
179   pfi->pfd.cDepthBits = depth->bits.depth;
180   pfi->pfd.cStencilBits = depth->bits.stencil;
181   pfi->pfd.cAuxBuffers = 0;
182   pfi->pfd.iLayerType = 0;
183   pfi->pfd.bReserved = 0;
184   pfi->pfd.dwLayerMask = 0;
185   pfi->pfd.dwVisibleMask = 0;
186   pfi->pfd.dwDamageMask = 0;
187
188   /*
189    * since state trackers can allocate depth/stencil/accum buffers, we provide
190    * only color buffers here
191    */
192   pfi->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
193   if (doublebuffer)
194      pfi->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
195
196   pfi->stvis.color_format = color->format;
197   pfi->stvis.depth_stencil_format = depth->format;
198
199   pfi->stvis.accum_format = (accum) ?
200      PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
201
202   pfi->stvis.samples = samples;
203   pfi->stvis.render_buffer = ST_ATTACHMENT_INVALID;
204
205   ++stw_dev->pixelformat_extended_count;
206
207   if(!extended) {
208      ++stw_dev->pixelformat_count;
209      assert(stw_dev->pixelformat_count == stw_dev->pixelformat_extended_count);
210   }
211}
212
213void
214stw_pixelformat_init( void )
215{
216   struct pipe_screen *screen = stw_dev->screen;
217   unsigned i, j, k, l;
218
219   assert( !stw_dev->pixelformat_count );
220   assert( !stw_dev->pixelformat_extended_count );
221
222   for(i = 0; i < Elements(stw_pf_multisample); ++i) {
223      unsigned samples = stw_pf_multisample[i];
224
225      /* FIXME: re-enabled MSAA when we can query it */
226      if(samples)
227         continue;
228
229      for(j = 0; j < Elements(stw_pf_color); ++j) {
230         const struct stw_pf_color_info *color = &stw_pf_color[j];
231
232         if(!screen->is_format_supported(screen, color->format, PIPE_TEXTURE_2D,
233                                         0, PIPE_BIND_RENDER_TARGET |
234                                         PIPE_BIND_DISPLAY_TARGET))
235            continue;
236
237         for(k = 0; k < Elements(stw_pf_doublebuffer); ++k) {
238            unsigned doublebuffer = stw_pf_doublebuffer[k];
239
240            for(l = 0; l < Elements(stw_pf_depth_stencil); ++l) {
241               const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[l];
242
243               if(!screen->is_format_supported(screen, depth->format, PIPE_TEXTURE_2D,
244                                               0, PIPE_BIND_DEPTH_STENCIL))
245                  continue;
246
247               stw_pixelformat_add( stw_dev, FALSE, color, depth,  0, doublebuffer, samples );
248               stw_pixelformat_add( stw_dev, FALSE, color, depth, 16, doublebuffer, samples );
249            }
250         }
251      }
252   }
253
254   /*
255    * Same as above, but for the extended color formats (e.g, float) and without PIPE_BIND_DISPLAY_TARGET bit.
256    */
257   for(i = 0; i < Elements(stw_pf_multisample); ++i) {
258      unsigned samples = stw_pf_multisample[i];
259
260      /* FIXME: re-enabled MSAA when we can query it */
261      if(samples)
262         continue;
263
264      for(j = 0; j < Elements(stw_pf_color_extended); ++j) {
265         const struct stw_pf_color_info *color = &stw_pf_color_extended[j];
266
267         if(!screen->is_format_supported(screen, color->format, PIPE_TEXTURE_2D,
268                                         0, PIPE_BIND_RENDER_TARGET))
269            continue;
270
271         for(k = 0; k < Elements(stw_pf_doublebuffer); ++k) {
272            unsigned doublebuffer = stw_pf_doublebuffer[k];
273
274            for(l = 0; l < Elements(stw_pf_depth_stencil); ++l) {
275               const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[l];
276
277               if(!screen->is_format_supported(screen, depth->format, PIPE_TEXTURE_2D,
278                                               0, PIPE_BIND_DEPTH_STENCIL))
279                  continue;
280
281               stw_pixelformat_add( stw_dev, TRUE, color, depth,  0, doublebuffer, samples );
282               stw_pixelformat_add( stw_dev, TRUE, color, depth, 16, doublebuffer, samples );
283            }
284         }
285      }
286   }
287
288   assert( stw_dev->pixelformat_count <= stw_dev->pixelformat_extended_count );
289   assert( stw_dev->pixelformat_extended_count <= STW_MAX_PIXELFORMATS );
290}
291
292uint
293stw_pixelformat_get_count( void )
294{
295   return stw_dev->pixelformat_count;
296}
297
298uint
299stw_pixelformat_get_extended_count( void )
300{
301   return stw_dev->pixelformat_extended_count;
302}
303
304const struct stw_pixelformat_info *
305stw_pixelformat_get_info( int iPixelFormat )
306{
307   int index;
308
309   if (iPixelFormat <= 0) {
310      return NULL;
311   }
312
313   index = iPixelFormat - 1;
314   if (index >= stw_dev->pixelformat_extended_count) {
315      return NULL;
316   }
317
318   return &stw_dev->pixelformats[index];
319}
320
321
322LONG APIENTRY
323DrvDescribePixelFormat(
324   HDC hdc,
325   INT iPixelFormat,
326   ULONG cjpfd,
327   PIXELFORMATDESCRIPTOR *ppfd )
328{
329   uint count;
330   const struct stw_pixelformat_info *pfi;
331
332   (void) hdc;
333
334   if (!stw_dev)
335      return 0;
336
337   count = stw_pixelformat_get_count();
338
339   if (ppfd == NULL)
340      return count;
341   if (cjpfd != sizeof( PIXELFORMATDESCRIPTOR ))
342      return 0;
343
344   pfi = stw_pixelformat_get_info( iPixelFormat );
345   if (!pfi) {
346      return 0;
347   }
348
349   memcpy(ppfd, &pfi->pfd, sizeof( PIXELFORMATDESCRIPTOR ));
350
351   return count;
352}
353
354BOOL APIENTRY
355DrvDescribeLayerPlane(
356   HDC hdc,
357   INT iPixelFormat,
358   INT iLayerPlane,
359   UINT nBytes,
360   LPLAYERPLANEDESCRIPTOR plpd )
361{
362   assert(0);
363   return FALSE;
364}
365
366int APIENTRY
367DrvGetLayerPaletteEntries(
368   HDC hdc,
369   INT iLayerPlane,
370   INT iStart,
371   INT cEntries,
372   COLORREF *pcr )
373{
374   assert(0);
375   return 0;
376}
377
378int APIENTRY
379DrvSetLayerPaletteEntries(
380   HDC hdc,
381   INT iLayerPlane,
382   INT iStart,
383   INT cEntries,
384   CONST COLORREF *pcr )
385{
386   assert(0);
387   return 0;
388}
389
390BOOL APIENTRY
391DrvRealizeLayerPalette(
392   HDC hdc,
393   INT iLayerPlane,
394   BOOL bRealize )
395{
396   assert(0);
397   return FALSE;
398}
399
400/* Only used by the wgl code, but have it here to avoid exporting the
401 * pixelformat.h functionality.
402 */
403int stw_pixelformat_choose( HDC hdc,
404                            CONST PIXELFORMATDESCRIPTOR *ppfd )
405{
406   uint count;
407   uint index;
408   uint bestindex;
409   uint bestdelta;
410
411   (void) hdc;
412
413   count = stw_pixelformat_get_extended_count();
414   bestindex = 0;
415   bestdelta = ~0U;
416
417   for (index = 1; index <= count; index++) {
418      uint delta = 0;
419      const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info( index );
420
421      if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
422          !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) !=
423          !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
424         continue;
425
426      /* FIXME: Take in account individual channel bits */
427      if (ppfd->cColorBits != pfi->pfd.cColorBits)
428         delta += 8;
429
430      if (ppfd->cDepthBits != pfi->pfd.cDepthBits)
431         delta += 4;
432
433      if (ppfd->cStencilBits != pfi->pfd.cStencilBits)
434         delta += 2;
435
436      if (ppfd->cAlphaBits != pfi->pfd.cAlphaBits)
437         delta++;
438
439      if (delta < bestdelta) {
440         bestindex = index;
441         bestdelta = delta;
442         if (bestdelta == 0)
443            break;
444      }
445   }
446
447   return bestindex;
448}
449