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