wined3d: Add UnregisterClass() on DLL_PROCESS_DETACH.
[wine] / dlls / wined3d / state.c
1 /*
2  * Direct3D state management
3  *
4  * Copyright 2002 Lionel Ulmer
5  * Copyright 2002-2005 Jason Edmeades
6  * Copyright 2003-2004 Raphael Junqueira
7  * Copyright 2004 Christian Costa
8  * Copyright 2005 Oliver Stieber
9  * Copyright 2006 Henri Verbeet
10  * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
11  *
12  * This library is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU Lesser General Public
14  * License as published by the Free Software Foundation; either
15  * version 2.1 of the License, or (at your option) any later version.
16  *
17  * This library is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25  */
26
27 #include "config.h"
28 #include <stdio.h>
29 #ifdef HAVE_FLOAT_H
30 # include <float.h>
31 #endif
32 #include "wined3d_private.h"
33
34 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
35 WINE_DECLARE_DEBUG_CHANNEL(d3d_shader);
36
37 #define GLINFO_LOCATION stateblock->wineD3DDevice->adapter->gl_info
38
39 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context);
40
41 static void state_nogl(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
42     /* Used for states which are not mapped to a gl state as-is, but used somehow different,
43      * e.g as a parameter for drawing, or which are unimplemented in windows d3d
44      */
45     if(STATE_IS_RENDER(state)) {
46         WINED3DRENDERSTATETYPE RenderState = state - STATE_RENDER(0);
47         TRACE("(%s,%d) no direct mapping to gl\n", debug_d3drenderstate(RenderState), stateblock->renderState[RenderState]);
48     } else {
49         /* Shouldn't have an unknown type here */
50         FIXME("%d no direct mapping to gl of state with unknown type\n", state);
51     }
52 }
53
54 static void state_undefined(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
55     /* Print a WARN, this allows the stateblock code to loop over all states to generate a display
56      * list without causing confusing terminal output. Deliberately no special debug name here
57      * because its undefined.
58      */
59     WARN("undefined state %d\n", state);
60 }
61
62 static void state_fillmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
63     WINED3DFILLMODE Value = stateblock->renderState[WINED3DRS_FILLMODE];
64
65     switch(Value) {
66         case WINED3DFILL_POINT:
67             glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
68             checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
69             break;
70         case WINED3DFILL_WIREFRAME:
71             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
72             checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
73             break;
74         case WINED3DFILL_SOLID:
75             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
76             checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
77             break;
78         default:
79             FIXME("Unrecognized WINED3DRS_FILLMODE value %d\n", Value);
80     }
81 }
82
83 static void state_lighting(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
84     /* Lighting is not enabled if transformed vertices are drawn
85      * but lighting does not affect the stream sources, so it is not grouped for performance reasons.
86      * This state reads the decoded vertex declaration, so if it is dirty don't do anything. The
87      * vertex declaration applying function calls this function for updating
88      */
89
90     if(isStateDirty(context, STATE_VDECL)) {
91         return;
92     }
93
94     if (stateblock->renderState[WINED3DRS_LIGHTING]
95             && !stateblock->wineD3DDevice->strided_streams.position_transformed)
96     {
97         glEnable(GL_LIGHTING);
98         checkGLcall("glEnable GL_LIGHTING");
99     } else {
100         glDisable(GL_LIGHTING);
101         checkGLcall("glDisable GL_LIGHTING");
102     }
103 }
104
105 static void state_zenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
106     /* No z test without depth stencil buffers */
107     if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
108         TRACE("No Z buffer - disabling depth test\n");
109         glDisable(GL_DEPTH_TEST); /* This also disables z writing in gl */
110         checkGLcall("glDisable GL_DEPTH_TEST");
111         return;
112     }
113
114     switch ((WINED3DZBUFFERTYPE) stateblock->renderState[WINED3DRS_ZENABLE]) {
115         case WINED3DZB_FALSE:
116             glDisable(GL_DEPTH_TEST);
117             checkGLcall("glDisable GL_DEPTH_TEST");
118             break;
119         case WINED3DZB_TRUE:
120             glEnable(GL_DEPTH_TEST);
121             checkGLcall("glEnable GL_DEPTH_TEST");
122             break;
123         case WINED3DZB_USEW:
124             glEnable(GL_DEPTH_TEST);
125             checkGLcall("glEnable GL_DEPTH_TEST");
126             FIXME("W buffer is not well handled\n");
127             break;
128         default:
129             FIXME("Unrecognized D3DZBUFFERTYPE value %d\n", stateblock->renderState[WINED3DRS_ZENABLE]);
130     }
131 }
132
133 static void state_cullmode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
134     /* glFrontFace() is set in context.c at context init and on an offscreen / onscreen rendering
135      * switch
136      */
137     switch ((WINED3DCULL) stateblock->renderState[WINED3DRS_CULLMODE]) {
138         case WINED3DCULL_NONE:
139             glDisable(GL_CULL_FACE);
140             checkGLcall("glDisable GL_CULL_FACE");
141             break;
142         case WINED3DCULL_CW:
143             glEnable(GL_CULL_FACE);
144             checkGLcall("glEnable GL_CULL_FACE");
145             glCullFace(GL_FRONT);
146             checkGLcall("glCullFace(GL_FRONT)");
147             break;
148         case WINED3DCULL_CCW:
149             glEnable(GL_CULL_FACE);
150             checkGLcall("glEnable GL_CULL_FACE");
151             glCullFace(GL_BACK);
152             checkGLcall("glCullFace(GL_BACK)");
153             break;
154         default:
155             FIXME("Unrecognized/Unhandled WINED3DCULL value %d\n", stateblock->renderState[WINED3DRS_CULLMODE]);
156     }
157 }
158
159 static void state_shademode(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
160     switch ((WINED3DSHADEMODE) stateblock->renderState[WINED3DRS_SHADEMODE]) {
161         case WINED3DSHADE_FLAT:
162             glShadeModel(GL_FLAT);
163             checkGLcall("glShadeModel(GL_FLAT)");
164             break;
165         case WINED3DSHADE_GOURAUD:
166             glShadeModel(GL_SMOOTH);
167             checkGLcall("glShadeModel(GL_SMOOTH)");
168             break;
169         case WINED3DSHADE_PHONG:
170             FIXME("WINED3DSHADE_PHONG isn't supported\n");
171             break;
172         default:
173             FIXME("Unrecognized/Unhandled WINED3DSHADEMODE value %d\n", stateblock->renderState[WINED3DRS_SHADEMODE]);
174     }
175 }
176
177 static void state_ditherenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
178     if (stateblock->renderState[WINED3DRS_DITHERENABLE]) {
179         glEnable(GL_DITHER);
180         checkGLcall("glEnable GL_DITHER");
181     } else {
182         glDisable(GL_DITHER);
183         checkGLcall("glDisable GL_DITHER");
184     }
185 }
186
187 static void state_zwritenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
188     /* TODO: Test if in d3d z writing is enabled even if ZENABLE is off. If yes,
189      * this has to be merged with ZENABLE and ZFUNC
190      */
191     if (stateblock->renderState[WINED3DRS_ZWRITEENABLE]) {
192         glDepthMask(1);
193         checkGLcall("glDepthMask(1)");
194     } else {
195         glDepthMask(0);
196         checkGLcall("glDepthMask(0)");
197     }
198 }
199
200 static void state_zfunc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
201     int glParm = CompareFunc(stateblock->renderState[WINED3DRS_ZFUNC]);
202
203     if(glParm) {
204         if(glParm == GL_EQUAL || glParm == GL_NOTEQUAL) {
205             static BOOL once = FALSE;
206             /* There are a few issues with this: First, our inability to
207              * select a proper Z depth, most of the time we're stuck with
208              * D24S8, even if the app selects D32 or D16. There seem to be
209              * some other precision problems which have to be debugged to
210              * make NOTEQUAL and EQUAL work properly
211              */
212             if(!once) {
213                 once = TRUE;
214                 FIXME("D3DCMP_NOTEQUAL and D3DCMP_EQUAL do not work correctly yet\n");
215             }
216         }
217
218         glDepthFunc(glParm);
219         checkGLcall("glDepthFunc");
220     }
221 }
222
223 static void state_ambient(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
224     float col[4];
225     D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_AMBIENT], col);
226
227     TRACE("Setting ambient to (%f,%f,%f,%f)\n", col[0], col[1], col[2], col[3]);
228     glLightModelfv(GL_LIGHT_MODEL_AMBIENT, col);
229     checkGLcall("glLightModel for MODEL_AMBIENT");
230 }
231
232 static void state_blend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
233     int srcBlend = GL_ZERO;
234     int dstBlend = GL_ZERO;
235     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
236
237     /* GL_LINE_SMOOTH needs GL_BLEND to work, according to the red book, and special blending params */
238     if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE]      ||
239         stateblock->renderState[WINED3DRS_EDGEANTIALIAS]         ||
240         stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
241
242         /* Disable blending in all cases even without pixelshaders. With blending on we could face a big performance penalty.
243          * The d3d9 visual test confirms the behavior. */
244         if (!(target->resource.format_desc->Flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
245         {
246             glDisable(GL_BLEND);
247             checkGLcall("glDisable GL_BLEND");
248             return;
249         } else {
250             glEnable(GL_BLEND);
251             checkGLcall("glEnable GL_BLEND");
252         }
253     } else {
254         glDisable(GL_BLEND);
255         checkGLcall("glDisable GL_BLEND");
256         /* Nothing more to do - get out */
257         return;
258     };
259
260     switch (stateblock->renderState[WINED3DRS_DESTBLEND]) {
261         case WINED3DBLEND_ZERO               : dstBlend = GL_ZERO;  break;
262         case WINED3DBLEND_ONE                : dstBlend = GL_ONE;  break;
263         case WINED3DBLEND_SRCCOLOR           : dstBlend = GL_SRC_COLOR;  break;
264         case WINED3DBLEND_INVSRCCOLOR        : dstBlend = GL_ONE_MINUS_SRC_COLOR;  break;
265         case WINED3DBLEND_SRCALPHA           : dstBlend = GL_SRC_ALPHA;  break;
266         case WINED3DBLEND_INVSRCALPHA        : dstBlend = GL_ONE_MINUS_SRC_ALPHA;  break;
267         case WINED3DBLEND_DESTCOLOR          : dstBlend = GL_DST_COLOR;  break;
268         case WINED3DBLEND_INVDESTCOLOR       : dstBlend = GL_ONE_MINUS_DST_COLOR;  break;
269
270         /* To compensate the lack of format switching with backbuffer offscreen rendering,
271          * and with onscreen rendering, we modify the alpha test parameters for (INV)DESTALPHA
272          * if the render target doesn't support alpha blending. A nonexistent alpha channel
273          * returns 1.0, so D3DBLEND_DESTALPHA is GL_ONE, and D3DBLEND_INVDESTALPHA is GL_ZERO
274          */
275         case WINED3DBLEND_DESTALPHA          :
276             dstBlend = target->resource.format_desc->alpha_mask ? GL_DST_ALPHA : GL_ONE;
277             break;
278         case WINED3DBLEND_INVDESTALPHA       :
279             dstBlend = target->resource.format_desc->alpha_mask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
280             break;
281
282         case WINED3DBLEND_SRCALPHASAT        :
283             dstBlend = GL_SRC_ALPHA_SATURATE;
284             WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
285             break;
286
287         /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
288          * values which are still valid up to d3d9. They should not occur as dest blend values
289          */
290         case WINED3DBLEND_BOTHSRCALPHA       : dstBlend = GL_SRC_ALPHA;
291             srcBlend = GL_SRC_ALPHA;
292             FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
293             break;
294
295         case WINED3DBLEND_BOTHINVSRCALPHA    : dstBlend = GL_ONE_MINUS_SRC_ALPHA;
296             srcBlend = GL_ONE_MINUS_SRC_ALPHA;
297             FIXME("WINED3DRS_DESTBLEND = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
298             break;
299
300         case WINED3DBLEND_BLENDFACTOR        : dstBlend = GL_CONSTANT_COLOR;   break;
301         case WINED3DBLEND_INVBLENDFACTOR     : dstBlend = GL_ONE_MINUS_CONSTANT_COLOR;  break;
302         default:
303             FIXME("Unrecognized dst blend value %d\n", stateblock->renderState[WINED3DRS_DESTBLEND]);
304     }
305
306     switch (stateblock->renderState[WINED3DRS_SRCBLEND]) {
307         case WINED3DBLEND_ZERO               : srcBlend = GL_ZERO;  break;
308         case WINED3DBLEND_ONE                : srcBlend = GL_ONE;  break;
309         case WINED3DBLEND_SRCCOLOR           : srcBlend = GL_SRC_COLOR;  break;
310         case WINED3DBLEND_INVSRCCOLOR        : srcBlend = GL_ONE_MINUS_SRC_COLOR;  break;
311         case WINED3DBLEND_SRCALPHA           : srcBlend = GL_SRC_ALPHA;  break;
312         case WINED3DBLEND_INVSRCALPHA        : srcBlend = GL_ONE_MINUS_SRC_ALPHA;  break;
313         case WINED3DBLEND_DESTCOLOR          : srcBlend = GL_DST_COLOR;  break;
314         case WINED3DBLEND_INVDESTCOLOR       : srcBlend = GL_ONE_MINUS_DST_COLOR;  break;
315         case WINED3DBLEND_SRCALPHASAT        : srcBlend = GL_SRC_ALPHA_SATURATE;  break;
316
317         case WINED3DBLEND_DESTALPHA          :
318             srcBlend = target->resource.format_desc->alpha_mask ? GL_DST_ALPHA : GL_ONE;
319             break;
320         case WINED3DBLEND_INVDESTALPHA       :
321             srcBlend = target->resource.format_desc->alpha_mask ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
322             break;
323
324         case WINED3DBLEND_BOTHSRCALPHA       : srcBlend = GL_SRC_ALPHA;
325             dstBlend = GL_ONE_MINUS_SRC_ALPHA;
326             break;
327
328         case WINED3DBLEND_BOTHINVSRCALPHA    : srcBlend = GL_ONE_MINUS_SRC_ALPHA;
329             dstBlend = GL_SRC_ALPHA;
330             break;
331
332         case WINED3DBLEND_BLENDFACTOR        : srcBlend = GL_CONSTANT_COLOR;   break;
333         case WINED3DBLEND_INVBLENDFACTOR     : srcBlend = GL_ONE_MINUS_CONSTANT_COLOR;  break;
334         default:
335             FIXME("Unrecognized src blend value %d\n", stateblock->renderState[WINED3DRS_SRCBLEND]);
336     }
337
338     if(stateblock->renderState[WINED3DRS_EDGEANTIALIAS] ||
339        stateblock->renderState[WINED3DRS_ANTIALIASEDLINEENABLE]) {
340         glEnable(GL_LINE_SMOOTH);
341         checkGLcall("glEnable(GL_LINE_SMOOTH)");
342         if(srcBlend != GL_SRC_ALPHA) {
343             WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected src blending param\n");
344         }
345         if(dstBlend != GL_ONE_MINUS_SRC_ALPHA && dstBlend != GL_ONE) {
346             WARN("WINED3DRS_EDGEANTIALIAS enabled, but unexpected dst blending param\n");
347         }
348     } else {
349         glDisable(GL_LINE_SMOOTH);
350         checkGLcall("glDisable(GL_LINE_SMOOTH)");
351     }
352
353     /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
354     if(!isStateDirty(context, STATE_RENDER(WINED3DRS_BLENDOP))) {
355         state_blendop(STATE_RENDER(WINED3DRS_BLENDOPALPHA), stateblock, context);
356     }
357
358     if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
359         int srcBlendAlpha = GL_ZERO;
360         int dstBlendAlpha = GL_ZERO;
361
362         /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
363         if(!GL_SUPPORT(EXT_BLEND_FUNC_SEPARATE)) {
364             WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparateEXT\n");
365             return;
366         }
367
368         switch (stateblock->renderState[WINED3DRS_DESTBLENDALPHA]) {
369             case WINED3DBLEND_ZERO               : dstBlendAlpha = GL_ZERO;  break;
370             case WINED3DBLEND_ONE                : dstBlendAlpha = GL_ONE;  break;
371             case WINED3DBLEND_SRCCOLOR           : dstBlendAlpha = GL_SRC_COLOR;  break;
372             case WINED3DBLEND_INVSRCCOLOR        : dstBlendAlpha = GL_ONE_MINUS_SRC_COLOR;  break;
373             case WINED3DBLEND_SRCALPHA           : dstBlendAlpha = GL_SRC_ALPHA;  break;
374             case WINED3DBLEND_INVSRCALPHA        : dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;  break;
375             case WINED3DBLEND_DESTCOLOR          : dstBlendAlpha = GL_DST_COLOR;  break;
376             case WINED3DBLEND_INVDESTCOLOR       : dstBlendAlpha = GL_ONE_MINUS_DST_COLOR;  break;
377             case WINED3DBLEND_DESTALPHA          : dstBlendAlpha = GL_DST_ALPHA;  break;
378             case WINED3DBLEND_INVDESTALPHA       : dstBlendAlpha = GL_DST_ALPHA;  break;
379             case WINED3DBLEND_SRCALPHASAT        :
380                 dstBlend = GL_SRC_ALPHA_SATURATE;
381                 WARN("Application uses SRCALPHASAT as dest blend factor, expect problems\n");
382                 break;
383             /* WINED3DBLEND_BOTHSRCALPHA and WINED3DBLEND_BOTHINVSRCALPHA are legacy source blending
384             * values which are still valid up to d3d9. They should not occur as dest blend values
385             */
386             case WINED3DBLEND_BOTHSRCALPHA       :
387                 dstBlendAlpha = GL_SRC_ALPHA;
388                 srcBlendAlpha = GL_SRC_ALPHA;
389                 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHSRCALPHA, what to do?\n");
390                 break;
391             case WINED3DBLEND_BOTHINVSRCALPHA    :
392                 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
393                 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
394                 FIXME("WINED3DRS_DESTBLENDALPHA = WINED3DBLEND_BOTHINVSRCALPHA, what to do?\n");
395                 break;
396             case WINED3DBLEND_BLENDFACTOR        : dstBlendAlpha = GL_CONSTANT_COLOR;   break;
397             case WINED3DBLEND_INVBLENDFACTOR     : dstBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR;  break;
398             default:
399                 FIXME("Unrecognized dst blend alpha value %d\n", stateblock->renderState[WINED3DRS_DESTBLENDALPHA]);
400         }
401
402         switch (stateblock->renderState[WINED3DRS_SRCBLENDALPHA]) {
403             case WINED3DBLEND_ZERO               : srcBlendAlpha = GL_ZERO;  break;
404             case WINED3DBLEND_ONE                : srcBlendAlpha = GL_ONE;  break;
405             case WINED3DBLEND_SRCCOLOR           : srcBlendAlpha = GL_SRC_COLOR;  break;
406             case WINED3DBLEND_INVSRCCOLOR        : srcBlendAlpha = GL_ONE_MINUS_SRC_COLOR;  break;
407             case WINED3DBLEND_SRCALPHA           : srcBlendAlpha = GL_SRC_ALPHA;  break;
408             case WINED3DBLEND_INVSRCALPHA        : srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;  break;
409             case WINED3DBLEND_DESTCOLOR          : srcBlendAlpha = GL_DST_COLOR;  break;
410             case WINED3DBLEND_INVDESTCOLOR       : srcBlendAlpha = GL_ONE_MINUS_DST_COLOR;  break;
411             case WINED3DBLEND_SRCALPHASAT        : srcBlendAlpha = GL_SRC_ALPHA_SATURATE;  break;
412             case WINED3DBLEND_DESTALPHA          : srcBlendAlpha = GL_DST_ALPHA;  break;
413             case WINED3DBLEND_INVDESTALPHA       : srcBlendAlpha = GL_DST_ALPHA;  break;
414             case WINED3DBLEND_BOTHSRCALPHA       :
415                 srcBlendAlpha = GL_SRC_ALPHA;
416                 dstBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
417                 break;
418             case WINED3DBLEND_BOTHINVSRCALPHA    :
419                 srcBlendAlpha = GL_ONE_MINUS_SRC_ALPHA;
420                 dstBlendAlpha = GL_SRC_ALPHA;
421                 break;
422             case WINED3DBLEND_BLENDFACTOR        : srcBlendAlpha = GL_CONSTANT_COLOR;   break;
423             case WINED3DBLEND_INVBLENDFACTOR     : srcBlendAlpha = GL_ONE_MINUS_CONSTANT_COLOR;  break;
424             default:
425                 FIXME("Unrecognized src blend alpha value %d\n", stateblock->renderState[WINED3DRS_SRCBLENDALPHA]);
426         }
427
428         GL_EXTCALL(glBlendFuncSeparateEXT(srcBlend, dstBlend, srcBlendAlpha, dstBlendAlpha));
429         checkGLcall("glBlendFuncSeparateEXT");
430     } else {
431         TRACE("glBlendFunc src=%x, dst=%x\n", srcBlend, dstBlend);
432         glBlendFunc(srcBlend, dstBlend);
433         checkGLcall("glBlendFunc");
434     }
435
436     /* colorkey fixup for stage 0 alphaop depends on WINED3DRS_ALPHABLENDENABLE state,
437         so it may need updating */
438     if (stateblock->renderState[WINED3DRS_COLORKEYENABLE]) {
439         const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
440         StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
441     }
442 }
443
444 static void state_blendfactor_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
445     WARN("Unsupported in local OpenGL implementation: glBlendColorEXT\n");
446 }
447
448 static void state_blendfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
449     float col[4];
450
451     TRACE("Setting BlendFactor to %d\n", stateblock->renderState[WINED3DRS_BLENDFACTOR]);
452     D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_BLENDFACTOR], col);
453     GL_EXTCALL(glBlendColorEXT (col[0],col[1],col[2],col[3]));
454     checkGLcall("glBlendColor");
455 }
456
457 static void state_alpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
458     int glParm = 0;
459     float ref;
460     BOOL enable_ckey = FALSE;
461
462     TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
463
464     /* Find out if the texture on the first stage has a ckey set
465      * The alpha state func reads the texture settings, even though alpha and texture are not grouped
466      * together. This is to avoid making a huge alpha+texture+texture stage+ckey block due to the hardly
467      * used WINED3DRS_COLORKEYENABLE state(which is d3d <= 3 only). The texture function will call alpha
468      * in case it finds some texture+colorkeyenable combination which needs extra care.
469      */
470     if (stateblock->textures[0])
471     {
472         UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
473
474         if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
475         {
476             IWineD3DSurfaceImpl *surf;
477
478             surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *)stateblock->textures[0])->surfaces[0];
479
480             if (surf->CKeyFlags & WINEDDSD_CKSRCBLT)
481             {
482                 /* The surface conversion does not do color keying conversion for surfaces that have an alpha
483                  * channel on their own. Likewise, the alpha test shouldn't be set up for color keying if the
484                  * surface has alpha bits */
485                 if (!surf->resource.format_desc->alpha_mask) enable_ckey = TRUE;
486             }
487         }
488     }
489
490     if(enable_ckey || context->last_was_ckey) {
491         const struct StateEntry *StateTable = stateblock->wineD3DDevice->StateTable;
492         StateTable[STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP)].apply(STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP), stateblock, context);
493     }
494     context->last_was_ckey = enable_ckey;
495
496     if (stateblock->renderState[WINED3DRS_ALPHATESTENABLE] ||
497         (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey)) {
498         glEnable(GL_ALPHA_TEST);
499         checkGLcall("glEnable GL_ALPHA_TEST");
500     } else {
501         glDisable(GL_ALPHA_TEST);
502         checkGLcall("glDisable GL_ALPHA_TEST");
503         /* Alpha test is disabled, don't bother setting the params - it will happen on the next
504          * enable call
505          */
506         return;
507     }
508
509     if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && enable_ckey) {
510         glParm = GL_NOTEQUAL;
511         ref = 0.0;
512     } else {
513         ref = ((float) stateblock->renderState[WINED3DRS_ALPHAREF]) / 255.0f;
514         glParm = CompareFunc(stateblock->renderState[WINED3DRS_ALPHAFUNC]);
515     }
516     if(glParm) {
517         glAlphaFunc(glParm, ref);
518         checkGLcall("glAlphaFunc");
519     }
520 }
521
522 static void state_clipping(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
523     DWORD enable  = 0xFFFFFFFF;
524     DWORD disable = 0x00000000;
525
526     if (use_vs(stateblock))
527     {
528         /* The spec says that opengl clipping planes are disabled when using shaders. Direct3D planes aren't,
529          * so that is an issue. The MacOS ATI driver keeps clipping planes activated with shaders in some
530          * conditions I got sick of tracking down. The shader state handler disables all clip planes because
531          * of that - don't do anything here and keep them disabled
532          */
533         if(stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
534             static BOOL warned = FALSE;
535             if(!warned) {
536                 FIXME("Clipping not supported with vertex shaders\n");
537                 warned = TRUE;
538             }
539         }
540         return;
541     }
542
543     /* TODO: Keep track of previously enabled clipplanes to avoid unnecessary resetting
544      * of already set values
545      */
546
547     /* If enabling / disabling all
548      * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
549      */
550     if (stateblock->renderState[WINED3DRS_CLIPPING]) {
551         enable  = stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
552         disable = ~stateblock->renderState[WINED3DRS_CLIPPLANEENABLE];
553         if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
554             glDisable(GL_DEPTH_CLAMP_NV);
555             checkGLcall("glDisable(GL_DEPTH_CLAMP_NV)");
556         }
557     } else {
558         disable = 0xffffffff;
559         enable  = 0x00;
560         if(GL_SUPPORT(NV_DEPTH_CLAMP)) {
561             glEnable(GL_DEPTH_CLAMP_NV);
562             checkGLcall("glEnable(GL_DEPTH_CLAMP_NV)");
563         }
564     }
565
566     if (enable & WINED3DCLIPPLANE0)  { glEnable(GL_CLIP_PLANE0);  checkGLcall("glEnable(clip plane 0)"); }
567     if (enable & WINED3DCLIPPLANE1)  { glEnable(GL_CLIP_PLANE1);  checkGLcall("glEnable(clip plane 1)"); }
568     if (enable & WINED3DCLIPPLANE2)  { glEnable(GL_CLIP_PLANE2);  checkGLcall("glEnable(clip plane 2)"); }
569     if (enable & WINED3DCLIPPLANE3)  { glEnable(GL_CLIP_PLANE3);  checkGLcall("glEnable(clip plane 3)"); }
570     if (enable & WINED3DCLIPPLANE4)  { glEnable(GL_CLIP_PLANE4);  checkGLcall("glEnable(clip plane 4)"); }
571     if (enable & WINED3DCLIPPLANE5)  { glEnable(GL_CLIP_PLANE5);  checkGLcall("glEnable(clip plane 5)"); }
572
573     if (disable & WINED3DCLIPPLANE0) { glDisable(GL_CLIP_PLANE0); checkGLcall("glDisable(clip plane 0)"); }
574     if (disable & WINED3DCLIPPLANE1) { glDisable(GL_CLIP_PLANE1); checkGLcall("glDisable(clip plane 1)"); }
575     if (disable & WINED3DCLIPPLANE2) { glDisable(GL_CLIP_PLANE2); checkGLcall("glDisable(clip plane 2)"); }
576     if (disable & WINED3DCLIPPLANE3) { glDisable(GL_CLIP_PLANE3); checkGLcall("glDisable(clip plane 3)"); }
577     if (disable & WINED3DCLIPPLANE4) { glDisable(GL_CLIP_PLANE4); checkGLcall("glDisable(clip plane 4)"); }
578     if (disable & WINED3DCLIPPLANE5) { glDisable(GL_CLIP_PLANE5); checkGLcall("glDisable(clip plane 5)"); }
579
580     /** update clipping status */
581     if (enable) {
582         stateblock->clip_status.ClipUnion = 0;
583         stateblock->clip_status.ClipIntersection = 0xFFFFFFFF;
584     } else {
585         stateblock->clip_status.ClipUnion = 0;
586         stateblock->clip_status.ClipIntersection = 0;
587     }
588 }
589
590 static void state_blendop_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
591     WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
592 }
593
594 static void state_blendop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
595     int blendEquation = GL_FUNC_ADD;
596     int blendEquationAlpha = GL_FUNC_ADD;
597
598     /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
599     if(stateblock->renderState[WINED3DRS_BLENDOPALPHA] && !GL_SUPPORT(EXT_BLEND_EQUATION_SEPARATE)) {
600         WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparateEXT\n");
601         return;
602     }
603
604     switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOP]) {
605         case WINED3DBLENDOP_ADD              : blendEquation = GL_FUNC_ADD;              break;
606         case WINED3DBLENDOP_SUBTRACT         : blendEquation = GL_FUNC_SUBTRACT;         break;
607         case WINED3DBLENDOP_REVSUBTRACT      : blendEquation = GL_FUNC_REVERSE_SUBTRACT; break;
608         case WINED3DBLENDOP_MIN              : blendEquation = GL_MIN;                   break;
609         case WINED3DBLENDOP_MAX              : blendEquation = GL_MAX;                   break;
610         default:
611             FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOP]);
612     }
613
614     switch ((WINED3DBLENDOP) stateblock->renderState[WINED3DRS_BLENDOPALPHA]) {
615         case WINED3DBLENDOP_ADD              : blendEquationAlpha = GL_FUNC_ADD;              break;
616         case WINED3DBLENDOP_SUBTRACT         : blendEquationAlpha = GL_FUNC_SUBTRACT;         break;
617         case WINED3DBLENDOP_REVSUBTRACT      : blendEquationAlpha = GL_FUNC_REVERSE_SUBTRACT; break;
618         case WINED3DBLENDOP_MIN              : blendEquationAlpha = GL_MIN;                   break;
619         case WINED3DBLENDOP_MAX              : blendEquationAlpha = GL_MAX;                   break;
620         default:
621             FIXME("Unrecognized/Unhandled D3DBLENDOP value %d\n", stateblock->renderState[WINED3DRS_BLENDOPALPHA]);
622     }
623
624     if(stateblock->renderState[WINED3DRS_SEPARATEALPHABLENDENABLE]) {
625         TRACE("glBlendEquationSeparateEXT(%x, %x)\n", blendEquation, blendEquationAlpha);
626         GL_EXTCALL(glBlendEquationSeparateEXT(blendEquation, blendEquationAlpha));
627         checkGLcall("glBlendEquationSeparateEXT");
628     } else {
629         TRACE("glBlendEquation(%x)\n", blendEquation);
630         GL_EXTCALL(glBlendEquationEXT(blendEquation));
631         checkGLcall("glBlendEquation");
632     }
633 }
634
635 static void
636 state_specularenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
637     /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
638      * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
639      * specular color. This is wrong:
640      * Separate specular color means the specular colour is maintained separately, whereas
641      * single color means it is merged in. However in both cases they are being used to
642      * some extent.
643      * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
644      * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
645      * running 1.4 yet!
646      *
647      *
648      * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
649      * Instead, we need to setup the FinalCombiner properly.
650      *
651      * The default setup for the FinalCombiner is:
652      *
653      * <variable>       <input>                             <mapping>               <usage>
654      * GL_VARIABLE_A_NV GL_FOG,                             GL_UNSIGNED_IDENTITY_NV GL_ALPHA
655      * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV   GL_UNSIGNED_IDENTITY_NV GL_RGB
656      * GL_VARIABLE_C_NV GL_FOG                              GL_UNSIGNED_IDENTITY_NV GL_RGB
657      * GL_VARIABLE_D_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
658      * GL_VARIABLE_E_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
659      * GL_VARIABLE_F_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
660      * GL_VARIABLE_G_NV GL_SPARE0_NV                        GL_UNSIGNED_IDENTITY_NV GL_ALPHA
661      *
662      * That's pretty much fine as it is, except for variable B, which needs to take
663      * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
664      * whether WINED3DRS_SPECULARENABLE is enabled or not.
665      */
666
667     TRACE("Setting specular enable state and materials\n");
668     if (stateblock->renderState[WINED3DRS_SPECULARENABLE]) {
669         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*) &stateblock->material.Specular);
670         checkGLcall("glMaterialfv");
671
672         if(stateblock->material.Power > GL_LIMITS(shininess)) {
673             /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
674              * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
675              * allows bigger values. If the extension is supported, GL_LIMITS(shininess) contains the
676              * value reported by the extension, otherwise 128. For values > GL_LIMITS(shininess) clamp
677              * them, it should be safe to do so without major visual distortions.
678              */
679             WARN("Material power = %f, limit %f\n", stateblock->material.Power, GL_LIMITS(shininess));
680             glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, GL_LIMITS(shininess));
681         } else {
682             glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, stateblock->material.Power);
683         }
684         checkGLcall("glMaterialf(GL_SHININESS)");
685
686         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
687             glEnable(GL_COLOR_SUM_EXT);
688         } else {
689             TRACE("Specular colors cannot be enabled in this version of opengl\n");
690         }
691         checkGLcall("glEnable(GL_COLOR_SUM)");
692
693         if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
694             GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
695             checkGLcall("glFinalCombinerInputNV()");
696         }
697     } else {
698         static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
699
700         /* for the case of enabled lighting: */
701         glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
702         checkGLcall("glMaterialfv");
703
704         /* for the case of disabled lighting: */
705         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
706             glDisable(GL_COLOR_SUM_EXT);
707         } else {
708             TRACE("Specular colors cannot be disabled in this version of opengl\n");
709         }
710         checkGLcall("glDisable(GL_COLOR_SUM)");
711
712         if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
713             GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
714             checkGLcall("glFinalCombinerInputNV()");
715         }
716     }
717
718     TRACE("(%p) : Diffuse (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Diffuse.r, stateblock->material.Diffuse.g,
719           stateblock->material.Diffuse.b, stateblock->material.Diffuse.a);
720     TRACE("(%p) : Ambient (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Ambient.r, stateblock->material.Ambient.g,
721           stateblock->material.Ambient.b, stateblock->material.Ambient.a);
722     TRACE("(%p) : Specular (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Specular.r, stateblock->material.Specular.g,
723           stateblock->material.Specular.b, stateblock->material.Specular.a);
724     TRACE("(%p) : Emissive (%f,%f,%f,%f)\n", stateblock->wineD3DDevice, stateblock->material.Emissive.r, stateblock->material.Emissive.g,
725           stateblock->material.Emissive.b, stateblock->material.Emissive.a);
726
727     glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*) &stateblock->material.Ambient);
728     checkGLcall("glMaterialfv(GL_AMBIENT)");
729     glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*) &stateblock->material.Diffuse);
730     checkGLcall("glMaterialfv(GL_DIFFUSE)");
731     glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*) &stateblock->material.Emissive);
732     checkGLcall("glMaterialfv(GL_EMISSION)");
733 }
734
735 static void state_texfactor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
736     unsigned int i;
737
738     /* Note the texture color applies to all textures whereas
739      * GL_TEXTURE_ENV_COLOR applies to active only
740      */
741     float col[4];
742     D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_TEXTUREFACTOR], col);
743
744     /* And now the default texture color as well */
745     for (i = 0; i < GL_LIMITS(texture_stages); i++) {
746         /* Note the WINED3DRS value applies to all textures, but GL has one
747          * per texture, so apply it now ready to be used!
748          */
749         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + i));
750         checkGLcall("glActiveTextureARB");
751
752         glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &col[0]);
753         checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
754     }
755 }
756
757 static void
758 renderstate_stencil_twosided(IWineD3DStateBlockImpl *stateblock, GLint face, GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass ) {
759     glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
760     checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
761     GL_EXTCALL(glActiveStencilFaceEXT(face));
762     checkGLcall("glActiveStencilFaceEXT(...)");
763     glStencilFunc(func, ref, mask);
764     checkGLcall("glStencilFunc(...)");
765     glStencilOp(stencilFail, depthFail, stencilPass);
766     checkGLcall("glStencilOp(...)");
767 }
768
769 static void
770 state_stencil(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
771     DWORD onesided_enable = FALSE;
772     DWORD twosided_enable = FALSE;
773     GLint func = GL_ALWAYS;
774     GLint func_ccw = GL_ALWAYS;
775     GLint ref = 0;
776     GLuint mask = 0;
777     GLint stencilFail = GL_KEEP;
778     GLint depthFail = GL_KEEP;
779     GLint stencilPass = GL_KEEP;
780     GLint stencilFail_ccw = GL_KEEP;
781     GLint depthFail_ccw = GL_KEEP;
782     GLint stencilPass_ccw = GL_KEEP;
783
784     /* No stencil test without a stencil buffer */
785     if(stateblock->wineD3DDevice->stencilBufferTarget == NULL) {
786         glDisable(GL_STENCIL_TEST);
787         checkGLcall("glDisable GL_STENCIL_TEST");
788         return;
789     }
790
791     onesided_enable = stateblock->renderState[WINED3DRS_STENCILENABLE];
792     twosided_enable = stateblock->renderState[WINED3DRS_TWOSIDEDSTENCILMODE];
793     if( !( func = CompareFunc(stateblock->renderState[WINED3DRS_STENCILFUNC]) ) )
794         func = GL_ALWAYS;
795     if( !( func_ccw = CompareFunc(stateblock->renderState[WINED3DRS_CCW_STENCILFUNC]) ) )
796         func_ccw = GL_ALWAYS;
797     ref = stateblock->renderState[WINED3DRS_STENCILREF];
798     mask = stateblock->renderState[WINED3DRS_STENCILMASK];
799     stencilFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILFAIL]);
800     depthFail = StencilOp(stateblock->renderState[WINED3DRS_STENCILZFAIL]);
801     stencilPass = StencilOp(stateblock->renderState[WINED3DRS_STENCILPASS]);
802     stencilFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILFAIL]);
803     depthFail_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILZFAIL]);
804     stencilPass_ccw = StencilOp(stateblock->renderState[WINED3DRS_CCW_STENCILPASS]);
805
806     TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
807           "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
808           "GL_BACK: func: %x, fail %x, zfail %x, zpass %x )\n",
809     onesided_enable, twosided_enable, ref, mask,
810     func, stencilFail, depthFail, stencilPass,
811     func_ccw, stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
812
813     if (twosided_enable && onesided_enable) {
814         glEnable(GL_STENCIL_TEST);
815         checkGLcall("glEnable GL_STENCIL_TEST");
816
817         if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
818             /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
819              * which has an effect on the code below too. If we apply the front face
820              * afterwards, we are sure that the active stencil face is set to front,
821              * and other stencil functions which do not use two sided stencil do not have
822              * to set it back
823              */
824             renderstate_stencil_twosided(stateblock, GL_BACK, func_ccw, ref, mask,
825                                          stencilFail_ccw, depthFail_ccw, stencilPass_ccw);
826             renderstate_stencil_twosided(stateblock, GL_FRONT, func, ref, mask,
827                                          stencilFail, depthFail, stencilPass);
828         } else if(GL_SUPPORT(ATI_SEPARATE_STENCIL)) {
829             GL_EXTCALL(glStencilFuncSeparateATI(func, func_ccw, ref, mask));
830             checkGLcall("glStencilFuncSeparateATI(...)");
831             GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
832             checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
833             GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_ccw, depthFail_ccw, stencilPass_ccw));
834             checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
835         } else {
836             ERR("Separate (two sided) stencil not supported on this version of opengl. Caps weren't honored?\n");
837         }
838     } else if(onesided_enable) {
839         if(GL_SUPPORT(EXT_STENCIL_TWO_SIDE)) {
840             glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
841             checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
842         }
843
844         /* This code disables the ATI extension as well, since the standard stencil functions are equal
845          * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
846          */
847         glEnable(GL_STENCIL_TEST);
848         checkGLcall("glEnable GL_STENCIL_TEST");
849         glStencilFunc(func, ref, mask);
850         checkGLcall("glStencilFunc(...)");
851         glStencilOp(stencilFail, depthFail, stencilPass);
852         checkGLcall("glStencilOp(...)");
853     } else {
854         glDisable(GL_STENCIL_TEST);
855         checkGLcall("glDisable GL_STENCIL_TEST");
856     }
857 }
858
859 static void state_stencilwrite2s(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
860     DWORD mask;
861
862     if(stateblock->wineD3DDevice->stencilBufferTarget) {
863         mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
864     } else {
865         mask = 0;
866     }
867
868     GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
869     checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
870     glStencilMask(mask);
871     checkGLcall("glStencilMask");
872     GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
873     checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
874     glStencilMask(mask);
875 }
876
877 static void state_stencilwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
878     DWORD mask;
879
880     if(stateblock->wineD3DDevice->stencilBufferTarget) {
881         mask = stateblock->renderState[WINED3DRS_STENCILWRITEMASK];
882     } else {
883         mask = 0;
884     }
885
886     glStencilMask(mask);
887     checkGLcall("glStencilMask");
888 }
889
890 static void state_fog_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
891
892     TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
893
894     if (!stateblock->renderState[WINED3DRS_FOGENABLE]) return;
895
896     /* Table fog on: Never use fog coords, and use per-fragment fog */
897     if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE) {
898         glHint(GL_FOG_HINT, GL_NICEST);
899         if(context->fog_coord) {
900             glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
901             checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
902             context->fog_coord = FALSE;
903         }
904         return;
905     }
906
907     /* Otherwise use per-vertex fog in any case */
908     glHint(GL_FOG_HINT, GL_FASTEST);
909
910     if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
911         /* No fog at all, or transformed vertices: Use fog coord */
912         if(!context->fog_coord) {
913             glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
914             checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
915             context->fog_coord = TRUE;
916         }
917     } else {
918         /* Otherwise, use the fragment depth */
919         if(context->fog_coord) {
920             glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
921             checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
922             context->fog_coord = FALSE;
923         }
924     }
925 }
926
927 void state_fogstartend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
928     float fogstart, fogend;
929     union {
930         DWORD d;
931         float f;
932     } tmpvalue;
933
934     switch(context->fog_source) {
935         case FOGSOURCE_VS:
936             fogstart = 1.0;
937             fogend = 0.0;
938             break;
939
940         case FOGSOURCE_COORD:
941             fogstart = 255.0;
942             fogend = 0.0;
943             break;
944
945         case FOGSOURCE_FFP:
946             tmpvalue.d = stateblock->renderState[WINED3DRS_FOGSTART];
947             fogstart = tmpvalue.f;
948             tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
949             fogend = tmpvalue.f;
950             /* In GL, fogstart == fogend disables fog, in D3D everything's fogged.*/
951             if(fogstart == fogend) {
952                 fogstart = -1.0 / 0.0;
953                 fogend = 0.0;
954             }
955             break;
956
957         default:
958             /* This should not happen.context->fog_source is set in wined3d, not the app.
959              * Still this is needed to make the compiler happy
960              */
961             ERR("Unexpected fog coordinate source\n");
962             fogstart = 0.0;
963             fogend = 0.0;
964     }
965
966     glFogf(GL_FOG_START, fogstart);
967     checkGLcall("glFogf(GL_FOG_START, fogstart)");
968     TRACE("Fog Start == %f\n", fogstart);
969
970     glFogf(GL_FOG_END, fogend);
971     checkGLcall("glFogf(GL_FOG_END, fogend)");
972     TRACE("Fog End == %f\n", fogend);
973 }
974
975 void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
976     enum fogsource new_source;
977
978     TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
979
980     if (!stateblock->renderState[WINED3DRS_FOGENABLE]) {
981         /* No fog? Disable it, and we're done :-) */
982         glDisableWINE(GL_FOG);
983         checkGLcall("glDisable GL_FOG");
984         return;
985     }
986
987     /* Fog Rules:
988      *
989      * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
990      * It can use the Z value of the vertex, or the alpha component of the specular color.
991      * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
992      * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
993      * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
994      *
995      * FOGTABLEMODE != NONE:
996      *  The Z value is used, with the equation specified, no matter what vertex type.
997      *
998      * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
999      *  Per vertex fog is calculated using the specified fog equation and the parameters
1000      *
1001      * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
1002      * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
1003      *  Linear fog with start = 255.0, end = 0.0, input comes from the specular color
1004      *
1005      *
1006      * Rules for vertex fog with shaders:
1007      *
1008      * When mixing fixed function functionality with the programmable pipeline, D3D expects
1009      * the fog computation to happen during transformation while openGL expects it to happen
1010      * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
1011      * the pixel shader while openGL always expects the pixel shader to handle the blending.
1012      * To solve this problem, WineD3D does:
1013      * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
1014      * shader,
1015      * and 2) disables the fog computation (in either the fixed function or programmable
1016      * rasterizer) if using a vertex program.
1017      *
1018      * D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with
1019      * D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear
1020      * fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in
1021      * the specular color, a vertex shader counts as pretransformed geometry in this case.
1022      * There are some GL differences between specular fog coords and vertex shaders though.
1023      *
1024      * With table fog the vertex shader fog coordinate is ignored.
1025      *
1026      * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
1027      * without shaders).
1028      */
1029
1030     /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
1031      * the system will apply only pixel(=table) fog effects."
1032      */
1033     if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
1034         if(use_vs(stateblock)) {
1035             glFogi(GL_FOG_MODE, GL_LINEAR);
1036             checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1037             new_source = FOGSOURCE_VS;
1038         } else {
1039             switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
1040                 /* If processed vertices are used, fall through to the NONE case */
1041                 case WINED3DFOG_EXP:
1042                     if(!context->last_was_rhw) {
1043                         glFogi(GL_FOG_MODE, GL_EXP);
1044                         checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1045                         new_source = FOGSOURCE_FFP;
1046                         break;
1047                     }
1048                     /* drop through */
1049
1050                 case WINED3DFOG_EXP2:
1051                     if(!context->last_was_rhw) {
1052                         glFogi(GL_FOG_MODE, GL_EXP2);
1053                         checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1054                         new_source = FOGSOURCE_FFP;
1055                         break;
1056                     }
1057                     /* drop through */
1058
1059                 case WINED3DFOG_LINEAR:
1060                     if(!context->last_was_rhw) {
1061                         glFogi(GL_FOG_MODE, GL_LINEAR);
1062                         checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1063                         new_source = FOGSOURCE_FFP;
1064                         break;
1065                     }
1066                     /* drop through */
1067
1068                 case WINED3DFOG_NONE:
1069                     /* Both are none? According to msdn the alpha channel of the specular
1070                      * color contains a fog factor. Set it in drawStridedSlow.
1071                      * Same happens with Vertexfog on transformed vertices
1072                      */
1073                     new_source = FOGSOURCE_COORD;
1074                     glFogi(GL_FOG_MODE, GL_LINEAR);
1075                     checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1076                     break;
1077
1078                 default:
1079                     FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
1080                     new_source = FOGSOURCE_FFP; /* Make the compiler happy */
1081             }
1082         }
1083     } else {
1084         new_source = FOGSOURCE_FFP;
1085
1086         switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
1087             case WINED3DFOG_EXP:
1088                 glFogi(GL_FOG_MODE, GL_EXP);
1089                 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1090                 break;
1091
1092             case WINED3DFOG_EXP2:
1093                 glFogi(GL_FOG_MODE, GL_EXP2);
1094                 checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1095                 break;
1096
1097             case WINED3DFOG_LINEAR:
1098                 glFogi(GL_FOG_MODE, GL_LINEAR);
1099                 checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1100                 break;
1101
1102             case WINED3DFOG_NONE:   /* Won't happen */
1103             default:
1104                 FIXME("Unexpected WINED3DRS_FOGTABLEMODE %d\n", stateblock->renderState[WINED3DRS_FOGTABLEMODE]);
1105         }
1106     }
1107
1108     glEnableWINE(GL_FOG);
1109     checkGLcall("glEnable GL_FOG");
1110     if(new_source != context->fog_source) {
1111         context->fog_source = new_source;
1112         state_fogstartend(STATE_RENDER(WINED3DRS_FOGSTART), stateblock, context);
1113     }
1114 }
1115
1116 static void state_rangefog_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1117     if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1118         WARN("Range fog enabled, but not supported by this opengl implementation\n");
1119     }
1120 }
1121
1122 static void state_rangefog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1123     if(stateblock->renderState[WINED3DRS_RANGEFOGENABLE]) {
1124         glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1125         checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
1126     } else {
1127         glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1128         checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
1129     }
1130 }
1131
1132 void state_fogcolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1133     float col[4];
1134     D3DCOLORTOGLFLOAT4(stateblock->renderState[WINED3DRS_FOGCOLOR], col);
1135     glFogfv(GL_FOG_COLOR, &col[0]);
1136     checkGLcall("glFog GL_FOG_COLOR");
1137 }
1138
1139 void state_fogdensity(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1140     union {
1141         DWORD d;
1142         float f;
1143     } tmpvalue;
1144     tmpvalue.d = stateblock->renderState[WINED3DRS_FOGDENSITY];
1145     glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1146     checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
1147 }
1148
1149 static void state_colormat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1150     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
1151     GLenum Parm = 0;
1152     const struct wined3d_stream_info_element *diffuse = &device->strided_streams.elements[WINED3D_FFP_DIFFUSE];
1153     BOOL isDiffuseSupplied;
1154
1155     /* Depends on the decoded vertex declaration to read the existence of diffuse data.
1156      * The vertex declaration will call this function if the fixed function pipeline is used.
1157      */
1158
1159     if(isStateDirty(context, STATE_VDECL)) {
1160         return;
1161     }
1162
1163     isDiffuseSupplied = diffuse->data || diffuse->buffer_object;
1164
1165     context->num_untracked_materials = 0;
1166     if (isDiffuseSupplied && stateblock->renderState[WINED3DRS_COLORVERTEX]) {
1167         TRACE("diff %d, amb %d, emis %d, spec %d\n",
1168               stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE],
1169               stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE],
1170               stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE],
1171               stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE]);
1172
1173         if (stateblock->renderState[WINED3DRS_DIFFUSEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1174             if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1175                 Parm = GL_AMBIENT_AND_DIFFUSE;
1176             } else {
1177                 Parm = GL_DIFFUSE;
1178             }
1179             if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1180                 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1181                 context->num_untracked_materials++;
1182             }
1183             if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1184                 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1185                 context->num_untracked_materials++;
1186             }
1187         } else if (stateblock->renderState[WINED3DRS_AMBIENTMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1188             Parm = GL_AMBIENT;
1189             if(stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1190                 context->untracked_materials[context->num_untracked_materials] = GL_EMISSION;
1191                 context->num_untracked_materials++;
1192             }
1193             if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1194                 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1195                 context->num_untracked_materials++;
1196             }
1197         } else if (stateblock->renderState[WINED3DRS_EMISSIVEMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1198             Parm = GL_EMISSION;
1199             if(stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1200                 context->untracked_materials[context->num_untracked_materials] = GL_SPECULAR;
1201                 context->num_untracked_materials++;
1202             }
1203         } else if (stateblock->renderState[WINED3DRS_SPECULARMATERIALSOURCE] == WINED3DMCS_COLOR1) {
1204             Parm = GL_SPECULAR;
1205         }
1206     }
1207
1208     /* Nothing changed, return. */
1209     if (Parm == context->tracking_parm) return;
1210
1211     if(!Parm) {
1212         glDisable(GL_COLOR_MATERIAL);
1213         checkGLcall("glDisable GL_COLOR_MATERIAL");
1214     } else {
1215         glColorMaterial(GL_FRONT_AND_BACK, Parm);
1216         checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1217         glEnable(GL_COLOR_MATERIAL);
1218         checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1219     }
1220
1221     /* Apparently calls to glMaterialfv are ignored for properties we're
1222      * tracking with glColorMaterial, so apply those here. */
1223     switch (context->tracking_parm) {
1224         case GL_AMBIENT_AND_DIFFUSE:
1225             glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1226             glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1227             checkGLcall("glMaterialfv");
1228             break;
1229
1230         case GL_DIFFUSE:
1231             glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float*)&device->updateStateBlock->material.Diffuse);
1232             checkGLcall("glMaterialfv");
1233             break;
1234
1235         case GL_AMBIENT:
1236             glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float*)&device->updateStateBlock->material.Ambient);
1237             checkGLcall("glMaterialfv");
1238             break;
1239
1240         case GL_EMISSION:
1241             glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float*)&device->updateStateBlock->material.Emissive);
1242             checkGLcall("glMaterialfv");
1243             break;
1244
1245         case GL_SPECULAR:
1246             /* Only change material color if specular is enabled, otherwise it is set to black */
1247             if (device->stateBlock->renderState[WINED3DRS_SPECULARENABLE]) {
1248                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float*)&device->updateStateBlock->material.Specular);
1249                 checkGLcall("glMaterialfv");
1250             } else {
1251                 static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1252                 glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1253                 checkGLcall("glMaterialfv");
1254             }
1255             break;
1256     }
1257
1258     context->tracking_parm = Parm;
1259 }
1260
1261 static void state_linepattern(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1262     union {
1263         DWORD                 d;
1264         WINED3DLINEPATTERN    lp;
1265     } tmppattern;
1266     tmppattern.d = stateblock->renderState[WINED3DRS_LINEPATTERN];
1267
1268     TRACE("Line pattern: repeat %d bits %x\n", tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1269
1270     if (tmppattern.lp.wRepeatFactor) {
1271         glLineStipple(tmppattern.lp.wRepeatFactor, tmppattern.lp.wLinePattern);
1272         checkGLcall("glLineStipple(repeat, linepattern)");
1273         glEnable(GL_LINE_STIPPLE);
1274         checkGLcall("glEnable(GL_LINE_STIPPLE);");
1275     } else {
1276         glDisable(GL_LINE_STIPPLE);
1277         checkGLcall("glDisable(GL_LINE_STIPPLE);");
1278     }
1279 }
1280
1281 static void state_zbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1282     union {
1283         DWORD d;
1284         float f;
1285     } tmpvalue;
1286
1287     if (stateblock->renderState[WINED3DRS_ZBIAS]) {
1288         tmpvalue.d = stateblock->renderState[WINED3DRS_ZBIAS];
1289         TRACE("ZBias value %f\n", tmpvalue.f);
1290         glPolygonOffset(0, -tmpvalue.f);
1291         checkGLcall("glPolygonOffset(0, -Value)");
1292         glEnable(GL_POLYGON_OFFSET_FILL);
1293         checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL);");
1294         glEnable(GL_POLYGON_OFFSET_LINE);
1295         checkGLcall("glEnable(GL_POLYGON_OFFSET_LINE);");
1296         glEnable(GL_POLYGON_OFFSET_POINT);
1297         checkGLcall("glEnable(GL_POLYGON_OFFSET_POINT);");
1298     } else {
1299         glDisable(GL_POLYGON_OFFSET_FILL);
1300         checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL);");
1301         glDisable(GL_POLYGON_OFFSET_LINE);
1302         checkGLcall("glDisable(GL_POLYGON_OFFSET_LINE);");
1303         glDisable(GL_POLYGON_OFFSET_POINT);
1304         checkGLcall("glDisable(GL_POLYGON_OFFSET_POINT);");
1305     }
1306 }
1307
1308
1309 static void state_normalize(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1310     if(isStateDirty(context, STATE_VDECL)) {
1311         return;
1312     }
1313     /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
1314      * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
1315      * by zero and is not properly defined in opengl, so avoid it
1316      */
1317     if (stateblock->renderState[WINED3DRS_NORMALIZENORMALS]
1318             && (stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_NORMAL].data
1319             || stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_NORMAL].buffer_object))
1320     {
1321         glEnable(GL_NORMALIZE);
1322         checkGLcall("glEnable(GL_NORMALIZE);");
1323     } else {
1324         glDisable(GL_NORMALIZE);
1325         checkGLcall("glDisable(GL_NORMALIZE);");
1326     }
1327 }
1328
1329 static void state_psizemin_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1330     union {
1331         DWORD d;
1332         float f;
1333     } tmpvalue;
1334
1335     tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1336     if(tmpvalue.f != 1.0) {
1337         FIXME("WINED3DRS_POINTSIZE_MIN not supported on this opengl, value is %f\n", tmpvalue.f);
1338     }
1339     tmpvalue.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1340     if(tmpvalue.f != 64.0) {
1341         FIXME("WINED3DRS_POINTSIZE_MAX not supported on this opengl, value is %f\n", tmpvalue.f);
1342     }
1343
1344 }
1345
1346 static void state_psizemin_ext(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1347     union {
1348         DWORD d;
1349         float f;
1350     } min, max;
1351
1352     min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1353     max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1354
1355     /* Max point size trumps min point size */
1356     if(min.f > max.f) {
1357         min.f = max.f;
1358     }
1359
1360     GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min.f);
1361     checkGLcall("glPointParameterfEXT(...)");
1362     GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max.f);
1363     checkGLcall("glPointParameterfEXT(...)");
1364 }
1365
1366 static void state_psizemin_arb(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1367     union {
1368         DWORD d;
1369         float f;
1370     } min, max;
1371
1372     min.d = stateblock->renderState[WINED3DRS_POINTSIZE_MIN];
1373     max.d = stateblock->renderState[WINED3DRS_POINTSIZE_MAX];
1374
1375     /* Max point size trumps min point size */
1376     if(min.f > max.f) {
1377         min.f = max.f;
1378     }
1379
1380     GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min.f);
1381     checkGLcall("glPointParameterfARB(...)");
1382     GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max.f);
1383     checkGLcall("glPointParameterfARB(...)");
1384 }
1385
1386 static void state_pscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1387     /* TODO: Group this with the viewport */
1388     /*
1389      * POINTSCALEENABLE controls how point size value is treated. If set to
1390      * true, the point size is scaled with respect to height of viewport.
1391      * When set to false point size is in pixels.
1392      */
1393
1394     /* Default values */
1395     GLfloat att[3] = {1.0f, 0.0f, 0.0f};
1396     union {
1397         DWORD d;
1398         float f;
1399     } pointSize, A, B, C;
1400
1401     pointSize.d = stateblock->renderState[WINED3DRS_POINTSIZE];
1402     A.d = stateblock->renderState[WINED3DRS_POINTSCALE_A];
1403     B.d = stateblock->renderState[WINED3DRS_POINTSCALE_B];
1404     C.d = stateblock->renderState[WINED3DRS_POINTSCALE_C];
1405
1406     if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1407         GLfloat scaleFactor;
1408         float h = stateblock->viewport.Height;
1409
1410         if(pointSize.f < GL_LIMITS(pointsizemin)) {
1411             /*
1412              * Minimum valid point size for OpenGL is driver specific. For Direct3D it is
1413              * 0.0f. This means that OpenGL will clamp really small point sizes to the
1414              * driver minimum. To correct for this we need to multiply by the scale factor when sizes
1415              * are less than 1.0f. scale_factor =  1.0f / point_size.
1416              */
1417             scaleFactor = pointSize.f / GL_LIMITS(pointsizemin);
1418             /* Clamp the point size, don't rely on the driver to do it. MacOS says min point size
1419              * is 1.0, but then accepts points below that and draws too small points
1420              */
1421             pointSize.f = GL_LIMITS(pointsizemin);
1422         } else if(pointSize.f > GL_LIMITS(pointsize)) {
1423             /* gl already scales the input to glPointSize,
1424              * d3d scales the result after the point size scale.
1425              * If the point size is bigger than the max size, use the
1426              * scaling to scale it bigger, and set the gl point size to max
1427              */
1428             scaleFactor = pointSize.f / GL_LIMITS(pointsize);
1429             TRACE("scale: %f\n", scaleFactor);
1430             pointSize.f = GL_LIMITS(pointsize);
1431         } else {
1432             scaleFactor = 1.0f;
1433         }
1434         scaleFactor = pow(h * scaleFactor, 2);
1435
1436         att[0] = A.f / scaleFactor;
1437         att[1] = B.f / scaleFactor;
1438         att[2] = C.f / scaleFactor;
1439     }
1440
1441     if(GL_SUPPORT(ARB_POINT_PARAMETERS)) {
1442         GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1443         checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1444     }
1445     else if(GL_SUPPORT(EXT_POINT_PARAMETERS)) {
1446         GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1447         checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1448     } else if(stateblock->renderState[WINED3DRS_POINTSCALEENABLE]) {
1449         WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1450     }
1451
1452     glPointSize(pointSize.f);
1453     checkGLcall("glPointSize(...);");
1454 }
1455
1456 static void state_colorwrite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1457     DWORD Value = stateblock->renderState[WINED3DRS_COLORWRITEENABLE];
1458
1459     TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1460         Value & WINED3DCOLORWRITEENABLE_RED   ? 1 : 0,
1461         Value & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
1462         Value & WINED3DCOLORWRITEENABLE_BLUE  ? 1 : 0,
1463         Value & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1464     glColorMask(Value & WINED3DCOLORWRITEENABLE_RED   ? GL_TRUE : GL_FALSE,
1465                 Value & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
1466                 Value & WINED3DCOLORWRITEENABLE_BLUE  ? GL_TRUE : GL_FALSE,
1467                 Value & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1468     checkGLcall("glColorMask(...)");
1469
1470     /* depends on WINED3DRS_COLORWRITEENABLE. */
1471     if(stateblock->renderState[WINED3DRS_COLORWRITEENABLE1] != 0x0000000F ||
1472        stateblock->renderState[WINED3DRS_COLORWRITEENABLE2] != 0x0000000F ||
1473        stateblock->renderState[WINED3DRS_COLORWRITEENABLE3] != 0x0000000F ) {
1474         ERR("(WINED3DRS_COLORWRITEENABLE1/2/3,%d,%d,%d) not yet implemented. Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n",
1475             stateblock->renderState[WINED3DRS_COLORWRITEENABLE1],
1476             stateblock->renderState[WINED3DRS_COLORWRITEENABLE2],
1477             stateblock->renderState[WINED3DRS_COLORWRITEENABLE3]);
1478     }
1479 }
1480
1481 static void state_localviewer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1482     if(stateblock->renderState[WINED3DRS_LOCALVIEWER]) {
1483         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1484         checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1485     } else {
1486         glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1487         checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
1488     }
1489 }
1490
1491 static void state_lastpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1492     if(stateblock->renderState[WINED3DRS_LASTPIXEL]) {
1493         TRACE("Last Pixel Drawing Enabled\n");
1494     } else {
1495         static BOOL warned;
1496         if (!warned) {
1497             FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1498             warned = TRUE;
1499         } else {
1500             TRACE("Last Pixel Drawing Disabled, not handled yet\n");
1501         }
1502     }
1503 }
1504
1505 static void state_pointsprite_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1506     BOOL warned = FALSE;
1507     /* TODO: NV_POINT_SPRITE */
1508     if (!warned && stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1509         /* A FIXME, not a WARN because point sprites should be software emulated if not supported by HW */
1510         FIXME("Point sprites not supported\n");
1511         warned = TRUE;
1512     }
1513 }
1514
1515 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1516     if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1517         BOOL warned = FALSE;
1518         if(GL_LIMITS(point_sprite_units) < GL_LIMITS(textures) && !warned) {
1519             if(use_ps(stateblock) || stateblock->lowest_disabled_stage > GL_LIMITS(point_sprite_units)) {
1520                 FIXME("The app uses point sprite texture coordinates on more units than supported by the driver\n");
1521                 warned = TRUE;
1522             }
1523         }
1524
1525         glEnable(GL_POINT_SPRITE_ARB);
1526         checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1527     } else {
1528         glDisable(GL_POINT_SPRITE_ARB);
1529         checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1530     }
1531 }
1532
1533 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1534     /**
1535      http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1536      http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1537      Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1538      http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1539
1540      so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1541      */
1542     TRACE("Stub\n");
1543     if(stateblock->renderState[WINED3DRS_WRAP0] ||
1544        stateblock->renderState[WINED3DRS_WRAP1] ||
1545        stateblock->renderState[WINED3DRS_WRAP2] ||
1546        stateblock->renderState[WINED3DRS_WRAP3] ||
1547        stateblock->renderState[WINED3DRS_WRAP4] ||
1548        stateblock->renderState[WINED3DRS_WRAP5] ||
1549        stateblock->renderState[WINED3DRS_WRAP6] ||
1550        stateblock->renderState[WINED3DRS_WRAP7] ||
1551        stateblock->renderState[WINED3DRS_WRAP8] ||
1552        stateblock->renderState[WINED3DRS_WRAP9] ||
1553        stateblock->renderState[WINED3DRS_WRAP10] ||
1554        stateblock->renderState[WINED3DRS_WRAP11] ||
1555        stateblock->renderState[WINED3DRS_WRAP12] ||
1556        stateblock->renderState[WINED3DRS_WRAP13] ||
1557        stateblock->renderState[WINED3DRS_WRAP14] ||
1558        stateblock->renderState[WINED3DRS_WRAP15] ) {
1559         FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1560     }
1561 }
1562
1563 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1564     if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1565         WARN("Multisample antialiasing not supported by gl\n");
1566     }
1567 }
1568
1569 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1570     if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1571         glEnable(GL_MULTISAMPLE_ARB);
1572         checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1573     } else {
1574         glDisable(GL_MULTISAMPLE_ARB);
1575         checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1576     }
1577 }
1578
1579 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1580     if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1581         glEnable(GL_SCISSOR_TEST);
1582         checkGLcall("glEnable(GL_SCISSOR_TEST)");
1583     } else {
1584         glDisable(GL_SCISSOR_TEST);
1585         checkGLcall("glDisable(GL_SCISSOR_TEST)");
1586     }
1587 }
1588
1589 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1590     union {
1591         DWORD d;
1592         float f;
1593     } tmpvalue;
1594
1595     if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1596        stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1597         tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1598         glEnable(GL_POLYGON_OFFSET_FILL);
1599         checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1600         glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1601         checkGLcall("glPolygonOffset(...)");
1602     } else {
1603         glDisable(GL_POLYGON_OFFSET_FILL);
1604         checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1605     }
1606 }
1607
1608 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1609     if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1610         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1611         checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1612     } else {
1613         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1614         checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1615     }
1616 }
1617
1618 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1619     TRACE("Stub\n");
1620     if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1621         FIXME(" Stippled Alpha not supported yet.\n");
1622 }
1623
1624 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1625     TRACE("Stub\n");
1626     if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1627         FIXME(" Antialias not supported yet.\n");
1628 }
1629
1630 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1631     TRACE("Stub\n");
1632     if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1633         FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1634 }
1635
1636 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1637     TRACE("Stub\n");
1638     if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1639         FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1640 }
1641
1642 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1643     union {
1644         DWORD d;
1645         float f;
1646     } tmpvalue;
1647     tmpvalue.f = 1.0f;
1648
1649     TRACE("Stub\n");
1650     if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1651     {
1652         static BOOL displayed = FALSE;
1653
1654         tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1655         if(!displayed)
1656             FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1657
1658         displayed = TRUE;
1659     }
1660 }
1661
1662 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1663     TRACE("Stub\n");
1664     if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1665         FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1666 }
1667
1668 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1669     TRACE("Stub\n");
1670     if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1671         FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1672 }
1673
1674 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1675     TRACE("Stub\n");
1676     if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1677         FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1678 }
1679
1680 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1681     if(stateblock->renderState[WINED3DRS_WRAPU]) {
1682         FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1683     }
1684 }
1685
1686 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1687     if(stateblock->renderState[WINED3DRS_WRAPV]) {
1688         FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1689     }
1690 }
1691
1692 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1693     if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1694         FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1695     }
1696 }
1697
1698 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1699     if(stateblock->renderState[WINED3DRS_ROP2]) {
1700         FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1701     }
1702 }
1703
1704 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1705     if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1706         FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1707     }
1708 }
1709
1710 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1711     if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1712         FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1713     }
1714 }
1715
1716 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1717     if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1718         FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1719     }
1720 }
1721
1722 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1723     if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1724         FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1725     }
1726 }
1727
1728 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1729     if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1730         FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1731     }
1732 }
1733
1734 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1735     if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1736         FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1737     }
1738 }
1739
1740 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1741     if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1742         FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1743     }
1744 }
1745
1746 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1747     if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1748         FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1749     }
1750 }
1751
1752 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1753     if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1754         FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1755     }
1756 }
1757
1758 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1759     if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1760         FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1761     }
1762 }
1763
1764 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1765     if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1766         FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1767     }
1768 }
1769
1770 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
1771 #if defined (GL_VERSION_1_3)
1772 # define useext(A) A
1773 #elif defined (GL_EXT_texture_env_combine)
1774 # define useext(A) A##_EXT
1775 #elif defined (GL_ARB_texture_env_combine)
1776 # define useext(A) A##_ARB
1777 #endif
1778
1779 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
1780     /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
1781     * input should be used for all input components. The WINED3DTA_COMPLEMENT
1782     * flag specifies the complement of the input should be used. */
1783     BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
1784     BOOL complement = arg & WINED3DTA_COMPLEMENT;
1785
1786     /* Calculate the operand */
1787     if (complement) {
1788         if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
1789         else *operand = GL_ONE_MINUS_SRC_COLOR;
1790     } else {
1791         if (from_alpha) *operand = GL_SRC_ALPHA;
1792         else *operand = GL_SRC_COLOR;
1793     }
1794
1795     /* Calculate the source */
1796     switch (arg & WINED3DTA_SELECTMASK) {
1797         case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
1798         case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
1799         case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
1800         case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
1801         case WINED3DTA_SPECULAR:
1802             /*
1803             * According to the GL_ARB_texture_env_combine specs, SPECULAR is
1804             * 'Secondary color' and isn't supported until base GL supports it
1805             * There is no concept of temp registers as far as I can tell
1806             */
1807             FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
1808             *source = GL_TEXTURE;
1809             break;
1810         default:
1811             FIXME("Unrecognized texture arg %#x\n", arg);
1812             *source = GL_TEXTURE;
1813             break;
1814     }
1815 }
1816
1817 /* Setup the texture operations texture stage states */
1818 static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1819 {
1820     GLenum src1, src2, src3;
1821     GLenum opr1, opr2, opr3;
1822     GLenum comb_target;
1823     GLenum src0_target, src1_target, src2_target;
1824     GLenum opr0_target, opr1_target, opr2_target;
1825     GLenum scal_target;
1826     GLenum opr=0, invopr, src3_target, opr3_target;
1827     BOOL Handled = FALSE;
1828     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1829     IWineD3DStateBlockImpl *stateblock = This->stateBlock; /* for GLINFO_LOCATION */
1830
1831     TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
1832
1833     /* This is called by a state handler which has the gl lock held and a context for the thread */
1834
1835         /* Note: Operations usually involve two ars, src0 and src1 and are operations of
1836     the form (a1 <operation> a2). However, some of the more complex operations
1837     take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
1838     in a third parameter called a0. Therefore these are operations of the form
1839     a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
1840
1841     However, below we treat the new (a0) parameter as src2/opr2, so in the actual
1842     functions below, expect their syntax to differ slightly to those listed in the
1843     manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
1844     This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP                     */
1845
1846     if (isAlpha) {
1847         comb_target = useext(GL_COMBINE_ALPHA);
1848         src0_target = useext(GL_SOURCE0_ALPHA);
1849         src1_target = useext(GL_SOURCE1_ALPHA);
1850         src2_target = useext(GL_SOURCE2_ALPHA);
1851         opr0_target = useext(GL_OPERAND0_ALPHA);
1852         opr1_target = useext(GL_OPERAND1_ALPHA);
1853         opr2_target = useext(GL_OPERAND2_ALPHA);
1854         scal_target = GL_ALPHA_SCALE;
1855     }
1856     else {
1857         comb_target = useext(GL_COMBINE_RGB);
1858         src0_target = useext(GL_SOURCE0_RGB);
1859         src1_target = useext(GL_SOURCE1_RGB);
1860         src2_target = useext(GL_SOURCE2_RGB);
1861         opr0_target = useext(GL_OPERAND0_RGB);
1862         opr1_target = useext(GL_OPERAND1_RGB);
1863         opr2_target = useext(GL_OPERAND2_RGB);
1864         scal_target = useext(GL_RGB_SCALE);
1865     }
1866
1867         /* If a texture stage references an invalid texture unit the stage just
1868         * passes through the result from the previous stage */
1869     if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
1870         arg1 = WINED3DTA_CURRENT;
1871         op = WINED3DTOP_SELECTARG1;
1872     }
1873
1874     if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) {
1875         get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
1876     } else {
1877         get_src_and_opr(arg1, isAlpha, &src1, &opr1);
1878     }
1879     get_src_and_opr(arg2, isAlpha, &src2, &opr2);
1880     get_src_and_opr(arg3, isAlpha, &src3, &opr3);
1881
1882     TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
1883
1884     Handled = TRUE; /* Assume will be handled */
1885
1886     /* Other texture operations require special extensions: */
1887     if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1888         if (isAlpha) {
1889             opr = GL_SRC_ALPHA;
1890             invopr = GL_ONE_MINUS_SRC_ALPHA;
1891             src3_target = GL_SOURCE3_ALPHA_NV;
1892             opr3_target = GL_OPERAND3_ALPHA_NV;
1893         } else {
1894             opr = GL_SRC_COLOR;
1895             invopr = GL_ONE_MINUS_SRC_COLOR;
1896             src3_target = GL_SOURCE3_RGB_NV;
1897             opr3_target = GL_OPERAND3_RGB_NV;
1898         }
1899         switch (op) {
1900             case WINED3DTOP_DISABLE: /* Only for alpha */
1901                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1902                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1903                 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
1904                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1905                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
1906                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1907                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1908                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1909                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1910                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1911                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1912                 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1913                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1914                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1915                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1916                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1917                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1918                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1919                 break;
1920                 case WINED3DTOP_SELECTARG1:                                          /* = a1 * 1 + 0 * 0 */
1921                 case WINED3DTOP_SELECTARG2:                                          /* = a2 * 1 + 0 * 0 */
1922                     glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1923                     checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1924                     if (op == WINED3DTOP_SELECTARG1) {
1925                         glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1926                         checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1927                         glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1928                         checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1929                     } else {
1930                         glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
1931                         checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
1932                         glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
1933                         checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
1934                     }
1935                     glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1936                     checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1937                     glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1938                     checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1939                     glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1940                     checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1941                     glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1942                     checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1943                     glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1944                     checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1945                     glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1946                     checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1947                     break;
1948
1949             case WINED3DTOP_MODULATE:
1950                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1951                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1952                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1953                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1954                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1955                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1956                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1957                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1958                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1959                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1960                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1961                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1962                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1963                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1964                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1965                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1966                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1967                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1968                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1969                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1970                 break;
1971             case WINED3DTOP_MODULATE2X:
1972                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1973                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1974                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1975                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1976                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1977                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1978                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1979                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1980                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1981                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1982                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1983                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1984                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1985                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1986                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1987                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1988                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1989                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1990                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
1991                 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
1992                 break;
1993             case WINED3DTOP_MODULATE4X:
1994                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1995                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1996                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1997                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1998                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1999                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2000                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2001                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2002                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2003                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2004                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2005                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2006                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2007                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2008                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2009                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2010                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2011                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2012                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2013                 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2014                 break;
2015
2016             case WINED3DTOP_ADD:
2017                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2018                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
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, GL_ZERO);
2024                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2025                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2026                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2027                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2028                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2029                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2030                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2031                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2032                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2033                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2034                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2035                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2036                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2037                 break;
2038
2039             case WINED3DTOP_ADDSIGNED:
2040                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2041                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2042                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2043                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2044                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2045                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2046                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2047                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2048                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2049                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2050                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2051                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2052                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2053                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2054                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2055                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2056                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2057                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2058                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2059                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2060                 break;
2061
2062             case WINED3DTOP_ADDSIGNED2X:
2063                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2064                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2065                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2066                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2067                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2068                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2069                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2070                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2071                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2072                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2073                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2074                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2075                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2076                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2077                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2078                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2079                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2080                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2081                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2082                 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2083                 break;
2084
2085             case WINED3DTOP_ADDSMOOTH:
2086                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2087                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2088                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2089                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2090                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2091                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2092                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2093                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2094                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2095                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2096                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2097                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2098                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2099                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2100                 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2101                 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2102                 switch (opr1) {
2103                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2104                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2105                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2106                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2107                 }
2108                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2109                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2110                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2111                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2112                 break;
2113
2114             case WINED3DTOP_BLENDDIFFUSEALPHA:
2115                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2116                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2117                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2118                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2119                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2120                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2121                 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
2122                 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
2123                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2124                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2125                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2126                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2127                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2128                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2129                 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
2130                 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
2131                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2132                 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2133                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2134                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2135                 break;
2136             case WINED3DTOP_BLENDTEXTUREALPHA:
2137                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2138                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2139                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2140                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2141                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2142                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2143                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2144                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2145                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2146                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2147                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2148                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2149                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2150                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2151                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2152                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2153                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2154                 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2155                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2156                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2157                 break;
2158             case WINED3DTOP_BLENDFACTORALPHA:
2159                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2160                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2161                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2162                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2163                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2164                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2165                 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
2166                 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
2167                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2168                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2169                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2170                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2171                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2172                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2173                 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
2174                 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
2175                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2176                 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2177                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2178                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2179                 break;
2180             case WINED3DTOP_BLENDTEXTUREALPHAPM:
2181                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2182                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2183                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2184                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2185                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2186                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2187                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2188                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2189                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2190                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2191                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2192                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2193                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2194                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2195                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2196                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2197                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2198                 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2199                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2200                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2201                 break;
2202             case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2203                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2204                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");  /* Add = a0*a1 + a2*a3 */
2205                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);        /*   a0 = src1/opr1    */
2206                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2207                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2208                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");    /*   a1 = 1 (see docs) */
2209                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2210                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2211                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2212                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2213                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);        /*   a2 = arg2         */
2214                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2215                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2216                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");     /*  a3 = src1 alpha   */
2217                 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2218                 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2219                 switch (opr) {
2220                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2221                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2222                 }
2223                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2224                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2225                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2226                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2227                 break;
2228             case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2229                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2230                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2231                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2232                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2233                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2234                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2235                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2236                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2237                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2238                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2239                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2240                 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2241                 switch (opr1) {
2242                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2243                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2244                 }
2245                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2246                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2247                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2248                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2249                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2250                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2251                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2252                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2253                 break;
2254             case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2255                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2256                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2257                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2258                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2259                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2260                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2261                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2262                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2263                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2264                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
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, src3_target, src1);
2270                 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2271                 switch (opr1) {
2272                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2273                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2274                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2275                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2276                 }
2277                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2278                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2279                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2280                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2281                 break;
2282             case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2283                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2284                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2285                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2286                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2287                 switch (opr1) {
2288                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2289                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2290                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2291                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2292                 }
2293                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2294                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2295                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2296                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2297                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2298                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2299                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2300                 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2301                 switch (opr1) {
2302                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2303                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2304                 }
2305                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2306                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2307                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2308                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2309                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2310                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2311                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2312                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2313                 break;
2314             case WINED3DTOP_MULTIPLYADD:
2315                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2316                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2317                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2318                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2319                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2320                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2321                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2322                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2323                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2324                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2325                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2326                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2327                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2328                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2329                 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2330                 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2331                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2332                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2333                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2334                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2335                 break;
2336
2337             case WINED3DTOP_BUMPENVMAP:
2338             {
2339             }
2340
2341             case WINED3DTOP_BUMPENVMAPLUMINANCE:
2342                 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2343
2344             default:
2345                 Handled = FALSE;
2346         }
2347         if (Handled) {
2348             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2349             checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2350
2351             return;
2352         }
2353     } /* GL_NV_texture_env_combine4 */
2354
2355     Handled = TRUE; /* Again, assume handled */
2356     switch (op) {
2357         case WINED3DTOP_DISABLE: /* Only for alpha */
2358             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2359             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2360             glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2361             checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2362             glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2363             checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2364             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2365             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2366             break;
2367         case WINED3DTOP_SELECTARG1:
2368             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2369             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2370             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2371             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2372             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2373             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2374             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2375             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2376             break;
2377         case WINED3DTOP_SELECTARG2:
2378             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2379             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2380             glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2381             checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2382             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2383             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2384             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2385             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2386             break;
2387         case WINED3DTOP_MODULATE:
2388             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2389             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2390             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2391             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2392             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2393             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2394             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2395             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2396             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2397             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2398             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2399             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2400             break;
2401         case WINED3DTOP_MODULATE2X:
2402             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2403             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2404             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2405             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2406             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2407             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2408             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2409             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2410             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2411             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2412             glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2413             checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2414             break;
2415         case WINED3DTOP_MODULATE4X:
2416             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2417             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2418             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2419             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2420             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2421             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2422             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2423             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2424             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2425             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2426             glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2427             checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2428             break;
2429         case WINED3DTOP_ADD:
2430             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2431             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2432             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2433             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2434             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2435             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2436             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2437             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2438             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2439             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2440             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2441             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2442             break;
2443         case WINED3DTOP_ADDSIGNED:
2444             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2445             checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
2446             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2447             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2448             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2449             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2450             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2451             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2452             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2453             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2454             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2455             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2456             break;
2457         case WINED3DTOP_ADDSIGNED2X:
2458             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2459             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2460             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2461             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2462             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2463             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2464             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2465             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2466             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2467             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2468             glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2469             checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2470             break;
2471         case WINED3DTOP_SUBTRACT:
2472             if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
2473                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2474                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
2475                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2476                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2477                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2478                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2479                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2480                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2481                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2482                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2483                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2484                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2485             } else {
2486                 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2487             }
2488             break;
2489
2490         case WINED3DTOP_BLENDDIFFUSEALPHA:
2491             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2492             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2493             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2494             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2495             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2496             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2497             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2498             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2499             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2500             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2501             glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2502             checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2503             glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2504             checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2505             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2506             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2507             break;
2508         case WINED3DTOP_BLENDTEXTUREALPHA:
2509             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2510             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2511             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2512             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2513             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2514             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2515             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2516             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2517             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2518             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2519             glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2520             checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2521             glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2522             checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2523             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2524             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2525             break;
2526         case WINED3DTOP_BLENDFACTORALPHA:
2527             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2528             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2529             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2530             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2531             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2532             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2533             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2534             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2535             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2536             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2537             glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2538             checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2539             glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2540             checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2541             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2542             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2543             break;
2544         case WINED3DTOP_BLENDCURRENTALPHA:
2545             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2546             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2547             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2548             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2549             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2550             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2551             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2552             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2553             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2554             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2555             glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2556             checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2557             glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2558             checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2559             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2560             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2561             break;
2562         case WINED3DTOP_DOTPRODUCT3:
2563             if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
2564                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2565                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2566             } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) {
2567                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2568                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2569             } else {
2570                 FIXME("This version of opengl does not support GL_DOT3\n");
2571             }
2572             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2573             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2574             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2575             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2576             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2577             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2578             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2579             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2580             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2581             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2582             break;
2583         case WINED3DTOP_LERP:
2584             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2585             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2586             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2587             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2588             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2589             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2590             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2591             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2592             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2593             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2594             glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2595             checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2596             glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2597             checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2598             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2599             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2600             break;
2601         case WINED3DTOP_ADDSMOOTH:
2602             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2603                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2604                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2605                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2606                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2607                 switch (opr1) {
2608                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2609                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2610                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2611                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2612                 }
2613                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2614                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2615                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2616                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2617                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2618                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2619                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2620                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2621                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2622                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2623                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2624                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2625             } else
2626                 Handled = FALSE;
2627                 break;
2628         case WINED3DTOP_BLENDTEXTUREALPHAPM:
2629             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2630                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2631                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2632                 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2633                 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2634                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2635                 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2636                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2637                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2638                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2639                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2640                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2641                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2642                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2643                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2644                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2645                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2646             } else
2647                 Handled = FALSE;
2648                 break;
2649         case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2650             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2651                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2652                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2653                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2654                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2655                 switch (opr1) {
2656                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2657                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2658                     case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2659                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2660                 }
2661                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2662                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2663                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2664                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2665                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2666                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2667                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2668                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2669                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2670                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2671                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2672                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2673             } else
2674                 Handled = FALSE;
2675                 break;
2676         case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2677             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2678                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2679                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2680                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2681                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2682                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2683                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2684                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2685                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2686                 switch (opr1) {
2687                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2688                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2689                     case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2690                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2691                 }
2692                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2693                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2694                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2695                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2696                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2697                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2698                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2699                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2700             } else
2701                 Handled = FALSE;
2702                 break;
2703         case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2704             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2705                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2706                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2707                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2708                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2709                 switch (opr1) {
2710                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2711                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2712                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2713                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2714                 }
2715                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2716                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2717                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2718                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2719                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2720                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2721                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2722                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2723                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2724                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2725                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2726                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2727             } else
2728                 Handled = FALSE;
2729                 break;
2730         case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2731             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2732                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2733                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2734                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2735                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2736                 switch (opr1) {
2737                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2738                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2739                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2740                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2741                 }
2742                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2743                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2744                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2745                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2746                 switch (opr1) {
2747                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2748                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2749                     case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2750                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2751                 }
2752                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2753                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2754                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2755                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2756                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2757                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2758                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2759                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2760             } else
2761                 Handled = FALSE;
2762                 break;
2763         case WINED3DTOP_MULTIPLYADD:
2764             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2765                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2766                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2767                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2768                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2769                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2770                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2771                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
2772                 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
2773                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
2774                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
2775                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2776                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2777                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2778                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2779                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2780                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2781             } else
2782                 Handled = FALSE;
2783                 break;
2784         case WINED3DTOP_BUMPENVMAPLUMINANCE:
2785         case WINED3DTOP_BUMPENVMAP:
2786             if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2787                 /* Technically texture shader support without register combiners is possible, but not expected to occur
2788                  * on real world cards, so for now a fixme should be enough
2789                  */
2790                 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
2791             }
2792         default:
2793             Handled = FALSE;
2794     }
2795
2796     if (Handled) {
2797         BOOL  combineOK = TRUE;
2798         if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2799             DWORD op2;
2800
2801             if (isAlpha) {
2802                 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP];
2803             } else {
2804                 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP];
2805             }
2806
2807             /* Note: If COMBINE4 in effect can't go back to combine! */
2808             switch (op2) {
2809                 case WINED3DTOP_ADDSMOOTH:
2810                 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2811                 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2812                 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2813                 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2814                 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2815                 case WINED3DTOP_MULTIPLYADD:
2816                     /* Ignore those implemented in both cases */
2817                     switch (op) {
2818                         case WINED3DTOP_SELECTARG1:
2819                         case WINED3DTOP_SELECTARG2:
2820                             combineOK = FALSE;
2821                             Handled   = FALSE;
2822                             break;
2823                         default:
2824                             FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
2825                             return;
2826                     }
2827             }
2828         }
2829
2830         if (combineOK) {
2831             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
2832             checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
2833
2834             return;
2835         }
2836     }
2837
2838     /* After all the extensions, if still unhandled, report fixme */
2839     FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
2840 }
2841
2842
2843 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2844     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2845     DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2846     BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2847
2848     TRACE("Setting color op for stage %d\n", stage);
2849
2850     /* Using a pixel shader? Don't care for anything here, the shader applying does it */
2851     if (use_ps(stateblock)) return;
2852
2853     if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
2854
2855     if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2856     {
2857         if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2858             FIXME("Attempt to enable unsupported stage!\n");
2859             return;
2860         }
2861         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2862         checkGLcall("glActiveTextureARB");
2863     }
2864
2865     if(stage >= stateblock->lowest_disabled_stage) {
2866         TRACE("Stage disabled\n");
2867         if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2868         {
2869             /* Disable everything here */
2870             glDisable(GL_TEXTURE_2D);
2871             checkGLcall("glDisable(GL_TEXTURE_2D)");
2872             glDisable(GL_TEXTURE_3D);
2873             checkGLcall("glDisable(GL_TEXTURE_3D)");
2874             if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2875                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2876                 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
2877             }
2878             if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
2879                 glDisable(GL_TEXTURE_RECTANGLE_ARB);
2880                 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
2881             }
2882         }
2883         /* All done */
2884         return;
2885     }
2886
2887     /* The sampler will also activate the correct texture dimensions, so no need to do it here
2888      * if the sampler for this stage is dirty
2889      */
2890     if(!isStateDirty(context, STATE_SAMPLER(stage))) {
2891         if (tex_used) texture_activate_dimensions(stage, stateblock, context);
2892     }
2893
2894     set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
2895                 stateblock->textureState[stage][WINED3DTSS_COLOROP],
2896                 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
2897                 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
2898                 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
2899 }
2900
2901 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2902     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2903     DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2904     BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2905     DWORD op, arg1, arg2, arg0;
2906
2907     TRACE("Setting alpha op for stage %d\n", stage);
2908     /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
2909     if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2910     {
2911         if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2912             FIXME("Attempt to enable unsupported stage!\n");
2913             return;
2914         }
2915         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2916         checkGLcall("glActiveTextureARB");
2917     }
2918
2919     op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
2920     arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
2921     arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
2922     arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
2923
2924     if (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && stateblock->textures[0])
2925     {
2926         UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
2927
2928         if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
2929         {
2930             IWineD3DSurfaceImpl *surf;
2931
2932             surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
2933
2934             if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format_desc->alpha_mask)
2935             {
2936                 /* Color keying needs to pass alpha values from the texture through to have the alpha test work
2937                  * properly. On the other hand applications can still use texture combiners apparently. This code
2938                  * takes care that apps cannot remove the texture's alpha channel entirely.
2939                  *
2940                  * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
2941                  * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
2942                  * and alpha component of diffuse color to draw things like translucent text and perform other
2943                  * blending effects.
2944                  *
2945                  * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
2946                  * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
2947                  * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
2948                  * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
2949                  * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
2950                  * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
2951                  * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
2952                  * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
2953                  * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
2954                  * alpha.
2955                  *
2956                  * What to do with multitexturing? So far no app has been found that uses color keying with
2957                  * multitexturing */
2958                 if (op == WINED3DTOP_DISABLE)
2959                 {
2960                     arg1 = WINED3DTA_TEXTURE;
2961                     op = WINED3DTOP_SELECTARG1;
2962                 }
2963                 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE)
2964                 {
2965                     if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
2966                     {
2967                         arg2 = WINED3DTA_TEXTURE;
2968                         op = WINED3DTOP_MODULATE;
2969                     }
2970                     else arg1 = WINED3DTA_TEXTURE;
2971                 }
2972                 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE)
2973                 {
2974                     if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
2975                     {
2976                         arg1 = WINED3DTA_TEXTURE;
2977                         op = WINED3DTOP_MODULATE;
2978                     }
2979                     else arg2 = WINED3DTA_TEXTURE;
2980                 }
2981             }
2982         }
2983     }
2984
2985     /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
2986      * this if block here, and the other code(color keying, texture unit selection) are the same
2987      */
2988     TRACE("Setting alpha op for stage %d\n", stage);
2989     if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2990         set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2991                          op, arg1, arg2, arg0,
2992                          mapped_stage,
2993                          stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
2994     } else {
2995         set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2996                     op, arg1, arg2, arg0);
2997     }
2998 }
2999
3000 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3001     DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3002     DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
3003     BOOL generated;
3004     int coordIdx;
3005
3006     /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
3007     if (use_vs(stateblock) || isStateDirty(context, STATE_VDECL))
3008     {
3009         TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
3010         return;
3011     }
3012
3013     if (mapped_stage == WINED3D_UNMAPPED_STAGE) return;
3014
3015     if(mapped_stage >= GL_LIMITS(textures)) {
3016         return;
3017     }
3018     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3019     checkGLcall("glActiveTextureARB");
3020     generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
3021     coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1);
3022
3023     set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
3024             stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS], generated, context->last_was_rhw,
3025             stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].stride
3026             ? stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].format_desc->format
3027             : WINED3DFMT_UNKNOWN,
3028             stateblock->wineD3DDevice->frag_pipe->ffp_proj_control);
3029
3030     /* The sampler applying function calls us if this changes */
3031     if ((context->lastWasPow2Texture & (1 << texUnit)) && stateblock->textures[texUnit])
3032     {
3033         if(generated) {
3034             FIXME("Non-power2 texture being used with generated texture coords\n");
3035         }
3036         /* NP2 texcoord fixup is implemented for pixelshaders (currently only in GLSL backend) so
3037            only enable the fixed-function-pipeline fixup via pow2Matrix when no PS is used. */
3038         if (!use_ps(stateblock)) {
3039             TRACE("Non power two matrix multiply fixup\n");
3040             glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
3041         }
3042     }
3043 }
3044
3045 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
3046     unsigned int texture_idx;
3047
3048     for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
3049         GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
3050         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3051     }
3052 }
3053
3054 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const struct wined3d_stream_info *si, GLuint *curVBO)
3055 {
3056     const UINT *offset = stateblock->streamOffset;
3057     unsigned int mapped_stage = 0;
3058     unsigned int textureNo = 0;
3059
3060     for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
3061         int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
3062         const struct wined3d_stream_info_element *e;
3063
3064         mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
3065         if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue;
3066
3067         e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
3068         if (coordIdx < MAX_TEXTURES && (e->data || e->buffer_object))
3069         {
3070             TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
3071                     textureNo, mapped_stage, coordIdx, e->data);
3072
3073             if (*curVBO != e->buffer_object)
3074             {
3075                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
3076                 checkGLcall("glBindBufferARB");
3077                 *curVBO = e->buffer_object;
3078             }
3079
3080             GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3081             checkGLcall("glClientActiveTextureARB");
3082
3083             /* The coords to supply depend completely on the fvf / vertex shader */
3084             glTexCoordPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
3085                     e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
3086             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3087         } else {
3088             GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
3089         }
3090     }
3091     if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3092         /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
3093         for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
3094             GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
3095         }
3096     }
3097
3098     checkGLcall("loadTexCoords");
3099 }
3100
3101 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3102     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3103     DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
3104     static const GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3105     static const GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3106     static const GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3107     static const GLfloat q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3108
3109     if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3110     {
3111         TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3112         return;
3113     }
3114
3115     if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
3116         WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage);
3117         return;
3118     }
3119     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3120     checkGLcall("glActiveTextureARB");
3121
3122     /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3123      *
3124      * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
3125      * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3126      * means use the vertex position (camera-space) as the input texture coordinates
3127      * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3128      * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3129      * to the TEXCOORDINDEX value
3130      */
3131     switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xffff0000)
3132     {
3133         case WINED3DTSS_TCI_PASSTHRU:
3134             /* Use the specified texture coordinates contained within the
3135              * vertex format. This value resolves to zero. */
3136             glDisable(GL_TEXTURE_GEN_S);
3137             glDisable(GL_TEXTURE_GEN_T);
3138             glDisable(GL_TEXTURE_GEN_R);
3139             glDisable(GL_TEXTURE_GEN_Q);
3140             checkGLcall("WINED3DTSS_TCI_PASSTHRU - Disable texgen.");
3141             break;
3142
3143         case WINED3DTSS_TCI_CAMERASPACEPOSITION:
3144             /* CameraSpacePosition means use the vertex position, transformed to camera space,
3145              * as the input texture coordinates for this stage's texture transformation. This
3146              * equates roughly to EYE_LINEAR */
3147
3148             glMatrixMode(GL_MODELVIEW);
3149             glPushMatrix();
3150             glLoadIdentity();
3151             glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3152             glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3153             glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3154             glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3155             glPopMatrix();
3156             checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane.");
3157
3158             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3159             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3160             glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3161             checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set texgen mode.");
3162
3163             glEnable(GL_TEXTURE_GEN_S);
3164             glEnable(GL_TEXTURE_GEN_T);
3165             glEnable(GL_TEXTURE_GEN_R);
3166             checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Enable texgen.");
3167
3168             break;
3169
3170         case WINED3DTSS_TCI_CAMERASPACENORMAL:
3171             /* Note that NV_TEXGEN_REFLECTION support is implied when
3172              * ARB_TEXTURE_CUBE_MAP is supported */
3173             if (!GL_SUPPORT(NV_TEXGEN_REFLECTION))
3174             {
3175                 FIXME("WINED3DTSS_TCI_CAMERASPACENORMAL not supported.\n");
3176                 break;
3177             }
3178
3179             glMatrixMode(GL_MODELVIEW);
3180             glPushMatrix();
3181             glLoadIdentity();
3182             glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3183             glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3184             glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3185             glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3186             glPopMatrix();
3187             checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane.");
3188
3189             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3190             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3191             glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3192             checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set texgen mode.");
3193
3194             glEnable(GL_TEXTURE_GEN_S);
3195             glEnable(GL_TEXTURE_GEN_T);
3196             glEnable(GL_TEXTURE_GEN_R);
3197             checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Enable texgen.");
3198
3199             break;
3200
3201         case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3202             /* Note that NV_TEXGEN_REFLECTION support is implied when
3203              * ARB_TEXTURE_CUBE_MAP is supported */
3204             if (!GL_SUPPORT(NV_TEXGEN_REFLECTION))
3205             {
3206                 FIXME("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR not supported.\n");
3207                 break;
3208             }
3209
3210             glMatrixMode(GL_MODELVIEW);
3211             glPushMatrix();
3212             glLoadIdentity();
3213             glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3214             glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3215             glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3216             glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3217             glPopMatrix();
3218             checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane.");
3219
3220             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3221             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3222             glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3223             checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set texgen mode.");
3224
3225             glEnable(GL_TEXTURE_GEN_S);
3226             glEnable(GL_TEXTURE_GEN_T);
3227             glEnable(GL_TEXTURE_GEN_R);
3228             checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Enable texgen.");
3229
3230             break;
3231
3232         case WINED3DTSS_TCI_SPHEREMAP:
3233             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3234             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3235             checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Set texgen mode.");
3236
3237             glEnable(GL_TEXTURE_GEN_S);
3238             glEnable(GL_TEXTURE_GEN_T);
3239             glDisable(GL_TEXTURE_GEN_R);
3240             checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Enable texgen.");
3241
3242             break;
3243
3244         default:
3245             FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %#x\n",
3246                     stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
3247             glDisable(GL_TEXTURE_GEN_S);
3248             glDisable(GL_TEXTURE_GEN_T);
3249             glDisable(GL_TEXTURE_GEN_R);
3250             glDisable(GL_TEXTURE_GEN_Q);
3251             checkGLcall("Disable texgen.");
3252
3253             break;
3254     }
3255
3256     /* Update the texture matrix */
3257     if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
3258         transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3259     }
3260
3261     if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
3262         /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3263          * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3264          * and do all the things linked to it
3265          * TODO: Tidy that up to reload only the arrays of the changed unit
3266          */
3267         GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3268
3269         unloadTexCoords(stateblock);
3270         loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
3271     }
3272 }
3273
3274 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3275     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3276
3277     /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
3278      * has an update pending
3279      */
3280     if(isStateDirty(context, STATE_VDECL) ||
3281        isStateDirty(context, STATE_PIXELSHADER)) {
3282        return;
3283     }
3284
3285     device->shader_backend->shader_load_constants((IWineD3DDevice *)device, use_ps(stateblock), use_vs(stateblock));
3286 }
3287
3288 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3289     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3290
3291     if(stateblock->pixelShader && stage != 0 &&
3292        ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
3293         /* The pixel shader has to know the luminance scale. Do a constants update if it
3294          * isn't scheduled anyway
3295          */
3296         if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3297            !isStateDirty(context, STATE_PIXELSHADER)) {
3298             shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3299         }
3300     }
3301 }
3302
3303 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3304     const DWORD sampler = state - STATE_SAMPLER(0);
3305     IWineD3DBaseTexture *texture = stateblock->textures[sampler];
3306
3307     TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
3308
3309     if(!texture) return;
3310     /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3311      * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
3312      * scaling is reapplied or removed, the texture matrix has to be reapplied
3313      *
3314      * The mapped stage is already active because the sampler() function below, which is part of the
3315      * misc pipeline
3316      */
3317     if(sampler < MAX_TEXTURES) {
3318         const BOOL texIsPow2 = !((IWineD3DBaseTextureImpl *)texture)->baseTexture.pow2Matrix_identity;
3319
3320         if (texIsPow2 || (context->lastWasPow2Texture & (1 << sampler)))
3321         {
3322             if (texIsPow2) context->lastWasPow2Texture |= 1 << sampler;
3323             else context->lastWasPow2Texture &= ~(1 << sampler);
3324             transform_texture(STATE_TEXTURESTAGE(stateblock->wineD3DDevice->texUnitMap[sampler], WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3325         }
3326     }
3327 }
3328
3329 static void sampler(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3330     DWORD sampler = state - STATE_SAMPLER(0);
3331     DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[sampler];
3332     union {
3333         float f;
3334         DWORD d;
3335     } tmpvalue;
3336
3337     TRACE("Sampler: %d\n", sampler);
3338     /* Enabling and disabling texture dimensions is done by texture stage state / pixel shader setup, this function
3339      * only has to bind textures and set the per texture states
3340      */
3341
3342     if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3343     {
3344         TRACE("No sampler mapped to stage %d. Returning.\n", sampler);
3345         return;
3346     }
3347
3348     if (mapped_stage >= GL_LIMITS(combined_samplers)) {
3349         return;
3350     }
3351     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3352     checkGLcall("glActiveTextureARB");
3353
3354     if(stateblock->textures[sampler]) {
3355         BOOL srgb = stateblock->samplerState[sampler][WINED3DSAMP_SRGBTEXTURE];
3356         IWineD3DBaseTextureImpl *tex_impl = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler];
3357         tex_impl->baseTexture.internal_preload(stateblock->textures[sampler], srgb ? SRGB_SRGB : SRGB_RGB);
3358         IWineD3DBaseTexture_BindTexture(stateblock->textures[sampler], srgb);
3359         IWineD3DBaseTexture_ApplyStateChanges(stateblock->textures[sampler], stateblock->textureState[sampler], stateblock->samplerState[sampler]);
3360
3361         if (GL_SUPPORT(EXT_TEXTURE_LOD_BIAS)) {
3362             tmpvalue.d = stateblock->samplerState[sampler][WINED3DSAMP_MIPMAPLODBIAS];
3363             glTexEnvf(GL_TEXTURE_FILTER_CONTROL_EXT,
3364                       GL_TEXTURE_LOD_BIAS_EXT,
3365                       tmpvalue.f);
3366             checkGLcall("glTexEnvi(GL_TEXTURE_LOD_BIAS_EXT, ...)");
3367         }
3368
3369         if (!use_ps(stateblock) && sampler < stateblock->lowest_disabled_stage)
3370         {
3371             if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3372                 /* If color keying is enabled update the alpha test, it depends on the existence
3373                  * of a color key in stage 0
3374                  */
3375                 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3376             }
3377         }
3378
3379         /* Trigger shader constant reloading (for NP2 texcoord fixup)
3380          * Only do this if pshaders are used (note: fixup is currently only implemented in GLSL). */
3381         if (!tex_impl->baseTexture.pow2Matrix_identity) {
3382             IWineD3DDeviceImpl* d3ddevice = stateblock->wineD3DDevice;
3383             d3ddevice->shader_backend->shader_load_np2fixup_constants(
3384                 (IWineD3DDevice*)d3ddevice, use_ps(stateblock), use_vs(stateblock));
3385         }
3386     } else if(mapped_stage < GL_LIMITS(textures)) {
3387         if(sampler < stateblock->lowest_disabled_stage) {
3388             /* TODO: What should I do with pixel shaders here ??? */
3389             if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3390                 /* If color keying is enabled update the alpha test, it depends on the existence
3391                 * of a color key in stage 0
3392                 */
3393                 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3394             }
3395         } /* Otherwise tex_colorop disables the stage */
3396         glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
3397         checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
3398     }
3399 }
3400
3401 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3402     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3403     BOOL use_pshader = use_ps(stateblock);
3404     BOOL use_vshader = use_vs(stateblock);
3405     int i;
3406
3407     if (use_pshader) {
3408         if(!context->last_was_pshader) {
3409             /* Former draw without a pixel shader, some samplers
3410              * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
3411              * make sure to enable them
3412              */
3413             for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
3414                 if(!isStateDirty(context, STATE_SAMPLER(i))) {
3415                     sampler(STATE_SAMPLER(i), stateblock, context);
3416                 }
3417             }
3418             context->last_was_pshader = TRUE;
3419         } else {
3420            /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
3421             * if a different texture was bound. I don't have to do anything.
3422             */
3423         }
3424     } else {
3425         /* Disabled the pixel shader - color ops weren't applied
3426          * while it was enabled, so re-apply them.
3427          */
3428         for(i=0; i < MAX_TEXTURES; i++) {
3429             if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
3430                 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
3431                         (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
3432             }
3433         }
3434         context->last_was_pshader = FALSE;
3435     }
3436
3437     if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
3438         device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
3439
3440         if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
3441             shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3442         }
3443     }
3444 }
3445
3446 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3447     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3448     if(stateblock->pixelShader && stage != 0 &&
3449        ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
3450         /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
3451          * anyway
3452          */
3453         if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3454             !isStateDirty(context, STATE_PIXELSHADER)) {
3455             shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3456         }
3457     }
3458 }
3459
3460 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3461     /* This function is called by transform_view below if the view matrix was changed too
3462      *
3463      * Deliberately no check if the vertex declaration is dirty because the vdecl state
3464      * does not always update the world matrix, only on a switch between transformed
3465      * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3466      * draw, but that should be rather rare and cheaper in total.
3467      */
3468     glMatrixMode(GL_MODELVIEW);
3469     checkGLcall("glMatrixMode");
3470
3471     if(context->last_was_rhw) {
3472         glLoadIdentity();
3473         checkGLcall("glLoadIdentity()");
3474     } else {
3475         /* In the general case, the view matrix is the identity matrix */
3476         if (stateblock->wineD3DDevice->view_ident) {
3477             glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3478             checkGLcall("glLoadMatrixf");
3479         } else {
3480             glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3481             checkGLcall("glLoadMatrixf");
3482             glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3483             checkGLcall("glMultMatrixf");
3484         }
3485     }
3486 }
3487
3488 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3489     UINT index = state - STATE_CLIPPLANE(0);
3490
3491     if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
3492         return;
3493     }
3494
3495     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3496     glMatrixMode(GL_MODELVIEW);
3497     glPushMatrix();
3498     glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3499
3500     TRACE("Clipplane [%f,%f,%f,%f]\n",
3501           stateblock->clipplane[index][0],
3502           stateblock->clipplane[index][1],
3503           stateblock->clipplane[index][2],
3504           stateblock->clipplane[index][3]);
3505     glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
3506     checkGLcall("glClipPlane");
3507
3508     glPopMatrix();
3509 }
3510
3511 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3512     UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
3513     GLenum glMat;
3514     TRACE("Setting world matrix %d\n", matrix);
3515
3516     if(matrix >= GL_LIMITS(blends)) {
3517         WARN("Unsupported blend matrix set\n");
3518         return;
3519     } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3520         return;
3521     }
3522
3523     /* GL_MODELVIEW0_ARB:  0x1700
3524      * GL_MODELVIEW1_ARB:  0x850a
3525      * GL_MODELVIEW2_ARB:  0x8722
3526      * GL_MODELVIEW3_ARB:  0x8723
3527      * etc
3528      * GL_MODELVIEW31_ARB: 0x873F
3529      */
3530     if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
3531     else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
3532
3533     glMatrixMode(glMat);
3534     checkGLcall("glMatrixMode(glMat)");
3535
3536     /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
3537      * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
3538      */
3539     if(stateblock->wineD3DDevice->view_ident) {
3540         glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3541         checkGLcall("glLoadMatrixf");
3542     } else {
3543         glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3544         checkGLcall("glLoadMatrixf");
3545         glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3546         checkGLcall("glMultMatrixf");
3547     }
3548 }
3549
3550 static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3551     static BOOL once = FALSE;
3552
3553     switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) {
3554         case WINED3DVBF_1WEIGHTS:
3555         case WINED3DVBF_2WEIGHTS:
3556         case WINED3DVBF_3WEIGHTS:
3557             if(!once) {
3558                 once = TRUE;
3559                 /* TODO: Implement vertex blending in drawStridedSlow */
3560                 FIXME("Vertex blending enabled, but not supported by hardware\n");
3561             }
3562             break;
3563
3564         case WINED3DVBF_TWEENING:
3565             WARN("Tweening not supported yet\n");
3566     }
3567 }
3568
3569 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3570     WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
3571
3572     switch(val) {
3573         case WINED3DVBF_1WEIGHTS:
3574         case WINED3DVBF_2WEIGHTS:
3575         case WINED3DVBF_3WEIGHTS:
3576             glEnable(GL_VERTEX_BLEND_ARB);
3577             checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
3578
3579             /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
3580              * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
3581              */
3582             GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
3583
3584             if(!stateblock->wineD3DDevice->vertexBlendUsed) {
3585                 unsigned int i;
3586                 for(i = 1; i < GL_LIMITS(blends); i++) {
3587                     if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
3588                         transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
3589                     }
3590                 }
3591                 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
3592             }
3593             break;
3594
3595         case WINED3DVBF_DISABLE:
3596         case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
3597             glDisable(GL_VERTEX_BLEND_ARB);
3598             checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
3599             break;
3600
3601         case WINED3DVBF_TWEENING:
3602             /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
3603              * vertex weights in the vertices?
3604              * For now we don't report that as supported, so a warn should suffice
3605              */
3606             WARN("Tweening not supported yet\n");
3607             break;
3608     }
3609 }
3610
3611 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3612     unsigned int k;
3613
3614     /* If we are changing the View matrix, reset the light and clipping planes to the new view
3615      * NOTE: We have to reset the positions even if the light/plane is not currently
3616      *       enabled, since the call to enable it will not reset the position.
3617      * NOTE2: Apparently texture transforms do NOT need reapplying
3618      */
3619
3620     const PLIGHTINFOEL *light = NULL;
3621
3622     glMatrixMode(GL_MODELVIEW);
3623     checkGLcall("glMatrixMode(GL_MODELVIEW)");
3624     glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3625     checkGLcall("glLoadMatrixf(...)");
3626
3627     /* Reset lights. TODO: Call light apply func */
3628     for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
3629         light = stateblock->activeLights[k];
3630         if(!light) continue;
3631         glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
3632         checkGLcall("glLightfv posn");
3633         glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
3634         checkGLcall("glLightfv dirn");
3635     }
3636
3637     /* Reset Clipping Planes  */
3638     for (k = 0; k < GL_LIMITS(clipplanes); k++) {
3639         if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
3640             clipplane(STATE_CLIPPLANE(k), stateblock, context);
3641         }
3642     }
3643
3644     if(context->last_was_rhw) {
3645         glLoadIdentity();
3646         checkGLcall("glLoadIdentity()");
3647         /* No need to update the world matrix, the identity is fine */
3648         return;
3649     }
3650
3651     /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3652      * No need to do it here if the state is scheduled for update.
3653      */
3654     if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3655         transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3656     }
3657
3658     /* Avoid looping over a number of matrices if the app never used the functionality */
3659     if(stateblock->wineD3DDevice->vertexBlendUsed) {
3660         for(k = 1; k < GL_LIMITS(blends); k++) {
3661             if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
3662                 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
3663             }
3664         }
3665     }
3666 }
3667
3668 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3669     glMatrixMode(GL_PROJECTION);
3670     checkGLcall("glMatrixMode(GL_PROJECTION)");
3671     glLoadIdentity();
3672     checkGLcall("glLoadIdentity");
3673
3674     if(context->last_was_rhw) {
3675         double X, Y, height, width, minZ, maxZ;
3676
3677         X      = stateblock->viewport.X;
3678         Y      = stateblock->viewport.Y;
3679         height = stateblock->viewport.Height;
3680         width  = stateblock->viewport.Width;
3681         minZ   = stateblock->viewport.MinZ;
3682         maxZ   = stateblock->viewport.MaxZ;
3683
3684         if(!stateblock->wineD3DDevice->untransformed) {
3685             /* Transformed vertices are supposed to bypass the whole transform pipeline including
3686              * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
3687              * suppress depth clipping. This can be done because it is an orthogonal projection and
3688              * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
3689              * Persia 3D need this.
3690              *
3691              * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
3692              * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
3693              * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
3694              * to the viewer.
3695              *
3696              * Also note that this breaks z comparison against z values filled in with clear,
3697              * but no app depending on that and disabled clipping has been found yet. Comparing
3698              * primitives against themselves works, so the Z buffer is still intact for normal hidden
3699              * surface removal.
3700              *
3701              * We could disable clipping entirely by setting the near to infinity and far to -infinity,
3702              * but this would break Z buffer operation. Raising the range to something less than
3703              * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
3704              * problem either.
3705              */
3706             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
3707             if(stateblock->wineD3DDevice->render_offscreen) {
3708                 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
3709             } else {
3710                 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
3711             }
3712         } else {
3713             /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
3714              * trick above because this would mess up transformed and untransformed Z order. Pass the z position
3715              * unmodified to opengl.
3716              *
3717              * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
3718              * replacement shader.
3719              */
3720             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
3721             if(stateblock->wineD3DDevice->render_offscreen) {
3722                 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
3723             } else {
3724                 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
3725             }
3726         }
3727         checkGLcall("glOrtho");
3728
3729         /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
3730         glTranslatef(0.5, 0.5, 0);
3731         checkGLcall("glTranslatef(0.5, 0.5, 0)");
3732         /* D3D texture coordinates are flipped compared to OpenGL ones, so
3733          * render everything upside down when rendering offscreen. */
3734         if (stateblock->wineD3DDevice->render_offscreen) {
3735             glScalef(1.0, -1.0, 1.0);
3736             checkGLcall("glScalef");
3737         }
3738     } else {
3739         /* The rule is that the window coordinate 0 does not correspond to the
3740             beginning of the first pixel, but the center of the first pixel.
3741             As a consequence if you want to correctly draw one line exactly from
3742             the left to the right end of the viewport (with all matrices set to
3743             be identity), the x coords of both ends of the line would be not
3744             -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
3745             instead.
3746
3747             1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
3748             divide by the Width/Height, so we need the half range(1.0) to translate by
3749             half a pixel.
3750
3751             The other fun is that d3d's output z range after the transformation is [0;1],
3752             but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
3753             scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
3754             of Z buffer precision and the clear values do not match in the z test. Thus scale
3755             [0;1] to [-1;1], so when gl undoes that we utilize the full z range
3756          */
3757
3758         /*
3759          * Careful with the order of operations here, we're essentially working backwards:
3760          * x = x + 1/w;
3761          * y = (y - 1/h) * flip;
3762          * z = z * 2 - 1;
3763          *
3764          * Becomes:
3765          * glTranslatef(0.0, 0.0, -1.0);
3766          * glScalef(1.0, 1.0, 2.0);
3767          *
3768          * glScalef(1.0, flip, 1.0);
3769          * glTranslatef(1/w, -1/h, 0.0);
3770          *
3771          * This is equivalent to:
3772          * glTranslatef(1/w, -flip/h, -1.0)
3773          * glScalef(1.0, flip, 2.0);
3774          */
3775
3776         if (stateblock->wineD3DDevice->render_offscreen) {
3777             /* D3D texture coordinates are flipped compared to OpenGL ones, so
3778              * render everything upside down when rendering offscreen. */
3779             glTranslatef(1.0 / stateblock->viewport.Width, 1.0 / stateblock->viewport.Height, -1.0);
3780             checkGLcall("glTranslatef(1.0 / width, 1.0 / height, -1.0)");
3781             glScalef(1.0, -1.0, 2.0);
3782         } else {
3783             glTranslatef(1.0 / stateblock->viewport.Width, -1.0 / stateblock->viewport.Height, -1.0);
3784             checkGLcall("glTranslatef(1.0 / width, -1.0 / height, -1.0)");
3785             glScalef(1.0, 1.0, 2.0);
3786         }
3787         checkGLcall("glScalef");
3788
3789         glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
3790         checkGLcall("glLoadMatrixf");
3791     }
3792 }
3793
3794 /* This should match any arrays loaded in loadVertexData.
3795  * stateblock impl is required for GL_SUPPORT
3796  * TODO: Only load / unload arrays if we have to.
3797  */
3798 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
3799     glDisableClientState(GL_VERTEX_ARRAY);
3800     glDisableClientState(GL_NORMAL_ARRAY);
3801     glDisableClientState(GL_COLOR_ARRAY);
3802     if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3803         glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3804     }
3805     if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3806         glDisableClientState(GL_WEIGHT_ARRAY_ARB);
3807     }
3808     unloadTexCoords(stateblock);
3809 }
3810
3811 static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context, int i)
3812 {
3813     GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3814     checkGLcall("glDisableVertexAttribArrayARB(reg)");
3815     /* Some Windows drivers(NV GF 7) use the latest value that was used when drawing with the now
3816      * deactivated stream disabled, some other drivers(ATI, NV GF 8) set the undefined values to 0x00.
3817      * Let's set them to 0x00 to avoid hitting some undefined aspects of OpenGL. All that is really
3818      * important here is the glDisableVertexAttribArrayARB call above. The test shows that the refrast
3819      * keeps dereferencing the pointers, which would cause crashes in some games like Half Life 2: Episode Two.
3820      */
3821     GL_EXTCALL(glVertexAttrib4NubARB(i, 0, 0, 0, 0));
3822     checkGLcall("glVertexAttrib4NubARB(i, 0, 0, 0, 0)");
3823
3824     context->numbered_array_mask &= ~(1 << i);
3825 }
3826
3827 /* This should match any arrays loaded in loadNumberedArrays
3828  * TODO: Only load / unload arrays if we have to.
3829  */
3830 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context)
3831 {
3832     /* disable any attribs (this is the same for both GLSL and ARB modes) */
3833     GLint maxAttribs = 16;
3834     int i;
3835
3836     /* Leave all the attribs disabled */
3837     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
3838     /* MESA does not support it right not */
3839     if (glGetError() != GL_NO_ERROR)
3840         maxAttribs = 16;
3841     for (i = 0; i < maxAttribs; ++i) {
3842         unload_numbered_array(stateblock, context, i);
3843     }
3844 }
3845
3846 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock,
3847         const struct wined3d_stream_info *stream_info, WineD3DContext *context)
3848 {
3849     GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3850     int i;
3851     const UINT *offset = stateblock->streamOffset;
3852     struct wined3d_buffer *vb;
3853     DWORD_PTR shift_index;
3854
3855     /* Default to no instancing */
3856     stateblock->wineD3DDevice->instancedDraw = FALSE;
3857
3858     for (i = 0; i < MAX_ATTRIBS; i++) {
3859         if (!(stream_info->use_map & (1 << i)))
3860         {
3861             if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3862             continue;
3863         }
3864
3865         /* Do not load instance data. It will be specified using glTexCoord by drawprim */
3866         if (stateblock->streamFlags[stream_info->elements[i].stream_idx] & WINED3DSTREAMSOURCE_INSTANCEDATA)
3867         {
3868             if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3869             stateblock->wineD3DDevice->instancedDraw = TRUE;
3870             continue;
3871         }
3872
3873         TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, stream_info->elements[i].buffer_object);
3874
3875         if (stream_info->elements[i].stride)
3876         {
3877             if (curVBO != stream_info->elements[i].buffer_object)
3878             {
3879                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, stream_info->elements[i].buffer_object));
3880                 checkGLcall("glBindBufferARB");
3881                 curVBO = stream_info->elements[i].buffer_object;
3882             }
3883             vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
3884             /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
3885              * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
3886              * vbo we won't be load converted attributes anyway
3887              */
3888             if (curVBO && vb->conversion_shift)
3889             {
3890                 TRACE("Loading attribute from shifted buffer\n");
3891                 TRACE("Attrib %d has original stride %d, new stride %d\n",
3892                         i, stream_info->elements[i].stride, vb->conversion_stride);
3893                 TRACE("Original offset %p, additional offset 0x%08x\n",
3894                         stream_info->elements[i].data, vb->conversion_shift[(DWORD_PTR)stream_info->elements[i].data]);
3895                 TRACE("Opengl type %#x\n", stream_info->elements[i].format_desc->gl_vtx_type);
3896                 shift_index = ((DWORD_PTR)stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx]);
3897                 shift_index = shift_index % stream_info->elements[i].stride;
3898                 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format_desc->gl_vtx_format,
3899                         stream_info->elements[i].format_desc->gl_vtx_type,
3900                         stream_info->elements[i].format_desc->gl_normalized,
3901                         vb->conversion_stride, stream_info->elements[i].data + vb->conversion_shift[shift_index]
3902                         + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
3903                         + offset[stream_info->elements[i].stream_idx]));
3904
3905             } else {
3906                 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format_desc->gl_vtx_format,
3907                         stream_info->elements[i].format_desc->gl_vtx_type,
3908                         stream_info->elements[i].format_desc->gl_normalized,
3909                         stream_info->elements[i].stride, stream_info->elements[i].data
3910                         + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
3911                         + offset[stream_info->elements[i].stream_idx]));
3912             }
3913
3914             if (!(context->numbered_array_mask & (1 << i)))
3915             {
3916                 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
3917                 context->numbered_array_mask |= (1 << i);
3918             }
3919         } else {
3920             /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
3921              * set up the attribute statically. But we have to figure out the system memory address.
3922              */
3923             const BYTE *ptr = stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx];
3924             if (stream_info->elements[i].buffer_object)
3925             {
3926                 vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
3927                 ptr += (long) buffer_get_sysmem(vb);
3928             }
3929
3930             if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3931
3932             switch (stream_info->elements[i].format_desc->format)
3933             {
3934                 case WINED3DFMT_R32_FLOAT:
3935                     GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
3936                     break;
3937                 case WINED3DFMT_R32G32_FLOAT:
3938                     GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
3939                     break;
3940                 case WINED3DFMT_R32G32B32_FLOAT:
3941                     GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
3942                     break;
3943                 case WINED3DFMT_R32G32B32A32_FLOAT:
3944                     GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
3945                     break;
3946
3947                 case WINED3DFMT_R8G8B8A8_UINT:
3948                     GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3949                     break;
3950                 case WINED3DFMT_A8R8G8B8:
3951                     if (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA))
3952                     {
3953                         const DWORD *src = (const DWORD *)ptr;
3954                         DWORD c = *src & 0xff00ff00;
3955                         c |= (*src & 0xff0000) >> 16;
3956                         c |= (*src & 0xff) << 16;
3957                         GL_EXTCALL(glVertexAttrib4NubvARB(i, (GLubyte *)&c));
3958                         break;
3959                     }
3960                     /* else fallthrough */
3961                 case WINED3DFMT_R8G8B8A8_UNORM:
3962                     GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3963                     break;
3964
3965                 case WINED3DFMT_R16G16_SINT:
3966                     GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3967                     break;
3968                 case WINED3DFMT_R16G16B16A16_SINT:
3969                     GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3970                     break;
3971
3972                 case WINED3DFMT_R16G16_SNORM:
3973                 {
3974                     const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
3975                     GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
3976                     break;
3977                 }
3978                 case WINED3DFMT_R16G16_UNORM:
3979                 {
3980                     const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
3981                     GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
3982                     break;
3983                 }
3984                 case WINED3DFMT_R16G16B16A16_SNORM:
3985                     GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
3986                     break;
3987                 case WINED3DFMT_R16G16B16A16_UNORM:
3988                     GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
3989                     break;
3990
3991                 case WINED3DFMT_R10G10B10A2_UINT:
3992                     FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
3993                     /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
3994                     break;
3995                 case WINED3DFMT_R10G10B10A2_SNORM:
3996                     FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
3997                     /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
3998                     break;
3999
4000                 case WINED3DFMT_R16G16_FLOAT:
4001                     /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
4002                      * byte float according to the IEEE standard
4003                      */
4004                     FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
4005                     break;
4006                 case WINED3DFMT_R16G16B16A16_FLOAT:
4007                     FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
4008                     break;
4009
4010                 default:
4011                     ERR("Unexpected declaration in stride 0 attributes\n");
4012                     break;
4013
4014             }
4015         }
4016     }
4017     checkGLcall("Loading numbered arrays");
4018 }
4019
4020 /* Used from 2 different functions, and too big to justify making it inlined */
4021 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wined3d_stream_info *si)
4022 {
4023     const UINT *offset = stateblock->streamOffset;
4024     GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
4025     const struct wined3d_stream_info_element *e;
4026
4027     TRACE("Using fast vertex array code\n");
4028
4029     /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
4030     stateblock->wineD3DDevice->instancedDraw = FALSE;
4031
4032     /* Blend Data ---------------------------------------------- */
4033     e = &si->elements[WINED3D_FFP_BLENDWEIGHT];
4034     if (e->data || e->buffer_object
4035             || si->elements[WINED3D_FFP_BLENDINDICES].data
4036             || si->elements[WINED3D_FFP_BLENDINDICES].buffer_object)
4037     {
4038         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4039             TRACE("Blend %d %p %d\n", e->format_desc->component_count,
4040                     e->data + stateblock->loadBaseVertexIndex * e->stride, e->stride + offset[e->stream_idx]);
4041
4042             glEnableClientState(GL_WEIGHT_ARRAY_ARB);
4043             checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
4044
4045             GL_EXTCALL(glVertexBlendARB(e->format_desc->component_count + 1));
4046
4047             VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
4048                 WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) ,
4049                 sd->u.s.blendWeights.dwStride,
4050                 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
4051
4052             if (curVBO != e->buffer_object)
4053             {
4054                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4055                 checkGLcall("glBindBufferARB");
4056                 curVBO = e->buffer_object;
4057             }
4058
4059             GL_EXTCALL(glWeightPointerARB)(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4060                 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4061
4062             checkGLcall("glWeightPointerARB");
4063
4064             if (si->elements[WINED3D_FFP_BLENDINDICES].data
4065                     || (si->elements[WINED3D_FFP_BLENDINDICES].buffer_object))
4066             {
4067                 static BOOL warned;
4068                 if (!warned)
4069                 {
4070                     FIXME("blendMatrixIndices support\n");
4071                     warned = TRUE;
4072                 }
4073             }
4074         } else {
4075             /* TODO: support blends in drawStridedSlow
4076              * No need to write a FIXME here, this is done after the general vertex decl decoding
4077              */
4078             WARN("unsupported blending in openGl\n");
4079         }
4080     } else {
4081         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4082             static const GLbyte one = 1;
4083             GL_EXTCALL(glWeightbvARB(1, &one));
4084             checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
4085         }
4086     }
4087
4088     /* Point Size ----------------------------------------------*/
4089     e = &si->elements[WINED3D_FFP_PSIZE];
4090     if (e->data || e->buffer_object)
4091     {
4092         /* no such functionality in the fixed function GL pipeline */
4093         TRACE("Cannot change ptSize here in openGl\n");
4094         /* TODO: Implement this function in using shaders if they are available */
4095     }
4096
4097     /* Vertex Pointers -----------------------------------------*/
4098     e = &si->elements[WINED3D_FFP_POSITION];
4099     if (e->data || e->buffer_object)
4100     {
4101         VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n", e->stride, e->size, e->data));
4102
4103         if (curVBO != e->buffer_object)
4104         {
4105             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4106             checkGLcall("glBindBufferARB");
4107             curVBO = e->buffer_object;
4108         }
4109
4110         /* min(WINED3D_ATR_FORMAT(position),3) to Disable RHW mode as 'w' coord
4111            handling for rhw mode should not impact screen position whereas in GL it does.
4112            This may result in very slightly distorted textures in rhw mode.
4113            There's always the other option of fixing the view matrix to
4114            prevent w from having any effect.
4115
4116            This only applies to user pointer sources, in VBOs the vertices are fixed up
4117          */
4118         if (!e->buffer_object)
4119         {
4120             glVertexPointer(3 /* min(e->format_desc->gl_vtx_format, 3) */, e->format_desc->gl_vtx_type, e->stride,
4121                     e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4122         } else {
4123             glVertexPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4124                     e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4125         }
4126         checkGLcall("glVertexPointer(...)");
4127         glEnableClientState(GL_VERTEX_ARRAY);
4128         checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
4129     }
4130
4131     /* Normals -------------------------------------------------*/
4132     e = &si->elements[WINED3D_FFP_NORMAL];
4133     if (e->data || e->buffer_object)
4134     {
4135         VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n", e->stride, e->data));
4136         if (curVBO != e->buffer_object)
4137         {
4138             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4139             checkGLcall("glBindBufferARB");
4140             curVBO = e->buffer_object;
4141         }
4142         glNormalPointer(e->format_desc->gl_vtx_type, e->stride,
4143                 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4144         checkGLcall("glNormalPointer(...)");
4145         glEnableClientState(GL_NORMAL_ARRAY);
4146         checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
4147
4148     } else {
4149         glNormal3f(0, 0, 0);
4150         checkGLcall("glNormal3f(0, 0, 0)");
4151     }
4152
4153     /* Diffuse Colour --------------------------------------------*/
4154     /*  WARNING: Data here MUST be in RGBA format, so cannot      */
4155     /*     go directly into fast mode from app pgm, because       */
4156     /*     directx requires data in BGRA format.                  */
4157     /* currently fixupVertices swizzles the format, but this isn't*/
4158     /* very practical when using VBOs                             */
4159     /* NOTE: Unless we write a vertex shader to swizzle the colour*/
4160     /* , or the user doesn't care and wants the speed advantage   */
4161
4162     e = &si->elements[WINED3D_FFP_DIFFUSE];
4163     if (e->data || e->buffer_object)
4164     {
4165         VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data));
4166
4167         if (curVBO != e->buffer_object)
4168         {
4169             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4170             checkGLcall("glBindBufferARB");
4171             curVBO = e->buffer_object;
4172         }
4173
4174         glColorPointer(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type, e->stride,
4175                 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4176         checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
4177         glEnableClientState(GL_COLOR_ARRAY);
4178         checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
4179
4180     } else {
4181         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
4182         checkGLcall("glColor4f(1, 1, 1, 1)");
4183     }
4184
4185     /* Specular Colour ------------------------------------------*/
4186     e = &si->elements[WINED3D_FFP_SPECULAR];
4187     if (e->data || e->buffer_object)
4188     {
4189         TRACE("setting specular colour\n");
4190         VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data));
4191
4192         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4193             if (curVBO != e->buffer_object)
4194             {
4195                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4196                 checkGLcall("glBindBufferARB");
4197                 curVBO = e->buffer_object;
4198             }
4199             GL_EXTCALL(glSecondaryColorPointerEXT)(e->format_desc->gl_vtx_format, e->format_desc->gl_vtx_type,
4200                     e->stride, e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4201             checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
4202             glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4203             checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
4204         } else {
4205
4206         /* Missing specular color is not critical, no warnings */
4207         VTRACE(("Specular colour is not supported in this GL implementation\n"));
4208         }
4209
4210     } else {
4211         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4212             GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
4213             checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
4214         } else {
4215
4216             /* Missing specular color is not critical, no warnings */
4217             VTRACE(("Specular colour is not supported in this GL implementation\n"));
4218         }
4219     }
4220
4221     /* Texture coords -------------------------------------------*/
4222     loadTexCoords(stateblock, si, &curVBO);
4223 }
4224
4225 static inline void drawPrimitiveTraceDataLocations(const struct wined3d_stream_info *dataLocations)
4226 {
4227     /* Dump out what parts we have supplied */
4228     TRACE("Strided Data:\n");
4229     TRACE_STRIDED((dataLocations), WINED3D_FFP_POSITION);
4230     TRACE_STRIDED((dataLocations), WINED3D_FFP_BLENDWEIGHT);
4231     TRACE_STRIDED((dataLocations), WINED3D_FFP_BLENDINDICES);
4232     TRACE_STRIDED((dataLocations), WINED3D_FFP_NORMAL);
4233     TRACE_STRIDED((dataLocations), WINED3D_FFP_PSIZE);
4234     TRACE_STRIDED((dataLocations), WINED3D_FFP_DIFFUSE);
4235     TRACE_STRIDED((dataLocations), WINED3D_FFP_SPECULAR);
4236     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD0);
4237     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD1);
4238     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD2);
4239     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD3);
4240     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD4);
4241     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD5);
4242     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD6);
4243     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD7);
4244
4245     return;
4246 }
4247
4248 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4249     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4250     BOOL fixup = FALSE;
4251     struct wined3d_stream_info *dataLocations = &device->strided_streams;
4252     BOOL useVertexShaderFunction;
4253     BOOL load_numbered = FALSE;
4254     BOOL load_named = FALSE;
4255
4256     useVertexShaderFunction = (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader) ? TRUE : FALSE;
4257
4258     if(device->up_strided) {
4259         /* Note: this is a ddraw fixed-function code path */
4260         TRACE("================ Strided Input ===================\n");
4261         device_stream_info_from_strided(device, device->up_strided, dataLocations);
4262
4263         if(TRACE_ON(d3d)) {
4264             drawPrimitiveTraceDataLocations(dataLocations);
4265         }
4266     } else {
4267         /* Note: This is a fixed function or shader codepath.
4268          * This means it must handle both types of strided data.
4269          * Shaders must go through here to zero the strided data, even if they
4270          * don't set any declaration at all
4271          */
4272         TRACE("================ Vertex Declaration  ===================\n");
4273         device_stream_info_from_declaration(device, useVertexShaderFunction, dataLocations, &fixup);
4274     }
4275
4276     if (dataLocations->position_transformed) useVertexShaderFunction = FALSE;
4277
4278     if(useVertexShaderFunction) {
4279         if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
4280             TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
4281             device->useDrawStridedSlow = TRUE;
4282         } else {
4283             load_numbered = TRUE;
4284             device->useDrawStridedSlow = FALSE;
4285         }
4286     }
4287     else if (fixup || (!dataLocations->elements[WINED3D_FFP_PSIZE].data
4288             && !dataLocations->position_transformed
4289             && (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA)
4290             || (!dataLocations->elements[WINED3D_FFP_DIFFUSE].data
4291             && !dataLocations->elements[WINED3D_FFP_SPECULAR].data))))
4292     {
4293         /* Load the vertex data using named arrays */
4294         load_named = TRUE;
4295         device->useDrawStridedSlow = FALSE;
4296     } else {
4297         TRACE("Not loading vertex data\n");
4298         device->useDrawStridedSlow = TRUE;
4299     }
4300
4301     if (context->numberedArraysLoaded && !load_numbered)
4302     {
4303         unloadNumberedArrays(stateblock, context);
4304         context->numberedArraysLoaded = FALSE;
4305         context->numbered_array_mask = 0;
4306     }
4307     else if (context->namedArraysLoaded)
4308     {
4309         unloadVertexData(stateblock);
4310         context->namedArraysLoaded = FALSE;
4311     }
4312
4313     if (load_numbered)
4314     {
4315         TRACE("Loading numbered arrays\n");
4316         loadNumberedArrays(stateblock, dataLocations, context);
4317         context->numberedArraysLoaded = TRUE;
4318     }
4319     else if (load_named)
4320     {
4321         TRACE("Loading vertex data\n");
4322         loadVertexData(stateblock, dataLocations);
4323         context->namedArraysLoaded = TRUE;
4324     }
4325 }
4326
4327 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4328     BOOL updateFog = FALSE;
4329     BOOL useVertexShaderFunction = use_vs(stateblock);
4330     BOOL usePixelShaderFunction = use_ps(stateblock);
4331     BOOL transformed;
4332     /* Some stuff is in the device until we have per context tracking */
4333     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4334     BOOL wasrhw = context->last_was_rhw;
4335
4336     transformed = device->strided_streams.position_transformed;
4337     if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
4338         updateFog = TRUE;
4339     }
4340
4341     /* Reapply lighting if it is not scheduled for reapplication already */
4342     if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
4343         state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
4344     }
4345
4346     if (transformed) {
4347         context->last_was_rhw = TRUE;
4348     } else {
4349
4350         /* Untransformed, so relies on the view and projection matrices */
4351         context->last_was_rhw = FALSE;
4352         /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
4353         device->untransformed = TRUE;
4354
4355         /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
4356          * Not needed as long as only hw shaders are supported
4357          */
4358
4359         /* This sets the shader output position correction constants.
4360          * TODO: Move to the viewport state
4361          */
4362         if (useVertexShaderFunction) {
4363             device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
4364             device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
4365         }
4366     }
4367
4368     /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
4369      * off this function will be called again anyway to make sure they're properly set
4370      */
4371     if(!useVertexShaderFunction) {
4372         /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
4373          * or transformed / untransformed was switched
4374          */
4375        if(wasrhw != context->last_was_rhw &&
4376           !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
4377           !isStateDirty(context, STATE_VIEWPORT)) {
4378             transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4379         }
4380         /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
4381          * mode.
4382          *
4383          * If a vertex shader is used, the world matrix changed and then vertex shader unbound
4384          * this check will fail and the matrix not applied again. This is OK because a simple
4385          * world matrix change reapplies the matrix - These checks here are only to satisfy the
4386          * needs of the vertex declaration.
4387          *
4388          * World and view matrix go into the same gl matrix, so only apply them when neither is
4389          * dirty
4390          */
4391         if(transformed != wasrhw &&
4392            !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
4393            !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
4394             transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4395         }
4396
4397         if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
4398             state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
4399         }
4400
4401         if(context->last_was_vshader) {
4402             updateFog = TRUE;
4403             if(!isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
4404                 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
4405             }
4406         }
4407         if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
4408             state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
4409         }
4410     } else {
4411         if(!context->last_was_vshader) {
4412             unsigned int i;
4413             static BOOL warned = FALSE;
4414             /* Disable all clip planes to get defined results on all drivers. See comment in the
4415              * state_clipping state handler
4416              */
4417             for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4418                 glDisable(GL_CLIP_PLANE0 + i);
4419                 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
4420             }
4421
4422             if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
4423                 FIXME("Clipping not supported with vertex shaders\n");
4424                 warned = TRUE;
4425             }
4426             if(wasrhw) {
4427                 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
4428                  * shaders themselves do not need it, but the matrices are not reapplied automatically when
4429                  * switching back from vertex shaders to fixed function processing. So make sure we leave the
4430                  * fixed function vertex processing states back in a sane state before switching to shaders
4431                  */
4432                 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4433                     transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4434                 }
4435                 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
4436                     transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4437                 }
4438             }
4439             updateFog = TRUE;
4440         }
4441     }
4442
4443     /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
4444      * application
4445      */
4446     if (!isStateDirty(context, STATE_PIXELSHADER)) {
4447         device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
4448
4449         if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
4450             shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4451         }
4452     }
4453
4454     context->last_was_vshader = useVertexShaderFunction;
4455
4456     if(updateFog) {
4457         device->StateTable[STATE_RENDER(WINED3DRS_FOGVERTEXMODE)].apply(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context);
4458     }
4459     if(!useVertexShaderFunction) {
4460         int i;
4461         for(i = 0; i < MAX_TEXTURES; i++) {
4462             if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
4463                 transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
4464             }
4465         }
4466     }
4467 }
4468
4469 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4470     UINT width, height;
4471     IWineD3DSurfaceImpl *target;
4472
4473     glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
4474     checkGLcall("glDepthRange");
4475     /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
4476      */
4477     if(stateblock->wineD3DDevice->render_offscreen) {
4478         glViewport(stateblock->viewport.X,
4479                    stateblock->viewport.Y,
4480                    stateblock->viewport.Width, stateblock->viewport.Height);
4481     } else {
4482         target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4483         target->get_drawable_size(target, &width, &height);
4484
4485         glViewport(stateblock->viewport.X,
4486                    (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
4487                    stateblock->viewport.Width, stateblock->viewport.Height);
4488     }
4489
4490     checkGLcall("glViewport");
4491 }
4492
4493 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4494     stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
4495     stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
4496     if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4497         transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4498     }
4499     if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
4500         state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
4501     }
4502 }
4503
4504 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4505     UINT Index = state - STATE_ACTIVELIGHT(0);
4506     const PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
4507
4508     if(!lightInfo) {
4509         glDisable(GL_LIGHT0 + Index);
4510         checkGLcall("glDisable(GL_LIGHT0 + Index)");
4511     } else {
4512         float quad_att;
4513         float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
4514
4515         /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4516         glMatrixMode(GL_MODELVIEW);
4517         glPushMatrix();
4518         glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
4519
4520         /* Diffuse: */
4521         colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
4522         colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
4523         colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
4524         colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
4525         glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
4526         checkGLcall("glLightfv");
4527
4528         /* Specular */
4529         colRGBA[0] = lightInfo->OriginalParms.Specular.r;
4530         colRGBA[1] = lightInfo->OriginalParms.Specular.g;
4531         colRGBA[2] = lightInfo->OriginalParms.Specular.b;
4532         colRGBA[3] = lightInfo->OriginalParms.Specular.a;
4533         glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
4534         checkGLcall("glLightfv");
4535
4536         /* Ambient */
4537         colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
4538         colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
4539         colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
4540         colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
4541         glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
4542         checkGLcall("glLightfv");
4543
4544         if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
4545             quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
4546         } else {
4547             quad_att = 0; /*  0 or  MAX?  (0 seems to be ok) */
4548         }
4549
4550         /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
4551          * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
4552          * Attenuation0 to NaN and crashes in the gl lib
4553          */
4554
4555         switch (lightInfo->OriginalParms.Type) {
4556             case WINED3DLIGHT_POINT:
4557                 /* Position */
4558                 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4559                 checkGLcall("glLightfv");
4560                 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4561                 checkGLcall("glLightf");
4562                 /* Attenuation - Are these right? guessing... */
4563                 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
4564                 checkGLcall("glLightf");
4565                 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
4566                 checkGLcall("glLightf");
4567                 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4568                 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4569                 checkGLcall("glLightf");
4570                 /* FIXME: Range */
4571                 break;
4572
4573             case WINED3DLIGHT_SPOT:
4574                 /* Position */
4575                 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4576                 checkGLcall("glLightfv");
4577                 /* Direction */
4578                 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
4579                 checkGLcall("glLightfv");
4580                 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4581                 checkGLcall("glLightf");
4582                 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4583                 checkGLcall("glLightf");
4584                 /* Attenuation - Are these right? guessing... */
4585                 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
4586                 checkGLcall("glLightf");
4587                 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
4588                 checkGLcall("glLightf");
4589                 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4590                 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4591                 checkGLcall("glLightf");
4592                 /* FIXME: Range */
4593                 break;
4594
4595             case WINED3DLIGHT_DIRECTIONAL:
4596                 /* Direction */
4597                 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
4598                 checkGLcall("glLightfv");
4599                 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4600                 checkGLcall("glLightf");
4601                 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4602                 checkGLcall("glLightf");
4603                 break;
4604
4605             default:
4606                 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
4607         }
4608
4609         /* Restore the modelview matrix */
4610         glPopMatrix();
4611
4612         glEnable(GL_LIGHT0 + Index);
4613         checkGLcall("glEnable(GL_LIGHT0 + Index)");
4614     }
4615
4616     return;
4617 }
4618
4619 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4620     RECT *pRect = &stateblock->scissorRect;
4621     UINT height;
4622     UINT width;
4623     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4624
4625     target->get_drawable_size(target, &width, &height);
4626     /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4627      * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4628      */
4629     TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
4630           pRect->right - pRect->left, pRect->bottom - pRect->top);
4631
4632     if (stateblock->wineD3DDevice->render_offscreen) {
4633         glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4634     } else {
4635         glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4636     }
4637     checkGLcall("glScissor");
4638 }
4639
4640 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4641     if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
4642         GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
4643     } else {
4644         struct wined3d_buffer *ib = (struct wined3d_buffer *) stateblock->pIndexData;
4645         GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->buffer_object));
4646     }
4647 }
4648
4649 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4650     if(stateblock->wineD3DDevice->render_offscreen) {
4651         glFrontFace(GL_CCW);
4652         checkGLcall("glFrontFace(GL_CCW)");
4653     } else {
4654         glFrontFace(GL_CW);
4655         checkGLcall("glFrontFace(GL_CW)");
4656     }
4657 }
4658
4659 const struct StateEntryTemplate misc_state_template[] = {
4660     { STATE_RENDER(WINED3DRS_SRCBLEND),                   { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4661     { STATE_RENDER(WINED3DRS_DESTBLEND),                  { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4662     { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4663     { STATE_RENDER(WINED3DRS_EDGEANTIALIAS),              { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4664     { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE),      { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4665     { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE),   { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4666     { STATE_RENDER(WINED3DRS_SRCBLENDALPHA),              { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4667     { STATE_RENDER(WINED3DRS_DESTBLENDALPHA),             { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4668     { STATE_RENDER(WINED3DRS_DESTBLENDALPHA),             { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4669     { STATE_RENDER(WINED3DRS_BLENDOPALPHA),               { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4670     { STATE_STREAMSRC,                                    { STATE_VDECL,                                        streamsrc           }, 0                               },
4671     { STATE_VDECL,                                        { STATE_VDECL,                                        streamsrc           }, 0                               },
4672     { STATE_FRONTFACE,                                    { STATE_FRONTFACE,                                    frontface           }, 0                               },
4673     { STATE_SCISSORRECT,                                  { STATE_SCISSORRECT,                                  scissorrect         }, 0                               },
4674     /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
4675      * vshader loadings are untied from each other
4676      */
4677     { STATE_VERTEXSHADERCONSTANT,                         { STATE_VERTEXSHADERCONSTANT,                         shaderconstant      }, 0                               },
4678     { STATE_PIXELSHADERCONSTANT,                          { STATE_VERTEXSHADERCONSTANT,                         shaderconstant      }, 0                               },
4679     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4680     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4681     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4682     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4683     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4684     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4685     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4686     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4687     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4688     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4689     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4690     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4691     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4692     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4693     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4694     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4695     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4696     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4697     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4698     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4699     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4700     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4701     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4702     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4703     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4704     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4705     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4706     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4707     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4708     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4709     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4710     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4711     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4712     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4713     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4714     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4715     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4716     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4717     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4718     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4719     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4720     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4721     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4722     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4723     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4724     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4725     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4726     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4727
4728     { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_miscpart   }, 0                               },
4729     { STATE_INDEXBUFFER,                                  { STATE_INDEXBUFFER,                                  indexbuffer         }, ARB_VERTEX_BUFFER_OBJECT        },
4730     { STATE_RENDER(WINED3DRS_ANTIALIAS),                  { STATE_RENDER(WINED3DRS_ANTIALIAS),                  state_antialias     }, 0                               },
4731     { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE),         { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE),         state_perspective   }, 0                               },
4732     { STATE_RENDER(WINED3DRS_ZENABLE),                    { STATE_RENDER(WINED3DRS_ZENABLE),                    state_zenable       }, 0                               },
4733     { STATE_RENDER(WINED3DRS_WRAPU),                      { STATE_RENDER(WINED3DRS_WRAPU),                      state_wrapu         }, 0                               },
4734     { STATE_RENDER(WINED3DRS_WRAPV),                      { STATE_RENDER(WINED3DRS_WRAPV),                      state_wrapv         }, 0                               },
4735     { STATE_RENDER(WINED3DRS_FILLMODE),                   { STATE_RENDER(WINED3DRS_FILLMODE),                   state_fillmode      }, 0                               },
4736     { STATE_RENDER(WINED3DRS_SHADEMODE),                  { STATE_RENDER(WINED3DRS_SHADEMODE),                  state_shademode     }, 0                               },
4737     { STATE_RENDER(WINED3DRS_LINEPATTERN),                { STATE_RENDER(WINED3DRS_LINEPATTERN),                state_linepattern   }, 0                               },
4738     { STATE_RENDER(WINED3DRS_MONOENABLE),                 { STATE_RENDER(WINED3DRS_MONOENABLE),                 state_monoenable    }, 0                               },
4739     { STATE_RENDER(WINED3DRS_ROP2),                       { STATE_RENDER(WINED3DRS_ROP2),                       state_rop2          }, 0                               },
4740     { STATE_RENDER(WINED3DRS_PLANEMASK),                  { STATE_RENDER(WINED3DRS_PLANEMASK),                  state_planemask     }, 0                               },
4741     { STATE_RENDER(WINED3DRS_ZWRITEENABLE),               { STATE_RENDER(WINED3DRS_ZWRITEENABLE),               state_zwritenable   }, 0                               },
4742     { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
4743     { STATE_RENDER(WINED3DRS_ALPHAREF),                   { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
4744     { STATE_RENDER(WINED3DRS_ALPHAFUNC),                  { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
4745     { STATE_RENDER(WINED3DRS_COLORKEYENABLE),             { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
4746     { STATE_RENDER(WINED3DRS_LASTPIXEL),                  { STATE_RENDER(WINED3DRS_LASTPIXEL),                  state_lastpixel     }, 0                               },
4747     { STATE_RENDER(WINED3DRS_CULLMODE),                   { STATE_RENDER(WINED3DRS_CULLMODE),                   state_cullmode      }, 0                               },
4748     { STATE_RENDER(WINED3DRS_ZFUNC),                      { STATE_RENDER(WINED3DRS_ZFUNC),                      state_zfunc         }, 0                               },
4749     { STATE_RENDER(WINED3DRS_DITHERENABLE),               { STATE_RENDER(WINED3DRS_DITHERENABLE),               state_ditherenable  }, 0                               },
4750     { STATE_RENDER(WINED3DRS_SUBPIXEL),                   { STATE_RENDER(WINED3DRS_SUBPIXEL),                   state_subpixel      }, 0                               },
4751     { STATE_RENDER(WINED3DRS_SUBPIXELX),                  { STATE_RENDER(WINED3DRS_SUBPIXELX),                  state_subpixelx     }, 0                               },
4752     { STATE_RENDER(WINED3DRS_STIPPLEDALPHA),              { STATE_RENDER(WINED3DRS_STIPPLEDALPHA),              state_stippledalpha }, 0                               },
4753     { STATE_RENDER(WINED3DRS_ZBIAS),                      { STATE_RENDER(WINED3DRS_ZBIAS),                      state_zbias         }, 0                               },
4754     { STATE_RENDER(WINED3DRS_STIPPLEENABLE),              { STATE_RENDER(WINED3DRS_STIPPLEENABLE),              state_stippleenable }, 0                               },
4755     { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS),              { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS),              state_mipmaplodbias }, 0                               },
4756     { STATE_RENDER(WINED3DRS_ANISOTROPY),                 { STATE_RENDER(WINED3DRS_ANISOTROPY),                 state_anisotropy    }, 0                               },
4757     { STATE_RENDER(WINED3DRS_FLUSHBATCH),                 { STATE_RENDER(WINED3DRS_FLUSHBATCH),                 state_flushbatch    }, 0                               },
4758     { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, 0                               },
4759     { STATE_RENDER(WINED3DRS_STENCILENABLE),              { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4760     { STATE_RENDER(WINED3DRS_STENCILFAIL),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4761     { STATE_RENDER(WINED3DRS_STENCILZFAIL),               { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4762     { STATE_RENDER(WINED3DRS_STENCILPASS),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4763     { STATE_RENDER(WINED3DRS_STENCILFUNC),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4764     { STATE_RENDER(WINED3DRS_STENCILREF),                 { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4765     { STATE_RENDER(WINED3DRS_STENCILMASK),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4766     { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE            },
4767     { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           state_stencilwrite  }, 0                               },
4768     { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE),        { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4769     { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL),            { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4770     { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL),           { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4771     { STATE_RENDER(WINED3DRS_CCW_STENCILPASS),            { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4772     { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC),            { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4773     { STATE_RENDER(WINED3DRS_WRAP0),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4774     { STATE_RENDER(WINED3DRS_WRAP1),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4775     { STATE_RENDER(WINED3DRS_WRAP2),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4776     { STATE_RENDER(WINED3DRS_WRAP3),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4777     { STATE_RENDER(WINED3DRS_WRAP4),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4778     { STATE_RENDER(WINED3DRS_WRAP5),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4779     { STATE_RENDER(WINED3DRS_WRAP6),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4780     { STATE_RENDER(WINED3DRS_WRAP7),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4781     { STATE_RENDER(WINED3DRS_WRAP8),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4782     { STATE_RENDER(WINED3DRS_WRAP9),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4783     { STATE_RENDER(WINED3DRS_WRAP10),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4784     { STATE_RENDER(WINED3DRS_WRAP11),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4785     { STATE_RENDER(WINED3DRS_WRAP12),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4786     { STATE_RENDER(WINED3DRS_WRAP13),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4787     { STATE_RENDER(WINED3DRS_WRAP14),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4788     { STATE_RENDER(WINED3DRS_WRAP15),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4789     { STATE_RENDER(WINED3DRS_EXTENTS),                    { STATE_RENDER(WINED3DRS_EXTENTS),                    state_extents       }, 0                               },
4790     { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE),        { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE),        state_ckeyblend     }, 0                               },
4791     { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE),             { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE),             state_patchedgestyle}, 0                               },
4792     { STATE_RENDER(WINED3DRS_PATCHSEGMENTS),              { STATE_RENDER(WINED3DRS_PATCHSEGMENTS),              state_patchsegments }, 0                               },
4793     { STATE_RENDER(WINED3DRS_POSITIONDEGREE),             { STATE_RENDER(WINED3DRS_POSITIONDEGREE),             state_positiondegree}, 0                               },
4794     { STATE_RENDER(WINED3DRS_NORMALDEGREE),               { STATE_RENDER(WINED3DRS_NORMALDEGREE),               state_normaldegree  }, 0                               },
4795     { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL),       { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4796     { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL),       { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4797     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4798     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4799     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4800     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4801     { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4802     { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       state_msaa          }, ARB_MULTISAMPLE                 },
4803     { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       state_msaa_w        }, 0                               },
4804     { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK),            { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK),            state_multisampmask }, 0                               },
4805     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
4806     { STATE_RENDER(WINED3DRS_BLENDOP),                    { STATE_RENDER(WINED3DRS_BLENDOP),                    state_blendop       }, EXT_BLEND_MINMAX                },
4807     { STATE_RENDER(WINED3DRS_BLENDOP),                    { STATE_RENDER(WINED3DRS_BLENDOP),                    state_blendop_w     }, 0                               },
4808     { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE),          { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE),          state_scissor       }, 0                               },
4809     { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS),        { STATE_RENDER(WINED3DRS_DEPTHBIAS),                  state_depthbias     }, 0                               },
4810     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1),          { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
4811     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2),          { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
4812     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3),          { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
4813     { STATE_RENDER(WINED3DRS_BLENDFACTOR),                { STATE_RENDER(WINED3DRS_BLENDFACTOR),                state_blendfactor   }, EXT_BLEND_COLOR                 },
4814     { STATE_RENDER(WINED3DRS_BLENDFACTOR),                { STATE_RENDER(WINED3DRS_BLENDFACTOR),                state_blendfactor_w }, 0                               },
4815     { STATE_RENDER(WINED3DRS_DEPTHBIAS),                  { STATE_RENDER(WINED3DRS_DEPTHBIAS),                  state_depthbias     }, 0                               },
4816     /* Samplers */
4817     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler             }, 0                               },
4818     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler             }, 0                               },
4819     { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler             }, 0                               },
4820     { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler             }, 0                               },
4821     { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler             }, 0                               },
4822     { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler             }, 0                               },
4823     { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler             }, 0                               },
4824     { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler             }, 0                               },
4825     { STATE_SAMPLER(8),                                   { STATE_SAMPLER(8),                                   sampler             }, 0                               },
4826     { STATE_SAMPLER(9),                                   { STATE_SAMPLER(9),                                   sampler             }, 0                               },
4827     { STATE_SAMPLER(10),                                  { STATE_SAMPLER(10),                                  sampler             }, 0                               },
4828     { STATE_SAMPLER(11),                                  { STATE_SAMPLER(11),                                  sampler             }, 0                               },
4829     { STATE_SAMPLER(12),                                  { STATE_SAMPLER(12),                                  sampler             }, 0                               },
4830     { STATE_SAMPLER(13),                                  { STATE_SAMPLER(13),                                  sampler             }, 0                               },
4831     { STATE_SAMPLER(14),                                  { STATE_SAMPLER(14),                                  sampler             }, 0                               },
4832     { STATE_SAMPLER(15),                                  { STATE_SAMPLER(15),                                  sampler             }, 0                               },
4833     { STATE_SAMPLER(16), /* Vertex sampler 0 */           { STATE_SAMPLER(16),                                  sampler             }, 0                               },
4834     { STATE_SAMPLER(17), /* Vertex sampler 1 */           { STATE_SAMPLER(17),                                  sampler             }, 0                               },
4835     { STATE_SAMPLER(18), /* Vertex sampler 2 */           { STATE_SAMPLER(18),                                  sampler             }, 0                               },
4836     { STATE_SAMPLER(19), /* Vertex sampler 3 */           { STATE_SAMPLER(19),                                  sampler             }, 0                               },
4837     {0 /* Terminate */,                                   { 0,                                                  0                   }, 0                               },
4838 };
4839
4840 const struct StateEntryTemplate ffp_vertexstate_template[] = {
4841     { STATE_VDECL,                                        { STATE_VDECL,                                        vertexdeclaration   }, 0                               },
4842     { STATE_VSHADER,                                      { STATE_VDECL,                                        vertexdeclaration   }, 0                               },
4843     { STATE_MATERIAL,                                     { STATE_RENDER(WINED3DRS_SPECULARENABLE),             state_specularenable}, 0                               },
4844     { STATE_RENDER(WINED3DRS_SPECULARENABLE),             { STATE_RENDER(WINED3DRS_SPECULARENABLE),             state_specularenable}, 0                               },
4845       /* Clip planes */
4846     { STATE_CLIPPLANE(0),                                 { STATE_CLIPPLANE(0),                                 clipplane           }, 0                               },
4847     { STATE_CLIPPLANE(1),                                 { STATE_CLIPPLANE(1),                                 clipplane           }, 0                               },
4848     { STATE_CLIPPLANE(2),                                 { STATE_CLIPPLANE(2),                                 clipplane           }, 0                               },
4849     { STATE_CLIPPLANE(3),                                 { STATE_CLIPPLANE(3),                                 clipplane           }, 0                               },
4850     { STATE_CLIPPLANE(4),                                 { STATE_CLIPPLANE(4),                                 clipplane           }, 0                               },
4851     { STATE_CLIPPLANE(5),                                 { STATE_CLIPPLANE(5),                                 clipplane           }, 0                               },
4852     { STATE_CLIPPLANE(6),                                 { STATE_CLIPPLANE(6),                                 clipplane           }, 0                               },
4853     { STATE_CLIPPLANE(7),                                 { STATE_CLIPPLANE(7),                                 clipplane           }, 0                               },
4854     { STATE_CLIPPLANE(8),                                 { STATE_CLIPPLANE(8),                                 clipplane           }, 0                               },
4855     { STATE_CLIPPLANE(9),                                 { STATE_CLIPPLANE(9),                                 clipplane           }, 0                               },
4856     { STATE_CLIPPLANE(10),                                { STATE_CLIPPLANE(10),                                clipplane           }, 0                               },
4857     { STATE_CLIPPLANE(11),                                { STATE_CLIPPLANE(11),                                clipplane           }, 0                               },
4858     { STATE_CLIPPLANE(12),                                { STATE_CLIPPLANE(12),                                clipplane           }, 0                               },
4859     { STATE_CLIPPLANE(13),                                { STATE_CLIPPLANE(13),                                clipplane           }, 0                               },
4860     { STATE_CLIPPLANE(14),                                { STATE_CLIPPLANE(14),                                clipplane           }, 0                               },
4861     { STATE_CLIPPLANE(15),                                { STATE_CLIPPLANE(15),                                clipplane           }, 0                               },
4862     { STATE_CLIPPLANE(16),                                { STATE_CLIPPLANE(16),                                clipplane           }, 0                               },
4863     { STATE_CLIPPLANE(17),                                { STATE_CLIPPLANE(17),                                clipplane           }, 0                               },
4864     { STATE_CLIPPLANE(18),                                { STATE_CLIPPLANE(18),                                clipplane           }, 0                               },
4865     { STATE_CLIPPLANE(19),                                { STATE_CLIPPLANE(19),                                clipplane           }, 0                               },
4866     { STATE_CLIPPLANE(20),                                { STATE_CLIPPLANE(20),                                clipplane           }, 0                               },
4867     { STATE_CLIPPLANE(21),                                { STATE_CLIPPLANE(21),                                clipplane           }, 0                               },
4868     { STATE_CLIPPLANE(22),                                { STATE_CLIPPLANE(22),                                clipplane           }, 0                               },
4869     { STATE_CLIPPLANE(23),                                { STATE_CLIPPLANE(23),                                clipplane           }, 0                               },
4870     { STATE_CLIPPLANE(24),                                { STATE_CLIPPLANE(24),                                clipplane           }, 0                               },
4871     { STATE_CLIPPLANE(25),                                { STATE_CLIPPLANE(25),                                clipplane           }, 0                               },
4872     { STATE_CLIPPLANE(26),                                { STATE_CLIPPLANE(26),                                clipplane           }, 0                               },
4873     { STATE_CLIPPLANE(27),                                { STATE_CLIPPLANE(27),                                clipplane           }, 0                               },
4874     { STATE_CLIPPLANE(28),                                { STATE_CLIPPLANE(28),                                clipplane           }, 0                               },
4875     { STATE_CLIPPLANE(29),                                { STATE_CLIPPLANE(29),                                clipplane           }, 0                               },
4876     { STATE_CLIPPLANE(30),                                { STATE_CLIPPLANE(30),                                clipplane           }, 0                               },
4877     { STATE_CLIPPLANE(31),                                { STATE_CLIPPLANE(31),                                clipplane           }, 0                               },
4878       /* Lights */
4879     { STATE_ACTIVELIGHT(0),                               { STATE_ACTIVELIGHT(0),                               light               }, 0                               },
4880     { STATE_ACTIVELIGHT(1),                               { STATE_ACTIVELIGHT(1),                               light               }, 0                               },
4881     { STATE_ACTIVELIGHT(2),                               { STATE_ACTIVELIGHT(2),                               light               }, 0                               },
4882     { STATE_ACTIVELIGHT(3),                               { STATE_ACTIVELIGHT(3),                               light               }, 0                               },
4883     { STATE_ACTIVELIGHT(4),                               { STATE_ACTIVELIGHT(4),                               light               }, 0                               },
4884     { STATE_ACTIVELIGHT(5),                               { STATE_ACTIVELIGHT(5),                               light               }, 0                               },
4885     { STATE_ACTIVELIGHT(6),                               { STATE_ACTIVELIGHT(6),                               light               }, 0                               },
4886     { STATE_ACTIVELIGHT(7),                               { STATE_ACTIVELIGHT(7),                               light               }, 0                               },
4887     /* Viewport */
4888     { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_vertexpart }, 0                               },
4889       /* Transform states follow                    */
4890     { STATE_TRANSFORM(WINED3DTS_VIEW),                    { STATE_TRANSFORM(WINED3DTS_VIEW),                    transform_view      }, 0                               },
4891     { STATE_TRANSFORM(WINED3DTS_PROJECTION),              { STATE_TRANSFORM(WINED3DTS_PROJECTION),              transform_projection}, 0                               },
4892     { STATE_TRANSFORM(WINED3DTS_TEXTURE0),                { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4893     { STATE_TRANSFORM(WINED3DTS_TEXTURE1),                { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4894     { STATE_TRANSFORM(WINED3DTS_TEXTURE2),                { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4895     { STATE_TRANSFORM(WINED3DTS_TEXTURE3),                { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4896     { STATE_TRANSFORM(WINED3DTS_TEXTURE4),                { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4897     { STATE_TRANSFORM(WINED3DTS_TEXTURE5),                { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4898     { STATE_TRANSFORM(WINED3DTS_TEXTURE6),                { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4899     { STATE_TRANSFORM(WINED3DTS_TEXTURE7),                { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4900     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  0)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  0)),        transform_world     }, 0                               },
4901     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  1)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  1)),        transform_worldex   }, 0                               },
4902     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  2)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  2)),        transform_worldex   }, 0                               },
4903     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  3)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  3)),        transform_worldex   }, 0                               },
4904     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  4)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  4)),        transform_worldex   }, 0                               },
4905     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  5)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  5)),        transform_worldex   }, 0                               },
4906     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  6)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  6)),        transform_worldex   }, 0                               },
4907     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  7)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  7)),        transform_worldex   }, 0                               },
4908     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  8)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  8)),        transform_worldex   }, 0                               },
4909     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  9)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  9)),        transform_worldex   }, 0                               },
4910     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)),        transform_worldex   }, 0                               },
4911     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)),        transform_worldex   }, 0                               },
4912     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)),        transform_worldex   }, 0                               },
4913     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)),        transform_worldex   }, 0                               },
4914     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)),        transform_worldex   }, 0                               },
4915     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)),        transform_worldex   }, 0                               },
4916     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)),        transform_worldex   }, 0                               },
4917     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)),        transform_worldex   }, 0                               },
4918     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)),        transform_worldex   }, 0                               },
4919     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)),        transform_worldex   }, 0                               },
4920     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)),        transform_worldex   }, 0                               },
4921     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)),        transform_worldex   }, 0                               },
4922     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)),        transform_worldex   }, 0                               },
4923     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)),        transform_worldex   }, 0                               },
4924     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)),        transform_worldex   }, 0                               },
4925     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)),        transform_worldex   }, 0                               },
4926     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)),        transform_worldex   }, 0                               },
4927     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)),        transform_worldex   }, 0                               },
4928     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)),        transform_worldex   }, 0                               },
4929     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)),        transform_worldex   }, 0                               },
4930     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)),        transform_worldex   }, 0                               },
4931     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)),        transform_worldex   }, 0                               },
4932     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)),        transform_worldex   }, 0                               },
4933     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)),        transform_worldex   }, 0                               },
4934     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)),        transform_worldex   }, 0                               },
4935     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)),        transform_worldex   }, 0                               },
4936     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)),        transform_worldex   }, 0                               },
4937     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)),        transform_worldex   }, 0                               },
4938     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)),        transform_worldex   }, 0                               },
4939     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)),        transform_worldex   }, 0                               },
4940     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)),        transform_worldex   }, 0                               },
4941     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)),        transform_worldex   }, 0                               },
4942     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)),        transform_worldex   }, 0                               },
4943     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)),        transform_worldex   }, 0                               },
4944     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)),        transform_worldex   }, 0                               },
4945     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)),        transform_worldex   }, 0                               },
4946     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)),        transform_worldex   }, 0                               },
4947     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)),        transform_worldex   }, 0                               },
4948     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)),        transform_worldex   }, 0                               },
4949     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)),        transform_worldex   }, 0                               },
4950     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)),        transform_worldex   }, 0                               },
4951     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)),        transform_worldex   }, 0                               },
4952     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)),        transform_worldex   }, 0                               },
4953     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)),        transform_worldex   }, 0                               },
4954     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)),        transform_worldex   }, 0                               },
4955     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)),        transform_worldex   }, 0                               },
4956     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)),        transform_worldex   }, 0                               },
4957     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)),        transform_worldex   }, 0                               },
4958     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)),        transform_worldex   }, 0                               },
4959     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)),        transform_worldex   }, 0                               },
4960     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)),        transform_worldex   }, 0                               },
4961     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)),        transform_worldex   }, 0                               },
4962     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)),        transform_worldex   }, 0                               },
4963     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)),        transform_worldex   }, 0                               },
4964     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)),        transform_worldex   }, 0                               },
4965     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)),        transform_worldex   }, 0                               },
4966     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)),        transform_worldex   }, 0                               },
4967     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)),        transform_worldex   }, 0                               },
4968     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)),        transform_worldex   }, 0                               },
4969     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)),        transform_worldex   }, 0                               },
4970     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)),        transform_worldex   }, 0                               },
4971     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)),        transform_worldex   }, 0                               },
4972     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)),        transform_worldex   }, 0                               },
4973     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)),        transform_worldex   }, 0                               },
4974     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)),        transform_worldex   }, 0                               },
4975     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)),        transform_worldex   }, 0                               },
4976     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)),        transform_worldex   }, 0                               },
4977     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)),        transform_worldex   }, 0                               },
4978     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)),        transform_worldex   }, 0                               },
4979     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)),        transform_worldex   }, 0                               },
4980     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)),        transform_worldex   }, 0                               },
4981     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)),        transform_worldex   }, 0                               },
4982     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)),        transform_worldex   }, 0                               },
4983     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)),        transform_worldex   }, 0                               },
4984     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)),        transform_worldex   }, 0                               },
4985     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)),        transform_worldex   }, 0                               },
4986     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)),        transform_worldex   }, 0                               },
4987     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)),        transform_worldex   }, 0                               },
4988     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)),        transform_worldex   }, 0                               },
4989     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)),        transform_worldex   }, 0                               },
4990     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)),        transform_worldex   }, 0                               },
4991     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)),        transform_worldex   }, 0                               },
4992     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)),        transform_worldex   }, 0                               },
4993     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)),        transform_worldex   }, 0                               },
4994     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)),        transform_worldex   }, 0                               },
4995     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)),        transform_worldex   }, 0                               },
4996     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)),        transform_worldex   }, 0                               },
4997     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)),        transform_worldex   }, 0                               },
4998     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)),        transform_worldex   }, 0                               },
4999     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)),        transform_worldex   }, 0                               },
5000     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)),        transform_worldex   }, 0                               },
5001     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)),        transform_worldex   }, 0                               },
5002     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)),        transform_worldex   }, 0                               },
5003     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)),        transform_worldex   }, 0                               },
5004     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)),        transform_worldex   }, 0                               },
5005     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)),        transform_worldex   }, 0                               },
5006     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)),        transform_worldex   }, 0                               },
5007     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)),        transform_worldex   }, 0                               },
5008     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)),        transform_worldex   }, 0                               },
5009     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)),        transform_worldex   }, 0                               },
5010     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)),        transform_worldex   }, 0                               },
5011     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)),        transform_worldex   }, 0                               },
5012     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)),        transform_worldex   }, 0                               },
5013     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)),        transform_worldex   }, 0                               },
5014     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)),        transform_worldex   }, 0                               },
5015     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)),        transform_worldex   }, 0                               },
5016     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)),        transform_worldex   }, 0                               },
5017     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)),        transform_worldex   }, 0                               },
5018     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)),        transform_worldex   }, 0                               },
5019     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)),        transform_worldex   }, 0                               },
5020     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)),        transform_worldex   }, 0                               },
5021     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)),        transform_worldex   }, 0                               },
5022     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)),        transform_worldex   }, 0                               },
5023     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)),        transform_worldex   }, 0                               },
5024     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)),        transform_worldex   }, 0                               },
5025     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)),        transform_worldex   }, 0                               },
5026     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)),        transform_worldex   }, 0                               },
5027     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)),        transform_worldex   }, 0                               },
5028     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)),        transform_worldex   }, 0                               },
5029     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)),        transform_worldex   }, 0                               },
5030     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)),        transform_worldex   }, 0                               },
5031     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)),        transform_worldex   }, 0                               },
5032     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)),        transform_worldex   }, 0                               },
5033     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)),        transform_worldex   }, 0                               },
5034     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)),        transform_worldex   }, 0                               },
5035     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)),        transform_worldex   }, 0                               },
5036     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)),        transform_worldex   }, 0                               },
5037     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)),        transform_worldex   }, 0                               },
5038     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)),        transform_worldex   }, 0                               },
5039     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)),        transform_worldex   }, 0                               },
5040     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)),        transform_worldex   }, 0                               },
5041     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)),        transform_worldex   }, 0                               },
5042     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)),        transform_worldex   }, 0                               },
5043     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)),        transform_worldex   }, 0                               },
5044     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)),        transform_worldex   }, 0                               },
5045     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)),        transform_worldex   }, 0                               },
5046     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)),        transform_worldex   }, 0                               },
5047     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)),        transform_worldex   }, 0                               },
5048     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)),        transform_worldex   }, 0                               },
5049     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)),        transform_worldex   }, 0                               },
5050     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)),        transform_worldex   }, 0                               },
5051     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)),        transform_worldex   }, 0                               },
5052     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)),        transform_worldex   }, 0                               },
5053     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)),        transform_worldex   }, 0                               },
5054     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)),        transform_worldex   }, 0                               },
5055     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)),        transform_worldex   }, 0                               },
5056     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)),        transform_worldex   }, 0                               },
5057     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)),        transform_worldex   }, 0                               },
5058     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)),        transform_worldex   }, 0                               },
5059     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)),        transform_worldex   }, 0                               },
5060     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)),        transform_worldex   }, 0                               },
5061     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)),        transform_worldex   }, 0                               },
5062     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)),        transform_worldex   }, 0                               },
5063     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)),        transform_worldex   }, 0                               },
5064     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)),        transform_worldex   }, 0                               },
5065     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)),        transform_worldex   }, 0                               },
5066     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)),        transform_worldex   }, 0                               },
5067     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)),        transform_worldex   }, 0                               },
5068     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)),        transform_worldex   }, 0                               },
5069     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)),        transform_worldex   }, 0                               },
5070     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)),        transform_worldex   }, 0                               },
5071     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)),        transform_worldex   }, 0                               },
5072     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)),        transform_worldex   }, 0                               },
5073     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)),        transform_worldex   }, 0                               },
5074     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)),        transform_worldex   }, 0                               },
5075     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)),        transform_worldex   }, 0                               },
5076     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)),        transform_worldex   }, 0                               },
5077     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)),        transform_worldex   }, 0                               },
5078     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)),        transform_worldex   }, 0                               },
5079     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)),        transform_worldex   }, 0                               },
5080     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)),        transform_worldex   }, 0                               },
5081     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)),        transform_worldex   }, 0                               },
5082     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)),        transform_worldex   }, 0                               },
5083     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)),        transform_worldex   }, 0                               },
5084     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)),        transform_worldex   }, 0                               },
5085     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)),        transform_worldex   }, 0                               },
5086     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)),        transform_worldex   }, 0                               },
5087     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)),        transform_worldex   }, 0                               },
5088     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)),        transform_worldex   }, 0                               },
5089     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)),        transform_worldex   }, 0                               },
5090     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)),        transform_worldex   }, 0                               },
5091     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)),        transform_worldex   }, 0                               },
5092     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)),        transform_worldex   }, 0                               },
5093     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)),        transform_worldex   }, 0                               },
5094     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)),        transform_worldex   }, 0                               },
5095     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)),        transform_worldex   }, 0                               },
5096     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)),        transform_worldex   }, 0                               },
5097     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)),        transform_worldex   }, 0                               },
5098     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)),        transform_worldex   }, 0                               },
5099     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)),        transform_worldex   }, 0                               },
5100     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)),        transform_worldex   }, 0                               },
5101     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)),        transform_worldex   }, 0                               },
5102     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)),        transform_worldex   }, 0                               },
5103     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)),        transform_worldex   }, 0                               },
5104     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)),        transform_worldex   }, 0                               },
5105     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)),        transform_worldex   }, 0                               },
5106     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)),        transform_worldex   }, 0                               },
5107     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)),        transform_worldex   }, 0                               },
5108     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)),        transform_worldex   }, 0                               },
5109     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)),        transform_worldex   }, 0                               },
5110     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)),        transform_worldex   }, 0                               },
5111     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)),        transform_worldex   }, 0                               },
5112     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)),        transform_worldex   }, 0                               },
5113     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)),        transform_worldex   }, 0                               },
5114     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)),        transform_worldex   }, 0                               },
5115     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)),        transform_worldex   }, 0                               },
5116     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)),        transform_worldex   }, 0                               },
5117     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)),        transform_worldex   }, 0                               },
5118     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)),        transform_worldex   }, 0                               },
5119     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)),        transform_worldex   }, 0                               },
5120     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)),        transform_worldex   }, 0                               },
5121     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)),        transform_worldex   }, 0                               },
5122     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)),        transform_worldex   }, 0                               },
5123     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)),        transform_worldex   }, 0                               },
5124     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)),        transform_worldex   }, 0                               },
5125     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)),        transform_worldex   }, 0                               },
5126     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)),        transform_worldex   }, 0                               },
5127     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)),        transform_worldex   }, 0                               },
5128     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)),        transform_worldex   }, 0                               },
5129     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)),        transform_worldex   }, 0                               },
5130     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)),        transform_worldex   }, 0                               },
5131     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)),        transform_worldex   }, 0                               },
5132     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)),        transform_worldex   }, 0                               },
5133     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)),        transform_worldex   }, 0                               },
5134     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)),        transform_worldex   }, 0                               },
5135     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)),        transform_worldex   }, 0                               },
5136     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)),        transform_worldex   }, 0                               },
5137     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)),        transform_worldex   }, 0                               },
5138     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)),        transform_worldex   }, 0                               },
5139     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)),        transform_worldex   }, 0                               },
5140     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)),        transform_worldex   }, 0                               },
5141     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)),        transform_worldex   }, 0                               },
5142     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)),        transform_worldex   }, 0                               },
5143     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)),        transform_worldex   }, 0                               },
5144     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)),        transform_worldex   }, 0                               },
5145     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)),        transform_worldex   }, 0                               },
5146     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)),        transform_worldex   }, 0                               },
5147     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)),        transform_worldex   }, 0                               },
5148     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)),        transform_worldex   }, 0                               },
5149     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)),        transform_worldex   }, 0                               },
5150     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)),        transform_worldex   }, 0                               },
5151     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)),        transform_worldex   }, 0                               },
5152     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)),        transform_worldex   }, 0                               },
5153     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)),        transform_worldex   }, 0                               },
5154     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)),        transform_worldex   }, 0                               },
5155     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)),        transform_worldex   }, 0                               },
5156     { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5157     { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5158     { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5159     { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5160     { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5161     { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5162     { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5163     { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5164     { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5165     { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5166     { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5167     { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5168     { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5169     { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5170     { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5171     { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5172       /* Fog */
5173     { STATE_RENDER(WINED3DRS_FOGENABLE),                  { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_vertexpart}, 0                               },
5174     { STATE_RENDER(WINED3DRS_FOGTABLEMODE),               { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_vertexpart}, 0                               },
5175     { STATE_RENDER(WINED3DRS_FOGVERTEXMODE),              { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_vertexpart}, 0                               },
5176     { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             state_rangefog      }, NV_FOG_DISTANCE                 },
5177     { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             state_rangefog_w    }, 0                               },
5178     { STATE_RENDER(WINED3DRS_CLIPPING),                   { STATE_RENDER(WINED3DRS_CLIPPING),                   state_clipping      }, 0                               },
5179     { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE),            { STATE_RENDER(WINED3DRS_CLIPPING),                   state_clipping      }, 0                               },
5180     { STATE_RENDER(WINED3DRS_LIGHTING),                   { STATE_RENDER(WINED3DRS_LIGHTING),                   state_lighting      }, 0                               },
5181     { STATE_RENDER(WINED3DRS_AMBIENT),                    { STATE_RENDER(WINED3DRS_AMBIENT),                    state_ambient       }, 0                               },
5182     { STATE_RENDER(WINED3DRS_COLORVERTEX),                { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
5183     { STATE_RENDER(WINED3DRS_LOCALVIEWER),                { STATE_RENDER(WINED3DRS_LOCALVIEWER),                state_localviewer   }, 0                               },
5184     { STATE_RENDER(WINED3DRS_NORMALIZENORMALS),           { STATE_RENDER(WINED3DRS_NORMALIZENORMALS),           state_normalize     }, 0                               },
5185     { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE),      { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
5186     { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE),     { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
5187     { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE),      { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
5188     { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE),     { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
5189     { STATE_RENDER(WINED3DRS_VERTEXBLEND),                { STATE_RENDER(WINED3DRS_VERTEXBLEND),                state_vertexblend   }, ARB_VERTEX_BLEND                },
5190     { STATE_RENDER(WINED3DRS_VERTEXBLEND),                { STATE_RENDER(WINED3DRS_VERTEXBLEND),                state_vertexblend_w }, 0                               },
5191     { STATE_RENDER(WINED3DRS_POINTSIZE),                  { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
5192     { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_arb  }, ARB_POINT_PARAMETERS            },
5193     { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_ext  }, EXT_POINT_PARAMETERS            },
5194     { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_w    }, 0                               },
5195     { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          state_pointsprite   }, ARB_POINT_SPRITE                },
5196     { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          state_pointsprite_w }, 0                               },
5197     { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
5198     { STATE_RENDER(WINED3DRS_POINTSCALE_A),               { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
5199     { STATE_RENDER(WINED3DRS_POINTSCALE_B),               { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
5200     { STATE_RENDER(WINED3DRS_POINTSCALE_C),               { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
5201     { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_arb  }, ARB_POINT_PARAMETERS            },
5202     { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_ext  }, EXT_POINT_PARAMETERS            },
5203     { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_w    }, 0                               },
5204     /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
5205      * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
5206      * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
5207      */
5208     { STATE_SAMPLER(0),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5209     { STATE_SAMPLER(0),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5210     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texmatrix   }, 0                               },
5211     { STATE_SAMPLER(1),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5212     { STATE_SAMPLER(1),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5213     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texmatrix   }, 0                               },
5214     { STATE_SAMPLER(2),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5215     { STATE_SAMPLER(2),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5216     { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texmatrix   }, 0                               },
5217     { STATE_SAMPLER(3),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5218     { STATE_SAMPLER(3),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5219     { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texmatrix   }, 0                               },
5220     { STATE_SAMPLER(4),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5221     { STATE_SAMPLER(4),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5222     { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texmatrix   }, 0                               },
5223     { STATE_SAMPLER(5),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5224     { STATE_SAMPLER(5),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5225     { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texmatrix   }, 0                               },
5226     { STATE_SAMPLER(6),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5227     { STATE_SAMPLER(6),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5228     { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texmatrix   }, 0                               },
5229     { STATE_SAMPLER(7),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5230     { STATE_SAMPLER(7),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5231     { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texmatrix   }, 0                               },
5232     {0 /* Terminate */,                                   { 0,                                                  0                   }, 0                               },
5233 };
5234
5235 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
5236     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5237     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5238     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5239     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5240     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5241     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5242     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5243     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5244     { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5245     { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5246     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5247     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5248     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5249     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5250     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5251     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5252     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5253     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5254     { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5255     { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5256     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5257     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5258     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5259     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5260     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5261     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5262     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5263     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5264     { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5265     { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5266     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5267     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5268     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5269     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5270     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5271     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5272     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5273     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5274     { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5275     { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5276     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5277     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5278     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5279     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5280     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5281     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5282     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5283     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5284     { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5285     { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5286     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5287     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5288     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5289     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5290     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5291     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5292     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5293     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5294     { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5295     { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5296     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5297     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5298     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5299     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5300     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5301     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5302     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5303     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5304     { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5305     { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5306     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5307     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5308     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5309     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5310     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5311     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5312     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5313     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5314     { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5315     { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5316     { STATE_PIXELSHADER,                                  { STATE_PIXELSHADER,                                  apply_pixelshader   }, 0                               },
5317     { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE),            { STATE_PIXELSHADER,                                  apply_pixelshader   }, 0                               },
5318     { STATE_RENDER(WINED3DRS_BORDERCOLOR),                { STATE_RENDER(WINED3DRS_BORDERCOLOR),                state_bordercolor   }, 0                               },
5319     { STATE_RENDER(WINED3DRS_TEXTUREFACTOR),              { STATE_RENDER(WINED3DRS_TEXTUREFACTOR),              state_texfactor     }, 0                               },
5320     { STATE_RENDER(WINED3DRS_FOGCOLOR),                   { STATE_RENDER(WINED3DRS_FOGCOLOR),                   state_fogcolor      }, 0                               },
5321     { STATE_RENDER(WINED3DRS_FOGDENSITY),                 { STATE_RENDER(WINED3DRS_FOGDENSITY),                 state_fogdensity    }, 0                               },
5322     { STATE_RENDER(WINED3DRS_FOGENABLE),                  { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_fragpart  }, 0                               },
5323     { STATE_RENDER(WINED3DRS_FOGTABLEMODE),               { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_fragpart  }, 0                               },
5324     { STATE_RENDER(WINED3DRS_FOGVERTEXMODE),              { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_fragpart  }, 0                               },
5325     { STATE_RENDER(WINED3DRS_FOGSTART),                   { STATE_RENDER(WINED3DRS_FOGSTART),                   state_fogstartend   }, 0                               },
5326     { STATE_RENDER(WINED3DRS_FOGEND),                     { STATE_RENDER(WINED3DRS_FOGSTART),                   state_fogstartend   }, 0                               },
5327     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texdim      }, 0                               },
5328     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texdim      }, 0                               },
5329     { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texdim      }, 0                               },
5330     { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texdim      }, 0                               },
5331     { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texdim      }, 0                               },
5332     { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texdim      }, 0                               },
5333     { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texdim      }, 0                               },
5334     { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texdim      }, 0                               },
5335     {0 /* Terminate */,                                   { 0,                                                  0                   }, 0                               },
5336 };
5337 #undef GLINFO_LOCATION
5338
5339 #define GLINFO_LOCATION (*gl_info)
5340 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
5341
5342 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps)
5343 {
5344     pCaps->TextureOpCaps =  WINED3DTEXOPCAPS_ADD         |
5345                             WINED3DTEXOPCAPS_ADDSIGNED   |
5346                             WINED3DTEXOPCAPS_ADDSIGNED2X |
5347                             WINED3DTEXOPCAPS_MODULATE    |
5348                             WINED3DTEXOPCAPS_MODULATE2X  |
5349                             WINED3DTEXOPCAPS_MODULATE4X  |
5350                             WINED3DTEXOPCAPS_SELECTARG1  |
5351                             WINED3DTEXOPCAPS_SELECTARG2  |
5352                             WINED3DTEXOPCAPS_DISABLE;
5353
5354     if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
5355         GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
5356         GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5357         pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA  |
5358                                 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA  |
5359                                 WINED3DTEXOPCAPS_BLENDFACTORALPHA   |
5360                                 WINED3DTEXOPCAPS_BLENDCURRENTALPHA  |
5361                                 WINED3DTEXOPCAPS_LERP               |
5362                                 WINED3DTEXOPCAPS_SUBTRACT;
5363     }
5364     if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
5365         GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5366         pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH              |
5367                                 WINED3DTEXOPCAPS_MULTIPLYADD            |
5368                                 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
5369                                 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5370                                 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5371     }
5372     if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
5373         pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5374
5375     pCaps->MaxTextureBlendStages   = GL_LIMITS(texture_stages);
5376     pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
5377 }
5378
5379 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
5380 static void ffp_fragment_free(IWineD3DDevice *iface) {}
5381 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
5382 {
5383     if (TRACE_ON(d3d))
5384     {
5385         TRACE("Checking support for fixup:\n");
5386         dump_color_fixup_desc(fixup);
5387     }
5388
5389     /* We only support identity conversions. */
5390     if (is_identity_fixup(fixup))
5391     {
5392         TRACE("[OK]\n");
5393         return TRUE;
5394     }
5395
5396     TRACE("[FAILED]\n");
5397     return FALSE;
5398 }
5399
5400 const struct fragment_pipeline ffp_fragment_pipeline = {
5401     ffp_enable,
5402     ffp_fragment_get_caps,
5403     ffp_fragment_alloc,
5404     ffp_fragment_free,
5405     ffp_color_fixup_supported,
5406     ffp_fragmentstate_template,
5407     FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
5408 };
5409
5410 static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
5411 {
5412     unsigned int i;
5413     for(i = 0; funcs[i]; i++);
5414     return i;
5415 }
5416
5417 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5418     stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5419     stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5420 }
5421
5422 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5423     stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5424     stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5425     stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
5426 }
5427
5428 HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
5429         const WineD3D_GL_Info *gl_info, const struct StateEntryTemplate *vertex,
5430         const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
5431 {
5432     unsigned int i, type, handlers;
5433     APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5434     const struct StateEntryTemplate *cur;
5435     BOOL set[STATE_HIGHEST + 1];
5436
5437     memset(multistate_funcs, 0, sizeof(multistate_funcs));
5438
5439     for(i = 0; i < STATE_HIGHEST + 1; i++) {
5440         StateTable[i].representative = 0;
5441         StateTable[i].apply = state_undefined;
5442     }
5443
5444     for(type = 0; type < 3; type++) {
5445         /* This switch decides the order in which the states are applied */
5446         switch(type) {
5447             case 0: cur = misc; break;
5448             case 1: cur = fragment->states; break;
5449             case 2: cur = vertex; break;
5450             default: cur = NULL; /* Stupid compiler */
5451         }
5452         if(!cur) continue;
5453
5454         /* GL extension filtering should not prevent multiple handlers being applied from different
5455          * pipeline parts
5456          */
5457         memset(set, 0, sizeof(set));
5458
5459         for(i = 0; cur[i].state; i++) {
5460             APPLYSTATEFUNC *funcs_array;
5461
5462             /* Only use the first matching state with the available extension from one template.
5463              * e.g.
5464              * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
5465              * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0        }
5466              *
5467              * if GL_XYZ_fancy is supported, ignore the 2nd line
5468              */
5469             if(set[cur[i].state]) continue;
5470             /* Skip state lines depending on unsupported extensions */
5471             if(cur[i].extension && !GL_SUPPORT(cur[i].extension)) continue;
5472             set[cur[i].state] = TRUE;
5473             /* In some cases having an extension means that nothing has to be
5474              * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
5475              * supported, the texture coordinate fixup can be ignored. If the
5476              * apply function is used, mark the state set(done above) to prevent
5477              * applying later lines, but do not record anything in the state
5478              * table
5479              */
5480             if(!cur[i].content.apply) continue;
5481
5482             handlers = num_handlers(multistate_funcs[cur[i].state]);
5483             multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5484             switch(handlers) {
5485                 case 0:
5486                     StateTable[cur[i].state].apply = cur[i].content.apply;
5487                     break;
5488                 case 1:
5489                     StateTable[cur[i].state].apply = multistate_apply_2;
5490                     dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5491                                                                    0,
5492                                                                    sizeof(**dev_multistate_funcs) * 2);
5493                     if (!dev_multistate_funcs[cur[i].state]) {
5494                         goto out_of_mem;
5495                     }
5496
5497                     dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5498                     dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5499                     break;
5500                 case 2:
5501                     StateTable[cur[i].state].apply = multistate_apply_3;
5502                     funcs_array = HeapReAlloc(GetProcessHeap(),
5503                                               0,
5504                                               dev_multistate_funcs[cur[i].state],
5505                                               sizeof(**dev_multistate_funcs) * 3);
5506                     if (!funcs_array) {
5507                         goto out_of_mem;
5508                     }
5509
5510                     dev_multistate_funcs[cur[i].state] = funcs_array;
5511                     dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
5512                     break;
5513                 default:
5514                     ERR("Unexpected amount of state handlers for state %u: %u\n",
5515                         cur[i].state, handlers + 1);
5516             }
5517
5518             if(StateTable[cur[i].state].representative &&
5519             StateTable[cur[i].state].representative != cur[i].content.representative) {
5520                 FIXME("State %u has different representatives in different pipeline parts\n",
5521                     cur[i].state);
5522             }
5523             StateTable[cur[i].state].representative = cur[i].content.representative;
5524         }
5525     }
5526
5527     return WINED3D_OK;
5528
5529 out_of_mem:
5530     for (i = 0; i <= STATE_HIGHEST; ++i) {
5531         HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]);
5532     }
5533
5534     memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs));
5535
5536     return E_OUTOFMEMORY;
5537 }
5538 #undef GLINFO_LOCATION