ReactOS 0.4.15-dev-8428-g6910fa6
utils.c
Go to the documentation of this file.
1/*
2 * Utility functions for the WineD3D Library
3 *
4 * Copyright 2002-2004 Jason Edmeades
5 * Copyright 2003-2004 Raphael Junqueira
6 * Copyright 2004 Christian Costa
7 * Copyright 2005 Oliver Stieber
8 * Copyright 2006-2008 Henri Verbeet
9 * Copyright 2007-2008 Stefan Dösinger for CodeWeavers
10 * Copyright 2009-2010 Henri Verbeet for CodeWeavers
11 *
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2.1 of the License, or (at your option) any later version.
16 *
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * Lesser General Public License for more details.
21 *
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this library; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 */
26
27#include "config.h"
28#include "wine/port.h"
29
30#include <stdio.h>
31
32#include "wined3d_private.h"
33
35
36#define WINED3D_FORMAT_FOURCC_BASE (WINED3DFMT_BC7_UNORM_SRGB + 1)
37
38static const struct
39{
41 unsigned int idx;
42}
44{
68};
69
70#define WINED3D_FORMAT_COUNT (WINED3D_FORMAT_FOURCC_BASE + ARRAY_SIZE(format_index_remap))
71
73{
79};
80
81static const struct wined3d_format_channels formats[] =
82{
83 /* size offset
84 * format id r g b a r g b a bpp depth stencil */
85 {WINED3DFMT_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
86 /* FourCC formats */
87 {WINED3DFMT_UYVY, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
88 {WINED3DFMT_YUY2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
89 {WINED3DFMT_YV12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
90 {WINED3DFMT_NV12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
91 {WINED3DFMT_DXT1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
92 {WINED3DFMT_DXT2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
93 {WINED3DFMT_DXT3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
94 {WINED3DFMT_DXT4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
95 {WINED3DFMT_DXT5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
96 {WINED3DFMT_MULTI2_ARGB8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
97 {WINED3DFMT_G8R8_G8B8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
98 {WINED3DFMT_R8G8_B8G8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
99 /* Hmm? */
100 {WINED3DFMT_R8G8_SNORM_Cx, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
101 {WINED3DFMT_R11G11B10_FLOAT, 11, 11, 10, 0, 0, 11, 22, 0, 4, 0, 0},
102 /* Palettized formats */
103 {WINED3DFMT_P8_UINT_A8_UNORM, 0, 0, 0, 8, 0, 0, 0, 8, 2, 0, 0},
104 {WINED3DFMT_P8_UINT, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
105 /* Standard ARGB formats. */
106 {WINED3DFMT_B8G8R8_UNORM, 8, 8, 8, 0, 16, 8, 0, 0, 3, 0, 0},
107 {WINED3DFMT_B5G6R5_UNORM, 5, 6, 5, 0, 11, 5, 0, 0, 2, 0, 0},
108 {WINED3DFMT_B5G5R5X1_UNORM, 5, 5, 5, 0, 10, 5, 0, 0, 2, 0, 0},
109 {WINED3DFMT_B5G5R5A1_UNORM, 5, 5, 5, 1, 10, 5, 0, 15, 2, 0, 0},
110 {WINED3DFMT_B4G4R4A4_UNORM, 4, 4, 4, 4, 8, 4, 0, 12, 2, 0, 0},
111 {WINED3DFMT_B2G3R3_UNORM, 3, 3, 2, 0, 5, 2, 0, 0, 1, 0, 0},
112 {WINED3DFMT_A8_UNORM, 0, 0, 0, 8, 0, 0, 0, 0, 1, 0, 0},
113 {WINED3DFMT_B2G3R3A8_UNORM, 3, 3, 2, 8, 5, 2, 0, 8, 2, 0, 0},
114 {WINED3DFMT_B4G4R4X4_UNORM, 4, 4, 4, 0, 8, 4, 0, 0, 2, 0, 0},
115 {WINED3DFMT_R8G8B8X8_UNORM, 8, 8, 8, 0, 0, 8, 16, 0, 4, 0, 0},
116 {WINED3DFMT_B10G10R10A2_UNORM, 10, 10, 10, 2, 20, 10, 0, 30, 4, 0, 0},
117 /* Luminance */
118 {WINED3DFMT_L8_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
119 {WINED3DFMT_L8A8_UNORM, 0, 0, 0, 8, 0, 0, 0, 8, 2, 0, 0},
120 {WINED3DFMT_L4A4_UNORM, 0, 0, 0, 4, 0, 0, 0, 4, 1, 0, 0},
121 {WINED3DFMT_L16_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
122 /* Bump mapping stuff */
123 {WINED3DFMT_R5G5_SNORM_L6_UNORM, 5, 5, 0, 0, 0, 5, 0, 0, 2, 0, 0},
124 {WINED3DFMT_R8G8_SNORM_L8X8_UNORM, 8, 8, 0, 0, 0, 8, 0, 0, 4, 0, 0},
125 {WINED3DFMT_R8G8B8A8_SNORM, 8, 8, 8, 8, 0, 8, 16, 24, 4, 0, 0},
126 {WINED3DFMT_R10G11B11_SNORM, 10, 11, 11, 0, 0, 10, 21, 0, 4, 0, 0},
127 {WINED3DFMT_R10G10B10X2_UINT, 10, 10, 10, 0, 0, 10, 20, 0, 4, 0, 0},
128 {WINED3DFMT_R10G10B10X2_SNORM, 10, 10, 10, 0, 0, 10, 20, 0, 4, 0, 0},
129 {WINED3DFMT_R10G10B10_SNORM_A2_UNORM, 10, 10, 10, 2, 0, 10, 20, 30, 4, 0, 0},
130 /* Depth stencil formats */
131 {WINED3DFMT_D16_LOCKABLE, 0, 0, 0, 0, 0, 0, 0, 0, 2, 16, 0},
132 {WINED3DFMT_D32_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 0},
133 {WINED3DFMT_S1_UINT_D15_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 2, 15, 1},
134 {WINED3DFMT_X8D24_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 0},
135 {WINED3DFMT_S4X4_UINT_D24_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 4},
136 {WINED3DFMT_D16_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 2, 16, 0},
137 {WINED3DFMT_D32_FLOAT, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 0},
138 {WINED3DFMT_S8_UINT_D24_FLOAT, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 8},
139 /* Vendor-specific formats */
140 {WINED3DFMT_ATI1N, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
141 {WINED3DFMT_ATI2N, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
142 {WINED3DFMT_NVDB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
143 {WINED3DFMT_INST, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
144 {WINED3DFMT_INTZ, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 8},
145 {WINED3DFMT_RESZ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
146 {WINED3DFMT_NVHU, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
147 {WINED3DFMT_NVHS, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
148 {WINED3DFMT_NULL, 8, 8, 8, 8, 0, 8, 16, 24, 4, 0, 0},
149 /* Unsure about them, could not find a Windows driver that supports them */
150 {WINED3DFMT_R16, 16, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
151 {WINED3DFMT_AL16, 0, 0, 0, 16, 0, 0, 0, 16, 4, 0, 0},
152 /* DirectX 10 HDR formats */
153 {WINED3DFMT_R9G9B9E5_SHAREDEXP, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0},
154 /* Typeless */
155 {WINED3DFMT_R32G32B32A32_TYPELESS, 32, 32, 32, 32, 0, 32, 64, 96, 16, 0, 0},
156 {WINED3DFMT_R32G32B32_TYPELESS, 32, 32, 32, 0, 0, 32, 64, 0, 12, 0, 0},
157 {WINED3DFMT_R16G16B16A16_TYPELESS, 16, 16, 16, 16, 0, 16, 32, 48, 8, 0, 0},
158 {WINED3DFMT_R32G32_TYPELESS, 32, 32, 0, 0, 0, 32, 0, 0, 8, 0, 0},
159 {WINED3DFMT_R32G8X24_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 8, 32, 8},
160 {WINED3DFMT_R10G10B10A2_TYPELESS, 10, 10, 10, 2, 0, 10, 20, 30, 4, 0, 0},
161 {WINED3DFMT_R8G8B8A8_TYPELESS, 8, 8, 8, 8, 0, 8, 16, 24, 4, 0, 0},
162 {WINED3DFMT_R16G16_TYPELESS, 16, 16, 0, 0, 0, 16, 0, 0, 4, 0, 0},
163 {WINED3DFMT_R32_TYPELESS, 32, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0},
164 {WINED3DFMT_R24G8_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 8},
165 {WINED3DFMT_R8G8_TYPELESS, 8, 8, 0, 0, 0, 8, 0, 0, 2, 0, 0},
166 {WINED3DFMT_R16_TYPELESS, 16, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
167 {WINED3DFMT_R8_TYPELESS, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
168 {WINED3DFMT_BC1_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
169 {WINED3DFMT_BC2_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
170 {WINED3DFMT_BC3_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
171 {WINED3DFMT_BC4_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
172 {WINED3DFMT_BC5_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
173 {WINED3DFMT_BC6H_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
174 {WINED3DFMT_BC7_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
175 {WINED3DFMT_B8G8R8A8_TYPELESS, 8, 8, 8, 8, 16, 8, 0, 24, 4, 0, 0},
176 {WINED3DFMT_B8G8R8X8_TYPELESS, 8, 8, 8, 0, 16, 8, 0, 0, 4, 0, 0},
177};
178
180{
190};
191
193{
196 const char *channels;
197};
198
212{
282};
283
285{
291};
292
294{
301};
302
304{
307};
308
310{
320};
321
323{
326};
327
328/* The ATI2N format behaves like an uncompressed format in LockRect(), but
329 * still needs to use the correct block based calculation for e.g. the
330 * resource size. */
332{
343};
344
346{
352};
353
355{
356 {WINED3DFMT_DXT1, 4, 4, 8, TRUE},
357 {WINED3DFMT_DXT2, 4, 4, 16, TRUE},
358 {WINED3DFMT_DXT3, 4, 4, 16, TRUE},
359 {WINED3DFMT_DXT4, 4, 4, 16, TRUE},
360 {WINED3DFMT_DXT5, 4, 4, 16, TRUE},
361 {WINED3DFMT_BC1_UNORM, 4, 4, 8, TRUE},
362 {WINED3DFMT_BC2_UNORM, 4, 4, 16, TRUE},
363 {WINED3DFMT_BC3_UNORM, 4, 4, 16, TRUE},
364 {WINED3DFMT_BC4_UNORM, 4, 4, 8, TRUE},
365 {WINED3DFMT_BC4_SNORM, 4, 4, 8, TRUE},
366 {WINED3DFMT_BC5_UNORM, 4, 4, 16, TRUE},
367 {WINED3DFMT_BC5_SNORM, 4, 4, 16, TRUE},
368 {WINED3DFMT_BC6H_UF16, 4, 4, 16, TRUE},
369 {WINED3DFMT_BC6H_SF16, 4, 4, 16, TRUE},
370 {WINED3DFMT_BC7_UNORM, 4, 4, 16, TRUE},
371 {WINED3DFMT_ATI1N, 4, 4, 8, FALSE},
372 {WINED3DFMT_ATI2N, 4, 4, 16, FALSE},
373 {WINED3DFMT_YUY2, 2, 1, 4, FALSE},
374 {WINED3DFMT_UYVY, 2, 1, 4, FALSE},
375};
376
378{
381 unsigned int component_count;
385};
386
388{
424};
425
427{
434 unsigned int conv_byte_count;
435 unsigned int flags;
437 void (*upload)(const BYTE *src, BYTE *dst, unsigned int src_row_pitch, unsigned int src_slice_pitch,
438 unsigned int dst_row_pitch, unsigned int dst_slice_pitch,
439 unsigned int width, unsigned int height, unsigned int depth);
440 void (*download)(const BYTE *src, BYTE *dst, unsigned int src_row_pitch, unsigned int src_slice_pitch,
441 unsigned int dst_row_pitch, unsigned int dst_slice_pitch,
442 unsigned int width, unsigned int height, unsigned int depth);
443};
444
445static void convert_l4a4_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
446 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
447{
448 /* WINED3DFMT_L4A4_UNORM exists as an internal gl format, but for some reason there is not
449 * format+type combination to load it. Thus convert it to A8L8, then load it
450 * with A4L4 internal, but A8L8 format+type
451 */
452 unsigned int x, y, z;
453 const unsigned char *Source;
454 unsigned char *Dest;
455
456 for (z = 0; z < depth; z++)
457 {
458 for (y = 0; y < height; y++)
459 {
460 Source = src + z * src_slice_pitch + y * src_row_pitch;
461 Dest = dst + z * dst_slice_pitch + y * dst_row_pitch;
462 for (x = 0; x < width; x++ )
463 {
464 unsigned char color = (*Source++);
465 /* A */ Dest[1] = (color & 0xf0u) << 0;
466 /* L */ Dest[0] = (color & 0x0fu) << 4;
467 Dest += 2;
468 }
469 }
470 }
471}
472
473static void convert_r5g5_snorm_l6_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
474 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
475{
476 unsigned int x, y, z;
477 unsigned char r_in, g_in, l_in;
478 const unsigned short *texel_in;
479 unsigned short *texel_out;
480
481 /* Emulating signed 5 bit values with unsigned 5 bit values has some precision problems by design:
482 * E.g. the signed input value 0 becomes 16. GL normalizes it to 16 / 31 = 0.516. We convert it
483 * back to a signed value by subtracting 0.5 and multiplying by 2.0. The resulting value is
484 * ((16 / 31) - 0.5) * 2.0 = 0.032, which is quite different from the intended result 0.000. */
485 for (z = 0; z < depth; z++)
486 {
487 for (y = 0; y < height; y++)
488 {
489 texel_out = (unsigned short *) (dst + z * dst_slice_pitch + y * dst_row_pitch);
490 texel_in = (const unsigned short *)(src + z * src_slice_pitch + y * src_row_pitch);
491 for (x = 0; x < width; x++ )
492 {
493 l_in = (*texel_in & 0xfc00u) >> 10;
494 g_in = (*texel_in & 0x03e0u) >> 5;
495 r_in = *texel_in & 0x001fu;
496
497 *texel_out = ((r_in + 16) << 11) | (l_in << 5) | (g_in + 16);
498 texel_out++;
499 texel_in++;
500 }
501 }
502 }
503}
504
505static void convert_r5g5_snorm_l6_unorm_ext(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
506 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
507{
508 unsigned int x, y, z;
509 unsigned char *texel_out, r_out, g_out, r_in, g_in, l_in;
510 const unsigned short *texel_in;
511
512 for (z = 0; z < depth; z++)
513 {
514 for (y = 0; y < height; y++)
515 {
516 texel_in = (const unsigned short *)(src + z * src_slice_pitch + y * src_row_pitch);
517 texel_out = dst + z * dst_slice_pitch + y * dst_row_pitch;
518 for (x = 0; x < width; x++ )
519 {
520 l_in = (*texel_in & 0xfc00u) >> 10;
521 g_in = (*texel_in & 0x03e0u) >> 5;
522 r_in = *texel_in & 0x001fu;
523
524 r_out = r_in << 3;
525 if (!(r_in & 0x10)) /* r > 0 */
526 r_out |= r_in >> 1;
527
528 g_out = g_in << 3;
529 if (!(g_in & 0x10)) /* g > 0 */
530 g_out |= g_in >> 1;
531
532 texel_out[0] = r_out;
533 texel_out[1] = g_out;
534 texel_out[2] = l_in << 1 | l_in >> 5;
535 texel_out[3] = 0;
536
537 texel_out += 4;
538 texel_in++;
539 }
540 }
541 }
542}
543
544static void convert_r5g5_snorm_l6_unorm_nv(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
545 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
546{
547 unsigned int x, y, z;
548 unsigned char *texel_out, ds_out, dt_out, r_in, g_in, l_in;
549 const unsigned short *texel_in;
550
551 /* This makes the gl surface bigger(24 bit instead of 16), but it works with
552 * fixed function and shaders without further conversion once the surface is
553 * loaded.
554 *
555 * The difference between this function and convert_r5g5_snorm_l6_unorm_ext
556 * is that convert_r5g5_snorm_l6_unorm_ext creates a 32 bit XRGB texture and
557 * this function creates a 24 bit DSDT_MAG texture. Trying to load a DSDT_MAG
558 * internal with a 32 bit DSDT_MAG_INTENSITY or DSDT_MAG_VIB format fails. */
559 for (z = 0; z < depth; z++)
560 {
561 for (y = 0; y < height; y++)
562 {
563 texel_in = (const unsigned short *)(src + z * src_slice_pitch + y * src_row_pitch);
564 texel_out = dst + z * dst_slice_pitch + y * dst_row_pitch;
565 for (x = 0; x < width; x++ )
566 {
567 l_in = (*texel_in & 0xfc00u) >> 10;
568 g_in = (*texel_in & 0x03e0u) >> 5;
569 r_in = *texel_in & 0x001fu;
570
571 ds_out = r_in << 3;
572 if (!(r_in & 0x10)) /* r > 0 */
573 ds_out |= r_in >> 1;
574
575 dt_out = g_in << 3;
576 if (!(g_in & 0x10)) /* g > 0 */
577 dt_out |= g_in >> 1;
578
579 texel_out[0] = ds_out;
580 texel_out[1] = dt_out;
581 texel_out[2] = l_in << 1 | l_in >> 5;
582
583 texel_out += 3;
584 texel_in++;
585 }
586 }
587 }
588}
589
590static void convert_r8g8_snorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
591 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
592{
593 unsigned int x, y, z;
594 const short *Source;
595 unsigned char *Dest;
596
597 for (z = 0; z < depth; z++)
598 {
599 for (y = 0; y < height; y++)
600 {
601 Source = (const short *)(src + z * src_slice_pitch + y * src_row_pitch);
602 Dest = dst + z * dst_slice_pitch + y * dst_row_pitch;
603 for (x = 0; x < width; x++ )
604 {
605 const short color = (*Source++);
606 /* B */ Dest[0] = 0xff;
607 /* G */ Dest[1] = (color >> 8) + 128; /* V */
608 /* R */ Dest[2] = (color & 0xff) + 128; /* U */
609 Dest += 3;
610 }
611 }
612 }
613}
614
615static void convert_r8g8_snorm_l8x8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
616 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
617{
618 unsigned int x, y, z;
619 const DWORD *Source;
620 unsigned char *Dest;
621
622 /* Doesn't work correctly with the fixed function pipeline, but can work in
623 * shaders if the shader is adjusted. (There's no use for this format in gl's
624 * standard fixed function pipeline anyway).
625 */
626 for (z = 0; z < depth; z++)
627 {
628 for (y = 0; y < height; y++)
629 {
630 Source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
631 Dest = dst + z * dst_slice_pitch + y * dst_row_pitch;
632 for (x = 0; x < width; x++ )
633 {
634 LONG color = (*Source++);
635 /* B */ Dest[0] = ((color >> 16) & 0xff); /* L */
636 /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
637 /* R */ Dest[2] = (color & 0xff) + 128; /* U */
638 Dest += 4;
639 }
640 }
641 }
642}
643
644static void convert_r8g8_snorm_l8x8_unorm_nv(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
645 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
646{
647 unsigned int x, y, z;
648 const DWORD *Source;
649 unsigned char *Dest;
650
651 /* This implementation works with the fixed function pipeline and shaders
652 * without further modification after converting the surface.
653 */
654 for (z = 0; z < depth; z++)
655 {
656 for (y = 0; y < height; y++)
657 {
658 Source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
659 Dest = dst + z * dst_slice_pitch + y * dst_row_pitch;
660 for (x = 0; x < width; x++ )
661 {
662 LONG color = (*Source++);
663 /* L */ Dest[2] = ((color >> 16) & 0xff); /* L */
664 /* V */ Dest[1] = ((color >> 8 ) & 0xff); /* V */
665 /* U */ Dest[0] = (color & 0xff); /* U */
666 /* I */ Dest[3] = 255; /* X */
667 Dest += 4;
668 }
669 }
670 }
671}
672
673static void convert_r8g8b8a8_snorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
674 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
675{
676 unsigned int x, y, z;
677 const DWORD *Source;
678 unsigned char *Dest;
679
680 for (z = 0; z < depth; z++)
681 {
682 for (y = 0; y < height; y++)
683 {
684 Source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
685 Dest = dst + z * dst_slice_pitch + y * dst_row_pitch;
686 for (x = 0; x < width; x++ )
687 {
688 LONG color = (*Source++);
689 /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */
690 /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
691 /* R */ Dest[2] = (color & 0xff) + 128; /* U */
692 /* A */ Dest[3] = ((color >> 24) & 0xff) + 128; /* Q */
693 Dest += 4;
694 }
695 }
696 }
697}
698
699static void convert_r16g16_snorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
700 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
701{
702 unsigned int x, y, z;
703 const DWORD *Source;
704 unsigned short *Dest;
705
706 for (z = 0; z < depth; z++)
707 {
708 for (y = 0; y < height; y++)
709 {
710 Source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
711 Dest = (unsigned short *) (dst + z * dst_slice_pitch + y * dst_row_pitch);
712 for (x = 0; x < width; x++ )
713 {
714 const DWORD color = (*Source++);
715 /* B */ Dest[0] = 0xffff;
716 /* G */ Dest[1] = (color >> 16) + 32768; /* V */
717 /* R */ Dest[2] = (color & 0xffff) + 32768; /* U */
718 Dest += 3;
719 }
720 }
721 }
722}
723
724static void convert_r16g16(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
725 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
726{
727 unsigned int x, y, z;
728 const WORD *Source;
729 WORD *Dest;
730
731 for (z = 0; z < depth; z++)
732 {
733 for (y = 0; y < height; y++)
734 {
735 Source = (const WORD *)(src + z * src_slice_pitch + y * src_row_pitch);
736 Dest = (WORD *) (dst + z * dst_slice_pitch + y * dst_row_pitch);
737 for (x = 0; x < width; x++ )
738 {
739 WORD green = (*Source++);
740 WORD red = (*Source++);
741 Dest[0] = green;
742 Dest[1] = red;
743 /* Strictly speaking not correct for R16G16F, but it doesn't matter because the
744 * shader overwrites it anyway */
745 Dest[2] = 0xffff;
746 Dest += 3;
747 }
748 }
749 }
750}
751
752static void convert_r32g32_float(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
753 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
754{
755 unsigned int x, y, z;
756 const float *Source;
757 float *Dest;
758
759 for (z = 0; z < depth; z++)
760 {
761 for (y = 0; y < height; y++)
762 {
763 Source = (const float *)(src + z * src_slice_pitch + y * src_row_pitch);
764 Dest = (float *) (dst + z * dst_slice_pitch + y * dst_row_pitch);
765 for (x = 0; x < width; x++ )
766 {
767 float green = (*Source++);
768 float red = (*Source++);
769 Dest[0] = green;
770 Dest[1] = red;
771 Dest[2] = 1.0f;
772 Dest += 3;
773 }
774 }
775 }
776}
777
778static void convert_s1_uint_d15_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
779 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
780{
781 unsigned int x, y, z;
782
783 for (z = 0; z < depth; z++)
784 {
785 for (y = 0; y < height; ++y)
786 {
787 const WORD *source = (const WORD *)(src + z * src_slice_pitch + y * src_row_pitch);
788 DWORD *dest = (DWORD *)(dst + z * dst_slice_pitch + y * dst_row_pitch);
789
790 for (x = 0; x < width; ++x)
791 {
792 /* The depth data is normalized, so needs to be scaled,
793 * the stencil data isn't. Scale depth data by
794 * (2^24-1)/(2^15-1) ~~ (2^9 + 2^-6). */
795 WORD d15 = source[x] >> 1;
796 DWORD d24 = (d15 << 9) + (d15 >> 6);
797 dest[x] = (d24 << 8) | (source[x] & 0x1);
798 }
799 }
800 }
801}
802
803static void convert_s4x4_uint_d24_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
804 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
805{
806 unsigned int x, y, z;
807
808 for (z = 0; z < depth; z++)
809 {
810 for (y = 0; y < height; ++y)
811 {
812 const DWORD *source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
813 DWORD *dest = (DWORD *)(dst + z * dst_slice_pitch + y * dst_row_pitch);
814
815 for (x = 0; x < width; ++x)
816 {
817 /* Just need to clear out the X4 part. */
818 dest[x] = source[x] & ~0xf0;
819 }
820 }
821 }
822}
823
824static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
825 UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
826{
827 unsigned int x, y, z;
828
829 for (z = 0; z < depth; z++)
830 {
831 for (y = 0; y < height; ++y)
832 {
833 const DWORD *source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
834 float *dest_f = (float *)(dst + z * dst_slice_pitch + y * dst_row_pitch);
835 DWORD *dest_s = (DWORD *)dest_f;
836
837 for (x = 0; x < width; ++x)
838 {
839 dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00u) >> 8);
840 dest_s[x * 2 + 1] = source[x] & 0xff;
841 }
842 }
843 }
844}
845
846static void x8_d24_unorm_upload(const BYTE *src, BYTE *dst,
847 unsigned int src_row_pitch, unsigned int src_slice_pitch,
848 unsigned int dst_row_pitch, unsigned int dst_slice_pitch,
849 unsigned int width, unsigned int height, unsigned int depth)
850{
851 unsigned int x, y, z;
852
853 for (z = 0; z < depth; ++z)
854 {
855 for (y = 0; y < height; ++y)
856 {
857 const DWORD *source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
858 DWORD *dest = (DWORD *)(dst + z * dst_slice_pitch + y * dst_row_pitch);
859
860 for (x = 0; x < width; ++x)
861 {
862 dest[x] = source[x] << 8 | ((source[x] >> 16) & 0xff);
863 }
864 }
865 }
866}
867
868static void x8_d24_unorm_download(const BYTE *src, BYTE *dst,
869 unsigned int src_row_pitch, unsigned int src_slice_pitch,
870 unsigned int dst_row_pitch, unsigned int dst_slice_pitch,
871 unsigned int width, unsigned int height, unsigned int depth)
872{
873 unsigned int x, y, z;
874
875 for (z = 0; z < depth; ++z)
876 {
877 for (y = 0; y < height; ++y)
878 {
879 const DWORD *source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
880 DWORD *dest = (DWORD *)(dst + z * dst_slice_pitch + y * dst_row_pitch);
881
882 for (x = 0; x < width; ++x)
883 {
884 dest[x] = source[x] >> 8;
885 }
886 }
887 }
888}
889
891{
892 /* FIXME: Is this really how color keys are supposed to work? I think it
893 * makes more sense to compare the individual channels. */
894 return color >= color_key->color_space_low_value
895 && color <= color_key->color_space_high_value;
896}
897
898static void convert_p8_uint_b8g8r8a8_unorm(const BYTE *src, unsigned int src_pitch,
899 BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
900 const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
901{
902 const BYTE *src_row;
903 unsigned int x, y;
904 DWORD *dst_row;
905
906 if (!palette)
907 {
908 /* FIXME: This should probably use the system palette. */
909 FIXME("P8 surface loaded without a palette.\n");
910
911 for (y = 0; y < height; ++y)
912 {
913 memset(&dst[dst_pitch * y], 0, width * 4);
914 }
915
916 return;
917 }
918
919 for (y = 0; y < height; ++y)
920 {
921 src_row = &src[src_pitch * y];
922 dst_row = (DWORD *)&dst[dst_pitch * y];
923 for (x = 0; x < width; ++x)
924 {
925 BYTE src_color = src_row[x];
926 dst_row[x] = 0xff000000
927 | (palette->colors[src_color].rgbRed << 16)
928 | (palette->colors[src_color].rgbGreen << 8)
929 | palette->colors[src_color].rgbBlue;
930 }
931 }
932}
933
934static void convert_b5g6r5_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsigned int src_pitch,
935 BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
936 const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
937{
938 const WORD *src_row;
939 unsigned int x, y;
940 WORD *dst_row;
941
942 for (y = 0; y < height; ++y)
943 {
944 src_row = (WORD *)&src[src_pitch * y];
945 dst_row = (WORD *)&dst[dst_pitch * y];
946 for (x = 0; x < width; ++x)
947 {
948 WORD src_color = src_row[x];
949 if (!color_in_range(color_key, src_color))
950 dst_row[x] = 0x8000u | ((src_color & 0xffc0u) >> 1) | (src_color & 0x1fu);
951 else
952 dst_row[x] = ((src_color & 0xffc0u) >> 1) | (src_color & 0x1fu);
953 }
954 }
955}
956
957static void convert_b5g5r5x1_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsigned int src_pitch,
958 BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
959 const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
960{
961 const WORD *src_row;
962 unsigned int x, y;
963 WORD *dst_row;
964
965 for (y = 0; y < height; ++y)
966 {
967 src_row = (WORD *)&src[src_pitch * y];
968 dst_row = (WORD *)&dst[dst_pitch * y];
969 for (x = 0; x < width; ++x)
970 {
971 WORD src_color = src_row[x];
972 if (color_in_range(color_key, src_color))
973 dst_row[x] = src_color & ~0x8000;
974 else
975 dst_row[x] = src_color | 0x8000;
976 }
977 }
978}
979
980static void convert_b8g8r8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
981 BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
982 const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
983{
984 const BYTE *src_row;
985 unsigned int x, y;
986 DWORD *dst_row;
987
988 for (y = 0; y < height; ++y)
989 {
990 src_row = &src[src_pitch * y];
991 dst_row = (DWORD *)&dst[dst_pitch * y];
992 for (x = 0; x < width; ++x)
993 {
994 DWORD src_color = (src_row[x * 3 + 2] << 16) | (src_row[x * 3 + 1] << 8) | src_row[x * 3];
995 if (!color_in_range(color_key, src_color))
996 dst_row[x] = src_color | 0xff000000;
997 }
998 }
999}
1000
1001static void convert_b8g8r8x8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
1002 BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
1003 const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
1004{
1005 const DWORD *src_row;
1006 unsigned int x, y;
1007 DWORD *dst_row;
1008
1009 for (y = 0; y < height; ++y)
1010 {
1011 src_row = (DWORD *)&src[src_pitch * y];
1012 dst_row = (DWORD *)&dst[dst_pitch * y];
1013 for (x = 0; x < width; ++x)
1014 {
1015 DWORD src_color = src_row[x];
1016 if (color_in_range(color_key, src_color))
1017 dst_row[x] = src_color & ~0xff000000;
1018 else
1019 dst_row[x] = src_color | 0xff000000;
1020 }
1021 }
1022}
1023
1024static void convert_b8g8r8a8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
1025 BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
1026 const struct wined3d_palette *palette, const struct wined3d_color_key *color_key)
1027{
1028 const DWORD *src_row;
1029 unsigned int x, y;
1030 DWORD *dst_row;
1031
1032 for (y = 0; y < height; ++y)
1033 {
1034 src_row = (DWORD *)&src[src_pitch * y];
1035 dst_row = (DWORD *)&dst[dst_pitch * y];
1036 for (x = 0; x < width; ++x)
1037 {
1038 DWORD src_color = src_row[x];
1039 if (color_in_range(color_key, src_color))
1040 src_color &= ~0xff000000;
1041 dst_row[x] = src_color;
1042 }
1043 }
1044}
1045
1047 const struct wined3d_texture *texture, BOOL need_alpha_ck)
1048{
1049 const struct wined3d_format *format = texture->resource.format;
1050 unsigned int i;
1051
1052 static const struct
1053 {
1054 enum wined3d_format_id src_format;
1055 struct wined3d_color_key_conversion conversion;
1056 }
1057 color_key_info[] =
1058 {
1064 };
1065 static const struct wined3d_color_key_conversion convert_p8 =
1066 {
1068 };
1069
1070 if (need_alpha_ck && (texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY))
1071 {
1072 for (i = 0; i < ARRAY_SIZE(color_key_info); ++i)
1073 {
1074 if (color_key_info[i].src_format == format->id)
1075 return &color_key_info[i].conversion;
1076 }
1077
1078 FIXME("Color-keying not supported with format %s.\n", debug_d3dformat(format->id));
1079 }
1080
1081 /* FIXME: This should check if the blitter backend can do P8 conversion,
1082 * instead of checking for ARB_fragment_program. */
1083 if (format->id == WINED3DFMT_P8_UINT
1084 && !(texture->resource.device->adapter->gl_info.supported[ARB_FRAGMENT_PROGRAM]
1085 && texture->swapchain && texture == texture->swapchain->front_buffer))
1086 return &convert_p8;
1087
1088 return NULL;
1089}
1090
1091/* The following formats explicitly don't have WINED3DFMT_FLAG_TEXTURE set:
1092 *
1093 * These are never supported on native.
1094 * WINED3DFMT_B8G8R8_UNORM
1095 * WINED3DFMT_B2G3R3_UNORM
1096 * WINED3DFMT_L4A4_UNORM
1097 * WINED3DFMT_S1_UINT_D15_UNORM
1098 * WINED3DFMT_S4X4_UINT_D24_UNORM
1099 *
1100 * Only some Geforce/Voodoo3/G400 cards offer 8-bit textures in case of ddraw.
1101 * Since it is not widely available, don't offer it. Further no Windows driver
1102 * offers WINED3DFMT_P8_UINT_A8_NORM, so don't offer it either.
1103 * WINED3DFMT_P8_UINT
1104 * WINED3DFMT_P8_UINT_A8_UNORM
1105 *
1106 * These formats seem to be similar to the HILO formats in
1107 * GL_NV_texture_shader. NVHU is said to be GL_UNSIGNED_HILO16,
1108 * NVHS GL_SIGNED_HILO16. Rumours say that D3D computes a 3rd channel
1109 * similarly to D3DFMT_CxV8U8 (So NVHS could be called D3DFMT_CxV16U16). ATI
1110 * refused to support formats which can easily be emulated with pixel shaders,
1111 * so applications have to deal with not having NVHS and NVHU.
1112 * WINED3DFMT_NVHU
1113 * WINED3DFMT_NVHS */
1115{
1116 /* format id gl_internal gl_srgb_internal gl_rt_internal
1117 gl_format gl_type conv_byte_count
1118 flags
1119 extension upload download */
1120 /* FourCC formats */
1121 /* GL_APPLE_ycbcr_422 claims that its '2YUV' format, which is supported via the UNSIGNED_SHORT_8_8_REV_APPLE type
1122 * is equivalent to 'UYVY' format on Windows, and the 'YUVS' via UNSIGNED_SHORT_8_8_APPLE equates to 'YUY2'. The
1123 * d3d9 test however shows that the opposite is true. Since the extension is from 2002, it predates the x86 based
1124 * Macs, so probably the endianness differs. This could be tested as soon as we have a Windows and MacOS on a big
1125 * endian machine
1126 */
1242 /* IEEE formats */
1244 GL_RED, GL_FLOAT, 0,
1248 GL_RED, GL_FLOAT, 0,
1252 GL_RGB, GL_FLOAT, 12,
1256 GL_RG, GL_FLOAT, 0,
1260 GL_RGB, GL_FLOAT, 0,
1264 GL_RGBA, GL_FLOAT, 0,
1267 /* Float */
1293 /* Palettized formats */
1296 0,
1300 0,
1302 /* Standard ARGB formats */
1471 /* Luminance */
1507 /* Bump mapping stuff */
1514 GL_DSDT_NV, GL_BYTE, 0,
1519 GL_RG, GL_BYTE, 0,
1534 GL_RGBA, GL_BYTE, 4,
1554 GL_RGBA, GL_BYTE, 0,
1559 GL_RGBA, GL_BYTE, 0,
1569 GL_HILO_NV, GL_SHORT, 0,
1574 GL_RG, GL_SHORT, 0,
1579 GL_RGBA, GL_SHORT, 0,
1584 GL_RED, GL_SHORT, 0,
1589 GL_RED, GL_BYTE, 0,
1593 /* Depth stencil formats */
1691 /* Vendor-specific formats */
1722 {WINED3DFMT_NULL, 0, 0, 0,
1726 /* DirectX 10 HDR formats */
1731};
1732
1734{
1737};
1738
1740{
1748};
1749
1751{
1752 unsigned int i;
1753
1755 return format_id;
1756
1757 for (i = 0; i < ARRAY_SIZE(format_index_remap); ++i)
1758 {
1759 if (format_index_remap[i].id == format_id)
1760 return format_index_remap[i].idx;
1761 }
1762
1763 return -1;
1764}
1765
1768{
1769 int fmt_idx;
1770
1771 if ((fmt_idx = get_format_idx(format_id)) == -1)
1772 {
1773 ERR("Format %s (%#x) not found.\n", debug_d3dformat(format_id), format_id);
1774 return NULL;
1775 }
1776
1777 return &gl_info->formats[fmt_idx];
1778}
1779
1780static void copy_format(struct wined3d_format *dst_format, const struct wined3d_format *src_format)
1781{
1782 enum wined3d_format_id id = dst_format->id;
1783 *dst_format = *src_format;
1784 dst_format->id = id;
1785}
1786
1787static void format_set_flag(struct wined3d_format *format, unsigned int flag)
1788{
1789 unsigned int i;
1790
1791 for (i = 0; i < ARRAY_SIZE(format->flags); ++i)
1792 format->flags[i] |= flag;
1793}
1794
1795static void format_clear_flag(struct wined3d_format *format, unsigned int flag)
1796{
1797 unsigned int i;
1798
1799 for (i = 0; i < ARRAY_SIZE(format->flags); ++i)
1800 format->flags[i] &= ~flag;
1801}
1802
1804{
1805 switch (t)
1806 {
1807 case 'u':
1809 case 'i':
1811 case 'U':
1813 case 'I':
1815 case 'F':
1817 case 'D':
1819 case 'S':
1821 case 'X':
1823 default:
1824 ERR("Invalid channel type '%c'.\n", t);
1826 }
1827}
1828
1830{
1831 struct wined3d_format *format;
1832 unsigned int i, j;
1833
1835 if (!(gl_info->formats = heap_calloc(gl_info->format_count
1836 + ARRAY_SIZE(typeless_depth_stencil_formats), sizeof(*gl_info->formats))))
1837 {
1838 ERR("Failed to allocate memory.\n");
1839 return FALSE;
1840 }
1841
1842 for (i = 0; i < ARRAY_SIZE(formats); ++i)
1843 {
1844 if (!(format = get_format_internal(gl_info, formats[i].id)))
1845 goto fail;
1846
1847 format->id = formats[i].id;
1848 format->red_size = formats[i].red_size;
1849 format->green_size = formats[i].green_size;
1850 format->blue_size = formats[i].blue_size;
1851 format->alpha_size = formats[i].alpha_size;
1852 format->red_offset = formats[i].red_offset;
1853 format->green_offset = formats[i].green_offset;
1854 format->blue_offset = formats[i].blue_offset;
1855 format->alpha_offset = formats[i].alpha_offset;
1856 format->byte_count = formats[i].bpp;
1857 format->depth_size = formats[i].depth_size;
1858 format->stencil_size = formats[i].stencil_size;
1859 format->block_width = 1;
1860 format->block_height = 1;
1861 format->block_byte_count = formats[i].bpp;
1862 }
1863
1864 for (i = 0; i < ARRAY_SIZE(typed_formats); ++i)
1865 {
1866 const struct wined3d_format *typeless_format;
1867 DWORD flags = 0;
1868
1869 if (!(format = get_format_internal(gl_info, typed_formats[i].id)))
1870 goto fail;
1871
1872 if (!(typeless_format = get_format_internal(gl_info, typed_formats[i].typeless_id)))
1873 goto fail;
1874
1875 format->id = typed_formats[i].id;
1876 format->red_size = typeless_format->red_size;
1877 format->green_size = typeless_format->green_size;
1878 format->blue_size = typeless_format->blue_size;
1879 format->alpha_size = typeless_format->alpha_size;
1880 format->red_offset = typeless_format->red_offset;
1881 format->green_offset = typeless_format->green_offset;
1882 format->blue_offset = typeless_format->blue_offset;
1883 format->alpha_offset = typeless_format->alpha_offset;
1884 format->byte_count = typeless_format->byte_count;
1885 format->depth_size = typeless_format->depth_size;
1886 format->stencil_size = typeless_format->stencil_size;
1887 format->block_width = typeless_format->block_width;
1888 format->block_height = typeless_format->block_height;
1889 format->block_byte_count = typeless_format->block_byte_count;
1890 format->typeless_id = typeless_format->id;
1891
1892 for (j = 0; j < strlen(typed_formats[i].channels); ++j)
1893 {
1895 if (channel_type == WINED3D_CHANNEL_TYPE_UINT || channel_type == WINED3D_CHANNEL_TYPE_SINT)
1897 if (channel_type == WINED3D_CHANNEL_TYPE_FLOAT)
1899
1900 if (channel_type == WINED3D_CHANNEL_TYPE_DEPTH && !format->depth_size)
1901 {
1902 format->depth_size = format->red_size;
1903 format->red_size = format->red_offset = 0;
1904 }
1905 }
1906
1908 }
1909
1910 for (i = 0; i < ARRAY_SIZE(ddi_formats); ++i)
1911 {
1912 if (!(format = get_format_internal(gl_info, ddi_formats[i].id)))
1913 goto fail;
1914
1915 format->ddi_format = ddi_formats[i].ddi_format;
1916 }
1917
1918 for (i = 0; i < ARRAY_SIZE(format_base_flags); ++i)
1919 {
1920 if (!(format = get_format_internal(gl_info, format_base_flags[i].id)))
1921 goto fail;
1922
1924 }
1925
1926 return TRUE;
1927
1928fail:
1929 heap_free(gl_info->formats);
1930 return FALSE;
1931}
1932
1934{
1935 struct wined3d_format *format;
1936 unsigned int i;
1937
1938 for (i = 0; i < ARRAY_SIZE(format_block_info); ++i)
1939 {
1940 if (!(format = get_format_internal(gl_info, format_block_info[i].id)))
1941 return FALSE;
1942
1943 format->block_width = format_block_info[i].block_width;
1944 format->block_height = format_block_info[i].block_height;
1945 format->block_byte_count = format_block_info[i].block_byte_count;
1947 if (!format_block_info[i].verify)
1949 }
1950
1951 return TRUE;
1952}
1953
1955{
1956 switch (type)
1957 {
1959 return GL_TEXTURE_1D;
1961 return GL_TEXTURE_2D;
1963 return GL_TEXTURE_3D;
1969 return GL_TEXTURE_2D; /* TODO: GL_TEXTURE_BUFFER. */
1971 return GL_RENDERBUFFER;
1973 break;
1974 }
1975 ERR("Unexpected GL resource type %u.\n", type);
1976 return 0;
1977}
1978
1979static void delete_fbo_attachment(const struct wined3d_gl_info *gl_info,
1980 enum wined3d_gl_resource_type d3d_type, GLuint object)
1981{
1982 switch (d3d_type)
1983 {
1989 gl_info->gl_ops.gl.p_glDeleteTextures(1, &object);
1990 break;
1991
1993 gl_info->fbo_ops.glDeleteRenderbuffers(1, &object);
1994 break;
1995
1998 break;
1999 }
2000}
2001
2002/* Context activation is done by the caller. */
2003static void create_and_bind_fbo_attachment(const struct wined3d_gl_info *gl_info, unsigned int flags,
2005{
2006 GLenum attach_type = flags & WINED3DFMT_FLAG_DEPTH ?
2008
2009 switch (d3d_type)
2010 {
2012 gl_info->gl_ops.gl.p_glGenTextures(1, object);
2013 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, *object);
2014 gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, internal, 16, 0, format, type, NULL);
2015 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2016 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2017
2018 gl_info->fbo_ops.glFramebufferTexture1D(GL_FRAMEBUFFER, attach_type, GL_TEXTURE_1D,
2019 *object, 0);
2021 gl_info->fbo_ops.glFramebufferTexture1D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_1D,
2022 *object, 0);
2023 break;
2024
2027 gl_info->gl_ops.gl.p_glGenTextures(1, object);
2028 gl_info->gl_ops.gl.p_glBindTexture(wined3d_gl_type_to_enum(d3d_type), *object);
2029 gl_info->gl_ops.gl.p_glTexImage2D(wined3d_gl_type_to_enum(d3d_type), 0, internal, 16, 16, 0,
2030 format, type, NULL);
2031 gl_info->gl_ops.gl.p_glTexParameteri(wined3d_gl_type_to_enum(d3d_type), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2032 gl_info->gl_ops.gl.p_glTexParameteri(wined3d_gl_type_to_enum(d3d_type), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2033
2034 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, attach_type,
2035 wined3d_gl_type_to_enum(d3d_type), *object, 0);
2037 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
2038 wined3d_gl_type_to_enum(d3d_type), *object, 0);
2039 break;
2040
2042 gl_info->gl_ops.gl.p_glGenTextures(1, object);
2043 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, *object);
2045 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2046 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2047
2048 gl_info->fbo_ops.glFramebufferTexture3D(GL_FRAMEBUFFER, attach_type,
2049 GL_TEXTURE_3D, *object, 0, 0);
2051 gl_info->fbo_ops.glFramebufferTexture3D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
2052 GL_TEXTURE_3D, *object, 0, 0);
2053 break;
2054
2056 gl_info->gl_ops.gl.p_glGenTextures(1, object);
2057 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, *object);
2058 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, internal, 16, 16, 0,
2059 format, type, NULL);
2060 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, internal, 16, 16, 0,
2061 format, type, NULL);
2062 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, internal, 16, 16, 0,
2063 format, type, NULL);
2064 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, internal, 16, 16, 0,
2065 format, type, NULL);
2066 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, internal, 16, 16, 0,
2067 format, type, NULL);
2068 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, internal, 16, 16, 0,
2069 format, type, NULL);
2070 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2071 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2072
2073 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, attach_type,
2076 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
2078 break;
2079
2081 gl_info->fbo_ops.glGenRenderbuffers(1, object);
2082 gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, *object);
2083 gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, internal, 16, 16);
2084 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, attach_type, GL_RENDERBUFFER,
2085 *object);
2087 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2088 *object);
2089 break;
2090
2093 break;
2094 }
2095
2096 /* Ideally we'd skip all formats already known not to work on textures
2097 * by checking for WINED3DFMT_FLAG_TEXTURE here. However, we want to
2098 * know if we can attach WINED3DFMT_P8_UINT textures to FBOs, and this
2099 * format never has WINED3DFMT_FLAG_TEXTURE set. Instead, swallow GL
2100 * errors generated by invalid formats. */
2101 while (gl_info->gl_ops.gl.p_glGetError());
2102}
2103
2104static void draw_test_quad(struct wined3d_caps_gl_ctx *ctx, const struct wined3d_vec3 *geometry,
2105 const struct wined3d_color *color)
2106{
2107 const struct wined3d_gl_info *gl_info = ctx->gl_info;
2108 static const struct wined3d_vec3 default_geometry[] =
2109 {
2110 {-1.0f, -1.0f, 0.0f},
2111 { 1.0f, -1.0f, 0.0f},
2112 {-1.0f, 1.0f, 0.0f},
2113 { 1.0f, 1.0f, 0.0f},
2114 };
2115 static const char vs_core_header[] =
2116 "#version 150\n"
2117 "in vec4 pos;\n"
2118 "in vec4 color;\n"
2119 "out vec4 out_color;\n"
2120 "\n";
2121 static const char vs_legacy_header[] =
2122 "#version 120\n"
2123 "attribute vec4 pos;\n"
2124 "attribute vec4 color;\n"
2125 "varying vec4 out_color;\n"
2126 "\n";
2127 static const char vs_body[] =
2128 "void main()\n"
2129 "{\n"
2130 " gl_Position = pos;\n"
2131 " out_color = color;\n"
2132 "}\n";
2133 static const char fs_core[] =
2134 "#version 150\n"
2135 "in vec4 out_color;\n"
2136 "out vec4 fragment_color;\n"
2137 "\n"
2138 "void main()\n"
2139 "{\n"
2140 " fragment_color = out_color;\n"
2141 "}\n";
2142 static const char fs_legacy[] =
2143 "#version 120\n"
2144 "varying vec4 out_color;\n"
2145 "\n"
2146 "void main()\n"
2147 "{\n"
2148 " gl_FragData[0] = out_color;\n"
2149 "}\n";
2150 const char *source[2];
2151 GLuint vs_id, fs_id;
2152 unsigned int i;
2153
2154 if (!geometry)
2155 geometry = default_geometry;
2156
2158 || !gl_info->supported[ARB_FRAGMENT_SHADER])
2159 {
2160 gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
2161 gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
2162 gl_info->gl_ops.gl.p_glLoadIdentity();
2163 gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
2164 gl_info->gl_ops.gl.p_glLoadIdentity();
2165
2166 gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
2167 gl_info->gl_ops.gl.p_glColor4f(color->r, color->g, color->b, color->a);
2168 for (i = 0; i < 4; ++i)
2169 gl_info->gl_ops.gl.p_glVertex3fv(&geometry[i].x);
2170 gl_info->gl_ops.gl.p_glEnd();
2171 checkGLcall("draw quad");
2172 return;
2173 }
2174
2175 if (!ctx->test_vbo)
2176 GL_EXTCALL(glGenBuffers(1, &ctx->test_vbo));
2177 GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, ctx->test_vbo));
2178 GL_EXTCALL(glBufferData(GL_ARRAY_BUFFER, sizeof(struct wined3d_vec3) * 4, geometry, GL_STREAM_DRAW));
2179 GL_EXTCALL(glVertexAttribPointer(0, 3, GL_FLOAT, FALSE, 0, NULL));
2180 GL_EXTCALL(glVertexAttrib4f(1, color->r, color->g, color->b, color->a));
2181 GL_EXTCALL(glEnableVertexAttribArray(0));
2182 GL_EXTCALL(glDisableVertexAttribArray(1));
2183
2184 if (!ctx->test_program_id)
2185 {
2186#ifdef __REACTOS__
2187 /* workaround CORE-15408 crash for many 3D applications.
2188 VBoxDisp with enabled 3D acceleration only supports OpenGL 2.1 (GLSL 120).
2189 Wine must not use shaders for OpenGL 3.2 (GLSL 150). */
2190 BOOL use_glsl_150 = FALSE;
2191#else
2192 BOOL use_glsl_150 = gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50);
2193#endif
2194
2195 ctx->test_program_id = GL_EXTCALL(glCreateProgram());
2196
2197 vs_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
2198 source[0] = use_glsl_150 ? vs_core_header : vs_legacy_header;
2199 source[1] = vs_body;
2200 GL_EXTCALL(glShaderSource(vs_id, 2, source, NULL));
2201 GL_EXTCALL(glAttachShader(ctx->test_program_id, vs_id));
2202 GL_EXTCALL(glDeleteShader(vs_id));
2203
2204 fs_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER));
2205 source[0] = use_glsl_150 ? fs_core : fs_legacy;
2206 GL_EXTCALL(glShaderSource(fs_id, 1, source, NULL));
2207 GL_EXTCALL(glAttachShader(ctx->test_program_id, fs_id));
2208 GL_EXTCALL(glDeleteShader(fs_id));
2209
2210 GL_EXTCALL(glBindAttribLocation(ctx->test_program_id, 0, "pos"));
2211 GL_EXTCALL(glBindAttribLocation(ctx->test_program_id, 1, "color"));
2212
2213 if (use_glsl_150)
2214 GL_EXTCALL(glBindFragDataLocation(ctx->test_program_id, 0, "fragment_color"));
2215
2216 GL_EXTCALL(glCompileShader(vs_id));
2217 print_glsl_info_log(gl_info, vs_id, FALSE);
2218 GL_EXTCALL(glCompileShader(fs_id));
2219 print_glsl_info_log(gl_info, fs_id, FALSE);
2220 GL_EXTCALL(glLinkProgram(ctx->test_program_id));
2221 shader_glsl_validate_link(gl_info, ctx->test_program_id);
2222 }
2223 GL_EXTCALL(glUseProgram(ctx->test_program_id));
2224
2225 gl_info->gl_ops.gl.p_glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2226
2227 GL_EXTCALL(glUseProgram(0));
2228 GL_EXTCALL(glDisableVertexAttribArray(0));
2229 GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
2230 checkGLcall("draw quad");
2231}
2232
2233/* Context activation is done by the caller. */
2235{
2236 /* Check if the default internal format is supported as a frame buffer
2237 * target, otherwise fall back to the render target internal.
2238 *
2239 * Try to stick to the standard format if possible, this limits precision differences. */
2240 static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 1.0f};
2241 static const struct wined3d_color half_transparent_red = {1.0f, 0.0f, 0.0f, 0.5f};
2242 const struct wined3d_gl_info *gl_info = ctx->gl_info;
2243 GLenum status, rt_internal = format->rtInternal;
2244 GLuint object, color_rb;
2246 BOOL fallback_fmt_used = FALSE, regular_fmt_used = FALSE;
2247
2248 gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
2249
2250 for (type = 0; type < ARRAY_SIZE(format->flags); ++type)
2251 {
2252 const char *type_string = "color";
2253
2255 continue;
2256
2257 create_and_bind_fbo_attachment(gl_info, format->flags[type], type, &object, format->glInternal,
2258 format->glFormat, format->glType);
2259
2261 {
2262 gl_info->fbo_ops.glGenRenderbuffers(1, &color_rb);
2263 gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, color_rb);
2265 gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 1);
2266 else
2267 gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
2268
2269 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
2271 checkGLcall("Create and attach color rb attachment");
2272 type_string = "depth / stencil";
2273 }
2274
2275 status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
2276 checkGLcall("Framebuffer format check");
2277
2279 {
2280 TRACE("Format %s is supported as FBO %s attachment, type %u.\n",
2281 debug_d3dformat(format->id), type_string, type);
2283 format->rtInternal = format->glInternal;
2284 regular_fmt_used = TRUE;
2285 }
2286 else
2287 {
2288 if (!rt_internal)
2289 {
2291 {
2292 WARN("Format %s with rendertarget flag is not supported as FBO color attachment (type %u),"
2293 " and no fallback specified.\n", debug_d3dformat(format->id), type);
2294 format->flags[type] &= ~WINED3DFMT_FLAG_RENDERTARGET;
2295 }
2296 else
2297 {
2298 TRACE("Format %s is not supported as FBO %s attachment, type %u.\n",
2299 debug_d3dformat(format->id), type_string, type);
2300 }
2301 format->rtInternal = format->glInternal;
2302 }
2303 else
2304 {
2305 TRACE("Format %s is not supported as FBO %s attachment (type %u),"
2306 " trying rtInternal format as fallback.\n",
2307 debug_d3dformat(format->id), type_string, type);
2308
2309 while (gl_info->gl_ops.gl.p_glGetError());
2310
2311 delete_fbo_attachment(gl_info, type, object);
2312 create_and_bind_fbo_attachment(gl_info, format->flags[type], type, &object, format->rtInternal,
2313 format->glFormat, format->glType);
2314
2315 status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
2316 checkGLcall("Framebuffer format check");
2317
2319 {
2320 TRACE("Format %s rtInternal format is supported as FBO %s attachment, type %u.\n",
2321 debug_d3dformat(format->id), type_string, type);
2322 fallback_fmt_used = TRUE;
2323 }
2324 else
2325 {
2326 WARN("Format %s rtInternal format is not supported as FBO %s attachment, type %u.\n",
2327 debug_d3dformat(format->id), type_string, type);
2328 format->flags[type] &= ~WINED3DFMT_FLAG_RENDERTARGET;
2329 }
2330 }
2331 }
2332
2336 && !(format->flags[type] & WINED3DFMT_FLAG_INTEGER)
2338 && format->glFormat != GL_LUMINANCE && format->glFormat != GL_LUMINANCE_ALPHA
2339 && (format->red_size || format->alpha_size))
2340 {
2341 DWORD readback[16 * 16 * 16], color, r_range, a_range;
2342 BYTE r, a;
2343 BOOL match = TRUE;
2344 GLuint rb;
2345
2346 if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
2348 {
2349 gl_info->fbo_ops.glGenRenderbuffers(1, &rb);
2350 gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, rb);
2352 gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 1);
2353 else
2354 gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
2355 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);
2356 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb);
2357 checkGLcall("RB attachment");
2358 }
2359
2360 gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
2361 gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
2362 gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
2363 if (gl_info->gl_ops.gl.p_glGetError() == GL_INVALID_FRAMEBUFFER_OPERATION)
2364 {
2365 while (gl_info->gl_ops.gl.p_glGetError());
2366 TRACE("Format %s doesn't support post-pixelshader blending, type %u.\n",
2368 format->flags[type] &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
2369 }
2370 else
2371 {
2372 gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
2374 gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1);
2375 else
2376 gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 16);
2377 gl_info->gl_ops.gl.p_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2378
2379 draw_test_quad(ctx, NULL, &black);
2380
2381 gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
2382
2383 draw_test_quad(ctx, NULL, &half_transparent_red);
2384
2385 gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
2386
2387 switch (type)
2388 {
2390 /* Rebinding texture to workaround a fglrx bug. */
2391 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, object);
2392 gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_1D, 0, GL_BGRA,
2393 GL_UNSIGNED_INT_8_8_8_8_REV, readback);
2394 color = readback[7];
2395 break;
2396
2400 /* Rebinding texture to workaround a fglrx bug. */
2401 gl_info->gl_ops.gl.p_glBindTexture(wined3d_gl_type_to_enum(type), object);
2402 gl_info->gl_ops.gl.p_glGetTexImage(wined3d_gl_type_to_enum(type), 0, GL_BGRA,
2403 GL_UNSIGNED_INT_8_8_8_8_REV, readback);
2404 color = readback[7 * 16 + 7];
2405 break;
2406
2408 /* Rebinding texture to workaround a fglrx bug. */
2409 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, object);
2410 gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_BGRA,
2411 GL_UNSIGNED_INT_8_8_8_8_REV, readback);
2412 color = readback[7 * 16 + 7];
2413 break;
2414
2416 gl_info->gl_ops.gl.p_glReadPixels(0, 0, 16, 16,
2418 color = readback[7 * 16 + 7];
2419 break;
2420
2423 color = 0;
2424 break;
2425 }
2426 checkGLcall("Post-pixelshader blending check");
2427
2428 a = color >> 24;
2429 r = (color & 0x00ff0000u) >> 16;
2430
2431 r_range = format->red_size < 8 ? 1u << (8 - format->red_size) : 1;
2432 a_range = format->alpha_size < 8 ? 1u << (8 - format->alpha_size) : 1;
2433 if (format->red_size && (r < 0x7f - r_range || r > 0x7f + r_range))
2434 match = FALSE;
2435 else if (format->alpha_size > 1 && (a < 0xbf - a_range || a > 0xbf + a_range))
2436 match = FALSE;
2437 if (!match)
2438 {
2439 TRACE("Format %s doesn't support post-pixelshader blending, type %u.\n",
2441 TRACE("Color output: %#x\n", color);
2442 format->flags[type] &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
2443 }
2444 else
2445 {
2446 TRACE("Format %s supports post-pixelshader blending, type %u.\n",
2448 TRACE("Color output: %#x\n", color);
2450 }
2451 }
2452
2453 if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
2455 {
2456 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
2457 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
2458 gl_info->fbo_ops.glDeleteRenderbuffers(1, &rb);
2459 checkGLcall("RB cleanup");
2460 }
2461 }
2462
2463 if (format->glInternal != format->glGammaInternal)
2464 {
2465 delete_fbo_attachment(gl_info, type, object);
2466 create_and_bind_fbo_attachment(gl_info, format->flags[type], type, &object, format->glGammaInternal,
2467 format->glFormat, format->glType);
2468
2469 status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
2470 checkGLcall("Framebuffer format check");
2471
2473 {
2474 TRACE("Format %s's sRGB format is FBO attachable, type %u.\n",
2477 if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
2478 format->glInternal = format->glGammaInternal;
2479 }
2480 else
2481 {
2482 WARN("Format %s's sRGB format is not FBO attachable, type %u.\n",
2485 }
2486 }
2487 else if (status == GL_FRAMEBUFFER_COMPLETE)
2489
2491 {
2492 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
2493 gl_info->fbo_ops.glDeleteRenderbuffers(1, &color_rb);
2494 }
2495
2496 delete_fbo_attachment(gl_info, type, object);
2497 checkGLcall("Framebuffer format check cleanup");
2498 }
2499
2500 if (fallback_fmt_used && regular_fmt_used)
2501 {
2502 FIXME("Format %s needs different render target formats for different resource types.\n",
2503 debug_d3dformat(format->id));
2506 }
2507}
2508
2509static void query_format_flag(struct wined3d_gl_info *gl_info, struct wined3d_format *format,
2510 GLint internal, GLenum pname, DWORD flag, const char *string)
2511{
2512 GLint value;
2514
2515 for (type = 0; type < ARRAY_SIZE(format->flags); ++type)
2516 {
2517 gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type), internal, pname, 1, &value);
2518 if (value == GL_FULL_SUPPORT)
2519 {
2520 TRACE("Format %s supports %s, resource type %u.\n", debug_d3dformat(format->id), string, type);
2521 format->flags[type] |= flag;
2522 }
2523 else
2524 {
2525 TRACE("Format %s doesn't support %s, resource type %u.\n", debug_d3dformat(format->id), string, type);
2526 format->flags[type] &= ~flag;
2527 }
2528 }
2529}
2530
2531/* Context activation is done by the caller. */
2533{
2534 const struct wined3d_gl_info *gl_info = ctx->gl_info;
2535 unsigned int i, type;
2536 GLuint fbo;
2537
2539 {
2540 for (i = 0; i < gl_info->format_count; ++i)
2541 {
2542 GLint value;
2543 struct wined3d_format *format = &gl_info->formats[i];
2544 BOOL fallback_fmt_used = FALSE, regular_fmt_used = FALSE;
2545 GLenum rt_internal = format->rtInternal;
2546
2547 if (!format->glInternal)
2548 continue;
2549
2550 for (type = 0; type < ARRAY_SIZE(format->flags); ++type)
2551 {
2552 gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2553 format->glInternal, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
2554 if (value == GL_FULL_SUPPORT)
2555 {
2556 TRACE("Format %s is supported as FBO color attachment, resource type %u.\n",
2559 format->rtInternal = format->glInternal;
2560 regular_fmt_used = TRUE;
2561
2562 gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2563 format->glInternal, GL_FRAMEBUFFER_BLEND, 1, &value);
2564 if (value == GL_FULL_SUPPORT)
2565 {
2566 TRACE("Format %s supports post-pixelshader blending, resource type %u.\n",
2569 }
2570 else
2571 {
2572 TRACE("Format %s doesn't support post-pixelshader blending, resource typed %u.\n",
2574 format->flags[type] &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
2575 }
2576 }
2577 else
2578 {
2579 if (!rt_internal)
2580 {
2582 {
2583 WARN("Format %s with rendertarget flag is not supported as FBO color attachment"
2584 " and no fallback specified, resource type %u.\n",
2586 format->flags[type] &= ~WINED3DFMT_FLAG_RENDERTARGET;
2587 }
2588 else
2589 TRACE("Format %s is not supported as FBO color attachment,"
2590 " resource type %u.\n", debug_d3dformat(format->id), type);
2591 format->rtInternal = format->glInternal;
2592 }
2593 else
2594 {
2595 gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2596 rt_internal, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
2597 if (value == GL_FULL_SUPPORT)
2598 {
2599 TRACE("Format %s rtInternal format is supported as FBO color attachment,"
2600 " resource type %u.\n", debug_d3dformat(format->id), type);
2601 fallback_fmt_used = TRUE;
2602 }
2603 else
2604 {
2605 WARN("Format %s rtInternal format is not supported as FBO color attachment,"
2606 " resource type %u.\n", debug_d3dformat(format->id), type);
2607 format->flags[type] &= ~WINED3DFMT_FLAG_RENDERTARGET;
2608 }
2609 }
2610 }
2611
2612 if (format->glInternal != format->glGammaInternal)
2613 {
2614 gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2615 format->glGammaInternal, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
2616 if (value == GL_FULL_SUPPORT)
2617 {
2618 TRACE("Format %s's sRGB format is FBO attachable, resource type %u.\n",
2621 if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
2622 format->glInternal = format->glGammaInternal;
2623 }
2624 else
2625 {
2626 WARN("Format %s's sRGB format is not FBO attachable, resource type %u.\n",
2629 }
2630 }
2631 else if (format->flags[type] & WINED3DFMT_FLAG_FBO_ATTACHABLE)
2633 }
2634
2635 if (fallback_fmt_used && regular_fmt_used)
2636 {
2637 FIXME("Format %s needs different render target formats for different resource types.\n",
2638 debug_d3dformat(format->id));
2641 }
2642 }
2643 return;
2644 }
2645
2647 {
2648 gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
2649 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2650 gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);
2651 gl_info->gl_ops.gl.p_glReadBuffer(GL_COLOR_ATTACHMENT0);
2652 }
2653
2654 for (i = 0; i < gl_info->format_count; ++i)
2655 {
2656 struct wined3d_format *format = &gl_info->formats[i];
2657
2658 if (!format->glInternal) continue;
2659
2661 {
2662 TRACE("Skipping format %s because it's a compressed format.\n",
2663 debug_d3dformat(format->id));
2664 continue;
2665 }
2666
2668 {
2669 TRACE("Checking if format %s is supported as FBO color attachment...\n", debug_d3dformat(format->id));
2671 }
2672 else
2673 {
2674 format->rtInternal = format->glInternal;
2675 }
2676 }
2677
2679 gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
2680}
2681
2682static GLenum lookup_gl_view_class(GLenum internal_format)
2683{
2684 static const struct
2685 {
2686 GLenum internal_format;
2687 GLenum view_class;
2688 }
2689 view_classes[] =
2690 {
2691 /* 128-bit */
2695 /* 96-bit */
2699 /* 64-bit */
2708 /* 48-bit */
2714 /* 32-bit */
2732 /* 24-bit */
2738 /* 16-bit */
2748 /* 8-bit */
2753
2754 /* RGTC1 */
2757 /* RGTC2 */
2760
2761 /* BPTC unorm */
2764 /* BPTC float */
2767
2768 /* DXT1 RGB */
2771 /* DXT1 RGBA */
2774 /* DXT3 */
2777 /* DXT5 */
2780 };
2781
2782 unsigned int i;
2783
2784 for (i = 0; i < ARRAY_SIZE(view_classes); ++i)
2785 {
2786 if (view_classes[i].internal_format == internal_format)
2787 return view_classes[i].view_class;
2788 }
2789
2790 return GL_NONE;
2791}
2792
2794{
2795 GLenum internal_view_class, gamma_view_class, rt_view_class;
2796
2797 internal_view_class = lookup_gl_view_class(format->glInternal);
2798 gamma_view_class = lookup_gl_view_class(format->glGammaInternal);
2799 rt_view_class = lookup_gl_view_class(format->rtInternal);
2800
2801 if (internal_view_class == gamma_view_class || gamma_view_class == rt_view_class)
2802 {
2803 format->gl_view_class = internal_view_class;
2804 TRACE("Format %s is member of GL view class %#x.\n",
2805 debug_d3dformat(format->id), format->gl_view_class);
2806 }
2807 else
2808 {
2809 format->gl_view_class = GL_NONE;
2810 }
2811}
2812
2814 struct wined3d_format *format, const struct wined3d_format_texture_info *texture_info,
2815 struct wined3d_gl_info *gl_info, BOOL srgb_write_supported, BOOL srgb_format)
2816{
2818 unsigned int i, max_log2;
2819 GLenum target;
2820
2822 {
2823 query_format_flag(gl_info, format, format->glInternal, GL_VERTEX_TEXTURE,
2824 WINED3DFMT_FLAG_VTF, "vertex texture usage");
2825 query_format_flag(gl_info, format, format->glInternal, GL_FILTER,
2826 WINED3DFMT_FLAG_FILTERING, "filtering");
2827
2828 if (srgb_format || format->glGammaInternal != format->glInternal)
2829 {
2830 query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_READ,
2831 WINED3DFMT_FLAG_SRGB_READ, "sRGB read");
2832
2833 if (srgb_write_supported)
2834 query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_WRITE,
2835 WINED3DFMT_FLAG_SRGB_WRITE, "sRGB write");
2836 else
2838
2840 format->glGammaInternal = format->glInternal;
2843 format->glInternal = format->glGammaInternal;
2844 }
2845 }
2846 else
2847 {
2848 if (!gl_info->limits.samplers[WINED3D_SHADER_TYPE_VERTEX])
2850
2855
2856 if (srgb_format || format->glGammaInternal != format->glInternal)
2857 {
2858 /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */
2859 if (!gl_info->supported[EXT_TEXTURE_SRGB])
2860 {
2861 format->glGammaInternal = format->glInternal;
2863 }
2866 {
2867 format->glInternal = format->glGammaInternal;
2868 }
2869 }
2870
2871 if ((format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_SRGB_WRITE) && !srgb_write_supported)
2873
2874 if (!gl_info->supported[ARB_DEPTH_TEXTURE]
2876 {
2877 format->flags[WINED3D_GL_RES_TYPE_TEX_1D] &= ~WINED3DFMT_FLAG_TEXTURE;
2878 format->flags[WINED3D_GL_RES_TYPE_TEX_2D] &= ~WINED3DFMT_FLAG_TEXTURE;
2879 format->flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
2880 format->flags[WINED3D_GL_RES_TYPE_TEX_CUBE] &= ~WINED3DFMT_FLAG_TEXTURE;
2881 format->flags[WINED3D_GL_RES_TYPE_TEX_RECT] &= ~WINED3DFMT_FLAG_TEXTURE;
2882 }
2883 }
2884
2886
2887 if (format->glInternal && format->flags[WINED3D_GL_RES_TYPE_RB]
2889 {
2890 if (gl_info->supported[ARB_INTERNALFORMAT_QUERY])
2891 {
2893 count = 0;
2894 GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
2897 GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
2899 checkGLcall("query sample counts");
2900 for (i = 0; i < count; ++i)
2901 {
2902 if (multisample_types[i] > sizeof(format->multisample_types) * CHAR_BIT)
2903 continue;
2904 format->multisample_types |= 1u << (multisample_types[i] - 1);
2905 }
2906 }
2907 else
2908 {
2909#ifdef __REACTOS__
2910 if (gl_info->limits.samples) {
2911#endif
2912 max_log2 = wined3d_log2i(min(gl_info->limits.samples,
2913 sizeof(format->multisample_types) * CHAR_BIT));
2914 for (i = 1; i <= max_log2; ++i)
2915 format->multisample_types |= 1u << ((1u << i) - 1);
2916#ifdef __REACTOS__
2917 }
2918#endif
2919 }
2920 }
2921}
2922
2924{
2925 struct wined3d_format *format, *srgb_format;
2927 struct shader_caps shader_caps;
2928 unsigned int i, j;
2929 BOOL srgb_write;
2930
2931 adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
2932 adapter->shader_backend->shader_get_caps(gl_info, &shader_caps);
2935
2936 for (i = 0; i < ARRAY_SIZE(format_texture_info); ++i)
2937 {
2938 if (!(format = get_format_internal(gl_info, format_texture_info[i].id)))
2939 return FALSE;
2940
2941 if (!gl_info->supported[format_texture_info[i].extension])
2942 continue;
2943
2944 /* ARB_texture_rg defines floating point formats, but only if
2945 * ARB_texture_float is also supported. */
2946 if (!gl_info->supported[ARB_TEXTURE_FLOAT]
2948 continue;
2949
2950 /* ARB_texture_rg defines integer formats if EXT_texture_integer is also supported. */
2951 if (!gl_info->supported[EXT_TEXTURE_INTEGER]
2953 continue;
2954
2955 format->glInternal = format_texture_info[i].gl_internal;
2956 format->glGammaInternal = format_texture_info[i].gl_srgb_internal;
2957 format->rtInternal = format_texture_info[i].gl_rt_internal;
2958 format->glFormat = format_texture_info[i].gl_format;
2959 format->glType = format_texture_info[i].gl_type;
2960 format->color_fixup = COLOR_FIXUP_IDENTITY;
2961 format->height_scale.numerator = 1;
2962 format->height_scale.denominator = 1;
2963
2967
2968 /* GL_ARB_depth_texture does not support 3D textures. It also says "cube textures are
2969 * problematic", but doesn't explicitly mandate that an error is generated. */
2970 if (gl_info->supported[EXT_TEXTURE3D]
2973
2976
2977 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
2979
2981 format->flags[WINED3D_GL_RES_TYPE_RB] &= ~WINED3DFMT_FLAG_TEXTURE;
2982
2983 if (format->glGammaInternal != format->glInternal
2984 && !(adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL))
2985 {
2986 format->glGammaInternal = format->glInternal;
2988 }
2989
2991
2992 /* Texture conversion stuff */
2993 format->conv_byte_count = format_texture_info[i].conv_byte_count;
2994 format->upload = format_texture_info[i].upload;
2995 format->download = format_texture_info[i].download;
2996
2997 srgb_format = NULL;
2998 for (j = 0; j < ARRAY_SIZE(format_srgb_info); ++j)
2999 {
3000 if (format_srgb_info[j].base_format_id == format->id)
3001 {
3002 if (!(srgb_format = get_format_internal(gl_info, format_srgb_info[j].srgb_format_id)))
3003 return FALSE;
3004 break;
3005 }
3006 }
3007 if (!srgb_format)
3008 continue;
3009
3010 copy_format(srgb_format, format);
3011
3012 if (gl_info->supported[EXT_TEXTURE_SRGB]
3013 && !(adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL))
3014 {
3015 srgb_format->glInternal = format_texture_info[i].gl_srgb_internal;
3016 srgb_format->glGammaInternal = format_texture_info[i].gl_srgb_internal;
3018 query_internal_format(adapter, srgb_format, &format_texture_info[i], gl_info, srgb_write, TRUE);
3019 }
3020 }
3021
3022 return TRUE;
3023}
3024
3025static BOOL color_match(DWORD c1, DWORD c2, BYTE max_diff)
3026{
3027 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
3028 c1 >>= 8; c2 >>= 8;
3029 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
3030 c1 >>= 8; c2 >>= 8;
3031 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
3032 c1 >>= 8; c2 >>= 8;
3033 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
3034 return TRUE;
3035}
3036
3037/* A context is provided by the caller */
3038static BOOL check_filter(const struct wined3d_gl_info *gl_info, GLenum internal)
3039{
3040 static const DWORD data[] = {0x00000000, 0xffffffff};
3041 GLuint tex, fbo, buffer;
3042 DWORD readback[16 * 1];
3043 BOOL ret = FALSE;
3044
3045 /* Render a filtered texture and see what happens. This is intended to detect the lack of
3046 * float16 filtering on ATI X1000 class cards. The drivers disable filtering instead of
3047 * falling back to software. If this changes in the future this code will get fooled and
3048 * apps might hit the software path due to incorrectly advertised caps.
3049 *
3050 * Its unlikely that this changes however. GL Games like Mass Effect depend on the filter
3051 * disable fallback, if Apple or ATI ever change the driver behavior they will break more
3052 * than Wine. The Linux binary <= r500 driver is not maintained any more anyway
3053 */
3054
3055 while (gl_info->gl_ops.gl.p_glGetError());
3056
3057 gl_info->gl_ops.gl.p_glGenTextures(1, &buffer);
3058 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
3059 memset(readback, 0x7e, sizeof(readback));
3060 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 1, 0,
3061 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, readback);
3062 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3063 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3064 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3065 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3066 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3067
3068 gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
3069 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
3070 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, internal, 2, 1, 0,
3072 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3073 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3074 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3075 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3076 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3077 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
3078
3079 gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
3080 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3081 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffer, 0);
3082 gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);
3083
3084 gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1);
3085 gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
3086 gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
3087 gl_info->gl_ops.gl.p_glLoadIdentity();
3088 gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
3089 gl_info->gl_ops.gl.p_glLoadIdentity();
3090
3091 gl_info->gl_ops.gl.p_glClearColor(0, 1, 0, 0);
3092 gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
3093
3094 gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
3095 gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 0.0);
3096 gl_info->gl_ops.gl.p_glVertex2f(-1.0f, -1.0f);
3097 gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 0.0);
3098 gl_info->gl_ops.gl.p_glVertex2f(1.0f, -1.0f);
3099 gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 1.0);
3100 gl_info->gl_ops.gl.p_glVertex2f(-1.0f, 1.0f);
3101 gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 1.0);
3102 gl_info->gl_ops.gl.p_glVertex2f(1.0f, 1.0f);
3103 gl_info->gl_ops.gl.p_glEnd();
3104
3105 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
3106 memset(readback, 0x7f, sizeof(readback));
3107 gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
3108 if (color_match(readback[6], 0xffffffff, 5) || color_match(readback[6], 0x00000000, 5)
3109 || color_match(readback[9], 0xffffffff, 5) || color_match(readback[9], 0x00000000, 5))
3110 {
3111 TRACE("Read back colors 0x%08x and 0x%08x close to unfiltered color, assuming no filtering\n",
3112 readback[6], readback[9]);
3113 ret = FALSE;
3114 }
3115 else
3116 {
3117 TRACE("Read back colors are 0x%08x and 0x%08x, assuming texture is filtered\n",
3118 readback[6], readback[9]);
3119 ret = TRUE;
3120 }
3121
3122 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
3123 gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
3124 gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
3125 gl_info->gl_ops.gl.p_glDeleteTextures(1, &buffer);
3126 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
3127
3128 if (gl_info->gl_ops.gl.p_glGetError())
3129 {
3130 FIXME("Error during filtering test for format %x, returning no filtering\n", internal);
3131 ret = FALSE;
3132 }
3133
3134 return ret;
3135}
3136
3138{
3139 struct wined3d_format *format;
3140 unsigned int fmt_idx, i;
3141 static const enum wined3d_format_id fmts16[] =
3142 {
3146 };
3147 BOOL filtered;
3148
3150 /* This was already handled by init_format_texture_info(). */
3151 return;
3152
3155 {
3156 WARN("No FBO support, or no FBO ORM, guessing filter info from GL caps\n");
3158 {
3159 TRACE("Nvidia card with texture_float support: Assuming float16 blending\n");
3160 filtered = TRUE;
3161 }
3162 else if (gl_info->limits.glsl_varyings > 44)
3163 {
3164 TRACE("More than 44 GLSL varyings - assuming d3d10 card with float16 blending\n");
3165 filtered = TRUE;
3166 }
3167 else
3168 {
3169 TRACE("Assuming no float16 blending\n");
3170 filtered = FALSE;
3171 }
3172
3173 if (filtered)
3174 {
3175 for (i = 0; i <