ReactOS  0.4.14-dev-606-g14ebc0b
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 
38 static 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 
81 static 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 
309 static const struct wined3d_format_ddi_info ddi_formats[] =
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 
445 static 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 
473 static 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 
505 static 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 
544 static 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 
590 static 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 
615 static 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 
644 static 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 
673 static 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 
699 static 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 
724 static 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 
752 static 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 
778 static 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 
803 static 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 
824 static 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 
846 static 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 
868 static 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 
898 static 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 
934 static 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 
957 static 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 
980 static 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 
1001 static 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 
1024 static 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  */
1128  GL_RG, GL_UNSIGNED_BYTE, 0,
1130  ARB_TEXTURE_RG, NULL},
1140  GL_RG, GL_UNSIGNED_BYTE, 0,
1142  ARB_TEXTURE_RG, NULL},
1151  {WINED3DFMT_YV12, GL_R8, GL_R8, 0,
1154  ARB_TEXTURE_RG, NULL},
1159  {WINED3DFMT_NV12, GL_R8, GL_R8, 0,
1162  ARB_TEXTURE_RG, NULL},
1218  GL_RG, GL_UNSIGNED_BYTE, 0,
1223  GL_RG, GL_UNSIGNED_BYTE, 0,
1242  /* IEEE formats */
1244  GL_RED, GL_FLOAT, 0,
1248  GL_RED, GL_FLOAT, 0,
1250  ARB_TEXTURE_RG, NULL},
1252  GL_RGB, GL_FLOAT, 12,
1256  GL_RG, GL_FLOAT, 0,
1258  ARB_TEXTURE_RG, NULL},
1260  GL_RGB, GL_FLOAT, 0,
1264  GL_RGBA, GL_FLOAT, 0,
1267  /* Float */
1275  ARB_TEXTURE_RG, NULL},
1283  ARB_TEXTURE_RG, NULL},
1293  /* Palettized formats */
1296  0,
1297  ARB_TEXTURE_RG, NULL},
1300  0,
1302  /* Standard ARGB formats */
1350  ARB_TEXTURE_RG, NULL},
1354  ARB_TEXTURE_RG, NULL},
1394  ARB_TEXTURE_RG, NULL},
1406  GL_RG, GL_UNSIGNED_BYTE, 0,
1409  ARB_TEXTURE_RG, NULL},
1413  ARB_TEXTURE_RG, NULL},
1415  GL_RG_INTEGER, GL_BYTE, 0,
1417  ARB_TEXTURE_RG, NULL},
1429  ARB_TEXTURE_RG, NULL},
1431  GL_RG_INTEGER, GL_INT, 0,
1433  ARB_TEXTURE_RG, NULL},
1437  ARB_TEXTURE_RG, NULL},
1439  GL_RG_INTEGER, GL_SHORT, 0,
1441  ARB_TEXTURE_RG, NULL},
1445  ARB_TEXTURE_RG, NULL},
1447  GL_RED_INTEGER, GL_INT, 0,
1449  ARB_TEXTURE_RG, NULL},
1454  ARB_TEXTURE_RG, NULL},
1458  ARB_TEXTURE_RG, NULL},
1462  ARB_TEXTURE_RG, NULL},
1466  ARB_TEXTURE_RG, NULL},
1468  GL_RED_INTEGER, GL_BYTE, 0,
1470  ARB_TEXTURE_RG, NULL},
1471  /* Luminance */
1481  ARB_TEXTURE_RG, NULL},
1483  GL_RG, GL_UNSIGNED_BYTE, 0,
1485  ARB_TEXTURE_RG, NULL},
1492  GL_RG, GL_UNSIGNED_BYTE, 2,
1502  ARB_TEXTURE_RG, NULL},
1507  /* Bump mapping stuff */
1514  GL_DSDT_NV, GL_BYTE, 0,
1519  GL_RG, GL_BYTE, 0,
1529  GL_DSDT_MAG_NV, GL_BYTE, 3,
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 */
1684  GL_RGBA_INTEGER, GL_INT, 0,
1691  /* Vendor-specific formats */
1708  GL_RG, GL_UNSIGNED_BYTE, 0,
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 
1766 static struct wined3d_format *get_format_internal(struct wined3d_gl_info *gl_info,
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 
1780 static 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 
1787 static 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 
1795 static 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 
1928 fail:
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;
1965  return GL_TEXTURE_CUBE_MAP_ARB;
1967  return GL_TEXTURE_RECTANGLE_ARB;
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 
1979 static 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. */
2003 static void create_and_bind_fbo_attachment(const struct wined3d_gl_info *gl_info, unsigned int flags,
2004  enum wined3d_gl_resource_type d3d_type, GLuint *object, GLenum internal, GLenum format, GLenum type)
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);
2044  GL_EXTCALL(glTexImage3D(GL_TEXTURE_3D, 0, internal, 16, 16, 16, 0, format, type, NULL));
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 
2104 static 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 
2157  if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] || !gl_info->supported[ARB_VERTEX_SHADER]
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));
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);
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);
2329  }
2330  }
2331  }
2332 
2336  && !(format->flags[type] & WINED3DFMT_FLAG_INTEGER)
2337  && format->id != WINED3DFMT_NULL && format->id != WINED3DFMT_P8_UINT
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]
2347  || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
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",
2367  debug_d3dformat(format->id), type);
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",
2440  debug_d3dformat(format->id), type);
2441  TRACE("Color output: %#x\n", color);
2443  }
2444  else
2445  {
2446  TRACE("Format %s supports post-pixelshader blending, type %u.\n",
2447  debug_d3dformat(format->id), type);
2448  TRACE("Color output: %#x\n", color);
2450  }
2451  }
2452 
2453  if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
2454  || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
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",
2475  debug_d3dformat(format->id), type);
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",
2483  debug_d3dformat(format->id), type);
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 
2509 static 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 
2538  if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
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",
2557  debug_d3dformat(format->id), type);
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",
2567  debug_d3dformat(format->id), type);
2569  }
2570  else
2571  {
2572  TRACE("Format %s doesn't support post-pixelshader blending, resource typed %u.\n",
2573  debug_d3dformat(format->id), type);
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",
2585  debug_d3dformat(format->id), type);
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);
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",
2619  debug_d3dformat(format->id), type);
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",
2627  debug_d3dformat(format->id), type);
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));
2670  check_fbo_compat(ctx, format);
2671  }
2672  else
2673  {
2674  format->rtInternal = format->glInternal;
2675  }
2676  }
2677 
2679  gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
2680 }
2681 
2682 static 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 
2813 static void query_internal_format(struct wined3d_adapter *adapter,
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 
2821  if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
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;
2842  && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
2843  format->glInternal = format->glGammaInternal;
2844  }
2845  }
2846  else
2847  {
2848  if (!gl_info->limits.samplers[WINED3D_SHADER_TYPE_VERTEX])
2850 
2851  if (!(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
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  }
2865  && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
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]
2875  && texture_info->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
2876  {
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,
2895  GL_NUM_SAMPLE_COUNTS, 1, &count));
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 
2923 static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct wined3d_gl_info *gl_info)
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 
2974  if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
2976 
2977  if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
2979 
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 
2990  query_internal_format(adapter, format, &format_texture_info[i], gl_info, srgb_write, FALSE);
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 
3025 static 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 */
3038 static 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 
3149  if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
3150  /* This was already handled by init_format_texture_info(). */
3151  return;
3152 
3154  || !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
3155  {
3156  WARN("No FBO support, or no FBO ORM, guessing filter info from GL caps\n");
3157  if (vendor == HW_VENDOR_NVIDIA && gl_info->supported[ARB_TEXTURE_FLOAT])
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 < ARRAY_SIZE(fmts16); ++i)
3176  {
3177  fmt_idx = get_format_idx(fmts16[i]);
3178  format_set_flag(&gl_info->formats[fmt_idx], WINED3DFMT_FLAG_FILTERING);
3179  }
3180  }
3181  return;
3182  }
3183 
3184  for (i = 0; i < ARRAY_SIZE(fmts16); ++i)
3185  {
3186  fmt_idx = get_format_idx(fmts16[i]);
3187  format = &gl_info->formats[fmt_idx];
3188  if (!format->glInternal) continue; /* Not supported by GL */
3189 
3190  filtered = check_filter(gl_info, gl_info->formats[fmt_idx].glInternal);
3191  if (filtered)
3192  {
3193  TRACE("Format %s supports filtering\n", debug_d3dformat(fmts16[i]));
3195  }
3196  else
3197  {
3198  TRACE("Format %s does not support filtering\n", debug_d3dformat(fmts16[i]));
3199  }
3200  }
3201 }
3202 
3203 static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_gl_info *gl_info)
3204 {
3205  unsigned int i;
3206  int idx;
3207 
3209  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3211 
3213  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3215 
3217  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3219 
3221  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3223 
3225  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3227 
3228  /* GL_ATI_envmap_bumpmap in theory supports R8G8_SNORM but is no longer supported by
3229  * any driver. */
3230  if (gl_info->supported[NV_TEXTURE_SHADER] || gl_info->supported[EXT_TEXTURE_SNORM])
3231  {
3232  /* R8G8_SNORM and R16G16_SNORM need a fixup of the undefined blue channel. OpenGL
3233  * returns 0.0 when sampling from it, DirectX 1.0. So we always have in-shader
3234  * conversion for this format. */
3236  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3239  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3241  }
3242  else
3243  {
3244  /* Emulate using unsigned formats. This requires load-time conversion in addition to the
3245  * fixups here. */
3247  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3250  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3253  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3256  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3258  }
3259 
3260  if (!gl_info->supported[NV_TEXTURE_SHADER])
3261  {
3263  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3265  }
3266 
3268  {
3270  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3272 
3274  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3276  }
3277  else if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC])
3278  {
3280  gl_info->formats[idx].color_fixup= create_color_fixup_desc(
3282  }
3283 
3284  if (!gl_info->supported[APPLE_YCBCR_422] && gl_info->supported[ARB_FRAGMENT_PROGRAM]
3285  && gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
3286  {
3288  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YUY2);
3289 
3291  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_UYVY);
3292  }
3293  else if (!gl_info->supported[APPLE_YCBCR_422] && (!gl_info->supported[ARB_FRAGMENT_PROGRAM]
3294  || !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]))
3295  {
3297  gl_info->formats[idx].glInternal = 0;
3298 
3300  gl_info->formats[idx].glInternal = 0;
3301  }
3302 
3304  {
3307  gl_info->formats[idx].height_scale.numerator = 3;
3308  gl_info->formats[idx].height_scale.denominator = 2;
3309  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YV12);
3310 
3313  gl_info->formats[idx].height_scale.numerator = 3;
3314  gl_info->formats[idx].height_scale.denominator = 2;
3315  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_NV12);
3316  }
3317  else
3318  {
3320  gl_info->formats[idx].glInternal = 0;
3321 
3323  gl_info->formats[idx].glInternal = 0;
3324  }
3325 
3326  if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
3327  {
3329  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3332  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3335  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3338  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3341  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3343  }
3344 
3345  if (gl_info->supported[ARB_TEXTURE_RG])
3346  {
3348  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3350  }
3351 
3352  if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
3353  {
3355  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8);
3356  }
3357 
3358  if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
3359  {
3361  gl_info->formats[idx].gl_vtx_format = GL_BGRA;
3362  }
3363 
3364  if (!gl_info->supported[ARB_HALF_FLOAT_VERTEX])
3365  {
3366  /* Do not change the size of the type, it is CPU side. We have to change the GPU-side information though.
3367  * It is the job of the vertex buffer code to make sure that the vbos have the right format */
3369  gl_info->formats[idx].gl_vtx_type = GL_FLOAT;
3370 
3372  gl_info->formats[idx].gl_vtx_type = GL_FLOAT;
3373  }
3374 
3375  if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
3376  {
3379 
3382 
3385  }
3386 
3387  if (gl_info->quirks & WINED3D_QUIRK_BROKEN_RGBA16)
3388  {
3389