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