xref: /reactos/dll/directx/wine/wined3d/utils.c (revision f4d29a74)
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 
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 
36 #define WINED3D_FORMAT_FOURCC_BASE (WINED3DFMT_BC7_UNORM_SRGB + 1)
37 
38 static const struct
39 {
40     enum wined3d_format_id id;
41     unsigned int idx;
42 }
43 format_index_remap[] =
44 {
45     {WINED3DFMT_UYVY,         WINED3D_FORMAT_FOURCC_BASE},
46     {WINED3DFMT_YUY2,         WINED3D_FORMAT_FOURCC_BASE + 1},
47     {WINED3DFMT_YV12,         WINED3D_FORMAT_FOURCC_BASE + 2},
48     {WINED3DFMT_DXT1,         WINED3D_FORMAT_FOURCC_BASE + 3},
49     {WINED3DFMT_DXT2,         WINED3D_FORMAT_FOURCC_BASE + 4},
50     {WINED3DFMT_DXT3,         WINED3D_FORMAT_FOURCC_BASE + 5},
51     {WINED3DFMT_DXT4,         WINED3D_FORMAT_FOURCC_BASE + 6},
52     {WINED3DFMT_DXT5,         WINED3D_FORMAT_FOURCC_BASE + 7},
53     {WINED3DFMT_MULTI2_ARGB8, WINED3D_FORMAT_FOURCC_BASE + 8},
54     {WINED3DFMT_G8R8_G8B8,    WINED3D_FORMAT_FOURCC_BASE + 9},
55     {WINED3DFMT_R8G8_B8G8,    WINED3D_FORMAT_FOURCC_BASE + 10},
56     {WINED3DFMT_ATI1N,        WINED3D_FORMAT_FOURCC_BASE + 11},
57     {WINED3DFMT_ATI2N,        WINED3D_FORMAT_FOURCC_BASE + 12},
58     {WINED3DFMT_INST,         WINED3D_FORMAT_FOURCC_BASE + 13},
59     {WINED3DFMT_NVDB,         WINED3D_FORMAT_FOURCC_BASE + 14},
60     {WINED3DFMT_NVHU,         WINED3D_FORMAT_FOURCC_BASE + 15},
61     {WINED3DFMT_NVHS,         WINED3D_FORMAT_FOURCC_BASE + 16},
62     {WINED3DFMT_INTZ,         WINED3D_FORMAT_FOURCC_BASE + 17},
63     {WINED3DFMT_RESZ,         WINED3D_FORMAT_FOURCC_BASE + 18},
64     {WINED3DFMT_NULL,         WINED3D_FORMAT_FOURCC_BASE + 19},
65     {WINED3DFMT_R16,          WINED3D_FORMAT_FOURCC_BASE + 20},
66     {WINED3DFMT_AL16,         WINED3D_FORMAT_FOURCC_BASE + 21},
67     {WINED3DFMT_NV12,         WINED3D_FORMAT_FOURCC_BASE + 22},
68 };
69 
70 #define WINED3D_FORMAT_COUNT (WINED3D_FORMAT_FOURCC_BASE + ARRAY_SIZE(format_index_remap))
71 
72 struct wined3d_format_channels
73 {
74     enum wined3d_format_id id;
75     DWORD red_size, green_size, blue_size, alpha_size;
76     DWORD red_offset, green_offset, blue_offset, alpha_offset;
77     UINT bpp;
78     BYTE depth_size, stencil_size;
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 
176 enum wined3d_channel_type
177 {
178     WINED3D_CHANNEL_TYPE_NONE,
179     WINED3D_CHANNEL_TYPE_UNORM,
180     WINED3D_CHANNEL_TYPE_SNORM,
181     WINED3D_CHANNEL_TYPE_UINT,
182     WINED3D_CHANNEL_TYPE_SINT,
183     WINED3D_CHANNEL_TYPE_FLOAT,
184     WINED3D_CHANNEL_TYPE_DEPTH,
185     WINED3D_CHANNEL_TYPE_STENCIL,
186     WINED3D_CHANNEL_TYPE_UNUSED,
187 };
188 
189 struct wined3d_typed_format_info
190 {
191     enum wined3d_format_id id;
192     enum wined3d_format_id typeless_id;
193     const char *channels;
194 };
195 
196 /**
197  * The last entry for a given typeless format defines its internal format.
198  *
199  * u - WINED3D_CHANNEL_TYPE_UNORM
200  * i - WINED3D_CHANNEL_TYPE_SNORM
201  * U - WINED3D_CHANNEL_TYPE_UINT
202  * I - WINED3D_CHANNEL_TYPE_SINT
203  * F - WINED3D_CHANNEL_TYPE_FLOAT
204  * D - WINED3D_CHANNEL_TYPE_DEPTH
205  * S - WINED3D_CHANNEL_TYPE_STENCIL
206  * X - WINED3D_CHANNEL_TYPE_UNUSED
207  */
208 static const struct wined3d_typed_format_info typed_formats[] =
209 {
210     {WINED3DFMT_R32G32B32A32_UINT,        WINED3DFMT_R32G32B32A32_TYPELESS, "UUUU"},
211     {WINED3DFMT_R32G32B32A32_SINT,        WINED3DFMT_R32G32B32A32_TYPELESS, "IIII"},
212     {WINED3DFMT_R32G32B32A32_FLOAT,       WINED3DFMT_R32G32B32A32_TYPELESS, "FFFF"},
213     {WINED3DFMT_R32G32B32_UINT,           WINED3DFMT_R32G32B32_TYPELESS,    "UUU"},
214     {WINED3DFMT_R32G32B32_SINT,           WINED3DFMT_R32G32B32_TYPELESS,    "III"},
215     {WINED3DFMT_R32G32B32_FLOAT,          WINED3DFMT_R32G32B32_TYPELESS,    "FFF"},
216     {WINED3DFMT_R16G16B16A16_UNORM,       WINED3DFMT_R16G16B16A16_TYPELESS, "uuuu"},
217     {WINED3DFMT_R16G16B16A16_SNORM,       WINED3DFMT_R16G16B16A16_TYPELESS, "iiii"},
218     {WINED3DFMT_R16G16B16A16_UINT,        WINED3DFMT_R16G16B16A16_TYPELESS, "UUUU"},
219     {WINED3DFMT_R16G16B16A16_SINT,        WINED3DFMT_R16G16B16A16_TYPELESS, "IIII"},
220     {WINED3DFMT_R16G16B16A16_FLOAT,       WINED3DFMT_R16G16B16A16_TYPELESS, "FFFF"},
221     {WINED3DFMT_R32G32_UINT,              WINED3DFMT_R32G32_TYPELESS,       "UU"},
222     {WINED3DFMT_R32G32_SINT,              WINED3DFMT_R32G32_TYPELESS,       "II"},
223     {WINED3DFMT_R32G32_FLOAT,             WINED3DFMT_R32G32_TYPELESS,       "FF"},
224     {WINED3DFMT_R32_FLOAT_X8X24_TYPELESS, WINED3DFMT_R32G8X24_TYPELESS,     "DX"},
225     {WINED3DFMT_X32_TYPELESS_G8X24_UINT,  WINED3DFMT_R32G8X24_TYPELESS,     "XS"},
226     {WINED3DFMT_D32_FLOAT_S8X24_UINT,     WINED3DFMT_R32G8X24_TYPELESS,     "DS"},
227     {WINED3DFMT_R10G10B10A2_SNORM,        WINED3DFMT_R10G10B10A2_TYPELESS,  "iiii"},
228     {WINED3DFMT_R10G10B10A2_UINT,         WINED3DFMT_R10G10B10A2_TYPELESS,  "UUUU"},
229     {WINED3DFMT_R10G10B10A2_UNORM,        WINED3DFMT_R10G10B10A2_TYPELESS,  "uuuu"},
230     {WINED3DFMT_R8G8B8A8_UINT,            WINED3DFMT_R8G8B8A8_TYPELESS,     "UUUU"},
231     {WINED3DFMT_R8G8B8A8_SINT,            WINED3DFMT_R8G8B8A8_TYPELESS,     "IIII"},
232     {WINED3DFMT_R8G8B8A8_SNORM,           WINED3DFMT_R8G8B8A8_TYPELESS,     "iiii"},
233     {WINED3DFMT_R8G8B8A8_UNORM_SRGB,      WINED3DFMT_R8G8B8A8_TYPELESS,     "uuuu"},
234     {WINED3DFMT_R8G8B8A8_UNORM,           WINED3DFMT_R8G8B8A8_TYPELESS,     "uuuu"},
235     {WINED3DFMT_R16G16_UNORM,             WINED3DFMT_R16G16_TYPELESS,       "uu"},
236     {WINED3DFMT_R16G16_SNORM,             WINED3DFMT_R16G16_TYPELESS,       "ii"},
237     {WINED3DFMT_R16G16_UINT,              WINED3DFMT_R16G16_TYPELESS,       "UU"},
238     {WINED3DFMT_R16G16_SINT,              WINED3DFMT_R16G16_TYPELESS,       "II"},
239     {WINED3DFMT_R16G16_FLOAT,             WINED3DFMT_R16G16_TYPELESS,       "FF"},
240     {WINED3DFMT_D32_FLOAT,                WINED3DFMT_R32_TYPELESS,          "D"},
241     {WINED3DFMT_R32_FLOAT,                WINED3DFMT_R32_TYPELESS,          "F"},
242     {WINED3DFMT_R32_UINT,                 WINED3DFMT_R32_TYPELESS,          "U"},
243     {WINED3DFMT_R32_SINT,                 WINED3DFMT_R32_TYPELESS,          "I"},
244     {WINED3DFMT_R24_UNORM_X8_TYPELESS,    WINED3DFMT_R24G8_TYPELESS,        "DX"},
245     {WINED3DFMT_X24_TYPELESS_G8_UINT,     WINED3DFMT_R24G8_TYPELESS,        "XS"},
246     {WINED3DFMT_D24_UNORM_S8_UINT,        WINED3DFMT_R24G8_TYPELESS,        "DS"},
247     {WINED3DFMT_R8G8_SNORM,               WINED3DFMT_R8G8_TYPELESS,         "ii"},
248     {WINED3DFMT_R8G8_UNORM,               WINED3DFMT_R8G8_TYPELESS,         "uu"},
249     {WINED3DFMT_R8G8_UINT,                WINED3DFMT_R8G8_TYPELESS,         "UU"},
250     {WINED3DFMT_R8G8_SINT,                WINED3DFMT_R8G8_TYPELESS,         "II"},
251     {WINED3DFMT_D16_UNORM,                WINED3DFMT_R16_TYPELESS,          "D"},
252     {WINED3DFMT_R16_UNORM,                WINED3DFMT_R16_TYPELESS,          "u"},
253     {WINED3DFMT_R16_SNORM,                WINED3DFMT_R16_TYPELESS,          "i"},
254     {WINED3DFMT_R16_UINT,                 WINED3DFMT_R16_TYPELESS,          "U"},
255     {WINED3DFMT_R16_SINT,                 WINED3DFMT_R16_TYPELESS,          "I"},
256     {WINED3DFMT_R16_FLOAT,                WINED3DFMT_R16_TYPELESS,          "F"},
257     {WINED3DFMT_R8_UNORM,                 WINED3DFMT_R8_TYPELESS,           "u"},
258     {WINED3DFMT_R8_SNORM,                 WINED3DFMT_R8_TYPELESS,           "i"},
259     {WINED3DFMT_R8_UINT,                  WINED3DFMT_R8_TYPELESS,           "U"},
260     {WINED3DFMT_R8_SINT,                  WINED3DFMT_R8_TYPELESS,           "I"},
261     {WINED3DFMT_BC1_UNORM_SRGB,           WINED3DFMT_BC1_TYPELESS,          ""},
262     {WINED3DFMT_BC1_UNORM,                WINED3DFMT_BC1_TYPELESS,          ""},
263     {WINED3DFMT_BC2_UNORM_SRGB,           WINED3DFMT_BC2_TYPELESS,          ""},
264     {WINED3DFMT_BC2_UNORM,                WINED3DFMT_BC2_TYPELESS,          ""},
265     {WINED3DFMT_BC3_UNORM_SRGB,           WINED3DFMT_BC3_TYPELESS,          ""},
266     {WINED3DFMT_BC3_UNORM,                WINED3DFMT_BC3_TYPELESS,          ""},
267     {WINED3DFMT_BC4_UNORM,                WINED3DFMT_BC4_TYPELESS,          ""},
268     {WINED3DFMT_BC4_SNORM,                WINED3DFMT_BC4_TYPELESS,          ""},
269     {WINED3DFMT_BC5_UNORM,                WINED3DFMT_BC5_TYPELESS,          ""},
270     {WINED3DFMT_BC5_SNORM,                WINED3DFMT_BC5_TYPELESS,          ""},
271     {WINED3DFMT_BC6H_UF16,                WINED3DFMT_BC6H_TYPELESS,         ""},
272     {WINED3DFMT_BC6H_SF16,                WINED3DFMT_BC6H_TYPELESS,         ""},
273     {WINED3DFMT_BC7_UNORM_SRGB,           WINED3DFMT_BC7_TYPELESS,          ""},
274     {WINED3DFMT_BC7_UNORM,                WINED3DFMT_BC7_TYPELESS,          ""},
275     {WINED3DFMT_B8G8R8A8_UNORM_SRGB,      WINED3DFMT_B8G8R8A8_TYPELESS,     "uuuu"},
276     {WINED3DFMT_B8G8R8A8_UNORM,           WINED3DFMT_B8G8R8A8_TYPELESS,     "uuuu"},
277     {WINED3DFMT_B8G8R8X8_UNORM_SRGB,      WINED3DFMT_B8G8R8X8_TYPELESS,     "uuuX"},
278     {WINED3DFMT_B8G8R8X8_UNORM,           WINED3DFMT_B8G8R8X8_TYPELESS,     "uuuX"},
279 };
280 
281 struct wined3d_typeless_format_depth_stencil_info
282 {
283     enum wined3d_format_id typeless_id;
284     enum wined3d_format_id depth_stencil_id;
285     enum wined3d_format_id depth_view_id;
286     enum wined3d_format_id stencil_view_id;
287     BOOL separate_depth_view_format;
288 };
289 
290 static const struct wined3d_typeless_format_depth_stencil_info typeless_depth_stencil_formats[] =
291 {
292     {WINED3DFMT_R32G8X24_TYPELESS, WINED3DFMT_D32_FLOAT_S8X24_UINT,
293             WINED3DFMT_R32_FLOAT_X8X24_TYPELESS, WINED3DFMT_X32_TYPELESS_G8X24_UINT, TRUE},
294     {WINED3DFMT_R24G8_TYPELESS,    WINED3DFMT_D24_UNORM_S8_UINT,
295             WINED3DFMT_R24_UNORM_X8_TYPELESS,    WINED3DFMT_X24_TYPELESS_G8_UINT,    TRUE},
296     {WINED3DFMT_R32_TYPELESS,      WINED3DFMT_D32_FLOAT, WINED3DFMT_R32_FLOAT},
297     {WINED3DFMT_R16_TYPELESS,      WINED3DFMT_D16_UNORM, WINED3DFMT_R16_UNORM},
298 };
299 
300 struct wined3d_format_ddi_info
301 {
302     enum wined3d_format_id id;
303     D3DDDIFORMAT ddi_format;
304 };
305 
306 static const struct wined3d_format_ddi_info ddi_formats[] =
307 {
308     {WINED3DFMT_B8G8R8_UNORM,       D3DDDIFMT_R8G8B8},
309     {WINED3DFMT_B8G8R8A8_UNORM,     D3DDDIFMT_A8R8G8B8},
310     {WINED3DFMT_B8G8R8X8_UNORM,     D3DDDIFMT_X8R8G8B8},
311     {WINED3DFMT_B5G6R5_UNORM,       D3DDDIFMT_R5G6B5},
312     {WINED3DFMT_B5G5R5X1_UNORM,     D3DDDIFMT_X1R5G5B5},
313     {WINED3DFMT_B5G5R5A1_UNORM,     D3DDDIFMT_A1R5G5B5},
314     {WINED3DFMT_B4G4R4A4_UNORM,     D3DDDIFMT_A4R4G4B4},
315     {WINED3DFMT_B4G4R4X4_UNORM,     D3DDDIFMT_X4R4G4B4},
316     {WINED3DFMT_P8_UINT,            D3DDDIFMT_P8},
317 };
318 
319 struct wined3d_format_base_flags
320 {
321     enum wined3d_format_id id;
322     DWORD flags;
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. */
328 static const struct wined3d_format_base_flags format_base_flags[] =
329 {
330     {WINED3DFMT_ATI1N,                WINED3DFMT_FLAG_BROKEN_PITCH},
331     {WINED3DFMT_ATI2N,                WINED3DFMT_FLAG_BROKEN_PITCH},
332     {WINED3DFMT_R11G11B10_FLOAT,      WINED3DFMT_FLAG_FLOAT},
333     {WINED3DFMT_D32_FLOAT,            WINED3DFMT_FLAG_FLOAT},
334     {WINED3DFMT_S8_UINT_D24_FLOAT,    WINED3DFMT_FLAG_FLOAT},
335     {WINED3DFMT_D32_FLOAT_S8X24_UINT, WINED3DFMT_FLAG_FLOAT},
336     {WINED3DFMT_INST,                 WINED3DFMT_FLAG_EXTENSION},
337     {WINED3DFMT_NULL,                 WINED3DFMT_FLAG_EXTENSION},
338     {WINED3DFMT_NVDB,                 WINED3DFMT_FLAG_EXTENSION},
339     {WINED3DFMT_RESZ,                 WINED3DFMT_FLAG_EXTENSION},
340 };
341 
342 struct wined3d_format_block_info
343 {
344     enum wined3d_format_id id;
345     UINT block_width;
346     UINT block_height;
347     UINT block_byte_count;
348     BOOL verify;
349 };
350 
351 static const struct wined3d_format_block_info format_block_info[] =
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 
374 struct wined3d_format_vertex_info
375 {
376     enum wined3d_format_id id;
377     enum wined3d_ffp_emit_idx emit_idx;
378     unsigned int component_count;
379     GLenum gl_vtx_type;
380     GLboolean gl_normalized;
381     enum wined3d_gl_extension extension;
382 };
383 
384 static const struct wined3d_format_vertex_info format_vertex_info[] =
385 {
386     {WINED3DFMT_R32_FLOAT,          WINED3D_FFP_EMIT_FLOAT1,    1, GL_FLOAT,                       GL_FALSE},
387     {WINED3DFMT_R32G32_FLOAT,       WINED3D_FFP_EMIT_FLOAT2,    2, GL_FLOAT,                       GL_FALSE},
388     {WINED3DFMT_R32G32B32_FLOAT,    WINED3D_FFP_EMIT_FLOAT3,    3, GL_FLOAT,                       GL_FALSE},
389     {WINED3DFMT_R32G32B32A32_FLOAT, WINED3D_FFP_EMIT_FLOAT4,    4, GL_FLOAT,                       GL_FALSE},
390     {WINED3DFMT_B8G8R8A8_UNORM,     WINED3D_FFP_EMIT_D3DCOLOR,  4, GL_UNSIGNED_BYTE,               GL_TRUE },
391     {WINED3DFMT_R8G8B8A8_UINT,      WINED3D_FFP_EMIT_UBYTE4,    4, GL_UNSIGNED_BYTE,               GL_FALSE},
392     {WINED3DFMT_R16G16_UINT,        WINED3D_FFP_EMIT_INVALID,   2, GL_UNSIGNED_SHORT,              GL_FALSE},
393     {WINED3DFMT_R16G16_SINT,        WINED3D_FFP_EMIT_SHORT2,    2, GL_SHORT,                       GL_FALSE},
394     {WINED3DFMT_R16G16B16A16_SINT,  WINED3D_FFP_EMIT_SHORT4,    4, GL_SHORT,                       GL_FALSE},
395     {WINED3DFMT_R8G8B8A8_UNORM,     WINED3D_FFP_EMIT_UBYTE4N,   4, GL_UNSIGNED_BYTE,               GL_TRUE },
396     {WINED3DFMT_R16G16_SNORM,       WINED3D_FFP_EMIT_SHORT2N,   2, GL_SHORT,                       GL_TRUE },
397     {WINED3DFMT_R16G16B16A16_SNORM, WINED3D_FFP_EMIT_SHORT4N,   4, GL_SHORT,                       GL_TRUE },
398     {WINED3DFMT_R16G16_UNORM,       WINED3D_FFP_EMIT_USHORT2N,  2, GL_UNSIGNED_SHORT,              GL_TRUE },
399     {WINED3DFMT_R16G16B16A16_UNORM, WINED3D_FFP_EMIT_USHORT4N,  4, GL_UNSIGNED_SHORT,              GL_TRUE },
400     {WINED3DFMT_R10G10B10X2_UINT,   WINED3D_FFP_EMIT_UDEC3,     3, GL_UNSIGNED_SHORT,              GL_FALSE},
401     {WINED3DFMT_R10G10B10X2_SNORM,  WINED3D_FFP_EMIT_DEC3N,     3, GL_SHORT,                       GL_TRUE },
402     {WINED3DFMT_R10G10B10A2_UNORM,  WINED3D_FFP_EMIT_INVALID,   4, GL_UNSIGNED_INT_2_10_10_10_REV, GL_TRUE,
403             ARB_VERTEX_TYPE_2_10_10_10_REV},
404     {WINED3DFMT_R16G16_FLOAT,       WINED3D_FFP_EMIT_FLOAT16_2, 2, GL_HALF_FLOAT,                  GL_FALSE},
405     {WINED3DFMT_R16G16B16A16_FLOAT, WINED3D_FFP_EMIT_FLOAT16_4, 4, GL_HALF_FLOAT,                  GL_FALSE},
406     {WINED3DFMT_R8G8B8A8_SNORM,     WINED3D_FFP_EMIT_INVALID,   4, GL_BYTE,                        GL_TRUE },
407     {WINED3DFMT_R8G8B8A8_SINT,      WINED3D_FFP_EMIT_INVALID,   4, GL_BYTE,                        GL_FALSE},
408     {WINED3DFMT_R16G16B16A16_UINT,  WINED3D_FFP_EMIT_INVALID,   4, GL_UNSIGNED_SHORT,              GL_FALSE},
409     {WINED3DFMT_R8_UNORM,           WINED3D_FFP_EMIT_INVALID,   1, GL_UNSIGNED_BYTE,               GL_TRUE},
410     {WINED3DFMT_R8_UINT,            WINED3D_FFP_EMIT_INVALID,   1, GL_UNSIGNED_BYTE,               GL_FALSE},
411     {WINED3DFMT_R8_SINT,            WINED3D_FFP_EMIT_INVALID,   1, GL_BYTE,                        GL_FALSE},
412     {WINED3DFMT_R16_UINT,           WINED3D_FFP_EMIT_INVALID,   1, GL_UNSIGNED_SHORT,              GL_FALSE},
413     {WINED3DFMT_R16_SINT,           WINED3D_FFP_EMIT_INVALID,   1, GL_SHORT,                       GL_FALSE},
414     {WINED3DFMT_R32_UINT,           WINED3D_FFP_EMIT_INVALID,   1, GL_UNSIGNED_INT,                GL_FALSE},
415     {WINED3DFMT_R32_SINT,           WINED3D_FFP_EMIT_INVALID,   1, GL_INT,                         GL_FALSE},
416     {WINED3DFMT_R32G32_UINT,        WINED3D_FFP_EMIT_INVALID,   2, GL_UNSIGNED_INT,                GL_FALSE},
417     {WINED3DFMT_R32G32_SINT,        WINED3D_FFP_EMIT_INVALID,   2, GL_INT,                         GL_FALSE},
418     {WINED3DFMT_R32G32B32_UINT,     WINED3D_FFP_EMIT_INVALID,   3, GL_UNSIGNED_INT,                GL_FALSE},
419     {WINED3DFMT_R32G32B32A32_UINT,  WINED3D_FFP_EMIT_INVALID,   4, GL_UNSIGNED_INT,                GL_FALSE},
420     {WINED3DFMT_R32G32B32A32_SINT,  WINED3D_FFP_EMIT_INVALID,   4, GL_INT,                         GL_FALSE},
421 };
422 
423 struct wined3d_format_texture_info
424 {
425     enum wined3d_format_id id;
426     GLint gl_internal;
427     GLint gl_srgb_internal;
428     GLint gl_rt_internal;
429     GLint gl_format;
430     GLint gl_type;
431     unsigned int conv_byte_count;
432     unsigned int flags;
433     enum wined3d_gl_extension extension;
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 
887 static BOOL color_in_range(const struct wined3d_color_key *color_key, DWORD color)
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 
1007 const struct wined3d_color_key_conversion * wined3d_format_get_color_key_conversion(
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     {
1020         {WINED3DFMT_B5G6R5_UNORM,   {WINED3DFMT_B5G5R5A1_UNORM, convert_b5g6r5_unorm_b5g5r5a1_unorm_color_key   }},
1021         {WINED3DFMT_B5G5R5X1_UNORM, {WINED3DFMT_B5G5R5A1_UNORM, convert_b5g5r5x1_unorm_b5g5r5a1_unorm_color_key }},
1022         {WINED3DFMT_B8G8R8_UNORM,   {WINED3DFMT_B8G8R8A8_UNORM, convert_b8g8r8_unorm_b8g8r8a8_unorm_color_key   }},
1023         {WINED3DFMT_B8G8R8X8_UNORM, {WINED3DFMT_B8G8R8A8_UNORM, convert_b8g8r8x8_unorm_b8g8r8a8_unorm_color_key }},
1024         {WINED3DFMT_B8G8R8A8_UNORM, {WINED3DFMT_B8G8R8A8_UNORM, convert_b8g8r8a8_unorm_b8g8r8a8_unorm_color_key }},
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 */
1064 static const struct wined3d_format_texture_info format_texture_info[] =
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      */
1077     {WINED3DFMT_UYVY,                   GL_RG8,                           GL_RG8,                                 0,
1078             GL_RG,                      GL_UNSIGNED_BYTE,                 0,
1079             WINED3DFMT_FLAG_FILTERING,
1080             ARB_TEXTURE_RG,             NULL},
1081     {WINED3DFMT_UYVY,                   GL_LUMINANCE8_ALPHA8,             GL_LUMINANCE8_ALPHA8,                   0,
1082             GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
1083             WINED3DFMT_FLAG_FILTERING,
1084             WINED3D_GL_LEGACY_CONTEXT,  NULL},
1085     {WINED3DFMT_UYVY,                   GL_RGB,                           GL_RGB,                                 0,
1086             GL_YCBCR_422_APPLE,         GL_UNSIGNED_SHORT_8_8_APPLE,      0,
1087             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_FILTERING,
1088             APPLE_YCBCR_422,            NULL},
1089     {WINED3DFMT_YUY2,                   GL_RG8,                           GL_RG8,                                 0,
1090             GL_RG,                      GL_UNSIGNED_BYTE,                 0,
1091             WINED3DFMT_FLAG_FILTERING,
1092             ARB_TEXTURE_RG,             NULL},
1093     {WINED3DFMT_YUY2,                   GL_LUMINANCE8_ALPHA8,             GL_LUMINANCE8_ALPHA8,                   0,
1094             GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
1095             WINED3DFMT_FLAG_FILTERING,
1096             WINED3D_GL_LEGACY_CONTEXT,  NULL},
1097     {WINED3DFMT_YUY2,                   GL_RGB,                           GL_RGB,                                 0,
1098             GL_YCBCR_422_APPLE,         GL_UNSIGNED_SHORT_8_8_REV_APPLE,  0,
1099             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_FILTERING,
1100             APPLE_YCBCR_422,            NULL},
1101     {WINED3DFMT_YV12,                   GL_R8,                            GL_R8,                                  0,
1102             GL_RED,                     GL_UNSIGNED_BYTE,                 0,
1103             WINED3DFMT_FLAG_FILTERING,
1104             ARB_TEXTURE_RG,             NULL},
1105     {WINED3DFMT_YV12,                   GL_ALPHA8,                        GL_ALPHA8,                              0,
1106             GL_ALPHA,                   GL_UNSIGNED_BYTE,                 0,
1107             WINED3DFMT_FLAG_FILTERING,
1108             WINED3D_GL_LEGACY_CONTEXT,  NULL},
1109     {WINED3DFMT_NV12,                   GL_R8,                            GL_R8,                                  0,
1110             GL_RED,                     GL_UNSIGNED_BYTE,                 0,
1111             WINED3DFMT_FLAG_FILTERING,
1112             ARB_TEXTURE_RG,             NULL},
1113     {WINED3DFMT_NV12,                   GL_ALPHA8,                        GL_ALPHA8,                              0,
1114             GL_ALPHA,                   GL_UNSIGNED_BYTE,                 0,
1115             WINED3DFMT_FLAG_FILTERING,
1116             WINED3D_GL_LEGACY_CONTEXT,  NULL},
1117     {WINED3DFMT_DXT1,                   GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0,
1118             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
1119             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1120             | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
1121             EXT_TEXTURE_COMPRESSION_S3TC, NULL},
1122     {WINED3DFMT_DXT2,                   GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
1123             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
1124             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1125             | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
1126             EXT_TEXTURE_COMPRESSION_S3TC, NULL},
1127     {WINED3DFMT_DXT3,                   GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
1128             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
1129             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1130             | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
1131             EXT_TEXTURE_COMPRESSION_S3TC, NULL},
1132     {WINED3DFMT_DXT4,                   GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
1133             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
1134             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1135             | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
1136             EXT_TEXTURE_COMPRESSION_S3TC, NULL},
1137     {WINED3DFMT_DXT5,                   GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
1138             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
1139             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1140             | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_COMPRESSED,
1141             EXT_TEXTURE_COMPRESSION_S3TC, NULL},
1142     {WINED3DFMT_BC1_UNORM,              GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0,
1143             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
1144             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1145             | WINED3DFMT_FLAG_COMPRESSED,
1146             EXT_TEXTURE_COMPRESSION_S3TC, NULL},
1147     {WINED3DFMT_BC2_UNORM,              GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
1148             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
1149             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1150             | WINED3DFMT_FLAG_COMPRESSED,
1151             EXT_TEXTURE_COMPRESSION_S3TC, NULL},
1152     {WINED3DFMT_BC3_UNORM,              GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
1153             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
1154             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1155             | WINED3DFMT_FLAG_COMPRESSED,
1156             EXT_TEXTURE_COMPRESSION_S3TC, NULL},
1157     {WINED3DFMT_BC4_UNORM,              GL_COMPRESSED_RED_RGTC1,          GL_COMPRESSED_RED_RGTC1,                0,
1158             GL_RED,                     GL_UNSIGNED_BYTE,                 0,
1159             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1160             | WINED3DFMT_FLAG_COMPRESSED,
1161             ARB_TEXTURE_COMPRESSION_RGTC, NULL},
1162     {WINED3DFMT_BC4_SNORM,              GL_COMPRESSED_SIGNED_RED_RGTC1,   GL_COMPRESSED_SIGNED_RED_RGTC1,         0,
1163             GL_RED,                     GL_UNSIGNED_BYTE,                 0,
1164             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1165             | WINED3DFMT_FLAG_COMPRESSED,
1166             ARB_TEXTURE_COMPRESSION_RGTC, NULL},
1167     {WINED3DFMT_BC5_UNORM,              GL_COMPRESSED_RG_RGTC2,           GL_COMPRESSED_RG_RGTC2,                 0,
1168             GL_RG,                      GL_UNSIGNED_BYTE,                 0,
1169             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1170             | WINED3DFMT_FLAG_COMPRESSED,
1171             ARB_TEXTURE_COMPRESSION_RGTC, NULL},
1172     {WINED3DFMT_BC5_SNORM,              GL_COMPRESSED_SIGNED_RG_RGTC2,    GL_COMPRESSED_SIGNED_RG_RGTC2,          0,
1173             GL_RG,                      GL_UNSIGNED_BYTE,                 0,
1174             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1175             | WINED3DFMT_FLAG_COMPRESSED,
1176             ARB_TEXTURE_COMPRESSION_RGTC, NULL},
1177     {WINED3DFMT_BC6H_UF16,              GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB, GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB, 0,
1178             GL_RGB,                     GL_UNSIGNED_BYTE,                 0,
1179             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1180             | WINED3DFMT_FLAG_COMPRESSED,
1181             ARB_TEXTURE_COMPRESSION_BPTC, NULL},
1182     {WINED3DFMT_BC6H_SF16,              GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB, 0,
1183             GL_RGB,                     GL_UNSIGNED_BYTE,                 0,
1184             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1185             | WINED3DFMT_FLAG_COMPRESSED,
1186             ARB_TEXTURE_COMPRESSION_BPTC, NULL},
1187     {WINED3DFMT_BC7_UNORM,              GL_COMPRESSED_RGBA_BPTC_UNORM_ARB, GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB, 0,
1188             GL_RGBA,                    GL_UNSIGNED_BYTE,                 0,
1189             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1190             | WINED3DFMT_FLAG_COMPRESSED,
1191             ARB_TEXTURE_COMPRESSION_BPTC, NULL},
1192     /* IEEE formats */
1193     {WINED3DFMT_R32_FLOAT,              GL_RGB32F_ARB,                    GL_RGB32F_ARB,                          0,
1194             GL_RED,                     GL_FLOAT,                         0,
1195             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
1196             ARB_TEXTURE_FLOAT,          NULL},
1197     {WINED3DFMT_R32_FLOAT,              GL_R32F,                          GL_R32F,                                0,
1198             GL_RED,                     GL_FLOAT,                         0,
1199             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
1200             ARB_TEXTURE_RG,             NULL},
1201     {WINED3DFMT_R32G32_FLOAT,           GL_RGB32F_ARB,                    GL_RGB32F_ARB,                          0,
1202             GL_RGB,                     GL_FLOAT,                         12,
1203             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
1204             ARB_TEXTURE_FLOAT,          convert_r32g32_float},
1205     {WINED3DFMT_R32G32_FLOAT,           GL_RG32F,                         GL_RG32F,                               0,
1206             GL_RG,                      GL_FLOAT,                         0,
1207             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
1208             ARB_TEXTURE_RG,             NULL},
1209     {WINED3DFMT_R32G32B32_FLOAT,        GL_RGB32F,                        GL_RGB32F,                              0,
1210             GL_RGB,                     GL_FLOAT,                         0,
1211             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1212             ARB_TEXTURE_FLOAT,          NULL},
1213     {WINED3DFMT_R32G32B32A32_FLOAT,     GL_RGBA32F_ARB,                   GL_RGBA32F_ARB,                         0,
1214             GL_RGBA,                    GL_FLOAT,                         0,
1215             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
1216             ARB_TEXTURE_FLOAT,          NULL},
1217     /* Float */
1218     {WINED3DFMT_R16_FLOAT,              GL_RGB16F_ARB,                    GL_RGB16F_ARB,                          0,
1219             GL_RED,                     GL_HALF_FLOAT_ARB,                0,
1220             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
1221             ARB_TEXTURE_FLOAT,          NULL},
1222     {WINED3DFMT_R16_FLOAT,              GL_R16F,                          GL_R16F,                                0,
1223             GL_RED,                     GL_HALF_FLOAT_ARB,                0,
1224             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
1225             ARB_TEXTURE_RG,             NULL},
1226     {WINED3DFMT_R16G16_FLOAT,           GL_RGB16F_ARB,                    GL_RGB16F_ARB,                          0,
1227             GL_RGB,                     GL_HALF_FLOAT_ARB,                6,
1228             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
1229             ARB_TEXTURE_FLOAT,          convert_r16g16},
1230     {WINED3DFMT_R16G16_FLOAT,           GL_RG16F,                         GL_RG16F,                               0,
1231             GL_RG,                      GL_HALF_FLOAT_ARB,                0,
1232             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
1233             ARB_TEXTURE_RG,             NULL},
1234     {WINED3DFMT_R16G16B16A16_FLOAT,     GL_RGBA16F_ARB,                   GL_RGBA16F_ARB,                         0,
1235             GL_RGBA,                    GL_HALF_FLOAT_ARB,                0,
1236             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_RENDERTARGET
1237             | WINED3DFMT_FLAG_VTF,
1238             ARB_TEXTURE_FLOAT,          NULL},
1239     {WINED3DFMT_R11G11B10_FLOAT,        GL_R11F_G11F_B10F,                GL_R11F_G11F_B10F,                      0,
1240             GL_RGB,                     GL_UNSIGNED_INT_10F_11F_11F_REV,  0,
1241             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_RENDERTARGET,
1242             EXT_PACKED_FLOAT},
1243     /* Palettized formats */
1244     {WINED3DFMT_P8_UINT,                GL_R8,                            GL_R8,                                  0,
1245             GL_RED,                     GL_UNSIGNED_BYTE,                 0,
1246             0,
1247             ARB_TEXTURE_RG,             NULL},
1248     {WINED3DFMT_P8_UINT,                GL_ALPHA8,                        GL_ALPHA8,                              0,
1249             GL_ALPHA,                   GL_UNSIGNED_BYTE,                 0,
1250             0,
1251             WINED3D_GL_LEGACY_CONTEXT,  NULL},
1252     /* Standard ARGB formats */
1253     {WINED3DFMT_B8G8R8_UNORM,           GL_RGB8,                          GL_RGB8,                                0,
1254             GL_BGR,                     GL_UNSIGNED_BYTE,                 0,
1255             WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
1256             WINED3D_GL_EXT_NONE,        NULL},
1257     {WINED3DFMT_B8G8R8A8_UNORM,         GL_RGBA8,                         GL_SRGB8_ALPHA8_EXT,                    0,
1258             GL_BGRA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
1259             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1260             | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE
1261             | WINED3DFMT_FLAG_VTF,
1262             WINED3D_GL_EXT_NONE,        NULL},
1263     {WINED3DFMT_B8G8R8X8_UNORM,         GL_RGB8,                          GL_SRGB8_EXT,                           0,
1264             GL_BGRA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
1265             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1266             | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE,
1267             WINED3D_GL_EXT_NONE,        NULL},
1268     {WINED3DFMT_B5G6R5_UNORM,           GL_RGB5,                          GL_RGB5,                          GL_RGB8,
1269             GL_RGB,                     GL_UNSIGNED_SHORT_5_6_5,          0,
1270             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1271             | WINED3DFMT_FLAG_RENDERTARGET,
1272             WINED3D_GL_EXT_NONE,        NULL},
1273     {WINED3DFMT_B5G6R5_UNORM,           GL_RGB565,                        GL_RGB565,                        GL_RGB8,
1274             GL_RGB,                     GL_UNSIGNED_SHORT_5_6_5,          0,
1275             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1276             | WINED3DFMT_FLAG_RENDERTARGET,
1277             ARB_ES2_COMPATIBILITY,      NULL},
1278     {WINED3DFMT_B5G5R5X1_UNORM,         GL_RGB5,                          GL_RGB5,                                0,
1279             GL_BGRA,                    GL_UNSIGNED_SHORT_1_5_5_5_REV,    0,
1280             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1281             | WINED3DFMT_FLAG_RENDERTARGET,
1282             WINED3D_GL_EXT_NONE,        NULL},
1283     {WINED3DFMT_B5G5R5A1_UNORM,         GL_RGB5_A1,                       GL_RGB5_A1,                             0,
1284             GL_BGRA,                    GL_UNSIGNED_SHORT_1_5_5_5_REV,    0,
1285             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
1286             WINED3D_GL_EXT_NONE,        NULL},
1287     {WINED3DFMT_B4G4R4A4_UNORM,         GL_RGBA4,                         GL_SRGB8_ALPHA8_EXT,                    0,
1288             GL_BGRA,                    GL_UNSIGNED_SHORT_4_4_4_4_REV,    0,
1289             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1290             | WINED3DFMT_FLAG_SRGB_READ,
1291             WINED3D_GL_EXT_NONE,        NULL},
1292     {WINED3DFMT_B2G3R3_UNORM,           GL_R3_G3_B2,                      GL_R3_G3_B2,                            0,
1293             GL_RGB,                     GL_UNSIGNED_BYTE_3_3_2,           0,
1294             WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
1295             WINED3D_GL_EXT_NONE,        NULL},
1296     {WINED3DFMT_R8_UNORM,               GL_R8,                            GL_R8,                                  0,
1297             GL_RED,                     GL_UNSIGNED_BYTE,                 0,
1298             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1299             | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
1300             ARB_TEXTURE_RG,             NULL},
1301     {WINED3DFMT_A8_UNORM,               GL_R8,                            GL_R8,                                  0,
1302             GL_RED,                     GL_UNSIGNED_BYTE,                 0,
1303             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
1304             ARB_TEXTURE_RG,             NULL},
1305     {WINED3DFMT_A8_UNORM,               GL_ALPHA8,                        GL_ALPHA8,                              0,
1306             GL_ALPHA,                   GL_UNSIGNED_BYTE,                 0,
1307             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
1308             WINED3D_GL_LEGACY_CONTEXT,  NULL},
1309     {WINED3DFMT_B4G4R4X4_UNORM,         GL_RGB4,                          GL_RGB4,                                0,
1310             GL_BGRA,                    GL_UNSIGNED_SHORT_4_4_4_4_REV,    0,
1311             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
1312             WINED3D_GL_EXT_NONE,        NULL},
1313     {WINED3DFMT_R10G10B10A2_UNORM,      GL_RGB10_A2,                      GL_RGB10_A2,                            0,
1314             GL_RGBA,                    GL_UNSIGNED_INT_2_10_10_10_REV,   0,
1315             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1316             | WINED3DFMT_FLAG_RENDERTARGET,
1317             WINED3D_GL_EXT_NONE,        NULL},
1318     {WINED3DFMT_R8G8B8A8_UNORM,         GL_RGBA8,                         GL_SRGB8_ALPHA8_EXT,                    0,
1319             GL_RGBA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
1320             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1321             | WINED3DFMT_FLAG_RENDERTARGET |  WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE
1322             | WINED3DFMT_FLAG_VTF,
1323             WINED3D_GL_EXT_NONE,        NULL},
1324     {WINED3DFMT_R8G8B8A8_UINT,          GL_RGBA8UI,                       GL_RGBA8UI,                             0,
1325             GL_RGBA_INTEGER,            GL_UNSIGNED_INT_8_8_8_8_REV,      0,
1326             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1327             ARB_TEXTURE_RGB10_A2UI,     NULL},
1328     {WINED3DFMT_R8G8B8A8_SINT,          GL_RGBA8I,                        GL_RGBA8I,                              0,
1329             GL_RGBA_INTEGER,            GL_BYTE,                          0,
1330             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1331             EXT_TEXTURE_INTEGER,        NULL},
1332     {WINED3DFMT_R8G8B8X8_UNORM,         GL_RGB8,                          GL_RGB8,                                0,
1333             GL_RGBA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
1334             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
1335             WINED3D_GL_EXT_NONE,        NULL},
1336     {WINED3DFMT_R16G16_UNORM,           GL_RGB16,                         GL_RGB16,                       GL_RGBA16,
1337             GL_RGB,                     GL_UNSIGNED_SHORT,                6,
1338             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
1339             WINED3D_GL_EXT_NONE,        convert_r16g16},
1340     {WINED3DFMT_R16G16_UNORM,           GL_RG16,                          GL_RG16,                                0,
1341             GL_RG,                      GL_UNSIGNED_SHORT,                0,
1342             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1343             | WINED3DFMT_FLAG_RENDERTARGET,
1344             ARB_TEXTURE_RG,             NULL},
1345     {WINED3DFMT_B10G10R10A2_UNORM,      GL_RGB10_A2,                      GL_RGB10_A2,                            0,
1346             GL_BGRA,                    GL_UNSIGNED_INT_2_10_10_10_REV,   0,
1347             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1348             | WINED3DFMT_FLAG_RENDERTARGET,
1349             WINED3D_GL_EXT_NONE,        NULL},
1350     {WINED3DFMT_R16G16B16A16_UNORM,     GL_RGBA16,                        GL_RGBA16,                              0,
1351             GL_RGBA,                    GL_UNSIGNED_SHORT,                0,
1352             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1353             | WINED3DFMT_FLAG_RENDERTARGET,
1354             WINED3D_GL_EXT_NONE,        NULL},
1355     {WINED3DFMT_R8G8_UNORM,             GL_RG8,                           GL_RG8,                                 0,
1356             GL_RG,                      GL_UNSIGNED_BYTE,                 0,
1357             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1358             | WINED3DFMT_FLAG_RENDERTARGET,
1359             ARB_TEXTURE_RG,             NULL},
1360     {WINED3DFMT_R8G8_UINT,              GL_RG8UI,                         GL_RG8UI,                               0,
1361             GL_RG_INTEGER,              GL_UNSIGNED_BYTE,                 0,
1362             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1363             ARB_TEXTURE_RG,             NULL},
1364     {WINED3DFMT_R8G8_SINT,              GL_RG8I,                          GL_RG8I,                                0,
1365             GL_RG_INTEGER,              GL_BYTE,                          0,
1366             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1367             ARB_TEXTURE_RG,             NULL},
1368     {WINED3DFMT_R16G16B16A16_UINT,      GL_RGBA16UI,                      GL_RGBA16UI,                            0,
1369             GL_RGBA_INTEGER,            GL_UNSIGNED_SHORT,                0,
1370             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1371             EXT_TEXTURE_INTEGER,        NULL},
1372     {WINED3DFMT_R16G16B16A16_SINT,      GL_RGBA16I,                       GL_RGBA16I,                             0,
1373             GL_RGBA_INTEGER,            GL_SHORT,                         0,
1374             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1375             EXT_TEXTURE_INTEGER,        NULL},
1376     {WINED3DFMT_R32G32_UINT,            GL_RG32UI,                        GL_RG32UI,                              0,
1377             GL_RG_INTEGER,              GL_UNSIGNED_INT,                  0,
1378             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1379             ARB_TEXTURE_RG,             NULL},
1380     {WINED3DFMT_R32G32_SINT,            GL_RG32I,                         GL_RG32I,                               0,
1381             GL_RG_INTEGER,              GL_INT,                           0,
1382             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1383             ARB_TEXTURE_RG,             NULL},
1384     {WINED3DFMT_R16G16_UINT,            GL_RG16UI,                        GL_RG16UI,                              0,
1385             GL_RG_INTEGER,              GL_UNSIGNED_SHORT,                0,
1386             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1387             ARB_TEXTURE_RG,             NULL},
1388     {WINED3DFMT_R16G16_SINT,            GL_RG16I,                         GL_RG16I,                               0,
1389             GL_RG_INTEGER,              GL_SHORT,                         0,
1390             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1391             ARB_TEXTURE_RG,             NULL},
1392     {WINED3DFMT_R32_UINT,               GL_R32UI,                         GL_R32UI,                               0,
1393             GL_RED_INTEGER,             GL_UNSIGNED_INT,                  0,
1394             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1395             ARB_TEXTURE_RG,             NULL},
1396     {WINED3DFMT_R32_SINT,               GL_R32I,                          GL_R32I,                                0,
1397             GL_RED_INTEGER,             GL_INT,                           0,
1398             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1399             ARB_TEXTURE_RG,             NULL},
1400     {WINED3DFMT_R16_UNORM,              GL_R16,                           GL_R16,                                 0,
1401             GL_RED,                     GL_UNSIGNED_SHORT,                0,
1402             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1403             | WINED3DFMT_FLAG_RENDERTARGET,
1404             ARB_TEXTURE_RG,             NULL},
1405     {WINED3DFMT_R16_UINT,               GL_R16UI,                         GL_R16UI,                               0,
1406             GL_RED_INTEGER,             GL_UNSIGNED_SHORT,                0,
1407             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1408             ARB_TEXTURE_RG,             NULL},
1409     {WINED3DFMT_R16_SINT,               GL_R16I,                          GL_R16I,                                0,
1410             GL_RED_INTEGER,             GL_SHORT,                         0,
1411             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1412             ARB_TEXTURE_RG,             NULL},
1413     {WINED3DFMT_R8_UINT,                GL_R8UI,                          GL_R8UI,                                0,
1414             GL_RED_INTEGER,             GL_UNSIGNED_BYTE,                 0,
1415             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1416             ARB_TEXTURE_RG,             NULL},
1417     {WINED3DFMT_R8_SINT,                GL_R8I,                           GL_R8I,                                 0,
1418             GL_RED_INTEGER,             GL_BYTE,                          0,
1419             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1420             ARB_TEXTURE_RG,             NULL},
1421     /* Luminance */
1422     {WINED3DFMT_L8_UNORM,               GL_LUMINANCE8,                    GL_SLUMINANCE8_EXT,                     0,
1423             GL_LUMINANCE,               GL_UNSIGNED_BYTE,                 0,
1424             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1425             | WINED3DFMT_FLAG_SRGB_READ,
1426             WINED3D_GL_LEGACY_CONTEXT,  NULL},
1427     {WINED3DFMT_L8_UNORM,               GL_R8,                            GL_R8,                                  0,
1428             GL_RED,                     GL_UNSIGNED_BYTE,                 0,
1429             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1430             | WINED3DFMT_FLAG_RENDERTARGET,
1431             ARB_TEXTURE_RG,             NULL},
1432     {WINED3DFMT_L8A8_UNORM,             GL_RG8,                           GL_RG8,                                 0,
1433             GL_RG,                      GL_UNSIGNED_BYTE,                 0,
1434             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
1435             ARB_TEXTURE_RG,             NULL},
1436     {WINED3DFMT_L8A8_UNORM,             GL_LUMINANCE8_ALPHA8,             GL_SLUMINANCE8_ALPHA8_EXT,              0,
1437             GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
1438             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1439             | WINED3DFMT_FLAG_SRGB_READ,
1440             WINED3D_GL_LEGACY_CONTEXT,  NULL},
1441     {WINED3DFMT_L4A4_UNORM,             GL_RG8,                           GL_RG8,                                 0,
1442             GL_RG,                      GL_UNSIGNED_BYTE,                 2,
1443             WINED3DFMT_FLAG_FILTERING,
1444             ARB_TEXTURE_RG,             convert_l4a4_unorm},
1445     {WINED3DFMT_L4A4_UNORM,             GL_LUMINANCE4_ALPHA4,             GL_LUMINANCE4_ALPHA4,                   0,
1446             GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 2,
1447             WINED3DFMT_FLAG_FILTERING,
1448             WINED3D_GL_LEGACY_CONTEXT,  convert_l4a4_unorm},
1449     {WINED3DFMT_L16_UNORM,              GL_R16,                           GL_R16,                                 0,
1450             GL_RED,                     GL_UNSIGNED_SHORT,                0,
1451             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
1452             ARB_TEXTURE_RG,  NULL},
1453     {WINED3DFMT_L16_UNORM,              GL_LUMINANCE16,                   GL_LUMINANCE16,                         0,
1454             GL_LUMINANCE,               GL_UNSIGNED_SHORT,                0,
1455             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
1456             WINED3D_GL_LEGACY_CONTEXT,  NULL},
1457     /* Bump mapping stuff */
1458     {WINED3DFMT_R8G8_SNORM,             GL_RGB8,                          GL_RGB8,                                0,
1459             GL_BGR,                     GL_UNSIGNED_BYTE,                 3,
1460             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1461             | WINED3DFMT_FLAG_BUMPMAP,
1462             WINED3D_GL_EXT_NONE,        convert_r8g8_snorm},
1463     {WINED3DFMT_R8G8_SNORM,             GL_DSDT8_NV,                      GL_DSDT8_NV,                            0,
1464             GL_DSDT_NV,                 GL_BYTE,                          0,
1465             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1466             | WINED3DFMT_FLAG_BUMPMAP,
1467             NV_TEXTURE_SHADER,          NULL},
1468     {WINED3DFMT_R8G8_SNORM,             GL_RG8_SNORM,                     GL_RG8_SNORM,                           0,
1469             GL_RG,                      GL_BYTE,                          0,
1470             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1471             | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_BUMPMAP,
1472             EXT_TEXTURE_SNORM,          NULL},
1473     {WINED3DFMT_R5G5_SNORM_L6_UNORM,    GL_RGB5,                          GL_RGB5,                                0,
1474             GL_RGB,                     GL_UNSIGNED_SHORT_5_6_5,          2,
1475             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1476             | WINED3DFMT_FLAG_BUMPMAP,
1477             WINED3D_GL_EXT_NONE,        convert_r5g5_snorm_l6_unorm},
1478     {WINED3DFMT_R5G5_SNORM_L6_UNORM,    GL_DSDT8_MAG8_NV,                 GL_DSDT8_MAG8_NV,                       0,
1479             GL_DSDT_MAG_NV,             GL_BYTE,                          3,
1480             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1481             | WINED3DFMT_FLAG_BUMPMAP,
1482             NV_TEXTURE_SHADER,          convert_r5g5_snorm_l6_unorm_nv},
1483     {WINED3DFMT_R5G5_SNORM_L6_UNORM,    GL_RGB8_SNORM,                    GL_RGB8_SNORM,                          0,
1484             GL_RGBA,                    GL_BYTE,                          4,
1485             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1486             | WINED3DFMT_FLAG_BUMPMAP,
1487             EXT_TEXTURE_SNORM,          convert_r5g5_snorm_l6_unorm_ext},
1488     {WINED3DFMT_R8G8_SNORM_L8X8_UNORM,  GL_RGB8,                          GL_RGB8,                                0,
1489             GL_BGRA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      4,
1490             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1491             | WINED3DFMT_FLAG_BUMPMAP,
1492             WINED3D_GL_EXT_NONE,        convert_r8g8_snorm_l8x8_unorm},
1493     {WINED3DFMT_R8G8_SNORM_L8X8_UNORM,  GL_DSDT8_MAG8_INTENSITY8_NV,      GL_DSDT8_MAG8_INTENSITY8_NV,            0,
1494             GL_DSDT_MAG_VIB_NV,         GL_UNSIGNED_INT_8_8_S8_S8_REV_NV, 4,
1495             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1496             | WINED3DFMT_FLAG_BUMPMAP,
1497             NV_TEXTURE_SHADER,          convert_r8g8_snorm_l8x8_unorm_nv},
1498     {WINED3DFMT_R8G8B8A8_SNORM,         GL_RGBA8,                         GL_RGBA8,                               0,
1499             GL_BGRA,                    GL_UNSIGNED_BYTE,                 4,
1500             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1501             | WINED3DFMT_FLAG_BUMPMAP,
1502             WINED3D_GL_EXT_NONE,        convert_r8g8b8a8_snorm},
1503     {WINED3DFMT_R8G8B8A8_SNORM,         GL_SIGNED_RGBA8_NV,               GL_SIGNED_RGBA8_NV,                     0,
1504             GL_RGBA,                    GL_BYTE,                          0,
1505             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1506             | WINED3DFMT_FLAG_BUMPMAP,
1507             NV_TEXTURE_SHADER,          NULL},
1508     {WINED3DFMT_R8G8B8A8_SNORM,         GL_RGBA8_SNORM,                   GL_RGBA8_SNORM,                         0,
1509             GL_RGBA,                    GL_BYTE,                          0,
1510             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1511             | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_BUMPMAP,
1512             EXT_TEXTURE_SNORM,          NULL},
1513     {WINED3DFMT_R16G16_SNORM,           GL_RGB16,                         GL_RGB16,                               0,
1514             GL_BGR,                     GL_UNSIGNED_SHORT,                6,
1515             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1516             | WINED3DFMT_FLAG_BUMPMAP,
1517             WINED3D_GL_EXT_NONE,        convert_r16g16_snorm},
1518     {WINED3DFMT_R16G16_SNORM,           GL_SIGNED_HILO16_NV,              GL_SIGNED_HILO16_NV,                    0,
1519             GL_HILO_NV,                 GL_SHORT,                         0,
1520             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1521             | WINED3DFMT_FLAG_BUMPMAP,
1522             NV_TEXTURE_SHADER,          NULL},
1523     {WINED3DFMT_R16G16_SNORM,           GL_RG16_SNORM,                    GL_RG16_SNORM,                          0,
1524             GL_RG,                      GL_SHORT,                         0,
1525             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1526             | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_BUMPMAP,
1527             EXT_TEXTURE_SNORM,          NULL},
1528     {WINED3DFMT_R16G16B16A16_SNORM,     GL_RGBA16_SNORM,                  GL_RGBA16_SNORM,                        0,
1529             GL_RGBA,                    GL_SHORT,                         0,
1530             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1531             | WINED3DFMT_FLAG_RENDERTARGET,
1532             EXT_TEXTURE_SNORM,          NULL},
1533     {WINED3DFMT_R16_SNORM,              GL_R16_SNORM,                     GL_R16_SNORM,                           0,
1534             GL_RED,                     GL_SHORT,                         0,
1535             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1536             | WINED3DFMT_FLAG_RENDERTARGET,
1537             EXT_TEXTURE_SNORM,          NULL},
1538     {WINED3DFMT_R8_SNORM,               GL_R8_SNORM,                      GL_R8_SNORM,                           0,
1539             GL_RED,                     GL_BYTE,                          0,
1540             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1541             | WINED3DFMT_FLAG_RENDERTARGET,
1542             EXT_TEXTURE_SNORM,          NULL},
1543     /* Depth stencil formats */
1544     {WINED3DFMT_D16_LOCKABLE,           GL_DEPTH_COMPONENT,               GL_DEPTH_COMPONENT,                     0,
1545             GL_DEPTH_COMPONENT,         GL_UNSIGNED_SHORT,                0,
1546             WINED3DFMT_FLAG_DEPTH,
1547             WINED3D_GL_EXT_NONE,        NULL},
1548     {WINED3DFMT_D16_LOCKABLE,           GL_DEPTH_COMPONENT16,             GL_DEPTH_COMPONENT16,                   0,
1549             GL_DEPTH_COMPONENT,         GL_UNSIGNED_SHORT,                0,
1550             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
1551             ARB_DEPTH_TEXTURE,          NULL},
1552     {WINED3DFMT_D32_UNORM,              GL_DEPTH_COMPONENT,               GL_DEPTH_COMPONENT,                     0,
1553             GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
1554             WINED3DFMT_FLAG_DEPTH,
1555             WINED3D_GL_EXT_NONE,        NULL},
1556     {WINED3DFMT_D32_UNORM,              GL_DEPTH_COMPONENT32_ARB,         GL_DEPTH_COMPONENT32_ARB,               0,
1557             GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
1558             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
1559             ARB_DEPTH_TEXTURE,          NULL},
1560     {WINED3DFMT_S1_UINT_D15_UNORM,      GL_DEPTH_COMPONENT16,             GL_DEPTH_COMPONENT16,                   0,
1561             GL_DEPTH_COMPONENT,         GL_UNSIGNED_SHORT,                0,
1562             WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
1563             ARB_DEPTH_TEXTURE,          NULL},
1564     {WINED3DFMT_S1_UINT_D15_UNORM,      GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
1565             GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         4,
1566             WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
1567             EXT_PACKED_DEPTH_STENCIL,   convert_s1_uint_d15_unorm},
1568     {WINED3DFMT_S1_UINT_D15_UNORM,      GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
1569             GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             4,
1570             WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
1571             ARB_FRAMEBUFFER_OBJECT,     convert_s1_uint_d15_unorm},
1572     {WINED3DFMT_D24_UNORM_S8_UINT,      GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
1573             GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
1574             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1575             | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
1576             ARB_DEPTH_TEXTURE,          NULL},
1577     {WINED3DFMT_D24_UNORM_S8_UINT,      GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
1578             GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         0,
1579             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1580             | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
1581             EXT_PACKED_DEPTH_STENCIL,   NULL},
1582     {WINED3DFMT_D24_UNORM_S8_UINT,      GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
1583             GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             0,
1584             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1585             | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
1586             ARB_FRAMEBUFFER_OBJECT,     NULL},
1587     {WINED3DFMT_X8D24_UNORM,            GL_DEPTH_COMPONENT,               GL_DEPTH_COMPONENT,                     0,
1588             GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  4,
1589             WINED3DFMT_FLAG_DEPTH,
1590             WINED3D_GL_EXT_NONE,        x8_d24_unorm_upload,              x8_d24_unorm_download},
1591     {WINED3DFMT_X8D24_UNORM,            GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
1592             GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  4,
1593             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1594             | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
1595             ARB_DEPTH_TEXTURE,          x8_d24_unorm_upload,              x8_d24_unorm_download},
1596     {WINED3DFMT_S4X4_UINT_D24_UNORM,    GL_DEPTH_COMPONENT24_ARB,         GL_DEPTH_COMPONENT24_ARB,               0,
1597             GL_DEPTH_COMPONENT,         GL_UNSIGNED_INT,                  0,
1598             WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
1599             ARB_DEPTH_TEXTURE,          NULL},
1600     {WINED3DFMT_S4X4_UINT_D24_UNORM,    GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
1601             GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         4,
1602             WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
1603             EXT_PACKED_DEPTH_STENCIL,   convert_s4x4_uint_d24_unorm},
1604     {WINED3DFMT_S4X4_UINT_D24_UNORM,    GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
1605             GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             4,
1606             WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
1607             ARB_FRAMEBUFFER_OBJECT,     convert_s4x4_uint_d24_unorm},
1608     {WINED3DFMT_D16_UNORM,              GL_DEPTH_COMPONENT,               GL_DEPTH_COMPONENT,                     0,
1609             GL_DEPTH_COMPONENT,         GL_UNSIGNED_SHORT,                0,
1610             WINED3DFMT_FLAG_DEPTH,
1611             WINED3D_GL_EXT_NONE,        NULL},
1612     {WINED3DFMT_D16_UNORM,              GL_DEPTH_COMPONENT16,             GL_DEPTH_COMPONENT16,                   0,
1613             GL_DEPTH_COMPONENT,         GL_UNSIGNED_SHORT,                0,
1614             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1615             | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
1616             ARB_DEPTH_TEXTURE,          NULL},
1617     {WINED3DFMT_D32_FLOAT,              GL_DEPTH_COMPONENT32F,            GL_DEPTH_COMPONENT32F,                  0,
1618             GL_DEPTH_COMPONENT,         GL_FLOAT,                         0,
1619             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
1620             ARB_DEPTH_BUFFER_FLOAT,     NULL},
1621     {WINED3DFMT_D32_FLOAT_S8X24_UINT,   GL_DEPTH32F_STENCIL8,             GL_DEPTH32F_STENCIL8,                   0,
1622             GL_DEPTH_STENCIL,           GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 0,
1623             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
1624             ARB_DEPTH_BUFFER_FLOAT,     NULL},
1625     {WINED3DFMT_S8_UINT_D24_FLOAT,      GL_DEPTH32F_STENCIL8,             GL_DEPTH32F_STENCIL8,                   0,
1626             GL_DEPTH_STENCIL,           GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8,
1627             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
1628             ARB_DEPTH_BUFFER_FLOAT,     convert_s8_uint_d24_float},
1629     {WINED3DFMT_R32G32B32A32_UINT,      GL_RGBA32UI,                      GL_RGBA32UI,                            0,
1630             GL_RGBA_INTEGER,            GL_UNSIGNED_INT,                  0,
1631             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1632             EXT_TEXTURE_INTEGER,        NULL},
1633     {WINED3DFMT_R32G32B32A32_SINT,      GL_RGBA32I,                       GL_RGBA32I,                             0,
1634             GL_RGBA_INTEGER,            GL_INT,                           0,
1635             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET,
1636             EXT_TEXTURE_INTEGER,        NULL},
1637     /* Vendor-specific formats */
1638     {WINED3DFMT_ATI1N,                  GL_COMPRESSED_RED_RGTC1,          GL_COMPRESSED_RED_RGTC1,                0,
1639             GL_RED,                     GL_UNSIGNED_BYTE,                 0,
1640             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1641             | WINED3DFMT_FLAG_COMPRESSED,
1642             ARB_TEXTURE_COMPRESSION_RGTC, NULL},
1643     {WINED3DFMT_ATI2N,                  GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, 0,
1644             GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
1645             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1646             | WINED3DFMT_FLAG_COMPRESSED,
1647             ATI_TEXTURE_COMPRESSION_3DC, NULL},
1648     {WINED3DFMT_ATI2N,                  GL_COMPRESSED_RG_RGTC2,           GL_COMPRESSED_RG_RGTC2,                 0,
1649             GL_LUMINANCE_ALPHA,         GL_UNSIGNED_BYTE,                 0,
1650             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1651             | WINED3DFMT_FLAG_COMPRESSED,
1652             EXT_TEXTURE_COMPRESSION_RGTC, NULL},
1653     {WINED3DFMT_ATI2N,                  GL_COMPRESSED_RG_RGTC2,           GL_COMPRESSED_RG_RGTC2,                 0,
1654             GL_RG,                      GL_UNSIGNED_BYTE,                 0,
1655             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1656             | WINED3DFMT_FLAG_COMPRESSED,
1657             ARB_TEXTURE_COMPRESSION_RGTC, NULL},
1658     {WINED3DFMT_INTZ,                   GL_DEPTH24_STENCIL8_EXT,          GL_DEPTH24_STENCIL8_EXT,                0,
1659             GL_DEPTH_STENCIL_EXT,       GL_UNSIGNED_INT_24_8_EXT,         0,
1660             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1661             | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL,
1662             EXT_PACKED_DEPTH_STENCIL,   NULL},
1663     {WINED3DFMT_INTZ,                   GL_DEPTH24_STENCIL8,              GL_DEPTH24_STENCIL8,                    0,
1664             GL_DEPTH_STENCIL,           GL_UNSIGNED_INT_24_8,             0,
1665             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING
1666             | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL,
1667             ARB_FRAMEBUFFER_OBJECT,     NULL},
1668     {WINED3DFMT_NULL,                   0,                                0,                                      0,
1669             GL_RGBA,                    GL_UNSIGNED_INT_8_8_8_8_REV,      0,
1670             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_FBO_ATTACHABLE,
1671             ARB_FRAMEBUFFER_OBJECT,     NULL},
1672     /* DirectX 10 HDR formats */
1673     {WINED3DFMT_R9G9B9E5_SHAREDEXP,     GL_RGB9_E5_EXT,                   GL_RGB9_E5_EXT,                            0,
1674             GL_RGB,                     GL_UNSIGNED_INT_5_9_9_9_REV_EXT,  0,
1675             WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
1676             EXT_TEXTURE_SHARED_EXPONENT, NULL},
1677 };
1678 
1679 struct wined3d_format_srgb_info
1680 {
1681     enum wined3d_format_id srgb_format_id;
1682     enum wined3d_format_id base_format_id;
1683 };
1684 
1685 static const struct wined3d_format_srgb_info format_srgb_info[] =
1686 {
1687     {WINED3DFMT_R8G8B8A8_UNORM_SRGB, WINED3DFMT_R8G8B8A8_UNORM},
1688     {WINED3DFMT_BC1_UNORM_SRGB,      WINED3DFMT_BC1_UNORM},
1689     {WINED3DFMT_BC2_UNORM_SRGB,      WINED3DFMT_BC2_UNORM},
1690     {WINED3DFMT_BC3_UNORM_SRGB,      WINED3DFMT_BC3_UNORM},
1691     {WINED3DFMT_B8G8R8A8_UNORM_SRGB, WINED3DFMT_B8G8R8A8_UNORM},
1692     {WINED3DFMT_B8G8R8X8_UNORM_SRGB, WINED3DFMT_B8G8R8X8_UNORM},
1693     {WINED3DFMT_BC7_UNORM_SRGB,      WINED3DFMT_BC7_UNORM},
1694 };
1695 
1696 static inline int get_format_idx(enum wined3d_format_id format_id)
1697 {
1698     unsigned int i;
1699 
1700     if (format_id < WINED3D_FORMAT_FOURCC_BASE)
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,
1713         enum wined3d_format_id format_id)
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 
1749 static enum wined3d_channel_type map_channel_type(char t)
1750 {
1751     switch (t)
1752     {
1753         case 'u':
1754             return WINED3D_CHANNEL_TYPE_UNORM;
1755         case 'i':
1756             return WINED3D_CHANNEL_TYPE_SNORM;
1757         case 'U':
1758             return WINED3D_CHANNEL_TYPE_UINT;
1759         case 'I':
1760             return WINED3D_CHANNEL_TYPE_SINT;
1761         case 'F':
1762             return WINED3D_CHANNEL_TYPE_FLOAT;
1763         case 'D':
1764             return WINED3D_CHANNEL_TYPE_DEPTH;
1765         case 'S':
1766             return WINED3D_CHANNEL_TYPE_STENCIL;
1767         case 'X':
1768             return WINED3D_CHANNEL_TYPE_UNUSED;
1769         default:
1770             ERR("Invalid channel type '%c'.\n", t);
1771             return WINED3D_CHANNEL_TYPE_NONE;
1772     }
1773 }
1774 
1775 static BOOL init_format_base_info(struct wined3d_gl_info *gl_info)
1776 {
1777     struct wined3d_format *format;
1778     unsigned int i, j;
1779 
1780     gl_info->format_count = WINED3D_FORMAT_COUNT;
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         {
1840             enum wined3d_channel_type channel_type = map_channel_type(typed_formats[i].channels[j]);
1841             if (channel_type == WINED3D_CHANNEL_TYPE_UINT || channel_type == WINED3D_CHANNEL_TYPE_SINT)
1842                 flags |= WINED3DFMT_FLAG_INTEGER;
1843             if (channel_type == WINED3D_CHANNEL_TYPE_FLOAT)
1844                 flags |= WINED3DFMT_FLAG_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 
1853         format_set_flag(format, flags);
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 
1869         format_set_flag(format, format_base_flags[i].flags);
1870     }
1871 
1872     return TRUE;
1873 
1874 fail:
1875     heap_free(gl_info->formats);
1876     return FALSE;
1877 }
1878 
1879 static BOOL init_format_block_info(struct wined3d_gl_info *gl_info)
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;
1892         format_set_flag(format, WINED3DFMT_FLAG_BLOCKS);
1893         if (!format_block_info[i].verify)
1894             format_set_flag(format, WINED3DFMT_FLAG_BLOCKS_NO_VERIFY);
1895     }
1896 
1897     return TRUE;
1898 }
1899 
1900 static GLenum wined3d_gl_type_to_enum(enum wined3d_gl_resource_type type)
1901 {
1902     switch (type)
1903     {
1904         case WINED3D_GL_RES_TYPE_TEX_1D:
1905             return GL_TEXTURE_1D;
1906         case WINED3D_GL_RES_TYPE_TEX_2D:
1907             return GL_TEXTURE_2D;
1908         case WINED3D_GL_RES_TYPE_TEX_3D:
1909             return GL_TEXTURE_3D;
1910         case WINED3D_GL_RES_TYPE_TEX_CUBE:
1911             return GL_TEXTURE_CUBE_MAP_ARB;
1912         case WINED3D_GL_RES_TYPE_TEX_RECT:
1913             return GL_TEXTURE_RECTANGLE_ARB;
1914         case WINED3D_GL_RES_TYPE_BUFFER:
1915             return GL_TEXTURE_2D; /* TODO: GL_TEXTURE_BUFFER. */
1916         case WINED3D_GL_RES_TYPE_RB:
1917             return GL_RENDERBUFFER;
1918         case WINED3D_GL_RES_TYPE_COUNT:
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     {
1930         case WINED3D_GL_RES_TYPE_TEX_1D:
1931         case WINED3D_GL_RES_TYPE_TEX_2D:
1932         case WINED3D_GL_RES_TYPE_TEX_RECT:
1933         case WINED3D_GL_RES_TYPE_TEX_3D:
1934         case WINED3D_GL_RES_TYPE_TEX_CUBE:
1935             gl_info->gl_ops.gl.p_glDeleteTextures(1, &object);
1936             break;
1937 
1938         case WINED3D_GL_RES_TYPE_RB:
1939             gl_info->fbo_ops.glDeleteRenderbuffers(1, &object);
1940             break;
1941 
1942         case WINED3D_GL_RES_TYPE_BUFFER:
1943         case WINED3D_GL_RES_TYPE_COUNT:
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 ?
1953             GL_DEPTH_ATTACHMENT : GL_COLOR_ATTACHMENT0;
1954 
1955     switch (d3d_type)
1956     {
1957         case WINED3D_GL_RES_TYPE_TEX_1D:
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);
1966             if (flags & WINED3DFMT_FLAG_STENCIL)
1967                 gl_info->fbo_ops.glFramebufferTexture1D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_1D,
1968                         *object, 0);
1969             break;
1970 
1971         case WINED3D_GL_RES_TYPE_TEX_2D:
1972         case WINED3D_GL_RES_TYPE_TEX_RECT:
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);
1982             if (flags & WINED3DFMT_FLAG_STENCIL)
1983                 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
1984                         wined3d_gl_type_to_enum(d3d_type), *object, 0);
1985             break;
1986 
1987         case WINED3D_GL_RES_TYPE_TEX_3D:
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);
1996             if (flags & WINED3DFMT_FLAG_STENCIL)
1997                 gl_info->fbo_ops.glFramebufferTexture3D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
1998                         GL_TEXTURE_3D, *object, 0, 0);
1999             break;
2000 
2001         case WINED3D_GL_RES_TYPE_TEX_CUBE:
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,
2020                     GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, *object, 0);
2021             if (flags & WINED3DFMT_FLAG_STENCIL)
2022                 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
2023                         GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, *object, 0);
2024             break;
2025 
2026         case WINED3D_GL_RES_TYPE_RB:
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);
2032             if (flags & WINED3DFMT_FLAG_STENCIL)
2033                 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER,
2034                         *object);
2035             break;
2036 
2037         case WINED3D_GL_RES_TYPE_BUFFER:
2038         case WINED3D_GL_RES_TYPE_COUNT:
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));
2160         shader_glsl_validate_link(gl_info, 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. */
2173 static void check_fbo_compat(struct wined3d_caps_gl_ctx *ctx, struct wined3d_format *format)
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;
2184     enum wined3d_gl_resource_type type;
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 
2193         if (type == WINED3D_GL_RES_TYPE_BUFFER)
2194             continue;
2195 
2196         create_and_bind_fbo_attachment(gl_info, format->flags[type], type, &object, format->glInternal,
2197                 format->glFormat, format->glType);
2198 
2199         if (format->flags[type] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
2200         {
2201             gl_info->fbo_ops.glGenRenderbuffers(1, &color_rb);
2202             gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, color_rb);
2203             if (type == WINED3D_GL_RES_TYPE_TEX_1D)
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,
2209                     GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, color_rb);
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 
2217         if (status == GL_FRAMEBUFFER_COMPLETE)
2218         {
2219             TRACE("Format %s is supported as FBO %s attachment, type %u.\n",
2220                     debug_d3dformat(format->id), type_string, type);
2221             format->flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE;
2222             format->rtInternal = format->glInternal;
2223             regular_fmt_used = TRUE;
2224         }
2225         else
2226         {
2227             if (!rt_internal)
2228             {
2229                 if (format->flags[type] & WINED3DFMT_FLAG_RENDERTARGET)
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);
2233                     format->flags[type] &= ~WINED3DFMT_FLAG_RENDERTARGET;
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 
2257                 if (status == GL_FRAMEBUFFER_COMPLETE)
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);
2267                     format->flags[type] &= ~WINED3DFMT_FLAG_RENDERTARGET;
2268                 }
2269             }
2270         }
2271 
2272         if (status == GL_FRAMEBUFFER_COMPLETE
2273                 && ((format->flags[type] & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)
2274                 || !(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
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);
2290                 if (type == WINED3D_GL_RES_TYPE_TEX_1D)
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);
2307                 format->flags[type] &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
2308             }
2309             else
2310             {
2311                 gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
2312                 if (type == WINED3D_GL_RES_TYPE_TEX_1D)
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                 {
2328                     case WINED3D_GL_RES_TYPE_TEX_1D:
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 
2336                     case WINED3D_GL_RES_TYPE_TEX_2D:
2337                     case WINED3D_GL_RES_TYPE_TEX_3D:
2338                     case WINED3D_GL_RES_TYPE_TEX_RECT:
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 
2346                     case WINED3D_GL_RES_TYPE_TEX_CUBE:
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 
2354                     case WINED3D_GL_RES_TYPE_RB:
2355                         gl_info->gl_ops.gl.p_glReadPixels(0, 0, 16, 16,
2356                                 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
2357                         color = readback[7 * 16 + 7];
2358                         break;
2359 
2360                     case WINED3D_GL_RES_TYPE_BUFFER:
2361                     case WINED3D_GL_RES_TYPE_COUNT:
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);
2381                     format->flags[type] &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
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);
2388                     format->flags[type] |= WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
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 
2411             if (status == GL_FRAMEBUFFER_COMPLETE)
2412             {
2413                 TRACE("Format %s's sRGB format is FBO attachable, type %u.\n",
2414                         debug_d3dformat(format->id), type);
2415                 format->flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
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);
2423                 format_clear_flag(format, WINED3DFMT_FLAG_SRGB_WRITE);
2424             }
2425         }
2426         else if (status == GL_FRAMEBUFFER_COMPLETE)
2427             format->flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
2428 
2429         if (format->flags[type] & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
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));
2443         format_clear_flag(format, WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_FBO_ATTACHABLE
2444                 | WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING);
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;
2452     enum wined3d_gl_resource_type type;
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. */
2471 static void init_format_fbo_compat_info(struct wined3d_caps_gl_ctx *ctx)
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);
2497                     format->flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE;
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);
2507                         format->flags[type] |= WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
2508                     }
2509                     else
2510                     {
2511                         TRACE("Format %s doesn't support post-pixelshader blending, resource typed %u.\n",
2512                                 debug_d3dformat(format->id), type);
2513                         format->flags[type] &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
2514                     }
2515                 }
2516                 else
2517                 {
2518                     if (!rt_internal)
2519                     {
2520                         if (format->flags[type] & WINED3DFMT_FLAG_RENDERTARGET)
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);
2525                             format->flags[type] &= ~WINED3DFMT_FLAG_RENDERTARGET;
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);
2546                             format->flags[type] &= ~WINED3DFMT_FLAG_RENDERTARGET;
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);
2559                         format->flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
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);
2567                         format_clear_flag(format, WINED3DFMT_FLAG_SRGB_WRITE);
2568                     }
2569                 }
2570                 else if (format->flags[type] & WINED3DFMT_FLAG_FBO_ATTACHABLE)
2571                     format->flags[type] |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
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));
2578                 format_clear_flag(format, WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_FBO_ATTACHABLE
2579                         | WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB | WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING);
2580             }
2581         }
2582         return;
2583     }
2584 
2585     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
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 
2599         if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_COMPRESSED)
2600         {
2601             TRACE("Skipping format %s because it's a compressed format.\n",
2602                     debug_d3dformat(format->id));
2603             continue;
2604         }
2605 
2606         if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
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 
2617     if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
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 */
2631         {GL_RGBA32F,        GL_VIEW_CLASS_128_BITS},
2632         {GL_RGBA32UI,       GL_VIEW_CLASS_128_BITS},
2633         {GL_RGBA32I,        GL_VIEW_CLASS_128_BITS},
2634         /* 96-bit */
2635         {GL_RGB32F,         GL_VIEW_CLASS_96_BITS},
2636         {GL_RGB32UI,        GL_VIEW_CLASS_96_BITS},
2637         {GL_RGB32I,         GL_VIEW_CLASS_96_BITS},
2638         /* 64-bit */
2639         {GL_RGBA16F,        GL_VIEW_CLASS_64_BITS},
2640         {GL_RG32F,          GL_VIEW_CLASS_64_BITS},
2641         {GL_RGBA16UI,       GL_VIEW_CLASS_64_BITS},
2642         {GL_RG32UI,         GL_VIEW_CLASS_64_BITS},
2643         {GL_RGBA16I,        GL_VIEW_CLASS_64_BITS},
2644         {GL_RG32I,          GL_VIEW_CLASS_64_BITS},
2645         {GL_RGBA16,         GL_VIEW_CLASS_64_BITS},
2646         {GL_RGBA16_SNORM,   GL_VIEW_CLASS_64_BITS},
2647         /* 48-bit */
2648         {GL_RGB16,          GL_VIEW_CLASS_48_BITS},
2649         {GL_RGB16_SNORM,    GL_VIEW_CLASS_48_BITS},
2650         {GL_RGB16F,         GL_VIEW_CLASS_48_BITS},
2651         {GL_RGB16UI,        GL_VIEW_CLASS_48_BITS},
2652         {GL_RGB16I,         GL_VIEW_CLASS_48_BITS},
2653         /* 32-bit */
2654         {GL_RG16F,          GL_VIEW_CLASS_32_BITS},
2655         {GL_R11F_G11F_B10F, GL_VIEW_CLASS_32_BITS},
2656         {GL_R32F,           GL_VIEW_CLASS_32_BITS},
2657         {GL_RGB10_A2UI,     GL_VIEW_CLASS_32_BITS},
2658         {GL_RGBA8UI,        GL_VIEW_CLASS_32_BITS},
2659         {GL_RG16UI,         GL_VIEW_CLASS_32_BITS},
2660         {GL_R32UI,          GL_VIEW_CLASS_32_BITS},
2661         {GL_RGBA8I,         GL_VIEW_CLASS_32_BITS},
2662         {GL_RG16I,          GL_VIEW_CLASS_32_BITS},
2663         {GL_R32I,           GL_VIEW_CLASS_32_BITS},
2664         {GL_RGB10_A2,       GL_VIEW_CLASS_32_BITS},
2665         {GL_RGBA8,          GL_VIEW_CLASS_32_BITS},
2666         {GL_RG16,           GL_VIEW_CLASS_32_BITS},
2667         {GL_RGBA8_SNORM,    GL_VIEW_CLASS_32_BITS},
2668         {GL_RG16_SNORM,     GL_VIEW_CLASS_32_BITS},
2669         {GL_SRGB8_ALPHA8,   GL_VIEW_CLASS_32_BITS},
2670         {GL_RGB9_E5,        GL_VIEW_CLASS_32_BITS},
2671         /* 24-bit */
2672         {GL_RGB8,           GL_VIEW_CLASS_24_BITS},
2673         {GL_RGB8_SNORM,     GL_VIEW_CLASS_24_BITS},
2674         {GL_SRGB8,          GL_VIEW_CLASS_24_BITS},
2675         {GL_RGB8UI,         GL_VIEW_CLASS_24_BITS},
2676         {GL_RGB8I,          GL_VIEW_CLASS_24_BITS},
2677         /* 16-bit */
2678         {GL_R16F,           GL_VIEW_CLASS_16_BITS},
2679         {GL_RG8UI,          GL_VIEW_CLASS_16_BITS},
2680         {GL_R16UI,          GL_VIEW_CLASS_16_BITS},
2681         {GL_RG8I,           GL_VIEW_CLASS_16_BITS},
2682         {GL_R16I,           GL_VIEW_CLASS_16_BITS},
2683         {GL_RG8,            GL_VIEW_CLASS_16_BITS},
2684         {GL_R16,            GL_VIEW_CLASS_16_BITS},
2685         {GL_RG8_SNORM,      GL_VIEW_CLASS_16_BITS},
2686         {GL_R16_SNORM,      GL_VIEW_CLASS_16_BITS},
2687         /* 8-bit */
2688         {GL_R8UI,           GL_VIEW_CLASS_8_BITS},
2689         {GL_R8I,            GL_VIEW_CLASS_8_BITS},
2690         {GL_R8,             GL_VIEW_CLASS_8_BITS},
2691         {GL_R8_SNORM,       GL_VIEW_CLASS_8_BITS},
2692 
2693         /* RGTC1 */
2694         {GL_COMPRESSED_RED_RGTC1,        GL_VIEW_CLASS_RGTC1_RED},
2695         {GL_COMPRESSED_SIGNED_RED_RGTC1, GL_VIEW_CLASS_RGTC1_RED},
2696         /* RGTC2 */
2697         {GL_COMPRESSED_RG_RGTC2,         GL_VIEW_CLASS_RGTC2_RG},
2698         {GL_COMPRESSED_SIGNED_RG_RGTC2,  GL_VIEW_CLASS_RGTC2_RG},
2699 
2700         /* BPTC unorm */
2701         {GL_COMPRESSED_RGBA_BPTC_UNORM,         GL_VIEW_CLASS_BPTC_UNORM},
2702         {GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM,   GL_VIEW_CLASS_BPTC_UNORM},
2703         /* BPTC float */
2704         {GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT,   GL_VIEW_CLASS_BPTC_FLOAT},
2705         {GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT, GL_VIEW_CLASS_BPTC_FLOAT},
2706 
2707         /* DXT1 RGB */
2708         {GL_COMPRESSED_RGB_S3TC_DXT1_EXT,        GL_VIEW_CLASS_S3TC_DXT1_RGB},
2709         {GL_COMPRESSED_SRGB_S3TC_DXT1_EXT,       GL_VIEW_CLASS_S3TC_DXT1_RGB},
2710         /* DXT1 RGBA */
2711         {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT,       GL_VIEW_CLASS_S3TC_DXT1_RGBA},
2712         {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_VIEW_CLASS_S3TC_DXT1_RGBA},
2713         /* DXT3 */
2714         {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT,       GL_VIEW_CLASS_S3TC_DXT3_RGBA},
2715         {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_VIEW_CLASS_S3TC_DXT3_RGBA},
2716         /* DXT5 */
2717         {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT,       GL_VIEW_CLASS_S3TC_DXT5_RGBA},
2718         {GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_VIEW_CLASS_S3TC_DXT5_RGBA},
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 
2732 static void query_view_class(struct wined3d_format *format)
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 {
2756     GLint count, multisample_types[8];
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
2776                 format_clear_flag(format, WINED3DFMT_FLAG_SRGB_WRITE);
2777 
2778             if (!(format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & (WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE)))
2779                 format->glGammaInternal = format->glInternal;
2780             else if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
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])
2788             format_clear_flag(format, WINED3DFMT_FLAG_VTF);
2789 
2790         if (!(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
2791             format_set_flag(format, WINED3DFMT_FLAG_FILTERING);
2792         else if (format->id != WINED3DFMT_R32G32B32A32_FLOAT && format->id != WINED3DFMT_R32_FLOAT)
2793             format_clear_flag(format, WINED3DFMT_FLAG_VTF);
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;
2801                 format_clear_flag(format, WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
2802             }
2803             else if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
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)
2811             format_clear_flag(format, WINED3DFMT_FLAG_SRGB_WRITE);
2812 
2813         if (!gl_info->supported[ARB_DEPTH_TEXTURE]
2814                 && texture_info->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
2815         {
2816             format->flags[WINED3D_GL_RES_TYPE_TEX_1D] &= ~WINED3DFMT_FLAG_TEXTURE;
2817             format->flags[WINED3D_GL_RES_TYPE_TEX_2D] &= ~WINED3DFMT_FLAG_TEXTURE;
2818             format->flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
2819             format->flags[WINED3D_GL_RES_TYPE_TEX_CUBE] &= ~WINED3DFMT_FLAG_TEXTURE;
2820             format->flags[WINED3D_GL_RES_TYPE_TEX_RECT] &= ~WINED3DFMT_FLAG_TEXTURE;
2821         }
2822     }
2823 
2824     query_view_class(format);
2825 
2826     if (format->glInternal && format->flags[WINED3D_GL_RES_TYPE_RB]
2827             & (WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
2828     {
2829         if (gl_info->supported[ARB_INTERNALFORMAT_QUERY])
2830         {
2831             target = gl_info->supported[ARB_TEXTURE_MULTISAMPLE] ? GL_TEXTURE_2D_MULTISAMPLE : GL_RENDERBUFFER;
2832             count = 0;
2833             GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
2834                     GL_NUM_SAMPLE_COUNTS, 1, &count));
2835             if (count > ARRAY_SIZE(multisample_types))
2836                 FIXME("Unexpectedly high number of multisample types %d.\n", count);
2837             count = min(count, ARRAY_SIZE(multisample_types));
2838             GL_EXTCALL(glGetInternalformativ(target, format->glInternal,
2839                     GL_SAMPLES, count, multisample_types));
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;
2867     struct fragment_caps fragment_caps;
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);
2874     srgb_write = (fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_SRGB_WRITE)
2875             && (shader_caps.wined3d_caps & WINED3D_SHADER_CAP_SRGB_WRITE);
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]
2888                 && (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_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]
2893                 && (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_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 
2905         format->flags[WINED3D_GL_RES_TYPE_TEX_1D] |= format_texture_info[i].flags;
2906         format->flags[WINED3D_GL_RES_TYPE_TEX_2D] |= format_texture_info[i].flags;
2907         format->flags[WINED3D_GL_RES_TYPE_BUFFER] |= format_texture_info[i].flags;
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]
2912                 && !(format_texture_info[i].flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL)))
2913             format->flags[WINED3D_GL_RES_TYPE_TEX_3D] |= format_texture_info[i].flags;
2914 
2915         if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
2916             format->flags[WINED3D_GL_RES_TYPE_TEX_CUBE] |= format_texture_info[i].flags;
2917 
2918         if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
2919             format->flags[WINED3D_GL_RES_TYPE_TEX_RECT] |= format_texture_info[i].flags;
2920 
2921         format->flags[WINED3D_GL_RES_TYPE_RB] |= format_texture_info[i].flags;
2922         format->flags[WINED3D_GL_RES_TYPE_RB] &= ~WINED3DFMT_FLAG_TEXTURE;
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;
2928             format_clear_flag(format, WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
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;
2958             format_set_flag(srgb_format, WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
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,
3012             GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
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 
3078 static void init_format_filter_info(struct wined3d_gl_info *gl_info, enum wined3d_pci_vendor vendor)
3079 {
3080     struct wined3d_format *format;
3081     unsigned int fmt_idx, i;
3082     static const enum wined3d_format_id fmts16[] =
3083     {
3084         WINED3DFMT_R16_FLOAT,
3085         WINED3DFMT_R16G16_FLOAT,
3086         WINED3DFMT_R16G16B16A16_FLOAT,
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 
3094     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO
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]));
3135             format_set_flag(format, WINED3DFMT_FLAG_FILTERING);
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 
3149     idx = get_format_idx(WINED3DFMT_R16_FLOAT);
3150     gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3151             0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
3152 
3153     idx = get_format_idx(WINED3DFMT_R32_FLOAT);
3154     gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3155             0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
3156 
3157     idx = get_format_idx(WINED3DFMT_R16G16_UNORM);
3158     gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3159             0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
3160 
3161     idx = get_format_idx(WINED3DFMT_R16G16_FLOAT);
3162     gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3163             0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
3164 
3165     idx = get_format_idx(WINED3DFMT_R32G32_FLOAT);
3166     gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3167             0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
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. */
3176         idx = get_format_idx(WINED3DFMT_R8G8_SNORM);
3177         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3178                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
3179         idx = get_format_idx(WINED3DFMT_R16G16_SNORM);
3180         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3181                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
3182     }
3183     else
3184     {
3185         /* Emulate using unsigned formats. This requires load-time conversion in addition to the
3186          * fixups here. */
3187         idx = get_format_idx(WINED3DFMT_R8G8_SNORM);
3188         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3189                 1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
3190         idx = get_format_idx(WINED3DFMT_R16G16_SNORM);
3191         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3192                 1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
3193         idx = get_format_idx(WINED3DFMT_R8G8B8A8_SNORM);
3194         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3195                 1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 1, CHANNEL_SOURCE_Z, 1, CHANNEL_SOURCE_W);
3196         idx = get_format_idx(WINED3DFMT_R5G5_SNORM_L6_UNORM);
3197         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3198                 1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE);
3199     }
3200 
3201     if (!gl_info->supported[NV_TEXTURE_SHADER])
3202     {
3203         idx = get_format_idx(WINED3DFMT_R8G8_SNORM_L8X8_UNORM);
3204         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3205                 1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_W);
3206     }
3207 
3208     if (gl_info->supported[ARB_TEXTURE_COMPRESSION_RGTC] || gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
3209     {
3210         idx = get_format_idx(WINED3DFMT_ATI1N);
3211         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3212                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X);
3213 
3214         idx = get_format_idx(WINED3DFMT_ATI2N);
3215         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3216                 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
3217     }
3218     else if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC])
3219     {
3220         idx = get_format_idx(WINED3DFMT_ATI2N);
3221         gl_info->formats[idx].color_fixup= create_color_fixup_desc(
3222                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_W, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
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     {
3228         idx = get_format_idx(WINED3DFMT_YUY2);
3229         gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YUY2);
3230 
3231         idx = get_format_idx(WINED3DFMT_UYVY);
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     {
3237         idx = get_format_idx(WINED3DFMT_YUY2);
3238         gl_info->formats[idx].glInternal = 0;
3239 
3240         idx = get_format_idx(WINED3DFMT_UYVY);
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     {
3247         idx = get_format_idx(WINED3DFMT_YV12);
3248         format_set_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_HEIGHT_SCALE);
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 
3253         idx = get_format_idx(WINED3DFMT_NV12);
3254         format_set_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_HEIGHT_SCALE);
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     {
3261         idx = get_format_idx(WINED3DFMT_YV12);
3262         gl_info->formats[idx].glInternal = 0;
3263 
3264         idx = get_format_idx(WINED3DFMT_NV12);
3265         gl_info->formats[idx].glInternal = 0;
3266     }
3267 
3268     if (!gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
3269     {
3270         idx = get_format_idx(WINED3DFMT_A8_UNORM);
3271         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3272                 0, CHANNEL_SOURCE_ZERO, 0, CHANNEL_SOURCE_ZERO, 0, CHANNEL_SOURCE_ZERO, 0, CHANNEL_SOURCE_X);
3273         idx = get_format_idx(WINED3DFMT_L8A8_UNORM);
3274         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3275                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y);
3276         idx = get_format_idx(WINED3DFMT_L4A4_UNORM);
3277         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3278                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y);
3279         idx = get_format_idx(WINED3DFMT_L16_UNORM);
3280         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3281                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE);
3282         idx = get_format_idx(WINED3DFMT_INTZ);
3283         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3284                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X);
3285     }
3286 
3287     if (gl_info->supported[ARB_TEXTURE_RG])
3288     {
3289         idx = get_format_idx(WINED3DFMT_L8_UNORM);
3290         gl_info->formats[idx].color_fixup = create_color_fixup_desc(
3291                 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE);
3292     }
3293 
3294     if (gl_info->supported[ARB_FRAGMENT_PROGRAM] || gl_info->supported[ARB_FRAGMENT_SHADER])
3295     {
3296         idx = get_format_idx(WINED3DFMT_P8_UINT);
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     {
3302         idx = get_format_idx(WINED3DFMT_B8G8R8A8_UNORM);
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 */
3310         idx = get_format_idx(WINED3DFMT_R16G16_FLOAT);
3311         gl_info->formats[idx].gl_vtx_type = GL_FLOAT;
3312 
3313         idx = get_format_idx(WINED3DFMT_R16G16B16A16_FLOAT);
3314         gl_info->formats[idx].gl_vtx_type = GL_FLOAT;
3315     }
3316 
3317     if (!gl_info->supported[ARB_HALF_FLOAT_PIXEL])
3318     {
3319         idx = get_format_idx(WINED3DFMT_R16_FLOAT);
3320         format_clear_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_TEXTURE);
3321 
3322         idx = get_format_idx(WINED3DFMT_R16G16_FLOAT);
3323         format_clear_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_TEXTURE);
3324 
3325         idx = get_format_idx(WINED3DFMT_R16G16B16A16_FLOAT);
3326         format_clear_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_TEXTURE);
3327     }
3328 
3329     if (gl_info->quirks & WINED3D_QUIRK_BROKEN_RGBA16)
3330     {
3331         idx = get_format_idx(WINED3DFMT_R16G16B16A16_UNORM);
3332         format_clear_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_TEXTURE);
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     {
3350         idx = get_format_idx(WINED3DFMT_INST);
3351         format_set_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_TEXTURE);
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     {
3362         idx = get_format_idx(WINED3DFMT_NVDB);
3363         format_set_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_TEXTURE);
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     {
3371         idx = get_format_idx(WINED3DFMT_RESZ);
3372         format_set_flag(&gl_info->formats[idx], WINED3DFMT_FLAG_TEXTURE | WINED3DFMT_FLAG_RENDERTARGET);
3373     }
3374 
3375     for (i = 0; i < gl_info->format_count; ++i)
3376     {
3377         struct wined3d_format *format = &gl_info->formats[i];
3378 
3379         if (!(format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_TEXTURE))
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");
3391             format_clear_flag(format, WINED3DFMT_FLAG_TEXTURE);
3392         }
3393         else
3394         {
3395             TRACE("[OK]\n");
3396         }
3397     }
3398 
3399     /* GL_EXT_texture_compression_s3tc does not support 3D textures. Some Windows drivers
3400      * for dx9 GPUs support it, some do not, so not supporting DXTn volumes is OK for d3d9.
3401      *
3402      * Note that GL_NV_texture_compression_vtc adds this functionality to OpenGL, but the
3403      * block layout is not compatible with the one used by d3d. See volume_dxt5_test. */
3404     idx = get_format_idx(WINED3DFMT_DXT1);
3405     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3406     idx = get_format_idx(WINED3DFMT_DXT2);
3407     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3408     idx = get_format_idx(WINED3DFMT_DXT3);
3409     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3410     idx = get_format_idx(WINED3DFMT_DXT4);
3411     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3412     idx = get_format_idx(WINED3DFMT_DXT5);
3413     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3414     idx = get_format_idx(WINED3DFMT_BC1_UNORM);
3415     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3416     idx = get_format_idx(WINED3DFMT_BC1_UNORM_SRGB);
3417     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3418     idx = get_format_idx(WINED3DFMT_BC2_UNORM);
3419     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3420     idx = get_format_idx(WINED3DFMT_BC2_UNORM_SRGB);
3421     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3422     idx = get_format_idx(WINED3DFMT_BC3_UNORM);
3423     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3424     idx = get_format_idx(WINED3DFMT_BC3_UNORM_SRGB);
3425     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3426     /* Similarly with ATI1N / ATI2N and GL_ARB_texture_compression_rgtc. */
3427     idx = get_format_idx(WINED3DFMT_ATI1N);
3428     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3429     idx = get_format_idx(WINED3DFMT_ATI2N);
3430     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3431     idx = get_format_idx(WINED3DFMT_BC4_UNORM);
3432     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3433     idx = get_format_idx(WINED3DFMT_BC4_SNORM);
3434     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3435     idx = get_format_idx(WINED3DFMT_BC5_UNORM);
3436     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3437     idx = get_format_idx(WINED3DFMT_BC5_SNORM);
3438     gl_info->formats[idx].flags[WINED3D_GL_RES_TYPE_TEX_3D] &= ~WINED3DFMT_FLAG_TEXTURE;
3439 }
3440 
3441 static unsigned int calculate_vertex_attribute_size(GLenum type, unsigned int component_count)
3442 {
3443     switch (type)
3444     {
3445         case GL_HALF_FLOAT:
3446             return component_count * sizeof(GLhalfNV);
3447         case GL_FLOAT:
3448             return component_count * sizeof(GLfloat);
3449         case GL_BYTE:
3450             return component_count * sizeof(GLbyte);
3451         case GL_UNSIGNED_BYTE:
3452             return component_count * sizeof(GLubyte);
3453         case GL_SHORT:
3454             return component_count * sizeof(GLshort);
3455         case GL_UNSIGNED_SHORT:
3456             return component_count * sizeof(GLushort);
3457         case GL_INT:
3458             return component_count * sizeof(GLint);
3459         case GL_UNSIGNED_INT:
3460             return component_count * sizeof(GLuint);
3461         case GL_UNSIGNED_INT_2_10_10_10_REV:
3462             return sizeof(GLuint);
3463         default:
3464             FIXME("Unhandled GL type %#x.\n", type);
3465             return 0;
3466     }
3467 }
3468 
3469 static BOOL init_format_vertex_info(struct wined3d_gl_info *gl_info)
3470 {
3471     struct wined3d_format *format;
3472     unsigned int i;
3473 
3474     for (i = 0; i < ARRAY_SIZE(format_vertex_info); ++i)
3475     {
3476         if (!(format = get_format_internal(gl_info, format_vertex_info[i].id)))
3477             return FALSE;
3478 
3479         if (!gl_info->supported[format_vertex_info[i].extension])
3480             continue;
3481 
3482         format->emit_idx = format_vertex_info[i].emit_idx;
3483         format->component_count = format_vertex_info[i].component_count;
3484         format->gl_vtx_type = format_vertex_info[i].gl_vtx_type;
3485         format->gl_vtx_format = format_vertex_info[i].component_count;
3486         format->gl_normalized = format_vertex_info[i].gl_normalized;
3487         if (!(format->attribute_size = calculate_vertex_attribute_size(format->gl_vtx_type,
3488                 format->component_count)))
3489         {
3490             ERR("Invalid attribute size for vertex format %s (%#x).\n",
3491                     debug_d3dformat(format_vertex_info[i].id), format_vertex_info[i].id);
3492             return FALSE;
3493         }
3494     }
3495 
3496     return TRUE;
3497 }
3498 
3499 static BOOL init_typeless_formats(struct wined3d_gl_info *gl_info)
3500 {
3501     unsigned int flags[WINED3D_GL_RES_TYPE_COUNT];
3502     unsigned int i, j;
3503 
3504     for (i = 0; i < ARRAY_SIZE(typed_formats); ++i)
3505     {
3506         struct wined3d_format *format, *typeless_format;
3507 
3508         if (!(format = get_format_internal(gl_info, typed_formats[i].id)))
3509             return FALSE;
3510         if (!(typeless_format = get_format_internal(gl_info, typed_formats[i].typeless_id)))
3511             return FALSE;
3512 
3513         memcpy(flags, typeless_format->flags, sizeof(flags));
3514         copy_format(typeless_format, format);
3515         for (j = 0; j < ARRAY_SIZE(typeless_format->flags); ++j)
3516             typeless_format->flags[j] |= flags[j];
3517     }
3518 
3519     for (i = 0; i < ARRAY_SIZE(typeless_depth_stencil_formats); ++i)
3520     {
3521         struct wined3d_format *typeless_format, *typeless_ds_format, *ds_format;
3522         struct wined3d_format *depth_view_format, *stencil_view_format;
3523         enum wined3d_format_id format_id;
3524 
3525         if (!(typeless_format = get_format_internal(gl_info, typeless_depth_stencil_formats[i].typeless_id)))
3526             return FALSE;
3527         if (!(ds_format = get_format_internal(gl_info, typeless_depth_stencil_formats[i].depth_stencil_id)))
3528             return FALSE;
3529 
3530         typeless_ds_format = &gl_info->formats[WINED3D_FORMAT_COUNT + i];
3531         typeless_ds_format->id = typeless_depth_stencil_formats[i].typeless_id;
3532         copy_format(typeless_ds_format, ds_format);
3533         for (j = 0; j < ARRAY_SIZE(typeless_ds_format->flags); ++j)
3534         {
3535             typeless_ds_format->flags[j] = typeless_format->flags[j];
3536             typeless_format->flags[j] &= ~(WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL);
3537         }
3538 
3539         if ((format_id = typeless_depth_stencil_formats[i].depth_view_id)
3540                 && typeless_depth_stencil_formats[i].separate_depth_view_format)
3541         {
3542             if (!(depth_view_format = get_format_internal(gl_info, format_id)))
3543                 return FALSE;
3544             copy_format(depth_view_format, ds_format);
3545         }
3546         if ((format_id = typeless_depth_stencil_formats[i].stencil_view_id))
3547         {
3548             if (!(stencil_view_format = get_format_internal(gl_info, format_id)))
3549                 return FALSE;
3550             copy_format(stencil_view_format, ds_format);
3551         }
3552     }
3553 
3554     return TRUE;
3555 }
3556 
3557 static void init_format_gen_mipmap_info(struct wined3d_gl_info *gl_info)
3558 {
3559     unsigned int i, j;
3560 
3561     if (!gl_info->fbo_ops.glGenerateMipmap)
3562         return;
3563 
3564     for (i = 0; i < gl_info->format_count; ++i)
3565     {
3566         struct wined3d_format *format = &gl_info->formats[i];
3567 
3568         for (j = 0; j < ARRAY_SIZE(format->flags); ++j)
3569             if (!(~format->flags[j] & (WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_FILTERING)))
3570                 format->flags[j] |= WINED3DFMT_FLAG_GEN_MIPMAP;
3571     }
3572 }
3573 
3574 BOOL wined3d_caps_gl_ctx_test_viewport_subpixel_bits(struct wined3d_caps_gl_ctx *ctx)
3575 {
3576     static const struct wined3d_color red = {1.0f, 0.0f, 0.0f, 1.0f};
3577     const struct wined3d_gl_info *gl_info = ctx->gl_info;
3578     static const float offset = -63.0f / 128.0f;
3579     GLuint texture, fbo;
3580     DWORD readback[4];
3581     unsigned int i;
3582 
3583     gl_info->gl_ops.gl.p_glGenTextures(1, &texture);
3584     gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, texture);
3585     gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3586     gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, ARRAY_SIZE(readback), 1, 0,
3587             GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
3588     gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
3589     gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3590     gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
3591             GL_TEXTURE_2D, texture, 0);
3592     checkGLcall("create resources");
3593 
3594     gl_info->gl_ops.gl.p_glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
3595     gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
3596     GL_EXTCALL(glViewportIndexedf(0, offset, offset, 4.0f, 1.0f));
3597     draw_test_quad(ctx, NULL, &red);
3598     checkGLcall("draw");
3599 
3600     gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, texture);
3601     gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0,
3602             GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
3603     checkGLcall("readback");
3604 
3605     TRACE("Readback colors are 0x%08x, 0x%08x, 0x%08x, 0x%08x.\n",
3606             readback[0], readback[1], readback[2], readback[3]);
3607 
3608     gl_info->gl_ops.gl.p_glDeleteTextures(1, &texture);
3609     gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
3610     gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
3611     checkGLcall("delete resources");
3612 
3613     for (i = 0; i < ARRAY_SIZE(readback); ++i)
3614     {
3615         if (readback[i] != 0xffff0000)
3616             return FALSE;
3617     }
3618     return TRUE;
3619 }
3620 
3621 static float wined3d_adapter_find_polyoffset_scale(struct wined3d_caps_gl_ctx *ctx, GLenum format)
3622 {
3623     const struct wined3d_gl_info *gl_info = ctx->gl_info;
3624     static const struct wined3d_color blue = {0.0f, 0.0f, 1.0f, 1.0f};
3625     GLuint fbo, color, depth;
3626     unsigned int low = 0, high = 32, cur;
3627     DWORD readback[256];
3628     static const struct wined3d_vec3 geometry[] =
3629     {
3630         {-1.0f, -1.0f, -1.0f},
3631         { 1.0f, -1.0f,  0.0f},
3632         {-1.0f,  1.0f, -1.0f},
3633         { 1.0f,  1.0f,  0.0f},
3634     };
3635 
3636     /* Most drivers want 2^23 for fixed point depth buffers, including r300g, r600g,
3637      * Nvidia. Use this as a fallback if the detection fails. */
3638     unsigned int fallback = 23;
3639 
3640     if (wined3d_settings.offscreen_rendering_mode != ORM_FBO)
3641     {
3642         FIXME("No FBOs, assuming polyoffset scale of 2^%u.\n", fallback);
3643         return (float)(1u << fallback);
3644     }
3645 
3646     gl_info->gl_ops.gl.p_glGenTextures(1, &color);
3647     gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, color);
3648     gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0);
3649     gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 256, 1, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
3650 
3651     gl_info->fbo_ops.glGenRenderbuffers(1, &depth);
3652     gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, depth);
3653     gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, format, 256, 1);
3654 
3655     gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
3656     gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
3657     gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, color, 0);
3658     gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depth);
3659     checkGLcall("Setup framebuffer");
3660 
3661     gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 0.5f, 0.0f);
3662     gl_info->gl_ops.gl.p_glClearDepth(0.5f);
3663     gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_TEST);
3664     gl_info->gl_ops.gl.p_glEnable(GL_POLYGON_OFFSET_FILL);
3665     gl_info->gl_ops.gl.p_glViewport(0, 0, 256, 1);
3666     checkGLcall("Misc parameters");
3667 
3668     for (;;)
3669     {
3670         if (high - low <= 1)
3671         {
3672             ERR("PolygonOffset scale factor detection failed, using fallback value 2^%u.\n", fallback);
3673             cur = fallback;
3674             break;
3675         }
3676         cur = (low + high) / 2;
3677 
3678         gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
3679         /* The post viewport transform Z of the geometry runs from 0.0 to 0.5. We want to push it another
3680          * 0.25 so that the Z buffer content (0.5) cuts the quad off at half the screen. */
3681         gl_info->gl_ops.gl.p_glPolygonOffset(0.0f, (float)(1u << cur) * 0.25f);
3682         draw_test_quad(ctx, geometry, &blue);
3683         checkGLcall("Test draw");
3684 
3685         /* Rebinding texture to workaround a fglrx bug. */
3686         gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, color);
3687         gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
3688         checkGLcall("readback");
3689 
3690         TRACE("low %02u, high %02u, cur %2u, 0=0x%08x, 125=0x%08x, 131=0x%08x, 255=0x%08x\n",
3691                 low, high, cur, readback[0], readback[125], readback[131], readback[255]);
3692 
3693         if ((readback[125] & 0xff) < 0xa0)
3694             high = cur;
3695         else if ((readback[131] & 0xff) > 0xa0)
3696             low = cur;
3697         else
3698         {
3699             TRACE("Found scale factor 2^%u for format %x.\n", cur, format);
3700             break;
3701         }
3702     }
3703 
3704     gl_info->gl_ops.gl.p_glDeleteTextures(1, &color);
3705     gl_info->fbo_ops.glDeleteRenderbuffers(1, &depth);
3706     gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
3707     gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
3708     checkGLcall("Delete framebuffer");
3709 
3710     gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST);
3711     gl_info->gl_ops.gl.p_glDisable(GL_POLYGON_OFFSET_FILL);
3712     return (float)(1u << cur);
3713 }
3714 
3715 static void init_format_depth_bias_scale(struct wined3d_caps_gl_ctx *ctx,
3716         const struct wined3d_d3d_info *d3d_info)
3717 {
3718     const struct wined3d_gl_info *gl_info = ctx->gl_info;
3719     unsigned int i;
3720 
3721     for (i = 0; i < gl_info->format_count; ++i)
3722     {
3723         struct wined3d_format *format = &gl_info->formats[i];
3724 
3725         if (format->flags[WINED3D_GL_RES_TYPE_RB] & WINED3DFMT_FLAG_DEPTH)
3726         {
3727             TRACE("Testing depth bias scale for format %s.\n", debug_d3dformat(format->id));
3728             format->depth_bias_scale = wined3d_adapter_find_polyoffset_scale(ctx, format->glInternal);
3729 
3730             if (!(d3d_info->wined3d_creation_flags & WINED3D_NORMALIZED_DEPTH_BIAS))
3731             {
3732                 /* The single-precision binary floating-point format has
3733                  * a significand precision of 24 bits.
3734                  */
3735                 if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_FLOAT)
3736                     format->depth_bias_scale /= 1u << 24;
3737                 else
3738                     format->depth_bias_scale /= 1u << format->depth_size;
3739             }
3740         }
3741     }
3742 }
3743 
3744 /* Context activation is done by the caller. */
3745 BOOL wined3d_adapter_init_format_info(struct wined3d_adapter *adapter, struct wined3d_caps_gl_ctx *ctx)
3746 {
3747     struct wined3d_gl_info *gl_info = &adapter->gl_info;
3748 
3749     if (!init_format_base_info(gl_info)) return FALSE;
3750     if (!init_format_block_info(gl_info)) goto fail;
3751 
3752     if (!ctx) /* WINED3D_NO3D */
3753         return TRUE;
3754 
3755     if (!init_format_texture_info(adapter, gl_info)) goto fail;
3756     if (!init_format_vertex_info(gl_info)) goto fail;
3757 
3758     apply_format_fixups(adapter, gl_info);
3759     init_format_fbo_compat_info(ctx);
3760     init_format_filter_info(gl_info, adapter->driver_info.vendor);
3761     if (!init_typeless_formats(gl_info)) goto fail;
3762     init_format_gen_mipmap_info(gl_info);
3763     init_format_depth_bias_scale(ctx, &adapter->d3d_info);
3764 
3765     return TRUE;
3766 
3767 fail:
3768     heap_free(gl_info->formats);
3769     gl_info->formats = NULL;
3770     return FALSE;
3771 }
3772 
3773 const struct wined3d_format *wined3d_get_format(const struct wined3d_gl_info *gl_info,
3774         enum wined3d_format_id format_id, unsigned int resource_usage)
3775 {
3776     const struct wined3d_format *format;
3777     int idx = get_format_idx(format_id);
3778     unsigned int i;
3779 
3780     if (idx == -1)
3781     {
3782         FIXME("Can't find format %s (%#x) in the format lookup table.\n",
3783                 debug_d3dformat(format_id), format_id);
3784         return &gl_info->formats[get_format_idx(WINED3DFMT_UNKNOWN)];
3785     }
3786 
3787     format = &gl_info->formats[idx];
3788 
3789     if (resource_usage & WINED3DUSAGE_DEPTHSTENCIL && wined3d_format_is_typeless(format))
3790     {
3791         for (i = 0; i < ARRAY_SIZE(typeless_depth_stencil_formats); ++i)
3792         {
3793             if (typeless_depth_stencil_formats[i].typeless_id == format_id)
3794                 return &gl_info->formats[WINED3D_FORMAT_COUNT + i];
3795         }
3796 
3797         FIXME("Cannot find depth/stencil typeless format %s (%#x).\n",
3798                 debug_d3dformat(format_id), format_id);
3799         return &gl_info->formats[get_format_idx(WINED3DFMT_UNKNOWN)];
3800     }
3801 
3802     return format;
3803 }
3804 
3805 BOOL wined3d_format_is_depth_view(enum wined3d_format_id resource_format_id,
3806         enum wined3d_format_id view_format_id)
3807 {
3808     unsigned int i;
3809 
3810     for (i = 0; i < ARRAY_SIZE(typeless_depth_stencil_formats); ++i)
3811     {
3812         if (typeless_depth_stencil_formats[i].typeless_id == resource_format_id)
3813             return typeless_depth_stencil_formats[i].depth_view_id == view_format_id;
3814     }
3815     return FALSE;
3816 }
3817 
3818 void wined3d_format_calculate_pitch(const struct wined3d_format *format, unsigned int alignment,
3819         unsigned int width, unsigned int height, unsigned int *row_pitch, unsigned int *slice_pitch)
3820 {
3821     /* For block based formats, pitch means the amount of bytes to the next
3822      * row of blocks rather than the next row of pixels. */
3823     if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_BLOCKS)
3824     {
3825         unsigned int row_block_count = (width + format->block_width - 1) / format->block_width;
3826         unsigned int slice_block_count = (height + format->block_height - 1) / format->block_height;
3827         *row_pitch = row_block_count * format->block_byte_count;
3828         *row_pitch = (*row_pitch + alignment - 1) & ~(alignment - 1);
3829         *slice_pitch = *row_pitch * slice_block_count;
3830     }
3831     else
3832     {
3833         *row_pitch = format->byte_count * width;  /* Bytes / row */
3834         *row_pitch = (*row_pitch + alignment - 1) & ~(alignment - 1);
3835         *slice_pitch = *row_pitch * height;
3836     }
3837 
3838     if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_HEIGHT_SCALE)
3839     {
3840         /* The D3D format requirements make sure that the resulting format is an integer again */
3841         *slice_pitch *= format->height_scale.numerator;
3842         *slice_pitch /= format->height_scale.denominator;
3843     }
3844 
3845     TRACE("Returning row pitch %u, slice pitch %u.\n", *row_pitch, *slice_pitch);
3846 }
3847 
3848 UINT wined3d_format_calculate_size(const struct wined3d_format *format, UINT alignment,
3849         UINT width, UINT height, UINT depth)
3850 {
3851     unsigned int row_pitch, slice_pitch;
3852 
3853     if (format->id == WINED3DFMT_UNKNOWN)
3854         return 0;
3855 
3856     if (format->flags[WINED3D_GL_RES_TYPE_TEX_2D] & WINED3DFMT_FLAG_BROKEN_PITCH)
3857         return width * height * depth * format->byte_count;
3858 
3859     wined3d_format_calculate_pitch(format, alignment, width, height, &row_pitch, &slice_pitch);
3860 
3861     return slice_pitch * depth;
3862 }
3863 
3864 BOOL wined3d_formats_are_srgb_variants(enum wined3d_format_id format1, enum wined3d_format_id format2)
3865 {
3866     unsigned int i;
3867 
3868     for (i = 0; i < ARRAY_SIZE(format_srgb_info); ++i)
3869     {
3870         if (format1 == format_srgb_info[i].srgb_format_id)
3871             return format2 == format_srgb_info[i].base_format_id;
3872         if (format1 == format_srgb_info[i].base_format_id)
3873             return format2 == format_srgb_info[i].srgb_format_id;
3874     }
3875     return FALSE;
3876 }
3877 
3878 /*****************************************************************************
3879  * Trace formatting of useful values
3880  */
3881 const char *debug_box(const struct wined3d_box *box)
3882 {
3883     if (!box)
3884         return "(null)";
3885     return wine_dbg_sprintf("(%u, %u, %u)-(%u, %u, %u)",
3886             box->left, box->top, box->front,
3887             box->right, box->bottom, box->back);
3888 }
3889 
3890 const char *debug_color(const struct wined3d_color *color)
3891 {
3892     if (!color)
3893         return "(null)";
3894     return wine_dbg_sprintf("{%.8e, %.8e, %.8e, %.8e}",
3895             color->r, color->g, color->b, color->a);
3896 }
3897 
3898 const char *debug_ivec4(const struct wined3d_ivec4 *v)
3899 {
3900     if (!v)
3901         return "(null)";
3902     return wine_dbg_sprintf("{%d, %d, %d, %d}",
3903             v->x, v->y, v->z, v->w);
3904 }
3905 
3906 const char *debug_uvec4(const struct wined3d_uvec4 *v)
3907 {
3908     if (!v)
3909         return "(null)";
3910     return wine_dbg_sprintf("{%u, %u, %u, %u}",
3911             v->x, v->y, v->z, v->w);
3912 }
3913 
3914 const char *debug_vec4(const struct wined3d_vec4 *v)
3915 {
3916     if (!v)
3917         return "(null)";
3918     return wine_dbg_sprintf("{%.8e, %.8e, %.8e, %.8e}",
3919             v->x, v->y, v->z, v->w);
3920 }
3921 
3922 const char *debug_d3dformat(enum wined3d_format_id format_id)
3923 {
3924     switch (format_id)
3925     {
3926 #define FMT_TO_STR(format_id) case format_id: return #format_id
3927         FMT_TO_STR(WINED3DFMT_UNKNOWN);
3928         FMT_TO_STR(WINED3DFMT_B8G8R8_UNORM);
3929         FMT_TO_STR(WINED3DFMT_B5G5R5X1_UNORM);
3930         FMT_TO_STR(WINED3DFMT_B4G4R4A4_UNORM);
3931         FMT_TO_STR(WINED3DFMT_B2G3R3_UNORM);
3932         FMT_TO_STR(WINED3DFMT_B2G3R3A8_UNORM);
3933         FMT_TO_STR(WINED3DFMT_B4G4R4X4_UNORM);
3934         FMT_TO_STR(WINED3DFMT_R8G8B8X8_UNORM);
3935         FMT_TO_STR(WINED3DFMT_B10G10R10A2_UNORM);
3936         FMT_TO_STR(WINED3DFMT_P8_UINT_A8_UNORM);
3937         FMT_TO_STR(WINED3DFMT_P8_UINT);
3938         FMT_TO_STR(WINED3DFMT_L8_UNORM);
3939         FMT_TO_STR(WINED3DFMT_L8A8_UNORM);
3940         FMT_TO_STR(WINED3DFMT_L4A4_UNORM);
3941         FMT_TO_STR(WINED3DFMT_R5G5_SNORM_L6_UNORM);
3942         FMT_TO_STR(WINED3DFMT_R8G8_SNORM_L8X8_UNORM);
3943         FMT_TO_STR(WINED3DFMT_R10G11B11_SNORM);
3944         FMT_TO_STR(WINED3DFMT_R10G10B10X2_UINT);
3945         FMT_TO_STR(WINED3DFMT_R10G10B10X2_SNORM);
3946         FMT_TO_STR(WINED3DFMT_R10G10B10_SNORM_A2_UNORM);
3947         FMT_TO_STR(WINED3DFMT_UYVY);
3948         FMT_TO_STR(WINED3DFMT_YUY2);
3949         FMT_TO_STR(WINED3DFMT_YV12);
3950         FMT_TO_STR(WINED3DFMT_NV12);
3951         FMT_TO_STR(WINED3DFMT_DXT1);
3952         FMT_TO_STR(WINED3DFMT_DXT2);
3953         FMT_TO_STR(WINED3DFMT_DXT3);
3954         FMT_TO_STR(WINED3DFMT_DXT4);
3955         FMT_TO_STR(WINED3DFMT_DXT5);
3956         FMT_TO_STR(WINED3DFMT_MULTI2_ARGB8);
3957         FMT_TO_STR(WINED3DFMT_G8R8_G8B8);
3958         FMT_TO_STR(WINED3DFMT_R8G8_B8G8);
3959         FMT_TO_STR(WINED3DFMT_D16_LOCKABLE);
3960         FMT_TO_STR(WINED3DFMT_D32_UNORM);
3961         FMT_TO_STR(WINED3DFMT_S1_UINT_D15_UNORM);
3962         FMT_TO_STR(WINED3DFMT_X8D24_UNORM);
3963         FMT_TO_STR(WINED3DFMT_S4X4_UINT_D24_UNORM);
3964         FMT_TO_STR(WINED3DFMT_L16_UNORM);
3965         FMT_TO_STR(WINED3DFMT_S8_UINT_D24_FLOAT);
3966         FMT_TO_STR(WINED3DFMT_R8G8_SNORM_Cx);
3967         FMT_TO_STR(WINED3DFMT_ATI1N);
3968         FMT_TO_STR(WINED3DFMT_ATI2N);
3969         FMT_TO_STR(WINED3DFMT_NVDB);
3970         FMT_TO_STR(WINED3DFMT_NVHU);
3971         FMT_TO_STR(WINED3DFMT_NVHS);
3972         FMT_TO_STR(WINED3DFMT_R32G32B32A32_TYPELESS);
3973         FMT_TO_STR(WINED3DFMT_R32G32B32A32_FLOAT);
3974         FMT_TO_STR(WINED3DFMT_R32G32B32A32_UINT);
3975         FMT_TO_STR(WINED3DFMT_R32G32B32A32_SINT);
3976         FMT_TO_STR(WINED3DFMT_R32G32B32_TYPELESS);
3977         FMT_TO_STR(WINED3DFMT_R32G32B32_FLOAT);
3978         FMT_TO_STR(WINED3DFMT_R32G32B32_UINT);
3979         FMT_TO_STR(WINED3DFMT_R32G32B32_SINT);
3980         FMT_TO_STR(WINED3DFMT_R16G16B16A16_TYPELESS);
3981         FMT_TO_STR(WINED3DFMT_R16G16B16A16_FLOAT);
3982         FMT_TO_STR(WINED3DFMT_R16G16B16A16_UNORM);
3983         FMT_TO_STR(WINED3DFMT_R16G16B16A16_UINT);
3984         FMT_TO_STR(WINED3DFMT_R16G16B16A16_SNORM);
3985         FMT_TO_STR(WINED3DFMT_R16G16B16A16_SINT);
3986         FMT_TO_STR(WINED3DFMT_R32G32_TYPELESS);
3987         FMT_TO_STR(WINED3DFMT_R32G32_FLOAT);
3988         FMT_TO_STR(WINED3DFMT_R32G32_UINT);
3989         FMT_TO_STR(WINED3DFMT_R32G32_SINT);
3990         FMT_TO_STR(WINED3DFMT_R32G8X24_TYPELESS);
3991         FMT_TO_STR(WINED3DFMT_D32_FLOAT_S8X24_UINT);
3992         FMT_TO_STR(WINED3DFMT_R32_FLOAT_X8X24_TYPELESS);
3993         FMT_TO_STR(WINED3DFMT_X32_TYPELESS_G8X24_UINT);
3994         FMT_TO_STR(WINED3DFMT_R10G10B10A2_TYPELESS);
3995         FMT_TO_STR(WINED3DFMT_R10G10B10A2_UNORM);
3996         FMT_TO_STR(WINED3DFMT_R10G10B10A2_UINT);
3997         FMT_TO_STR(WINED3DFMT_R10G10B10A2_SNORM);
3998         FMT_TO_STR(WINED3DFMT_R10G10B10_XR_BIAS_A2_UNORM);
3999         FMT_TO_STR(WINED3DFMT_R11G11B10_FLOAT);
4000         FMT_TO_STR(WINED3DFMT_R8G8B8A8_TYPELESS);
4001         FMT_TO_STR(WINED3DFMT_R8G8B8A8_UNORM);
4002         FMT_TO_STR(WINED3DFMT_R8G8B8A8_UNORM_SRGB);
4003         FMT_TO_STR(WINED3DFMT_R8G8B8A8_UINT);
4004         FMT_TO_STR(WINED3DFMT_R8G8B8A8_SNORM);
4005         FMT_TO_STR(WINED3DFMT_R8G8B8A8_SINT);
4006         FMT_TO_STR(WINED3DFMT_R16G16_TYPELESS);
4007         FMT_TO_STR(WINED3DFMT_R16G16_FLOAT);
4008         FMT_TO_STR(WINED3DFMT_R16G16_UNORM);
4009         FMT_TO_STR(WINED3DFMT_R16G16_UINT);
4010         FMT_TO_STR(WINED3DFMT_R16G16_SNORM);
4011         FMT_TO_STR(WINED3DFMT_R16G16_SINT);
4012         FMT_TO_STR(WINED3DFMT_R32_TYPELESS);
4013         FMT_TO_STR(WINED3DFMT_D32_FLOAT);
4014         FMT_TO_STR(WINED3DFMT_R32_FLOAT);
4015         FMT_TO_STR(WINED3DFMT_R32_UINT);
4016         FMT_TO_STR(WINED3DFMT_R32_SINT);
4017         FMT_TO_STR(WINED3DFMT_R24G8_TYPELESS);
4018         FMT_TO_STR(WINED3DFMT_D24_UNORM_S8_UINT);
4019         FMT_TO_STR(WINED3DFMT_R24_UNORM_X8_TYPELESS);
4020         FMT_TO_STR(WINED3DFMT_X24_TYPELESS_G8_UINT);
4021         FMT_TO_STR(WINED3DFMT_R8G8_TYPELESS);
4022         FMT_TO_STR(WINED3DFMT_R8G8_UNORM);
4023         FMT_TO_STR(WINED3DFMT_R8G8_UINT);
4024         FMT_TO_STR(WINED3DFMT_R8G8_SNORM);
4025         FMT_TO_STR(WINED3DFMT_R8G8_SINT);
4026         FMT_TO_STR(WINED3DFMT_R16_TYPELESS);
4027         FMT_TO_STR(WINED3DFMT_R16_FLOAT);
4028         FMT_TO_STR(WINED3DFMT_D16_UNORM);
4029         FMT_TO_STR(WINED3DFMT_R16_UNORM);
4030         FMT_TO_STR(WINED3DFMT_R16_UINT);
4031         FMT_TO_STR(WINED3DFMT_R16_SNORM);
4032         FMT_TO_STR(WINED3DFMT_R16_SINT);
4033         FMT_TO_STR(WINED3DFMT_R8_TYPELESS);
4034         FMT_TO_STR(WINED3DFMT_R8_UNORM);
4035         FMT_TO_STR(WINED3DFMT_R8_UINT);
4036         FMT_TO_STR(WINED3DFMT_R8_SNORM);
4037         FMT_TO_STR(WINED3DFMT_R8_SINT);
4038         FMT_TO_STR(WINED3DFMT_A8_UNORM);
4039         FMT_TO_STR(WINED3DFMT_R1_UNORM);
4040         FMT_TO_STR(WINED3DFMT_R9G9B9E5_SHAREDEXP);
4041         FMT_TO_STR(WINED3DFMT_R8G8_B8G8_UNORM);
4042         FMT_TO_STR(WINED3DFMT_G8R8_G8B8_UNORM);
4043         FMT_TO_STR(WINED3DFMT_BC1_TYPELESS);
4044         FMT_TO_STR(WINED3DFMT_BC1_UNORM);
4045         FMT_TO_STR(WINED3DFMT_BC1_UNORM_SRGB);
4046         FMT_TO_STR(WINED3DFMT_BC2_TYPELESS);
4047         FMT_TO_STR(WINED3DFMT_BC2_UNORM);
4048         FMT_TO_STR(WINED3DFMT_BC2_UNORM_SRGB);
4049         FMT_TO_STR(WINED3DFMT_BC3_TYPELESS);
4050         FMT_TO_STR(WINED3DFMT_BC3_UNORM);
4051         FMT_TO_STR(WINED3DFMT_BC3_UNORM_SRGB);
4052         FMT_TO_STR(WINED3DFMT_BC4_TYPELESS);
4053         FMT_TO_STR(WINED3DFMT_BC4_UNORM);
4054         FMT_TO_STR(WINED3DFMT_BC4_SNORM);
4055         FMT_TO_STR(WINED3DFMT_BC5_TYPELESS);
4056         FMT_TO_STR(WINED3DFMT_BC5_UNORM);
4057         FMT_TO_STR(WINED3DFMT_BC5_SNORM);
4058         FMT_TO_STR(WINED3DFMT_B5G6R5_UNORM);
4059         FMT_TO_STR(WINED3DFMT_B5G5R5A1_UNORM);
4060         FMT_TO_STR(WINED3DFMT_B8G8R8A8_UNORM);
4061         FMT_TO_STR(WINED3DFMT_B8G8R8X8_UNORM);
4062         FMT_TO_STR(WINED3DFMT_B8G8R8A8_TYPELESS);
4063         FMT_TO_STR(WINED3DFMT_B8G8R8A8_UNORM_SRGB);
4064         FMT_TO_STR(WINED3DFMT_B8G8R8X8_TYPELESS);
4065         FMT_TO_STR(WINED3DFMT_B8G8R8X8_UNORM_SRGB);
4066         FMT_TO_STR(WINED3DFMT_BC6H_TYPELESS);
4067         FMT_TO_STR(WINED3DFMT_BC6H_UF16);
4068         FMT_TO_STR(WINED3DFMT_BC6H_SF16);
4069         FMT_TO_STR(WINED3DFMT_BC7_TYPELESS);
4070         FMT_TO_STR(WINED3DFMT_BC7_UNORM);
4071         FMT_TO_STR(WINED3DFMT_BC7_UNORM_SRGB);
4072         FMT_TO_STR(WINED3DFMT_INTZ);
4073         FMT_TO_STR(WINED3DFMT_RESZ);
4074         FMT_TO_STR(WINED3DFMT_NULL);
4075         FMT_TO_STR(WINED3DFMT_R16);
4076         FMT_TO_STR(WINED3DFMT_AL16);
4077 #undef FMT_TO_STR
4078         default:
4079         {
4080             char fourcc[5];
4081             fourcc[0] = (char)(format_id);
4082             fourcc[1] = (char)(format_id >> 8);
4083             fourcc[2] = (char)(format_id >> 16);
4084             fourcc[3] = (char)(format_id >> 24);
4085             fourcc[4] = 0;
4086             if (isprint(fourcc[0]) && isprint(fourcc[1]) && isprint(fourcc[2]) && isprint(fourcc[3]))
4087                 FIXME("Unrecognized %#x (as fourcc: %s) WINED3DFORMAT!\n", format_id, fourcc);
4088             else
4089                 FIXME("Unrecognized %#x WINED3DFORMAT!\n", format_id);
4090         }
4091         return "unrecognized";
4092     }
4093 }
4094 
4095 const char *debug_d3ddevicetype(enum wined3d_device_type device_type)
4096 {
4097     switch (device_type)
4098     {
4099 #define DEVTYPE_TO_STR(dev) case dev: return #dev
4100         DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_HAL);
4101         DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_REF);
4102         DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_SW);
4103 #undef DEVTYPE_TO_STR
4104         default:
4105             FIXME("Unrecognized device type %#x.\n", device_type);
4106             return "unrecognized";
4107     }
4108 }
4109 
4110 struct debug_buffer
4111 {
4112     char str[200]; /* wine_dbg_sprintf() limits string size to 200 */
4113     char *ptr;
4114     int size;
4115 };
4116 
4117 static void init_debug_buffer(struct debug_buffer *buffer, const char *default_string)
4118 {
4119     strcpy(buffer->str, default_string);
4120     buffer->ptr = buffer->str;
4121     buffer->size = ARRAY_SIZE(buffer->str);
4122 }
4123 
4124 static void debug_append(struct debug_buffer *buffer, const char *str, const char *separator)
4125 {
4126     int size;
4127 
4128     if (!separator || buffer->ptr == buffer->str)
4129         separator = "";
4130     size = snprintf(buffer->ptr, buffer->size, "%s%s", separator, str);
4131     if (size == -1 || size >= buffer->size)
4132     {
4133         buffer->size = 0;
4134         strcpy(&buffer->str[ARRAY_SIZE(buffer->str) - 4], "...");
4135         return;
4136     }
4137 
4138     buffer->ptr += size;
4139     buffer->size -= size;
4140 }
4141 
4142 const char *wined3d_debug_resource_access(DWORD access)
4143 {
4144     struct debug_buffer buffer;
4145 
4146     init_debug_buffer(&buffer, "0");
4147 #define ACCESS_TO_STR(x) if (access & x) { debug_append(&buffer, #x, " | "); access &= ~x; }
4148     ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_GPU);
4149     ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_CPU);
4150     ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_MAP_R);
4151     ACCESS_TO_STR(WINED3D_RESOURCE_ACCESS_MAP_W);
4152 #undef ACCESS_TO_STR
4153     if (access)
4154         FIXME("Unrecognised access flag(s) %#x.\n", access);
4155 
4156     return wine_dbg_sprintf("%s", buffer.str);
4157 }
4158 
4159 const char *debug_d3dusage(DWORD usage)
4160 {
4161     struct debug_buffer buffer;
4162 
4163     init_debug_buffer(&buffer, "0");
4164 #define WINED3DUSAGE_TO_STR(x) if (usage & x) { debug_append(&buffer, #x, " | "); usage &= ~x; }
4165     WINED3DUSAGE_TO_STR(WINED3DUSAGE_RENDERTARGET);
4166     WINED3DUSAGE_TO_STR(WINED3DUSAGE_DEPTHSTENCIL);
4167     WINED3DUSAGE_TO_STR(WINED3DUSAGE_WRITEONLY);
4168     WINED3DUSAGE_TO_STR(WINED3DUSAGE_SOFTWAREPROCESSING);
4169     WINED3DUSAGE_TO_STR(WINED3DUSAGE_DONOTCLIP);
4170     WINED3DUSAGE_TO_STR(WINED3DUSAGE_POINTS);
4171     WINED3DUSAGE_TO_STR(WINED3DUSAGE_RTPATCHES);
4172     WINED3DUSAGE_TO_STR(WINED3DUSAGE_NPATCHES);
4173     WINED3DUSAGE_TO_STR(WINED3DUSAGE_DYNAMIC);
4174     WINED3DUSAGE_TO_STR(WINED3DUSAGE_RESTRICTED_CONTENT);
4175     WINED3DUSAGE_TO_STR(WINED3DUSAGE_RESTRICT_SHARED_RESOURCE_DRIVER);
4176     WINED3DUSAGE_TO_STR(WINED3DUSAGE_RESTRICT_SHARED_RESOURCE);
4177     WINED3DUSAGE_TO_STR(WINED3DUSAGE_DMAP);
4178     WINED3DUSAGE_TO_STR(WINED3DUSAGE_TEXTAPI);
4179     WINED3DUSAGE_TO_STR(WINED3DUSAGE_LEGACY_CUBEMAP);
4180     WINED3DUSAGE_TO_STR(WINED3DUSAGE_TEXTURE);
4181     WINED3DUSAGE_TO_STR(WINED3DUSAGE_OWNDC);
4182     WINED3DUSAGE_TO_STR(WINED3DUSAGE_STATICDECL);
4183     WINED3DUSAGE_TO_STR(WINED3DUSAGE_OVERLAY);
4184 #undef WINED3DUSAGE_TO_STR
4185     if (usage)
4186         FIXME("Unrecognized usage flag(s) %#x.\n", usage);
4187 
4188     return wine_dbg_sprintf("%s", buffer.str);
4189 }
4190 
4191 const char *debug_d3dusagequery(DWORD usage)
4192 {
4193     struct debug_buffer buffer;
4194 
4195     init_debug_buffer(&buffer, "0");
4196 #define WINED3DUSAGEQUERY_TO_STR(x) if (usage & x) { debug_append(&buffer, #x, " | "); usage &= ~x; }
4197     WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_FILTER);
4198     WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_GENMIPMAP);
4199     WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_LEGACYBUMPMAP);
4200     WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING);
4201     WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_SRGBREAD);
4202     WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_SRGBWRITE);
4203     WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_VERTEXTEXTURE);
4204     WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_WRAPANDMIP);
4205 #undef WINED3DUSAGEQUERY_TO_STR
4206     if (usage)
4207         FIXME("Unrecognized usage query flag(s) %#x.\n", usage);
4208 
4209     return wine_dbg_sprintf("%s", buffer.str);
4210 }
4211 
4212 const char *debug_d3ddeclmethod(enum wined3d_decl_method method)
4213 {
4214     switch (method)
4215     {
4216 #define WINED3DDECLMETHOD_TO_STR(u) case u: return #u
4217         WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_DEFAULT);
4218         WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_PARTIAL_U);
4219         WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_PARTIAL_V);
4220         WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_CROSS_UV);
4221         WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_UV);
4222         WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_LOOKUP);
4223         WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_LOOKUP_PRESAMPLED);
4224 #undef WINED3DDECLMETHOD_TO_STR
4225         default:
4226             FIXME("Unrecognized declaration method %#x.\n", method);
4227             return "unrecognized";
4228     }
4229 }
4230 
4231 const char *debug_d3ddeclusage(enum wined3d_decl_usage usage)
4232 {
4233     switch (usage)
4234     {
4235 #define WINED3DDECLUSAGE_TO_STR(u) case u: return #u
4236         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_POSITION);
4237         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BLEND_WEIGHT);
4238         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BLEND_INDICES);
4239         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_NORMAL);
4240         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_PSIZE);
4241         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TEXCOORD);
4242         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TANGENT);
4243         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BINORMAL);
4244         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TESS_FACTOR);
4245         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_POSITIONT);
4246         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_COLOR);
4247         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_FOG);
4248         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_DEPTH);
4249         WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_SAMPLE);
4250 #undef WINED3DDECLUSAGE_TO_STR
4251         default:
4252             FIXME("Unrecognized %u declaration usage!\n", usage);
4253             return "unrecognized";
4254     }
4255 }
4256 
4257 const char *debug_d3dinput_classification(enum wined3d_input_classification classification)
4258 {
4259     switch (classification)
4260     {
4261 #define WINED3D_TO_STR(x) case x: return #x
4262         WINED3D_TO_STR(WINED3D_INPUT_PER_VERTEX_DATA);
4263         WINED3D_TO_STR(WINED3D_INPUT_PER_INSTANCE_DATA);
4264 #undef WINED3D_TO_STR
4265         default:
4266             FIXME("Unrecognized input classification %#x.\n", classification);
4267             return "unrecognized";
4268     }
4269 }
4270 
4271 const char *debug_d3dresourcetype(enum wined3d_resource_type resource_type)
4272 {
4273     switch (resource_type)
4274     {
4275 #define WINED3D_TO_STR(x) case x: return #x
4276         WINED3D_TO_STR(WINED3D_RTYPE_NONE);
4277         WINED3D_TO_STR(WINED3D_RTYPE_BUFFER);
4278         WINED3D_TO_STR(WINED3D_RTYPE_TEXTURE_1D);
4279         WINED3D_TO_STR(WINED3D_RTYPE_TEXTURE_2D);
4280         WINED3D_TO_STR(WINED3D_RTYPE_TEXTURE_3D);
4281 #undef WINED3D_TO_STR
4282         default:
4283             FIXME("Unrecognized resource type %#x.\n", resource_type);
4284             return "unrecognized";
4285     }
4286 }
4287 
4288 const char *debug_d3dprimitivetype(enum wined3d_primitive_type primitive_type)
4289 {
4290     switch (primitive_type)
4291     {
4292 #define PRIM_TO_STR(prim) case prim: return #prim
4293         PRIM_TO_STR(WINED3D_PT_UNDEFINED);
4294         PRIM_TO_STR(WINED3D_PT_POINTLIST);
4295         PRIM_TO_STR(WINED3D_PT_LINELIST);
4296         PRIM_TO_STR(WINED3D_PT_LINESTRIP);
4297         PRIM_TO_STR(WINED3D_PT_TRIANGLELIST);
4298         PRIM_TO_STR(WINED3D_PT_TRIANGLESTRIP);
4299         PRIM_TO_STR(WINED3D_PT_TRIANGLEFAN);
4300         PRIM_TO_STR(WINED3D_PT_LINELIST_ADJ);
4301         PRIM_TO_STR(WINED3D_PT_LINESTRIP_ADJ);
4302         PRIM_TO_STR(WINED3D_PT_TRIANGLELIST_ADJ);
4303         PRIM_TO_STR(WINED3D_PT_TRIANGLESTRIP_ADJ);
4304         PRIM_TO_STR(WINED3D_PT_PATCH);
4305 #undef  PRIM_TO_STR
4306         default:
4307             FIXME("Unrecognized primitive type %#x.\n", primitive_type);
4308             return "unrecognized";
4309     }
4310 }
4311 
4312 const char *debug_d3drenderstate(enum wined3d_render_state state)
4313 {
4314     switch (state)
4315     {
4316 #define D3DSTATE_TO_STR(u) case u: return #u
4317         D3DSTATE_TO_STR(WINED3D_RS_ANTIALIAS);
4318         D3DSTATE_TO_STR(WINED3D_RS_TEXTUREPERSPECTIVE);
4319         D3DSTATE_TO_STR(WINED3D_RS_WRAPU);
4320         D3DSTATE_TO_STR(WINED3D_RS_WRAPV);
4321         D3DSTATE_TO_STR(WINED3D_RS_ZENABLE);
4322         D3DSTATE_TO_STR(WINED3D_RS_FILLMODE);
4323         D3DSTATE_TO_STR(WINED3D_RS_SHADEMODE);
4324         D3DSTATE_TO_STR(WINED3D_RS_LINEPATTERN);
4325         D3DSTATE_TO_STR(WINED3D_RS_MONOENABLE);
4326         D3DSTATE_TO_STR(WINED3D_RS_ROP2);
4327         D3DSTATE_TO_STR(WINED3D_RS_PLANEMASK);
4328         D3DSTATE_TO_STR(WINED3D_RS_ZWRITEENABLE);
4329         D3DSTATE_TO_STR(WINED3D_RS_ALPHATESTENABLE);
4330         D3DSTATE_TO_STR(WINED3D_RS_LASTPIXEL);
4331         D3DSTATE_TO_STR(WINED3D_RS_SRCBLEND);
4332         D3DSTATE_TO_STR(WINED3D_RS_DESTBLEND);
4333         D3DSTATE_TO_STR(WINED3D_RS_CULLMODE);
4334         D3DSTATE_TO_STR(WINED3D_RS_ZFUNC);
4335         D3DSTATE_TO_STR(WINED3D_RS_ALPHAREF);
4336         D3DSTATE_TO_STR(WINED3D_RS_ALPHAFUNC);
4337         D3DSTATE_TO_STR(WINED3D_RS_DITHERENABLE);
4338         D3DSTATE_TO_STR(WINED3D_RS_ALPHABLENDENABLE);
4339         D3DSTATE_TO_STR(WINED3D_RS_FOGENABLE);
4340         D3DSTATE_TO_STR(WINED3D_RS_SPECULARENABLE);
4341         D3DSTATE_TO_STR(WINED3D_RS_ZVISIBLE);
4342         D3DSTATE_TO_STR(WINED3D_RS_SUBPIXEL);
4343         D3DSTATE_TO_STR(WINED3D_RS_SUBPIXELX);
4344         D3DSTATE_TO_STR(WINED3D_RS_STIPPLEDALPHA);
4345         D3DSTATE_TO_STR(WINED3D_RS_FOGCOLOR);
4346         D3DSTATE_TO_STR(WINED3D_RS_FOGTABLEMODE);
4347         D3DSTATE_TO_STR(WINED3D_RS_FOGSTART);
4348         D3DSTATE_TO_STR(WINED3D_RS_FOGEND);
4349         D3DSTATE_TO_STR(WINED3D_RS_FOGDENSITY);
4350         D3DSTATE_TO_STR(WINED3D_RS_STIPPLEENABLE);
4351         D3DSTATE_TO_STR(WINED3D_RS_EDGEANTIALIAS);
4352         D3DSTATE_TO_STR(WINED3D_RS_COLORKEYENABLE);
4353         D3DSTATE_TO_STR(WINED3D_RS_MIPMAPLODBIAS);
4354         D3DSTATE_TO_STR(WINED3D_RS_RANGEFOGENABLE);
4355         D3DSTATE_TO_STR(WINED3D_RS_ANISOTROPY);
4356         D3DSTATE_TO_STR(WINED3D_RS_FLUSHBATCH);
4357         D3DSTATE_TO_STR(WINED3D_RS_TRANSLUCENTSORTINDEPENDENT);
4358         D3DSTATE_TO_STR(WINED3D_RS_STENCILENABLE);
4359         D3DSTATE_TO_STR(WINED3D_RS_STENCILFAIL);
4360         D3DSTATE_TO_STR(WINED3D_RS_STENCILZFAIL);
4361         D3DSTATE_TO_STR(WINED3D_RS_STENCILPASS);
4362         D3DSTATE_TO_STR(WINED3D_RS_STENCILFUNC);
4363         D3DSTATE_TO_STR(WINED3D_RS_STENCILREF);
4364         D3DSTATE_TO_STR(WINED3D_RS_STENCILMASK);
4365         D3DSTATE_TO_STR(WINED3D_RS_STENCILWRITEMASK);
4366         D3DSTATE_TO_STR(WINED3D_RS_TEXTUREFACTOR);
4367         D3DSTATE_TO_STR(WINED3D_RS_WRAP0);
4368         D3DSTATE_TO_STR(WINED3D_RS_WRAP1);
4369         D3DSTATE_TO_STR(WINED3D_RS_WRAP2);
4370         D3DSTATE_TO_STR(WINED3D_RS_WRAP3);
4371         D3DSTATE_TO_STR(WINED3D_RS_WRAP4);
4372         D3DSTATE_TO_STR(WINED3D_RS_WRAP5);
4373         D3DSTATE_TO_STR(WINED3D_RS_WRAP6);
4374         D3DSTATE_TO_STR(WINED3D_RS_WRAP7);
4375         D3DSTATE_TO_STR(WINED3D_RS_CLIPPING);
4376         D3DSTATE_TO_STR(WINED3D_RS_LIGHTING);
4377         D3DSTATE_TO_STR(WINED3D_RS_EXTENTS);
4378         D3DSTATE_TO_STR(WINED3D_RS_AMBIENT);
4379         D3DSTATE_TO_STR(WINED3D_RS_FOGVERTEXMODE);
4380         D3DSTATE_TO_STR(WINED3D_RS_COLORVERTEX);
4381         D3DSTATE_TO_STR(WINED3D_RS_LOCALVIEWER);
4382         D3DSTATE_TO_STR(WINED3D_RS_NORMALIZENORMALS);
4383         D3DSTATE_TO_STR(WINED3D_RS_COLORKEYBLENDENABLE);
4384         D3DSTATE_TO_STR(WINED3D_RS_DIFFUSEMATERIALSOURCE);
4385         D3DSTATE_TO_STR(WINED3D_RS_SPECULARMATERIALSOURCE);
4386         D3DSTATE_TO_STR(WINED3D_RS_AMBIENTMATERIALSOURCE);
4387         D3DSTATE_TO_STR(WINED3D_RS_EMISSIVEMATERIALSOURCE);
4388         D3DSTATE_TO_STR(WINED3D_RS_VERTEXBLEND);
4389         D3DSTATE_TO_STR(WINED3D_RS_CLIPPLANEENABLE);
4390         D3DSTATE_TO_STR(WINED3D_RS_SOFTWAREVERTEXPROCESSING);
4391         D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE);
4392         D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE_MIN);
4393         D3DSTATE_TO_STR(WINED3D_RS_POINTSPRITEENABLE);
4394         D3DSTATE_TO_STR(WINED3D_RS_POINTSCALEENABLE);
4395         D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_A);
4396         D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_B);
4397         D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_C);
4398         D3DSTATE_TO_STR(WINED3D_RS_MULTISAMPLEANTIALIAS);
4399         D3DSTATE_TO_STR(WINED3D_RS_MULTISAMPLEMASK);
4400         D3DSTATE_TO_STR(WINED3D_RS_PATCHEDGESTYLE);
4401         D3DSTATE_TO_STR(WINED3D_RS_PATCHSEGMENTS);
4402         D3DSTATE_TO_STR(WINED3D_RS_DEBUGMONITORTOKEN);
4403         D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE_MAX);
4404         D3DSTATE_TO_STR(WINED3D_RS_INDEXEDVERTEXBLENDENABLE);
4405         D3DSTATE_TO_STR(WINED3D_RS_TWEENFACTOR);
4406         D3DSTATE_TO_STR(WINED3D_RS_BLENDOP);
4407         D3DSTATE_TO_STR(WINED3D_RS_POSITIONDEGREE);
4408         D3DSTATE_TO_STR(WINED3D_RS_NORMALDEGREE);
4409         D3DSTATE_TO_STR(WINED3D_RS_SCISSORTESTENABLE);
4410         D3DSTATE_TO_STR(WINED3D_RS_SLOPESCALEDEPTHBIAS);
4411         D3DSTATE_TO_STR(WINED3D_RS_ANTIALIASEDLINEENABLE);
4412         D3DSTATE_TO_STR(WINED3D_RS_MINTESSELLATIONLEVEL);
4413         D3DSTATE_TO_STR(WINED3D_RS_MAXTESSELLATIONLEVEL);
4414         D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_X);
4415         D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_Y);
4416         D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_Z);
4417         D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_W);
4418         D3DSTATE_TO_STR(WINED3D_RS_ENABLEADAPTIVETESSELLATION);
4419         D3DSTATE_TO_STR(WINED3D_RS_TWOSIDEDSTENCILMODE);
4420         D3DSTATE_TO_STR(WINED3D_RS_BACK_STENCILFAIL);
4421         D3DSTATE_TO_STR(WINED3D_RS_BACK_STENCILZFAIL);
4422         D3DSTATE_TO_STR(WINED3D_RS_BACK_STENCILPASS);
4423         D3DSTATE_TO_STR(WINED3D_RS_BACK_STENCILFUNC);
4424         D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE);
4425         D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE1);
4426         D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE2);
4427         D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE3);
4428         D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE4);
4429         D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE5);
4430         D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE6);
4431         D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE7);
4432         D3DSTATE_TO_STR(WINED3D_RS_BLENDFACTOR);
4433         D3DSTATE_TO_STR(WINED3D_RS_SRGBWRITEENABLE);
4434         D3DSTATE_TO_STR(WINED3D_RS_DEPTHBIAS);
4435         D3DSTATE_TO_STR(WINED3D_RS_DEPTHBIASCLAMP);
4436         D3DSTATE_TO_STR(WINED3D_RS_WRAP8);
4437         D3DSTATE_TO_STR(WINED3D_RS_WRAP9);
4438         D3DSTATE_TO_STR(WINED3D_RS_WRAP10);
4439         D3DSTATE_TO_STR(WINED3D_RS_WRAP11);
4440         D3DSTATE_TO_STR(WINED3D_RS_WRAP12);
4441         D3DSTATE_TO_STR(WINED3D_RS_WRAP13);
4442         D3DSTATE_TO_STR(WINED3D_RS_WRAP14);
4443         D3DSTATE_TO_STR(WINED3D_RS_WRAP15);
4444         D3DSTATE_TO_STR(WINED3D_RS_SEPARATEALPHABLENDENABLE);
4445         D3DSTATE_TO_STR(WINED3D_RS_SRCBLENDALPHA);
4446         D3DSTATE_TO_STR(WINED3D_RS_DESTBLENDALPHA);
4447         D3DSTATE_TO_STR(WINED3D_RS_BLENDOPALPHA);
4448 #undef D3DSTATE_TO_STR
4449         default:
4450             FIXME("Unrecognized %u render state!\n", state);
4451             return "unrecognized";
4452     }
4453 }
4454 
4455 const char *debug_d3dsamplerstate(enum wined3d_sampler_state state)
4456 {
4457     switch (state)
4458     {
4459 #define D3DSTATE_TO_STR(u) case u: return #u
4460         D3DSTATE_TO_STR(WINED3D_SAMP_BORDER_COLOR);
4461         D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_U);
4462         D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_V);
4463         D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_W);
4464         D3DSTATE_TO_STR(WINED3D_SAMP_MAG_FILTER);
4465         D3DSTATE_TO_STR(WINED3D_SAMP_MIN_FILTER);
4466         D3DSTATE_TO_STR(WINED3D_SAMP_MIP_FILTER);
4467         D3DSTATE_TO_STR(WINED3D_SAMP_MIPMAP_LOD_BIAS);
4468         D3DSTATE_TO_STR(WINED3D_SAMP_MAX_MIP_LEVEL);
4469         D3DSTATE_TO_STR(WINED3D_SAMP_MAX_ANISOTROPY);
4470         D3DSTATE_TO_STR(WINED3D_SAMP_SRGB_TEXTURE);
4471         D3DSTATE_TO_STR(WINED3D_SAMP_ELEMENT_INDEX);
4472         D3DSTATE_TO_STR(WINED3D_SAMP_DMAP_OFFSET);
4473 #undef D3DSTATE_TO_STR
4474         default:
4475             FIXME("Unrecognized %u sampler state!\n", state);
4476             return "unrecognized";
4477     }
4478 }
4479 
4480 const char *debug_d3dtexturefiltertype(enum wined3d_texture_filter_type filter_type)
4481 {
4482     switch (filter_type)
4483     {
4484 #define D3DTEXTUREFILTERTYPE_TO_STR(u) case u: return #u
4485         D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_NONE);
4486         D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_POINT);
4487         D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_LINEAR);
4488         D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_ANISOTROPIC);
4489         D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_FLAT_CUBIC);
4490         D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_GAUSSIAN_CUBIC);
4491         D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_PYRAMIDAL_QUAD);
4492         D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_GAUSSIAN_QUAD);
4493 #undef D3DTEXTUREFILTERTYPE_TO_STR
4494         default:
4495             FIXME("Unrecognized texture filter type 0x%08x.\n", filter_type);
4496             return "unrecognized";
4497     }
4498 }
4499 
4500 const char *debug_d3dtexturestate(enum wined3d_texture_stage_state state)
4501 {
4502     switch (state)
4503     {
4504 #define D3DSTATE_TO_STR(u) case u: return #u
4505         D3DSTATE_TO_STR(WINED3D_TSS_COLOR_OP);
4506         D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG1);
4507         D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG2);
4508         D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_OP);
4509         D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG1);
4510         D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG2);
4511         D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT00);
4512         D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT01);
4513         D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT10);
4514         D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT11);
4515         D3DSTATE_TO_STR(WINED3D_TSS_TEXCOORD_INDEX);
4516         D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_LSCALE);
4517         D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_LOFFSET);
4518         D3DSTATE_TO_STR(WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS);
4519         D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG0);
4520         D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG0);
4521         D3DSTATE_TO_STR(WINED3D_TSS_RESULT_ARG);
4522         D3DSTATE_TO_STR(WINED3D_TSS_CONSTANT);
4523 #undef D3DSTATE_TO_STR
4524         default:
4525             FIXME("Unrecognized %u texture state!\n", state);
4526             return "unrecognized";
4527     }
4528 }
4529 
4530 const char *debug_d3dtop(enum wined3d_texture_op d3dtop)
4531 {
4532     switch (d3dtop)
4533     {
4534 #define D3DTOP_TO_STR(u) case u: return #u
4535         D3DTOP_TO_STR(WINED3D_TOP_DISABLE);
4536         D3DTOP_TO_STR(WINED3D_TOP_SELECT_ARG1);
4537         D3DTOP_TO_STR(WINED3D_TOP_SELECT_ARG2);
4538         D3DTOP_TO_STR(WINED3D_TOP_MODULATE);
4539         D3DTOP_TO_STR(WINED3D_TOP_MODULATE_2X);
4540         D3DTOP_TO_STR(WINED3D_TOP_MODULATE_4X);
4541         D3DTOP_TO_STR(WINED3D_TOP_ADD);
4542         D3DTOP_TO_STR(WINED3D_TOP_ADD_SIGNED);
4543         D3DTOP_TO_STR(WINED3D_TOP_ADD_SIGNED_2X);
4544         D3DTOP_TO_STR(WINED3D_TOP_SUBTRACT);
4545         D3DTOP_TO_STR(WINED3D_TOP_ADD_SMOOTH);
4546         D3DTOP_TO_STR(WINED3D_TOP_BLEND_DIFFUSE_ALPHA);
4547         D3DTOP_TO_STR(WINED3D_TOP_BLEND_TEXTURE_ALPHA);
4548         D3DTOP_TO_STR(WINED3D_TOP_BLEND_FACTOR_ALPHA);
4549         D3DTOP_TO_STR(WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM);
4550         D3DTOP_TO_STR(WINED3D_TOP_BLEND_CURRENT_ALPHA);
4551         D3DTOP_TO_STR(WINED3D_TOP_PREMODULATE);
4552         D3DTOP_TO_STR(WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR);
4553         D3DTOP_TO_STR(WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA);
4554         D3DTOP_TO_STR(WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR);
4555         D3DTOP_TO_STR(WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA);
4556         D3DTOP_TO_STR(WINED3D_TOP_BUMPENVMAP);
4557         D3DTOP_TO_STR(WINED3D_TOP_BUMPENVMAP_LUMINANCE);
4558         D3DTOP_TO_STR(WINED3D_TOP_DOTPRODUCT3);
4559         D3DTOP_TO_STR(WINED3D_TOP_MULTIPLY_ADD);
4560         D3DTOP_TO_STR(WINED3D_TOP_LERP);
4561 #undef D3DTOP_TO_STR
4562         default:
4563             FIXME("Unrecognized texture op %#x.\n", d3dtop);
4564             return "unrecognized";
4565     }
4566 }
4567 
4568 const char *debug_d3dtstype(enum wined3d_transform_state tstype)
4569 {
4570     switch (tstype)
4571     {
4572 #define TSTYPE_TO_STR(tstype) case tstype: return #tstype
4573     TSTYPE_TO_STR(WINED3D_TS_VIEW);
4574     TSTYPE_TO_STR(WINED3D_TS_PROJECTION);
4575     TSTYPE_TO_STR(WINED3D_TS_TEXTURE0);
4576     TSTYPE_TO_STR(WINED3D_TS_TEXTURE1);
4577     TSTYPE_TO_STR(WINED3D_TS_TEXTURE2);
4578     TSTYPE_TO_STR(WINED3D_TS_TEXTURE3);
4579     TSTYPE_TO_STR(WINED3D_TS_TEXTURE4);
4580     TSTYPE_TO_STR(WINED3D_TS_TEXTURE5);
4581     TSTYPE_TO_STR(WINED3D_TS_TEXTURE6);
4582     TSTYPE_TO_STR(WINED3D_TS_TEXTURE7);
4583     TSTYPE_TO_STR(WINED3D_TS_WORLD_MATRIX(0));
4584     TSTYPE_TO_STR(WINED3D_TS_WORLD_MATRIX(1));
4585     TSTYPE_TO_STR(WINED3D_TS_WORLD_MATRIX(2));
4586     TSTYPE_TO_STR(WINED3D_TS_WORLD_MATRIX(3));
4587 #undef TSTYPE_TO_STR
4588     default:
4589         if (tstype > 256 && tstype < 512)
4590         {
4591             FIXME("WINED3D_TS_WORLD_MATRIX(%u). 1..255 not currently supported.\n", tstype);
4592             return ("WINED3D_TS_WORLD_MATRIX > 0");
4593         }
4594         FIXME("Unrecognized transform state %#x.\n", tstype);
4595         return "unrecognized";
4596     }
4597 }
4598 
4599 const char *debug_shader_type(enum wined3d_shader_type type)
4600 {
4601     switch(type)
4602     {
4603 #define WINED3D_TO_STR(type) case type: return #type
4604         WINED3D_TO_STR(WINED3D_SHADER_TYPE_PIXEL);
4605         WINED3D_TO_STR(WINED3D_SHADER_TYPE_VERTEX);
4606         WINED3D_TO_STR(WINED3D_SHADER_TYPE_GEOMETRY);
4607         WINED3D_TO_STR(WINED3D_SHADER_TYPE_HULL);
4608         WINED3D_TO_STR(WINED3D_SHADER_TYPE_DOMAIN);
4609         WINED3D_TO_STR(WINED3D_SHADER_TYPE_COMPUTE);
4610 #undef WINED3D_TO_STR
4611         default:
4612             FIXME("Unrecognized shader type %#x.\n", type);
4613             return "unrecognized";
4614     }
4615 }
4616 
4617 const char *debug_d3dstate(DWORD state)
4618 {
4619     if (STATE_IS_RENDER(state))
4620         return wine_dbg_sprintf("STATE_RENDER(%s)", debug_d3drenderstate(state - STATE_RENDER(0)));
4621     if (STATE_IS_TEXTURESTAGE(state))
4622     {
4623         DWORD texture_stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
4624         DWORD texture_state = state - STATE_TEXTURESTAGE(texture_stage, 0);
4625         return wine_dbg_sprintf("STATE_TEXTURESTAGE(%#x, %s)",
4626                 texture_stage, debug_d3dtexturestate(texture_state));
4627     }
4628     if (STATE_IS_SAMPLER(state))
4629         return wine_dbg_sprintf("STATE_SAMPLER(%#x)", state - STATE_SAMPLER(0));
4630     if (STATE_IS_COMPUTE_SHADER(state))
4631         return wine_dbg_sprintf("STATE_SHADER(%s)", debug_shader_type(WINED3D_SHADER_TYPE_COMPUTE));
4632     if (STATE_IS_GRAPHICS_SHADER(state))
4633         return wine_dbg_sprintf("STATE_SHADER(%s)", debug_shader_type(state - STATE_SHADER(0)));
4634     if (STATE_IS_COMPUTE_CONSTANT_BUFFER(state))
4635         return wine_dbg_sprintf("STATE_CONSTANT_BUFFER(%s)", debug_shader_type(WINED3D_SHADER_TYPE_COMPUTE));
4636     if (STATE_IS_GRAPHICS_CONSTANT_BUFFER(state))
4637         return wine_dbg_sprintf("STATE_CONSTANT_BUFFER(%s)", debug_shader_type(state - STATE_CONSTANT_BUFFER(0)));
4638     if (STATE_IS_COMPUTE_SHADER_RESOURCE_BINDING(state))
4639         return "STATE_COMPUTE_SHADER_RESOURCE_BINDING";
4640     if (STATE_IS_GRAPHICS_SHADER_RESOURCE_BINDING(state))
4641         return "STATE_GRAPHICS_SHADER_RESOURCE_BINDING";
4642     if (STATE_IS_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING(state))
4643         return "STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING";
4644     if (STATE_IS_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING(state))
4645         return "STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING";
4646     if (STATE_IS_TRANSFORM(state))
4647         return wine_dbg_sprintf("STATE_TRANSFORM(%s)", debug_d3dtstype(state - STATE_TRANSFORM(0)));
4648     if (STATE_IS_STREAMSRC(state))
4649         return "STATE_STREAMSRC";
4650     if (STATE_IS_INDEXBUFFER(state))
4651         return "STATE_INDEXBUFFER";
4652     if (STATE_IS_VDECL(state))
4653         return "STATE_VDECL";
4654     if (STATE_IS_VIEWPORT(state))
4655         return "STATE_VIEWPORT";
4656     if (STATE_IS_LIGHT_TYPE(state))
4657         return "STATE_LIGHT_TYPE";
4658     if (STATE_IS_ACTIVELIGHT(state))
4659         return wine_dbg_sprintf("STATE_ACTIVELIGHT(%#x)", state - STATE_ACTIVELIGHT(0));
4660     if (STATE_IS_SCISSORRECT(state))
4661         return "STATE_SCISSORRECT";
4662     if (STATE_IS_CLIPPLANE(state))
4663         return wine_dbg_sprintf("STATE_CLIPPLANE(%#x)", state - STATE_CLIPPLANE(0));
4664     if (STATE_IS_MATERIAL(state))
4665         return "STATE_MATERIAL";
4666     if (STATE_IS_RASTERIZER(state))
4667         return "STATE_RASTERIZER";
4668     if (STATE_IS_POINTSPRITECOORDORIGIN(state))
4669         return "STATE_POINTSPRITECOORDORIGIN";
4670     if (STATE_IS_BASEVERTEXINDEX(state))
4671         return "STATE_BASEVERTEXINDEX";
4672     if (STATE_IS_FRAMEBUFFER(state))
4673         return "STATE_FRAMEBUFFER";
4674     if (STATE_IS_POINT_ENABLE(state))
4675         return "STATE_POINT_ENABLE";
4676     if (STATE_IS_COLOR_KEY(state))
4677         return "STATE_COLOR_KEY";
4678     if (STATE_IS_STREAM_OUTPUT(state))
4679         return "STATE_STREAM_OUTPUT";
4680     if (STATE_IS_BLEND(state))
4681         return "STATE_BLEND";
4682 
4683     return wine_dbg_sprintf("UNKNOWN_STATE(%#x)", state);
4684 }
4685 
4686 const char *debug_fboattachment(GLenum attachment)
4687 {
4688     switch(attachment)
4689     {
4690 #define WINED3D_TO_STR(x) case x: return #x
4691         WINED3D_TO_STR(GL_COLOR_ATTACHMENT0);
4692         WINED3D_TO_STR(GL_COLOR_ATTACHMENT1);
4693         WINED3D_TO_STR(GL_COLOR_ATTACHMENT2);
4694         WINED3D_TO_STR(GL_COLOR_ATTACHMENT3);
4695         WINED3D_TO_STR(GL_COLOR_ATTACHMENT4);
4696         WINED3D_TO_STR(GL_COLOR_ATTACHMENT5);
4697         WINED3D_TO_STR(GL_COLOR_ATTACHMENT6);
4698         WINED3D_TO_STR(GL_COLOR_ATTACHMENT7);
4699         WINED3D_TO_STR(GL_COLOR_ATTACHMENT8);
4700         WINED3D_TO_STR(GL_COLOR_ATTACHMENT9);
4701         WINED3D_TO_STR(GL_COLOR_ATTACHMENT10);
4702         WINED3D_TO_STR(GL_COLOR_ATTACHMENT11);
4703         WINED3D_TO_STR(GL_COLOR_ATTACHMENT12);
4704         WINED3D_TO_STR(GL_COLOR_ATTACHMENT13);
4705         WINED3D_TO_STR(GL_COLOR_ATTACHMENT14);
4706         WINED3D_TO_STR(GL_COLOR_ATTACHMENT15);
4707         WINED3D_TO_STR(GL_DEPTH_ATTACHMENT);
4708         WINED3D_TO_STR(GL_STENCIL_ATTACHMENT);
4709 #undef WINED3D_TO_STR
4710         default:
4711             return wine_dbg_sprintf("Unknown FBO attachment %#x", attachment);
4712     }
4713 }
4714 
4715 const char *debug_fbostatus(GLenum status) {
4716     switch(status) {
4717 #define FBOSTATUS_TO_STR(u) case u: return #u
4718         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_COMPLETE);
4719         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
4720         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
4721         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT);
4722         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT);
4723         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER);
4724         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER);
4725         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
4726         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS);
4727         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_LAYER_COUNT_ARB);
4728         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_UNSUPPORTED);
4729         FBOSTATUS_TO_STR(GL_FRAMEBUFFER_UNDEFINED);
4730 #undef FBOSTATUS_TO_STR
4731         default:
4732             FIXME("Unrecognized FBO status 0x%08x.\n", status);
4733             return "unrecognized";
4734     }
4735 }
4736 
4737 const char *debug_glerror(GLenum error) {
4738     switch(error) {
4739 #define GLERROR_TO_STR(u) case u: return #u
4740         GLERROR_TO_STR(GL_NO_ERROR);
4741         GLERROR_TO_STR(GL_INVALID_ENUM);
4742         GLERROR_TO_STR(GL_INVALID_VALUE);
4743         GLERROR_TO_STR(GL_INVALID_OPERATION);
4744         GLERROR_TO_STR(GL_STACK_OVERFLOW);
4745         GLERROR_TO_STR(GL_STACK_UNDERFLOW);
4746         GLERROR_TO_STR(GL_OUT_OF_MEMORY);
4747         GLERROR_TO_STR(GL_INVALID_FRAMEBUFFER_OPERATION);
4748 #undef GLERROR_TO_STR
4749         default:
4750             FIXME("Unrecognized GL error 0x%08x.\n", error);
4751             return "unrecognized";
4752     }
4753 }
4754 
4755 static const char *debug_fixup_channel_source(enum fixup_channel_source source)
4756 {
4757     switch(source)
4758     {
4759 #define WINED3D_TO_STR(x) case x: return #x
4760         WINED3D_TO_STR(CHANNEL_SOURCE_ZERO);
4761         WINED3D_TO_STR(CHANNEL_SOURCE_ONE);
4762         WINED3D_TO_STR(CHANNEL_SOURCE_X);
4763         WINED3D_TO_STR(CHANNEL_SOURCE_Y);
4764         WINED3D_TO_STR(CHANNEL_SOURCE_Z);
4765         WINED3D_TO_STR(CHANNEL_SOURCE_W);
4766         WINED3D_TO_STR(CHANNEL_SOURCE_COMPLEX0);
4767         WINED3D_TO_STR(CHANNEL_SOURCE_COMPLEX1);
4768 #undef WINED3D_TO_STR
4769         default:
4770             FIXME("Unrecognized fixup_channel_source %#x\n", source);
4771             return "unrecognized";
4772     }
4773 }
4774 
4775 static const char *debug_complex_fixup(enum complex_fixup fixup)
4776 {
4777     switch(fixup)
4778     {
4779 #define WINED3D_TO_STR(x) case x: return #x
4780         WINED3D_TO_STR(COMPLEX_FIXUP_YUY2);
4781         WINED3D_TO_STR(COMPLEX_FIXUP_UYVY);
4782         WINED3D_TO_STR(COMPLEX_FIXUP_YV12);
4783         WINED3D_TO_STR(COMPLEX_FIXUP_NV12);
4784         WINED3D_TO_STR(COMPLEX_FIXUP_P8);
4785 #undef WINED3D_TO_STR
4786         default:
4787             FIXME("Unrecognized complex fixup %#x\n", fixup);
4788             return "unrecognized";
4789     }
4790 }
4791 
4792 void dump_color_fixup_desc(struct color_fixup_desc fixup)
4793 {
4794     if (is_complex_fixup(fixup))
4795     {
4796         TRACE("\tComplex: %s\n", debug_complex_fixup(get_complex_fixup(fixup)));
4797         return;
4798     }
4799 
4800     TRACE("\tX: %s%s\n", debug_fixup_channel_source(fixup.x_source), fixup.x_sign_fixup ? ", SIGN_FIXUP" : "");
4801     TRACE("\tY: %s%s\n", debug_fixup_channel_source(fixup.y_source), fixup.y_sign_fixup ? ", SIGN_FIXUP" : "");
4802     TRACE("\tZ: %s%s\n", debug_fixup_channel_source(fixup.z_source), fixup.z_sign_fixup ? ", SIGN_FIXUP" : "");
4803     TRACE("\tW: %s%s\n", debug_fixup_channel_source(fixup.w_source), fixup.w_sign_fixup ? ", SIGN_FIXUP" : "");
4804 }
4805 
4806 BOOL is_invalid_op(const struct wined3d_state *state, int stage,
4807         enum wined3d_texture_op op, DWORD arg1, DWORD arg2, DWORD arg3)
4808 {
4809     if (op == WINED3D_TOP_DISABLE)
4810         return FALSE;
4811     if (state->textures[stage])
4812         return FALSE;
4813 
4814     if ((arg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
4815             && op != WINED3D_TOP_SELECT_ARG2)
4816         return TRUE;
4817     if ((arg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
4818             && op != WINED3D_TOP_SELECT_ARG1)
4819         return TRUE;
4820     if ((arg3 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
4821             && (op == WINED3D_TOP_MULTIPLY_ADD || op == WINED3D_TOP_LERP))
4822         return TRUE;
4823 
4824     return FALSE;
4825 }
4826 
4827 void get_identity_matrix(struct wined3d_matrix *mat)
4828 {
4829     static const struct wined3d_matrix identity =
4830     {
4831         1.0f, 0.0f, 0.0f, 0.0f,
4832         0.0f, 1.0f, 0.0f, 0.0f,
4833         0.0f, 0.0f, 1.0f, 0.0f,
4834         0.0f, 0.0f, 0.0f, 1.0f,
4835     };
4836 
4837     *mat = identity;
4838 }
4839 
4840 void get_modelview_matrix(const struct wined3d_context *context, const struct wined3d_state *state,
4841         unsigned int index, struct wined3d_matrix *mat)
4842 {
4843     if (context->last_was_rhw)
4844         get_identity_matrix(mat);
4845     else
4846         multiply_matrix(mat, &state->transforms[WINED3D_TS_VIEW], &state->transforms[WINED3D_TS_WORLD_MATRIX(index)]);
4847 }
4848 
4849 void get_projection_matrix(const struct wined3d_context *context, const struct wined3d_state *state,
4850         struct wined3d_matrix *mat)
4851 {
4852     BOOL clip_control = context->gl_info->supported[ARB_CLIP_CONTROL];
4853     BOOL flip = !clip_control && context->render_offscreen;
4854     float center_offset;
4855 
4856     /* There are a couple of additional things we have to take into account
4857      * here besides the projection transformation itself:
4858      *   - We need to flip along the y-axis in case of offscreen rendering.
4859      *   - OpenGL Z range is {-Wc,...,Wc} while D3D Z range is {0,...,Wc}.
4860      *   - <= D3D9 coordinates refer to pixel centers while GL coordinates
4861      *     refer to pixel corners.
4862      *   - D3D has a top-left filling convention. We need to maintain this
4863      *     even after the y-flip mentioned above.
4864      * In order to handle the last two points, we translate by
4865      * (63.0 / 128.0) / VPw and (63.0 / 128.0) / VPh. This is equivalent to
4866      * translating slightly less than half a pixel. We want the difference to
4867      * be large enough that it doesn't get lost due to rounding inside the
4868      * driver, but small enough to prevent it from interfering with any
4869      * anti-aliasing. */
4870 
4871     if (!clip_control && context->d3d_info->wined3d_creation_flags & WINED3D_PIXEL_CENTER_INTEGER)
4872         center_offset = 63.0f / 64.0f;
4873     else
4874         center_offset = -1.0f / 64.0f;
4875 
4876     if (context->last_was_rhw)
4877     {
4878         /* Transform D3D RHW coordinates to OpenGL clip coordinates. */
4879         float x = state->viewports[0].x;
4880         float y = state->viewports[0].y;
4881         float w = state->viewports[0].width;
4882         float h = state->viewports[0].height;
4883         float x_scale = 2.0f / w;
4884         float x_offset = (center_offset - (2.0f * x) - w) / w;
4885         float y_scale = flip ? 2.0f / h : 2.0f / -h;
4886         float y_offset = flip
4887                 ? (center_offset - (2.0f * y) - h) / h
4888                 : (center_offset - (2.0f * y) - h) / -h;
4889         enum wined3d_depth_buffer_type zenable = state->fb->depth_stencil ?
4890                 state->render_states[WINED3D_RS_ZENABLE] : WINED3D_ZB_FALSE;
4891         float z_scale = zenable ? clip_control ? 1.0f : 2.0f : 0.0f;
4892         float z_offset = zenable ? clip_control ? 0.0f : -1.0f : 0.0f;
4893         const struct wined3d_matrix projection =
4894         {
4895              x_scale,     0.0f,      0.0f, 0.0f,
4896                 0.0f,  y_scale,      0.0f, 0.0f,
4897                 0.0f,     0.0f,   z_scale, 0.0f,
4898             x_offset, y_offset,  z_offset, 1.0f,
4899         };
4900 
4901         *mat = projection;
4902     }
4903     else
4904     {
4905         float y_scale = flip ? -1.0f : 1.0f;
4906         float x_offset = center_offset / state->viewports[0].width;
4907         float y_offset = flip
4908                 ? center_offset / state->viewports[0].height
4909                 : -center_offset / state->viewports[0].height;
4910         float z_scale = clip_control ? 1.0f : 2.0f;
4911         float z_offset = clip_control ? 0.0f : -1.0f;
4912         const struct wined3d_matrix projection =
4913         {
4914                 1.0f,     0.0f,     0.0f, 0.0f,
4915                 0.0f,  y_scale,     0.0f, 0.0f,
4916                 0.0f,     0.0f,  z_scale, 0.0f,
4917             x_offset, y_offset, z_offset, 1.0f,
4918         };
4919 
4920         multiply_matrix(mat, &projection, &state->transforms[WINED3D_TS_PROJECTION]);
4921     }
4922 }
4923 
4924 /* Setup this textures matrix according to the texture flags. */
4925 static void compute_texture_matrix(const struct wined3d_gl_info *gl_info, const struct wined3d_matrix *matrix,
4926         DWORD flags, BOOL calculated_coords, BOOL transformed, enum wined3d_format_id format_id,
4927         BOOL ffp_proj_control, struct wined3d_matrix *out_matrix)
4928 {
4929     struct wined3d_matrix mat;
4930 
4931     if (flags == WINED3D_TTFF_DISABLE || flags == WINED3D_TTFF_COUNT1 || transformed)
4932     {
4933         get_identity_matrix(out_matrix);
4934         return;
4935     }
4936 
4937     if (flags == (WINED3D_TTFF_COUNT1 | WINED3D_TTFF_PROJECTED))
4938     {
4939         ERR("Invalid texture transform flags: WINED3D_TTFF_COUNT1 | WINED3D_TTFF_PROJECTED.\n");
4940         return;
4941     }
4942 
4943     mat = *matrix;
4944 
4945     if (flags & WINED3D_TTFF_PROJECTED)
4946     {
4947         if (!ffp_proj_control)
4948         {
4949             switch (flags & ~WINED3D_TTFF_PROJECTED)
4950             {
4951                 case WINED3D_TTFF_COUNT2:
4952                     mat._14 = mat._12;
4953                     mat._24 = mat._22;
4954                     mat._34 = mat._32;
4955                     mat._44 = mat._42;
4956                     mat._12 = mat._22 = mat._32 = mat._42 = 0.0f;
4957                     break;
4958                 case WINED3D_TTFF_COUNT3:
4959                     mat._14 = mat._13;
4960                     mat._24 = mat._23;
4961                     mat._34 = mat._33;
4962                     mat._44 = mat._43;
4963                     mat._13 = mat._23 = mat._33 = mat._43 = 0.0f;
4964                     break;
4965             }
4966         }
4967     }
4968     else
4969     {
4970         /* Under Direct3D the R/Z coord can be used for translation, under
4971          * OpenGL we use the Q coord instead. */
4972         if (!calculated_coords)
4973         {
4974             switch (format_id)
4975             {
4976                 /* Direct3D passes the default 1.0 in the 2nd coord, while GL
4977                  * passes it in the 4th. Swap 2nd and 4th coord. No need to
4978                  * store the value of mat._41 in mat._21 because the input
4979                  * value to the transformation will be 0, so the matrix value
4980                  * is irrelevant. */
4981                 case WINED3DFMT_R32_FLOAT:
4982                     mat._41 = mat._21;
4983                     mat._42 = mat._22;
4984                     mat._43 = mat._23;
4985                     mat._44 = mat._24;
4986                     break;
4987                 /* See above, just 3rd and 4th coord. */
4988                 case WINED3DFMT_R32G32_FLOAT:
4989                     mat._41 = mat._31;
4990                     mat._42 = mat._32;
4991                     mat._43 = mat._33;
4992                     mat._44 = mat._34;
4993                     break;
4994                 case WINED3DFMT_R32G32B32_FLOAT: /* Opengl defaults match dx defaults */
4995                 case WINED3DFMT_R32G32B32A32_FLOAT: /* No defaults apply, all app defined */
4996 
4997                 /* This is to prevent swapping the matrix lines and put the default 4th coord = 1.0
4998                  * into a bad place. The division elimination below will apply to make sure the
4999                  * 1.0 doesn't do anything bad. The caller will set this value if the stride is 0
5000                  */
5001                 case WINED3DFMT_UNKNOWN: /* No texture coords, 0/0/0/1 defaults are passed */
5002                     break;
5003                 default:
5004                     FIXME("Unexpected fixed function texture coord input\n");
5005             }
5006         }
5007         if (!ffp_proj_control)
5008         {
5009             switch (flags & ~WINED3D_TTFF_PROJECTED)
5010             {
5011                 /* case WINED3D_TTFF_COUNT1: Won't ever get here. */
5012                 case WINED3D_TTFF_COUNT2:
5013                     mat._13 = mat._23 = mat._33 = mat._43 = 0.0f;
5014                 /* OpenGL divides the first 3 vertex coordinates by the 4th by
5015                  * default, which is essentially the same as D3DTTFF_PROJECTED.
5016                  * Make sure that the 4th coordinate evaluates to 1.0 to
5017                  * eliminate that.
5018                  *
5019                  * If the fixed function pipeline is used, the 4th value
5020                  * remains unused, so there is no danger in doing this. With
5021                  * vertex shaders we have a problem. Should an application hit
5022                  * that problem, the code here would have to check for pixel
5023                  * shaders, and the shader has to undo the default GL divide.
5024                  *
5025                  * A more serious problem occurs if the application passes 4
5026                  * coordinates in, and the 4th is != 1.0 (OpenGL default).
5027                  * This would have to be fixed with immediate mode draws. */
5028                 default:
5029                     mat._14 = mat._24 = mat._34 = 0.0f; mat._44 = 1.0f;
5030             }
5031         }
5032     }
5033 
5034     *out_matrix = mat;
5035 }
5036 
5037 void get_texture_matrix(const struct wined3d_context *context, const struct wined3d_state *state,
5038         unsigned int tex, struct wined3d_matrix *mat)
5039 {
5040     const struct wined3d_device *device = context->device;
5041     const struct wined3d_gl_info *gl_info = context->gl_info;
5042     BOOL generated = (state->texture_states[tex][WINED3D_TSS_TEXCOORD_INDEX] & 0xffff0000)
5043             != WINED3DTSS_TCI_PASSTHRU;
5044     unsigned int coord_idx = min(state->texture_states[tex][WINED3D_TSS_TEXCOORD_INDEX & 0x0000ffff],
5045             MAX_TEXTURES - 1);
5046 
5047     compute_texture_matrix(gl_info, &state->transforms[WINED3D_TS_TEXTURE0 + tex],
5048             state->texture_states[tex][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS],
5049             generated, context->last_was_rhw,
5050             context->stream_info.use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx))
5051             ? context->stream_info.elements[WINED3D_FFP_TEXCOORD0 + coord_idx].format->id
5052             : WINED3DFMT_UNKNOWN,
5053             device->shader_backend->shader_has_ffp_proj_control(device->shader_priv), mat);
5054 
5055     if ((context->lastWasPow2Texture & (1u << tex)) && state->textures[tex])
5056     {
5057         if (generated)
5058             FIXME("Non-power-of-two texture being used with generated texture coords.\n");
5059         /* NP2 texcoord fixup is implemented for pixelshaders so only enable the
5060          * fixed-function-pipeline fixup via pow2Matrix when no PS is used. */
5061         if (!use_ps(state))
5062         {
5063             TRACE("Non-power-of-two texture matrix multiply fixup.\n");
5064             multiply_matrix(mat, mat, (struct wined3d_matrix *)state->textures[tex]->pow2_matrix);
5065         }
5066     }
5067 }
5068 
5069 void get_pointsize_minmax(const struct wined3d_context *context, const struct wined3d_state *state,
5070         float *out_min, float *out_max)
5071 {
5072     union
5073     {
5074         DWORD d;
5075         float f;
5076     } min, max;
5077 
5078     min.d = state->render_states[WINED3D_RS_POINTSIZE_MIN];
5079     max.d = state->render_states[WINED3D_RS_POINTSIZE_MAX];
5080 
5081     if (min.f > max.f)
5082         min.f = max.f;
5083 
5084     *out_min = min.f;
5085     *out_max = max.f;
5086 }
5087 
5088 void get_pointsize(const struct wined3d_context *context, const struct wined3d_state *state,
5089         float *out_pointsize, float *out_att)
5090 {
5091     /* POINTSCALEENABLE controls how point size value is treated. If set to
5092      * true, the point size is scaled with respect to height of viewport.
5093      * When set to false point size is in pixels. */
5094     union
5095     {
5096         DWORD d;
5097         float f;
5098     } pointsize, a, b, c;
5099 
5100     out_att[0] = 1.0f;
5101     out_att[1] = 0.0f;
5102     out_att[2] = 0.0f;
5103 
5104     pointsize.d = state->render_states[WINED3D_RS_POINTSIZE];
5105     a.d = state->render_states[WINED3D_RS_POINTSCALE_A];
5106     b.d = state->render_states[WINED3D_RS_POINTSCALE_B];
5107     c.d = state->render_states[WINED3D_RS_POINTSCALE_C];
5108 
5109     /* Always use first viewport, this path does not apply to d3d10/11 multiple viewports case. */
5110     if (state->render_states[WINED3D_RS_POINTSCALEENABLE])
5111     {
5112         float scale_factor = state->viewports[0].height * state->viewports[0].height;
5113 
5114         out_att[0] = a.f / scale_factor;
5115         out_att[1] = b.f / scale_factor;
5116         out_att[2] = c.f / scale_factor;
5117     }
5118     *out_pointsize = pointsize.f;
5119 }
5120 
5121 void get_fog_start_end(const struct wined3d_context *context, const struct wined3d_state *state,
5122         float *start, float *end)
5123 {
5124     union
5125     {
5126         DWORD d;
5127         float f;
5128     } tmpvalue;
5129 
5130     switch (context->fog_source)
5131     {
5132         case FOGSOURCE_VS:
5133             *start = 1.0f;
5134             *end = 0.0f;
5135             break;
5136 
5137         case FOGSOURCE_COORD:
5138             *start = 255.0f;
5139             *end = 0.0f;
5140             break;
5141 
5142         case FOGSOURCE_FFP:
5143             tmpvalue.d = state->render_states[WINED3D_RS_FOGSTART];
5144             *start = tmpvalue.f;
5145             tmpvalue.d = state->render_states[WINED3D_RS_FOGEND];
5146             *end = tmpvalue.f;
5147             /* Special handling for fog_start == fog_end. In d3d with vertex
5148              * fog, everything is fogged. With table fog, everything with
5149              * fog_coord < fog_start is unfogged, and fog_coord > fog_start
5150              * is fogged. Windows drivers disagree when fog_coord == fog_start. */
5151             if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE && *start == *end)
5152             {
5153                 *start = -INFINITY;
5154                 *end = 0.0f;
5155             }
5156             break;
5157 
5158         default:
5159             /* This should not happen, context->fog_source is set in wined3d, not the app. */
5160             ERR("Unexpected fog coordinate source.\n");
5161             *start = 0.0f;
5162             *end = 0.0f;
5163     }
5164 }
5165 
5166 /* Note: It's the caller's responsibility to ensure values can be expressed
5167  * in the requested format. UNORM formats for example can only express values
5168  * in the range 0.0f -> 1.0f. */
5169 DWORD wined3d_format_convert_from_float(const struct wined3d_format *format, const struct wined3d_color *color)
5170 {
5171     static const struct
5172     {
5173         enum wined3d_format_id format_id;
5174         struct wined3d_vec4 mul;
5175         struct wined3d_uvec4 shift;
5176     }
5177     float_conv[] =
5178     {
5179         {WINED3DFMT_B8G8R8A8_UNORM,    {       255.0f,  255.0f,  255.0f, 255.0f}, {16,  8,  0, 24}},
5180         {WINED3DFMT_B8G8R8X8_UNORM,    {       255.0f,  255.0f,  255.0f, 255.0f}, {16,  8,  0, 24}},
5181         {WINED3DFMT_B8G8R8_UNORM,      {       255.0f,  255.0f,  255.0f, 255.0f}, {16,  8,  0, 24}},
5182         {WINED3DFMT_B5G6R5_UNORM,      {        31.0f,   63.0f,   31.0f,   0.0f}, {11,  5,  0,  0}},
5183         {WINED3DFMT_B5G5R5A1_UNORM,    {        31.0f,   31.0f,   31.0f,   1.0f}, {10,  5,  0, 15}},
5184         {WINED3DFMT_B5G5R5X1_UNORM,    {        31.0f,   31.0f,   31.0f,   1.0f}, {10,  5,  0, 15}},
5185         {WINED3DFMT_R8_UNORM,          {       255.0f,    0.0f,    0.0f,   0.0f}, { 0,  0,  0,  0}},
5186         {WINED3DFMT_A8_UNORM,          {         0.0f,    0.0f,    0.0f, 255.0f}, { 0,  0,  0,  0}},
5187         {WINED3DFMT_B4G4R4A4_UNORM,    {        15.0f,   15.0f,   15.0f,  15.0f}, { 8,  4,  0, 12}},
5188         {WINED3DFMT_B4G4R4X4_UNORM,    {        15.0f,   15.0f,   15.0f,  15.0f}, { 8,  4,  0, 12}},
5189         {WINED3DFMT_B2G3R3_UNORM,      {         7.0f,    7.0f,    3.0f,   0.0f}, { 5,  2,  0,  0}},
5190         {WINED3DFMT_R8G8B8A8_UNORM,    {       255.0f,  255.0f,  255.0f, 255.0f}, { 0,  8, 16, 24}},
5191         {WINED3DFMT_R8G8B8X8_UNORM,    {       255.0f,  255.0f,  255.0f, 255.0f}, { 0,  8, 16, 24}},
5192         {WINED3DFMT_B10G10R10A2_UNORM, {      1023.0f, 1023.0f, 1023.0f,   3.0f}, {20, 10,  0, 30}},
5193         {WINED3DFMT_R10G10B10A2_UNORM, {      1023.0f, 1023.0f, 1023.0f,   3.0f}, { 0, 10, 20, 30}},
5194         {WINED3DFMT_P8_UINT,           {         0.0f,    0.0f,    0.0f, 255.0f}, { 0,  0,  0,  0}},
5195         {WINED3DFMT_S1_UINT_D15_UNORM, {     32767.0f,    0.0f,    0.0f,   0.0f}, { 0,  0,  0,  0}},
5196         {WINED3DFMT_D16_UNORM,         {     65535.0f,    0.0f,    0.0f,   0.0f}, { 0,  0,  0,  0}},
5197     };
5198     static const struct
5199     {
5200         enum wined3d_format_id format_id;
5201         struct wined3d_dvec4 mul;
5202         struct wined3d_uvec4 shift;
5203     }
5204     double_conv[] =
5205     {
5206         {WINED3DFMT_D24_UNORM_S8_UINT, {  16777215.0, 1.0, 0.0, 0.0}, {8, 0, 0, 0}},
5207         {WINED3DFMT_X8D24_UNORM,       {  16777215.0, 0.0, 0.0, 0.0}, {0, 0, 0, 0}},
5208         {WINED3DFMT_D32_UNORM,         {4294967295.0, 0.0, 0.0, 0.0}, {0, 0, 0, 0}},
5209     };
5210     unsigned int i;
5211     DWORD ret;
5212 
5213     TRACE("Converting color %s to format %s.\n", debug_color(color), debug_d3dformat(format->id));
5214 
5215     for (i = 0; i < ARRAY_SIZE(float_conv); ++i)
5216     {
5217         if (format->id != float_conv[i].format_id)
5218             continue;
5219 
5220         ret = ((DWORD)((color->r * float_conv[i].mul.x) + 0.5f)) << float_conv[i].shift.x;
5221         ret |= ((DWORD)((color->g * float_conv[i].mul.y) + 0.5f)) << float_conv[i].shift.y;
5222         ret |= ((DWORD)((color->b * float_conv[i].mul.z) + 0.5f)) << float_conv[i].shift.z;
5223         ret |= ((DWORD)((color->a * float_conv[i].mul.w) + 0.5f)) << float_conv[i].shift.w;
5224 
5225         TRACE("Returning 0x%08x.\n", ret);
5226 
5227         return ret;
5228     }
5229 
5230     for (i = 0; i < ARRAY_SIZE(double_conv); ++i)
5231     {
5232         if (format->id != double_conv[i].format_id)
5233             continue;
5234 
5235         ret = ((DWORD)((color->r * double_conv[i].mul.x) + 0.5)) << double_conv[i].shift.x;
5236         ret |= ((DWORD)((color->g * double_conv[i].mul.y) + 0.5)) << double_conv[i].shift.y;
5237         ret |= ((DWORD)((color->b * double_conv[i].mul.z) + 0.5)) << double_conv[i].shift.z;
5238         ret |= ((DWORD)((color->a * double_conv[i].mul.w) + 0.5)) << double_conv[i].shift.w;
5239 
5240         TRACE("Returning 0x%08x.\n", ret);
5241 
5242         return ret;
5243     }
5244 
5245     FIXME("Conversion for format %s not implemented.\n", debug_d3dformat(format->id));
5246 
5247     return 0;
5248 }
5249 
5250 static float color_to_float(DWORD color, DWORD size, DWORD offset)
5251 {
5252     DWORD mask = size < 32 ? (1u << size) - 1 : ~0u;
5253 
5254     if (!size)
5255         return 1.0f;
5256 
5257     color >>= offset;
5258     color &= mask;
5259 
5260     return (float)color / (float)mask;
5261 }
5262 
5263 void wined3d_format_get_float_color_key(const struct wined3d_format *format,
5264         const struct wined3d_color_key *key, struct wined3d_color *float_colors)
5265 {
5266     struct wined3d_color slop;
5267 
5268     switch (format->id)
5269     {
5270         case WINED3DFMT_B8G8R8_UNORM:
5271         case WINED3DFMT_B8G8R8A8_UNORM:
5272         case WINED3DFMT_B8G8R8X8_UNORM:
5273         case WINED3DFMT_B5G6R5_UNORM:
5274         case WINED3DFMT_B5G5R5X1_UNORM:
5275         case WINED3DFMT_B5G5R5A1_UNORM:
5276         case WINED3DFMT_B4G4R4A4_UNORM:
5277         case WINED3DFMT_B2G3R3_UNORM:
5278         case WINED3DFMT_R8_UNORM:
5279         case WINED3DFMT_A8_UNORM:
5280         case WINED3DFMT_B2G3R3A8_UNORM:
5281         case WINED3DFMT_B4G4R4X4_UNORM:
5282         case WINED3DFMT_R10G10B10A2_UNORM:
5283         case WINED3DFMT_R10G10B10A2_SNORM:
5284         case WINED3DFMT_R8G8B8A8_UNORM:
5285         case WINED3DFMT_R8G8B8X8_UNORM:
5286         case WINED3DFMT_R16G16_UNORM:
5287         case WINED3DFMT_B10G10R10A2_UNORM:
5288             slop.r = 0.5f / ((1u << format->red_size) - 1);
5289             slop.g = 0.5f / ((1u << format->green_size) - 1);
5290             slop.b = 0.5f / ((1u << format->blue_size) - 1);
5291             slop.a = 0.5f / ((1u << format->alpha_size) - 1);
5292 
5293             float_colors[0].r = color_to_float(key->color_space_low_value, format->red_size, format->red_offset)
5294                     - slop.r;
5295             float_colors[0].g = color_to_float(key->color_space_low_value, format->green_size, format->green_offset)
5296                     - slop.g;
5297             float_colors[0].b = color_to_float(key->color_space_low_value, format->blue_size, format->blue_offset)
5298                     - slop.b;
5299             float_colors[0].a = color_to_float(key->color_space_low_value, format->alpha_size, format->alpha_offset)
5300                     - slop.a;
5301 
5302             float_colors[1].r = color_to_float(key->color_space_high_value, format->red_size, format->red_offset)
5303                     + slop.r;
5304             float_colors[1].g = color_to_float(key->color_space_high_value, format->green_size, format->green_offset)
5305                     + slop.g;
5306             float_colors[1].b = color_to_float(key->color_space_high_value, format->blue_size, format->blue_offset)
5307                     + slop.b;
5308             float_colors[1].a = color_to_float(key->color_space_high_value, format->alpha_size, format->alpha_offset)
5309                     + slop.a;
5310             break;
5311 
5312         case WINED3DFMT_P8_UINT:
5313             float_colors[0].r = 0.0f;
5314             float_colors[0].g = 0.0f;
5315             float_colors[0].b = 0.0f;
5316             float_colors[0].a = (key->color_space_low_value - 0.5f) / 255.0f;
5317 
5318             float_colors[1].r = 0.0f;
5319             float_colors[1].g = 0.0f;
5320             float_colors[1].b = 0.0f;
5321             float_colors[1].a = (key->color_space_high_value + 0.5f) / 255.0f;
5322             break;
5323 
5324         default:
5325             ERR("Unhandled color key to float conversion for format %s.\n", debug_d3dformat(format->id));
5326     }
5327 }
5328 
5329 /* DirectDraw stuff */
5330 enum wined3d_format_id pixelformat_for_depth(DWORD depth)
5331 {
5332     switch (depth)
5333     {
5334         case 8:  return WINED3DFMT_P8_UINT;
5335         case 15: return WINED3DFMT_B5G5R5X1_UNORM;
5336         case 16: return WINED3DFMT_B5G6R5_UNORM;
5337         case 24: return WINED3DFMT_B8G8R8X8_UNORM; /* Robots needs 24bit to be WINED3DFMT_B8G8R8X8_UNORM */
5338         case 32: return WINED3DFMT_B8G8R8X8_UNORM; /* EVE online and the Fur demo need 32bit AdapterDisplayMode to return WINED3DFMT_B8G8R8X8_UNORM */
5339         default: return WINED3DFMT_UNKNOWN;
5340     }
5341 }
5342 
5343 void multiply_matrix(struct wined3d_matrix *dst, const struct wined3d_matrix *src1, const struct wined3d_matrix *src2)
5344 {
5345     struct wined3d_matrix tmp;
5346 
5347     /* Now do the multiplication 'by hand'.
5348        I know that all this could be optimised, but this will be done later :-) */
5349     tmp._11 = (src1->_11 * src2->_11) + (src1->_21 * src2->_12) + (src1->_31 * src2->_13) + (src1->_41 * src2->_14);
5350     tmp._21 = (src1->_11 * src2->_21) + (src1->_21 * src2->_22) + (src1->_31 * src2->_23) + (src1->_41 * src2->_24);
5351     tmp._31 = (src1->_11 * src2->_31) + (src1->_21 * src2->_32) + (src1->_31 * src2->_33) + (src1->_41 * src2->_34);
5352     tmp._41 = (src1->_11 * src2->_41) + (src1->_21 * src2->_42) + (src1->_31 * src2->_43) + (src1->_41 * src2->_44);
5353 
5354     tmp._12 = (src1->_12 * src2->_11) + (src1->_22 * src2->_12) + (src1->_32 * src2->_13) + (src1->_42 * src2->_14);
5355     tmp._22 = (src1->_12 * src2->_21) + (src1->_22 * src2->_22) + (src1->_32 * src2->_23) + (src1->_42 * src2->_24);
5356     tmp._32 = (src1->_12 * src2->_31) + (src1->_22 * src2->_32) + (src1->_32 * src2->_33) + (src1->_42 * src2->_34);
5357     tmp._42 = (src1->_12 * src2->_41) + (src1->_22 * src2->_42) + (src1->_32 * src2->_43) + (src1->_42 * src2->_44);
5358 
5359     tmp._13 = (src1->_13 * src2->_11) + (src1->_23 * src2->_12) + (src1->_33 * src2->_13) + (src1->_43 * src2->_14);
5360     tmp._23 = (src1->_13 * src2->_21) + (src1->_23 * src2->_22) + (src1->_33 * src2->_23) + (src1->_43 * src2->_24);
5361     tmp._33 = (src1->_13 * src2->_31) + (src1->_23 * src2->_32) + (src1->_33 * src2->_33) + (src1->_43 * src2->_34);
5362     tmp._43 = (src1->_13 * src2->_41) + (src1->_23 * src2->_42) + (src1->_33 * src2->_43) + (src1->_43 * src2->_44);
5363 
5364     tmp._14 = (src1->_14 * src2->_11) + (src1->_24 * src2->_12) + (src1->_34 * src2->_13) + (src1->_44 * src2->_14);
5365     tmp._24 = (src1->_14 * src2->_21) + (src1->_24 * src2->_22) + (src1->_34 * src2->_23) + (src1->_44 * src2->_24);
5366     tmp._34 = (src1->_14 * src2->_31) + (src1->_24 * src2->_32) + (src1->_34 * src2->_33) + (src1->_44 * src2->_34);
5367     tmp._44 = (src1->_14 * src2->_41) + (src1->_24 * src2->_42) + (src1->_34 * src2->_43) + (src1->_44 * src2->_44);
5368 
5369     *dst = tmp;
5370 }
5371 
5372 /* Taken and adapted from Mesa. */
5373 BOOL invert_matrix_3d(struct wined3d_matrix *out, const struct wined3d_matrix *in)
5374 {
5375     float pos, neg, t, det;
5376     struct wined3d_matrix temp;
5377 
5378     /* Calculate the determinant of upper left 3x3 submatrix and
5379      * determine if the matrix is singular. */
5380     pos = neg = 0.0f;
5381     t =  in->_11 * in->_22 * in->_33;
5382     if (t >= 0.0f)
5383         pos += t;
5384     else
5385         neg += t;
5386 
5387     t =  in->_21 * in->_32 * in->_13;
5388     if (t >= 0.0f)
5389         pos += t;
5390     else
5391         neg += t;
5392     t =  in->_31 * in->_12 * in->_23;
5393     if (t >= 0.0f)
5394         pos += t;
5395     else
5396         neg += t;
5397 
5398     t = -in->_31 * in->_22 * in->_13;
5399     if (t >= 0.0f)
5400         pos += t;
5401     else
5402         neg += t;
5403     t = -in->_21 * in->_12 * in->_33;
5404     if (t >= 0.0f)
5405         pos += t;
5406     else
5407         neg += t;
5408 
5409     t = -in->_11 * in->_32 * in->_23;
5410     if (t >= 0.0f)
5411         pos += t;
5412     else
5413         neg += t;
5414 
5415     det = pos + neg;
5416 
5417     if (fabsf(det) < 1e-25f)
5418         return FALSE;
5419 
5420     det = 1.0f / det;
5421     temp._11 =  (in->_22 * in->_33 - in->_32 * in->_23) * det;
5422     temp._12 = -(in->_12 * in->_33 - in->_32 * in->_13) * det;
5423     temp._13 =  (in->_12 * in->_23 - in->_22 * in->_13) * det;
5424     temp._21 = -(in->_21 * in->_33 - in->_31 * in->_23) * det;
5425     temp._22 =  (in->_11 * in->_33 - in->_31 * in->_13) * det;
5426     temp._23 = -(in->_11 * in->_23 - in->_21 * in->_13) * det;
5427     temp._31 =  (in->_21 * in->_32 - in->_31 * in->_22) * det;
5428     temp._32 = -(in->_11 * in->_32 - in->_31 * in->_12) * det;
5429     temp._33 =  (in->_11 * in->_22 - in->_21 * in->_12) * det;
5430 
5431     *out = temp;
5432     return TRUE;
5433 }
5434 
5435 static void swap_rows(float **a, float **b)
5436 {
5437     float *tmp = *a;
5438 
5439     *a = *b;
5440     *b = tmp;
5441 }
5442 
5443 BOOL invert_matrix(struct wined3d_matrix *out, const struct wined3d_matrix *m)
5444 {
5445     float wtmp[4][8];
5446     float m0, m1, m2, m3, s;
5447     float *r0, *r1, *r2, *r3;
5448 
5449     r0 = wtmp[0];
5450     r1 = wtmp[1];
5451     r2 = wtmp[2];
5452     r3 = wtmp[3];
5453 
5454     r0[0] = m->_11;
5455     r0[1] = m->_12;
5456     r0[2] = m->_13;
5457     r0[3] = m->_14;
5458     r0[4] = 1.0f;
5459     r0[5] = r0[6] = r0[7] = 0.0f;
5460 
5461     r1[0] = m->_21;
5462     r1[1] = m->_22;
5463     r1[2] = m->_23;
5464     r1[3] = m->_24;
5465     r1[5] = 1.0f;
5466     r1[4] = r1[6] = r1[7] = 0.0f;
5467 
5468     r2[0] = m->_31;
5469     r2[1] = m->_32;
5470     r2[2] = m->_33;
5471     r2[3] = m->_34;
5472     r2[6] = 1.0f;
5473     r2[4] = r2[5] = r2[7] = 0.0f;
5474 
5475     r3[0] = m->_41;
5476     r3[1] = m->_42;
5477     r3[2] = m->_43;
5478     r3[3] = m->_44;
5479     r3[7] = 1.0f;
5480     r3[4] = r3[5] = r3[6] = 0.0f;
5481 
5482     /* Choose pivot - or die. */
5483     if (fabsf(r3[0]) > fabsf(r2[0]))
5484         swap_rows(&r3, &r2);
5485     if (fabsf(r2[0]) > fabsf(r1[0]))
5486         swap_rows(&r2, &r1);
5487     if (fabsf(r1[0]) > fabsf(r0[0]))
5488         swap_rows(&r1, &r0);
5489     if (r0[0] == 0.0f)
5490         return FALSE;
5491 
5492     /* Eliminate first variable. */
5493     m1 = r1[0] / r0[0]; m2 = r2[0] / r0[0]; m3 = r3[0] / r0[0];
5494     s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s;
5495     s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s;
5496     s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s;
5497     s = r0[4];
5498     if (s != 0.0f)
5499     {
5500         r1[4] -= m1 * s;
5501         r2[4] -= m2 * s;
5502         r3[4] -= m3 * s;
5503     }
5504     s = r0[5];
5505     if (s != 0.0f)
5506     {
5507         r1[5] -= m1 * s;
5508         r2[5] -= m2 * s;
5509         r3[5] -= m3 * s;
5510     }
5511     s = r0[6];
5512     if (s != 0.0f)
5513     {
5514         r1[6] -= m1 * s;
5515         r2[6] -= m2 * s;
5516         r3[6] -= m3 * s;
5517     }
5518     s = r0[7];
5519     if (s != 0.0f)
5520     {
5521         r1[7] -= m1 * s;
5522         r2[7] -= m2 * s;
5523         r3[7] -= m3 * s;
5524     }
5525 
5526     /* Choose pivot - or die. */
5527     if (fabsf(r3[1]) > fabsf(r2[1]))
5528         swap_rows(&r3, &r2);
5529     if (fabsf(r2[1]) > fabsf(r1[1]))
5530         swap_rows(&r2, &r1);
5531     if (r1[1] == 0.0f)
5532         return FALSE;
5533 
5534     /* Eliminate second variable. */
5535     m2 = r2[1] / r1[1]; m3 = r3[1] / r1[1];
5536     r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2];
5537     r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3];
5538     s = r1[4];
5539     if (s != 0.0f)
5540     {
5541         r2[4] -= m2 * s;
5542         r3[4] -= m3 * s;
5543     }
5544     s = r1[5];
5545     if (s != 0.0f)
5546     {
5547         r2[5] -= m2 * s;
5548         r3[5] -= m3 * s;
5549     }
5550     s = r1[6];
5551     if (s != 0.0f)
5552     {
5553         r2[6] -= m2 * s;
5554         r3[6] -= m3 * s;
5555     }
5556     s = r1[7];
5557     if (s != 0.0f)
5558     {
5559         r2[7] -= m2 * s;
5560         r3[7] -= m3 * s;
5561     }
5562 
5563     /* Choose pivot - or die. */
5564     if (fabsf(r3[2]) > fabsf(r2[2]))
5565         swap_rows(&r3, &r2);
5566     if (r2[2] == 0.0f)
5567         return FALSE;
5568 
5569     /* Eliminate third variable. */
5570     m3 = r3[2] / r2[2];
5571     r3[3] -= m3 * r2[3];
5572     r3[4] -= m3 * r2[4];
5573     r3[5] -= m3 * r2[5];
5574     r3[6] -= m3 * r2[6];
5575     r3[7] -= m3 * r2[7];
5576 
5577     /* Last check. */
5578     if (r3[3] == 0.0f)
5579         return FALSE;
5580 
5581     /* Back substitute row 3. */
5582     s = 1.0f / r3[3];
5583     r3[4] *= s;
5584     r3[5] *= s;
5585     r3[6] *= s;
5586     r3[7] *= s;
5587 
5588     /* Back substitute row 2. */
5589     m2 = r2[3];
5590     s = 1.0f / r2[2];
5591     r2[4] = s * (r2[4] - r3[4] * m2);
5592     r2[5] = s * (r2[5] - r3[5] * m2);
5593     r2[6] = s * (r2[6] - r3[6] * m2);
5594     r2[7] = s * (r2[7] - r3[7] * m2);
5595     m1 = r1[3];
5596     r1[4] -= r3[4] * m1;
5597     r1[5] -= r3[5] * m1;
5598     r1[6] -= r3[6] * m1;
5599     r1[7] -= r3[7] * m1;
5600     m0 = r0[3];
5601     r0[4] -= r3[4] * m0;
5602     r0[5] -= r3[5] * m0;
5603     r0[6] -= r3[6] * m0;
5604     r0[7] -= r3[7] * m0;
5605 
5606     /* Back substitute row 1. */
5607     m1 = r1[2];
5608     s = 1.0f / r1[1];
5609     r1[4] = s * (r1[4] - r2[4] * m1);
5610     r1[5] = s * (r1[5] - r2[5] * m1);
5611     r1[6] = s * (r1[6] - r2[6] * m1);
5612     r1[7] = s * (r1[7] - r2[7] * m1);
5613     m0 = r0[2];
5614     r0[4] -= r2[4] * m0;
5615     r0[5] -= r2[5] * m0;
5616     r0[6] -= r2[6] * m0;
5617     r0[7] -= r2[7] * m0;
5618 
5619     /* Back substitute row 0. */
5620     m0 = r0[1];
5621     s = 1.0f / r0[0];
5622     r0[4] = s * (r0[4] - r1[4] * m0);
5623     r0[5] = s * (r0[5] - r1[5] * m0);
5624     r0[6] = s * (r0[6] - r1[6] * m0);
5625     r0[7] = s * (r0[7] - r1[7] * m0);
5626 
5627     out->_11 = r0[4];
5628     out->_12 = r0[5];
5629     out->_13 = r0[6];
5630     out->_14 = r0[7];
5631     out->_21 = r1[4];
5632     out->_22 = r1[5];
5633     out->_23 = r1[6];
5634     out->_24 = r1[7];
5635     out->_31 = r2[4];
5636     out->_32 = r2[5];
5637     out->_33 = r2[6];
5638     out->_34 = r2[7];
5639     out->_41 = r3[4];
5640     out->_42 = r3[5];
5641     out->_43 = r3[6];
5642     out->_44 = r3[7];
5643 
5644     return TRUE;
5645 }
5646 
5647 void transpose_matrix(struct wined3d_matrix *out, const struct wined3d_matrix *m)
5648 {
5649     struct wined3d_matrix temp;
5650     unsigned int i, j;
5651 
5652     for (i = 0; i < 4; ++i)
5653         for (j = 0; j < 4; ++j)
5654             (&temp._11)[4 * j + i] = (&m->_11)[4 * i + j];
5655 
5656     *out = temp;
5657 }
5658 
5659 DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) {
5660     DWORD size = 0;
5661     int i;
5662     int numTextures = (d3dvtVertexType & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
5663 
5664     if (d3dvtVertexType & WINED3DFVF_NORMAL) size += 3 * sizeof(float);
5665     if (d3dvtVertexType & WINED3DFVF_DIFFUSE) size += sizeof(DWORD);
5666     if (d3dvtVertexType & WINED3DFVF_SPECULAR) size += sizeof(DWORD);
5667     if (d3dvtVertexType & WINED3DFVF_PSIZE) size += sizeof(DWORD);
5668     switch (d3dvtVertexType & WINED3DFVF_POSITION_MASK) {
5669         case WINED3DFVF_XYZ:    size += 3 * sizeof(float); break;
5670         case WINED3DFVF_XYZRHW: size += 4 * sizeof(float); break;
5671         case WINED3DFVF_XYZB1:  size += 4 * sizeof(float); break;
5672         case WINED3DFVF_XYZB2:  size += 5 * sizeof(float); break;
5673         case WINED3DFVF_XYZB3:  size += 6 * sizeof(float); break;
5674         case WINED3DFVF_XYZB4:  size += 7 * sizeof(float); break;
5675         case WINED3DFVF_XYZB5:  size += 8 * sizeof(float); break;
5676         case WINED3DFVF_XYZW:   size += 4 * sizeof(float); break;
5677         default: ERR("Unexpected position mask\n");
5678     }
5679     for (i = 0; i < numTextures; i++) {
5680         size += GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, i) * sizeof(float);
5681     }
5682 
5683     return size;
5684 }
5685 
5686 unsigned int wined3d_max_compat_varyings(const struct wined3d_gl_info *gl_info)
5687 {
5688     /* On core profile we have to also count diffuse and specular colors and the
5689      * fog coordinate. */
5690     return gl_info->supported[WINED3D_GL_LEGACY_CONTEXT] ? MAX_TEXTURES * 4 : (MAX_TEXTURES + 2) * 4 + 1;
5691 }
5692 
5693 void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d_state *state,
5694         struct ffp_frag_settings *settings, BOOL ignore_textype)
5695 {
5696 #define ARG1 0x01
5697 #define ARG2 0x02
5698 #define ARG0 0x04
5699     static const unsigned char args[WINED3D_TOP_LERP + 1] =
5700     {
5701         /* undefined                        */  0,
5702         /* D3DTOP_DISABLE                   */  0,
5703         /* D3DTOP_SELECTARG1                */  ARG1,
5704         /* D3DTOP_SELECTARG2                */  ARG2,
5705         /* D3DTOP_MODULATE                  */  ARG1 | ARG2,
5706         /* D3DTOP_MODULATE2X                */  ARG1 | ARG2,
5707         /* D3DTOP_MODULATE4X                */  ARG1 | ARG2,
5708         /* D3DTOP_ADD                       */  ARG1 | ARG2,
5709         /* D3DTOP_ADDSIGNED                 */  ARG1 | ARG2,
5710         /* D3DTOP_ADDSIGNED2X               */  ARG1 | ARG2,
5711         /* D3DTOP_SUBTRACT                  */  ARG1 | ARG2,
5712         /* D3DTOP_ADDSMOOTH                 */  ARG1 | ARG2,
5713         /* D3DTOP_BLENDDIFFUSEALPHA         */  ARG1 | ARG2,
5714         /* D3DTOP_BLENDTEXTUREALPHA         */  ARG1 | ARG2,
5715         /* D3DTOP_BLENDFACTORALPHA          */  ARG1 | ARG2,
5716         /* D3DTOP_BLENDTEXTUREALPHAPM       */  ARG1 | ARG2,
5717         /* D3DTOP_BLENDCURRENTALPHA         */  ARG1 | ARG2,
5718         /* D3DTOP_PREMODULATE               */  ARG1 | ARG2,
5719         /* D3DTOP_MODULATEALPHA_ADDCOLOR    */  ARG1 | ARG2,
5720         /* D3DTOP_MODULATECOLOR_ADDALPHA    */  ARG1 | ARG2,
5721         /* D3DTOP_MODULATEINVALPHA_ADDCOLOR */  ARG1 | ARG2,
5722         /* D3DTOP_MODULATEINVCOLOR_ADDALPHA */  ARG1 | ARG2,
5723         /* D3DTOP_BUMPENVMAP                */  ARG1 | ARG2,
5724         /* D3DTOP_BUMPENVMAPLUMINANCE       */  ARG1 | ARG2,
5725         /* D3DTOP_DOTPRODUCT3               */  ARG1 | ARG2,
5726         /* D3DTOP_MULTIPLYADD               */  ARG1 | ARG2 | ARG0,
5727         /* D3DTOP_LERP                      */  ARG1 | ARG2 | ARG0
5728     };
5729     unsigned int i;
5730     DWORD ttff;
5731     DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2;
5732     const struct wined3d_gl_info *gl_info = context->gl_info;
5733     const struct wined3d_d3d_info *d3d_info = context->d3d_info;
5734 
5735     settings->padding = 0;
5736 
5737     for (i = 0; i < d3d_info->limits.ffp_blend_stages; ++i)
5738     {
5739         const struct wined3d_texture *texture;
5740 
5741         settings->op[i].padding = 0;
5742         if (state->texture_states[i][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_DISABLE)
5743         {
5744             settings->op[i].cop = WINED3D_TOP_DISABLE;
5745             settings->op[i].aop = WINED3D_TOP_DISABLE;
5746             settings->op[i].carg0 = settings->op[i].carg1 = settings->op[i].carg2 = ARG_UNUSED;
5747             settings->op[i].aarg0 = settings->op[i].aarg1 = settings->op[i].aarg2 = ARG_UNUSED;
5748             settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
5749             settings->op[i].tmp_dst = 0;
5750             settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_1D;
5751             settings->op[i].projected = WINED3D_PROJECTION_NONE;
5752             i++;
5753             break;
5754         }
5755 
5756         if ((texture = state->textures[i]))
5757         {
5758             if (can_use_texture_swizzle(gl_info, texture->resource.format))
5759                 settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
5760             else
5761                 settings->op[i].color_fixup = texture->resource.format->color_fixup;
5762             if (ignore_textype)
5763             {
5764                 settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_1D;
5765             }
5766             else
5767             {
5768                 switch (texture->target)
5769                 {
5770                     case GL_TEXTURE_1D:
5771                         settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_1D;
5772                         break;
5773                     case GL_TEXTURE_2D:
5774                         settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_2D;
5775                         break;
5776                     case GL_TEXTURE_3D:
5777                         settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_3D;
5778                         break;
5779                     case GL_TEXTURE_CUBE_MAP_ARB:
5780                         settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_CUBE;
5781                         break;
5782                     case GL_TEXTURE_RECTANGLE_ARB:
5783                         settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_RECT;
5784                         break;
5785                 }
5786             }
5787         } else {
5788             settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
5789             settings->op[i].tex_type = WINED3D_GL_RES_TYPE_TEX_1D;
5790         }
5791 
5792         cop = state->texture_states[i][WINED3D_TSS_COLOR_OP];
5793         aop = state->texture_states[i][WINED3D_TSS_ALPHA_OP];
5794 
5795         carg1 = (args[cop] & ARG1) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG1] : ARG_UNUSED;
5796         carg2 = (args[cop] & ARG2) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG2] : ARG_UNUSED;
5797         carg0 = (args[cop] & ARG0) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG0] : ARG_UNUSED;
5798 
5799         if (is_invalid_op(state, i, cop, carg1, carg2, carg0))
5800         {
5801             carg0 = ARG_UNUSED;
5802             carg2 = ARG_UNUSED;
5803             carg1 = WINED3DTA_CURRENT;
5804             cop = WINED3D_TOP_SELECT_ARG1;
5805         }
5806 
5807         if (cop == WINED3D_TOP_DOTPRODUCT3)
5808         {
5809             /* A dotproduct3 on the colorop overwrites the alphaop operation and replicates
5810              * the color result to the alpha component of the destination
5811              */
5812             aop = cop;
5813             aarg1 = carg1;
5814             aarg2 = carg2;
5815             aarg0 = carg0;
5816         }
5817         else
5818         {
5819             aarg1 = (args[aop] & ARG1) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG1] : ARG_UNUSED;
5820             aarg2 = (args[aop] & ARG2) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG2] : ARG_UNUSED;
5821             aarg0 = (args[aop] & ARG0) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG0] : ARG_UNUSED;
5822         }
5823 
5824         if (!i && state->textures[0] && state->render_states[WINED3D_RS_COLORKEYENABLE])
5825         {
5826             GLenum texture_dimensions;
5827 
5828             texture = state->textures[0];
5829             texture_dimensions = texture->target;
5830 
5831             if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
5832             {
5833                 if (texture->async.color_key_flags & WINED3D_CKEY_SRC_BLT && !texture->resource.format->alpha_size)
5834                 {
5835                     if (aop == WINED3D_TOP_DISABLE)
5836                     {
5837                        aarg1 = WINED3DTA_TEXTURE;
5838                        aop = WINED3D_TOP_SELECT_ARG1;
5839                     }
5840                     else if (aop == WINED3D_TOP_SELECT_ARG1 && aarg1 != WINED3DTA_TEXTURE)
5841                     {
5842                         if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
5843                         {
5844                             aarg2 = WINED3DTA_TEXTURE;
5845                             aop = WINED3D_TOP_MODULATE;
5846                         }
5847                         else aarg1 = WINED3DTA_TEXTURE;
5848                     }
5849                     else if (aop == WINED3D_TOP_SELECT_ARG2 && aarg2 != WINED3DTA_TEXTURE)
5850                     {
5851                         if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
5852                         {
5853                             aarg1 = WINED3DTA_TEXTURE;
5854                             aop = WINED3D_TOP_MODULATE;
5855                         }
5856                         else aarg2 = WINED3DTA_TEXTURE;
5857                     }
5858                 }
5859             }
5860         }
5861 
5862         if (is_invalid_op(state, i, aop, aarg1, aarg2, aarg0))
5863         {
5864                aarg0 = ARG_UNUSED;
5865                aarg2 = ARG_UNUSED;
5866                aarg1 = WINED3DTA_CURRENT;
5867                aop = WINED3D_TOP_SELECT_ARG1;
5868         }
5869 
5870         if (carg1 == WINED3DTA_TEXTURE || carg2 == WINED3DTA_TEXTURE || carg0 == WINED3DTA_TEXTURE
5871                 || aarg1 == WINED3DTA_TEXTURE || aarg2 == WINED3DTA_TEXTURE || aarg0 == WINED3DTA_TEXTURE)
5872         {
5873             ttff = state->texture_states[i][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS];
5874             if (ttff == (WINED3D_TTFF_PROJECTED | WINED3D_TTFF_COUNT3))
5875                 settings->op[i].projected = WINED3D_PROJECTION_COUNT3;
5876             else if (ttff & WINED3D_TTFF_PROJECTED)
5877                 settings->op[i].projected = WINED3D_PROJECTION_COUNT4;
5878             else
5879                 settings->op[i].projected = WINED3D_PROJECTION_NONE;
5880         }
5881         else
5882         {
5883             settings->op[i].projected = WINED3D_PROJECTION_NONE;
5884         }
5885 
5886         settings->op[i].cop = cop;
5887         settings->op[i].aop = aop;
5888         settings->op[i].carg0 = carg0;
5889         settings->op[i].carg1 = carg1;
5890         settings->op[i].carg2 = carg2;
5891         settings->op[i].aarg0 = aarg0;
5892         settings->op[i].aarg1 = aarg1;
5893         settings->op[i].aarg2 = aarg2;
5894         settings->op[i].tmp_dst = state->texture_states[i][WINED3D_TSS_RESULT_ARG] == WINED3DTA_TEMP;
5895     }
5896 
5897     /* Clear unsupported stages */
5898     for(; i < MAX_TEXTURES; i++) {
5899         memset(&settings->op[i], 0xff, sizeof(settings->op[i]));
5900     }
5901 
5902     if (!state->render_states[WINED3D_RS_FOGENABLE])
5903     {
5904         settings->fog = WINED3D_FFP_PS_FOG_OFF;
5905     }
5906     else if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
5907     {
5908         if (use_vs(state) || state->vertex_declaration->position_transformed)
5909         {
5910             settings->fog = WINED3D_FFP_PS_FOG_LINEAR;
5911         }
5912         else
5913         {
5914             switch (state->render_states[WINED3D_RS_FOGVERTEXMODE])
5915             {
5916                 case WINED3D_FOG_NONE:
5917                 case WINED3D_FOG_LINEAR:
5918                     settings->fog = WINED3D_FFP_PS_FOG_LINEAR;
5919                     break;
5920                 case WINED3D_FOG_EXP:
5921                     settings->fog = WINED3D_FFP_PS_FOG_EXP;
5922                     break;
5923                 case WINED3D_FOG_EXP2:
5924                     settings->fog = WINED3D_FFP_PS_FOG_EXP2;
5925                     break;
5926             }
5927         }
5928     }
5929     else
5930     {
5931         switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
5932         {
5933             case WINED3D_FOG_LINEAR:
5934                 settings->fog = WINED3D_FFP_PS_FOG_LINEAR;
5935                 break;
5936             case WINED3D_FOG_EXP:
5937                 settings->fog = WINED3D_FFP_PS_FOG_EXP;
5938                 break;
5939             case WINED3D_FOG_EXP2:
5940                 settings->fog = WINED3D_FFP_PS_FOG_EXP2;
5941                 break;
5942         }
5943     }
5944     settings->sRGB_write = !gl_info->supported[ARB_FRAMEBUFFER_SRGB] && needs_srgb_write(context, state, state->fb);
5945     if (d3d_info->vs_clipping || !use_vs(state) || !state->render_states[WINED3D_RS_CLIPPING]
5946             || !state->render_states[WINED3D_RS_CLIPPLANEENABLE])
5947     {
5948         /* No need to emulate clipplanes if GL supports native vertex shader clipping or if
5949          * the fixed function vertex pipeline is used(which always supports clipplanes), or
5950          * if no clipplane is enabled
5951          */
5952         settings->emul_clipplanes = 0;
5953     } else {
5954         settings->emul_clipplanes = 1;
5955     }
5956 
5957     if (state->render_states[WINED3D_RS_COLORKEYENABLE] && state->textures[0]
5958             && state->textures[0]->async.color_key_flags & WINED3D_CKEY_SRC_BLT
5959             && settings->op[0].cop != WINED3D_TOP_DISABLE)
5960         settings->color_key_enabled = 1;
5961     else
5962         settings->color_key_enabled = 0;
5963 
5964     /* texcoords_initialized is set to meaningful values only when GL doesn't
5965      * support enough varyings to always pass around all the possible texture
5966      * coordinates.
5967      * This is used to avoid reading a varying not written by the vertex shader.
5968      * Reading uninitialized varyings on core profile contexts results in an
5969      * error while with builtin varyings on legacy contexts you get undefined
5970      * behavior. */
5971     if (d3d_info->limits.varying_count
5972             && d3d_info->limits.varying_count < wined3d_max_compat_varyings(gl_info))
5973     {
5974         settings->texcoords_initialized = 0;
5975         for (i = 0; i < MAX_TEXTURES; ++i)
5976         {
5977             if (use_vs(state))
5978             {
5979                 if (state->shader[WINED3D_SHADER_TYPE_VERTEX]->reg_maps.output_registers & (1u << i))
5980                     settings->texcoords_initialized |= 1u << i;
5981             }
5982             else
5983             {
5984                 const struct wined3d_stream_info *si = &context->stream_info;
5985                 unsigned int coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
5986                 if ((state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX] >> WINED3D_FFP_TCI_SHIFT)
5987                         & WINED3D_FFP_TCI_MASK
5988                         || (coord_idx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx)))))
5989                     settings->texcoords_initialized |= 1u << i;
5990             }
5991         }
5992     }
5993     else
5994     {
5995         settings->texcoords_initialized = (1u << MAX_TEXTURES) - 1;
5996     }
5997 
5998     settings->pointsprite = state->render_states[WINED3D_RS_POINTSPRITEENABLE]
5999             && state->gl_primitive_type == GL_POINTS;
6000 
6001     if (gl_info->supported[WINED3D_GL_LEGACY_CONTEXT])
6002         settings->alpha_test_func = WINED3D_CMP_ALWAYS - 1;
6003     else
6004         settings->alpha_test_func = (state->render_states[WINED3D_RS_ALPHATESTENABLE]
6005                 ? wined3d_sanitize_cmp_func(state->render_states[WINED3D_RS_ALPHAFUNC])
6006                 : WINED3D_CMP_ALWAYS) - 1;
6007 
6008     if (d3d_info->emulated_flatshading)
6009         settings->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
6010     else
6011         settings->flatshading = FALSE;
6012 }
6013 
6014 const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders,
6015         const struct ffp_frag_settings *settings)
6016 {
6017     struct wine_rb_entry *entry = wine_rb_get(fragment_shaders, settings);
6018     return entry ? WINE_RB_ENTRY_VALUE(entry, struct ffp_frag_desc, entry) : NULL;
6019 }
6020 
6021 void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc)
6022 {
6023     /* Note that the key is the implementation independent part of the ffp_frag_desc structure,
6024      * whereas desc points to an extended structure with implementation specific parts. */
6025     if (wine_rb_put(shaders, &desc->settings, &desc->entry) == -1)
6026     {
6027         ERR("Failed to insert ffp frag shader.\n");
6028     }
6029 }
6030 
6031 /* Activates the texture dimension according to the bound D3D texture. Does
6032  * not care for the colorop or correct gl texture unit (when using nvrc).
6033  * Requires the caller to activate the correct unit. */
6034 /* Context activation is done by the caller (state handler). */
6035 void texture_activate_dimensions(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info)
6036 {
6037     if (texture)
6038     {
6039         switch (texture->target)
6040         {
6041             case GL_TEXTURE_2D:
6042                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
6043                 checkGLcall("glDisable(GL_TEXTURE_3D)");
6044                 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
6045                 {
6046                     gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
6047                     checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
6048                 }
6049                 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
6050                 {
6051                     gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
6052                     checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
6053                 }
6054                 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
6055                 checkGLcall("glEnable(GL_TEXTURE_2D)");
6056                 break;
6057             case GL_TEXTURE_RECTANGLE_ARB:
6058                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
6059                 checkGLcall("glDisable(GL_TEXTURE_2D)");
6060                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
6061                 checkGLcall("glDisable(GL_TEXTURE_3D)");
6062                 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
6063                 {
6064                     gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
6065                     checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
6066                 }
6067                 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_RECTANGLE_ARB);
6068                 checkGLcall("glEnable(GL_TEXTURE_RECTANGLE_ARB)");
6069                 break;
6070             case GL_TEXTURE_3D:
6071                 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
6072                 {
6073                     gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
6074                     checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
6075                 }
6076                 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
6077                 {
6078                     gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
6079                     checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
6080                 }
6081                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
6082                 checkGLcall("glDisable(GL_TEXTURE_2D)");
6083                 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_3D);
6084                 checkGLcall("glEnable(GL_TEXTURE_3D)");
6085                 break;
6086             case GL_TEXTURE_CUBE_MAP_ARB:
6087                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
6088                 checkGLcall("glDisable(GL_TEXTURE_2D)");
6089                 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
6090                 checkGLcall("glDisable(GL_TEXTURE_3D)");
6091                 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
6092                 {
6093                     gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
6094                     checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
6095                 }
6096                 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_CUBE_MAP_ARB);
6097                 checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
6098               break;
6099         }
6100     }
6101     else
6102     {
6103         gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
6104         checkGLcall("glEnable(GL_TEXTURE_2D)");
6105         gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
6106         checkGLcall("glDisable(GL_TEXTURE_3D)");
6107         if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
6108         {
6109             gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
6110             checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
6111         }
6112         if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
6113         {
6114             gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
6115             checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
6116         }
6117         /* Binding textures is done by samplers. A dummy texture will be bound */
6118     }
6119 }
6120 
6121 /* Context activation is done by the caller (state handler). */
6122 void sampler_texdim(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
6123 {
6124     DWORD sampler = state_id - STATE_SAMPLER(0);
6125     DWORD mapped_stage = context->tex_unit_map[sampler];
6126 
6127     /* No need to enable / disable anything here for unused samplers. The
6128      * tex_colorop handler takes care. Also no action is needed with pixel
6129      * shaders, or if tex_colorop will take care of this business. */
6130     if (mapped_stage == WINED3D_UNMAPPED_STAGE || mapped_stage >= context->gl_info->limits.textures)
6131         return;
6132     if (sampler >= context->lowest_disabled_stage)
6133         return;
6134     if (isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)))
6135         return;
6136 
6137     texture_activate_dimensions(state->textures[sampler], context->gl_info);
6138 }
6139 
6140 int wined3d_ffp_frag_program_key_compare(const void *key, const struct wine_rb_entry *entry)
6141 {
6142     const struct ffp_frag_settings *ka = key;
6143     const struct ffp_frag_settings *kb = &WINE_RB_ENTRY_VALUE(entry, const struct ffp_frag_desc, entry)->settings;
6144 
6145     return memcmp(ka, kb, sizeof(*ka));
6146 }
6147 
6148 void wined3d_ffp_get_vs_settings(const struct wined3d_context *context,
6149         const struct wined3d_state *state, struct wined3d_ffp_vs_settings *settings)
6150 {
6151     const struct wined3d_stream_info *si = &context->stream_info;
6152     const struct wined3d_gl_info *gl_info = context->gl_info;
6153     const struct wined3d_d3d_info *d3d_info = context->d3d_info;
6154     unsigned int coord_idx, i;
6155 
6156     memset(settings, 0, sizeof(*settings));
6157 
6158     if (si->position_transformed)
6159     {
6160         settings->transformed = 1;
6161         settings->point_size = state->gl_primitive_type == GL_POINTS;
6162         settings->per_vertex_point_size = !!(si->use_map & 1u << WINED3D_FFP_PSIZE);
6163         if (!state->render_states[WINED3D_RS_FOGENABLE])
6164             settings->fog_mode = WINED3D_FFP_VS_FOG_OFF;
6165         else if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
6166             settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH;
6167         else
6168             settings->fog_mode = WINED3D_FFP_VS_FOG_FOGCOORD;
6169 
6170         for (i = 0; i < MAX_TEXTURES; ++i)
6171         {
6172             coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
6173             if (coord_idx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx))))
6174                 settings->texcoords |= 1u << i;
6175             settings->texgen[i] = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
6176         }
6177         if (d3d_info->limits.varying_count >= wined3d_max_compat_varyings(gl_info))
6178             settings->texcoords = (1u << MAX_TEXTURES) - 1;
6179 
6180         if (d3d_info->emulated_flatshading)
6181             settings->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
6182         else
6183             settings->flatshading = FALSE;
6184 
6185         settings->swizzle_map = si->swizzle_map;
6186 
6187         return;
6188     }
6189 
6190     switch (state->render_states[WINED3D_RS_VERTEXBLEND])
6191     {
6192         case WINED3D_VBF_DISABLE:
6193         case WINED3D_VBF_1WEIGHTS:
6194         case WINED3D_VBF_2WEIGHTS:
6195         case WINED3D_VBF_3WEIGHTS:
6196             settings->vertexblends = state->render_states[WINED3D_RS_VERTEXBLEND];
6197             break;
6198         default:
6199             FIXME("Unsupported vertex blending: %d\n", state->render_states[WINED3D_RS_VERTEXBLEND]);
6200             break;
6201     }
6202 
6203     if (use_indexed_vertex_blending(state, si))
6204     {
6205         if (use_software_vertex_processing(context->device))
6206             settings->sw_blending = 1;
6207         else
6208             settings->vb_indices = 1;
6209     }
6210 
6211     settings->clipping = state->render_states[WINED3D_RS_CLIPPING]
6212             && state->render_states[WINED3D_RS_CLIPPLANEENABLE];
6213     settings->normal = !!(si->use_map & (1u << WINED3D_FFP_NORMAL));
6214     settings->normalize = settings->normal && state->render_states[WINED3D_RS_NORMALIZENORMALS];
6215     settings->lighting = !!state->render_states[WINED3D_RS_LIGHTING];
6216     settings->localviewer = !!state->render_states[WINED3D_RS_LOCALVIEWER];
6217     settings->point_size = state->gl_primitive_type == GL_POINTS;
6218     settings->per_vertex_point_size = !!(si->use_map & 1u << WINED3D_FFP_PSIZE);
6219 
6220     if (state->render_states[WINED3D_RS_COLORVERTEX] && (si->use_map & (1u << WINED3D_FFP_DIFFUSE)))
6221     {
6222         settings->diffuse_source = state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE];
6223         settings->emissive_source = state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE];
6224         settings->ambient_source = state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE];
6225         settings->specular_source = state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE];
6226     }
6227     else
6228     {
6229         settings->diffuse_source = WINED3D_MCS_MATERIAL;
6230         settings->emissive_source = WINED3D_MCS_MATERIAL;
6231         settings->ambient_source = WINED3D_MCS_MATERIAL;
6232         settings->specular_source = WINED3D_MCS_MATERIAL;
6233     }
6234 
6235     for (i = 0; i < MAX_TEXTURES; ++i)
6236     {
6237         coord_idx = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
6238         if (coord_idx < MAX_TEXTURES && (si->use_map & (1u << (WINED3D_FFP_TEXCOORD0 + coord_idx))))
6239             settings->texcoords |= 1u << i;
6240         settings->texgen[i] = state->texture_states[i][WINED3D_TSS_TEXCOORD_INDEX];
6241     }
6242     if (d3d_info->limits.varying_count >= wined3d_max_compat_varyings(gl_info))
6243         settings->texcoords = (1u << MAX_TEXTURES) - 1;
6244 
6245     for (i = 0; i < MAX_ACTIVE_LIGHTS; ++i)
6246     {
6247         if (!state->lights[i])
6248             continue;
6249 
6250         switch (state->lights[i]->OriginalParms.type)
6251         {
6252             case WINED3D_LIGHT_POINT:
6253                 ++settings->point_light_count;
6254                 break;
6255             case WINED3D_LIGHT_SPOT:
6256                 ++settings->spot_light_count;
6257                 break;
6258             case WINED3D_LIGHT_DIRECTIONAL:
6259                 ++settings->directional_light_count;
6260                 break;
6261             case WINED3D_LIGHT_PARALLELPOINT:
6262                 ++settings->parallel_point_light_count;
6263                 break;
6264             default:
6265                 FIXME("Unhandled light type %#x.\n", state->lights[i]->OriginalParms.type);
6266                 break;
6267         }
6268     }
6269 
6270     if (!state->render_states[WINED3D_RS_FOGENABLE])
6271         settings->fog_mode = WINED3D_FFP_VS_FOG_OFF;
6272     else if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
6273     {
6274         settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH;
6275 
6276         if (state->transforms[WINED3D_TS_PROJECTION]._14 == 0.0f
6277                 && state->transforms[WINED3D_TS_PROJECTION]._24 == 0.0f
6278                 && state->transforms[WINED3D_TS_PROJECTION]._34 == 0.0f
6279                 && state->transforms[WINED3D_TS_PROJECTION]._44 == 1.0f)
6280             settings->ortho_fog = 1;
6281     }
6282     else if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE)
6283         settings->fog_mode = WINED3D_FFP_VS_FOG_FOGCOORD;
6284     else if (state->render_states[WINED3D_RS_RANGEFOGENABLE])
6285         settings->fog_mode = WINED3D_FFP_VS_FOG_RANGE;
6286     else
6287         settings->fog_mode = WINED3D_FFP_VS_FOG_DEPTH;
6288 
6289     if (d3d_info->emulated_flatshading)
6290         settings->flatshading = state->render_states[WINED3D_RS_SHADEMODE] == WINED3D_SHADE_FLAT;
6291     else
6292         settings->flatshading = FALSE;
6293 
6294     settings->swizzle_map = si->swizzle_map;
6295 }
6296 
6297 int wined3d_ffp_vertex_program_key_compare(const void *key, const struct wine_rb_entry *entry)
6298 {
6299     const struct wined3d_ffp_vs_settings *ka = key;
6300     const struct wined3d_ffp_vs_settings *kb = &WINE_RB_ENTRY_VALUE(entry,
6301             const struct wined3d_ffp_vs_desc, entry)->settings;
6302 
6303     return memcmp(ka, kb, sizeof(*ka));
6304 }
6305 
6306 const char *wined3d_debug_location(DWORD location)
6307 {
6308     struct debug_buffer buffer;
6309     const char *prefix = "";
6310     const char *suffix = "";
6311 
6312     if (wined3d_popcount(location) > 16)
6313     {
6314         prefix = "~(";
6315         location = ~location;
6316         suffix = ")";
6317     }
6318 
6319     init_debug_buffer(&buffer, "0");
6320 #define LOCATION_TO_STR(x) if (location & x) { debug_append(&buffer, #x, " | "); location &= ~x; }
6321     LOCATION_TO_STR(WINED3D_LOCATION_DISCARDED);
6322     LOCATION_TO_STR(WINED3D_LOCATION_SYSMEM);
6323     LOCATION_TO_STR(WINED3D_LOCATION_USER_MEMORY);
6324     LOCATION_TO_STR(WINED3D_LOCATION_BUFFER);
6325     LOCATION_TO_STR(WINED3D_LOCATION_TEXTURE_RGB);
6326     LOCATION_TO_STR(WINED3D_LOCATION_TEXTURE_SRGB);
6327     LOCATION_TO_STR(WINED3D_LOCATION_DRAWABLE);
6328     LOCATION_TO_STR(WINED3D_LOCATION_RB_MULTISAMPLE);
6329     LOCATION_TO_STR(WINED3D_LOCATION_RB_RESOLVED);
6330 #undef LOCATION_TO_STR
6331     if (location)
6332         FIXME("Unrecognized location flag(s) %#x.\n", location);
6333 
6334     return wine_dbg_sprintf("%s%s%s", prefix, buffer.str, suffix);
6335 }
6336 
6337 /* Print a floating point value with the %.8e format specifier, always using
6338  * '.' as decimal separator. */
6339 void wined3d_ftoa(float value, char *s)
6340 {
6341     int idx = 1;
6342 
6343     if (copysignf(1.0f, value) < 0.0f)
6344         ++idx;
6345 
6346     /* Be sure to allocate a buffer of at least 17 characters for the result
6347        as sprintf may return a 3 digit exponent when using the MSVC runtime
6348        instead of a 2 digit exponent. */
6349     sprintf(s, "%.8e", value);
6350     if (isfinite(value))
6351         s[idx] = '.';
6352 }
6353 
6354 void wined3d_release_dc(HWND window, HDC dc)
6355 {
6356     /* You'd figure ReleaseDC() would fail if the DC doesn't match the window.
6357      * However, that's not what actually happens, and there are user32 tests
6358      * that confirm ReleaseDC() with the wrong window is supposed to succeed.
6359      * So explicitly check that the DC belongs to the window, since we want to
6360      * avoid releasing a DC that belongs to some other window if the original
6361      * window was already destroyed. */
6362     if (WindowFromDC(dc) != window)
6363         WARN("DC %p does not belong to window %p.\n", dc, window);
6364     else if (!ReleaseDC(window, dc))
6365         ERR("Failed to release device context %p, last error %#x.\n", dc, GetLastError());
6366 }
6367 
6368 BOOL wined3d_clip_blit(const RECT *clip_rect, RECT *clipped, RECT *other)
6369 {
6370     RECT orig = *clipped;
6371     float scale_x = (float)(orig.right - orig.left) / (float)(other->right - other->left);
6372     float scale_y = (float)(orig.bottom - orig.top) / (float)(other->bottom - other->top);
6373 
6374     IntersectRect(clipped, clipped, clip_rect);
6375 
6376     if (IsRectEmpty(clipped))
6377     {
6378         SetRectEmpty(other);
6379         return FALSE;
6380     }
6381 
6382     other->left += (LONG)((clipped->left - orig.left) / scale_x);
6383     other->top += (LONG)((clipped->top - orig.top) / scale_y);
6384     other->right -= (LONG)((orig.right - clipped->right) / scale_x);
6385     other->bottom -= (LONG)((orig.bottom - clipped->bottom) / scale_y);
6386 
6387     return TRUE;
6388 }
6389 
6390 void wined3d_gl_limits_get_uniform_block_range(const struct wined3d_gl_limits *gl_limits,
6391         enum wined3d_shader_type shader_type, unsigned int *base, unsigned int *count)
6392 {
6393     unsigned int i;
6394 
6395     *base = 0;
6396     for (i = 0; i < WINED3D_SHADER_TYPE_COUNT; ++i)
6397     {
6398         *count = gl_limits->uniform_blocks[i];
6399         if (i == shader_type)
6400             return;
6401         *base += *count;
6402     }
6403 
6404     ERR("Unrecognized shader type %#x.\n", shader_type);
6405     *count = 0;
6406 }
6407 
6408 void wined3d_gl_limits_get_texture_unit_range(const struct wined3d_gl_limits *gl_limits,
6409         enum wined3d_shader_type shader_type, unsigned int *base, unsigned int *count)
6410 {
6411     unsigned int i;
6412 
6413     if (shader_type == WINED3D_SHADER_TYPE_COMPUTE)
6414     {
6415         if (gl_limits->combined_samplers == gl_limits->graphics_samplers)
6416             *base = 0;
6417         else
6418             *base = gl_limits->graphics_samplers;
6419         *count = gl_limits->samplers[WINED3D_SHADER_TYPE_COMPUTE];
6420         return;
6421     }
6422 
6423     *base = 0;
6424     for (i = 0; i < WINED3D_SHADER_TYPE_GRAPHICS_COUNT; ++i)
6425     {
6426         *count = gl_limits->samplers[i];
6427         if (i == shader_type)
6428             return;
6429         *base += *count;
6430     }
6431 
6432     ERR("Unrecognized shader type %#x.\n", shader_type);
6433     *count = 0;
6434 }
6435 
6436 BOOL wined3d_array_reserve(void **elements, SIZE_T *capacity, SIZE_T count, SIZE_T size)
6437 {
6438     SIZE_T max_capacity, new_capacity;
6439     void *new_elements;
6440 
6441     if (count <= *capacity)
6442         return TRUE;
6443 
6444     max_capacity = ~(SIZE_T)0 / size;
6445     if (count > max_capacity)
6446         return FALSE;
6447 
6448     new_capacity = max(1, *capacity);
6449     while (new_capacity < count && new_capacity <= max_capacity / 2)
6450         new_capacity *= 2;
6451     if (new_capacity < count)
6452         new_capacity = count;
6453 
6454     if (!*elements)
6455         new_elements = heap_alloc_zero(new_capacity * size);
6456     else
6457         new_elements = HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, *elements, new_capacity * size);
6458     if (!new_elements)
6459         return FALSE;
6460 
6461     *elements = new_elements;
6462     *capacity = new_capacity;
6463     return TRUE;
6464 }
6465