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