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