wined3d: Remove a TODO.
[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     /* TODO: NV_POINT_SPRITE */
1507     if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1508         TRACE("Point sprites not supported\n");
1509     }
1510 }
1511
1512 static void state_pointsprite(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1513     if (stateblock->renderState[WINED3DRS_POINTSPRITEENABLE]) {
1514         glEnable(GL_POINT_SPRITE_ARB);
1515         checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1516     } else {
1517         glDisable(GL_POINT_SPRITE_ARB);
1518         checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1519     }
1520 }
1521
1522 static void state_wrap(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1523     /**
1524      http://www.cosc.brocku.ca/Offerings/3P98/course/lectures/texture/
1525      http://www.gamedev.net/reference/programming/features/rendererdll3/page2.asp
1526      Discussion on the ways to turn on WRAPing to solve an OpenGL conversion problem.
1527      http://www.flipcode.org/cgi-bin/fcmsg.cgi?thread_show=10248
1528
1529      so far as I can tell, wrapping and texture-coordinate generate go hand in hand,
1530      */
1531     TRACE("Stub\n");
1532     if(stateblock->renderState[WINED3DRS_WRAP0] ||
1533        stateblock->renderState[WINED3DRS_WRAP1] ||
1534        stateblock->renderState[WINED3DRS_WRAP2] ||
1535        stateblock->renderState[WINED3DRS_WRAP3] ||
1536        stateblock->renderState[WINED3DRS_WRAP4] ||
1537        stateblock->renderState[WINED3DRS_WRAP5] ||
1538        stateblock->renderState[WINED3DRS_WRAP6] ||
1539        stateblock->renderState[WINED3DRS_WRAP7] ||
1540        stateblock->renderState[WINED3DRS_WRAP8] ||
1541        stateblock->renderState[WINED3DRS_WRAP9] ||
1542        stateblock->renderState[WINED3DRS_WRAP10] ||
1543        stateblock->renderState[WINED3DRS_WRAP11] ||
1544        stateblock->renderState[WINED3DRS_WRAP12] ||
1545        stateblock->renderState[WINED3DRS_WRAP13] ||
1546        stateblock->renderState[WINED3DRS_WRAP14] ||
1547        stateblock->renderState[WINED3DRS_WRAP15] ) {
1548         FIXME("(WINED3DRS_WRAP0) Texture wraping not yet supported\n");
1549     }
1550 }
1551
1552 static void state_msaa_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1553     if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1554         WARN("Multisample antialiasing not supported by gl\n");
1555     }
1556 }
1557
1558 static void state_msaa(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1559     if(stateblock->renderState[WINED3DRS_MULTISAMPLEANTIALIAS]) {
1560         glEnable(GL_MULTISAMPLE_ARB);
1561         checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1562     } else {
1563         glDisable(GL_MULTISAMPLE_ARB);
1564         checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1565     }
1566 }
1567
1568 static void state_scissor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1569     if(stateblock->renderState[WINED3DRS_SCISSORTESTENABLE]) {
1570         glEnable(GL_SCISSOR_TEST);
1571         checkGLcall("glEnable(GL_SCISSOR_TEST)");
1572     } else {
1573         glDisable(GL_SCISSOR_TEST);
1574         checkGLcall("glDisable(GL_SCISSOR_TEST)");
1575     }
1576 }
1577
1578 static void state_depthbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1579     union {
1580         DWORD d;
1581         float f;
1582     } tmpvalue;
1583
1584     if(stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS] ||
1585        stateblock->renderState[WINED3DRS_DEPTHBIAS]) {
1586         tmpvalue.d = stateblock->renderState[WINED3DRS_SLOPESCALEDEPTHBIAS];
1587         glEnable(GL_POLYGON_OFFSET_FILL);
1588         checkGLcall("glEnable(GL_POLYGON_OFFSET_FILL)");
1589         glPolygonOffset(tmpvalue.f, *((float*)&stateblock->renderState[WINED3DRS_DEPTHBIAS]));
1590         checkGLcall("glPolygonOffset(...)");
1591     } else {
1592         glDisable(GL_POLYGON_OFFSET_FILL);
1593         checkGLcall("glDisable(GL_POLYGON_OFFSET_FILL)");
1594     }
1595 }
1596
1597 static void state_perspective(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1598     if (stateblock->renderState[WINED3DRS_TEXTUREPERSPECTIVE]) {
1599         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
1600         checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST)");
1601     } else {
1602         glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST);
1603         checkGLcall("glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_FASTEST)");
1604     }
1605 }
1606
1607 static void state_stippledalpha(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1608     TRACE("Stub\n");
1609     if (stateblock->renderState[WINED3DRS_STIPPLEDALPHA])
1610         FIXME(" Stippled Alpha not supported yet.\n");
1611 }
1612
1613 static void state_antialias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1614     TRACE("Stub\n");
1615     if (stateblock->renderState[WINED3DRS_ANTIALIAS])
1616         FIXME(" Antialias not supported yet.\n");
1617 }
1618
1619 static void state_multisampmask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1620     TRACE("Stub\n");
1621     if (stateblock->renderState[WINED3DRS_MULTISAMPLEMASK] != 0xFFFFFFFF)
1622         FIXME("(WINED3DRS_MULTISAMPLEMASK,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_MULTISAMPLEMASK]);
1623 }
1624
1625 static void state_patchedgestyle(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1626     TRACE("Stub\n");
1627     if (stateblock->renderState[WINED3DRS_PATCHEDGESTYLE] != WINED3DPATCHEDGE_DISCRETE)
1628         FIXME("(WINED3DRS_PATCHEDGESTYLE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_PATCHEDGESTYLE]);
1629 }
1630
1631 static void state_patchsegments(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1632     union {
1633         DWORD d;
1634         float f;
1635     } tmpvalue;
1636     tmpvalue.f = 1.0f;
1637
1638     TRACE("Stub\n");
1639     if (stateblock->renderState[WINED3DRS_PATCHSEGMENTS] != tmpvalue.d)
1640     {
1641         static BOOL displayed = FALSE;
1642
1643         tmpvalue.d = stateblock->renderState[WINED3DRS_PATCHSEGMENTS];
1644         if(!displayed)
1645             FIXME("(WINED3DRS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1646
1647         displayed = TRUE;
1648     }
1649 }
1650
1651 static void state_positiondegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1652     TRACE("Stub\n");
1653     if (stateblock->renderState[WINED3DRS_POSITIONDEGREE] != WINED3DDEGREE_CUBIC)
1654         FIXME("(WINED3DRS_POSITIONDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_POSITIONDEGREE]);
1655 }
1656
1657 static void state_normaldegree(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1658     TRACE("Stub\n");
1659     if (stateblock->renderState[WINED3DRS_NORMALDEGREE] != WINED3DDEGREE_LINEAR)
1660         FIXME("(WINED3DRS_NORMALDEGREE,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_NORMALDEGREE]);
1661 }
1662
1663 static void state_tessellation(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1664     TRACE("Stub\n");
1665     if(stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION])
1666         FIXME("(WINED3DRS_ENABLEADAPTIVETESSELLATION,%d) not yet implemented\n", stateblock->renderState[WINED3DRS_ENABLEADAPTIVETESSELLATION]);
1667 }
1668
1669 static void state_wrapu(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1670     if(stateblock->renderState[WINED3DRS_WRAPU]) {
1671         FIXME("Render state WINED3DRS_WRAPU not implemented yet\n");
1672     }
1673 }
1674
1675 static void state_wrapv(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1676     if(stateblock->renderState[WINED3DRS_WRAPV]) {
1677         FIXME("Render state WINED3DRS_WRAPV not implemented yet\n");
1678     }
1679 }
1680
1681 static void state_monoenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1682     if(stateblock->renderState[WINED3DRS_MONOENABLE]) {
1683         FIXME("Render state WINED3DRS_MONOENABLE not implemented yet\n");
1684     }
1685 }
1686
1687 static void state_rop2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1688     if(stateblock->renderState[WINED3DRS_ROP2]) {
1689         FIXME("Render state WINED3DRS_ROP2 not implemented yet\n");
1690     }
1691 }
1692
1693 static void state_planemask(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1694     if(stateblock->renderState[WINED3DRS_PLANEMASK]) {
1695         FIXME("Render state WINED3DRS_PLANEMASK not implemented yet\n");
1696     }
1697 }
1698
1699 static void state_subpixel(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1700     if(stateblock->renderState[WINED3DRS_SUBPIXEL]) {
1701         FIXME("Render state WINED3DRS_SUBPIXEL not implemented yet\n");
1702     }
1703 }
1704
1705 static void state_subpixelx(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1706     if(stateblock->renderState[WINED3DRS_SUBPIXELX]) {
1707         FIXME("Render state WINED3DRS_SUBPIXELX not implemented yet\n");
1708     }
1709 }
1710
1711 static void state_stippleenable(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1712     if(stateblock->renderState[WINED3DRS_STIPPLEENABLE]) {
1713         FIXME("Render state WINED3DRS_STIPPLEENABLE not implemented yet\n");
1714     }
1715 }
1716
1717 static void state_bordercolor(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1718     if(stateblock->renderState[WINED3DRS_BORDERCOLOR]) {
1719         FIXME("Render state WINED3DRS_BORDERCOLOR not implemented yet\n");
1720     }
1721 }
1722
1723 static void state_mipmaplodbias(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1724     if(stateblock->renderState[WINED3DRS_MIPMAPLODBIAS]) {
1725         FIXME("Render state WINED3DRS_MIPMAPLODBIAS not implemented yet\n");
1726     }
1727 }
1728
1729 static void state_anisotropy(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1730     if(stateblock->renderState[WINED3DRS_ANISOTROPY]) {
1731         FIXME("Render state WINED3DRS_ANISOTROPY not implemented yet\n");
1732     }
1733 }
1734
1735 static void state_flushbatch(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1736     if(stateblock->renderState[WINED3DRS_FLUSHBATCH]) {
1737         FIXME("Render state WINED3DRS_FLUSHBATCH not implemented yet\n");
1738     }
1739 }
1740
1741 static void state_translucentsi(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1742     if(stateblock->renderState[WINED3DRS_TRANSLUCENTSORTINDEPENDENT]) {
1743         FIXME("Render state WINED3DRS_TRANSLUCENTSORTINDEPENDENT not implemented yet\n");
1744     }
1745 }
1746
1747 static void state_extents(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1748     if(stateblock->renderState[WINED3DRS_EXTENTS]) {
1749         FIXME("Render state WINED3DRS_EXTENTS not implemented yet\n");
1750     }
1751 }
1752
1753 static void state_ckeyblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
1754     if(stateblock->renderState[WINED3DRS_COLORKEYBLENDENABLE]) {
1755         FIXME("Render state WINED3DRS_COLORKEYBLENDENABLE not implemented yet\n");
1756     }
1757 }
1758
1759 /* Set texture operations up - The following avoids lots of ifdefs in this routine!*/
1760 #if defined (GL_VERSION_1_3)
1761 # define useext(A) A
1762 #elif defined (GL_EXT_texture_env_combine)
1763 # define useext(A) A##_EXT
1764 #elif defined (GL_ARB_texture_env_combine)
1765 # define useext(A) A##_ARB
1766 #endif
1767
1768 static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
1769     /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
1770     * input should be used for all input components. The WINED3DTA_COMPLEMENT
1771     * flag specifies the complement of the input should be used. */
1772     BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
1773     BOOL complement = arg & WINED3DTA_COMPLEMENT;
1774
1775     /* Calculate the operand */
1776     if (complement) {
1777         if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
1778         else *operand = GL_ONE_MINUS_SRC_COLOR;
1779     } else {
1780         if (from_alpha) *operand = GL_SRC_ALPHA;
1781         else *operand = GL_SRC_COLOR;
1782     }
1783
1784     /* Calculate the source */
1785     switch (arg & WINED3DTA_SELECTMASK) {
1786         case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
1787         case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
1788         case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
1789         case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
1790         case WINED3DTA_SPECULAR:
1791             /*
1792             * According to the GL_ARB_texture_env_combine specs, SPECULAR is
1793             * 'Secondary color' and isn't supported until base GL supports it
1794             * There is no concept of temp registers as far as I can tell
1795             */
1796             FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
1797             *source = GL_TEXTURE;
1798             break;
1799         default:
1800             FIXME("Unrecognized texture arg %#x\n", arg);
1801             *source = GL_TEXTURE;
1802             break;
1803     }
1804 }
1805
1806 /* Setup the texture operations texture stage states */
1807 static void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, WINED3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3)
1808 {
1809     GLenum src1, src2, src3;
1810     GLenum opr1, opr2, opr3;
1811     GLenum comb_target;
1812     GLenum src0_target, src1_target, src2_target;
1813     GLenum opr0_target, opr1_target, opr2_target;
1814     GLenum scal_target;
1815     GLenum opr=0, invopr, src3_target, opr3_target;
1816     BOOL Handled = FALSE;
1817     IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
1818     IWineD3DStateBlockImpl *stateblock = This->stateBlock; /* for GLINFO_LOCATION */
1819
1820     TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);
1821
1822     /* This is called by a state handler which has the gl lock held and a context for the thread */
1823
1824         /* Note: Operations usually involve two ars, src0 and src1 and are operations of
1825     the form (a1 <operation> a2). However, some of the more complex operations
1826     take 3 parameters. Instead of the (sensible) addition of a3, Microsoft added
1827     in a third parameter called a0. Therefore these are operations of the form
1828     a0 <operation> a1 <operation> a2, i.e., the new parameter goes to the front.
1829
1830     However, below we treat the new (a0) parameter as src2/opr2, so in the actual
1831     functions below, expect their syntax to differ slightly to those listed in the
1832     manuals, i.e., replace arg1 with arg3, arg2 with arg1 and arg3 with arg2
1833     This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP                     */
1834
1835     if (isAlpha) {
1836         comb_target = useext(GL_COMBINE_ALPHA);
1837         src0_target = useext(GL_SOURCE0_ALPHA);
1838         src1_target = useext(GL_SOURCE1_ALPHA);
1839         src2_target = useext(GL_SOURCE2_ALPHA);
1840         opr0_target = useext(GL_OPERAND0_ALPHA);
1841         opr1_target = useext(GL_OPERAND1_ALPHA);
1842         opr2_target = useext(GL_OPERAND2_ALPHA);
1843         scal_target = GL_ALPHA_SCALE;
1844     }
1845     else {
1846         comb_target = useext(GL_COMBINE_RGB);
1847         src0_target = useext(GL_SOURCE0_RGB);
1848         src1_target = useext(GL_SOURCE1_RGB);
1849         src2_target = useext(GL_SOURCE2_RGB);
1850         opr0_target = useext(GL_OPERAND0_RGB);
1851         opr1_target = useext(GL_OPERAND1_RGB);
1852         opr2_target = useext(GL_OPERAND2_RGB);
1853         scal_target = useext(GL_RGB_SCALE);
1854     }
1855
1856         /* If a texture stage references an invalid texture unit the stage just
1857         * passes through the result from the previous stage */
1858     if (is_invalid_op(This, Stage, op, arg1, arg2, arg3)) {
1859         arg1 = WINED3DTA_CURRENT;
1860         op = WINED3DTOP_SELECTARG1;
1861     }
1862
1863     if (isAlpha && This->stateBlock->textures[Stage] == NULL && arg1 == WINED3DTA_TEXTURE) {
1864         get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
1865     } else {
1866         get_src_and_opr(arg1, isAlpha, &src1, &opr1);
1867     }
1868     get_src_and_opr(arg2, isAlpha, &src2, &opr2);
1869     get_src_and_opr(arg3, isAlpha, &src3, &opr3);
1870
1871     TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);
1872
1873     Handled = TRUE; /* Assume will be handled */
1874
1875     /* Other texture operations require special extensions: */
1876     if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
1877         if (isAlpha) {
1878             opr = GL_SRC_ALPHA;
1879             invopr = GL_ONE_MINUS_SRC_ALPHA;
1880             src3_target = GL_SOURCE3_ALPHA_NV;
1881             opr3_target = GL_OPERAND3_ALPHA_NV;
1882         } else {
1883             opr = GL_SRC_COLOR;
1884             invopr = GL_ONE_MINUS_SRC_COLOR;
1885             src3_target = GL_SOURCE3_RGB_NV;
1886             opr3_target = GL_OPERAND3_RGB_NV;
1887         }
1888         switch (op) {
1889             case WINED3DTOP_DISABLE: /* Only for alpha */
1890                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1891                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
1892                 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
1893                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1894                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
1895                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1896                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1897                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1898                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1899                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1900                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1901                 checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1902                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1903                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1904                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1905                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1906                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1907                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1908                 break;
1909                 case WINED3DTOP_SELECTARG1:                                          /* = a1 * 1 + 0 * 0 */
1910                 case WINED3DTOP_SELECTARG2:                                          /* = a2 * 1 + 0 * 0 */
1911                     glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1912                     checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
1913                     if (op == WINED3DTOP_SELECTARG1) {
1914                         glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1915                         checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1916                         glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1917                         checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1918                     } else {
1919                         glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
1920                         checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
1921                         glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
1922                         checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
1923                     }
1924                     glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
1925                     checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1926                     glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
1927                     checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1928                     glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1929                     checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
1930                     glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1931                     checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
1932                     glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1933                     checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1934                     glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1935                     checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
1936                     break;
1937
1938             case WINED3DTOP_MODULATE:
1939                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1940                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1941                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1942                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1943                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1944                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1945                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1946                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1947                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1948                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1949                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1950                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1951                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1952                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1953                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1954                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1955                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1956                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1957                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
1958                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
1959                 break;
1960             case WINED3DTOP_MODULATE2X:
1961                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1962                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1963                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1964                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1965                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1966                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1967                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1968                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1969                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1970                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1971                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1972                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1973                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1974                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1975                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1976                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1977                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
1978                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
1979                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
1980                 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
1981                 break;
1982             case WINED3DTOP_MODULATE4X:
1983                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
1984                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
1985                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
1986                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
1987                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
1988                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
1989                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
1990                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
1991                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
1992                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
1993                 glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
1994                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
1995                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
1996                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
1997                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
1998                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
1999                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2000                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2001                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2002                 checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2003                 break;
2004
2005             case WINED3DTOP_ADD:
2006                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2007                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2008                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2009                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2010                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2011                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2012                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2013                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2014                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2015                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2016                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2017                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2018                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2019                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2020                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2021                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2022                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2023                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2024                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2025                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2026                 break;
2027
2028             case WINED3DTOP_ADDSIGNED:
2029                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2030                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2031                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2032                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2033                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2034                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2035                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2036                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2037                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2038                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2039                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2040                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2041                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2042                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2043                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2044                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2045                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2046                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2047                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2048                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2049                 break;
2050
2051             case WINED3DTOP_ADDSIGNED2X:
2052                 glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2053                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2054                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2055                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2056                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2057                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2058                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2059                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2060                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2061                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2062                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2063                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2064                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2065                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2066                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2067                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2068                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2069                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2070                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2071                 checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2072                 break;
2073
2074             case WINED3DTOP_ADDSMOOTH:
2075                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2076                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2077                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2078                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2079                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2080                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2081                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2082                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2083                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2084                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2085                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2086                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2087                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2088                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2089                 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2090                 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2091                 switch (opr1) {
2092                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2093                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2094                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2095                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2096                 }
2097                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2098                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2099                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2100                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2101                 break;
2102
2103             case WINED3DTOP_BLENDDIFFUSEALPHA:
2104                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2105                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2106                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2107                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2108                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2109                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2110                 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR));
2111                 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_PRIMARY_COLOR)");
2112                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2113                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2114                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2115                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2116                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2117                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2118                 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR));
2119                 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_PRIMARY_COLOR)");
2120                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2121                 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2122                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2123                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2124                 break;
2125             case WINED3DTOP_BLENDTEXTUREALPHA:
2126                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2127                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2128                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2129                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2130                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2131                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2132                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2133                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2134                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2135                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2136                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2137                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2138                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2139                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2140                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2141                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2142                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2143                 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2144                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2145                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2146                 break;
2147             case WINED3DTOP_BLENDFACTORALPHA:
2148                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2149                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2150                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2151                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2152                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2153                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2154                 glTexEnvi(GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT));
2155                 checkGLcall("GL_TEXTURE_ENV, src1_target, useext(GL_CONSTANT)");
2156                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2157                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2158                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2159                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2160                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2161                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2162                 glTexEnvi(GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT));
2163                 checkGLcall("GL_TEXTURE_ENV, src3_target, useext(GL_CONSTANT)");
2164                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2165                 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2166                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2167                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2168                 break;
2169             case WINED3DTOP_BLENDTEXTUREALPHAPM:
2170                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2171                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2172                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2173                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2174                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2175                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2176                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2177                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2178                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2179                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2180                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2181                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2182                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2183                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2184                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2185                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2186                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2187                 checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2188                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2189                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2190                 break;
2191             case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2192                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2193                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");  /* Add = a0*a1 + a2*a3 */
2194                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);        /*   a0 = src1/opr1    */
2195                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2196                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2197                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");    /*   a1 = 1 (see docs) */
2198                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2199                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2200                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2201                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2202                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);        /*   a2 = arg2         */
2203                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2204                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2205                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");     /*  a3 = src1 alpha   */
2206                 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2207                 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2208                 switch (opr) {
2209                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2210                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2211                 }
2212                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2213                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2214                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2215                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2216                 break;
2217             case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2218                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2219                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2220                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2221                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2222                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2223                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2224                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2225                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2226                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2227                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2228                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2229                 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2230                 switch (opr1) {
2231                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2232                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2233                 }
2234                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2235                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2236                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2237                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2238                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2239                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2240                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2241                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2242                 break;
2243             case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2244                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2245                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2246                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2247                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2248                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2249                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2250                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2251                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2252                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2253                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2254                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2255                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2256                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2257                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2258                 glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2259                 checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
2260                 switch (opr1) {
2261                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2262                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2263                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2264                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2265                 }
2266                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2267                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2268                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2269                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2270                 break;
2271             case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2272                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2273                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2274                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2275                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2276                 switch (opr1) {
2277                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2278                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2279                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2280                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2281                 }
2282                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2283                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2284                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2285                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2286                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2287                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2288                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2289                 checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
2290                 switch (opr1) {
2291                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2292                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2293                 }
2294                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2295                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2296                 glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2297                 checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2298                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2299                 checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2300                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2301                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2302                 break;
2303             case WINED3DTOP_MULTIPLYADD:
2304                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2305                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2306                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2307                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2308                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2309                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2310                 glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2311                 checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2312                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2313                 checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2314                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2315                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2316                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2317                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2318                 glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2319                 checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2320                 glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2321                 checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2322                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2323                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2324                 break;
2325
2326             case WINED3DTOP_BUMPENVMAP:
2327             {
2328             }
2329
2330             case WINED3DTOP_BUMPENVMAPLUMINANCE:
2331                 FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2332
2333             default:
2334                 Handled = FALSE;
2335         }
2336         if (Handled) {
2337             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2338             checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");
2339
2340             return;
2341         }
2342     } /* GL_NV_texture_env_combine4 */
2343
2344     Handled = TRUE; /* Again, assume handled */
2345     switch (op) {
2346         case WINED3DTOP_DISABLE: /* Only for alpha */
2347             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2348             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2349             glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2350             checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2351             glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2352             checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2353             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2354             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2355             break;
2356         case WINED3DTOP_SELECTARG1:
2357             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2358             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2359             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2360             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2361             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2362             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2363             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2364             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2365             break;
2366         case WINED3DTOP_SELECTARG2:
2367             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2368             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2369             glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2370             checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2371             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2372             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2373             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2374             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2375             break;
2376         case WINED3DTOP_MODULATE:
2377             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2378             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2379             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2380             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2381             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2382             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2383             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2384             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2385             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2386             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2387             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2388             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2389             break;
2390         case WINED3DTOP_MODULATE2X:
2391             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2392             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2393             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2394             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2395             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2396             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2397             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2398             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2399             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2400             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2401             glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2402             checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2403             break;
2404         case WINED3DTOP_MODULATE4X:
2405             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2406             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2407             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2408             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2409             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2410             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2411             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2412             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2413             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2414             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2415             glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2416             checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
2417             break;
2418         case WINED3DTOP_ADD:
2419             glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2420             checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2421             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2422             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2423             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2424             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2425             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2426             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2427             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2428             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2429             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2430             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2431             break;
2432         case WINED3DTOP_ADDSIGNED:
2433             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2434             checkGLcall("GL_TEXTURE_ENV, comb_target, useext((GL_ADD_SIGNED)");
2435             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2436             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2437             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2438             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2439             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2440             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2441             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2442             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2443             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2444             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2445             break;
2446         case WINED3DTOP_ADDSIGNED2X:
2447             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED));
2448             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_ADD_SIGNED)");
2449             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2450             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2451             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2452             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2453             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2454             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2455             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2456             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2457             glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2458             checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
2459             break;
2460         case WINED3DTOP_SUBTRACT:
2461             if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE)) {
2462                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2463                 checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_SUBTRACT)");
2464                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2465                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2466                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2467                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2468                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2469                 checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2470                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2471                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2472                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2473                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2474             } else {
2475                 FIXME("This version of opengl does not support GL_SUBTRACT\n");
2476             }
2477             break;
2478
2479         case WINED3DTOP_BLENDDIFFUSEALPHA:
2480             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2481             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2482             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2483             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2484             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2485             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2486             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2487             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2488             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2489             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2490             glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PRIMARY_COLOR));
2491             checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2492             glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2493             checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2494             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2495             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2496             break;
2497         case WINED3DTOP_BLENDTEXTUREALPHA:
2498             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2499             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2500             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2501             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2502             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2503             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2504             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2505             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2506             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2507             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2508             glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2509             checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2510             glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2511             checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2512             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2513             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2514             break;
2515         case WINED3DTOP_BLENDFACTORALPHA:
2516             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2517             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2518             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2519             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2520             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2521             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2522             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2523             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2524             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2525             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2526             glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_CONSTANT));
2527             checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2528             glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2529             checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2530             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2531             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2532             break;
2533         case WINED3DTOP_BLENDCURRENTALPHA:
2534             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2535             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2536             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2537             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2538             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2539             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2540             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2541             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2542             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2543             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2544             glTexEnvi(GL_TEXTURE_ENV, src2_target, useext(GL_PREVIOUS));
2545             checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2546             glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2547             checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2548             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2549             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2550             break;
2551         case WINED3DTOP_DOTPRODUCT3:
2552             if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3)) {
2553                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2554                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2555             } else if (GL_SUPPORT(EXT_TEXTURE_ENV_DOT3)) {
2556                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2557                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
2558             } else {
2559                 FIXME("This version of opengl does not support GL_DOT3\n");
2560             }
2561             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2562             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2563             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2564             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2565             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2566             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2567             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2568             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2569             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2570             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2571             break;
2572         case WINED3DTOP_LERP:
2573             glTexEnvi(GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE));
2574             checkGLcall("GL_TEXTURE_ENV, comb_target, useext(GL_INTERPOLATE)");
2575             glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2576             checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2577             glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2578             checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2579             glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2580             checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2581             glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2582             checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2583             glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2584             checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2585             glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2586             checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2587             glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2588             checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2589             break;
2590         case WINED3DTOP_ADDSMOOTH:
2591             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2592                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2593                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2594                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2595                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2596                 switch (opr1) {
2597                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2598                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2599                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2600                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2601                 }
2602                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2603                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2604                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2605                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2606                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2607                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2608                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2609                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2610                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2611                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2612                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2613                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2614             } else
2615                 Handled = FALSE;
2616                 break;
2617         case WINED3DTOP_BLENDTEXTUREALPHAPM:
2618             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2619                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2620                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2621                 glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2622                 checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2623                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2624                 checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2625                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2626                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2627                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2628                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2629                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2630                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2631                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2632                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2633                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2634                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2635             } else
2636                 Handled = FALSE;
2637                 break;
2638         case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2639             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2640                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2641                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2642                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2643                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2644                 switch (opr1) {
2645                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2646                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2647                     case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2648                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2649                 }
2650                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2651                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2652                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2653                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2654                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2655                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2656                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2657                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2658                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2659                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2660                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2661                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2662             } else
2663                 Handled = FALSE;
2664                 break;
2665         case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2666             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2667                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2668                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2669                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2670                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2671                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2672                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2673                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2674                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2675                 switch (opr1) {
2676                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2677                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2678                     case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2679                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2680                 }
2681                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2682                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2683                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2684                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2685                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2686                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2687                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2688                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2689             } else
2690                 Handled = FALSE;
2691                 break;
2692         case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2693             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2694                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2695                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2696                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2697                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2698                 switch (opr1) {
2699                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2700                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2701                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2702                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2703                 }
2704                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2705                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2706                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2707                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2708                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2709                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2710                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2711                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2712                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2713                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2714                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2715                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2716             } else
2717                 Handled = FALSE;
2718                 break;
2719         case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2720             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2721                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2722                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2723                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2724                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2725                 switch (opr1) {
2726                     case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
2727                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
2728                     case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2729                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2730                 }
2731                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2732                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2733                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2734                 checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2735                 switch (opr1) {
2736                     case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
2737                     case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2738                     case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
2739                     case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
2740                 }
2741                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2742                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2743                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2744                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2745                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2746                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2747                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2748                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2749             } else
2750                 Handled = FALSE;
2751                 break;
2752         case WINED3DTOP_MULTIPLYADD:
2753             if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3)) {
2754                 glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2755                 checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2756                 glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2757                 checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2758                 glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2759                 checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2760                 glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
2761                 checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
2762                 glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
2763                 checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
2764                 glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2765                 checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2766                 glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2767                 checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2768                 glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2769                 checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
2770             } else
2771                 Handled = FALSE;
2772                 break;
2773         case WINED3DTOP_BUMPENVMAPLUMINANCE:
2774         case WINED3DTOP_BUMPENVMAP:
2775             if(GL_SUPPORT(NV_TEXTURE_SHADER2)) {
2776                 /* Technically texture shader support without register combiners is possible, but not expected to occur
2777                  * on real world cards, so for now a fixme should be enough
2778                  */
2779                 FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
2780             }
2781         default:
2782             Handled = FALSE;
2783     }
2784
2785     if (Handled) {
2786         BOOL  combineOK = TRUE;
2787         if (GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
2788             DWORD op2;
2789
2790             if (isAlpha) {
2791                 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_COLOROP];
2792             } else {
2793                 op2 = This->stateBlock->textureState[Stage][WINED3DTSS_ALPHAOP];
2794             }
2795
2796             /* Note: If COMBINE4 in effect can't go back to combine! */
2797             switch (op2) {
2798                 case WINED3DTOP_ADDSMOOTH:
2799                 case WINED3DTOP_BLENDTEXTUREALPHAPM:
2800                 case WINED3DTOP_MODULATEALPHA_ADDCOLOR:
2801                 case WINED3DTOP_MODULATECOLOR_ADDALPHA:
2802                 case WINED3DTOP_MODULATEINVALPHA_ADDCOLOR:
2803                 case WINED3DTOP_MODULATEINVCOLOR_ADDALPHA:
2804                 case WINED3DTOP_MULTIPLYADD:
2805                     /* Ignore those implemented in both cases */
2806                     switch (op) {
2807                         case WINED3DTOP_SELECTARG1:
2808                         case WINED3DTOP_SELECTARG2:
2809                             combineOK = FALSE;
2810                             Handled   = FALSE;
2811                             break;
2812                         default:
2813                             FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
2814                             return;
2815                     }
2816             }
2817         }
2818
2819         if (combineOK) {
2820             glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE));
2821             checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, useext(GL_COMBINE)");
2822
2823             return;
2824         }
2825     }
2826
2827     /* After all the extensions, if still unhandled, report fixme */
2828     FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
2829 }
2830
2831
2832 static void tex_colorop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2833     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2834     DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2835     BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2836
2837     TRACE("Setting color op for stage %d\n", stage);
2838
2839     /* Using a pixel shader? Don't care for anything here, the shader applying does it */
2840     if (use_ps(stateblock)) return;
2841
2842     if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);
2843
2844     if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2845     {
2846         if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2847             FIXME("Attempt to enable unsupported stage!\n");
2848             return;
2849         }
2850         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2851         checkGLcall("glActiveTextureARB");
2852     }
2853
2854     if(stage >= stateblock->lowest_disabled_stage) {
2855         TRACE("Stage disabled\n");
2856         if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2857         {
2858             /* Disable everything here */
2859             glDisable(GL_TEXTURE_2D);
2860             checkGLcall("glDisable(GL_TEXTURE_2D)");
2861             glDisable(GL_TEXTURE_3D);
2862             checkGLcall("glDisable(GL_TEXTURE_3D)");
2863             if(GL_SUPPORT(ARB_TEXTURE_CUBE_MAP)) {
2864                 glDisable(GL_TEXTURE_CUBE_MAP_ARB);
2865                 checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
2866             }
2867             if(GL_SUPPORT(ARB_TEXTURE_RECTANGLE)) {
2868                 glDisable(GL_TEXTURE_RECTANGLE_ARB);
2869                 checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
2870             }
2871         }
2872         /* All done */
2873         return;
2874     }
2875
2876     /* The sampler will also activate the correct texture dimensions, so no need to do it here
2877      * if the sampler for this stage is dirty
2878      */
2879     if(!isStateDirty(context, STATE_SAMPLER(stage))) {
2880         if (tex_used) texture_activate_dimensions(stage, stateblock, context);
2881     }
2882
2883     set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, FALSE, stage,
2884                 stateblock->textureState[stage][WINED3DTSS_COLOROP],
2885                 stateblock->textureState[stage][WINED3DTSS_COLORARG1],
2886                 stateblock->textureState[stage][WINED3DTSS_COLORARG2],
2887                 stateblock->textureState[stage][WINED3DTSS_COLORARG0]);
2888 }
2889
2890 void tex_alphaop(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2891     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2892     DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
2893     BOOL tex_used = stateblock->wineD3DDevice->fixed_function_usage_map & (1 << stage);
2894     DWORD op, arg1, arg2, arg0;
2895
2896     TRACE("Setting alpha op for stage %d\n", stage);
2897     /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
2898     if (mapped_stage != WINED3D_UNMAPPED_STAGE)
2899     {
2900         if (tex_used && mapped_stage >= GL_LIMITS(textures)) {
2901             FIXME("Attempt to enable unsupported stage!\n");
2902             return;
2903         }
2904         GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
2905         checkGLcall("glActiveTextureARB");
2906     }
2907
2908     op = stateblock->textureState[stage][WINED3DTSS_ALPHAOP];
2909     arg1 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG1];
2910     arg2 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG2];
2911     arg0 = stateblock->textureState[stage][WINED3DTSS_ALPHAARG0];
2912
2913     if (stateblock->renderState[WINED3DRS_COLORKEYENABLE] && stage == 0 && stateblock->textures[0])
2914     {
2915         UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(stateblock->textures[0]);
2916
2917         if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
2918         {
2919             IWineD3DSurfaceImpl *surf;
2920
2921             surf = (IWineD3DSurfaceImpl *) ((IWineD3DTextureImpl *) stateblock->textures[0])->surfaces[0];
2922
2923             if (surf->CKeyFlags & WINEDDSD_CKSRCBLT && !surf->resource.format_desc->alpha_mask)
2924             {
2925                 /* Color keying needs to pass alpha values from the texture through to have the alpha test work
2926                  * properly. On the other hand applications can still use texture combiners apparently. This code
2927                  * takes care that apps cannot remove the texture's alpha channel entirely.
2928                  *
2929                  * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
2930                  * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
2931                  * and alpha component of diffuse color to draw things like translucent text and perform other
2932                  * blending effects.
2933                  *
2934                  * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
2935                  * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
2936                  * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
2937                  * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
2938                  * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
2939                  * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
2940                  * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
2941                  * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
2942                  * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
2943                  * alpha.
2944                  *
2945                  * What to do with multitexturing? So far no app has been found that uses color keying with
2946                  * multitexturing */
2947                 if (op == WINED3DTOP_DISABLE)
2948                 {
2949                     arg1 = WINED3DTA_TEXTURE;
2950                     op = WINED3DTOP_SELECTARG1;
2951                 }
2952                 else if(op == WINED3DTOP_SELECTARG1 && arg1 != WINED3DTA_TEXTURE)
2953                 {
2954                     if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
2955                     {
2956                         arg2 = WINED3DTA_TEXTURE;
2957                         op = WINED3DTOP_MODULATE;
2958                     }
2959                     else arg1 = WINED3DTA_TEXTURE;
2960                 }
2961                 else if(op == WINED3DTOP_SELECTARG2 && arg2 != WINED3DTA_TEXTURE)
2962                 {
2963                     if (stateblock->renderState[WINED3DRS_ALPHABLENDENABLE])
2964                     {
2965                         arg1 = WINED3DTA_TEXTURE;
2966                         op = WINED3DTOP_MODULATE;
2967                     }
2968                     else arg2 = WINED3DTA_TEXTURE;
2969                 }
2970             }
2971         }
2972     }
2973
2974     /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
2975      * this if block here, and the other code(color keying, texture unit selection) are the same
2976      */
2977     TRACE("Setting alpha op for stage %d\n", stage);
2978     if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
2979         set_tex_op_nvrc((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2980                          op, arg1, arg2, arg0,
2981                          mapped_stage,
2982                          stateblock->textureState[stage][WINED3DTSS_RESULTARG]);
2983     } else {
2984         set_tex_op((IWineD3DDevice *)stateblock->wineD3DDevice, TRUE, stage,
2985                     op, arg1, arg2, arg0);
2986     }
2987 }
2988
2989 static void transform_texture(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2990     DWORD texUnit = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
2991     DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[texUnit];
2992     BOOL generated;
2993     int coordIdx;
2994
2995     /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
2996     if (use_vs(stateblock) || isStateDirty(context, STATE_VDECL))
2997     {
2998         TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
2999         return;
3000     }
3001
3002     if (mapped_stage == WINED3D_UNMAPPED_STAGE) return;
3003
3004     if(mapped_stage >= GL_LIMITS(textures)) {
3005         return;
3006     }
3007     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3008     checkGLcall("glActiveTextureARB");
3009     generated = (stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX] & 0xFFFF0000) != WINED3DTSS_TCI_PASSTHRU;
3010     coordIdx = min(stateblock->textureState[texUnit][WINED3DTSS_TEXCOORDINDEX & 0x0000FFFF], MAX_TEXTURES - 1);
3011
3012     set_texture_matrix(&stateblock->transforms[WINED3DTS_TEXTURE0 + texUnit].u.m[0][0],
3013             stateblock->textureState[texUnit][WINED3DTSS_TEXTURETRANSFORMFLAGS], generated, context->last_was_rhw,
3014             stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].stride
3015             ? stateblock->wineD3DDevice->strided_streams.elements[WINED3D_FFP_TEXCOORD0 + coordIdx].d3d_format
3016             : WINED3DFMT_UNKNOWN,
3017             stateblock->wineD3DDevice->frag_pipe->ffp_proj_control);
3018
3019     /* The sampler applying function calls us if this changes */
3020     if ((context->lastWasPow2Texture & (1 << texUnit)) && stateblock->textures[texUnit])
3021     {
3022         if(generated) {
3023             FIXME("Non-power2 texture being used with generated texture coords\n");
3024         }
3025         TRACE("Non power two matrix multiply fixup\n");
3026         glMultMatrixf(((IWineD3DTextureImpl *) stateblock->textures[texUnit])->baseTexture.pow2Matrix);
3027     }
3028 }
3029
3030 static void unloadTexCoords(IWineD3DStateBlockImpl *stateblock) {
3031     unsigned int texture_idx;
3032
3033     for (texture_idx = 0; texture_idx < GL_LIMITS(texture_stages); ++texture_idx) {
3034         GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + texture_idx));
3035         glDisableClientState(GL_TEXTURE_COORD_ARRAY);
3036     }
3037 }
3038
3039 static void loadTexCoords(IWineD3DStateBlockImpl *stateblock, const struct wined3d_stream_info *si, GLuint *curVBO)
3040 {
3041     const UINT *offset = stateblock->streamOffset;
3042     unsigned int mapped_stage = 0;
3043     unsigned int textureNo = 0;
3044
3045     for (textureNo = 0; textureNo < GL_LIMITS(texture_stages); ++textureNo) {
3046         int coordIdx = stateblock->textureState[textureNo][WINED3DTSS_TEXCOORDINDEX];
3047         const struct wined3d_stream_info_element *e;
3048
3049         mapped_stage = stateblock->wineD3DDevice->texUnitMap[textureNo];
3050         if (mapped_stage == WINED3D_UNMAPPED_STAGE) continue;
3051
3052         e = &si->elements[WINED3D_FFP_TEXCOORD0 + coordIdx];
3053         if (coordIdx < MAX_TEXTURES && (e->data || e->buffer_object))
3054         {
3055             TRACE("Setting up texture %u, idx %d, cordindx %u, data %p\n",
3056                     textureNo, mapped_stage, coordIdx, e->data);
3057
3058             if (*curVBO != e->buffer_object)
3059             {
3060                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
3061                 checkGLcall("glBindBufferARB");
3062                 *curVBO = e->buffer_object;
3063             }
3064
3065             GL_EXTCALL(glClientActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3066             checkGLcall("glClientActiveTextureARB");
3067
3068             /* The coords to supply depend completely on the fvf / vertex shader */
3069             glTexCoordPointer(e->format, e->type, e->stride,
3070                     e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
3071             glEnableClientState(GL_TEXTURE_COORD_ARRAY);
3072         } else {
3073             GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + mapped_stage, 0, 0, 0, 1));
3074         }
3075     }
3076     if (GL_SUPPORT(NV_REGISTER_COMBINERS)) {
3077         /* The number of the mapped stages increases monotonically, so it's fine to use the last used one */
3078         for (textureNo = mapped_stage + 1; textureNo < GL_LIMITS(textures); ++textureNo) {
3079             GL_EXTCALL(glMultiTexCoord4fARB(GL_TEXTURE0_ARB + textureNo, 0, 0, 0, 1));
3080         }
3081     }
3082
3083     checkGLcall("loadTexCoords");
3084 }
3085
3086 static void tex_coordindex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3087     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3088     DWORD mapped_stage = stateblock->wineD3DDevice->texUnitMap[stage];
3089     static const GLfloat s_plane[] = { 1.0, 0.0, 0.0, 0.0 };
3090     static const GLfloat t_plane[] = { 0.0, 1.0, 0.0, 0.0 };
3091     static const GLfloat r_plane[] = { 0.0, 0.0, 1.0, 0.0 };
3092     static const GLfloat q_plane[] = { 0.0, 0.0, 0.0, 1.0 };
3093
3094     if (mapped_stage == WINED3D_UNMAPPED_STAGE)
3095     {
3096         TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
3097         return;
3098     }
3099
3100     if(mapped_stage >= GL_LIMITS(fragment_samplers)) {
3101         WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage);
3102         return;
3103     }
3104     GL_EXTCALL(glActiveTextureARB(GL_TEXTURE0_ARB + mapped_stage));
3105     checkGLcall("glActiveTextureARB");
3106
3107     /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
3108      *
3109      * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
3110      * eg. SetTextureStageState( 0, WINED3DTSS_TEXCOORDINDEX, WINED3DTSS_TCI_CAMERASPACEPOSITION | 1 );
3111      * means use the vertex position (camera-space) as the input texture coordinates
3112      * for this texture stage, and the wrap mode set in the WINED3DRS_WRAP1 render
3113      * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
3114      * to the TEXCOORDINDEX value
3115      */
3116     switch (stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX] & 0xffff0000)
3117     {
3118         case WINED3DTSS_TCI_PASSTHRU:
3119             /* Use the specified texture coordinates contained within the
3120              * vertex format. This value resolves to zero. */
3121             glDisable(GL_TEXTURE_GEN_S);
3122             glDisable(GL_TEXTURE_GEN_T);
3123             glDisable(GL_TEXTURE_GEN_R);
3124             glDisable(GL_TEXTURE_GEN_Q);
3125             checkGLcall("WINED3DTSS_TCI_PASSTHRU - Disable texgen.");
3126             break;
3127
3128         case WINED3DTSS_TCI_CAMERASPACEPOSITION:
3129             /* CameraSpacePosition means use the vertex position, transformed to camera space,
3130              * as the input texture coordinates for this stage's texture transformation. This
3131              * equates roughly to EYE_LINEAR */
3132
3133             glMatrixMode(GL_MODELVIEW);
3134             glPushMatrix();
3135             glLoadIdentity();
3136             glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3137             glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3138             glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3139             glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3140             glPopMatrix();
3141             checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane.");
3142
3143             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3144             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3145             glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3146             checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set texgen mode.");
3147
3148             glEnable(GL_TEXTURE_GEN_S);
3149             glEnable(GL_TEXTURE_GEN_T);
3150             glEnable(GL_TEXTURE_GEN_R);
3151             checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Enable texgen.");
3152
3153             break;
3154
3155         case WINED3DTSS_TCI_CAMERASPACENORMAL:
3156             /* Note that NV_TEXGEN_REFLECTION support is implied when
3157              * ARB_TEXTURE_CUBE_MAP is supported */
3158             if (!GL_SUPPORT(NV_TEXGEN_REFLECTION))
3159             {
3160                 FIXME("WINED3DTSS_TCI_CAMERASPACENORMAL not supported.\n");
3161                 break;
3162             }
3163
3164             glMatrixMode(GL_MODELVIEW);
3165             glPushMatrix();
3166             glLoadIdentity();
3167             glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3168             glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3169             glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3170             glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3171             glPopMatrix();
3172             checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane.");
3173
3174             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3175             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3176             glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3177             checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set texgen mode.");
3178
3179             glEnable(GL_TEXTURE_GEN_S);
3180             glEnable(GL_TEXTURE_GEN_T);
3181             glEnable(GL_TEXTURE_GEN_R);
3182             checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Enable texgen.");
3183
3184             break;
3185
3186         case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3187             /* Note that NV_TEXGEN_REFLECTION support is implied when
3188              * ARB_TEXTURE_CUBE_MAP is supported */
3189             if (!GL_SUPPORT(NV_TEXGEN_REFLECTION))
3190             {
3191                 FIXME("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR not supported.\n");
3192                 break;
3193             }
3194
3195             glMatrixMode(GL_MODELVIEW);
3196             glPushMatrix();
3197             glLoadIdentity();
3198             glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
3199             glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
3200             glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
3201             glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
3202             glPopMatrix();
3203             checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane.");
3204
3205             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3206             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3207             glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3208             checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set texgen mode.");
3209
3210             glEnable(GL_TEXTURE_GEN_S);
3211             glEnable(GL_TEXTURE_GEN_T);
3212             glEnable(GL_TEXTURE_GEN_R);
3213             checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Enable texgen.");
3214
3215             break;
3216
3217         case WINED3DTSS_TCI_SPHEREMAP:
3218             glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3219             glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3220             checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Set texgen mode.");
3221
3222             glEnable(GL_TEXTURE_GEN_S);
3223             glEnable(GL_TEXTURE_GEN_T);
3224             glDisable(GL_TEXTURE_GEN_R);
3225             checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Enable texgen.");
3226
3227             break;
3228
3229         default:
3230             FIXME("Unhandled WINED3DTSS_TEXCOORDINDEX %#x\n",
3231                     stateblock->textureState[stage][WINED3DTSS_TEXCOORDINDEX]);
3232             glDisable(GL_TEXTURE_GEN_S);
3233             glDisable(GL_TEXTURE_GEN_T);
3234             glDisable(GL_TEXTURE_GEN_R);
3235             glDisable(GL_TEXTURE_GEN_Q);
3236             checkGLcall("Disable texgen.");
3237
3238             break;
3239     }
3240
3241     /* Update the texture matrix */
3242     if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + stage))) {
3243         transform_texture(STATE_TEXTURESTAGE(stage, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
3244     }
3245
3246     if(!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded) {
3247         /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3248          * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3249          * and do all the things linked to it
3250          * TODO: Tidy that up to reload only the arrays of the changed unit
3251          */
3252         GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3253
3254         unloadTexCoords(stateblock);
3255         loadTexCoords(stateblock, &stateblock->wineD3DDevice->strided_streams, &curVBO);
3256     }
3257 }
3258
3259 static void shaderconstant(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3260     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3261
3262     /* Vertex and pixel shader states will call a shader upload, don't do anything as long one of them
3263      * has an update pending
3264      */
3265     if(isStateDirty(context, STATE_VDECL) ||
3266        isStateDirty(context, STATE_PIXELSHADER)) {
3267        return;
3268     }
3269
3270     device->shader_backend->shader_load_constants((IWineD3DDevice *)device, use_ps(stateblock), use_vs(stateblock));
3271 }
3272
3273 static void tex_bumpenvlscale(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3274     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3275
3276     if(stateblock->pixelShader && stage != 0 &&
3277        ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.luminanceparams[stage]) {
3278         /* The pixel shader has to know the luminance scale. Do a constants update if it
3279          * isn't scheduled anyway
3280          */
3281         if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3282            !isStateDirty(context, STATE_PIXELSHADER)) {
3283             shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3284         }
3285     }
3286 }
3287
3288 static void sampler_texmatrix(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3289     BOOL texIsPow2 = FALSE;
3290     DWORD sampler = state - STATE_SAMPLER(0);
3291     IWineD3DBaseTexture *texture = stateblock->textures[sampler];
3292
3293     TRACE("state %#x, stateblock %p, context %p\n", state, stateblock, context);
3294
3295     if(!texture) return;
3296     /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3297      * IWineD3DBaseTexture::ApplyStateChanges multiplies the set matrix with a fixup matrix. Before the
3298      * scaling is reapplied or removed, the texture matrix has to be reapplied
3299      *
3300      * The mapped stage is already active because the sampler() function below, which is part of the
3301      * misc pipeline
3302      */
3303     if(sampler < MAX_TEXTURES) {
3304         UINT texture_dimensions = IWineD3DBaseTexture_GetTextureDimensions(texture);
3305
3306         if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
3307         {
3308             if(((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0 ||
3309                ((IWineD3DTextureImpl *)texture)->baseTexture.pow2Matrix[5] != 1.0 ) {
3310                 texIsPow2 = TRUE;
3311             }
3312         }
3313         else if (texture_dimensions == GL_TEXTURE_CUBE_MAP_ARB)
3314         {
3315             if(((IWineD3DCubeTextureImpl *)texture)->baseTexture.pow2Matrix[0] != 1.0) {
3316                 texIsPow2 = TRUE;
3317             }
3318         }
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     } else if(mapped_stage < GL_LIMITS(textures)) {
3379         if(sampler < stateblock->lowest_disabled_stage) {
3380             /* TODO: What should I do with pixel shaders here ??? */
3381             if(stateblock->renderState[WINED3DRS_COLORKEYENABLE] && sampler == 0) {
3382                 /* If color keying is enabled update the alpha test, it depends on the existence
3383                 * of a color key in stage 0
3384                 */
3385                 state_alpha(WINED3DRS_COLORKEYENABLE, stateblock, context);
3386             }
3387         } /* Otherwise tex_colorop disables the stage */
3388         glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler]);
3389         checkGLcall("glBindTexture(GL_TEXTURE_2D, stateblock->wineD3DDevice->dummyTextureName[sampler])");
3390     }
3391 }
3392
3393 void apply_pixelshader(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3394     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3395     BOOL use_pshader = use_ps(stateblock);
3396     BOOL use_vshader = use_vs(stateblock);
3397     int i;
3398
3399     if (use_pshader) {
3400         if(!context->last_was_pshader) {
3401             /* Former draw without a pixel shader, some samplers
3402              * may be disabled because of WINED3DTSS_COLOROP = WINED3DTOP_DISABLE
3403              * make sure to enable them
3404              */
3405             for(i=0; i < MAX_FRAGMENT_SAMPLERS; i++) {
3406                 if(!isStateDirty(context, STATE_SAMPLER(i))) {
3407                     sampler(STATE_SAMPLER(i), stateblock, context);
3408                 }
3409             }
3410             context->last_was_pshader = TRUE;
3411         } else {
3412            /* Otherwise all samplers were activated by the code above in earlier draws, or by sampler()
3413             * if a different texture was bound. I don't have to do anything.
3414             */
3415         }
3416     } else {
3417         /* Disabled the pixel shader - color ops weren't applied
3418          * while it was enabled, so re-apply them.
3419          */
3420         for(i=0; i < MAX_TEXTURES; i++) {
3421             if(!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP))) {
3422                 device->StateTable[STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP)].apply
3423                         (STATE_TEXTURESTAGE(i, WINED3DTSS_COLOROP), stateblock, context);
3424             }
3425         }
3426         context->last_was_pshader = FALSE;
3427     }
3428
3429     if(!isStateDirty(context, device->StateTable[STATE_VSHADER].representative)) {
3430         device->shader_backend->shader_select((IWineD3DDevice *)stateblock->wineD3DDevice, use_pshader, use_vshader);
3431
3432         if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (use_vshader || use_pshader)) {
3433             shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3434         }
3435     }
3436 }
3437
3438 static void shader_bumpenvmat(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3439     DWORD stage = (state - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3440     if(stateblock->pixelShader && stage != 0 &&
3441        ((IWineD3DPixelShaderImpl *) stateblock->pixelShader)->baseShader.reg_maps.bumpmat[stage]) {
3442         /* The pixel shader has to know the bump env matrix. Do a constants update if it isn't scheduled
3443          * anyway
3444          */
3445         if(!isStateDirty(context, STATE_PIXELSHADERCONSTANT) &&
3446             !isStateDirty(context, STATE_PIXELSHADER)) {
3447             shaderconstant(STATE_PIXELSHADERCONSTANT, stateblock, context);
3448         }
3449     }
3450 }
3451
3452 static void transform_world(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3453     /* This function is called by transform_view below if the view matrix was changed too
3454      *
3455      * Deliberately no check if the vertex declaration is dirty because the vdecl state
3456      * does not always update the world matrix, only on a switch between transformed
3457      * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3458      * draw, but that should be rather rare and cheaper in total.
3459      */
3460     glMatrixMode(GL_MODELVIEW);
3461     checkGLcall("glMatrixMode");
3462
3463     if(context->last_was_rhw) {
3464         glLoadIdentity();
3465         checkGLcall("glLoadIdentity()");
3466     } else {
3467         /* In the general case, the view matrix is the identity matrix */
3468         if (stateblock->wineD3DDevice->view_ident) {
3469             glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3470             checkGLcall("glLoadMatrixf");
3471         } else {
3472             glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3473             checkGLcall("glLoadMatrixf");
3474             glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(0)].u.m[0][0]);
3475             checkGLcall("glMultMatrixf");
3476         }
3477     }
3478 }
3479
3480 static void clipplane(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3481     UINT index = state - STATE_CLIPPLANE(0);
3482
3483     if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW)) || index >= GL_LIMITS(clipplanes)) {
3484         return;
3485     }
3486
3487     /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3488     glMatrixMode(GL_MODELVIEW);
3489     glPushMatrix();
3490     glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3491
3492     TRACE("Clipplane [%f,%f,%f,%f]\n",
3493           stateblock->clipplane[index][0],
3494           stateblock->clipplane[index][1],
3495           stateblock->clipplane[index][2],
3496           stateblock->clipplane[index][3]);
3497     glClipPlane(GL_CLIP_PLANE0 + index, stateblock->clipplane[index]);
3498     checkGLcall("glClipPlane");
3499
3500     glPopMatrix();
3501 }
3502
3503 static void transform_worldex(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3504     UINT matrix = state - STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0));
3505     GLenum glMat;
3506     TRACE("Setting world matrix %d\n", matrix);
3507
3508     if(matrix >= GL_LIMITS(blends)) {
3509         WARN("Unsupported blend matrix set\n");
3510         return;
3511     } else if(isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3512         return;
3513     }
3514
3515     /* GL_MODELVIEW0_ARB:  0x1700
3516      * GL_MODELVIEW1_ARB:  0x850a
3517      * GL_MODELVIEW2_ARB:  0x8722
3518      * GL_MODELVIEW3_ARB:  0x8723
3519      * etc
3520      * GL_MODELVIEW31_ARB: 0x873F
3521      */
3522     if(matrix == 1) glMat = GL_MODELVIEW1_ARB;
3523     else glMat = GL_MODELVIEW2_ARB - 2 + matrix;
3524
3525     glMatrixMode(glMat);
3526     checkGLcall("glMatrixMode(glMat)");
3527
3528     /* World matrix 0 is multiplied with the view matrix because d3d uses 3 matrices while gl uses only 2. To avoid
3529      * weighting the view matrix incorrectly it has to be multiplied into every gl modelview matrix
3530      */
3531     if(stateblock->wineD3DDevice->view_ident) {
3532         glLoadMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3533         checkGLcall("glLoadMatrixf");
3534     } else {
3535         glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3536         checkGLcall("glLoadMatrixf");
3537         glMultMatrixf(&stateblock->transforms[WINED3DTS_WORLDMATRIX(matrix)].u.m[0][0]);
3538         checkGLcall("glMultMatrixf");
3539     }
3540 }
3541
3542 static void state_vertexblend_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3543     static BOOL once = FALSE;
3544
3545     switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) {
3546         case WINED3DVBF_1WEIGHTS:
3547         case WINED3DVBF_2WEIGHTS:
3548         case WINED3DVBF_3WEIGHTS:
3549             if(!once) {
3550                 once = TRUE;
3551                 /* TODO: Implement vertex blending in drawStridedSlow */
3552                 FIXME("Vertex blending enabled, but not supported by hardware\n");
3553             }
3554             break;
3555
3556         case WINED3DVBF_TWEENING:
3557             WARN("Tweening not supported yet\n");
3558     }
3559 }
3560
3561 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3562     WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
3563
3564     switch(val) {
3565         case WINED3DVBF_1WEIGHTS:
3566         case WINED3DVBF_2WEIGHTS:
3567         case WINED3DVBF_3WEIGHTS:
3568             glEnable(GL_VERTEX_BLEND_ARB);
3569             checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
3570
3571             /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
3572              * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
3573              */
3574             GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
3575
3576             if(!stateblock->wineD3DDevice->vertexBlendUsed) {
3577                 unsigned int i;
3578                 for(i = 1; i < GL_LIMITS(blends); i++) {
3579                     if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
3580                         transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
3581                     }
3582                 }
3583                 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
3584             }
3585             break;
3586
3587         case WINED3DVBF_DISABLE:
3588         case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
3589             glDisable(GL_VERTEX_BLEND_ARB);
3590             checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
3591             break;
3592
3593         case WINED3DVBF_TWEENING:
3594             /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
3595              * vertex weights in the vertices?
3596              * For now we don't report that as supported, so a warn should suffice
3597              */
3598             WARN("Tweening not supported yet\n");
3599             break;
3600     }
3601 }
3602
3603 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3604     unsigned int k;
3605
3606     /* If we are changing the View matrix, reset the light and clipping planes to the new view
3607      * NOTE: We have to reset the positions even if the light/plane is not currently
3608      *       enabled, since the call to enable it will not reset the position.
3609      * NOTE2: Apparently texture transforms do NOT need reapplying
3610      */
3611
3612     const PLIGHTINFOEL *light = NULL;
3613
3614     glMatrixMode(GL_MODELVIEW);
3615     checkGLcall("glMatrixMode(GL_MODELVIEW)");
3616     glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3617     checkGLcall("glLoadMatrixf(...)");
3618
3619     /* Reset lights. TODO: Call light apply func */
3620     for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
3621         light = stateblock->activeLights[k];
3622         if(!light) continue;
3623         glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
3624         checkGLcall("glLightfv posn");
3625         glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
3626         checkGLcall("glLightfv dirn");
3627     }
3628
3629     /* Reset Clipping Planes  */
3630     for (k = 0; k < GL_LIMITS(clipplanes); k++) {
3631         if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
3632             clipplane(STATE_CLIPPLANE(k), stateblock, context);
3633         }
3634     }
3635
3636     if(context->last_was_rhw) {
3637         glLoadIdentity();
3638         checkGLcall("glLoadIdentity()");
3639         /* No need to update the world matrix, the identity is fine */
3640         return;
3641     }
3642
3643     /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3644      * No need to do it here if the state is scheduled for update.
3645      */
3646     if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3647         transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3648     }
3649
3650     /* Avoid looping over a number of matrices if the app never used the functionality */
3651     if(stateblock->wineD3DDevice->vertexBlendUsed) {
3652         for(k = 1; k < GL_LIMITS(blends); k++) {
3653             if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
3654                 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
3655             }
3656         }
3657     }
3658 }
3659
3660 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3661     glMatrixMode(GL_PROJECTION);
3662     checkGLcall("glMatrixMode(GL_PROJECTION)");
3663     glLoadIdentity();
3664     checkGLcall("glLoadIdentity");
3665
3666     if(context->last_was_rhw) {
3667         double X, Y, height, width, minZ, maxZ;
3668
3669         X      = stateblock->viewport.X;
3670         Y      = stateblock->viewport.Y;
3671         height = stateblock->viewport.Height;
3672         width  = stateblock->viewport.Width;
3673         minZ   = stateblock->viewport.MinZ;
3674         maxZ   = stateblock->viewport.MaxZ;
3675
3676         if(!stateblock->wineD3DDevice->untransformed) {
3677             /* Transformed vertices are supposed to bypass the whole transform pipeline including
3678              * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
3679              * suppress depth clipping. This can be done because it is an orthogonal projection and
3680              * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
3681              * Persia 3D need this.
3682              *
3683              * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
3684              * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
3685              * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
3686              * to the viewer.
3687              *
3688              * Also note that this breaks z comparison against z values filled in with clear,
3689              * but no app depending on that and disabled clipping has been found yet. Comparing
3690              * primitives against themselves works, so the Z buffer is still intact for normal hidden
3691              * surface removal.
3692              *
3693              * We could disable clipping entirely by setting the near to infinity and far to -infinity,
3694              * but this would break Z buffer operation. Raising the range to something less than
3695              * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
3696              * problem either.
3697              */
3698             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
3699             if(stateblock->wineD3DDevice->render_offscreen) {
3700                 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
3701             } else {
3702                 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
3703             }
3704         } else {
3705             /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
3706              * trick above because this would mess up transformed and untransformed Z order. Pass the z position
3707              * unmodified to opengl.
3708              *
3709              * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
3710              * replacement shader.
3711              */
3712             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
3713             if(stateblock->wineD3DDevice->render_offscreen) {
3714                 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
3715             } else {
3716                 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
3717             }
3718         }
3719         checkGLcall("glOrtho");
3720
3721         /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
3722         glTranslatef(0.5, 0.5, 0);
3723         checkGLcall("glTranslatef(0.5, 0.5, 0)");
3724         /* D3D texture coordinates are flipped compared to OpenGL ones, so
3725          * render everything upside down when rendering offscreen. */
3726         if (stateblock->wineD3DDevice->render_offscreen) {
3727             glScalef(1.0, -1.0, 1.0);
3728             checkGLcall("glScalef");
3729         }
3730     } else {
3731         /* The rule is that the window coordinate 0 does not correspond to the
3732             beginning of the first pixel, but the center of the first pixel.
3733             As a consequence if you want to correctly draw one line exactly from
3734             the left to the right end of the viewport (with all matrices set to
3735             be identity), the x coords of both ends of the line would be not
3736             -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
3737             instead.
3738
3739             1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
3740             divide by the Width/Height, so we need the half range(1.0) to translate by
3741             half a pixel.
3742
3743             The other fun is that d3d's output z range after the transformation is [0;1],
3744             but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
3745             scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
3746             of Z buffer precision and the clear values do not match in the z test. Thus scale
3747             [0;1] to [-1;1], so when gl undoes that we utilize the full z range
3748          */
3749
3750         /*
3751          * Careful with the order of operations here, we're essentially working backwards:
3752          * x = x + 1/w;
3753          * y = (y - 1/h) * flip;
3754          * z = z * 2 - 1;
3755          *
3756          * Becomes:
3757          * glTranslatef(0.0, 0.0, -1.0);
3758          * glScalef(1.0, 1.0, 2.0);
3759          *
3760          * glScalef(1.0, flip, 1.0);
3761          * glTranslatef(1/w, -1/h, 0.0);
3762          *
3763          * This is equivalent to:
3764          * glTranslatef(1/w, -flip/h, -1.0)
3765          * glScalef(1.0, flip, 2.0);
3766          */
3767
3768         if (stateblock->wineD3DDevice->render_offscreen) {
3769             /* D3D texture coordinates are flipped compared to OpenGL ones, so
3770              * render everything upside down when rendering offscreen. */
3771             glTranslatef(1.0 / stateblock->viewport.Width, 1.0 / stateblock->viewport.Height, -1.0);
3772             checkGLcall("glTranslatef(1.0 / width, 1.0 / height, -1.0)");
3773             glScalef(1.0, -1.0, 2.0);
3774         } else {
3775             glTranslatef(1.0 / stateblock->viewport.Width, -1.0 / stateblock->viewport.Height, -1.0);
3776             checkGLcall("glTranslatef(1.0 / width, -1.0 / height, -1.0)");
3777             glScalef(1.0, 1.0, 2.0);
3778         }
3779         checkGLcall("glScalef");
3780
3781         glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
3782         checkGLcall("glLoadMatrixf");
3783     }
3784 }
3785
3786 /* This should match any arrays loaded in loadVertexData.
3787  * stateblock impl is required for GL_SUPPORT
3788  * TODO: Only load / unload arrays if we have to.
3789  */
3790 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
3791     glDisableClientState(GL_VERTEX_ARRAY);
3792     glDisableClientState(GL_NORMAL_ARRAY);
3793     glDisableClientState(GL_COLOR_ARRAY);
3794     if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3795         glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3796     }
3797     if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3798         glDisableClientState(GL_WEIGHT_ARRAY_ARB);
3799     }
3800     unloadTexCoords(stateblock);
3801 }
3802
3803 static inline void unload_numbered_array(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context, int i)
3804 {
3805     GL_EXTCALL(glDisableVertexAttribArrayARB(i));
3806     checkGLcall("glDisableVertexAttribArrayARB(reg)");
3807     /* Some Windows drivers(NV GF 7) use the latest value that was used when drawing with the now
3808      * deactivated stream disabled, some other drivers(ATI, NV GF 8) set the undefined values to 0x00.
3809      * Let's set them to 0x00 to avoid hitting some undefined aspects of OpenGL. All that is really
3810      * important here is the glDisableVertexAttribArrayARB call above. The test shows that the refrast
3811      * keeps dereferencing the pointers, which would cause crashes in some games like Half Life 2: Episode Two.
3812      */
3813     GL_EXTCALL(glVertexAttrib4NubARB(i, 0, 0, 0, 0));
3814     checkGLcall("glVertexAttrib4NubARB(i, 0, 0, 0, 0)");
3815
3816     context->numbered_array_mask &= ~(1 << i);
3817 }
3818
3819 /* This should match any arrays loaded in loadNumberedArrays
3820  * TODO: Only load / unload arrays if we have to.
3821  */
3822 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineD3DContext *context)
3823 {
3824     /* disable any attribs (this is the same for both GLSL and ARB modes) */
3825     GLint maxAttribs = 16;
3826     int i;
3827
3828     /* Leave all the attribs disabled */
3829     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
3830     /* MESA does not support it right not */
3831     if (glGetError() != GL_NO_ERROR)
3832         maxAttribs = 16;
3833     for (i = 0; i < maxAttribs; ++i) {
3834         unload_numbered_array(stateblock, context, i);
3835     }
3836 }
3837
3838 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock,
3839         const struct wined3d_stream_info *stream_info, WineD3DContext *context)
3840 {
3841     GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
3842     int i;
3843     const UINT *offset = stateblock->streamOffset;
3844     struct wined3d_buffer *vb;
3845     DWORD_PTR shift_index;
3846
3847     /* Default to no instancing */
3848     stateblock->wineD3DDevice->instancedDraw = FALSE;
3849
3850     for (i = 0; i < MAX_ATTRIBS; i++) {
3851         if (!(stream_info->use_map & (1 << i)))
3852         {
3853             if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3854             continue;
3855         }
3856
3857         /* Do not load instance data. It will be specified using glTexCoord by drawprim */
3858         if (stateblock->streamFlags[stream_info->elements[i].stream_idx] & WINED3DSTREAMSOURCE_INSTANCEDATA)
3859         {
3860             if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3861             stateblock->wineD3DDevice->instancedDraw = TRUE;
3862             continue;
3863         }
3864
3865         TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, stream_info->elements[i].buffer_object);
3866
3867         if (stream_info->elements[i].stride)
3868         {
3869             if (curVBO != stream_info->elements[i].buffer_object)
3870             {
3871                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, stream_info->elements[i].buffer_object));
3872                 checkGLcall("glBindBufferARB");
3873                 curVBO = stream_info->elements[i].buffer_object;
3874             }
3875             vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
3876             /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
3877              * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
3878              * vbo we won't be load converted attributes anyway
3879              */
3880             if (curVBO && vb->conversion_shift)
3881             {
3882                 TRACE("Loading attribute from shifted buffer\n");
3883                 TRACE("Attrib %d has original stride %d, new stride %d\n",
3884                         i, stream_info->elements[i].stride, vb->conversion_stride);
3885                 TRACE("Original offset %p, additional offset 0x%08x\n",
3886                         stream_info->elements[i].data, vb->conversion_shift[(DWORD_PTR)stream_info->elements[i].data]);
3887                 TRACE("Opengl type %#x\n", stream_info->elements[i].type);
3888                 shift_index = ((DWORD_PTR)stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx]);
3889                 shift_index = shift_index % stream_info->elements[i].stride;
3890                 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format,
3891                         stream_info->elements[i].type, stream_info->elements[i].normalized,
3892                         vb->conversion_stride, stream_info->elements[i].data + vb->conversion_shift[shift_index]
3893                         + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
3894                         + offset[stream_info->elements[i].stream_idx]));
3895
3896             } else {
3897                 GL_EXTCALL(glVertexAttribPointerARB(i, stream_info->elements[i].format,
3898                         stream_info->elements[i].type, stream_info->elements[i].normalized,
3899                         stream_info->elements[i].stride, stream_info->elements[i].data
3900                         + stateblock->loadBaseVertexIndex * stream_info->elements[i].stride
3901                         + offset[stream_info->elements[i].stream_idx]));
3902             }
3903
3904             if (!(context->numbered_array_mask & (1 << i)))
3905             {
3906                 GL_EXTCALL(glEnableVertexAttribArrayARB(i));
3907                 context->numbered_array_mask |= (1 << i);
3908             }
3909         } else {
3910             /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
3911              * set up the attribute statically. But we have to figure out the system memory address.
3912              */
3913             const BYTE *ptr = stream_info->elements[i].data + offset[stream_info->elements[i].stream_idx];
3914             if (stream_info->elements[i].buffer_object)
3915             {
3916                 vb = (struct wined3d_buffer *)stateblock->streamSource[stream_info->elements[i].stream_idx];
3917                 ptr += (long) vb->resource.allocatedMemory;
3918             }
3919
3920             if (context->numbered_array_mask & (1 << i)) unload_numbered_array(stateblock, context, i);
3921
3922             switch(stream_info->elements[i].d3d_format)
3923             {
3924                 case WINED3DFMT_R32_FLOAT:
3925                     GL_EXTCALL(glVertexAttrib1fvARB(i, (const GLfloat *)ptr));
3926                     break;
3927                 case WINED3DFMT_R32G32_FLOAT:
3928                     GL_EXTCALL(glVertexAttrib2fvARB(i, (const GLfloat *)ptr));
3929                     break;
3930                 case WINED3DFMT_R32G32B32_FLOAT:
3931                     GL_EXTCALL(glVertexAttrib3fvARB(i, (const GLfloat *)ptr));
3932                     break;
3933                 case WINED3DFMT_R32G32B32A32_FLOAT:
3934                     GL_EXTCALL(glVertexAttrib4fvARB(i, (const GLfloat *)ptr));
3935                     break;
3936
3937                 case WINED3DFMT_R8G8B8A8_UINT:
3938                     GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3939                     break;
3940                 case WINED3DFMT_A8R8G8B8:
3941                     if (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA))
3942                     {
3943                         const DWORD *src = (const DWORD *)ptr;
3944                         DWORD c = *src & 0xff00ff00;
3945                         c |= (*src & 0xff0000) >> 16;
3946                         c |= (*src & 0xff) << 16;
3947                         GL_EXTCALL(glVertexAttrib4NubvARB(i, (GLubyte *)&c));
3948                         break;
3949                     }
3950                     /* else fallthrough */
3951                 case WINED3DFMT_R8G8B8A8_UNORM:
3952                     GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
3953                     break;
3954
3955                 case WINED3DFMT_R16G16_SINT:
3956                     GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3957                     break;
3958                 case WINED3DFMT_R16G16B16A16_SINT:
3959                     GL_EXTCALL(glVertexAttrib4svARB(i, (const GLshort *)ptr));
3960                     break;
3961
3962                 case WINED3DFMT_R16G16_SNORM:
3963                 {
3964                     const GLshort s[4] = {((const GLshort *)ptr)[0], ((const GLshort *)ptr)[1], 0, 1};
3965                     GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
3966                     break;
3967                 }
3968                 case WINED3DFMT_R16G16_UNORM:
3969                 {
3970                     const GLushort s[4] = {((const GLushort *)ptr)[0], ((const GLushort *)ptr)[1], 0, 1};
3971                     GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
3972                     break;
3973                 }
3974                 case WINED3DFMT_R16G16B16A16_SNORM:
3975                     GL_EXTCALL(glVertexAttrib4NsvARB(i, (const GLshort *)ptr));
3976                     break;
3977                 case WINED3DFMT_R16G16B16A16_UNORM:
3978                     GL_EXTCALL(glVertexAttrib4NusvARB(i, (const GLushort *)ptr));
3979                     break;
3980
3981                 case WINED3DFMT_R10G10B10A2_UINT:
3982                     FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
3983                     /*glVertexAttrib3usvARB(i, (const GLushort *)ptr); Does not exist */
3984                     break;
3985                 case WINED3DFMT_R10G10B10A2_SNORM:
3986                     FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
3987                     /*glVertexAttrib3NusvARB(i, (const GLushort *)ptr); Does not exist */
3988                     break;
3989
3990                 case WINED3DFMT_R16G16_FLOAT:
3991                     /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
3992                      * byte float according to the IEEE standard
3993                      */
3994                     FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
3995                     break;
3996                 case WINED3DFMT_R16G16B16A16_FLOAT:
3997                     FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
3998                     break;
3999
4000                 default:
4001                     ERR("Unexpected declaration in stride 0 attributes\n");
4002                     break;
4003
4004             }
4005         }
4006     }
4007     checkGLcall("Loading numbered arrays");
4008 }
4009
4010 /* Used from 2 different functions, and too big to justify making it inlined */
4011 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, const struct wined3d_stream_info *si)
4012 {
4013     const UINT *offset = stateblock->streamOffset;
4014     GLuint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? ~0U : 0;
4015     const struct wined3d_stream_info_element *e;
4016
4017     TRACE("Using fast vertex array code\n");
4018
4019     /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
4020     stateblock->wineD3DDevice->instancedDraw = FALSE;
4021
4022     /* Blend Data ---------------------------------------------- */
4023     e = &si->elements[WINED3D_FFP_BLENDWEIGHT];
4024     if (e->data || e->buffer_object
4025             || si->elements[WINED3D_FFP_BLENDINDICES].data
4026             || si->elements[WINED3D_FFP_BLENDINDICES].buffer_object)
4027     {
4028         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4029             TRACE("Blend %d %p %d\n", e->size,
4030                     e->data + stateblock->loadBaseVertexIndex * e->stride, e->stride + offset[e->stream_idx]);
4031
4032             glEnableClientState(GL_WEIGHT_ARRAY_ARB);
4033             checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
4034
4035             GL_EXTCALL(glVertexBlendARB(e->size + 1));
4036
4037             VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
4038                 WINED3D_ATR_FORMAT(sd->u.s.blendWeights.dwType) ,
4039                 sd->u.s.blendWeights.dwStride,
4040                 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
4041
4042             if (curVBO != e->buffer_object)
4043             {
4044                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4045                 checkGLcall("glBindBufferARB");
4046                 curVBO = e->buffer_object;
4047             }
4048
4049             GL_EXTCALL(glWeightPointerARB)(e->format, e->type, e->stride,
4050                 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4051
4052             checkGLcall("glWeightPointerARB");
4053
4054             if (si->elements[WINED3D_FFP_BLENDINDICES].data
4055                     || (si->elements[WINED3D_FFP_BLENDINDICES].buffer_object))
4056             {
4057                 static BOOL warned;
4058                 if (!warned)
4059                 {
4060                     FIXME("blendMatrixIndices support\n");
4061                     warned = TRUE;
4062                 }
4063             }
4064         } else {
4065             /* TODO: support blends in drawStridedSlow
4066              * No need to write a FIXME here, this is done after the general vertex decl decoding
4067              */
4068             WARN("unsupported blending in openGl\n");
4069         }
4070     } else {
4071         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
4072             static const GLbyte one = 1;
4073             GL_EXTCALL(glWeightbvARB(1, &one));
4074             checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
4075         }
4076     }
4077
4078     /* Point Size ----------------------------------------------*/
4079     e = &si->elements[WINED3D_FFP_PSIZE];
4080     if (e->data || e->buffer_object)
4081     {
4082         /* no such functionality in the fixed function GL pipeline */
4083         TRACE("Cannot change ptSize here in openGl\n");
4084         /* TODO: Implement this function in using shaders if they are available */
4085     }
4086
4087     /* Vertex Pointers -----------------------------------------*/
4088     e = &si->elements[WINED3D_FFP_POSITION];
4089     if (e->data || e->buffer_object)
4090     {
4091         VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n", e->stride, e->size, e->data));
4092
4093         if (curVBO != e->buffer_object)
4094         {
4095             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4096             checkGLcall("glBindBufferARB");
4097             curVBO = e->buffer_object;
4098         }
4099
4100         /* min(WINED3D_ATR_FORMAT(position),3) to Disable RHW mode as 'w' coord
4101            handling for rhw mode should not impact screen position whereas in GL it does.
4102            This may result in very slightly distorted textures in rhw mode.
4103            There's always the other option of fixing the view matrix to
4104            prevent w from having any effect.
4105
4106            This only applies to user pointer sources, in VBOs the vertices are fixed up
4107          */
4108         if (!e->buffer_object)
4109         {
4110             glVertexPointer(3 /* min(e->format, 3) */, e->type, e->stride,
4111                     e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4112         } else {
4113             glVertexPointer(e->format, e->type, e->stride,
4114                     e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4115         }
4116         checkGLcall("glVertexPointer(...)");
4117         glEnableClientState(GL_VERTEX_ARRAY);
4118         checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
4119     }
4120
4121     /* Normals -------------------------------------------------*/
4122     e = &si->elements[WINED3D_FFP_NORMAL];
4123     if (e->data || e->buffer_object)
4124     {
4125         VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n", e->stride, e->data));
4126         if (curVBO != e->buffer_object)
4127         {
4128             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4129             checkGLcall("glBindBufferARB");
4130             curVBO = e->buffer_object;
4131         }
4132         glNormalPointer(e->type, e->stride,
4133                 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4134         checkGLcall("glNormalPointer(...)");
4135         glEnableClientState(GL_NORMAL_ARRAY);
4136         checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
4137
4138     } else {
4139         glNormal3f(0, 0, 0);
4140         checkGLcall("glNormal3f(0, 0, 0)");
4141     }
4142
4143     /* Diffuse Colour --------------------------------------------*/
4144     /*  WARNING: Data here MUST be in RGBA format, so cannot      */
4145     /*     go directly into fast mode from app pgm, because       */
4146     /*     directx requires data in BGRA format.                  */
4147     /* currently fixupVertices swizzles the format, but this isn't*/
4148     /* very practical when using VBOs                             */
4149     /* NOTE: Unless we write a vertex shader to swizzle the colour*/
4150     /* , or the user doesn't care and wants the speed advantage   */
4151
4152     e = &si->elements[WINED3D_FFP_DIFFUSE];
4153     if (e->data || e->buffer_object)
4154     {
4155         VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data));
4156
4157         if (curVBO != e->buffer_object)
4158         {
4159             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4160             checkGLcall("glBindBufferARB");
4161             curVBO = e->buffer_object;
4162         }
4163
4164         glColorPointer(e->format, e->type, e->stride,
4165                 e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4166         checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
4167         glEnableClientState(GL_COLOR_ARRAY);
4168         checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
4169
4170     } else {
4171         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
4172         checkGLcall("glColor4f(1, 1, 1, 1)");
4173     }
4174
4175     /* Specular Colour ------------------------------------------*/
4176     e = &si->elements[WINED3D_FFP_SPECULAR];
4177     if (e->data || e->buffer_object)
4178     {
4179         TRACE("setting specular colour\n");
4180         VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n", e->stride, e->data));
4181
4182         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4183             if (curVBO != e->buffer_object)
4184             {
4185                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, e->buffer_object));
4186                 checkGLcall("glBindBufferARB");
4187                 curVBO = e->buffer_object;
4188             }
4189             GL_EXTCALL(glSecondaryColorPointerEXT)(e->format, e->type, e->stride,
4190                     e->data + stateblock->loadBaseVertexIndex * e->stride + offset[e->stream_idx]);
4191             checkGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
4192             glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
4193             checkGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
4194         } else {
4195
4196         /* Missing specular color is not critical, no warnings */
4197         VTRACE(("Specular colour is not supported in this GL implementation\n"));
4198         }
4199
4200     } else {
4201         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
4202             GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
4203             checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
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
4211     /* Texture coords -------------------------------------------*/
4212     loadTexCoords(stateblock, si, &curVBO);
4213 }
4214
4215 static inline void drawPrimitiveTraceDataLocations(const struct wined3d_stream_info *dataLocations)
4216 {
4217     /* Dump out what parts we have supplied */
4218     TRACE("Strided Data:\n");
4219     TRACE_STRIDED((dataLocations), WINED3D_FFP_POSITION);
4220     TRACE_STRIDED((dataLocations), WINED3D_FFP_BLENDWEIGHT);
4221     TRACE_STRIDED((dataLocations), WINED3D_FFP_BLENDINDICES);
4222     TRACE_STRIDED((dataLocations), WINED3D_FFP_NORMAL);
4223     TRACE_STRIDED((dataLocations), WINED3D_FFP_PSIZE);
4224     TRACE_STRIDED((dataLocations), WINED3D_FFP_DIFFUSE);
4225     TRACE_STRIDED((dataLocations), WINED3D_FFP_SPECULAR);
4226     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD0);
4227     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD1);
4228     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD2);
4229     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD3);
4230     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD4);
4231     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD5);
4232     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD6);
4233     TRACE_STRIDED((dataLocations), WINED3D_FFP_TEXCOORD7);
4234
4235     return;
4236 }
4237
4238 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4239     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4240     BOOL fixup = FALSE;
4241     struct wined3d_stream_info *dataLocations = &device->strided_streams;
4242     BOOL useVertexShaderFunction;
4243     BOOL load_numbered = FALSE;
4244     BOOL load_named = FALSE;
4245
4246     useVertexShaderFunction = (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader) ? TRUE : FALSE;
4247
4248     if(device->up_strided) {
4249         /* Note: this is a ddraw fixed-function code path */
4250         TRACE("================ Strided Input ===================\n");
4251         device_stream_info_from_strided(device, device->up_strided, dataLocations);
4252
4253         if(TRACE_ON(d3d)) {
4254             drawPrimitiveTraceDataLocations(dataLocations);
4255         }
4256     } else {
4257         /* Note: This is a fixed function or shader codepath.
4258          * This means it must handle both types of strided data.
4259          * Shaders must go through here to zero the strided data, even if they
4260          * don't set any declaration at all
4261          */
4262         TRACE("================ Vertex Declaration  ===================\n");
4263         device_stream_info_from_declaration(device, useVertexShaderFunction, dataLocations, &fixup);
4264     }
4265
4266     if (dataLocations->position_transformed) useVertexShaderFunction = FALSE;
4267
4268     if(useVertexShaderFunction) {
4269         if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
4270             TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
4271             device->useDrawStridedSlow = TRUE;
4272         } else {
4273             load_numbered = TRUE;
4274             device->useDrawStridedSlow = FALSE;
4275         }
4276     }
4277     else if (fixup || (!dataLocations->elements[WINED3D_FFP_PSIZE].data
4278             && !dataLocations->position_transformed
4279             && (GL_SUPPORT(EXT_VERTEX_ARRAY_BGRA)
4280             || (!dataLocations->elements[WINED3D_FFP_DIFFUSE].data
4281             && !dataLocations->elements[WINED3D_FFP_SPECULAR].data))))
4282     {
4283         /* Load the vertex data using named arrays */
4284         load_named = TRUE;
4285         device->useDrawStridedSlow = FALSE;
4286     } else {
4287         TRACE("Not loading vertex data\n");
4288         device->useDrawStridedSlow = TRUE;
4289     }
4290
4291     if (context->numberedArraysLoaded && !load_numbered)
4292     {
4293         unloadNumberedArrays(stateblock, context);
4294         context->numberedArraysLoaded = FALSE;
4295         context->numbered_array_mask = 0;
4296     }
4297     else if (context->namedArraysLoaded)
4298     {
4299         unloadVertexData(stateblock);
4300         context->namedArraysLoaded = FALSE;
4301     }
4302
4303     if (load_numbered)
4304     {
4305         TRACE("Loading numbered arrays\n");
4306         loadNumberedArrays(stateblock, dataLocations, context);
4307         context->numberedArraysLoaded = TRUE;
4308     }
4309     else if (load_named)
4310     {
4311         TRACE("Loading vertex data\n");
4312         loadVertexData(stateblock, dataLocations);
4313         context->namedArraysLoaded = TRUE;
4314     }
4315 }
4316
4317 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4318     BOOL updateFog = FALSE;
4319     BOOL useVertexShaderFunction = use_vs(stateblock);
4320     BOOL usePixelShaderFunction = use_ps(stateblock);
4321     BOOL transformed;
4322     /* Some stuff is in the device until we have per context tracking */
4323     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
4324     BOOL wasrhw = context->last_was_rhw;
4325
4326     transformed = device->strided_streams.position_transformed;
4327     if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
4328         updateFog = TRUE;
4329     }
4330
4331     /* Reapply lighting if it is not scheduled for reapplication already */
4332     if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
4333         state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
4334     }
4335
4336     if (transformed) {
4337         context->last_was_rhw = TRUE;
4338     } else {
4339
4340         /* Untransformed, so relies on the view and projection matrices */
4341         context->last_was_rhw = FALSE;
4342         /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
4343         device->untransformed = TRUE;
4344
4345         /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
4346          * Not needed as long as only hw shaders are supported
4347          */
4348
4349         /* This sets the shader output position correction constants.
4350          * TODO: Move to the viewport state
4351          */
4352         if (useVertexShaderFunction) {
4353             device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
4354             device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
4355         }
4356     }
4357
4358     /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
4359      * off this function will be called again anyway to make sure they're properly set
4360      */
4361     if(!useVertexShaderFunction) {
4362         /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
4363          * or transformed / untransformed was switched
4364          */
4365        if(wasrhw != context->last_was_rhw &&
4366           !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
4367           !isStateDirty(context, STATE_VIEWPORT)) {
4368             transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4369         }
4370         /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
4371          * mode.
4372          *
4373          * If a vertex shader is used, the world matrix changed and then vertex shader unbound
4374          * this check will fail and the matrix not applied again. This is OK because a simple
4375          * world matrix change reapplies the matrix - These checks here are only to satisfy the
4376          * needs of the vertex declaration.
4377          *
4378          * World and view matrix go into the same gl matrix, so only apply them when neither is
4379          * dirty
4380          */
4381         if(transformed != wasrhw &&
4382            !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
4383            !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
4384             transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4385         }
4386
4387         if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
4388             state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
4389         }
4390
4391         if(context->last_was_vshader) {
4392             updateFog = TRUE;
4393             if(!isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
4394                 state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
4395             }
4396         }
4397         if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
4398             state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
4399         }
4400     } else {
4401         if(!context->last_was_vshader) {
4402             unsigned int i;
4403             static BOOL warned = FALSE;
4404             /* Disable all clip planes to get defined results on all drivers. See comment in the
4405              * state_clipping state handler
4406              */
4407             for(i = 0; i < GL_LIMITS(clipplanes); i++) {
4408                 glDisable(GL_CLIP_PLANE0 + i);
4409                 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
4410             }
4411
4412             if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
4413                 FIXME("Clipping not supported with vertex shaders\n");
4414                 warned = TRUE;
4415             }
4416             if(wasrhw) {
4417                 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
4418                  * shaders themselves do not need it, but the matrices are not reapplied automatically when
4419                  * switching back from vertex shaders to fixed function processing. So make sure we leave the
4420                  * fixed function vertex processing states back in a sane state before switching to shaders
4421                  */
4422                 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4423                     transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4424                 }
4425                 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
4426                     transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
4427                 }
4428             }
4429             updateFog = TRUE;
4430         }
4431     }
4432
4433     /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
4434      * application
4435      */
4436     if (!isStateDirty(context, STATE_PIXELSHADER)) {
4437         device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
4438
4439         if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
4440             shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
4441         }
4442     }
4443
4444     context->last_was_vshader = useVertexShaderFunction;
4445
4446     if(updateFog) {
4447         device->StateTable[STATE_RENDER(WINED3DRS_FOGVERTEXMODE)].apply(STATE_RENDER(WINED3DRS_FOGVERTEXMODE), stateblock, context);
4448     }
4449     if(!useVertexShaderFunction) {
4450         int i;
4451         for(i = 0; i < MAX_TEXTURES; i++) {
4452             if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
4453                 transform_texture(STATE_TEXTURESTAGE(i, WINED3DTSS_TEXTURETRANSFORMFLAGS), stateblock, context);
4454             }
4455         }
4456     }
4457 }
4458
4459 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4460     UINT width, height;
4461     IWineD3DSurfaceImpl *target;
4462
4463     glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
4464     checkGLcall("glDepthRange");
4465     /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
4466      */
4467     if(stateblock->wineD3DDevice->render_offscreen) {
4468         glViewport(stateblock->viewport.X,
4469                    stateblock->viewport.Y,
4470                    stateblock->viewport.Width, stateblock->viewport.Height);
4471     } else {
4472         target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4473         target->get_drawable_size(target, &width, &height);
4474
4475         glViewport(stateblock->viewport.X,
4476                    (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
4477                    stateblock->viewport.Width, stateblock->viewport.Height);
4478     }
4479
4480     checkGLcall("glViewport");
4481 }
4482
4483 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4484     stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
4485     stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
4486     if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
4487         transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
4488     }
4489     if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
4490         state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
4491     }
4492 }
4493
4494 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4495     UINT Index = state - STATE_ACTIVELIGHT(0);
4496     const PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
4497
4498     if(!lightInfo) {
4499         glDisable(GL_LIGHT0 + Index);
4500         checkGLcall("glDisable(GL_LIGHT0 + Index)");
4501     } else {
4502         float quad_att;
4503         float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
4504
4505         /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4506         glMatrixMode(GL_MODELVIEW);
4507         glPushMatrix();
4508         glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
4509
4510         /* Diffuse: */
4511         colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
4512         colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
4513         colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
4514         colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
4515         glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
4516         checkGLcall("glLightfv");
4517
4518         /* Specular */
4519         colRGBA[0] = lightInfo->OriginalParms.Specular.r;
4520         colRGBA[1] = lightInfo->OriginalParms.Specular.g;
4521         colRGBA[2] = lightInfo->OriginalParms.Specular.b;
4522         colRGBA[3] = lightInfo->OriginalParms.Specular.a;
4523         glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
4524         checkGLcall("glLightfv");
4525
4526         /* Ambient */
4527         colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
4528         colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
4529         colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
4530         colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
4531         glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
4532         checkGLcall("glLightfv");
4533
4534         if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
4535             quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
4536         } else {
4537             quad_att = 0; /*  0 or  MAX?  (0 seems to be ok) */
4538         }
4539
4540         /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
4541          * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
4542          * Attenuation0 to NaN and crashes in the gl lib
4543          */
4544
4545         switch (lightInfo->OriginalParms.Type) {
4546             case WINED3DLIGHT_POINT:
4547                 /* Position */
4548                 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4549                 checkGLcall("glLightfv");
4550                 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4551                 checkGLcall("glLightf");
4552                 /* Attenuation - Are these right? guessing... */
4553                 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
4554                 checkGLcall("glLightf");
4555                 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
4556                 checkGLcall("glLightf");
4557                 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4558                 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4559                 checkGLcall("glLightf");
4560                 /* FIXME: Range */
4561                 break;
4562
4563             case WINED3DLIGHT_SPOT:
4564                 /* Position */
4565                 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
4566                 checkGLcall("glLightfv");
4567                 /* Direction */
4568                 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
4569                 checkGLcall("glLightfv");
4570                 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4571                 checkGLcall("glLightf");
4572                 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4573                 checkGLcall("glLightf");
4574                 /* Attenuation - Are these right? guessing... */
4575                 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
4576                 checkGLcall("glLightf");
4577                 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
4578                 checkGLcall("glLightf");
4579                 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
4580                 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4581                 checkGLcall("glLightf");
4582                 /* FIXME: Range */
4583                 break;
4584
4585             case WINED3DLIGHT_DIRECTIONAL:
4586                 /* Direction */
4587                 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
4588                 checkGLcall("glLightfv");
4589                 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4590                 checkGLcall("glLightf");
4591                 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4592                 checkGLcall("glLightf");
4593                 break;
4594
4595             default:
4596                 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
4597         }
4598
4599         /* Restore the modelview matrix */
4600         glPopMatrix();
4601
4602         glEnable(GL_LIGHT0 + Index);
4603         checkGLcall("glEnable(GL_LIGHT0 + Index)");
4604     }
4605
4606     return;
4607 }
4608
4609 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4610     RECT *pRect = &stateblock->scissorRect;
4611     UINT height;
4612     UINT width;
4613     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
4614
4615     target->get_drawable_size(target, &width, &height);
4616     /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
4617      * Warning2: Even in windowed mode the coords are relative to the window, not the screen
4618      */
4619     TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
4620           pRect->right - pRect->left, pRect->bottom - pRect->top);
4621
4622     if (stateblock->wineD3DDevice->render_offscreen) {
4623         glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
4624     } else {
4625         glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
4626     }
4627     checkGLcall("glScissor");
4628 }
4629
4630 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4631     if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
4632         GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
4633     } else {
4634         IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
4635         GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
4636     }
4637 }
4638
4639 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4640     if(stateblock->wineD3DDevice->render_offscreen) {
4641         glFrontFace(GL_CCW);
4642         checkGLcall("glFrontFace(GL_CCW)");
4643     } else {
4644         glFrontFace(GL_CW);
4645         checkGLcall("glFrontFace(GL_CW)");
4646     }
4647 }
4648
4649 const struct StateEntryTemplate misc_state_template[] = {
4650     { STATE_RENDER(WINED3DRS_SRCBLEND),                   { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4651     { STATE_RENDER(WINED3DRS_DESTBLEND),                  { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4652     { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4653     { STATE_RENDER(WINED3DRS_EDGEANTIALIAS),              { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4654     { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE),      { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4655     { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE),   { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4656     { STATE_RENDER(WINED3DRS_SRCBLENDALPHA),              { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4657     { STATE_RENDER(WINED3DRS_DESTBLENDALPHA),             { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4658     { STATE_RENDER(WINED3DRS_DESTBLENDALPHA),             { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4659     { STATE_RENDER(WINED3DRS_BLENDOPALPHA),               { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
4660     { STATE_STREAMSRC,                                    { STATE_VDECL,                                        streamsrc           }, 0                               },
4661     { STATE_VDECL,                                        { STATE_VDECL,                                        streamsrc           }, 0                               },
4662     { STATE_FRONTFACE,                                    { STATE_FRONTFACE,                                    frontface           }, 0                               },
4663     { STATE_SCISSORRECT,                                  { STATE_SCISSORRECT,                                  scissorrect         }, 0                               },
4664     /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
4665      * vshader loadings are untied from each other
4666      */
4667     { STATE_VERTEXSHADERCONSTANT,                         { STATE_VERTEXSHADERCONSTANT,                         shaderconstant      }, 0                               },
4668     { STATE_PIXELSHADERCONSTANT,                          { STATE_VERTEXSHADERCONSTANT,                         shaderconstant      }, 0                               },
4669     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4670     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4671     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4672     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4673     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4674     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4675     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4676     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4677     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4678     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4679     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4680     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4681     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4682     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4683     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4684     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4685     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4686     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4687     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4688     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4689     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4690     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4691     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4692     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4693     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4694     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4695     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4696     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4697     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4698     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4699     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4700     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
4701     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4702     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4703     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4704     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4705     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4706     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4707     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4708     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4709     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4710     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4711     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4712     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4713     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4714     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4715     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4716     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
4717
4718     { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_miscpart   }, 0                               },
4719     { STATE_INDEXBUFFER,                                  { STATE_INDEXBUFFER,                                  indexbuffer         }, ARB_VERTEX_BUFFER_OBJECT        },
4720     { STATE_RENDER(WINED3DRS_ANTIALIAS),                  { STATE_RENDER(WINED3DRS_ANTIALIAS),                  state_antialias     }, 0                               },
4721     { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE),         { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE),         state_perspective   }, 0                               },
4722     { STATE_RENDER(WINED3DRS_ZENABLE),                    { STATE_RENDER(WINED3DRS_ZENABLE),                    state_zenable       }, 0                               },
4723     { STATE_RENDER(WINED3DRS_WRAPU),                      { STATE_RENDER(WINED3DRS_WRAPU),                      state_wrapu         }, 0                               },
4724     { STATE_RENDER(WINED3DRS_WRAPV),                      { STATE_RENDER(WINED3DRS_WRAPV),                      state_wrapv         }, 0                               },
4725     { STATE_RENDER(WINED3DRS_FILLMODE),                   { STATE_RENDER(WINED3DRS_FILLMODE),                   state_fillmode      }, 0                               },
4726     { STATE_RENDER(WINED3DRS_SHADEMODE),                  { STATE_RENDER(WINED3DRS_SHADEMODE),                  state_shademode     }, 0                               },
4727     { STATE_RENDER(WINED3DRS_LINEPATTERN),                { STATE_RENDER(WINED3DRS_LINEPATTERN),                state_linepattern   }, 0                               },
4728     { STATE_RENDER(WINED3DRS_MONOENABLE),                 { STATE_RENDER(WINED3DRS_MONOENABLE),                 state_monoenable    }, 0                               },
4729     { STATE_RENDER(WINED3DRS_ROP2),                       { STATE_RENDER(WINED3DRS_ROP2),                       state_rop2          }, 0                               },
4730     { STATE_RENDER(WINED3DRS_PLANEMASK),                  { STATE_RENDER(WINED3DRS_PLANEMASK),                  state_planemask     }, 0                               },
4731     { STATE_RENDER(WINED3DRS_ZWRITEENABLE),               { STATE_RENDER(WINED3DRS_ZWRITEENABLE),               state_zwritenable   }, 0                               },
4732     { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
4733     { STATE_RENDER(WINED3DRS_ALPHAREF),                   { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
4734     { STATE_RENDER(WINED3DRS_ALPHAFUNC),                  { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
4735     { STATE_RENDER(WINED3DRS_COLORKEYENABLE),             { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
4736     { STATE_RENDER(WINED3DRS_LASTPIXEL),                  { STATE_RENDER(WINED3DRS_LASTPIXEL),                  state_lastpixel     }, 0                               },
4737     { STATE_RENDER(WINED3DRS_CULLMODE),                   { STATE_RENDER(WINED3DRS_CULLMODE),                   state_cullmode      }, 0                               },
4738     { STATE_RENDER(WINED3DRS_ZFUNC),                      { STATE_RENDER(WINED3DRS_ZFUNC),                      state_zfunc         }, 0                               },
4739     { STATE_RENDER(WINED3DRS_DITHERENABLE),               { STATE_RENDER(WINED3DRS_DITHERENABLE),               state_ditherenable  }, 0                               },
4740     { STATE_RENDER(WINED3DRS_SUBPIXEL),                   { STATE_RENDER(WINED3DRS_SUBPIXEL),                   state_subpixel      }, 0                               },
4741     { STATE_RENDER(WINED3DRS_SUBPIXELX),                  { STATE_RENDER(WINED3DRS_SUBPIXELX),                  state_subpixelx     }, 0                               },
4742     { STATE_RENDER(WINED3DRS_STIPPLEDALPHA),              { STATE_RENDER(WINED3DRS_STIPPLEDALPHA),              state_stippledalpha }, 0                               },
4743     { STATE_RENDER(WINED3DRS_ZBIAS),                      { STATE_RENDER(WINED3DRS_ZBIAS),                      state_zbias         }, 0                               },
4744     { STATE_RENDER(WINED3DRS_STIPPLEENABLE),              { STATE_RENDER(WINED3DRS_STIPPLEENABLE),              state_stippleenable }, 0                               },
4745     { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS),              { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS),              state_mipmaplodbias }, 0                               },
4746     { STATE_RENDER(WINED3DRS_ANISOTROPY),                 { STATE_RENDER(WINED3DRS_ANISOTROPY),                 state_anisotropy    }, 0                               },
4747     { STATE_RENDER(WINED3DRS_FLUSHBATCH),                 { STATE_RENDER(WINED3DRS_FLUSHBATCH),                 state_flushbatch    }, 0                               },
4748     { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, 0                               },
4749     { STATE_RENDER(WINED3DRS_STENCILENABLE),              { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4750     { STATE_RENDER(WINED3DRS_STENCILFAIL),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4751     { STATE_RENDER(WINED3DRS_STENCILZFAIL),               { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4752     { STATE_RENDER(WINED3DRS_STENCILPASS),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4753     { STATE_RENDER(WINED3DRS_STENCILFUNC),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4754     { STATE_RENDER(WINED3DRS_STENCILREF),                 { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4755     { STATE_RENDER(WINED3DRS_STENCILMASK),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4756     { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE            },
4757     { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           state_stencilwrite  }, 0                               },
4758     { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE),        { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4759     { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL),            { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4760     { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL),           { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4761     { STATE_RENDER(WINED3DRS_CCW_STENCILPASS),            { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4762     { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC),            { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
4763     { STATE_RENDER(WINED3DRS_WRAP0),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4764     { STATE_RENDER(WINED3DRS_WRAP1),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4765     { STATE_RENDER(WINED3DRS_WRAP2),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4766     { STATE_RENDER(WINED3DRS_WRAP3),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4767     { STATE_RENDER(WINED3DRS_WRAP4),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4768     { STATE_RENDER(WINED3DRS_WRAP5),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4769     { STATE_RENDER(WINED3DRS_WRAP6),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4770     { STATE_RENDER(WINED3DRS_WRAP7),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4771     { STATE_RENDER(WINED3DRS_WRAP8),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4772     { STATE_RENDER(WINED3DRS_WRAP9),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4773     { STATE_RENDER(WINED3DRS_WRAP10),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4774     { STATE_RENDER(WINED3DRS_WRAP11),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4775     { STATE_RENDER(WINED3DRS_WRAP12),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4776     { STATE_RENDER(WINED3DRS_WRAP13),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4777     { STATE_RENDER(WINED3DRS_WRAP14),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4778     { STATE_RENDER(WINED3DRS_WRAP15),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
4779     { STATE_RENDER(WINED3DRS_EXTENTS),                    { STATE_RENDER(WINED3DRS_EXTENTS),                    state_extents       }, 0                               },
4780     { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE),        { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE),        state_ckeyblend     }, 0                               },
4781     { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE),             { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE),             state_patchedgestyle}, 0                               },
4782     { STATE_RENDER(WINED3DRS_PATCHSEGMENTS),              { STATE_RENDER(WINED3DRS_PATCHSEGMENTS),              state_patchsegments }, 0                               },
4783     { STATE_RENDER(WINED3DRS_POSITIONDEGREE),             { STATE_RENDER(WINED3DRS_POSITIONDEGREE),             state_positiondegree}, 0                               },
4784     { STATE_RENDER(WINED3DRS_NORMALDEGREE),               { STATE_RENDER(WINED3DRS_NORMALDEGREE),               state_normaldegree  }, 0                               },
4785     { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL),       { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4786     { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL),       { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4787     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4788     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4789     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4790     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4791     { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
4792     { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       state_msaa          }, ARB_MULTISAMPLE                 },
4793     { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       state_msaa_w        }, 0                               },
4794     { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK),            { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK),            state_multisampmask }, 0                               },
4795     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
4796     { STATE_RENDER(WINED3DRS_BLENDOP),                    { STATE_RENDER(WINED3DRS_BLENDOP),                    state_blendop       }, EXT_BLEND_MINMAX                },
4797     { STATE_RENDER(WINED3DRS_BLENDOP),                    { STATE_RENDER(WINED3DRS_BLENDOP),                    state_blendop_w     }, 0                               },
4798     { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE),          { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE),          state_scissor       }, 0                               },
4799     { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS),        { STATE_RENDER(WINED3DRS_DEPTHBIAS),                  state_depthbias     }, 0                               },
4800     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1),          { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
4801     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2),          { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
4802     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3),          { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
4803     { STATE_RENDER(WINED3DRS_BLENDFACTOR),                { STATE_RENDER(WINED3DRS_BLENDFACTOR),                state_blendfactor   }, EXT_BLEND_COLOR                 },
4804     { STATE_RENDER(WINED3DRS_BLENDFACTOR),                { STATE_RENDER(WINED3DRS_BLENDFACTOR),                state_blendfactor_w }, 0                               },
4805     { STATE_RENDER(WINED3DRS_DEPTHBIAS),                  { STATE_RENDER(WINED3DRS_DEPTHBIAS),                  state_depthbias     }, 0                               },
4806     /* Samplers */
4807     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler             }, 0                               },
4808     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler             }, 0                               },
4809     { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler             }, 0                               },
4810     { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler             }, 0                               },
4811     { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler             }, 0                               },
4812     { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler             }, 0                               },
4813     { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler             }, 0                               },
4814     { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler             }, 0                               },
4815     { STATE_SAMPLER(8),                                   { STATE_SAMPLER(8),                                   sampler             }, 0                               },
4816     { STATE_SAMPLER(9),                                   { STATE_SAMPLER(9),                                   sampler             }, 0                               },
4817     { STATE_SAMPLER(10),                                  { STATE_SAMPLER(10),                                  sampler             }, 0                               },
4818     { STATE_SAMPLER(11),                                  { STATE_SAMPLER(11),                                  sampler             }, 0                               },
4819     { STATE_SAMPLER(12),                                  { STATE_SAMPLER(12),                                  sampler             }, 0                               },
4820     { STATE_SAMPLER(13),                                  { STATE_SAMPLER(13),                                  sampler             }, 0                               },
4821     { STATE_SAMPLER(14),                                  { STATE_SAMPLER(14),                                  sampler             }, 0                               },
4822     { STATE_SAMPLER(15),                                  { STATE_SAMPLER(15),                                  sampler             }, 0                               },
4823     { STATE_SAMPLER(16), /* Vertex sampler 0 */           { STATE_SAMPLER(16),                                  sampler             }, 0                               },
4824     { STATE_SAMPLER(17), /* Vertex sampler 1 */           { STATE_SAMPLER(17),                                  sampler             }, 0                               },
4825     { STATE_SAMPLER(18), /* Vertex sampler 2 */           { STATE_SAMPLER(18),                                  sampler             }, 0                               },
4826     { STATE_SAMPLER(19), /* Vertex sampler 3 */           { STATE_SAMPLER(19),                                  sampler             }, 0                               },
4827     {0 /* Terminate */,                                   { 0,                                                  0                   }, 0                               },
4828 };
4829
4830 const struct StateEntryTemplate ffp_vertexstate_template[] = {
4831     { STATE_VDECL,                                        { STATE_VDECL,                                        vertexdeclaration   }, 0                               },
4832     { STATE_VSHADER,                                      { STATE_VDECL,                                        vertexdeclaration   }, 0                               },
4833     { STATE_MATERIAL,                                     { STATE_RENDER(WINED3DRS_SPECULARENABLE),             state_specularenable}, 0                               },
4834     { STATE_RENDER(WINED3DRS_SPECULARENABLE),             { STATE_RENDER(WINED3DRS_SPECULARENABLE),             state_specularenable}, 0                               },
4835       /* Clip planes */
4836     { STATE_CLIPPLANE(0),                                 { STATE_CLIPPLANE(0),                                 clipplane           }, 0                               },
4837     { STATE_CLIPPLANE(1),                                 { STATE_CLIPPLANE(1),                                 clipplane           }, 0                               },
4838     { STATE_CLIPPLANE(2),                                 { STATE_CLIPPLANE(2),                                 clipplane           }, 0                               },
4839     { STATE_CLIPPLANE(3),                                 { STATE_CLIPPLANE(3),                                 clipplane           }, 0                               },
4840     { STATE_CLIPPLANE(4),                                 { STATE_CLIPPLANE(4),                                 clipplane           }, 0                               },
4841     { STATE_CLIPPLANE(5),                                 { STATE_CLIPPLANE(5),                                 clipplane           }, 0                               },
4842     { STATE_CLIPPLANE(6),                                 { STATE_CLIPPLANE(6),                                 clipplane           }, 0                               },
4843     { STATE_CLIPPLANE(7),                                 { STATE_CLIPPLANE(7),                                 clipplane           }, 0                               },
4844     { STATE_CLIPPLANE(8),                                 { STATE_CLIPPLANE(8),                                 clipplane           }, 0                               },
4845     { STATE_CLIPPLANE(9),                                 { STATE_CLIPPLANE(9),                                 clipplane           }, 0                               },
4846     { STATE_CLIPPLANE(10),                                { STATE_CLIPPLANE(10),                                clipplane           }, 0                               },
4847     { STATE_CLIPPLANE(11),                                { STATE_CLIPPLANE(11),                                clipplane           }, 0                               },
4848     { STATE_CLIPPLANE(12),                                { STATE_CLIPPLANE(12),                                clipplane           }, 0                               },
4849     { STATE_CLIPPLANE(13),                                { STATE_CLIPPLANE(13),                                clipplane           }, 0                               },
4850     { STATE_CLIPPLANE(14),                                { STATE_CLIPPLANE(14),                                clipplane           }, 0                               },
4851     { STATE_CLIPPLANE(15),                                { STATE_CLIPPLANE(15),                                clipplane           }, 0                               },
4852     { STATE_CLIPPLANE(16),                                { STATE_CLIPPLANE(16),                                clipplane           }, 0                               },
4853     { STATE_CLIPPLANE(17),                                { STATE_CLIPPLANE(17),                                clipplane           }, 0                               },
4854     { STATE_CLIPPLANE(18),                                { STATE_CLIPPLANE(18),                                clipplane           }, 0                               },
4855     { STATE_CLIPPLANE(19),                                { STATE_CLIPPLANE(19),                                clipplane           }, 0                               },
4856     { STATE_CLIPPLANE(20),                                { STATE_CLIPPLANE(20),                                clipplane           }, 0                               },
4857     { STATE_CLIPPLANE(21),                                { STATE_CLIPPLANE(21),                                clipplane           }, 0                               },
4858     { STATE_CLIPPLANE(22),                                { STATE_CLIPPLANE(22),                                clipplane           }, 0                               },
4859     { STATE_CLIPPLANE(23),                                { STATE_CLIPPLANE(23),                                clipplane           }, 0                               },
4860     { STATE_CLIPPLANE(24),                                { STATE_CLIPPLANE(24),                                clipplane           }, 0                               },
4861     { STATE_CLIPPLANE(25),                                { STATE_CLIPPLANE(25),                                clipplane           }, 0                               },
4862     { STATE_CLIPPLANE(26),                                { STATE_CLIPPLANE(26),                                clipplane           }, 0                               },
4863     { STATE_CLIPPLANE(27),                                { STATE_CLIPPLANE(27),                                clipplane           }, 0                               },
4864     { STATE_CLIPPLANE(28),                                { STATE_CLIPPLANE(28),                                clipplane           }, 0                               },
4865     { STATE_CLIPPLANE(29),                                { STATE_CLIPPLANE(29),                                clipplane           }, 0                               },
4866     { STATE_CLIPPLANE(30),                                { STATE_CLIPPLANE(30),                                clipplane           }, 0                               },
4867     { STATE_CLIPPLANE(31),                                { STATE_CLIPPLANE(31),                                clipplane           }, 0                               },
4868       /* Lights */
4869     { STATE_ACTIVELIGHT(0),                               { STATE_ACTIVELIGHT(0),                               light               }, 0                               },
4870     { STATE_ACTIVELIGHT(1),                               { STATE_ACTIVELIGHT(1),                               light               }, 0                               },
4871     { STATE_ACTIVELIGHT(2),                               { STATE_ACTIVELIGHT(2),                               light               }, 0                               },
4872     { STATE_ACTIVELIGHT(3),                               { STATE_ACTIVELIGHT(3),                               light               }, 0                               },
4873     { STATE_ACTIVELIGHT(4),                               { STATE_ACTIVELIGHT(4),                               light               }, 0                               },
4874     { STATE_ACTIVELIGHT(5),                               { STATE_ACTIVELIGHT(5),                               light               }, 0                               },
4875     { STATE_ACTIVELIGHT(6),                               { STATE_ACTIVELIGHT(6),                               light               }, 0                               },
4876     { STATE_ACTIVELIGHT(7),                               { STATE_ACTIVELIGHT(7),                               light               }, 0                               },
4877     /* Viewport */
4878     { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_vertexpart }, 0                               },
4879       /* Transform states follow                    */
4880     { STATE_TRANSFORM(WINED3DTS_VIEW),                    { STATE_TRANSFORM(WINED3DTS_VIEW),                    transform_view      }, 0                               },
4881     { STATE_TRANSFORM(WINED3DTS_PROJECTION),              { STATE_TRANSFORM(WINED3DTS_PROJECTION),              transform_projection}, 0                               },
4882     { STATE_TRANSFORM(WINED3DTS_TEXTURE0),                { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4883     { STATE_TRANSFORM(WINED3DTS_TEXTURE1),                { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4884     { STATE_TRANSFORM(WINED3DTS_TEXTURE2),                { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4885     { STATE_TRANSFORM(WINED3DTS_TEXTURE3),                { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4886     { STATE_TRANSFORM(WINED3DTS_TEXTURE4),                { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4887     { STATE_TRANSFORM(WINED3DTS_TEXTURE5),                { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4888     { STATE_TRANSFORM(WINED3DTS_TEXTURE6),                { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4889     { STATE_TRANSFORM(WINED3DTS_TEXTURE7),                { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),  transform_texture   }, 0                               },
4890     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  0)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  0)),        transform_world     }, 0                               },
4891     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  1)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  1)),        transform_worldex   }, 0                               },
4892     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  2)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  2)),        transform_worldex   }, 0                               },
4893     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  3)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  3)),        transform_worldex   }, 0                               },
4894     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  4)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  4)),        transform_worldex   }, 0                               },
4895     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  5)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  5)),        transform_worldex   }, 0                               },
4896     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  6)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  6)),        transform_worldex   }, 0                               },
4897     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  7)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  7)),        transform_worldex   }, 0                               },
4898     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  8)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  8)),        transform_worldex   }, 0                               },
4899     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  9)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  9)),        transform_worldex   }, 0                               },
4900     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)),        transform_worldex   }, 0                               },
4901     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)),        transform_worldex   }, 0                               },
4902     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)),        transform_worldex   }, 0                               },
4903     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)),        transform_worldex   }, 0                               },
4904     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)),        transform_worldex   }, 0                               },
4905     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)),        transform_worldex   }, 0                               },
4906     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)),        transform_worldex   }, 0                               },
4907     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)),        transform_worldex   }, 0                               },
4908     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)),        transform_worldex   }, 0                               },
4909     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)),        transform_worldex   }, 0                               },
4910     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)),        transform_worldex   }, 0                               },
4911     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)),        transform_worldex   }, 0                               },
4912     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)),        transform_worldex   }, 0                               },
4913     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)),        transform_worldex   }, 0                               },
4914     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)),        transform_worldex   }, 0                               },
4915     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)),        transform_worldex   }, 0                               },
4916     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)),        transform_worldex   }, 0                               },
4917     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)),        transform_worldex   }, 0                               },
4918     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)),        transform_worldex   }, 0                               },
4919     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)),        transform_worldex   }, 0                               },
4920     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)),        transform_worldex   }, 0                               },
4921     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)),        transform_worldex   }, 0                               },
4922     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)),        transform_worldex   }, 0                               },
4923     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)),        transform_worldex   }, 0                               },
4924     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)),        transform_worldex   }, 0                               },
4925     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)),        transform_worldex   }, 0                               },
4926     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)),        transform_worldex   }, 0                               },
4927     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)),        transform_worldex   }, 0                               },
4928     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)),        transform_worldex   }, 0                               },
4929     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)),        transform_worldex   }, 0                               },
4930     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)),        transform_worldex   }, 0                               },
4931     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)),        transform_worldex   }, 0                               },
4932     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)),        transform_worldex   }, 0                               },
4933     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)),        transform_worldex   }, 0                               },
4934     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)),        transform_worldex   }, 0                               },
4935     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)),        transform_worldex   }, 0                               },
4936     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)),        transform_worldex   }, 0                               },
4937     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)),        transform_worldex   }, 0                               },
4938     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)),        transform_worldex   }, 0                               },
4939     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)),        transform_worldex   }, 0                               },
4940     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)),        transform_worldex   }, 0                               },
4941     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)),        transform_worldex   }, 0                               },
4942     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)),        transform_worldex   }, 0                               },
4943     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)),        transform_worldex   }, 0                               },
4944     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)),        transform_worldex   }, 0                               },
4945     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)),        transform_worldex   }, 0                               },
4946     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)),        transform_worldex   }, 0                               },
4947     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)),        transform_worldex   }, 0                               },
4948     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)),        transform_worldex   }, 0                               },
4949     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)),        transform_worldex   }, 0                               },
4950     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)),        transform_worldex   }, 0                               },
4951     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)),        transform_worldex   }, 0                               },
4952     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)),        transform_worldex   }, 0                               },
4953     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)),        transform_worldex   }, 0                               },
4954     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)),        transform_worldex   }, 0                               },
4955     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)),        transform_worldex   }, 0                               },
4956     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)),        transform_worldex   }, 0                               },
4957     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)),        transform_worldex   }, 0                               },
4958     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)),        transform_worldex   }, 0                               },
4959     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)),        transform_worldex   }, 0                               },
4960     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)),        transform_worldex   }, 0                               },
4961     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)),        transform_worldex   }, 0                               },
4962     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)),        transform_worldex   }, 0                               },
4963     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)),        transform_worldex   }, 0                               },
4964     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)),        transform_worldex   }, 0                               },
4965     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)),        transform_worldex   }, 0                               },
4966     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)),        transform_worldex   }, 0                               },
4967     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)),        transform_worldex   }, 0                               },
4968     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)),        transform_worldex   }, 0                               },
4969     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)),        transform_worldex   }, 0                               },
4970     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)),        transform_worldex   }, 0                               },
4971     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)),        transform_worldex   }, 0                               },
4972     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)),        transform_worldex   }, 0                               },
4973     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)),        transform_worldex   }, 0                               },
4974     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)),        transform_worldex   }, 0                               },
4975     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)),        transform_worldex   }, 0                               },
4976     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)),        transform_worldex   }, 0                               },
4977     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)),        transform_worldex   }, 0                               },
4978     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)),        transform_worldex   }, 0                               },
4979     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)),        transform_worldex   }, 0                               },
4980     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)),        transform_worldex   }, 0                               },
4981     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)),        transform_worldex   }, 0                               },
4982     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)),        transform_worldex   }, 0                               },
4983     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)),        transform_worldex   }, 0                               },
4984     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)),        transform_worldex   }, 0                               },
4985     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)),        transform_worldex   }, 0                               },
4986     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)),        transform_worldex   }, 0                               },
4987     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)),        transform_worldex   }, 0                               },
4988     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)),        transform_worldex   }, 0                               },
4989     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)),        transform_worldex   }, 0                               },
4990     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)),        transform_worldex   }, 0                               },
4991     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)),        transform_worldex   }, 0                               },
4992     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)),        transform_worldex   }, 0                               },
4993     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)),        transform_worldex   }, 0                               },
4994     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)),        transform_worldex   }, 0                               },
4995     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)),        transform_worldex   }, 0                               },
4996     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)),        transform_worldex   }, 0                               },
4997     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)),        transform_worldex   }, 0                               },
4998     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)),        transform_worldex   }, 0                               },
4999     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)),        transform_worldex   }, 0                               },
5000     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)),        transform_worldex   }, 0                               },
5001     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)),        transform_worldex   }, 0                               },
5002     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)),        transform_worldex   }, 0                               },
5003     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)),        transform_worldex   }, 0                               },
5004     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)),        transform_worldex   }, 0                               },
5005     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)),        transform_worldex   }, 0                               },
5006     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)),        transform_worldex   }, 0                               },
5007     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)),        transform_worldex   }, 0                               },
5008     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)),        transform_worldex   }, 0                               },
5009     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)),        transform_worldex   }, 0                               },
5010     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)),        transform_worldex   }, 0                               },
5011     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)),        transform_worldex   }, 0                               },
5012     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)),        transform_worldex   }, 0                               },
5013     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)),        transform_worldex   }, 0                               },
5014     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)),        transform_worldex   }, 0                               },
5015     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)),        transform_worldex   }, 0                               },
5016     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)),        transform_worldex   }, 0                               },
5017     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)),        transform_worldex   }, 0                               },
5018     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)),        transform_worldex   }, 0                               },
5019     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)),        transform_worldex   }, 0                               },
5020     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)),        transform_worldex   }, 0                               },
5021     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)),        transform_worldex   }, 0                               },
5022     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)),        transform_worldex   }, 0                               },
5023     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)),        transform_worldex   }, 0                               },
5024     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)),        transform_worldex   }, 0                               },
5025     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)),        transform_worldex   }, 0                               },
5026     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)),        transform_worldex   }, 0                               },
5027     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)),        transform_worldex   }, 0                               },
5028     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)),        transform_worldex   }, 0                               },
5029     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)),        transform_worldex   }, 0                               },
5030     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)),        transform_worldex   }, 0                               },
5031     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)),        transform_worldex   }, 0                               },
5032     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)),        transform_worldex   }, 0                               },
5033     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)),        transform_worldex   }, 0                               },
5034     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)),        transform_worldex   }, 0                               },
5035     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)),        transform_worldex   }, 0                               },
5036     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)),        transform_worldex   }, 0                               },
5037     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)),        transform_worldex   }, 0                               },
5038     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)),        transform_worldex   }, 0                               },
5039     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)),        transform_worldex   }, 0                               },
5040     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)),        transform_worldex   }, 0                               },
5041     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)),        transform_worldex   }, 0                               },
5042     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)),        transform_worldex   }, 0                               },
5043     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)),        transform_worldex   }, 0                               },
5044     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)),        transform_worldex   }, 0                               },
5045     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)),        transform_worldex   }, 0                               },
5046     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)),        transform_worldex   }, 0                               },
5047     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)),        transform_worldex   }, 0                               },
5048     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)),        transform_worldex   }, 0                               },
5049     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)),        transform_worldex   }, 0                               },
5050     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)),        transform_worldex   }, 0                               },
5051     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)),        transform_worldex   }, 0                               },
5052     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)),        transform_worldex   }, 0                               },
5053     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)),        transform_worldex   }, 0                               },
5054     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)),        transform_worldex   }, 0                               },
5055     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)),        transform_worldex   }, 0                               },
5056     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)),        transform_worldex   }, 0                               },
5057     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)),        transform_worldex   }, 0                               },
5058     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)),        transform_worldex   }, 0                               },
5059     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)),        transform_worldex   }, 0                               },
5060     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)),        transform_worldex   }, 0                               },
5061     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)),        transform_worldex   }, 0                               },
5062     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)),        transform_worldex   }, 0                               },
5063     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)),        transform_worldex   }, 0                               },
5064     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)),        transform_worldex   }, 0                               },
5065     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)),        transform_worldex   }, 0                               },
5066     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)),        transform_worldex   }, 0                               },
5067     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)),        transform_worldex   }, 0                               },
5068     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)),        transform_worldex   }, 0                               },
5069     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)),        transform_worldex   }, 0                               },
5070     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)),        transform_worldex   }, 0                               },
5071     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)),        transform_worldex   }, 0                               },
5072     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)),        transform_worldex   }, 0                               },
5073     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)),        transform_worldex   }, 0                               },
5074     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)),        transform_worldex   }, 0                               },
5075     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)),        transform_worldex   }, 0                               },
5076     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)),        transform_worldex   }, 0                               },
5077     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)),        transform_worldex   }, 0                               },
5078     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)),        transform_worldex   }, 0                               },
5079     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)),        transform_worldex   }, 0                               },
5080     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)),        transform_worldex   }, 0                               },
5081     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)),        transform_worldex   }, 0                               },
5082     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)),        transform_worldex   }, 0                               },
5083     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)),        transform_worldex   }, 0                               },
5084     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)),        transform_worldex   }, 0                               },
5085     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)),        transform_worldex   }, 0                               },
5086     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)),        transform_worldex   }, 0                               },
5087     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)),        transform_worldex   }, 0                               },
5088     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)),        transform_worldex   }, 0                               },
5089     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)),        transform_worldex   }, 0                               },
5090     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)),        transform_worldex   }, 0                               },
5091     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)),        transform_worldex   }, 0                               },
5092     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)),        transform_worldex   }, 0                               },
5093     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)),        transform_worldex   }, 0                               },
5094     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)),        transform_worldex   }, 0                               },
5095     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)),        transform_worldex   }, 0                               },
5096     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)),        transform_worldex   }, 0                               },
5097     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)),        transform_worldex   }, 0                               },
5098     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)),        transform_worldex   }, 0                               },
5099     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)),        transform_worldex   }, 0                               },
5100     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)),        transform_worldex   }, 0                               },
5101     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)),        transform_worldex   }, 0                               },
5102     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)),        transform_worldex   }, 0                               },
5103     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)),        transform_worldex   }, 0                               },
5104     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)),        transform_worldex   }, 0                               },
5105     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)),        transform_worldex   }, 0                               },
5106     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)),        transform_worldex   }, 0                               },
5107     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)),        transform_worldex   }, 0                               },
5108     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)),        transform_worldex   }, 0                               },
5109     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)),        transform_worldex   }, 0                               },
5110     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)),        transform_worldex   }, 0                               },
5111     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)),        transform_worldex   }, 0                               },
5112     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)),        transform_worldex   }, 0                               },
5113     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)),        transform_worldex   }, 0                               },
5114     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)),        transform_worldex   }, 0                               },
5115     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)),        transform_worldex   }, 0                               },
5116     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)),        transform_worldex   }, 0                               },
5117     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)),        transform_worldex   }, 0                               },
5118     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)),        transform_worldex   }, 0                               },
5119     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)),        transform_worldex   }, 0                               },
5120     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)),        transform_worldex   }, 0                               },
5121     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)),        transform_worldex   }, 0                               },
5122     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)),        transform_worldex   }, 0                               },
5123     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)),        transform_worldex   }, 0                               },
5124     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)),        transform_worldex   }, 0                               },
5125     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)),        transform_worldex   }, 0                               },
5126     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)),        transform_worldex   }, 0                               },
5127     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)),        transform_worldex   }, 0                               },
5128     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)),        transform_worldex   }, 0                               },
5129     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)),        transform_worldex   }, 0                               },
5130     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)),        transform_worldex   }, 0                               },
5131     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)),        transform_worldex   }, 0                               },
5132     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)),        transform_worldex   }, 0                               },
5133     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)),        transform_worldex   }, 0                               },
5134     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)),        transform_worldex   }, 0                               },
5135     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)),        transform_worldex   }, 0                               },
5136     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)),        transform_worldex   }, 0                               },
5137     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)),        transform_worldex   }, 0                               },
5138     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)),        transform_worldex   }, 0                               },
5139     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)),        transform_worldex   }, 0                               },
5140     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)),        transform_worldex   }, 0                               },
5141     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)),        transform_worldex   }, 0                               },
5142     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)),        transform_worldex   }, 0                               },
5143     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)),        transform_worldex   }, 0                               },
5144     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)),        transform_worldex   }, 0                               },
5145     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)),        transform_worldex   }, 0                               },
5146     { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5147     { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5148     { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5149     { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5150     { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5151     { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5152     { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5153     { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),transform_texture   }, 0                               },
5154     { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5155     { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5156     { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5157     { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5158     { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5159     { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5160     { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5161     { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
5162       /* Fog */
5163     { STATE_RENDER(WINED3DRS_FOGENABLE),                  { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_vertexpart}, 0                               },
5164     { STATE_RENDER(WINED3DRS_FOGTABLEMODE),               { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_vertexpart}, 0                               },
5165     { STATE_RENDER(WINED3DRS_FOGVERTEXMODE),              { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_vertexpart}, 0                               },
5166     { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             state_rangefog      }, NV_FOG_DISTANCE                 },
5167     { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             state_rangefog_w    }, 0                               },
5168     { STATE_RENDER(WINED3DRS_CLIPPING),                   { STATE_RENDER(WINED3DRS_CLIPPING),                   state_clipping      }, 0                               },
5169     { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE),            { STATE_RENDER(WINED3DRS_CLIPPING),                   state_clipping      }, 0                               },
5170     { STATE_RENDER(WINED3DRS_LIGHTING),                   { STATE_RENDER(WINED3DRS_LIGHTING),                   state_lighting      }, 0                               },
5171     { STATE_RENDER(WINED3DRS_AMBIENT),                    { STATE_RENDER(WINED3DRS_AMBIENT),                    state_ambient       }, 0                               },
5172     { STATE_RENDER(WINED3DRS_COLORVERTEX),                { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
5173     { STATE_RENDER(WINED3DRS_LOCALVIEWER),                { STATE_RENDER(WINED3DRS_LOCALVIEWER),                state_localviewer   }, 0                               },
5174     { STATE_RENDER(WINED3DRS_NORMALIZENORMALS),           { STATE_RENDER(WINED3DRS_NORMALIZENORMALS),           state_normalize     }, 0                               },
5175     { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE),      { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
5176     { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE),     { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
5177     { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE),      { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
5178     { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE),     { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
5179     { STATE_RENDER(WINED3DRS_VERTEXBLEND),                { STATE_RENDER(WINED3DRS_VERTEXBLEND),                state_vertexblend   }, ARB_VERTEX_BLEND                },
5180     { STATE_RENDER(WINED3DRS_VERTEXBLEND),                { STATE_RENDER(WINED3DRS_VERTEXBLEND),                state_vertexblend_w }, 0                               },
5181     { STATE_RENDER(WINED3DRS_POINTSIZE),                  { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
5182     { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_arb  }, ARB_POINT_PARAMETERS            },
5183     { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_ext  }, EXT_POINT_PARAMETERS            },
5184     { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_w    }, 0                               },
5185     { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          state_pointsprite   }, ARB_POINT_SPRITE                },
5186     { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          state_pointsprite_w }, 0                               },
5187     { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
5188     { STATE_RENDER(WINED3DRS_POINTSCALE_A),               { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
5189     { STATE_RENDER(WINED3DRS_POINTSCALE_B),               { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
5190     { STATE_RENDER(WINED3DRS_POINTSCALE_C),               { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
5191     { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_arb  }, ARB_POINT_PARAMETERS            },
5192     { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_ext  }, EXT_POINT_PARAMETERS            },
5193     { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_w    }, 0                               },
5194     /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
5195      * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
5196      * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
5197      */
5198     { STATE_SAMPLER(0),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5199     { STATE_SAMPLER(0),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5200     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texmatrix   }, 0                               },
5201     { STATE_SAMPLER(1),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5202     { STATE_SAMPLER(1),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5203     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texmatrix   }, 0                               },
5204     { STATE_SAMPLER(2),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5205     { STATE_SAMPLER(2),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5206     { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texmatrix   }, 0                               },
5207     { STATE_SAMPLER(3),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5208     { STATE_SAMPLER(3),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5209     { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texmatrix   }, 0                               },
5210     { STATE_SAMPLER(4),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5211     { STATE_SAMPLER(4),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5212     { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texmatrix   }, 0                               },
5213     { STATE_SAMPLER(5),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5214     { STATE_SAMPLER(5),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5215     { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texmatrix   }, 0                               },
5216     { STATE_SAMPLER(6),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5217     { STATE_SAMPLER(6),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5218     { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texmatrix   }, 0                               },
5219     { STATE_SAMPLER(7),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5220     { STATE_SAMPLER(7),                                   { 0,                                                  NULL                }, WINE_NORMALIZED_TEXRECT         },
5221     { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texmatrix   }, 0                               },
5222     {0 /* Terminate */,                                   { 0,                                                  0                   }, 0                               },
5223 };
5224
5225 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
5226     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5227     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5228     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5229     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5230     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5231     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5232     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5233     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5234     { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5235     { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5236     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5237     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5238     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5239     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5240     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5241     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5242     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5243     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5244     { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5245     { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5246     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5247     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5248     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5249     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5250     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5251     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5252     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5253     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5254     { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5255     { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5256     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5257     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5258     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5259     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5260     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5261     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5262     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5263     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5264     { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5265     { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5266     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5267     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5268     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5269     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5270     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5271     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5272     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5273     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5274     { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5275     { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5276     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5277     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5278     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5279     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5280     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5281     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5282     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5283     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5284     { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5285     { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5286     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5287     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5288     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5289     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5290     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5291     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5292     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5293     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5294     { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5295     { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5296     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5297     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5298     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5299     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5300     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5301     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5302     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5303     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
5304     { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
5305     { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
5306     { STATE_PIXELSHADER,                                  { STATE_PIXELSHADER,                                  apply_pixelshader   }, 0                               },
5307     { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE),            { STATE_PIXELSHADER,                                  apply_pixelshader   }, 0                               },
5308     { STATE_RENDER(WINED3DRS_BORDERCOLOR),                { STATE_RENDER(WINED3DRS_BORDERCOLOR),                state_bordercolor   }, 0                               },
5309     { STATE_RENDER(WINED3DRS_TEXTUREFACTOR),              { STATE_RENDER(WINED3DRS_TEXTUREFACTOR),              state_texfactor     }, 0                               },
5310     { STATE_RENDER(WINED3DRS_FOGCOLOR),                   { STATE_RENDER(WINED3DRS_FOGCOLOR),                   state_fogcolor      }, 0                               },
5311     { STATE_RENDER(WINED3DRS_FOGDENSITY),                 { STATE_RENDER(WINED3DRS_FOGDENSITY),                 state_fogdensity    }, 0                               },
5312     { STATE_RENDER(WINED3DRS_FOGENABLE),                  { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_fragpart  }, 0                               },
5313     { STATE_RENDER(WINED3DRS_FOGTABLEMODE),               { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_fragpart  }, 0                               },
5314     { STATE_RENDER(WINED3DRS_FOGVERTEXMODE),              { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog_fragpart  }, 0                               },
5315     { STATE_RENDER(WINED3DRS_FOGSTART),                   { STATE_RENDER(WINED3DRS_FOGSTART),                   state_fogstartend   }, 0                               },
5316     { STATE_RENDER(WINED3DRS_FOGEND),                     { STATE_RENDER(WINED3DRS_FOGSTART),                   state_fogstartend   }, 0                               },
5317     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texdim      }, 0                               },
5318     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texdim      }, 0                               },
5319     { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texdim      }, 0                               },
5320     { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texdim      }, 0                               },
5321     { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texdim      }, 0                               },
5322     { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texdim      }, 0                               },
5323     { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texdim      }, 0                               },
5324     { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texdim      }, 0                               },
5325     {0 /* Terminate */,                                   { 0,                                                  0                   }, 0                               },
5326 };
5327 #undef GLINFO_LOCATION
5328
5329 #define GLINFO_LOCATION (*gl_info)
5330 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
5331
5332 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, const WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps)
5333 {
5334     pCaps->TextureOpCaps =  WINED3DTEXOPCAPS_ADD         |
5335                             WINED3DTEXOPCAPS_ADDSIGNED   |
5336                             WINED3DTEXOPCAPS_ADDSIGNED2X |
5337                             WINED3DTEXOPCAPS_MODULATE    |
5338                             WINED3DTEXOPCAPS_MODULATE2X  |
5339                             WINED3DTEXOPCAPS_MODULATE4X  |
5340                             WINED3DTEXOPCAPS_SELECTARG1  |
5341                             WINED3DTEXOPCAPS_SELECTARG2  |
5342                             WINED3DTEXOPCAPS_DISABLE;
5343
5344     if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
5345         GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
5346         GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5347         pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA  |
5348                                 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA  |
5349                                 WINED3DTEXOPCAPS_BLENDFACTORALPHA   |
5350                                 WINED3DTEXOPCAPS_BLENDCURRENTALPHA  |
5351                                 WINED3DTEXOPCAPS_LERP               |
5352                                 WINED3DTEXOPCAPS_SUBTRACT;
5353     }
5354     if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
5355         GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
5356         pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH              |
5357                                 WINED3DTEXOPCAPS_MULTIPLYADD            |
5358                                 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
5359                                 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
5360                                 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5361     }
5362     if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
5363         pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5364
5365     pCaps->MaxTextureBlendStages   = GL_LIMITS(texture_stages);
5366     pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
5367 }
5368
5369 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
5370 static void ffp_fragment_free(IWineD3DDevice *iface) {}
5371 static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
5372 {
5373     if (TRACE_ON(d3d))
5374     {
5375         TRACE("Checking support for fixup:\n");
5376         dump_color_fixup_desc(fixup);
5377     }
5378
5379     /* We only support identity conversions. */
5380     if (is_identity_fixup(fixup))
5381     {
5382         TRACE("[OK]\n");
5383         return TRUE;
5384     }
5385
5386     TRACE("[FAILED]\n");
5387     return FALSE;
5388 }
5389
5390 const struct fragment_pipeline ffp_fragment_pipeline = {
5391     ffp_enable,
5392     ffp_fragment_get_caps,
5393     ffp_fragment_alloc,
5394     ffp_fragment_free,
5395     ffp_color_fixup_supported,
5396     ffp_fragmentstate_template,
5397     FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
5398 };
5399
5400 static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
5401 {
5402     unsigned int i;
5403     for(i = 0; funcs[i]; i++);
5404     return i;
5405 }
5406
5407 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5408     stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5409     stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5410 }
5411
5412 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
5413     stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
5414     stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
5415     stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
5416 }
5417
5418 HRESULT compile_state_table(struct StateEntry *StateTable, APPLYSTATEFUNC **dev_multistate_funcs,
5419         const WineD3D_GL_Info *gl_info, const struct StateEntryTemplate *vertex,
5420         const struct fragment_pipeline *fragment, const struct StateEntryTemplate *misc)
5421 {
5422     unsigned int i, type, handlers;
5423     APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5424     const struct StateEntryTemplate *cur;
5425     BOOL set[STATE_HIGHEST + 1];
5426
5427     memset(multistate_funcs, 0, sizeof(multistate_funcs));
5428
5429     for(i = 0; i < STATE_HIGHEST + 1; i++) {
5430         StateTable[i].representative = 0;
5431         StateTable[i].apply = state_undefined;
5432     }
5433
5434     for(type = 0; type < 3; type++) {
5435         /* This switch decides the order in which the states are applied */
5436         switch(type) {
5437             case 0: cur = misc; break;
5438             case 1: cur = fragment->states; break;
5439             case 2: cur = vertex; break;
5440             default: cur = NULL; /* Stupid compiler */
5441         }
5442         if(!cur) continue;
5443
5444         /* GL extension filtering should not prevent multiple handlers being applied from different
5445          * pipeline parts
5446          */
5447         memset(set, 0, sizeof(set));
5448
5449         for(i = 0; cur[i].state; i++) {
5450             APPLYSTATEFUNC *funcs_array;
5451
5452             /* Only use the first matching state with the available extension from one template.
5453              * e.g.
5454              * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
5455              * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0        }
5456              *
5457              * if GL_XYZ_fancy is supported, ignore the 2nd line
5458              */
5459             if(set[cur[i].state]) continue;
5460             /* Skip state lines depending on unsupported extensions */
5461             if(cur[i].extension && !GL_SUPPORT(cur[i].extension)) continue;
5462             set[cur[i].state] = TRUE;
5463             /* In some cases having an extension means that nothing has to be
5464              * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
5465              * supported, the texture coordinate fixup can be ignored. If the
5466              * apply function is used, mark the state set(done above) to prevent
5467              * applying later lines, but do not record anything in the state
5468              * table
5469              */
5470             if(!cur[i].content.apply) continue;
5471
5472             handlers = num_handlers(multistate_funcs[cur[i].state]);
5473             multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5474             switch(handlers) {
5475                 case 0:
5476                     StateTable[cur[i].state].apply = cur[i].content.apply;
5477                     break;
5478                 case 1:
5479                     StateTable[cur[i].state].apply = multistate_apply_2;
5480                     dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
5481                                                                    0,
5482                                                                    sizeof(**dev_multistate_funcs) * 2);
5483                     if (!dev_multistate_funcs[cur[i].state]) {
5484                         goto out_of_mem;
5485                     }
5486
5487                     dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
5488                     dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
5489                     break;
5490                 case 2:
5491                     StateTable[cur[i].state].apply = multistate_apply_3;
5492                     funcs_array = HeapReAlloc(GetProcessHeap(),
5493                                               0,
5494                                               dev_multistate_funcs[cur[i].state],
5495                                               sizeof(**dev_multistate_funcs) * 3);
5496                     if (!funcs_array) {
5497                         goto out_of_mem;
5498                     }
5499
5500                     dev_multistate_funcs[cur[i].state] = funcs_array;
5501                     dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
5502                     break;
5503                 default:
5504                     ERR("Unexpected amount of state handlers for state %u: %u\n",
5505                         cur[i].state, handlers + 1);
5506             }
5507
5508             if(StateTable[cur[i].state].representative &&
5509             StateTable[cur[i].state].representative != cur[i].content.representative) {
5510                 FIXME("State %u has different representatives in different pipeline parts\n",
5511                     cur[i].state);
5512             }
5513             StateTable[cur[i].state].representative = cur[i].content.representative;
5514         }
5515     }
5516
5517     return WINED3D_OK;
5518
5519 out_of_mem:
5520     for (i = 0; i <= STATE_HIGHEST; ++i) {
5521         HeapFree(GetProcessHeap(), 0, dev_multistate_funcs[i]);
5522     }
5523
5524     memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1)*sizeof(*dev_multistate_funcs));
5525
5526     return E_OUTOFMEMORY;
5527 }
5528 #undef GLINFO_LOCATION