ReactOS  0.4.13-dev-257-gfabbd7c
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_R10G11B11_SNORM, 10, 11, 11, 0, 0, 10, 21, 0, 4, 0, 0},
126  {WINED3DFMT_R10G10B10X2_UINT, 10, 10, 10, 0, 0, 10, 20, 0, 4, 0, 0},
127  {WINED3DFMT_R10G10B10X2_SNORM, 10, 10, 10, 0, 0, 10, 20, 0, 4, 0, 0},
128  {WINED3DFMT_R10G10B10_SNORM_A2_UNORM, 10, 10, 10, 2, 0, 10, 20, 30, 4, 0, 0},
129  /* Depth stencil formats */
130  {WINED3DFMT_D16_LOCKABLE, 0, 0, 0, 0, 0, 0, 0, 0, 2, 16, 0},
131  {WINED3DFMT_D32_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 0},
132  {WINED3DFMT_S1_UINT_D15_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 2, 15, 1},
133  {WINED3DFMT_X8D24_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 0},
134  {WINED3DFMT_S4X4_UINT_D24_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 4},
135  {WINED3DFMT_S8_UINT_D24_FLOAT, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 8},
136  /* Vendor-specific formats */
137  {WINED3DFMT_ATI1N, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
138  {WINED3DFMT_ATI2N, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
139  {WINED3DFMT_NVDB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
140  {WINED3DFMT_INST, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
141  {WINED3DFMT_INTZ, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 8},
142  {WINED3DFMT_RESZ, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
143  {WINED3DFMT_NVHU, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
144  {WINED3DFMT_NVHS, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
145  {WINED3DFMT_NULL, 8, 8, 8, 8, 0, 8, 16, 24, 4, 0, 0},
146  /* Unsure about them, could not find a Windows driver that supports them */
147  {WINED3DFMT_R16, 16, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
148  {WINED3DFMT_AL16, 0, 0, 0, 16, 0, 0, 0, 16, 4, 0, 0},
149  /* DirectX 10 HDR formats */
150  {WINED3DFMT_R9G9B9E5_SHAREDEXP, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0},
151  /* Typeless */
152  {WINED3DFMT_R32G32B32A32_TYPELESS, 32, 32, 32, 32, 0, 32, 64, 96, 16, 0, 0},
153  {WINED3DFMT_R32G32B32_TYPELESS, 32, 32, 32, 0, 0, 32, 64, 0, 12, 0, 0},
154  {WINED3DFMT_R16G16B16A16_TYPELESS, 16, 16, 16, 16, 0, 16, 32, 48, 8, 0, 0},
155  {WINED3DFMT_R32G32_TYPELESS, 32, 32, 0, 0, 0, 32, 0, 0, 8, 0, 0},
156  {WINED3DFMT_R32G8X24_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 8, 32, 8},
157  {WINED3DFMT_R10G10B10A2_TYPELESS, 10, 10, 10, 2, 0, 10, 20, 30, 4, 0, 0},
158  {WINED3DFMT_R8G8B8A8_TYPELESS, 8, 8, 8, 8, 0, 8, 16, 24, 4, 0, 0},
159  {WINED3DFMT_R16G16_TYPELESS, 16, 16, 0, 0, 0, 16, 0, 0, 4, 0, 0},
160  {WINED3DFMT_R32_TYPELESS, 32, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0},
161  {WINED3DFMT_R24G8_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 8},
162  {WINED3DFMT_R8G8_TYPELESS, 8, 8, 0, 0, 0, 8, 0, 0, 2, 0, 0},
163  {WINED3DFMT_R16_TYPELESS, 16, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
164  {WINED3DFMT_R8_TYPELESS, 8, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
165  {WINED3DFMT_BC1_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
166  {WINED3DFMT_BC2_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
167  {WINED3DFMT_BC3_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
168  {WINED3DFMT_BC4_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
169  {WINED3DFMT_BC5_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
170  {WINED3DFMT_BC6H_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
171  {WINED3DFMT_BC7_TYPELESS, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
172  {WINED3DFMT_B8G8R8A8_TYPELESS, 8, 8, 8, 8, 16, 8, 0, 24, 4, 0, 0},
173  {WINED3DFMT_B8G8R8X8_TYPELESS, 8, 8, 8, 0, 16, 8, 0, 0, 4, 0, 0},
174 };
175 
177 {
187 };
188 
190 {
193  const char *channels;
194 };
195 
209 {
279 };
280 
282 {
288 };
289 
291 {
298 };
299 
301 {
304 };
305 
306 static const struct wined3d_format_ddi_info ddi_formats[] =
307 {
317 };
318 
320 {
323 };
324 
325 /* The ATI2N format behaves like an uncompressed format in LockRect(), but
326  * still needs to use the correct block based calculation for e.g. the
327  * resource size. */
329 {
340 };
341 
343 {
349 };
350 
352 {
353  {WINED3DFMT_DXT1, 4, 4, 8, TRUE},
354  {WINED3DFMT_DXT2, 4, 4, 16, TRUE},
355  {WINED3DFMT_DXT3, 4, 4, 16, TRUE},
356  {WINED3DFMT_DXT4, 4, 4, 16, TRUE},
357  {WINED3DFMT_DXT5, 4, 4, 16, TRUE},
358  {WINED3DFMT_BC1_UNORM, 4, 4, 8, TRUE},
359  {WINED3DFMT_BC2_UNORM, 4, 4, 16, TRUE},
360  {WINED3DFMT_BC3_UNORM, 4, 4, 16, TRUE},
361  {WINED3DFMT_BC4_UNORM, 4, 4, 8, TRUE},
362  {WINED3DFMT_BC4_SNORM, 4, 4, 8, TRUE},
363  {WINED3DFMT_BC5_UNORM, 4, 4, 16, TRUE},
364  {WINED3DFMT_BC5_SNORM, 4, 4, 16, TRUE},
365  {WINED3DFMT_BC6H_UF16, 4, 4, 16, TRUE},
366  {WINED3DFMT_BC6H_SF16, 4, 4, 16, TRUE},
367  {WINED3DFMT_BC7_UNORM, 4, 4, 16, TRUE},
368  {WINED3DFMT_ATI1N, 4, 4, 8, FALSE},
369  {WINED3DFMT_ATI2N, 4, 4, 16, FALSE},
370  {WINED3DFMT_YUY2, 2, 1, 4, FALSE},
371  {WINED3DFMT_UYVY, 2, 1, 4, FALSE},
372 };
373 
375 {
378  unsigned int component_count;
382 };
383 
385 {
421 };
422 
424 {
431  unsigned int conv_byte_count;
432  unsigned int flags;
434  void (*upload)(const BYTE *src, BYTE *dst, unsigned int src_row_pitch, unsigned int src_slice_pitch,
435  unsigned int dst_row_pitch, unsigned int dst_slice_pitch,
436  unsigned int width, unsigned int height, unsigned int depth);
437  void (*download)(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 };
441 
442 static void convert_l4a4_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
443  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
444 {
445  /* WINED3DFMT_L4A4_UNORM exists as an internal gl format, but for some reason there is not
446  * format+type combination to load it. Thus convert it to A8L8, then load it
447  * with A4L4 internal, but A8L8 format+type
448  */
449  unsigned int x, y, z;
450  const unsigned char *Source;
451  unsigned char *Dest;
452 
453  for (z = 0; z < depth; z++)
454  {
455  for (y = 0; y < height; y++)
456  {
457  Source = src + z * src_slice_pitch + y * src_row_pitch;
458  Dest = dst + z * dst_slice_pitch + y * dst_row_pitch;
459  for (x = 0; x < width; x++ )
460  {
461  unsigned char color = (*Source++);
462  /* A */ Dest[1] = (color & 0xf0u) << 0;
463  /* L */ Dest[0] = (color & 0x0fu) << 4;
464  Dest += 2;
465  }
466  }
467  }
468 }
469 
470 static void convert_r5g5_snorm_l6_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
471  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
472 {
473  unsigned int x, y, z;
474  unsigned char r_in, g_in, l_in;
475  const unsigned short *texel_in;
476  unsigned short *texel_out;
477 
478  /* Emulating signed 5 bit values with unsigned 5 bit values has some precision problems by design:
479  * E.g. the signed input value 0 becomes 16. GL normalizes it to 16 / 31 = 0.516. We convert it
480  * back to a signed value by subtracting 0.5 and multiplying by 2.0. The resulting value is
481  * ((16 / 31) - 0.5) * 2.0 = 0.032, which is quite different from the intended result 0.000. */
482  for (z = 0; z < depth; z++)
483  {
484  for (y = 0; y < height; y++)
485  {
486  texel_out = (unsigned short *) (dst + z * dst_slice_pitch + y * dst_row_pitch);
487  texel_in = (const unsigned short *)(src + z * src_slice_pitch + y * src_row_pitch);
488  for (x = 0; x < width; x++ )
489  {
490  l_in = (*texel_in & 0xfc00u) >> 10;
491  g_in = (*texel_in & 0x03e0u) >> 5;
492  r_in = *texel_in & 0x001fu;
493 
494  *texel_out = ((r_in + 16) << 11) | (l_in << 5) | (g_in + 16);
495  texel_out++;
496  texel_in++;
497  }
498  }
499  }
500 }
501 
502 static void convert_r5g5_snorm_l6_unorm_ext(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
503  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
504 {
505  unsigned int x, y, z;
506  unsigned char *texel_out, r_out, g_out, r_in, g_in, l_in;
507  const unsigned short *texel_in;
508 
509  for (z = 0; z < depth; z++)
510  {
511  for (y = 0; y < height; y++)
512  {
513  texel_in = (const unsigned short *)(src + z * src_slice_pitch + y * src_row_pitch);
514  texel_out = dst + z * dst_slice_pitch + y * dst_row_pitch;
515  for (x = 0; x < width; x++ )
516  {
517  l_in = (*texel_in & 0xfc00u) >> 10;
518  g_in = (*texel_in & 0x03e0u) >> 5;
519  r_in = *texel_in & 0x001fu;
520 
521  r_out = r_in << 3;
522  if (!(r_in & 0x10)) /* r > 0 */
523  r_out |= r_in >> 1;
524 
525  g_out = g_in << 3;
526  if (!(g_in & 0x10)) /* g > 0 */
527  g_out |= g_in >> 1;
528 
529  texel_out[0] = r_out;
530  texel_out[1] = g_out;
531  texel_out[2] = l_in << 1 | l_in >> 5;
532  texel_out[3] = 0;
533 
534  texel_out += 4;
535  texel_in++;
536  }
537  }
538  }
539 }
540 
541 static void convert_r5g5_snorm_l6_unorm_nv(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
542  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
543 {
544  unsigned int x, y, z;
545  unsigned char *texel_out, ds_out, dt_out, r_in, g_in, l_in;
546  const unsigned short *texel_in;
547 
548  /* This makes the gl surface bigger(24 bit instead of 16), but it works with
549  * fixed function and shaders without further conversion once the surface is
550  * loaded.
551  *
552  * The difference between this function and convert_r5g5_snorm_l6_unorm_ext
553  * is that convert_r5g5_snorm_l6_unorm_ext creates a 32 bit XRGB texture and
554  * this function creates a 24 bit DSDT_MAG texture. Trying to load a DSDT_MAG
555  * internal with a 32 bit DSDT_MAG_INTENSITY or DSDT_MAG_VIB format fails. */
556  for (z = 0; z < depth; z++)
557  {
558  for (y = 0; y < height; y++)
559  {
560  texel_in = (const unsigned short *)(src + z * src_slice_pitch + y * src_row_pitch);
561  texel_out = dst + z * dst_slice_pitch + y * dst_row_pitch;
562  for (x = 0; x < width; x++ )
563  {
564  l_in = (*texel_in & 0xfc00u) >> 10;
565  g_in = (*texel_in & 0x03e0u) >> 5;
566  r_in = *texel_in & 0x001fu;
567 
568  ds_out = r_in << 3;
569  if (!(r_in & 0x10)) /* r > 0 */
570  ds_out |= r_in >> 1;
571 
572  dt_out = g_in << 3;
573  if (!(g_in & 0x10)) /* g > 0 */
574  dt_out |= g_in >> 1;
575 
576  texel_out[0] = ds_out;
577  texel_out[1] = dt_out;
578  texel_out[2] = l_in << 1 | l_in >> 5;
579 
580  texel_out += 3;
581  texel_in++;
582  }
583  }
584  }
585 }
586 
587 static void convert_r8g8_snorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
588  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
589 {
590  unsigned int x, y, z;
591  const short *Source;
592  unsigned char *Dest;
593 
594  for (z = 0; z < depth; z++)
595  {
596  for (y = 0; y < height; y++)
597  {
598  Source = (const short *)(src + z * src_slice_pitch + y * src_row_pitch);
599  Dest = dst + z * dst_slice_pitch + y * dst_row_pitch;
600  for (x = 0; x < width; x++ )
601  {
602  const short color = (*Source++);
603  /* B */ Dest[0] = 0xff;
604  /* G */ Dest[1] = (color >> 8) + 128; /* V */
605  /* R */ Dest[2] = (color & 0xff) + 128; /* U */
606  Dest += 3;
607  }
608  }
609  }
610 }
611 
612 static void convert_r8g8_snorm_l8x8_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
613  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
614 {
615  unsigned int x, y, z;
616  const DWORD *Source;
617  unsigned char *Dest;
618 
619  /* Doesn't work correctly with the fixed function pipeline, but can work in
620  * shaders if the shader is adjusted. (There's no use for this format in gl's
621  * standard fixed function pipeline anyway).
622  */
623  for (z = 0; z < depth; z++)
624  {
625  for (y = 0; y < height; y++)
626  {
627  Source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
628  Dest = dst + z * dst_slice_pitch + y * dst_row_pitch;
629  for (x = 0; x < width; x++ )
630  {
631  LONG color = (*Source++);
632  /* B */ Dest[0] = ((color >> 16) & 0xff); /* L */
633  /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
634  /* R */ Dest[2] = (color & 0xff) + 128; /* U */
635  Dest += 4;
636  }
637  }
638  }
639 }
640 
641 static void convert_r8g8_snorm_l8x8_unorm_nv(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
642  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
643 {
644  unsigned int x, y, z;
645  const DWORD *Source;
646  unsigned char *Dest;
647 
648  /* This implementation works with the fixed function pipeline and shaders
649  * without further modification after converting the surface.
650  */
651  for (z = 0; z < depth; z++)
652  {
653  for (y = 0; y < height; y++)
654  {
655  Source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
656  Dest = dst + z * dst_slice_pitch + y * dst_row_pitch;
657  for (x = 0; x < width; x++ )
658  {
659  LONG color = (*Source++);
660  /* L */ Dest[2] = ((color >> 16) & 0xff); /* L */
661  /* V */ Dest[1] = ((color >> 8 ) & 0xff); /* V */
662  /* U */ Dest[0] = (color & 0xff); /* U */
663  /* I */ Dest[3] = 255; /* X */
664  Dest += 4;
665  }
666  }
667  }
668 }
669 
670 static void convert_r8g8b8a8_snorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
671  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
672 {
673  unsigned int x, y, z;
674  const DWORD *Source;
675  unsigned char *Dest;
676 
677  for (z = 0; z < depth; z++)
678  {
679  for (y = 0; y < height; y++)
680  {
681  Source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
682  Dest = dst + z * dst_slice_pitch + y * dst_row_pitch;
683  for (x = 0; x < width; x++ )
684  {
685  LONG color = (*Source++);
686  /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */
687  /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
688  /* R */ Dest[2] = (color & 0xff) + 128; /* U */
689  /* A */ Dest[3] = ((color >> 24) & 0xff) + 128; /* Q */
690  Dest += 4;
691  }
692  }
693  }
694 }
695 
696 static void convert_r16g16_snorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
697  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
698 {
699  unsigned int x, y, z;
700  const DWORD *Source;
701  unsigned short *Dest;
702 
703  for (z = 0; z < depth; z++)
704  {
705  for (y = 0; y < height; y++)
706  {
707  Source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
708  Dest = (unsigned short *) (dst + z * dst_slice_pitch + y * dst_row_pitch);
709  for (x = 0; x < width; x++ )
710  {
711  const DWORD color = (*Source++);
712  /* B */ Dest[0] = 0xffff;
713  /* G */ Dest[1] = (color >> 16) + 32768; /* V */
714  /* R */ Dest[2] = (color & 0xffff) + 32768; /* U */
715  Dest += 3;
716  }
717  }
718  }
719 }
720 
721 static void convert_r16g16(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
722  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
723 {
724  unsigned int x, y, z;
725  const WORD *Source;
726  WORD *Dest;
727 
728  for (z = 0; z < depth; z++)
729  {
730  for (y = 0; y < height; y++)
731  {
732  Source = (const WORD *)(src + z * src_slice_pitch + y * src_row_pitch);
733  Dest = (WORD *) (dst + z * dst_slice_pitch + y * dst_row_pitch);
734  for (x = 0; x < width; x++ )
735  {
736  WORD green = (*Source++);
737  WORD red = (*Source++);
738  Dest[0] = green;
739  Dest[1] = red;
740  /* Strictly speaking not correct for R16G16F, but it doesn't matter because the
741  * shader overwrites it anyway */
742  Dest[2] = 0xffff;
743  Dest += 3;
744  }
745  }
746  }
747 }
748 
749 static void convert_r32g32_float(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
750  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
751 {
752  unsigned int x, y, z;
753  const float *Source;
754  float *Dest;
755 
756  for (z = 0; z < depth; z++)
757  {
758  for (y = 0; y < height; y++)
759  {
760  Source = (const float *)(src + z * src_slice_pitch + y * src_row_pitch);
761  Dest = (float *) (dst + z * dst_slice_pitch + y * dst_row_pitch);
762  for (x = 0; x < width; x++ )
763  {
764  float green = (*Source++);
765  float red = (*Source++);
766  Dest[0] = green;
767  Dest[1] = red;
768  Dest[2] = 1.0f;
769  Dest += 3;
770  }
771  }
772  }
773 }
774 
775 static void convert_s1_uint_d15_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
776  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
777 {
778  unsigned int x, y, z;
779 
780  for (z = 0; z < depth; z++)
781  {
782  for (y = 0; y < height; ++y)
783  {
784  const WORD *source = (const WORD *)(src + z * src_slice_pitch + y * src_row_pitch);
785  DWORD *dest = (DWORD *)(dst + z * dst_slice_pitch + y * dst_row_pitch);
786 
787  for (x = 0; x < width; ++x)
788  {
789  /* The depth data is normalized, so needs to be scaled,
790  * the stencil data isn't. Scale depth data by
791  * (2^24-1)/(2^15-1) ~~ (2^9 + 2^-6). */
792  WORD d15 = source[x] >> 1;
793  DWORD d24 = (d15 << 9) + (d15 >> 6);
794  dest[x] = (d24 << 8) | (source[x] & 0x1);
795  }
796  }
797  }
798 }
799 
800 static void convert_s4x4_uint_d24_unorm(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
801  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
802 {
803  unsigned int x, y, z;
804 
805  for (z = 0; z < depth; z++)
806  {
807  for (y = 0; y < height; ++y)
808  {
809  const DWORD *source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
810  DWORD *dest = (DWORD *)(dst + z * dst_slice_pitch + y * dst_row_pitch);
811 
812  for (x = 0; x < width; ++x)
813  {
814  /* Just need to clear out the X4 part. */
815  dest[x] = source[x] & ~0xf0;
816  }
817  }
818  }
819 }
820 
821 static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT src_row_pitch, UINT src_slice_pitch,
822  UINT dst_row_pitch, UINT dst_slice_pitch, UINT width, UINT height, UINT depth)
823 {
824  unsigned int x, y, z;
825 
826  for (z = 0; z < depth; z++)
827  {
828  for (y = 0; y < height; ++y)
829  {
830  const DWORD *source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
831  float *dest_f = (float *)(dst + z * dst_slice_pitch + y * dst_row_pitch);
832  DWORD *dest_s = (DWORD *)dest_f;
833 
834  for (x = 0; x < width; ++x)
835  {
836  dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00u) >> 8);
837  dest_s[x * 2 + 1] = source[x] & 0xff;
838  }
839  }
840  }
841 }
842 
843 static void x8_d24_unorm_upload(const BYTE *src, BYTE *dst,
844  unsigned int src_row_pitch, unsigned int src_slice_pitch,
845  unsigned int dst_row_pitch, unsigned int dst_slice_pitch,
846  unsigned int width, unsigned int height, unsigned int depth)
847 {
848  unsigned int x, y, z;
849 
850  for (z = 0; z < depth; ++z)
851  {
852  for (y = 0; y < height; ++y)
853  {
854  const DWORD *source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
855  DWORD *dest = (DWORD *)(dst + z * dst_slice_pitch + y * dst_row_pitch);
856 
857  for (x = 0; x < width; ++x)
858  {
859  dest[x] = source[x] << 8 | ((source[x] >> 16) & 0xff);
860  }
861  }
862  }
863 }
864 
865 static void x8_d24_unorm_download(const BYTE *src, BYTE *dst,
866  unsigned int src_row_pitch, unsigned int src_slice_pitch,
867  unsigned int dst_row_pitch, unsigned int dst_slice_pitch,
868  unsigned int width, unsigned int height, unsigned int depth)
869 {
870  unsigned int x, y, z;
871 
872  for (z = 0; z < depth; ++z)
873  {
874  for (y = 0; y < height; ++y)
875  {
876  const DWORD *source = (const DWORD *)(src + z * src_slice_pitch + y * src_row_pitch);
877  DWORD *dest = (DWORD *)(dst + z * dst_slice_pitch + y * dst_row_pitch);
878 
879  for (x = 0; x < width; ++x)
880  {
881  dest[x] = source[x] >> 8;
882  }
883  }
884  }
885 }
886 
888 {
889  /* FIXME: Is this really how color keys are supposed to work? I think it
890  * makes more sense to compare the individual channels. */
891  return color >= color_key->color_space_low_value
892  && color <= color_key->color_space_high_value;
893 }
894 
895 static void convert_b5g6r5_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsigned int src_pitch,
896  BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
897  const struct wined3d_color_key *color_key)
898 {
899  const WORD *src_row;
900  unsigned int x, y;
901  WORD *dst_row;
902 
903  for (y = 0; y < height; ++y)
904  {
905  src_row = (WORD *)&src[src_pitch * y];
906  dst_row = (WORD *)&dst[dst_pitch * y];
907  for (x = 0; x < width; ++x)
908  {
909  WORD src_color = src_row[x];
910  if (!color_in_range(color_key, src_color))
911  dst_row[x] = 0x8000u | ((src_color & 0xffc0u) >> 1) | (src_color & 0x1fu);
912  else
913  dst_row[x] = ((src_color & 0xffc0u) >> 1) | (src_color & 0x1fu);
914  }
915  }
916 }
917 
918 static void convert_b5g5r5x1_unorm_b5g5r5a1_unorm_color_key(const BYTE *src, unsigned int src_pitch,
919  BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
920  const struct wined3d_color_key *color_key)
921 {
922  const WORD *src_row;
923  unsigned int x, y;
924  WORD *dst_row;
925 
926  for (y = 0; y < height; ++y)
927  {
928  src_row = (WORD *)&src[src_pitch * y];
929  dst_row = (WORD *)&dst[dst_pitch * y];
930  for (x = 0; x < width; ++x)
931  {
932  WORD src_color = src_row[x];
933  if (color_in_range(color_key, src_color))
934  dst_row[x] = src_color & ~0x8000;
935  else
936  dst_row[x] = src_color | 0x8000;
937  }
938  }
939 }
940 
941 static void convert_b8g8r8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
942  BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
943  const struct wined3d_color_key *color_key)
944 {
945  const BYTE *src_row;
946  unsigned int x, y;
947  DWORD *dst_row;
948 
949  for (y = 0; y < height; ++y)
950  {
951  src_row = &src[src_pitch * y];
952  dst_row = (DWORD *)&dst[dst_pitch * y];
953  for (x = 0; x < width; ++x)
954  {
955  DWORD src_color = (src_row[x * 3 + 2] << 16) | (src_row[x * 3 + 1] << 8) | src_row[x * 3];
956  if (!color_in_range(color_key, src_color))
957  dst_row[x] = src_color | 0xff000000;
958  }
959  }
960 }
961 
962 static void convert_b8g8r8x8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
963  BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
964  const struct wined3d_color_key *color_key)
965 {
966  const DWORD *src_row;
967  unsigned int x, y;
968  DWORD *dst_row;
969 
970  for (y = 0; y < height; ++y)
971  {
972  src_row = (DWORD *)&src[src_pitch * y];
973  dst_row = (DWORD *)&dst[dst_pitch * y];
974  for (x = 0; x < width; ++x)
975  {
976  DWORD src_color = src_row[x];
977  if (color_in_range(color_key, src_color))
978  dst_row[x] = src_color & ~0xff000000;
979  else
980  dst_row[x] = src_color | 0xff000000;
981  }
982  }
983 }
984 
985 static void convert_b8g8r8a8_unorm_b8g8r8a8_unorm_color_key(const BYTE *src, unsigned int src_pitch,
986  BYTE *dst, unsigned int dst_pitch, unsigned int width, unsigned int height,
987  const struct wined3d_color_key *color_key)
988 {
989  const DWORD *src_row;
990  unsigned int x, y;
991  DWORD *dst_row;
992 
993  for (y = 0; y < height; ++y)
994  {
995  src_row = (DWORD *)&src[src_pitch * y];
996  dst_row = (DWORD *)&dst[dst_pitch * y];
997  for (x = 0; x < width; ++x)
998  {
999  DWORD src_color = src_row[x];
1000  if (color_in_range(color_key, src_color))
1001  src_color &= ~0xff000000;
1002  dst_row[x] = src_color;
1003  }
1004  }
1005 }
1006 
1008  const struct wined3d_texture *texture, BOOL need_alpha_ck)
1009 {
1010  const struct wined3d_format *format = texture->resource.format;
1011  unsigned int i;
1012 
1013  static const struct
1014  {
1015  enum wined3d_format_id src_format;
1016  struct wined3d_color_key_conversion conversion;
1017  }
1018  color_key_info[] =
1019  {
1025  };
1026 
1027  if (need_alpha_ck && (texture->async.flags & WINED3D_TEXTURE_ASYNC_COLOR_KEY))
1028  {
1029  for (i = 0; i < ARRAY_SIZE(color_key_info); ++i)
1030  {
1031  if (color_key_info[i].src_format == format->id)
1032  return &color_key_info[i].conversion;
1033  }
1034 
1035  FIXME("Color-keying not supported with format %s.\n", debug_d3dformat(format->id));
1036  }
1037 
1038  return NULL;
1039 }
1040 
1041 /* The following formats explicitly don't have WINED3DFMT_FLAG_TEXTURE set:
1042  *
1043  * These are never supported on native.
1044  * WINED3DFMT_B8G8R8_UNORM
1045  * WINED3DFMT_B2G3R3_UNORM
1046  * WINED3DFMT_L4A4_UNORM
1047  * WINED3DFMT_S1_UINT_D15_UNORM
1048  * WINED3DFMT_S4X4_UINT_D24_UNORM
1049  *
1050  * Only some Geforce/Voodoo3/G400 cards offer 8-bit textures in case of ddraw.
1051  * Since it is not widely available, don't offer it. Further no Windows driver
1052  * offers WINED3DFMT_P8_UINT_A8_NORM, so don't offer it either.
1053  * WINED3DFMT_P8_UINT
1054  * WINED3DFMT_P8_UINT_A8_UNORM
1055  *
1056  * These formats seem to be similar to the HILO formats in
1057  * GL_NV_texture_shader. NVHU is said to be GL_UNSIGNED_HILO16,
1058  * NVHS GL_SIGNED_HILO16. Rumours say that D3D computes a 3rd channel
1059  * similarly to D3DFMT_CxV8U8 (So NVHS could be called D3DFMT_CxV16U16). ATI
1060  * refused to support formats which can easily be emulated with pixel shaders,
1061  * so applications have to deal with not having NVHS and NVHU.
1062  * WINED3DFMT_NVHU
1063  * WINED3DFMT_NVHS */
1065 {
1066  /* format id gl_internal gl_srgb_internal gl_rt_internal
1067  gl_format gl_type conv_byte_count
1068  flags
1069  extension upload download */
1070  /* FourCC formats */
1071  /* GL_APPLE_ycbcr_422 claims that its '2YUV' format, which is supported via the UNSIGNED_SHORT_8_8_REV_APPLE type
1072  * is equivalent to 'UYVY' format on Windows, and the 'YUVS' via UNSIGNED_SHORT_8_8_APPLE equates to 'YUY2'. The
1073  * d3d9 test however shows that the opposite is true. Since the extension is from 2002, it predates the x86 based
1074  * Macs, so probably the endianness differs. This could be tested as soon as we have a Windows and MacOS on a big
1075  * endian machine
1076  */
1078  GL_RG, GL_UNSIGNED_BYTE, 0,
1080  ARB_TEXTURE_RG, NULL},
1090  GL_RG, GL_UNSIGNED_BYTE, 0,
1092  ARB_TEXTURE_RG, NULL},
1101  {WINED3DFMT_YV12, GL_R8, GL_R8, 0,
1104  ARB_TEXTURE_RG, NULL},
1109  {WINED3DFMT_NV12, GL_R8, GL_R8, 0,
1112  ARB_TEXTURE_RG, NULL},
1168  GL_RG, GL_UNSIGNED_BYTE, 0,
1173  GL_RG, GL_UNSIGNED_BYTE, 0,
1192  /* IEEE formats */
1194  GL_RED, GL_FLOAT, 0,
1198  GL_RED, GL_FLOAT, 0,
1200  ARB_TEXTURE_RG, NULL},
1202  GL_RGB, GL_FLOAT, 12,
1206  GL_RG, GL_FLOAT, 0,
1208  ARB_TEXTURE_RG, NULL},
1210  GL_RGB, GL_FLOAT, 0,
1214  GL_RGBA, GL_FLOAT, 0,
1217  /* Float */
1225  ARB_TEXTURE_RG, NULL},
1233  ARB_TEXTURE_RG, NULL},
1243  /* Palettized formats */
1246  0,
1247  ARB_TEXTURE_RG, NULL},
1250  0,
1252  /* Standard ARGB formats */
1300  ARB_TEXTURE_RG, NULL},
1304  ARB_TEXTURE_RG, NULL},
1344  ARB_TEXTURE_RG, NULL},
1356  GL_RG, GL_UNSIGNED_BYTE, 0,
1359  ARB_TEXTURE_RG, NULL},
1363  ARB_TEXTURE_RG, NULL},
1365  GL_RG_INTEGER, GL_BYTE, 0,
1367  ARB_TEXTURE_RG, NULL},
1379  ARB_TEXTURE_RG, NULL},
1381  GL_RG_INTEGER, GL_INT, 0,
1383  ARB_TEXTURE_RG, NULL},
1387  ARB_TEXTURE_RG, NULL},
1389  GL_RG_INTEGER, GL_SHORT, 0,
1391  ARB_TEXTURE_RG, NULL},
1395  ARB_TEXTURE_RG, NULL},
1397  GL_RED_INTEGER, GL_INT, 0,
1399  ARB_TEXTURE_RG, NULL},
1404  ARB_TEXTURE_RG, NULL},
1408  ARB_TEXTURE_RG, NULL},
1412  ARB_TEXTURE_RG, NULL},
1416  ARB_TEXTURE_RG, NULL},
1418  GL_RED_INTEGER, GL_BYTE, 0,
1420  ARB_TEXTURE_RG, NULL},
1421  /* Luminance */
1431  ARB_TEXTURE_RG, NULL},
1433  GL_RG, GL_UNSIGNED_BYTE, 0,
1435  ARB_TEXTURE_RG, NULL},
1442  GL_RG, GL_UNSIGNED_BYTE, 2,
1452  ARB_TEXTURE_RG, NULL},
1457  /* Bump mapping stuff */
1464  GL_DSDT_NV, GL_BYTE, 0,
1469  GL_RG, GL_BYTE, 0,
1479  GL_DSDT_MAG_NV, GL_BYTE, 3,
1484  GL_RGBA, GL_BYTE, 4,
1504  GL_RGBA, GL_BYTE, 0,
1509  GL_RGBA, GL_BYTE, 0,
1519  GL_HILO_NV, GL_SHORT, 0,
1524  GL_RG, GL_SHORT, 0,
1529  GL_RGBA, GL_SHORT, 0,
1534  GL_RED, GL_SHORT, 0,
1539  GL_RED, GL_BYTE, 0,
1543  /* Depth stencil formats */
1634  GL_RGBA_INTEGER, GL_INT, 0,
1637  /* Vendor-specific formats */
1654  GL_RG, GL_UNSIGNED_BYTE, 0,
1668  {WINED3DFMT_NULL, 0, 0, 0,
1672  /* DirectX 10 HDR formats */
1677 };
1678 
1680 {
1683 };
1684 
1686 {
1694 };
1695 
1697 {
1698  unsigned int i;
1699 
1701  return format_id;
1702 
1703  for (i = 0; i < ARRAY_SIZE(format_index_remap); ++i)
1704  {
1705  if (format_index_remap[i].id == format_id)
1706  return format_index_remap[i].idx;
1707  }
1708 
1709  return -1;
1710 }
1711 
1712 static struct wined3d_format *get_format_internal(struct wined3d_gl_info *gl_info,
1714 {
1715  int fmt_idx;
1716 
1717  if ((fmt_idx = get_format_idx(format_id)) == -1)
1718  {
1719  ERR("Format %s (%#x) not found.\n", debug_d3dformat(format_id), format_id);
1720  return NULL;
1721  }
1722 
1723  return &gl_info->formats[fmt_idx];
1724 }
1725 
1726 static void copy_format(struct wined3d_format *dst_format, const struct wined3d_format *src_format)
1727 {
1728  enum wined3d_format_id id = dst_format->id;
1729  *dst_format = *src_format;
1730  dst_format->id = id;
1731 }
1732 
1733 static void format_set_flag(struct wined3d_format *format, unsigned int flag)
1734 {
1735  unsigned int i;
1736 
1737  for (i = 0; i < ARRAY_SIZE(format->flags); ++i)
1738  format->flags[i] |= flag;
1739 }
1740 
1741 static void format_clear_flag(struct wined3d_format *format, unsigned int flag)
1742 {
1743  unsigned int i;
1744 
1745  for (i = 0; i < ARRAY_SIZE(format->flags); ++i)
1746  format->flags[i] &= ~flag;
1747 }
1748 
1750 {
1751  switch (t)
1752  {
1753  case 'u':
1755  case 'i':
1757  case 'U':
1759  case 'I':
1761  case 'F':
1763  case 'D':
1765  case 'S':
1767  case 'X':
1769  default:
1770  ERR("Invalid channel type '%c'.\n", t);
1772  }
1773 }
1774 
1776 {
1777  struct wined3d_format *format;
1778  unsigned int i, j;
1779 
1781  if (!(gl_info->formats = heap_calloc(gl_info->format_count
1782  + ARRAY_SIZE(typeless_depth_stencil_formats), sizeof(*gl_info->formats))))
1783  {
1784  ERR("Failed to allocate memory.\n");
1785  return FALSE;
1786  }
1787 
1788  for (i = 0; i < ARRAY_SIZE(formats); ++i)
1789  {
1790  if (!(format = get_format_internal(gl_info, formats[i].id)))
1791  goto fail;
1792 
1793  format->id = formats[i].id;
1794  format->red_size = formats[i].red_size;
1795  format->green_size = formats[i].green_size;
1796  format->blue_size = formats[i].blue_size;
1797  format->alpha_size = formats[i].alpha_size;
1798  format->red_offset = formats[i].red_offset;
1799  format->green_offset = formats[i].green_offset;
1800  format->blue_offset = formats[i].blue_offset;
1801  format->alpha_offset = formats[i].alpha_offset;
1802  format->byte_count = formats[i].bpp;
1803  format->depth_size = formats[i].depth_size;
1804  format->stencil_size = formats[i].stencil_size;
1805  format->block_width = 1;
1806  format->block_height = 1;
1807  format->block_byte_count = formats[i].bpp;
1808  }
1809 
1810  for (i = 0; i < ARRAY_SIZE(typed_formats); ++i)
1811  {
1812  const struct wined3d_format *typeless_format;
1813  DWORD flags = 0;
1814 
1815  if (!(format = get_format_internal(gl_info, typed_formats[i].id)))
1816  goto fail;
1817 
1818  if (!(typeless_format = get_format_internal(gl_info, typed_formats[i].typeless_id)))
1819  goto fail;
1820 
1821  format->id = typed_formats[i].id;
1822  format->red_size = typeless_format->red_size;
1823  format->green_size = typeless_format->green_size;
1824  format->blue_size = typeless_format->blue_size;
1825  format->alpha_size = typeless_format->alpha_size;
1826  format->red_offset = typeless_format->red_offset;
1827  format->green_offset = typeless_format->green_offset;
1828  format->blue_offset = typeless_format->blue_offset;
1829  format->alpha_offset = typeless_format->alpha_offset;
1830  format->byte_count = typeless_format->byte_count;
1831  format->depth_size = typeless_format->depth_size;
1832  format->stencil_size = typeless_format->stencil_size;
1833  format->block_width = typeless_format->block_width;
1834  format->block_height = typeless_format->block_height;
1835  format->block_byte_count = typeless_format->block_byte_count;
1836  format->typeless_id = typeless_format->id;
1837 
1838  for (j = 0; j < strlen(typed_formats[i].channels); ++j)
1839  {
1841  if (channel_type == WINED3D_CHANNEL_TYPE_UINT || channel_type == WINED3D_CHANNEL_TYPE_SINT)
1843  if (channel_type == WINED3D_CHANNEL_TYPE_FLOAT)
1845 
1846  if (channel_type == WINED3D_CHANNEL_TYPE_DEPTH && !format->depth_size)
1847  {
1848  format->depth_size = format->red_size;
1849  format->red_size = format->red_offset = 0;
1850  }
1851  }
1852 
1854  }
1855 
1856  for (i = 0; i < ARRAY_SIZE(ddi_formats); ++i)
1857  {
1858  if (!(format = get_format_internal(gl_info, ddi_formats[i].id)))
1859  goto fail;
1860 
1861  format->ddi_format = ddi_formats[i].ddi_format;
1862  }
1863 
1864  for (i = 0; i < ARRAY_SIZE(format_base_flags); ++i)
1865  {
1866  if (!(format = get_format_internal(gl_info, format_base_flags[i].id)))
1867  goto fail;
1868 
1870  }
1871 
1872  return TRUE;
1873 
1874 fail:
1875  heap_free(gl_info->formats);
1876  return FALSE;
1877 }
1878 
1880 {
1881  struct wined3d_format *format;
1882  unsigned int i;
1883 
1884  for (i = 0; i < ARRAY_SIZE(format_block_info); ++i)
1885  {
1886  if (!(format = get_format_internal(gl_info, format_block_info[i].id)))
1887  return FALSE;
1888 
1889  format->block_width = format_block_info[i].block_width;
1890  format->block_height = format_block_info[i].block_height;
1891  format->block_byte_count = format_block_info[i].block_byte_count;
1893  if (!format_block_info[i].verify)
1895  }
1896 
1897  return TRUE;
1898 }
1899 
1901 {
1902  switch (type)
1903  {
1905  return GL_TEXTURE_1D;
1907  return GL_TEXTURE_2D;
1909  return GL_TEXTURE_3D;
1911  return GL_TEXTURE_CUBE_MAP_ARB;
1913  return GL_TEXTURE_RECTANGLE_ARB;
1915  return GL_TEXTURE_2D; /* TODO: GL_TEXTURE_BUFFER. */
1917  return GL_RENDERBUFFER;
1919  break;
1920  }
1921  ERR("Unexpected GL resource type %u.\n", type);
1922  return 0;
1923 }
1924 
1925 static void delete_fbo_attachment(const struct wined3d_gl_info *gl_info,
1926  enum wined3d_gl_resource_type d3d_type, GLuint object)
1927 {
1928  switch (d3d_type)
1929  {
1935  gl_info->gl_ops.gl.p_glDeleteTextures(1, &object);
1936  break;
1937 
1939  gl_info->fbo_ops.glDeleteRenderbuffers(1, &object);
1940  break;
1941 
1944  break;
1945  }
1946 }
1947 
1948 /* Context activation is done by the caller. */
1949 static void create_and_bind_fbo_attachment(const struct wined3d_gl_info *gl_info, unsigned int flags,
1950  enum wined3d_gl_resource_type d3d_type, GLuint *object, GLenum internal, GLenum format, GLenum type)
1951 {
1952  GLenum attach_type = flags & WINED3DFMT_FLAG_DEPTH ?
1954 
1955  switch (d3d_type)
1956  {
1958  gl_info->gl_ops.gl.p_glGenTextures(1, object);
1959  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, *object);
1960  gl_info->gl_ops.gl.p_glTexImage1D(GL_TEXTURE_1D, 0, internal, 16, 0, format, type, NULL);
1961  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1962  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1963 
1964  gl_info->fbo_ops.glFramebufferTexture1D(GL_FRAMEBUFFER, attach_type, GL_TEXTURE_1D,
1965  *object, 0);
1967  gl_info->fbo_ops.glFramebufferTexture1D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_1D,
1968  *object, 0);
1969  break;
1970 
1973  gl_info->gl_ops.gl.p_glGenTextures(1, object);
1974  gl_info->gl_ops.gl.p_glBindTexture(wined3d_gl_type_to_enum(d3d_type), *object);
1975  gl_info->gl_ops.gl.p_glTexImage2D(wined3d_gl_type_to_enum(d3d_type), 0, internal, 16, 16, 0,
1976  format, type, NULL);
1977  gl_info->gl_ops.gl.p_glTexParameteri(wined3d_gl_type_to_enum(d3d_type), GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1978  gl_info->gl_ops.gl.p_glTexParameteri(wined3d_gl_type_to_enum(d3d_type), GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1979 
1980  gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, attach_type,
1981  wined3d_gl_type_to_enum(d3d_type), *object, 0);
1983  gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
1984  wined3d_gl_type_to_enum(d3d_type), *object, 0);
1985  break;
1986 
1988  gl_info->gl_ops.gl.p_glGenTextures(1, object);
1989  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_3D, *object);
1990  GL_EXTCALL(glTexImage3D(GL_TEXTURE_3D, 0, internal, 16, 16, 16, 0, format, type, NULL));
1991  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1992  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1993 
1994  gl_info->fbo_ops.glFramebufferTexture3D(GL_FRAMEBUFFER, attach_type,
1995  GL_TEXTURE_3D, *object, 0, 0);
1997  gl_info->fbo_ops.glFramebufferTexture3D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
1998  GL_TEXTURE_3D, *object, 0, 0);
1999  break;
2000 
2002  gl_info->gl_ops.gl.p_glGenTextures(1, object);
2003  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, *object);
2004  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, internal, 16, 16, 0,
2005  format, type, NULL);
2006  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, 0, internal, 16, 16, 0,
2007  format, type, NULL);
2008  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, 0, internal, 16, 16, 0,
2009  format, type, NULL);
2010  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, 0, internal, 16, 16, 0,
2011  format, type, NULL);
2012  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, 0, internal, 16, 16, 0,
2013  format, type, NULL);
2014  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, 0, internal, 16, 16, 0,
2015  format, type, NULL);
2016  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
2017  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
2018 
2019  gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, attach_type,
2022  gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
2024  break;
2025 
2027  gl_info->fbo_ops.glGenRenderbuffers(1, object);
2028  gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, *object);
2029  gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, internal, 16, 16);
2030  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, attach_type, GL_RENDERBUFFER,
2031  *object);
2033  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2034  *object);
2035  break;
2036 
2039  break;
2040  }
2041 
2042  /* Ideally we'd skip all formats already known not to work on textures
2043  * by checking for WINED3DFMT_FLAG_TEXTURE here. However, we want to
2044  * know if we can attach WINED3DFMT_P8_UINT textures to FBOs, and this
2045  * format never has WINED3DFMT_FLAG_TEXTURE set. Instead, swallow GL
2046  * errors generated by invalid formats. */
2047  while (gl_info->gl_ops.gl.p_glGetError());
2048 }
2049 
2050 static void draw_test_quad(struct wined3d_caps_gl_ctx *ctx, const struct wined3d_vec3 *geometry,
2051  const struct wined3d_color *color)
2052 {
2053  const struct wined3d_gl_info *gl_info = ctx->gl_info;
2054  static const struct wined3d_vec3 default_geometry[] =
2055  {
2056  {-1.0f, -1.0f, 0.0f},
2057  { 1.0f, -1.0f, 0.0f},
2058  {-1.0f, 1.0f, 0.0f},
2059  { 1.0f, 1.0f, 0.0f},
2060  };
2061  static const char vs_core_header[] =
2062  "#version 150\n"
2063  "in vec4 pos;\n"
2064  "in vec4 color;\n"
2065  "out vec4 out_color;\n"
2066  "\n";
2067  static const char vs_legacy_header[] =
2068  "#version 120\n"
2069  "attribute vec4 pos;\n"
2070  "attribute vec4 color;\n"
2071  "varying vec4 out_color;\n"
2072  "\n";
2073  static const char vs_body[] =
2074  "void main()\n"
2075  "{\n"
2076  " gl_Position = pos;\n"
2077  " out_color = color;\n"
2078  "}\n";
2079  static const char fs_core[] =
2080  "#version 150\n"
2081  "in vec4 out_color;\n"
2082  "out vec4 fragment_color;\n"
2083  "\n"
2084  "void main()\n"
2085  "{\n"
2086  " fragment_color = out_color;\n"
2087  "}\n";
2088  static const char fs_legacy[] =
2089  "#version 120\n"
2090  "varying vec4 out_color;\n"
2091  "\n"
2092  "void main()\n"
2093  "{\n"
2094  " gl_FragData[0] = out_color;\n"
2095  "}\n";
2096  const char *source[2];
2097  GLuint vs_id, fs_id;
2098  unsigned int i;
2099 
2100  if (!geometry)
2101  geometry = default_geometry;
2102 
2103  if (!gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] || !gl_info->supported[ARB_VERTEX_SHADER]
2104  || !gl_info->supported[ARB_FRAGMENT_SHADER])
2105  {
2106  gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
2107  gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
2108  gl_info->gl_ops.gl.p_glLoadIdentity();
2109  gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
2110  gl_info->gl_ops.gl.p_glLoadIdentity();
2111 
2112  gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
2113  gl_info->gl_ops.gl.p_glColor4f(color->r, color->g, color->b, color->a);
2114  for (i = 0; i < 4; ++i)
2115  gl_info->gl_ops.gl.p_glVertex3fv(&geometry[i].x);
2116  gl_info->gl_ops.gl.p_glEnd();
2117  checkGLcall("draw quad");
2118  return;
2119  }
2120 
2121  if (!ctx->test_vbo)
2122  GL_EXTCALL(glGenBuffers(1, &ctx->test_vbo));
2123  GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, ctx->test_vbo));
2124  GL_EXTCALL(glBufferData(GL_ARRAY_BUFFER, sizeof(struct wined3d_vec3) * 4, geometry, GL_STREAM_DRAW));
2125  GL_EXTCALL(glVertexAttribPointer(0, 3, GL_FLOAT, FALSE, 0, NULL));
2126  GL_EXTCALL(glVertexAttrib4f(1, color->r, color->g, color->b, color->a));
2127  GL_EXTCALL(glEnableVertexAttribArray(0));
2128  GL_EXTCALL(glDisableVertexAttribArray(1));
2129 
2130  if (!ctx->test_program_id)
2131  {
2132  BOOL use_glsl_150 = gl_info->glsl_version >= MAKEDWORD_VERSION(1, 50);
2133 
2134  ctx->test_program_id = GL_EXTCALL(glCreateProgram());
2135 
2136  vs_id = GL_EXTCALL(glCreateShader(GL_VERTEX_SHADER));
2137  source[0] = use_glsl_150 ? vs_core_header : vs_legacy_header;
2138  source[1] = vs_body;
2139  GL_EXTCALL(glShaderSource(vs_id, 2, source, NULL));
2140  GL_EXTCALL(glAttachShader(ctx->test_program_id, vs_id));
2141  GL_EXTCALL(glDeleteShader(vs_id));
2142 
2143  fs_id = GL_EXTCALL(glCreateShader(GL_FRAGMENT_SHADER));
2144  source[0] = use_glsl_150 ? fs_core : fs_legacy;
2145  GL_EXTCALL(glShaderSource(fs_id, 1, source, NULL));
2146  GL_EXTCALL(glAttachShader(ctx->test_program_id, fs_id));
2147  GL_EXTCALL(glDeleteShader(fs_id));
2148 
2149  GL_EXTCALL(glBindAttribLocation(ctx->test_program_id, 0, "pos"));
2150  GL_EXTCALL(glBindAttribLocation(ctx->test_program_id, 1, "color"));
2151 
2152  if (use_glsl_150)
2153  GL_EXTCALL(glBindFragDataLocation(ctx->test_program_id, 0, "fragment_color"));
2154 
2155  GL_EXTCALL(glCompileShader(vs_id));
2156  print_glsl_info_log(gl_info, vs_id, FALSE);
2157  GL_EXTCALL(glCompileShader(fs_id));
2158  print_glsl_info_log(gl_info, fs_id, FALSE);
2159  GL_EXTCALL(glLinkProgram(ctx->test_program_id));
2161  }
2162  GL_EXTCALL(glUseProgram(ctx->test_program_id));
2163 
2164  gl_info->gl_ops.gl.p_glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
2165 
2166  GL_EXTCALL(glUseProgram(0));
2167  GL_EXTCALL(glDisableVertexAttribArray(0));
2168  GL_EXTCALL(glBindBuffer(GL_ARRAY_BUFFER, 0));
2169  checkGLcall("draw quad");
2170 }
2171 
2172 /* Context activation is done by the caller. */
2174 {
2175  /* Check if the default internal format is supported as a frame buffer
2176  * target, otherwise fall back to the render target internal.
2177  *
2178  * Try to stick to the standard format if possible, this limits precision differences. */
2179  static const struct wined3d_color black = {0.0f, 0.0f, 0.0f, 1.0f};
2180  static const struct wined3d_color half_transparent_red = {1.0f, 0.0f, 0.0f, 0.5f};
2181  const struct wined3d_gl_info *gl_info = ctx->gl_info;
2182  GLenum status, rt_internal = format->rtInternal;
2183  GLuint object, color_rb;
2185  BOOL fallback_fmt_used = FALSE, regular_fmt_used = FALSE;
2186 
2187  gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
2188 
2189  for (type = 0; type < ARRAY_SIZE(format->flags); ++type)
2190  {
2191  const char *type_string = "color";
2192 
2194  continue;
2195 
2196  create_and_bind_fbo_attachment(gl_info, format->flags[type], type, &object, format->glInternal,
2197  format->glFormat, format->glType);
2198 
2200  {
2201  gl_info->fbo_ops.glGenRenderbuffers(1, &color_rb);
2202  gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, color_rb);
2204  gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 1);
2205  else
2206  gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_RGBA8, 16, 16);
2207 
2208  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER,
2210  checkGLcall("Create and attach color rb attachment");
2211  type_string = "depth / stencil";
2212  }
2213 
2214  status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
2215  checkGLcall("Framebuffer format check");
2216 
2218  {
2219  TRACE("Format %s is supported as FBO %s attachment, type %u.\n",
2220  debug_d3dformat(format->id), type_string, type);
2222  format->rtInternal = format->glInternal;
2223  regular_fmt_used = TRUE;
2224  }
2225  else
2226  {
2227  if (!rt_internal)
2228  {
2230  {
2231  WARN("Format %s with rendertarget flag is not supported as FBO color attachment (type %u),"
2232  " and no fallback specified.\n", debug_d3dformat(format->id), type);
2234  }
2235  else
2236  {
2237  TRACE("Format %s is not supported as FBO %s attachment, type %u.\n",
2238  debug_d3dformat(format->id), type_string, type);
2239  }
2240  format->rtInternal = format->glInternal;
2241  }
2242  else
2243  {
2244  TRACE("Format %s is not supported as FBO %s attachment (type %u),"
2245  " trying rtInternal format as fallback.\n",
2246  debug_d3dformat(format->id), type_string, type);
2247 
2248  while (gl_info->gl_ops.gl.p_glGetError());
2249 
2250  delete_fbo_attachment(gl_info, type, object);
2251  create_and_bind_fbo_attachment(gl_info, format->flags[type], type, &object, format->rtInternal,
2252  format->glFormat, format->glType);
2253 
2254  status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
2255  checkGLcall("Framebuffer format check");
2256 
2258  {
2259  TRACE("Format %s rtInternal format is supported as FBO %s attachment, type %u.\n",
2260  debug_d3dformat(format->id), type_string, type);
2261  fallback_fmt_used = TRUE;
2262  }
2263  else
2264  {
2265  WARN("Format %s rtInternal format is not supported as FBO %s attachment, type %u.\n",
2266  debug_d3dformat(format->id), type_string, type);
2268  }
2269  }
2270  }
2271 
2275  && !(format->flags[type] & WINED3DFMT_FLAG_INTEGER)
2276  && format->id != WINED3DFMT_NULL && format->id != WINED3DFMT_P8_UINT
2277  && format->glFormat != GL_LUMINANCE && format->glFormat != GL_LUMINANCE_ALPHA
2278  && (format->red_size || format->alpha_size))
2279  {
2280  DWORD readback[16 * 16 * 16], color, r_range, a_range;
2281  BYTE r, a;
2282  BOOL match = TRUE;
2283  GLuint rb;
2284 
2285  if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
2286  || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
2287  {
2288  gl_info->fbo_ops.glGenRenderbuffers(1, &rb);
2289  gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, rb);
2291  gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 1);
2292  else
2293  gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
2294  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);
2295  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb);
2296  checkGLcall("RB attachment");
2297  }
2298 
2299  gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
2300  gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
2301  gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
2302  if (gl_info->gl_ops.gl.p_glGetError() == GL_INVALID_FRAMEBUFFER_OPERATION)
2303  {
2304  while (gl_info->gl_ops.gl.p_glGetError());
2305  TRACE("Format %s doesn't support post-pixelshader blending, type %u.\n",
2306  debug_d3dformat(format->id), type);
2308  }
2309  else
2310  {
2311  gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
2313  gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1);
2314  else
2315  gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 16);
2316  gl_info->gl_ops.gl.p_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
2317 
2318  draw_test_quad(ctx, NULL, &black);
2319 
2320  gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
2321 
2322  draw_test_quad(ctx, NULL, &half_transparent_red);
2323 
2324  gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
2325 
2326  switch (type)
2327  {
2329  /* Rebinding texture to workaround a fglrx bug. */
2330  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_1D, object);
2331  gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_1D, 0, GL_BGRA,
2332  GL_UNSIGNED_INT_8_8_8_8_REV, readback);
2333  color = readback[7];
2334  break;
2335 
2339  /* Rebinding texture to workaround a fglrx bug. */
2340  gl_info->gl_ops.gl.p_glBindTexture(wined3d_gl_type_to_enum(type), object);
2341  gl_info->gl_ops.gl.p_glGetTexImage(wined3d_gl_type_to_enum(type), 0, GL_BGRA,
2342  GL_UNSIGNED_INT_8_8_8_8_REV, readback);
2343  color = readback[7 * 16 + 7];
2344  break;
2345 
2347  /* Rebinding texture to workaround a fglrx bug. */
2348  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_CUBE_MAP_ARB, object);
2349  gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, 0, GL_BGRA,
2350  GL_UNSIGNED_INT_8_8_8_8_REV, readback);
2351  color = readback[7 * 16 + 7];
2352  break;
2353 
2355  gl_info->gl_ops.gl.p_glReadPixels(0, 0, 16, 16,
2357  color = readback[7 * 16 + 7];
2358  break;
2359 
2362  color = 0;
2363  break;
2364  }
2365  checkGLcall("Post-pixelshader blending check");
2366 
2367  a = color >> 24;
2368  r = (color & 0x00ff0000u) >> 16;
2369 
2370  r_range = format->red_size < 8 ? 1u << (8 - format->red_size) : 1;
2371  a_range = format->alpha_size < 8 ? 1u << (8 - format->alpha_size) : 1;
2372  if (format->red_size && (r < 0x7f - r_range || r > 0x7f + r_range))
2373  match = FALSE;
2374  else if (format->alpha_size > 1 && (a < 0xbf - a_range || a > 0xbf + a_range))
2375  match = FALSE;
2376  if (!match)
2377  {
2378  TRACE("Format %s doesn't support post-pixelshader blending, type %u.\n",
2379  debug_d3dformat(format->id), type);
2380  TRACE("Color output: %#x\n", color);
2382  }
2383  else
2384  {
2385  TRACE("Format %s supports post-pixelshader blending, type %u.\n",
2386  debug_d3dformat(format->id), type);
2387  TRACE("Color output: %#x\n", color);
2389  }
2390  }
2391 
2392  if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
2393  || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
2394  {
2395  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
2396  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
2397  gl_info->fbo_ops.glDeleteRenderbuffers(1, &rb);
2398  checkGLcall("RB cleanup");
2399  }
2400  }
2401 
2402  if (format->glInternal != format->glGammaInternal)
2403  {
2404  delete_fbo_attachment(gl_info, type, object);
2405  create_and_bind_fbo_attachment(gl_info, format->flags[type], type, &object, format->glGammaInternal,
2406  format->glFormat, format->glType);
2407 
2408  status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
2409  checkGLcall("Framebuffer format check");
2410 
2412  {
2413  TRACE("Format %s's sRGB format is FBO attachable, type %u.\n",
2414  debug_d3dformat(format->id), type);
2416  if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
2417  format->glInternal = format->glGammaInternal;
2418  }
2419  else
2420  {
2421  WARN("Format %s's sRGB format is not FBO attachable, type %u.\n",
2422  debug_d3dformat(format->id), type);
2424  }
2425  }
2426  else if (status == GL_FRAMEBUFFER_COMPLETE)
2428 
2430  {
2431  gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, 0);
2432  gl_info->fbo_ops.glDeleteRenderbuffers(1, &color_rb);
2433  }
2434 
2435  delete_fbo_attachment(gl_info, type, object);
2436  checkGLcall("Framebuffer format check cleanup");
2437  }
2438 
2439  if (fallback_fmt_used && regular_fmt_used)
2440  {
2441  FIXME("Format %s needs different render target formats for different resource types.\n",
2442  debug_d3dformat(format->id));
2445  }
2446 }
2447 
2448 static void query_format_flag(struct wined3d_gl_info *gl_info, struct wined3d_format *format,
2449  GLint internal, GLenum pname, DWORD flag, const char *string)
2450 {
2451  GLint value;
2453 
2454  for (type = 0; type < ARRAY_SIZE(format->flags); ++type)
2455  {
2456  gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type), internal, pname, 1, &value);
2457  if (value == GL_FULL_SUPPORT)
2458  {
2459  TRACE("Format %s supports %s, resource type %u.\n", debug_d3dformat(format->id), string, type);
2460  format->flags[type] |= flag;
2461  }
2462  else
2463  {
2464  TRACE("Format %s doesn't support %s, resource type %u.\n", debug_d3dformat(format->id), string, type);
2465  format->flags[type] &= ~flag;
2466  }
2467  }
2468 }
2469 
2470 /* Context activation is done by the caller. */
2472 {
2473  const struct wined3d_gl_info *gl_info = ctx->gl_info;
2474  unsigned int i, type;
2475  GLuint fbo;
2476 
2477  if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
2478  {
2479  for (i = 0; i < gl_info->format_count; ++i)
2480  {
2481  GLint value;
2482  struct wined3d_format *format = &gl_info->formats[i];
2483  BOOL fallback_fmt_used = FALSE, regular_fmt_used = FALSE;
2484  GLenum rt_internal = format->rtInternal;
2485 
2486  if (!format->glInternal)
2487  continue;
2488 
2489  for (type = 0; type < ARRAY_SIZE(format->flags); ++type)
2490  {
2491  gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2492  format->glInternal, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
2493  if (value == GL_FULL_SUPPORT)
2494  {
2495  TRACE("Format %s is supported as FBO color attachment, resource type %u.\n",
2496  debug_d3dformat(format->id), type);
2498  format->rtInternal = format->glInternal;
2499  regular_fmt_used = TRUE;
2500 
2501  gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2502  format->glInternal, GL_FRAMEBUFFER_BLEND, 1, &value);
2503  if (value == GL_FULL_SUPPORT)
2504  {
2505  TRACE("Format %s supports post-pixelshader blending, resource type %u.\n",
2506  debug_d3dformat(format->id), type);
2508  }
2509  else
2510  {
2511  TRACE("Format %s doesn't support post-pixelshader blending, resource typed %u.\n",
2512  debug_d3dformat(format->id), type);
2514  }
2515  }
2516  else
2517  {
2518  if (!rt_internal)
2519  {
2521  {
2522  WARN("Format %s with rendertarget flag is not supported as FBO color attachment"
2523  " and no fallback specified, resource type %u.\n",
2524  debug_d3dformat(format->id), type);
2526  }
2527  else
2528  TRACE("Format %s is not supported as FBO color attachment,"
2529  " resource type %u.\n", debug_d3dformat(format->id), type);
2530  format->rtInternal = format->glInternal;
2531  }
2532  else
2533  {
2534  gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2535  rt_internal, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
2536  if (value == GL_FULL_SUPPORT)
2537  {
2538  TRACE("Format %s rtInternal format is supported as FBO color attachment,"
2539  " resource type %u.\n", debug_d3dformat(format->id), type);
2540  fallback_fmt_used = TRUE;
2541  }
2542  else
2543  {
2544  WARN("Format %s rtInternal format is not supported as FBO color attachment,"
2545  " resource type %u.\n", debug_d3dformat(format->id), type);
2547  }
2548  }
2549  }
2550 
2551  if (format->glInternal != format->glGammaInternal)
2552  {
2553  gl_info->gl_ops.ext.p_glGetInternalformativ(wined3d_gl_type_to_enum(type),
2554  format->glGammaInternal, GL_FRAMEBUFFER_RENDERABLE, 1, &value);
2555  if (value == GL_FULL_SUPPORT)
2556  {
2557  TRACE("Format %s's sRGB format is FBO attachable, resource type %u.\n",
2558  debug_d3dformat(format->id), type);
2560  if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
2561  format->glInternal = format->glGammaInternal;
2562  }
2563  else
2564  {
2565  WARN("Format %s's sRGB format is not FBO attachable, resource type %u.\n",
2566  debug_d3dformat(format->id), type);
2568  }
2569  }
2570  else if (format->flags[type] & WINED3DFMT_FLAG_FBO_ATTACHABLE)
2572  }
2573 
2574  if (fallback_fmt_used && regular_fmt_used)
2575  {
2576  FIXME("Format %s needs different render target formats for different resource types.\n",
2577  debug_d3dformat(format->id));
2580  }
2581  }
2582  return;
2583  }
2584 
2586  {
2587  gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
2588  gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
2589  gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);
2590  gl_info->gl_ops.gl.p_glReadBuffer(GL_COLOR_ATTACHMENT0);
2591  }
2592 
2593  for (i = 0; i < gl_info->format_count; ++i)
2594  {
2595  struct wined3d_format *format = &gl_info->formats[i];
2596 
2597  if (!format->glInternal) continue;
2598 
2600  {
2601  TRACE("Skipping format %s because it's a compressed format.\n",
2602  debug_d3dformat(format->id));
2603  continue;
2604  }
2605 
2607  {
2608  TRACE("Checking if format %s is supported as FBO color attachment...\n", debug_d3dformat(format->id));
2609  check_fbo_compat(ctx, format);
2610  }
2611  else
2612  {
2613  format->rtInternal = format->glInternal;
2614  }
2615  }
2616 
2618  gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
2619 }
2620 
2621 static GLenum lookup_gl_view_class(GLenum internal_format)
2622 {
2623  static const struct
2624  {
2625  GLenum internal_format;
2626  GLenum view_class;
2627  }
2628  view_classes[] =
2629  {
2630  /* 128-bit */
2634  /* 96-bit */
2638  /* 64-bit */
2647  /* 48-bit */
2653  /* 32-bit */
2671  /* 24-bit */
2677  /* 16-bit */
2687  /* 8-bit */
2692 
2693  /* RGTC1 */
2696  /* RGTC2 */
2699 
2700  /* BPTC unorm */
2703  /* BPTC float */
2706 
2707  /* DXT1 RGB */
2710  /* DXT1 RGBA */
2713  /* DXT3 */
2716  /* DXT5 */
2719  };
2720 
2721  unsigned int i;
2722 
2723  for (i = 0; i < ARRAY_SIZE(view_classes); ++i)
2724  {
2725  if (view_classes[i].internal_format == internal_format)
2726  return view_classes[i].view_class;
2727  }
2728 
2729  return GL_NONE;
2730 }
2731 
2733 {
2734  GLenum internal_view_class, gamma_view_class, rt_view_class;
2735 
2736  internal_view_class = lookup_gl_view_class(format->glInternal);
2737  gamma_view_class = lookup_gl_view_class(format->glGammaInternal);
2738  rt_view_class = lookup_gl_view_class(format->rtInternal);
2739 
2740  if (internal_view_class == gamma_view_class || gamma_view_class == rt_view_class)
2741  {
2742  format->gl_view_class = internal_view_class;
2743  TRACE("Format %s is member of GL view class %#x.\n",
2744  debug_d3dformat(format->id), format->gl_view_class);
2745  }
2746  else
2747  {
2748  format->gl_view_class = GL_NONE;
2749  }
2750 }
2751 
2752 static void query_internal_format(struct wined3d_adapter *adapter,
2753  struct wined3d_format *format, const struct wined3d_format_texture_info *texture_info,
2754  struct wined3d_gl_info *gl_info, BOOL srgb_write_supported, BOOL srgb_format)
2755 {
2757  unsigned int i, max_log2;
2758  GLenum target;
2759 
2760  if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
2761  {
2762  query_format_flag(gl_info, format, format->glInternal, GL_VERTEX_TEXTURE,
2763  WINED3DFMT_FLAG_VTF, "vertex texture usage");
2764  query_format_flag(gl_info, format, format->glInternal, GL_FILTER,
2765  WINED3DFMT_FLAG_FILTERING, "filtering");
2766 
2767  if (srgb_format || format->glGammaInternal != format->glInternal)
2768  {
2769  query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_READ,
2770  WINED3DFMT_FLAG_SRGB_READ, "sRGB read");
2771 
2772  if (srgb_write_supported)
2773  query_format_flag(gl_info, format, format->glGammaInternal, GL_SRGB_WRITE,
2774  WINED3DFMT_FLAG_SRGB_WRITE, "sRGB write");
2775  else
2777 
2779  format->glGammaInternal = format->glInternal;
2781  && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
2782  format->glInternal = format->glGammaInternal;
2783  }
2784  }
2785  else
2786  {
2787  if (!gl_info->limits.samplers[WINED3D_SHADER_TYPE_VERTEX])
2789 
2790  if (!(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
2794 
2795  if (srgb_format || format->glGammaInternal != format->glInternal)
2796  {
2797  /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */
2798  if (!gl_info->supported[EXT_TEXTURE_SRGB])
2799  {
2800  format->glGammaInternal = format->glInternal;
2802  }
2804  && gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
2805  {
2806  format->glInternal = format->glGammaInternal;
2807  }
2808  }
2809 
2810  if ((format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_SRGB_WRITE) && !srgb_write_supported)
2812 
2813  if (!gl_info->supported[ARB_DEPTH_TEXTURE]
2814  && texture_info->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
2815  {
2821  }
2822  }
2823 
2825 
2826  if (format->glInternal && format->flags[WINED3D_GL_RES_TYPE_RB]
2828  {
2829  if (gl_info->supported[ARB_INTERNALFORMAT_QUERY])
2830  {
2832  count = 0;
2833  GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
2834  GL_NUM_SAMPLE_COUNTS, 1, &count));
2836  FIXME("Unexpectedly high number of multisample types %d.\n", count);
2838  GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
2840  checkGLcall("query sample counts");
2841  for (i = 0; i < count; ++i)
2842  {
2843  if (multisample_types[i] > sizeof(format->multisample_types) * CHAR_BIT)
2844  continue;
2845  format->multisample_types |= 1u << (multisample_types[i] - 1);
2846  }
2847  }
2848  else
2849  {
2850 #ifdef __REACTOS__
2851  if (gl_info->limits.samples) {
2852 #endif
2853  max_log2 = wined3d_log2i(min(gl_info->limits.samples,
2854  sizeof(format->multisample_types) * CHAR_BIT));
2855  for (i = 1; i <= max_log2; ++i)
2856  format->multisample_types |= 1u << ((1u << i) - 1);
2857 #ifdef __REACTOS__
2858  }
2859 #endif
2860  }
2861  }
2862 }
2863 
2864 static BOOL init_format_texture_info(struct wined3d_adapter *adapter, struct wined3d_gl_info *gl_info)
2865 {
2866  struct wined3d_format *format, *srgb_format;
2868  struct shader_caps shader_caps;
2869  unsigned int i, j;
2870  BOOL srgb_write;
2871 
2872  adapter->fragment_pipe->get_caps(gl_info, &fragment_caps);
2873  adapter->shader_backend->shader_get_caps(gl_info, &shader_caps);
2876 
2877  for (i = 0; i < ARRAY_SIZE(format_texture_info); ++i)
2878  {
2879  if (!(format = get_format_internal(gl_info, format_texture_info[i].id)))
2880  return FALSE;
2881 
2882  if (!gl_info->supported[format_texture_info[i].extension])
2883  continue;
2884 
2885  /* ARB_texture_rg defines floating point formats, but only if
2886  * ARB_texture_float is also supported. */
2887  if (!gl_info->supported[ARB_TEXTURE_FLOAT]
2889  continue;
2890 
2891  /* ARB_texture_rg defines integer formats if EXT_texture_integer is also supported. */
2892  if (!gl_info->supported[EXT_TEXTURE_INTEGER]
2894  continue;
2895 
2896  format->glInternal = format_texture_info[i].gl_internal;
2897  format->glGammaInternal = format_texture_info[i].gl_srgb_internal;
2898  format->rtInternal = format_texture_info[i].gl_rt_internal;
2899  format->glFormat = format_texture_info[i].gl_format;
2900  format->glType = format_texture_info[i].gl_type;
2901  format->color_fixup = COLOR_FIXUP_IDENTITY;
2902  format->height_scale.numerator = 1;
2903  format->height_scale.denominator = 1;
2904 
2908 
2909  /* GL_ARB_depth_texture does not support 3D textures. It also says "cube textures are
2910  * problematic", but doesn't explicitly mandate that an error is generated. */
2911  if (gl_info->supported[EXT_TEXTURE3D]
2914 
2915  if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
2917 
2918  if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
2920 
2923 
2924  if (format->glGammaInternal != format->glInternal
2925  && !(adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL))
2926  {
2927  format->glGammaInternal = format->glInternal;
2929  }
2930 
2931  query_internal_format(adapter, format, &format_texture_info[i], gl_info, srgb_write, FALSE);
2932 
2933  /* Texture conversion stuff */
2934  format->conv_byte_count = format_texture_info[i].conv_byte_count;
2935  format->upload = format_texture_info[i].upload;
2936  format->download = format_texture_info[i].download;
2937 
2938  srgb_format = NULL;
2939  for (j = 0; j < ARRAY_SIZE(format_srgb_info); ++j)
2940  {
2941  if (format_srgb_info[j].base_format_id == format->id)
2942  {
2943  if (!(srgb_format = get_format_internal(gl_info, format_srgb_info[j].srgb_format_id)))
2944  return FALSE;
2945  break;
2946  }
2947  }
2948  if (!srgb_format)
2949  continue;
2950 
2951  copy_format(srgb_format, format);
2952 
2953  if (gl_info->supported[EXT_TEXTURE_SRGB]
2954  && !(adapter->d3d_info.wined3d_creation_flags & WINED3D_SRGB_READ_WRITE_CONTROL))
2955  {
2956  srgb_format->glInternal = format_texture_info[i].gl_srgb_internal;
2957  srgb_format->glGammaInternal = format_texture_info[i].gl_srgb_internal;
2959  query_internal_format(adapter, srgb_format, &format_texture_info[i], gl_info, srgb_write, TRUE);
2960  }
2961  }
2962 
2963  return TRUE;
2964 }
2965 
2966 static BOOL color_match(DWORD c1, DWORD c2, BYTE max_diff)
2967 {
2968  if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
2969  c1 >>= 8; c2 >>= 8;
2970  if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
2971  c1 >>= 8; c2 >>= 8;
2972  if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
2973  c1 >>= 8; c2 >>= 8;
2974  if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
2975  return TRUE;
2976 }
2977 
2978 /* A context is provided by the caller */
2979 static BOOL check_filter(const struct wined3d_gl_info *gl_info, GLenum internal)
2980 {
2981  static const DWORD data[] = {0x00000000, 0xffffffff};
2982  GLuint tex, fbo, buffer;
2983  DWORD readback[16 * 1];
2984  BOOL ret = FALSE;
2985 
2986  /* Render a filtered texture and see what happens. This is intended to detect the lack of
2987  * float16 filtering on ATI X1000 class cards. The drivers disable filtering instead of
2988  * falling back to software. If this changes in the future this code will get fooled and
2989  * apps might hit the software path due to incorrectly advertised caps.
2990  *
2991  * Its unlikely that this changes however. GL Games like Mass Effect depend on the filter
2992  * disable fallback, if Apple or ATI ever change the driver behavior they will break more
2993  * than Wine. The Linux binary <= r500 driver is not maintained any more anyway
2994  */
2995 
2996  while (gl_info->gl_ops.gl.p_glGetError());
2997 
2998  gl_info->gl_ops.gl.p_glGenTextures(1, &buffer);
2999  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
3000  memset(readback, 0x7e, sizeof(readback));
3001  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 1, 0,
3002  GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, readback);
3003  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
3004  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
3005  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3006  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3007  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3008 
3009  gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
3010  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
3011  gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, internal, 2, 1, 0,
3013  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
3014  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
3015  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
3016  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
3017  gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
3018  gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
3019 
3020  gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
3021  gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3022  gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffer, 0);
3023  gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);
3024 
3025  gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1);
3026  gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
3027  gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
3028  gl_info->gl_ops.gl.p_glLoadIdentity();
3029  gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
3030  gl_info->gl_ops.gl.p_glLoadIdentity();
3031 
3032  gl_info->gl_ops.gl.p_glClearColor(0, 1, 0, 0);
3033  gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
3034 
3035  gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
3036  gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 0.0);
3037  gl_info->gl_ops.gl.p_glVertex2f(-1.0f, -1.0f);
3038  gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 0.0);
3039  gl_info->gl_ops.gl.p_glVertex2f(1.0f, -1.0f);
3040  gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 1.0);
3041  gl_info->gl_ops.gl.p_glVertex2f(-1.0f, 1.0f);
3042  gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 1.0);
3043  gl_info->gl_ops.gl.p_glVertex2f(1.0f, 1.0f);
3044  gl_info->gl_ops.gl.p_glEnd();
3045 
3046  gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
3047  memset(readback, 0x7f, sizeof(readback));
3048  gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
3049  if (color_match(readback[6], 0xffffffff, 5) || color_match(readback[6], 0x00000000, 5)
3050  || color_match(readback[9], 0xffffffff, 5) || color_match(readback[9], 0x00000000, 5))
3051  {
3052  TRACE("Read back colors 0x%08x and 0x%08x close to unfiltered color, assuming no filtering\n",
3053  readback[6], readback[9]);
3054  ret = FALSE;
3055  }
3056  else
3057  {
3058  TRACE("Read back colors are 0x%08x and 0x%08x, assuming texture is filtered\n",
3059  readback[6], readback[9]);
3060  ret = TRUE;
3061  }
3062 
3063  gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
3064  gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
3065  gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
3066  gl_info->gl_ops.gl.p_glDeleteTextures(1, &buffer);
3067  gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
3068 
3069  if (gl_info->gl_ops.gl.p_glGetError())
3070  {
3071  FIXME("Error during filtering test for format %x, returning no filtering\n", internal);
3072  ret = FALSE;
3073  }
3074 
3075  return ret;
3076 }
3077 
3079 {
3080  struct wined3d_format *format;
3081  unsigned int fmt_idx, i;
3082  static const enum wined3d_format_id fmts16[] =
3083  {
3087  };
3088  BOOL filtered;
3089 
3090  if (gl_info->supported[ARB_INTERNALFORMAT_QUERY2])
3091  /* This was already handled by init_format_texture_info(). */
3092  return;
3093 
3095  || !gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
3096  {
3097  WARN("No FBO support, or no FBO ORM, guessing filter info from GL caps\n");
3098  if (vendor == HW_VENDOR_NVIDIA && gl_info->supported[ARB_TEXTURE_FLOAT])
3099  {
3100  TRACE("Nvidia card with texture_float support: Assuming float16 blending\n");
3101  filtered = TRUE;
3102  }
3103  else if (gl_info->limits.glsl_varyings > 44)
3104  {
3105  TRACE("More than 44 GLSL varyings - assuming d3d10 card with float16 blending\n");
3106  filtered = TRUE;
3107  }
3108  else
3109  {
3110  TRACE("Assuming no float16 blending\n");
3111  filtered = FALSE;
3112  }
3113 
3114  if (filtered)
3115  {
3116  for (i = 0; i < ARRAY_SIZE(fmts16); ++i)
3117  {
3118  fmt_idx = get_format_idx(fmts16[i]);
3119  format_set_flag(&gl_info->formats[fmt_idx], WINED3DFMT_FLAG_FILTERING);
3120  }
3121  }
3122  return;
3123  }
3124 
3125  for (i = 0; i < ARRAY_SIZE(fmts16); ++i)
3126  {
3127  fmt_idx = get_format_idx(fmts16[i]);
3128  format = &gl_info->formats[fmt_idx];
3129  if (!format->glInternal) continue; /* Not supported by GL */
3130 
3131  filtered = check_filter(gl_info, gl_info->formats[fmt_idx].glInternal);
3132  if (filtered)
3133  {
3134  TRACE("Format %s supports filtering\n", debug_d3dformat(fmts16[i]));
3136  }
3137  else
3138  {
3139  TRACE("Format %s does not support filtering\n", debug_d3dformat(fmts16[i]));
3140  }
3141  }
3142 }
3143 
3144 static void apply_format_fixups(struct wined3d_adapter *adapter, struct wined3d_gl_info *gl_info)
3145 {
3146  unsigned int i;
3147  int idx;
3148 
3150  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3152 
3154  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3156 
3158  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3160 
3162  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3164 
3166  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3168 
3169  /* GL_ATI_envmap_bumpmap in theory supports R8G8_SNORM but is no longer supported by
3170  * any driver. */
3171  if (gl_info->supported[NV_TEXTURE_SHADER] || gl_info->supported[EXT_TEXTURE_SNORM])
3172  {
3173  /* R8G8_SNORM and R16G16_SNORM need a fixup of the undefined blue channel. OpenGL
3174  * returns 0.0 when sampling from it, DirectX 1.0. So we always have in-shader
3175  * conversion for this format. */
3177  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3180  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3182  }
3183  else
3184  {
3185  /* Emulate using unsigned formats. This requires load-time conversion in addition to the
3186  * fixups here. */
3188  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3191  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3194  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3197  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3199  }
3200 
3201  if (!gl_info->supported[NV_TEXTURE_SHADER])
3202  {
3204  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3206  }
3207 
3209  {
3211  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3213 
3215  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3217  }
3218  else if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC])
3219  {
3221  gl_info->formats[idx].color_fixup= create_color_fixup_desc(
3223  }
3224 
3225  if (!gl_info->supported[APPLE_YCBCR_422] && (gl_info->supported[ARB_FRAGMENT_PROGRAM]
3226  || (gl_info->supported[ARB_FRAGMENT_SHADER] && gl_info->supported[ARB_VERTEX_SHADER])))
3227  {
3229  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YUY2);
3230 
3232  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_UYVY);
3233  }
3234  else if (!gl_info->supported[APPLE_YCBCR_422] && (!gl_info->supported[ARB_FRAGMENT_PROGRAM]
3235  && (!gl_info->supported[ARB_FRAGMENT_SHADER] || !gl_info->supported[ARB_VERTEX_SHADER])))
3236  {
3238  gl_info->formats[idx].glInternal = 0;
3239 
3241  gl_info->formats[idx].glInternal = 0;
3242  }
3243 
3244  if (gl_info->supported[ARB_FRAGMENT_PROGRAM]
3245  || (gl_info->supported[ARB_FRAGMENT_SHADER] && gl_info->supported[ARB_VERTEX_SHADER]))
3246  {
3249  gl_info->formats[idx].height_scale.numerator = 3;
3250  gl_info->formats[idx].height_scale.denominator = 2;
3251  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YV12);
3252 
3255  gl_info->formats[idx].height_scale.numerator = 3;
3256  gl_info->formats[idx].height_scale.denominator = 2;
3257  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_NV12);
3258  }
3259  else
3260  {
3262  gl_info->formats[idx].glInternal = 0;
3263 
3265  gl_info->formats[idx].glInternal = 0;
3266  }
3267 
3268  if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
3269  {
3271  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3274  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3277  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3280  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3283  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3285  }
3286 
3287  if (gl_info->supported[ARB_TEXTURE_RG])
3288  {
3290  gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3292  }
3293 
3294  if (gl_info->supported[ARB_FRAGMENT_PROGRAM] || gl_info->supported[ARB_FRAGMENT_SHADER])
3295  {
3297  gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8);
3298  }
3299 
3300  if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
3301  {
3303  gl_info->formats[idx].gl_vtx_format = GL_BGRA;
3304  }
3305 
3306  if (!gl_info->supported[ARB_HALF_FLOAT_VERTEX])
3307  {
3308  /* Do not change the size of the type, it is CPU side. We have to change the GPU-side information though.
3309  * It is the job of the vertex buffer code to make sure that the vbos have the right format */
3311  gl_info->formats[idx].gl_vtx_type = GL_FLOAT;
3312 
3314  gl_info->formats[idx].gl_vtx_type = GL_FLOAT;
3315  }
3316 
3317  if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
3318  {
3321 
3324 
3327  }
3328 
3329  if (gl_info->quirks & WINED3D_QUIRK_BROKEN_RGBA16)
3330  {
3333  }
3334 
3335  /* ATI instancing hack: Although ATI cards do not support Shader Model
3336  * 3.0, they support instancing. To query if the card supports instancing
3337  * CheckDeviceFormat() with the special format MAKEFOURCC('I','N','S','T')
3338  * is used. Should an application check for this, provide a proper return
3339  * value. We can do instancing with all shader versions, but we need
3340  * vertex shaders.
3341  *
3342  * Additionally applications have to set the D3DRS_POINTSIZE render state
3343  * to MAKEFOURCC('I','N','S','T') once to enable instancing. Wined3d
3344  * doesn't need that and just ignores it.
3345  *
3346  * With Shader Model 3.0 capable cards Instancing 'just works' in Windows. */
3347  /* FIXME: This should just check the shader backend caps. */
3348  if (gl_info->supported[ARB_VERTEX_PROGRAM] || gl_info->supported[ARB_VERTEX_SHADER])
3349  {
3352  }
3353 
3354  /* Depth bound test. To query if the card supports it CheckDeviceFormat()
3355  * with the special format MAKEFOURCC('N','V','D','B') is used. It is
3356  * enabled by setting D3DRS_ADAPTIVETESS_X render state to
3357  * MAKEFOURCC('N','V','D','B') and then controlled by setting
3358  * D3DRS_ADAPTIVETESS_Z (zMin) and D3DRS_ADAPTIVETESS_W (zMax) to test
3359  * value. */
3360  if (gl_info->supported[EXT_DEPTH_BOUNDS_TEST])
3361  {
3364  }
3365 
3366  /* RESZ aka AMD DX9-level hack for multisampled depth buffer resolve. You query for RESZ
3367  * support by checking for availability of MAKEFOURCC('R','E','S','Z') surfaces with
3368  * RENDERTARGET usage. */
3369  if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT])
3370  {
3373  }
3374 
3375  for (i = 0; i < gl_info->format_count; ++i)
3376  {
3377  struct wined3d_format *format = &gl_info->formats[i];
3378 
3380  continue;
3381 
3382  if (is_identity_fixup(format->color_fixup))
3383  continue;
3384 
3385  TRACE("Checking support for fixup:\n");
3386  dump_color_fixup_desc(format->color_fixup);
3387  if (!adapter->shader_backend->shader_color_fixup_supported(format->color_fixup)
3388  || !adapter->fragment_pipe->color_fixup_supported(format->color_fixup))
3389  {
3390  TRACE("[FAILED]\n");<