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