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