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