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