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