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