~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/gallium/frontends/wgl/stw_pixelformat.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/**************************************************************************
2
 
 *
3
 
 * Copyright 2008 VMware, Inc.
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 VMWARE 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/format/u_format.h"
33
 
#include "util/u_debug.h"
34
 
#include "util/u_memory.h"
35
 
 
36
 
#include <GL/gl.h>
37
 
#include "gldrv.h"
38
 
#include "stw_device.h"
39
 
#include "stw_pixelformat.h"
40
 
#include "stw_tls.h"
41
 
#include "stw_winsys.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
 
   /* alpha */
80
 
   { PIPE_FORMAT_B8G8R8A8_UNORM,    { 8,  8,  8,  8}, {16,  8,  0, 24} },
81
 
   { PIPE_FORMAT_A8R8G8B8_UNORM,    { 8,  8,  8,  8}, { 8, 16, 24,  0} },
82
 
   /* shallow bit depths */
83
 
   { PIPE_FORMAT_B5G6R5_UNORM,      { 5,  6,  5,  0}, {11,  5,  0,  0} },
84
 
#if 0
85
 
   { PIPE_FORMAT_R10G10B10A2_UNORM, {10, 10, 10,  2}, { 0, 10, 20, 30} },
86
 
#endif
87
 
   { PIPE_FORMAT_B5G5R5A1_UNORM,    { 5,  5,  5,  1}, {10,  5,  0, 15} },
88
 
   { PIPE_FORMAT_B4G4R4A4_UNORM,    { 4,  4,  4,  4}, {16,  4,  0, 12} }
89
 
};
90
 
 
91
 
static const struct stw_pf_color_info
92
 
stw_pf_color_extended[] = {
93
 
   { PIPE_FORMAT_R32G32B32A32_FLOAT, {32, 32, 32, 32}, {0, 32, 64, 96} }
94
 
};
95
 
 
96
 
static const struct stw_pf_depth_info
97
 
stw_pf_depth_stencil[] = {
98
 
   /* pure depth */
99
 
   { PIPE_FORMAT_Z32_UNORM,   {32, 0} },
100
 
   { PIPE_FORMAT_X8Z24_UNORM, {24, 0} },
101
 
   { PIPE_FORMAT_Z24X8_UNORM, {24, 0} },
102
 
   { PIPE_FORMAT_Z16_UNORM,   {16, 0} },
103
 
   /* combined depth-stencil */
104
 
   { PIPE_FORMAT_Z24_UNORM_S8_UINT, {24, 8} },
105
 
   { PIPE_FORMAT_S8_UINT_Z24_UNORM, {24, 8} }
106
 
};
107
 
 
108
 
 
109
 
static const boolean
110
 
stw_pf_doublebuffer[] = {
111
 
   FALSE,
112
 
   TRUE,
113
 
};
114
 
 
115
 
 
116
 
static const stw_pfd_flag
117
 
stw_pf_flag[] = {
118
 
   stw_pfd_double_buffer,
119
 
   stw_pfd_gdi_support,
120
 
};
121
 
 
122
 
 
123
 
const unsigned
124
 
stw_pf_multisample[] = {
125
 
   0,
126
 
   4,
127
 
   8,
128
 
   16
129
 
};
130
 
 
131
 
 
132
 
static void
133
 
stw_pixelformat_add(struct stw_device *stw_dev,
134
 
                    boolean extended,
135
 
                    const struct stw_pf_color_info *color,
136
 
                    const struct stw_pf_depth_info *depth,
137
 
                    unsigned accum,
138
 
                    boolean doublebuffer,
139
 
                    boolean gdi,
140
 
                    unsigned samples)
141
 
{
142
 
   struct stw_pixelformat_info *pfi;
143
 
 
144
 
   assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 0) == color->bits.red);
145
 
   assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 1) == color->bits.green);
146
 
   assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 2) == color->bits.blue);
147
 
   assert(util_format_get_component_bits(color->format, UTIL_FORMAT_COLORSPACE_RGB, 3) == color->bits.alpha);
148
 
   assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 0) == depth->bits.depth);
149
 
   assert(util_format_get_component_bits(depth->format, UTIL_FORMAT_COLORSPACE_ZS, 1) == depth->bits.stencil);
150
 
 
151
 
   pfi = util_dynarray_grow(&stw_dev->pixelformats,
152
 
                            struct stw_pixelformat_info,
153
 
                            1);
154
 
 
155
 
   memset(pfi, 0, sizeof *pfi);
156
 
 
157
 
   pfi->iPixelFormat = util_dynarray_num_elements(&stw_dev->pixelformats, struct stw_pixelformat_info);
158
 
   pfi->pfd.nSize = sizeof pfi->pfd;
159
 
   pfi->pfd.nVersion = 1;
160
 
 
161
 
   pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL;
162
 
 
163
 
   /* TODO: also support non-native pixel formats */
164
 
   if (!extended) {
165
 
      pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW;
166
 
   }
167
 
 
168
 
   /* See http://www.opengl.org/pipeline/article/vol003_7/ */
169
 
   pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION;
170
 
 
171
 
   if (doublebuffer)
172
 
      pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE;
173
 
 
174
 
   if (gdi)
175
 
      pfi->pfd.dwFlags |= PFD_SUPPORT_GDI;
176
 
 
177
 
   pfi->pfd.iPixelType = PFD_TYPE_RGBA;
178
 
 
179
 
   pfi->pfd.cColorBits =
180
 
      color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha;
181
 
   pfi->pfd.cRedBits = color->bits.red;
182
 
   pfi->pfd.cRedShift = color->shift.red;
183
 
   pfi->pfd.cGreenBits = color->bits.green;
184
 
   pfi->pfd.cGreenShift = color->shift.green;
185
 
   pfi->pfd.cBlueBits = color->bits.blue;
186
 
   pfi->pfd.cBlueShift = color->shift.blue;
187
 
   pfi->pfd.cAlphaBits = color->bits.alpha;
188
 
   pfi->pfd.cAlphaShift = color->shift.alpha;
189
 
   pfi->pfd.cAccumBits = 4*accum;
190
 
   pfi->pfd.cAccumRedBits = accum;
191
 
   pfi->pfd.cAccumGreenBits = accum;
192
 
   pfi->pfd.cAccumBlueBits = accum;
193
 
   pfi->pfd.cAccumAlphaBits = accum;
194
 
   pfi->pfd.cDepthBits = depth->bits.depth;
195
 
   pfi->pfd.cStencilBits = depth->bits.stencil;
196
 
   pfi->pfd.cAuxBuffers = 0;
197
 
   pfi->pfd.iLayerType = 0;
198
 
   pfi->pfd.bReserved = 0;
199
 
   pfi->pfd.dwLayerMask = 0;
200
 
   pfi->pfd.dwVisibleMask = 0;
201
 
   pfi->pfd.dwDamageMask = 0;
202
 
 
203
 
   /*
204
 
    * since gallium frontend can allocate depth/stencil/accum buffers, we provide
205
 
    * only color buffers here
206
 
    */
207
 
   pfi->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
208
 
   if (doublebuffer)
209
 
      pfi->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
210
 
 
211
 
   pfi->stvis.color_format = color->format;
212
 
   pfi->stvis.depth_stencil_format = depth->format;
213
 
 
214
 
   pfi->stvis.accum_format = (accum) ?
215
 
      PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
216
 
 
217
 
   pfi->stvis.samples = samples;
218
 
 
219
 
   /* WGL_ARB_render_texture */
220
 
   if (color->bits.alpha)
221
 
      pfi->bindToTextureRGBA = TRUE;
222
 
 
223
 
   pfi->bindToTextureRGB = TRUE;
224
 
 
225
 
   if (!extended) {
226
 
      ++stw_dev->pixelformat_count;
227
 
      assert(stw_dev->pixelformat_count ==
228
 
             util_dynarray_num_elements(&stw_dev->pixelformats,
229
 
                                        struct stw_pixelformat_info));
230
 
   }
231
 
}
232
 
 
233
 
 
234
 
/**
235
 
 * Add the depth/stencil/accum/ms variants for a list of color formats.
236
 
 */
237
 
static unsigned
238
 
add_color_format_variants(const struct stw_pf_color_info *color_formats,
239
 
                          unsigned num_color_formats, boolean extended)
240
 
{
241
 
   struct pipe_screen *screen = stw_dev->screen;
242
 
   unsigned cfmt, ms, db, ds, acc, f;
243
 
   unsigned bind_flags = PIPE_BIND_RENDER_TARGET;
244
 
   unsigned num_added = 0;
245
 
   int force_samples = 0;
246
 
 
247
 
   unsigned supported_flags = 0;
248
 
   if (stw_dev->stw_winsys && stw_dev->stw_winsys->get_pfd_flags)
249
 
      supported_flags = stw_dev->stw_winsys->get_pfd_flags(screen);
250
 
 
251
 
   /* Since GLUT for Windows doesn't support MSAA we have an env var
252
 
    * to force all pixel formats to have a particular number of samples.
253
 
    */
254
 
   {
255
 
      const char *samples = getenv("WGL_FORCE_MSAA");
256
 
      if (!samples) {
257
 
         static bool warned = false;
258
 
         samples = getenv("SVGA_FORCE_MSAA");
259
 
         if (samples && !warned) {
260
 
            fprintf(stderr, "*** SVGA_FORCE_MSAA is deprecated; "
261
 
                    "use WGL_FORCE_MSAA instead ***\n");
262
 
            warned = true;
263
 
         }
264
 
      }
265
 
 
266
 
      if (samples)
267
 
         force_samples = atoi(samples);
268
 
   }
269
 
 
270
 
   if (!extended) {
271
 
      bind_flags |= PIPE_BIND_DISPLAY_TARGET;
272
 
   }
273
 
 
274
 
   for (ms = 0; ms < ARRAY_SIZE(stw_pf_multisample); ms++) {
275
 
      unsigned samples = stw_pf_multisample[ms];
276
 
 
277
 
      if (force_samples && samples != force_samples)
278
 
         continue;
279
 
 
280
 
      for (cfmt = 0; cfmt < num_color_formats; cfmt++) {
281
 
         if (!screen->is_format_supported(screen, color_formats[cfmt].format,
282
 
                                          PIPE_TEXTURE_2D, samples, samples,
283
 
                                          bind_flags)) {
284
 
            continue;
285
 
         }
286
 
 
287
 
         for (db = 0; db < ARRAY_SIZE(stw_pf_doublebuffer); db++) {
288
 
            unsigned doublebuffer = stw_pf_doublebuffer[db];
289
 
 
290
 
            for (ds = 0; ds < ARRAY_SIZE(stw_pf_depth_stencil); ds++) {
291
 
               const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[ds];
292
 
 
293
 
               if (!screen->is_format_supported(screen, depth->format,
294
 
                                                PIPE_TEXTURE_2D, samples,
295
 
                                                samples,
296
 
                                                PIPE_BIND_DEPTH_STENCIL)) {
297
 
                  continue;
298
 
               }
299
 
 
300
 
               for (f = 0; f < ARRAY_SIZE(stw_pf_flag); f++) {
301
 
                  stw_pfd_flag flag = stw_pf_flag[f];
302
 
                  if (!(supported_flags & flag) || (flag == stw_pfd_double_buffer && !doublebuffer))
303
 
                     continue;
304
 
                  for (acc = 0; acc < 2; acc++) {
305
 
                     stw_pixelformat_add(stw_dev, extended, &color_formats[cfmt],
306
 
                                         depth, acc * 16, doublebuffer,
307
 
                                         (flag == stw_pfd_gdi_support), samples);
308
 
                     num_added++;
309
 
                  }
310
 
               }
311
 
            }
312
 
         }
313
 
      }
314
 
   }
315
 
 
316
 
   return num_added;
317
 
}
318
 
 
319
 
 
320
 
void
321
 
stw_pixelformat_init(void)
322
 
{
323
 
   unsigned num_formats;
324
 
 
325
 
   assert(!stw_dev->pixelformat_count);
326
 
 
327
 
   util_dynarray_init(&stw_dev->pixelformats, NULL);
328
 
 
329
 
   /* normal, displayable formats */
330
 
   num_formats = add_color_format_variants(stw_pf_color,
331
 
                                           ARRAY_SIZE(stw_pf_color), FALSE);
332
 
   assert(num_formats > 0);
333
 
 
334
 
   /* extended, pbuffer-only formats */
335
 
   add_color_format_variants(stw_pf_color_extended,
336
 
                             ARRAY_SIZE(stw_pf_color_extended), TRUE);
337
 
 
338
 
   assert(stw_dev->pixelformat_count <=
339
 
          util_dynarray_num_elements(&stw_dev->pixelformats,
340
 
                                     struct stw_pixelformat_info));
341
 
}
342
 
 
343
 
 
344
 
uint
345
 
stw_pixelformat_get_count(HDC hdc)
346
 
{
347
 
   if (!stw_init_screen(hdc))
348
 
      return 0;
349
 
 
350
 
   return stw_dev->pixelformat_count;
351
 
}
352
 
 
353
 
 
354
 
uint
355
 
stw_pixelformat_get_extended_count(HDC hdc)
356
 
{
357
 
   if (!stw_init_screen(hdc))
358
 
      return 0;
359
 
 
360
 
   return util_dynarray_num_elements(&stw_dev->pixelformats,
361
 
                                     struct stw_pixelformat_info);
362
 
}
363
 
 
364
 
 
365
 
const struct stw_pixelformat_info *
366
 
stw_pixelformat_get_info(int iPixelFormat)
367
 
{
368
 
   unsigned index;
369
 
 
370
 
   if (iPixelFormat <= 0) {
371
 
      return NULL;
372
 
   }
373
 
 
374
 
   index = iPixelFormat - 1;
375
 
   if (index >= util_dynarray_num_elements(&stw_dev->pixelformats,
376
 
                                           struct stw_pixelformat_info)) {
377
 
      return NULL;
378
 
   }
379
 
 
380
 
   return util_dynarray_element(&stw_dev->pixelformats,
381
 
                                struct stw_pixelformat_info,
382
 
                                index);
383
 
}
384
 
 
385
 
 
386
 
LONG APIENTRY
387
 
DrvDescribePixelFormat(HDC hdc, INT iPixelFormat, ULONG cjpfd,
388
 
                       PIXELFORMATDESCRIPTOR *ppfd)
389
 
{
390
 
   uint count;
391
 
   const struct stw_pixelformat_info *pfi;
392
 
 
393
 
   if (!stw_dev)
394
 
      return 0;
395
 
 
396
 
   count = stw_pixelformat_get_count(hdc);
397
 
 
398
 
   if (ppfd == NULL)
399
 
      return count;
400
 
 
401
 
   if (cjpfd != sizeof(PIXELFORMATDESCRIPTOR))
402
 
      return 0;
403
 
 
404
 
   pfi = stw_pixelformat_get_info(iPixelFormat);
405
 
   if (!pfi) {
406
 
      return 0;
407
 
   }
408
 
 
409
 
   memcpy(ppfd, &pfi->pfd, sizeof(PIXELFORMATDESCRIPTOR));
410
 
 
411
 
   return count;
412
 
}
413
 
 
414
 
 
415
 
BOOL APIENTRY
416
 
DrvDescribeLayerPlane(HDC hdc, INT iPixelFormat, INT iLayerPlane,
417
 
                      UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd)
418
 
{
419
 
   assert(0);
420
 
   return FALSE;
421
 
}
422
 
 
423
 
 
424
 
int APIENTRY
425
 
DrvGetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart,
426
 
                          INT cEntries, COLORREF *pcr)
427
 
{
428
 
   assert(0);
429
 
   return 0;
430
 
}
431
 
 
432
 
 
433
 
int APIENTRY
434
 
DrvSetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart,
435
 
                          INT cEntries, CONST COLORREF *pcr)
436
 
{
437
 
   assert(0);
438
 
   return 0;
439
 
}
440
 
 
441
 
 
442
 
BOOL APIENTRY
443
 
DrvRealizeLayerPalette(HDC hdc, INT iLayerPlane, BOOL bRealize)
444
 
{
445
 
   assert(0);
446
 
   return FALSE;
447
 
}
448
 
 
449
 
 
450
 
/* Only used by the wgl code, but have it here to avoid exporting the
451
 
 * pixelformat.h functionality.
452
 
 */
453
 
int
454
 
stw_pixelformat_choose(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd)
455
 
{
456
 
   uint count;
457
 
   uint index;
458
 
   uint bestindex;
459
 
   uint bestdelta;
460
 
 
461
 
   count = stw_pixelformat_get_extended_count(hdc);
462
 
   bestindex = 0;
463
 
   bestdelta = ~0U;
464
 
 
465
 
   for (index = 1; index <= count; index++) {
466
 
      uint delta = 0;
467
 
      const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info(index);
468
 
 
469
 
      if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
470
 
          !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) !=
471
 
          !!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
472
 
         continue;
473
 
 
474
 
      /* Selection logic:
475
 
      * - Enabling a feature (depth, stencil...) is given highest priority.
476
 
      * - Giving as many bits as requested is given medium priority.
477
 
      * - Giving no more bits than requested is given lowest priority.
478
 
      */
479
 
 
480
 
      /* FIXME: Take in account individual channel bits */
481
 
      if (ppfd->cColorBits && !pfi->pfd.cColorBits)
482
 
         delta += 10000;
483
 
      else if (ppfd->cColorBits > pfi->pfd.cColorBits)
484
 
         delta += 100;
485
 
      else if (ppfd->cColorBits < pfi->pfd.cColorBits)
486
 
         delta++;
487
 
 
488
 
      if (ppfd->cDepthBits && !pfi->pfd.cDepthBits)
489
 
         delta += 10000;
490
 
      else if (ppfd->cDepthBits > pfi->pfd.cDepthBits)
491
 
         delta += 200;
492
 
      else if (ppfd->cDepthBits < pfi->pfd.cDepthBits)
493
 
         delta += 2;
494
 
 
495
 
      if (ppfd->cStencilBits && !pfi->pfd.cStencilBits)
496
 
         delta += 10000;
497
 
      else if (ppfd->cStencilBits > pfi->pfd.cStencilBits)
498
 
         delta += 400;
499
 
      else if (ppfd->cStencilBits < pfi->pfd.cStencilBits)
500
 
         delta++;
501
 
 
502
 
      if (ppfd->cAlphaBits && !pfi->pfd.cAlphaBits)
503
 
         delta += 10000;
504
 
      else if (ppfd->cAlphaBits > pfi->pfd.cAlphaBits)
505
 
         delta += 100;
506
 
      else if (ppfd->cAlphaBits < pfi->pfd.cAlphaBits)
507
 
         delta++;
508
 
 
509
 
      if (delta < bestdelta) {
510
 
         bestindex = index;
511
 
         bestdelta = delta;
512
 
         if (bestdelta == 0)
513
 
            break;
514
 
      }
515
 
   }
516
 
 
517
 
   return bestindex;
518
 
}