state.c 329 KB
Newer Older
1 2 3
/*
 * Direct3D state management
 *
4 5 6 7 8 9
 * Copyright 2002 Lionel Ulmer
 * Copyright 2002-2005 Jason Edmeades
 * Copyright 2003-2004 Raphael Junqueira
 * Copyright 2004 Christian Costa
 * Copyright 2005 Oliver Stieber
 * Copyright 2006 Henri Verbeet
10
 * Copyright 2006-2008 Stefan Dösinger for CodeWeavers
11
 * Copyright 2009-2011 Henri Verbeet for CodeWeavers
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

#include "config.h"
29 30
#include "wine/port.h"

31 32 33 34
#include <stdio.h>
#ifdef HAVE_FLOAT_H
# include <float.h>
#endif
35

36 37 38 39
#include "wined3d_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d);

40 41 42 43 44 45 46 47 48 49 50
ULONG CDECL wined3d_blend_state_incref(struct wined3d_blend_state *state)
{
    ULONG refcount = InterlockedIncrement(&state->refcount);

    TRACE("%p increasing refcount to %u.\n", state, refcount);

    return refcount;
}

static void wined3d_blend_state_destroy_object(void *object)
{
51
    heap_free(object);
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85
}

ULONG CDECL wined3d_blend_state_decref(struct wined3d_blend_state *state)
{
    ULONG refcount = InterlockedDecrement(&state->refcount);
    struct wined3d_device *device = state->device;

    TRACE("%p decreasing refcount to %u.\n", state, refcount);

    if (!refcount)
    {
        state->parent_ops->wined3d_object_destroyed(state->parent);
        wined3d_cs_destroy_object(device->cs, wined3d_blend_state_destroy_object, state);
    }

    return refcount;
}

void * CDECL wined3d_blend_state_get_parent(const struct wined3d_blend_state *state)
{
    TRACE("state %p.\n", state);

    return state->parent;
}

HRESULT CDECL wined3d_blend_state_create(struct wined3d_device *device,
        const struct wined3d_blend_state_desc *desc, void *parent,
        const struct wined3d_parent_ops *parent_ops, struct wined3d_blend_state **state)
{
    struct wined3d_blend_state *object;

    TRACE("device %p, desc %p, parent %p, parent_ops %p, state %p.\n",
            device, desc, parent, parent_ops, state);

86
    if (!(object = heap_alloc_zero(sizeof(*object))))
87 88 89 90 91 92 93 94 95 96 97 98 99 100
        return E_OUTOFMEMORY;

    object->refcount = 1;
    object->desc = *desc;
    object->parent = parent;
    object->parent_ops = parent_ops;
    object->device = device;

    TRACE("Created blend state %p.\n", object);
    *state = object;

    return WINED3D_OK;
}

101 102 103 104 105 106 107 108 109 110 111
ULONG CDECL wined3d_rasterizer_state_incref(struct wined3d_rasterizer_state *state)
{
    ULONG refcount = InterlockedIncrement(&state->refcount);

    TRACE("%p increasing refcount to %u.\n", state, refcount);

    return refcount;
}

static void wined3d_rasterizer_state_destroy_object(void *object)
{
112
    heap_free(object);
113 114 115 116 117 118 119 120 121 122
}

ULONG CDECL wined3d_rasterizer_state_decref(struct wined3d_rasterizer_state *state)
{
    ULONG refcount = InterlockedDecrement(&state->refcount);
    struct wined3d_device *device = state->device;

    TRACE("%p decreasing refcount to %u.\n", state, refcount);

    if (!refcount)
123 124
    {
        state->parent_ops->wined3d_object_destroyed(state->parent);
125
        wined3d_cs_destroy_object(device->cs, wined3d_rasterizer_state_destroy_object, state);
126
    }
127 128 129 130

    return refcount;
}

131 132 133 134 135 136 137
void * CDECL wined3d_rasterizer_state_get_parent(const struct wined3d_rasterizer_state *state)
{
    TRACE("rasterizer_state %p.\n", state);

    return state->parent;
}

138
HRESULT CDECL wined3d_rasterizer_state_create(struct wined3d_device *device,
139 140
        const struct wined3d_rasterizer_state_desc *desc, void *parent,
        const struct wined3d_parent_ops *parent_ops, struct wined3d_rasterizer_state **state)
141 142 143
{
    struct wined3d_rasterizer_state *object;

144 145
    TRACE("device %p, desc %p, parent %p, parent_ops %p, state %p.\n",
            device, desc, parent, parent_ops, state);
146

147
    if (!(object = heap_alloc_zero(sizeof(*object))))
148 149 150 151
        return E_OUTOFMEMORY;

    object->refcount = 1;
    object->desc = *desc;
152 153
    object->parent = parent;
    object->parent_ops = parent_ops;
154 155 156 157 158 159 160 161
    object->device = device;

    TRACE("Created rasterizer state %p.\n", object);
    *state = object;

    return WINED3D_OK;
}

162
/* Context activation for state handler is done by the caller. */
163

164
static void state_undefined(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
165
{
166
    ERR("Undefined state %s (%#x).\n", debug_d3dstate(state_id), state_id);
167 168
}

169
void state_nop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
170
{
171
    TRACE("%s: nop in current pipe config.\n", debug_d3dstate(state_id));
172 173
}

174
static void state_fillmode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
175
{
176
    enum wined3d_fill_mode mode = state->render_states[WINED3D_RS_FILLMODE];
177
    const struct wined3d_gl_info *gl_info = context->gl_info;
178

179 180
    switch (mode)
    {
181
        case WINED3D_FILL_POINT:
182
            gl_info->gl_ops.gl.p_glPolygonMode(GL_FRONT_AND_BACK, GL_POINT);
183 184
            checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_POINT)");
            break;
185
        case WINED3D_FILL_WIREFRAME:
186
            gl_info->gl_ops.gl.p_glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
187 188
            checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_LINE)");
            break;
189
        case WINED3D_FILL_SOLID:
190
            gl_info->gl_ops.gl.p_glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
191 192 193
            checkGLcall("glPolygonMode(GL_FRONT_AND_BACK, GL_FILL)");
            break;
        default:
194
            FIXME("Unrecognized fill mode %#x.\n", mode);
195 196 197
    }
}

198
static void state_lighting(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
199
{
200 201
    const struct wined3d_gl_info *gl_info = context->gl_info;

202 203 204 205 206 207
    /* Lighting is not enabled if transformed vertices are drawn, but lighting
     * does not affect the stream sources, so it is not grouped for
     * performance reasons. This state reads the decoded vertex declaration,
     * so if it is dirty don't do anything. The vertex declaration applying
     * function calls this function for updating. */
    if (isStateDirty(context, STATE_VDECL))
208
        return;
209

210
    if (state->render_states[WINED3D_RS_LIGHTING]
211
            && !context->stream_info.position_transformed)
212
    {
213
        gl_info->gl_ops.gl.p_glEnable(GL_LIGHTING);
214
        checkGLcall("glEnable GL_LIGHTING");
215 216 217 218
    }
    else
    {
        gl_info->gl_ops.gl.p_glDisable(GL_LIGHTING);
219 220 221 222
        checkGLcall("glDisable GL_LIGHTING");
    }
}

223
static void state_zenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
224
{
225
    enum wined3d_depth_buffer_type zenable = state->render_states[WINED3D_RS_ZENABLE];
226
    const struct wined3d_gl_info *gl_info = context->gl_info;
227

228
    /* No z test without depth stencil buffers */
229
    if (!state->fb->depth_stencil)
230
    {
231
        TRACE("No Z buffer - disabling depth test\n");
232
        zenable = WINED3D_ZB_FALSE;
233 234
    }

235
    switch (zenable)
236
    {
237
        case WINED3D_ZB_FALSE:
238
            gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_TEST);
239 240
            checkGLcall("glDisable GL_DEPTH_TEST");
            break;
241
        case WINED3D_ZB_TRUE:
242
            gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_TEST);
243 244
            checkGLcall("glEnable GL_DEPTH_TEST");
            break;
245
        case WINED3D_ZB_USEW:
246
            gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_TEST);
247 248 249 250
            checkGLcall("glEnable GL_DEPTH_TEST");
            FIXME("W buffer is not well handled\n");
            break;
        default:
251 252 253 254
            FIXME("Unrecognized depth buffer type %#x.\n", zenable);
            break;
    }

255
    if (context->last_was_rhw && !isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)))
256
        context_apply_state(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
257 258
}

259
static void state_cullmode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
260
{
261 262
    const struct wined3d_gl_info *gl_info = context->gl_info;

263 264
    /* glFrontFace() is set in context.c at context init and on an
     * offscreen / onscreen rendering switch. */
265
    switch (state->render_states[WINED3D_RS_CULLMODE])
266
    {
267
        case WINED3D_CULL_NONE:
268
            gl_info->gl_ops.gl.p_glDisable(GL_CULL_FACE);
269 270
            checkGLcall("glDisable GL_CULL_FACE");
            break;
271
        case WINED3D_CULL_FRONT:
272
            gl_info->gl_ops.gl.p_glEnable(GL_CULL_FACE);
273
            checkGLcall("glEnable GL_CULL_FACE");
274
            gl_info->gl_ops.gl.p_glCullFace(GL_FRONT);
275
            checkGLcall("glCullFace(GL_FRONT)");
276
            break;
277
        case WINED3D_CULL_BACK:
278
            gl_info->gl_ops.gl.p_glEnable(GL_CULL_FACE);
279
            checkGLcall("glEnable GL_CULL_FACE");
280
            gl_info->gl_ops.gl.p_glCullFace(GL_BACK);
281
            checkGLcall("glCullFace(GL_BACK)");
282 283
            break;
        default:
284
            FIXME("Unrecognized cull mode %#x.\n",
285
                    state->render_states[WINED3D_RS_CULLMODE]);
286 287 288
    }
}

289
void state_shademode(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
290
{
291 292
    const struct wined3d_gl_info *gl_info = context->gl_info;

293
    switch (state->render_states[WINED3D_RS_SHADEMODE])
294
    {
295
        case WINED3D_SHADE_FLAT:
296
            gl_info->gl_ops.gl.p_glShadeModel(GL_FLAT);
297 298
            checkGLcall("glShadeModel(GL_FLAT)");
            break;
299
        case WINED3D_SHADE_GOURAUD:
300 301 302
        /* WINED3D_SHADE_PHONG in practice is the same as WINED3D_SHADE_GOURAUD
         * in D3D. */
        case WINED3D_SHADE_PHONG:
303
            gl_info->gl_ops.gl.p_glShadeModel(GL_SMOOTH);
304 305 306
            checkGLcall("glShadeModel(GL_SMOOTH)");
            break;
        default:
307
            FIXME("Unrecognized shade mode %#x.\n",
308
                    state->render_states[WINED3D_RS_SHADEMODE]);
309 310 311
    }
}

312
static void state_ditherenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
313
{
314 315
    const struct wined3d_gl_info *gl_info = context->gl_info;

316
    if (state->render_states[WINED3D_RS_DITHERENABLE])
317
    {
318
        gl_info->gl_ops.gl.p_glEnable(GL_DITHER);
319
        checkGLcall("glEnable GL_DITHER");
320 321 322
    }
    else
    {
323
        gl_info->gl_ops.gl.p_glDisable(GL_DITHER);
324 325 326 327
        checkGLcall("glDisable GL_DITHER");
    }
}

328
static void state_zwriteenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
329
{
330 331
    const struct wined3d_gl_info *gl_info = context->gl_info;

332
    if (state->render_states[WINED3D_RS_ZWRITEENABLE])
333
    {
334
        gl_info->gl_ops.gl.p_glDepthMask(1);
335
        checkGLcall("glDepthMask(1)");
336 337 338
    }
    else
    {
339
        gl_info->gl_ops.gl.p_glDepthMask(0);
340 341 342 343
        checkGLcall("glDepthMask(0)");
    }
}

344
GLenum wined3d_gl_compare_func(enum wined3d_cmp_func f)
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364
{
    switch (f)
    {
        case WINED3D_CMP_NEVER:
            return GL_NEVER;
        case WINED3D_CMP_LESS:
            return GL_LESS;
        case WINED3D_CMP_EQUAL:
            return GL_EQUAL;
        case WINED3D_CMP_LESSEQUAL:
            return GL_LEQUAL;
        case WINED3D_CMP_GREATER:
            return GL_GREATER;
        case WINED3D_CMP_NOTEQUAL:
            return GL_NOTEQUAL;
        case WINED3D_CMP_GREATEREQUAL:
            return GL_GEQUAL;
        case WINED3D_CMP_ALWAYS:
            return GL_ALWAYS;
        default:
365 366 367 368
            if (!f)
                WARN("Unrecognized compare function %#x.\n", f);
            else
                FIXME("Unrecognized compare function %#x.\n", f);
369 370 371 372
            return GL_NONE;
    }
}

373
static void state_zfunc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
374
{
375
    GLenum depth_func = wined3d_gl_compare_func(state->render_states[WINED3D_RS_ZFUNC]);
376
    const struct wined3d_gl_info *gl_info = context->gl_info;
377

378
    if (!depth_func) return;
379

380
    gl_info->gl_ops.gl.p_glDepthFunc(depth_func);
381
    checkGLcall("glDepthFunc");
382 383
}

384
static void state_ambient(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
385
{
386
    const struct wined3d_gl_info *gl_info = context->gl_info;
387
    struct wined3d_color color;
388

389
    wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_AMBIENT]);
390
    TRACE("Setting ambient to %s.\n", debug_color(&color));
391
    gl_info->gl_ops.gl.p_glLightModelfv(GL_LIGHT_MODEL_AMBIENT, &color.r);
392 393 394
    checkGLcall("glLightModel for MODEL_AMBIENT");
}

395 396 397 398 399
static void state_blendop_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
    WARN("Unsupported in local OpenGL implementation: glBlendEquation\n");
}

400
static GLenum gl_blend_op(const struct wined3d_gl_info *gl_info, enum wined3d_blend_op op)
401 402 403
{
    switch (op)
    {
404
        case WINED3D_BLEND_OP_ADD:
405
            return GL_FUNC_ADD;
406
        case WINED3D_BLEND_OP_SUBTRACT:
407
            return gl_info->supported[EXT_BLEND_SUBTRACT] ? GL_FUNC_SUBTRACT : GL_FUNC_ADD;
408
        case WINED3D_BLEND_OP_REVSUBTRACT:
409
            return gl_info->supported[EXT_BLEND_SUBTRACT] ? GL_FUNC_REVERSE_SUBTRACT : GL_FUNC_ADD;
410
        case WINED3D_BLEND_OP_MIN:
411
            return gl_info->supported[EXT_BLEND_MINMAX] ? GL_MIN : GL_FUNC_ADD;
412
        case WINED3D_BLEND_OP_MAX:
413
            return gl_info->supported[EXT_BLEND_MINMAX] ? GL_MAX : GL_FUNC_ADD;
414
        default:
415 416 417 418
            if (!op)
                WARN("Unhandled blend op %#x.\n", op);
            else
                FIXME("Unhandled blend op %#x.\n", op);
419
            return GL_FUNC_ADD;
420 421 422 423 424 425 426 427 428 429
    }
}

static void state_blendop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
    const struct wined3d_gl_info *gl_info = context->gl_info;
    GLenum blend_equation_alpha = GL_FUNC_ADD_EXT;
    GLenum blend_equation = GL_FUNC_ADD_EXT;

    /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
430
    if (state->render_states[WINED3D_RS_BLENDOPALPHA]
431 432
            && !gl_info->supported[EXT_BLEND_EQUATION_SEPARATE])
    {
433
        WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparate.\n");
434 435 436
        return;
    }

437 438
    blend_equation = gl_blend_op(gl_info, state->render_states[WINED3D_RS_BLENDOP]);
    blend_equation_alpha = gl_blend_op(gl_info, state->render_states[WINED3D_RS_BLENDOPALPHA]);
439 440
    TRACE("blend_equation %#x, blend_equation_alpha %#x.\n", blend_equation, blend_equation_alpha);

441
    if (state->render_states[WINED3D_RS_SEPARATEALPHABLENDENABLE])
442
    {
443 444
        GL_EXTCALL(glBlendEquationSeparate(blend_equation, blend_equation_alpha));
        checkGLcall("glBlendEquationSeparate");
445 446 447
    }
    else
    {
448
        GL_EXTCALL(glBlendEquation(blend_equation));
449 450 451 452
        checkGLcall("glBlendEquation");
    }
}

453
static GLenum gl_blend_factor(enum wined3d_blend factor, const struct wined3d_format *dst_format)
454 455 456
{
    switch (factor)
    {
457
        case WINED3D_BLEND_ZERO:
458
            return GL_ZERO;
459
        case WINED3D_BLEND_ONE:
460
            return GL_ONE;
461
        case WINED3D_BLEND_SRCCOLOR:
462
            return GL_SRC_COLOR;
463
        case WINED3D_BLEND_INVSRCCOLOR:
464
            return GL_ONE_MINUS_SRC_COLOR;
465
        case WINED3D_BLEND_SRCALPHA:
466
            return GL_SRC_ALPHA;
467
        case WINED3D_BLEND_INVSRCALPHA:
468
            return GL_ONE_MINUS_SRC_ALPHA;
469
        case WINED3D_BLEND_DESTCOLOR:
470
            return GL_DST_COLOR;
471
        case WINED3D_BLEND_INVDESTCOLOR:
472 473 474 475
            return GL_ONE_MINUS_DST_COLOR;
        /* To compensate for the lack of format switching with backbuffer
         * offscreen rendering, and with onscreen rendering, we modify the
         * alpha test parameters for (INV)DESTALPHA if the render target
476
         * doesn't support alpha blending. A nonexistent alpha channel
477 478 479
         * returns 1.0, so WINED3D_BLEND_DESTALPHA becomes GL_ONE, and
         * WINED3D_BLEND_INVDESTALPHA becomes GL_ZERO. */
        case WINED3D_BLEND_DESTALPHA:
480
            return dst_format->alpha_size ? GL_DST_ALPHA : GL_ONE;
481
        case WINED3D_BLEND_INVDESTALPHA:
482
            return dst_format->alpha_size ? GL_ONE_MINUS_DST_ALPHA : GL_ZERO;
483
        case WINED3D_BLEND_SRCALPHASAT:
484
            return GL_SRC_ALPHA_SATURATE;
485
        case WINED3D_BLEND_BLENDFACTOR:
486
            return GL_CONSTANT_COLOR_EXT;
487
        case WINED3D_BLEND_INVBLENDFACTOR:
488
            return GL_ONE_MINUS_CONSTANT_COLOR_EXT;
489 490 491 492 493 494 495 496
        case WINED3D_BLEND_SRC1COLOR:
            return GL_SRC1_COLOR;
        case WINED3D_BLEND_INVSRC1COLOR:
            return GL_ONE_MINUS_SRC1_COLOR;
        case WINED3D_BLEND_SRC1ALPHA:
            return GL_SRC1_ALPHA;
        case WINED3D_BLEND_INVSRC1ALPHA:
            return GL_ONE_MINUS_SRC1_ALPHA;
497
        default:
498 499 500 501
            if (!factor)
                WARN("Unhandled blend factor %#x.\n", factor);
            else
                FIXME("Unhandled blend factor %#x.\n", factor);
502 503 504 505
            return GL_NONE;
    }
}

506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529
static void gl_blend_from_d3d(GLenum *src_blend, GLenum *dst_blend,
        enum wined3d_blend d3d_src_blend, enum wined3d_blend d3d_dst_blend,
        const struct wined3d_format *rt_format)
{
    /* WINED3D_BLEND_BOTHSRCALPHA and WINED3D_BLEND_BOTHINVSRCALPHA are legacy
     * source blending values which are still valid up to d3d9. They should
     * not occur as dest blend values. */
    if (d3d_src_blend == WINED3D_BLEND_BOTHSRCALPHA)
    {
        *src_blend = GL_SRC_ALPHA;
        *dst_blend = GL_ONE_MINUS_SRC_ALPHA;
    }
    else if (d3d_src_blend == WINED3D_BLEND_BOTHINVSRCALPHA)
    {
        *src_blend = GL_ONE_MINUS_SRC_ALPHA;
        *dst_blend = GL_SRC_ALPHA;
    }
    else
    {
        *src_blend = gl_blend_factor(d3d_src_blend, rt_format);
        *dst_blend = gl_blend_factor(d3d_dst_blend, rt_format);
    }
}

530
static void state_blend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
531
{
532
    const struct wined3d_gl_info *gl_info = context->gl_info;
533
    const struct wined3d_format *rt_format;
534
    GLenum src_blend, dst_blend;
535
    unsigned int rt_fmt_flags;
536
    BOOL enable_blend;
537

538 539
    enable_blend = state->fb->render_targets[0] && state->render_states[WINED3D_RS_ALPHABLENDENABLE];
    if (enable_blend)
540
    {
541 542 543
        rt_format = state->fb->render_targets[0]->format;
        rt_fmt_flags = state->fb->render_targets[0]->format_flags;

544 545
        /* Disable blending in all cases even without pixelshaders.
         * With blending on we could face a big performance penalty.
546
         * The d3d9 visual test confirms the behavior. */
547
        if (context->render_offscreen && !(rt_fmt_flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
548 549 550
            enable_blend = FALSE;
    }

551
    if (!enable_blend)
552 553
    {
        gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
554
        checkGLcall("glDisable(GL_BLEND)");
555
        return;
556
    }
557

558 559 560
    gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
    checkGLcall("glEnable(GL_BLEND)");

561 562 563
    gl_blend_from_d3d(&src_blend, &dst_blend,
            state->render_states[WINED3D_RS_SRCBLEND],
            state->render_states[WINED3D_RS_DESTBLEND], rt_format);
564

565
    /* Re-apply BLENDOP(ALPHA) because of a possible SEPARATEALPHABLENDENABLE change */
566 567
    if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_BLENDOP)))
        state_blendop(context, state, STATE_RENDER(WINED3D_RS_BLENDOPALPHA));
568

569
    if (state->render_states[WINED3D_RS_SEPARATEALPHABLENDENABLE])
570
    {
571
        GLenum src_blend_alpha, dst_blend_alpha;
572 573

        /* Separate alpha blending requires GL_EXT_blend_function_separate, so make sure it is around */
574 575
        if (!context->gl_info->supported[EXT_BLEND_FUNC_SEPARATE])
        {
576
            WARN("Unsupported in local OpenGL implementation: glBlendFuncSeparate.\n");
577 578 579
            return;
        }

580 581 582
        gl_blend_from_d3d(&src_blend_alpha, &dst_blend_alpha,
                state->render_states[WINED3D_RS_SRCBLENDALPHA],
                state->render_states[WINED3D_RS_DESTBLENDALPHA], rt_format);
583

584
        GL_EXTCALL(glBlendFuncSeparate(src_blend, dst_blend, src_blend_alpha, dst_blend_alpha));
585
        checkGLcall("glBlendFuncSeparate");
586 587 588
    }
    else
    {
589 590
        TRACE("glBlendFunc src=%x, dst=%x.\n", src_blend, dst_blend);
        gl_info->gl_ops.gl.p_glBlendFunc(src_blend, dst_blend);
591 592
        checkGLcall("glBlendFunc");
    }
593

594
    /* Colorkey fixup for stage 0 alphaop depends on
595 596
     * WINED3D_RS_ALPHABLENDENABLE state, so it may need updating. */
    if (state->render_states[WINED3D_RS_COLORKEYENABLE])
597
        context_apply_state(context, state, STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP));
598 599
}

600
static void state_blend_factor_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
601
{
602
    WARN("Unsupported in local OpenGL implementation: glBlendColor.\n");
603 604
}

605
static void state_blend_factor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
606
{
607
    const struct wined3d_color *factor = &state->blend_factor;
608
    const struct wined3d_gl_info *gl_info = context->gl_info;
609

610
    TRACE("Setting blend factor to %s.\n", debug_color(factor));
611

612
    GL_EXTCALL(glBlendColor(factor->r, factor->g, factor->b, factor->a));
613 614 615
    checkGLcall("glBlendColor");
}

616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
static void state_blend_object(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
    const struct wined3d_gl_info *gl_info = context->gl_info;
    BOOL alpha_to_coverage = FALSE;

    if (!gl_info->supported[ARB_MULTISAMPLE])
        return;

    if (state->blend_state)
    {
        struct wined3d_blend_state_desc *desc = &state->blend_state->desc;
        alpha_to_coverage = desc->alpha_to_coverage;
    }

    if (alpha_to_coverage)
        gl_info->gl_ops.gl.p_glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
    else
        gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);

    checkGLcall("blend state");
}

638
void state_alpha_test(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
639
{
640
    const struct wined3d_gl_info *gl_info = context->gl_info;
641 642 643 644
    int glParm = 0;
    float ref;
    BOOL enable_ckey = FALSE;

645
    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
646

647 648 649 650 651 652 653
    /* Find out if the texture on the first stage has a ckey set. The alpha
     * state func reads the texture settings, even though alpha and texture
     * are not grouped together. This is to avoid making a huge alpha +
     * texture + texture stage + ckey block due to the hardly used
     * WINED3D_RS_COLORKEYENABLE state(which is d3d <= 3 only). The texture
     * function will call alpha in case it finds some texture + colorkeyenable
     * combination which needs extra care. */
654
    if (state->textures[0] && (state->textures[0]->async.color_key_flags & WINED3D_CKEY_SRC_BLT))
655
        enable_ckey = TRUE;
656

657
    if (enable_ckey || context->last_was_ckey)
658
        context_apply_state(context, state, STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP));
659 660
    context->last_was_ckey = enable_ckey;

661 662
    if (state->render_states[WINED3D_RS_ALPHATESTENABLE]
            || (state->render_states[WINED3D_RS_COLORKEYENABLE] && enable_ckey))
663
    {
664
        gl_info->gl_ops.gl.p_glEnable(GL_ALPHA_TEST);
665
        checkGLcall("glEnable GL_ALPHA_TEST");
666 667 668 669
    }
    else
    {
        gl_info->gl_ops.gl.p_glDisable(GL_ALPHA_TEST);
670 671 672 673 674 675 676
        checkGLcall("glDisable GL_ALPHA_TEST");
        /* Alpha test is disabled, don't bother setting the params - it will happen on the next
         * enable call
         */
        return;
    }

677
    if (state->render_states[WINED3D_RS_COLORKEYENABLE] && enable_ckey)
678
    {
679
        glParm = GL_NOTEQUAL;
680
        ref = 0.0f;
681 682 683
    }
    else
    {
684
        ref = wined3d_alpha_ref(state);
685
        glParm = wined3d_gl_compare_func(state->render_states[WINED3D_RS_ALPHAFUNC]);
686
    }
687 688 689
    if (glParm)
    {
        gl_info->gl_ops.gl.p_glAlphaFunc(glParm, ref);
690 691 692 693
        checkGLcall("glAlphaFunc");
    }
}

694
void state_clipping(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
695
{
696 697
    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
    uint32_t enable_mask;
698

699 700 701 702 703 704 705 706 707 708 709
    if (use_vs(state) && !context->d3d_info->vs_clipping)
    {
        static BOOL warned;

        /* The OpenGL spec says that clipping planes are disabled when using
         * shaders. Direct3D planes aren't, so that is an issue. The MacOS ATI
         * driver keeps clipping planes activated with shaders in some
         * conditions I got sick of tracking down. The shader state handler
         * disables all clip planes because of that - don't do anything here
         * and keep them disabled. */
        if (state->render_states[WINED3D_RS_CLIPPLANEENABLE] && !warned++)
710
            FIXME("Clipping not supported with vertex shaders.\n");
711
        return;
712 713
    }

714 715 716 717
    /* glEnable(GL_CLIP_PLANEx) doesn't apply to (ARB backend) vertex shaders.
     * The enabled / disabled planes are hardcoded into the shader. Update the
     * shader to update the enabled clipplanes. In case of fixed function, we
     * need to update the clipping field from ffp_vertex_settings. */
718
    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
719

720 721 722
    /* If enabling / disabling all
     * TODO: Is this correct? Doesn't D3DRS_CLIPPING disable clipping on the viewport frustrum?
     */
723 724
    enable_mask = state->render_states[WINED3D_RS_CLIPPING] ?
            state->render_states[WINED3D_RS_CLIPPLANEENABLE] : 0;
725
    wined3d_context_gl_enable_clip_distances(context_gl, enable_mask);
726 727
}

728
static void state_specularenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
729
{
730
    const struct wined3d_gl_info *gl_info = context->gl_info;
731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757
    /* Originally this used glLightModeli(GL_LIGHT_MODEL_COLOR_CONTROL,GL_SEPARATE_SPECULAR_COLOR)
     * and (GL_LIGHT_MODEL_COLOR_CONTROL,GL_SINGLE_COLOR) to swap between enabled/disabled
     * specular color. This is wrong:
     * Separate specular color means the specular colour is maintained separately, whereas
     * single color means it is merged in. However in both cases they are being used to
     * some extent.
     * To disable specular color, set it explicitly to black and turn off GL_COLOR_SUM_EXT
     * NOTE: If not supported don't give FIXMEs the impact is really minimal and very few people are
     * running 1.4 yet!
     *
     *
     * If register combiners are enabled, enabling / disabling GL_COLOR_SUM has no effect.
     * Instead, we need to setup the FinalCombiner properly.
     *
     * The default setup for the FinalCombiner is:
     *
     * <variable>       <input>                             <mapping>               <usage>
     * GL_VARIABLE_A_NV GL_FOG,                             GL_UNSIGNED_IDENTITY_NV GL_ALPHA
     * GL_VARIABLE_B_NV GL_SPARE0_PLUS_SECONDARY_COLOR_NV   GL_UNSIGNED_IDENTITY_NV GL_RGB
     * GL_VARIABLE_C_NV GL_FOG                              GL_UNSIGNED_IDENTITY_NV GL_RGB
     * GL_VARIABLE_D_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
     * GL_VARIABLE_E_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
     * GL_VARIABLE_F_NV GL_ZERO                             GL_UNSIGNED_IDENTITY_NV GL_RGB
     * GL_VARIABLE_G_NV GL_SPARE0_NV                        GL_UNSIGNED_IDENTITY_NV GL_ALPHA
     *
     * That's pretty much fine as it is, except for variable B, which needs to take
     * either GL_SPARE0_PLUS_SECONDARY_COLOR_NV or GL_SPARE0_NV, depending on
758
     * whether WINED3D_RS_SPECULARENABLE is enabled or not.
759 760
     */

761
    TRACE("Setting specular enable state and materials\n");
762
    if (state->render_states[WINED3D_RS_SPECULARENABLE])
763
    {
764
        gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&state->material.specular);
765
        checkGLcall("glMaterialfv");
766

767
        if (state->material.power > gl_info->limits.shininess)
768
        {
769
            /* glMaterialf man page says that the material says that GL_SHININESS must be between 0.0
770
             * and 128.0, although in d3d neither -1 nor 129 produce an error. GL_NV_max_light_exponent
771 772
             * allows bigger values. If the extension is supported, gl_info->limits.shininess contains the
             * value reported by the extension, otherwise 128. For values > gl_info->limits.shininess clamp
Austin English's avatar
Austin English committed
773
             * them, it should be safe to do so without major visual distortions.
774
             */
775
            WARN("Material power = %.8e, limit %.8e\n", state->material.power, gl_info->limits.shininess);
776
            gl_info->gl_ops.gl.p_glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, gl_info->limits.shininess);
777 778 779
        }
        else
        {
780
            gl_info->gl_ops.gl.p_glMaterialf(GL_FRONT_AND_BACK, GL_SHININESS, state->material.power);
781
        }
782
        checkGLcall("glMaterialf(GL_SHININESS)");
783

784
        if (gl_info->supported[EXT_SECONDARY_COLOR])
785
            gl_info->gl_ops.gl.p_glEnable(GL_COLOR_SUM_EXT);
786
        else
787 788 789
            TRACE("Specular colors cannot be enabled in this version of opengl\n");
        checkGLcall("glEnable(GL_COLOR_SUM)");

790
        if (gl_info->supported[NV_REGISTER_COMBINERS])
791
        {
792 793 794 795
            GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_PLUS_SECONDARY_COLOR_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
            checkGLcall("glFinalCombinerInputNV()");
        }
    } else {
796
        static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
797 798

        /* for the case of enabled lighting: */
799
        gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
800 801 802
        checkGLcall("glMaterialfv");

        /* for the case of disabled lighting: */
803
        if (gl_info->supported[EXT_SECONDARY_COLOR])
804
            gl_info->gl_ops.gl.p_glDisable(GL_COLOR_SUM_EXT);
805
        else
806 807 808
            TRACE("Specular colors cannot be disabled in this version of opengl\n");
        checkGLcall("glDisable(GL_COLOR_SUM)");

809
        if (gl_info->supported[NV_REGISTER_COMBINERS])
810
        {
811 812 813 814
            GL_EXTCALL(glFinalCombinerInputNV(GL_VARIABLE_B_NV, GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_RGB));
            checkGLcall("glFinalCombinerInputNV()");
        }
    }
815

816 817 818 819
    TRACE("diffuse %s\n", debug_color(&state->material.diffuse));
    TRACE("ambient %s\n", debug_color(&state->material.ambient));
    TRACE("specular %s\n", debug_color(&state->material.specular));
    TRACE("emissive %s\n", debug_color(&state->material.emissive));
820

821
    gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&state->material.ambient);
822
    checkGLcall("glMaterialfv(GL_AMBIENT)");
823
    gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&state->material.diffuse);
824
    checkGLcall("glMaterialfv(GL_DIFFUSE)");
825
    gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&state->material.emissive);
826
    checkGLcall("glMaterialfv(GL_EMISSION)");
827 828
}

829
static void state_texfactor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
830
{
831
    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
832
    const struct wined3d_gl_info *gl_info = context->gl_info;
833
    struct wined3d_color color;
834 835 836
    unsigned int i;

    /* Note the texture color applies to all textures whereas
837
     * GL_TEXTURE_ENV_COLOR applies to active only. */
838
    wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_TEXTUREFACTOR]);
839

840
    /* And now the default texture color as well */
841
    for (i = 0; i < context->d3d_info->limits.ffp_blend_stages; ++i)
842
    {
843 844
        /* Note the WINED3D_RS value applies to all textures, but GL has one
         * per texture, so apply it now ready to be used! */
845
        wined3d_context_gl_active_texture(context_gl, gl_info, i);
846

847
        gl_info->gl_ops.gl.p_glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, &color.r);
848
        checkGLcall("glTexEnvfv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_COLOR, color);");
849 850 851
    }
}

852 853 854
static void renderstate_stencil_twosided(struct wined3d_context *context, GLint face,
        GLint func, GLint ref, GLuint mask, GLint stencilFail, GLint depthFail, GLint stencilPass)
{
855 856
    const struct wined3d_gl_info *gl_info = context->gl_info;

857
    gl_info->gl_ops.gl.p_glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT);
858 859 860
    checkGLcall("glEnable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
    GL_EXTCALL(glActiveStencilFaceEXT(face));
    checkGLcall("glActiveStencilFaceEXT(...)");
861
    gl_info->gl_ops.gl.p_glStencilFunc(func, ref, mask);
862
    checkGLcall("glStencilFunc(...)");
863
    gl_info->gl_ops.gl.p_glStencilOp(stencilFail, depthFail, stencilPass);
864
    checkGLcall("glStencilOp(...)");
865 866
}

867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883
static GLenum gl_stencil_op(enum wined3d_stencil_op op)
{
    switch (op)
    {
        case WINED3D_STENCIL_OP_KEEP:
            return GL_KEEP;
        case WINED3D_STENCIL_OP_ZERO:
            return GL_ZERO;
        case WINED3D_STENCIL_OP_REPLACE:
            return GL_REPLACE;
        case WINED3D_STENCIL_OP_INCR_SAT:
            return GL_INCR;
        case WINED3D_STENCIL_OP_DECR_SAT:
            return GL_DECR;
        case WINED3D_STENCIL_OP_INVERT:
            return GL_INVERT;
        case WINED3D_STENCIL_OP_INCR:
884
            return GL_INCR_WRAP;
885
        case WINED3D_STENCIL_OP_DECR:
886
            return GL_DECR_WRAP;
887
        default:
888 889 890 891
            if (!op)
                WARN("Unrecognized stencil op %#x.\n", op);
            else
                FIXME("Unrecognized stencil op %#x.\n", op);
892 893 894 895
            return GL_KEEP;
    }
}

896
static void state_stencil(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
897
{
898
    const struct wined3d_gl_info *gl_info = context->gl_info;
899 900
    DWORD onesided_enable;
    DWORD twosided_enable;
901
    GLint func;
902
    GLint func_back;
903 904 905
    GLint ref;
    GLuint mask;
    GLint stencilFail;
906
    GLint stencilFail_back;
907
    GLint stencilPass;
908
    GLint stencilPass_back;
909
    GLint depthFail;
910
    GLint depthFail_back;
911

912
    /* No stencil test without a stencil buffer. */
913
    if (!state->fb->depth_stencil)
914
    {
915
        gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST);
916 917 918 919
        checkGLcall("glDisable GL_STENCIL_TEST");
        return;
    }

920 921
    onesided_enable = state->render_states[WINED3D_RS_STENCILENABLE];
    twosided_enable = state->render_states[WINED3D_RS_TWOSIDEDSTENCILMODE];
922
    if (!(func = wined3d_gl_compare_func(state->render_states[WINED3D_RS_STENCILFUNC])))
923
        func = GL_ALWAYS;
924 925
    if (!(func_back = wined3d_gl_compare_func(state->render_states[WINED3D_RS_BACK_STENCILFUNC])))
        func_back = GL_ALWAYS;
926
    mask = state->render_states[WINED3D_RS_STENCILMASK];
927
    ref = state->render_states[WINED3D_RS_STENCILREF] & mask;
928 929 930
    stencilFail = gl_stencil_op(state->render_states[WINED3D_RS_STENCILFAIL]);
    depthFail = gl_stencil_op(state->render_states[WINED3D_RS_STENCILZFAIL]);
    stencilPass = gl_stencil_op(state->render_states[WINED3D_RS_STENCILPASS]);
931 932 933
    stencilFail_back = gl_stencil_op(state->render_states[WINED3D_RS_BACK_STENCILFAIL]);
    depthFail_back = gl_stencil_op(state->render_states[WINED3D_RS_BACK_STENCILZFAIL]);
    stencilPass_back = gl_stencil_op(state->render_states[WINED3D_RS_BACK_STENCILPASS]);
934

935
    TRACE("(onesided %d, twosided %d, ref %x, mask %x, "
936 937 938 939 940
            "GL_FRONT: func: %x, fail %x, zfail %x, zpass %x "
            "GL_BACK: func: %x, fail %x, zfail %x, zpass %x)\n",
            onesided_enable, twosided_enable, ref, mask,
            func, stencilFail, depthFail, stencilPass,
            func_back, stencilFail_back, depthFail_back, stencilPass_back);
941

942 943 944
    if (twosided_enable && onesided_enable)
    {
        gl_info->gl_ops.gl.p_glEnable(GL_STENCIL_TEST);
945 946
        checkGLcall("glEnable GL_STENCIL_TEST");

947 948 949 950
        if (gl_info->supported[WINED3D_GL_VERSION_2_0])
        {
            GL_EXTCALL(glStencilFuncSeparate(GL_FRONT, func, ref, mask));
            GL_EXTCALL(glStencilOpSeparate(GL_FRONT, stencilFail, depthFail, stencilPass));
951 952
            GL_EXTCALL(glStencilFuncSeparate(GL_BACK, func_back, ref, mask));
            GL_EXTCALL(glStencilOpSeparate(GL_BACK, stencilFail_back, depthFail_back, stencilPass_back));
953 954 955
            checkGLcall("setting two sided stencil state");
        }
        else if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
956
        {
957 958 959 960 961 962
            /* Apply back first, then front. This function calls glActiveStencilFaceEXT,
             * which has an effect on the code below too. If we apply the front face
             * afterwards, we are sure that the active stencil face is set to front,
             * and other stencil functions which do not use two sided stencil do not have
             * to set it back
             */
963
            renderstate_stencil_twosided(context, GL_BACK,
964
                    func_back, ref, mask, stencilFail_back, depthFail_back, stencilPass_back);
965 966
            renderstate_stencil_twosided(context, GL_FRONT,
                    func, ref, mask, stencilFail, depthFail, stencilPass);
967
        }
968
        else if (gl_info->supported[ATI_SEPARATE_STENCIL])
969
        {
970
            GL_EXTCALL(glStencilFuncSeparateATI(func, func_back, ref, mask));
971 972 973
            checkGLcall("glStencilFuncSeparateATI(...)");
            GL_EXTCALL(glStencilOpSeparateATI(GL_FRONT, stencilFail, depthFail, stencilPass));
            checkGLcall("glStencilOpSeparateATI(GL_FRONT, ...)");
974
            GL_EXTCALL(glStencilOpSeparateATI(GL_BACK, stencilFail_back, depthFail_back, stencilPass_back));
975
            checkGLcall("glStencilOpSeparateATI(GL_BACK, ...)");
976 977 978
        }
        else
        {
979
            FIXME("Separate (two sided) stencil not supported on this version of OpenGL. Caps weren't honored?\n");
980
        }
981 982 983
    }
    else if(onesided_enable)
    {
984
        if (gl_info->supported[EXT_STENCIL_TWO_SIDE])
985
        {
986
            gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT);
987
            checkGLcall("glDisable(GL_STENCIL_TEST_TWO_SIDE_EXT)");
988
        }
989

990 991 992
        /* This code disables the ATI extension as well, since the standard stencil functions are equal
         * to calling the ATI functions with GL_FRONT_AND_BACK as face parameter
         */
993
        gl_info->gl_ops.gl.p_glEnable(GL_STENCIL_TEST);
994
        checkGLcall("glEnable GL_STENCIL_TEST");
995
        gl_info->gl_ops.gl.p_glStencilFunc(func, ref, mask);
996
        checkGLcall("glStencilFunc(...)");
997
        gl_info->gl_ops.gl.p_glStencilOp(stencilFail, depthFail, stencilPass);
998
        checkGLcall("glStencilOp(...)");
999 1000 1001 1002
    }
    else
    {
        gl_info->gl_ops.gl.p_glDisable(GL_STENCIL_TEST);
1003
        checkGLcall("glDisable GL_STENCIL_TEST");
1004 1005 1006
    }
}

1007
static void state_stencilwrite2s_ext(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1008
{
1009
    DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0;
1010
    const struct wined3d_gl_info *gl_info = context->gl_info;
1011

1012 1013
    GL_EXTCALL(glActiveStencilFaceEXT(GL_BACK));
    checkGLcall("glActiveStencilFaceEXT(GL_BACK)");
1014
    gl_info->gl_ops.gl.p_glStencilMask(mask);
1015 1016 1017
    checkGLcall("glStencilMask");
    GL_EXTCALL(glActiveStencilFaceEXT(GL_FRONT));
    checkGLcall("glActiveStencilFaceEXT(GL_FRONT)");
1018
    gl_info->gl_ops.gl.p_glStencilMask(mask);
1019 1020
}

1021
static void state_stencilwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1022
{
1023
    DWORD mask = state->fb->depth_stencil ? state->render_states[WINED3D_RS_STENCILWRITEMASK] : 0;
1024
    const struct wined3d_gl_info *gl_info = context->gl_info;
1025

1026
    gl_info->gl_ops.gl.p_glStencilMask(mask);
1027 1028 1029
    checkGLcall("glStencilMask");
}

1030
static void state_fog_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1031
{
1032
    const struct wined3d_gl_info *gl_info = context->gl_info;
1033

1034
    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
1035

1036
    if (!state->render_states[WINED3D_RS_FOGENABLE])
1037
        return;
1038 1039

    /* Table fog on: Never use fog coords, and use per-fragment fog */
1040
    if (state->render_states[WINED3D_RS_FOGTABLEMODE] != WINED3D_FOG_NONE)
1041
    {
1042 1043 1044 1045
        gl_info->gl_ops.gl.p_glHint(GL_FOG_HINT, GL_NICEST);
        if (context->fog_coord)
        {
            gl_info->gl_ops.gl.p_glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1046 1047 1048
            checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
            context->fog_coord = FALSE;
        }
1049 1050 1051 1052

        /* Range fog is only used with per-vertex fog in d3d */
        if (gl_info->supported[NV_FOG_DISTANCE])
        {
1053
            gl_info->gl_ops.gl.p_glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1054 1055
            checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
        }
1056 1057 1058 1059
        return;
    }

    /* Otherwise use per-vertex fog in any case */
1060
    gl_info->gl_ops.gl.p_glHint(GL_FOG_HINT, GL_FASTEST);
1061

1062
    if (state->render_states[WINED3D_RS_FOGVERTEXMODE] == WINED3D_FOG_NONE || context->last_was_rhw)
1063
    {
1064
        /* No fog at all, or transformed vertices: Use fog coord */
1065 1066 1067
        if (!context->fog_coord)
        {
            gl_info->gl_ops.gl.p_glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT);
1068 1069 1070
            checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FOG_COORDINATE_EXT)");
            context->fog_coord = TRUE;
        }
1071 1072 1073
    }
    else
    {
1074
        /* Otherwise, use the fragment depth */
1075 1076 1077
        if (context->fog_coord)
        {
            gl_info->gl_ops.gl.p_glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT);
1078 1079 1080
            checkGLcall("glFogi(GL_FOG_COORDINATE_SOURCE_EXT, GL_FRAGMENT_DEPTH_EXT)");
            context->fog_coord = FALSE;
        }
1081

1082
        if (state->render_states[WINED3D_RS_RANGEFOGENABLE])
1083 1084 1085
        {
            if (gl_info->supported[NV_FOG_DISTANCE])
            {
1086
                gl_info->gl_ops.gl.p_glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV);
1087 1088 1089 1090 1091 1092 1093 1094 1095
                checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_RADIAL_NV)");
            }
            else
            {
                WARN("Range fog enabled, but not supported by this GL implementation.\n");
            }
        }
        else if (gl_info->supported[NV_FOG_DISTANCE])
        {
1096
            gl_info->gl_ops.gl.p_glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
1097 1098
            checkGLcall("glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV)");
        }
1099 1100
    }
}
1101

1102
void state_fogstartend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1103
{
1104
    const struct wined3d_gl_info *gl_info = context->gl_info;
1105 1106
    float fogstart, fogend;

1107
    get_fog_start_end(context, state, &fogstart, &fogend);
1108

1109
    gl_info->gl_ops.gl.p_glFogf(GL_FOG_START, fogstart);
1110 1111 1112
    checkGLcall("glFogf(GL_FOG_START, fogstart)");
    TRACE("Fog Start == %f\n", fogstart);

1113
    gl_info->gl_ops.gl.p_glFogf(GL_FOG_END, fogend);
1114 1115 1116 1117
    checkGLcall("glFogf(GL_FOG_END, fogend)");
    TRACE("Fog End == %f\n", fogend);
}

1118
void state_fog_fragpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1119
{
1120
    const struct wined3d_gl_info *gl_info = context->gl_info;
1121
    enum fogsource new_source;
1122 1123
    DWORD fogstart = state->render_states[WINED3D_RS_FOGSTART];
    DWORD fogend = state->render_states[WINED3D_RS_FOGEND];
1124

1125
    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
1126

1127
    if (!state->render_states[WINED3D_RS_FOGENABLE])
1128
    {
1129
        /* No fog? Disable it, and we're done :-) */
1130
        gl_info->p_glDisableWINE(GL_FOG);
1131
        checkGLcall("glDisable GL_FOG");
1132
        return;
1133 1134
    }

1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152
    /* Fog Rules:
     *
     * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
     * It can use the Z value of the vertex, or the alpha component of the specular color.
     * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
     * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
     * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
     *
     * FOGTABLEMODE != NONE:
     *  The Z value is used, with the equation specified, no matter what vertex type.
     *
     * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
     *  Per vertex fog is calculated using the specified fog equation and the parameters
     *
     * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
     * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
     *  Linear fog with start = 255.0, end = 0.0, input comes from the specular color
     *
1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165
     *
     * Rules for vertex fog with shaders:
     *
     * When mixing fixed function functionality with the programmable pipeline, D3D expects
     * the fog computation to happen during transformation while openGL expects it to happen
     * during rasterization. Also, prior to pixel shader 3.0 D3D handles fog blending after
     * the pixel shader while openGL always expects the pixel shader to handle the blending.
     * To solve this problem, WineD3D does:
     * 1) implement a linear fog equation and fog blending at the end of every pre 3.0 pixel
     * shader,
     * and 2) disables the fog computation (in either the fixed function or programmable
     * rasterizer) if using a vertex program.
     *
1166 1167 1168 1169 1170 1171 1172
     * D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with
     * D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear
     * fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in
     * the specular color, a vertex shader counts as pretransformed geometry in this case.
     * There are some GL differences between specular fog coords and vertex shaders though.
     *
     * With table fog the vertex shader fog coordinate is ignored.
1173 1174 1175
     *
     * If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
     * without shaders).
1176
     */
1177

1178 1179 1180
    /* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
     * the system will apply only pixel(=table) fog effects."
     */
1181
    if (state->render_states[WINED3D_RS_FOGTABLEMODE] == WINED3D_FOG_NONE)
1182
    {
1183 1184
        if (use_vs(state))
        {
1185
            gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
1186 1187
            checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
            new_source = FOGSOURCE_VS;
1188 1189 1190
        }
        else
        {
1191
            switch (state->render_states[WINED3D_RS_FOGVERTEXMODE])
1192
            {
1193
                /* If processed vertices are used, fall through to the NONE case */
1194 1195 1196
                case WINED3D_FOG_EXP:
                    if (!context->last_was_rhw)
                    {
1197
                        gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP);
1198 1199 1200 1201 1202 1203
                        checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
                        new_source = FOGSOURCE_FFP;
                        break;
                    }
                    /* drop through */

1204 1205 1206
                case WINED3D_FOG_EXP2:
                    if (!context->last_was_rhw)
                    {
1207
                        gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP2);
1208 1209 1210 1211 1212 1213
                        checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
                        new_source = FOGSOURCE_FFP;
                        break;
                    }
                    /* drop through */

1214 1215 1216
                case WINED3D_FOG_LINEAR:
                    if (!context->last_was_rhw)
                    {
1217
                        gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
1218 1219 1220 1221 1222
                        checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
                        new_source = FOGSOURCE_FFP;
                        break;
                    }
                    /* drop through */
1223

1224
                case WINED3D_FOG_NONE:
1225 1226 1227 1228
                    /* Both are none? According to msdn the alpha channel of
                     * the specular colour contains a fog factor. Set it in
                     * draw_primitive_immediate_mode(). Same happens with
                     * vertex fog on transformed vertices. */
1229
                    new_source = FOGSOURCE_COORD;
1230
                    gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
1231
                    checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1232
                    break;
1233

1234
                default:
1235 1236
                    FIXME("Unexpected WINED3D_RS_FOGVERTEXMODE %#x.\n",
                            state->render_states[WINED3D_RS_FOGVERTEXMODE]);
1237 1238
                    new_source = FOGSOURCE_FFP; /* Make the compiler happy */
            }
1239 1240
        }
    } else {
1241
        new_source = FOGSOURCE_FFP;
1242

1243
        switch (state->render_states[WINED3D_RS_FOGTABLEMODE])
1244
        {
1245
            case WINED3D_FOG_EXP:
1246
                gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP);
1247
                checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
1248 1249
                break;

1250
            case WINED3D_FOG_EXP2:
1251
                gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_EXP2);
1252
                checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
1253 1254
                break;

1255
            case WINED3D_FOG_LINEAR:
1256
                gl_info->gl_ops.gl.p_glFogi(GL_FOG_MODE, GL_LINEAR);
1257
                checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
1258 1259
                break;

1260
            case WINED3D_FOG_NONE:   /* Won't happen */
1261
            default:
1262 1263
                FIXME("Unexpected WINED3D_RS_FOGTABLEMODE %#x.\n",
                        state->render_states[WINED3D_RS_FOGTABLEMODE]);
1264 1265 1266
        }
    }

1267
    gl_info->p_glEnableWINE(GL_FOG);
1268
    checkGLcall("glEnable GL_FOG");
1269
    if (new_source != context->fog_source || fogstart == fogend)
1270
    {
1271
        context->fog_source = new_source;
1272
        state_fogstartend(context, state, STATE_RENDER(WINED3D_RS_FOGSTART));
1273
    }
1274
}
1275

1276
void state_fogcolor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1277
{
1278
    const struct wined3d_gl_info *gl_info = context->gl_info;
1279
    struct wined3d_color color;
1280

1281 1282
    wined3d_color_from_d3dcolor(&color, state->render_states[WINED3D_RS_FOGCOLOR]);
    gl_info->gl_ops.gl.p_glFogfv(GL_FOG_COLOR, &color.r);
1283 1284 1285
    checkGLcall("glFog GL_FOG_COLOR");
}

1286
void state_fogdensity(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1287
{
1288
    const struct wined3d_gl_info *gl_info = context->gl_info;
1289 1290 1291 1292
    union {
        DWORD d;
        float f;
    } tmpvalue;
1293

1294
    tmpvalue.d = state->render_states[WINED3D_RS_FOGDENSITY];
1295
    gl_info->gl_ops.gl.p_glFogfv(GL_FOG_DENSITY, &tmpvalue.f);
1296 1297 1298
    checkGLcall("glFogf(GL_FOG_DENSITY, (float) Value)");
}

1299
static void state_colormat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1300
{
1301 1302
    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
    const struct wined3d_gl_info *gl_info = context_gl->c.gl_info;
1303
    GLenum Parm = 0;
1304

1305 1306 1307 1308
    /* Depends on the decoded vertex declaration to read the existence of
     * diffuse data. The vertex declaration will call this function if the
     * fixed function pipeline is used. */
    if (isStateDirty(&context_gl->c, STATE_VDECL))
1309 1310
        return;

1311 1312
    context_gl->untracked_material_count = 0;
    if ((context_gl->c.stream_info.use_map & (1u << WINED3D_FFP_DIFFUSE))
1313
            && state->render_states[WINED3D_RS_COLORVERTEX])
1314
    {
1315
        TRACE("diff %d, amb %d, emis %d, spec %d\n",
1316 1317 1318 1319
                state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE],
                state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE],
                state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE],
                state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE]);
1320

1321
        if (state->render_states[WINED3D_RS_DIFFUSEMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1322
        {
1323
            if (state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1324
                Parm = GL_AMBIENT_AND_DIFFUSE;
1325
            else
1326
                Parm = GL_DIFFUSE;
1327
            if (state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1328
                context_gl->untracked_materials[context_gl->untracked_material_count++] = GL_EMISSION;
1329
            if (state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1330
                context_gl->untracked_materials[context_gl->untracked_material_count++] = GL_SPECULAR;
1331
        }
1332
        else if (state->render_states[WINED3D_RS_AMBIENTMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1333
        {
1334
            Parm = GL_AMBIENT;
1335
            if (state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1336
                context_gl->untracked_materials[context_gl->untracked_material_count++] = GL_EMISSION;
1337
            if (state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1338
                context_gl->untracked_materials[context_gl->untracked_material_count++] = GL_SPECULAR;
1339
        }
1340
        else if (state->render_states[WINED3D_RS_EMISSIVEMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1341
        {
1342
            Parm = GL_EMISSION;
1343
            if (state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1344
                context_gl->untracked_materials[context_gl->untracked_material_count++] = GL_SPECULAR;
1345
        }
1346
        else if (state->render_states[WINED3D_RS_SPECULARMATERIALSOURCE] == WINED3D_MCS_COLOR1)
1347
        {
1348 1349
            Parm = GL_SPECULAR;
        }
1350
    }
1351

1352
    /* Nothing changed, return. */
1353 1354
    if (Parm == context_gl->tracking_parm)
        return;
1355

1356 1357 1358
    if (!Parm)
    {
        gl_info->gl_ops.gl.p_glDisable(GL_COLOR_MATERIAL);
1359
        checkGLcall("glDisable GL_COLOR_MATERIAL");
1360 1361 1362 1363
    }
    else
    {
        gl_info->gl_ops.gl.p_glColorMaterial(GL_FRONT_AND_BACK, Parm);
1364
        checkGLcall("glColorMaterial(GL_FRONT_AND_BACK, Parm)");
1365
        gl_info->gl_ops.gl.p_glEnable(GL_COLOR_MATERIAL);
1366
        checkGLcall("glEnable(GL_COLOR_MATERIAL)");
1367
    }
1368 1369 1370

    /* Apparently calls to glMaterialfv are ignored for properties we're
     * tracking with glColorMaterial, so apply those here. */
1371
    switch (context_gl->tracking_parm)
1372
    {
1373
        case GL_AMBIENT_AND_DIFFUSE:
1374 1375
            gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&state->material.ambient);
            gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&state->material.diffuse);
1376 1377 1378 1379
            checkGLcall("glMaterialfv");
            break;

        case GL_DIFFUSE:
1380
            gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, (float *)&state->material.diffuse);
1381 1382 1383 1384
            checkGLcall("glMaterialfv");
            break;

        case GL_AMBIENT:
1385
            gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT, (float *)&state->material.ambient);
1386 1387 1388 1389
            checkGLcall("glMaterialfv");
            break;

        case GL_EMISSION:
1390
            gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, (float *)&state->material.emissive);
1391 1392 1393 1394 1395
            checkGLcall("glMaterialfv");
            break;

        case GL_SPECULAR:
            /* Only change material color if specular is enabled, otherwise it is set to black */
1396
            if (state->render_states[WINED3D_RS_SPECULARENABLE])
1397
            {
1398
                gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, (float *)&state->material.specular);
1399
                checkGLcall("glMaterialfv");
1400 1401 1402
            }
            else
            {
1403
                static const GLfloat black[] = {0.0f, 0.0f, 0.0f, 0.0f};
1404
                gl_info->gl_ops.gl.p_glMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, &black[0]);
1405 1406 1407 1408 1409
                checkGLcall("glMaterialfv");
            }
            break;
    }

1410
    context_gl->tracking_parm = Parm;
1411 1412
}

1413
static void state_linepattern(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1414
{
1415
    const struct wined3d_gl_info *gl_info = context->gl_info;
1416 1417 1418 1419
    union
    {
        DWORD d;
        struct wined3d_line_pattern lp;
1420
    } tmppattern;
1421
    tmppattern.d = state->render_states[WINED3D_RS_LINEPATTERN];
1422

1423
    TRACE("Line pattern: repeat %d bits %x.\n", tmppattern.lp.repeat_factor, tmppattern.lp.line_pattern);
1424

1425 1426
    if (tmppattern.lp.repeat_factor)
    {
1427
        gl_info->gl_ops.gl.p_glLineStipple(tmppattern.lp.repeat_factor, tmppattern.lp.line_pattern);
1428
        checkGLcall("glLineStipple(repeat, linepattern)");
1429
        gl_info->gl_ops.gl.p_glEnable(GL_LINE_STIPPLE);
1430
        checkGLcall("glEnable(GL_LINE_STIPPLE);");
1431 1432 1433
    }
    else
    {
1434
        gl_info->gl_ops.gl.p_glDisable(GL_LINE_STIPPLE);
1435 1436 1437 1438
        checkGLcall("glDisable(GL_LINE_STIPPLE);");
    }
}

1439 1440 1441 1442 1443 1444 1445 1446
static void state_linepattern_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
    static unsigned int once;

    if (!once++)
        FIXME("Setting line patterns is not supported in OpenGL core contexts.\n");
}

1447
static void state_normalize(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1448
{
1449 1450
    const struct wined3d_gl_info *gl_info = context->gl_info;

1451
    if (isStateDirty(context, STATE_VDECL))
1452
        return;
1453

1454 1455 1456 1457
    /* Without vertex normals, we set the current normal to 0/0/0 to remove the diffuse factor
     * from the opengl lighting equation, as d3d does. Normalization of 0/0/0 can lead to a division
     * by zero and is not properly defined in opengl, so avoid it
     */
1458
    if (state->render_states[WINED3D_RS_NORMALIZENORMALS]
1459
            && (context->stream_info.use_map & (1u << WINED3D_FFP_NORMAL)))
1460
    {
1461
        gl_info->gl_ops.gl.p_glEnable(GL_NORMALIZE);
1462
        checkGLcall("glEnable(GL_NORMALIZE);");
1463 1464 1465
    }
    else
    {
1466
        gl_info->gl_ops.gl.p_glDisable(GL_NORMALIZE);
1467 1468 1469 1470
        checkGLcall("glDisable(GL_NORMALIZE);");
    }
}

1471
static void state_psizemin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1472
{
1473
    float min, max;
1474

1475
    get_pointsize_minmax(context, state, &min, &max);
1476

1477 1478 1479 1480
    if (min != 1.0f)
        FIXME("WINED3D_RS_POINTSIZE_MIN value %.8e not supported on this OpenGL implementation.\n", min);
    if (max != 64.0f)
        FIXME("WINED3D_RS_POINTSIZE_MAX value %.8e not supported on this OpenGL implementation.\n", max);
1481 1482
}

1483
static void state_psizemin_ext(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1484
{
1485
    const struct wined3d_gl_info *gl_info = context->gl_info;
1486
    float min, max;
1487

1488
    get_pointsize_minmax(context, state, &min, &max);
1489

1490
    GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MIN_EXT, min);
1491
    checkGLcall("glPointParameterfEXT(...)");
1492
    GL_EXTCALL(glPointParameterfEXT)(GL_POINT_SIZE_MAX_EXT, max);
1493 1494 1495
    checkGLcall("glPointParameterfEXT(...)");
}

1496
static void state_psizemin_arb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1497
{
1498
    const struct wined3d_gl_info *gl_info = context->gl_info;
1499
    float min, max;
1500

1501
    get_pointsize_minmax(context, state, &min, &max);
1502

1503
    GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MIN_ARB, min);
1504
    checkGLcall("glPointParameterfARB(...)");
1505
    GL_EXTCALL(glPointParameterfARB)(GL_POINT_SIZE_MAX_ARB, max);
1506
    checkGLcall("glPointParameterfARB(...)");
1507 1508
}

1509
static void state_pscale(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1510
{
1511
    const struct wined3d_gl_info *gl_info = context->gl_info;
1512 1513
    float att[3];
    float pointsize;
1514

1515
    get_pointsize(context, state, &pointsize, att);
1516

1517
    if (gl_info->supported[ARB_POINT_PARAMETERS])
1518
    {
1519
        GL_EXTCALL(glPointParameterfvARB)(GL_POINT_DISTANCE_ATTENUATION_ARB, att);
1520
        checkGLcall("glPointParameterfvARB(GL_DISTANCE_ATTENUATION_ARB, ...)");
1521
    }
1522
    else if (gl_info->supported[EXT_POINT_PARAMETERS])
1523
    {
1524
        GL_EXTCALL(glPointParameterfvEXT)(GL_DISTANCE_ATTENUATION_EXT, att);
1525
        checkGLcall("glPointParameterfvEXT(GL_DISTANCE_ATTENUATION_EXT, ...)");
1526
    }
1527
    else if (state->render_states[WINED3D_RS_POINTSCALEENABLE])
1528
    {
1529
        WARN("POINT_PARAMETERS not supported in this version of opengl\n");
1530
    }
1531

1532
    gl_info->gl_ops.gl.p_glPointSize(max(pointsize, FLT_MIN));
1533
    checkGLcall("glPointSize(...);");
1534 1535
}

1536
static void state_debug_monitor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1537
{
1538
    WARN("token: %#x.\n", state->render_states[WINED3D_RS_DEBUGMONITORTOKEN]);
1539 1540
}

1541
static void state_colorwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1542
{
1543 1544 1545 1546
    DWORD mask0 = state->render_states[WINED3D_RS_COLORWRITEENABLE];
    DWORD mask1 = state->render_states[WINED3D_RS_COLORWRITEENABLE1];
    DWORD mask2 = state->render_states[WINED3D_RS_COLORWRITEENABLE2];
    DWORD mask3 = state->render_states[WINED3D_RS_COLORWRITEENABLE3];
1547
    const struct wined3d_gl_info *gl_info = context->gl_info;
1548 1549

    TRACE("Color mask: r(%d) g(%d) b(%d) a(%d)\n",
1550 1551 1552 1553
            mask0 & WINED3DCOLORWRITEENABLE_RED ? 1 : 0,
            mask0 & WINED3DCOLORWRITEENABLE_GREEN ? 1 : 0,
            mask0 & WINED3DCOLORWRITEENABLE_BLUE ? 1 : 0,
            mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? 1 : 0);
1554
    gl_info->gl_ops.gl.p_glColorMask(mask0 & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
1555 1556 1557
            mask0 & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
            mask0 & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
            mask0 & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE);
1558 1559
    checkGLcall("glColorMask(...)");

1560 1561 1562
    if (!((mask1 == mask0 && mask2 == mask0 && mask3 == mask0)
        || (mask1 == 0xf && mask2 == 0xf && mask3 == 0xf)))
    {
1563
        FIXME("WINED3D_RS_COLORWRITEENABLE/1/2/3, %#x/%#x/%#x/%#x not yet implemented.\n",
1564 1565
            mask0, mask1, mask2, mask3);
        FIXME("Missing of cap D3DPMISCCAPS_INDEPENDENTWRITEMASKS wasn't honored?\n");
1566 1567 1568
    }
}

1569
static void set_color_mask(const struct wined3d_gl_info *gl_info, UINT index, DWORD mask)
1570
{
1571
    GL_EXTCALL(glColorMaski(index,
1572 1573 1574 1575
            mask & WINED3DCOLORWRITEENABLE_RED ? GL_TRUE : GL_FALSE,
            mask & WINED3DCOLORWRITEENABLE_GREEN ? GL_TRUE : GL_FALSE,
            mask & WINED3DCOLORWRITEENABLE_BLUE ? GL_TRUE : GL_FALSE,
            mask & WINED3DCOLORWRITEENABLE_ALPHA ? GL_TRUE : GL_FALSE));
1576
    checkGLcall("glColorMaski");
1577 1578
}

1579
static void state_colorwrite0(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1580
{
1581
    set_color_mask(context->gl_info, 0, state->render_states[WINED3D_RS_COLORWRITEENABLE]);
1582 1583
}

1584
static void state_colorwrite1(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1585
{
1586
    set_color_mask(context->gl_info, 1, state->render_states[WINED3D_RS_COLORWRITEENABLE1]);
1587 1588
}

1589
static void state_colorwrite2(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1590
{
1591
    set_color_mask(context->gl_info, 2, state->render_states[WINED3D_RS_COLORWRITEENABLE2]);
1592 1593
}

1594
static void state_colorwrite3(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1595
{
1596
    set_color_mask(context->gl_info, 3, state->render_states[WINED3D_RS_COLORWRITEENABLE3]);
1597 1598
}

1599
static void state_localviewer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1600
{
1601 1602
    const struct wined3d_gl_info *gl_info = context->gl_info;

1603
    if (state->render_states[WINED3D_RS_LOCALVIEWER])
1604
    {
1605
        gl_info->gl_ops.gl.p_glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1);
1606
        checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 1)");
1607 1608 1609 1610
    }
    else
    {
        gl_info->gl_ops.gl.p_glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0);
1611 1612 1613 1614
        checkGLcall("glLightModeli(GL_LIGHT_MODEL_LOCAL_VIEWER, 0)");
    }
}

1615
static void state_lastpixel(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1616
{
1617
    if (state->render_states[WINED3D_RS_LASTPIXEL])
1618
    {
1619
        TRACE("Last Pixel Drawing Enabled\n");
1620 1621 1622
    }
    else
    {
1623 1624
        static BOOL warned;
        if (!warned) {
1625
            FIXME("Last Pixel Drawing Disabled, not handled yet\n");
1626
            warned = TRUE;
1627 1628 1629
        } else {
            TRACE("Last Pixel Drawing Disabled, not handled yet\n");
        }
1630 1631 1632
    }
}

1633
void state_pointsprite_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1634
{
1635 1636
    static BOOL warned;

1637
    /* TODO: NV_POINT_SPRITE */
1638
    if (!warned && state->render_states[WINED3D_RS_POINTSPRITEENABLE])
1639
    {
1640 1641 1642
        /* A FIXME, not a WARN because point sprites should be software emulated if not supported by HW */
        FIXME("Point sprites not supported\n");
        warned = TRUE;
1643
    }
1644
}
1645

1646
void state_pointsprite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1647
{
1648 1649
    const struct wined3d_gl_info *gl_info = context->gl_info;

1650
    if (state->render_states[WINED3D_RS_POINTSPRITEENABLE])
1651
    {
1652
        gl_info->gl_ops.gl.p_glEnable(GL_POINT_SPRITE_ARB);
1653
        checkGLcall("glEnable(GL_POINT_SPRITE_ARB)");
1654 1655 1656 1657
    }
    else
    {
        gl_info->gl_ops.gl.p_glDisable(GL_POINT_SPRITE_ARB);
1658
        checkGLcall("glDisable(GL_POINT_SPRITE_ARB)");
1659 1660 1661
    }
}

1662
static void state_wrap(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1663
{
1664 1665 1666
    static unsigned int once;

    if ((state->render_states[WINED3D_RS_WRAP0]
1667 1668 1669 1670 1671 1672 1673 1674 1675 1676 1677 1678 1679 1680 1681
            || state->render_states[WINED3D_RS_WRAP1]
            || state->render_states[WINED3D_RS_WRAP2]
            || state->render_states[WINED3D_RS_WRAP3]
            || state->render_states[WINED3D_RS_WRAP4]
            || state->render_states[WINED3D_RS_WRAP5]
            || state->render_states[WINED3D_RS_WRAP6]
            || state->render_states[WINED3D_RS_WRAP7]
            || state->render_states[WINED3D_RS_WRAP8]
            || state->render_states[WINED3D_RS_WRAP9]
            || state->render_states[WINED3D_RS_WRAP10]
            || state->render_states[WINED3D_RS_WRAP11]
            || state->render_states[WINED3D_RS_WRAP12]
            || state->render_states[WINED3D_RS_WRAP13]
            || state->render_states[WINED3D_RS_WRAP14]
            || state->render_states[WINED3D_RS_WRAP15])
1682
            && !once++)
1683
        FIXME("(WINED3D_RS_WRAP0) Texture wrapping not yet supported.\n");
1684 1685
}

1686
static void state_msaa_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1687
{
1688
    if (state->render_states[WINED3D_RS_MULTISAMPLEANTIALIAS])
1689
        WARN("Multisample antialiasing not supported by GL.\n");
1690 1691
}

1692
static void state_msaa(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1693
{
1694 1695
    const struct wined3d_gl_info *gl_info = context->gl_info;

1696
    if (state->render_states[WINED3D_RS_MULTISAMPLEANTIALIAS])
1697
    {
1698
        gl_info->gl_ops.gl.p_glEnable(GL_MULTISAMPLE_ARB);
1699
        checkGLcall("glEnable(GL_MULTISAMPLE_ARB)");
1700 1701 1702 1703
    }
    else
    {
        gl_info->gl_ops.gl.p_glDisable(GL_MULTISAMPLE_ARB);
1704
        checkGLcall("glDisable(GL_MULTISAMPLE_ARB)");
1705 1706 1707
    }
}

1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723 1724
static void state_line_antialias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
    const struct wined3d_gl_info *gl_info = context->gl_info;

    if (state->render_states[WINED3D_RS_EDGEANTIALIAS]
            || state->render_states[WINED3D_RS_ANTIALIASEDLINEENABLE])
    {
        gl_info->gl_ops.gl.p_glEnable(GL_LINE_SMOOTH);
        checkGLcall("glEnable(GL_LINE_SMOOTH)");
    }
    else
    {
        gl_info->gl_ops.gl.p_glDisable(GL_LINE_SMOOTH);
        checkGLcall("glDisable(GL_LINE_SMOOTH)");
    }
}

1725
static void state_scissor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1726
{
1727 1728
    const struct wined3d_gl_info *gl_info = context->gl_info;

1729
    if (state->render_states[WINED3D_RS_SCISSORTESTENABLE])
1730
    {
1731
        gl_info->gl_ops.gl.p_glEnable(GL_SCISSOR_TEST);
1732
        checkGLcall("glEnable(GL_SCISSOR_TEST)");
1733 1734 1735 1736
    }
    else
    {
        gl_info->gl_ops.gl.p_glDisable(GL_SCISSOR_TEST);
1737 1738 1739 1740
        checkGLcall("glDisable(GL_SCISSOR_TEST)");
    }
}

1741 1742 1743 1744
/* The Direct3D depth bias is specified in normalized depth coordinates. In
 * OpenGL the bias is specified in units of "the smallest value that is
 * guaranteed to produce a resolvable offset for a given implementation". To
 * convert from D3D to GL we need to divide the D3D depth bias by that value.
1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755
 * We try to detect the value from GL with test draws. On most drivers (r300g,
 * 600g, Nvidia, i965 on Mesa) the value is 2^23 for fixed point depth buffers,
 * for r200 and i965 on OSX it is 2^24, for r500 on OSX it is 2^22. For floating
 * point buffers it is 2^22, 2^23 or 2^24 depending on the GPU. The value does
 * not depend on the depth buffer precision on any driver.
 *
 * Two games that are picky regarding depth bias are Mass Effect 2 (flickering
 * decals) and F.E.A.R and F.E.A.R. 2 (semi-transparent guns).
 *
 * Note that SLOPESCALEDEPTHBIAS is a scaling factor for the depth slope, and
 * doesn't need to be scaled to account for GL vs D3D differences. */
1756
static void state_depthbias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1757
{
1758 1759
    const struct wined3d_gl_info *gl_info = context->gl_info;

1760 1761
    if (state->render_states[WINED3D_RS_SLOPESCALEDEPTHBIAS]
            || state->render_states[WINED3D_RS_DEPTHBIAS])
1762
    {
1763
        const struct wined3d_rendertarget_view *depth = state->fb->depth_stencil;
1764
        float factor, units, scale, clamp;
1765

1766 1767 1768 1769 1770 1771
        union
        {
            DWORD d;
            float f;
        } scale_bias, const_bias;

1772
        clamp = state->rasterizer_state ? state->rasterizer_state->desc.depth_bias_clamp : 0.0f;
1773 1774
        scale_bias.d = state->render_states[WINED3D_RS_SLOPESCALEDEPTHBIAS];
        const_bias.d = state->render_states[WINED3D_RS_DEPTHBIAS];
1775

1776
        if (context->d3d_info->wined3d_creation_flags & WINED3D_LEGACY_DEPTH_BIAS)
1777
        {
1778
            factor = units = -(float)const_bias.d;
1779 1780 1781
        }
        else
        {
1782 1783
            if (depth)
            {
1784
                scale = depth->format->depth_bias_scale;
1785

1786
                TRACE("Depth format %s, using depthbias scale of %.8e.\n",
1787
                        debug_d3dformat(depth->format->id), scale);
1788 1789 1790 1791
            }
            else
            {
                /* The context manager will reapply this state on a depth stencil change */
1792
                TRACE("No depth stencil, using depth bias scale of 0.0.\n");
1793 1794
                scale = 0.0f;
            }
1795

1796 1797
            factor = scale_bias.f;
            units = const_bias.f * scale;
1798
        }
1799 1800

        gl_info->gl_ops.gl.p_glEnable(GL_POLYGON_OFFSET_FILL);
1801 1802 1803 1804 1805 1806 1807 1808 1809 1810
        if (gl_info->supported[ARB_POLYGON_OFFSET_CLAMP])
        {
            gl_info->gl_ops.ext.p_glPolygonOffsetClamp(factor, units, clamp);
        }
        else
        {
            if (clamp != 0.0f)
                WARN("Ignoring depth bias clamp %.8e.\n", clamp);
            gl_info->gl_ops.gl.p_glPolygonOffset(factor, units);
        }
1811 1812 1813
    }
    else
    {
1814
        gl_info->gl_ops.gl.p_glDisable(GL_POLYGON_OFFSET_FILL);
1815
    }
1816 1817

    checkGLcall("depth bias");
1818 1819
}

1820
static void state_zvisible(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1821
{
1822 1823
    if (state->render_states[WINED3D_RS_ZVISIBLE])
        FIXME("WINED3D_RS_ZVISIBLE not implemented.\n");
1824 1825
}

1826
static void state_stippledalpha(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1827
{
1828
    if (state->render_states[WINED3D_RS_STIPPLEDALPHA])
1829
        FIXME("Stippled Alpha not supported yet.\n");
1830 1831
}

1832
static void state_antialias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1833
{
1834
    if (state->render_states[WINED3D_RS_ANTIALIAS])
1835
        FIXME("Antialias not supported yet.\n");
1836 1837
}

1838
static void state_multisampmask(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1839
{
1840 1841 1842
    if (state->render_states[WINED3D_RS_MULTISAMPLEMASK] != 0xffffffff)
        FIXME("WINED3D_RS_MULTISAMPLEMASK %#x not yet implemented.\n",
                state->render_states[WINED3D_RS_MULTISAMPLEMASK]);
1843 1844
}

1845
static void state_patchedgestyle(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1846
{
1847
    if (state->render_states[WINED3D_RS_PATCHEDGESTYLE] != WINED3D_PATCH_EDGE_DISCRETE)
1848 1849
        FIXME("WINED3D_RS_PATCHEDGESTYLE %#x not yet implemented.\n",
                state->render_states[WINED3D_RS_PATCHEDGESTYLE]);
1850 1851
}

1852
static void state_patchsegments(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1853
{
1854 1855 1856 1857 1858 1859
    union {
        DWORD d;
        float f;
    } tmpvalue;
    tmpvalue.f = 1.0f;

1860
    if (state->render_states[WINED3D_RS_PATCHSEGMENTS] != tmpvalue.d)
1861
    {
1862 1863
        static BOOL displayed = FALSE;

1864
        tmpvalue.d = state->render_states[WINED3D_RS_PATCHSEGMENTS];
1865
        if(!displayed)
1866
            FIXME("(WINED3D_RS_PATCHSEGMENTS,%f) not yet implemented\n", tmpvalue.f);
1867 1868

        displayed = TRUE;
1869
    }
1870 1871
}

1872
static void state_positiondegree(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1873
{
1874 1875 1876
    if (state->render_states[WINED3D_RS_POSITIONDEGREE] != WINED3D_DEGREE_CUBIC)
        FIXME("WINED3D_RS_POSITIONDEGREE %#x not yet implemented.\n",
                state->render_states[WINED3D_RS_POSITIONDEGREE]);
1877 1878
}

1879
static void state_normaldegree(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1880
{
1881 1882 1883
    if (state->render_states[WINED3D_RS_NORMALDEGREE] != WINED3D_DEGREE_LINEAR)
        FIXME("WINED3D_RS_NORMALDEGREE %#x not yet implemented.\n",
                state->render_states[WINED3D_RS_NORMALDEGREE]);
1884 1885
}

1886
static void state_tessellation(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1887
{
1888 1889 1890
    if (state->render_states[WINED3D_RS_ENABLEADAPTIVETESSELLATION])
        FIXME("WINED3D_RS_ENABLEADAPTIVETESSELLATION %#x not yet implemented.\n",
                state->render_states[WINED3D_RS_ENABLEADAPTIVETESSELLATION]);
1891 1892
}

1893
static void state_nvdb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1894 1895 1896 1897 1898 1899 1900 1901
{
    union {
        DWORD d;
        float f;
    } zmin, zmax;

    const struct wined3d_gl_info *gl_info = context->gl_info;

1902
    if (state->render_states[WINED3D_RS_ADAPTIVETESS_X] == WINED3DFMT_NVDB)
1903
    {
1904 1905
        zmin.d = state->render_states[WINED3D_RS_ADAPTIVETESS_Z];
        zmax.d = state->render_states[WINED3D_RS_ADAPTIVETESS_W];
1906 1907 1908 1909 1910

        /* If zmin is larger than zmax INVALID_VALUE error is generated.
         * In d3d9 test is not performed in this case*/
        if (zmin.f <= zmax.f)
        {
1911
            gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_BOUNDS_TEST_EXT);
1912 1913 1914 1915
            checkGLcall("glEnable(GL_DEPTH_BOUNDS_TEST_EXT)");
            GL_EXTCALL(glDepthBoundsEXT(zmin.f, zmax.f));
            checkGLcall("glDepthBoundsEXT(...)");
        }
1916 1917 1918
        else
        {
            gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_BOUNDS_TEST_EXT);
1919 1920 1921
            checkGLcall("glDisable(GL_DEPTH_BOUNDS_TEST_EXT)");
        }
    }
1922 1923 1924
    else
    {
        gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_BOUNDS_TEST_EXT);
1925 1926 1927
        checkGLcall("glDisable(GL_DEPTH_BOUNDS_TEST_EXT)");
    }

1928
    state_tessellation(context, state, STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION));
1929 1930
}

1931
static void state_wrapu(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1932
{
1933 1934
    if (state->render_states[WINED3D_RS_WRAPU])
        FIXME("Render state WINED3D_RS_WRAPU not implemented yet.\n");
1935 1936
}

1937
static void state_wrapv(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1938
{
1939 1940
    if (state->render_states[WINED3D_RS_WRAPV])
        FIXME("Render state WINED3D_RS_WRAPV not implemented yet.\n");
1941 1942
}

1943
static void state_monoenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1944
{
1945 1946
    if (state->render_states[WINED3D_RS_MONOENABLE])
        FIXME("Render state WINED3D_RS_MONOENABLE not implemented yet.\n");
1947 1948
}

1949
static void state_rop2(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1950
{
1951 1952
    if (state->render_states[WINED3D_RS_ROP2])
        FIXME("Render state WINED3D_RS_ROP2 not implemented yet.\n");
1953 1954
}

1955
static void state_planemask(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1956
{
1957 1958
    if (state->render_states[WINED3D_RS_PLANEMASK])
        FIXME("Render state WINED3D_RS_PLANEMASK not implemented yet.\n");
1959 1960
}

1961
static void state_subpixel(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1962
{
1963 1964
    if (state->render_states[WINED3D_RS_SUBPIXEL])
        FIXME("Render state WINED3D_RS_SUBPIXEL not implemented yet.\n");
1965 1966
}

1967
static void state_subpixelx(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1968
{
1969 1970
    if (state->render_states[WINED3D_RS_SUBPIXELX])
        FIXME("Render state WINED3D_RS_SUBPIXELX not implemented yet.\n");
1971 1972
}

1973
static void state_stippleenable(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1974
{
1975 1976
    if (state->render_states[WINED3D_RS_STIPPLEENABLE])
        FIXME("Render state WINED3D_RS_STIPPLEENABLE not implemented yet.\n");
1977 1978
}

1979
static void state_mipmaplodbias(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1980
{
1981 1982
    if (state->render_states[WINED3D_RS_MIPMAPLODBIAS])
        FIXME("Render state WINED3D_RS_MIPMAPLODBIAS not implemented yet.\n");
1983 1984
}

1985
static void state_anisotropy(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1986
{
1987 1988
    if (state->render_states[WINED3D_RS_ANISOTROPY])
        FIXME("Render state WINED3D_RS_ANISOTROPY not implemented yet.\n");
1989 1990
}

1991
static void state_flushbatch(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1992
{
1993 1994
    if (state->render_states[WINED3D_RS_FLUSHBATCH])
        FIXME("Render state WINED3D_RS_FLUSHBATCH not implemented yet.\n");
1995 1996
}

1997
static void state_translucentsi(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
1998
{
1999 2000
    if (state->render_states[WINED3D_RS_TRANSLUCENTSORTINDEPENDENT])
        FIXME("Render state WINED3D_RS_TRANSLUCENTSORTINDEPENDENT not implemented yet.\n");
2001 2002
}

2003
static void state_extents(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
2004
{
2005 2006
    if (state->render_states[WINED3D_RS_EXTENTS])
        FIXME("Render state WINED3D_RS_EXTENTS not implemented yet.\n");
2007 2008
}

2009
static void state_ckeyblend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
2010
{
2011 2012
    if (state->render_states[WINED3D_RS_COLORKEYBLENDENABLE])
        FIXME("Render state WINED3D_RS_COLORKEYBLENDENABLE not implemented yet.\n");
2013 2014
}

2015
static void state_swvp(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
2016
{
2017
    static int once;
2018
    if (state->render_states[WINED3D_RS_SOFTWAREVERTEXPROCESSING])
2019 2020 2021 2022
    {
        if (!once++)
            FIXME("Software vertex processing not implemented.\n");
    }
2023 2024
}

2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063
static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) {
    /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the
    * input should be used for all input components. The WINED3DTA_COMPLEMENT
    * flag specifies the complement of the input should be used. */
    BOOL from_alpha = is_alpha || arg & WINED3DTA_ALPHAREPLICATE;
    BOOL complement = arg & WINED3DTA_COMPLEMENT;

    /* Calculate the operand */
    if (complement) {
        if (from_alpha) *operand = GL_ONE_MINUS_SRC_ALPHA;
        else *operand = GL_ONE_MINUS_SRC_COLOR;
    } else {
        if (from_alpha) *operand = GL_SRC_ALPHA;
        else *operand = GL_SRC_COLOR;
    }

    /* Calculate the source */
    switch (arg & WINED3DTA_SELECTMASK) {
        case WINED3DTA_CURRENT: *source = GL_PREVIOUS_EXT; break;
        case WINED3DTA_DIFFUSE: *source = GL_PRIMARY_COLOR_EXT; break;
        case WINED3DTA_TEXTURE: *source = GL_TEXTURE; break;
        case WINED3DTA_TFACTOR: *source = GL_CONSTANT_EXT; break;
        case WINED3DTA_SPECULAR:
            /*
            * According to the GL_ARB_texture_env_combine specs, SPECULAR is
            * 'Secondary color' and isn't supported until base GL supports it
            * There is no concept of temp registers as far as I can tell
            */
            FIXME("Unhandled texture arg WINED3DTA_SPECULAR\n");
            *source = GL_TEXTURE;
            break;
        default:
            FIXME("Unrecognized texture arg %#x\n", arg);
            *source = GL_TEXTURE;
            break;
    }
}

/* Setup the texture operations texture stage states */
2064
static void set_tex_op(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state,
2065
        BOOL isAlpha, int Stage, enum wined3d_texture_op op, DWORD arg1, DWORD arg2, DWORD arg3)
2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 2076 2077
{
    GLenum src1, src2, src3;
    GLenum opr1, opr2, opr3;
    GLenum comb_target;
    GLenum src0_target, src1_target, src2_target;
    GLenum opr0_target, opr1_target, opr2_target;
    GLenum scal_target;
    GLenum opr=0, invopr, src3_target, opr3_target;
    BOOL Handled = FALSE;

    TRACE("Alpha?(%d), Stage:%d Op(%s), a1(%d), a2(%d), a3(%d)\n", isAlpha, Stage, debug_d3dtop(op), arg1, arg2, arg3);

2078 2079 2080 2081 2082 2083 2084 2085 2086 2087 2088
    /* Operations usually involve two args, src0 and src1 and are operations
     * of the form (a1 <operation> a2). However, some of the more complex
     * operations take 3 parameters. Instead of the (sensible) addition of a3,
     * Microsoft added in a third parameter called a0. Therefore these are
     * operations of the form a0 <operation> a1 <operation> a2. I.e., the new
     * parameter goes to the front.
     *
     * However, below we treat the new (a0) parameter as src2/opr2, so in the
     * actual functions below, expect their syntax to differ slightly to those
     * listed in the manuals. I.e., replace arg1 with arg3, arg2 with arg1 and
     * arg3 with arg2. This affects WINED3DTOP_MULTIPLYADD and WINED3DTOP_LERP. */
2089

2090 2091 2092 2093 2094 2095 2096 2097 2098
    if (isAlpha)
    {
        comb_target = GL_COMBINE_ALPHA;
        src0_target = GL_SOURCE0_ALPHA;
        src1_target = GL_SOURCE1_ALPHA;
        src2_target = GL_SOURCE2_ALPHA;
        opr0_target = GL_OPERAND0_ALPHA;
        opr1_target = GL_OPERAND1_ALPHA;
        opr2_target = GL_OPERAND2_ALPHA;
2099 2100
        scal_target = GL_ALPHA_SCALE;
    }
2101 2102 2103 2104 2105 2106 2107 2108 2109 2110
    else
    {
        comb_target = GL_COMBINE_RGB;
        src0_target = GL_SOURCE0_RGB;
        src1_target = GL_SOURCE1_RGB;
        src2_target = GL_SOURCE2_RGB;
        opr0_target = GL_OPERAND0_RGB;
        opr1_target = GL_OPERAND1_RGB;
        opr2_target = GL_OPERAND2_RGB;
        scal_target = GL_RGB_SCALE;
2111 2112 2113 2114
    }

        /* If a texture stage references an invalid texture unit the stage just
        * passes through the result from the previous stage */
2115
    if (is_invalid_op(state, Stage, op, arg1, arg2, arg3))
2116
    {
2117
        arg1 = WINED3DTA_CURRENT;
2118
        op = WINED3D_TOP_SELECT_ARG1;
2119 2120
    }

2121
    if (isAlpha && !state->textures[Stage] && arg1 == WINED3DTA_TEXTURE)
2122
    {
2123 2124 2125 2126 2127 2128 2129 2130 2131 2132 2133 2134
        get_src_and_opr(WINED3DTA_DIFFUSE, isAlpha, &src1, &opr1);
    } else {
        get_src_and_opr(arg1, isAlpha, &src1, &opr1);
    }
    get_src_and_opr(arg2, isAlpha, &src2, &opr2);
    get_src_and_opr(arg3, isAlpha, &src3, &opr3);

    TRACE("ct(%x), 1:(%x,%x), 2:(%x,%x), 3:(%x,%x)\n", comb_target, src1, opr1, src2, opr2, src3, opr3);

    Handled = TRUE; /* Assume will be handled */

    /* Other texture operations require special extensions: */
2135
    if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
2136
    {
2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147
        if (isAlpha) {
            opr = GL_SRC_ALPHA;
            invopr = GL_ONE_MINUS_SRC_ALPHA;
            src3_target = GL_SOURCE3_ALPHA_NV;
            opr3_target = GL_OPERAND3_ALPHA_NV;
        } else {
            opr = GL_SRC_COLOR;
            invopr = GL_ONE_MINUS_SRC_COLOR;
            src3_target = GL_SOURCE3_RGB_NV;
            opr3_target = GL_OPERAND3_RGB_NV;
        }
2148 2149 2150
        switch (op)
        {
            case WINED3D_TOP_DISABLE: /* Only for alpha */
2151
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2152
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2153
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2154
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2155
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2156
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2157
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2158
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2159
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2160
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2161
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2162
                checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
2163
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2164
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2165
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2166
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179 2180 2181 2182 2183 2184 2185 2186 2187 2188 2189 2190 2191 2192 2193 2194 2195 2196 2197 2198 2199
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
                break;

            case WINED3D_TOP_SELECT_ARG1: /* = a1 * 1 + 0 * 0 */
            case WINED3D_TOP_SELECT_ARG2: /* = a2 * 1 + 0 * 0 */
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
                if (op == WINED3D_TOP_SELECT_ARG1)
                {
                    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
                    checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
                    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
                    checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
                }
                else
                {
                    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
                    checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
                    gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
                    checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
                }
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
                checkGLcall("GL_TEXTURE_ENV, src2_target, GL_ZERO");
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2200 2201 2202
                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
                break;

2203
            case WINED3D_TOP_MODULATE:
2204
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2205
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2206
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2207
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2208
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2209
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2210
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2211
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2212
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2213
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2214
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2215
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2216
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2217
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2218
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2219
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2220
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2221
                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2222
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2223 2224
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;
2225
            case WINED3D_TOP_MODULATE_2X:
2226
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2227
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2228
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2229
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2230
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2231
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2232
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2233
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2234
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2235
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2236
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2237
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2238
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2239
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2240
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2241
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2242
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2243
                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2244
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2245 2246
                checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
                break;
2247
            case WINED3D_TOP_MODULATE_4X:
2248
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2249
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD"); /* Add = a0*a1 + a2*a3 */
2250
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2251
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2252
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2253
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2254
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2255
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2256
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2257
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2258
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_ZERO);
2259
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2260
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2261
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2262
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2263
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2264
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2265
                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr1");
2266
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2267 2268 2269
                checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
                break;

2270
            case WINED3D_TOP_ADD:
2271
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2272
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2273
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2274
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2275
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2276
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2277
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2278
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2279
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2280
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2281
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2282
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2283
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2284
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2285
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2286
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2287
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2288
                checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2289
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2290 2291 2292
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;

2293
            case WINED3D_TOP_ADD_SIGNED:
2294
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
2295
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
2296
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2297
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2298
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2299
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2300
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2301
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2302
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2303
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2304
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2305
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2306
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2307
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2308
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2309
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2310
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2311
                checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2312
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2313 2314 2315
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;

2316
            case WINED3D_TOP_ADD_SIGNED_2X:
2317
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
2318
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
2319
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2320
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2321
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2322
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2323
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2324
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2325
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2326
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2327
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2328
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2329
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2330
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2331
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2332
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2333
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2334
                checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2335
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2336 2337 2338
                checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
                break;

2339
            case WINED3D_TOP_ADD_SMOOTH:
2340
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2341
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2342
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2343
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2344
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2345
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2346
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2347
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2348
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2349
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2350
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2351
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2352
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2353
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2354
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2355 2356 2357 2358 2359 2360 2361
                checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
                switch (opr1) {
                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
                }
2362
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2363
                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2364
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2365 2366 2367
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;

2368
            case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
2369
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2370
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2371
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2372
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2373
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2374
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2375
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_PRIMARY_COLOR);
2376
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_PRIMARY_COLOR");
2377
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2378
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2379
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2380
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2381
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2382
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2383
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_PRIMARY_COLOR);
2384
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_PRIMARY_COLOR");
2385
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2386
                checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2387
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2388 2389
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;
2390
            case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
2391
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2392
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2393
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2394
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2395
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2396
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2397
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_TEXTURE);
2398
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_TEXTURE");
2399
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2400
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2401
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2402
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2403
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2404
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2405
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2406
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2407
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2408
                checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2409
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2410 2411
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;
2412
            case WINED3D_TOP_BLEND_FACTOR_ALPHA:
2413
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2414
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2415
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2416
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2417
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2418
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2419
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_CONSTANT);
2420
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_CONSTANT");
2421
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2422
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2423
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2424
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2425
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2426
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2427
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_CONSTANT);
2428
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_CONSTANT");
2429
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2430
                checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2431
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2432 2433
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;
2434
            case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
2435
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2436
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2437
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2438
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2439
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2440
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2441
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2442
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2443
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2444
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2445
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2446
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2447
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2448
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2449
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_TEXTURE);
2450
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_TEXTURE");
2451
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA);
2452
                checkGLcall("GL_TEXTURE_ENV, opr3_target, GL_ONE_MINUS_SRC_ALPHA");
2453
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2454 2455
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;
2456
            case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
2457 2458 2459
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");                 /* Add = a0*a1 + a2*a3 */
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);  /*  a0 = src1/opr1     */
2460
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2461 2462 2463
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");                   /*  a1 = 1 (see docs)  */
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2464
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2465
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2466
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2467
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);  /*  a2 = arg2          */
2468
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2469 2470 2471
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");                   /*  a3 = src1 alpha    */
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2472 2473 2474 2475 2476
                checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
                switch (opr) {
                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                }
2477
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2478
                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2479
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2480 2481
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;
2482
            case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
2483
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2484
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2485
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2486
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2487
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2488
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2489
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2490
                checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2491
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2492
                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2493
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2494 2495 2496 2497 2498
                checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
                switch (opr1) {
                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                }
2499
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2500
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2501
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2502
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2503
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2504
                checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2505
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2506 2507
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;
2508
            case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
2509
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2510
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2511
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2512
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2513
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2514
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2515
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2516
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2517
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2518
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2519
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2520
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2521
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2522
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2523
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src1);
2524 2525 2526 2527 2528 2529 2530
                checkGLcall("GL_TEXTURE_ENV, src3_target, src1");
                switch (opr1) {
                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
                }
2531
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr);
2532
                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr");
2533
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2534 2535
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;
2536
            case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
2537
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2538
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2539
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2540 2541 2542 2543 2544 2545 2546
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
                switch (opr1) {
                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
                }
2547
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2548
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2549
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2550
                checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2551
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2552
                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2553
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2554 2555 2556 2557 2558
                checkGLcall("GL_TEXTURE_ENV, src2_target, src1");
                switch (opr1) {
                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                }
2559
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr);
2560
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr");
2561
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, GL_ZERO);
2562
                checkGLcall("GL_TEXTURE_ENV, src3_target, GL_ZERO");
2563
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, invopr);
2564
                checkGLcall("GL_TEXTURE_ENV, opr3_target, invopr");
2565
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2566 2567
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;
2568
            case WINED3D_TOP_MULTIPLY_ADD:
2569
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2570
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2571
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src3);
2572
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2573
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr3);
2574
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2575
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, GL_ZERO);
2576
                checkGLcall("GL_TEXTURE_ENV, src1_target, GL_ZERO");
2577
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, invopr);
2578
                checkGLcall("GL_TEXTURE_ENV, opr1_target, invopr");
2579
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src1);
2580
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2581
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr1);
2582
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2583
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src3_target, src2);
2584
                checkGLcall("GL_TEXTURE_ENV, src3_target, src3");
2585
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr3_target, opr2);
2586
                checkGLcall("GL_TEXTURE_ENV, opr3_target, opr3");
2587
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2588 2589 2590
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
                break;

2591 2592
            case WINED3D_TOP_BUMPENVMAP:
            case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
2593
                FIXME("Implement bump environment mapping in GL_NV_texture_env_combine4 path\n");
2594 2595
                Handled = FALSE;
                break;
2596 2597 2598 2599

            default:
                Handled = FALSE;
        }
2600 2601 2602
        if (Handled)
        {
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV);
2603 2604 2605 2606 2607 2608 2609 2610
            checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE4_NV");

            return;
        }
    } /* GL_NV_texture_env_combine4 */

    Handled = TRUE; /* Again, assume handled */
    switch (op) {
2611
        case WINED3D_TOP_DISABLE: /* Only for alpha */
2612
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2613
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2614
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT);
2615
            checkGLcall("GL_TEXTURE_ENV, src0_target, GL_PREVIOUS_EXT");
2616
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA);
2617
            checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_SRC_ALPHA");
2618
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2619 2620
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2621
        case WINED3D_TOP_SELECT_ARG1:
2622
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2623
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2624
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2625
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2626
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2627
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2628
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2629 2630
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2631
        case WINED3D_TOP_SELECT_ARG2:
2632
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_REPLACE);
2633
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_REPLACE");
2634
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src2);
2635
            checkGLcall("GL_TEXTURE_ENV, src0_target, src2");
2636
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr2);
2637
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr2");
2638
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2639 2640
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2641
        case WINED3D_TOP_MODULATE:
2642
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2643
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2644
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2645
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2646
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2647
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2648
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2649
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2650
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2651
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2652
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2653 2654
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2655
        case WINED3D_TOP_MODULATE_2X:
2656
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2657
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2658
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2659
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2660
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2661
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2662
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2663
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2664
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2665
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2666
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2667 2668
            checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
            break;
2669
        case WINED3D_TOP_MODULATE_4X:
2670
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE);
2671
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE");
2672
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2673
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2674
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2675
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2676
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2677
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2678
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2679
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2680
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 4);
2681 2682
            checkGLcall("GL_TEXTURE_ENV, scal_target, 4");
            break;
2683
        case WINED3D_TOP_ADD:
2684
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD);
2685
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD");
2686
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2687
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2688
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2689
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2690
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2691
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2692
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2693
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2694
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2695 2696
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2697
        case WINED3D_TOP_ADD_SIGNED:
2698
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
2699
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
2700
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2701
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2702
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2703
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2704
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2705
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2706
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2707
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2708
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2709 2710
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2711
        case WINED3D_TOP_ADD_SIGNED_2X:
2712
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED);
2713
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_ADD_SIGNED");
2714
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2715
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2716
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2717
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2718
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2719
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2720
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2721
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2722
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 2);
2723 2724
            checkGLcall("GL_TEXTURE_ENV, scal_target, 2");
            break;
2725
        case WINED3D_TOP_SUBTRACT:
2726
            if (gl_info->supported[ARB_TEXTURE_ENV_COMBINE])
2727
            {
2728
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_SUBTRACT);
2729
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_SUBTRACT");
2730
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2731
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2732
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2733
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2734
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2735
                checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2736
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2737
                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2738
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2739 2740 2741 2742 2743 2744
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            } else {
                FIXME("This version of opengl does not support GL_SUBTRACT\n");
            }
            break;

2745
        case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
2746
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
2747
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
2748
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2749
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2750
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2751
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2752
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2753
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2754
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2755
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2756
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR);
2757
            checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PRIMARY_COLOR");
2758
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2759
            checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2760
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2761 2762
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2763
        case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
2764
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
2765
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
2766
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2767
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2768
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2769
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2770
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2771
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2772
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2773
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2774
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_TEXTURE);
2775
            checkGLcall("GL_TEXTURE_ENV, src2_target, GL_TEXTURE");
2776
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2777
            checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2778
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2779 2780
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2781
        case WINED3D_TOP_BLEND_FACTOR_ALPHA:
2782
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
2783
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
2784
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2785
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2786
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2787
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2788
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2789
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2790
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2791
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2792
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_CONSTANT);
2793
            checkGLcall("GL_TEXTURE_ENV, src2_target, GL_CONSTANT");
2794
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2795
            checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2796
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2797 2798
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2799
        case WINED3D_TOP_BLEND_CURRENT_ALPHA:
2800
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
2801
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
2802
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2803
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2804
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2805
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2806
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2807
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2808
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2809
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2810
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, GL_PREVIOUS);
2811
            checkGLcall("GL_TEXTURE_ENV, src2_target, GL_PREVIOUS");
2812
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA);
2813
            checkGLcall("GL_TEXTURE_ENV, opr2_target, GL_SRC_ALPHA");
2814
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2815 2816
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2817
        case WINED3D_TOP_DOTPRODUCT3:
2818
            if (gl_info->supported[ARB_TEXTURE_ENV_DOT3])
2819
            {
2820
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB);
2821
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_ARB");
2822
            }
2823
            else if (gl_info->supported[EXT_TEXTURE_ENV_DOT3])
2824
            {
2825
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT);
2826 2827 2828 2829
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_DOT3_RGBA_EXT");
            } else {
                FIXME("This version of opengl does not support GL_DOT3\n");
            }
2830
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2831
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2832
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2833
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2834
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2835
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2836
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2837
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2838
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2839 2840
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2841
        case WINED3D_TOP_LERP:
2842
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE);
2843
            checkGLcall("GL_TEXTURE_ENV, comb_target, GL_INTERPOLATE");
2844
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2845
            checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2846
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2847
            checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2848
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src2);
2849
            checkGLcall("GL_TEXTURE_ENV, src1_target, src2");
2850
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr2);
2851
            checkGLcall("GL_TEXTURE_ENV, opr1_target, opr2");
2852
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src3);
2853
            checkGLcall("GL_TEXTURE_ENV, src2_target, src3");
2854
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr3);
2855
            checkGLcall("GL_TEXTURE_ENV, opr2_target, opr3");
2856
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2857 2858
            checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            break;
2859
        case WINED3D_TOP_ADD_SMOOTH:
2860
            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2861
            {
2862
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2863
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2864
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2865 2866 2867 2868 2869 2870 2871
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
                switch (opr1) {
                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
                }
2872
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2873
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2874
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2875
                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2876
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2877
                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2878
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2879
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2880
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2881
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2882
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2883 2884 2885
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            } else
                Handled = FALSE;
2886
            break;
2887
        case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
2888
            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2889
            {
2890
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2891
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2892
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, GL_TEXTURE);
2893
                checkGLcall("GL_TEXTURE_ENV, src0_target, GL_TEXTURE");
2894
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_ALPHA);
2895
                checkGLcall("GL_TEXTURE_ENV, opr0_target, GL_ONE_MINUS_SRC_APHA");
2896
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2897
                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2898
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2899
                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2900
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2901
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2902
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2903
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2904
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2905 2906 2907
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            } else
                Handled = FALSE;
2908
            break;
2909
        case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
2910
            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2911
            {
2912
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2913
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2914
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2915 2916 2917 2918 2919 2920 2921
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
                switch (opr1) {
                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                    case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                }
2922
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2923
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2924
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2925
                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2926
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2927
                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2928
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2929
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2930
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2931
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2932
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2933 2934 2935
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            } else
                Handled = FALSE;
2936
            break;
2937
        case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
2938
            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2939
            {
2940
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2941
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2942
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2943
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
2944
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
2945
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
2946
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2947 2948 2949 2950 2951 2952 2953
                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
                switch (opr1) {
                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                    case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                }
2954
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
2955
                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
2956
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2957
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2958
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2959
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2960
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2961 2962 2963
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            } else
                Handled = FALSE;
2964
            break;
2965
        case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
2966
            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2967
            {
2968
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2969
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2970
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2971 2972 2973 2974 2975 2976 2977
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
                switch (opr1) {
                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_ALPHA; break;
                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
                }
2978
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
2979
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
2980
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
2981
                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
2982
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr1);
2983
                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr1");
2984
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
2985
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
2986
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
2987
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
2988
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
2989 2990 2991
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            } else
                Handled = FALSE;
2992
            break;
2993
        case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
2994
            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
2995
            {
2996
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
2997
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
2998
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
2999 3000 3001 3002 3003 3004 3005
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
                switch (opr1) {
                    case GL_SRC_COLOR: opr = GL_ONE_MINUS_SRC_COLOR; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_SRC_COLOR; break;
                    case GL_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
                }
3006
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr);
3007
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr");
3008
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src1);
3009 3010 3011 3012 3013 3014 3015
                checkGLcall("GL_TEXTURE_ENV, src1_target, src1");
                switch (opr1) {
                    case GL_SRC_COLOR: opr = GL_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_COLOR: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                    case GL_SRC_ALPHA: opr = GL_SRC_ALPHA; break;
                    case GL_ONE_MINUS_SRC_ALPHA: opr = GL_ONE_MINUS_SRC_ALPHA; break;
                }
3016
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr);
3017
                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr");
3018
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
3019
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
3020
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
3021
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
3022
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
3023 3024 3025
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            } else
                Handled = FALSE;
3026
            break;
3027
        case WINED3D_TOP_MULTIPLY_ADD:
3028
            if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3])
3029
            {
3030
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI);
3031
                checkGLcall("GL_TEXTURE_ENV, comb_target, GL_MODULATE_ADD_ATI");
3032
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src0_target, src1);
3033
                checkGLcall("GL_TEXTURE_ENV, src0_target, src1");
3034
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr0_target, opr1);
3035
                checkGLcall("GL_TEXTURE_ENV, opr0_target, opr1");
3036
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src1_target, src3);
3037
                checkGLcall("GL_TEXTURE_ENV, src1_target, src3");
3038
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr1_target, opr3);
3039
                checkGLcall("GL_TEXTURE_ENV, opr1_target, opr3");
3040
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, src2_target, src2);
3041
                checkGLcall("GL_TEXTURE_ENV, src2_target, src2");
3042
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, opr2_target, opr2);
3043
                checkGLcall("GL_TEXTURE_ENV, opr2_target, opr2");
3044
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, scal_target, 1);
3045 3046 3047
                checkGLcall("GL_TEXTURE_ENV, scal_target, 1");
            } else
                Handled = FALSE;
3048
            break;
3049 3050
        case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
        case WINED3D_TOP_BUMPENVMAP:
3051
            if (gl_info->supported[NV_TEXTURE_SHADER2])
3052
            {
3053 3054 3055 3056 3057
                /* Technically texture shader support without register combiners is possible, but not expected to occur
                 * on real world cards, so for now a fixme should be enough
                 */
                FIXME("Implement bump mapping with GL_NV_texture_shader in non register combiner path\n");
            }
3058 3059 3060
            Handled = FALSE;
            break;

3061 3062 3063 3064 3065 3066
        default:
            Handled = FALSE;
    }

    if (Handled) {
        BOOL  combineOK = TRUE;
3067
        if (gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
3068
        {
3069 3070
            DWORD op2;

3071
            if (isAlpha)
3072
                op2 = state->texture_states[Stage][WINED3D_TSS_COLOR_OP];
3073
            else
3074
                op2 = state->texture_states[Stage][WINED3D_TSS_ALPHA_OP];
3075 3076

            /* Note: If COMBINE4 in effect can't go back to combine! */
3077 3078 3079 3080 3081 3082 3083 3084 3085
            switch (op2)
            {
                case WINED3D_TOP_ADD_SMOOTH:
                case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
                case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
                case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
                case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
                case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
                case WINED3D_TOP_MULTIPLY_ADD:
3086
                    /* Ignore those implemented in both cases */
3087 3088 3089 3090
                    switch (op)
                    {
                        case WINED3D_TOP_SELECT_ARG1:
                        case WINED3D_TOP_SELECT_ARG2:
3091 3092 3093 3094 3095 3096 3097 3098 3099 3100
                            combineOK = FALSE;
                            Handled   = FALSE;
                            break;
                        default:
                            FIXME("Can't use COMBINE4 and COMBINE together, thisop=%s, otherop=%s, isAlpha(%d)\n", debug_d3dtop(op), debug_d3dtop(op2), isAlpha);
                            return;
                    }
            }
        }

3101 3102
        if (combineOK)
        {
3103
            gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE);
3104
            checkGLcall("GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE");
3105 3106 3107 3108 3109 3110 3111 3112 3113 3114

            return;
        }
    }

    /* After all the extensions, if still unhandled, report fixme */
    FIXME("Unhandled texture operation %s\n", debug_d3dtop(op));
}


3115
static void tex_colorop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3116
{
3117
    unsigned int stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3118
    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
3119
    BOOL tex_used = context->fixed_function_usage_map & (1u << stage);
3120
    unsigned int mapped_stage = context_gl->tex_unit_map[stage];
3121
    const struct wined3d_gl_info *gl_info = context->gl_info;
3122 3123 3124

    TRACE("Setting color op for stage %d\n", stage);

3125
    /* Using a pixel shader? Don't care for anything here, the shader applying does it */
3126
    if (use_ps(state)) return;
3127

3128 3129
    if (stage != mapped_stage) WARN("Using non 1:1 mapping: %d -> %d!\n", stage, mapped_stage);

3130 3131
    if (mapped_stage != WINED3D_UNMAPPED_STAGE)
    {
3132
        if (tex_used && mapped_stage >= gl_info->limits.textures)
3133
        {
3134
            FIXME("Attempt to enable unsupported stage!\n");
3135 3136
            return;
        }
3137
        wined3d_context_gl_active_texture(context_gl, gl_info, mapped_stage);
3138 3139
    }

3140
    if (stage >= context->lowest_disabled_stage)
3141
    {
3142
        TRACE("Stage disabled\n");
3143 3144
        if (mapped_stage != WINED3D_UNMAPPED_STAGE)
        {
3145
            /* Disable everything here */
3146
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
3147
            checkGLcall("glDisable(GL_TEXTURE_2D)");
3148
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
3149
            checkGLcall("glDisable(GL_TEXTURE_3D)");
3150
            if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
3151
            {
3152
                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
3153 3154
                checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
            }
3155
            if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
3156
            {
3157
                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
3158 3159
                checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
            }
3160
        }
3161 3162 3163 3164
        /* All done */
        return;
    }

3165 3166 3167
    /* The sampler will also activate the correct texture dimensions, so no
     * need to do it here if the sampler for this stage is dirty. */
    if (!isStateDirty(context, STATE_SAMPLER(stage)) && tex_used)
3168
        texture_activate_dimensions(state->textures[stage], gl_info);
3169

3170
    set_tex_op(gl_info, state, FALSE, stage,
3171 3172 3173 3174
            state->texture_states[stage][WINED3D_TSS_COLOR_OP],
            state->texture_states[stage][WINED3D_TSS_COLOR_ARG1],
            state->texture_states[stage][WINED3D_TSS_COLOR_ARG2],
            state->texture_states[stage][WINED3D_TSS_COLOR_ARG0]);
3175 3176
}

3177
void tex_alphaop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3178
{
3179
    unsigned int stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3180
    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
3181
    BOOL tex_used = context->fixed_function_usage_map & (1u << stage);
3182
    unsigned int mapped_stage = context_gl->tex_unit_map[stage];
3183
    const struct wined3d_gl_info *gl_info = context->gl_info;
3184
    DWORD op, arg1, arg2, arg0;
3185 3186

    TRACE("Setting alpha op for stage %d\n", stage);
3187
    /* Do not care for enabled / disabled stages, just assign the settings. colorop disables / enables required stuff */
3188 3189
    if (mapped_stage != WINED3D_UNMAPPED_STAGE)
    {
3190
        if (tex_used && mapped_stage >= gl_info->limits.textures)
3191
        {
3192
            FIXME("Attempt to enable unsupported stage!\n");
3193 3194
            return;
        }
3195
        wined3d_context_gl_active_texture(context_gl, gl_info, mapped_stage);
3196 3197
    }

3198 3199 3200 3201
    op = state->texture_states[stage][WINED3D_TSS_ALPHA_OP];
    arg1 = state->texture_states[stage][WINED3D_TSS_ALPHA_ARG1];
    arg2 = state->texture_states[stage][WINED3D_TSS_ALPHA_ARG2];
    arg0 = state->texture_states[stage][WINED3D_TSS_ALPHA_ARG0];
3202

3203
    if (state->render_states[WINED3D_RS_COLORKEYENABLE] && !stage && state->textures[0])
3204
    {
3205 3206
        struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(state->textures[0]);
        GLenum texture_dimensions = texture_gl->target;
3207 3208 3209

        if (texture_dimensions == GL_TEXTURE_2D || texture_dimensions == GL_TEXTURE_RECTANGLE_ARB)
        {
3210 3211
            if (texture_gl->t.async.color_key_flags & WINED3D_CKEY_SRC_BLT
                    && !texture_gl->t.resource.format->alpha_size)
3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234
            {
                /* Color keying needs to pass alpha values from the texture through to have the alpha test work
                 * properly. On the other hand applications can still use texture combiners apparently. This code
                 * takes care that apps cannot remove the texture's alpha channel entirely.
                 *
                 * The fixup is required for Prince of Persia 3D(prison bars), while Moto racer 2 requires
                 * D3DTOP_MODULATE to work on color keyed surfaces. Aliens vs Predator 1 uses color keyed textures
                 * and alpha component of diffuse color to draw things like translucent text and perform other
                 * blending effects.
                 *
                 * Aliens vs Predator 1 relies on diffuse alpha having an effect, so it cannot be ignored. To
                 * provide the behavior expected by the game, while emulating the colorkey, diffuse alpha must be
                 * modulated with texture alpha. OTOH, Moto racer 2 at some points sets alphaop/alphaarg to
                 * SELECTARG/CURRENT, yet puts garbage in diffuse alpha (zeroes). This works on native, because the
                 * game disables alpha test and alpha blending. Alpha test is overwritten by wine's for purposes of
                 * color-keying though, so this will lead to missing geometry if texture alpha is modulated (pixels
                 * fail alpha test). To get around this, ALPHABLENDENABLE state is checked: if the app enables alpha
                 * blending, it can be expected to provide meaningful values in diffuse alpha, so it should be
                 * modulated with texture alpha; otherwise, selecting diffuse alpha is ignored in favour of texture
                 * alpha.
                 *
                 * What to do with multitexturing? So far no app has been found that uses color keying with
                 * multitexturing */
3235
                if (op == WINED3D_TOP_DISABLE)
3236
                {
3237
                    arg1 = WINED3DTA_TEXTURE;
3238
                    op = WINED3D_TOP_SELECT_ARG1;
3239
                }
3240
                else if (op == WINED3D_TOP_SELECT_ARG1 && arg1 != WINED3DTA_TEXTURE)
3241
                {
3242
                    if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
3243 3244
                    {
                        arg2 = WINED3DTA_TEXTURE;
3245
                        op = WINED3D_TOP_MODULATE;
3246 3247 3248
                    }
                    else arg1 = WINED3DTA_TEXTURE;
                }
3249
                else if (op == WINED3D_TOP_SELECT_ARG2 && arg2 != WINED3DTA_TEXTURE)
3250
                {
3251
                    if (state->render_states[WINED3D_RS_ALPHABLENDENABLE])
3252 3253
                    {
                        arg1 = WINED3DTA_TEXTURE;
3254
                        op = WINED3D_TOP_MODULATE;
3255 3256
                    }
                    else arg2 = WINED3DTA_TEXTURE;
3257 3258
                }
            }
3259 3260 3261
        }
    }

3262 3263 3264
    /* tex_alphaop is shared between the ffp and nvrc because the difference only comes down to
     * this if block here, and the other code(color keying, texture unit selection) are the same
     */
3265
    TRACE("Setting alpha op for stage %d\n", stage);
3266
    if (gl_info->supported[NV_REGISTER_COMBINERS])
3267
    {
3268
        set_tex_op_nvrc(gl_info, state, TRUE, stage, op, arg1, arg2, arg0,
3269
                mapped_stage, state->texture_states[stage][WINED3D_TSS_RESULT_ARG]);
3270 3271 3272
    }
    else
    {
3273
        set_tex_op(gl_info, state, TRUE, stage, op, arg1, arg2, arg0);
3274 3275 3276
    }
}

3277
static void transform_texture(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3278
{
3279
    unsigned int tex = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3280 3281
    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
    unsigned int mapped_stage = context_gl->tex_unit_map[tex];
3282
    const struct wined3d_gl_info *gl_info = context->gl_info;
3283
    struct wined3d_matrix mat;
3284

3285
    /* Ignore this when a vertex shader is used, or if the streams aren't sorted out yet */
3286
    if (use_vs(state) || isStateDirty(context, STATE_VDECL))
3287
    {
3288 3289 3290 3291
        TRACE("Using a vertex shader, or stream sources not sorted out yet, skipping\n");
        return;
    }

3292
    if (mapped_stage == WINED3D_UNMAPPED_STAGE) return;
3293
    if (mapped_stage >= gl_info->limits.textures) return;
3294

3295
    wined3d_context_gl_active_texture(context_gl, gl_info, mapped_stage);
3296 3297 3298 3299 3300 3301 3302
    gl_info->gl_ops.gl.p_glMatrixMode(GL_TEXTURE);
    checkGLcall("glMatrixMode(GL_TEXTURE)");

    get_texture_matrix(context, state, mapped_stage, &mat);

    gl_info->gl_ops.gl.p_glLoadMatrixf(&mat._11);
    checkGLcall("glLoadMatrixf");
3303 3304
}

3305
static void tex_coordindex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3306
{
3307
    unsigned int stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
3308
    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
3309 3310 3311
    unsigned int mapped_stage = context_gl->tex_unit_map[stage];
    const struct wined3d_gl_info *gl_info = context->gl_info;

3312 3313 3314 3315
    static const GLfloat s_plane[] = { 1.0f, 0.0f, 0.0f, 0.0f };
    static const GLfloat t_plane[] = { 0.0f, 1.0f, 0.0f, 0.0f };
    static const GLfloat r_plane[] = { 0.0f, 0.0f, 1.0f, 0.0f };
    static const GLfloat q_plane[] = { 0.0f, 0.0f, 0.0f, 1.0f };
3316

3317 3318
    if (mapped_stage == WINED3D_UNMAPPED_STAGE)
    {
3319 3320 3321
        TRACE("No texture unit mapped to stage %d. Skipping texture coordinates.\n", stage);
        return;
    }
3322

3323
    if (mapped_stage >= min(gl_info->limits.samplers[WINED3D_SHADER_TYPE_PIXEL], WINED3D_MAX_FRAGMENT_SAMPLERS))
3324
    {
3325
        WARN("stage %u not mapped to a valid texture unit (%u)\n", stage, mapped_stage);
3326 3327
        return;
    }
3328
    wined3d_context_gl_active_texture(context_gl, gl_info, mapped_stage);
3329 3330 3331

    /* Values 0-7 are indexes into the FVF tex coords - See comments in DrawPrimitive
     *
3332
     * FIXME: When using generated texture coordinates, the index value is used to specify the wrapping mode.
3333
     * eg. SetTextureStageState( 0, WINED3D_TSS_TEXCOORDINDEX, WINED3D_TSS_TCI_CAMERASPACEPOSITION | 1 );
3334
     * means use the vertex position (camera-space) as the input texture coordinates
3335
     * for this texture stage, and the wrap mode set in the WINED3D_RS_WRAP1 render
3336 3337 3338
     * state. We do not (yet) support the WINED3DRENDERSTATE_WRAPx values, nor tie them up
     * to the TEXCOORDINDEX value
     */
3339
    switch (state->texture_states[stage][WINED3D_TSS_TEXCOORD_INDEX] & 0xffff0000)
3340 3341 3342 3343
    {
        case WINED3DTSS_TCI_PASSTHRU:
            /* Use the specified texture coordinates contained within the
             * vertex format. This value resolves to zero. */
3344 3345 3346 3347
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_S);
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_T);
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_R);
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_Q);
3348
            checkGLcall("WINED3DTSS_TCI_PASSTHRU - Disable texgen.");
3349
            break;
3350

3351 3352 3353 3354
        case WINED3DTSS_TCI_CAMERASPACEPOSITION:
            /* CameraSpacePosition means use the vertex position, transformed to camera space,
             * as the input texture coordinates for this stage's texture transformation. This
             * equates roughly to EYE_LINEAR */
3355

3356 3357 3358 3359 3360 3361 3362 3363
            gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
            gl_info->gl_ops.gl.p_glPushMatrix();
            gl_info->gl_ops.gl.p_glLoadIdentity();
            gl_info->gl_ops.gl.p_glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
            gl_info->gl_ops.gl.p_glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
            gl_info->gl_ops.gl.p_glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
            gl_info->gl_ops.gl.p_glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
            gl_info->gl_ops.gl.p_glPopMatrix();
3364
            checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set eye plane.");
3365

3366 3367 3368
            gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
            gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
            gl_info->gl_ops.gl.p_glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_EYE_LINEAR);
3369 3370
            checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Set texgen mode.");

3371 3372 3373
            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_R);
3374 3375
            checkGLcall("WINED3DTSS_TCI_CAMERASPACEPOSITION - Enable texgen.");

3376
            break;
3377

3378
        case WINED3DTSS_TCI_CAMERASPACENORMAL:
3379 3380
            /* Note that NV_TEXGEN_REFLECTION support is implied when
             * ARB_TEXTURE_CUBE_MAP is supported */
3381
            if (!gl_info->supported[NV_TEXGEN_REFLECTION])
3382
            {
3383
                FIXME("WINED3DTSS_TCI_CAMERASPACENORMAL not supported.\n");
3384 3385 3386
                break;
            }

3387 3388 3389 3390 3391 3392 3393 3394
            gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
            gl_info->gl_ops.gl.p_glPushMatrix();
            gl_info->gl_ops.gl.p_glLoadIdentity();
            gl_info->gl_ops.gl.p_glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
            gl_info->gl_ops.gl.p_glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
            gl_info->gl_ops.gl.p_glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
            gl_info->gl_ops.gl.p_glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
            gl_info->gl_ops.gl.p_glPopMatrix();
3395
            checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set eye plane.");
3396

3397 3398 3399
            gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
            gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
            gl_info->gl_ops.gl.p_glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_NORMAL_MAP_NV);
3400 3401
            checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Set texgen mode.");

3402 3403 3404
            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_R);
3405
            checkGLcall("WINED3DTSS_TCI_CAMERASPACENORMAL - Enable texgen.");
3406 3407 3408 3409

            break;

        case WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR:
3410 3411
            /* Note that NV_TEXGEN_REFLECTION support is implied when
             * ARB_TEXTURE_CUBE_MAP is supported */
3412
            if (!gl_info->supported[NV_TEXGEN_REFLECTION])
3413
            {
3414
                FIXME("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR not supported.\n");
3415
                break;
3416 3417
            }

3418 3419 3420 3421 3422 3423 3424 3425
            gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
            gl_info->gl_ops.gl.p_glPushMatrix();
            gl_info->gl_ops.gl.p_glLoadIdentity();
            gl_info->gl_ops.gl.p_glTexGenfv(GL_S, GL_EYE_PLANE, s_plane);
            gl_info->gl_ops.gl.p_glTexGenfv(GL_T, GL_EYE_PLANE, t_plane);
            gl_info->gl_ops.gl.p_glTexGenfv(GL_R, GL_EYE_PLANE, r_plane);
            gl_info->gl_ops.gl.p_glTexGenfv(GL_Q, GL_EYE_PLANE, q_plane);
            gl_info->gl_ops.gl.p_glPopMatrix();
3426
            checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set eye plane.");
3427

3428 3429 3430
            gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
            gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
            gl_info->gl_ops.gl.p_glTexGeni(GL_R, GL_TEXTURE_GEN_MODE, GL_REFLECTION_MAP_NV);
3431 3432
            checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Set texgen mode.");

3433 3434 3435
            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_R);
3436
            checkGLcall("WINED3DTSS_TCI_CAMERASPACEREFLECTIONVECTOR - Enable texgen.");
3437 3438 3439

            break;

3440
        case WINED3DTSS_TCI_SPHEREMAP:
3441 3442
            gl_info->gl_ops.gl.p_glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
            gl_info->gl_ops.gl.p_glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP);
3443 3444
            checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Set texgen mode.");

3445 3446 3447
            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_S);
            gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_GEN_T);
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_R);
3448 3449 3450 3451
            checkGLcall("WINED3DTSS_TCI_SPHEREMAP - Enable texgen.");

            break;

3452
        default:
3453 3454
            FIXME("Unhandled WINED3D_TSS_TEXCOORD_INDEX %#x.\n",
                    state->texture_states[stage][WINED3D_TSS_TEXCOORD_INDEX]);
3455 3456 3457 3458
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_S);
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_T);
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_R);
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_GEN_Q);
3459 3460
            checkGLcall("Disable texgen.");

3461
            break;
3462
    }
3463

3464
    /* Update the texture matrix. */
3465
    if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + stage)))
3466
        transform_texture(context, state, STATE_TEXTURESTAGE(stage, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS));
3467

3468 3469
    if (!isStateDirty(context, STATE_VDECL) && context->namedArraysLoaded)
    {
3470
        /* Reload the arrays if we are using fixed function arrays to reflect the selected coord input
3471
         * source. Call loadTexCoords directly because there is no need to reparse the vertex declaration
3472 3473 3474
         * and do all the things linked to it
         * TODO: Tidy that up to reload only the arrays of the changed unit
         */
3475
        GLuint curVBO = gl_info->supported[ARB_VERTEX_BUFFER_OBJECT] ? ~0U : 0;
3476

3477
        wined3d_context_gl_unload_tex_coords(context_gl);
3478
        wined3d_context_gl_load_tex_coords(context_gl, &context->stream_info, &curVBO, state);
3479
    }
3480 3481
}

3482
static void sampler_texmatrix(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3483
{
3484 3485
    const DWORD sampler = state_id - STATE_SAMPLER(0);
    const struct wined3d_texture *texture = state->textures[sampler];
3486

3487
    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
3488

3489 3490 3491
    if (!texture)
        return;

3492
    /* The fixed function np2 texture emulation uses the texture matrix to fix up the coordinates
3493
     * wined3d_texture_apply_state_changes() multiplies the set matrix with a fixup matrix. Before the
3494
     * scaling is reapplied or removed, the texture matrix has to be reapplied.
3495
     */
3496
    if (sampler < WINED3D_MAX_TEXTURES)
3497
    {
3498
        const BOOL tex_is_pow2 = !(texture->flags & WINED3D_TEXTURE_POW2_MAT_IDENT);
3499

3500
        if (tex_is_pow2 || (context->lastWasPow2Texture & (1u << sampler)))
3501
        {
3502
            if (tex_is_pow2)
3503
                context->lastWasPow2Texture |= 1u << sampler;
3504
            else
3505
                context->lastWasPow2Texture &= ~(1u << sampler);
3506

3507
            transform_texture(context, state, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS));
3508 3509 3510 3511
        }
    }
}

3512
static enum wined3d_texture_address wined3d_texture_gl_address_mode(const struct wined3d_texture_gl *texture_gl,
3513
        enum wined3d_texture_address t)
3514
{
3515 3516 3517 3518 3519 3520 3521
    if (t < WINED3D_TADDRESS_WRAP || t > WINED3D_TADDRESS_MIRROR_ONCE)
    {
        FIXME("Unrecognized or unsupported texture address mode %#x.\n", t);
        return WINED3D_TADDRESS_WRAP;
    }

    /* Cubemaps are always set to clamp, regardless of the sampler state. */
3522
    if (texture_gl->target == GL_TEXTURE_CUBE_MAP_ARB || ((texture_gl->t.flags & WINED3D_TEXTURE_COND_NP2)
3523 3524 3525 3526 3527 3528 3529
            && t == WINED3D_TADDRESS_WRAP))
        return WINED3D_TADDRESS_CLAMP;

    return t;
}

static void wined3d_sampler_desc_from_sampler_states(struct wined3d_sampler_desc *desc,
3530
        const struct wined3d_context_gl *context_gl, const DWORD *sampler_states,
3531
        const struct wined3d_texture_gl *texture_gl)
3532 3533 3534
{
    union
    {
3535 3536
        float f;
        DWORD d;
3537 3538
    } lod_bias;

3539 3540 3541
    desc->address_u = wined3d_texture_gl_address_mode(texture_gl, sampler_states[WINED3D_SAMP_ADDRESS_U]);
    desc->address_v = wined3d_texture_gl_address_mode(texture_gl, sampler_states[WINED3D_SAMP_ADDRESS_V]);
    desc->address_w = wined3d_texture_gl_address_mode(texture_gl, sampler_states[WINED3D_SAMP_ADDRESS_W]);
3542 3543
    wined3d_color_from_d3dcolor((struct wined3d_color *)desc->border_color,
            sampler_states[WINED3D_SAMP_BORDER_COLOR]);
3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559
    if (sampler_states[WINED3D_SAMP_MAG_FILTER] > WINED3D_TEXF_ANISOTROPIC)
        FIXME("Unrecognized or unsupported WINED3D_SAMP_MAG_FILTER %#x.\n",
                sampler_states[WINED3D_SAMP_MAG_FILTER]);
    desc->mag_filter = min(max(sampler_states[WINED3D_SAMP_MAG_FILTER], WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR);
    if (sampler_states[WINED3D_SAMP_MIN_FILTER] > WINED3D_TEXF_ANISOTROPIC)
        FIXME("Unrecognized or unsupported WINED3D_SAMP_MIN_FILTER %#x.\n",
                sampler_states[WINED3D_SAMP_MIN_FILTER]);
    desc->min_filter = min(max(sampler_states[WINED3D_SAMP_MIN_FILTER], WINED3D_TEXF_POINT), WINED3D_TEXF_LINEAR);
    if (sampler_states[WINED3D_SAMP_MIP_FILTER] > WINED3D_TEXF_ANISOTROPIC)
        FIXME("Unrecognized or unsupported WINED3D_SAMP_MIP_FILTER %#x.\n",
                sampler_states[WINED3D_SAMP_MIP_FILTER]);
    desc->mip_filter = min(max(sampler_states[WINED3D_SAMP_MIP_FILTER], WINED3D_TEXF_NONE), WINED3D_TEXF_LINEAR);
    lod_bias.d = sampler_states[WINED3D_SAMP_MIPMAP_LOD_BIAS];
    desc->lod_bias = lod_bias.f;
    desc->min_lod = -1000.0f;
    desc->max_lod = 1000.0f;
3560
    desc->mip_base_level = sampler_states[WINED3D_SAMP_MAX_MIP_LEVEL];
3561 3562 3563 3564
    desc->max_anisotropy = sampler_states[WINED3D_SAMP_MAX_ANISOTROPY];
    if ((sampler_states[WINED3D_SAMP_MAG_FILTER] != WINED3D_TEXF_ANISOTROPIC
                && sampler_states[WINED3D_SAMP_MIN_FILTER] != WINED3D_TEXF_ANISOTROPIC
                && sampler_states[WINED3D_SAMP_MIP_FILTER] != WINED3D_TEXF_ANISOTROPIC)
3565
            || (texture_gl->t.flags & WINED3D_TEXTURE_COND_NP2))
3566
        desc->max_anisotropy = 1;
3567
    desc->compare = texture_gl->t.resource.format_flags & WINED3DFMT_FLAG_SHADOW;
3568
    desc->comparison_func = WINED3D_CMP_LESSEQUAL;
3569
    desc->srgb_decode = is_srgb_enabled(sampler_states);
3570

3571
    if (!(texture_gl->t.resource.format_flags & WINED3DFMT_FLAG_FILTERING))
3572 3573 3574 3575 3576 3577
    {
        desc->mag_filter = WINED3D_TEXF_POINT;
        desc->min_filter = WINED3D_TEXF_POINT;
        desc->mip_filter = WINED3D_TEXF_NONE;
    }

3578
    if (texture_gl->t.flags & WINED3D_TEXTURE_COND_NP2)
3579 3580
    {
        desc->mip_filter = WINED3D_TEXF_NONE;
3581
        if (context_gl->c.gl_info->supported[WINED3D_GL_NORMALIZED_TEXRECT])
3582 3583 3584 3585 3586 3587 3588 3589 3590
            desc->min_filter = WINED3D_TEXF_POINT;
    }
}

/* Enabling and disabling texture dimensions is done by texture stage state /
 * pixel shader setup, this function only has to bind textures and set the per
 * texture states. */
static void sampler(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
3591
    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
3592 3593
    unsigned int sampler_idx = state_id - STATE_SAMPLER(0);
    unsigned int mapped_stage = context_gl->tex_unit_map[sampler_idx];
3594 3595 3596
    const struct wined3d_gl_info *gl_info = context->gl_info;

    TRACE("Sampler %u.\n", sampler_idx);
3597

3598 3599
    if (mapped_stage == WINED3D_UNMAPPED_STAGE)
    {
3600
        TRACE("No sampler mapped to stage %u. Returning.\n", sampler_idx);
3601 3602 3603
        return;
    }

3604
    if (mapped_stage >= gl_info->limits.graphics_samplers)
3605
        return;
3606
    wined3d_context_gl_active_texture(context_gl, gl_info, mapped_stage);
3607

3608
    if (state->textures[sampler_idx])
3609
    {
3610
        struct wined3d_texture_gl *texture_gl = wined3d_texture_gl(state->textures[sampler_idx]);
3611
        const DWORD *sampler_states = state->sampler_states[sampler_idx];
3612
        struct wined3d_device *device = context->device;
3613
        BOOL srgb = is_srgb_enabled(sampler_states);
3614
        struct wined3d_sampler_desc desc;
3615 3616
        struct wined3d_sampler *sampler;
        struct wine_rb_entry *entry;
3617

3618
        wined3d_sampler_desc_from_sampler_states(&desc, context_gl, sampler_states, texture_gl);
3619

3620
        wined3d_texture_gl_bind(texture_gl, context_gl, srgb);
3621 3622

        if ((entry = wine_rb_get(&device->samplers, &desc)))
3623
        {
3624
            sampler = WINE_RB_ENTRY_VALUE(entry, struct wined3d_sampler, entry);
3625 3626 3627
        }
        else
        {
3628
            if (FAILED(wined3d_sampler_create(device, &desc, NULL, &wined3d_null_parent_ops, &sampler)))
3629
            {
3630
                ERR("Failed to create sampler.\n");
3631
                return;
3632
            }
3633
            if (wine_rb_put(&device->samplers, &desc, &sampler->entry) == -1)
3634
            {
3635 3636 3637
                ERR("Failed to insert sampler.\n");
                wined3d_sampler_decref(sampler);
                return;
3638 3639
            }
        }
3640

3641
        wined3d_sampler_bind(sampler, mapped_stage, texture_gl, context_gl);
3642

3643
        /* Trigger shader constant reloading (for NP2 texcoord fixup) */
3644
        if (!(texture_gl->t.flags & WINED3D_TEXTURE_POW2_MAT_IDENT))
3645
            context->constant_update_mask |= WINED3D_SHADER_CONST_PS_NP2_FIXUP;
3646
    }
3647
    else
3648
    {
3649
        wined3d_context_gl_bind_texture(context_gl, GL_NONE, 0);
3650 3651 3652 3653 3654
        if (gl_info->supported[ARB_SAMPLER_OBJECTS])
        {
            GL_EXTCALL(glBindSampler(mapped_stage, 0));
            checkGLcall("glBindSampler");
        }
3655 3656 3657
    }
}

3658
void apply_pixelshader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3659
{
3660
    unsigned int i;
3661

3662
    if (use_ps(state))
3663 3664 3665 3666
    {
        if (!context->last_was_pshader)
        {
            /* Former draw without a pixel shader, some samplers may be
3667
             * disabled because of WINED3D_TSS_COLOR_OP = WINED3DTOP_DISABLE
3668
             * make sure to enable them. */
3669
            for (i = 0; i < WINED3D_MAX_FRAGMENT_SAMPLERS; ++i)
3670 3671 3672
            {
                if (!isStateDirty(context, STATE_SAMPLER(i)))
                    sampler(context, state, STATE_SAMPLER(i));
3673
            }
3674
            context->last_was_pshader = TRUE;
3675
        }
3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686
        else
        {
            /* Otherwise all samplers were activated by the code above in
             * earlier draws, or by sampler() if a different texture was
             * bound. I don't have to do anything. */
        }
    }
    else
    {
        /* Disabled the pixel shader - color ops weren't applied while it was
         * enabled, so re-apply them. */
3687
        for (i = 0; i < context->d3d_info->limits.ffp_blend_stages; ++i)
3688
        {
3689 3690
            if (!isStateDirty(context, STATE_TEXTURESTAGE(i, WINED3D_TSS_COLOR_OP)))
                context_apply_state(context, state, STATE_TEXTURESTAGE(i, WINED3D_TSS_COLOR_OP));
3691
        }
3692
        context->last_was_pshader = FALSE;
3693
    }
3694

3695
    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
3696 3697
}

3698 3699 3700 3701 3702
static void state_compute_shader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_COMPUTE;
}

3703
static void state_shader(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3704
{
3705 3706
    enum wined3d_shader_type shader_type = state_id - STATE_SHADER(0);
    context->shader_update_mask |= 1u << shader_type;
3707 3708
}

3709
static void shader_bumpenv(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3710
{
3711
    context->constant_update_mask |= WINED3D_SHADER_CONST_PS_BUMP_ENV;
3712
}
3713

3714
static void transform_world(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3715
{
3716
    const struct wined3d_gl_info *gl_info = context->gl_info;
3717
    struct wined3d_matrix mat;
3718

3719 3720 3721 3722
    /* This function is called by transform_view below if the view matrix was changed too
     *
     * Deliberately no check if the vertex declaration is dirty because the vdecl state
     * does not always update the world matrix, only on a switch between transformed
3723
     * and untransformed draws. It *may* happen that the world matrix is set 2 times during one
3724
     * draw, but that should be rather rare and cheaper in total.
3725
     */
3726
    gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
3727 3728
    checkGLcall("glMatrixMode");

3729
    get_modelview_matrix(context, state, 0, &mat);
3730 3731 3732

    gl_info->gl_ops.gl.p_glLoadMatrixf((GLfloat *)&mat);
    checkGLcall("glLoadMatrixf");
3733 3734
}

3735
void clipplane(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3736
{
3737
    const struct wined3d_gl_info *gl_info = context->gl_info;
3738
    UINT index = state_id - STATE_CLIPPLANE(0);
3739
    GLdouble plane[4];
3740

3741
    if (isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_VIEW)) || index >= gl_info->limits.user_clip_distances)
3742 3743
        return;

3744 3745
    gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
    gl_info->gl_ops.gl.p_glPushMatrix();
3746

3747
    /* Clip Plane settings are affected by the model view in OpenGL, the View transform in direct3d */
3748
    if (!use_vs(state))
3749
        gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW]._11);
3750
    else
3751
        /* With vertex shaders, clip planes are not transformed in Direct3D,
3752
         * while in OpenGL they are still transformed by the model view matrix. */
3753
        gl_info->gl_ops.gl.p_glLoadIdentity();
3754

3755 3756 3757 3758 3759
    plane[0] = state->clip_planes[index].x;
    plane[1] = state->clip_planes[index].y;
    plane[2] = state->clip_planes[index].z;
    plane[3] = state->clip_planes[index].w;

3760
    TRACE("Clipplane [%.8e, %.8e, %.8e, %.8e]\n",
3761
            plane[0], plane[1], plane[2], plane[3]);
3762
    gl_info->gl_ops.gl.p_glClipPlane(GL_CLIP_PLANE0 + index, plane);
3763 3764
    checkGLcall("glClipPlane");

3765
    gl_info->gl_ops.gl.p_glPopMatrix();
3766 3767
}

3768
static void transform_worldex(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3769
{
3770
    unsigned int matrix = state_id - STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0));
3771

3772
    WARN("Unsupported world matrix %u set.\n", matrix);
3773 3774
}

3775
static void state_vertexblend_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3776
{
3777
    enum wined3d_vertex_blend_flags f = state->render_states[WINED3D_RS_VERTEXBLEND];
3778
    static unsigned int once;
3779

3780 3781
    if (f == WINED3D_VBF_DISABLE)
        return;
3782

3783 3784
    if (!once++) FIXME("Vertex blend flags %#x not supported.\n", f);
    else WARN("Vertex blend flags %#x not supported.\n", f);
3785 3786
}

3787
static void transform_view(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3788
{
3789
    const struct wined3d_gl_info *gl_info = context->gl_info;
3790
    const struct wined3d_light_info *light = NULL;
3791 3792 3793 3794 3795 3796 3797 3798
    unsigned int k;

    /* If we are changing the View matrix, reset the light and clipping planes to the new view
     * NOTE: We have to reset the positions even if the light/plane is not currently
     *       enabled, since the call to enable it will not reset the position.
     * NOTE2: Apparently texture transforms do NOT need reapplying
     */

3799
    gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
3800
    checkGLcall("glMatrixMode(GL_MODELVIEW)");
3801
    gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW]._11);
3802 3803 3804
    checkGLcall("glLoadMatrixf(...)");

    /* Reset lights. TODO: Call light apply func */
3805
    for (k = 0; k < gl_info->limits.lights; ++k)
3806
    {
3807
        if (!(light = state->light_state.lights[k]))
3808
            continue;
3809
        if (light->OriginalParms.type == WINED3D_LIGHT_DIRECTIONAL)
3810
            gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, &light->direction.x);
3811
        else
3812
            gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + light->glIndex, GL_POSITION, &light->position.x);
3813
        checkGLcall("glLightfv posn");
3814
        gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + light->glIndex, GL_SPOT_DIRECTION, &light->direction.x);
3815 3816 3817
        checkGLcall("glLightfv dirn");
    }

3818
    /* Reset Clipping Planes  */
3819
    for (k = 0; k < gl_info->limits.user_clip_distances; ++k)
3820
    {
3821 3822
        if (!isStateDirty(context, STATE_CLIPPLANE(k)))
            clipplane(context, state, STATE_CLIPPLANE(k));
3823
    }
3824

3825 3826 3827
    if (context->last_was_rhw)
    {
        gl_info->gl_ops.gl.p_glLoadIdentity();
3828 3829 3830 3831 3832 3833
        checkGLcall("glLoadIdentity()");
        /* No need to update the world matrix, the identity is fine */
        return;
    }

    /* Call the world matrix state, this will apply the combined WORLD + VIEW matrix
3834
     * No need to do it here if the state is scheduled for update. */
3835 3836
    if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0))))
        transform_world(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
3837 3838
}

3839
static void transform_projection(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3840
{
3841
    const struct wined3d_gl_info *gl_info = context->gl_info;
3842
    struct wined3d_matrix projection;
3843 3844

    gl_info->gl_ops.gl.p_glMatrixMode(GL_PROJECTION);
3845
    checkGLcall("glMatrixMode(GL_PROJECTION)");
3846

3847 3848 3849
    get_projection_matrix(context, state, &projection);
    gl_info->gl_ops.gl.p_glLoadMatrixf(&projection._11);
    checkGLcall("glLoadMatrixf");
3850 3851
}

3852
static void streamsrc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3853
{
3854 3855
    if (isStateDirty(context, STATE_VDECL))
        return;
3856
    wined3d_context_gl_update_stream_sources(wined3d_context_gl(context), state);
3857 3858
}

3859
static void vdecl_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3860
{
3861 3862
    if (isStateDirty(context, STATE_STREAMSRC))
        return;
3863
    wined3d_context_gl_update_stream_sources(wined3d_context_gl(context), state);
3864 3865
}

3866
static void vertexdeclaration(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
3867
{
3868
    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
3869
    const struct wined3d_gl_info *gl_info = context->gl_info;
3870
    BOOL useVertexShaderFunction = use_vs(state);
3871
    BOOL updateFog = FALSE;
3872
    BOOL transformed;
3873
    BOOL wasrhw = context->last_was_rhw;
3874
    unsigned int i;
3875

3876
    transformed = context->stream_info.position_transformed;
3877
    if (transformed != context->last_was_rhw && !useVertexShaderFunction)
3878 3879
        updateFog = TRUE;

3880
    context->last_was_rhw = transformed;
3881

3882 3883 3884 3885 3886
    if (context->stream_info.swizzle_map != context->last_swizzle_map)
        context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;

    context->last_swizzle_map = context->stream_info.swizzle_map;

3887 3888 3889 3890 3891 3892 3893 3894
    /* Don't have to apply the matrices when vertex shaders are used. When
     * vshaders are turned off this function will be called again anyway to
     * make sure they're properly set. */
    if (!useVertexShaderFunction)
    {
        /* TODO: Move this mainly to the viewport state and only apply when
         * the vp has changed or transformed / untransformed was switched. */
        if (wasrhw != context->last_was_rhw
3895
                && !isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION))
3896
                && !isStateDirty(context, STATE_VIEWPORT))
3897
            transform_projection(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
3898 3899 3900 3901 3902 3903 3904 3905 3906 3907 3908
        /* World matrix needs reapplication here only if we're switching between rhw and non-rhw
         * mode.
         *
         * If a vertex shader is used, the world matrix changed and then vertex shader unbound
         * this check will fail and the matrix not applied again. This is OK because a simple
         * world matrix change reapplies the matrix - These checks here are only to satisfy the
         * needs of the vertex declaration.
         *
         * World and view matrix go into the same gl matrix, so only apply them when neither is
         * dirty
         */
3909 3910 3911
        if (transformed != wasrhw && !isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)))
                && !isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_VIEW)))
            transform_world(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
3912
        if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_COLORVERTEX)))
3913
            context_apply_state(context, state, STATE_RENDER(WINED3D_RS_COLORVERTEX));
3914 3915
        if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_LIGHTING)))
            state_lighting(context, state, STATE_RENDER(WINED3D_RS_LIGHTING));
3916 3917 3918 3919

        if (context->last_was_vshader)
        {
            updateFog = TRUE;
3920

3921 3922 3923
            if (!context->d3d_info->vs_clipping
                    && !isStateDirty(context, STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE)))
            {
3924
                state_clipping(context, state, STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE));
3925
            }
3926

3927
            for (i = 0; i < gl_info->limits.user_clip_distances; ++i)
3928
            {
3929
                clipplane(context, state, STATE_CLIPPLANE(i));
3930
            }
3931
        }
3932 3933
        if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_NORMALIZENORMALS)))
            state_normalize(context, state, STATE_RENDER(WINED3D_RS_NORMALIZENORMALS));
3934 3935 3936
    }
    else
    {
3937 3938
        if (!context->last_was_vshader)
        {
3939
            static BOOL warned = FALSE;
3940 3941
            if (!context->d3d_info->vs_clipping)
            {
3942 3943 3944
                /* Disable all clip planes to get defined results on all drivers. See comment in the
                 * state_clipping state handler
                 */
3945
                wined3d_context_gl_enable_clip_distances(context_gl, 0);
3946

3947
                if (!warned && state->render_states[WINED3D_RS_CLIPPLANEENABLE])
3948
                {
3949
                    FIXME("Clipping not supported with vertex shaders.\n");
3950 3951
                    warned = TRUE;
                }
3952
            }
3953 3954 3955 3956 3957 3958 3959 3960 3961
            if (wasrhw)
            {
                /* Apply the transform matrices when switching from rhw
                 * drawing to vertex shaders. Vertex shaders themselves do
                 * not need it, but the matrices are not reapplied
                 * automatically when switching back from vertex shaders to
                 * fixed function processing. So make sure we leave the fixed
                 * function vertex processing states back in a sane state
                 * before switching to shaders. */
3962 3963 3964 3965
                if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)))
                    transform_projection(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
                if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0))))
                    transform_world(context, state, STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(0)));
3966
            }
3967
            updateFog = TRUE;
3968 3969 3970 3971 3972

            /* Vertex shader clipping ignores the view matrix. Update all clipplanes
             * (Note: ARB shaders can read the clip planes for clipping emulation even if
             * device->vs_clipping is false.
             */
3973
            for (i = 0; i < gl_info->limits.user_clip_distances; ++i)
3974
            {
3975
                clipplane(context, state, STATE_CLIPPLANE(i));
3976
            }
3977
        }
3978
    }
3979

3980
    context->last_was_vshader = useVertexShaderFunction;
3981
    context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_VERTEX;
3982

3983
    if (updateFog)
3984
        context_apply_state(context, state, STATE_RENDER(WINED3D_RS_FOGVERTEXMODE));
3985

3986 3987 3988 3989
    if (!useVertexShaderFunction)
    {
        unsigned int i;

3990
        for (i = 0; i < WINED3D_MAX_TEXTURES; ++i)
3991
        {
3992
            if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + i)))
3993
                transform_texture(context, state, STATE_TEXTURESTAGE(i, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS));
3994
        }
3995

3996 3997
        if (use_ps(state) && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.major == 1
                && state->shader[WINED3D_SHADER_TYPE_PIXEL]->reg_maps.shader_version.minor <= 3)
3998
            context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
3999
    }
4000 4001
}

4002 4003
static void get_viewports(struct wined3d_context *context, const struct wined3d_state *state,
        unsigned int viewport_count, struct wined3d_viewport *viewports)
4004
{
4005
    const struct wined3d_rendertarget_view *depth_stencil = state->fb->depth_stencil;
4006
    const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
4007
    unsigned int width, height, i;
4008

4009 4010 4011
    for (i = 0; i < viewport_count; ++i)
        viewports[i] = state->viewports[i];

4012 4013
    /* Note: GL uses a lower left origin while DirectX uses upper left. This
     * is reversed when using offscreen rendering. */
4014 4015
    if (context->render_offscreen)
        return;
4016

4017 4018
    if (target)
    {
4019
        wined3d_rendertarget_view_get_drawable_size(target, context, &width, &height);
4020 4021 4022 4023 4024 4025 4026
    }
    else if (depth_stencil)
    {
        height = depth_stencil->height;
    }
    else
    {
4027 4028
        FIXME("Could not get the height of render targets.\n");
        return;
4029
    }
4030

4031 4032
    for (i = 0; i < viewport_count; ++i)
        viewports[i].y = height - (viewports[i].y + viewports[i].height);
4033 4034 4035 4036 4037
}

static void viewport_miscpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
    const struct wined3d_gl_info *gl_info = context->gl_info;
4038 4039 4040 4041
    struct wined3d_viewport vp[WINED3D_MAX_VIEWPORTS];

    if (gl_info->supported[ARB_VIEWPORT_ARRAY])
    {
4042 4043 4044
        GLdouble depth_ranges[2 * WINED3D_MAX_VIEWPORTS];
        GLfloat viewports[4 * WINED3D_MAX_VIEWPORTS];

4045
        unsigned int i, reset_count = 0;
4046

4047 4048 4049
        get_viewports(context, state, state->viewport_count, vp);
        for (i = 0; i < state->viewport_count; ++i)
        {
4050 4051 4052 4053 4054 4055 4056
            depth_ranges[i * 2]     = vp[i].min_z;
            depth_ranges[i * 2 + 1] = vp[i].max_z;

            viewports[i * 4]     = vp[i].x;
            viewports[i * 4 + 1] = vp[i].y;
            viewports[i * 4 + 2] = vp[i].width;
            viewports[i * 4 + 3] = vp[i].height;
4057
        }
4058

4059 4060
        if (context->viewport_count > state->viewport_count)
            reset_count = context->viewport_count - state->viewport_count;
4061

4062 4063
        if (reset_count)
        {
4064 4065
            memset(&depth_ranges[state->viewport_count * 2], 0, reset_count * 2 * sizeof(*depth_ranges));
            memset(&viewports[state->viewport_count * 4], 0, reset_count * 4 * sizeof(*viewports));
4066
        }
4067 4068 4069

        GL_EXTCALL(glDepthRangeArrayv(0, state->viewport_count + reset_count, depth_ranges));
        GL_EXTCALL(glViewportArrayv(0, state->viewport_count + reset_count, viewports));
4070 4071
        context->viewport_count = state->viewport_count;
    }
4072
    else
4073 4074 4075 4076 4077
    {
        get_viewports(context, state, 1, vp);
        gl_info->gl_ops.gl.p_glDepthRange(vp[0].min_z, vp[0].max_z);
        gl_info->gl_ops.gl.p_glViewport(vp[0].x, vp[0].y, vp[0].width, vp[0].height);
    }
4078
    checkGLcall("setting clip space and viewport");
4079
}
4080

4081 4082 4083
static void viewport_miscpart_cc(struct wined3d_context *context,
        const struct wined3d_state *state, DWORD state_id)
{
4084
    /* See get_projection_matrix() in utils.c for a discussion about those values. */
4085
    float pixel_center_offset = context->d3d_info->wined3d_creation_flags
4086
            & WINED3D_PIXEL_CENTER_INTEGER ? 63.0f / 128.0f : -1.0f / 128.0f;
4087
    const struct wined3d_gl_info *gl_info = context->gl_info;
4088
    struct wined3d_viewport vp[WINED3D_MAX_VIEWPORTS];
4089 4090
    GLdouble depth_ranges[2 * WINED3D_MAX_VIEWPORTS];
    GLfloat viewports[4 * WINED3D_MAX_VIEWPORTS];
4091
    unsigned int i, reset_count = 0;
4092

4093
    get_viewports(context, state, state->viewport_count, vp);
4094

4095
    GL_EXTCALL(glClipControl(context->render_offscreen ? GL_UPPER_LEFT : GL_LOWER_LEFT, GL_ZERO_TO_ONE));
4096 4097 4098

    for (i = 0; i < state->viewport_count; ++i)
    {
4099 4100 4101
        depth_ranges[i * 2]     = vp[i].min_z;
        depth_ranges[i * 2 + 1] = vp[i].max_z;

4102
        viewports[i * 4] = vp[i].x + pixel_center_offset;
4103 4104 4105
        viewports[i * 4 + 1] = vp[i].y + pixel_center_offset;
        viewports[i * 4 + 2] = vp[i].width;
        viewports[i * 4 + 3] = vp[i].height;
4106 4107 4108 4109 4110 4111 4112
    }

    if (context->viewport_count > state->viewport_count)
        reset_count = context->viewport_count - state->viewport_count;

    if (reset_count)
    {
4113 4114
        memset(&depth_ranges[state->viewport_count * 2], 0, reset_count * 2 * sizeof(*depth_ranges));
        memset(&viewports[state->viewport_count * 4], 0, reset_count * 4 * sizeof(*viewports));
4115
    }
4116 4117 4118

    GL_EXTCALL(glDepthRangeArrayv(0, state->viewport_count + reset_count, depth_ranges));
    GL_EXTCALL(glViewportArrayv(0, state->viewport_count + reset_count, viewports));
4119 4120
    context->viewport_count = state->viewport_count;

4121 4122 4123
    checkGLcall("setting clip space and viewport");
}

4124
static void viewport_vertexpart(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
4125
{
4126 4127
    if (!isStateDirty(context, STATE_TRANSFORM(WINED3D_TS_PROJECTION)))
        transform_projection(context, state, STATE_TRANSFORM(WINED3D_TS_PROJECTION));
4128 4129
    if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE))
            && state->render_states[WINED3D_RS_POINTSCALEENABLE])
4130
        state_pscale(context, state, STATE_RENDER(WINED3D_RS_POINTSCALEENABLE));
4131
    /* Update the position fixup. */
4132
    context->constant_update_mask |= WINED3D_SHADER_CONST_POS_FIXUP;
4133 4134
}

4135
static void light(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
4136
{
4137
    const struct wined3d_gl_info *gl_info = context->gl_info;
4138
    UINT Index = state_id - STATE_ACTIVELIGHT(0);
4139
    const struct wined3d_light_info *lightInfo = state->light_state.lights[Index];
4140

4141 4142
    if (!lightInfo)
    {
4143
        gl_info->gl_ops.gl.p_glDisable(GL_LIGHT0 + Index);
4144
        checkGLcall("glDisable(GL_LIGHT0 + Index)");
4145 4146 4147
    }
    else
    {
4148 4149 4150
        float quad_att;

        /* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
4151 4152
        gl_info->gl_ops.gl.p_glMatrixMode(GL_MODELVIEW);
        gl_info->gl_ops.gl.p_glPushMatrix();
4153
        gl_info->gl_ops.gl.p_glLoadMatrixf(&state->transforms[WINED3D_TS_VIEW]._11);
4154

4155 4156 4157
        gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_DIFFUSE, &lightInfo->OriginalParms.diffuse.r);
        gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_SPECULAR, &lightInfo->OriginalParms.specular.r);
        gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, &lightInfo->OriginalParms.ambient.r);
4158 4159
        checkGLcall("glLightfv");

4160 4161 4162
        if ((lightInfo->OriginalParms.range * lightInfo->OriginalParms.range) >= FLT_MIN)
            quad_att = 1.4f / (lightInfo->OriginalParms.range * lightInfo->OriginalParms.range);
        else
4163
            quad_att = 0.0f; /*  0 or  MAX?  (0 seems to be ok) */
4164

4165 4166 4167 4168
        /* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
         * but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
         * Attenuation0 to NaN and crashes in the gl lib
         */
4169

4170 4171
        switch (lightInfo->OriginalParms.type)
        {
4172
            case WINED3D_LIGHT_POINT:
4173
                /* Position */
4174
                gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->position.x);
4175
                checkGLcall("glLightfv");
4176
                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4177
                checkGLcall("glLightf");
4178 4179
                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION,
                        lightInfo->OriginalParms.attenuation0);
4180
                checkGLcall("glLightf");
4181 4182
                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION,
                        lightInfo->OriginalParms.attenuation1);
4183
                checkGLcall("glLightf");
4184 4185
                if (quad_att < lightInfo->OriginalParms.attenuation2)
                    quad_att = lightInfo->OriginalParms.attenuation2;
4186
                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4187
                checkGLcall("glLightf");
4188 4189 4190
                /* FIXME: Range */
                break;

4191
            case WINED3D_LIGHT_SPOT:
4192
                /* Position */
4193
                gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->position.x);
4194 4195
                checkGLcall("glLightfv");
                /* Direction */
4196
                gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_SPOT_DIRECTION, &lightInfo->direction.x);
4197
                checkGLcall("glLightfv");
4198
                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, lightInfo->exponent);
4199
                checkGLcall("glLightf");
4200
                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4201
                checkGLcall("glLightf");
4202 4203
                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION,
                        lightInfo->OriginalParms.attenuation0);
4204
                checkGLcall("glLightf");
4205 4206
                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION,
                        lightInfo->OriginalParms.attenuation1);
4207
                checkGLcall("glLightf");
4208 4209
                if (quad_att < lightInfo->OriginalParms.attenuation2)
                    quad_att = lightInfo->OriginalParms.attenuation2;
4210
                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
4211
                checkGLcall("glLightf");
4212 4213 4214
                /* FIXME: Range */
                break;

4215
            case WINED3D_LIGHT_DIRECTIONAL:
4216
                /* Direction */
4217
                /* Note GL uses w position of 0 for direction! */
4218
                gl_info->gl_ops.gl.p_glLightfv(GL_LIGHT0 + Index, GL_POSITION, &lightInfo->direction.x);
4219
                checkGLcall("glLightfv");
4220
                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
4221
                checkGLcall("glLightf");
4222
                gl_info->gl_ops.gl.p_glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, 0.0f);
4223 4224 4225 4226
                checkGLcall("glLightf");
                break;

            default:
4227
                FIXME("Unrecognized light type %#x.\n", lightInfo->OriginalParms.type);
4228 4229 4230
        }

        /* Restore the modelview matrix */
4231
        gl_info->gl_ops.gl.p_glPopMatrix();
4232

4233
        gl_info->gl_ops.gl.p_glEnable(GL_LIGHT0 + Index);
4234 4235 4236 4237
        checkGLcall("glEnable(GL_LIGHT0 + Index)");
    }
}

4238
static void scissorrect(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
4239
{
4240
    const struct wined3d_gl_info *gl_info = context->gl_info;
4241 4242
    unsigned int height = 0;
    const RECT *r;
4243 4244 4245 4246

    /* Warning: glScissor uses window coordinates, not viewport coordinates,
     * so our viewport correction does not apply. Warning2: Even in windowed
     * mode the coords are relative to the window, not the screen. */
4247

4248
    if (!context->render_offscreen)
4249
    {
4250
        const struct wined3d_rendertarget_view *target = state->fb->render_targets[0];
4251
        unsigned int width;
4252

4253
        wined3d_rendertarget_view_get_drawable_size(target, context, &width, &height);
4254
    }
4255 4256 4257 4258 4259 4260 4261 4262 4263 4264 4265 4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283 4284 4285 4286 4287

    if (gl_info->supported[ARB_VIEWPORT_ARRAY])
    {
        GLint sr[4 * WINED3D_MAX_VIEWPORTS];
        unsigned int i, reset_count = 0;

        for (i = 0; i < state->scissor_rect_count; ++i)
        {
            r = &state->scissor_rects[i];

            sr[i * 4] = r->left;
            sr[i * 4 + 1] = height ? height - r->top : r->top;
            sr[i * 4 + 2] = r->right - r->left;
            sr[i * 4 + 3] = r->bottom - r->top;
        }

        if (context->scissor_rect_count > state->scissor_rect_count)
            reset_count = context->scissor_rect_count - state->scissor_rect_count;

        if (reset_count)
            memset(&sr[state->scissor_rect_count * 4], 0, reset_count * 4 * sizeof(GLint));

        GL_EXTCALL(glScissorArrayv(0, state->scissor_rect_count + reset_count, sr));
        checkGLcall("glScissorArrayv");
        context->scissor_rect_count = state->scissor_rect_count;
    }
    else
    {
        r = &state->scissor_rects[0];
        gl_info->gl_ops.gl.p_glScissor(r->left, height ? height - r->top : r->top,
                r->right - r->left, r->bottom - r->top);
        checkGLcall("glScissor");
    }
4288 4289
}

4290
static void indexbuffer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
4291
{
4292
    const struct wined3d_stream_info *stream_info = &context->stream_info;
4293 4294
    const struct wined3d_gl_info *gl_info = context->gl_info;

4295
    if (!state->index_buffer || !stream_info->all_vbo)
4296
    {
4297
        GL_EXTCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0));
4298 4299 4300
    }
    else
    {
4301
        struct wined3d_buffer_gl *ib = wined3d_buffer_gl(state->index_buffer);
4302
        GL_EXTCALL(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->buffer_object));
4303 4304 4305
    }
}

4306 4307 4308 4309 4310 4311 4312 4313 4314 4315 4316 4317 4318 4319 4320 4321 4322
static void depth_clip(const struct wined3d_rasterizer_state *r, const struct wined3d_gl_info *gl_info)
{
    if (!gl_info->supported[ARB_DEPTH_CLAMP])
    {
        if (r && !r->desc.depth_clip)
            FIXME("Depth clamp not supported by this GL implementation.\n");
        return;
    }

    if (r && !r->desc.depth_clip)
        gl_info->gl_ops.gl.p_glEnable(GL_DEPTH_CLAMP);
    else
        gl_info->gl_ops.gl.p_glDisable(GL_DEPTH_CLAMP);
    checkGLcall("depth clip");
}

static void rasterizer(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
4323
{
4324
    const struct wined3d_gl_info *gl_info = context->gl_info;
4325
    GLenum mode;
4326

4327
    mode = state->rasterizer_state && state->rasterizer_state->desc.front_ccw ? GL_CCW : GL_CW;
4328
    if (context->render_offscreen)
4329 4330 4331 4332
        mode = (mode == GL_CW) ? GL_CCW : GL_CW;

    gl_info->gl_ops.gl.p_glFrontFace(mode);
    checkGLcall("glFrontFace");
4333 4334
    if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_DEPTHBIAS)))
        state_depthbias(context, state, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
4335
    depth_clip(state->rasterizer_state, gl_info);
4336 4337
}

4338
static void rasterizer_cc(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
4339 4340 4341 4342 4343 4344 4345 4346
{
    const struct wined3d_gl_info *gl_info = context->gl_info;
    GLenum mode;

    mode = state->rasterizer_state && state->rasterizer_state->desc.front_ccw ? GL_CCW : GL_CW;

    gl_info->gl_ops.gl.p_glFrontFace(mode);
    checkGLcall("glFrontFace");
4347 4348
    if (!isStateDirty(context, STATE_RENDER(WINED3D_RS_DEPTHBIAS)))
        state_depthbias(context, state, STATE_RENDER(WINED3D_RS_DEPTHBIAS));
4349
    depth_clip(state->rasterizer_state, gl_info);
4350 4351
}

4352
static void psorigin_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
4353 4354 4355 4356 4357 4358 4359 4360 4361 4362
{
    static BOOL warned;

    if (!warned)
    {
        WARN("Point sprite coordinate origin switching not supported.\n");
        warned = TRUE;
    }
}

4363
static void psorigin(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
4364 4365 4366 4367
{
    const struct wined3d_gl_info *gl_info = context->gl_info;
    GLint origin = context->render_offscreen ? GL_LOWER_LEFT : GL_UPPER_LEFT;

4368 4369
    GL_EXTCALL(glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, origin));
    checkGLcall("glPointParameteri(GL_POINT_SPRITE_COORD_ORIGIN, ...)");
4370 4371
}

4372 4373 4374 4375 4376 4377
void state_srgbwrite(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
    const struct wined3d_gl_info *gl_info = context->gl_info;

    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);

4378
    if (needs_srgb_write(context, state, state->fb))
4379 4380 4381 4382 4383
        gl_info->gl_ops.gl.p_glEnable(GL_FRAMEBUFFER_SRGB);
    else
        gl_info->gl_ops.gl.p_glDisable(GL_FRAMEBUFFER_SRGB);
}

4384
static void state_cb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
4385
{
4386
    const struct wined3d_gl_info *gl_info = context->gl_info;
4387
    enum wined3d_shader_type shader_type;
4388
    struct wined3d_buffer *buffer;
4389 4390 4391
    unsigned int i, base, count;

    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
4392

4393 4394 4395 4396 4397
    if (STATE_IS_GRAPHICS_CONSTANT_BUFFER(state_id))
        shader_type = state_id - STATE_GRAPHICS_CONSTANT_BUFFER(0);
    else
        shader_type = WINED3D_SHADER_TYPE_COMPUTE;

4398
    wined3d_gl_limits_get_uniform_block_range(&gl_info->limits, shader_type, &base, &count);
4399 4400
    for (i = 0; i < count; ++i)
    {
4401
        buffer = state->cb[shader_type][i];
4402 4403
        GL_EXTCALL(glBindBufferBase(GL_UNIFORM_BUFFER, base + i,
                buffer ? wined3d_buffer_gl(buffer)->buffer_object : 0));
4404
    }
4405
    checkGLcall("bind constant buffers");
4406 4407 4408 4409 4410 4411 4412 4413 4414
}

static void state_cb_warn(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);

    WARN("Constant buffers (%s) no supported.\n", debug_d3dstate(state_id));
}

4415 4416 4417 4418 4419 4420 4421 4422
static void state_shader_resource_binding(struct wined3d_context *context,
        const struct wined3d_state *state, DWORD state_id)
{
    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);

    context->update_shader_resource_bindings = 1;
}

4423 4424 4425 4426 4427 4428 4429
static void state_cs_resource_binding(struct wined3d_context *context,
        const struct wined3d_state *state, DWORD state_id)
{
    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
    context->update_compute_shader_resource_bindings = 1;
}

4430 4431 4432 4433 4434 4435 4436
static void state_uav_binding(struct wined3d_context *context,
        const struct wined3d_state *state, DWORD state_id)
{
    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
    context->update_unordered_access_view_bindings = 1;
}

4437 4438 4439 4440 4441 4442 4443
static void state_cs_uav_binding(struct wined3d_context *context,
        const struct wined3d_state *state, DWORD state_id)
{
    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);
    context->update_compute_unordered_access_view_bindings = 1;
}

4444 4445 4446 4447 4448
static void state_uav_warn(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
    WARN("ARB_image_load_store is not supported by OpenGL implementation.\n");
}

4449 4450
static void state_so(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
4451
    struct wined3d_context_gl *context_gl = wined3d_context_gl(context);
4452 4453 4454 4455 4456 4457
    const struct wined3d_gl_info *gl_info = context->gl_info;
    struct wined3d_buffer *buffer;
    unsigned int offset, size, i;

    TRACE("context %p, state %p, state_id %#x.\n", context, state, state_id);

4458
    wined3d_context_gl_end_transform_feedback(context_gl);
4459

4460 4461 4462 4463 4464 4465 4466 4467 4468 4469 4470 4471 4472 4473 4474 4475
    for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
    {
        if (!(buffer = state->stream_output[i].buffer))
        {
            GL_EXTCALL(glBindBufferBase(GL_TRANSFORM_FEEDBACK_BUFFER, i, 0));
            continue;
        }

        offset = state->stream_output[i].offset;
        if (offset == ~0u)
        {
            FIXME("Appending to stream output buffers not implemented.\n");
            offset = 0;
        }
        size = buffer->resource.size - offset;
        GL_EXTCALL(glBindBufferRange(GL_TRANSFORM_FEEDBACK_BUFFER, i,
4476
                wined3d_buffer_gl(buffer)->buffer_object, offset, size));
4477 4478 4479 4480 4481 4482 4483 4484 4485
    }
    checkGLcall("bind transform feedback buffers");
}

static void state_so_warn(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
{
    WARN("Transform feedback not supported.\n");
}

4486
const struct wined3d_state_entry_template misc_state_template[] =
4487
{
4488
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX),  { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX),  state_cb,           }, ARB_UNIFORM_BUFFER_OBJECT       },
4489
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX),  { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX),  state_cb_warn,      }, WINED3D_GL_EXT_NONE             },
4490 4491
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL),    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL),    state_cb,           }, ARB_UNIFORM_BUFFER_OBJECT       },
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL),    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL),    state_cb_warn,      }, WINED3D_GL_EXT_NONE             },
4492 4493
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN),  { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN),  state_cb,           }, ARB_UNIFORM_BUFFER_OBJECT       },
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN),  { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN),  state_cb_warn,      }, WINED3D_GL_EXT_NONE             },
4494
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY),{ STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY),state_cb,           }, ARB_UNIFORM_BUFFER_OBJECT       },
4495
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY),{ STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY),state_cb_warn,      }, WINED3D_GL_EXT_NONE             },
4496
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL),   { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL),   state_cb,           }, ARB_UNIFORM_BUFFER_OBJECT       },
4497
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL),   { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL),   state_cb_warn,      }, WINED3D_GL_EXT_NONE             },
4498 4499
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE), { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE), state_cb,           }, ARB_UNIFORM_BUFFER_OBJECT       },
    { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE), { STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE), state_cb_warn,      }, WINED3D_GL_EXT_NONE             },
4500
    { STATE_GRAPHICS_SHADER_RESOURCE_BINDING,             { STATE_GRAPHICS_SHADER_RESOURCE_BINDING,             state_shader_resource_binding}, WINED3D_GL_EXT_NONE    },
4501 4502
    { STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING,       { STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING,       state_uav_binding   }, ARB_SHADER_IMAGE_LOAD_STORE     },
    { STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING,       { STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING,       state_uav_warn      }, WINED3D_GL_EXT_NONE             },
4503
    { STATE_COMPUTE_SHADER_RESOURCE_BINDING,              { STATE_COMPUTE_SHADER_RESOURCE_BINDING,              state_cs_resource_binding}, WINED3D_GL_EXT_NONE        },
4504 4505
    { STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING,        { STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING,        state_cs_uav_binding}, ARB_SHADER_IMAGE_LOAD_STORE     },
    { STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING,        { STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING,        state_uav_warn      }, WINED3D_GL_EXT_NONE             },
4506 4507
    { STATE_STREAM_OUTPUT,                                { STATE_STREAM_OUTPUT,                                state_so,           }, WINED3D_GL_VERSION_3_2          },
    { STATE_STREAM_OUTPUT,                                { STATE_STREAM_OUTPUT,                                state_so_warn,      }, WINED3D_GL_EXT_NONE             },
4508 4509 4510
    { STATE_RENDER(WINED3D_RS_SRCBLEND),                  { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_DESTBLEND),                 { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          state_blend         }, WINED3D_GL_EXT_NONE             },
4511 4512
    { STATE_RENDER(WINED3D_RS_EDGEANTIALIAS),             { STATE_RENDER(WINED3D_RS_EDGEANTIALIAS),             state_line_antialias}, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ANTIALIASEDLINEENABLE),     { STATE_RENDER(WINED3D_RS_ANTIALIASEDLINEENABLE),     state_line_antialias}, WINED3D_GL_EXT_NONE             },
4513 4514 4515 4516 4517
    { STATE_RENDER(WINED3D_RS_SEPARATEALPHABLENDENABLE),  { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_SRCBLENDALPHA),             { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_DESTBLENDALPHA),            { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_DESTBLENDALPHA),            { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_BLENDOPALPHA),              { STATE_RENDER(WINED3D_RS_ALPHABLENDENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
4518
    { STATE_BLEND,                                        { STATE_BLEND,                                        state_blend_object  }, WINED3D_GL_EXT_NONE             },
4519 4520
    { STATE_BLEND_FACTOR,                                 { STATE_BLEND_FACTOR,                                 state_blend_factor  }, EXT_BLEND_COLOR                 },
    { STATE_BLEND_FACTOR,                                 { STATE_BLEND_FACTOR,                                 state_blend_factor_w}, WINED3D_GL_EXT_NONE             },
4521 4522
    { STATE_STREAMSRC,                                    { STATE_STREAMSRC,                                    streamsrc           }, WINED3D_GL_EXT_NONE             },
    { STATE_VDECL,                                        { STATE_VDECL,                                        vdecl_miscpart      }, WINED3D_GL_EXT_NONE             },
4523 4524
    { STATE_RASTERIZER,                                   { STATE_RASTERIZER,                                   rasterizer_cc       }, ARB_CLIP_CONTROL                },
    { STATE_RASTERIZER,                                   { STATE_RASTERIZER,                                   rasterizer          }, WINED3D_GL_EXT_NONE             },
4525
    { STATE_SCISSORRECT,                                  { STATE_SCISSORRECT,                                  scissorrect         }, WINED3D_GL_EXT_NONE             },
4526
    { STATE_POINTSPRITECOORDORIGIN,                       { STATE_POINTSPRITECOORDORIGIN,                       state_nop           }, ARB_CLIP_CONTROL                },
4527 4528 4529
    { STATE_POINTSPRITECOORDORIGIN,                       { STATE_POINTSPRITECOORDORIGIN,                       psorigin            }, WINED3D_GL_VERSION_2_0          },
    { STATE_POINTSPRITECOORDORIGIN,                       { STATE_POINTSPRITECOORDORIGIN,                       psorigin_w          }, WINED3D_GL_EXT_NONE             },

4530
    /* TODO: Move shader constant loading to vertex and fragment pipeline respectively, as soon as the pshader and
4531 4532
     * vshader loadings are untied from each other
     */
4533
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4534 4535 4536
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
4537
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4538 4539 4540
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
4541
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4542 4543 4544
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
4545
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4546 4547 4548
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
4549
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4550 4551 4552
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
4553
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4554 4555 4556
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
4557
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4558 4559 4560
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
4561
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4562 4563 4564
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, WINED3D_GL_EXT_NONE             },
4565
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4566
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
4567
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4568
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
4569
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4570
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
4571
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4572
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
4573
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4574
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
4575
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4576
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
4577
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4578
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
4579
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  shader_bumpenv      }, WINED3D_GL_EXT_NONE             },
4580
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET), { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE),  NULL                }, WINED3D_GL_EXT_NONE             },
4581

4582
    { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_miscpart_cc}, ARB_CLIP_CONTROL                },
4583
    { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_miscpart   }, WINED3D_GL_EXT_NONE             },
4584
    { STATE_INDEXBUFFER,                                  { STATE_INDEXBUFFER,                                  indexbuffer         }, ARB_VERTEX_BUFFER_OBJECT        },
4585
    { STATE_INDEXBUFFER,                                  { STATE_INDEXBUFFER,                                  state_nop           }, WINED3D_GL_EXT_NONE             },
4586
    { STATE_RENDER(WINED3D_RS_ANTIALIAS),                 { STATE_RENDER(WINED3D_RS_ANTIALIAS),                 state_antialias     }, WINED3D_GL_EXT_NONE             },
4587
    { STATE_RENDER(WINED3D_RS_TEXTUREPERSPECTIVE),        { STATE_RENDER(WINED3D_RS_TEXTUREPERSPECTIVE),        state_nop           }, WINED3D_GL_EXT_NONE             },
4588 4589 4590 4591
    { STATE_RENDER(WINED3D_RS_ZENABLE),                   { STATE_RENDER(WINED3D_RS_ZENABLE),                   state_zenable       }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAPU),                     { STATE_RENDER(WINED3D_RS_WRAPU),                     state_wrapu         }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAPV),                     { STATE_RENDER(WINED3D_RS_WRAPV),                     state_wrapv         }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_FILLMODE),                  { STATE_RENDER(WINED3D_RS_FILLMODE),                  state_fillmode      }, WINED3D_GL_EXT_NONE             },
4592 4593
    { STATE_RENDER(WINED3D_RS_LINEPATTERN),               { STATE_RENDER(WINED3D_RS_LINEPATTERN),               state_linepattern   }, WINED3D_GL_LEGACY_CONTEXT       },
    { STATE_RENDER(WINED3D_RS_LINEPATTERN),               { STATE_RENDER(WINED3D_RS_LINEPATTERN),               state_linepattern_w }, WINED3D_GL_EXT_NONE             },
4594 4595 4596
    { STATE_RENDER(WINED3D_RS_MONOENABLE),                { STATE_RENDER(WINED3D_RS_MONOENABLE),                state_monoenable    }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ROP2),                      { STATE_RENDER(WINED3D_RS_ROP2),                      state_rop2          }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_PLANEMASK),                 { STATE_RENDER(WINED3D_RS_PLANEMASK),                 state_planemask     }, WINED3D_GL_EXT_NONE             },
4597
    { STATE_RENDER(WINED3D_RS_ZWRITEENABLE),              { STATE_RENDER(WINED3D_RS_ZWRITEENABLE),              state_zwriteenable  }, WINED3D_GL_EXT_NONE             },
4598 4599 4600 4601 4602 4603 4604 4605 4606 4607 4608 4609 4610 4611 4612 4613 4614 4615 4616
    { STATE_RENDER(WINED3D_RS_LASTPIXEL),                 { STATE_RENDER(WINED3D_RS_LASTPIXEL),                 state_lastpixel     }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_CULLMODE),                  { STATE_RENDER(WINED3D_RS_CULLMODE),                  state_cullmode      }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ZFUNC),                     { STATE_RENDER(WINED3D_RS_ZFUNC),                     state_zfunc         }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_DITHERENABLE),              { STATE_RENDER(WINED3D_RS_DITHERENABLE),              state_ditherenable  }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_SUBPIXEL),                  { STATE_RENDER(WINED3D_RS_SUBPIXEL),                  state_subpixel      }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_SUBPIXELX),                 { STATE_RENDER(WINED3D_RS_SUBPIXELX),                 state_subpixelx     }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_STIPPLEDALPHA),             { STATE_RENDER(WINED3D_RS_STIPPLEDALPHA),             state_stippledalpha }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_STIPPLEENABLE),             { STATE_RENDER(WINED3D_RS_STIPPLEENABLE),             state_stippleenable }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_MIPMAPLODBIAS),             { STATE_RENDER(WINED3D_RS_MIPMAPLODBIAS),             state_mipmaplodbias }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ANISOTROPY),                { STATE_RENDER(WINED3D_RS_ANISOTROPY),                state_anisotropy    }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_FLUSHBATCH),                { STATE_RENDER(WINED3D_RS_FLUSHBATCH),                state_flushbatch    }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_TRANSLUCENTSORTINDEPENDENT),{ STATE_RENDER(WINED3D_RS_TRANSLUCENTSORTINDEPENDENT),state_translucentsi }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_STENCILENABLE),             { STATE_RENDER(WINED3D_RS_STENCILENABLE),             state_stencil       }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_STENCILFAIL),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_STENCILZFAIL),              { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_STENCILPASS),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_STENCILFUNC),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_STENCILREF),                { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_STENCILMASK),               { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
4617
    { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          state_stencilwrite2s_ext}, EXT_STENCIL_TWO_SIDE        },
4618 4619
    { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          { STATE_RENDER(WINED3D_RS_STENCILWRITEMASK),          state_stencilwrite  }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_TWOSIDEDSTENCILMODE),       { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
4620 4621 4622 4623
    { STATE_RENDER(WINED3D_RS_BACK_STENCILFAIL),          { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_BACK_STENCILZFAIL),         { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_BACK_STENCILPASS),          { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_BACK_STENCILFUNC),          { STATE_RENDER(WINED3D_RS_STENCILENABLE),             NULL                }, WINED3D_GL_EXT_NONE             },
4624 4625 4626 4627 4628 4629 4630 4631 4632 4633 4634 4635 4636 4637 4638 4639 4640 4641 4642 4643 4644 4645 4646 4647 4648 4649 4650 4651 4652 4653 4654 4655 4656 4657 4658 4659 4660
    { STATE_RENDER(WINED3D_RS_WRAP0),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     state_wrap          }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP1),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP2),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP3),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP4),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP5),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP6),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP7),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP8),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP9),                     { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP10),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP11),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP12),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP13),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP14),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_WRAP15),                    { STATE_RENDER(WINED3D_RS_WRAP0),                     NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_EXTENTS),                   { STATE_RENDER(WINED3D_RS_EXTENTS),                   state_extents       }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_COLORKEYBLENDENABLE),       { STATE_RENDER(WINED3D_RS_COLORKEYBLENDENABLE),       state_ckeyblend     }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_SOFTWAREVERTEXPROCESSING),  { STATE_RENDER(WINED3D_RS_SOFTWAREVERTEXPROCESSING),  state_swvp          }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_PATCHEDGESTYLE),            { STATE_RENDER(WINED3D_RS_PATCHEDGESTYLE),            state_patchedgestyle}, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_PATCHSEGMENTS),             { STATE_RENDER(WINED3D_RS_PATCHSEGMENTS),             state_patchsegments }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_POSITIONDEGREE),            { STATE_RENDER(WINED3D_RS_POSITIONDEGREE),            state_positiondegree}, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_NORMALDEGREE),              { STATE_RENDER(WINED3D_RS_NORMALDEGREE),              state_normaldegree  }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_MINTESSELLATIONLEVEL),      { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_MAXTESSELLATIONLEVEL),      { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ADAPTIVETESS_X),            { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Y),            { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ADAPTIVETESS_Z),            { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ADAPTIVETESS_W),            { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),{ STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),state_nvdb          }, EXT_DEPTH_BOUNDS_TEST           },
    { STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),{ STATE_RENDER(WINED3D_RS_ENABLEADAPTIVETESSELLATION),state_tessellation  }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS),      { STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS),      state_msaa          }, ARB_MULTISAMPLE                 },
    { STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS),      { STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS),      state_msaa_w        }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_MULTISAMPLEMASK),           { STATE_RENDER(WINED3D_RS_MULTISAMPLEMASK),           state_multisampmask }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_DEBUGMONITORTOKEN),         { STATE_RENDER(WINED3D_RS_DEBUGMONITORTOKEN),         state_debug_monitor }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          state_colorwrite0   }, EXT_DRAW_BUFFERS2               },
    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          state_colorwrite    }, WINED3D_GL_EXT_NONE             },
4661
    { STATE_RENDER(WINED3D_RS_BLENDOP),                   { STATE_RENDER(WINED3D_RS_BLENDOP),                   state_blendop       }, WINED3D_GL_BLEND_EQUATION       },
4662 4663 4664 4665 4666 4667 4668 4669 4670 4671 4672
    { STATE_RENDER(WINED3D_RS_BLENDOP),                   { STATE_RENDER(WINED3D_RS_BLENDOP),                   state_blendop_w     }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE),         { STATE_RENDER(WINED3D_RS_SCISSORTESTENABLE),         state_scissor       }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_SLOPESCALEDEPTHBIAS),       { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1),         state_colorwrite1   }, EXT_DRAW_BUFFERS2               },
    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE1),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2),         state_colorwrite2   }, EXT_DRAW_BUFFERS2               },
    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE2),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3),         state_colorwrite3   }, EXT_DRAW_BUFFERS2               },
    { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE3),         { STATE_RENDER(WINED3D_RS_COLORWRITEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 { STATE_RENDER(WINED3D_RS_DEPTHBIAS),                 state_depthbias     }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ZVISIBLE),                  { STATE_RENDER(WINED3D_RS_ZVISIBLE),                  state_zvisible      }, WINED3D_GL_EXT_NONE             },
4673
    /* Samplers */
4674 4675 4676 4677 4678 4679 4680 4681 4682 4683 4684 4685 4686 4687 4688 4689 4690 4691 4692 4693
    { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(8),                                   { STATE_SAMPLER(8),                                   sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(9),                                   { STATE_SAMPLER(9),                                   sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(10),                                  { STATE_SAMPLER(10),                                  sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(11),                                  { STATE_SAMPLER(11),                                  sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(12),                                  { STATE_SAMPLER(12),                                  sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(13),                                  { STATE_SAMPLER(13),                                  sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(14),                                  { STATE_SAMPLER(14),                                  sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(15),                                  { STATE_SAMPLER(15),                                  sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(16), /* Vertex sampler 0 */           { STATE_SAMPLER(16),                                  sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(17), /* Vertex sampler 1 */           { STATE_SAMPLER(17),                                  sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(18), /* Vertex sampler 2 */           { STATE_SAMPLER(18),                                  sampler             }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(19), /* Vertex sampler 3 */           { STATE_SAMPLER(19),                                  sampler             }, WINED3D_GL_EXT_NONE             },
4694
    { STATE_BASEVERTEXINDEX,                              { STATE_BASEVERTEXINDEX,                              state_nop,          }, ARB_DRAW_ELEMENTS_BASE_VERTEX   },
4695
    { STATE_BASEVERTEXINDEX,                              { STATE_STREAMSRC,                                    NULL,               }, WINED3D_GL_EXT_NONE             },
4696
    { STATE_FRAMEBUFFER,                                  { STATE_FRAMEBUFFER,                                  context_state_fb    }, WINED3D_GL_EXT_NONE             },
4697
    { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            context_state_drawbuf},WINED3D_GL_EXT_NONE             },
4698
    { STATE_SHADER(WINED3D_SHADER_TYPE_HULL),             { STATE_SHADER(WINED3D_SHADER_TYPE_HULL),             state_shader        }, WINED3D_GL_EXT_NONE             },
4699
    { STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN),           { STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN),           state_shader        }, WINED3D_GL_EXT_NONE             },
4700
    { STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY),         { STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY),         state_shader        }, WINED3D_GL_EXT_NONE             },
4701
    { STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE),          { STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE),          state_compute_shader}, WINED3D_GL_EXT_NONE             },
4702
    {0 /* Terminate */,                                   { 0,                                                  0                   }, WINED3D_GL_EXT_NONE             },
4703 4704
};

4705
static const struct wined3d_state_entry_template vp_ffp_states[] =
4706
{
4707
    { STATE_VDECL,                                        { STATE_VDECL,                                        vertexdeclaration   }, WINED3D_GL_EXT_NONE             },
4708
    { STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX),           { STATE_VDECL,                                        NULL                }, WINED3D_GL_EXT_NONE             },
4709 4710
    { STATE_MATERIAL,                                     { STATE_RENDER(WINED3D_RS_SPECULARENABLE),            NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_SPECULARENABLE),            { STATE_RENDER(WINED3D_RS_SPECULARENABLE),            state_specularenable}, WINED3D_GL_EXT_NONE             },
4711
      /* Clip planes */
4712 4713 4714 4715 4716 4717 4718 4719
    { STATE_CLIPPLANE(0),                                 { STATE_CLIPPLANE(0),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
    { STATE_CLIPPLANE(1),                                 { STATE_CLIPPLANE(1),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
    { STATE_CLIPPLANE(2),                                 { STATE_CLIPPLANE(2),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
    { STATE_CLIPPLANE(3),                                 { STATE_CLIPPLANE(3),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
    { STATE_CLIPPLANE(4),                                 { STATE_CLIPPLANE(4),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
    { STATE_CLIPPLANE(5),                                 { STATE_CLIPPLANE(5),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
    { STATE_CLIPPLANE(6),                                 { STATE_CLIPPLANE(6),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
    { STATE_CLIPPLANE(7),                                 { STATE_CLIPPLANE(7),                                 clipplane           }, WINED3D_GL_EXT_NONE             },
4720
      /* Lights */
4721
    { STATE_LIGHT_TYPE,                                   { STATE_LIGHT_TYPE,                                   state_nop           }, WINED3D_GL_EXT_NONE             },
4722 4723 4724 4725 4726 4727 4728 4729
    { STATE_ACTIVELIGHT(0),                               { STATE_ACTIVELIGHT(0),                               light               }, WINED3D_GL_EXT_NONE             },
    { STATE_ACTIVELIGHT(1),                               { STATE_ACTIVELIGHT(1),                               light               }, WINED3D_GL_EXT_NONE             },
    { STATE_ACTIVELIGHT(2),                               { STATE_ACTIVELIGHT(2),                               light               }, WINED3D_GL_EXT_NONE             },
    { STATE_ACTIVELIGHT(3),                               { STATE_ACTIVELIGHT(3),                               light               }, WINED3D_GL_EXT_NONE             },
    { STATE_ACTIVELIGHT(4),                               { STATE_ACTIVELIGHT(4),                               light               }, WINED3D_GL_EXT_NONE             },
    { STATE_ACTIVELIGHT(5),                               { STATE_ACTIVELIGHT(5),                               light               }, WINED3D_GL_EXT_NONE             },
    { STATE_ACTIVELIGHT(6),                               { STATE_ACTIVELIGHT(6),                               light               }, WINED3D_GL_EXT_NONE             },
    { STATE_ACTIVELIGHT(7),                               { STATE_ACTIVELIGHT(7),                               light               }, WINED3D_GL_EXT_NONE             },
4730
    /* Viewport */
4731
    { STATE_VIEWPORT,                                     { STATE_VIEWPORT,                                     viewport_vertexpart }, WINED3D_GL_EXT_NONE             },
4732
      /* Transform states follow                    */
4733 4734 4735 4736 4737 4738 4739 4740 4741 4742 4743 4744 4745 4746 4747 4748 4749 4750 4751 4752 4753 4754 4755 4756 4757 4758 4759 4760 4761 4762 4763 4764 4765 4766 4767 4768 4769 4770 4771 4772 4773 4774 4775 4776 4777 4778 4779 4780 4781 4782 4783 4784 4785 4786 4787 4788 4789 4790 4791 4792 4793 4794 4795 4796 4797 4798 4799 4800 4801 4802 4803 4804 4805 4806 4807 4808 4809 4810 4811 4812 4813 4814 4815 4816 4817 4818 4819 4820 4821 4822 4823 4824 4825 4826 4827 4828 4829 4830 4831 4832 4833 4834 4835 4836 4837 4838 4839 4840 4841 4842 4843 4844 4845 4846 4847 4848 4849 4850 4851 4852 4853 4854 4855 4856 4857 4858 4859 4860 4861 4862 4863 4864 4865 4866 4867 4868 4869 4870 4871 4872 4873 4874 4875 4876 4877 4878 4879 4880 4881 4882 4883 4884 4885 4886 4887 4888 4889 4890 4891 4892 4893 4894 4895 4896 4897 4898 4899 4900 4901 4902 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 4918 4919 4920 4921 4922 4923 4924 4925 4926 4927 4928 4929 4930 4931 4932 4933 4934 4935 4936 4937 4938 4939 4940 4941 4942 4943 4944 4945 4946 4947 4948 4949 4950 4951 4952 4953 4954 4955 4956 4957 4958 4959 4960 4961 4962 4963 4964 4965 4966 4967 4968 4969 4970 4971 4972 4973 4974 4975 4976 4977 4978 4979 4980 4981 4982 4983 4984 4985 4986 4987 4988 4989 4990 4991 4992 4993 4994 4995 4996 4997 4998
    { STATE_TRANSFORM(WINED3D_TS_VIEW),                   { STATE_TRANSFORM(WINED3D_TS_VIEW),                   transform_view      }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_PROJECTION),             { STATE_TRANSFORM(WINED3D_TS_PROJECTION),             transform_projection}, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_TEXTURE0),               { STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_TEXTURE1),               { STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_TEXTURE2),               { STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_TEXTURE3),               { STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_TEXTURE4),               { STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_TEXTURE5),               { STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_TEXTURE6),               { STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_TEXTURE7),               { STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), NULL            }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  0)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  0)),      transform_world     }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  1)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  1)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  2)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  2)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  3)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  3)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  4)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  4)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  5)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  5)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  6)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  6)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  7)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  7)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  8)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  8)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  9)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(  9)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 10)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 10)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 11)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 11)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 12)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 12)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 13)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 13)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 14)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 14)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 15)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 15)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 16)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 16)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 17)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 17)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 18)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 18)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 19)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 19)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 20)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 20)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 21)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 21)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 22)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 22)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 23)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 23)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 24)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 24)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 25)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 25)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 26)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 26)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 27)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 27)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 28)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 28)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 29)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 29)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 30)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 30)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 31)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 31)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 32)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 32)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 33)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 33)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 34)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 34)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 35)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 35)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 36)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 36)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 37)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 37)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 38)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 38)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 39)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 39)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 40)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 40)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 41)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 41)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 42)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 42)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 43)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 43)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 44)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 44)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 45)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 45)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 46)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 46)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 47)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 47)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 48)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 48)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 49)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 49)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 50)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 50)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 51)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 51)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 52)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 52)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 53)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 53)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 54)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 54)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 55)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 55)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 56)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 56)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 57)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 57)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 58)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 58)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 59)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 59)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 60)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 60)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 61)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 61)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 62)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 62)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 63)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 63)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 64)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 64)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 65)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 65)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 66)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 66)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 67)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 67)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 68)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 68)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 69)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 69)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 70)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 70)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 71)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 71)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 72)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 72)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 73)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 73)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 74)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 74)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 75)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 75)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 76)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 76)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 77)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 77)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 78)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 78)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 79)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 79)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 80)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 80)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 81)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 81)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 82)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 82)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 83)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 83)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 84)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 84)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 85)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 85)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 86)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 86)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 87)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 87)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 88)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 88)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 89)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 89)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 90)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 90)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 91)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 91)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 92)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 92)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 93)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 93)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 94)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 94)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 95)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 95)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 96)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 96)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 97)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 97)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 98)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 98)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 99)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX( 99)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(100)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(100)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(101)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(101)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(102)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(102)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(103)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(103)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(104)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(104)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(105)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(105)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(106)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(106)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(107)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(107)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(108)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(108)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(109)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(109)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(110)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(110)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(111)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(111)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(112)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(112)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(113)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(113)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(114)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(114)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(115)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(115)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(116)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(116)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(117)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(117)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(118)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(118)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(119)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(119)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(120)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(120)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(121)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(121)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(122)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(122)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(123)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(123)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(124)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(124)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(125)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(125)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(126)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(126)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(127)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(127)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(128)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(128)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(129)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(129)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(130)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(130)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(131)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(131)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(132)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(132)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(133)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(133)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(134)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(134)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(135)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(135)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(136)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(136)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(137)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(137)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(138)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(138)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(139)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(139)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(140)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(140)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(141)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(141)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(142)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(142)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(143)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(143)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(144)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(144)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(145)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(145)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(146)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(146)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(147)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(147)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(148)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(148)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(149)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(149)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(150)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(150)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(151)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(151)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(152)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(152)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(153)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(153)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(154)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(154)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(155)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(155)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(156)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(156)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(157)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(157)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(158)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(158)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(159)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(159)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(160)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(160)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(161)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(161)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(162)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(162)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(163)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(163)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(164)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(164)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(165)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(165)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(166)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(166)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(167)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(167)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(168)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(168)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(169)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(169)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(170)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(170)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(171)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(171)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(172)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(172)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(173)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(173)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(174)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(174)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(175)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(175)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(176)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(176)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(177)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(177)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(178)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(178)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(179)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(179)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(180)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(180)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(181)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(181)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(182)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(182)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(183)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(183)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(184)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(184)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(185)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(185)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(186)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(186)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(187)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(187)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(188)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(188)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(189)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(189)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(190)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(190)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(191)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(191)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(192)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(192)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(193)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(193)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(194)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(194)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(195)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(195)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(196)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(196)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(197)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(197)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(198)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(198)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(199)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(199)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(200)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(200)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(201)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(201)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(202)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(202)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(203)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(203)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(204)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(204)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(205)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(205)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(206)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(206)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(207)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(207)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(208)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(208)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(209)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(209)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(210)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(210)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(211)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(211)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(212)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(212)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(213)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(213)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(214)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(214)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(215)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(215)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(216)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(216)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(217)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(217)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(218)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(218)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(219)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(219)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(220)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(220)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(221)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(221)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(222)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(222)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(223)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(223)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(224)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(224)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(225)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(225)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(226)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(226)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(227)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(227)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(228)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(228)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(229)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(229)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(230)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(230)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(231)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(231)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(232)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(232)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(233)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(233)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(234)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(234)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(235)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(235)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(236)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(236)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(237)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(237)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(238)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(238)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(239)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(239)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(240)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(240)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(241)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(241)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(242)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(242)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(243)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(243)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(244)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(244)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(245)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(245)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(246)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(246)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(247)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(247)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(248)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(248)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(249)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(249)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(250)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(250)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(251)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(251)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(252)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(252)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(253)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(253)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(254)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(254)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
    { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255)),      { STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255)),      transform_worldex   }, WINED3D_GL_EXT_NONE             },
4999 5000 5001 5002 5003 5004 5005 5006 5007 5008 5009 5010 5011 5012 5013 5014
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), {STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXTURE_TRANSFORM_FLAGS), transform_texture   }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(0, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(1, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(2, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(3, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(4, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(5, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(6, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXCOORD_INDEX),  { STATE_TEXTURESTAGE(7, WINED3D_TSS_TEXCOORD_INDEX),  tex_coordindex      }, WINED3D_GL_EXT_NONE             },
5015
      /* Fog */
5016 5017 5018 5019 5020 5021 5022 5023 5024 5025 5026 5027 5028 5029 5030 5031 5032 5033 5034 5035 5036 5037 5038 5039 5040 5041 5042 5043 5044 5045 5046
    { STATE_RENDER(WINED3D_RS_FOGENABLE),                 { STATE_RENDER(WINED3D_RS_FOGENABLE),                 state_fog_vertexpart}, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_FOGTABLEMODE),              { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),             { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_RANGEFOGENABLE),            { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_CLIPPING),                  { STATE_RENDER(WINED3D_RS_CLIPPING),                  state_clipping      }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_CLIPPLANEENABLE),           { STATE_RENDER(WINED3D_RS_CLIPPING),                  NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_LIGHTING),                  { STATE_RENDER(WINED3D_RS_LIGHTING),                  state_lighting      }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_AMBIENT),                   { STATE_RENDER(WINED3D_RS_AMBIENT),                   state_ambient       }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_COLORVERTEX),               { STATE_RENDER(WINED3D_RS_COLORVERTEX),               state_colormat      }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_LOCALVIEWER),               { STATE_RENDER(WINED3D_RS_LOCALVIEWER),               state_localviewer   }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_NORMALIZENORMALS),          { STATE_RENDER(WINED3D_RS_NORMALIZENORMALS),          state_normalize     }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_DIFFUSEMATERIALSOURCE),     { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_SPECULARMATERIALSOURCE),    { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_AMBIENTMATERIALSOURCE),     { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_EMISSIVEMATERIALSOURCE),    { STATE_RENDER(WINED3D_RS_COLORVERTEX),               NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               state_vertexblend_w }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_POINTSIZE),                 { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             state_psizemin_arb  }, ARB_POINT_PARAMETERS            },
    { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             state_psizemin_ext  }, EXT_POINT_PARAMETERS            },
    { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             state_psizemin_w    }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),         { STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),         state_pointsprite   }, ARB_POINT_SPRITE                },
    { STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),         { STATE_RENDER(WINED3D_RS_POINTSPRITEENABLE),         state_pointsprite_w }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          state_pscale        }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_POINTSCALE_A),              { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_POINTSCALE_B),              { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_POINTSCALE_C),              { STATE_RENDER(WINED3D_RS_POINTSCALEENABLE),          NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             NULL                }, ARB_POINT_PARAMETERS            },
    { STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             NULL                }, EXT_POINT_PARAMETERS            },
    { STATE_RENDER(WINED3D_RS_POINTSIZE_MAX),             { STATE_RENDER(WINED3D_RS_POINTSIZE_MIN),             NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_TWEENFACTOR),               { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_INDEXEDVERTEXBLENDENABLE),  { STATE_RENDER(WINED3D_RS_VERTEXBLEND),               NULL                }, WINED3D_GL_EXT_NONE             },
5047

5048 5049 5050 5051 5052
    /* Samplers for NP2 texture matrix adjustions. They are not needed if GL_ARB_texture_non_power_of_two is supported,
     * so register a NULL state handler in that case to get the vertex part of sampler() skipped(VTF is handled in the misc states.
     * otherwise, register sampler_texmatrix, which takes care of updating the texture matrix
     */
    { STATE_SAMPLER(0),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5053
    { STATE_SAMPLER(0),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
5054
    { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
5055
    { STATE_SAMPLER(1),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5056
    { STATE_SAMPLER(1),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
5057
    { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
5058
    { STATE_SAMPLER(2),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5059
    { STATE_SAMPLER(2),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
5060
    { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
5061
    { STATE_SAMPLER(3),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5062
    { STATE_SAMPLER(3),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
5063
    { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
5064
    { STATE_SAMPLER(4),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5065
    { STATE_SAMPLER(4),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
5066
    { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
5067
    { STATE_SAMPLER(5),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5068
    { STATE_SAMPLER(5),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
5069
    { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
5070
    { STATE_SAMPLER(6),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5071
    { STATE_SAMPLER(6),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
5072
    { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
5073
    { STATE_SAMPLER(7),                                   { 0,                                                  NULL                }, ARB_TEXTURE_NON_POWER_OF_TWO    },
5074
    { STATE_SAMPLER(7),                                   { 0,                                                  NULL                }, WINED3D_GL_NORMALIZED_TEXRECT   },
5075
    { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texmatrix   }, WINED3D_GL_EXT_NONE             },
5076
    { STATE_POINT_ENABLE,                                 { STATE_POINT_ENABLE,                                 state_nop           }, WINED3D_GL_EXT_NONE             },
5077
    {0 /* Terminate */,                                   { 0,                                                  0                   }, WINED3D_GL_EXT_NONE             },
5078 5079
};

5080
static const struct wined3d_state_entry_template ffp_fragmentstate_template[] = {
5081 5082 5083 5084 5085 5086 5087 5088 5089 5090 5091 5092 5093 5094 5095 5096 5097 5098 5099 5100 5101 5102 5103 5104 5105 5106 5107 5108 5109 5110 5111 5112 5113 5114 5115 5116 5117 5118 5119 5120 5121 5122 5123 5124 5125 5126 5127 5128 5129 5130 5131 5132 5133 5134 5135 5136 5137 5138 5139 5140 5141 5142 5143 5144 5145 5146 5147 5148 5149 5150 5151 5152 5153 5154 5155 5156 5157 5158 5159 5160
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        tex_colorop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG1),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG2),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        tex_alphaop         }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG1),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG2),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_ARG0),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_ARG0),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_ALPHA_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_RESULT_ARG),      { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_CONSTANT),        { 0 /* As long as we don't support D3DTA_CONSTANT */, NULL                }, WINED3D_GL_EXT_NONE             },
5161
    { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            apply_pixelshader   }, WINED3D_GL_EXT_NONE             },
5162 5163 5164 5165
    { STATE_RENDER(WINED3D_RS_ALPHAFUNC),                 { STATE_RENDER(WINED3D_RS_ALPHATESTENABLE),           NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ALPHAREF),                  { STATE_RENDER(WINED3D_RS_ALPHATESTENABLE),           NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_ALPHATESTENABLE),           { STATE_RENDER(WINED3D_RS_ALPHATESTENABLE),           state_alpha_test    }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_COLORKEYENABLE),            { STATE_RENDER(WINED3D_RS_ALPHATESTENABLE),           NULL                }, WINED3D_GL_EXT_NONE             },
5166
    { STATE_COLOR_KEY,                                    { STATE_COLOR_KEY,                                    state_nop           }, WINED3D_GL_EXT_NONE             },
5167
    { STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),           { STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),            NULL                }, WINED3D_GL_EXT_NONE             },
5168 5169 5170 5171 5172 5173 5174 5175
    { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             state_texfactor     }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_FOGCOLOR),                  { STATE_RENDER(WINED3D_RS_FOGCOLOR),                  state_fogcolor      }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_FOGDENSITY),                { STATE_RENDER(WINED3D_RS_FOGDENSITY),                state_fogdensity    }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_FOGENABLE),                 { STATE_RENDER(WINED3D_RS_FOGENABLE),                 state_fog_fragpart  }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_FOGTABLEMODE),              { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_FOGVERTEXMODE),             { STATE_RENDER(WINED3D_RS_FOGENABLE),                 NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_FOGSTART),                  { STATE_RENDER(WINED3D_RS_FOGSTART),                  state_fogstartend   }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_FOGEND),                    { STATE_RENDER(WINED3D_RS_FOGSTART),                  NULL                }, WINED3D_GL_EXT_NONE             },
5176
    { STATE_RENDER(WINED3D_RS_SHADEMODE),                 { STATE_RENDER(WINED3D_RS_SHADEMODE),                 state_shademode     }, WINED3D_GL_EXT_NONE             },
5177 5178 5179 5180 5181 5182 5183 5184 5185
    { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
    { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
    {0 /* Terminate */,                                   { 0,                                                  0                   }, WINED3D_GL_EXT_NONE             },
5186
};
5187

5188
/* Context activation is done by the caller. */
5189
static void ffp_pipe_enable(const struct wined3d_context *context, BOOL enable) {}
5190

5191 5192 5193 5194 5195
static void *ffp_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
{
    return shader_priv;
}

5196
static void ffp_free(struct wined3d_device *device, struct wined3d_context *context) {}
5197

5198
static void vp_ffp_get_caps(const struct wined3d_adapter *adapter, struct wined3d_vertex_caps *caps)
5199
{
5200 5201
    const struct wined3d_gl_info *gl_info = &adapter->gl_info;

5202
    caps->xyzrhw = FALSE;
5203
    caps->ffp_generic_attributes = FALSE;
5204
    caps->max_active_lights = gl_info->limits.lights;
5205
    caps->max_vertex_blend_matrices = 1;
5206 5207 5208 5209 5210 5211
    caps->max_vertex_blend_matrix_index = 0;
    caps->vertex_processing_caps = WINED3DVTXPCAPS_DIRECTIONALLIGHTS
            | WINED3DVTXPCAPS_MATERIALSOURCE7
            | WINED3DVTXPCAPS_POSITIONALLIGHTS
            | WINED3DVTXPCAPS_LOCALVIEWER
            | WINED3DVTXPCAPS_VERTEXFOG
5212 5213
            | WINED3DVTXPCAPS_TEXGEN
            | WINED3DVTXPCAPS_TEXGEN_SPHEREMAP;
5214
    caps->fvf_caps = WINED3DFVFCAPS_PSIZE | 0x0008; /* 8 texture coords */
5215
    caps->max_user_clip_planes = gl_info->limits.user_clip_distances;
5216 5217 5218 5219 5220
    caps->raster_caps = 0;
    if (gl_info->supported[NV_FOG_DISTANCE])
        caps->raster_caps |= WINED3DPRASTERCAPS_FOGRANGE;
}

5221 5222 5223 5224 5225
static DWORD vp_ffp_get_emul_mask(const struct wined3d_gl_info *gl_info)
{
    return GL_EXT_EMUL_ARB_MULTITEXTURE | GL_EXT_EMUL_EXT_FOG_COORD;
}

5226 5227
const struct wined3d_vertex_pipe_ops ffp_vertex_pipe =
{
5228
    ffp_pipe_enable,
5229
    vp_ffp_get_caps,
5230
    vp_ffp_get_emul_mask,
5231 5232 5233 5234 5235
    ffp_alloc,
    ffp_free,
    vp_ffp_states,
};

5236
static void ffp_fragment_get_caps(const struct wined3d_adapter *adapter, struct fragment_caps *caps)
5237
{
5238 5239
    const struct wined3d_gl_info *gl_info = &adapter->gl_info;

5240
    caps->wined3d_caps = 0;
5241 5242 5243 5244 5245 5246 5247 5248 5249 5250
    caps->PrimitiveMiscCaps = 0;
    caps->TextureOpCaps = WINED3DTEXOPCAPS_ADD
            | WINED3DTEXOPCAPS_ADDSIGNED
            | WINED3DTEXOPCAPS_ADDSIGNED2X
            | WINED3DTEXOPCAPS_MODULATE
            | WINED3DTEXOPCAPS_MODULATE2X
            | WINED3DTEXOPCAPS_MODULATE4X
            | WINED3DTEXOPCAPS_SELECTARG1
            | WINED3DTEXOPCAPS_SELECTARG2
            | WINED3DTEXOPCAPS_DISABLE;
5251

5252 5253 5254 5255
    if (gl_info->supported[ARB_TEXTURE_ENV_COMBINE]
            || gl_info->supported[EXT_TEXTURE_ENV_COMBINE]
            || gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
    {
5256 5257 5258 5259 5260 5261
        caps->TextureOpCaps |= WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA
                | WINED3DTEXOPCAPS_BLENDTEXTUREALPHA
                | WINED3DTEXOPCAPS_BLENDFACTORALPHA
                | WINED3DTEXOPCAPS_BLENDCURRENTALPHA
                | WINED3DTEXOPCAPS_LERP
                | WINED3DTEXOPCAPS_SUBTRACT;
5262
    }
5263 5264 5265
    if (gl_info->supported[ATI_TEXTURE_ENV_COMBINE3]
            || gl_info->supported[NV_TEXTURE_ENV_COMBINE4])
    {
5266 5267 5268 5269 5270
        caps->TextureOpCaps |= WINED3DTEXOPCAPS_ADDSMOOTH
                | WINED3DTEXOPCAPS_MULTIPLYADD
                | WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
                | WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
                | WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM;
5271
    }
5272
    if (gl_info->supported[ARB_TEXTURE_ENV_DOT3])
5273
        caps->TextureOpCaps |= WINED3DTEXOPCAPS_DOTPRODUCT3;
5274

5275 5276
    caps->MaxTextureBlendStages = gl_info->limits.textures;
    caps->MaxSimultaneousTextures = gl_info->limits.textures;
5277 5278
}

5279 5280 5281 5282 5283
static DWORD ffp_fragment_get_emul_mask(const struct wined3d_gl_info *gl_info)
{
    return GL_EXT_EMUL_ARB_MULTITEXTURE | GL_EXT_EMUL_EXT_FOG_COORD;
}

5284 5285 5286
static BOOL ffp_color_fixup_supported(struct color_fixup_desc fixup)
{
    /* We only support identity conversions. */
5287
    return is_identity_fixup(fixup);
5288
}
5289

5290 5291 5292 5293 5294 5295 5296 5297 5298
static BOOL ffp_none_context_alloc(struct wined3d_context *context)
{
    return TRUE;
}

static void ffp_none_context_free(struct wined3d_context *context)
{
}

5299 5300 5301
const struct wined3d_fragment_pipe_ops ffp_fragment_pipeline =
{
    ffp_pipe_enable,
5302
    ffp_fragment_get_caps,
5303
    ffp_fragment_get_emul_mask,
5304 5305
    ffp_alloc,
    ffp_free,
5306 5307
    ffp_none_context_alloc,
    ffp_none_context_free,
5308
    ffp_color_fixup_supported,
5309
    ffp_fragmentstate_template,
5310
};
5311

5312
static void none_pipe_enable(const struct wined3d_context *context, BOOL enable) {}
5313

5314
static void *none_alloc(const struct wined3d_shader_backend_ops *shader_backend, void *shader_priv)
5315
{
5316
    return shader_priv;
5317 5318
}

5319
static void none_free(struct wined3d_device *device, struct wined3d_context *context) {}
5320

5321
static void vp_none_get_caps(const struct wined3d_adapter *adapter, struct wined3d_vertex_caps *caps)
5322
{
5323
    memset(caps, 0, sizeof(*caps));
5324 5325
}

5326 5327 5328 5329 5330
static DWORD vp_none_get_emul_mask(const struct wined3d_gl_info *gl_info)
{
    return 0;
}

5331 5332
const struct wined3d_vertex_pipe_ops none_vertex_pipe =
{
5333
    none_pipe_enable,
5334
    vp_none_get_caps,
5335
    vp_none_get_emul_mask,
5336 5337 5338 5339 5340
    none_alloc,
    none_free,
    NULL,
};

5341
static void fp_none_get_caps(const struct wined3d_adapter *adapter, struct fragment_caps *caps)
5342 5343 5344
{
    memset(caps, 0, sizeof(*caps));
}
5345

5346 5347 5348 5349 5350
static DWORD fp_none_get_emul_mask(const struct wined3d_gl_info *gl_info)
{
    return 0;
}

5351 5352 5353 5354 5355
static BOOL fp_none_color_fixup_supported(struct color_fixup_desc fixup)
{
    return is_identity_fixup(fixup);
}

5356
const struct wined3d_fragment_pipe_ops none_fragment_pipe =
5357
{
5358
    none_pipe_enable,
5359
    fp_none_get_caps,
5360
    fp_none_get_emul_mask,
5361 5362
    none_alloc,
    none_free,
5363 5364
    ffp_none_context_alloc,
    ffp_none_context_free,
5365 5366 5367 5368
    fp_none_color_fixup_supported,
    NULL,
};

5369 5370
static unsigned int num_handlers(const APPLYSTATEFUNC *funcs)
{
5371 5372 5373 5374 5375
    unsigned int i;
    for(i = 0; funcs[i]; i++);
    return i;
}

5376
static void multistate_apply_2(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
5377
{
5378 5379
    context->device->multistate_funcs[state_id][0](context, state, state_id);
    context->device->multistate_funcs[state_id][1](context, state, state_id);
5380 5381
}

5382
static void multistate_apply_3(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
5383
{
5384 5385 5386
    context->device->multistate_funcs[state_id][0](context, state, state_id);
    context->device->multistate_funcs[state_id][1](context, state, state_id);
    context->device->multistate_funcs[state_id][2](context, state, state_id);
5387 5388
}

5389
static void prune_invalid_states(struct wined3d_state_entry *state_table, const struct wined3d_d3d_info *d3d_info)
5390 5391 5392
{
    unsigned int start, last, i;

5393
    start = STATE_TEXTURESTAGE(d3d_info->limits.ffp_blend_stages, 0);
5394
    last = STATE_TEXTURESTAGE(WINED3D_MAX_TEXTURES - 1, WINED3D_HIGHEST_TEXTURE_STATE);
5395 5396 5397 5398 5399 5400
    for (i = start; i <= last; ++i)
    {
        state_table[i].representative = 0;
        state_table[i].apply = state_undefined;
    }

5401
    start = STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + d3d_info->limits.ffp_blend_stages);
5402
    last = STATE_TRANSFORM(WINED3D_TS_TEXTURE0 + WINED3D_MAX_TEXTURES - 1);
5403 5404 5405 5406 5407
    for (i = start; i <= last; ++i)
    {
        state_table[i].representative = 0;
        state_table[i].apply = state_undefined;
    }
5408

5409
    start = STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(d3d_info->limits.ffp_vertex_blend_matrices));
5410
    last = STATE_TRANSFORM(WINED3D_TS_WORLD_MATRIX(255));
5411 5412 5413 5414 5415
    for (i = start; i <= last; ++i)
    {
        state_table[i].representative = 0;
        state_table[i].apply = state_undefined;
    }
5416 5417
}

5418
static void validate_state_table(struct wined3d_state_entry *state_table)
5419
{
5420 5421 5422 5423 5424 5425 5426 5427 5428 5429 5430 5431
    static const struct
    {
        DWORD first;
        DWORD last;
    }
    rs_holes[] =
    {
        {  1,   1},
        {  3,   3},
        { 17,  18},
        { 21,  21},
        { 42,  45},
5432
        { 47,  47},
5433 5434 5435 5436
        { 61, 127},
        {149, 150},
        {169, 169},
        {177, 177},
5437
        {193, 193},
5438 5439 5440
        {196, 197},
        {  0,   0},
    };
5441 5442 5443 5444 5445 5446
    static const DWORD simple_states[] =
    {
        STATE_MATERIAL,
        STATE_VDECL,
        STATE_STREAMSRC,
        STATE_INDEXBUFFER,
5447
        STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX),
5448
        STATE_SHADER(WINED3D_SHADER_TYPE_HULL),
5449
        STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN),
5450 5451
        STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY),
        STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL),
5452
        STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE),
5453
        STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX),
5454
        STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL),
5455
        STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN),
5456 5457
        STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY),
        STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL),
5458
        STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE),
5459 5460 5461 5462
        STATE_COMPUTE_SHADER_RESOURCE_BINDING,
        STATE_GRAPHICS_SHADER_RESOURCE_BINDING,
        STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING,
        STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING,
5463
        STATE_VIEWPORT,
5464
        STATE_LIGHT_TYPE,
5465
        STATE_SCISSORRECT,
5466
        STATE_RASTERIZER,
5467
        STATE_POINTSPRITECOORDORIGIN,
5468
        STATE_BASEVERTEXINDEX,
5469
        STATE_FRAMEBUFFER,
5470
        STATE_POINT_ENABLE,
5471
        STATE_COLOR_KEY,
5472
        STATE_BLEND,
5473
        STATE_BLEND_FACTOR,
5474
    };
5475 5476 5477 5478 5479 5480 5481 5482 5483 5484 5485 5486 5487 5488
    unsigned int i, current;

    for (i = STATE_RENDER(1), current = 0; i <= STATE_RENDER(WINEHIGHEST_RENDER_STATE); ++i)
    {
        if (!rs_holes[current].first || i < STATE_RENDER(rs_holes[current].first))
        {
            if (!state_table[i].representative)
                ERR("State %s (%#x) should have a representative.\n", debug_d3dstate(i), i);
        }
        else if (state_table[i].representative)
            ERR("State %s (%#x) shouldn't have a representative.\n", debug_d3dstate(i), i);

        if (i == STATE_RENDER(rs_holes[current].last)) ++current;
    }
5489

5490
    for (i = 0; i < ARRAY_SIZE(simple_states); ++i)
5491 5492 5493 5494 5495 5496
    {
        if (!state_table[simple_states[i]].representative)
            ERR("State %s (%#x) should have a representative.\n",
                    debug_d3dstate(simple_states[i]), simple_states[i]);
    }

5497 5498 5499
    for (i = 0; i < STATE_HIGHEST + 1; ++i)
    {
        DWORD rep = state_table[i].representative;
5500
        if (rep)
5501
        {
5502
            if (state_table[rep].representative != rep)
5503 5504 5505 5506 5507 5508 5509 5510 5511 5512 5513 5514 5515 5516 5517
            {
                ERR("State %s (%#x) has invalid representative %s (%#x).\n",
                        debug_d3dstate(i), i, debug_d3dstate(rep), rep);
                state_table[i].representative = 0;
            }

            if (rep != i)
            {
                if (state_table[i].apply)
                    ERR("State %s (%#x) has both a handler and representative.\n", debug_d3dstate(i), i);
            }
            else if (!state_table[i].apply)
            {
                ERR("Self representing state %s (%#x) has no handler.\n", debug_d3dstate(i), i);
            }
5518 5519 5520 5521
        }
    }
}

5522
HRESULT compile_state_table(struct wined3d_state_entry *state_table, APPLYSTATEFUNC **dev_multistate_funcs,
5523
        const struct wined3d_d3d_info *d3d_info, const BOOL *supported_extensions,
5524
        const struct wined3d_vertex_pipe_ops *vertex, const struct wined3d_fragment_pipe_ops *fragment,
5525
        const struct wined3d_state_entry_template *misc)
5526
{
5527
    APPLYSTATEFUNC multistate_funcs[STATE_HIGHEST + 1][3];
5528
    const struct wined3d_state_entry_template *cur;
5529
    unsigned int i, type, handlers;
5530
    BOOL set[STATE_HIGHEST + 1];
5531 5532 5533

    memset(multistate_funcs, 0, sizeof(multistate_funcs));

5534 5535 5536 5537
    for (i = 0; i < STATE_HIGHEST + 1; ++i)
    {
        state_table[i].representative = 0;
        state_table[i].apply = state_undefined;
5538 5539
    }

5540 5541
    for (type = 0; type < 3; ++type)
    {
5542
        /* This switch decides the order in which the states are applied */
5543 5544
        switch (type)
        {
5545
            case 0: cur = misc; break;
5546
            case 1: cur = fragment->states; break;
5547
            case 2: cur = vertex->vp_states; break;
5548 5549
            default: cur = NULL; /* Stupid compiler */
        }
5550
        if (!cur) continue;
5551

5552 5553 5554 5555 5556
        /* GL extension filtering should not prevent multiple handlers being applied from different
         * pipeline parts
         */
        memset(set, 0, sizeof(set));

5557 5558
        for (i = 0; cur[i].state; ++i)
        {
5559
            APPLYSTATEFUNC *funcs_array;
5560 5561 5562 5563 5564 5565 5566 5567

            /* Only use the first matching state with the available extension from one template.
             * e.g.
             * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func1}, XYZ_FANCY},
             * {D3DRS_FOOBAR, {D3DRS_FOOBAR, func2}, 0        }
             *
             * if GL_XYZ_fancy is supported, ignore the 2nd line
             */
5568
            if (set[cur[i].state]) continue;
5569
            /* Skip state lines depending on unsupported extensions */
5570
            if (!supported_extensions[cur[i].extension]) continue;
5571 5572 5573 5574 5575 5576 5577 5578
            set[cur[i].state] = TRUE;
            /* In some cases having an extension means that nothing has to be
             * done for a state, e.g. if GL_ARB_texture_non_power_of_two is
             * supported, the texture coordinate fixup can be ignored. If the
             * apply function is used, mark the state set(done above) to prevent
             * applying later lines, but do not record anything in the state
             * table
             */
5579
            if (!cur[i].content.representative) continue;
5580

5581 5582
            handlers = num_handlers(multistate_funcs[cur[i].state]);
            multistate_funcs[cur[i].state][handlers] = cur[i].content.apply;
5583 5584
            switch (handlers)
            {
5585
                case 0:
5586
                    state_table[cur[i].state].apply = cur[i].content.apply;
5587 5588
                    break;
                case 1:
5589
                    state_table[cur[i].state].apply = multistate_apply_2;
5590
                    if (!(dev_multistate_funcs[cur[i].state] = heap_calloc(2, sizeof(**dev_multistate_funcs))))
5591 5592
                        goto out_of_mem;

5593 5594 5595 5596
                    dev_multistate_funcs[cur[i].state][0] = multistate_funcs[cur[i].state][0];
                    dev_multistate_funcs[cur[i].state][1] = multistate_funcs[cur[i].state][1];
                    break;
                case 2:
5597
                    state_table[cur[i].state].apply = multistate_apply_3;
5598 5599
                    if (!(funcs_array = heap_realloc(dev_multistate_funcs[cur[i].state],
                            sizeof(**dev_multistate_funcs) * 3)))
5600 5601 5602
                        goto out_of_mem;

                    dev_multistate_funcs[cur[i].state] = funcs_array;
5603 5604 5605
                    dev_multistate_funcs[cur[i].state][2] = multistate_funcs[cur[i].state][2];
                    break;
                default:
5606 5607
                    ERR("Unexpected amount of state handlers for state %u: %u.\n",
                            cur[i].state, handlers + 1);
5608 5609
            }

5610 5611
            if (state_table[cur[i].state].representative
                    && state_table[cur[i].state].representative != cur[i].content.representative)
5612 5613 5614
            {
                FIXME("State %s (%#x) has different representatives in different pipeline parts.\n",
                        debug_d3dstate(cur[i].state), cur[i].state);
5615
            }
5616
            state_table[cur[i].state].representative = cur[i].content.representative;
5617 5618
        }
    }
5619

5620 5621
    prune_invalid_states(state_table, d3d_info);
    validate_state_table(state_table);
5622

5623 5624 5625
    return WINED3D_OK;

out_of_mem:
5626 5627 5628
    for (i = 0; i <= STATE_HIGHEST; ++i)
    {
        heap_free(dev_multistate_funcs[i]);
5629 5630
    }

5631
    memset(dev_multistate_funcs, 0, (STATE_HIGHEST + 1) * sizeof(*dev_multistate_funcs));
5632 5633

    return E_OUTOFMEMORY;
5634
}