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