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