* Slap *some* sense into our header inclusions.
[reactos.git] / reactos / dll / directx / wine / wined3d / utils.c
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 "wined3d_private.h"
31
32 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
33
34 struct wined3d_format_channels
35 {
36 enum wined3d_format_id id;
37 DWORD red_size, green_size, blue_size, alpha_size;
38 DWORD red_offset, green_offset, blue_offset, alpha_offset;
39 UINT bpp;
40 BYTE depth_size, stencil_size;
41 };
42
43 static const struct wined3d_format_channels formats[] =
44 {
45 /* size offset
46 * format id r g b a r g b a bpp depth stencil */
47 {WINED3DFMT_UNKNOWN, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
48 /* FourCC formats */
49 {WINED3DFMT_UYVY, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
50 {WINED3DFMT_YUY2, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
51 {WINED3DFMT_YV12, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
52 {WINED3DFMT_DXT1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
53 {WINED3DFMT_DXT2, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
54 {WINED3DFMT_DXT3, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
55 {WINED3DFMT_DXT4, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
56 {WINED3DFMT_DXT5, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
57 {WINED3DFMT_MULTI2_ARGB8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
58 {WINED3DFMT_G8R8_G8B8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
59 {WINED3DFMT_R8G8_B8G8, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
60 /* IEEE formats */
61 {WINED3DFMT_R32_FLOAT, 32, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0},
62 {WINED3DFMT_R32G32_FLOAT, 32, 32, 0, 0, 0, 32, 0, 0, 8, 0, 0},
63 {WINED3DFMT_R32G32B32_FLOAT, 32, 32, 32, 0, 0, 32, 64, 0, 12, 0, 0},
64 {WINED3DFMT_R32G32B32A32_FLOAT, 32, 32, 32, 32, 0, 32, 64, 96, 16, 0, 0},
65 /* Hmm? */
66 {WINED3DFMT_R8G8_SNORM_Cx, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
67 /* Float */
68 {WINED3DFMT_R16_FLOAT, 16, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
69 {WINED3DFMT_R16G16_FLOAT, 16, 16, 0, 0, 0, 16, 0, 0, 4, 0, 0},
70 {WINED3DFMT_R16G16_SINT, 16, 16, 0, 0, 0, 16, 0, 0, 4, 0, 0},
71 {WINED3DFMT_R16G16B16A16_FLOAT, 16, 16, 16, 16, 0, 16, 32, 48, 8, 0, 0},
72 {WINED3DFMT_R16G16B16A16_SINT, 16, 16, 16, 16, 0, 16, 32, 48, 8, 0, 0},
73 /* Palettized formats */
74 {WINED3DFMT_P8_UINT_A8_UNORM, 0, 0, 0, 8, 0, 0, 0, 8, 2, 0, 0},
75 {WINED3DFMT_P8_UINT, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
76 /* Standard ARGB formats. */
77 {WINED3DFMT_B8G8R8_UNORM, 8, 8, 8, 0, 16, 8, 0, 0, 3, 0, 0},
78 {WINED3DFMT_B8G8R8A8_UNORM, 8, 8, 8, 8, 16, 8, 0, 24, 4, 0, 0},
79 {WINED3DFMT_B8G8R8X8_UNORM, 8, 8, 8, 0, 16, 8, 0, 0, 4, 0, 0},
80 {WINED3DFMT_B5G6R5_UNORM, 5, 6, 5, 0, 11, 5, 0, 0, 2, 0, 0},
81 {WINED3DFMT_B5G5R5X1_UNORM, 5, 5, 5, 0, 10, 5, 0, 0, 2, 0, 0},
82 {WINED3DFMT_B5G5R5A1_UNORM, 5, 5, 5, 1, 10, 5, 0, 15, 2, 0, 0},
83 {WINED3DFMT_B4G4R4A4_UNORM, 4, 4, 4, 4, 8, 4, 0, 12, 2, 0, 0},
84 {WINED3DFMT_B2G3R3_UNORM, 3, 3, 2, 0, 5, 2, 0, 0, 1, 0, 0},
85 {WINED3DFMT_A8_UNORM, 0, 0, 0, 8, 0, 0, 0, 0, 1, 0, 0},
86 {WINED3DFMT_B2G3R3A8_UNORM, 3, 3, 2, 8, 5, 2, 0, 8, 2, 0, 0},
87 {WINED3DFMT_B4G4R4X4_UNORM, 4, 4, 4, 0, 8, 4, 0, 0, 2, 0, 0},
88 {WINED3DFMT_R10G10B10A2_UNORM, 10, 10, 10, 2, 0, 10, 20, 30, 4, 0, 0},
89 {WINED3DFMT_R10G10B10A2_UINT, 10, 10, 10, 2, 0, 10, 20, 30, 4, 0, 0},
90 {WINED3DFMT_R10G10B10A2_SNORM, 10, 10, 10, 2, 0, 10, 20, 30, 4, 0, 0},
91 {WINED3DFMT_R8G8B8A8_UNORM, 8, 8, 8, 8, 0, 8, 16, 24, 4, 0, 0},
92 {WINED3DFMT_R8G8B8A8_UINT, 8, 8, 8, 8, 0, 8, 16, 24, 4, 0, 0},
93 {WINED3DFMT_R8G8B8X8_UNORM, 8, 8, 8, 0, 0, 8, 16, 0, 4, 0, 0},
94 {WINED3DFMT_R16G16_UNORM, 16, 16, 0, 0, 0, 16, 0, 0, 4, 0, 0},
95 {WINED3DFMT_B10G10R10A2_UNORM, 10, 10, 10, 2, 20, 10, 0, 30, 4, 0, 0},
96 {WINED3DFMT_R16G16B16A16_UNORM, 16, 16, 16, 16, 0, 16, 32, 48, 8, 0, 0},
97 /* Luminance */
98 {WINED3DFMT_L8_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
99 {WINED3DFMT_L8A8_UNORM, 0, 0, 0, 8, 0, 0, 0, 8, 2, 0, 0},
100 {WINED3DFMT_L4A4_UNORM, 0, 0, 0, 4, 0, 0, 0, 4, 1, 0, 0},
101 {WINED3DFMT_L16_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
102 /* Bump mapping stuff */
103 {WINED3DFMT_R8G8_SNORM, 8, 8, 0, 0, 0, 8, 0, 0, 2, 0, 0},
104 {WINED3DFMT_R5G5_SNORM_L6_UNORM, 5, 5, 0, 0, 0, 5, 0, 0, 2, 0, 0},
105 {WINED3DFMT_R8G8_SNORM_L8X8_UNORM, 8, 8, 0, 0, 0, 8, 0, 0, 4, 0, 0},
106 {WINED3DFMT_R8G8B8A8_SNORM, 8, 8, 8, 8, 0, 8, 16, 24, 4, 0, 0},
107 {WINED3DFMT_R16G16_SNORM, 16, 16, 0, 0, 0, 16, 0, 0, 4, 0, 0},
108 {WINED3DFMT_R10G11B11_SNORM, 10, 11, 11, 0, 0, 10, 21, 0, 4, 0, 0},
109 {WINED3DFMT_R10G10B10_SNORM_A2_UNORM, 10, 10, 10, 2, 0, 10, 20, 30, 4, 0, 0},
110 /* Depth stencil formats */
111 {WINED3DFMT_D16_LOCKABLE, 0, 0, 0, 0, 0, 0, 0, 0, 2, 16, 0},
112 {WINED3DFMT_D32_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 0},
113 {WINED3DFMT_S1_UINT_D15_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 2, 15, 1},
114 {WINED3DFMT_D24_UNORM_S8_UINT, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 8},
115 {WINED3DFMT_X8D24_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 0},
116 {WINED3DFMT_S4X4_UINT_D24_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 4},
117 {WINED3DFMT_D16_UNORM, 0, 0, 0, 0, 0, 0, 0, 0, 2, 16, 0},
118 {WINED3DFMT_D32_FLOAT, 0, 0, 0, 0, 0, 0, 0, 0, 4, 32, 0},
119 {WINED3DFMT_S8_UINT_D24_FLOAT, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 8},
120 {WINED3DFMT_VERTEXDATA, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
121 {WINED3DFMT_R16_UINT, 16, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
122 {WINED3DFMT_R32_UINT, 32, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0},
123 {WINED3DFMT_R16G16B16A16_SNORM, 16, 16, 16, 16, 0, 16, 32, 48, 8, 0, 0},
124 /* Vendor-specific formats */
125 {WINED3DFMT_ATI2N, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0},
126 {WINED3DFMT_NVDB, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
127 {WINED3DFMT_INTZ, 0, 0, 0, 0, 0, 0, 0, 0, 4, 24, 8},
128 {WINED3DFMT_NVHU, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
129 {WINED3DFMT_NVHS, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
130 {WINED3DFMT_NULL, 8, 8, 8, 8, 0, 8, 16, 24, 4, 0, 0},
131 /* Unsure about them, could not find a Windows driver that supports them */
132 {WINED3DFMT_R16, 16, 0, 0, 0, 0, 0, 0, 0, 2, 0, 0},
133 {WINED3DFMT_AL16, 0, 0, 0, 16, 0, 0, 0, 16, 4, 0, 0},
134 };
135
136 struct wined3d_format_base_flags
137 {
138 enum wined3d_format_id id;
139 DWORD flags;
140 };
141
142 /* The ATI2N format behaves like an uncompressed format in LockRect(), but
143 * still needs to use the correct block based calculation for e.g. the
144 * resource size. */
145 static const struct wined3d_format_base_flags format_base_flags[] =
146 {
147 {WINED3DFMT_UYVY, WINED3DFMT_FLAG_FOURCC},
148 {WINED3DFMT_YUY2, WINED3DFMT_FLAG_FOURCC},
149 {WINED3DFMT_YV12, WINED3DFMT_FLAG_FOURCC},
150 {WINED3DFMT_DXT1, WINED3DFMT_FLAG_FOURCC},
151 {WINED3DFMT_DXT2, WINED3DFMT_FLAG_FOURCC},
152 {WINED3DFMT_DXT3, WINED3DFMT_FLAG_FOURCC},
153 {WINED3DFMT_DXT4, WINED3DFMT_FLAG_FOURCC},
154 {WINED3DFMT_DXT5, WINED3DFMT_FLAG_FOURCC},
155 {WINED3DFMT_MULTI2_ARGB8, WINED3DFMT_FLAG_FOURCC},
156 {WINED3DFMT_G8R8_G8B8, WINED3DFMT_FLAG_FOURCC},
157 {WINED3DFMT_R8G8_B8G8, WINED3DFMT_FLAG_FOURCC},
158 {WINED3DFMT_INTZ, WINED3DFMT_FLAG_FOURCC},
159 {WINED3DFMT_NULL, WINED3DFMT_FLAG_FOURCC},
160 {WINED3DFMT_P8_UINT, WINED3DFMT_FLAG_GETDC},
161 {WINED3DFMT_B8G8R8_UNORM, WINED3DFMT_FLAG_GETDC},
162 {WINED3DFMT_B8G8R8A8_UNORM, WINED3DFMT_FLAG_GETDC},
163 {WINED3DFMT_B8G8R8X8_UNORM, WINED3DFMT_FLAG_GETDC},
164 {WINED3DFMT_B5G6R5_UNORM, WINED3DFMT_FLAG_GETDC},
165 {WINED3DFMT_B5G5R5X1_UNORM, WINED3DFMT_FLAG_GETDC},
166 {WINED3DFMT_B5G5R5A1_UNORM, WINED3DFMT_FLAG_GETDC},
167 {WINED3DFMT_B4G4R4A4_UNORM, WINED3DFMT_FLAG_GETDC},
168 {WINED3DFMT_B4G4R4X4_UNORM, WINED3DFMT_FLAG_GETDC},
169 {WINED3DFMT_R8G8B8A8_UNORM, WINED3DFMT_FLAG_GETDC},
170 {WINED3DFMT_R8G8B8X8_UNORM, WINED3DFMT_FLAG_GETDC},
171 {WINED3DFMT_ATI2N, WINED3DFMT_FLAG_FOURCC | WINED3DFMT_FLAG_BROKEN_PITCH},
172 {WINED3DFMT_NVDB, WINED3DFMT_FLAG_FOURCC},
173 {WINED3DFMT_NVHU, WINED3DFMT_FLAG_FOURCC},
174 {WINED3DFMT_NVHS, WINED3DFMT_FLAG_FOURCC},
175 {WINED3DFMT_R32_FLOAT, WINED3DFMT_FLAG_FLOAT},
176 {WINED3DFMT_R32G32_FLOAT, WINED3DFMT_FLAG_FLOAT},
177 {WINED3DFMT_R32G32B32_FLOAT, WINED3DFMT_FLAG_FLOAT},
178 {WINED3DFMT_R32G32B32A32_FLOAT, WINED3DFMT_FLAG_FLOAT},
179 {WINED3DFMT_R16_FLOAT, WINED3DFMT_FLAG_FLOAT},
180 {WINED3DFMT_R16G16_FLOAT, WINED3DFMT_FLAG_FLOAT},
181 {WINED3DFMT_R16G16B16A16_FLOAT, WINED3DFMT_FLAG_FLOAT},
182 {WINED3DFMT_D32_FLOAT, WINED3DFMT_FLAG_FLOAT},
183 {WINED3DFMT_S8_UINT_D24_FLOAT, WINED3DFMT_FLAG_FLOAT},
184 };
185
186 struct wined3d_format_block_info
187 {
188 enum wined3d_format_id id;
189 UINT block_width;
190 UINT block_height;
191 UINT block_byte_count;
192 };
193
194 static const struct wined3d_format_block_info format_block_info[] =
195 {
196 {WINED3DFMT_DXT1, 4, 4, 8},
197 {WINED3DFMT_DXT2, 4, 4, 16},
198 {WINED3DFMT_DXT3, 4, 4, 16},
199 {WINED3DFMT_DXT4, 4, 4, 16},
200 {WINED3DFMT_DXT5, 4, 4, 16},
201 {WINED3DFMT_ATI2N, 4, 4, 16},
202 {WINED3DFMT_YUY2, 2, 1, 4},
203 {WINED3DFMT_UYVY, 2, 1, 4},
204 };
205
206 struct wined3d_format_vertex_info
207 {
208 enum wined3d_format_id id;
209 enum wined3d_ffp_emit_idx emit_idx;
210 GLint component_count;
211 GLenum gl_vtx_type;
212 GLint gl_vtx_format;
213 GLboolean gl_normalized;
214 unsigned int component_size;
215 };
216
217 static const struct wined3d_format_vertex_info format_vertex_info[] =
218 {
219 {WINED3DFMT_R32_FLOAT, WINED3D_FFP_EMIT_FLOAT1, 1, GL_FLOAT, 1, GL_FALSE, sizeof(float)},
220 {WINED3DFMT_R32G32_FLOAT, WINED3D_FFP_EMIT_FLOAT2, 2, GL_FLOAT, 2, GL_FALSE, sizeof(float)},
221 {WINED3DFMT_R32G32B32_FLOAT, WINED3D_FFP_EMIT_FLOAT3, 3, GL_FLOAT, 3, GL_FALSE, sizeof(float)},
222 {WINED3DFMT_R32G32B32A32_FLOAT, WINED3D_FFP_EMIT_FLOAT4, 4, GL_FLOAT, 4, GL_FALSE, sizeof(float)},
223 {WINED3DFMT_B8G8R8A8_UNORM, WINED3D_FFP_EMIT_D3DCOLOR, 4, GL_UNSIGNED_BYTE, 4, GL_TRUE, sizeof(BYTE)},
224 {WINED3DFMT_R8G8B8A8_UINT, WINED3D_FFP_EMIT_UBYTE4, 4, GL_UNSIGNED_BYTE, 4, GL_FALSE, sizeof(BYTE)},
225 {WINED3DFMT_R16G16_SINT, WINED3D_FFP_EMIT_SHORT2, 2, GL_SHORT, 2, GL_FALSE, sizeof(short int)},
226 {WINED3DFMT_R16G16B16A16_SINT, WINED3D_FFP_EMIT_SHORT4, 4, GL_SHORT, 4, GL_FALSE, sizeof(short int)},
227 {WINED3DFMT_R8G8B8A8_UNORM, WINED3D_FFP_EMIT_UBYTE4N, 4, GL_UNSIGNED_BYTE, 4, GL_TRUE, sizeof(BYTE)},
228 {WINED3DFMT_R16G16_SNORM, WINED3D_FFP_EMIT_SHORT2N, 2, GL_SHORT, 2, GL_TRUE, sizeof(short int)},
229 {WINED3DFMT_R16G16B16A16_SNORM, WINED3D_FFP_EMIT_SHORT4N, 4, GL_SHORT, 4, GL_TRUE, sizeof(short int)},
230 {WINED3DFMT_R16G16_UNORM, WINED3D_FFP_EMIT_USHORT2N, 2, GL_UNSIGNED_SHORT, 2, GL_TRUE, sizeof(short int)},
231 {WINED3DFMT_R16G16B16A16_UNORM, WINED3D_FFP_EMIT_USHORT4N, 4, GL_UNSIGNED_SHORT, 4, GL_TRUE, sizeof(short int)},
232 {WINED3DFMT_R10G10B10A2_UINT, WINED3D_FFP_EMIT_UDEC3, 3, GL_UNSIGNED_SHORT, 3, GL_FALSE, sizeof(short int)},
233 {WINED3DFMT_R10G10B10A2_SNORM, WINED3D_FFP_EMIT_DEC3N, 3, GL_SHORT, 3, GL_TRUE, sizeof(short int)},
234 {WINED3DFMT_R16G16_FLOAT, WINED3D_FFP_EMIT_FLOAT16_2, 2, GL_FLOAT, 2, GL_FALSE, sizeof(GLhalfNV)},
235 {WINED3DFMT_R16G16B16A16_FLOAT, WINED3D_FFP_EMIT_FLOAT16_4, 4, GL_FLOAT, 4, GL_FALSE, sizeof(GLhalfNV)}
236 };
237
238 struct wined3d_format_texture_info
239 {
240 enum wined3d_format_id id;
241 GLint gl_internal;
242 GLint gl_srgb_internal;
243 GLint gl_rt_internal;
244 GLint gl_format;
245 GLint gl_type;
246 unsigned int conv_byte_count;
247 unsigned int flags;
248 enum wined3d_gl_extension extension;
249 void (*convert)(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height);
250 };
251
252 static void convert_l4a4_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
253 {
254 /* WINED3DFMT_L4A4_UNORM exists as an internal gl format, but for some reason there is not
255 * format+type combination to load it. Thus convert it to A8L8, then load it
256 * with A4L4 internal, but A8L8 format+type
257 */
258 unsigned int x, y;
259 const unsigned char *Source;
260 unsigned char *Dest;
261 UINT outpitch = pitch * 2;
262
263 for(y = 0; y < height; y++) {
264 Source = src + y * pitch;
265 Dest = dst + y * outpitch;
266 for (x = 0; x < width; x++ ) {
267 unsigned char color = (*Source++);
268 /* A */ Dest[1] = (color & 0xf0) << 0;
269 /* L */ Dest[0] = (color & 0x0f) << 4;
270 Dest += 2;
271 }
272 }
273 }
274
275 static void convert_r5g5_snorm_l6_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
276 {
277 unsigned int x, y;
278 const WORD *Source;
279
280 for(y = 0; y < height; y++)
281 {
282 unsigned short *Dest_s = (unsigned short *) (dst + y * pitch);
283 Source = (const WORD *)(src + y * pitch);
284 for (x = 0; x < width; x++ )
285 {
286 short color = (*Source++);
287 unsigned char l = ((color >> 10) & 0xfc);
288 short v = ((color >> 5) & 0x3e);
289 short u = ((color ) & 0x1f);
290 short v_conv = v + 16;
291 short u_conv = u + 16;
292
293 *Dest_s = ((v_conv << 11) & 0xf800) | ((l << 5) & 0x7e0) | (u_conv & 0x1f);
294 Dest_s += 1;
295 }
296 }
297 }
298
299 static void convert_r5g5_snorm_l6_unorm_nv(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
300 {
301 unsigned int x, y;
302 const WORD *Source;
303 unsigned char *Dest;
304 UINT outpitch = (pitch * 3)/2;
305
306 /* This makes the gl surface bigger(24 bit instead of 16), but it works with
307 * fixed function and shaders without further conversion once the surface is
308 * loaded
309 */
310 for(y = 0; y < height; y++) {
311 Source = (const WORD *)(src + y * pitch);
312 Dest = dst + y * outpitch;
313 for (x = 0; x < width; x++ ) {
314 short color = (*Source++);
315 unsigned char l = ((color >> 10) & 0xfc);
316 char v = ((color >> 5) & 0x3e);
317 char u = ((color ) & 0x1f);
318
319 /* 8 bits destination, 6 bits source, 8th bit is the sign. gl ignores the sign
320 * and doubles the positive range. Thus shift left only once, gl does the 2nd
321 * shift. GL reads a signed value and converts it into an unsigned value.
322 */
323 /* M */ Dest[2] = l << 1;
324
325 /* Those are read as signed, but kept signed. Just left-shift 3 times to scale
326 * from 5 bit values to 8 bit values.
327 */
328 /* V */ Dest[1] = v << 3;
329 /* U */ Dest[0] = u << 3;
330 Dest += 3;
331 }
332 }
333 }
334
335 static void convert_r8g8_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
336 {
337 unsigned int x, y;
338 const short *Source;
339 unsigned char *Dest;
340 UINT outpitch = (pitch * 3)/2;
341
342 for(y = 0; y < height; y++)
343 {
344 Source = (const short *)(src + y * pitch);
345 Dest = dst + y * outpitch;
346 for (x = 0; x < width; x++ )
347 {
348 const short color = (*Source++);
349 /* B */ Dest[0] = 0xff;
350 /* G */ Dest[1] = (color >> 8) + 128; /* V */
351 /* R */ Dest[2] = (color & 0xff) + 128; /* U */
352 Dest += 3;
353 }
354 }
355 }
356
357 static void convert_r8g8_snorm_l8x8_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
358 {
359 unsigned int x, y;
360 const DWORD *Source;
361 unsigned char *Dest;
362
363 /* Doesn't work correctly with the fixed function pipeline, but can work in
364 * shaders if the shader is adjusted. (There's no use for this format in gl's
365 * standard fixed function pipeline anyway).
366 */
367 for(y = 0; y < height; y++)
368 {
369 Source = (const DWORD *)(src + y * pitch);
370 Dest = dst + y * pitch;
371 for (x = 0; x < width; x++ )
372 {
373 LONG color = (*Source++);
374 /* B */ Dest[0] = ((color >> 16) & 0xff); /* L */
375 /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
376 /* R */ Dest[2] = (color & 0xff) + 128; /* U */
377 Dest += 4;
378 }
379 }
380 }
381
382 static void convert_r8g8_snorm_l8x8_unorm_nv(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
383 {
384 unsigned int x, y;
385 const DWORD *Source;
386 unsigned char *Dest;
387
388 /* This implementation works with the fixed function pipeline and shaders
389 * without further modification after converting the surface.
390 */
391 for(y = 0; y < height; y++)
392 {
393 Source = (const DWORD *)(src + y * pitch);
394 Dest = dst + y * pitch;
395 for (x = 0; x < width; x++ )
396 {
397 LONG color = (*Source++);
398 /* L */ Dest[2] = ((color >> 16) & 0xff); /* L */
399 /* V */ Dest[1] = ((color >> 8 ) & 0xff); /* V */
400 /* U */ Dest[0] = (color & 0xff); /* U */
401 /* I */ Dest[3] = 255; /* X */
402 Dest += 4;
403 }
404 }
405 }
406
407 static void convert_r8g8b8a8_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
408 {
409 unsigned int x, y;
410 const DWORD *Source;
411 unsigned char *Dest;
412
413 for(y = 0; y < height; y++)
414 {
415 Source = (const DWORD *)(src + y * pitch);
416 Dest = dst + y * pitch;
417 for (x = 0; x < width; x++ )
418 {
419 LONG color = (*Source++);
420 /* B */ Dest[0] = ((color >> 16) & 0xff) + 128; /* W */
421 /* G */ Dest[1] = ((color >> 8 ) & 0xff) + 128; /* V */
422 /* R */ Dest[2] = (color & 0xff) + 128; /* U */
423 /* A */ Dest[3] = ((color >> 24) & 0xff) + 128; /* Q */
424 Dest += 4;
425 }
426 }
427 }
428
429 static void convert_r16g16_snorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
430 {
431 unsigned int x, y;
432 const DWORD *Source;
433 unsigned short *Dest;
434 UINT outpitch = (pitch * 3)/2;
435
436 for(y = 0; y < height; y++)
437 {
438 Source = (const DWORD *)(src + y * pitch);
439 Dest = (unsigned short *) (dst + y * outpitch);
440 for (x = 0; x < width; x++ )
441 {
442 const DWORD color = (*Source++);
443 /* B */ Dest[0] = 0xffff;
444 /* G */ Dest[1] = (color >> 16) + 32768; /* V */
445 /* R */ Dest[2] = (color & 0xffff) + 32768; /* U */
446 Dest += 3;
447 }
448 }
449 }
450
451 static void convert_r16g16(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
452 {
453 unsigned int x, y;
454 const WORD *Source;
455 WORD *Dest;
456 UINT outpitch = (pitch * 3)/2;
457
458 for(y = 0; y < height; y++)
459 {
460 Source = (const WORD *)(src + y * pitch);
461 Dest = (WORD *) (dst + y * outpitch);
462 for (x = 0; x < width; x++ )
463 {
464 WORD green = (*Source++);
465 WORD red = (*Source++);
466 Dest[0] = green;
467 Dest[1] = red;
468 /* Strictly speaking not correct for R16G16F, but it doesn't matter because the
469 * shader overwrites it anyway
470 */
471 Dest[2] = 0xffff;
472 Dest += 3;
473 }
474 }
475 }
476
477 static void convert_r32g32_float(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
478 {
479 unsigned int x, y;
480 const float *Source;
481 float *Dest;
482 UINT outpitch = (pitch * 3)/2;
483
484 for(y = 0; y < height; y++)
485 {
486 Source = (const float *)(src + y * pitch);
487 Dest = (float *) (dst + y * outpitch);
488 for (x = 0; x < width; x++ )
489 {
490 float green = (*Source++);
491 float red = (*Source++);
492 Dest[0] = green;
493 Dest[1] = red;
494 Dest[2] = 1.0f;
495 Dest += 3;
496 }
497 }
498 }
499
500 static void convert_s1_uint_d15_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
501 {
502 unsigned int x, y;
503 UINT outpitch = pitch * 2;
504
505 for (y = 0; y < height; ++y)
506 {
507 const WORD *source = (const WORD *)(src + y * pitch);
508 DWORD *dest = (DWORD *)(dst + y * outpitch);
509
510 for (x = 0; x < width; ++x)
511 {
512 /* The depth data is normalized, so needs to be scaled,
513 * the stencil data isn't. Scale depth data by
514 * (2^24-1)/(2^15-1) ~~ (2^9 + 2^-6). */
515 WORD d15 = source[x] >> 1;
516 DWORD d24 = (d15 << 9) + (d15 >> 6);
517 dest[x] = (d24 << 8) | (source[x] & 0x1);
518 }
519 }
520 }
521
522 static void convert_s4x4_uint_d24_unorm(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
523 {
524 unsigned int x, y;
525
526 for (y = 0; y < height; ++y)
527 {
528 const DWORD *source = (const DWORD *)(src + y * pitch);
529 DWORD *dest = (DWORD *)(dst + y * pitch);
530
531 for (x = 0; x < width; ++x)
532 {
533 /* Just need to clear out the X4 part. */
534 dest[x] = source[x] & ~0xf0;
535 }
536 }
537 }
538
539 static void convert_s8_uint_d24_float(const BYTE *src, BYTE *dst, UINT pitch, UINT width, UINT height)
540 {
541 unsigned int x, y;
542 UINT outpitch = pitch * 2;
543
544 for (y = 0; y < height; ++y)
545 {
546 const DWORD *source = (const DWORD *)(src + y * pitch);
547 float *dest_f = (float *)(dst + y * outpitch);
548 DWORD *dest_s = (DWORD *)(dst + y * outpitch);
549
550 for (x = 0; x < width; ++x)
551 {
552 dest_f[x * 2] = float_24_to_32((source[x] & 0xffffff00) >> 8);
553 dest_s[x * 2 + 1] = source[x] & 0xff;
554 }
555 }
556 }
557
558 static const struct wined3d_format_texture_info format_texture_info[] =
559 {
560 /* format id internal srgbInternal rtInternal
561 format type
562 flags
563 extension */
564 /* FourCC formats */
565 /* GL_APPLE_ycbcr_422 claims that its '2YUV' format, which is supported via the UNSIGNED_SHORT_8_8_REV_APPLE type
566 * is equivalent to 'UYVY' format on Windows, and the 'YUVS' via UNSIGNED_SHORT_8_8_APPLE equates to 'YUY2'. The
567 * d3d9 test however shows that the opposite is true. Since the extension is from 2002, it predates the x86 based
568 * Macs, so probably the endianness differs. This could be tested as soon as we have a Windows and MacOS on a big
569 * endian machine
570 */
571 {WINED3DFMT_UYVY, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, 0,
572 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0,
573 WINED3DFMT_FLAG_FILTERING,
574 WINED3D_GL_EXT_NONE, NULL},
575 {WINED3DFMT_UYVY, GL_RGB, GL_RGB, 0,
576 GL_YCBCR_422_APPLE, UNSIGNED_SHORT_8_8_APPLE, 0,
577 WINED3DFMT_FLAG_FILTERING,
578 APPLE_YCBCR_422, NULL},
579 {WINED3DFMT_YUY2, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, 0,
580 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0,
581 WINED3DFMT_FLAG_FILTERING,
582 WINED3D_GL_EXT_NONE, NULL},
583 {WINED3DFMT_YUY2, GL_RGB, GL_RGB, 0,
584 GL_YCBCR_422_APPLE, UNSIGNED_SHORT_8_8_REV_APPLE, 0,
585 WINED3DFMT_FLAG_FILTERING,
586 APPLE_YCBCR_422, NULL},
587 {WINED3DFMT_YV12, GL_ALPHA, GL_ALPHA, 0,
588 GL_ALPHA, GL_UNSIGNED_BYTE, 0,
589 WINED3DFMT_FLAG_FILTERING,
590 WINED3D_GL_EXT_NONE, NULL},
591 {WINED3DFMT_DXT1, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, 0,
592 GL_RGBA, GL_UNSIGNED_BYTE, 0,
593 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ
594 | WINED3DFMT_FLAG_COMPRESSED,
595 EXT_TEXTURE_COMPRESSION_S3TC, NULL},
596 {WINED3DFMT_DXT2, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
597 GL_RGBA, GL_UNSIGNED_BYTE, 0,
598 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ
599 | WINED3DFMT_FLAG_COMPRESSED,
600 EXT_TEXTURE_COMPRESSION_S3TC, NULL},
601 {WINED3DFMT_DXT3, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, 0,
602 GL_RGBA, GL_UNSIGNED_BYTE, 0,
603 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ
604 | WINED3DFMT_FLAG_COMPRESSED,
605 EXT_TEXTURE_COMPRESSION_S3TC, NULL},
606 {WINED3DFMT_DXT4, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
607 GL_RGBA, GL_UNSIGNED_BYTE, 0,
608 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ
609 | WINED3DFMT_FLAG_COMPRESSED,
610 EXT_TEXTURE_COMPRESSION_S3TC, NULL},
611 {WINED3DFMT_DXT5, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, 0,
612 GL_RGBA, GL_UNSIGNED_BYTE, 0,
613 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ
614 | WINED3DFMT_FLAG_COMPRESSED,
615 EXT_TEXTURE_COMPRESSION_S3TC, NULL},
616 /* IEEE formats */
617 {WINED3DFMT_R32_FLOAT, GL_RGB32F_ARB, GL_RGB32F_ARB, 0,
618 GL_RED, GL_FLOAT, 0,
619 WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
620 ARB_TEXTURE_FLOAT, NULL},
621 {WINED3DFMT_R32_FLOAT, GL_R32F, GL_R32F, 0,
622 GL_RED, GL_FLOAT, 0,
623 WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
624 ARB_TEXTURE_RG, NULL},
625 {WINED3DFMT_R32G32_FLOAT, GL_RGB32F_ARB, GL_RGB32F_ARB, 0,
626 GL_RGB, GL_FLOAT, 12,
627 WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
628 ARB_TEXTURE_FLOAT, convert_r32g32_float},
629 {WINED3DFMT_R32G32_FLOAT, GL_RG32F, GL_RG32F, 0,
630 GL_RG, GL_FLOAT, 0,
631 WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
632 ARB_TEXTURE_RG, NULL},
633 {WINED3DFMT_R32G32B32A32_FLOAT, GL_RGBA32F_ARB, GL_RGBA32F_ARB, 0,
634 GL_RGBA, GL_FLOAT, 0,
635 WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
636 ARB_TEXTURE_FLOAT, NULL},
637 /* Float */
638 {WINED3DFMT_R16_FLOAT, GL_RGB16F_ARB, GL_RGB16F_ARB, 0,
639 GL_RED, GL_HALF_FLOAT_ARB, 0,
640 WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
641 ARB_TEXTURE_FLOAT, NULL},
642 {WINED3DFMT_R16_FLOAT, GL_R16F, GL_R16F, 0,
643 GL_RED, GL_HALF_FLOAT_ARB, 0,
644 WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
645 ARB_TEXTURE_RG, NULL},
646 {WINED3DFMT_R16G16_FLOAT, GL_RGB16F_ARB, GL_RGB16F_ARB, 0,
647 GL_RGB, GL_HALF_FLOAT_ARB, 6,
648 WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
649 ARB_TEXTURE_FLOAT, convert_r16g16},
650 {WINED3DFMT_R16G16_FLOAT, GL_RG16F, GL_RG16F, 0,
651 GL_RG, GL_HALF_FLOAT_ARB, 0,
652 WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
653 ARB_TEXTURE_RG, NULL},
654 {WINED3DFMT_R16G16B16A16_FLOAT, GL_RGBA16F_ARB, GL_RGBA16F_ARB, 0,
655 GL_RGBA, GL_HALF_FLOAT_ARB, 0,
656 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_RENDERTARGET | WINED3DFMT_FLAG_VTF,
657 ARB_TEXTURE_FLOAT, NULL},
658 /* Palettized formats */
659 {WINED3DFMT_P8_UINT, GL_RGBA, GL_RGBA, 0,
660 GL_ALPHA, GL_UNSIGNED_BYTE, 0,
661 0,
662 ARB_FRAGMENT_PROGRAM, NULL},
663 {WINED3DFMT_P8_UINT, GL_COLOR_INDEX8_EXT, GL_COLOR_INDEX8_EXT, 0,
664 GL_COLOR_INDEX, GL_UNSIGNED_BYTE, 0,
665 0,
666 EXT_PALETTED_TEXTURE, NULL},
667 /* Standard ARGB formats */
668 {WINED3DFMT_B8G8R8_UNORM, GL_RGB8, GL_RGB8, 0,
669 GL_BGR, GL_UNSIGNED_BYTE, 0,
670 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
671 WINED3D_GL_EXT_NONE, NULL},
672 {WINED3DFMT_B8G8R8A8_UNORM, GL_RGBA8, GL_SRGB8_ALPHA8_EXT, 0,
673 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0,
674 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET
675 | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE | WINED3DFMT_FLAG_VTF,
676 WINED3D_GL_EXT_NONE, NULL},
677 {WINED3DFMT_B8G8R8X8_UNORM, GL_RGB8, GL_SRGB8_EXT, 0,
678 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 0,
679 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET
680 | WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE,
681 WINED3D_GL_EXT_NONE, NULL},
682 {WINED3DFMT_B5G6R5_UNORM, GL_RGB5, GL_RGB5, GL_RGB8,
683 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 0,
684 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
685 WINED3D_GL_EXT_NONE, NULL},
686 {WINED3DFMT_B5G5R5X1_UNORM, GL_RGB5, GL_RGB5_A1, 0,
687 GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0,
688 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
689 WINED3D_GL_EXT_NONE, NULL},
690 {WINED3DFMT_B5G5R5A1_UNORM, GL_RGB5_A1, GL_RGB5_A1, 0,
691 GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, 0,
692 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
693 WINED3D_GL_EXT_NONE, NULL},
694 {WINED3DFMT_B4G4R4A4_UNORM, GL_RGBA4, GL_SRGB8_ALPHA8_EXT, 0,
695 GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 0,
696 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ,
697 WINED3D_GL_EXT_NONE, NULL},
698 {WINED3DFMT_B2G3R3_UNORM, GL_R3_G3_B2, GL_R3_G3_B2, 0,
699 GL_RGB, GL_UNSIGNED_BYTE_3_3_2, 0,
700 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
701 WINED3D_GL_EXT_NONE, NULL},
702 {WINED3DFMT_A8_UNORM, GL_ALPHA8, GL_ALPHA8, 0,
703 GL_ALPHA, GL_UNSIGNED_BYTE, 0,
704 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
705 WINED3D_GL_EXT_NONE, NULL},
706 {WINED3DFMT_B4G4R4X4_UNORM, GL_RGB4, GL_RGB4, 0,
707 GL_BGRA, GL_UNSIGNED_SHORT_4_4_4_4_REV, 0,
708 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
709 WINED3D_GL_EXT_NONE, NULL},
710 {WINED3DFMT_R10G10B10A2_UNORM, GL_RGB10_A2, GL_RGB10_A2, 0,
711 GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, 0,
712 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
713 WINED3D_GL_EXT_NONE, NULL},
714 {WINED3DFMT_R8G8B8A8_UNORM, GL_RGBA8, GL_RGBA8, 0,
715 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0,
716 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
717 WINED3D_GL_EXT_NONE, NULL},
718 {WINED3DFMT_R8G8B8X8_UNORM, GL_RGB8, GL_RGB8, 0,
719 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0,
720 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
721 WINED3D_GL_EXT_NONE, NULL},
722 {WINED3DFMT_R16G16_UNORM, GL_RGB16, GL_RGB16, GL_RGBA16,
723 GL_RGB, GL_UNSIGNED_SHORT, 6,
724 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
725 WINED3D_GL_EXT_NONE, convert_r16g16},
726 {WINED3DFMT_R16G16_UNORM, GL_RG16, GL_RG16, 0,
727 GL_RG, GL_UNSIGNED_SHORT, 0,
728 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
729 ARB_TEXTURE_RG, NULL},
730 {WINED3DFMT_B10G10R10A2_UNORM, GL_RGB10_A2, GL_RGB10_A2, 0,
731 GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, 0,
732 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
733 WINED3D_GL_EXT_NONE, NULL},
734 {WINED3DFMT_R16G16B16A16_UNORM, GL_RGBA16, GL_RGBA16, 0,
735 GL_RGBA, GL_UNSIGNED_SHORT, 0,
736 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_RENDERTARGET,
737 WINED3D_GL_EXT_NONE, NULL},
738 /* Luminance */
739 {WINED3DFMT_L8_UNORM, GL_LUMINANCE8, GL_SLUMINANCE8_EXT, 0,
740 GL_LUMINANCE, GL_UNSIGNED_BYTE, 0,
741 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ,
742 WINED3D_GL_EXT_NONE, NULL},
743 {WINED3DFMT_L8A8_UNORM, GL_LUMINANCE8_ALPHA8, GL_SLUMINANCE8_ALPHA8_EXT, 0,
744 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0,
745 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_SRGB_READ,
746 WINED3D_GL_EXT_NONE, NULL},
747 {WINED3DFMT_L4A4_UNORM, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE4_ALPHA4, 0,
748 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 2,
749 WINED3DFMT_FLAG_FILTERING,
750 WINED3D_GL_EXT_NONE, convert_l4a4_unorm},
751 /* Bump mapping stuff */
752 {WINED3DFMT_R8G8_SNORM, GL_RGB8, GL_RGB8, 0,
753 GL_BGR, GL_UNSIGNED_BYTE, 3,
754 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
755 WINED3D_GL_EXT_NONE, convert_r8g8_snorm},
756 {WINED3DFMT_R8G8_SNORM, GL_DSDT8_NV, GL_DSDT8_NV, 0,
757 GL_DSDT_NV, GL_BYTE, 0,
758 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
759 NV_TEXTURE_SHADER, NULL},
760 {WINED3DFMT_R5G5_SNORM_L6_UNORM, GL_RGB5, GL_RGB5, 0,
761 GL_RGB, GL_UNSIGNED_SHORT_5_6_5, 2,
762 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
763 WINED3D_GL_EXT_NONE, convert_r5g5_snorm_l6_unorm},
764 {WINED3DFMT_R5G5_SNORM_L6_UNORM, GL_DSDT8_MAG8_NV, GL_DSDT8_MAG8_NV, 0,
765 GL_DSDT_MAG_NV, GL_BYTE, 3,
766 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
767 NV_TEXTURE_SHADER, convert_r5g5_snorm_l6_unorm_nv},
768 {WINED3DFMT_R8G8_SNORM_L8X8_UNORM, GL_RGB8, GL_RGB8, 0,
769 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, 4,
770 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
771 WINED3D_GL_EXT_NONE, convert_r8g8_snorm_l8x8_unorm},
772 {WINED3DFMT_R8G8_SNORM_L8X8_UNORM, GL_DSDT8_MAG8_INTENSITY8_NV, GL_DSDT8_MAG8_INTENSITY8_NV, 0,
773 GL_DSDT_MAG_VIB_NV, GL_UNSIGNED_INT_8_8_S8_S8_REV_NV, 4,
774 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
775 NV_TEXTURE_SHADER, convert_r8g8_snorm_l8x8_unorm_nv},
776 {WINED3DFMT_R8G8B8A8_SNORM, GL_RGBA8, GL_RGBA8, 0,
777 GL_BGRA, GL_UNSIGNED_BYTE, 4,
778 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
779 WINED3D_GL_EXT_NONE, convert_r8g8b8a8_snorm},
780 {WINED3DFMT_R8G8B8A8_SNORM, GL_SIGNED_RGBA8_NV, GL_SIGNED_RGBA8_NV, 0,
781 GL_RGBA, GL_BYTE, 0,
782 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
783 NV_TEXTURE_SHADER, NULL},
784 {WINED3DFMT_R16G16_SNORM, GL_RGB16, GL_RGB16, 0,
785 GL_BGR, GL_UNSIGNED_SHORT, 6,
786 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
787 WINED3D_GL_EXT_NONE, convert_r16g16_snorm},
788 {WINED3DFMT_R16G16_SNORM, GL_SIGNED_HILO16_NV, GL_SIGNED_HILO16_NV, 0,
789 GL_HILO_NV, GL_SHORT, 0,
790 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_BUMPMAP,
791 NV_TEXTURE_SHADER, NULL},
792 /* Depth stencil formats */
793 {WINED3DFMT_D16_LOCKABLE, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
794 GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0,
795 WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
796 ARB_DEPTH_TEXTURE, NULL},
797 {WINED3DFMT_D32_UNORM, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT32_ARB, 0,
798 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0,
799 WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
800 ARB_DEPTH_TEXTURE, NULL},
801 {WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
802 GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0,
803 WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
804 ARB_DEPTH_TEXTURE, NULL},
805 {WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0,
806 GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 4,
807 WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
808 EXT_PACKED_DEPTH_STENCIL, convert_s1_uint_d15_unorm},
809 {WINED3DFMT_S1_UINT_D15_UNORM, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0,
810 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 4,
811 WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
812 ARB_FRAMEBUFFER_OBJECT, convert_s1_uint_d15_unorm},
813 {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
814 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0,
815 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
816 | WINED3DFMT_FLAG_SHADOW,
817 ARB_DEPTH_TEXTURE, NULL},
818 {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0,
819 GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0,
820 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
821 | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
822 EXT_PACKED_DEPTH_STENCIL, NULL},
823 {WINED3DFMT_D24_UNORM_S8_UINT, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0,
824 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0,
825 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
826 | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
827 ARB_FRAMEBUFFER_OBJECT, NULL},
828 {WINED3DFMT_X8D24_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
829 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0,
830 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
831 | WINED3DFMT_FLAG_SHADOW,
832 ARB_DEPTH_TEXTURE, NULL},
833 {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
834 GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, 0,
835 WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
836 ARB_DEPTH_TEXTURE, NULL},
837 {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0,
838 GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 4,
839 WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
840 EXT_PACKED_DEPTH_STENCIL, convert_s4x4_uint_d24_unorm},
841 {WINED3DFMT_S4X4_UINT_D24_UNORM, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0,
842 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 4,
843 WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
844 ARB_FRAMEBUFFER_OBJECT, convert_s4x4_uint_d24_unorm},
845 {WINED3DFMT_D16_UNORM, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT24_ARB, 0,
846 GL_DEPTH_COMPONENT, GL_UNSIGNED_SHORT, 0,
847 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
848 | WINED3DFMT_FLAG_SHADOW,
849 ARB_DEPTH_TEXTURE, NULL},
850 {WINED3DFMT_L16_UNORM, GL_LUMINANCE16, GL_LUMINANCE16, 0,
851 GL_LUMINANCE, GL_UNSIGNED_SHORT, 0,
852 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING,
853 WINED3D_GL_EXT_NONE, NULL},
854 {WINED3DFMT_D32_FLOAT, GL_DEPTH_COMPONENT32F, GL_DEPTH_COMPONENT32F, 0,
855 GL_DEPTH_COMPONENT, GL_FLOAT, 0,
856 WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_SHADOW,
857 ARB_DEPTH_BUFFER_FLOAT, NULL},
858 {WINED3DFMT_S8_UINT_D24_FLOAT, GL_DEPTH32F_STENCIL8, GL_DEPTH32F_STENCIL8, 0,
859 GL_DEPTH_STENCIL, GL_FLOAT_32_UNSIGNED_INT_24_8_REV, 8,
860 WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL | WINED3DFMT_FLAG_SHADOW,
861 ARB_DEPTH_BUFFER_FLOAT, convert_s8_uint_d24_float},
862 /* Vendor-specific formats */
863 {WINED3DFMT_ATI2N, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, GL_COMPRESSED_LUMINANCE_ALPHA_3DC_ATI, 0,
864 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0,
865 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_COMPRESSED,
866 ATI_TEXTURE_COMPRESSION_3DC, NULL},
867 {WINED3DFMT_ATI2N, GL_COMPRESSED_RED_GREEN_RGTC2, GL_COMPRESSED_RED_GREEN_RGTC2, 0,
868 GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, 0,
869 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_COMPRESSED,
870 ARB_TEXTURE_COMPRESSION_RGTC, NULL},
871 {WINED3DFMT_INTZ, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH24_STENCIL8_EXT, 0,
872 GL_DEPTH_STENCIL_EXT, GL_UNSIGNED_INT_24_8_EXT, 0,
873 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
874 | WINED3DFMT_FLAG_STENCIL,
875 EXT_PACKED_DEPTH_STENCIL, NULL},
876 {WINED3DFMT_INTZ, GL_DEPTH24_STENCIL8, GL_DEPTH24_STENCIL8, 0,
877 GL_DEPTH_STENCIL, GL_UNSIGNED_INT_24_8, 0,
878 WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING | WINED3DFMT_FLAG_FILTERING | WINED3DFMT_FLAG_DEPTH
879 | WINED3DFMT_FLAG_STENCIL,
880 ARB_FRAMEBUFFER_OBJECT, NULL},
881 {WINED3DFMT_NULL, GL_RGBA8, GL_RGBA8, 0,
882 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0,
883 WINED3DFMT_FLAG_RENDERTARGET,
884 ARB_FRAMEBUFFER_OBJECT, NULL},
885 };
886
887 static inline int getFmtIdx(enum wined3d_format_id format_id)
888 {
889 /* First check if the format is at the position of its value.
890 * This will catch the argb formats before the loop is entered. */
891 if (format_id < (sizeof(formats) / sizeof(*formats))
892 && formats[format_id].id == format_id)
893 {
894 return format_id;
895 }
896 else
897 {
898 unsigned int i;
899
900 for (i = 0; i < (sizeof(formats) / sizeof(*formats)); ++i)
901 {
902 if (formats[i].id == format_id) return i;
903 }
904 }
905 return -1;
906 }
907
908 static BOOL init_format_base_info(struct wined3d_gl_info *gl_info)
909 {
910 UINT format_count = sizeof(formats) / sizeof(*formats);
911 UINT i;
912
913 gl_info->formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, format_count * sizeof(*gl_info->formats));
914 if (!gl_info->formats)
915 {
916 ERR("Failed to allocate memory.\n");
917 return FALSE;
918 }
919
920 for (i = 0; i < format_count; ++i)
921 {
922 struct wined3d_format *format = &gl_info->formats[i];
923 format->id = formats[i].id;
924 format->red_size = formats[i].red_size;
925 format->green_size = formats[i].green_size;
926 format->blue_size = formats[i].blue_size;
927 format->alpha_size = formats[i].alpha_size;
928 format->red_offset = formats[i].red_offset;
929 format->green_offset = formats[i].green_offset;
930 format->blue_offset = formats[i].blue_offset;
931 format->alpha_offset = formats[i].alpha_offset;
932 format->byte_count = formats[i].bpp;
933 format->depth_size = formats[i].depth_size;
934 format->stencil_size = formats[i].stencil_size;
935 format->block_width = 1;
936 format->block_height = 1;
937 format->block_byte_count = formats[i].bpp;
938 }
939
940 for (i = 0; i < (sizeof(format_base_flags) / sizeof(*format_base_flags)); ++i)
941 {
942 int fmt_idx = getFmtIdx(format_base_flags[i].id);
943
944 if (fmt_idx == -1)
945 {
946 ERR("Format %s (%#x) not found.\n",
947 debug_d3dformat(format_base_flags[i].id), format_base_flags[i].id);
948 HeapFree(GetProcessHeap(), 0, gl_info->formats);
949 return FALSE;
950 }
951
952 gl_info->formats[fmt_idx].flags |= format_base_flags[i].flags;
953 }
954
955 return TRUE;
956 }
957
958 static BOOL init_format_block_info(struct wined3d_gl_info *gl_info)
959 {
960 unsigned int i;
961
962 for (i = 0; i < (sizeof(format_block_info) / sizeof(*format_block_info)); ++i)
963 {
964 struct wined3d_format *format;
965 int fmt_idx = getFmtIdx(format_block_info[i].id);
966
967 if (fmt_idx == -1)
968 {
969 ERR("Format %s (%#x) not found.\n",
970 debug_d3dformat(format_block_info[i].id), format_block_info[i].id);
971 return FALSE;
972 }
973
974 format = &gl_info->formats[fmt_idx];
975 format->block_width = format_block_info[i].block_width;
976 format->block_height = format_block_info[i].block_height;
977 format->block_byte_count = format_block_info[i].block_byte_count;
978 format->flags |= WINED3DFMT_FLAG_BLOCKS;
979 }
980
981 return TRUE;
982 }
983
984 /* Context activation is done by the caller. */
985 static void check_fbo_compat(const struct wined3d_gl_info *gl_info, struct wined3d_format *format)
986 {
987 /* Check if the default internal format is supported as a frame buffer
988 * target, otherwise fall back to the render target internal.
989 *
990 * Try to stick to the standard format if possible, this limits precision differences. */
991 GLenum status;
992 GLuint tex;
993
994 ENTER_GL();
995
996 while (gl_info->gl_ops.gl.p_glGetError());
997 gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
998
999 gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
1000 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
1001
1002 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->glInternal, 16, 16, 0,
1003 format->glFormat, format->glType, NULL);
1004 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1005 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1006
1007 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1008
1009 status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
1010 checkGLcall("Framebuffer format check");
1011
1012 if (status == GL_FRAMEBUFFER_COMPLETE)
1013 {
1014 TRACE("Format %s is supported as FBO color attachment.\n", debug_d3dformat(format->id));
1015 format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE;
1016 format->rtInternal = format->glInternal;
1017 }
1018 else
1019 {
1020 if (!format->rtInternal)
1021 {
1022 if (format->flags & WINED3DFMT_FLAG_RENDERTARGET)
1023 {
1024 FIXME("Format %s with rendertarget flag is not supported as FBO color attachment,"
1025 " and no fallback specified.\n", debug_d3dformat(format->id));
1026 format->flags &= ~WINED3DFMT_FLAG_RENDERTARGET;
1027 }
1028 else
1029 {
1030 TRACE("Format %s is not supported as FBO color attachment.\n", debug_d3dformat(format->id));
1031 }
1032 format->rtInternal = format->glInternal;
1033 }
1034 else
1035 {
1036 TRACE("Format %s is not supported as FBO color attachment, trying rtInternal format as fallback.\n",
1037 debug_d3dformat(format->id));
1038
1039 while (gl_info->gl_ops.gl.p_glGetError());
1040
1041 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
1042
1043 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->rtInternal, 16, 16, 0,
1044 format->glFormat, format->glType, NULL);
1045 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1046 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1047
1048 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1049
1050 status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
1051 checkGLcall("Framebuffer format check");
1052
1053 if (status == GL_FRAMEBUFFER_COMPLETE)
1054 {
1055 TRACE("Format %s rtInternal format is supported as FBO color attachment.\n",
1056 debug_d3dformat(format->id));
1057 }
1058 else
1059 {
1060 FIXME("Format %s rtInternal format is not supported as FBO color attachment.\n",
1061 debug_d3dformat(format->id));
1062 format->flags &= ~WINED3DFMT_FLAG_RENDERTARGET;
1063 }
1064 }
1065 }
1066
1067 if (status == GL_FRAMEBUFFER_COMPLETE && ((format->flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING)
1068 || !(gl_info->quirks & WINED3D_QUIRK_LIMITED_TEX_FILTERING))
1069 && format->id != WINED3DFMT_NULL && format->id != WINED3DFMT_P8_UINT
1070 && format->glFormat != GL_LUMINANCE && format->glFormat != GL_LUMINANCE_ALPHA
1071 && (format->red_size || format->alpha_size))
1072 {
1073 GLuint rb, tex2;
1074 DWORD readback[16 * 16], color, r_range, a_range;
1075 BYTE r, a;
1076 BOOL match = TRUE;
1077
1078 if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
1079 || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
1080 {
1081 gl_info->fbo_ops.glGenRenderbuffers(1, &rb);
1082 gl_info->fbo_ops.glBindRenderbuffer(GL_RENDERBUFFER, rb);
1083 gl_info->fbo_ops.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8, 16, 16);
1084 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rb);
1085 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rb);
1086 checkGLcall("RB attachment");
1087 }
1088
1089 gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
1090 gl_info->gl_ops.gl.p_glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
1091 gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
1092 if (gl_info->gl_ops.gl.p_glGetError() == GL_INVALID_FRAMEBUFFER_OPERATION)
1093 {
1094 while (gl_info->gl_ops.gl.p_glGetError());
1095 TRACE("Format doesn't support post-pixelshader blending.\n");
1096 format->flags &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
1097 }
1098 else
1099 {
1100 gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
1101 gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 16);
1102 gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
1103 gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
1104 gl_info->gl_ops.gl.p_glLoadIdentity();
1105 gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
1106 gl_info->gl_ops.gl.p_glLoadIdentity();
1107
1108 gl_info->gl_ops.gl.p_glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
1109
1110 /* Draw a full-black quad */
1111 gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
1112 gl_info->gl_ops.gl.p_glColor4f(0.0f, 0.0f, 0.0f, 1.0f);
1113 gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
1114 gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
1115 gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
1116 gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
1117 gl_info->gl_ops.gl.p_glEnd();
1118
1119 gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
1120 /* Draw a half-transparent red quad */
1121 gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
1122 gl_info->gl_ops.gl.p_glColor4f(1.0f, 0.0f, 0.0f, 0.5f);
1123 gl_info->gl_ops.gl.p_glVertex3f(-1.0f, -1.0f, 0.0f);
1124 gl_info->gl_ops.gl.p_glVertex3f(1.0f, -1.0f, 0.0f);
1125 gl_info->gl_ops.gl.p_glVertex3f(-1.0f, 1.0f, 0.0f);
1126 gl_info->gl_ops.gl.p_glVertex3f(1.0f, 1.0f, 0.0f);
1127 gl_info->gl_ops.gl.p_glEnd();
1128
1129 gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
1130 gl_info->gl_ops.gl.p_glGenTextures(1, &tex2);
1131 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex2);
1132
1133 gl_info->gl_ops.gl.p_glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, 16, 16, 0);
1134 gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
1135 checkGLcall("Post-pixelshader blending check");
1136
1137 color = readback[7 * 16 + 7];
1138 a = color >> 24;
1139 r = (color & 0x00ff0000) >> 16;
1140
1141 r_range = format->red_size < 8 ? 1 << (8 - format->red_size - 1) : 1;
1142 a_range = format->alpha_size < 8 ? 1 << (8 - format->alpha_size - 1) : 1;
1143 if (format->red_size && (r < 0x80 - r_range || r > 0x80 + r_range))
1144 match = FALSE;
1145 else if (format->alpha_size > 1 && (a < 0xbf - a_range || a > 0xbf + a_range))
1146 match = FALSE;
1147 if (!match)
1148 {
1149 TRACE("Format doesn't support post-pixelshader blending.\n");
1150 TRACE("Color output: %#x\n", color);
1151 format->flags &= ~WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
1152 }
1153 else
1154 {
1155 TRACE("Format supports post-pixelshader blending.\n");
1156 TRACE("Color output: %#x\n", color);
1157 format->flags |= WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING;
1158 }
1159
1160 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
1161 gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex2);
1162 }
1163
1164 if (gl_info->supported[ARB_FRAMEBUFFER_OBJECT]
1165 || gl_info->supported[EXT_PACKED_DEPTH_STENCIL])
1166 {
1167 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
1168 gl_info->fbo_ops.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
1169 gl_info->fbo_ops.glDeleteRenderbuffers(1, &rb);
1170 checkGLcall("RB cleanup");
1171 }
1172 }
1173
1174 if (format->glInternal != format->glGammaInternal)
1175 {
1176 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, format->glGammaInternal, 16, 16, 0,
1177 format->glFormat, format->glType, NULL);
1178 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, tex, 0);
1179
1180 status = gl_info->fbo_ops.glCheckFramebufferStatus(GL_FRAMEBUFFER);
1181 checkGLcall("Framebuffer format check");
1182
1183 if (status == GL_FRAMEBUFFER_COMPLETE)
1184 {
1185 TRACE("Format %s's sRGB format is FBO attachable.\n", debug_d3dformat(format->id));
1186 format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
1187 }
1188 else
1189 {
1190 WARN("Format %s's sRGB format is not FBO attachable.\n", debug_d3dformat(format->id));
1191 }
1192 }
1193 else if (status == GL_FRAMEBUFFER_COMPLETE)
1194 format->flags |= WINED3DFMT_FLAG_FBO_ATTACHABLE_SRGB;
1195
1196 gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
1197
1198 LEAVE_GL();
1199 }
1200
1201 /* Context activation is done by the caller. */
1202 static void init_format_fbo_compat_info(struct wined3d_gl_info *gl_info)
1203 {
1204 unsigned int i;
1205 GLuint fbo;
1206
1207 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
1208 {
1209 ENTER_GL();
1210
1211 gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
1212 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1213 gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);
1214 gl_info->gl_ops.gl.p_glReadBuffer(GL_COLOR_ATTACHMENT0);
1215
1216 LEAVE_GL();
1217 }
1218
1219 for (i = 0; i < sizeof(formats) / sizeof(*formats); ++i)
1220 {
1221 struct wined3d_format *format = &gl_info->formats[i];
1222
1223 if (!format->glInternal) continue;
1224
1225 if (format->flags & (WINED3DFMT_FLAG_DEPTH | WINED3DFMT_FLAG_STENCIL))
1226 {
1227 TRACE("Skipping format %s because it's a depth/stencil format.\n",
1228 debug_d3dformat(format->id));
1229 continue;
1230 }
1231
1232 if (format->flags & WINED3DFMT_FLAG_COMPRESSED)
1233 {
1234 TRACE("Skipping format %s because it's a compressed format.\n",
1235 debug_d3dformat(format->id));
1236 continue;
1237 }
1238
1239 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
1240 {
1241 TRACE("Checking if format %s is supported as FBO color attachment...\n", debug_d3dformat(format->id));
1242 check_fbo_compat(gl_info, format);
1243 }
1244 else
1245 {
1246 format->rtInternal = format->glInternal;
1247 }
1248 }
1249
1250 if (wined3d_settings.offscreen_rendering_mode == ORM_FBO)
1251 {
1252 ENTER_GL();
1253
1254 gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
1255
1256 LEAVE_GL();
1257 }
1258 }
1259
1260 static BOOL init_format_texture_info(struct wined3d_gl_info *gl_info)
1261 {
1262 unsigned int i;
1263
1264 for (i = 0; i < sizeof(format_texture_info) / sizeof(*format_texture_info); ++i)
1265 {
1266 int fmt_idx = getFmtIdx(format_texture_info[i].id);
1267 struct wined3d_format *format;
1268
1269 if (fmt_idx == -1)
1270 {
1271 ERR("Format %s (%#x) not found.\n",
1272 debug_d3dformat(format_texture_info[i].id), format_texture_info[i].id);
1273 return FALSE;
1274 }
1275
1276 if (!gl_info->supported[format_texture_info[i].extension]) continue;
1277
1278 format = &gl_info->formats[fmt_idx];
1279
1280 /* ARB_texture_rg defines floating point formats, but only if
1281 * ARB_texture_float is also supported. */
1282 if (!gl_info->supported[ARB_TEXTURE_FLOAT]
1283 && (format->flags & WINED3DFMT_FLAG_FLOAT))
1284 continue;
1285
1286 format->glInternal = format_texture_info[i].gl_internal;
1287 format->glGammaInternal = format_texture_info[i].gl_srgb_internal;
1288 format->rtInternal = format_texture_info[i].gl_rt_internal;
1289 format->glFormat = format_texture_info[i].gl_format;
1290 format->glType = format_texture_info[i].gl_type;
1291 format->color_fixup = COLOR_FIXUP_IDENTITY;
1292 format->flags |= format_texture_info[i].flags;
1293 format->height_scale.numerator = 1;
1294 format->height_scale.denominator = 1;
1295
1296 if (format->glGammaInternal != format->glInternal)
1297 {
1298 /* Filter sRGB capabilities if EXT_texture_sRGB is not supported. */
1299 if (!gl_info->supported[EXT_TEXTURE_SRGB])
1300 {
1301 format->glGammaInternal = format->glInternal;
1302 format->flags &= ~(WINED3DFMT_FLAG_SRGB_READ | WINED3DFMT_FLAG_SRGB_WRITE);
1303 }
1304 else if (gl_info->supported[EXT_TEXTURE_SRGB_DECODE])
1305 {
1306 format->glInternal = format->glGammaInternal;
1307 }
1308 }
1309
1310 /* Texture conversion stuff */
1311 format->convert = format_texture_info[i].convert;
1312 format->conv_byte_count = format_texture_info[i].conv_byte_count;
1313 }
1314
1315 return TRUE;
1316 }
1317
1318 static BOOL color_match(DWORD c1, DWORD c2, BYTE max_diff)
1319 {
1320 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
1321 c1 >>= 8; c2 >>= 8;
1322 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
1323 c1 >>= 8; c2 >>= 8;
1324 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
1325 c1 >>= 8; c2 >>= 8;
1326 if (abs((c1 & 0xff) - (c2 & 0xff)) > max_diff) return FALSE;
1327 return TRUE;
1328 }
1329
1330 /* A context is provided by the caller */
1331 static BOOL check_filter(const struct wined3d_gl_info *gl_info, GLenum internal)
1332 {
1333 static const DWORD data[] = {0x00000000, 0xffffffff};
1334 GLuint tex, fbo, buffer;
1335 DWORD readback[16 * 1];
1336 BOOL ret = FALSE;
1337
1338 /* Render a filtered texture and see what happens. This is intended to detect the lack of
1339 * float16 filtering on ATI X1000 class cards. The drivers disable filtering instead of
1340 * falling back to software. If this changes in the future this code will get fooled and
1341 * apps might hit the software path due to incorrectly advertised caps.
1342 *
1343 * Its unlikely that this changes however. GL Games like Mass Effect depend on the filter
1344 * disable fallback, if Apple or ATI ever change the driver behavior they will break more
1345 * than Wine. The Linux binary <= r500 driver is not maintained any more anyway
1346 */
1347
1348 ENTER_GL();
1349 while (gl_info->gl_ops.gl.p_glGetError());
1350
1351 gl_info->gl_ops.gl.p_glGenTextures(1, &buffer);
1352 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
1353 memset(readback, 0x7e, sizeof(readback));
1354 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 16, 1, 0,
1355 GL_RGBA, GL_UNSIGNED_INT_8_8_8_8, readback);
1356 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1357 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1358 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1359 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1360 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
1361
1362 gl_info->gl_ops.gl.p_glGenTextures(1, &tex);
1363 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, tex);
1364 gl_info->gl_ops.gl.p_glTexImage2D(GL_TEXTURE_2D, 0, internal, 2, 1, 0,
1365 GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, data);
1366 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
1367 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
1368 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1369 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1370 gl_info->gl_ops.gl.p_glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
1371 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
1372
1373 gl_info->fbo_ops.glGenFramebuffers(1, &fbo);
1374 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
1375 gl_info->fbo_ops.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, buffer, 0);
1376 gl_info->gl_ops.gl.p_glDrawBuffer(GL_COLOR_ATTACHMENT0);
1377
1378 gl_info->gl_ops.gl.p_glViewport(0, 0, 16, 1);
1379 gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
1380 gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
1381 gl_info->gl_ops.gl.p_glLoadIdentity();
1382 gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
1383 gl_info->gl_ops.gl.p_glLoadIdentity();
1384
1385 gl_info->gl_ops.gl.p_glClearColor(0, 1, 0, 0);
1386 gl_info->gl_ops.gl.p_glClear(GL_COLOR_BUFFER_BIT);
1387
1388 gl_info->gl_ops.gl.p_glBegin(GL_TRIANGLE_STRIP);
1389 gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 0.0);
1390 gl_info->gl_ops.gl.p_glVertex2f(-1.0f, -1.0f);
1391 gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 0.0);
1392 gl_info->gl_ops.gl.p_glVertex2f(1.0f, -1.0f);
1393 gl_info->gl_ops.gl.p_glTexCoord2f(0.0, 1.0);
1394 gl_info->gl_ops.gl.p_glVertex2f(-1.0f, 1.0f);
1395 gl_info->gl_ops.gl.p_glTexCoord2f(1.0, 1.0);
1396 gl_info->gl_ops.gl.p_glVertex2f(1.0f, 1.0f);
1397 gl_info->gl_ops.gl.p_glEnd();
1398
1399 gl_info->gl_ops.gl.p_glBindTexture(GL_TEXTURE_2D, buffer);
1400 memset(readback, 0x7f, sizeof(readback));
1401 gl_info->gl_ops.gl.p_glGetTexImage(GL_TEXTURE_2D, 0, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, readback);
1402 if (color_match(readback[6], 0xffffffff, 5) || color_match(readback[6], 0x00000000, 5)
1403 || color_match(readback[9], 0xffffffff, 5) || color_match(readback[9], 0x00000000, 5))
1404 {
1405 TRACE("Read back colors 0x%08x and 0x%08x close to unfiltered color, assuming no filtering\n",
1406 readback[6], readback[9]);
1407 ret = FALSE;
1408 }
1409 else
1410 {
1411 TRACE("Read back colors are 0x%08x and 0x%08x, assuming texture is filtered\n",
1412 readback[6], readback[9]);
1413 ret = TRUE;
1414 }
1415
1416 gl_info->fbo_ops.glBindFramebuffer(GL_FRAMEBUFFER, 0);
1417 gl_info->fbo_ops.glDeleteFramebuffers(1, &fbo);
1418 gl_info->gl_ops.gl.p_glDeleteTextures(1, &tex);
1419 gl_info->gl_ops.gl.p_glDeleteTextures(1, &buffer);
1420
1421 if (gl_info->gl_ops.gl.p_glGetError())
1422 {
1423 FIXME("Error during filtering test for format %x, returning no filtering\n", internal);
1424 ret = FALSE;
1425 }
1426 LEAVE_GL();
1427 return ret;
1428 }
1429
1430 static void init_format_filter_info(struct wined3d_gl_info *gl_info, enum wined3d_pci_vendor vendor)
1431 {
1432 struct wined3d_format *format;
1433 unsigned int fmt_idx, i;
1434 static const enum wined3d_format_id fmts16[] =
1435 {
1436 WINED3DFMT_R16_FLOAT,
1437 WINED3DFMT_R16G16_FLOAT,
1438 WINED3DFMT_R16G16B16A16_FLOAT,
1439 };
1440 BOOL filtered;
1441
1442 if(wined3d_settings.offscreen_rendering_mode != ORM_FBO)
1443 {
1444 WARN("No FBO support, or no FBO ORM, guessing filter info from GL caps\n");
1445 if (vendor == HW_VENDOR_NVIDIA && gl_info->supported[ARB_TEXTURE_FLOAT])
1446 {
1447 TRACE("Nvidia card with texture_float support: Assuming float16 blending\n");
1448 filtered = TRUE;
1449 }
1450 else if (gl_info->limits.glsl_varyings > 44)
1451 {
1452 TRACE("More than 44 GLSL varyings - assuming d3d10 card with float16 blending\n");
1453 filtered = TRUE;
1454 }
1455 else
1456 {
1457 TRACE("Assuming no float16 blending\n");
1458 filtered = FALSE;
1459 }
1460
1461 if(filtered)
1462 {
1463 for(i = 0; i < (sizeof(fmts16) / sizeof(*fmts16)); i++)
1464 {
1465 fmt_idx = getFmtIdx(fmts16[i]);
1466 gl_info->formats[fmt_idx].flags |= WINED3DFMT_FLAG_FILTERING;
1467 }
1468 }
1469 return;
1470 }
1471
1472 for(i = 0; i < (sizeof(fmts16) / sizeof(*fmts16)); i++)
1473 {
1474 fmt_idx = getFmtIdx(fmts16[i]);
1475 format = &gl_info->formats[fmt_idx];
1476 if (!format->glInternal) continue; /* Not supported by GL */
1477
1478 filtered = check_filter(gl_info, gl_info->formats[fmt_idx].glInternal);
1479 if(filtered)
1480 {
1481 TRACE("Format %s supports filtering\n", debug_d3dformat(fmts16[i]));
1482 format->flags |= WINED3DFMT_FLAG_FILTERING;
1483 }
1484 else
1485 {
1486 TRACE("Format %s does not support filtering\n", debug_d3dformat(fmts16[i]));
1487 }
1488 }
1489 }
1490
1491 static void apply_format_fixups(struct wined3d_gl_info *gl_info)
1492 {
1493 int idx;
1494
1495 idx = getFmtIdx(WINED3DFMT_R16_FLOAT);
1496 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1497 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
1498
1499 idx = getFmtIdx(WINED3DFMT_R32_FLOAT);
1500 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1501 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
1502
1503 idx = getFmtIdx(WINED3DFMT_R16G16_UNORM);
1504 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1505 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
1506
1507 idx = getFmtIdx(WINED3DFMT_R16G16_FLOAT);
1508 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1509 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
1510
1511 idx = getFmtIdx(WINED3DFMT_R32G32_FLOAT);
1512 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1513 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_W);
1514
1515 /* V8U8 is supported natively by GL_ATI_envmap_bumpmap and GL_NV_texture_shader.
1516 * V16U16 is only supported by GL_NV_texture_shader. The formats need fixup if
1517 * their extensions are not available. GL_ATI_envmap_bumpmap is not used because
1518 * the only driver that implements it(fglrx) has a buggy implementation.
1519 *
1520 * V8U8 and V16U16 need a fixup of the undefined blue channel. OpenGL
1521 * returns 0.0 when sampling from it, DirectX 1.0. So we always have in-shader
1522 * conversion for this format.
1523 */
1524 if (!gl_info->supported[NV_TEXTURE_SHADER])
1525 {
1526 idx = getFmtIdx(WINED3DFMT_R8G8_SNORM);
1527 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1528 1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
1529 idx = getFmtIdx(WINED3DFMT_R16G16_SNORM);
1530 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1531 1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
1532 }
1533 else
1534 {
1535 idx = getFmtIdx(WINED3DFMT_R8G8_SNORM);
1536 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1537 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
1538
1539 idx = getFmtIdx(WINED3DFMT_R16G16_SNORM);
1540 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1541 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
1542 }
1543
1544 if (!gl_info->supported[NV_TEXTURE_SHADER])
1545 {
1546 /* If GL_NV_texture_shader is not supported, those formats are converted, incompatibly
1547 * with each other
1548 */
1549 idx = getFmtIdx(WINED3DFMT_R5G5_SNORM_L6_UNORM);
1550 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1551 1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_ONE);
1552 idx = getFmtIdx(WINED3DFMT_R8G8_SNORM_L8X8_UNORM);
1553 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1554 1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_Z, 0, CHANNEL_SOURCE_W);
1555 idx = getFmtIdx(WINED3DFMT_R8G8B8A8_SNORM);
1556 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1557 1, CHANNEL_SOURCE_X, 1, CHANNEL_SOURCE_Y, 1, CHANNEL_SOURCE_Z, 1, CHANNEL_SOURCE_W);
1558 }
1559 else
1560 {
1561 /* If GL_NV_texture_shader is supported, WINED3DFMT_L6V5U5 and WINED3DFMT_X8L8V8U8
1562 * are converted at surface loading time, but they do not need any modification in
1563 * the shader, thus they are compatible with all WINED3DFMT_UNKNOWN group formats.
1564 * WINED3DFMT_Q8W8V8U8 doesn't even need load-time conversion
1565 */
1566 }
1567
1568 if (gl_info->supported[EXT_TEXTURE_COMPRESSION_RGTC])
1569 {
1570 idx = getFmtIdx(WINED3DFMT_ATI2N);
1571 gl_info->formats[idx].color_fixup = create_color_fixup_desc(
1572 0, CHANNEL_SOURCE_Y, 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
1573 }
1574 else if (gl_info->supported[ATI_TEXTURE_COMPRESSION_3DC])
1575 {
1576 idx = getFmtIdx(WINED3DFMT_ATI2N);
1577 gl_info->formats[idx].color_fixup= create_color_fixup_desc(
1578 0, CHANNEL_SOURCE_X, 0, CHANNEL_SOURCE_W, 0, CHANNEL_SOURCE_ONE, 0, CHANNEL_SOURCE_ONE);
1579 }
1580
1581 if (!gl_info->supported[APPLE_YCBCR_422])
1582 {
1583 idx = getFmtIdx(WINED3DFMT_YUY2);
1584 gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YUY2);
1585
1586 idx = getFmtIdx(WINED3DFMT_UYVY);
1587 gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_UYVY);
1588 }
1589
1590 idx = getFmtIdx(WINED3DFMT_YV12);
1591 gl_info->formats[idx].flags |= WINED3DFMT_FLAG_HEIGHT_SCALE;
1592 gl_info->formats[idx].height_scale.numerator = 3;
1593 gl_info->formats[idx].height_scale.denominator = 2;
1594 gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_YV12);
1595
1596 if (gl_info->supported[EXT_PALETTED_TEXTURE] || gl_info->supported[ARB_FRAGMENT_PROGRAM])
1597 {
1598 idx = getFmtIdx(WINED3DFMT_P8_UINT);
1599 gl_info->formats[idx].color_fixup = create_complex_fixup_desc(COMPLEX_FIXUP_P8);
1600 }
1601
1602 if (gl_info->supported[ARB_VERTEX_ARRAY_BGRA])
1603 {
1604 idx = getFmtIdx(WINED3DFMT_B8G8R8A8_UNORM);
1605 gl_info->formats[idx].gl_vtx_format = GL_BGRA;
1606 }
1607
1608 if (gl_info->supported[ARB_HALF_FLOAT_VERTEX])
1609 {
1610 /* Do not change the size of the type, it is CPU side. We have to change the GPU-side information though.
1611 * It is the job of the vertex buffer code to make sure that the vbos have the right format */
1612 idx = getFmtIdx(WINED3DFMT_R16G16_FLOAT);
1613 gl_info->formats[idx].gl_vtx_type = GL_HALF_FLOAT; /* == GL_HALF_FLOAT_NV */
1614
1615 idx = getFmtIdx(WINED3DFMT_R16G16B16A16_FLOAT);
1616 gl_info->formats[idx].gl_vtx_type = GL_HALF_FLOAT;
1617 }
1618 }
1619
1620 static BOOL init_format_vertex_info(struct wined3d_gl_info *gl_info)
1621 {
1622 unsigned int i;
1623
1624 for (i = 0; i < (sizeof(format_vertex_info) / sizeof(*format_vertex_info)); ++i)
1625 {
1626 struct wined3d_format *format;
1627 int fmt_idx = getFmtIdx(format_vertex_info[i].id);
1628
1629 if (fmt_idx == -1)
1630 {
1631 ERR("Format %s (%#x) not found.\n",
1632 debug_d3dformat(format_vertex_info[i].id), format_vertex_info[i].id);
1633 return FALSE;
1634 }
1635
1636 format = &gl_info->formats[fmt_idx];
1637 format->emit_idx = format_vertex_info[i].emit_idx;
1638 format->component_count = format_vertex_info[i].component_count;
1639 format->gl_vtx_type = format_vertex_info[i].gl_vtx_type;
1640 format->gl_vtx_format = format_vertex_info[i].gl_vtx_format;
1641 format->gl_normalized = format_vertex_info[i].gl_normalized;
1642 format->component_size = format_vertex_info[i].component_size;
1643 }
1644
1645 return TRUE;
1646 }
1647
1648 BOOL initPixelFormatsNoGL(struct wined3d_gl_info *gl_info)
1649 {
1650 if (!init_format_base_info(gl_info)) return FALSE;
1651
1652 if (!init_format_block_info(gl_info))
1653 {
1654 HeapFree(GetProcessHeap(), 0, gl_info->formats);
1655 gl_info->formats = NULL;
1656 return FALSE;
1657 }
1658
1659 return TRUE;
1660 }
1661
1662 /* Context activation is done by the caller. */
1663 BOOL initPixelFormats(struct wined3d_gl_info *gl_info, enum wined3d_pci_vendor vendor)
1664 {
1665 if (!init_format_base_info(gl_info)) return FALSE;
1666
1667 if (!init_format_block_info(gl_info)) goto fail;
1668 if (!init_format_texture_info(gl_info)) goto fail;
1669 if (!init_format_vertex_info(gl_info)) goto fail;
1670
1671 apply_format_fixups(gl_info);
1672 init_format_fbo_compat_info(gl_info);
1673 init_format_filter_info(gl_info, vendor);
1674
1675 return TRUE;
1676
1677 fail:
1678 HeapFree(GetProcessHeap(), 0, gl_info->formats);
1679 gl_info->formats = NULL;
1680 return FALSE;
1681 }
1682
1683 const struct wined3d_format *wined3d_get_format(const struct wined3d_gl_info *gl_info,
1684 enum wined3d_format_id format_id)
1685 {
1686 int idx = getFmtIdx(format_id);
1687
1688 if (idx == -1)
1689 {
1690 FIXME("Can't find format %s (%#x) in the format lookup table\n",
1691 debug_d3dformat(format_id), format_id);
1692 /* Get the caller a valid pointer */
1693 idx = getFmtIdx(WINED3DFMT_UNKNOWN);
1694 }
1695
1696 return &gl_info->formats[idx];
1697 }
1698
1699 UINT wined3d_format_calculate_size(const struct wined3d_format *format, UINT alignment, UINT width, UINT height)
1700 {
1701 UINT size;
1702
1703 if (format->id == WINED3DFMT_UNKNOWN)
1704 {
1705 size = 0;
1706 }
1707 else if (format->flags & WINED3DFMT_FLAG_BLOCKS)
1708 {
1709 UINT row_block_count = (width + format->block_width - 1) / format->block_width;
1710 UINT row_count = (height + format->block_height - 1) / format->block_height;
1711 size = row_count * (((row_block_count * format->block_byte_count) + alignment - 1) & ~(alignment - 1));
1712 }
1713 else
1714 {
1715 size = height * (((width * format->byte_count) + alignment - 1) & ~(alignment - 1));
1716 }
1717
1718 if (format->flags & WINED3DFMT_FLAG_HEIGHT_SCALE)
1719 {
1720 /* The D3D format requirements make sure that the resulting format is an integer again */
1721 size *= format->height_scale.numerator;
1722 size /= format->height_scale.denominator;
1723 }
1724
1725 return size;
1726 }
1727
1728 /*****************************************************************************
1729 * Trace formatting of useful values
1730 */
1731 const char *debug_d3dformat(enum wined3d_format_id format_id)
1732 {
1733 switch (format_id)
1734 {
1735 #define FMT_TO_STR(format_id) case format_id: return #format_id
1736 FMT_TO_STR(WINED3DFMT_UNKNOWN);
1737 FMT_TO_STR(WINED3DFMT_B8G8R8_UNORM);
1738 FMT_TO_STR(WINED3DFMT_B5G5R5X1_UNORM);
1739 FMT_TO_STR(WINED3DFMT_B4G4R4A4_UNORM);
1740 FMT_TO_STR(WINED3DFMT_B2G3R3_UNORM);
1741 FMT_TO_STR(WINED3DFMT_B2G3R3A8_UNORM);
1742 FMT_TO_STR(WINED3DFMT_B4G4R4X4_UNORM);
1743 FMT_TO_STR(WINED3DFMT_R8G8B8X8_UNORM);
1744 FMT_TO_STR(WINED3DFMT_B10G10R10A2_UNORM);
1745 FMT_TO_STR(WINED3DFMT_P8_UINT_A8_UNORM);
1746 FMT_TO_STR(WINED3DFMT_P8_UINT);
1747 FMT_TO_STR(WINED3DFMT_L8_UNORM);
1748 FMT_TO_STR(WINED3DFMT_L8A8_UNORM);
1749 FMT_TO_STR(WINED3DFMT_L4A4_UNORM);
1750 FMT_TO_STR(WINED3DFMT_R5G5_SNORM_L6_UNORM);
1751 FMT_TO_STR(WINED3DFMT_R8G8_SNORM_L8X8_UNORM);
1752 FMT_TO_STR(WINED3DFMT_R10G11B11_SNORM);
1753 FMT_TO_STR(WINED3DFMT_R10G10B10_SNORM_A2_UNORM);
1754 FMT_TO_STR(WINED3DFMT_UYVY);
1755 FMT_TO_STR(WINED3DFMT_YUY2);
1756 FMT_TO_STR(WINED3DFMT_YV12);
1757 FMT_TO_STR(WINED3DFMT_DXT1);
1758 FMT_TO_STR(WINED3DFMT_DXT2);
1759 FMT_TO_STR(WINED3DFMT_DXT3);
1760 FMT_TO_STR(WINED3DFMT_DXT4);
1761 FMT_TO_STR(WINED3DFMT_DXT5);
1762 FMT_TO_STR(WINED3DFMT_MULTI2_ARGB8);
1763 FMT_TO_STR(WINED3DFMT_G8R8_G8B8);
1764 FMT_TO_STR(WINED3DFMT_R8G8_B8G8);
1765 FMT_TO_STR(WINED3DFMT_D16_LOCKABLE);
1766 FMT_TO_STR(WINED3DFMT_D32_UNORM);
1767 FMT_TO_STR(WINED3DFMT_S1_UINT_D15_UNORM);
1768 FMT_TO_STR(WINED3DFMT_X8D24_UNORM);
1769 FMT_TO_STR(WINED3DFMT_S4X4_UINT_D24_UNORM);
1770 FMT_TO_STR(WINED3DFMT_L16_UNORM);
1771 FMT_TO_STR(WINED3DFMT_S8_UINT_D24_FLOAT);
1772 FMT_TO_STR(WINED3DFMT_VERTEXDATA);
1773 FMT_TO_STR(WINED3DFMT_R8G8_SNORM_Cx);
1774 FMT_TO_STR(WINED3DFMT_ATI2N);
1775 FMT_TO_STR(WINED3DFMT_NVDB);
1776 FMT_TO_STR(WINED3DFMT_NVHU);
1777 FMT_TO_STR(WINED3DFMT_NVHS);
1778 FMT_TO_STR(WINED3DFMT_R32G32B32A32_TYPELESS);
1779 FMT_TO_STR(WINED3DFMT_R32G32B32A32_FLOAT);
1780 FMT_TO_STR(WINED3DFMT_R32G32B32A32_UINT);
1781 FMT_TO_STR(WINED3DFMT_R32G32B32A32_SINT);
1782 FMT_TO_STR(WINED3DFMT_R32G32B32_TYPELESS);
1783 FMT_TO_STR(WINED3DFMT_R32G32B32_FLOAT);
1784 FMT_TO_STR(WINED3DFMT_R32G32B32_UINT);
1785 FMT_TO_STR(WINED3DFMT_R32G32B32_SINT);
1786 FMT_TO_STR(WINED3DFMT_R16G16B16A16_TYPELESS);
1787 FMT_TO_STR(WINED3DFMT_R16G16B16A16_FLOAT);
1788 FMT_TO_STR(WINED3DFMT_R16G16B16A16_UNORM);
1789 FMT_TO_STR(WINED3DFMT_R16G16B16A16_UINT);
1790 FMT_TO_STR(WINED3DFMT_R16G16B16A16_SNORM);
1791 FMT_TO_STR(WINED3DFMT_R16G16B16A16_SINT);
1792 FMT_TO_STR(WINED3DFMT_R32G32_TYPELESS);
1793 FMT_TO_STR(WINED3DFMT_R32G32_FLOAT);
1794 FMT_TO_STR(WINED3DFMT_R32G32_UINT);
1795 FMT_TO_STR(WINED3DFMT_R32G32_SINT);
1796 FMT_TO_STR(WINED3DFMT_R32G8X24_TYPELESS);
1797 FMT_TO_STR(WINED3DFMT_D32_FLOAT_S8X24_UINT);
1798 FMT_TO_STR(WINED3DFMT_R32_FLOAT_X8X24_TYPELESS);
1799 FMT_TO_STR(WINED3DFMT_X32_TYPELESS_G8X24_UINT);
1800 FMT_TO_STR(WINED3DFMT_R10G10B10A2_TYPELESS);
1801 FMT_TO_STR(WINED3DFMT_R10G10B10A2_UNORM);
1802 FMT_TO_STR(WINED3DFMT_R10G10B10A2_UINT);
1803 FMT_TO_STR(WINED3DFMT_R10G10B10A2_SNORM);
1804 FMT_TO_STR(WINED3DFMT_R11G11B10_FLOAT);
1805 FMT_TO_STR(WINED3DFMT_R8G8B8A8_TYPELESS);
1806 FMT_TO_STR(WINED3DFMT_R8G8B8A8_UNORM);
1807 FMT_TO_STR(WINED3DFMT_R8G8B8A8_UNORM_SRGB);
1808 FMT_TO_STR(WINED3DFMT_R8G8B8A8_UINT);
1809 FMT_TO_STR(WINED3DFMT_R8G8B8A8_SNORM);
1810 FMT_TO_STR(WINED3DFMT_R8G8B8A8_SINT);
1811 FMT_TO_STR(WINED3DFMT_R16G16_TYPELESS);
1812 FMT_TO_STR(WINED3DFMT_R16G16_FLOAT);
1813 FMT_TO_STR(WINED3DFMT_R16G16_UNORM);
1814 FMT_TO_STR(WINED3DFMT_R16G16_UINT);
1815 FMT_TO_STR(WINED3DFMT_R16G16_SNORM);
1816 FMT_TO_STR(WINED3DFMT_R16G16_SINT);
1817 FMT_TO_STR(WINED3DFMT_R32_TYPELESS);
1818 FMT_TO_STR(WINED3DFMT_D32_FLOAT);
1819 FMT_TO_STR(WINED3DFMT_R32_FLOAT);
1820 FMT_TO_STR(WINED3DFMT_R32_UINT);
1821 FMT_TO_STR(WINED3DFMT_R32_SINT);
1822 FMT_TO_STR(WINED3DFMT_R24G8_TYPELESS);
1823 FMT_TO_STR(WINED3DFMT_D24_UNORM_S8_UINT);
1824 FMT_TO_STR(WINED3DFMT_R24_UNORM_X8_TYPELESS);
1825 FMT_TO_STR(WINED3DFMT_X24_TYPELESS_G8_UINT);
1826 FMT_TO_STR(WINED3DFMT_R8G8_TYPELESS);
1827 FMT_TO_STR(WINED3DFMT_R8G8_UNORM);
1828 FMT_TO_STR(WINED3DFMT_R8G8_UINT);
1829 FMT_TO_STR(WINED3DFMT_R8G8_SNORM);
1830 FMT_TO_STR(WINED3DFMT_R8G8_SINT);
1831 FMT_TO_STR(WINED3DFMT_R16_TYPELESS);
1832 FMT_TO_STR(WINED3DFMT_R16_FLOAT);
1833 FMT_TO_STR(WINED3DFMT_D16_UNORM);
1834 FMT_TO_STR(WINED3DFMT_R16_UNORM);
1835 FMT_TO_STR(WINED3DFMT_R16_UINT);
1836 FMT_TO_STR(WINED3DFMT_R16_SNORM);
1837 FMT_TO_STR(WINED3DFMT_R16_SINT);
1838 FMT_TO_STR(WINED3DFMT_R8_TYPELESS);
1839 FMT_TO_STR(WINED3DFMT_R8_UNORM);
1840 FMT_TO_STR(WINED3DFMT_R8_UINT);
1841 FMT_TO_STR(WINED3DFMT_R8_SNORM);
1842 FMT_TO_STR(WINED3DFMT_R8_SINT);
1843 FMT_TO_STR(WINED3DFMT_A8_UNORM);
1844 FMT_TO_STR(WINED3DFMT_R1_UNORM);
1845 FMT_TO_STR(WINED3DFMT_R9G9B9E5_SHAREDEXP);
1846 FMT_TO_STR(WINED3DFMT_R8G8_B8G8_UNORM);
1847 FMT_TO_STR(WINED3DFMT_G8R8_G8B8_UNORM);
1848 FMT_TO_STR(WINED3DFMT_BC1_TYPELESS);
1849 FMT_TO_STR(WINED3DFMT_BC1_UNORM);
1850 FMT_TO_STR(WINED3DFMT_BC1_UNORM_SRGB);
1851 FMT_TO_STR(WINED3DFMT_BC2_TYPELESS);
1852 FMT_TO_STR(WINED3DFMT_BC2_UNORM);
1853 FMT_TO_STR(WINED3DFMT_BC2_UNORM_SRGB);
1854 FMT_TO_STR(WINED3DFMT_BC3_TYPELESS);
1855 FMT_TO_STR(WINED3DFMT_BC3_UNORM);
1856 FMT_TO_STR(WINED3DFMT_BC3_UNORM_SRGB);
1857 FMT_TO_STR(WINED3DFMT_BC4_TYPELESS);
1858 FMT_TO_STR(WINED3DFMT_BC4_UNORM);
1859 FMT_TO_STR(WINED3DFMT_BC4_SNORM);
1860 FMT_TO_STR(WINED3DFMT_BC5_TYPELESS);
1861 FMT_TO_STR(WINED3DFMT_BC5_UNORM);
1862 FMT_TO_STR(WINED3DFMT_BC5_SNORM);
1863 FMT_TO_STR(WINED3DFMT_B5G6R5_UNORM);
1864 FMT_TO_STR(WINED3DFMT_B5G5R5A1_UNORM);
1865 FMT_TO_STR(WINED3DFMT_B8G8R8A8_UNORM);
1866 FMT_TO_STR(WINED3DFMT_B8G8R8X8_UNORM);
1867 FMT_TO_STR(WINED3DFMT_INTZ);
1868 FMT_TO_STR(WINED3DFMT_NULL);
1869 FMT_TO_STR(WINED3DFMT_R16);
1870 FMT_TO_STR(WINED3DFMT_AL16);
1871 #undef FMT_TO_STR
1872 default:
1873 {
1874 char fourcc[5];
1875 fourcc[0] = (char)(format_id);
1876 fourcc[1] = (char)(format_id >> 8);
1877 fourcc[2] = (char)(format_id >> 16);
1878 fourcc[3] = (char)(format_id >> 24);
1879 fourcc[4] = 0;
1880 if (isprint(fourcc[0]) && isprint(fourcc[1]) && isprint(fourcc[2]) && isprint(fourcc[3]))
1881 FIXME("Unrecognized %#x (as fourcc: %s) WINED3DFORMAT!\n", format_id, fourcc);
1882 else
1883 FIXME("Unrecognized %#x WINED3DFORMAT!\n", format_id);
1884 }
1885 return "unrecognized";
1886 }
1887 }
1888
1889 const char *debug_d3ddevicetype(enum wined3d_device_type device_type)
1890 {
1891 switch (device_type)
1892 {
1893 #define DEVTYPE_TO_STR(dev) case dev: return #dev
1894 DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_HAL);
1895 DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_REF);
1896 DEVTYPE_TO_STR(WINED3D_DEVICE_TYPE_SW);
1897 #undef DEVTYPE_TO_STR
1898 default:
1899 FIXME("Unrecognized device type %#x.\n", device_type);
1900 return "unrecognized";
1901 }
1902 }
1903
1904 const char *debug_d3dusage(DWORD usage)
1905 {
1906 char buf[333];
1907
1908 buf[0] = '\0';
1909 #define WINED3DUSAGE_TO_STR(u) if (usage & u) { strcat(buf, " | "#u); usage &= ~u; }
1910 WINED3DUSAGE_TO_STR(WINED3DUSAGE_RENDERTARGET);
1911 WINED3DUSAGE_TO_STR(WINED3DUSAGE_DEPTHSTENCIL);
1912 WINED3DUSAGE_TO_STR(WINED3DUSAGE_WRITEONLY);
1913 WINED3DUSAGE_TO_STR(WINED3DUSAGE_SOFTWAREPROCESSING);
1914 WINED3DUSAGE_TO_STR(WINED3DUSAGE_DONOTCLIP);
1915 WINED3DUSAGE_TO_STR(WINED3DUSAGE_POINTS);
1916 WINED3DUSAGE_TO_STR(WINED3DUSAGE_RTPATCHES);
1917 WINED3DUSAGE_TO_STR(WINED3DUSAGE_NPATCHES);
1918 WINED3DUSAGE_TO_STR(WINED3DUSAGE_DYNAMIC);
1919 WINED3DUSAGE_TO_STR(WINED3DUSAGE_AUTOGENMIPMAP);
1920 WINED3DUSAGE_TO_STR(WINED3DUSAGE_DMAP);
1921 WINED3DUSAGE_TO_STR(WINED3DUSAGE_STATICDECL);
1922 WINED3DUSAGE_TO_STR(WINED3DUSAGE_OVERLAY);
1923 #undef WINED3DUSAGE_TO_STR
1924 if (usage) FIXME("Unrecognized usage flag(s) %#x\n", usage);
1925
1926 return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0";
1927 }
1928
1929 const char *debug_d3dusagequery(DWORD usagequery)
1930 {
1931 char buf[238];
1932
1933 buf[0] = '\0';
1934 #define WINED3DUSAGEQUERY_TO_STR(u) if (usagequery & u) { strcat(buf, " | "#u); usagequery &= ~u; }
1935 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_FILTER);
1936 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_LEGACYBUMPMAP);
1937 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING);
1938 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_SRGBREAD);
1939 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_SRGBWRITE);
1940 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_VERTEXTEXTURE);
1941 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_WRAPANDMIP);
1942 #undef WINED3DUSAGEQUERY_TO_STR
1943 if (usagequery) FIXME("Unrecognized usage query flag(s) %#x\n", usagequery);
1944
1945 return buf[0] ? wine_dbg_sprintf("%s", &buf[3]) : "0";
1946 }
1947
1948 const char *debug_d3ddeclmethod(enum wined3d_decl_method method)
1949 {
1950 switch (method)
1951 {
1952 #define WINED3DDECLMETHOD_TO_STR(u) case u: return #u
1953 WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_DEFAULT);
1954 WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_PARTIAL_U);
1955 WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_PARTIAL_V);
1956 WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_CROSS_UV);
1957 WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_UV);
1958 WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_LOOKUP);
1959 WINED3DDECLMETHOD_TO_STR(WINED3D_DECL_METHOD_LOOKUP_PRESAMPLED);
1960 #undef WINED3DDECLMETHOD_TO_STR
1961 default:
1962 FIXME("Unrecognized declaration method %#x.\n", method);
1963 return "unrecognized";
1964 }
1965 }
1966
1967 const char *debug_d3ddeclusage(enum wined3d_decl_usage usage)
1968 {
1969 switch (usage)
1970 {
1971 #define WINED3DDECLUSAGE_TO_STR(u) case u: return #u
1972 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_POSITION);
1973 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BLEND_WEIGHT);
1974 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BLEND_INDICES);
1975 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_NORMAL);
1976 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_PSIZE);
1977 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TEXCOORD);
1978 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TANGENT);
1979 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_BINORMAL);
1980 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_TESS_FACTOR);
1981 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_POSITIONT);
1982 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_COLOR);
1983 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_FOG);
1984 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_DEPTH);
1985 WINED3DDECLUSAGE_TO_STR(WINED3D_DECL_USAGE_SAMPLE);
1986 #undef WINED3DDECLUSAGE_TO_STR
1987 default:
1988 FIXME("Unrecognized %u declaration usage!\n", usage);
1989 return "unrecognized";
1990 }
1991 }
1992
1993 const char *debug_d3dresourcetype(enum wined3d_resource_type resource_type)
1994 {
1995 switch (resource_type)
1996 {
1997 #define RES_TO_STR(res) case res: return #res
1998 RES_TO_STR(WINED3D_RTYPE_SURFACE);
1999 RES_TO_STR(WINED3D_RTYPE_VOLUME);
2000 RES_TO_STR(WINED3D_RTYPE_TEXTURE);
2001 RES_TO_STR(WINED3D_RTYPE_VOLUME_TEXTURE);
2002 RES_TO_STR(WINED3D_RTYPE_CUBE_TEXTURE);
2003 RES_TO_STR(WINED3D_RTYPE_BUFFER);
2004 #undef RES_TO_STR
2005 default:
2006 FIXME("Unrecognized resource type %#x.\n", resource_type);
2007 return "unrecognized";
2008 }
2009 }
2010
2011 const char *debug_d3dprimitivetype(enum wined3d_primitive_type primitive_type)
2012 {
2013 switch (primitive_type)
2014 {
2015 #define PRIM_TO_STR(prim) case prim: return #prim
2016 PRIM_TO_STR(WINED3D_PT_UNDEFINED);
2017 PRIM_TO_STR(WINED3D_PT_POINTLIST);
2018 PRIM_TO_STR(WINED3D_PT_LINELIST);
2019 PRIM_TO_STR(WINED3D_PT_LINESTRIP);
2020 PRIM_TO_STR(WINED3D_PT_TRIANGLELIST);
2021 PRIM_TO_STR(WINED3D_PT_TRIANGLESTRIP);
2022 PRIM_TO_STR(WINED3D_PT_TRIANGLEFAN);
2023 PRIM_TO_STR(WINED3D_PT_LINELIST_ADJ);
2024 PRIM_TO_STR(WINED3D_PT_LINESTRIP_ADJ);
2025 PRIM_TO_STR(WINED3D_PT_TRIANGLELIST_ADJ);
2026 PRIM_TO_STR(WINED3D_PT_TRIANGLESTRIP_ADJ);
2027 #undef PRIM_TO_STR
2028 default:
2029 FIXME("Unrecognized %u primitive type!\n", primitive_type);
2030 return "unrecognized";
2031 }
2032 }
2033
2034 const char *debug_d3drenderstate(enum wined3d_render_state state)
2035 {
2036 switch (state)
2037 {
2038 #define D3DSTATE_TO_STR(u) case u: return #u
2039 D3DSTATE_TO_STR(WINED3D_RS_ANTIALIAS);
2040 D3DSTATE_TO_STR(WINED3D_RS_TEXTUREPERSPECTIVE);
2041 D3DSTATE_TO_STR(WINED3D_RS_WRAPU);
2042 D3DSTATE_TO_STR(WINED3D_RS_WRAPV);
2043 D3DSTATE_TO_STR(WINED3D_RS_ZENABLE);
2044 D3DSTATE_TO_STR(WINED3D_RS_FILLMODE);
2045 D3DSTATE_TO_STR(WINED3D_RS_SHADEMODE);
2046 D3DSTATE_TO_STR(WINED3D_RS_LINEPATTERN);
2047 D3DSTATE_TO_STR(WINED3D_RS_MONOENABLE);
2048 D3DSTATE_TO_STR(WINED3D_RS_ROP2);
2049 D3DSTATE_TO_STR(WINED3D_RS_PLANEMASK);
2050 D3DSTATE_TO_STR(WINED3D_RS_ZWRITEENABLE);
2051 D3DSTATE_TO_STR(WINED3D_RS_ALPHATESTENABLE);
2052 D3DSTATE_TO_STR(WINED3D_RS_LASTPIXEL);
2053 D3DSTATE_TO_STR(WINED3D_RS_SRCBLEND);
2054 D3DSTATE_TO_STR(WINED3D_RS_DESTBLEND);
2055 D3DSTATE_TO_STR(WINED3D_RS_CULLMODE);
2056 D3DSTATE_TO_STR(WINED3D_RS_ZFUNC);
2057 D3DSTATE_TO_STR(WINED3D_RS_ALPHAREF);
2058 D3DSTATE_TO_STR(WINED3D_RS_ALPHAFUNC);
2059 D3DSTATE_TO_STR(WINED3D_RS_DITHERENABLE);
2060 D3DSTATE_TO_STR(WINED3D_RS_ALPHABLENDENABLE);
2061 D3DSTATE_TO_STR(WINED3D_RS_FOGENABLE);
2062 D3DSTATE_TO_STR(WINED3D_RS_SPECULARENABLE);
2063 D3DSTATE_TO_STR(WINED3D_RS_ZVISIBLE);
2064 D3DSTATE_TO_STR(WINED3D_RS_SUBPIXEL);
2065 D3DSTATE_TO_STR(WINED3D_RS_SUBPIXELX);
2066 D3DSTATE_TO_STR(WINED3D_RS_STIPPLEDALPHA);
2067 D3DSTATE_TO_STR(WINED3D_RS_FOGCOLOR);
2068 D3DSTATE_TO_STR(WINED3D_RS_FOGTABLEMODE);
2069 D3DSTATE_TO_STR(WINED3D_RS_FOGSTART);
2070 D3DSTATE_TO_STR(WINED3D_RS_FOGEND);
2071 D3DSTATE_TO_STR(WINED3D_RS_FOGDENSITY);
2072 D3DSTATE_TO_STR(WINED3D_RS_STIPPLEENABLE);
2073 D3DSTATE_TO_STR(WINED3D_RS_EDGEANTIALIAS);
2074 D3DSTATE_TO_STR(WINED3D_RS_COLORKEYENABLE);
2075 D3DSTATE_TO_STR(WINED3D_RS_MIPMAPLODBIAS);
2076 D3DSTATE_TO_STR(WINED3D_RS_RANGEFOGENABLE);
2077 D3DSTATE_TO_STR(WINED3D_RS_ANISOTROPY);
2078 D3DSTATE_TO_STR(WINED3D_RS_FLUSHBATCH);
2079 D3DSTATE_TO_STR(WINED3D_RS_TRANSLUCENTSORTINDEPENDENT);
2080 D3DSTATE_TO_STR(WINED3D_RS_STENCILENABLE);
2081 D3DSTATE_TO_STR(WINED3D_RS_STENCILFAIL);
2082 D3DSTATE_TO_STR(WINED3D_RS_STENCILZFAIL);
2083 D3DSTATE_TO_STR(WINED3D_RS_STENCILPASS);
2084 D3DSTATE_TO_STR(WINED3D_RS_STENCILFUNC);
2085 D3DSTATE_TO_STR(WINED3D_RS_STENCILREF);
2086 D3DSTATE_TO_STR(WINED3D_RS_STENCILMASK);
2087 D3DSTATE_TO_STR(WINED3D_RS_STENCILWRITEMASK);
2088 D3DSTATE_TO_STR(WINED3D_RS_TEXTUREFACTOR);
2089 D3DSTATE_TO_STR(WINED3D_RS_WRAP0);
2090 D3DSTATE_TO_STR(WINED3D_RS_WRAP1);
2091 D3DSTATE_TO_STR(WINED3D_RS_WRAP2);
2092 D3DSTATE_TO_STR(WINED3D_RS_WRAP3);
2093 D3DSTATE_TO_STR(WINED3D_RS_WRAP4);
2094 D3DSTATE_TO_STR(WINED3D_RS_WRAP5);
2095 D3DSTATE_TO_STR(WINED3D_RS_WRAP6);
2096 D3DSTATE_TO_STR(WINED3D_RS_WRAP7);
2097 D3DSTATE_TO_STR(WINED3D_RS_CLIPPING);
2098 D3DSTATE_TO_STR(WINED3D_RS_LIGHTING);
2099 D3DSTATE_TO_STR(WINED3D_RS_EXTENTS);
2100 D3DSTATE_TO_STR(WINED3D_RS_AMBIENT);
2101 D3DSTATE_TO_STR(WINED3D_RS_FOGVERTEXMODE);
2102 D3DSTATE_TO_STR(WINED3D_RS_COLORVERTEX);
2103 D3DSTATE_TO_STR(WINED3D_RS_LOCALVIEWER);
2104 D3DSTATE_TO_STR(WINED3D_RS_NORMALIZENORMALS);
2105 D3DSTATE_TO_STR(WINED3D_RS_COLORKEYBLENDENABLE);
2106 D3DSTATE_TO_STR(WINED3D_RS_DIFFUSEMATERIALSOURCE);
2107 D3DSTATE_TO_STR(WINED3D_RS_SPECULARMATERIALSOURCE);
2108 D3DSTATE_TO_STR(WINED3D_RS_AMBIENTMATERIALSOURCE);
2109 D3DSTATE_TO_STR(WINED3D_RS_EMISSIVEMATERIALSOURCE);
2110 D3DSTATE_TO_STR(WINED3D_RS_VERTEXBLEND);
2111 D3DSTATE_TO_STR(WINED3D_RS_CLIPPLANEENABLE);
2112 D3DSTATE_TO_STR(WINED3D_RS_SOFTWAREVERTEXPROCESSING);
2113 D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE);
2114 D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE_MIN);
2115 D3DSTATE_TO_STR(WINED3D_RS_POINTSPRITEENABLE);
2116 D3DSTATE_TO_STR(WINED3D_RS_POINTSCALEENABLE);
2117 D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_A);
2118 D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_B);
2119 D3DSTATE_TO_STR(WINED3D_RS_POINTSCALE_C);
2120 D3DSTATE_TO_STR(WINED3D_RS_MULTISAMPLEANTIALIAS);
2121 D3DSTATE_TO_STR(WINED3D_RS_MULTISAMPLEMASK);
2122 D3DSTATE_TO_STR(WINED3D_RS_PATCHEDGESTYLE);
2123 D3DSTATE_TO_STR(WINED3D_RS_PATCHSEGMENTS);
2124 D3DSTATE_TO_STR(WINED3D_RS_DEBUGMONITORTOKEN);
2125 D3DSTATE_TO_STR(WINED3D_RS_POINTSIZE_MAX);
2126 D3DSTATE_TO_STR(WINED3D_RS_INDEXEDVERTEXBLENDENABLE);
2127 D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE);
2128 D3DSTATE_TO_STR(WINED3D_RS_TWEENFACTOR);
2129 D3DSTATE_TO_STR(WINED3D_RS_BLENDOP);
2130 D3DSTATE_TO_STR(WINED3D_RS_POSITIONDEGREE);
2131 D3DSTATE_TO_STR(WINED3D_RS_NORMALDEGREE);
2132 D3DSTATE_TO_STR(WINED3D_RS_SCISSORTESTENABLE);
2133 D3DSTATE_TO_STR(WINED3D_RS_SLOPESCALEDEPTHBIAS);
2134 D3DSTATE_TO_STR(WINED3D_RS_ANTIALIASEDLINEENABLE);
2135 D3DSTATE_TO_STR(WINED3D_RS_MINTESSELLATIONLEVEL);
2136 D3DSTATE_TO_STR(WINED3D_RS_MAXTESSELLATIONLEVEL);
2137 D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_X);
2138 D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_Y);
2139 D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_Z);
2140 D3DSTATE_TO_STR(WINED3D_RS_ADAPTIVETESS_W);
2141 D3DSTATE_TO_STR(WINED3D_RS_ENABLEADAPTIVETESSELLATION);
2142 D3DSTATE_TO_STR(WINED3D_RS_TWOSIDEDSTENCILMODE);
2143 D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILFAIL);
2144 D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILZFAIL);
2145 D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILPASS);
2146 D3DSTATE_TO_STR(WINED3D_RS_CCW_STENCILFUNC);
2147 D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE1);
2148 D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE2);
2149 D3DSTATE_TO_STR(WINED3D_RS_COLORWRITEENABLE3);
2150 D3DSTATE_TO_STR(WINED3D_RS_BLENDFACTOR);
2151 D3DSTATE_TO_STR(WINED3D_RS_SRGBWRITEENABLE);
2152 D3DSTATE_TO_STR(WINED3D_RS_DEPTHBIAS);
2153 D3DSTATE_TO_STR(WINED3D_RS_WRAP8);
2154 D3DSTATE_TO_STR(WINED3D_RS_WRAP9);
2155 D3DSTATE_TO_STR(WINED3D_RS_WRAP10);
2156 D3DSTATE_TO_STR(WINED3D_RS_WRAP11);
2157 D3DSTATE_TO_STR(WINED3D_RS_WRAP12);
2158 D3DSTATE_TO_STR(WINED3D_RS_WRAP13);
2159 D3DSTATE_TO_STR(WINED3D_RS_WRAP14);
2160 D3DSTATE_TO_STR(WINED3D_RS_WRAP15);
2161 D3DSTATE_TO_STR(WINED3D_RS_SEPARATEALPHABLENDENABLE);
2162 D3DSTATE_TO_STR(WINED3D_RS_SRCBLENDALPHA);
2163 D3DSTATE_TO_STR(WINED3D_RS_DESTBLENDALPHA);
2164 D3DSTATE_TO_STR(WINED3D_RS_BLENDOPALPHA);
2165 #undef D3DSTATE_TO_STR
2166 default:
2167 FIXME("Unrecognized %u render state!\n", state);
2168 return "unrecognized";
2169 }
2170 }
2171
2172 const char *debug_d3dsamplerstate(enum wined3d_sampler_state state)
2173 {
2174 switch (state)
2175 {
2176 #define D3DSTATE_TO_STR(u) case u: return #u
2177 D3DSTATE_TO_STR(WINED3D_SAMP_BORDER_COLOR);
2178 D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_U);
2179 D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_V);
2180 D3DSTATE_TO_STR(WINED3D_SAMP_ADDRESS_W);
2181 D3DSTATE_TO_STR(WINED3D_SAMP_MAG_FILTER);
2182 D3DSTATE_TO_STR(WINED3D_SAMP_MIN_FILTER);
2183 D3DSTATE_TO_STR(WINED3D_SAMP_MIP_FILTER);
2184 D3DSTATE_TO_STR(WINED3D_SAMP_MIPMAP_LOD_BIAS);
2185 D3DSTATE_TO_STR(WINED3D_SAMP_MAX_MIP_LEVEL);
2186 D3DSTATE_TO_STR(WINED3D_SAMP_MAX_ANISOTROPY);
2187 D3DSTATE_TO_STR(WINED3D_SAMP_SRGB_TEXTURE);
2188 D3DSTATE_TO_STR(WINED3D_SAMP_ELEMENT_INDEX);
2189 D3DSTATE_TO_STR(WINED3D_SAMP_DMAP_OFFSET);
2190 #undef D3DSTATE_TO_STR
2191 default:
2192 FIXME("Unrecognized %u sampler state!\n", state);
2193 return "unrecognized";
2194 }
2195 }
2196
2197 const char *debug_d3dtexturefiltertype(enum wined3d_texture_filter_type filter_type)
2198 {
2199 switch (filter_type)
2200 {
2201 #define D3DTEXTUREFILTERTYPE_TO_STR(u) case u: return #u
2202 D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_NONE);
2203 D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_POINT);
2204 D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_LINEAR);
2205 D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_ANISOTROPIC);
2206 D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_FLAT_CUBIC);
2207 D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_GAUSSIAN_CUBIC);
2208 D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_PYRAMIDAL_QUAD);
2209 D3DTEXTUREFILTERTYPE_TO_STR(WINED3D_TEXF_GAUSSIAN_QUAD);
2210 #undef D3DTEXTUREFILTERTYPE_TO_STR
2211 default:
2212 FIXME("Unrecognied texture filter type 0x%08x.\n", filter_type);
2213 return "unrecognized";
2214 }
2215 }
2216
2217 const char *debug_d3dtexturestate(enum wined3d_texture_stage_state state)
2218 {
2219 switch (state)
2220 {
2221 #define D3DSTATE_TO_STR(u) case u: return #u
2222 D3DSTATE_TO_STR(WINED3D_TSS_COLOR_OP);
2223 D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG1);
2224 D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG2);
2225 D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_OP);
2226 D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG1);
2227 D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG2);
2228 D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT00);
2229 D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT01);
2230 D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT10);
2231 D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_MAT11);
2232 D3DSTATE_TO_STR(WINED3D_TSS_TEXCOORD_INDEX);
2233 D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_LSCALE);
2234 D3DSTATE_TO_STR(WINED3D_TSS_BUMPENV_LOFFSET);
2235 D3DSTATE_TO_STR(WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS);
2236 D3DSTATE_TO_STR(WINED3D_TSS_COLOR_ARG0);
2237 D3DSTATE_TO_STR(WINED3D_TSS_ALPHA_ARG0);
2238 D3DSTATE_TO_STR(WINED3D_TSS_RESULT_ARG);
2239 D3DSTATE_TO_STR(WINED3D_TSS_CONSTANT);
2240 #undef D3DSTATE_TO_STR
2241 default:
2242 FIXME("Unrecognized %u texture state!\n", state);
2243 return "unrecognized";
2244 }
2245 }
2246
2247 const char *debug_d3dtop(enum wined3d_texture_op d3dtop)
2248 {
2249 switch (d3dtop)
2250 {
2251 #define D3DTOP_TO_STR(u) case u: return #u
2252 D3DTOP_TO_STR(WINED3D_TOP_DISABLE);
2253 D3DTOP_TO_STR(WINED3D_TOP_SELECT_ARG1);
2254 D3DTOP_TO_STR(WINED3D_TOP_SELECT_ARG2);
2255 D3DTOP_TO_STR(WINED3D_TOP_MODULATE);
2256 D3DTOP_TO_STR(WINED3D_TOP_MODULATE_2X);
2257 D3DTOP_TO_STR(WINED3D_TOP_MODULATE_4X);
2258 D3DTOP_TO_STR(WINED3D_TOP_ADD);
2259 D3DTOP_TO_STR(WINED3D_TOP_ADD_SIGNED);
2260 D3DTOP_TO_STR(WINED3D_TOP_ADD_SIGNED_2X);
2261 D3DTOP_TO_STR(WINED3D_TOP_SUBTRACT);
2262 D3DTOP_TO_STR(WINED3D_TOP_ADD_SMOOTH);
2263 D3DTOP_TO_STR(WINED3D_TOP_BLEND_DIFFUSE_ALPHA);
2264 D3DTOP_TO_STR(WINED3D_TOP_BLEND_TEXTURE_ALPHA);
2265 D3DTOP_TO_STR(WINED3D_TOP_BLEND_FACTOR_ALPHA);
2266 D3DTOP_TO_STR(WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM);
2267 D3DTOP_TO_STR(WINED3D_TOP_BLEND_CURRENT_ALPHA);
2268 D3DTOP_TO_STR(WINED3D_TOP_PREMODULATE);
2269 D3DTOP_TO_STR(WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR);
2270 D3DTOP_TO_STR(WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA);
2271 D3DTOP_TO_STR(WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR);
2272 D3DTOP_TO_STR(WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA);
2273 D3DTOP_TO_STR(WINED3D_TOP_BUMPENVMAP);
2274 D3DTOP_TO_STR(WINED3D_TOP_BUMPENVMAP_LUMINANCE);
2275 D3DTOP_TO_STR(WINED3D_TOP_DOTPRODUCT3);
2276 D3DTOP_TO_STR(WINED3D_TOP_MULTIPLY_ADD);
2277 D3DTOP_TO_STR(WINED3D_TOP_LERP);
2278 #undef D3DTOP_TO_STR
2279 default:
2280 FIXME("Unrecognized texture op %#x.\n", d3dtop);
2281 return "unrecognized";
2282 }
2283 }
2284
2285 const char *debug_d3dtstype(enum wined3d_transform_state tstype)
2286 {
2287 switch (tstype)
2288 {
2289 #define TSTYPE_TO_STR(tstype) case tstype: return #tstype
2290 TSTYPE_TO_STR(WINED3D_TS_VIEW);
2291 TSTYPE_TO_STR(WINED3D_TS_PROJECTION);
2292 TSTYPE_TO_STR(WINED3D_TS_TEXTURE0);
2293 TSTYPE_TO_STR(WINED3D_TS_TEXTURE1);
2294 TSTYPE_TO_STR(WINED3D_TS_TEXTURE2);
2295 TSTYPE_TO_STR(WINED3D_TS_TEXTURE3);
2296 TSTYPE_TO_STR(WINED3D_TS_TEXTURE4);
2297 TSTYPE_TO_STR(WINED3D_TS_TEXTURE5);
2298 TSTYPE_TO_STR(WINED3D_TS_TEXTURE6);
2299 TSTYPE_TO_STR(WINED3D_TS_TEXTURE7);
2300 TSTYPE_TO_STR(WINED3D_TS_WORLD_MATRIX(0));
2301 #undef TSTYPE_TO_STR
2302 default:
2303 if (tstype > 256 && tstype < 512)
2304 {
2305 FIXME("WINED3D_TS_WORLD_MATRIX(%u). 1..255 not currently supported.\n", tstype);
2306 return ("WINED3D_TS_WORLD_MATRIX > 0");
2307 }
2308 FIXME("Unrecognized transform state %#x.\n", tstype);
2309 return "unrecognized";
2310 }
2311 }
2312
2313 const char *debug_d3dstate(DWORD state)
2314 {
2315 if (STATE_IS_RENDER(state))
2316 return wine_dbg_sprintf("STATE_RENDER(%s)", debug_d3drenderstate(state - STATE_RENDER(0)));
2317 if (STATE_IS_TEXTURESTAGE(state))
2318 {
2319 DWORD texture_stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2320 DWORD texture_state = state - STATE_TEXTURESTAGE(texture_stage, 0);
2321 return wine_dbg_sprintf("STATE_TEXTURESTAGE(%#x, %s)",
2322 texture_stage, debug_d3dtexturestate(texture_state));
2323 }
2324 if (STATE_IS_SAMPLER(state))
2325 return wine_dbg_sprintf("STATE_SAMPLER(%#x)", state - STATE_SAMPLER(0));
2326 if (STATE_IS_PIXELSHADER(state))
2327 return "STATE_PIXELSHADER";
2328 if (STATE_IS_TRANSFORM(state))
2329 return wine_dbg_sprintf("STATE_TRANSFORM(%s)", debug_d3dtstype(state - STATE_TRANSFORM(0)));
2330 if (STATE_IS_STREAMSRC(state))
2331 return "STATE_STREAMSRC";
2332 if (STATE_IS_INDEXBUFFER(state))
2333 return "STATE_INDEXBUFFER";
2334 if (STATE_IS_VDECL(state))
2335 return "STATE_VDECL";
2336 if (STATE_IS_VSHADER(state))
2337 return "STATE_VSHADER";
2338 if (STATE_IS_VIEWPORT(state))
2339 return "STATE_VIEWPORT";
2340 if (STATE_IS_VERTEXSHADERCONSTANT(state))
2341 return "STATE_VERTEXSHADERCONSTANT";
2342 if (STATE_IS_PIXELSHADERCONSTANT(state))
2343 return "STATE_PIXELSHADERCONSTANT";
2344 if (STATE_IS_ACTIVELIGHT(state))
2345 return wine_dbg_sprintf("STATE_ACTIVELIGHT(%#x)", state - STATE_ACTIVELIGHT(0));
2346 if (STATE_IS_SCISSORRECT(state))
2347 return "STATE_SCISSORRECT";
2348 if (STATE_IS_CLIPPLANE(state))
2349 return wine_dbg_sprintf("STATE_CLIPPLANE(%#x)", state - STATE_CLIPPLANE(0));
2350 if (STATE_IS_MATERIAL(state))
2351 return "STATE_MATERIAL";
2352 if (STATE_IS_FRONTFACE(state))
2353 return "STATE_FRONTFACE";
2354 if (STATE_IS_POINTSPRITECOORDORIGIN(state))
2355 return "STATE_POINTSPRITECOORDORIGIN";
2356 if (STATE_IS_BASEVERTEXINDEX(state))
2357 return "STATE_BASEVERTEXINDEX";
2358 if (STATE_IS_FRAMEBUFFER(state))
2359 return "STATE_FRAMEBUFFER";
2360
2361 return wine_dbg_sprintf("UNKNOWN_STATE(%#x)", state);
2362 }
2363
2364 const char *debug_d3dpool(enum wined3d_pool pool)
2365 {
2366 switch (pool)
2367 {
2368 #define POOL_TO_STR(p) case p: return #p
2369 POOL_TO_STR(WINED3D_POOL_DEFAULT);
2370 POOL_TO_STR(WINED3D_POOL_MANAGED);
2371 POOL_TO_STR(WINED3D_POOL_SYSTEM_MEM);
2372 POOL_TO_STR(WINED3D_POOL_SCRATCH);
2373 #undef POOL_TO_STR
2374 default:
2375 FIXME("Unrecognized pool %#x.\n", pool);
2376 return "unrecognized";
2377 }
2378 }
2379
2380 const char *debug_fbostatus(GLenum status) {
2381 switch(status) {
2382 #define FBOSTATUS_TO_STR(u) case u: return #u
2383 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_COMPLETE);
2384 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT);
2385 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT);
2386 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT);
2387 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT);
2388 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER);
2389 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER);
2390 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE);
2391 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_UNSUPPORTED);
2392 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_UNDEFINED);
2393 #undef FBOSTATUS_TO_STR
2394 default:
2395 FIXME("Unrecognied FBO status 0x%08x\n", status);
2396 return "unrecognized";
2397 }
2398 }
2399
2400 const char *debug_glerror(GLenum error) {
2401 switch(error) {
2402 #define GLERROR_TO_STR(u) case u: return #u
2403 GLERROR_TO_STR(GL_NO_ERROR);
2404 GLERROR_TO_STR(GL_INVALID_ENUM);
2405 GLERROR_TO_STR(GL_INVALID_VALUE);
2406 GLERROR_TO_STR(GL_INVALID_OPERATION);
2407 GLERROR_TO_STR(GL_STACK_OVERFLOW);
2408 GLERROR_TO_STR(GL_STACK_UNDERFLOW);
2409 GLERROR_TO_STR(GL_OUT_OF_MEMORY);
2410 GLERROR_TO_STR(GL_INVALID_FRAMEBUFFER_OPERATION);
2411 #undef GLERROR_TO_STR
2412 default:
2413 FIXME("Unrecognied GL error 0x%08x\n", error);
2414 return "unrecognized";
2415 }
2416 }
2417
2418 const char *debug_d3dbasis(enum wined3d_basis_type basis)
2419 {
2420 switch (basis)
2421 {
2422 case WINED3D_BASIS_BEZIER: return "WINED3D_BASIS_BEZIER";
2423 case WINED3D_BASIS_BSPLINE: return "WINED3D_BASIS_BSPLINE";
2424 case WINED3D_BASIS_INTERPOLATE: return "WINED3D_BASIS_INTERPOLATE";
2425 default: return "unrecognized";
2426 }
2427 }
2428
2429 const char *debug_d3ddegree(enum wined3d_degree_type degree)
2430 {
2431 switch (degree)
2432 {
2433 case WINED3D_DEGREE_LINEAR: return "WINED3D_DEGREE_LINEAR";
2434 case WINED3D_DEGREE_QUADRATIC: return "WINED3D_DEGREE_QUADRATIC";
2435 case WINED3D_DEGREE_CUBIC: return "WINED3D_DEGREE_CUBIC";
2436 case WINED3D_DEGREE_QUINTIC: return "WINED3D_DEGREE_QUINTIC";
2437 default: return "unrecognized";
2438 }
2439 }
2440
2441 static const char *debug_fixup_channel_source(enum fixup_channel_source source)
2442 {
2443 switch(source)
2444 {
2445 #define WINED3D_TO_STR(x) case x: return #x
2446 WINED3D_TO_STR(CHANNEL_SOURCE_ZERO);
2447 WINED3D_TO_STR(CHANNEL_SOURCE_ONE);
2448 WINED3D_TO_STR(CHANNEL_SOURCE_X);
2449 WINED3D_TO_STR(CHANNEL_SOURCE_Y);
2450 WINED3D_TO_STR(CHANNEL_SOURCE_Z);
2451 WINED3D_TO_STR(CHANNEL_SOURCE_W);
2452 WINED3D_TO_STR(CHANNEL_SOURCE_COMPLEX0);
2453 WINED3D_TO_STR(CHANNEL_SOURCE_COMPLEX1);
2454 #undef WINED3D_TO_STR
2455 default:
2456 FIXME("Unrecognized fixup_channel_source %#x\n", source);
2457 return "unrecognized";
2458 }
2459 }
2460
2461 static const char *debug_complex_fixup(enum complex_fixup fixup)
2462 {
2463 switch(fixup)
2464 {
2465 #define WINED3D_TO_STR(x) case x: return #x
2466 WINED3D_TO_STR(COMPLEX_FIXUP_YUY2);
2467 WINED3D_TO_STR(COMPLEX_FIXUP_UYVY);
2468 WINED3D_TO_STR(COMPLEX_FIXUP_YV12);
2469 WINED3D_TO_STR(COMPLEX_FIXUP_P8);
2470 #undef WINED3D_TO_STR
2471 default:
2472 FIXME("Unrecognized complex fixup %#x\n", fixup);
2473 return "unrecognized";
2474 }
2475 }
2476
2477 void dump_color_fixup_desc(struct color_fixup_desc fixup)
2478 {
2479 if (is_complex_fixup(fixup))
2480 {
2481 TRACE("\tComplex: %s\n", debug_complex_fixup(get_complex_fixup(fixup)));
2482 return;
2483 }
2484
2485 TRACE("\tX: %s%s\n", debug_fixup_channel_source(fixup.x_source), fixup.x_sign_fixup ? ", SIGN_FIXUP" : "");
2486 TRACE("\tY: %s%s\n", debug_fixup_channel_source(fixup.y_source), fixup.y_sign_fixup ? ", SIGN_FIXUP" : "");
2487 TRACE("\tZ: %s%s\n", debug_fixup_channel_source(fixup.z_source), fixup.z_sign_fixup ? ", SIGN_FIXUP" : "");
2488 TRACE("\tW: %s%s\n", debug_fixup_channel_source(fixup.w_source), fixup.w_sign_fixup ? ", SIGN_FIXUP" : "");
2489 }
2490
2491 const char *debug_surflocation(DWORD flag) {
2492 char buf[128];
2493
2494 buf[0] = 0;
2495 if (flag & SFLAG_INSYSMEM) strcat(buf, " | SFLAG_INSYSMEM"); /* 17 */
2496 if (flag & SFLAG_INDRAWABLE) strcat(buf, " | SFLAG_INDRAWABLE"); /* 19 */
2497 if (flag & SFLAG_INTEXTURE) strcat(buf, " | SFLAG_INTEXTURE"); /* 18 */
2498 if (flag & SFLAG_INSRGBTEX) strcat(buf, " | SFLAG_INSRGBTEX"); /* 18 */
2499 if (flag & SFLAG_INRB_MULTISAMPLE) strcat(buf, " | SFLAG_INRB_MULTISAMPLE"); /* 25 */
2500 if (flag & SFLAG_INRB_RESOLVED) strcat(buf, " | SFLAG_INRB_RESOLVED"); /* 22 */
2501 return wine_dbg_sprintf("%s", buf[0] ? buf + 3 : "0");
2502 }
2503
2504 BOOL is_invalid_op(const struct wined3d_state *state, int stage,
2505 enum wined3d_texture_op op, DWORD arg1, DWORD arg2, DWORD arg3)
2506 {
2507 if (op == WINED3D_TOP_DISABLE)
2508 return FALSE;
2509 if (state->textures[stage])
2510 return FALSE;
2511
2512 if ((arg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
2513 && op != WINED3D_TOP_SELECT_ARG2)
2514 return TRUE;
2515 if ((arg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
2516 && op != WINED3D_TOP_SELECT_ARG1)
2517 return TRUE;
2518 if ((arg3 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
2519 && (op == WINED3D_TOP_MULTIPLY_ADD || op == WINED3D_TOP_LERP))
2520 return TRUE;
2521
2522 return FALSE;
2523 }
2524
2525 /* Setup this textures matrix according to the texture flags*/
2526 /* GL locking is done by the caller (state handler) */
2527 void set_texture_matrix(const struct wined3d_gl_info *gl_info, const float *smat, DWORD flags,
2528 BOOL calculatedCoords, BOOL transformed, enum wined3d_format_id vtx_fmt, BOOL ffp_proj_control)
2529 {
2530 float mat[16];
2531
2532 gl_info->gl_ops.gl.p_glMatrixMode(GL_TEXTURE);
2533 checkGLcall("glMatrixMode(GL_TEXTURE)");
2534
2535 if (flags == WINED3D_TTFF_DISABLE || flags == WINED3D_TTFF_COUNT1 || transformed)
2536 {
2537 gl_info->gl_ops.gl.p_glLoadIdentity();
2538 checkGLcall("glLoadIdentity()");
2539 return;
2540 }
2541
2542 if (flags == (WINED3D_TTFF_COUNT1 | WINED3D_TTFF_PROJECTED))
2543 {
2544 ERR("Invalid texture transform flags: WINED3D_TTFF_COUNT1 | WINED3D_TTFF_PROJECTED.\n");
2545 return;
2546 }
2547
2548 memcpy(mat, smat, 16 * sizeof(float));
2549
2550 if (flags & WINED3D_TTFF_PROJECTED)
2551 {
2552 if (!ffp_proj_control)
2553 {
2554 switch (flags & ~WINED3D_TTFF_PROJECTED)
2555 {
2556 case WINED3D_TTFF_COUNT2:
2557 mat[ 3] = mat[ 1];
2558 mat[ 7] = mat[ 5];
2559 mat[11] = mat[ 9];
2560 mat[15] = mat[13];
2561 mat[ 1] = mat[ 5] = mat[ 9] = mat[13] = 0.0f;
2562 break;
2563 case WINED3D_TTFF_COUNT3:
2564 mat[ 3] = mat[ 2];
2565 mat[ 7] = mat[ 6];
2566 mat[11] = mat[10];
2567 mat[15] = mat[14];
2568 mat[ 2] = mat[ 6] = mat[10] = mat[14] = 0.0f;
2569 break;
2570 }
2571 }
2572 } else { /* under directx the R/Z coord can be used for translation, under opengl we use the Q coord instead */
2573 if(!calculatedCoords) {
2574 switch(vtx_fmt)
2575 {
2576 case WINED3DFMT_R32_FLOAT:
2577 /* Direct3D passes the default 1.0 in the 2nd coord, while gl passes it in the 4th.
2578 * swap 2nd and 4th coord. No need to store the value of mat[12] in mat[4] because
2579 * the input value to the transformation will be 0, so the matrix value is irrelevant
2580 */
2581 mat[12] = mat[4];
2582 mat[13] = mat[5];
2583 mat[14] = mat[6];
2584 mat[15] = mat[7];
2585 break;
2586 case WINED3DFMT_R32G32_FLOAT:
2587 /* See above, just 3rd and 4th coord
2588 */
2589 mat[12] = mat[8];
2590 mat[13] = mat[9];
2591 mat[14] = mat[10];
2592 mat[15] = mat[11];
2593 break;
2594 case WINED3DFMT_R32G32B32_FLOAT: /* Opengl defaults match dx defaults */
2595 case WINED3DFMT_R32G32B32A32_FLOAT: /* No defaults apply, all app defined */
2596
2597 /* This is to prevent swapping the matrix lines and put the default 4th coord = 1.0
2598 * into a bad place. The division elimination below will apply to make sure the
2599 * 1.0 doesn't do anything bad. The caller will set this value if the stride is 0
2600 */
2601 case WINED3DFMT_UNKNOWN: /* No texture coords, 0/0/0/1 defaults are passed */
2602 break;
2603 default:
2604 FIXME("Unexpected fixed function texture coord input\n");
2605 }
2606 }
2607 if (!ffp_proj_control)
2608 {
2609 switch (flags & ~WINED3D_TTFF_PROJECTED)
2610 {
2611 /* case WINED3D_TTFF_COUNT1: Won't ever get here. */
2612 case WINED3D_TTFF_COUNT2:
2613 mat[2] = mat[6] = mat[10] = mat[14] = 0;
2614 /* OpenGL divides the first 3 vertex coord by the 4th by default,
2615 * which is essentially the same as D3DTTFF_PROJECTED. Make sure that
2616 * the 4th coord evaluates to 1.0 to eliminate that.
2617 *
2618 * If the fixed function pipeline is used, the 4th value remains unused,
2619 * so there is no danger in doing this. With vertex shaders we have a
2620 * problem. Should an app hit that problem, the code here would have to
2621 * check for pixel shaders, and the shader has to undo the default gl divide.
2622 *
2623 * A more serious problem occurs if the app passes 4 coordinates in, and the
2624 * 4th is != 1.0(opengl default). This would have to be fixed in drawStridedSlow
2625 * or a replacement shader. */
2626 default:
2627 mat[3] = mat[7] = mat[11] = 0; mat[15] = 1;
2628 }
2629 }
2630 }
2631
2632 gl_info->gl_ops.gl.p_glLoadMatrixf(mat);
2633 checkGLcall("glLoadMatrixf(mat)");
2634 }
2635
2636 /* This small helper function is used to convert a bitmask into the number of masked bits */
2637 unsigned int count_bits(unsigned int mask)
2638 {
2639 unsigned int count;
2640 for (count = 0; mask; ++count)
2641 {
2642 mask &= mask - 1;
2643 }
2644 return count;
2645 }
2646
2647 /* Helper function for retrieving color info for ChoosePixelFormat and wglChoosePixelFormatARB.
2648 * The later function requires individual color components. */
2649 BOOL getColorBits(const struct wined3d_format *format,
2650 BYTE *redSize, BYTE *greenSize, BYTE *blueSize, BYTE *alphaSize, BYTE *totalSize)
2651 {
2652 TRACE("format %s.\n", debug_d3dformat(format->id));
2653
2654 switch (format->id)
2655 {
2656 case WINED3DFMT_B10G10R10A2_UNORM:
2657 case WINED3DFMT_R10G10B10A2_UNORM:
2658 case WINED3DFMT_B8G8R8X8_UNORM:
2659 case WINED3DFMT_B8G8R8_UNORM:
2660 case WINED3DFMT_B8G8R8A8_UNORM:
2661 case WINED3DFMT_R8G8B8A8_UNORM:
2662 case WINED3DFMT_B5G5R5X1_UNORM:
2663 case WINED3DFMT_B5G5R5A1_UNORM:
2664 case WINED3DFMT_B5G6R5_UNORM:
2665 case WINED3DFMT_B4G4R4X4_UNORM:
2666 case WINED3DFMT_B4G4R4A4_UNORM:
2667 case WINED3DFMT_B2G3R3_UNORM:
2668 case WINED3DFMT_P8_UINT_A8_UNORM:
2669 case WINED3DFMT_P8_UINT:
2670 break;
2671 default:
2672 FIXME("Unsupported format %s.\n", debug_d3dformat(format->id));
2673 return FALSE;
2674 }
2675
2676 *redSize = format->red_size;
2677 *greenSize = format->green_size;
2678 *blueSize = format->blue_size;
2679 *alphaSize = format->alpha_size;
2680 *totalSize = *redSize + *greenSize + *blueSize + *alphaSize;
2681
2682 TRACE("Returning red: %d, green: %d, blue: %d, alpha: %d, total: %d for format %s.\n",
2683 *redSize, *greenSize, *blueSize, *alphaSize, *totalSize, debug_d3dformat(format->id));
2684 return TRUE;
2685 }
2686
2687 /* Helper function for retrieving depth/stencil info for ChoosePixelFormat and wglChoosePixelFormatARB */
2688 BOOL getDepthStencilBits(const struct wined3d_format *format, BYTE *depthSize, BYTE *stencilSize)
2689 {
2690 TRACE("format %s.\n", debug_d3dformat(format->id));
2691
2692 switch (format->id)
2693 {
2694 case WINED3DFMT_D16_LOCKABLE:
2695 case WINED3DFMT_D16_UNORM:
2696 case WINED3DFMT_S1_UINT_D15_UNORM:
2697 case WINED3DFMT_X8D24_UNORM:
2698 case WINED3DFMT_S4X4_UINT_D24_UNORM:
2699 case WINED3DFMT_D24_UNORM_S8_UINT:
2700 case WINED3DFMT_S8_UINT_D24_FLOAT:
2701 case WINED3DFMT_D32_UNORM:
2702 case WINED3DFMT_D32_FLOAT:
2703 case WINED3DFMT_INTZ:
2704 break;
2705 default:
2706 FIXME("Unsupported depth/stencil format %s.\n", debug_d3dformat(format->id));
2707 return FALSE;
2708 }
2709
2710 *depthSize = format->depth_size;
2711 *stencilSize = format->stencil_size;
2712
2713 TRACE("Returning depthSize: %d and stencilSize: %d for format %s.\n",
2714 *depthSize, *stencilSize, debug_d3dformat(format->id));
2715 return TRUE;
2716 }
2717
2718 /* Note: It's the caller's responsibility to ensure values can be expressed
2719 * in the requested format. UNORM formats for example can only express values
2720 * in the range 0.0f -> 1.0f. */
2721 DWORD wined3d_format_convert_from_float(const struct wined3d_surface *surface, const struct wined3d_color *color)
2722 {
2723 static const struct
2724 {
2725 enum wined3d_format_id format_id;
2726 float r_mul;
2727 float g_mul;
2728 float b_mul;
2729 float a_mul;
2730 BYTE r_shift;
2731 BYTE g_shift;
2732 BYTE b_shift;
2733 BYTE a_shift;
2734 }
2735 conv[] =
2736 {
2737 {WINED3DFMT_B8G8R8A8_UNORM, 255.0f, 255.0f, 255.0f, 255.0f, 16, 8, 0, 24},
2738 {WINED3DFMT_B8G8R8X8_UNORM, 255.0f, 255.0f, 255.0f, 255.0f, 16, 8, 0, 24},
2739 {WINED3DFMT_B8G8R8_UNORM, 255.0f, 255.0f, 255.0f, 255.0f, 16, 8, 0, 24},
2740 {WINED3DFMT_B5G6R5_UNORM, 31.0f, 63.0f, 31.0f, 0.0f, 11, 5, 0, 0},
2741 {WINED3DFMT_B5G5R5A1_UNORM, 31.0f, 31.0f, 31.0f, 1.0f, 10, 5, 0, 15},
2742 {WINED3DFMT_B5G5R5X1_UNORM, 31.0f, 31.0f, 31.0f, 1.0f, 10, 5, 0, 15},
2743 {WINED3DFMT_A8_UNORM, 0.0f, 0.0f, 0.0f, 255.0f, 0, 0, 0, 0},
2744 {WINED3DFMT_B4G4R4A4_UNORM, 15.0f, 15.0f, 15.0f, 15.0f, 8, 4, 0, 12},
2745 {WINED3DFMT_B4G4R4X4_UNORM, 15.0f, 15.0f, 15.0f, 15.0f, 8, 4, 0, 12},
2746 {WINED3DFMT_B2G3R3_UNORM, 7.0f, 7.0f, 3.0f, 0.0f, 5, 2, 0, 0},
2747 {WINED3DFMT_R8G8B8A8_UNORM, 255.0f, 255.0f, 255.0f, 255.0f, 0, 8, 16, 24},
2748 {WINED3DFMT_R8G8B8X8_UNORM, 255.0f, 255.0f, 255.0f, 255.0f, 0, 8, 16, 24},
2749 {WINED3DFMT_B10G10R10A2_UNORM, 1023.0f, 1023.0f, 1023.0f, 3.0f, 20, 10, 0, 30},
2750 {WINED3DFMT_R10G10B10A2_UNORM, 1023.0f, 1023.0f, 1023.0f, 3.0f, 0, 10, 20, 30},
2751 };
2752 const struct wined3d_format *format = surface->resource.format;
2753 unsigned int i;
2754
2755 TRACE("Converting color {%.8e %.8e %.8e %.8e} to format %s.\n",
2756 color->r, color->g, color->b, color->a, debug_d3dformat(format->id));
2757
2758 for (i = 0; i < sizeof(conv) / sizeof(*conv); ++i)
2759 {
2760 DWORD ret;
2761
2762 if (format->id != conv[i].format_id) continue;
2763
2764 ret = ((DWORD)((color->r * conv[i].r_mul) + 0.5f)) << conv[i].r_shift;
2765 ret |= ((DWORD)((color->g * conv[i].g_mul) + 0.5f)) << conv[i].g_shift;
2766 ret |= ((DWORD)((color->b * conv[i].b_mul) + 0.5f)) << conv[i].b_shift;
2767 ret |= ((DWORD)((color->a * conv[i].a_mul) + 0.5f)) << conv[i].a_shift;
2768
2769 TRACE("Returning 0x%08x.\n", ret);
2770
2771 return ret;
2772 }
2773
2774 if (format->id == WINED3DFMT_P8_UINT)
2775 {
2776 PALETTEENTRY *e;
2777 BYTE r, g, b, a;
2778
2779 if (!surface->palette)
2780 {
2781 WARN("Surface doesn't have a palette, returning 0.\n");
2782 return 0;
2783 }
2784
2785 r = (BYTE)((color->r * 255.0f) + 0.5f);
2786 g = (BYTE)((color->g * 255.0f) + 0.5f);
2787 b = (BYTE)((color->b * 255.0f) + 0.5f);
2788 a = (BYTE)((color->a * 255.0f) + 0.5f);
2789
2790 e = &surface->palette->palents[a];
2791 if (e->peRed == r && e->peGreen == g && e->peBlue == b)
2792 return a;
2793
2794 WARN("Alpha didn't match index, searching full palette.\n");
2795
2796 for (i = 0; i < 256; ++i)
2797 {
2798 e = &surface->palette->palents[i];
2799 if (e->peRed == r && e->peGreen == g && e->peBlue == b)
2800 return i;
2801 }
2802
2803 FIXME("Unable to convert color to palette index.\n");
2804
2805 return 0;
2806 }
2807
2808 FIXME("Conversion for format %s not implemented.\n", debug_d3dformat(format->id));
2809
2810 return 0;
2811 }
2812
2813 /* DirectDraw stuff */
2814 enum wined3d_format_id pixelformat_for_depth(DWORD depth)
2815 {
2816 switch (depth)
2817 {
2818 case 8: return WINED3DFMT_P8_UINT;
2819 case 15: return WINED3DFMT_B5G5R5X1_UNORM;
2820 case 16: return WINED3DFMT_B5G6R5_UNORM;
2821 case 24: return WINED3DFMT_B8G8R8X8_UNORM; /* Robots needs 24bit to be WINED3DFMT_B8G8R8X8_UNORM */
2822 case 32: return WINED3DFMT_B8G8R8X8_UNORM; /* EVE online and the Fur demo need 32bit AdapterDisplayMode to return WINED3DFMT_B8G8R8X8_UNORM */
2823 default: return WINED3DFMT_UNKNOWN;
2824 }
2825 }
2826
2827 void multiply_matrix(struct wined3d_matrix *dest, const struct wined3d_matrix *src1,
2828 const struct wined3d_matrix *src2)
2829 {
2830 struct wined3d_matrix temp;
2831
2832 /* Now do the multiplication 'by hand'.
2833 I know that all this could be optimised, but this will be done later :-) */
2834 temp.u.s._11 = (src1->u.s._11 * src2->u.s._11) + (src1->u.s._21 * src2->u.s._12) + (src1->u.s._31 * src2->u.s._13) + (src1->u.s._41 * src2->u.s._14);
2835 temp.u.s._21 = (src1->u.s._11 * src2->u.s._21) + (src1->u.s._21 * src2->u.s._22) + (src1->u.s._31 * src2->u.s._23) + (src1->u.s._41 * src2->u.s._24);
2836 temp.u.s._31 = (src1->u.s._11 * src2->u.s._31) + (src1->u.s._21 * src2->u.s._32) + (src1->u.s._31 * src2->u.s._33) + (src1->u.s._41 * src2->u.s._34);
2837 temp.u.s._41 = (src1->u.s._11 * src2->u.s._41) + (src1->u.s._21 * src2->u.s._42) + (src1->u.s._31 * src2->u.s._43) + (src1->u.s._41 * src2->u.s._44);
2838
2839 temp.u.s._12 = (src1->u.s._12 * src2->u.s._11) + (src1->u.s._22 * src2->u.s._12) + (src1->u.s._32 * src2->u.s._13) + (src1->u.s._42 * src2->u.s._14);
2840 temp.u.s._22 = (src1->u.s._12 * src2->u.s._21) + (src1->u.s._22 * src2->u.s._22) + (src1->u.s._32 * src2->u.s._23) + (src1->u.s._42 * src2->u.s._24);
2841 temp.u.s._32 = (src1->u.s._12 * src2->u.s._31) + (src1->u.s._22 * src2->u.s._32) + (src1->u.s._32 * src2->u.s._33) + (src1->u.s._42 * src2->u.s._34);
2842 temp.u.s._42 = (src1->u.s._12 * src2->u.s._41) + (src1->u.s._22 * src2->u.s._42) + (src1->u.s._32 * src2->u.s._43) + (src1->u.s._42 * src2->u.s._44);
2843
2844 temp.u.s._13 = (src1->u.s._13 * src2->u.s._11) + (src1->u.s._23 * src2->u.s._12) + (src1->u.s._33 * src2->u.s._13) + (src1->u.s._43 * src2->u.s._14);
2845 temp.u.s._23 = (src1->u.s._13 * src2->u.s._21) + (src1->u.s._23 * src2->u.s._22) + (src1->u.s._33 * src2->u.s._23) + (src1->u.s._43 * src2->u.s._24);
2846 temp.u.s._33 = (src1->u.s._13 * src2->u.s._31) + (src1->u.s._23 * src2->u.s._32) + (src1->u.s._33 * src2->u.s._33) + (src1->u.s._43 * src2->u.s._34);
2847 temp.u.s._43 = (src1->u.s._13 * src2->u.s._41) + (src1->u.s._23 * src2->u.s._42) + (src1->u.s._33 * src2->u.s._43) + (src1->u.s._43 * src2->u.s._44);
2848
2849 temp.u.s._14 = (src1->u.s._14 * src2->u.s._11) + (src1->u.s._24 * src2->u.s._12) + (src1->u.s._34 * src2->u.s._13) + (src1->u.s._44 * src2->u.s._14);
2850 temp.u.s._24 = (src1->u.s._14 * src2->u.s._21) + (src1->u.s._24 * src2->u.s._22) + (src1->u.s._34 * src2->u.s._23) + (src1->u.s._44 * src2->u.s._24);
2851 temp.u.s._34 = (src1->u.s._14 * src2->u.s._31) + (src1->u.s._24 * src2->u.s._32) + (src1->u.s._34 * src2->u.s._33) + (src1->u.s._44 * src2->u.s._34);
2852 temp.u.s._44 = (src1->u.s._14 * src2->u.s._41) + (src1->u.s._24 * src2->u.s._42) + (src1->u.s._34 * src2->u.s._43) + (src1->u.s._44 * src2->u.s._44);
2853
2854 /* And copy the new matrix in the good storage.. */
2855 memcpy(dest, &temp, 16 * sizeof(float));
2856 }
2857
2858 DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) {
2859 DWORD size = 0;
2860 int i;
2861 int numTextures = (d3dvtVertexType & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
2862
2863 if (d3dvtVertexType & WINED3DFVF_NORMAL) size += 3 * sizeof(float);
2864 if (d3dvtVertexType & WINED3DFVF_DIFFUSE) size += sizeof(DWORD);
2865 if (d3dvtVertexType & WINED3DFVF_SPECULAR) size += sizeof(DWORD);
2866 if (d3dvtVertexType & WINED3DFVF_PSIZE) size += sizeof(DWORD);
2867 switch (d3dvtVertexType & WINED3DFVF_POSITION_MASK) {
2868 case WINED3DFVF_XYZ: size += 3 * sizeof(float); break;
2869 case WINED3DFVF_XYZRHW: size += 4 * sizeof(float); break;
2870 case WINED3DFVF_XYZB1: size += 4 * sizeof(float); break;
2871 case WINED3DFVF_XYZB2: size += 5 * sizeof(float); break;
2872 case WINED3DFVF_XYZB3: size += 6 * sizeof(float); break;
2873 case WINED3DFVF_XYZB4: size += 7 * sizeof(float); break;
2874 case WINED3DFVF_XYZB5: size += 8 * sizeof(float); break;
2875 case WINED3DFVF_XYZW: size += 4 * sizeof(float); break;
2876 default: ERR("Unexpected position mask\n");
2877 }
2878 for (i = 0; i < numTextures; i++) {
2879 size += GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, i) * sizeof(float);
2880 }
2881
2882 return size;
2883 }
2884
2885 void gen_ffp_frag_op(const struct wined3d_device *device, const struct wined3d_state *state,
2886 struct ffp_frag_settings *settings, BOOL ignore_textype)
2887 {
2888 #define ARG1 0x01
2889 #define ARG2 0x02
2890 #define ARG0 0x04
2891 static const unsigned char args[WINED3D_TOP_LERP + 1] =
2892 {
2893 /* undefined */ 0,
2894 /* D3DTOP_DISABLE */ 0,
2895 /* D3DTOP_SELECTARG1 */ ARG1,
2896 /* D3DTOP_SELECTARG2 */ ARG2,
2897 /* D3DTOP_MODULATE */ ARG1 | ARG2,
2898 /* D3DTOP_MODULATE2X */ ARG1 | ARG2,
2899 /* D3DTOP_MODULATE4X */ ARG1 | ARG2,
2900 /* D3DTOP_ADD */ ARG1 | ARG2,
2901 /* D3DTOP_ADDSIGNED */ ARG1 | ARG2,
2902 /* D3DTOP_ADDSIGNED2X */ ARG1 | ARG2,
2903 /* D3DTOP_SUBTRACT */ ARG1 | ARG2,
2904 /* D3DTOP_ADDSMOOTH */ ARG1 | ARG2,
2905 /* D3DTOP_BLENDDIFFUSEALPHA */ ARG1 | ARG2,
2906 /* D3DTOP_BLENDTEXTUREALPHA */ ARG1 | ARG2,
2907 /* D3DTOP_BLENDFACTORALPHA */ ARG1 | ARG2,
2908 /* D3DTOP_BLENDTEXTUREALPHAPM */ ARG1 | ARG2,
2909 /* D3DTOP_BLENDCURRENTALPHA */ ARG1 | ARG2,
2910 /* D3DTOP_PREMODULATE */ ARG1 | ARG2,
2911 /* D3DTOP_MODULATEALPHA_ADDCOLOR */ ARG1 | ARG2,
2912 /* D3DTOP_MODULATECOLOR_ADDALPHA */ ARG1 | ARG2,
2913 /* D3DTOP_MODULATEINVALPHA_ADDCOLOR */ ARG1 | ARG2,
2914 /* D3DTOP_MODULATEINVCOLOR_ADDALPHA */ ARG1 | ARG2,
2915 /* D3DTOP_BUMPENVMAP */ ARG1 | ARG2,
2916 /* D3DTOP_BUMPENVMAPLUMINANCE */ ARG1 | ARG2,
2917 /* D3DTOP_DOTPRODUCT3 */ ARG1 | ARG2,
2918 /* D3DTOP_MULTIPLYADD */ ARG1 | ARG2 | ARG0,
2919 /* D3DTOP_LERP */ ARG1 | ARG2 | ARG0
2920 };
2921 unsigned int i;
2922 DWORD ttff;
2923 DWORD cop, aop, carg0, carg1, carg2, aarg0, aarg1, aarg2;
2924 const struct wined3d_surface *rt = state->fb->render_targets[0];
2925 const struct wined3d_gl_info *gl_info = &device->adapter->gl_info;
2926
2927 for (i = 0; i < gl_info->limits.texture_stages; ++i)
2928 {
2929 const struct wined3d_texture *texture;
2930
2931 settings->op[i].padding = 0;
2932 if (state->texture_states[i][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_DISABLE)
2933 {
2934 settings->op[i].cop = WINED3D_TOP_DISABLE;
2935 settings->op[i].aop = WINED3D_TOP_DISABLE;
2936 settings->op[i].carg0 = settings->op[i].carg1 = settings->op[i].carg2 = ARG_UNUSED;
2937 settings->op[i].aarg0 = settings->op[i].aarg1 = settings->op[i].aarg2 = ARG_UNUSED;
2938 settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
2939 settings->op[i].dst = resultreg;
2940 settings->op[i].tex_type = tex_1d;
2941 settings->op[i].projected = proj_none;
2942 i++;
2943 break;
2944 }
2945
2946 if ((texture = state->textures[i]))
2947 {
2948 settings->op[i].color_fixup = texture->resource.format->color_fixup;
2949 if (ignore_textype)
2950 {
2951 settings->op[i].tex_type = tex_1d;
2952 }
2953 else
2954 {
2955 switch (texture->target)
2956 {
2957 case GL_TEXTURE_1D:
2958 settings->op[i].tex_type = tex_1d;
2959 break;
2960 case GL_TEXTURE_2D:
2961 settings->op[i].tex_type = tex_2d;
2962 break;
2963 case GL_TEXTURE_3D:
2964 settings->op[i].tex_type = tex_3d;
2965 break;
2966 case GL_TEXTURE_CUBE_MAP_ARB:
2967 settings->op[i].tex_type = tex_cube;
2968 break;
2969 case GL_TEXTURE_RECTANGLE_ARB:
2970 settings->op[i].tex_type = tex_rect;
2971 break;
2972 }
2973 }
2974 } else {
2975 settings->op[i].color_fixup = COLOR_FIXUP_IDENTITY;
2976 settings->op[i].tex_type = tex_1d;
2977 }
2978
2979 cop = state->texture_states[i][WINED3D_TSS_COLOR_OP];
2980 aop = state->texture_states[i][WINED3D_TSS_ALPHA_OP];
2981
2982 carg1 = (args[cop] & ARG1) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG1] : ARG_UNUSED;
2983 carg2 = (args[cop] & ARG2) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG2] : ARG_UNUSED;
2984 carg0 = (args[cop] & ARG0) ? state->texture_states[i][WINED3D_TSS_COLOR_ARG0] : ARG_UNUSED;
2985
2986 if (is_invalid_op(state, i, cop, carg1, carg2, carg0))
2987 {
2988 carg0 = ARG_UNUSED;
2989 carg2 = ARG_UNUSED;
2990 carg1 = WINED3DTA_CURRENT;
2991 cop = WINED3D_TOP_SELECT_ARG1;
2992 }
2993
2994 if (cop == WINED3D_TOP_DOTPRODUCT3)
2995 {
2996 /* A dotproduct3 on the colorop overwrites the alphaop operation and replicates
2997 * the color result to the alpha component of the destination
2998 */
2999 aop = cop;
3000 aarg1 = carg1;
3001 aarg2 = carg2;
3002 aarg0 = carg0;
3003 }
3004 else
3005 {
3006 aarg1 = (args[aop] & ARG1) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG1] : ARG_UNUSED;
3007 aarg2 = (args[aop] & ARG2) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG2] : ARG_UNUSED;
3008 aarg0 = (args[aop] & ARG0) ? state->texture_states[i][WINED3D_TSS_ALPHA_ARG0] : ARG_UNUSED;
3009 }
3010
3011 if (!i && state->textures[0] && state->render_states[WINED3D_RS_COLORKEYENABLE])
3012 {
3013 GLenum texture_dimensions;
3014
3015 texture = state->textures[0];
3016 texture_dimensions = texture->target;
3017
3018 if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
3019 {
3020 struct wined3d_surface *surf = surface_from_resource(texture->sub_resources[0]);
3021
3022 if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format->alpha_size)
3023 {
3024 if (aop == WINED3D_TOP_DISABLE)
3025 {
3026 aarg1 = WINED3DTA_TEXTURE;
3027 aop = WINED3D_TOP_SELECT_ARG1;
3028 }
3029 else if (aop == WINED3D_TOP_SELECT_ARG1 && aarg1 != WINED3DTA_TEXTURE)
3030 {
3031 if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
3032 {
3033 aarg2 = WINED3DTA_TEXTURE;
3034 aop = WINED3D_TOP_MODULATE;
3035 }
3036 else aarg1 = WINED3DTA_TEXTURE;
3037 }
3038 else if (aop == WINED3D_TOP_SELECT_ARG2 && aarg2 != WINED3DTA_TEXTURE)
3039 {
3040 if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
3041 {
3042 aarg1 = WINED3DTA_TEXTURE;
3043 aop = WINED3D_TOP_MODULATE;
3044 }
3045 else aarg2 = WINED3DTA_TEXTURE;
3046 }
3047 }
3048 }
3049 }
3050
3051 if (is_invalid_op(state, i, aop, aarg1, aarg2, aarg0))
3052 {
3053 aarg0 = ARG_UNUSED;
3054 aarg2 = ARG_UNUSED;
3055 aarg1 = WINED3DTA_CURRENT;
3056 aop = WINED3D_TOP_SELECT_ARG1;
3057 }
3058
3059 if (carg1 == WINED3DTA_TEXTURE || carg2 == WINED3DTA_TEXTURE || carg0 == WINED3DTA_TEXTURE
3060 || aarg1 == WINED3DTA_TEXTURE || aarg2 == WINED3DTA_TEXTURE || aarg0 == WINED3DTA_TEXTURE)
3061 {
3062 ttff = state->texture_states[i][WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS];
3063 if (ttff == (WINED3D_TTFF_PROJECTED | WINED3D_TTFF_COUNT3))
3064 settings->op[i].projected = proj_count3;
3065 else if (ttff & WINED3D_TTFF_PROJECTED)
3066 settings->op[i].projected = proj_count4;
3067 else
3068 settings->op[i].projected = proj_none;
3069 }
3070 else
3071 {
3072 settings->op[i].projected = proj_none;
3073 }
3074
3075 settings->op[i].cop = cop;
3076 settings->op[i].aop = aop;
3077 settings->op[i].carg0 = carg0;
3078 settings->op[i].carg1 = carg1;
3079 settings->op[i].carg2 = carg2;
3080 settings->op[i].aarg0 = aarg0;
3081 settings->op[i].aarg1 = aarg1;
3082 settings->op[i].aarg2 = aarg2;
3083
3084 if (state->texture_states[i][WINED3D_TSS_RESULT_ARG] == WINED3DTA_TEMP)
3085 settings->op[i].dst = tempreg;
3086 else
3087 settings->op[i].dst = resultreg;
3088 }
3089
3090 /* Clear unsupported stages */
3091 for(; i < MAX_TEXTURES; i++) {
3092 memset(&settings->op[i], 0xff, sizeof(settings->op[i]));
3093 }
3094
3095 if (!state->render_states[WINED3D_RS_FOGENABLE])
3096 {
3097 settings->fog = FOG_OFF;
3098 }
3099 else if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
3100 {
3101 if (use_vs(state) || state->vertex_declaration->position_transformed)
3102 {
3103 settings->fog = FOG_LINEAR;
3104 }
3105 else
3106 {
3107 switch (state->render_states[WINED3D_RS_FOGVERTEXMODE])
3108 {
3109 case WINED3D_FOG_NONE:
3110 case WINED3D_FOG_LINEAR:
3111 settings->fog = FOG_LINEAR;
3112 break;
3113 case WINED3D_FOG_EXP:
3114 settings->fog = FOG_EXP;
3115 break;
3116 case WINED3D_FOG_EXP2:
3117 settings->fog = FOG_EXP2;
3118 break;
3119 }
3120 }
3121 }
3122 else
3123 {
3124 switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
3125 {
3126 case WINED3D_FOG_LINEAR:
3127 settings->fog = FOG_LINEAR;
3128 break;
3129 case WINED3D_FOG_EXP:
3130 settings->fog = FOG_EXP;
3131 break;
3132 case WINED3D_FOG_EXP2:
3133 settings->fog = FOG_EXP2;
3134 break;
3135 }
3136 }
3137 if (!gl_info->supported[ARB_FRAMEBUFFER_SRGB]
3138 && state->render_states[WINED3D_RS_SRGBWRITEENABLE]
3139 && rt->resource.format->flags & WINED3DFMT_FLAG_SRGB_WRITE)
3140 {
3141 settings->sRGB_write = 1;
3142 } else {
3143 settings->sRGB_write = 0;
3144 }
3145 if (device->vs_clipping || !use_vs(state) || !state->render_states[WINED3D_RS_CLIPPING]
3146 || !state->render_states[WINED3D_RS_CLIPPLANEENABLE])
3147 {
3148 /* No need to emulate clipplanes if GL supports native vertex shader clipping or if
3149 * the fixed function vertex pipeline is used(which always supports clipplanes), or
3150 * if no clipplane is enabled
3151 */
3152 settings->emul_clipplanes = 0;
3153 } else {
3154 settings->emul_clipplanes = 1;
3155 }
3156 }
3157
3158 const struct ffp_frag_desc *find_ffp_frag_shader(const struct wine_rb_tree *fragment_shaders,
3159 const struct ffp_frag_settings *settings)
3160 {
3161 struct wine_rb_entry *entry = wine_rb_get(fragment_shaders, settings);
3162 return entry ? WINE_RB_ENTRY_VALUE(entry, struct ffp_frag_desc, entry) : NULL;
3163 }
3164
3165 void add_ffp_frag_shader(struct wine_rb_tree *shaders, struct ffp_frag_desc *desc)
3166 {
3167 /* Note that the key is the implementation independent part of the ffp_frag_desc structure,
3168 * whereas desc points to an extended structure with implementation specific parts. */
3169 if (wine_rb_put(shaders, &desc->settings, &desc->entry) == -1)
3170 {
3171 ERR("Failed to insert ffp frag shader.\n");
3172 }
3173 }
3174
3175 /* Activates the texture dimension according to the bound D3D texture.
3176 * Does not care for the colorop or correct gl texture unit(when using nvrc)
3177 * Requires the caller to activate the correct unit before
3178 */
3179 /* GL locking is done by the caller (state handler) */
3180 void texture_activate_dimensions(const struct wined3d_texture *texture, const struct wined3d_gl_info *gl_info)
3181 {
3182 if (texture)
3183 {
3184 switch (texture->target)
3185 {
3186 case GL_TEXTURE_2D:
3187 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
3188 checkGLcall("glDisable(GL_TEXTURE_3D)");
3189 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3190 {
3191 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3192 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
3193 }
3194 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
3195 {
3196 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
3197 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
3198 }
3199 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
3200 checkGLcall("glEnable(GL_TEXTURE_2D)");
3201 break;
3202 case GL_TEXTURE_RECTANGLE_ARB:
3203 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
3204 checkGLcall("glDisable(GL_TEXTURE_2D)");
3205 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
3206 checkGLcall("glDisable(GL_TEXTURE_3D)");
3207 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3208 {
3209 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3210 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
3211 }
3212 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_RECTANGLE_ARB);
3213 checkGLcall("glEnable(GL_TEXTURE_RECTANGLE_ARB)");
3214 break;
3215 case GL_TEXTURE_3D:
3216 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3217 {
3218 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3219 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
3220 }
3221 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
3222 {
3223 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
3224 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
3225 }
3226 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
3227 checkGLcall("glDisable(GL_TEXTURE_2D)");
3228 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_3D);
3229 checkGLcall("glEnable(GL_TEXTURE_3D)");
3230 break;
3231 case GL_TEXTURE_CUBE_MAP_ARB:
3232 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
3233 checkGLcall("glDisable(GL_TEXTURE_2D)");
3234 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
3235 checkGLcall("glDisable(GL_TEXTURE_3D)");
3236 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
3237 {
3238 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
3239 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
3240 }
3241 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_CUBE_MAP_ARB);
3242 checkGLcall("glEnable(GL_TEXTURE_CUBE_MAP_ARB)");
3243 break;
3244 }
3245 }
3246 else
3247 {
3248 gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_2D);
3249 checkGLcall("glEnable(GL_TEXTURE_2D)");
3250 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
3251 checkGLcall("glDisable(GL_TEXTURE_3D)");
3252 if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3253 {
3254 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3255 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
3256 }
3257 if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
3258 {
3259 gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
3260 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
3261 }
3262 /* Binding textures is done by samplers. A dummy texture will be bound */
3263 }
3264 }
3265
3266 /* GL locking is done by the caller (state handler) */
3267 void sampler_texdim(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3268 {
3269 DWORD sampler = state_id - STATE_SAMPLER(0);
3270 DWORD mapped_stage = context->swapchain->device->texUnitMap[sampler];
3271
3272 /* No need to enable / disable anything here for unused samplers. The
3273 * tex_colorop handler takes care. Also no action is needed with pixel
3274 * shaders, or if tex_colorop will take care of this business. */
3275 if (mapped_stage == WINED3D_UNMAPPED_STAGE || mapped_stage >= context->gl_info->limits.textures)
3276 return;
3277 if (sampler >= state->lowest_disabled_stage)
3278 return;
3279 if (isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)))
3280 return;
3281
3282 texture_activate_dimensions(state->textures[sampler], context->gl_info);
3283 }
3284
3285 void *wined3d_rb_alloc(size_t size)
3286 {
3287 return HeapAlloc(GetProcessHeap(), 0, size);
3288 }
3289
3290 void *wined3d_rb_realloc(void *ptr, size_t size)
3291 {
3292 return HeapReAlloc(GetProcessHeap(), 0, ptr, size);
3293 }
3294
3295 void wined3d_rb_free(void *ptr)
3296 {
3297 HeapFree(GetProcessHeap(), 0, ptr);
3298 }
3299
3300 static int ffp_frag_program_key_compare(const void *key, const struct wine_rb_entry *entry)
3301 {
3302 const struct ffp_frag_settings *ka = key;
3303 const struct ffp_frag_settings *kb = &WINE_RB_ENTRY_VALUE(entry, const struct ffp_frag_desc, entry)->settings;
3304
3305 return memcmp(ka, kb, sizeof(*ka));
3306 }
3307
3308 const struct wine_rb_functions wined3d_ffp_frag_program_rb_functions =
3309 {
3310 wined3d_rb_alloc,
3311 wined3d_rb_realloc,
3312 wined3d_rb_free,
3313 ffp_frag_program_key_compare,
3314 };
3315
3316 UINT wined3d_log2i(UINT32 x)
3317 {
3318 static const UINT l[] =
3319 {
3320 ~0U, 0, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 3, 3, 3, 3,
3321 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
3322 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3323 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
3324 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3325 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3326 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3327 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
3328 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3329 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3330 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3331 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3332 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3333 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3334 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3335 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
3336 };
3337 UINT32 i;
3338
3339 return (i = x >> 16) ? (x = i >> 8) ? l[x] + 24 : l[i] + 16 : (i = x >> 8) ? l[i] + 8 : l[x];
3340 }
3341
3342 /* Set the shader type for this device, depending on the given capabilities
3343 * and the user preferences in wined3d_settings. */
3344 void select_shader_mode(const struct wined3d_gl_info *gl_info, int *ps_selected, int *vs_selected)
3345 {
3346 BOOL glsl = wined3d_settings.glslRequested && gl_info->glsl_version >= MAKEDWORD_VERSION(1, 20);
3347
3348 if (wined3d_settings.vs_mode == VS_NONE) *vs_selected = SHADER_NONE;
3349 else if (gl_info->supported[ARB_VERTEX_SHADER] && glsl)
3350 {
3351 /* Geforce4 cards support GLSL but for vertex shaders only. Further its reported GLSL caps are
3352 * wrong. This combined with the fact that glsl won't offer more features or performance, use ARB
3353 * shaders only on this card. */
3354 if (gl_info->supported[NV_VERTEX_PROGRAM] && !gl_info->supported[NV_VERTEX_PROGRAM2]) *vs_selected = SHADER_ARB;
3355 else *vs_selected = SHADER_GLSL;
3356 }
3357 else if (gl_info->supported[ARB_VERTEX_PROGRAM]) *vs_selected = SHADER_ARB;
3358 else *vs_selected = SHADER_NONE;
3359
3360 if (wined3d_settings.ps_mode == PS_NONE) *ps_selected = SHADER_NONE;
3361 else if (gl_info->supported[ARB_FRAGMENT_SHADER] && glsl) *ps_selected = SHADER_GLSL;
3362 else if (gl_info->supported[ARB_FRAGMENT_PROGRAM]) *ps_selected = SHADER_ARB;
3363 else if (gl_info->supported[ATI_FRAGMENT_SHADER]) *ps_selected = SHADER_ATI;
3364 else *ps_selected = SHADER_NONE;
3365 }
3366
3367 const struct blit_shader *wined3d_select_blitter(const struct wined3d_gl_info *gl_info, enum wined3d_blit_op blit_op,
3368 const RECT *src_rect, DWORD src_usage, enum wined3d_pool src_pool, const struct wined3d_format *src_format,
3369 const RECT *dst_rect, DWORD dst_usage, enum wined3d_pool dst_pool, const struct wined3d_format *dst_format)
3370 {
3371 static const struct blit_shader * const blitters[] =
3372 {
3373 &arbfp_blit,
3374 &ffp_blit,
3375 &cpu_blit,
3376 };
3377 unsigned int i;
3378
3379 for (i = 0; i < sizeof(blitters) / sizeof(*blitters); ++i)
3380 {
3381 if (blitters[i]->blit_supported(gl_info, blit_op,
3382 src_rect, src_usage, src_pool, src_format,
3383 dst_rect, dst_usage, dst_pool, dst_format))
3384 return blitters[i];
3385 }
3386
3387 return NULL;
3388 }
3389
3390 void wined3d_get_draw_rect(const struct wined3d_state *state, RECT *rect)
3391 {
3392 const struct wined3d_viewport *vp = &state->viewport;
3393
3394 SetRect(rect, vp->x, vp->y, vp->x + vp->width, vp->y + vp->height);
3395
3396 if (state->render_states[WINED3D_RS_SCISSORTESTENABLE])
3397 IntersectRect(rect, rect, &state->scissor_rect);
3398 }