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