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