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