wined3d: Remove GL_EXT_vertex_weighting stubs.
[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_w(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2632     static BOOL once = FALSE;
2633
2634     switch(stateblock->renderState[WINED3DRS_VERTEXBLEND]) {
2635         case WINED3DVBF_1WEIGHTS:
2636         case WINED3DVBF_2WEIGHTS:
2637         case WINED3DVBF_3WEIGHTS:
2638             if(!once) {
2639                 once = TRUE;
2640                 /* TODO: Implement vertex blending in drawStridedSlow */
2641                 FIXME("Vertex blending enabled, but not supported by hardware\n");
2642             }
2643             break;
2644
2645         case WINED3DVBF_TWEENING:
2646             WARN("Tweening not supported yet\n");
2647     }
2648 }
2649
2650 static void state_vertexblend(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2651     WINED3DVERTEXBLENDFLAGS val = stateblock->renderState[WINED3DRS_VERTEXBLEND];
2652
2653     switch(val) {
2654         case WINED3DVBF_1WEIGHTS:
2655         case WINED3DVBF_2WEIGHTS:
2656         case WINED3DVBF_3WEIGHTS:
2657             glEnable(GL_VERTEX_BLEND_ARB);
2658             checkGLcall("glEnable(GL_VERTEX_BLEND_ARB)");
2659
2660             /* D3D adds one more matrix which has weight (1 - sum(weights)). This is enabled at context
2661              * creation with enabling GL_WEIGHT_SUM_UNITY_ARB.
2662              */
2663             GL_EXTCALL(glVertexBlendARB(stateblock->renderState[WINED3DRS_VERTEXBLEND] + 1));
2664
2665             if(!stateblock->wineD3DDevice->vertexBlendUsed) {
2666                 int i;
2667                 for(i = 1; i < GL_LIMITS(blends); i++) {
2668                     if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)))) {
2669                         transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(i)), stateblock, context);
2670                     }
2671                 }
2672                 stateblock->wineD3DDevice->vertexBlendUsed = TRUE;
2673             }
2674             break;
2675
2676         case WINED3DVBF_DISABLE:
2677         case WINED3DVBF_0WEIGHTS: /* for Indexed vertex blending - not supported */
2678             glDisable(GL_VERTEX_BLEND_ARB);
2679             checkGLcall("glDisable(GL_VERTEX_BLEND_ARB)");
2680             break;
2681
2682         case WINED3DVBF_TWEENING:
2683             /* Just set the vertex weight for weight 0, enable vertex blending and hope the app doesn't have
2684              * vertex weights in the vertices?
2685              * For now we don't report that as supported, so a warn should suffice
2686              */
2687             WARN("Tweening not supported yet\n");
2688             break;
2689     }
2690 }
2691
2692 static void transform_view(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2693     unsigned int k;
2694
2695     /* If we are changing the View matrix, reset the light and clipping planes to the new view
2696      * NOTE: We have to reset the positions even if the light/plane is not currently
2697      *       enabled, since the call to enable it will not reset the position.
2698      * NOTE2: Apparently texture transforms do NOT need reapplying
2699      */
2700
2701     PLIGHTINFOEL *light = NULL;
2702
2703     glMatrixMode(GL_MODELVIEW);
2704     checkGLcall("glMatrixMode(GL_MODELVIEW)");
2705     glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
2706     checkGLcall("glLoadMatrixf(...)");
2707
2708     /* Reset lights. TODO: Call light apply func */
2709     for(k = 0; k < stateblock->wineD3DDevice->maxConcurrentLights; k++) {
2710         light = stateblock->activeLights[k];
2711         if(!light) continue;
2712         glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, light->lightPosn);
2713         checkGLcall("glLightfv posn");
2714         glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, light->lightDirn);
2715         checkGLcall("glLightfv dirn");
2716     }
2717
2718     /* Reset Clipping Planes  */
2719     for (k = 0; k < GL_LIMITS(clipplanes); k++) {
2720         if(!isStateDirty(context, STATE_CLIPPLANE(k))) {
2721             clipplane(STATE_CLIPPLANE(k), stateblock, context);
2722         }
2723     }
2724
2725     if(context->last_was_rhw) {
2726         glLoadIdentity();
2727         checkGLcall("glLoadIdentity()");
2728         /* No need to update the world matrix, the identity is fine */
2729         return;
2730     }
2731
2732     /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
2733      * No need to do it here if the state is scheduled for update.
2734      */
2735     if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
2736         transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
2737     }
2738
2739     /* Avoid looping over a number of matrices if the app never used the functionality */
2740     if(stateblock->wineD3DDevice->vertexBlendUsed) {
2741         for(k = 1; k < GL_LIMITS(blends); k++) {
2742             if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)))) {
2743                 transform_worldex(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(k)), stateblock, context);
2744             }
2745         }
2746     }
2747 }
2748
2749 static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
2750     glMatrixMode(GL_PROJECTION);
2751     checkGLcall("glMatrixMode(GL_PROJECTION)");
2752     glLoadIdentity();
2753     checkGLcall("glLoadIdentity");
2754
2755     if(context->last_was_rhw) {
2756         double X, Y, height, width, minZ, maxZ;
2757
2758         X      = stateblock->viewport.X;
2759         Y      = stateblock->viewport.Y;
2760         height = stateblock->viewport.Height;
2761         width  = stateblock->viewport.Width;
2762         minZ   = stateblock->viewport.MinZ;
2763         maxZ   = stateblock->viewport.MaxZ;
2764
2765         if(!stateblock->wineD3DDevice->untransformed) {
2766             /* Transformed vertices are supposed to bypass the whole transform pipeline including
2767              * frustum clipping. This can't be done in opengl, so this code adjusts the Z range to
2768              * suppress depth clipping. This can be done because it is an orthogonal projection and
2769              * the Z coordinate does not affect the size of the primitives. Half Life 1 and Prince of
2770              * Persia 3D need this.
2771              *
2772              * Note that using minZ and maxZ here doesn't entirely fix the problem, since view frustum
2773              * clipping is still enabled, but it seems to fix it for all apps tested so far. A minor
2774              * problem can be witnessed in half-life 1 engine based games, the weapon is clipped close
2775              * to the viewer.
2776              *
2777              * Also note that this breaks z comparison against z values filled in with clear,
2778              * but no app depending on that and disabled clipping has been found yet. Comparing
2779              * primitives against themselves works, so the Z buffer is still intact for normal hidden
2780              * surface removal.
2781              *
2782              * We could disable clipping entirely by setting the near to infinity and far to -infinity,
2783              * but this would break Z buffer operation. Raising the range to something less than
2784              * infinity would help a bit at the cost of Z precision, but it wouldn't eliminate the
2785              * problem either.
2786              */
2787             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, -minZ, -maxZ);
2788             if(stateblock->wineD3DDevice->render_offscreen) {
2789                 glOrtho(X, X + width, -Y, -Y - height, -minZ, -maxZ);
2790             } else {
2791                 glOrtho(X, X + width, Y + height, Y, -minZ, -maxZ);
2792             }
2793         } else {
2794             /* If the app mixes transformed and untransformed primitives we can't use the coordinate system
2795              * trick above because this would mess up transformed and untransformed Z order. Pass the z position
2796              * unmodified to opengl.
2797              *
2798              * If the app depends on mixed types and disabled clipping we're out of luck without a pipeline
2799              * replacement shader.
2800              */
2801             TRACE("Calling glOrtho with %f, %f, %f, %f\n", width, height, 1.0, -1.0);
2802             if(stateblock->wineD3DDevice->render_offscreen) {
2803                 glOrtho(X, X + width, -Y, -Y - height, 0.0, -1.0);
2804             } else {
2805                 glOrtho(X, X + width, Y + height, Y, 0.0, -1.0);
2806             }
2807         }
2808         checkGLcall("glOrtho");
2809
2810         /* Window Coord 0 is the middle of the first pixel, so translate by 1/2 pixels */
2811         glTranslatef(0.5, 0.5, 0);
2812         checkGLcall("glTranslatef(0.5, 0.5, 0)");
2813         /* D3D texture coordinates are flipped compared to OpenGL ones, so
2814          * render everything upside down when rendering offscreen. */
2815         if (stateblock->wineD3DDevice->render_offscreen) {
2816             glScalef(1.0, -1.0, 1.0);
2817             checkGLcall("glScalef");
2818         }
2819     } else {
2820         /* The rule is that the window coordinate 0 does not correspond to the
2821             beginning of the first pixel, but the center of the first pixel.
2822             As a consequence if you want to correctly draw one line exactly from
2823             the left to the right end of the viewport (with all matrices set to
2824             be identity), the x coords of both ends of the line would be not
2825             -1 and 1 respectively but (-1-1/viewport_widh) and (1-1/viewport_width)
2826             instead.
2827
2828             1.0 / Width is used because the coord range goes from -1.0 to 1.0, then we
2829             divide by the Width/Height, so we need the half range(1.0) to translate by
2830             half a pixel.
2831
2832             The other fun is that d3d's output z range after the transformation is [0;1],
2833             but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl
2834             scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot
2835             of Z buffer precision and the clear values do not match in the z test. Thus scale
2836             [0;1] to [-1;1], so when gl undoes that we utilize the full z range
2837          */
2838         glTranslatef(1.0 / stateblock->viewport.Width, -1.0/ stateblock->viewport.Height, -1.0);
2839         checkGLcall("glTranslatef (1.0 / width, -1.0 / height, -1.0)");
2840         if (stateblock->wineD3DDevice->render_offscreen) {
2841             /* D3D texture coordinates are flipped compared to OpenGL ones, so
2842              * render everything upside down when rendering offscreen. */
2843             glScalef(1.0, -1.0, 2.0);
2844         } else {
2845             glScalef(1.0, 1.0, 2.0);
2846         }
2847         checkGLcall("glScalef");
2848
2849         glMultMatrixf(&stateblock->transforms[WINED3DTS_PROJECTION].u.m[0][0]);
2850         checkGLcall("glLoadMatrixf");
2851     }
2852 }
2853
2854 /* This should match any arrays loaded in loadVertexData.
2855  * stateblock impl is required for GL_SUPPORT
2856  * TODO: Only load / unload arrays if we have to.
2857  */
2858 static inline void unloadVertexData(IWineD3DStateBlockImpl *stateblock) {
2859     glDisableClientState(GL_VERTEX_ARRAY);
2860     glDisableClientState(GL_NORMAL_ARRAY);
2861     glDisableClientState(GL_COLOR_ARRAY);
2862     if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
2863         glDisableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
2864     }
2865     if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
2866         glDisableClientState(GL_WEIGHT_ARRAY_ARB);
2867     }
2868     unloadTexCoords(stateblock);
2869 }
2870
2871 /* This should match any arrays loaded in loadNumberedArrays
2872  * TODO: Only load / unload arrays if we have to.
2873  */
2874 static inline void unloadNumberedArrays(IWineD3DStateBlockImpl *stateblock) {
2875     /* disable any attribs (this is the same for both GLSL and ARB modes) */
2876     GLint maxAttribs = 16;
2877     int i;
2878
2879     /* Leave all the attribs disabled */
2880     glGetIntegerv(GL_MAX_VERTEX_ATTRIBS_ARB, &maxAttribs);
2881     /* MESA does not support it right not */
2882     if (glGetError() != GL_NO_ERROR)
2883         maxAttribs = 16;
2884     for (i = 0; i < maxAttribs; ++i) {
2885         GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2886         checkGLcall("glDisableVertexAttribArrayARB(reg)");
2887         /* Some Windows drivers(NV GF 7) use the latest value that was used when drawing with the now
2888          * deactivated stream disabled, some other drivers(ATI, NV GF 8) set the undefined values to 0x00.
2889          * Let's set them to 0x00 to avoid hitting some undefined aspects of OpenGL. All that is really
2890          * important here is the glDisableVertexAttribArrayARB call above. The test shows that the refrast
2891          * keeps dereferencing the pointers, which would cause crashes in some games like Half Life 2: Episode Two.
2892          */
2893         GL_EXTCALL(glVertexAttrib4NubARB(i, 0, 0, 0, 0));
2894         checkGLcall("glVertexAttrib4NubARB(i, 0, 0, 0, 0)");
2895     }
2896 }
2897
2898 static inline void loadNumberedArrays(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *strided) {
2899     GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
2900     int i;
2901     UINT *offset = stateblock->streamOffset;
2902     IWineD3DVertexBufferImpl *vb;
2903     DWORD_PTR shift_index;
2904
2905     /* Default to no instancing */
2906     stateblock->wineD3DDevice->instancedDraw = FALSE;
2907
2908     for (i = 0; i < MAX_ATTRIBS; i++) {
2909
2910         if (!strided->u.input[i].lpData && !strided->u.input[i].VBO)
2911             continue;
2912
2913         /* Do not load instance data. It will be specified using glTexCoord by drawprim */
2914         if(stateblock->streamFlags[strided->u.input[i].streamNo] & WINED3DSTREAMSOURCE_INSTANCEDATA) {
2915             GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2916             stateblock->wineD3DDevice->instancedDraw = TRUE;
2917             continue;
2918         }
2919
2920         TRACE_(d3d_shader)("Loading array %u [VBO=%u]\n", i, strided->u.input[i].VBO);
2921
2922         if(strided->u.input[i].dwStride) {
2923             if(curVBO != strided->u.input[i].VBO) {
2924                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, strided->u.input[i].VBO));
2925                 checkGLcall("glBindBufferARB");
2926                 curVBO = strided->u.input[i].VBO;
2927             }
2928             vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2929             /* Use the VBO to find out if a vertex buffer exists, not the vb pointer. vb can point to a
2930              * user pointer data blob. In that case curVBO will be 0. If there is a vertex buffer but no
2931              * vbo we won't be load converted attributes anyway
2932              */
2933             if(curVBO && vb->conv_shift) {
2934                 TRACE("Loading attribute from shifted buffer\n");
2935                 TRACE("Attrib %d has original stride %d, new stride %d\n", i, strided->u.input[i].dwStride, vb->conv_stride);
2936                 TRACE("Original offset %p, additional offset 0x%08x\n",strided->u.input[i].lpData, vb->conv_shift[(DWORD_PTR) strided->u.input[i].lpData]);
2937                 TRACE("Opengl type %x\n", WINED3D_ATR_GLTYPE(strided->u.input[i].dwType));
2938                 shift_index = ((DWORD_PTR) strided->u.input[i].lpData + offset[strided->u.input[i].streamNo]);
2939                 shift_index = shift_index % strided->u.input[i].dwStride;
2940                 GL_EXTCALL(glVertexAttribPointerARB(i,
2941                                 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2942                                 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2943                                 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2944                                 vb->conv_stride,
2945
2946                                 strided->u.input[i].lpData + vb->conv_shift[shift_index] +
2947                                 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
2948                                 offset[strided->u.input[i].streamNo]));
2949
2950             } else {
2951                 GL_EXTCALL(glVertexAttribPointerARB(i,
2952                                 WINED3D_ATR_SIZE(strided->u.input[i].dwType),
2953                                 WINED3D_ATR_GLTYPE(strided->u.input[i].dwType),
2954                                 WINED3D_ATR_NORMALIZED(strided->u.input[i].dwType),
2955                                 strided->u.input[i].dwStride,
2956
2957                                 strided->u.input[i].lpData +
2958                                 stateblock->loadBaseVertexIndex * strided->u.input[i].dwStride +
2959                                 offset[strided->u.input[i].streamNo]) );
2960                 }
2961             GL_EXTCALL(glEnableVertexAttribArrayARB(i));
2962         } else {
2963             /* Stride = 0 means always the same values. glVertexAttribPointerARB doesn't do that. Instead disable the pointer and
2964              * set up the attribute statically. But we have to figure out the system memory address.
2965              */
2966             BYTE *ptr = strided->u.input[i].lpData + offset[strided->u.input[i].streamNo];
2967             if(strided->u.input[i].VBO) {
2968                 vb = (IWineD3DVertexBufferImpl *) stateblock->streamSource[strided->u.input[i].streamNo];
2969                 ptr += (long) vb->resource.allocatedMemory;
2970             }
2971             GL_EXTCALL(glDisableVertexAttribArrayARB(i));
2972
2973             switch(strided->u.input[i].dwType) {
2974                 case WINED3DDECLTYPE_FLOAT1:
2975                     GL_EXTCALL(glVertexAttrib1fvARB(i, (float *) ptr));
2976                     break;
2977                 case WINED3DDECLTYPE_FLOAT2:
2978                     GL_EXTCALL(glVertexAttrib2fvARB(i, (float *) ptr));
2979                     break;
2980                 case WINED3DDECLTYPE_FLOAT3:
2981                     GL_EXTCALL(glVertexAttrib3fvARB(i, (float *) ptr));
2982                     break;
2983                 case WINED3DDECLTYPE_FLOAT4:
2984                     GL_EXTCALL(glVertexAttrib4fvARB(i, (float *) ptr));
2985                     break;
2986
2987                 case WINED3DDECLTYPE_UBYTE4:
2988                     GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2989                     break;
2990                 case WINED3DDECLTYPE_UBYTE4N:
2991                 case WINED3DDECLTYPE_D3DCOLOR:
2992                     GL_EXTCALL(glVertexAttrib4NubvARB(i, ptr));
2993                     break;
2994
2995                 case WINED3DDECLTYPE_SHORT2:
2996                     GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
2997                     break;
2998                 case WINED3DDECLTYPE_SHORT4:
2999                     GL_EXTCALL(glVertexAttrib4svARB(i, (GLshort *) ptr));
3000                     break;
3001
3002                 case WINED3DDECLTYPE_SHORT2N:
3003                 {
3004                     GLshort s[4] = {((short *) ptr)[0], ((short *) ptr)[1], 0, 1};
3005                     GL_EXTCALL(glVertexAttrib4NsvARB(i, s));
3006                     break;
3007                 }
3008                 case WINED3DDECLTYPE_USHORT2N:
3009                 {
3010                     GLushort s[4] = {((unsigned short *) ptr)[0], ((unsigned short *) ptr)[1], 0, 1};
3011                     GL_EXTCALL(glVertexAttrib4NusvARB(i, s));
3012                     break;
3013                 }
3014                 case WINED3DDECLTYPE_SHORT4N:
3015                     GL_EXTCALL(glVertexAttrib4NsvARB(i, (GLshort *) ptr));
3016                     break;
3017                 case WINED3DDECLTYPE_USHORT4N:
3018                     GL_EXTCALL(glVertexAttrib4NusvARB(i, (GLushort *) ptr));
3019                     break;
3020
3021                 case WINED3DDECLTYPE_UDEC3:
3022                     FIXME("Unsure about WINED3DDECLTYPE_UDEC3\n");
3023                     /*glVertexAttrib3usvARB(i, (GLushort *) ptr); Does not exist */
3024                     break;
3025                 case WINED3DDECLTYPE_DEC3N:
3026                     FIXME("Unsure about WINED3DDECLTYPE_DEC3N\n");
3027                     /*glVertexAttrib3NusvARB(i, (GLushort *) ptr); Does not exist */
3028                     break;
3029
3030                 case WINED3DDECLTYPE_FLOAT16_2:
3031                     /* Are those 16 bit floats. C doesn't have a 16 bit float type. I could read the single bits and calculate a 4
3032                      * byte float according to the IEEE standard
3033                      */
3034                     FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_2\n");
3035                     break;
3036                 case WINED3DDECLTYPE_FLOAT16_4:
3037                     FIXME("Unsupported WINED3DDECLTYPE_FLOAT16_4\n");
3038                     break;
3039
3040                 case WINED3DDECLTYPE_UNUSED:
3041                 default:
3042                     ERR("Unexpected declaration in stride 0 attributes\n");
3043                     break;
3044
3045             }
3046         }
3047     }
3048     checkGLcall("Loading numbered arrays");
3049 }
3050
3051 /* Used from 2 different functions, and too big to justify making it inlined */
3052 static void loadVertexData(IWineD3DStateBlockImpl *stateblock, WineDirect3DVertexStridedData *sd) {
3053     UINT *offset = stateblock->streamOffset;
3054     GLint curVBO = GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT) ? -1 : 0;
3055
3056     TRACE("Using fast vertex array code\n");
3057
3058     /* This is fixed function pipeline only, and the fixed function pipeline doesn't do instancing */
3059     stateblock->wineD3DDevice->instancedDraw = FALSE;
3060
3061     /* Blend Data ---------------------------------------------- */
3062     if( (sd->u.s.blendWeights.lpData) || (sd->u.s.blendWeights.VBO) ||
3063         (sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO) ) {
3064
3065         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3066             TRACE("Blend %d %p %d\n", WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3067                 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride, sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3068
3069             glEnableClientState(GL_WEIGHT_ARRAY_ARB);
3070             checkGLcall("glEnableClientState(GL_WEIGHT_ARRAY_ARB)");
3071
3072             GL_EXTCALL(glVertexBlendARB(WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) + 1));
3073
3074             VTRACE(("glWeightPointerARB(%d, GL_FLOAT, %d, %p)\n",
3075                 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType) ,
3076                 sd->u.s.blendWeights.dwStride,
3077                 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]));
3078
3079             if(curVBO != sd->u.s.blendWeights.VBO) {
3080                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.blendWeights.VBO));
3081                 checkGLcall("glBindBufferARB");
3082                 curVBO = sd->u.s.blendWeights.VBO;
3083             }
3084
3085             GL_EXTCALL(glWeightPointerARB)(
3086                 WINED3D_ATR_SIZE(sd->u.s.blendWeights.dwType),
3087                 WINED3D_ATR_GLTYPE(sd->u.s.blendWeights.dwType),
3088                 sd->u.s.blendWeights.dwStride,
3089                 sd->u.s.blendWeights.lpData + stateblock->loadBaseVertexIndex * sd->u.s.blendWeights.dwStride + offset[sd->u.s.blendWeights.streamNo]);
3090
3091             checkGLcall("glWeightPointerARB");
3092
3093             if((sd->u.s.blendMatrixIndices.lpData) || (sd->u.s.blendMatrixIndices.VBO)){
3094                 static BOOL showfixme = TRUE;
3095                 if(showfixme){
3096                     FIXME("blendMatrixIndices support\n");
3097                     showfixme = FALSE;
3098                 }
3099             }
3100         } else {
3101             /* TODO: support blends in drawStridedSlow
3102              * No need to write a FIXME here, this is done after the general vertex decl decoding
3103              */
3104             WARN("unsupported blending in openGl\n");
3105         }
3106     } else {
3107         if (GL_SUPPORT(ARB_VERTEX_BLEND)) {
3108             static const GLbyte one = 1;
3109             GL_EXTCALL(glWeightbvARB(1, &one));
3110             checkGLcall("glWeightivARB(GL_LIMITS(blends), weights)");
3111         }
3112     }
3113
3114 #if 0 /* FOG  ----------------------------------------------*/
3115     if (sd->u.s.fog.lpData || sd->u.s.fog.VBO) {
3116         /* TODO: fog*/
3117     if (GL_SUPPORT(EXT_FOG_COORD) {
3118              glEnableClientState(GL_FOG_COORDINATE_EXT);
3119             (GL_EXTCALL)(FogCoordPointerEXT)(
3120                 WINED3D_ATR_GLTYPE(sd->u.s.fog.dwType),
3121                 sd->u.s.fog.dwStride,
3122                 sd->u.s.fog.lpData + stateblock->loadBaseVertexIndex * sd->u.s.fog.dwStride);
3123         } else {
3124             /* don't bother falling back to 'slow' as we don't support software FOG yet. */
3125             /* FIXME: fixme once */
3126             TRACE("Hardware support for FOG is not avaiable, FOG disabled.\n");
3127         }
3128     } else {
3129         if (GL_SUPPRT(EXT_FOR_COORD) {
3130              /* make sure fog is disabled */
3131              glDisableClientState(GL_FOG_COORDINATE_EXT);
3132         }
3133     }
3134 #endif
3135
3136 #if 0 /* tangents  ----------------------------------------------*/
3137     if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO ||
3138         sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3139         /* TODO: tangents*/
3140         if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3141             if (sd->u.s.tangent.lpData || sd->u.s.tangent.VBO) {
3142                 glEnable(GL_TANGENT_ARRAY_EXT);
3143                 (GL_EXTCALL)(TangentPointerEXT)(
3144                     WINED3D_ATR_GLTYPE(sd->u.s.tangent.dwType),
3145                     sd->u.s.tangent.dwStride,
3146                     sd->u.s.tangent.lpData + stateblock->loadBaseVertexIndex * sd->u.s.tangent.dwStride);
3147             } else {
3148                     glDisable(GL_TANGENT_ARRAY_EXT);
3149             }
3150             if (sd->u.s.binormal.lpData || sd->u.s.binormal.VBO) {
3151                     glEnable(GL_BINORMAL_ARRAY_EXT);
3152                     (GL_EXTCALL)(BinormalPointerEXT)(
3153                         WINED3D_ATR_GLTYPE(sd->u.s.binormal.dwType),
3154                         sd->u.s.binormal.dwStride,
3155                         sd->u.s.binormal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.binormal.dwStride);
3156             } else{
3157                     glDisable(GL_BINORMAL_ARRAY_EXT);
3158             }
3159
3160         } else {
3161             /* don't bother falling back to 'slow' as we don't support software tangents and binormals yet . */
3162             /* FIXME: fixme once */
3163             TRACE("Hardware support for tangents and binormals is not avaiable, tangents and binormals disabled.\n");
3164         }
3165     } else {
3166         if (GL_SUPPORT(EXT_COORDINATE_FRAME) {
3167              /* make sure fog is disabled */
3168              glDisable(GL_TANGENT_ARRAY_EXT);
3169              glDisable(GL_BINORMAL_ARRAY_EXT);
3170         }
3171     }
3172 #endif
3173
3174     /* Point Size ----------------------------------------------*/
3175     if (sd->u.s.pSize.lpData || sd->u.s.pSize.VBO) {
3176
3177         /* no such functionality in the fixed function GL pipeline */
3178         TRACE("Cannot change ptSize here in openGl\n");
3179         /* TODO: Implement this function in using shaders if they are available */
3180
3181     }
3182
3183     /* Vertex Pointers -----------------------------------------*/
3184     if (sd->u.s.position.lpData != NULL || sd->u.s.position.VBO != 0) {
3185         /* Note dwType == float3 or float4 == 2 or 3 */
3186         VTRACE(("glVertexPointer(%d, GL_FLOAT, %d, %p)\n",
3187                 sd->u.s.position.dwStride,
3188                 sd->u.s.position.dwType + 1,
3189                 sd->u.s.position.lpData));
3190
3191         if(curVBO != sd->u.s.position.VBO) {
3192             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.position.VBO));
3193             checkGLcall("glBindBufferARB");
3194             curVBO = sd->u.s.position.VBO;
3195         }
3196
3197         /* min(WINED3D_ATR_SIZE(position),3) to Disable RHW mode as 'w' coord
3198            handling for rhw mode should not impact screen position whereas in GL it does.
3199            This may result in very slightly distorted textures in rhw mode.
3200            There's always the other option of fixing the view matrix to
3201            prevent w from having any effect.
3202
3203            This only applies to user pointer sources, in VBOs the vertices are fixed up
3204          */
3205         if(sd->u.s.position.VBO == 0) {
3206             glVertexPointer(3 /* min(WINED3D_ATR_SIZE(sd->u.s.position.dwType),3) */,
3207                 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3208                 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3209         } else {
3210             glVertexPointer(
3211                 WINED3D_ATR_SIZE(sd->u.s.position.dwType),
3212                 WINED3D_ATR_GLTYPE(sd->u.s.position.dwType),
3213                 sd->u.s.position.dwStride, sd->u.s.position.lpData + stateblock->loadBaseVertexIndex * sd->u.s.position.dwStride + offset[sd->u.s.position.streamNo]);
3214         }
3215         checkGLcall("glVertexPointer(...)");
3216         glEnableClientState(GL_VERTEX_ARRAY);
3217         checkGLcall("glEnableClientState(GL_VERTEX_ARRAY)");
3218     }
3219
3220     /* Normals -------------------------------------------------*/
3221     if (sd->u.s.normal.lpData || sd->u.s.normal.VBO) {
3222         /* Note dwType == float3 or float4 == 2 or 3 */
3223         VTRACE(("glNormalPointer(GL_FLOAT, %d, %p)\n",
3224                 sd->u.s.normal.dwStride,
3225                 sd->u.s.normal.lpData));
3226         if(curVBO != sd->u.s.normal.VBO) {
3227             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.normal.VBO));
3228             checkGLcall("glBindBufferARB");
3229             curVBO = sd->u.s.normal.VBO;
3230         }
3231         glNormalPointer(
3232             WINED3D_ATR_GLTYPE(sd->u.s.normal.dwType),
3233             sd->u.s.normal.dwStride,
3234             sd->u.s.normal.lpData + stateblock->loadBaseVertexIndex * sd->u.s.normal.dwStride + offset[sd->u.s.normal.streamNo]);
3235         checkGLcall("glNormalPointer(...)");
3236         glEnableClientState(GL_NORMAL_ARRAY);
3237         checkGLcall("glEnableClientState(GL_NORMAL_ARRAY)");
3238
3239     } else {
3240         glNormal3f(0, 0, 0);
3241         checkGLcall("glNormal3f(0, 0, 0)");
3242     }
3243
3244     /* Diffuse Colour --------------------------------------------*/
3245     /*  WARNING: Data here MUST be in RGBA format, so cannot      */
3246     /*     go directly into fast mode from app pgm, because       */
3247     /*     directx requires data in BGRA format.                  */
3248     /* currently fixupVertices swizzles the format, but this isn't*/
3249     /* very practical when using VBOs                             */
3250     /* NOTE: Unless we write a vertex shader to swizzle the colour*/
3251     /* , or the user doesn't care and wants the speed advantage   */
3252
3253     if (sd->u.s.diffuse.lpData || sd->u.s.diffuse.VBO) {
3254         /* Note dwType == float3 or float4 == 2 or 3 */
3255         VTRACE(("glColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3256                 sd->u.s.diffuse.dwStride,
3257                 sd->u.s.diffuse.lpData));
3258
3259         if(curVBO != sd->u.s.diffuse.VBO) {
3260             GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.diffuse.VBO));
3261             checkGLcall("glBindBufferARB");
3262             curVBO = sd->u.s.diffuse.VBO;
3263         }
3264
3265         glColorPointer(WINED3D_ATR_SIZE(sd->u.s.diffuse.dwType),
3266                        WINED3D_ATR_GLTYPE(sd->u.s.diffuse.dwType),
3267                        sd->u.s.diffuse.dwStride,
3268                        sd->u.s.diffuse.lpData + stateblock->loadBaseVertexIndex * sd->u.s.diffuse.dwStride + offset[sd->u.s.diffuse.streamNo]);
3269         checkGLcall("glColorPointer(4, GL_UNSIGNED_BYTE, ...)");
3270         glEnableClientState(GL_COLOR_ARRAY);
3271         checkGLcall("glEnableClientState(GL_COLOR_ARRAY)");
3272
3273     } else {
3274         glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
3275         checkGLcall("glColor4f(1, 1, 1, 1)");
3276     }
3277
3278     /* Specular Colour ------------------------------------------*/
3279     if (sd->u.s.specular.lpData || sd->u.s.specular.VBO) {
3280         TRACE("setting specular colour\n");
3281         /* Note dwType == float3 or float4 == 2 or 3 */
3282         VTRACE(("glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, %d, %p)\n",
3283                 sd->u.s.specular.dwStride,
3284                 sd->u.s.specular.lpData));
3285         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3286             if(curVBO != sd->u.s.specular.VBO) {
3287                 GL_EXTCALL(glBindBufferARB(GL_ARRAY_BUFFER_ARB, sd->u.s.specular.VBO));
3288                 checkGLcall("glBindBufferARB");
3289                 curVBO = sd->u.s.specular.VBO;
3290             }
3291             GL_EXTCALL(glSecondaryColorPointerEXT)(WINED3D_ATR_SIZE(sd->u.s.specular.dwType),
3292                                                    WINED3D_ATR_GLTYPE(sd->u.s.specular.dwType),
3293                                                    sd->u.s.specular.dwStride,
3294                                                    sd->u.s.specular.lpData + stateblock->loadBaseVertexIndex * sd->u.s.specular.dwStride + offset[sd->u.s.specular.streamNo]);
3295             vcheckGLcall("glSecondaryColorPointerEXT(4, GL_UNSIGNED_BYTE, ...)");
3296             glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT);
3297             vcheckGLcall("glEnableClientState(GL_SECONDARY_COLOR_ARRAY_EXT)");
3298         } else {
3299
3300         /* Missing specular color is not critical, no warnings */
3301         VTRACE(("Specular colour is not supported in this GL implementation\n"));
3302         }
3303
3304     } else {
3305         if (GL_SUPPORT(EXT_SECONDARY_COLOR)) {
3306             GL_EXTCALL(glSecondaryColor3fEXT)(0, 0, 0);
3307             checkGLcall("glSecondaryColor3fEXT(0, 0, 0)");
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
3315     /* Texture coords -------------------------------------------*/
3316     loadTexCoords(stateblock, sd, &curVBO);
3317 }
3318
3319 static inline void drawPrimitiveTraceDataLocations(
3320     WineDirect3DVertexStridedData *dataLocations) {
3321
3322     /* Dump out what parts we have supplied */
3323     TRACE("Strided Data:\n");
3324     TRACE_STRIDED((dataLocations), position);
3325     TRACE_STRIDED((dataLocations), blendWeights);
3326     TRACE_STRIDED((dataLocations), blendMatrixIndices);
3327     TRACE_STRIDED((dataLocations), normal);
3328     TRACE_STRIDED((dataLocations), pSize);
3329     TRACE_STRIDED((dataLocations), diffuse);
3330     TRACE_STRIDED((dataLocations), specular);
3331     TRACE_STRIDED((dataLocations), texCoords[0]);
3332     TRACE_STRIDED((dataLocations), texCoords[1]);
3333     TRACE_STRIDED((dataLocations), texCoords[2]);
3334     TRACE_STRIDED((dataLocations), texCoords[3]);
3335     TRACE_STRIDED((dataLocations), texCoords[4]);
3336     TRACE_STRIDED((dataLocations), texCoords[5]);
3337     TRACE_STRIDED((dataLocations), texCoords[6]);
3338     TRACE_STRIDED((dataLocations), texCoords[7]);
3339     TRACE_STRIDED((dataLocations), position2);
3340     TRACE_STRIDED((dataLocations), normal2);
3341     TRACE_STRIDED((dataLocations), tangent);
3342     TRACE_STRIDED((dataLocations), binormal);
3343     TRACE_STRIDED((dataLocations), tessFactor);
3344     TRACE_STRIDED((dataLocations), fog);
3345     TRACE_STRIDED((dataLocations), depth);
3346     TRACE_STRIDED((dataLocations), sample);
3347
3348     return;
3349 }
3350
3351 static void streamsrc(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3352     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3353     BOOL fixup = FALSE;
3354     WineDirect3DVertexStridedData *dataLocations = &device->strided_streams;
3355     BOOL useVertexShaderFunction;
3356
3357     if (device->vs_selected_mode != SHADER_NONE && stateblock->vertexShader &&
3358         ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.function != NULL) {
3359         useVertexShaderFunction = TRUE;
3360     } else {
3361         useVertexShaderFunction = FALSE;
3362     }
3363
3364
3365     if(device->up_strided) {
3366         /* Note: this is a ddraw fixed-function code path */
3367         TRACE("================ Strided Input ===================\n");
3368         memcpy(dataLocations, device->up_strided, sizeof(*dataLocations));
3369
3370         if(TRACE_ON(d3d)) {
3371             drawPrimitiveTraceDataLocations(dataLocations);
3372         }
3373     } else {
3374         /* Note: This is a fixed function or shader codepath.
3375          * This means it must handle both types of strided data.
3376          * Shaders must go through here to zero the strided data, even if they
3377          * don't set any declaration at all
3378          */
3379         TRACE("================ Vertex Declaration  ===================\n");
3380         memset(dataLocations, 0, sizeof(*dataLocations));
3381         primitiveDeclarationConvertToStridedData((IWineD3DDevice *) device,
3382                 useVertexShaderFunction, dataLocations, &fixup);
3383     }
3384
3385     if (dataLocations->u.s.position_transformed) {
3386         useVertexShaderFunction = FALSE;
3387     }
3388
3389     /* Unload the old arrays before loading the new ones to get old junk out */
3390     if(context->numberedArraysLoaded) {
3391         unloadNumberedArrays(stateblock);
3392         context->numberedArraysLoaded = FALSE;
3393     }
3394     if(context->namedArraysLoaded) {
3395         unloadVertexData(stateblock);
3396         context->namedArraysLoaded = FALSE;
3397     }
3398
3399     if(useVertexShaderFunction) {
3400         if(((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->half_float_conv_needed && !fixup) {
3401             TRACE("Using drawStridedSlow with vertex shaders for FLOAT16 conversion\n");
3402             device->useDrawStridedSlow = TRUE;
3403             context->numberedArraysLoaded = FALSE;
3404         } else {
3405             TRACE("Loading numbered arrays\n");
3406             loadNumberedArrays(stateblock, dataLocations);
3407             device->useDrawStridedSlow = FALSE;
3408             context->numberedArraysLoaded = TRUE;
3409         }
3410     } else if (fixup ||
3411                (dataLocations->u.s.pSize.lpData == NULL &&
3412                 dataLocations->u.s.diffuse.lpData == NULL &&
3413                 dataLocations->u.s.specular.lpData == NULL)) {
3414         /* Load the vertex data using named arrays */
3415         TRACE("Loading vertex data\n");
3416         loadVertexData(stateblock, dataLocations);
3417         device->useDrawStridedSlow = FALSE;
3418         context->namedArraysLoaded = TRUE;
3419     } else {
3420         TRACE("Not loading vertex data\n");
3421         device->useDrawStridedSlow = TRUE;
3422     }
3423
3424 /* Generate some fixme's if unsupported functionality is being used */
3425 #define BUFFER_OR_DATA(_attribute) dataLocations->u.s._attribute.lpData
3426     /* TODO: Either support missing functionality in fixupVertices or by creating a shader to replace the pipeline. */
3427     if (!useVertexShaderFunction && (BUFFER_OR_DATA(position2) || BUFFER_OR_DATA(normal2))) {
3428         FIXME("Tweening is only valid with vertex shaders\n");
3429     }
3430     if (!useVertexShaderFunction && (BUFFER_OR_DATA(tangent) || BUFFER_OR_DATA(binormal))) {
3431         FIXME("Tangent and binormal bump mapping is only valid with vertex shaders\n");
3432     }
3433     if (!useVertexShaderFunction && (BUFFER_OR_DATA(tessFactor) || BUFFER_OR_DATA(fog) || BUFFER_OR_DATA(depth) || BUFFER_OR_DATA(sample))) {
3434         FIXME("Extended attributes are only valid with vertex shaders\n");
3435     }
3436 #undef BUFFER_OR_DATA
3437 }
3438
3439 static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3440     BOOL useVertexShaderFunction = FALSE, updateFog = FALSE;
3441     BOOL usePixelShaderFunction = stateblock->wineD3DDevice->ps_selected_mode != SHADER_NONE && stateblock->pixelShader
3442             && ((IWineD3DPixelShaderImpl *)stateblock->pixelShader)->baseShader.function;
3443     BOOL transformed;
3444     /* Some stuff is in the device until we have per context tracking */
3445     IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
3446     BOOL wasrhw = context->last_was_rhw;
3447
3448     /* Shaders can be implemented using ARB_PROGRAM, GLSL, or software -
3449      * here simply check whether a shader was set, or the user disabled shaders
3450      */
3451     if (use_vs(device)) {
3452         useVertexShaderFunction = TRUE;
3453
3454         if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
3455             updateFog = TRUE;
3456         }
3457     } else if(context->last_was_foggy_shader) {
3458         updateFog = TRUE;
3459     }
3460
3461     transformed = device->strided_streams.u.s.position_transformed;
3462     if (transformed) useVertexShaderFunction = FALSE;
3463
3464     if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
3465         updateFog = TRUE;
3466     }
3467
3468     /* Reapply lighting if it is not scheduled for reapplication already */
3469     if(!isStateDirty(context, STATE_RENDER(WINED3DRS_LIGHTING))) {
3470         state_lighting(STATE_RENDER(WINED3DRS_LIGHTING), stateblock, context);
3471     }
3472
3473     if (transformed) {
3474         context->last_was_rhw = TRUE;
3475     } else {
3476
3477         /* Untransformed, so relies on the view and projection matrices */
3478         context->last_was_rhw = FALSE;
3479         /* This turns off the Z scale trick to 'disable' viewport frustum clipping in rhw mode*/
3480         device->untransformed = TRUE;
3481
3482         /* Todo for sw shaders: Vertex Shader output is already transformed, so set up identity matrices
3483          * Not needed as long as only hw shaders are supported
3484          */
3485
3486         /* This sets the shader output position correction constants.
3487          * TODO: Move to the viewport state
3488          */
3489         if (useVertexShaderFunction) {
3490             device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0;
3491             device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height;
3492         }
3493     }
3494
3495     /* Don't have to apply the matrices when vertex shaders are used. When vshaders are turned
3496      * off this function will be called again anyway to make sure they're properly set
3497      */
3498     if(!useVertexShaderFunction) {
3499         /* TODO: Move this mainly to the viewport state and only apply when the vp has changed
3500          * or transformed / untransformed was switched
3501          */
3502        if(wasrhw != context->last_was_rhw &&
3503           !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION)) &&
3504           !isStateDirty(context, STATE_VIEWPORT)) {
3505             transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3506         }
3507         /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
3508          * mode.
3509          *
3510          * If a vertex shader is used, the world matrix changed and then vertex shader unbound
3511          * this check will fail and the matrix not applied again. This is OK because a simple
3512          * world matrix change reapplies the matrix - These checks here are only to satisfy the
3513          * needs of the vertex declaration.
3514          *
3515          * World and view matrix go into the same gl matrix, so only apply them when neither is
3516          * dirty
3517          */
3518         if(transformed != wasrhw &&
3519            !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0))) &&
3520            !isStateDirty(context, STATE_TRANSFORM(WINED3DTS_VIEW))) {
3521             transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3522         }
3523
3524         if(!isStateDirty(context, STATE_RENDER(WINED3DRS_COLORVERTEX))) {
3525             state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
3526         }
3527
3528         if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
3529             state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
3530         }
3531         if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
3532             state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
3533         }
3534     } else {
3535         /* We compile the shader here because we need the vertex declaration
3536          * in order to determine if we need to do any swizzling for D3DCOLOR
3537          * registers. If the shader is already compiled this call will do nothing. */
3538         IWineD3DVertexShader_CompileShader(stateblock->vertexShader);
3539
3540         if(!context->last_was_vshader) {
3541             int i;
3542             static BOOL warned = FALSE;
3543             /* Disable all clip planes to get defined results on all drivers. See comment in the
3544              * state_clipping state handler
3545              */
3546             for(i = 0; i < GL_LIMITS(clipplanes); i++) {
3547                 glDisable(GL_CLIP_PLANE0 + i);
3548                 checkGLcall("glDisable(GL_CLIP_PLANE0 + i)");
3549             }
3550
3551             if(!warned && stateblock->renderState[WINED3DRS_CLIPPLANEENABLE]) {
3552                 FIXME("Clipping not supported with vertex shaders\n");
3553                 warned = TRUE;
3554             }
3555             if(wasrhw) {
3556                 /* Apply the transform matrices when switching from rhw drawing to vertex shaders. Vertex
3557                  * shaders themselves do not need it, but the matrices are not reapplied automatically when
3558                  * switching back from vertex shaders to fixed function processing. So make sure we leave the
3559                  * fixed function vertex processing states back in a sane state before switching to shaders
3560                  */
3561                 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3562                     transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3563                 }
3564                 if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)))) {
3565                     transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
3566                 }
3567             }
3568         }
3569     }
3570
3571     /* Vertex and pixel shaders are applied together for now, so let the last dirty state do the
3572      * application
3573      */
3574     if (!isStateDirty(context, STATE_PIXELSHADER)) {
3575         device->shader_backend->shader_select((IWineD3DDevice *)device, usePixelShaderFunction, useVertexShaderFunction);
3576
3577         if (!isStateDirty(context, STATE_VERTEXSHADERCONSTANT) && (useVertexShaderFunction || usePixelShaderFunction)) {
3578             shaderconstant(STATE_VERTEXSHADERCONSTANT, stateblock, context);
3579         }
3580     }
3581
3582     context->last_was_vshader = useVertexShaderFunction;
3583
3584     if(updateFog) {
3585         state_fog(STATE_RENDER(WINED3DRS_FOGENABLE), stateblock, context);
3586     }
3587     if(!useVertexShaderFunction) {
3588         int i;
3589         for(i = 0; i < MAX_TEXTURES; i++) {
3590             if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i))) {
3591                 transform_texture(STATE_TRANSFORM(WINED3DTS_TEXTURE0 + i), stateblock, context);
3592             }
3593         }
3594     }
3595 }
3596
3597 static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3598     UINT width, height;
3599     IWineD3DSurfaceImpl *target;
3600
3601     glDepthRange(stateblock->viewport.MinZ, stateblock->viewport.MaxZ);
3602     checkGLcall("glDepthRange");
3603     /* Note: GL requires lower left, DirectX supplies upper left. This is reversed when using offscreen rendering
3604      */
3605     if(stateblock->wineD3DDevice->render_offscreen) {
3606         glViewport(stateblock->viewport.X,
3607                    stateblock->viewport.Y,
3608                    stateblock->viewport.Width, stateblock->viewport.Height);
3609     } else {
3610         target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3611         target->get_drawable_size(target, &width, &height);
3612
3613         glViewport(stateblock->viewport.X,
3614                    (height - (stateblock->viewport.Y + stateblock->viewport.Height)),
3615                    stateblock->viewport.Width, stateblock->viewport.Height);
3616     }
3617
3618     checkGLcall("glViewport");
3619 }
3620
3621 static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3622     stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width;
3623     stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height;
3624     if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) {
3625         transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context);
3626     }
3627     if(!isStateDirty(context, STATE_RENDER(WINED3DRS_POINTSCALEENABLE))) {
3628         state_pscale(STATE_RENDER(WINED3DRS_POINTSCALEENABLE), stateblock, context);
3629     }
3630 }
3631
3632 static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3633     UINT Index = state - STATE_ACTIVELIGHT(0);
3634     PLIGHTINFOEL *lightInfo = stateblock->activeLights[Index];
3635
3636     if(!lightInfo) {
3637         glDisable(GL_LIGHT0 + Index);
3638         checkGLcall("glDisable(GL_LIGHT0 + Index)");
3639     } else {
3640         float quad_att;
3641         float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
3642
3643         /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
3644         glMatrixMode(GL_MODELVIEW);
3645         glPushMatrix();
3646         glLoadMatrixf(&stateblock->transforms[WINED3DTS_VIEW].u.m[0][0]);
3647
3648         /* Diffuse: */
3649         colRGBA[0] = lightInfo->OriginalParms.Diffuse.r;
3650         colRGBA[1] = lightInfo->OriginalParms.Diffuse.g;
3651         colRGBA[2] = lightInfo->OriginalParms.Diffuse.b;
3652         colRGBA[3] = lightInfo->OriginalParms.Diffuse.a;
3653         glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, colRGBA);
3654         checkGLcall("glLightfv");
3655
3656         /* Specular */
3657         colRGBA[0] = lightInfo->OriginalParms.Specular.r;
3658         colRGBA[1] = lightInfo->OriginalParms.Specular.g;
3659         colRGBA[2] = lightInfo->OriginalParms.Specular.b;
3660         colRGBA[3] = lightInfo->OriginalParms.Specular.a;
3661         glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, colRGBA);
3662         checkGLcall("glLightfv");
3663
3664         /* Ambient */
3665         colRGBA[0] = lightInfo->OriginalParms.Ambient.r;
3666         colRGBA[1] = lightInfo->OriginalParms.Ambient.g;
3667         colRGBA[2] = lightInfo->OriginalParms.Ambient.b;
3668         colRGBA[3] = lightInfo->OriginalParms.Ambient.a;
3669         glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
3670         checkGLcall("glLightfv");
3671
3672         if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
3673             quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
3674         } else {
3675             quad_att = 0; /*  0 or  MAX?  (0 seems to be ok) */
3676         }
3677
3678         /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
3679          * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
3680          * Attenuation0 to NaN and crashes in the gl lib
3681          */
3682
3683         switch (lightInfo->OriginalParms.Type) {
3684             case WINED3DLIGHT_POINT:
3685                 /* Position */
3686                 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3687                 checkGLcall("glLightfv");
3688                 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3689                 checkGLcall("glLightf");
3690                 /* Attenuation - Are these right? guessing... */
3691                 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
3692                 checkGLcall("glLightf");
3693                 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
3694                 checkGLcall("glLightf");
3695                 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3696                 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3697                 checkGLcall("glLightf");
3698                 /* FIXME: Range */
3699                 break;
3700
3701             case WINED3DLIGHT_SPOT:
3702                 /* Position */
3703                 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]);
3704                 checkGLcall("glLightfv");
3705                 /* Direction */
3706                 glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->lightDirn[0]);
3707                 checkGLcall("glLightfv");
3708                 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
3709                 checkGLcall("glLightf");
3710                 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3711                 checkGLcall("glLightf");
3712                 /* Attenuation - Are these right? guessing... */
3713                 glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION,  lightInfo->OriginalParms.Attenuation0);
3714                 checkGLcall("glLightf");
3715                 glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION,    lightInfo->OriginalParms.Attenuation1);
3716                 checkGLcall("glLightf");
3717                 if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
3718                 glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
3719                 checkGLcall("glLightf");
3720                 /* FIXME: Range */
3721                 break;
3722
3723             case WINED3DLIGHT_DIRECTIONAL:
3724                 /* Direction */
3725                 glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->lightPosn[0]); /* Note gl uses w position of 0 for direction! */
3726                 checkGLcall("glLightfv");
3727                 glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
3728                 checkGLcall("glLightf");
3729                 glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
3730                 checkGLcall("glLightf");
3731                 break;
3732
3733             default:
3734                 FIXME("Unrecognized light type %d\n", lightInfo->OriginalParms.Type);
3735         }
3736
3737         /* Restore the modelview matrix */
3738         glPopMatrix();
3739
3740         glEnable(GL_LIGHT0 + Index);
3741         checkGLcall("glEnable(GL_LIGHT0 + Index)");
3742     }
3743
3744     return;
3745 }
3746
3747 static void scissorrect(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3748     RECT *pRect = &stateblock->scissorRect;
3749     UINT height;
3750     UINT width;
3751     IWineD3DSurfaceImpl *target = (IWineD3DSurfaceImpl *) stateblock->wineD3DDevice->render_targets[0];
3752
3753     target->get_drawable_size(target, &width, &height);
3754     /* Warning: glScissor uses window coordinates, not viewport coordinates, so our viewport correction does not apply
3755      * Warning2: Even in windowed mode the coords are relative to the window, not the screen
3756      */
3757     TRACE("(%p) Setting new Scissor Rect to %d:%d-%d:%d\n", stateblock->wineD3DDevice, pRect->left, pRect->bottom - height,
3758           pRect->right - pRect->left, pRect->bottom - pRect->top);
3759
3760     if (stateblock->wineD3DDevice->render_offscreen) {
3761         glScissor(pRect->left, pRect->top, pRect->right - pRect->left, pRect->bottom - pRect->top);
3762     } else {
3763         glScissor(pRect->left, height - pRect->bottom, pRect->right - pRect->left, pRect->bottom - pRect->top);
3764     }
3765     checkGLcall("glScissor");
3766 }
3767
3768 static void indexbuffer(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3769     if(GL_SUPPORT(ARB_VERTEX_BUFFER_OBJECT)) {
3770         if(stateblock->streamIsUP || stateblock->pIndexData == NULL ) {
3771             GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0));
3772         } else {
3773             IWineD3DIndexBufferImpl *ib = (IWineD3DIndexBufferImpl *) stateblock->pIndexData;
3774             GL_EXTCALL(glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, ib->vbo));
3775         }
3776     }
3777 }
3778
3779 static void frontface(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
3780     if(stateblock->wineD3DDevice->render_offscreen) {
3781         glFrontFace(GL_CCW);
3782         checkGLcall("glFrontFace(GL_CCW)");
3783     } else {
3784         glFrontFace(GL_CW);
3785         checkGLcall("glFrontFace(GL_CW)");
3786     }
3787 }
3788
3789 const struct StateEntryTemplate misc_state_template[] = {
3790     { STATE_RENDER(WINED3DRS_SRCBLEND),                   { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
3791     { STATE_RENDER(WINED3DRS_DESTBLEND),                  { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
3792     { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
3793     { STATE_RENDER(WINED3DRS_EDGEANTIALIAS),              { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
3794     { STATE_RENDER(WINED3DRS_ANTIALIASEDLINEENABLE),      { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
3795     { STATE_RENDER(WINED3DRS_SEPARATEALPHABLENDENABLE),   { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
3796     { STATE_RENDER(WINED3DRS_SRCBLENDALPHA),              { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
3797     { STATE_RENDER(WINED3DRS_DESTBLENDALPHA),             { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
3798     { STATE_RENDER(WINED3DRS_DESTBLENDALPHA),             { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
3799     { STATE_RENDER(WINED3DRS_BLENDOPALPHA),               { STATE_RENDER(WINED3DRS_ALPHABLENDENABLE),           state_blend         }, 0                               },
3800     { STATE_STREAMSRC,                                    { STATE_VDECL,                                        streamsrc           }, 0                               },
3801     { STATE_VDECL,                                        { STATE_VDECL,                                        streamsrc           }, 0                               },
3802     { STATE_FRONTFACE,                                    { STATE_FRONTFACE,                                    frontface           }, 0                               },
3803     { STATE_SCISSORRECT,                                  { STATE_SCISSORRECT,                                  scissorrect         }, 0                               },
3804     /* TODO: Move shader constant loading to vertex and fragment pipeline repectively, as soon as the pshader and
3805      * vshader loadings are untied from each other
3806      */
3807     { STATE_VERTEXSHADERCONSTANT,                         { STATE_VERTEXSHADERCONSTANT,                         shaderconstant      }, 0                               },
3808     { STATE_PIXELSHADERCONSTANT,                          { STATE_VERTEXSHADERCONSTANT,                         shaderconstant      }, 0                               },
3809     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3810     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3811     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3812     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3813     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3814     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3815     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3816     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3817     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3818     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3819     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3820     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3821     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3822     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3823     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3824     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3825     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3826     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3827     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3828     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3829     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3830     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3831     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3832     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3833     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3834     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3835     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3836     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3837     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3838     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3839     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3840     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     shader_bumpenvmat   }, 0                               },
3841     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
3842     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVLOFFSET),   tex_bumpenvloffset  }, 0                               },
3843     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
3844     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVLOFFSET),   tex_bumpenvloffset  }, 0                               },
3845     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
3846     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVLOFFSET),   tex_bumpenvloffset  }, 0                               },
3847     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
3848     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVLOFFSET),   tex_bumpenvloffset  }, 0                               },
3849     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
3850     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVLOFFSET),   tex_bumpenvloffset  }, 0                               },
3851     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
3852     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVLOFFSET),   tex_bumpenvloffset  }, 0                               },
3853     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
3854     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVLOFFSET),   tex_bumpenvloffset  }, 0                               },
3855     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE),    { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLSCALE),    tex_bumpenvlscale   }, 0                               },
3856     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET),   { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVLOFFSET),   tex_bumpenvloffset  }, 0                               },
3857
3858     { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_miscpart   }, 0                               },
3859     { STATE_INDEXBUFFER,                                  { STATE_INDEXBUFFER,                                  indexbuffer         }, 0                               },
3860     { STATE_RENDER(WINED3DRS_ANTIALIAS),                  { STATE_RENDER(WINED3DRS_ANTIALIAS),                  state_antialias     }, 0                               },
3861     { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE),         { STATE_RENDER(WINED3DRS_TEXTUREPERSPECTIVE),         state_perspective   }, 0                               },
3862     { STATE_RENDER(WINED3DRS_ZENABLE),                    { STATE_RENDER(WINED3DRS_ZENABLE),                    state_zenable       }, 0                               },
3863     { STATE_RENDER(WINED3DRS_WRAPU),                      { STATE_RENDER(WINED3DRS_WRAPU),                      state_wrapu         }, 0                               },
3864     { STATE_RENDER(WINED3DRS_WRAPV),                      { STATE_RENDER(WINED3DRS_WRAPV),                      state_wrapv         }, 0                               },
3865     { STATE_RENDER(WINED3DRS_FILLMODE),                   { STATE_RENDER(WINED3DRS_FILLMODE),                   state_fillmode      }, 0                               },
3866     { STATE_RENDER(WINED3DRS_SHADEMODE),                  { STATE_RENDER(WINED3DRS_SHADEMODE),                  state_shademode     }, 0                               },
3867     { STATE_RENDER(WINED3DRS_LINEPATTERN),                { STATE_RENDER(WINED3DRS_LINEPATTERN),                state_linepattern   }, 0                               },
3868     { STATE_RENDER(WINED3DRS_MONOENABLE),                 { STATE_RENDER(WINED3DRS_MONOENABLE),                 state_monoenable    }, 0                               },
3869     { STATE_RENDER(WINED3DRS_ROP2),                       { STATE_RENDER(WINED3DRS_ROP2),                       state_rop2          }, 0                               },
3870     { STATE_RENDER(WINED3DRS_PLANEMASK),                  { STATE_RENDER(WINED3DRS_PLANEMASK),                  state_planemask     }, 0                               },
3871     { STATE_RENDER(WINED3DRS_ZWRITEENABLE),               { STATE_RENDER(WINED3DRS_ZWRITEENABLE),               state_zwritenable   }, 0                               },
3872     { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
3873     { STATE_RENDER(WINED3DRS_ALPHAREF),                   { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
3874     { STATE_RENDER(WINED3DRS_ALPHAFUNC),                  { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
3875     { STATE_RENDER(WINED3DRS_COLORKEYENABLE),             { STATE_RENDER(WINED3DRS_ALPHATESTENABLE),            state_alpha         }, 0                               },
3876     { STATE_RENDER(WINED3DRS_LASTPIXEL),                  { STATE_RENDER(WINED3DRS_LASTPIXEL),                  state_lastpixel     }, 0                               },
3877     { STATE_RENDER(WINED3DRS_CULLMODE),                   { STATE_RENDER(WINED3DRS_CULLMODE),                   state_cullmode      }, 0                               },
3878     { STATE_RENDER(WINED3DRS_ZFUNC),                      { STATE_RENDER(WINED3DRS_ZFUNC),                      state_zfunc         }, 0                               },
3879     { STATE_RENDER(WINED3DRS_DITHERENABLE),               { STATE_RENDER(WINED3DRS_DITHERENABLE),               state_ditherenable  }, 0                               },
3880     { STATE_RENDER(WINED3DRS_SUBPIXEL),                   { STATE_RENDER(WINED3DRS_SUBPIXEL),                   state_subpixel      }, 0                               },
3881     { STATE_RENDER(WINED3DRS_SUBPIXELX),                  { STATE_RENDER(WINED3DRS_SUBPIXELX),                  state_subpixelx     }, 0                               },
3882     { STATE_RENDER(WINED3DRS_STIPPLEDALPHA),              { STATE_RENDER(WINED3DRS_STIPPLEDALPHA),              state_stippledalpha }, 0                               },
3883     { STATE_RENDER(WINED3DRS_ZBIAS),                      { STATE_RENDER(WINED3DRS_ZBIAS),                      state_zbias         }, 0                               },
3884     { STATE_RENDER(WINED3DRS_STIPPLEENABLE),              { STATE_RENDER(WINED3DRS_STIPPLEENABLE),              state_stippleenable }, 0                               },
3885     { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS),              { STATE_RENDER(WINED3DRS_MIPMAPLODBIAS),              state_mipmaplodbias }, 0                               },
3886     { STATE_RENDER(WINED3DRS_ANISOTROPY),                 { STATE_RENDER(WINED3DRS_ANISOTROPY),                 state_anisotropy    }, 0                               },
3887     { STATE_RENDER(WINED3DRS_FLUSHBATCH),                 { STATE_RENDER(WINED3DRS_FLUSHBATCH),                 state_flushbatch    }, 0                               },
3888     { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), { STATE_RENDER(WINED3DRS_TRANSLUCENTSORTINDEPENDENT), state_translucentsi }, 0                               },
3889     { STATE_RENDER(WINED3DRS_STENCILENABLE),              { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3890     { STATE_RENDER(WINED3DRS_STENCILFAIL),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3891     { STATE_RENDER(WINED3DRS_STENCILZFAIL),               { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3892     { STATE_RENDER(WINED3DRS_STENCILPASS),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3893     { STATE_RENDER(WINED3DRS_STENCILFUNC),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3894     { STATE_RENDER(WINED3DRS_STENCILREF),                 { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3895     { STATE_RENDER(WINED3DRS_STENCILMASK),                { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3896     { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           state_stencilwrite2s}, EXT_STENCIL_TWO_SIDE            },
3897     { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           { STATE_RENDER(WINED3DRS_STENCILWRITEMASK),           state_stencilwrite  }, 0                               },
3898     { STATE_RENDER(WINED3DRS_TWOSIDEDSTENCILMODE),        { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3899     { STATE_RENDER(WINED3DRS_CCW_STENCILFAIL),            { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3900     { STATE_RENDER(WINED3DRS_CCW_STENCILZFAIL),           { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3901     { STATE_RENDER(WINED3DRS_CCW_STENCILPASS),            { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3902     { STATE_RENDER(WINED3DRS_CCW_STENCILFUNC),            { STATE_RENDER(WINED3DRS_STENCILENABLE),              state_stencil       }, 0                               },
3903     { STATE_RENDER(WINED3DRS_WRAP0),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3904     { STATE_RENDER(WINED3DRS_WRAP1),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3905     { STATE_RENDER(WINED3DRS_WRAP2),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3906     { STATE_RENDER(WINED3DRS_WRAP3),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3907     { STATE_RENDER(WINED3DRS_WRAP4),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3908     { STATE_RENDER(WINED3DRS_WRAP5),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3909     { STATE_RENDER(WINED3DRS_WRAP6),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3910     { STATE_RENDER(WINED3DRS_WRAP7),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3911     { STATE_RENDER(WINED3DRS_WRAP8),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3912     { STATE_RENDER(WINED3DRS_WRAP9),                      { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3913     { STATE_RENDER(WINED3DRS_WRAP10),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3914     { STATE_RENDER(WINED3DRS_WRAP11),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3915     { STATE_RENDER(WINED3DRS_WRAP12),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3916     { STATE_RENDER(WINED3DRS_WRAP13),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3917     { STATE_RENDER(WINED3DRS_WRAP14),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3918     { STATE_RENDER(WINED3DRS_WRAP15),                     { STATE_RENDER(WINED3DRS_WRAP0),                      state_wrap          }, 0                               },
3919     { STATE_RENDER(WINED3DRS_EXTENTS),                    { STATE_RENDER(WINED3DRS_EXTENTS),                    state_extents       }, 0                               },
3920     { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE),        { STATE_RENDER(WINED3DRS_COLORKEYBLENDENABLE),        state_ckeyblend     }, 0                               },
3921     { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE),             { STATE_RENDER(WINED3DRS_PATCHEDGESTYLE),             state_patchedgestyle}, 0                               },
3922     { STATE_RENDER(WINED3DRS_PATCHSEGMENTS),              { STATE_RENDER(WINED3DRS_PATCHSEGMENTS),              state_patchsegments }, 0                               },
3923     { STATE_RENDER(WINED3DRS_POSITIONDEGREE),             { STATE_RENDER(WINED3DRS_POSITIONDEGREE),             state_positiondegree}, 0                               },
3924     { STATE_RENDER(WINED3DRS_NORMALDEGREE),               { STATE_RENDER(WINED3DRS_NORMALDEGREE),               state_normaldegree  }, 0                               },
3925     { STATE_RENDER(WINED3DRS_MINTESSELLATIONLEVEL),       { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
3926     { STATE_RENDER(WINED3DRS_MAXTESSELLATIONLEVEL),       { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
3927     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_X),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
3928     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Y),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
3929     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_Z),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
3930     { STATE_RENDER(WINED3DRS_ADAPTIVETESS_W),             { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
3931     { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), { STATE_RENDER(WINED3DRS_ENABLEADAPTIVETESSELLATION), state_tessellation  }, 0                               },
3932     { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       state_msaa          }, ARB_MULTISAMPLE                 },
3933     { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       { STATE_RENDER(WINED3DRS_MULTISAMPLEANTIALIAS),       state_msaa_w        }, 0                               },
3934     { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK),            { STATE_RENDER(WINED3DRS_MULTISAMPLEMASK),            state_multisampmask }, 0                               },
3935     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
3936     { STATE_RENDER(WINED3DRS_BLENDOP),                    { STATE_RENDER(WINED3DRS_BLENDOP),                    state_blendop       }, EXT_BLEND_MINMAX                },
3937     { STATE_RENDER(WINED3DRS_BLENDOP),                    { STATE_RENDER(WINED3DRS_BLENDOP),                    state_blendop_w     }, 0                               },
3938     { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE),          { STATE_RENDER(WINED3DRS_SCISSORTESTENABLE),          state_scissor       }, 0                               },
3939     { STATE_RENDER(WINED3DRS_SLOPESCALEDEPTHBIAS),        { STATE_RENDER(WINED3DRS_DEPTHBIAS),                  state_depthbias     }, 0                               },
3940     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE1),          { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
3941     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE2),          { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
3942     { STATE_RENDER(WINED3DRS_COLORWRITEENABLE3),          { STATE_RENDER(WINED3DRS_COLORWRITEENABLE),           state_colorwrite    }, 0                               },
3943     { STATE_RENDER(WINED3DRS_BLENDFACTOR),                { STATE_RENDER(WINED3DRS_BLENDFACTOR),                state_blendfactor   }, EXT_BLEND_COLOR                 },
3944     { STATE_RENDER(WINED3DRS_BLENDFACTOR),                { STATE_RENDER(WINED3DRS_BLENDFACTOR),                state_blendfactor_w }, 0                               },
3945     { STATE_RENDER(WINED3DRS_DEPTHBIAS),                  { STATE_RENDER(WINED3DRS_DEPTHBIAS),                  state_depthbias     }, 0                               },
3946     /* Samplers */
3947     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler             }, 0                               },
3948     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler             }, 0                               },
3949     { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler             }, 0                               },
3950     { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler             }, 0                               },
3951     { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler             }, 0                               },
3952     { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler             }, 0                               },
3953     { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler             }, 0                               },
3954     { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler             }, 0                               },
3955     { STATE_SAMPLER(8),                                   { STATE_SAMPLER(8),                                   sampler             }, 0                               },
3956     { STATE_SAMPLER(9),                                   { STATE_SAMPLER(9),                                   sampler             }, 0                               },
3957     { STATE_SAMPLER(10),                                  { STATE_SAMPLER(10),                                  sampler             }, 0                               },
3958     { STATE_SAMPLER(11),                                  { STATE_SAMPLER(11),                                  sampler             }, 0                               },
3959     { STATE_SAMPLER(12),                                  { STATE_SAMPLER(12),                                  sampler             }, 0                               },
3960     { STATE_SAMPLER(13),                                  { STATE_SAMPLER(13),                                  sampler             }, 0                               },
3961     { STATE_SAMPLER(14),                                  { STATE_SAMPLER(14),                                  sampler             }, 0                               },
3962     { STATE_SAMPLER(15),                                  { STATE_SAMPLER(15),                                  sampler             }, 0                               },
3963     { STATE_SAMPLER(16), /* Vertex sampler 0 */           { STATE_SAMPLER(16),                                  sampler             }, 0                               },
3964     { STATE_SAMPLER(17), /* Vertex sampler 1 */           { STATE_SAMPLER(17),                                  sampler             }, 0                               },
3965     { STATE_SAMPLER(18), /* Vertex sampler 2 */           { STATE_SAMPLER(18),                                  sampler             }, 0                               },
3966     { STATE_SAMPLER(19), /* Vertex sampler 3 */           { STATE_SAMPLER(19),                                  sampler             }, 0                               },
3967     {0 /* Terminate */,                                   { 0,                                                  0                   }, 0                               },
3968 };
3969
3970 const struct StateEntryTemplate ffp_vertexstate_template[] = {
3971     { STATE_VDECL,                                        { STATE_VDECL,                                        vertexdeclaration   }, 0                               },
3972     { STATE_VSHADER,                                      { STATE_VDECL,                                        vertexdeclaration   }, 0                               },
3973     { STATE_MATERIAL,                                     { STATE_RENDER(WINED3DRS_SPECULARENABLE),             state_specularenable}, 0                               },
3974     { STATE_RENDER(WINED3DRS_SPECULARENABLE),             { STATE_RENDER(WINED3DRS_SPECULARENABLE),             state_specularenable}, 0                               },
3975       /* Clip planes */
3976     { STATE_CLIPPLANE(0),                                 { STATE_CLIPPLANE(0),                                 clipplane           }, 0                               },
3977     { STATE_CLIPPLANE(1),                                 { STATE_CLIPPLANE(1),                                 clipplane           }, 0                               },
3978     { STATE_CLIPPLANE(2),                                 { STATE_CLIPPLANE(2),                                 clipplane           }, 0                               },
3979     { STATE_CLIPPLANE(3),                                 { STATE_CLIPPLANE(3),                                 clipplane           }, 0                               },
3980     { STATE_CLIPPLANE(4),                                 { STATE_CLIPPLANE(4),                                 clipplane           }, 0                               },
3981     { STATE_CLIPPLANE(5),                                 { STATE_CLIPPLANE(5),                                 clipplane           }, 0                               },
3982     { STATE_CLIPPLANE(6),                                 { STATE_CLIPPLANE(6),                                 clipplane           }, 0                               },
3983     { STATE_CLIPPLANE(7),                                 { STATE_CLIPPLANE(7),                                 clipplane           }, 0                               },
3984     { STATE_CLIPPLANE(8),                                 { STATE_CLIPPLANE(8),                                 clipplane           }, 0                               },
3985     { STATE_CLIPPLANE(9),                                 { STATE_CLIPPLANE(9),                                 clipplane           }, 0                               },
3986     { STATE_CLIPPLANE(10),                                { STATE_CLIPPLANE(10),                                clipplane           }, 0                               },
3987     { STATE_CLIPPLANE(11),                                { STATE_CLIPPLANE(11),                                clipplane           }, 0                               },
3988     { STATE_CLIPPLANE(12),                                { STATE_CLIPPLANE(12),                                clipplane           }, 0                               },
3989     { STATE_CLIPPLANE(13),                                { STATE_CLIPPLANE(13),                                clipplane           }, 0                               },
3990     { STATE_CLIPPLANE(14),                                { STATE_CLIPPLANE(14),                                clipplane           }, 0                               },
3991     { STATE_CLIPPLANE(15),                                { STATE_CLIPPLANE(15),                                clipplane           }, 0                               },
3992     { STATE_CLIPPLANE(16),                                { STATE_CLIPPLANE(16),                                clipplane           }, 0                               },
3993     { STATE_CLIPPLANE(17),                                { STATE_CLIPPLANE(17),                                clipplane           }, 0                               },
3994     { STATE_CLIPPLANE(18),                                { STATE_CLIPPLANE(18),                                clipplane           }, 0                               },
3995     { STATE_CLIPPLANE(19),                                { STATE_CLIPPLANE(19),                                clipplane           }, 0                               },
3996     { STATE_CLIPPLANE(20),                                { STATE_CLIPPLANE(20),                                clipplane           }, 0                               },
3997     { STATE_CLIPPLANE(21),                                { STATE_CLIPPLANE(21),                                clipplane           }, 0                               },
3998     { STATE_CLIPPLANE(22),                                { STATE_CLIPPLANE(22),                                clipplane           }, 0                               },
3999     { STATE_CLIPPLANE(23),                                { STATE_CLIPPLANE(23),                                clipplane           }, 0                               },
4000     { STATE_CLIPPLANE(24),                                { STATE_CLIPPLANE(24),                                clipplane           }, 0                               },
4001     { STATE_CLIPPLANE(25),                                { STATE_CLIPPLANE(25),                                clipplane           }, 0                               },
4002     { STATE_CLIPPLANE(26),                                { STATE_CLIPPLANE(26),                                clipplane           }, 0                               },
4003     { STATE_CLIPPLANE(27),                                { STATE_CLIPPLANE(27),                                clipplane           }, 0                               },
4004     { STATE_CLIPPLANE(28),                                { STATE_CLIPPLANE(28),                                clipplane           }, 0                               },
4005     { STATE_CLIPPLANE(29),                                { STATE_CLIPPLANE(29),                                clipplane           }, 0                               },
4006     { STATE_CLIPPLANE(30),                                { STATE_CLIPPLANE(30),                                clipplane           }, 0                               },
4007     { STATE_CLIPPLANE(31),                                { STATE_CLIPPLANE(31),                                clipplane           }, 0                               },
4008       /* Lights */
4009     { STATE_ACTIVELIGHT(0),                               { STATE_ACTIVELIGHT(0),                               light               }, 0                               },
4010     { STATE_ACTIVELIGHT(1),                               { STATE_ACTIVELIGHT(1),                               light               }, 0                               },
4011     { STATE_ACTIVELIGHT(2),                               { STATE_ACTIVELIGHT(2),                               light               }, 0                               },
4012     { STATE_ACTIVELIGHT(3),                               { STATE_ACTIVELIGHT(3),                               light               }, 0                               },
4013     { STATE_ACTIVELIGHT(4),                               { STATE_ACTIVELIGHT(4),                               light               }, 0                               },
4014     { STATE_ACTIVELIGHT(5),                               { STATE_ACTIVELIGHT(5),                               light               }, 0                               },
4015     { STATE_ACTIVELIGHT(6),                               { STATE_ACTIVELIGHT(6),                               light               }, 0                               },
4016     { STATE_ACTIVELIGHT(7),                               { STATE_ACTIVELIGHT(7),                               light               }, 0                               },
4017     /* Viewport */
4018     { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_vertexpart }, 0                               },
4019       /* Transform states follow                    */
4020     { STATE_TRANSFORM(WINED3DTS_VIEW),                    { STATE_TRANSFORM(WINED3DTS_VIEW),                    transform_view      }, 0                               },
4021     { STATE_TRANSFORM(WINED3DTS_PROJECTION),              { STATE_TRANSFORM(WINED3DTS_PROJECTION),              transform_projection}, 0                               },
4022     { STATE_TRANSFORM(WINED3DTS_TEXTURE0),                { STATE_TRANSFORM(WINED3DTS_TEXTURE0),                transform_texture   }, 0                               },
4023     { STATE_TRANSFORM(WINED3DTS_TEXTURE1),                { STATE_TRANSFORM(WINED3DTS_TEXTURE1),                transform_texture   }, 0                               },
4024     { STATE_TRANSFORM(WINED3DTS_TEXTURE2),                { STATE_TRANSFORM(WINED3DTS_TEXTURE2),                transform_texture   }, 0                               },
4025     { STATE_TRANSFORM(WINED3DTS_TEXTURE3),                { STATE_TRANSFORM(WINED3DTS_TEXTURE3),                transform_texture   }, 0                               },
4026     { STATE_TRANSFORM(WINED3DTS_TEXTURE4),                { STATE_TRANSFORM(WINED3DTS_TEXTURE4),                transform_texture   }, 0                               },
4027     { STATE_TRANSFORM(WINED3DTS_TEXTURE5),                { STATE_TRANSFORM(WINED3DTS_TEXTURE5),                transform_texture   }, 0                               },
4028     { STATE_TRANSFORM(WINED3DTS_TEXTURE6),                { STATE_TRANSFORM(WINED3DTS_TEXTURE6),                transform_texture   }, 0                               },
4029     { STATE_TRANSFORM(WINED3DTS_TEXTURE7),                { STATE_TRANSFORM(WINED3DTS_TEXTURE7),                transform_texture   }, 0                               },
4030     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  0)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  0)),        transform_world     }, 0                               },
4031     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  1)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  1)),        transform_world     }, 0                               },
4032     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  2)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  2)),        transform_world     }, 0                               },
4033     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  3)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  3)),        transform_world     }, 0                               },
4034     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  4)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  4)),        transform_world     }, 0                               },
4035     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  5)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  5)),        transform_world     }, 0                               },
4036     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  6)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  6)),        transform_world     }, 0                               },
4037     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  7)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  7)),        transform_world     }, 0                               },
4038     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  8)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  8)),        transform_world     }, 0                               },
4039     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  9)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(  9)),        transform_world     }, 0                               },
4040     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 10)),        transform_world     }, 0                               },
4041     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 11)),        transform_world     }, 0                               },
4042     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 12)),        transform_world     }, 0                               },
4043     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 13)),        transform_world     }, 0                               },
4044     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 14)),        transform_world     }, 0                               },
4045     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 15)),        transform_world     }, 0                               },
4046     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 16)),        transform_world     }, 0                               },
4047     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 17)),        transform_world     }, 0                               },
4048     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 18)),        transform_world     }, 0                               },
4049     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 19)),        transform_world     }, 0                               },
4050     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 20)),        transform_world     }, 0                               },
4051     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 21)),        transform_world     }, 0                               },
4052     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 22)),        transform_world     }, 0                               },
4053     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 23)),        transform_world     }, 0                               },
4054     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 24)),        transform_world     }, 0                               },
4055     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 25)),        transform_world     }, 0                               },
4056     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 26)),        transform_world     }, 0                               },
4057     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 27)),        transform_world     }, 0                               },
4058     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 28)),        transform_world     }, 0                               },
4059     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 29)),        transform_world     }, 0                               },
4060     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 30)),        transform_world     }, 0                               },
4061     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 31)),        transform_world     }, 0                               },
4062     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 32)),        transform_world     }, 0                               },
4063     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 33)),        transform_world     }, 0                               },
4064     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 34)),        transform_world     }, 0                               },
4065     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 35)),        transform_world     }, 0                               },
4066     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 36)),        transform_world     }, 0                               },
4067     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 37)),        transform_world     }, 0                               },
4068     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 38)),        transform_world     }, 0                               },
4069     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 39)),        transform_world     }, 0                               },
4070     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 40)),        transform_world     }, 0                               },
4071     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 41)),        transform_world     }, 0                               },
4072     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 42)),        transform_world     }, 0                               },
4073     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 43)),        transform_world     }, 0                               },
4074     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 44)),        transform_world     }, 0                               },
4075     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 45)),        transform_world     }, 0                               },
4076     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 46)),        transform_world     }, 0                               },
4077     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 47)),        transform_world     }, 0                               },
4078     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 48)),        transform_world     }, 0                               },
4079     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 49)),        transform_world     }, 0                               },
4080     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 50)),        transform_world     }, 0                               },
4081     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 51)),        transform_world     }, 0                               },
4082     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 52)),        transform_world     }, 0                               },
4083     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 53)),        transform_world     }, 0                               },
4084     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 54)),        transform_world     }, 0                               },
4085     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 55)),        transform_world     }, 0                               },
4086     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 56)),        transform_world     }, 0                               },
4087     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 57)),        transform_world     }, 0                               },
4088     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 58)),        transform_world     }, 0                               },
4089     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 59)),        transform_world     }, 0                               },
4090     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 60)),        transform_world     }, 0                               },
4091     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 61)),        transform_world     }, 0                               },
4092     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 62)),        transform_world     }, 0                               },
4093     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 63)),        transform_world     }, 0                               },
4094     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 64)),        transform_world     }, 0                               },
4095     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 65)),        transform_world     }, 0                               },
4096     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 66)),        transform_world     }, 0                               },
4097     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 67)),        transform_world     }, 0                               },
4098     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 68)),        transform_world     }, 0                               },
4099     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 69)),        transform_world     }, 0                               },
4100     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 70)),        transform_world     }, 0                               },
4101     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 71)),        transform_world     }, 0                               },
4102     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 72)),        transform_world     }, 0                               },
4103     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 73)),        transform_world     }, 0                               },
4104     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 74)),        transform_world     }, 0                               },
4105     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 75)),        transform_world     }, 0                               },
4106     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 76)),        transform_world     }, 0                               },
4107     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 77)),        transform_world     }, 0                               },
4108     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 78)),        transform_world     }, 0                               },
4109     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 79)),        transform_world     }, 0                               },
4110     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 80)),        transform_world     }, 0                               },
4111     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 81)),        transform_world     }, 0                               },
4112     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 82)),        transform_world     }, 0                               },
4113     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 83)),        transform_world     }, 0                               },
4114     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 84)),        transform_world     }, 0                               },
4115     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 85)),        transform_world     }, 0                               },
4116     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 86)),        transform_world     }, 0                               },
4117     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 87)),        transform_world     }, 0                               },
4118     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 88)),        transform_world     }, 0                               },
4119     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 89)),        transform_world     }, 0                               },
4120     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 90)),        transform_world     }, 0                               },
4121     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 91)),        transform_world     }, 0                               },
4122     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 92)),        transform_world     }, 0                               },
4123     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 93)),        transform_world     }, 0                               },
4124     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 94)),        transform_world     }, 0                               },
4125     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 95)),        transform_world     }, 0                               },
4126     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 96)),        transform_world     }, 0                               },
4127     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 97)),        transform_world     }, 0                               },
4128     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 98)),        transform_world     }, 0                               },
4129     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX( 99)),        transform_world     }, 0                               },
4130     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(100)),        transform_world     }, 0                               },
4131     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(101)),        transform_world     }, 0                               },
4132     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(102)),        transform_world     }, 0                               },
4133     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(103)),        transform_world     }, 0                               },
4134     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(104)),        transform_world     }, 0                               },
4135     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(105)),        transform_world     }, 0                               },
4136     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(106)),        transform_world     }, 0                               },
4137     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(107)),        transform_world     }, 0                               },
4138     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(108)),        transform_world     }, 0                               },
4139     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(109)),        transform_world     }, 0                               },
4140     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(110)),        transform_world     }, 0                               },
4141     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(111)),        transform_world     }, 0                               },
4142     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(112)),        transform_world     }, 0                               },
4143     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(113)),        transform_world     }, 0                               },
4144     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(114)),        transform_world     }, 0                               },
4145     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(115)),        transform_world     }, 0                               },
4146     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(116)),        transform_world     }, 0                               },
4147     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(117)),        transform_world     }, 0                               },
4148     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(118)),        transform_world     }, 0                               },
4149     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(119)),        transform_world     }, 0                               },
4150     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(120)),        transform_world     }, 0                               },
4151     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(121)),        transform_world     }, 0                               },
4152     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(122)),        transform_world     }, 0                               },
4153     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(123)),        transform_world     }, 0                               },
4154     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(124)),        transform_world     }, 0                               },
4155     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(125)),        transform_world     }, 0                               },
4156     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(126)),        transform_world     }, 0                               },
4157     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(127)),        transform_world     }, 0                               },
4158     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(128)),        transform_world     }, 0                               },
4159     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(129)),        transform_world     }, 0                               },
4160     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(130)),        transform_world     }, 0                               },
4161     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(131)),        transform_world     }, 0                               },
4162     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(132)),        transform_world     }, 0                               },
4163     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(133)),        transform_world     }, 0                               },
4164     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(134)),        transform_world     }, 0                               },
4165     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(135)),        transform_world     }, 0                               },
4166     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(136)),        transform_world     }, 0                               },
4167     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(137)),        transform_world     }, 0                               },
4168     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(138)),        transform_world     }, 0                               },
4169     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(139)),        transform_world     }, 0                               },
4170     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(140)),        transform_world     }, 0                               },
4171     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(141)),        transform_world     }, 0                               },
4172     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(142)),        transform_world     }, 0                               },
4173     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(143)),        transform_world     }, 0                               },
4174     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(144)),        transform_world     }, 0                               },
4175     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(145)),        transform_world     }, 0                               },
4176     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(146)),        transform_world     }, 0                               },
4177     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(147)),        transform_world     }, 0                               },
4178     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(148)),        transform_world     }, 0                               },
4179     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(149)),        transform_world     }, 0                               },
4180     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(150)),        transform_world     }, 0                               },
4181     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(151)),        transform_world     }, 0                               },
4182     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(152)),        transform_world     }, 0                               },
4183     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(153)),        transform_world     }, 0                               },
4184     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(154)),        transform_world     }, 0                               },
4185     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(155)),        transform_world     }, 0                               },
4186     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(156)),        transform_world     }, 0                               },
4187     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(157)),        transform_world     }, 0                               },
4188     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(158)),        transform_world     }, 0                               },
4189     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(159)),        transform_world     }, 0                               },
4190     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(160)),        transform_world     }, 0                               },
4191     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(161)),        transform_world     }, 0                               },
4192     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(162)),        transform_world     }, 0                               },
4193     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(163)),        transform_world     }, 0                               },
4194     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(164)),        transform_world     }, 0                               },
4195     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(165)),        transform_world     }, 0                               },
4196     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(166)),        transform_world     }, 0                               },
4197     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(167)),        transform_world     }, 0                               },
4198     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(168)),        transform_world     }, 0                               },
4199     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(169)),        transform_world     }, 0                               },
4200     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(170)),        transform_world     }, 0                               },
4201     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(171)),        transform_world     }, 0                               },
4202     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(172)),        transform_world     }, 0                               },
4203     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(173)),        transform_world     }, 0                               },
4204     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(174)),        transform_world     }, 0                               },
4205     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(175)),        transform_world     }, 0                               },
4206     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(176)),        transform_world     }, 0                               },
4207     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(177)),        transform_world     }, 0                               },
4208     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(178)),        transform_world     }, 0                               },
4209     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(179)),        transform_world     }, 0                               },
4210     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(180)),        transform_world     }, 0                               },
4211     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(181)),        transform_world     }, 0                               },
4212     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(182)),        transform_world     }, 0                               },
4213     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(183)),        transform_world     }, 0                               },
4214     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(184)),        transform_world     }, 0                               },
4215     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(185)),        transform_world     }, 0                               },
4216     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(186)),        transform_world     }, 0                               },
4217     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(187)),        transform_world     }, 0                               },
4218     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(188)),        transform_world     }, 0                               },
4219     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(189)),        transform_world     }, 0                               },
4220     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(190)),        transform_world     }, 0                               },
4221     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(191)),        transform_world     }, 0                               },
4222     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(192)),        transform_world     }, 0                               },
4223     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(193)),        transform_world     }, 0                               },
4224     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(194)),        transform_world     }, 0                               },
4225     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(195)),        transform_world     }, 0                               },
4226     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(196)),        transform_world     }, 0                               },
4227     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(197)),        transform_world     }, 0                               },
4228     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(198)),        transform_world     }, 0                               },
4229     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(199)),        transform_world     }, 0                               },
4230     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(200)),        transform_world     }, 0                               },
4231     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(201)),        transform_world     }, 0                               },
4232     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(202)),        transform_world     }, 0                               },
4233     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(203)),        transform_world     }, 0                               },
4234     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(204)),        transform_world     }, 0                               },
4235     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(205)),        transform_world     }, 0                               },
4236     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(206)),        transform_world     }, 0                               },
4237     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(207)),        transform_world     }, 0                               },
4238     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(208)),        transform_world     }, 0                               },
4239     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(209)),        transform_world     }, 0                               },
4240     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(210)),        transform_world     }, 0                               },
4241     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(211)),        transform_world     }, 0                               },
4242     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(212)),        transform_world     }, 0                               },
4243     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(213)),        transform_world     }, 0                               },
4244     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(214)),        transform_world     }, 0                               },
4245     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(215)),        transform_world     }, 0                               },
4246     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(216)),        transform_world     }, 0                               },
4247     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(217)),        transform_world     }, 0                               },
4248     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(218)),        transform_world     }, 0                               },
4249     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(219)),        transform_world     }, 0                               },
4250     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(220)),        transform_world     }, 0                               },
4251     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(221)),        transform_world     }, 0                               },
4252     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(222)),        transform_world     }, 0                               },
4253     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(223)),        transform_world     }, 0                               },
4254     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(224)),        transform_world     }, 0                               },
4255     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(225)),        transform_world     }, 0                               },
4256     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(226)),        transform_world     }, 0                               },
4257     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(227)),        transform_world     }, 0                               },
4258     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(228)),        transform_world     }, 0                               },
4259     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(229)),        transform_world     }, 0                               },
4260     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(230)),        transform_world     }, 0                               },
4261     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(231)),        transform_world     }, 0                               },
4262     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(232)),        transform_world     }, 0                               },
4263     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(233)),        transform_world     }, 0                               },
4264     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(234)),        transform_world     }, 0                               },
4265     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(235)),        transform_world     }, 0                               },
4266     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(236)),        transform_world     }, 0                               },
4267     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(237)),        transform_world     }, 0                               },
4268     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(238)),        transform_world     }, 0                               },
4269     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(239)),        transform_world     }, 0                               },
4270     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(240)),        transform_world     }, 0                               },
4271     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(241)),        transform_world     }, 0                               },
4272     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(242)),        transform_world     }, 0                               },
4273     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(243)),        transform_world     }, 0                               },
4274     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(244)),        transform_world     }, 0                               },
4275     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(245)),        transform_world     }, 0                               },
4276     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(246)),        transform_world     }, 0                               },
4277     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(247)),        transform_world     }, 0                               },
4278     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(248)),        transform_world     }, 0                               },
4279     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(249)),        transform_world     }, 0                               },
4280     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(250)),        transform_world     }, 0                               },
4281     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(251)),        transform_world     }, 0                               },
4282     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(252)),        transform_world     }, 0                               },
4283     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(253)),        transform_world     }, 0                               },
4284     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(254)),        transform_world     }, 0                               },
4285     { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)),        { STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(255)),        transform_world     }, 0                               },
4286     { STATE_TEXTURESTAGE(0,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE0),              transform_texture   }, 0                               },
4287     { STATE_TEXTURESTAGE(1,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE1),              transform_texture   }, 0                               },
4288     { STATE_TEXTURESTAGE(2,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE2),              transform_texture   }, 0                               },
4289     { STATE_TEXTURESTAGE(3,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE3),              transform_texture   }, 0                               },
4290     { STATE_TEXTURESTAGE(4,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE4),              transform_texture   }, 0                               },
4291     { STATE_TEXTURESTAGE(5,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE5),              transform_texture   }, 0                               },
4292     { STATE_TEXTURESTAGE(6,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE6),              transform_texture   }, 0                               },
4293     { STATE_TEXTURESTAGE(7,WINED3DTSS_TEXTURETRANSFORMFLAGS),{STATE_TRANSFORM(WINED3DTS_TEXTURE7),              transform_texture   }, 0                               },
4294     { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(0, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
4295     { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(1, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
4296     { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(2, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
4297     { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(3, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
4298     { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(4, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
4299     { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(5, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
4300     { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(6, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
4301     { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX),    { STATE_TEXTURESTAGE(7, WINED3DTSS_TEXCOORDINDEX),    tex_coordindex      }, 0                               },
4302       /* Fog */
4303     { STATE_RENDER(WINED3DRS_FOGENABLE),                  { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog           }, 0                               },
4304     { STATE_RENDER(WINED3DRS_FOGTABLEMODE),               { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog           }, 0                               },
4305     { STATE_RENDER(WINED3DRS_FOGSTART),                   { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog           }, 0                               },
4306     { STATE_RENDER(WINED3DRS_FOGEND),                     { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog           }, 0                               },
4307     { STATE_RENDER(WINED3DRS_FOGVERTEXMODE),              { STATE_RENDER(WINED3DRS_FOGENABLE),                  state_fog           }, 0                               },
4308     { STATE_RENDER(WINED3DRS_FOGCOLOR),                   { STATE_RENDER(WINED3DRS_FOGCOLOR),                   state_fogcolor      }, 0                               },
4309     { STATE_RENDER(WINED3DRS_FOGDENSITY),                 { STATE_RENDER(WINED3DRS_FOGDENSITY),                 state_fogdensity    }, 0                               },
4310     { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             state_rangefog      }, NV_FOG_DISTANCE                 },
4311     { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             { STATE_RENDER(WINED3DRS_RANGEFOGENABLE),             state_rangefog_w    }, 0                               },
4312     { STATE_RENDER(WINED3DRS_CLIPPING),                   { STATE_RENDER(WINED3DRS_CLIPPING),                   state_clipping      }, 0                               },
4313     { STATE_RENDER(WINED3DRS_CLIPPLANEENABLE),            { STATE_RENDER(WINED3DRS_CLIPPING),                   state_clipping      }, 0                               },
4314     { STATE_RENDER(WINED3DRS_LIGHTING),                   { STATE_RENDER(WINED3DRS_LIGHTING),                   state_lighting      }, 0                               },
4315     { STATE_RENDER(WINED3DRS_AMBIENT),                    { STATE_RENDER(WINED3DRS_AMBIENT),                    state_ambient       }, 0                               },
4316     { STATE_RENDER(WINED3DRS_COLORVERTEX),                { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
4317     { STATE_RENDER(WINED3DRS_LOCALVIEWER),                { STATE_RENDER(WINED3DRS_LOCALVIEWER),                state_localviewer   }, 0                               },
4318     { STATE_RENDER(WINED3DRS_NORMALIZENORMALS),           { STATE_RENDER(WINED3DRS_NORMALIZENORMALS),           state_normalize     }, 0                               },
4319     { STATE_RENDER(WINED3DRS_DIFFUSEMATERIALSOURCE),      { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
4320     { STATE_RENDER(WINED3DRS_SPECULARMATERIALSOURCE),     { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
4321     { STATE_RENDER(WINED3DRS_AMBIENTMATERIALSOURCE),      { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
4322     { STATE_RENDER(WINED3DRS_EMISSIVEMATERIALSOURCE),     { STATE_RENDER(WINED3DRS_COLORVERTEX),                state_colormat      }, 0                               },
4323     { STATE_RENDER(WINED3DRS_VERTEXBLEND),                { STATE_RENDER(WINED3DRS_VERTEXBLEND),                state_vertexblend   }, ARB_VERTEX_BLEND                },
4324     { STATE_RENDER(WINED3DRS_VERTEXBLEND),                { STATE_RENDER(WINED3DRS_VERTEXBLEND),                state_vertexblend_w }, 0                               },
4325     { STATE_RENDER(WINED3DRS_POINTSIZE),                  { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
4326     { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_arb  }, ARB_POINT_PARAMETERS            },
4327     { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_ext  }, EXT_POINT_PARAMETERS            },
4328     { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              { STATE_RENDER(WINED3DRS_POINTSIZE_MIN),              state_psizemin_w    }, 0                               },
4329     { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          state_pointsprite   }, ARB_POINT_SPRITE                },
4330     { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          { STATE_RENDER(WINED3DRS_POINTSPRITEENABLE),          state_pointsprite_w }, 0                               },
4331     { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
4332     { STATE_RENDER(WINED3DRS_POINTSCALE_A),               { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
4333     { STATE_RENDER(WINED3DRS_POINTSCALE_B),               { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
4334     { STATE_RENDER(WINED3DRS_POINTSCALE_C),               { STATE_RENDER(WINED3DRS_POINTSCALEENABLE),           state_pscale        }, 0                               },
4335     { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              state_psizemax_arb  }, ARB_POINT_PARAMETERS            },
4336     { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              state_psizemax_ext  }, EXT_POINT_PARAMETERS            },
4337     { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              { STATE_RENDER(WINED3DRS_POINTSIZE_MAX),              state_psizemax_w    }, 0                               },
4338     /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
4339      * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
4340      * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
4341      */
4342     { STATE_SAMPLER(0),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
4343     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texmatrix   }, 0                               },
4344     { STATE_SAMPLER(1),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
4345     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texmatrix   }, 0                               },
4346     { STATE_SAMPLER(2),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
4347     { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texmatrix   }, 0                               },
4348     { STATE_SAMPLER(3),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
4349     { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texmatrix   }, 0                               },
4350     { STATE_SAMPLER(4),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
4351     { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texmatrix   }, 0                               },
4352     { STATE_SAMPLER(5),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
4353     { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texmatrix   }, 0                               },
4354     { STATE_SAMPLER(6),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
4355     { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texmatrix   }, 0                               },
4356     { STATE_SAMPLER(7),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
4357     { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texmatrix   }, 0                               },
4358     {0 /* Terminate */,                                   { 0,                                                  0                   }, 0                               },
4359 };
4360
4361 static const struct StateEntryTemplate ffp_fragmentstate_template[] = {
4362     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4363     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4364     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4365     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4366     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4367     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4368     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4369     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4370     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4371     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(0, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4372     { STATE_TEXTURESTAGE(0, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4373     { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(0, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4374     { STATE_TEXTURESTAGE(0, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(0, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4375     { STATE_TEXTURESTAGE(0, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
4376     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4377     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4378     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4379     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4380     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4381     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4382     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4383     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4384     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4385     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(1, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4386     { STATE_TEXTURESTAGE(1, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4387     { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(1, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4388     { STATE_TEXTURESTAGE(1, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(1, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4389     { STATE_TEXTURESTAGE(1, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
4390     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4391     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4392     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4393     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4394     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4395     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4396     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4397     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4398     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4399     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(2, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4400     { STATE_TEXTURESTAGE(2, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4401     { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(2, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4402     { STATE_TEXTURESTAGE(2, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(2, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4403     { STATE_TEXTURESTAGE(2, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
4404     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4405     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4406     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4407     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4408     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4409     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4410     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4411     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4412     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4413     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(3, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4414     { STATE_TEXTURESTAGE(3, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4415     { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(3, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4416     { STATE_TEXTURESTAGE(3, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(3, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4417     { STATE_TEXTURESTAGE(3, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
4418     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4419     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4420     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4421     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4422     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4423     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4424     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4425     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4426     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4427     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(4, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4428     { STATE_TEXTURESTAGE(4, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4429     { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(4, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4430     { STATE_TEXTURESTAGE(4, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(4, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4431     { STATE_TEXTURESTAGE(4, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
4432     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4433     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4434     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4435     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4436     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4437     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4438     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4439     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4440     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4441     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(5, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4442     { STATE_TEXTURESTAGE(5, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4443     { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(5, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4444     { STATE_TEXTURESTAGE(5, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(5, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4445     { STATE_TEXTURESTAGE(5, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
4446     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4447     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4448     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4449     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4450     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4451     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4452     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4453     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4454     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4455     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(6, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4456     { STATE_TEXTURESTAGE(6, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4457     { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(6, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4458     { STATE_TEXTURESTAGE(6, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(6, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4459     { STATE_TEXTURESTAGE(6, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
4460     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4461     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG1),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4462     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG2),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4463     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4464     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG1),        { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4465     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG2),        { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4466     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4467     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT01),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4468     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT10),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4469     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT11),     { STATE_TEXTURESTAGE(7, WINED3DTSS_BUMPENVMAT00),     tex_bumpenvmat      }, ATI_ENVMAP_BUMPMAP              },
4470     { STATE_TEXTURESTAGE(7, WINED3DTSS_COLORARG0),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4471     { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAARG0),        { STATE_TEXTURESTAGE(7, WINED3DTSS_ALPHAOP),          tex_alphaop         }, 0                               },
4472     { STATE_TEXTURESTAGE(7, WINED3DTSS_RESULTARG),        { STATE_TEXTURESTAGE(7, WINED3DTSS_COLOROP),          tex_colorop         }, 0                               },
4473     { STATE_TEXTURESTAGE(7, WINED3DTSS_CONSTANT),         { 0 /* As long as we don't support D3DTA_CONSTANT */, state_nogl          }, 0                               },
4474     { STATE_PIXELSHADER,                                  { STATE_PIXELSHADER,                                  apply_pixelshader   }, 0                               },
4475     { STATE_RENDER(WINED3DRS_SRGBWRITEENABLE),            { STATE_PIXELSHADER,                                  apply_pixelshader   }, 0                               },
4476     { STATE_RENDER(WINED3DRS_BORDERCOLOR),                { STATE_RENDER(WINED3DRS_BORDERCOLOR),                state_bordercolor   }, 0                               },
4477     { STATE_RENDER(WINED3DRS_TEXTUREFACTOR),              { STATE_RENDER(WINED3DRS_TEXTUREFACTOR),              state_texfactor     }, 0                               },
4478     { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texdim      }, 0                               },
4479     { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texdim      }, 0                               },
4480     { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texdim      }, 0                               },
4481     { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texdim      }, 0                               },
4482     { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texdim      }, 0                               },
4483     { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texdim      }, 0                               },
4484     { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texdim      }, 0                               },
4485     { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texdim      }, 0                               },
4486     {0 /* Terminate */,                                   { 0,                                                  0                   }, 0                               },
4487 };
4488 #undef GLINFO_LOCATION
4489
4490 #define GLINFO_LOCATION (*gl_info)
4491 static void ffp_enable(IWineD3DDevice *iface, BOOL enable) { }
4492
4493 static void ffp_fragment_get_caps(WINED3DDEVTYPE devtype, WineD3D_GL_Info *gl_info, struct fragment_caps *pCaps) {
4494     pCaps->TextureOpCaps =  WINED3DTEXOPCAPS_ADD         |
4495                             WINED3DTEXOPCAPS_ADDSIGNED   |
4496                             WINED3DTEXOPCAPS_ADDSIGNED2X |
4497                             WINED3DTEXOPCAPS_MODULATE    |
4498                             WINED3DTEXOPCAPS_MODULATE2X  |
4499                             WINED3DTEXOPCAPS_MODULATE4X  |
4500                             WINED3DTEXOPCAPS_SELECTARG1  |
4501                             WINED3DTEXOPCAPS_SELECTARG2  |
4502                             WINED3DTEXOPCAPS_DISABLE;
4503
4504     if (GL_SUPPORT(ARB_TEXTURE_ENV_COMBINE) ||
4505         GL_SUPPORT(EXT_TEXTURE_ENV_COMBINE) ||
4506         GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
4507         pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA  |
4508                                 WINED3DTEXOPCAPS_BLENDTEXTUREALPHA  |
4509                                 WINED3DTEXOPCAPS_BLENDFACTORALPHA   |
4510                                 WINED3DTEXOPCAPS_BLENDCURRENTALPHA  |
4511                                 WINED3DTEXOPCAPS_LERP               |
4512                                 WINED3DTEXOPCAPS_SUBTRACT;
4513     }
4514     if (GL_SUPPORT(ATI_TEXTURE_ENV_COMBINE3) ||
4515         GL_SUPPORT(NV_TEXTURE_ENV_COMBINE4)) {
4516         pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH              |
4517                                 WINED3DTEXOPCAPS_MULTIPLYADD            |
4518                                 WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR |
4519                                 WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA |
4520                                 WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
4521     }
4522     if (GL_SUPPORT(ARB_TEXTURE_ENV_DOT3))
4523         pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
4524
4525     if(GL_SUPPORT(ATI_ENVMAP_BUMPMAP)) {
4526         pCaps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
4527     }
4528
4529     pCaps->MaxTextureBlendStages   = GL_LIMITS(texture_stages);
4530     pCaps->MaxSimultaneousTextures = GL_LIMITS(textures);
4531 }
4532
4533 static HRESULT ffp_fragment_alloc(IWineD3DDevice *iface) { return WINED3D_OK; }
4534 static void ffp_fragment_free(IWineD3DDevice *iface) {}
4535
4536 const struct fragment_pipeline ffp_fragment_pipeline = {
4537     ffp_enable,
4538     ffp_fragment_get_caps,
4539     ffp_fragment_alloc,
4540     ffp_fragment_free,
4541     ffp_fragmentstate_template
4542 };
4543
4544 static int num_handlers(APPLYSTATEFUNC *funcs) {
4545     unsigned int i;
4546     for(i = 0; funcs[i]; i++);
4547     return i;
4548 }
4549
4550 static void multistate_apply_2(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4551     stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
4552     stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
4553 }
4554
4555 static void multistate_apply_3(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) {
4556     stateblock->wineD3DDevice->multistate_funcs[state][0](state, stateblock, context);
4557     stateblock->wineD3DDevice->multistate_funcs[state][1](state, stateblock, context);
4558     stateblock->wineD3DDevice->multistate_funcs[state][2](state, stateblock, context);
4559 }
4560
4561 void compile_state_table(struct StateEntry *StateTable,
4562                          APPLYSTATEFUNC **dev_multistate_funcs,
4563                          WineD3D_GL_Info *gl_info,
4564                          const struct StateEntryTemplate *vertex,
4565                          const struct fragment_pipeline *fragment,
4566                          const struct StateEntryTemplate *misc) {
4567     unsigned int i, type, handlers;
4568     APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
4569     const struct StateEntryTemplate *cur;
4570     BOOL set[STATE_HIGHEST + 1];
4571
4572     memset(multistate_funcs, 0, sizeof(multistate_funcs));
4573
4574     for(i = 0; i < STATE_HIGHEST + 1; i++) {
4575         StateTable[i].representative = 0;
4576         StateTable[i].apply = state_undefined;
4577     }
4578
4579     for(type = 0; type < 3; type++) {
4580         /* This switch decides the order in which the states are applied */
4581         switch(type) {
4582             case 0: cur = misc; break;
4583             case 1: cur = fragment->states; break;
4584             case 2: cur = vertex; break;
4585             default: cur = NULL; /* Stupid compiler */
4586         }
4587         if(!cur) continue;
4588
4589         /* GL extension filtering should not prevent multiple handlers being applied from different
4590          * pipeline parts
4591          */
4592         memset(set, 0, sizeof(set));
4593
4594         for(i = 0; cur[i].state; i++) {
4595
4596             /* Only use the first matching state with the available extension from one template.
4597              * e.g.
4598              * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
4599              * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0        }
4600              *
4601              * if GL_XYZ_fancy is supported, ignore the 2nd line
4602              */
4603             if(set[cur[i].state]) continue;
4604             /* Skip state lines depending on unsupported extensions */
4605             if(cur[i].extension && !GL_SUPPORT(cur[i].extension)) continue;
4606             set[cur[i].state] = TRUE;
4607             /* In some cases having an extension means that nothing has to be
4608              * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
4609              * supported, the texture coordinate fixup can be ignored. If the
4610              * apply function is used, mark the state set(done above) to prevent
4611              * applying later lines, but do not record anything in the state
4612              * table
4613              */
4614             if(!cur[i].content.apply) continue;
4615
4616             handlers = num_handlers(multistate_funcs[cur[i].state]);
4617             multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
4618             switch(handlers) {
4619                 case 0:
4620                     StateTable[cur[i].state].apply = cur[i].content.apply;
4621                     break;
4622                 case 1:
4623                     StateTable[cur[i].state].apply = multistate_apply_2;
4624                     dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
4625                                                                    0,
4626                                                                    sizeof(**dev_multistate_funcs) * 2);
4627                     dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
4628                     dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
4629                     break;
4630                 case 2:
4631                     StateTable[cur[i].state].apply = multistate_apply_3;
4632                     HeapFree(GetProcessHeap(), 0, multistate_funcs[cur[i].state]);
4633                     dev_multistate_funcs[cur[i].state] = HeapAlloc(GetProcessHeap(),
4634                                                                    0,
4635                                                                    sizeof(**dev_multistate_funcs) * 3);
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                     dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
4639                     break;
4640                 default:
4641                     ERR("Unexpected amount of state handlers for state %u: %u\n",
4642                         cur[i].state, handlers + 1);
4643             }
4644
4645             if(StateTable[cur[i].state].representative &&
4646             StateTable[cur[i].state].representative != cur[i].content.representative) {
4647                 FIXME("State %u has different representatives in different pipeline parts\n",
4648                     cur[i].state);
4649             }
4650             StateTable[cur[i].state].representative = cur[i].content.representative;
4651         }
4652     }
4653 }
4654 #undef GLINFO_LOCATION