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