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