ReactOS  0.4.14-dev-49-gfb4591c
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  BOOL use_glsl_150 = gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50);
2187 
2188  ctx->test_program_id = GL_EXTCALL(glCreateProgram());
2189 
2190  vs_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
2191  source[0] = use_glsl_150 ? vs_core_header : vs_legacy_header;
2192  source[1] = vs_body;
2193  GL_EXTCALL(glShaderSource(vs_id, 2, source, NULL));
2194  GL_EXTCALL(glAttachShader(ctx->test_program_id, vs_id));
2195  GL_EXTCALL(glDeleteShader(vs_id));
2196 
2197  fs_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER));
2198  source[0] = use_glsl_150 ? fs_core : fs_legacy;
2199  GL_EXTCALL(glShaderSource(fs_id, 1, source, NULL));
2200  GL_EXTCALL(glAttachShader(ctx->test_program_id, fs_id));
2201  GL_EXTCALL(glDeleteShader(fs_id));
2202 
2203  GL_EXTCALL(glBindAttribLocation(ctx->test_program_id, 0, "pos"));
2204  GL_EXTCALL(glBindAttribLocation(ctx->test_program_id, 1, "color"));
2205 
2206  if (use_glsl_150)
2207  GL_EXTCALL(glBindFragDataLocation(ctx->test_program_id, 0, "fragment_color"));
2208 
2209  GL_EXTCALL(glCompileShader(vs_id));
2210  print_glsl_info_log(gl_info, vs_id, FALSE);
2211  GL_EXTCALL(glCompileShader(fs_id));
2212  print_glsl_info_log(gl_info, fs_id, FALSE);
2213  GL_EXTCALL(glLinkProgram(ctx->test_program_id));
2215  }
2216  GL_EXTCALL(glUseProgram(ctx->test_program_id));
2217 
2218  gl_info->gl_ops.gl.p_glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2219 
2220  GL_EXTCALL(glUseProgram(0));
2221  GL_EXTCALL(glDisableVertexAttribArray(0));
2222  GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
2223  checkGLcall("draw quad");
2224 }
2225 
2226 /* Context activation is done by the caller. */
2228 {
2229  /* Check if the default internal format is supported as a frame buffer
2230  * target, otherwise fall back to the render target internal.
2231  *
2232  * Try to stick to the standard format if possible, this limits precision differences. */
2233  static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 1.0f};
2234  static const struct wined3d_color half_transparent_red = {1.0f, 0.0f, 0.0f, 0.5f};
2235  const struct wined3d_gl_info *gl_info = ctx->gl_info;
2236  GLenum status, rt_internal = format->rtInternal;
2237  GLuint object, color_rb;
2239  BOOL fallback_fmt_used = FALSE, regular_fmt_used = FALSE;
2240 
2241  gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
2242 
2243  for (type = 0; type < ARRAY_SIZE(format->flags); ++type)
2244  {
2245  const char *type_string = "color";
2246 
2248  continue;
2249 
2250  create_and_bind_fbo_attachment(gl_info, format->flags[type], type, &object, format->glInternal,
2251  format->glFormat, format->glType);
2252 
2254  {
2255  gl_info->fbo_ops.glGenRenderbuffers(1, &color_rb);
2256  gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, color_rb);
2258  gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 1);
2259  else
2260  gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
2261 
2262  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
2264  checkGLcall("Create and attach color rb attachment");
2265  type_string = "depth / stencil";
2266  }
2267 
2268  status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
2269  checkGLcall("Framebuffer format check");
2270 
2272  {
2273  TRACE("Format %s is supported as FBO %s attachment, type %u.\n",
2274  debug_d3dformat(format->id), type_string, type);
2276  format->rtInternal = format->glInternal;
2277  regular_fmt_used = TRUE;
2278  }
2279  else
2280  {
2281  if (!rt_internal)
2282  {
2284  {
2285  WARN("Format %s with rendertarget flag is not supported as FBO color attachment (type %u),"
2286  " and no fallback specified.\n", debug_d3dformat(format->id), type);
2288  }
2289  else
2290  {
2291  TRACE("Format %s is not supported as FBO %s attachment, type %u.\n",
2292  debug_d3dformat(format->id), type_string, type);
2293  }
2294  format->rtInternal = format->glInternal;
2295  }
2296  else
2297  {
2298  TRACE("Format %s is not supported as FBO %s attachment (type %u),"
2299  " trying rtInternal format as fallback.\n",
2300  debug_d3dformat(format->id), type_string, type);
2301 
2302  while (gl_info->gl_ops.gl.p_glGetError());
2303 
2304  delete_fbo_attachment(gl_info, type, object);
2305  create_and_bind_fbo_attachment(gl_info, format->flags[type], type, &object, format->rtInternal,
2306  format->glFormat, format->glType);
2307 
2308  status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
2309  checkGLcall("Framebuffer format check");
2310 
2312  {
2313  TRACE("Format %s rtInternal format is supported as FBO %s attachment, type %u.\n",
2314  debug_d3dformat(format->id), type_string, type);
2315  fallback_fmt_used = TRUE;
2316  }
2317  else
2318  {
2319  WARN("Format %s rtInternal format is not supported as FBO %s attachment, type %u.\n",
2320  debug_d3dformat(format->id), type_string, type);
2322  }
2323  }
2324  }
2325 
2329  && !(format->flags[type] & WINED3DFMT_FLAG_INTEGER)
2330  && format->id != WINED3DFMT_NULL && format->id != WINED3DFMT_P8_UINT
2331  && format->glFormat != GL_LUMINANCE && format->glFormat != GL_LUMINANCE_ALPHA
2332  && (format->red_size || format->alpha_size))
2333  {
2334  DWORD readback[16 * 16 * 16], color, r_range, a_range;
2335  BYTE r, a;
2336  BOOL match = TRUE;
2337  GLuint rb;
2338 
2339  if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
2340  || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
2341  {
2342  gl_info->fbo_ops.glGenRenderbuffers(1, &rb);
2343  gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, rb);
2345  gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 1);
2346  else
2347  gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
2348  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);
2349  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb);
2350  checkGLcall("RB attachment");
2351  }
2352 
2353  gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
2354  gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
2355  gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
2356  if (gl_info->gl_ops.gl.p_glGetError() == GL_INVALID_FRAMEBUFFER_OPERATION)
2357  {
2358  while (gl_info->gl_ops.gl.p_glGetError());
2359  TRACE("Format %s doesn't support post-pixelshader blending, type %u.\n",
2360  debug_d3dformat(format->id), type);
2362  }
2363  else
2364  {
2365  gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
2367  gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1);
2368  else
2369  gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 16);
2370  gl_info->gl_ops.gl.p_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2371 
2372  draw_test_quad(ctx, NULL, &black);
2373 
2374  gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
2375 
2376  draw_test_quad(ctx, NULL, &half_transparent_red);
2377 
2378  gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
2379 
2380  switch (type)
2381  {
2383  /* Rebinding texture to workaround a fglrx bug. */
2384  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, object);
2385  gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_1D, 0, GL_BGRA,
2386  GL_UNSIGNED_INT_8_8_8_8_REV, readback);
2387  color = readback[7];
2388  break;
2389 
2393  /* Rebinding texture to workaround a fglrx bug. */
2394  gl_info->gl_ops.gl.p_glBindTexture(wined3d_gl_type_to_enum(type), object);
2395  gl_info->gl_ops.gl.p_glGetTexImage(wined3d_gl_type_to_enum(type), 0, GL_BGRA,
2396  GL_UNSIGNED_INT_8_8_8_8_REV, readback);
2397  color = readback[7 * 16 + 7];
2398  break;
2399 
2401  /* Rebinding texture to workaround a fglrx bug. */
2402  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, object);
2403  gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_BGRA,
2404  GL_UNSIGNED_INT_8_8_8_8_REV, readback);
2405  color = readback[7 * 16 + 7];
2406  break;
2407 
2409  gl_info->gl_ops.gl.p_glReadPixels(0, 0, 16, 16,
2411  color = readback[7 * 16 + 7];
2412  break;
2413 
2416  color = 0;
2417  break;
2418  }
2419  checkGLcall("Post-pixelshader blending check");
2420 
2421  a = color >> 24;
2422  r = (color & 0x00ff0000u) >> 16;
2423 
2424  r_range = format->red_size < 8 ? 1u << (8 - format->red_size) : 1;
2425  a_range = format->alpha_size < 8 ? 1u << (8 - format->alpha_size) : 1;
2426  if (format->red_size && (r < 0x7f - r_range || r > 0x7f + r_range))
2427  match = FALSE;
2428  else if (format->alpha_size > 1 && (a < 0xbf - a_range || a > 0xbf + a_range))
2429  match = FALSE;
2430  if (!match)
2431  {
2432  TRACE("Format %s doesn't support post-pixelshader blending, type %u.\n",
2433  debug_d3dformat(format->id), type);
2434  TRACE("Color output: %#x\n", color);
2436  }
2437  else
2438  {
2439  TRACE("Format %s supports post-pixelshader blending, type %u.\n",
2440  debug_d3dformat(format->id), type);
2441  TRACE("Color output: %#x\n", color);
2443  }
2444  }
2445 
2446  if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
2447  || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
2448  {
2449  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
2450  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
2451  gl_info->fbo_ops.glDeleteRenderbuffers(1, &rb);
2452  checkGLcall("RB cleanup");
2453  }
2454  }
2455 
2456  if (format->glInternal != format->glGammaInternal)
2457  {
2458  delete_fbo_attachment(gl_info, type, object);
2459  create_and_bind_fbo_attachment(gl_info, format->flags[type], type, &object, format->glGammaInternal,
2460  format->glFormat, format->glType);
2461 
2462  status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
2463  checkGLcall("Framebuffer format check");
2464 
2466  {
2467  TRACE("Format %s's sRGB format is FBO attachable, type %u.\n",
2468  debug_d3dformat(format->id), type);
2470  if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
2471  format->glInternal = format->glGammaInternal;
2472  }
2473  else
2474  {
2475  WARN("Format %s's sRGB format is not FBO attachable, type %u.\n",
2476  debug_d3dformat(format->id), type);
2478  }
2479  }
2480  else if (status == GL_FRAMEBUFFER_COMPLETE)
2482 
2484  {
2485  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
2486  gl_info->fbo_ops.glDeleteRenderbuffers(1, &color_rb);
2487  }
2488 
2489  delete_fbo_attachment(gl_info, type, object);
2490  checkGLcall("Framebuffer format check cleanup");
2491  }
2492 
2493  if (fallback_fmt_used && regular_fmt_used)
2494  {
2495  FIXME("Format %s needs different render target formats for different resource types.\n",
2496  debug_d3dformat(format->id));
2499  }
2500 }
2501 
2502 static void query_format_flag(struct wined3d_gl_info *gl_info, struct wined3d_format *format,
2503  GLint internal, GLenum pname, DWORD flag, const char *string)
2504 {
2505  GLint value;
2507 
2508  for (type = 0; type < ARRAY_SIZE(format->flags); ++type)
2509  {
2510  gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type), internal, pname, 1, &value);
2511  if (value == GL_FULL_SUPPORT)
2512  {
2513  TRACE("Format %s supports %s, resource type %u.\n", debug_d3dformat(format->id), string, type);
2514  format->flags[type] |= flag;
2515  }
2516  else
2517  {
2518  TRACE("Format %s doesn't support %s, resource type %u.\n", debug_d3dformat(format->id), string, type);
2519  format->flags[type] &= ~flag;
2520  }
2521  }
2522 }
2523 
2524 /* Context activation is done by the caller. */
2526 {
2527  const struct wined3d_gl_info *gl_info = ctx->gl_info;
2528  unsigned int i, type;
2529  GLuint fbo;
2530 
2531  if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
2532  {
2533  for (i = 0; i < gl_info->format_count; ++i)
2534  {
2535  GLint value;
2536  struct wined3d_format *format = &gl_info->formats[i];
2537  BOOL fallback_fmt_used = FALSE, regular_fmt_used = FALSE;
2538  GLenum rt_internal = format->rtInternal;
2539 
2540  if (!format->glInternal)
2541  continue;
2542 
2543  for (type = 0; type < ARRAY_SIZE(format->flags); ++type)
2544  {
2545  gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2546  format->glInternal, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
2547  if (value == GL_FULL_SUPPORT)
2548  {
2549  TRACE("Format %s is supported as FBO color attachment, resource type %u.\n",
2550  debug_d3dformat(format->id), type);
2552  format->rtInternal = format->glInternal;
2553  regular_fmt_used = TRUE;
2554 
2555  gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2556  format->glInternal, GL_FRAMEBUFFER_BLEND, 1, &value);
2557  if (value == GL_FULL_SUPPORT)
2558  {
2559  TRACE("Format %s supports post-pixelshader blending, resource type %u.\n",
2560  debug_d3dformat(format->id), type);
2562  }
2563  else
2564  {
2565  TRACE("Format %s doesn't support post-pixelshader blending, resource typed %u.\n",
2566  debug_d3dformat(format->id), type);
2568  }
2569  }
2570  else
2571  {
2572  if (!rt_internal)
2573  {
2575  {
2576  WARN("Format %s with rendertarget flag is not supported as FBO color attachment"
2577  " and no fallback specified, resource type %u.\n",
2578  debug_d3dformat(format->id), type);
2580  }
2581  else
2582  TRACE("Format %s is not supported as FBO color attachment,"
2583  " resource type %u.\n", debug_d3dformat(format->id), type);
2584  format->rtInternal = format->glInternal;
2585  }
2586  else
2587  {
2588  gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2589  rt_internal, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
2590  if (value == GL_FULL_SUPPORT)
2591  {
2592  TRACE("Format %s rtInternal format is supported as FBO color attachment,"
2593  " resource type %u.\n", debug_d3dformat(format->id), type);
2594  fallback_fmt_used = TRUE;
2595  }
2596  else
2597  {
2598  WARN("Format %s rtInternal format is not supported as FBO color attachment,"
2599  " resource type %u.\n", debug_d3dformat(format->id), type);
2601  }
2602  }
2603  }
2604 
2605  if (format->glInternal != format->glGammaInternal)
2606  {
2607  gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2608  format->glGammaInternal, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
2609  if (value == GL_FULL_SUPPORT)
2610  {
2611  TRACE("Format %s's sRGB format is FBO attachable, resource type %u.\n",
2612  debug_d3dformat(format->id), type);
2614  if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
2615  format->glInternal = format->glGammaInternal;
2616  }
2617  else
2618  {
2619  WARN("Format %s's sRGB format is not FBO attachable, resource type %u.\n",
2620  debug_d3dformat(format->id), type);
2622  }
2623  }
2624  else if (format->flags[type] & WINED3DFMT_FLAG_FBO_ATTACHABLE)
2626  }
2627 
2628  if (fallback_fmt_used && regular_fmt_used)
2629  {
2630  FIXME("Format %s needs different render target formats for different resource types.\n",
2631  debug_d3dformat(format->id));
2634  }
2635  }
2636  return;
2637  }
2638 
2640  {
2641  gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
2642  gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2643  gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);
2644  gl_info->gl_ops.gl.p_glReadBuffer(GL_COLOR_ATTACHMENT0);
2645  }
2646 
2647  for (i = 0; i < gl_info->format_count; ++i)
2648  {
2649  struct wined3d_format *format = &gl_info->formats[i];
2650 
2651  if (!format->glInternal) continue;
2652 
2654  {
2655  TRACE("Skipping format %s because it's a compressed format.\n",
2656  debug_d3dformat(format->id));
2657  continue;
2658  }
2659 
2661  {
2662  TRACE("Checking if format %s is supported as FBO color attachment...\n", debug_d3dformat(format->id));
2663  check_fbo_compat(ctx, format);
2664  }
2665  else
2666  {
2667  format->rtInternal = format->glInternal;
2668  }
2669  }
2670 
2672  gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
2673 }
2674 
2675 static GLenum lookup_gl_view_class(GLenum internal_format)
2676 {
2677  static const struct
2678  {
2679  GLenum internal_format;
2680  GLenum view_class;
2681  }
2682  view_classes[] =
2683  {
2684  /* 128-bit */
2688  /* 96-bit */
2692  /* 64-bit */
2701  /* 48-bit */
2707  /* 32-bit */
2725  /* 24-bit */
2731  /* 16-bit */
2741  /* 8-bit */
2746 
2747  /* RGTC1 */
2750  /* RGTC2 */
2753 
2754  /* BPTC unorm */
2757  /* BPTC float */
2760 
2761  /* DXT1 RGB */
2764  /* DXT1 RGBA */
2767  /* DXT3 */
2770  /* DXT5 */
2773  };
2774 
2775  unsigned int i;
2776 
2777  for (i = 0; i < ARRAY_SIZE(view_classes); ++i)
2778  {
2779  if (view_classes[i].internal_format == internal_format)
2780  return view_classes[i].view_class;
2781  }
2782 
2783  return GL_NONE;
2784 }
2785 
2787 {
2788  GLenum internal_view_class, gamma_view_class, rt_view_class;
2789 
2790  internal_view_class = lookup_gl_view_class(format->glInternal);
2791  gamma_view_class = lookup_gl_view_class(format->glGammaInternal);
2792  rt_view_class = lookup_gl_view_class(format->rtInternal);
2793 
2794  if (internal_view_class == gamma_view_class || gamma_view_class == rt_view_class)
2795  {
2796  format->gl_view_class = internal_view_class;
2797  TRACE("Format %s is member of GL view class %#x.\n",
2798  debug_d3dformat(format->id), format->gl_view_class);
2799  }
2800  else
2801  {
2802  format->gl_view_class = GL_NONE;
2803  }
2804 }
2805 
2806 static void query_internal_format(struct wined3d_adapter *adapter,
2807  struct wined3d_format *format, const struct wined3d_format_texture_info *texture_info,
2808  struct wined3d_gl_info *gl_info, BOOL srgb_write_supported, BOOL srgb_format)
2809 {
2811  unsigned int i, max_log2;
2812  GLenum target;
2813 
2814  if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
2815  {
2816  query_format_flag(gl_info, format, format->glInternal, GL_VERTEX_TEXTURE,
2817  WINED3DFMT_FLAG_VTF, "vertex texture usage");
2818  query_format_flag(gl_info, format, format->glInternal, GL_FILTER,
2819  WINED3DFMT_FLAG_FILTERING, "filtering");
2820 
2821  if (srgb_format || format->glGammaInternal != format->glInternal)
2822  {
2823  query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_READ,
2824  WINED3DFMT_FLAG_SRGB_READ, "sRGB read");
2825 
2826  if (srgb_write_supported)
2827  query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_WRITE,
2828  WINED3DFMT_FLAG_SRGB_WRITE, "sRGB write");
2829  else
2831 
2833  format->glGammaInternal = format->glInternal;
2835  && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
2836  format->glInternal = format->glGammaInternal;
2837  }
2838  }
2839  else
2840  {
2841  if (!gl_info->limits.samplers[WINED3D_SHADER_TYPE_VERTEX])
2843 
2844  if (!(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
2848 
2849  if (srgb_format || format->glGammaInternal != format->glInternal)
2850  {
2851  /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */
2852  if (!gl_info->supported[EXT_TEXTURE_SRGB])
2853  {
2854  format->glGammaInternal = format->glInternal;
2856  }
2858  && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
2859  {
2860  format->glInternal = format->glGammaInternal;
2861  }
2862  }
2863 
2864  if ((format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_SRGB_WRITE) && !srgb_write_supported)
2866 
2867  if (!gl_info->supported[ARB_DEPTH_TEXTURE]
2868  && texture_info->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
2869  {
2875  }
2876  }
2877 
2879 
2880  if (format->glInternal && format->flags[WINED3D_GL_RES_TYPE_RB]
2882  {
2883  if (gl_info->supported[ARB_INTERNALFORMAT_QUERY])
2884  {
2886  count = 0;
2887  GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
2888  GL_NUM_SAMPLE_COUNTS, 1, &count));
2890  GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
2892  checkGLcall("query sample counts");
2893  for (i = 0; i < count; ++i)
2894  {
2895  if (multisample_types[i] > sizeof(format->multisample_types) * CHAR_BIT)
2896  continue;
2897  format->multisample_types |= 1u << (multisample_types[i] - 1);
2898  }
2899  }
2900  else
2901  {
2902 #ifdef __REACTOS__
2903  if (gl_info->limits.samples) {
2904 #endif
2905  max_log2 = wined3d_log2i(min(gl_info->limits.samples,
2906  sizeof(format->multisample_types) * CHAR_BIT));
2907  for (i = 1; i <= max_log2; ++i)
2908  format->multisample_types |= 1u << ((1u << i) - 1);
2909 #ifdef __REACTOS__
2910  }
2911 #endif
2912  }
2913  }
2914 }
2915 
2916 static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct wined3d_gl_info *gl_info)
2917 {
2918  struct wined3d_format *format, *srgb_format;
2920  struct shader_caps shader_caps;
2921  unsigned int i, j;
2922  BOOL srgb_write;
2923 
2924  adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
2925  adapter->shader_backend->shader_get_caps(gl_info, &shader_caps);
2928 
2929  for (i = 0; i < ARRAY_SIZE(format_texture_info); ++i)
2930  {
2931  if (!(format = get_format_internal(gl_info, format_texture_info[i].id)))
2932  return FALSE;
2933 
2934  if (!gl_info->supported[format_texture_info[i].extension])
2935  continue;
2936 
2937  /* ARB_texture_rg defines floating point formats, but only if
2938  * ARB_texture_float is also supported. */
2939  if (!gl_info->supported[ARB_TEXTURE_FLOAT]
2941  continue;
2942 
2943  /* ARB_texture_rg defines integer formats if EXT_texture_integer is also supported. */
2944  if (!gl_info->supported[EXT_TEXTURE_INTEGER]
2946  continue;
2947 
2948  format->glInternal = format_texture_info[i].gl_internal;
2949  format->glGammaInternal = format_texture_info[i].gl_srgb_internal;
2950  format->rtInternal = format_texture_info[i].gl_rt_internal;
2951  format->glFormat = format_texture_info[i].gl_format;
2952  format->glType = format_texture_info[i].gl_type;
2953  format->color_fixup = COLOR_FIXUP_IDENTITY;
2954  format->height_scale.numerator = 1;
2955  format->height_scale.denominator = 1;
2956 
2960 
2961  /* GL_ARB_depth_texture does not support 3D textures. It also says "cube textures are
2962  * problematic", but doesn't explicitly mandate that an error is generated. */
2963  if (gl_info->supported[EXT_TEXTURE3D]
2966 
2967  if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
2969 
2970  if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
2972 
2975 
2976  if (format->glGammaInternal != format->glInternal
2977  && !(adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL))
2978  {
2979  format->glGammaInternal = format->glInternal;
2981  }
2982 
2983  query_internal_format(adapter, format, &format_texture_info[i], gl_info, srgb_write, FALSE);
2984 
2985  /* Texture conversion stuff */
2986  format->conv_byte_count = format_texture_info[i].conv_byte_count;
2987  format->upload = format_texture_info[i].upload;
2988  format->download = format_texture_info[i].download;
2989 
2990  srgb_format = NULL;
2991  for (j = 0; j < ARRAY_SIZE(format_srgb_info); ++j)
2992  {
2993  if (format_srgb_info[j].base_format_id == format->id)
2994  {
2995  if (!(srgb_format = get_format_internal(gl_info, format_srgb_info[j].srgb_format_id)))
2996  return FALSE;
2997  break;
2998  }
2999  }
3000  if (!srgb_format)
3001  continue;
3002 
3003  copy_format(srgb_format, format);
3004 
3005  if (gl_info->supported[EXT_TEXTURE_SRGB]
3006  && !(adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL))
3007  {
3008  srgb_format->glInternal = format_texture_info[i].gl_srgb_internal;
3009  srgb_format->glGammaInternal = format_texture_info[i].gl_srgb_internal;
3011  query_internal_format(adapter, srgb_format, &format_texture_info[i], gl_info, srgb_write, TRUE);
3012  }
3013  }
3014 
3015  return TRUE;
3016 }
3017 
3018 static BOOL color_match(DWORD c1, DWORD c2, BYTE max_diff)
3019 {
3020  if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
3021  c1 >>= 8; c2 >>= 8;
3022  if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
3023  c1 >>= 8; c2 >>= 8;
3024  if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
3025  c1 >>= 8; c2 >>= 8;
3026  if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
3027  return TRUE;
3028 }
3029 
3030 /* A context is provided by the caller */
3031 static BOOL check_filter(const struct wined3d_gl_info *gl_info, GLenum internal)
3032 {
3033  static const DWORD data[] = {0x00000000, 0xffffffff};
3034  GLuint tex, fbo, buffer;
3035  DWORD readback[16 * 1];
3036  BOOL ret = FALSE;
3037 
3038  /* Render a filtered texture and see what happens. This is intended to detect the lack of
3039  * float16 filtering on ATI X1000 class cards. The drivers disable filtering instead of
3040  * falling back to software. If this changes in the future this code will get fooled and
3041  * apps might hit the software path due to incorrectly advertised caps.
3042  *
3043  * Its unlikely that this changes however. GL Games like Mass Effect depend on the filter
3044  * disable fallback, if Apple or ATI ever change the driver behavior they will break more
3045  * than Wine. The Linux binary <= r500 driver is not maintained any more anyway
3046  */
3047 
3048  while (gl_info->gl_ops.gl.p_glGetError());
3049 
3050  gl_info->gl_ops.gl.p_glGenTextures(1, &buffer);
3051  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
3052  memset(readback, 0x7e, sizeof(readback));
3053  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 1, 0,
3054  GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, readback);
3055  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3056  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3057  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3058  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3059  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3060 
3061  gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
3062  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
3063  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, internal, 2, 1, 0,
3065  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3066  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3067  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3068  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3069  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3070  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
3071 
3072  gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
3073  gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3074  gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffer, 0);
3075  gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);
3076 
3077  gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1);
3078  gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
3079  gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
3080  gl_info->gl_ops.gl.p_glLoadIdentity();
3081  gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
3082  gl_info->gl_ops.gl.p_glLoadIdentity();
3083 
3084  gl_info->gl_ops.gl.p_glClearColor(0, 1, 0, 0);
3085  gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
3086 
3087  gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
3088  gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 0.0);
3089  gl_info->gl_ops.gl.p_glVertex2f(-1.0f, -1.0f);
3090  gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 0.0);
3091  gl_info->gl_ops.gl.p_glVertex2f(1.0f, -1.0f);
3092  gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 1.0);
3093  gl_info->gl_ops.gl.p_glVertex2f(-1.0f, 1.0f);
3094  gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 1.0);
3095  gl_info->gl_ops.gl.p_glVertex2f(1.0f, 1.0f);
3096  gl_info->gl_ops.gl.p_glEnd();
3097 
3098  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
3099  memset(readback, 0x7f, sizeof(readback));
3100  gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
3101  if (color_match(readback[6], 0xffffffff, 5) || color_match(readback[6], 0x00000000, 5)
3102  || color_match(readback[9], 0xffffffff, 5) || color_match(readback[9], 0x00000000, 5))
3103  {
3104  TRACE("Read back colors 0x%08x and 0x%08x close to unfiltered color, assuming no filtering\n",
3105  readback[6], readback[9]);
3106  ret = FALSE;
3107  }
3108  else
3109  {
3110  TRACE("Read back colors are 0x%08x and 0x%08x, assuming texture is filtered\n",
3111  readback[6], readback[9]);
3112  ret = TRUE;
3113  }
3114 
3115  gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
3116  gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
3117  gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
3118  gl_info->gl_ops.gl.p_glDeleteTextures(1, &buffer);
3119  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
3120 
3121  if (gl_info->gl_ops.gl.p_glGetError())
3122  {
3123  FIXME("Error during filtering test for format %x, returning no filtering\n", internal);
3124  ret = FALSE;
3125  }
3126 
3127  return ret;
3128 }
3129 
3131 {
3132  struct wined3d_format *format;
3133  unsigned int fmt_idx, i;
3134  static const enum wined3d_format_id fmts16[] =
3135  {
3139  };
3140  BOOL filtered;
3141 
3142  if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
3143  /* This was already handled by init_format_texture_info(). */
3144  return;
3145 
3147  || !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
3148  {
3149  WARN("No FBO support, or no FBO ORM, guessing filter info from GL caps\n");
3150  if (vendor == HW_VENDOR_NVIDIA && gl_info->supported[ARB_TEXTURE_FLOAT])
3151  {
3152  TRACE("Nvidia card with texture_float support: Assuming float16 blending\n");
3153  filtered = TRUE;
3154  }
3155  else if (gl_info->limits.glsl_varyings > 44)
3156  {
3157  TRACE("More than 44 GLSL varyings - assuming d3d10 card with float16 blending\n");
3158  filtered = TRUE;
3159  }
3160  else
3161  {
3162  TRACE("Assuming no float16 blending\n");
3163  filtered = FALSE;
3164  }
3165 
3166  if (filtered)
3167  {
3168  for (i = 0; i < ARRAY_SIZE(fmts16); ++i)
3169  {
3170  fmt_idx = get_format_idx(fmts16[i]);
3171  format_set_flag(&gl_info->formats[fmt_idx], WINED3DFMT_FLAG_FILTERING);
3172  }
3173  }
3174  return;
3175  }
3176 
3177  for (i = 0; i < ARRAY_SIZE(fmts16); ++i)
3178  {
3179  fmt_idx = get_format_idx(fmts16[i]);
3180  format = &gl_info->formats[fmt_idx];
3181  if (!format->glInternal) continue; /* Not supported by GL */
3182 
3183  filtered = check_filter(gl_info, gl_info->formats[fmt_idx].glInternal);
3184  if (filtered)
3185  {
3186  TRACE("Format %s supports filtering\n", debug_d3dformat(fmts16[i]));
3188  }
3189  else
3190  {
3191  TRACE("Format %s does not support filtering\n", debug_d3dformat(fmts16[i]));
3192  }
3193  }
3194 }
3195 
3196 static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_gl_info *gl_info)
3197 {
3198  unsigned int i;
3199  int idx;
3200 
3202  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3204 
3206  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3208 
3210  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3212 
3214  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3216 
3218  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3220 
3221  /* GL_ATI_envmap_bumpmap in theory supports R8G8_SNORM but is no longer supported by
3222  * any driver. */
3223  if (gl_info->supported[NV_TEXTURE_SHADER] || gl_info->supported[EXT_TEXTURE_SNORM])
3224  {
3225  /* R8G8_SNORM and R16G16_SNORM need a fixup of the undefined blue channel. OpenGL
3226  * returns 0.0 when sampling from it, DirectX 1.0. So we always have in-shader
3227  * conversion for this format. */
3229  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3232  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3234  }
3235  else
3236  {
3237  /* Emulate using unsigned formats. This requires load-time conversion in addition to the
3238  * fixups here. */
3240  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3243  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3246  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3249  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3251  }
3252 
3253  if (!gl_info->supported[NV_TEXTURE_SHADER])
3254  {
3256  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3258  }
3259 
3261  {
3263  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3265 
3267  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3269  }
3270  else if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC])
3271  {
3273  gl_info->formats[idx].color_fixup= create_color_fixup_desc(
3275  }
3276 
3277  if (!gl_info->supported[APPLE_YCBCR_422] && gl_info->supported[ARB_FRAGMENT_PROGRAM]
3278  && gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
3279  {
3281  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YUY2);
3282 
3284  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_UYVY);
3285  }
3286  else if (!gl_info->supported[APPLE_YCBCR_422] && (!gl_info->supported[ARB_FRAGMENT_PROGRAM]
3287  || !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT]))
3288  {
3290  gl_info->formats[idx].glInternal = 0;
3291 
3293  gl_info->formats[idx].glInternal = 0;
3294  }
3295 
3297  {
3300  gl_info->formats[idx].height_scale.numerator = 3;
3301  gl_info->formats[idx].height_scale.denominator = 2;
3302  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YV12);
3303 
3306  gl_info->formats[idx].height_scale.numerator = 3;
3307  gl_info->formats[idx].height_scale.denominator = 2;
3308  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_NV12);
3309  }
3310  else
3311  {
3313  gl_info->formats[idx].glInternal = 0;
3314 
3316  gl_info->formats[idx].glInternal = 0;
3317  }
3318 
3319  if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
3320  {
3322  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3325  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3328  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3331  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3334  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3336  }
3337 
3338  if (gl_info->supported[ARB_TEXTURE_RG])
3339  {
3341  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3343  }
3344 
3345  if (gl_info->supported[ARB_FRAGMENT_PROGRAM])
3346  {
3348  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8);
3349  }
3350 
3351  if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
3352  {
3354  gl_info->formats[idx].gl_vtx_format = GL_BGRA;
3355  }
3356 
3357  if (!gl_info->supported[ARB_HALF_FLOAT_VERTEX])
3358  {
3359  /* Do not change the size of the type, it is CPU side. We have to change the GPU-side information though.
3360  * It is the job of the vertex buffer code to make sure that the vbos have the right format */
3362  gl_info->formats[idx].gl_vtx_type = GL_FLOAT;
3363 
3365  gl_info->formats[idx].gl_vtx_type = GL_FLOAT;
3366  }
3367 
3368  if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
3369  {
3372 
3375 
3378  }
3379 
3380  if (gl_info->quirks & WINED3D_QUIRK_BROKEN_RGBA16)
3381  {
3384  }
3385 
3386  /* ATI instancing hack: Although ATI cards do no