Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mesa
Path: blob/21.2-virgl/src/gallium/frontends/wgl/stw_pixelformat.c
4561 views
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->pfd.nSize = sizeof pfi->pfd;
158
pfi->pfd.nVersion = 1;
159
160
pfi->pfd.dwFlags = PFD_SUPPORT_OPENGL;
161
162
/* TODO: also support non-native pixel formats */
163
if (!extended) {
164
pfi->pfd.dwFlags |= PFD_DRAW_TO_WINDOW;
165
}
166
167
/* See http://www.opengl.org/pipeline/article/vol003_7/ */
168
pfi->pfd.dwFlags |= PFD_SUPPORT_COMPOSITION;
169
170
if (doublebuffer)
171
pfi->pfd.dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_EXCHANGE;
172
173
if (gdi)
174
pfi->pfd.dwFlags |= PFD_SUPPORT_GDI;
175
176
pfi->pfd.iPixelType = PFD_TYPE_RGBA;
177
178
pfi->pfd.cColorBits =
179
color->bits.red + color->bits.green + color->bits.blue + color->bits.alpha;
180
pfi->pfd.cRedBits = color->bits.red;
181
pfi->pfd.cRedShift = color->shift.red;
182
pfi->pfd.cGreenBits = color->bits.green;
183
pfi->pfd.cGreenShift = color->shift.green;
184
pfi->pfd.cBlueBits = color->bits.blue;
185
pfi->pfd.cBlueShift = color->shift.blue;
186
pfi->pfd.cAlphaBits = color->bits.alpha;
187
pfi->pfd.cAlphaShift = color->shift.alpha;
188
pfi->pfd.cAccumBits = 4*accum;
189
pfi->pfd.cAccumRedBits = accum;
190
pfi->pfd.cAccumGreenBits = accum;
191
pfi->pfd.cAccumBlueBits = accum;
192
pfi->pfd.cAccumAlphaBits = accum;
193
pfi->pfd.cDepthBits = depth->bits.depth;
194
pfi->pfd.cStencilBits = depth->bits.stencil;
195
pfi->pfd.cAuxBuffers = 0;
196
pfi->pfd.iLayerType = 0;
197
pfi->pfd.bReserved = 0;
198
pfi->pfd.dwLayerMask = 0;
199
pfi->pfd.dwVisibleMask = 0;
200
pfi->pfd.dwDamageMask = 0;
201
202
/*
203
* since gallium frontend can allocate depth/stencil/accum buffers, we provide
204
* only color buffers here
205
*/
206
pfi->stvis.buffer_mask = ST_ATTACHMENT_FRONT_LEFT_MASK;
207
if (doublebuffer)
208
pfi->stvis.buffer_mask |= ST_ATTACHMENT_BACK_LEFT_MASK;
209
210
pfi->stvis.color_format = color->format;
211
pfi->stvis.depth_stencil_format = depth->format;
212
213
pfi->stvis.accum_format = (accum) ?
214
PIPE_FORMAT_R16G16B16A16_SNORM : PIPE_FORMAT_NONE;
215
216
pfi->stvis.samples = samples;
217
218
/* WGL_ARB_render_texture */
219
if (color->bits.alpha)
220
pfi->bindToTextureRGBA = TRUE;
221
222
pfi->bindToTextureRGB = TRUE;
223
224
if (!extended) {
225
++stw_dev->pixelformat_count;
226
assert(stw_dev->pixelformat_count ==
227
util_dynarray_num_elements(&stw_dev->pixelformats,
228
struct stw_pixelformat_info));
229
}
230
}
231
232
233
/**
234
* Add the depth/stencil/accum/ms variants for a list of color formats.
235
*/
236
static unsigned
237
add_color_format_variants(const struct stw_pf_color_info *color_formats,
238
unsigned num_color_formats, boolean extended)
239
{
240
struct pipe_screen *screen = stw_dev->screen;
241
unsigned cfmt, ms, db, ds, acc, f;
242
unsigned bind_flags = PIPE_BIND_RENDER_TARGET;
243
unsigned num_added = 0;
244
int force_samples = 0;
245
246
unsigned supported_flags = 0;
247
if (stw_dev->stw_winsys && stw_dev->stw_winsys->get_pfd_flags)
248
supported_flags = stw_dev->stw_winsys->get_pfd_flags(screen);
249
250
/* Since GLUT for Windows doesn't support MSAA we have an env var
251
* to force all pixel formats to have a particular number of samples.
252
*/
253
{
254
const char *samples= getenv("SVGA_FORCE_MSAA");
255
if (samples)
256
force_samples = atoi(samples);
257
}
258
259
if (!extended) {
260
bind_flags |= PIPE_BIND_DISPLAY_TARGET;
261
}
262
263
for (ms = 0; ms < ARRAY_SIZE(stw_pf_multisample); ms++) {
264
unsigned samples = stw_pf_multisample[ms];
265
266
if (force_samples && samples != force_samples)
267
continue;
268
269
for (cfmt = 0; cfmt < num_color_formats; cfmt++) {
270
if (!screen->is_format_supported(screen, color_formats[cfmt].format,
271
PIPE_TEXTURE_2D, samples, samples,
272
bind_flags)) {
273
continue;
274
}
275
276
for (db = 0; db < ARRAY_SIZE(stw_pf_doublebuffer); db++) {
277
unsigned doublebuffer = stw_pf_doublebuffer[db];
278
279
for (ds = 0; ds < ARRAY_SIZE(stw_pf_depth_stencil); ds++) {
280
const struct stw_pf_depth_info *depth = &stw_pf_depth_stencil[ds];
281
282
if (!screen->is_format_supported(screen, depth->format,
283
PIPE_TEXTURE_2D, samples,
284
samples,
285
PIPE_BIND_DEPTH_STENCIL)) {
286
continue;
287
}
288
289
for (f = 0; f < ARRAY_SIZE(stw_pf_flag); f++) {
290
stw_pfd_flag flag = stw_pf_flag[f];
291
if (!(supported_flags & flag) || (flag == stw_pfd_double_buffer && !doublebuffer))
292
continue;
293
for (acc = 0; acc < 2; acc++) {
294
stw_pixelformat_add(stw_dev, extended, &color_formats[cfmt],
295
depth, acc * 16, doublebuffer,
296
(flag == stw_pfd_gdi_support), samples);
297
num_added++;
298
}
299
}
300
}
301
}
302
}
303
}
304
305
return num_added;
306
}
307
308
309
void
310
stw_pixelformat_init(void)
311
{
312
unsigned num_formats;
313
314
assert(!stw_dev->pixelformat_count);
315
316
util_dynarray_init(&stw_dev->pixelformats, NULL);
317
318
/* normal, displayable formats */
319
num_formats = add_color_format_variants(stw_pf_color,
320
ARRAY_SIZE(stw_pf_color), FALSE);
321
assert(num_formats > 0);
322
323
/* extended, pbuffer-only formats */
324
add_color_format_variants(stw_pf_color_extended,
325
ARRAY_SIZE(stw_pf_color_extended), TRUE);
326
327
assert(stw_dev->pixelformat_count <=
328
util_dynarray_num_elements(&stw_dev->pixelformats,
329
struct stw_pixelformat_info));
330
}
331
332
333
uint
334
stw_pixelformat_get_count(HDC hdc)
335
{
336
if (!stw_init_screen(hdc))
337
return 0;
338
339
return stw_dev->pixelformat_count;
340
}
341
342
343
uint
344
stw_pixelformat_get_extended_count(HDC hdc)
345
{
346
if (!stw_init_screen(hdc))
347
return 0;
348
349
return util_dynarray_num_elements(&stw_dev->pixelformats,
350
struct stw_pixelformat_info);
351
}
352
353
354
const struct stw_pixelformat_info *
355
stw_pixelformat_get_info(int iPixelFormat)
356
{
357
unsigned index;
358
359
if (iPixelFormat <= 0) {
360
return NULL;
361
}
362
363
index = iPixelFormat - 1;
364
if (index >= util_dynarray_num_elements(&stw_dev->pixelformats,
365
struct stw_pixelformat_info)) {
366
return NULL;
367
}
368
369
return util_dynarray_element(&stw_dev->pixelformats,
370
struct stw_pixelformat_info,
371
index);
372
}
373
374
375
LONG APIENTRY
376
DrvDescribePixelFormat(HDC hdc, INT iPixelFormat, ULONG cjpfd,
377
PIXELFORMATDESCRIPTOR *ppfd)
378
{
379
uint count;
380
const struct stw_pixelformat_info *pfi;
381
382
if (!stw_dev)
383
return 0;
384
385
count = stw_pixelformat_get_count(hdc);
386
387
if (ppfd == NULL)
388
return count;
389
390
if (cjpfd != sizeof(PIXELFORMATDESCRIPTOR))
391
return 0;
392
393
pfi = stw_pixelformat_get_info(iPixelFormat);
394
if (!pfi) {
395
return 0;
396
}
397
398
memcpy(ppfd, &pfi->pfd, sizeof(PIXELFORMATDESCRIPTOR));
399
400
return count;
401
}
402
403
404
BOOL APIENTRY
405
DrvDescribeLayerPlane(HDC hdc, INT iPixelFormat, INT iLayerPlane,
406
UINT nBytes, LPLAYERPLANEDESCRIPTOR plpd)
407
{
408
assert(0);
409
return FALSE;
410
}
411
412
413
int APIENTRY
414
DrvGetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart,
415
INT cEntries, COLORREF *pcr)
416
{
417
assert(0);
418
return 0;
419
}
420
421
422
int APIENTRY
423
DrvSetLayerPaletteEntries(HDC hdc, INT iLayerPlane, INT iStart,
424
INT cEntries, CONST COLORREF *pcr)
425
{
426
assert(0);
427
return 0;
428
}
429
430
431
BOOL APIENTRY
432
DrvRealizeLayerPalette(HDC hdc, INT iLayerPlane, BOOL bRealize)
433
{
434
assert(0);
435
return FALSE;
436
}
437
438
439
/* Only used by the wgl code, but have it here to avoid exporting the
440
* pixelformat.h functionality.
441
*/
442
int
443
stw_pixelformat_choose(HDC hdc, CONST PIXELFORMATDESCRIPTOR *ppfd)
444
{
445
uint count;
446
uint index;
447
uint bestindex;
448
uint bestdelta;
449
450
count = stw_pixelformat_get_extended_count(hdc);
451
bestindex = 0;
452
bestdelta = ~0U;
453
454
for (index = 1; index <= count; index++) {
455
uint delta = 0;
456
const struct stw_pixelformat_info *pfi = stw_pixelformat_get_info(index);
457
458
if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) &&
459
!!(ppfd->dwFlags & PFD_DOUBLEBUFFER) !=
460
!!(pfi->pfd.dwFlags & PFD_DOUBLEBUFFER))
461
continue;
462
463
/* Selection logic:
464
* - Enabling a feature (depth, stencil...) is given highest priority.
465
* - Giving as many bits as requested is given medium priority.
466
* - Giving no more bits than requested is given lowest priority.
467
*/
468
469
/* FIXME: Take in account individual channel bits */
470
if (ppfd->cColorBits && !pfi->pfd.cColorBits)
471
delta += 10000;
472
else if (ppfd->cColorBits > pfi->pfd.cColorBits)
473
delta += 100;
474
else if (ppfd->cColorBits < pfi->pfd.cColorBits)
475
delta++;
476
477
if (ppfd->cDepthBits && !pfi->pfd.cDepthBits)
478
delta += 10000;
479
else if (ppfd->cDepthBits > pfi->pfd.cDepthBits)
480
delta += 200;
481
else if (ppfd->cDepthBits < pfi->pfd.cDepthBits)
482
delta += 2;
483
484
if (ppfd->cStencilBits && !pfi->pfd.cStencilBits)
485
delta += 10000;
486
else if (ppfd->cStencilBits > pfi->pfd.cStencilBits)
487
delta += 400;
488
else if (ppfd->cStencilBits < pfi->pfd.cStencilBits)
489
delta++;
490
491
if (ppfd->cAlphaBits && !pfi->pfd.cAlphaBits)
492
delta += 10000;
493
else if (ppfd->cAlphaBits > pfi->pfd.cAlphaBits)
494
delta += 100;
495
else if (ppfd->cAlphaBits < pfi->pfd.cAlphaBits)
496
delta++;
497
498
if (delta < bestdelta) {
499
bestindex = index;
500
bestdelta = delta;
501
if (bestdelta == 0)
502
break;
503
}
504
}
505
506
return bestindex;
507
}
508
509