wined3d: Store the gl format table in the gl info structure.
[wine/hacks.git] / dlls / wined3d / utils.c
blob39a704a0c47badc0d702de1a42ee5d36c37e34f3
1 /*
2 * Utility functions for the WineD3D Library
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-2007 Henri Verbeet
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wined3d_private.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
30 #define GLINFO_LOCATION This->adapter->gl_info
32 /*****************************************************************************
33 * Pixel format array
35 static const StaticPixelFormatDesc formats[] = {
36 /*{WINED3DFORMAT ,alphamask ,redmask ,greenmask ,bluemask ,bpp ,isFourcc*/
37 {WINED3DFMT_UNKNOWN ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,FALSE },
38 /* FourCC formats, kept here to have WINED3DFMT_R8G8B8(=20) at position 20 */
39 {WINED3DFMT_UYVY ,0x0 ,0x0 ,0x0 ,0x0 ,1/*?*/ ,TRUE },
40 {WINED3DFMT_YUY2 ,0x0 ,0x0 ,0x0 ,0x0 ,1/*?*/ ,TRUE },
41 {WINED3DFMT_DXT1 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,TRUE },
42 {WINED3DFMT_DXT2 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,TRUE },
43 {WINED3DFMT_DXT3 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,TRUE },
44 {WINED3DFMT_DXT4 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,TRUE },
45 {WINED3DFMT_DXT5 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,TRUE },
46 {WINED3DFMT_MULTI2_ARGB8,0x0 ,0x0 ,0x0 ,0x0 ,1/*?*/ ,TRUE },
47 {WINED3DFMT_G8R8_G8B8 ,0x0 ,0x0 ,0x0 ,0x0 ,1/*?*/ ,TRUE },
48 {WINED3DFMT_R8G8_B8G8 ,0x0 ,0x0 ,0x0 ,0x0 ,1/*?*/ ,TRUE },
49 /* IEEE formats */
50 {WINED3DFMT_R32F ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
51 {WINED3DFMT_G32R32F ,0x0 ,0x0 ,0x0 ,0x0 ,8 ,FALSE },
52 {WINED3DFMT_A32B32G32R32F,0x0 ,0x0 ,0x0 ,0x0 ,16 ,FALSE },
53 /* Hmm? */
54 {WINED3DFMT_CxV8U8 ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,FALSE },
55 /* Float */
56 {WINED3DFMT_R16F ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,FALSE },
57 {WINED3DFMT_G16R16F ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
58 {WINED3DFMT_A16B16G16R16F,0x0 ,0x0 ,0x0 ,0x0 ,8 ,FALSE },
59 /* Palettized formats */
60 {WINED3DFMT_A8P8 ,0x0000ff00 ,0x0 ,0x0 ,0x0 ,2 ,FALSE },
61 {WINED3DFMT_P8 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,FALSE },
62 /* Standard ARGB formats. Keep WINED3DFMT_R8G8B8(=20) at position 20 */
63 {WINED3DFMT_R8G8B8 ,0x0 ,0x00ff0000 ,0x0000ff00 ,0x000000ff ,3 ,FALSE },
64 {WINED3DFMT_A8R8G8B8 ,0xff000000 ,0x00ff0000 ,0x0000ff00 ,0x000000ff ,4 ,FALSE },
65 {WINED3DFMT_X8R8G8B8 ,0x0 ,0x00ff0000 ,0x0000ff00 ,0x000000ff ,4 ,FALSE },
66 {WINED3DFMT_R5G6B5 ,0x0 ,0x0000F800 ,0x000007e0 ,0x0000001f ,2 ,FALSE },
67 {WINED3DFMT_X1R5G5B5 ,0x0 ,0x00007c00 ,0x000003e0 ,0x0000001f ,2 ,FALSE },
68 {WINED3DFMT_A1R5G5B5 ,0x00008000 ,0x00007c00 ,0x000003e0 ,0x0000001f ,2 ,FALSE },
69 {WINED3DFMT_A4R4G4B4 ,0x0000f000 ,0x00000f00 ,0x000000f0 ,0x0000000f ,2 ,FALSE },
70 {WINED3DFMT_R3G3B2 ,0x0 ,0x000000e0 ,0x0000001c ,0x00000003 ,1 ,FALSE },
71 {WINED3DFMT_A8 ,0x000000ff ,0x0 ,0x0 ,0x0 ,1 ,FALSE },
72 {WINED3DFMT_A8R3G3B2 ,0x0000ff00 ,0x000000e0 ,0x0000001c ,0x00000003 ,2 ,FALSE },
73 {WINED3DFMT_X4R4G4B4 ,0x0 ,0x00000f00 ,0x000000f0 ,0x0000000f ,2 ,FALSE },
74 {WINED3DFMT_A2B10G10R10 ,0xb0000000 ,0x000003ff ,0x000ffc00 ,0x3ff00000 ,4 ,FALSE },
75 {WINED3DFMT_A8B8G8R8 ,0xff000000 ,0x000000ff ,0x0000ff00 ,0x00ff0000 ,4 ,FALSE },
76 {WINED3DFMT_X8B8G8R8 ,0x0 ,0x000000ff ,0x0000ff00 ,0x00ff0000 ,4 ,FALSE },
77 {WINED3DFMT_G16R16 ,0x0 ,0x0000ffff ,0xffff0000 ,0x0 ,4 ,FALSE },
78 {WINED3DFMT_A2R10G10B10 ,0xb0000000 ,0x3ff00000 ,0x000ffc00 ,0x000003ff ,4 ,FALSE },
79 {WINED3DFMT_A16B16G16R16,0x0 ,0x0000ffff ,0xffff0000 ,0x0 ,8 ,FALSE },
80 /* Luminance */
81 {WINED3DFMT_L8 ,0x0 ,0x0 ,0x0 ,0x0 ,1 ,FALSE },
82 {WINED3DFMT_A8L8 ,0x0000ff00 ,0x0 ,0x0 ,0x0 ,2 ,FALSE },
83 {WINED3DFMT_A4L4 ,0x000000f0 ,0x0 ,0x0 ,0x0 ,1 ,FALSE },
84 /* Bump mapping stuff */
85 {WINED3DFMT_V8U8 ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,FALSE },
86 {WINED3DFMT_L6V5U5 ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,FALSE },
87 {WINED3DFMT_X8L8V8U8 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
88 {WINED3DFMT_Q8W8V8U8 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
89 {WINED3DFMT_V16U16 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
90 {WINED3DFMT_W11V11U10 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
91 {WINED3DFMT_A2W10V10U10 ,0xb0000000 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
92 /* Depth stencil formats */
93 {WINED3DFMT_D16_LOCKABLE,0x0 ,0x0 ,0x0 ,0x0 ,2 ,FALSE },
94 {WINED3DFMT_D32 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
95 {WINED3DFMT_D15S1 ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,FALSE },
96 {WINED3DFMT_D24S8 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
97 {WINED3DFMT_D24X8 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
98 {WINED3DFMT_D24X4S4 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
99 {WINED3DFMT_D16 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
100 {WINED3DFMT_L16 ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,FALSE },
101 {WINED3DFMT_D32F_LOCKABLE,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
102 {WINED3DFMT_D24FS8 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
103 /* Is this a vertex buffer? */
104 {WINED3DFMT_VERTEXDATA ,0x0 ,0x0 ,0x0 ,0x0 ,0 ,FALSE },
105 {WINED3DFMT_INDEX16 ,0x0 ,0x0 ,0x0 ,0x0 ,2 ,FALSE },
106 {WINED3DFMT_INDEX32 ,0x0 ,0x0 ,0x0 ,0x0 ,4 ,FALSE },
107 {WINED3DFMT_Q16W16V16U16,0x0 ,0x0 ,0x0 ,0x0 ,8 ,FALSE },
110 /*****************************************************************************
111 * Pixel format array
113 GlPixelFormatDesc gl_formats[] = {
114 /*{internal ,srgbInternal ,format ,type }*/
115 {0 ,0 ,0 ,0 },
116 /* FourCC formats, kept here to have WINED3DFMT_R8G8B8(=20) at position 20 */
117 {0 ,0 ,0 ,0 },
118 {0 ,0 ,0 ,0 },
119 {GL_COMPRESSED_RGBA_S3TC_DXT1_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT ,GL_RGBA ,GL_UNSIGNED_BYTE },
120 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ,GL_RGBA ,GL_UNSIGNED_BYTE },
121 {GL_COMPRESSED_RGBA_S3TC_DXT3_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT ,GL_RGBA ,GL_UNSIGNED_BYTE },
122 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT ,GL_RGBA ,GL_UNSIGNED_BYTE },
123 {GL_COMPRESSED_RGBA_S3TC_DXT5_EXT ,GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT ,GL_RGBA ,GL_UNSIGNED_BYTE },
124 {0 ,0 ,0 ,0 },
125 {0 ,0 ,0 ,0 },
126 {0 ,0 ,0 ,0 },
127 /* IEEE formats */
128 {GL_RGB32F_ARB ,GL_RGB32F_ARB ,GL_RED ,GL_FLOAT },
129 {0 ,0 ,0 ,0 },
130 {GL_RGBA32F_ARB ,GL_RGBA32F_ARB ,GL_RGBA ,GL_FLOAT },
131 /* Hmm? */
132 {0 ,0 ,0 ,0 },
133 /* Float */
134 {GL_RGB16F_ARB ,GL_RGB16F_ARB ,GL_RED ,GL_HALF_FLOAT_ARB },
135 {0 ,0 ,0 ,0 },
136 {GL_RGBA16F_ARB ,GL_RGBA16F_ARB ,GL_RGBA ,GL_HALF_FLOAT_ARB },
137 /* Palettized formats */
138 {0 ,0 ,0 ,0 },
139 {GL_COLOR_INDEX8_EXT ,GL_COLOR_INDEX8_EXT ,GL_COLOR_INDEX ,GL_UNSIGNED_BYTE },
140 /* Standard ARGB formats. Keep WINED3DFMT_R8G8B8(=20) at position 20 */
141 {GL_RGB8 ,GL_RGB8 ,GL_BGR ,GL_UNSIGNED_BYTE },
142 {GL_RGBA8 ,GL_SRGB8_ALPHA8_EXT ,GL_BGRA ,GL_UNSIGNED_INT_8_8_8_8_REV },
143 {GL_RGB8 ,GL_SRGB8_EXT ,GL_BGRA ,GL_UNSIGNED_INT_8_8_8_8_REV },
144 {GL_RGB5 ,GL_RGB5 ,GL_RGB ,GL_UNSIGNED_SHORT_5_6_5 },
145 {GL_RGB5_A1 ,GL_RGB5_A1 ,GL_BGRA ,GL_UNSIGNED_SHORT_1_5_5_5_REV },
146 {GL_RGB5_A1 ,GL_RGB5_A1 ,GL_BGRA ,GL_UNSIGNED_SHORT_1_5_5_5_REV },
147 {GL_RGBA4 ,GL_SRGB8_ALPHA8_EXT ,GL_BGRA ,GL_UNSIGNED_SHORT_4_4_4_4_REV },
148 {GL_R3_G3_B2 ,GL_R3_G3_B2 ,GL_RGB ,GL_UNSIGNED_BYTE_2_3_3_REV },
149 {GL_ALPHA8 ,GL_ALPHA8 ,GL_ALPHA ,GL_UNSIGNED_BYTE },
150 {0 ,0 ,0 ,0 },
151 {GL_RGB4 ,GL_RGB4 ,GL_BGRA ,GL_UNSIGNED_SHORT_4_4_4_4_REV },
152 {GL_RGB ,GL_RGB ,GL_RGBA ,GL_UNSIGNED_INT_2_10_10_10_REV },
153 {GL_RGBA8 ,GL_RGBA8 ,GL_RGBA ,GL_UNSIGNED_INT_8_8_8_8_REV },
154 {GL_RGB8 ,GL_RGB8 ,GL_RGBA ,GL_UNSIGNED_INT_8_8_8_8_REV },
155 {0 ,0 ,0 ,0 },
156 {GL_RGBA ,GL_RGBA ,GL_BGRA ,GL_UNSIGNED_INT_2_10_10_10_REV },
157 {GL_RGBA16_EXT ,GL_RGBA16_EXT ,GL_RGBA ,GL_UNSIGNED_SHORT },
158 /* Luminance */
159 {GL_LUMINANCE8 ,GL_SLUMINANCE8_EXT ,GL_LUMINANCE ,GL_UNSIGNED_BYTE },
160 {GL_LUMINANCE8_ALPHA8 ,GL_SLUMINANCE8_ALPHA8_EXT ,GL_LUMINANCE_ALPHA ,GL_UNSIGNED_BYTE },
161 {GL_LUMINANCE4_ALPHA4 ,GL_LUMINANCE4_ALPHA4 ,GL_LUMINANCE_ALPHA ,GL_UNSIGNED_BYTE },
162 /* Bump mapping stuff */
163 {GL_DSDT8_NV ,GL_DSDT8_NV ,GL_DSDT_NV ,GL_BYTE },
164 {GL_COLOR_INDEX8_EXT ,GL_COLOR_INDEX8_EXT ,GL_COLOR_INDEX ,GL_UNSIGNED_SHORT_5_5_5_1 },
165 {GL_DSDT8_MAG8_INTENSITY8_NV ,GL_DSDT8_MAG8_INTENSITY8_NV ,GL_DSDT_MAG_INTENSITY_NV ,GL_BYTE },
166 {GL_SIGNED_RGBA8_NV ,GL_SIGNED_RGBA8_NV ,GL_RGBA ,GL_BYTE },
167 {GL_SIGNED_HILO16_NV ,GL_SIGNED_HILO16_NV ,GL_HILO_NV ,GL_SHORT },
168 {0 ,0 ,0 ,0 },
169 {0 ,0 ,0 ,0 },
170 /* Depth stencil formats */
171 {GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT ,GL_UNSIGNED_SHORT },
172 {GL_DEPTH_COMPONENT32_ARB ,GL_DEPTH_COMPONENT32_ARB ,GL_DEPTH_COMPONENT ,GL_UNSIGNED_INT },
173 {GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT ,GL_UNSIGNED_SHORT },
174 {GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT ,GL_UNSIGNED_INT },
175 {GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT,GL_UNSIGNED_INT },
176 {GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT,GL_UNSIGNED_INT },
177 {GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT,GL_UNSIGNED_SHORT },
178 {GL_LUMINANCE16_EXT ,GL_LUMINANCE16_EXT ,GL_LUMINANCE ,GL_UNSIGNED_SHORT },
179 {GL_DEPTH_COMPONENT32_ARB ,GL_DEPTH_COMPONENT32_ARB ,GL_DEPTH_COMPONENT ,GL_FLOAT },
180 {GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT24_ARB ,GL_DEPTH_COMPONENT ,GL_FLOAT },
181 /* Is this a vertex buffer? */
182 {0 ,0 ,0 ,0 },
183 {0 ,0 ,0 ,0 },
184 {0 ,0 ,0 ,0 },
185 {GL_COLOR_INDEX ,GL_COLOR_INDEX ,GL_COLOR_INDEX ,GL_UNSIGNED_SHORT }
188 static inline int getFmtIdx(WINED3DFORMAT fmt) {
189 /* First check if the format is at the position of its value.
190 * This will catch the argb formats before the loop is entered
192 if(fmt < (sizeof(formats) / sizeof(formats[0])) && formats[fmt].format == fmt) {
193 return fmt;
194 } else {
195 unsigned int i;
196 for(i = 0; i < (sizeof(formats) / sizeof(formats[0])); i++) {
197 if(formats[i].format == fmt) {
198 return i;
202 return -1;
205 BOOL initPixelFormats(WineD3D_GL_Info *gl_info)
207 /* Will be replaced with some more sophisticated initialization later */
208 gl_info->gl_formats = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(gl_formats));
209 if(!gl_info->gl_formats) return FALSE;
211 memcpy(gl_info->gl_formats, &gl_formats, sizeof(gl_formats));
212 return TRUE;
215 const StaticPixelFormatDesc *getFormatDescEntry(WINED3DFORMAT fmt, WineD3D_GL_Info *gl_info, const GlPixelFormatDesc **glDesc)
217 int idx = getFmtIdx(fmt);
219 if(idx == -1) {
220 FIXME("Can't find format %s(%d) in the format lookup table\n", debug_d3dformat(fmt), fmt);
221 /* Get the caller a valid pointer */
222 idx = getFmtIdx(WINED3DFMT_UNKNOWN);
224 if(glDesc) {
225 if(!gl_info) {
226 ERR("OpenGL pixel format information was requested, but no gl info structure passed\n");
227 return NULL;
229 *glDesc = &gl_info->gl_formats[idx];
231 return &formats[idx];
234 /*****************************************************************************
235 * Trace formatting of useful values
237 const char* debug_d3dformat(WINED3DFORMAT fmt) {
238 switch (fmt) {
239 #define FMT_TO_STR(fmt) case fmt: return #fmt
240 FMT_TO_STR(WINED3DFMT_UNKNOWN);
241 FMT_TO_STR(WINED3DFMT_R8G8B8);
242 FMT_TO_STR(WINED3DFMT_A8R8G8B8);
243 FMT_TO_STR(WINED3DFMT_X8R8G8B8);
244 FMT_TO_STR(WINED3DFMT_R5G6B5);
245 FMT_TO_STR(WINED3DFMT_X1R5G5B5);
246 FMT_TO_STR(WINED3DFMT_A1R5G5B5);
247 FMT_TO_STR(WINED3DFMT_A4R4G4B4);
248 FMT_TO_STR(WINED3DFMT_R3G3B2);
249 FMT_TO_STR(WINED3DFMT_A8);
250 FMT_TO_STR(WINED3DFMT_A8R3G3B2);
251 FMT_TO_STR(WINED3DFMT_X4R4G4B4);
252 FMT_TO_STR(WINED3DFMT_A2B10G10R10);
253 FMT_TO_STR(WINED3DFMT_A8B8G8R8);
254 FMT_TO_STR(WINED3DFMT_X8B8G8R8);
255 FMT_TO_STR(WINED3DFMT_G16R16);
256 FMT_TO_STR(WINED3DFMT_A2R10G10B10);
257 FMT_TO_STR(WINED3DFMT_A16B16G16R16);
258 FMT_TO_STR(WINED3DFMT_A8P8);
259 FMT_TO_STR(WINED3DFMT_P8);
260 FMT_TO_STR(WINED3DFMT_L8);
261 FMT_TO_STR(WINED3DFMT_A8L8);
262 FMT_TO_STR(WINED3DFMT_A4L4);
263 FMT_TO_STR(WINED3DFMT_V8U8);
264 FMT_TO_STR(WINED3DFMT_L6V5U5);
265 FMT_TO_STR(WINED3DFMT_X8L8V8U8);
266 FMT_TO_STR(WINED3DFMT_Q8W8V8U8);
267 FMT_TO_STR(WINED3DFMT_V16U16);
268 FMT_TO_STR(WINED3DFMT_W11V11U10);
269 FMT_TO_STR(WINED3DFMT_A2W10V10U10);
270 FMT_TO_STR(WINED3DFMT_UYVY);
271 FMT_TO_STR(WINED3DFMT_YUY2);
272 FMT_TO_STR(WINED3DFMT_DXT1);
273 FMT_TO_STR(WINED3DFMT_DXT2);
274 FMT_TO_STR(WINED3DFMT_DXT3);
275 FMT_TO_STR(WINED3DFMT_DXT4);
276 FMT_TO_STR(WINED3DFMT_DXT5);
277 FMT_TO_STR(WINED3DFMT_MULTI2_ARGB8);
278 FMT_TO_STR(WINED3DFMT_G8R8_G8B8);
279 FMT_TO_STR(WINED3DFMT_R8G8_B8G8);
280 FMT_TO_STR(WINED3DFMT_D16_LOCKABLE);
281 FMT_TO_STR(WINED3DFMT_D32);
282 FMT_TO_STR(WINED3DFMT_D15S1);
283 FMT_TO_STR(WINED3DFMT_D24S8);
284 FMT_TO_STR(WINED3DFMT_D24X8);
285 FMT_TO_STR(WINED3DFMT_D24X4S4);
286 FMT_TO_STR(WINED3DFMT_D16);
287 FMT_TO_STR(WINED3DFMT_L16);
288 FMT_TO_STR(WINED3DFMT_D32F_LOCKABLE);
289 FMT_TO_STR(WINED3DFMT_D24FS8);
290 FMT_TO_STR(WINED3DFMT_VERTEXDATA);
291 FMT_TO_STR(WINED3DFMT_INDEX16);
292 FMT_TO_STR(WINED3DFMT_INDEX32);
293 FMT_TO_STR(WINED3DFMT_Q16W16V16U16);
294 FMT_TO_STR(WINED3DFMT_R16F);
295 FMT_TO_STR(WINED3DFMT_G16R16F);
296 FMT_TO_STR(WINED3DFMT_A16B16G16R16F);
297 FMT_TO_STR(WINED3DFMT_R32F);
298 FMT_TO_STR(WINED3DFMT_G32R32F);
299 FMT_TO_STR(WINED3DFMT_A32B32G32R32F);
300 FMT_TO_STR(WINED3DFMT_CxV8U8);
301 #undef FMT_TO_STR
302 default:
304 char fourcc[5];
305 fourcc[0] = (char)(fmt);
306 fourcc[1] = (char)(fmt >> 8);
307 fourcc[2] = (char)(fmt >> 16);
308 fourcc[3] = (char)(fmt >> 24);
309 fourcc[4] = 0;
310 if( isprint(fourcc[0]) && isprint(fourcc[1]) && isprint(fourcc[2]) && isprint(fourcc[3]) )
311 FIXME("Unrecognized %u (as fourcc: %s) WINED3DFORMAT!\n", fmt, fourcc);
312 else
313 FIXME("Unrecognized %u WINED3DFORMAT!\n", fmt);
315 return "unrecognized";
319 const char* debug_d3ddevicetype(WINED3DDEVTYPE devtype) {
320 switch (devtype) {
321 #define DEVTYPE_TO_STR(dev) case dev: return #dev
322 DEVTYPE_TO_STR(WINED3DDEVTYPE_HAL);
323 DEVTYPE_TO_STR(WINED3DDEVTYPE_REF);
324 DEVTYPE_TO_STR(WINED3DDEVTYPE_SW);
325 #undef DEVTYPE_TO_STR
326 default:
327 FIXME("Unrecognized %u WINED3DDEVTYPE!\n", devtype);
328 return "unrecognized";
332 const char* debug_d3dusage(DWORD usage) {
333 switch (usage & WINED3DUSAGE_MASK) {
334 #define WINED3DUSAGE_TO_STR(u) case u: return #u
335 WINED3DUSAGE_TO_STR(WINED3DUSAGE_RENDERTARGET);
336 WINED3DUSAGE_TO_STR(WINED3DUSAGE_DEPTHSTENCIL);
337 WINED3DUSAGE_TO_STR(WINED3DUSAGE_WRITEONLY);
338 WINED3DUSAGE_TO_STR(WINED3DUSAGE_SOFTWAREPROCESSING);
339 WINED3DUSAGE_TO_STR(WINED3DUSAGE_DONOTCLIP);
340 WINED3DUSAGE_TO_STR(WINED3DUSAGE_POINTS);
341 WINED3DUSAGE_TO_STR(WINED3DUSAGE_RTPATCHES);
342 WINED3DUSAGE_TO_STR(WINED3DUSAGE_NPATCHES);
343 WINED3DUSAGE_TO_STR(WINED3DUSAGE_DYNAMIC);
344 WINED3DUSAGE_TO_STR(WINED3DUSAGE_AUTOGENMIPMAP);
345 WINED3DUSAGE_TO_STR(WINED3DUSAGE_DMAP);
346 #undef WINED3DUSAGE_TO_STR
347 case 0: return "none";
348 default:
349 FIXME("Unrecognized %u Usage!\n", usage);
350 return "unrecognized";
354 const char* debug_d3dusagequery(DWORD usagequery) {
355 switch (usagequery & WINED3DUSAGE_QUERY_MASK) {
356 #define WINED3DUSAGEQUERY_TO_STR(u) case u: return #u
357 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_FILTER);
358 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_LEGACYBUMPMAP);
359 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_POSTPIXELSHADER_BLENDING);
360 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_SRGBREAD);
361 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_SRGBWRITE);
362 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_VERTEXTEXTURE);
363 WINED3DUSAGEQUERY_TO_STR(WINED3DUSAGE_QUERY_WRAPANDMIP);
364 #undef WINED3DUSAGEQUERY_TO_STR
365 case 0: return "none";
366 default:
367 FIXME("Unrecognized %u Usage Query!\n", usagequery);
368 return "unrecognized";
372 const char* debug_d3ddeclmethod(WINED3DDECLMETHOD method) {
373 switch (method) {
374 #define WINED3DDECLMETHOD_TO_STR(u) case u: return #u
375 WINED3DDECLMETHOD_TO_STR(WINED3DDECLMETHOD_DEFAULT);
376 WINED3DDECLMETHOD_TO_STR(WINED3DDECLMETHOD_PARTIALU);
377 WINED3DDECLMETHOD_TO_STR(WINED3DDECLMETHOD_PARTIALV);
378 WINED3DDECLMETHOD_TO_STR(WINED3DDECLMETHOD_CROSSUV);
379 WINED3DDECLMETHOD_TO_STR(WINED3DDECLMETHOD_UV);
380 WINED3DDECLMETHOD_TO_STR(WINED3DDECLMETHOD_LOOKUP);
381 WINED3DDECLMETHOD_TO_STR(WINED3DDECLMETHOD_LOOKUPPRESAMPLED);
382 #undef WINED3DDECLMETHOD_TO_STR
383 default:
384 FIXME("Unrecognized %u declaration method!\n", method);
385 return "unrecognized";
389 const char* debug_d3ddecltype(WINED3DDECLTYPE type) {
390 switch (type) {
391 #define WINED3DDECLTYPE_TO_STR(u) case u: return #u
392 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_FLOAT1);
393 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_FLOAT2);
394 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_FLOAT3);
395 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_FLOAT4);
396 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_D3DCOLOR);
397 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_UBYTE4);
398 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_SHORT2);
399 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_SHORT4);
400 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_UBYTE4N);
401 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_SHORT2N);
402 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_SHORT4N);
403 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_USHORT2N);
404 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_USHORT4N);
405 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_UDEC3);
406 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_DEC3N);
407 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_FLOAT16_2);
408 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_FLOAT16_4);
409 WINED3DDECLTYPE_TO_STR(WINED3DDECLTYPE_UNUSED);
410 #undef WINED3DDECLTYPE_TO_STR
411 default:
412 FIXME("Unrecognized %u declaration type!\n", type);
413 return "unrecognized";
417 const char* debug_d3ddeclusage(BYTE usage) {
418 switch (usage) {
419 #define WINED3DDECLUSAGE_TO_STR(u) case u: return #u
420 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_POSITION);
421 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_BLENDWEIGHT);
422 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_BLENDINDICES);
423 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_NORMAL);
424 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_PSIZE);
425 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_TEXCOORD);
426 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_TANGENT);
427 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_BINORMAL);
428 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_TESSFACTOR);
429 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_POSITIONT);
430 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_COLOR);
431 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_FOG);
432 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_DEPTH);
433 WINED3DDECLUSAGE_TO_STR(WINED3DDECLUSAGE_SAMPLE);
434 #undef WINED3DDECLUSAGE_TO_STR
435 default:
436 FIXME("Unrecognized %u declaration usage!\n", usage);
437 return "unrecognized";
441 const char* debug_d3dresourcetype(WINED3DRESOURCETYPE res) {
442 switch (res) {
443 #define RES_TO_STR(res) case res: return #res;
444 RES_TO_STR(WINED3DRTYPE_SURFACE);
445 RES_TO_STR(WINED3DRTYPE_VOLUME);
446 RES_TO_STR(WINED3DRTYPE_TEXTURE);
447 RES_TO_STR(WINED3DRTYPE_VOLUMETEXTURE);
448 RES_TO_STR(WINED3DRTYPE_CUBETEXTURE);
449 RES_TO_STR(WINED3DRTYPE_VERTEXBUFFER);
450 RES_TO_STR(WINED3DRTYPE_INDEXBUFFER);
451 #undef RES_TO_STR
452 default:
453 FIXME("Unrecognized %u WINED3DRESOURCETYPE!\n", res);
454 return "unrecognized";
458 const char* debug_d3dprimitivetype(WINED3DPRIMITIVETYPE PrimitiveType) {
459 switch (PrimitiveType) {
460 #define PRIM_TO_STR(prim) case prim: return #prim;
461 PRIM_TO_STR(WINED3DPT_POINTLIST);
462 PRIM_TO_STR(WINED3DPT_LINELIST);
463 PRIM_TO_STR(WINED3DPT_LINESTRIP);
464 PRIM_TO_STR(WINED3DPT_TRIANGLELIST);
465 PRIM_TO_STR(WINED3DPT_TRIANGLESTRIP);
466 PRIM_TO_STR(WINED3DPT_TRIANGLEFAN);
467 #undef PRIM_TO_STR
468 default:
469 FIXME("Unrecognized %u WINED3DPRIMITIVETYPE!\n", PrimitiveType);
470 return "unrecognized";
474 const char* debug_d3drenderstate(DWORD state) {
475 switch (state) {
476 #define D3DSTATE_TO_STR(u) case u: return #u
477 D3DSTATE_TO_STR(WINED3DRS_TEXTUREHANDLE );
478 D3DSTATE_TO_STR(WINED3DRS_ANTIALIAS );
479 D3DSTATE_TO_STR(WINED3DRS_TEXTUREADDRESS );
480 D3DSTATE_TO_STR(WINED3DRS_TEXTUREPERSPECTIVE );
481 D3DSTATE_TO_STR(WINED3DRS_WRAPU );
482 D3DSTATE_TO_STR(WINED3DRS_WRAPV );
483 D3DSTATE_TO_STR(WINED3DRS_ZENABLE );
484 D3DSTATE_TO_STR(WINED3DRS_FILLMODE );
485 D3DSTATE_TO_STR(WINED3DRS_SHADEMODE );
486 D3DSTATE_TO_STR(WINED3DRS_LINEPATTERN );
487 D3DSTATE_TO_STR(WINED3DRS_MONOENABLE );
488 D3DSTATE_TO_STR(WINED3DRS_ROP2 );
489 D3DSTATE_TO_STR(WINED3DRS_PLANEMASK );
490 D3DSTATE_TO_STR(WINED3DRS_ZWRITEENABLE );
491 D3DSTATE_TO_STR(WINED3DRS_ALPHATESTENABLE );
492 D3DSTATE_TO_STR(WINED3DRS_LASTPIXEL );
493 D3DSTATE_TO_STR(WINED3DRS_TEXTUREMAG );
494 D3DSTATE_TO_STR(WINED3DRS_TEXTUREMIN );
495 D3DSTATE_TO_STR(WINED3DRS_SRCBLEND );
496 D3DSTATE_TO_STR(WINED3DRS_DESTBLEND );
497 D3DSTATE_TO_STR(WINED3DRS_TEXTUREMAPBLEND );
498 D3DSTATE_TO_STR(WINED3DRS_CULLMODE );
499 D3DSTATE_TO_STR(WINED3DRS_ZFUNC );
500 D3DSTATE_TO_STR(WINED3DRS_ALPHAREF );
501 D3DSTATE_TO_STR(WINED3DRS_ALPHAFUNC );
502 D3DSTATE_TO_STR(WINED3DRS_DITHERENABLE );
503 D3DSTATE_TO_STR(WINED3DRS_ALPHABLENDENABLE );
504 D3DSTATE_TO_STR(WINED3DRS_FOGENABLE );
505 D3DSTATE_TO_STR(WINED3DRS_SPECULARENABLE );
506 D3DSTATE_TO_STR(WINED3DRS_ZVISIBLE );
507 D3DSTATE_TO_STR(WINED3DRS_SUBPIXEL );
508 D3DSTATE_TO_STR(WINED3DRS_SUBPIXELX );
509 D3DSTATE_TO_STR(WINED3DRS_STIPPLEDALPHA );
510 D3DSTATE_TO_STR(WINED3DRS_FOGCOLOR );
511 D3DSTATE_TO_STR(WINED3DRS_FOGTABLEMODE );
512 D3DSTATE_TO_STR(WINED3DRS_FOGSTART );
513 D3DSTATE_TO_STR(WINED3DRS_FOGEND );
514 D3DSTATE_TO_STR(WINED3DRS_FOGDENSITY );
515 D3DSTATE_TO_STR(WINED3DRS_STIPPLEENABLE );
516 D3DSTATE_TO_STR(WINED3DRS_EDGEANTIALIAS );
517 D3DSTATE_TO_STR(WINED3DRS_COLORKEYENABLE );
518 D3DSTATE_TO_STR(WINED3DRS_BORDERCOLOR );
519 D3DSTATE_TO_STR(WINED3DRS_TEXTUREADDRESSU );
520 D3DSTATE_TO_STR(WINED3DRS_TEXTUREADDRESSV );
521 D3DSTATE_TO_STR(WINED3DRS_MIPMAPLODBIAS );
522 D3DSTATE_TO_STR(WINED3DRS_ZBIAS );
523 D3DSTATE_TO_STR(WINED3DRS_RANGEFOGENABLE );
524 D3DSTATE_TO_STR(WINED3DRS_ANISOTROPY );
525 D3DSTATE_TO_STR(WINED3DRS_FLUSHBATCH );
526 D3DSTATE_TO_STR(WINED3DRS_TRANSLUCENTSORTINDEPENDENT);
527 D3DSTATE_TO_STR(WINED3DRS_STENCILENABLE );
528 D3DSTATE_TO_STR(WINED3DRS_STENCILFAIL );
529 D3DSTATE_TO_STR(WINED3DRS_STENCILZFAIL );
530 D3DSTATE_TO_STR(WINED3DRS_STENCILPASS );
531 D3DSTATE_TO_STR(WINED3DRS_STENCILFUNC );
532 D3DSTATE_TO_STR(WINED3DRS_STENCILREF );
533 D3DSTATE_TO_STR(WINED3DRS_STENCILMASK );
534 D3DSTATE_TO_STR(WINED3DRS_STENCILWRITEMASK );
535 D3DSTATE_TO_STR(WINED3DRS_TEXTUREFACTOR );
536 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN00 );
537 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN01 );
538 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN02 );
539 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN03 );
540 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN04 );
541 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN05 );
542 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN06 );
543 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN07 );
544 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN08 );
545 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN09 );
546 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN10 );
547 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN11 );
548 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN12 );
549 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN13 );
550 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN14 );
551 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN15 );
552 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN16 );
553 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN17 );
554 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN18 );
555 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN19 );
556 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN20 );
557 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN21 );
558 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN22 );
559 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN23 );
560 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN24 );
561 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN25 );
562 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN26 );
563 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN27 );
564 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN28 );
565 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN29 );
566 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN30 );
567 D3DSTATE_TO_STR(WINED3DRS_STIPPLEPATTERN31 );
568 D3DSTATE_TO_STR(WINED3DRS_WRAP0 );
569 D3DSTATE_TO_STR(WINED3DRS_WRAP1 );
570 D3DSTATE_TO_STR(WINED3DRS_WRAP2 );
571 D3DSTATE_TO_STR(WINED3DRS_WRAP3 );
572 D3DSTATE_TO_STR(WINED3DRS_WRAP4 );
573 D3DSTATE_TO_STR(WINED3DRS_WRAP5 );
574 D3DSTATE_TO_STR(WINED3DRS_WRAP6 );
575 D3DSTATE_TO_STR(WINED3DRS_WRAP7 );
576 D3DSTATE_TO_STR(WINED3DRS_CLIPPING );
577 D3DSTATE_TO_STR(WINED3DRS_LIGHTING );
578 D3DSTATE_TO_STR(WINED3DRS_EXTENTS );
579 D3DSTATE_TO_STR(WINED3DRS_AMBIENT );
580 D3DSTATE_TO_STR(WINED3DRS_FOGVERTEXMODE );
581 D3DSTATE_TO_STR(WINED3DRS_COLORVERTEX );
582 D3DSTATE_TO_STR(WINED3DRS_LOCALVIEWER );
583 D3DSTATE_TO_STR(WINED3DRS_NORMALIZENORMALS );
584 D3DSTATE_TO_STR(WINED3DRS_COLORKEYBLENDENABLE );
585 D3DSTATE_TO_STR(WINED3DRS_DIFFUSEMATERIALSOURCE );
586 D3DSTATE_TO_STR(WINED3DRS_SPECULARMATERIALSOURCE );
587 D3DSTATE_TO_STR(WINED3DRS_AMBIENTMATERIALSOURCE );
588 D3DSTATE_TO_STR(WINED3DRS_EMISSIVEMATERIALSOURCE );
589 D3DSTATE_TO_STR(WINED3DRS_VERTEXBLEND );
590 D3DSTATE_TO_STR(WINED3DRS_CLIPPLANEENABLE );
591 D3DSTATE_TO_STR(WINED3DRS_SOFTWAREVERTEXPROCESSING );
592 D3DSTATE_TO_STR(WINED3DRS_POINTSIZE );
593 D3DSTATE_TO_STR(WINED3DRS_POINTSIZE_MIN );
594 D3DSTATE_TO_STR(WINED3DRS_POINTSPRITEENABLE );
595 D3DSTATE_TO_STR(WINED3DRS_POINTSCALEENABLE );
596 D3DSTATE_TO_STR(WINED3DRS_POINTSCALE_A );
597 D3DSTATE_TO_STR(WINED3DRS_POINTSCALE_B );
598 D3DSTATE_TO_STR(WINED3DRS_POINTSCALE_C );
599 D3DSTATE_TO_STR(WINED3DRS_MULTISAMPLEANTIALIAS );
600 D3DSTATE_TO_STR(WINED3DRS_MULTISAMPLEMASK );
601 D3DSTATE_TO_STR(WINED3DRS_PATCHEDGESTYLE );
602 D3DSTATE_TO_STR(WINED3DRS_PATCHSEGMENTS );
603 D3DSTATE_TO_STR(WINED3DRS_DEBUGMONITORTOKEN );
604 D3DSTATE_TO_STR(WINED3DRS_POINTSIZE_MAX );
605 D3DSTATE_TO_STR(WINED3DRS_INDEXEDVERTEXBLENDENABLE );
606 D3DSTATE_TO_STR(WINED3DRS_COLORWRITEENABLE );
607 D3DSTATE_TO_STR(WINED3DRS_TWEENFACTOR );
608 D3DSTATE_TO_STR(WINED3DRS_BLENDOP );
609 D3DSTATE_TO_STR(WINED3DRS_POSITIONDEGREE );
610 D3DSTATE_TO_STR(WINED3DRS_NORMALDEGREE );
611 D3DSTATE_TO_STR(WINED3DRS_SCISSORTESTENABLE );
612 D3DSTATE_TO_STR(WINED3DRS_SLOPESCALEDEPTHBIAS );
613 D3DSTATE_TO_STR(WINED3DRS_ANTIALIASEDLINEENABLE );
614 D3DSTATE_TO_STR(WINED3DRS_MINTESSELLATIONLEVEL );
615 D3DSTATE_TO_STR(WINED3DRS_MAXTESSELLATIONLEVEL );
616 D3DSTATE_TO_STR(WINED3DRS_ADAPTIVETESS_X );
617 D3DSTATE_TO_STR(WINED3DRS_ADAPTIVETESS_Y );
618 D3DSTATE_TO_STR(WINED3DRS_ADAPTIVETESS_Z );
619 D3DSTATE_TO_STR(WINED3DRS_ADAPTIVETESS_W );
620 D3DSTATE_TO_STR(WINED3DRS_ENABLEADAPTIVETESSELLATION);
621 D3DSTATE_TO_STR(WINED3DRS_TWOSIDEDSTENCILMODE );
622 D3DSTATE_TO_STR(WINED3DRS_CCW_STENCILFAIL );
623 D3DSTATE_TO_STR(WINED3DRS_CCW_STENCILZFAIL );
624 D3DSTATE_TO_STR(WINED3DRS_CCW_STENCILPASS );
625 D3DSTATE_TO_STR(WINED3DRS_CCW_STENCILFUNC );
626 D3DSTATE_TO_STR(WINED3DRS_COLORWRITEENABLE1 );
627 D3DSTATE_TO_STR(WINED3DRS_COLORWRITEENABLE2 );
628 D3DSTATE_TO_STR(WINED3DRS_COLORWRITEENABLE3 );
629 D3DSTATE_TO_STR(WINED3DRS_BLENDFACTOR );
630 D3DSTATE_TO_STR(WINED3DRS_SRGBWRITEENABLE );
631 D3DSTATE_TO_STR(WINED3DRS_DEPTHBIAS );
632 D3DSTATE_TO_STR(WINED3DRS_WRAP8 );
633 D3DSTATE_TO_STR(WINED3DRS_WRAP9 );
634 D3DSTATE_TO_STR(WINED3DRS_WRAP10 );
635 D3DSTATE_TO_STR(WINED3DRS_WRAP11 );
636 D3DSTATE_TO_STR(WINED3DRS_WRAP12 );
637 D3DSTATE_TO_STR(WINED3DRS_WRAP13 );
638 D3DSTATE_TO_STR(WINED3DRS_WRAP14 );
639 D3DSTATE_TO_STR(WINED3DRS_WRAP15 );
640 D3DSTATE_TO_STR(WINED3DRS_SEPARATEALPHABLENDENABLE );
641 D3DSTATE_TO_STR(WINED3DRS_SRCBLENDALPHA );
642 D3DSTATE_TO_STR(WINED3DRS_DESTBLENDALPHA );
643 D3DSTATE_TO_STR(WINED3DRS_BLENDOPALPHA );
644 #undef D3DSTATE_TO_STR
645 default:
646 FIXME("Unrecognized %u render state!\n", state);
647 return "unrecognized";
651 const char* debug_d3dsamplerstate(DWORD state) {
652 switch (state) {
653 #define D3DSTATE_TO_STR(u) case u: return #u
654 D3DSTATE_TO_STR(WINED3DSAMP_BORDERCOLOR );
655 D3DSTATE_TO_STR(WINED3DSAMP_ADDRESSU );
656 D3DSTATE_TO_STR(WINED3DSAMP_ADDRESSV );
657 D3DSTATE_TO_STR(WINED3DSAMP_ADDRESSW );
658 D3DSTATE_TO_STR(WINED3DSAMP_MAGFILTER );
659 D3DSTATE_TO_STR(WINED3DSAMP_MINFILTER );
660 D3DSTATE_TO_STR(WINED3DSAMP_MIPFILTER );
661 D3DSTATE_TO_STR(WINED3DSAMP_MIPMAPLODBIAS);
662 D3DSTATE_TO_STR(WINED3DSAMP_MAXMIPLEVEL );
663 D3DSTATE_TO_STR(WINED3DSAMP_MAXANISOTROPY);
664 D3DSTATE_TO_STR(WINED3DSAMP_SRGBTEXTURE );
665 D3DSTATE_TO_STR(WINED3DSAMP_ELEMENTINDEX );
666 D3DSTATE_TO_STR(WINED3DSAMP_DMAPOFFSET );
667 #undef D3DSTATE_TO_STR
668 default:
669 FIXME("Unrecognized %u sampler state!\n", state);
670 return "unrecognized";
674 const char *debug_d3dtexturefiltertype(WINED3DTEXTUREFILTERTYPE filter_type) {
675 switch (filter_type) {
676 #define D3DTEXTUREFILTERTYPE_TO_STR(u) case u: return #u
677 D3DTEXTUREFILTERTYPE_TO_STR(WINED3DTEXF_NONE);
678 D3DTEXTUREFILTERTYPE_TO_STR(WINED3DTEXF_POINT);
679 D3DTEXTUREFILTERTYPE_TO_STR(WINED3DTEXF_LINEAR);
680 D3DTEXTUREFILTERTYPE_TO_STR(WINED3DTEXF_ANISOTROPIC);
681 D3DTEXTUREFILTERTYPE_TO_STR(WINED3DTEXF_FLATCUBIC);
682 D3DTEXTUREFILTERTYPE_TO_STR(WINED3DTEXF_GAUSSIANCUBIC);
683 D3DTEXTUREFILTERTYPE_TO_STR(WINED3DTEXF_PYRAMIDALQUAD);
684 D3DTEXTUREFILTERTYPE_TO_STR(WINED3DTEXF_GAUSSIANQUAD);
685 #undef D3DTEXTUREFILTERTYPE_TO_STR
686 default:
687 FIXME("Unrecognied texture filter type 0x%08x\n", filter_type);
688 return "unrecognized";
692 const char* debug_d3dtexturestate(DWORD state) {
693 switch (state) {
694 #define D3DSTATE_TO_STR(u) case u: return #u
695 D3DSTATE_TO_STR(WINED3DTSS_COLOROP );
696 D3DSTATE_TO_STR(WINED3DTSS_COLORARG1 );
697 D3DSTATE_TO_STR(WINED3DTSS_COLORARG2 );
698 D3DSTATE_TO_STR(WINED3DTSS_ALPHAOP );
699 D3DSTATE_TO_STR(WINED3DTSS_ALPHAARG1 );
700 D3DSTATE_TO_STR(WINED3DTSS_ALPHAARG2 );
701 D3DSTATE_TO_STR(WINED3DTSS_BUMPENVMAT00 );
702 D3DSTATE_TO_STR(WINED3DTSS_BUMPENVMAT01 );
703 D3DSTATE_TO_STR(WINED3DTSS_BUMPENVMAT10 );
704 D3DSTATE_TO_STR(WINED3DTSS_BUMPENVMAT11 );
705 D3DSTATE_TO_STR(WINED3DTSS_TEXCOORDINDEX );
706 D3DSTATE_TO_STR(WINED3DTSS_BUMPENVLSCALE );
707 D3DSTATE_TO_STR(WINED3DTSS_BUMPENVLOFFSET );
708 D3DSTATE_TO_STR(WINED3DTSS_TEXTURETRANSFORMFLAGS );
709 D3DSTATE_TO_STR(WINED3DTSS_ADDRESSW );
710 D3DSTATE_TO_STR(WINED3DTSS_COLORARG0 );
711 D3DSTATE_TO_STR(WINED3DTSS_ALPHAARG0 );
712 D3DSTATE_TO_STR(WINED3DTSS_RESULTARG );
713 D3DSTATE_TO_STR(WINED3DTSS_CONSTANT );
714 #undef D3DSTATE_TO_STR
715 case 12:
716 /* Note WINED3DTSS are not consecutive, so skip these */
717 return "unused";
718 default:
719 FIXME("Unrecognized %u texture state!\n", state);
720 return "unrecognized";
724 static const char* debug_d3dtop(WINED3DTEXTUREOP d3dtop) {
725 switch (d3dtop) {
726 #define D3DTOP_TO_STR(u) case u: return #u
727 D3DTOP_TO_STR(WINED3DTOP_DISABLE);
728 D3DTOP_TO_STR(WINED3DTOP_SELECTARG1);
729 D3DTOP_TO_STR(WINED3DTOP_SELECTARG2);
730 D3DTOP_TO_STR(WINED3DTOP_MODULATE);
731 D3DTOP_TO_STR(WINED3DTOP_MODULATE2X);
732 D3DTOP_TO_STR(WINED3DTOP_MODULATE4X);
733 D3DTOP_TO_STR(WINED3DTOP_ADD);
734 D3DTOP_TO_STR(WINED3DTOP_ADDSIGNED);
735 D3DTOP_TO_STR(WINED3DTOP_SUBTRACT);
736 D3DTOP_TO_STR(WINED3DTOP_ADDSMOOTH);
737 D3DTOP_TO_STR(WINED3DTOP_BLENDDIFFUSEALPHA);
738 D3DTOP_TO_STR(WINED3DTOP_BLENDTEXTUREALPHA);
739 D3DTOP_TO_STR(WINED3DTOP_BLENDFACTORALPHA);
740 D3DTOP_TO_STR(WINED3DTOP_BLENDTEXTUREALPHAPM);
741 D3DTOP_TO_STR(WINED3DTOP_BLENDCURRENTALPHA);
742 D3DTOP_TO_STR(WINED3DTOP_PREMODULATE);
743 D3DTOP_TO_STR(WINED3DTOP_MODULATEALPHA_ADDCOLOR);
744 D3DTOP_TO_STR(WINED3DTOP_MODULATECOLOR_ADDALPHA);
745 D3DTOP_TO_STR(WINED3DTOP_MODULATEINVALPHA_ADDCOLOR);
746 D3DTOP_TO_STR(WINED3DTOP_MODULATEINVCOLOR_ADDALPHA);
747 D3DTOP_TO_STR(WINED3DTOP_BUMPENVMAP);
748 D3DTOP_TO_STR(WINED3DTOP_BUMPENVMAPLUMINANCE);
749 D3DTOP_TO_STR(WINED3DTOP_DOTPRODUCT3);
750 D3DTOP_TO_STR(WINED3DTOP_MULTIPLYADD);
751 D3DTOP_TO_STR(WINED3DTOP_LERP);
752 #undef D3DTOP_TO_STR
753 default:
754 FIXME("Unrecognized %u WINED3DTOP\n", d3dtop);
755 return "unrecognized";
759 const char* debug_d3dtstype(WINED3DTRANSFORMSTATETYPE tstype) {
760 switch (tstype) {
761 #define TSTYPE_TO_STR(tstype) case tstype: return #tstype
762 TSTYPE_TO_STR(WINED3DTS_VIEW);
763 TSTYPE_TO_STR(WINED3DTS_PROJECTION);
764 TSTYPE_TO_STR(WINED3DTS_TEXTURE0);
765 TSTYPE_TO_STR(WINED3DTS_TEXTURE1);
766 TSTYPE_TO_STR(WINED3DTS_TEXTURE2);
767 TSTYPE_TO_STR(WINED3DTS_TEXTURE3);
768 TSTYPE_TO_STR(WINED3DTS_TEXTURE4);
769 TSTYPE_TO_STR(WINED3DTS_TEXTURE5);
770 TSTYPE_TO_STR(WINED3DTS_TEXTURE6);
771 TSTYPE_TO_STR(WINED3DTS_TEXTURE7);
772 TSTYPE_TO_STR(WINED3DTS_WORLDMATRIX(0));
773 #undef TSTYPE_TO_STR
774 default:
775 if (tstype > 256 && tstype < 512) {
776 FIXME("WINED3DTS_WORLDMATRIX(%u). 1..255 not currently supported\n", tstype);
777 return ("WINED3DTS_WORLDMATRIX > 0");
779 FIXME("Unrecognized %u WINED3DTS\n", tstype);
780 return "unrecognized";
784 const char* debug_d3dpool(WINED3DPOOL Pool) {
785 switch (Pool) {
786 #define POOL_TO_STR(p) case p: return #p;
787 POOL_TO_STR(WINED3DPOOL_DEFAULT);
788 POOL_TO_STR(WINED3DPOOL_MANAGED);
789 POOL_TO_STR(WINED3DPOOL_SYSTEMMEM);
790 POOL_TO_STR(WINED3DPOOL_SCRATCH);
791 #undef POOL_TO_STR
792 default:
793 FIXME("Unrecognized %u WINED3DPOOL!\n", Pool);
794 return "unrecognized";
798 const char *debug_fbostatus(GLenum status) {
799 switch(status) {
800 #define FBOSTATUS_TO_STR(u) case u: return #u
801 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_COMPLETE_EXT);
802 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT);
803 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT);
804 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT);
805 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT);
806 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT);
807 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT);
808 FBOSTATUS_TO_STR(GL_FRAMEBUFFER_UNSUPPORTED_EXT);
809 #undef FBOSTATUS_TO_STR
810 default:
811 FIXME("Unrecognied FBO status 0x%08x\n", status);
812 return "unrecognized";
816 const char *debug_glerror(GLenum error) {
817 switch(error) {
818 #define GLERROR_TO_STR(u) case u: return #u
819 GLERROR_TO_STR(GL_NO_ERROR);
820 GLERROR_TO_STR(GL_INVALID_ENUM);
821 GLERROR_TO_STR(GL_INVALID_VALUE);
822 GLERROR_TO_STR(GL_INVALID_OPERATION);
823 GLERROR_TO_STR(GL_STACK_OVERFLOW);
824 GLERROR_TO_STR(GL_STACK_UNDERFLOW);
825 GLERROR_TO_STR(GL_OUT_OF_MEMORY);
826 GLERROR_TO_STR(GL_INVALID_FRAMEBUFFER_OPERATION_EXT);
827 #undef GLERROR_TO_STR
828 default:
829 FIXME("Unrecognied GL error 0x%08x\n", error);
830 return "unrecognized";
834 const char *debug_d3dbasis(WINED3DBASISTYPE basis) {
835 switch(basis) {
836 case WINED3DBASIS_BEZIER: return "WINED3DBASIS_BEZIER";
837 case WINED3DBASIS_BSPLINE: return "WINED3DBASIS_BSPLINE";
838 case WINED3DBASIS_INTERPOLATE: return "WINED3DBASIS_INTERPOLATE";
839 default: return "unrecognized";
843 const char *debug_d3ddegree(WINED3DDEGREETYPE degree) {
844 switch(degree) {
845 case WINED3DDEGREE_LINEAR: return "WINED3DDEGREE_LINEAR";
846 case WINED3DDEGREE_QUADRATIC: return "WINED3DDEGREE_QUADRATIC";
847 case WINED3DDEGREE_CUBIC: return "WINED3DDEGREE_CUBIC";
848 case WINED3DDEGREE_QUINTIC: return "WINED3DDEGREE_QUINTIC";
849 default: return "unrecognized";
853 /*****************************************************************************
854 * Useful functions mapping GL <-> D3D values
856 GLenum StencilOp(DWORD op) {
857 switch(op) {
858 case WINED3DSTENCILOP_KEEP : return GL_KEEP;
859 case WINED3DSTENCILOP_ZERO : return GL_ZERO;
860 case WINED3DSTENCILOP_REPLACE : return GL_REPLACE;
861 case WINED3DSTENCILOP_INCRSAT : return GL_INCR;
862 case WINED3DSTENCILOP_DECRSAT : return GL_DECR;
863 case WINED3DSTENCILOP_INVERT : return GL_INVERT;
864 case WINED3DSTENCILOP_INCR : return GL_INCR_WRAP_EXT;
865 case WINED3DSTENCILOP_DECR : return GL_DECR_WRAP_EXT;
866 default:
867 FIXME("Unrecognized stencil op %d\n", op);
868 return GL_KEEP;
872 GLenum CompareFunc(DWORD func) {
873 switch ((WINED3DCMPFUNC)func) {
874 case WINED3DCMP_NEVER : return GL_NEVER;
875 case WINED3DCMP_LESS : return GL_LESS;
876 case WINED3DCMP_EQUAL : return GL_EQUAL;
877 case WINED3DCMP_LESSEQUAL : return GL_LEQUAL;
878 case WINED3DCMP_GREATER : return GL_GREATER;
879 case WINED3DCMP_NOTEQUAL : return GL_NOTEQUAL;
880 case WINED3DCMP_GREATEREQUAL : return GL_GEQUAL;
881 case WINED3DCMP_ALWAYS : return GL_ALWAYS;
882 default:
883 FIXME("Unrecognized WINED3DCMPFUNC value %d\n", func);
884 return 0;
888 static GLenum d3dta_to_combiner_input(DWORD d3dta, DWORD stage, INT texture_idx) {
889 switch (d3dta) {
890 case WINED3DTA_DIFFUSE:
891 return GL_PRIMARY_COLOR_NV;
893 case WINED3DTA_CURRENT:
894 if (stage) return GL_SPARE0_NV;
895 else return GL_PRIMARY_COLOR_NV;
897 case WINED3DTA_TEXTURE:
898 if (texture_idx > -1) return GL_TEXTURE0_ARB + texture_idx;
899 else return GL_PRIMARY_COLOR_NV;
901 case WINED3DTA_TFACTOR:
902 return GL_CONSTANT_COLOR0_NV;
904 case WINED3DTA_SPECULAR:
905 return GL_SECONDARY_COLOR_NV;
907 case WINED3DTA_TEMP:
908 /* TODO: Support WINED3DTSS_RESULTARG */
909 FIXME("WINED3DTA_TEMP, not properly supported.\n");
910 return GL_SPARE1_NV;
912 case WINED3DTA_CONSTANT:
913 /* TODO: Support per stage constants (WINED3DTSS_CONSTANT, NV_register_combiners2) */
914 FIXME("WINED3DTA_CONSTANT, not properly supported.\n");
915 return GL_CONSTANT_COLOR1_NV;
917 default:
918 FIXME("Unrecognized texture arg %#x\n", d3dta);
919 return GL_TEXTURE;
923 static GLenum invert_mapping(GLenum mapping) {
924 if (mapping == GL_UNSIGNED_INVERT_NV) return GL_SIGNED_IDENTITY_NV;
925 else if (mapping == GL_SIGNED_IDENTITY_NV) return GL_UNSIGNED_INVERT_NV;
927 FIXME("Unhandled mapping %#x\n", mapping);
928 return mapping;
931 static void get_src_and_opr_nvrc(DWORD stage, DWORD arg, BOOL is_alpha, GLenum* input, GLenum* mapping, GLenum *component_usage, INT texture_idx) {
932 /* The WINED3DTA_COMPLEMENT flag specifies the complement of the input should
933 * be used. */
934 if (arg & WINED3DTA_COMPLEMENT) *mapping = GL_UNSIGNED_INVERT_NV;
935 else *mapping = GL_SIGNED_IDENTITY_NV;
937 /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the input
938 * should be used for all input components. */
939 if (is_alpha || arg & WINED3DTA_ALPHAREPLICATE) *component_usage = GL_ALPHA;
940 else *component_usage = GL_RGB;
942 *input = d3dta_to_combiner_input(arg & WINED3DTA_SELECTMASK, stage, texture_idx);
945 typedef struct {
946 GLenum input[3];
947 GLenum mapping[3];
948 GLenum component_usage[3];
949 } tex_op_args;
951 static BOOL is_invalid_op(IWineD3DDeviceImpl *This, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3) {
952 if (op == WINED3DTOP_DISABLE) return FALSE;
953 if (This->stateBlock->textures[stage]) return FALSE;
955 if ((arg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
956 && op != WINED3DTOP_SELECTARG2) return TRUE;
957 if ((arg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
958 && op != WINED3DTOP_SELECTARG1) return TRUE;
959 if ((arg3 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE
960 && (op == WINED3DTOP_MULTIPLYADD || op == WINED3DTOP_LERP)) return TRUE;
962 return FALSE;
965 void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx) {
966 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl*)iface;
967 tex_op_args tex_op_args = {{0}, {0}, {0}};
968 GLenum portion = is_alpha ? GL_ALPHA : GL_RGB;
969 GLenum target = GL_COMBINER0_NV + stage;
971 TRACE("stage %d, is_alpha %d, op %s, arg1 %#x, arg2 %#x, arg3 %#x, texture_idx %d\n",
972 stage, is_alpha, debug_d3dtop(op), arg1, arg2, arg3, texture_idx);
974 /* If a texture stage references an invalid texture unit the stage just
975 * passes through the result from the previous stage */
976 if (is_invalid_op(This, stage, op, arg1, arg2, arg3)) {
977 arg1 = WINED3DTA_CURRENT;
978 op = WINED3DTOP_SELECTARG1;
981 get_src_and_opr_nvrc(stage, arg1, is_alpha, &tex_op_args.input[0],
982 &tex_op_args.mapping[0], &tex_op_args.component_usage[0], texture_idx);
983 get_src_and_opr_nvrc(stage, arg2, is_alpha, &tex_op_args.input[1],
984 &tex_op_args.mapping[1], &tex_op_args.component_usage[1], texture_idx);
985 get_src_and_opr_nvrc(stage, arg3, is_alpha, &tex_op_args.input[2],
986 &tex_op_args.mapping[2], &tex_op_args.component_usage[2], texture_idx);
989 /* This is called by a state handler which has the gl lock held and a context for the thread */
990 switch(op)
992 case WINED3DTOP_DISABLE:
993 /* Only for alpha */
994 if (!is_alpha) ERR("Shouldn't be called for WINED3DTSS_COLOROP (WINED3DTOP_DISABLE)\n");
995 /* Input, prev_alpha*1 */
996 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
997 GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA));
998 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
999 GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA));
1001 /* Output */
1002 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV,
1003 GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1004 break;
1006 case WINED3DTOP_SELECTARG1:
1007 case WINED3DTOP_SELECTARG2:
1008 /* Input, arg*1 */
1009 if (op == WINED3DTOP_SELECTARG1) {
1010 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1011 tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
1012 } else {
1013 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1014 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1016 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1017 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1019 /* Output */
1020 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV,
1021 GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1022 break;
1024 case WINED3DTOP_MODULATE:
1025 case WINED3DTOP_MODULATE2X:
1026 case WINED3DTOP_MODULATE4X:
1027 /* Input, arg1*arg2 */
1028 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1029 tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
1030 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1031 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1033 /* Output */
1034 if (op == WINED3DTOP_MODULATE) {
1035 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV,
1036 GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1037 } else if (op == WINED3DTOP_MODULATE2X) {
1038 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV,
1039 GL_DISCARD_NV, GL_SCALE_BY_TWO_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1040 } else if (op == WINED3DTOP_MODULATE4X) {
1041 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV,
1042 GL_DISCARD_NV, GL_SCALE_BY_FOUR_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1044 break;
1046 case WINED3DTOP_ADD:
1047 case WINED3DTOP_ADDSIGNED:
1048 case WINED3DTOP_ADDSIGNED2X:
1049 /* Input, arg1*1+arg2*1 */
1050 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1051 tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
1052 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1053 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1054 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
1055 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1056 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
1057 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1059 /* Output */
1060 if (op == WINED3DTOP_ADD) {
1061 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1062 GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1063 } else if (op == WINED3DTOP_ADDSIGNED) {
1064 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1065 GL_SPARE0_NV, GL_NONE, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE));
1066 } else if (op == WINED3DTOP_ADDSIGNED2X) {
1067 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1068 GL_SPARE0_NV, GL_SCALE_BY_TWO_NV, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE));
1070 break;
1072 case WINED3DTOP_SUBTRACT:
1073 /* Input, arg1*1+-arg2*1 */
1074 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1075 tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
1076 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1077 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1078 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
1079 tex_op_args.input[1], GL_SIGNED_NEGATE_NV, tex_op_args.component_usage[1]));
1080 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
1081 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1083 /* Output */
1084 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1085 GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1086 break;
1088 case WINED3DTOP_ADDSMOOTH:
1089 /* Input, arg1*1+(1-arg1)*arg2 */
1090 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1091 tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
1092 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1093 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1094 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
1095 tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0]));
1096 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
1097 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1099 /* Output */
1100 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1101 GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1102 break;
1104 case WINED3DTOP_BLENDDIFFUSEALPHA:
1105 case WINED3DTOP_BLENDTEXTUREALPHA:
1106 case WINED3DTOP_BLENDFACTORALPHA:
1107 case WINED3DTOP_BLENDTEXTUREALPHAPM:
1108 case WINED3DTOP_BLENDCURRENTALPHA:
1110 GLenum alpha_src = GL_PRIMARY_COLOR_NV;
1111 if (op == WINED3DTOP_BLENDDIFFUSEALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_DIFFUSE, stage, texture_idx);
1112 else if (op == WINED3DTOP_BLENDTEXTUREALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_TEXTURE, stage, texture_idx);
1113 else if (op == WINED3DTOP_BLENDFACTORALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_TFACTOR, stage, texture_idx);
1114 else if (op == WINED3DTOP_BLENDTEXTUREALPHAPM) alpha_src = d3dta_to_combiner_input(WINED3DTA_TEXTURE, stage, texture_idx);
1115 else if (op == WINED3DTOP_BLENDCURRENTALPHA) alpha_src = d3dta_to_combiner_input(WINED3DTA_CURRENT, stage, texture_idx);
1116 else FIXME("Unhandled WINED3DTOP %s, shouldn't happen\n", debug_d3dtop(op));
1118 /* Input, arg1*alpha_src+arg2*(1-alpha_src) */
1119 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1120 tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
1121 if (op == WINED3DTOP_BLENDTEXTUREALPHAPM)
1123 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1124 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1125 } else {
1126 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1127 alpha_src, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA));
1129 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
1130 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1131 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
1132 alpha_src, GL_UNSIGNED_INVERT_NV, GL_ALPHA));
1134 /* Output */
1135 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1136 GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1137 break;
1140 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
1141 /* Input, arg1_alpha*arg2_rgb+arg1_rgb*1 */
1142 if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATEALPHA_ADDCOLOR)\n");
1143 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1144 tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA));
1145 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1146 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1147 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
1148 tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
1149 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
1150 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1152 /* Output */
1153 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1154 GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1155 break;
1157 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
1158 /* Input, arg1_rgb*arg2_rgb+arg1_alpha*1 */
1159 if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATECOLOR_ADDALPHA)\n");
1160 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1161 tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
1162 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1163 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1164 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
1165 tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA));
1166 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
1167 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1169 /* Output */
1170 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1171 GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1172 break;
1174 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
1175 /* Input, (1-arg1_alpha)*arg2_rgb+arg1_rgb*1 */
1176 if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATEINVALPHA_ADDCOLOR)\n");
1177 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1178 tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), GL_ALPHA));
1179 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1180 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1181 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
1182 tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
1183 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
1184 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1186 /* Output */
1187 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1188 GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1189 break;
1191 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
1192 /* Input, (1-arg1_rgb)*arg2_rgb+arg1_alpha*1 */
1193 if (is_alpha) ERR("Only supported for WINED3DTSS_COLOROP (WINED3DTOP_MODULATEINVCOLOR_ADDALPHA)\n");
1194 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1195 tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0]));
1196 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1197 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1198 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
1199 tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA));
1200 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
1201 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1203 /* Output */
1204 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1205 GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1206 break;
1208 case WINED3DTOP_DOTPRODUCT3:
1209 /* Input, arg1 . arg2 */
1210 /* FIXME: DX7 uses a different calculation? */
1211 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1212 tex_op_args.input[0], GL_EXPAND_NORMAL_NV, tex_op_args.component_usage[0]));
1213 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1214 tex_op_args.input[1], GL_EXPAND_NORMAL_NV, tex_op_args.component_usage[1]));
1216 /* Output */
1217 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV,
1218 GL_DISCARD_NV, GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE));
1219 break;
1221 case WINED3DTOP_MULTIPLYADD:
1222 /* Input, arg1*1+arg2*arg3 */
1223 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1224 tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
1225 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1226 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1227 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
1228 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1229 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
1230 tex_op_args.input[2], tex_op_args.mapping[2], tex_op_args.component_usage[2]));
1232 /* Output */
1233 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1234 GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1235 break;
1237 case WINED3DTOP_LERP:
1238 /* Input, arg1*arg2+(1-arg1)*arg3 */
1239 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1240 tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
1241 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1242 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1243 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
1244 tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0]));
1245 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
1246 tex_op_args.input[2], tex_op_args.mapping[2], tex_op_args.component_usage[2]));
1248 /* Output */
1249 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
1250 GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1251 break;
1253 case WINED3DTOP_BUMPENVMAPLUMINANCE:
1254 case WINED3DTOP_BUMPENVMAP:
1255 if(GL_SUPPORT(NV_TEXTURE_SHADER)) {
1256 /* The bump map stage itself isn't exciting, just read the texture. But tell the next stage to
1257 * perform bump mapping and source from the current stage. Pretty much a SELECTARG2.
1258 * ARG2 is passed through unmodified(apps will most likely use D3DTA_CURRENT for arg2, arg1
1259 * (which will most likely be D3DTA_TEXTURE) is available as a texture shader input for the next stage
1261 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
1262 tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
1263 GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
1264 GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
1265 GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV,
1266 GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
1267 break;
1270 default:
1271 FIXME("Unhandled WINED3DTOP: stage %d, is_alpha %d, op %s (%#x), arg1 %#x, arg2 %#x, arg3 %#x, texture_idx %d\n",
1272 stage, is_alpha, debug_d3dtop(op), op, arg1, arg2, arg3, texture_idx);
1275 checkGLcall("set_tex_op_nvrc()\n");
1279 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
1280 /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
1281 * input should be used for all input components. The WINED3DTA_COMPLEMENT
1282 * flag specifies the complement of the input should be used. */
1283 BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
1284 BOOL complement = arg & WINED3DTA_COMPLEMENT;
1286 /* Calculate the operand */
1287 if (complement) {
1288 if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
1289 else *operand = GL_ONE_MINUS_SRC_COLOR;
1290 } else {
1291 if (from_alpha) *operand = GL_SRC_ALPHA;
1292 else *operand = GL_SRC_COLOR;
1295 /* Calculate the source */
1296 switch (arg & WINED3DTA_SELECTMASK) {
1297 case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
1298 case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
1299 case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
1300 case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
1301 case WINED3DTA_SPECULAR:
1303 * According to the GL_ARB_texture_env_combine specs, SPECULAR is
1304 * 'Secondary color' and isn't supported until base GL supports it
1305 * There is no concept of temp registers as far as I can tell
1307 FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
1308 *source = GL_TEXTURE;
1309 break;
1310 default:
1311 FIXME("Unrecognized texture arg %#x\n", arg);
1312 *source = GL_TEXTURE;
1313 break;
1317 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
1318 #if defined (GL_VERSION_1_3)
1319 # define useext(A) A
1320 # define combine_ext 1
1321 #elif defined (GL_EXT_texture_env_combine)
1322 # define useext(A) A##_EXT
1323 # define combine_ext 1
1324 #elif defined (GL_ARB_texture_env_combine)
1325 # define useext(A) A##_ARB
1326 # define combine_ext 1
1327 #else
1328 # undef combine_ext
1329 #endif
1331 #if !defined(combine_ext)
1332 void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1334 FIXME("Requires opengl combine extensions to work\n");
1335 return;
1337 #else
1338 /* Setup the texture operations texture stage states */
1339 void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1341 GLenum src1, src2, src3;
1342 GLenum opr1, opr2, opr3;
1343 GLenum comb_target;
1344 GLenum src0_target, src1_target, src2_target;
1345 GLenum opr0_target, opr1_target, opr2_target;
1346 GLenum scal_target;
1347 GLenum opr=0, invopr, src3_target, opr3_target;
1348 BOOL Handled = FALSE;
1349 IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1351 TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
1353 /* This is called by a state handler which has the gl lock held and a context for the thread */
1355 /* Note: Operations usually involve two ars, src0 and src1 and are operations of
1356 the form (a1 <operation> a2). However, some of the more complex operations
1357 take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
1358 in a third parameter called a0. Therefore these are operations of the form
1359 a0 <operation> a1 <operation> a2, ie the new parameter goes to the front.
1361 However, below we treat the new (a0) parameter as src2/opr2, so in the actual
1362 functions below, expect their syntax to differ slightly to those listed in the
1363 manuals, ie replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
1364 This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP */
1366 if (isAlpha) {
1367 comb_target = useext(GL_COMBINE_ALPHA);
1368 src0_target = useext(GL_SOURCE0_ALPHA);
1369 src1_target = useext(GL_SOURCE1_ALPHA);
1370 src2_target = useext(GL_SOURCE2_ALPHA);
1371 opr0_target = useext(GL_OPERAND0_ALPHA);
1372 opr1_target = useext(GL_OPERAND1_ALPHA);
1373 opr2_target = useext(GL_OPERAND2_ALPHA);
1374 scal_target = GL_ALPHA_SCALE;
1376 else {
1377 comb_target = useext(GL_COMBINE_RGB);
1378 src0_target = useext(GL_SOURCE0_RGB);
1379 src1_target = useext(GL_SOURCE1_RGB);
1380 src2_target = useext(GL_SOURCE2_RGB);
1381 opr0_target = useext(GL_OPERAND0_RGB);
1382 opr1_target = useext(GL_OPERAND1_RGB);
1383 opr2_target = useext(GL_OPERAND2_RGB);
1384 scal_target = useext(GL_RGB_SCALE);
1387 /* If a texture stage references an invalid texture unit the stage just
1388 * passes through the result from the previous stage */
1389 if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
1390 arg1 = WINED3DTA_CURRENT;
1391 op = WINED3DTOP_SELECTARG1;
1394 /* From MSDN (WINED3DTSS_ALPHAARG1) :
1395 The default argument is WINED3DTA_TEXTURE. If no texture is set for this stage,
1396 then the default argument is WINED3DTA_DIFFUSE.
1397 FIXME? If texture added/removed, may need to reset back as well? */
1398 if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) {
1399 get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
1400 } else {
1401 get_src_and_opr(arg1, isAlpha, &src1, &opr1);
1403 get_src_and_opr(arg2, isAlpha, &src2, &opr2);
1404 get_src_and_opr(arg3, isAlpha, &src3, &opr3);
1406 TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
1408 Handled = TRUE; /* Assume will be handled */
1410 /* Other texture operations require special extensions: */
1411 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1412 if (isAlpha) {
1413 opr = GL_SRC_ALPHA;
1414 invopr = GL_ONE_MINUS_SRC_ALPHA;
1415 src3_target = GL_SOURCE3_ALPHA_NV;
1416 opr3_target = GL_OPERAND3_ALPHA_NV;
1417 } else {
1418 opr = GL_SRC_COLOR;
1419 invopr = GL_ONE_MINUS_SRC_COLOR;
1420 src3_target = GL_SOURCE3_RGB_NV;
1421 opr3_target = GL_OPERAND3_RGB_NV;
1423 switch (op) {
1424 case WINED3DTOP_DISABLE: /* Only for alpha */
1425 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1426 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1427 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
1428 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1429 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
1430 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1431 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1432 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1433 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1434 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1435 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1436 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1437 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1438 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1439 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1440 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1441 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1442 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1443 break;
1444 case WINED3DTOP_SELECTARG1: /* = a1 * 1 + 0 * 0 */
1445 case WINED3DTOP_SELECTARG2: /* = a2 * 1 + 0 * 0 */
1446 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1447 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1448 if (op == WINED3DTOP_SELECTARG1) {
1449 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1450 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1451 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1452 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1453 } else {
1454 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
1455 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
1456 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
1457 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
1459 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1460 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1461 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1462 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1463 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1464 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1465 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1466 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1467 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1468 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1469 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1470 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1471 break;
1473 case WINED3DTOP_MODULATE:
1474 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1475 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1476 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1477 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1478 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1479 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1480 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1481 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1482 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1483 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1484 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1485 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1486 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1487 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1488 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1489 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1490 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1491 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1492 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1493 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1494 break;
1495 case WINED3DTOP_MODULATE2X:
1496 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1497 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1498 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1499 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1500 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1501 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1502 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1503 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1504 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1505 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1506 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1507 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1508 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1509 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1510 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1511 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1512 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1513 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1514 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
1515 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
1516 break;
1517 case WINED3DTOP_MODULATE4X:
1518 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1519 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1520 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1521 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1522 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1523 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1524 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1525 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1526 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1527 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1528 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1529 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1530 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1531 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1532 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1533 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1534 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1535 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1536 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
1537 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
1538 break;
1540 case WINED3DTOP_ADD:
1541 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1542 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1543 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1544 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1545 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1546 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1547 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1548 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1549 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1550 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1551 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
1552 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1553 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1554 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1555 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1556 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1557 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
1558 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
1559 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1560 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1561 break;
1563 case WINED3DTOP_ADDSIGNED:
1564 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
1565 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
1566 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1567 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1568 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1569 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1570 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1571 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1572 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1573 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1574 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
1575 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1576 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1577 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1578 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1579 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1580 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
1581 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
1582 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1583 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1584 break;
1586 case WINED3DTOP_ADDSIGNED2X:
1587 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
1588 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
1589 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1590 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1591 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1592 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1593 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1594 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1595 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1596 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1597 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
1598 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1599 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1600 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1601 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1602 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1603 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
1604 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
1605 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
1606 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
1607 break;
1609 case WINED3DTOP_ADDSMOOTH:
1610 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1611 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1612 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1613 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1614 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1615 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1616 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1617 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1618 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1619 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1620 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
1621 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1622 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1623 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1624 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
1625 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
1626 switch (opr1) {
1627 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
1628 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
1629 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
1630 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
1632 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1633 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1634 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1635 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1636 break;
1638 case WINED3DTOP_BLENDDIFFUSEALPHA:
1639 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1640 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1641 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1642 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1643 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1644 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1645 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
1646 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
1647 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1648 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1649 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
1650 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1651 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1652 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1653 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
1654 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
1655 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
1656 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
1657 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1658 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1659 break;
1660 case WINED3DTOP_BLENDTEXTUREALPHA:
1661 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1662 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1663 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1664 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1665 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1666 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1667 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
1668 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
1669 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1670 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1671 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
1672 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1673 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1674 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1675 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
1676 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
1677 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
1678 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
1679 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1680 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1681 break;
1682 case WINED3DTOP_BLENDFACTORALPHA:
1683 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1684 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1685 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1686 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1687 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1688 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1689 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
1690 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
1691 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1692 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1693 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
1694 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1695 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1696 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1697 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
1698 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
1699 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
1700 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
1701 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1702 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1703 break;
1704 case WINED3DTOP_BLENDTEXTUREALPHAPM:
1705 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1706 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1707 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1708 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1709 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1710 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1711 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1712 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1713 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1714 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1715 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
1716 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1717 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1718 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1719 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
1720 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
1721 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
1722 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
1723 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1724 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1725 break;
1726 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
1727 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1728 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1729 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1); /* a0 = src1/opr1 */
1730 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1731 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1732 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1"); /* a1 = 1 (see docs) */
1733 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1734 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1735 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1736 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1737 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2); /* a2 = arg2 */
1738 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1739 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1740 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2"); /* a3 = src1 alpha */
1741 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
1742 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
1743 switch (opr) {
1744 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
1745 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
1747 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1748 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1749 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1750 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1751 break;
1752 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
1753 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1754 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1755 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1756 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1757 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1758 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1759 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1760 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
1761 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1762 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
1763 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
1764 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
1765 switch (opr1) {
1766 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
1767 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
1769 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1770 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1771 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1772 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1773 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
1774 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
1775 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1776 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1777 break;
1778 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
1779 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1780 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1781 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1782 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1783 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1784 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1785 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1786 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1787 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1788 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1789 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
1790 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1791 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
1792 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1793 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
1794 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
1795 switch (opr1) {
1796 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
1797 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
1798 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
1799 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
1801 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1802 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1803 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1804 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1805 break;
1806 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
1807 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1808 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1809 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1810 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1811 switch (opr1) {
1812 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
1813 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
1814 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
1815 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
1817 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
1818 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
1819 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1820 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
1821 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1822 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
1823 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
1824 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
1825 switch (opr1) {
1826 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
1827 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
1829 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1830 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1831 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1832 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1833 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
1834 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
1835 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1836 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1837 break;
1838 case WINED3DTOP_MULTIPLYADD:
1839 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1840 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1841 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
1842 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1843 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
1844 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1845 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1846 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1847 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1848 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1849 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
1850 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1851 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
1852 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1853 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
1854 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
1855 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
1856 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
1857 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1858 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1859 break;
1861 case WINED3DTOP_BUMPENVMAP:
1865 case WINED3DTOP_BUMPENVMAPLUMINANCE:
1866 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
1868 default:
1869 Handled = FALSE;
1871 if (Handled) {
1872 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
1873 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
1875 return;
1877 } /* GL_NV_texture_env_combine4 */
1879 Handled = TRUE; /* Again, assume handled */
1880 switch (op) {
1881 case WINED3DTOP_DISABLE: /* Only for alpha */
1882 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
1883 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1884 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
1885 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
1886 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
1887 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
1888 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1889 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1890 break;
1891 case WINED3DTOP_SELECTARG1:
1892 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
1893 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1894 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1895 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1896 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1897 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1898 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1899 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1900 break;
1901 case WINED3DTOP_SELECTARG2:
1902 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
1903 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1904 glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
1905 checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
1906 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
1907 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
1908 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1909 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1910 break;
1911 case WINED3DTOP_MODULATE:
1912 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
1913 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
1914 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1915 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1916 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1917 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1918 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1919 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
1920 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1921 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
1922 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1923 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1924 break;
1925 case WINED3DTOP_MODULATE2X:
1926 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
1927 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
1928 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1929 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1930 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1931 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1932 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1933 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
1934 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1935 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
1936 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
1937 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
1938 break;
1939 case WINED3DTOP_MODULATE4X:
1940 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
1941 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
1942 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1943 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1944 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1945 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1946 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1947 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
1948 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1949 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
1950 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
1951 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
1952 break;
1953 case WINED3DTOP_ADD:
1954 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1955 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1956 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1957 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1958 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1959 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1960 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1961 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
1962 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1963 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
1964 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1965 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1966 break;
1967 case WINED3DTOP_ADDSIGNED:
1968 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
1969 checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
1970 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1971 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1972 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1973 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1974 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1975 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
1976 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1977 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
1978 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1979 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1980 break;
1981 case WINED3DTOP_ADDSIGNED2X:
1982 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
1983 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
1984 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1985 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1986 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1987 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1988 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1989 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
1990 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1991 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
1992 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
1993 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
1994 break;
1995 case WINED3DTOP_SUBTRACT:
1996 if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
1997 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
1998 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
1999 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2000 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2001 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2002 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2003 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2004 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2005 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2006 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2007 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2008 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2009 } else {
2010 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2012 break;
2014 case WINED3DTOP_BLENDDIFFUSEALPHA:
2015 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2016 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2017 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2018 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2019 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2020 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2021 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2022 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2023 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2024 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2025 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2026 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2027 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2028 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2029 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2030 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2031 break;
2032 case WINED3DTOP_BLENDTEXTUREALPHA:
2033 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2034 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2035 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2036 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2037 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2038 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2039 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2040 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2041 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2042 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2043 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2044 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2045 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2046 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2047 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2048 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2049 break;
2050 case WINED3DTOP_BLENDFACTORALPHA:
2051 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2052 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2053 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2054 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2055 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2056 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2057 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2058 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2059 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2060 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2061 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2062 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2063 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2064 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2065 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2066 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2067 break;
2068 case WINED3DTOP_BLENDCURRENTALPHA:
2069 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2070 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2071 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2072 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2073 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2074 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2075 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2076 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2077 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2078 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2079 glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2080 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2081 glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2082 checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2083 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2084 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2085 break;
2086 case WINED3DTOP_DOTPRODUCT3:
2087 if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
2088 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2089 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2090 } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) {
2091 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2092 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2093 } else {
2094 FIXME("This version of opengl does not support GL_DOT3\n");
2096 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2097 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2098 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2099 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2100 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2101 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2102 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2103 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2104 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2105 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2106 break;
2107 case WINED3DTOP_LERP:
2108 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2109 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2110 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2111 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2112 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2113 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2114 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2115 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2116 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2117 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2118 glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2119 checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2120 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2121 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2122 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2123 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2124 break;
2125 case WINED3DTOP_ADDSMOOTH:
2126 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2127 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2128 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2129 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2130 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2131 switch (opr1) {
2132 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2133 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2134 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2135 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2137 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2138 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2139 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2140 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2141 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2142 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2143 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2144 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2145 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2146 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2147 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2148 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2149 } else
2150 Handled = FALSE;
2151 break;
2152 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2153 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2154 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2155 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2156 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2157 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2158 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2159 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2160 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2161 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2162 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2163 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2164 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2165 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2166 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2167 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2168 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2169 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2170 } else
2171 Handled = FALSE;
2172 break;
2173 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2174 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2175 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2176 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2177 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2178 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2179 switch (opr1) {
2180 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2181 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2182 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2183 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2185 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2186 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2187 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2188 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2189 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2190 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2191 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2192 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2193 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2194 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2195 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2196 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2197 } else
2198 Handled = FALSE;
2199 break;
2200 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2201 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2202 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2203 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2204 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2205 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2206 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2207 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2208 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2209 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2210 switch (opr1) {
2211 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2212 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2213 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2214 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2216 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2217 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2218 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2219 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2220 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2221 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2222 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2223 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2224 } else
2225 Handled = FALSE;
2226 break;
2227 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2228 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2229 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2230 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2231 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2232 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2233 switch (opr1) {
2234 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2235 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2236 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2237 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2239 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2240 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2241 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2242 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2243 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2244 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2245 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2246 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2247 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2248 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2249 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2250 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2251 } else
2252 Handled = FALSE;
2253 break;
2254 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2255 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2256 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2257 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2258 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2259 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2260 switch (opr1) {
2261 case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2262 case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2263 case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2264 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2266 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2267 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2268 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2269 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2270 switch (opr1) {
2271 case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2272 case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2273 case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2274 case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2276 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2277 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2278 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2279 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2280 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2281 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2282 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2283 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2284 } else
2285 Handled = FALSE;
2286 break;
2287 case WINED3DTOP_MULTIPLYADD:
2288 if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2289 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2290 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2291 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2292 checkGLcall("GL_TEXTURE_ENV, src0_target, src3");
2293 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2294 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr3");
2295 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2296 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2297 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2298 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2299 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2300 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2301 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2302 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2303 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2304 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2305 } else
2306 Handled = FALSE;
2307 break;
2308 case WINED3DTOP_BUMPENVMAPLUMINANCE:
2309 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2310 /* Some apps use BUMPENVMAPLUMINANCE instead of D3DTOP_BUMPENVMAP, although
2311 * they check for the non-luminance cap flag. Well, give them what they asked
2312 * for :-)
2314 WARN("Application uses WINED3DTOP_BUMPENVMAPLUMINANCE\n");
2315 } else {
2316 Handled = FALSE;
2317 break;
2319 /* Fall through */
2320 case WINED3DTOP_BUMPENVMAP:
2321 if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
2322 TRACE("Using ati bumpmap on stage %d, target %d\n", Stage, Stage + 1);
2323 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_BUMP_ENVMAP_ATI);
2324 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_BUMP_ENVMAP_ATI)");
2325 glTexEnvi(GL_TEXTURE_ENV, GL_BUMP_TARGET_ATI, GL_TEXTURE0_ARB + Stage + 1);
2326 checkGLcall("glTexEnvi(GL_TEXTURE_ENV, GL_BUMP_TARGET_ATI, GL_TEXTURE0_ARB + Stage + 1)");
2327 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2328 checkGLcall("GL_TEXTURE_ENV, src0_target, src3");
2329 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2330 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr3");
2331 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2332 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2333 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2334 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2335 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2336 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2337 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2338 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2340 Handled = TRUE;
2341 break;
2342 } else if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2343 /* Technically texture shader support without register combiners is possible, but not expected to occur
2344 * on real world cards, so for now a fixme should be enough
2346 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
2348 default:
2349 Handled = FALSE;
2352 if (Handled) {
2353 BOOL combineOK = TRUE;
2354 if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2355 DWORD op2;
2357 if (isAlpha) {
2358 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP];
2359 } else {
2360 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP];
2363 /* Note: If COMBINE4 in effect can't go back to combine! */
2364 switch (op2) {
2365 case WINED3DTOP_ADDSMOOTH:
2366 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2367 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2368 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2369 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2370 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2371 case WINED3DTOP_MULTIPLYADD:
2372 /* Ignore those implemented in both cases */
2373 switch (op) {
2374 case WINED3DTOP_SELECTARG1:
2375 case WINED3DTOP_SELECTARG2:
2376 combineOK = FALSE;
2377 Handled = FALSE;
2378 break;
2379 default:
2380 FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
2381 return;
2386 if (combineOK) {
2387 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
2388 checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
2390 return;
2394 /* After all the extensions, if still unhandled, report fixme */
2395 FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
2396 #undef GLINFO_LOCATION
2398 #endif
2400 /* Setup this textures matrix according to the texture flags*/
2401 void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords)
2403 float mat[16];
2405 glMatrixMode(GL_TEXTURE);
2406 checkGLcall("glMatrixMode(GL_TEXTURE)");
2408 if (flags == WINED3DTTFF_DISABLE) {
2409 glLoadIdentity();
2410 checkGLcall("glLoadIdentity()");
2411 return;
2414 if (flags == (WINED3DTTFF_COUNT1|WINED3DTTFF_PROJECTED)) {
2415 ERR("Invalid texture transform flags: WINED3DTTFF_COUNT1|WINED3DTTFF_PROJECTED\n");
2416 return;
2419 memcpy(mat, smat, 16 * sizeof(float));
2421 switch (flags & ~WINED3DTTFF_PROJECTED) {
2422 case WINED3DTTFF_COUNT1: mat[1] = mat[5] = mat[13] = 0;
2423 case WINED3DTTFF_COUNT2: mat[2] = mat[6] = mat[10] = mat[14] = 0;
2424 default: mat[3] = mat[7] = mat[11] = 0, mat[15] = 1;
2427 if (flags & WINED3DTTFF_PROJECTED) {
2428 switch (flags & ~WINED3DTTFF_PROJECTED) {
2429 case WINED3DTTFF_COUNT2:
2430 mat[3] = mat[1], mat[7] = mat[5], mat[11] = mat[9], mat[15] = mat[13];
2431 mat[1] = mat[5] = mat[9] = mat[13] = 0;
2432 break;
2433 case WINED3DTTFF_COUNT3:
2434 mat[3] = mat[2], mat[7] = mat[6], mat[11] = mat[10], mat[15] = mat[14];
2435 mat[2] = mat[6] = mat[10] = mat[14] = 0;
2436 break;
2438 } else if(!calculatedCoords) { /* under directx the R/Z coord can be used for translation, under opengl we use the Q coord instead */
2439 mat[12] = mat[8];
2440 mat[13] = mat[9];
2443 glLoadMatrixf(mat);
2444 checkGLcall("glLoadMatrixf(mat)");
2447 #define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info
2449 /* Convertes a D3D format into a OpenGL configuration format */
2450 int D3DFmtMakeGlCfg(WINED3DFORMAT BackBufferFormat, WINED3DFORMAT StencilBufferFormat, int *attribs, int* nAttribs, BOOL alternate){
2451 #define PUSH1(att) attribs[(*nAttribs)++] = (att);
2452 #define PUSH2(att,value) attribs[(*nAttribs)++] = (att); attribs[(*nAttribs)++] = (value);
2453 /*We need to do some Card specific stuff in here at some point,
2454 D3D now supports floating point format buffers, and there are a number of different OpelGl ways of managing these e.g.
2455 GLX_ATI_pixel_format_float
2457 switch (BackBufferFormat) {
2458 /* color buffer */
2459 case WINED3DFMT_P8:
2460 PUSH2(GLX_RENDER_TYPE, GLX_COLOR_INDEX_BIT);
2461 PUSH2(GLX_BUFFER_SIZE, 8);
2462 PUSH2(GLX_DOUBLEBUFFER, TRUE);
2463 break;
2465 case WINED3DFMT_R3G3B2:
2466 PUSH2(GLX_RENDER_TYPE, GLX_RGBA_BIT);
2467 PUSH2(GLX_RED_SIZE, 3);
2468 PUSH2(GLX_GREEN_SIZE, 3);
2469 PUSH2(GLX_BLUE_SIZE, 2);
2470 break;
2472 case WINED3DFMT_A1R5G5B5:
2473 PUSH2(GLX_ALPHA_SIZE, 1);
2474 case WINED3DFMT_X1R5G5B5:
2475 PUSH2(GLX_RED_SIZE, 5);
2476 PUSH2(GLX_GREEN_SIZE, 5);
2477 PUSH2(GLX_BLUE_SIZE, 5);
2478 break;
2480 case WINED3DFMT_R5G6B5:
2481 PUSH2(GLX_RED_SIZE, 5);
2482 PUSH2(GLX_GREEN_SIZE, 6);
2483 PUSH2(GLX_BLUE_SIZE, 5);
2484 break;
2486 case WINED3DFMT_A4R4G4B4:
2487 PUSH2(GLX_ALPHA_SIZE, 4);
2488 case WINED3DFMT_X4R4G4B4:
2489 PUSH2(GLX_RED_SIZE, 4);
2490 PUSH2(GLX_GREEN_SIZE, 4);
2491 PUSH2(GLX_BLUE_SIZE, 4);
2492 break;
2494 case WINED3DFMT_A8R8G8B8:
2495 PUSH2(GLX_ALPHA_SIZE, 8);
2496 case WINED3DFMT_R8G8B8:
2497 case WINED3DFMT_X8R8G8B8:
2498 PUSH2(GLX_RED_SIZE, 8);
2499 PUSH2(GLX_GREEN_SIZE, 8);
2500 PUSH2(GLX_BLUE_SIZE, 8);
2501 break;
2503 case WINED3DFMT_A2R10G10B10:
2504 PUSH2(GLX_ALPHA_SIZE, 2);
2505 PUSH2(GLX_RED_SIZE, 10);
2506 PUSH2(GLX_GREEN_SIZE, 10);
2507 PUSH2(GLX_BLUE_SIZE, 10);
2508 break;
2510 case WINED3DFMT_A16B16G16R16:
2511 PUSH2(GLX_ALPHA_SIZE, 16);
2512 PUSH2(GLX_RED_SIZE, 16);
2513 PUSH2(GLX_GREEN_SIZE, 16);
2514 PUSH2(GLX_BLUE_SIZE, 16);
2515 break;
2517 default:
2518 FIXME("Unsupported color format: %s\n", debug_d3dformat(BackBufferFormat));
2519 break;
2521 if(!alternate){
2522 switch (StencilBufferFormat) {
2523 case 0:
2524 break;
2526 case WINED3DFMT_D16_LOCKABLE:
2527 case WINED3DFMT_D16:
2528 PUSH2(GLX_DEPTH_SIZE, 16);
2529 break;
2531 case WINED3DFMT_D15S1:
2532 PUSH2(GLX_DEPTH_SIZE, 15);
2533 PUSH2(GLX_STENCIL_SIZE, 1);
2534 /*Does openGl support a 1bit stencil?, I've seen it used elsewhere
2535 e.g. http://www.ks.uiuc.edu/Research/vmd/doxygen/OpenGLDisplayDevice_8C-source.html*/
2536 break;
2538 case WINED3DFMT_D24X8:
2539 PUSH2(GLX_DEPTH_SIZE, 24);
2540 break;
2542 case WINED3DFMT_D24X4S4:
2543 PUSH2(GLX_DEPTH_SIZE, 24);
2544 PUSH2(GLX_STENCIL_SIZE, 4);
2545 break;
2547 case WINED3DFMT_D24S8:
2548 PUSH2(GLX_DEPTH_SIZE, 24);
2549 PUSH2(GLX_STENCIL_SIZE, 8);
2550 break;
2552 case WINED3DFMT_D24FS8:
2553 PUSH2(GLX_DEPTH_SIZE, 24);
2554 PUSH2(GLX_STENCIL_SIZE, 8);
2555 break;
2557 case WINED3DFMT_D32:
2558 PUSH2(GLX_DEPTH_SIZE, 32);
2559 break;
2561 default:
2562 FIXME("Unsupported stencil format: %s\n", debug_d3dformat(StencilBufferFormat));
2563 break;
2566 } else { /* it the device doesn't support the 'exact' format, try to find something close */
2567 switch (StencilBufferFormat) {
2568 case 0:
2569 break;
2571 case WINED3DFMT_D16_LOCKABLE:
2572 case WINED3DFMT_D16:
2573 PUSH2(GLX_DEPTH_SIZE, 1);
2574 break;
2576 case WINED3DFMT_D15S1:
2577 PUSH2(GLX_DEPTH_SIZE, 1);
2578 PUSH2(GLX_STENCIL_SIZE, 1);
2579 /*Does openGl support a 1bit stencil?, I've seen it used elsewhere
2580 e.g. http://www.ks.uiuc.edu/Research/vmd/doxygen/OpenGLDisplayDevice_8C-source.html*/
2581 break;
2583 case WINED3DFMT_D24X8:
2584 PUSH2(GLX_DEPTH_SIZE, 1);
2585 break;
2587 case WINED3DFMT_D24X4S4:
2588 PUSH2(GLX_DEPTH_SIZE, 1);
2589 PUSH2(GLX_STENCIL_SIZE, 1);
2590 break;
2592 case WINED3DFMT_D24S8:
2593 PUSH2(GLX_DEPTH_SIZE, 1);
2594 PUSH2(GLX_STENCIL_SIZE, 1);
2595 break;
2597 case WINED3DFMT_D24FS8:
2598 PUSH2(GLX_DEPTH_SIZE, 1);
2599 PUSH2(GLX_STENCIL_SIZE, 1);
2600 break;
2602 case WINED3DFMT_D32:
2603 PUSH2(GLX_DEPTH_SIZE, 1);
2604 break;
2606 default:
2607 FIXME("Unsupported stencil format: %s\n", debug_d3dformat(StencilBufferFormat));
2608 break;
2612 return *nAttribs;
2615 #undef GLINFO_LOCATION
2617 /* DirectDraw stuff */
2618 WINED3DFORMAT pixelformat_for_depth(DWORD depth) {
2619 switch(depth) {
2620 case 8: return WINED3DFMT_P8;
2621 case 15: return WINED3DFMT_X1R5G5B5;
2622 case 16: return WINED3DFMT_R5G6B5;
2623 case 24: return WINED3DFMT_R8G8B8;
2624 case 32: return WINED3DFMT_X8R8G8B8;
2625 default: return WINED3DFMT_UNKNOWN;
2629 void multiply_matrix(WINED3DMATRIX *dest, const WINED3DMATRIX *src1, const WINED3DMATRIX *src2) {
2630 WINED3DMATRIX temp;
2632 /* Now do the multiplication 'by hand'.
2633 I know that all this could be optimised, but this will be done later :-) */
2634 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);
2635 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);
2636 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);
2637 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);
2639 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);
2640 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);
2641 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);
2642 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);
2644 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);
2645 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);
2646 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);
2647 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);
2649 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);
2650 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);
2651 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);
2652 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);
2654 /* And copy the new matrix in the good storage.. */
2655 memcpy(dest, &temp, 16 * sizeof(float));
2658 DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) {
2659 DWORD size = 0;
2660 int i;
2661 int numTextures = (d3dvtVertexType & WINED3DFVF_TEXCOUNT_MASK) >> WINED3DFVF_TEXCOUNT_SHIFT;
2663 if (d3dvtVertexType & WINED3DFVF_NORMAL) size += 3 * sizeof(float);
2664 if (d3dvtVertexType & WINED3DFVF_DIFFUSE) size += sizeof(DWORD);
2665 if (d3dvtVertexType & WINED3DFVF_SPECULAR) size += sizeof(DWORD);
2666 if (d3dvtVertexType & WINED3DFVF_PSIZE) size += sizeof(DWORD);
2667 switch (d3dvtVertexType & WINED3DFVF_POSITION_MASK) {
2668 case WINED3DFVF_XYZ: size += 3 * sizeof(float); break;
2669 case WINED3DFVF_XYZRHW: size += 4 * sizeof(float); break;
2670 case WINED3DFVF_XYZB1: size += 4 * sizeof(float); break;
2671 case WINED3DFVF_XYZB2: size += 5 * sizeof(float); break;
2672 case WINED3DFVF_XYZB3: size += 6 * sizeof(float); break;
2673 case WINED3DFVF_XYZB4: size += 7 * sizeof(float); break;
2674 case WINED3DFVF_XYZB5: size += 8 * sizeof(float); break;
2675 default: ERR("Unexpected position mask\n");
2677 for (i = 0; i < numTextures; i++) {
2678 size += GET_TEXCOORD_SIZE_FROM_FVF(d3dvtVertexType, i) * sizeof(float);
2681 return size;
2684 /***********************************************************************
2685 * CalculateTexRect
2687 * Calculates the dimensions of the opengl texture used for blits.
2688 * Handled oversized opengl textures and updates the source rectangle
2689 * accordingly
2691 * Params:
2692 * This: Surface to operate on
2693 * Rect: Requested rectangle
2695 * Returns:
2696 * TRUE if the texture part can be loaded,
2697 * FALSE otherwise
2699 *********************************************************************/
2700 #define GLINFO_LOCATION This->resource.wineD3DDevice->adapter->gl_info
2702 BOOL CalculateTexRect(IWineD3DSurfaceImpl *This, RECT *Rect, float glTexCoord[4]) {
2703 int x1 = Rect->left, x2 = Rect->right;
2704 int y1 = Rect->top, y2 = Rect->bottom;
2705 GLint maxSize = GL_LIMITS(texture_size);
2707 TRACE("(%p)->(%d,%d)-(%d,%d)\n", This,
2708 Rect->left, Rect->top, Rect->right, Rect->bottom);
2710 /* The sizes might be reversed */
2711 if(Rect->left > Rect->right) {
2712 x1 = Rect->right;
2713 x2 = Rect->left;
2715 if(Rect->top > Rect->bottom) {
2716 y1 = Rect->bottom;
2717 y2 = Rect->top;
2720 /* No oversized texture? This is easy */
2721 if(!(This->Flags & SFLAG_OVERSIZE)) {
2722 /* Which rect from the texture do I need? */
2723 glTexCoord[0] = (float) Rect->left / (float) This->pow2Width;
2724 glTexCoord[2] = (float) Rect->top / (float) This->pow2Height;
2725 glTexCoord[1] = (float) Rect->right / (float) This->pow2Width;
2726 glTexCoord[3] = (float) Rect->bottom / (float) This->pow2Height;
2728 return TRUE;
2729 } else {
2730 /* Check if we can succeed at all */
2731 if( (x2 - x1) > maxSize ||
2732 (y2 - y1) > maxSize ) {
2733 TRACE("Requested rectangle is too large for gl\n");
2734 return FALSE;
2737 /* A part of the texture has to be picked. First, check if
2738 * some texture part is loaded already, if yes try to re-use it.
2739 * If the texture is dirty, or the part can't be used,
2740 * re-position the part to load
2742 if(This->Flags & SFLAG_INTEXTURE) {
2743 if(This->glRect.left <= x1 && This->glRect.right >= x2 &&
2744 This->glRect.top <= y1 && This->glRect.bottom >= x2 ) {
2745 /* Ok, the rectangle is ok, re-use it */
2746 TRACE("Using existing gl Texture\n");
2747 } else {
2748 /* Rectangle is not ok, dirtify the texture to reload it */
2749 TRACE("Dirtifying texture to force reload\n");
2750 This->Flags &= ~SFLAG_INTEXTURE;
2754 /* Now if we are dirty(no else if!) */
2755 if(!(This->Flags & SFLAG_INTEXTURE)) {
2756 /* Set the new rectangle. Use the following strategy:
2757 * 1) Use as big textures as possible.
2758 * 2) Place the texture part in the way that the requested
2759 * part is in the middle of the texture(well, almost)
2760 * 3) If the texture is moved over the edges of the
2761 * surface, replace it nicely
2762 * 4) If the coord is not limiting the texture size,
2763 * use the whole size
2765 if((This->pow2Width) > maxSize) {
2766 This->glRect.left = x1 - maxSize / 2;
2767 if(This->glRect.left < 0) {
2768 This->glRect.left = 0;
2770 This->glRect.right = This->glRect.left + maxSize;
2771 if(This->glRect.right > This->currentDesc.Width) {
2772 This->glRect.right = This->currentDesc.Width;
2773 This->glRect.left = This->glRect.right - maxSize;
2775 } else {
2776 This->glRect.left = 0;
2777 This->glRect.right = This->pow2Width;
2780 if(This->pow2Height > maxSize) {
2781 This->glRect.top = x1 - GL_LIMITS(texture_size) / 2;
2782 if(This->glRect.top < 0) This->glRect.top = 0;
2783 This->glRect.bottom = This->glRect.left + maxSize;
2784 if(This->glRect.bottom > This->currentDesc.Height) {
2785 This->glRect.bottom = This->currentDesc.Height;
2786 This->glRect.top = This->glRect.bottom - maxSize;
2788 } else {
2789 This->glRect.top = 0;
2790 This->glRect.bottom = This->pow2Height;
2792 TRACE("(%p): Using rect (%d,%d)-(%d,%d)\n", This,
2793 This->glRect.left, This->glRect.top, This->glRect.right, This->glRect.bottom);
2796 /* Re-calculate the rect to draw */
2797 Rect->left -= This->glRect.left;
2798 Rect->right -= This->glRect.left;
2799 Rect->top -= This->glRect.top;
2800 Rect->bottom -= This->glRect.top;
2802 /* Get the gl coordinates. The gl rectangle is a power of 2, eigher the max size,
2803 * or the pow2Width / pow2Height of the surface
2805 glTexCoord[0] = (float) Rect->left / (float) (This->glRect.right - This->glRect.left);
2806 glTexCoord[2] = (float) Rect->top / (float) (This->glRect.bottom - This->glRect.top);
2807 glTexCoord[1] = (float) Rect->right / (float) (This->glRect.right - This->glRect.left);
2808 glTexCoord[3] = (float) Rect->bottom / (float) (This->glRect.bottom - This->glRect.top);
2810 return TRUE;
2812 #undef GLINFO_LOCATION
2814 /* Hash table functions */
2816 hash_table_t *hash_table_create(hash_function_t *hash_function, compare_function_t *compare_function)
2818 hash_table_t *table;
2819 unsigned int initial_size = 8;
2821 table = HeapAlloc(GetProcessHeap(), 0, sizeof(hash_table_t) + (initial_size * sizeof(struct list)));
2822 if (!table)
2824 ERR("Failed to allocate table, returning NULL.\n");
2825 return NULL;
2828 table->hash_function = hash_function;
2829 table->compare_function = compare_function;
2831 table->grow_size = initial_size - (initial_size >> 2);
2832 table->shrink_size = 0;
2834 table->buckets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, initial_size * sizeof(struct list));
2835 if (!table->buckets)
2837 ERR("Failed to allocate table buckets, returning NULL.\n");
2838 HeapFree(GetProcessHeap(), 0, table);
2839 return NULL;
2841 table->bucket_count = initial_size;
2843 table->entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, table->grow_size * sizeof(hash_table_entry_t));
2844 if (!table->entries)
2846 ERR("Failed to allocate table entries, returning NULL.\n");
2847 HeapFree(GetProcessHeap(), 0, table->buckets);
2848 HeapFree(GetProcessHeap(), 0, table);
2849 return NULL;
2851 table->entry_count = 0;
2853 list_init(&table->free_entries);
2854 table->count = 0;
2856 return table;
2859 void hash_table_destroy(hash_table_t *table)
2861 unsigned int i = 0;
2863 for (i = 0; i < table->entry_count; ++i)
2865 HeapFree(GetProcessHeap(), 0, table->entries[i].key);
2868 HeapFree(GetProcessHeap(), 0, table->entries);
2869 HeapFree(GetProcessHeap(), 0, table->buckets);
2870 HeapFree(GetProcessHeap(), 0, table);
2873 static inline hash_table_entry_t *hash_table_get_by_idx(hash_table_t *table, void *key, unsigned int idx)
2875 hash_table_entry_t *entry;
2877 if (table->buckets[idx].next)
2878 LIST_FOR_EACH_ENTRY(entry, &(table->buckets[idx]), hash_table_entry_t, entry)
2879 if (table->compare_function(entry->key, key)) return entry;
2881 return NULL;
2884 static BOOL hash_table_resize(hash_table_t *table, unsigned int new_bucket_count)
2886 unsigned int new_entry_count = 0;
2887 hash_table_entry_t *new_entries;
2888 struct list *new_buckets;
2889 unsigned int grow_size = new_bucket_count - (new_bucket_count >> 2);
2890 unsigned int i;
2892 new_buckets = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, new_bucket_count * sizeof(struct list));
2893 if (!new_buckets)
2895 ERR("Failed to allocate new buckets, returning FALSE.\n");
2896 return FALSE;
2899 new_entries = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, grow_size * sizeof(hash_table_entry_t));
2900 if (!new_entries)
2902 ERR("Failed to allocate new entries, returning FALSE.\n");
2903 HeapFree(GetProcessHeap(), 0, new_buckets);
2904 return FALSE;
2907 for (i = 0; i < table->bucket_count; ++i)
2909 if (table->buckets[i].next)
2911 hash_table_entry_t *entry, *entry2;
2913 LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, &table->buckets[i], hash_table_entry_t, entry)
2915 int j;
2916 hash_table_entry_t *new_entry = new_entries + (new_entry_count++);
2917 *new_entry = *entry;
2919 j = new_entry->hash & (new_bucket_count - 1);
2921 if (!new_buckets[j].next) list_init(&new_buckets[j]);
2922 list_add_head(&new_buckets[j], &new_entry->entry);
2927 HeapFree(GetProcessHeap(), 0, table->buckets);
2928 table->buckets = new_buckets;
2930 HeapFree(GetProcessHeap(), 0, table->entries);
2931 table->entries = new_entries;
2933 table->entry_count = new_entry_count;
2934 list_init(&table->free_entries);
2936 table->bucket_count = new_bucket_count;
2937 table->grow_size = grow_size;
2938 table->shrink_size = new_bucket_count > 8 ? new_bucket_count >> 2 : 0;
2940 return TRUE;
2943 void hash_table_put(hash_table_t *table, void *key, void *value)
2945 unsigned int idx;
2946 unsigned int hash;
2947 hash_table_entry_t *entry;
2949 hash = table->hash_function(key);
2950 idx = hash & (table->bucket_count - 1);
2951 entry = hash_table_get_by_idx(table, key, idx);
2953 if (entry)
2955 HeapFree(GetProcessHeap(), 0, key);
2956 entry->value = value;
2958 if (!value)
2960 HeapFree(GetProcessHeap(), 0, entry->key);
2961 entry->key = NULL;
2963 /* Remove the entry */
2964 list_remove(&entry->entry);
2965 list_add_head(&table->free_entries, &entry->entry);
2967 --table->count;
2969 /* Shrink if necessary */
2970 if (table->count < table->shrink_size) {
2971 if (!hash_table_resize(table, table->bucket_count >> 1))
2973 ERR("Failed to shrink the table...\n");
2978 return;
2981 if (!value) return;
2983 /* Grow if necessary */
2984 if (table->count >= table->grow_size)
2986 if (!hash_table_resize(table, table->bucket_count << 1))
2988 ERR("Failed to grow the table, returning.\n");
2989 return;
2992 idx = hash & (table->bucket_count - 1);
2995 /* Find an entry to insert */
2996 if (!list_empty(&table->free_entries))
2998 struct list *elem = list_head(&table->free_entries);
3000 list_remove(elem);
3001 entry = LIST_ENTRY(elem, hash_table_entry_t, entry);
3002 } else {
3003 entry = table->entries + (table->entry_count++);
3006 /* Insert the entry */
3007 entry->key = key;
3008 entry->value = value;
3009 entry->hash = hash;
3010 if (!table->buckets[idx].next) list_init(&table->buckets[idx]);
3011 list_add_head(&table->buckets[idx], &entry->entry);
3013 ++table->count;
3016 void hash_table_remove(hash_table_t *table, void *key)
3018 hash_table_put(table, key, NULL);
3021 void *hash_table_get(hash_table_t *table, void *key)
3023 unsigned int idx;
3024 hash_table_entry_t *entry;
3026 idx = table->hash_function(key) & (table->bucket_count - 1);
3027 entry = hash_table_get_by_idx(table, key, idx);
3029 return entry ? entry->value : NULL;