nvidia_texture_shader.c 57.1 KB
Newer Older
1 2 3 4 5
/*
 * Fixed function pipeline replacement using GL_NV_register_combiners
 * and GL_NV_texture_shader
 *
 * Copyright 2006 Henri Verbeet
6
 * Copyright 2008 Stefan Dösinger(for CodeWeavers)
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
 *
 * 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"
23
#include "wine/port.h"
24 25 26 27 28 29 30 31

#include <math.h>
#include <stdio.h>

#include "wined3d_private.h"

WINE_DEFAULT_DEBUG_CHANNEL(d3d);

32 33
/* GL locking for state handlers is done by the caller. */

34
static void nvts_activate_dimensions(const struct wined3d_state *state, DWORD stage, struct wined3d_context *context)
35
{
36
    const struct wined3d_gl_info *gl_info = context->gl_info;
37 38
    BOOL bumpmap = FALSE;

39 40 41
    if (stage > 0
            && (state->texture_states[stage - 1][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_BUMPENVMAP_LUMINANCE
            || state->texture_states[stage - 1][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_BUMPENVMAP))
42
    {
43 44 45 46 47 48
        bumpmap = TRUE;
        context->texShaderBumpMap |= (1 << stage);
    } else {
        context->texShaderBumpMap &= ~(1 << stage);
    }

49
    if (state->textures[stage])
50
    {
51
        switch (state->textures[stage]->target)
52
        {
53
            case GL_TEXTURE_2D:
54 55
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV,
                        bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_2D);
56 57 58
                checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)");
                break;
            case GL_TEXTURE_RECTANGLE_ARB:
59 60
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV,
                        bumpmap ? GL_OFFSET_TEXTURE_2D_NV : GL_TEXTURE_RECTANGLE_ARB);
61 62 63
                checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, ...)");
                break;
            case GL_TEXTURE_3D:
64
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D);
65 66 67
                checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_3D)");
                break;
            case GL_TEXTURE_CUBE_MAP_ARB:
68
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB);
69 70 71
                checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_TEXTURE_CUBE_MAP_ARB)");
                break;
        }
72 73 74 75
    }
    else
    {
        gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
76 77 78 79
        checkGLcall("glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE)");
    }
}

80 81
struct tex_op_args
{
82 83 84
    GLenum input[3];
    GLenum mapping[3];
    GLenum component_usage[3];
85
};
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109

static GLenum d3dta_to_combiner_input(DWORD d3dta, DWORD stage, INT texture_idx) {
    switch (d3dta) {
        case WINED3DTA_DIFFUSE:
            return GL_PRIMARY_COLOR_NV;

        case WINED3DTA_CURRENT:
            if (stage) return GL_SPARE0_NV;
            else return GL_PRIMARY_COLOR_NV;

        case WINED3DTA_TEXTURE:
            if (texture_idx > -1) return GL_TEXTURE0_ARB + texture_idx;
            else return GL_PRIMARY_COLOR_NV;

        case WINED3DTA_TFACTOR:
            return GL_CONSTANT_COLOR0_NV;

        case WINED3DTA_SPECULAR:
            return GL_SECONDARY_COLOR_NV;

        case WINED3DTA_TEMP:
            return GL_SPARE1_NV;

        case WINED3DTA_CONSTANT:
110
            /* TODO: Support per stage constants (WINED3D_TSS_CONSTANT, NV_register_combiners2) */
111 112 113 114 115 116 117 118 119 120
            FIXME("WINED3DTA_CONSTANT, not properly supported.\n");
            return GL_CONSTANT_COLOR1_NV;

        default:
            FIXME("Unrecognized texture arg %#x\n", d3dta);
            return GL_TEXTURE;
    }
}

static GLenum invert_mapping(GLenum mapping) {
121 122
    if (mapping == GL_UNSIGNED_INVERT_NV) return GL_UNSIGNED_IDENTITY_NV;
    else if (mapping == GL_UNSIGNED_IDENTITY_NV) return GL_UNSIGNED_INVERT_NV;
123 124 125 126 127 128 129 130 131

    FIXME("Unhandled mapping %#x\n", mapping);
    return mapping;
}

static void get_src_and_opr_nvrc(DWORD stage, DWORD arg, BOOL is_alpha, GLenum* input, GLenum* mapping, GLenum *component_usage, INT texture_idx) {
    /* The WINED3DTA_COMPLEMENT flag specifies the complement of the input should
    * be used. */
    if (arg & WINED3DTA_COMPLEMENT) *mapping = GL_UNSIGNED_INVERT_NV;
132
    else *mapping = GL_UNSIGNED_IDENTITY_NV; /* Clamp all values to positive ranges */
133 134 135 136 137 138 139 140 141

    /* The WINED3DTA_ALPHAREPLICATE flag specifies the alpha component of the input
    * should be used for all input components. */
    if (is_alpha || arg & WINED3DTA_ALPHAREPLICATE) *component_usage = GL_ALPHA;
    else *component_usage = GL_RGB;

    *input = d3dta_to_combiner_input(arg & WINED3DTA_SELECTMASK, stage, texture_idx);
}

142
void set_tex_op_nvrc(const struct wined3d_gl_info *gl_info, const struct wined3d_state *state, BOOL is_alpha,
143
        int stage, enum wined3d_texture_op op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx, DWORD dst)
144
{
145
    struct tex_op_args tex_op_args = {{0}, {0}, {0}};
146 147 148 149 150 151 152 153 154
    GLenum portion = is_alpha ? GL_ALPHA : GL_RGB;
    GLenum target = GL_COMBINER0_NV + stage;
    GLenum output;

    TRACE("stage %d, is_alpha %d, op %s, arg1 %#x, arg2 %#x, arg3 %#x, texture_idx %d\n",
          stage, is_alpha, debug_d3dtop(op), arg1, arg2, arg3, texture_idx);

    /* If a texture stage references an invalid texture unit the stage just
    * passes through the result from the previous stage */
155
    if (is_invalid_op(state, stage, op, arg1, arg2, arg3))
156
    {
157
        arg1 = WINED3DTA_CURRENT;
158
        op = WINED3D_TOP_SELECT_ARG1;
159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175
    }

    get_src_and_opr_nvrc(stage, arg1, is_alpha, &tex_op_args.input[0],
                         &tex_op_args.mapping[0], &tex_op_args.component_usage[0], texture_idx);
    get_src_and_opr_nvrc(stage, arg2, is_alpha, &tex_op_args.input[1],
                         &tex_op_args.mapping[1], &tex_op_args.component_usage[1], texture_idx);
    get_src_and_opr_nvrc(stage, arg3, is_alpha, &tex_op_args.input[2],
                         &tex_op_args.mapping[2], &tex_op_args.component_usage[2], texture_idx);


    if(dst == WINED3DTA_TEMP) {
        output = GL_SPARE1_NV;
    } else {
        output = GL_SPARE0_NV;
    }

    /* This is called by a state handler which has the gl lock held and a context for the thread */
176
    switch (op)
177
    {
178
        case WINED3D_TOP_DISABLE:
179
            /* Only for alpha */
180 181
            if (!is_alpha)
                ERR("Shouldn't be called for WINED3D_TSS_COLOR_OP (WINED3DTOP_DISABLE).\n");
182 183 184 185 186 187 188 189 190 191 192
            /* Input, prev_alpha*1 */
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       GL_SPARE0_NV, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, GL_ALPHA));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV,
                       GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

193 194
        case WINED3D_TOP_SELECT_ARG1:
        case WINED3D_TOP_SELECT_ARG2:
195
            /* Input, arg*1 */
196
            if (op == WINED3D_TOP_SELECT_ARG1)
197 198
                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                           tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
199
            else
200 201 202 203 204 205 206 207 208 209
                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                           tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV,
                       GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

210 211 212
        case WINED3D_TOP_MODULATE:
        case WINED3D_TOP_MODULATE_2X:
        case WINED3D_TOP_MODULATE_4X:
213 214 215 216 217 218 219
            /* Input, arg1*arg2 */
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));

            /* Output */
220
            if (op == WINED3D_TOP_MODULATE)
221 222
                GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV,
                           GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
223
            else if (op == WINED3D_TOP_MODULATE_2X)
224 225
                GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV,
                           GL_DISCARD_NV, GL_SCALE_BY_TWO_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
226
            else if (op == WINED3D_TOP_MODULATE_4X)
227 228 229 230
                GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV,
                           GL_DISCARD_NV, GL_SCALE_BY_FOUR_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

231 232 233
        case WINED3D_TOP_ADD:
        case WINED3D_TOP_ADD_SIGNED:
        case WINED3D_TOP_ADD_SIGNED_2X:
234 235 236 237 238 239 240 241 242 243 244
            /* Input, arg1*1+arg2*1 */
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));

            /* Output */
245
            if (op == WINED3D_TOP_ADD)
246 247
                GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                           output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
248
            else if (op == WINED3D_TOP_ADD_SIGNED)
249 250
                GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                           output, GL_NONE, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE));
251
            else if (op == WINED3D_TOP_ADD_SIGNED_2X)
252 253 254 255
                GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                           output, GL_SCALE_BY_TWO_NV, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

256
        case WINED3D_TOP_SUBTRACT:
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271
            /* Input, arg1*1+-arg2*1 */
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
                       tex_op_args.input[1], GL_SIGNED_NEGATE_NV, tex_op_args.component_usage[1]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

272
        case WINED3D_TOP_ADD_SMOOTH:
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287
            /* Input, arg1*1+(1-arg1)*arg2 */
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
                       tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

288 289 290 291 292
        case WINED3D_TOP_BLEND_DIFFUSE_ALPHA:
        case WINED3D_TOP_BLEND_TEXTURE_ALPHA:
        case WINED3D_TOP_BLEND_FACTOR_ALPHA:
        case WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM:
        case WINED3D_TOP_BLEND_CURRENT_ALPHA:
293 294
        {
            GLenum alpha_src = GL_PRIMARY_COLOR_NV;
295 296 297 298 299 300 301 302 303 304 305 306
            if (op == WINED3D_TOP_BLEND_DIFFUSE_ALPHA)
                alpha_src = d3dta_to_combiner_input(WINED3DTA_DIFFUSE, stage, texture_idx);
            else if (op == WINED3D_TOP_BLEND_TEXTURE_ALPHA)
                alpha_src = d3dta_to_combiner_input(WINED3DTA_TEXTURE, stage, texture_idx);
            else if (op == WINED3D_TOP_BLEND_FACTOR_ALPHA)
                alpha_src = d3dta_to_combiner_input(WINED3DTA_TFACTOR, stage, texture_idx);
            else if (op == WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM)
                alpha_src = d3dta_to_combiner_input(WINED3DTA_TEXTURE, stage, texture_idx);
            else if (op == WINED3D_TOP_BLEND_CURRENT_ALPHA)
                alpha_src = d3dta_to_combiner_input(WINED3DTA_CURRENT, stage, texture_idx);
            else
                FIXME("Unhandled texture op %s, shouldn't happen.\n", debug_d3dtop(op));
307 308 309 310

            /* Input, arg1*alpha_src+arg2*(1-alpha_src) */
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
311
            if (op == WINED3D_TOP_BLEND_TEXTURE_ALPHA_PM)
312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329
            {
                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                           GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
            } else {
                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                           alpha_src, GL_UNSIGNED_IDENTITY_NV, GL_ALPHA));
            }
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
                       alpha_src, GL_UNSIGNED_INVERT_NV, GL_ALPHA));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;
        }

330
        case WINED3D_TOP_MODULATE_ALPHA_ADD_COLOR:
331
            /* Input, arg1_alpha*arg2_rgb+arg1_rgb*1 */
332 333
            if (is_alpha)
                ERR("Only supported for WINED3D_TSS_COLOR_OP (WINED3DTOP_MODULATEALPHA_ADDCOLOR).\n");
334 335 336 337 338 339 340 341 342 343 344 345 346 347
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

348
        case WINED3D_TOP_MODULATE_COLOR_ADD_ALPHA:
349
            /* Input, arg1_rgb*arg2_rgb+arg1_alpha*1 */
350 351
            if (is_alpha)
                ERR("Only supported for WINED3D_TSS_COLOR_OP (WINED3DTOP_MODULATECOLOR_ADDALPHA).\n");
352 353 354 355 356 357 358 359 360 361 362 363 364 365
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

366
        case WINED3D_TOP_MODULATE_INVALPHA_ADD_COLOR:
367
            /* Input, (1-arg1_alpha)*arg2_rgb+arg1_rgb*1 */
368 369
            if (is_alpha)
                ERR("Only supported for WINED3D_TSS_COLOR_OP (WINED3DTOP_MODULATEINVALPHA_ADDCOLOR).\n");
370 371 372 373 374 375 376 377 378 379 380 381 382 383
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), GL_ALPHA));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

384
        case WINED3D_TOP_MODULATE_INVCOLOR_ADD_ALPHA:
385
            /* Input, (1-arg1_rgb)*arg2_rgb+arg1_alpha*1 */
386 387
            if (is_alpha)
                ERR("Only supported for WINED3D_TSS_COLOR_OP (WINED3DTOP_MODULATEINVCOLOR_ADDALPHA).\n");
388 389 390 391 392 393 394 395 396 397 398 399 400 401
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[0], invert_mapping(tex_op_args.mapping[0]), tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], GL_ALPHA));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

402
        case WINED3D_TOP_DOTPRODUCT3:
403 404 405 406 407 408 409 410 411 412 413 414
            /* Input, arg1 . arg2 */
            /* FIXME: DX7 uses a different calculation? */
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[0], GL_EXPAND_NORMAL_NV, tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       tex_op_args.input[1], GL_EXPAND_NORMAL_NV, tex_op_args.component_usage[1]));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, output, GL_DISCARD_NV,
                       GL_DISCARD_NV, GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE));
            break;

415
        case WINED3D_TOP_MULTIPLY_ADD:
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430
            /* Input, arg3*1+arg1*arg2 */
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[2], tex_op_args.mapping[2], tex_op_args.component_usage[2]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

431
        case WINED3D_TOP_LERP:
432 433 434 435 436 437 438 439 440 441 442 443 444 445 446
            /* Input, arg3*arg1+(1-arg3)*arg2 */
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                       tex_op_args.input[2], tex_op_args.mapping[2], tex_op_args.component_usage[2]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                       tex_op_args.input[0], tex_op_args.mapping[0], tex_op_args.component_usage[0]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_C_NV,
                       tex_op_args.input[2], invert_mapping(tex_op_args.mapping[2]), tex_op_args.component_usage[2]));
            GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_D_NV,
                       tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));

            /* Output */
            GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV,
                       output, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
            break;

447 448
        case WINED3D_TOP_BUMPENVMAP_LUMINANCE:
        case WINED3D_TOP_BUMPENVMAP:
449 450
            if (gl_info->supported[NV_TEXTURE_SHADER])
            {
451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
                /* The bump map stage itself isn't exciting, just read the texture. But tell the next stage to
                 * perform bump mapping and source from the current stage. Pretty much a SELECTARG2.
                 * ARG2 is passed through unmodified(apps will most likely use D3DTA_CURRENT for arg2, arg1
                 * (which will most likely be D3DTA_TEXTURE) is available as a texture shader input for the next stage
                 */
                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_A_NV,
                           tex_op_args.input[1], tex_op_args.mapping[1], tex_op_args.component_usage[1]));
                GL_EXTCALL(glCombinerInputNV(target, portion, GL_VARIABLE_B_NV,
                           GL_ZERO, GL_UNSIGNED_INVERT_NV, portion));
                /* Always pass through to CURRENT, ignore temp arg */
                GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV,
                           GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE));
                break;
            }

        default:
467
            FIXME("Unhandled texture op: stage %d, is_alpha %d, op %s (%#x), arg1 %#x, arg2 %#x, arg3 %#x, texture_idx %d.\n",
468 469 470
                  stage, is_alpha, debug_d3dtop(op), op, arg1, arg2, arg3, texture_idx);
    }

471
    checkGLcall("set_tex_op_nvrc()");
472 473 474
}


475
static void nvrc_colorop(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
476
{
477
    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
478 479 480
    const struct wined3d_device *device = context->swapchain->device;
    BOOL tex_used = device->fixed_function_usage_map & (1 << stage);
    DWORD mapped_stage = device->texUnitMap[stage];
481
    const struct wined3d_gl_info *gl_info = context->gl_info;
482

483
    TRACE("Setting color op for stage %u.\n", stage);
484

485
    /* Using a pixel shader? Don't care for anything here, the shader applying does it */
486
    if (use_ps(state)) return;
487 488 489

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

490 491
    if (mapped_stage != WINED3D_UNMAPPED_STAGE)
    {
492
        if (tex_used && mapped_stage >= gl_info->limits.textures)
493
        {
494
            FIXME("Attempt to enable unsupported stage!\n");
495 496
            return;
        }
497
        context_active_texture(context, gl_info, mapped_stage);
498 499
    }

500
    if (state->lowest_disabled_stage > 0)
501
    {
502
        gl_info->gl_ops.gl.p_glEnable(GL_REGISTER_COMBINERS_NV);
503
        GL_EXTCALL(glCombinerParameteriNV(GL_NUM_GENERAL_COMBINERS_NV, state->lowest_disabled_stage));
504 505 506
    }
    else
    {
507
        gl_info->gl_ops.gl.p_glDisable(GL_REGISTER_COMBINERS_NV);
508
    }
509
    if (stage >= state->lowest_disabled_stage)
510
    {
511
        TRACE("Stage disabled\n");
512 513
        if (mapped_stage != WINED3D_UNMAPPED_STAGE)
        {
514
            /* Disable everything here */
515
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_2D);
516
            checkGLcall("glDisable(GL_TEXTURE_2D)");
517
            gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_3D);
518
            checkGLcall("glDisable(GL_TEXTURE_3D)");
519 520
            if (gl_info->supported[ARB_TEXTURE_CUBE_MAP])
            {
521
                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_CUBE_MAP_ARB);
522 523
                checkGLcall("glDisable(GL_TEXTURE_CUBE_MAP_ARB)");
            }
524 525
            if (gl_info->supported[ARB_TEXTURE_RECTANGLE])
            {
526
                gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_RECTANGLE_ARB);
527 528
                checkGLcall("glDisable(GL_TEXTURE_RECTANGLE_ARB)");
            }
529
            if (gl_info->supported[NV_TEXTURE_SHADER2] && mapped_stage < gl_info->limits.textures)
530
            {
531
                gl_info->gl_ops.gl.p_glTexEnvi(GL_TEXTURE_SHADER_NV, GL_SHADER_OPERATION_NV, GL_NONE);
532 533 534 535 536 537 538 539 540
            }
        }
        /* All done */
        return;
    }

    /* The sampler will also activate the correct texture dimensions, so no need to do it here
     * if the sampler for this stage is dirty
     */
541 542 543 544 545 546
    if (!isStateDirty(context, STATE_SAMPLER(stage)))
    {
        if (tex_used)
        {
            if (gl_info->supported[NV_TEXTURE_SHADER2])
            {
547
                nvts_activate_dimensions(state, stage, context);
548 549 550
            }
            else
            {
551
                texture_activate_dimensions(state->textures[stage], gl_info);
552 553
            }
        }
554 555 556
    }

    /* Set the texture combiners */
557
    set_tex_op_nvrc(gl_info, state, FALSE, stage,
558 559 560 561
            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],
562
            mapped_stage,
563
            state->texture_states[stage][WINED3D_TSS_RESULT_ARG]);
564 565 566 567

    /* In register combiners bump mapping is done in the stage AFTER the one that has the bump map operation set,
     * thus the texture shader may have to be updated
     */
568 569
    if (gl_info->supported[NV_TEXTURE_SHADER2])
    {
570 571
        BOOL usesBump = (state->texture_states[stage][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_BUMPENVMAP_LUMINANCE
                || state->texture_states[stage][WINED3D_TSS_COLOR_OP] == WINED3D_TOP_BUMPENVMAP);
572 573 574
        BOOL usedBump = !!(context->texShaderBumpMap & 1 << (stage + 1));
        if (usesBump != usedBump)
        {
575
            context_active_texture(context, gl_info, mapped_stage + 1);
576
            nvts_activate_dimensions(state, stage + 1, context);
577
            context_active_texture(context, gl_info, mapped_stage);
578 579 580 581
        }
    }
}

582
static void nvts_texdim(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
583
{
584
    DWORD sampler = state_id - STATE_SAMPLER(0);
585
    DWORD mapped_stage = context->swapchain->device->texUnitMap[sampler];
586 587 588

    /* No need to enable / disable anything here for unused samplers. The tex_colorop
    * handler takes care. Also no action is needed with pixel shaders, or if tex_colorop
589 590 591 592 593 594 595
    * will take care of this business. */
    if (mapped_stage == WINED3D_UNMAPPED_STAGE || mapped_stage >= context->gl_info->limits.textures)
        return;
    if (sampler >= state->lowest_disabled_stage)
        return;
    if (isStateDirty(context, STATE_TEXTURESTAGE(sampler, WINED3D_TSS_COLOR_OP)))
        return;
596

597
    nvts_activate_dimensions(state, sampler, context);
598 599
}

600
static void nvts_bumpenvmat(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
601
{
602 603
    DWORD stage = (state_id - STATE_TEXTURESTAGE(0, 0)) / (WINED3D_HIGHEST_TEXTURE_STATE + 1);
    DWORD mapped_stage = context->swapchain->device->texUnitMap[stage + 1];
604
    const struct wined3d_gl_info *gl_info = context->gl_info;
605 606
    float mat[2][2];

607 608 609 610 611 612
    /* Direct3D sets the matrix in the stage reading the perturbation map. The result is used to
     * offset the destination stage(always stage + 1 in d3d). In GL_NV_texture_shader, the bump
     * map offsetting is done in the stage reading the bump mapped texture, and the perturbation
     * map is read from a specified source stage(always stage - 1 for d3d). Thus set the matrix
     * for stage + 1. Keep the nvrc tex unit mapping in mind too
     */
613
    if (mapped_stage < gl_info->limits.textures)
614
    {
615
        context_active_texture(context, gl_info, mapped_stage);
616

617
        /* We can't just pass a pointer to the state to GL due to the
618
         * different matrix format (column major vs row major). */
619 620 621 622
        mat[0][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT00]);
        mat[1][0] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT01]);
        mat[0][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT10]);
        mat[1][1] = *((float *)&state->texture_states[stage][WINED3D_TSS_BUMPENV_MAT11]);
623
        gl_info->gl_ops.gl.p_glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, (float *)mat);
624
        checkGLcall("glTexEnvfv(GL_TEXTURE_SHADER_NV, GL_OFFSET_TEXTURE_MATRIX_NV, mat)");
625 626 627
    }
}

628
static void nvrc_texfactor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
629
{
630
    const struct wined3d_gl_info *gl_info = context->gl_info;
631
    float col[4];
632 633

    D3DCOLORTOGLFLOAT4(state->render_states[WINED3D_RS_TEXTUREFACTOR], col);
634 635 636
    GL_EXTCALL(glCombinerParameterfvNV(GL_CONSTANT_COLOR0_NV, &col[0]));
}

637
/* Context activation is done by the caller. */
638
static void nvrc_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
639 640 641
{
    if (enable)
    {
642
        gl_info->gl_ops.gl.p_glEnable(GL_REGISTER_COMBINERS_NV);
643 644 645 646
        checkGLcall("glEnable(GL_REGISTER_COMBINERS_NV)");
    }
    else
    {
647
        gl_info->gl_ops.gl.p_glDisable(GL_REGISTER_COMBINERS_NV);
648 649 650
        checkGLcall("glDisable(GL_REGISTER_COMBINERS_NV)");
    }
}
651

652
/* Context activation and GL locking are done by the caller. */
653
static void nvts_enable(const struct wined3d_gl_info *gl_info, BOOL enable)
654
{
655
    nvrc_enable(gl_info, enable);
656 657
    if (enable)
    {
658
        gl_info->gl_ops.gl.p_glEnable(GL_TEXTURE_SHADER_NV);
659
        checkGLcall("glEnable(GL_TEXTURE_SHADER_NV)");
660 661 662
    }
    else
    {
663
        gl_info->gl_ops.gl.p_glDisable(GL_TEXTURE_SHADER_NV);
664 665 666 667
        checkGLcall("glDisable(GL_TEXTURE_SHADER_NV)");
    }
}

668
static void nvrc_fragment_get_caps(const struct wined3d_gl_info *gl_info, struct fragment_caps *caps)
669
{
670
    caps->PrimitiveMiscCaps = WINED3DPMISCCAPS_TSSARGTEMP;
671 672 673 674 675

    /* The caps below can be supported but aren't handled yet in utils.c
     * 'd3dta_to_combiner_input', disable them until support is fixed */
#if 0
    if (gl_info->supported[NV_REGISTER_COMBINERS2])
676
        caps->PrimitiveMiscCaps |=  WINED3DPMISCCAPS_PERSTAGECONSTANT;
677 678
#endif

679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701
    caps->TextureOpCaps = WINED3DTEXOPCAPS_ADD
            | WINED3DTEXOPCAPS_ADDSIGNED
            | WINED3DTEXOPCAPS_ADDSIGNED2X
            | WINED3DTEXOPCAPS_MODULATE
            | WINED3DTEXOPCAPS_MODULATE2X
            | WINED3DTEXOPCAPS_MODULATE4X
            | WINED3DTEXOPCAPS_SELECTARG1
            | WINED3DTEXOPCAPS_SELECTARG2
            | WINED3DTEXOPCAPS_DISABLE
            | WINED3DTEXOPCAPS_BLENDDIFFUSEALPHA
            | WINED3DTEXOPCAPS_BLENDTEXTUREALPHA
            | WINED3DTEXOPCAPS_BLENDFACTORALPHA
            | WINED3DTEXOPCAPS_BLENDCURRENTALPHA
            | WINED3DTEXOPCAPS_LERP
            | WINED3DTEXOPCAPS_SUBTRACT
            | WINED3DTEXOPCAPS_ADDSMOOTH
            | WINED3DTEXOPCAPS_MULTIPLYADD
            | WINED3DTEXOPCAPS_MODULATEALPHA_ADDCOLOR
            | WINED3DTEXOPCAPS_MODULATECOLOR_ADDALPHA
            | WINED3DTEXOPCAPS_BLENDTEXTUREALPHAPM
            | WINED3DTEXOPCAPS_DOTPRODUCT3
            | WINED3DTEXOPCAPS_MODULATEINVALPHA_ADDCOLOR
            | WINED3DTEXOPCAPS_MODULATEINVCOLOR_ADDALPHA;
702

703 704
    if (gl_info->supported[NV_TEXTURE_SHADER2])
    {
705 706 707
        /* Bump mapping is supported already in NV_TEXTURE_SHADER, but that extension does
         * not support 3D textures. This asks for trouble if an app uses both bump mapping
         * and 3D textures. It also allows us to keep the code simpler by having texture
708 709
         * shaders constantly enabled. */
        caps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAP;
710 711 712 713 714
        /* TODO: Luminance bump map? */
    }

#if 0
    /* FIXME: Add
715
            caps->TextureOpCaps |= WINED3DTEXOPCAPS_BUMPENVMAPLUMINANCE
716 717 718
            WINED3DTEXOPCAPS_PREMODULATE */
#endif

719 720
    caps->MaxTextureBlendStages = min(MAX_TEXTURES, gl_info->limits.general_combiners);
    caps->MaxSimultaneousTextures = gl_info->limits.textures;
721 722
}

723
static HRESULT nvrc_fragment_alloc(struct wined3d_device *device) { return WINED3D_OK; }
724
/* Context activation is done by the caller. */
725
static void nvrc_fragment_free(struct wined3d_device *device) {}
726 727 728 729 730 731

/* Two fixed function pipeline implementations using GL_NV_register_combiners and
 * GL_NV_texture_shader. The nvts_fragment_pipeline assumes that both extensions
 * are available(geforce 3 and newer), while nvrc_fragment_pipeline uses only the
 * register combiners extension(Pre-GF3).
 */
732

733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748
static BOOL nvts_color_fixup_supported(struct color_fixup_desc fixup)
{
    if (TRACE_ON(d3d))
    {
        TRACE("Checking support for fixup:\n");
        dump_color_fixup_desc(fixup);
    }

    /* We only support identity conversions. */
    if (is_identity_fixup(fixup))
    {
        TRACE("[OK]\n");
        return TRUE;
    }

    TRACE("[FAILED]\n");
749 750 751
    return FALSE;
}

752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
static const struct StateEntryTemplate nvrc_fragmentstate_template[] =
{
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(0, WINED3D_TSS_COLOR_OP),        nvrc_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_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { 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(1, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(1, WINED3D_TSS_COLOR_OP),        nvrc_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_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { 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(2, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(2, WINED3D_TSS_COLOR_OP),        nvrc_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_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { 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(3, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(3, WINED3D_TSS_COLOR_OP),        nvrc_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_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { 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(4, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(4, WINED3D_TSS_COLOR_OP),        nvrc_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_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { 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(5, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(5, WINED3D_TSS_COLOR_OP),        nvrc_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_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { 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(6, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(6, WINED3D_TSS_COLOR_OP),        nvrc_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_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { 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(7, WINED3D_TSS_COLOR_OP),        { STATE_TEXTURESTAGE(7, WINED3D_TSS_COLOR_OP),        nvrc_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_BUMPENV_MAT00),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   nvts_bumpenvmat     }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11),   { STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00),   NULL                }, NV_TEXTURE_SHADER2              },
    { 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             },
858
    { STATE_PIXELSHADER,                                  { STATE_PIXELSHADER,                                  apply_pixelshader   }, WINED3D_GL_EXT_NONE             },
859 860 861 862 863 864 865 866 867
    { STATE_RENDER(WINED3D_RS_SRGBWRITEENABLE),           { STATE_PIXELSHADER,                                  NULL                }, WINED3D_GL_EXT_NONE             },
    { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             { STATE_RENDER(WINED3D_RS_TEXTUREFACTOR),             nvrc_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             },
868
    { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
869
    { STATE_SAMPLER(0),                                   { STATE_SAMPLER(0),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
870
    { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
871
    { STATE_SAMPLER(1),                                   { STATE_SAMPLER(1),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
872
    { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
873
    { STATE_SAMPLER(2),                                   { STATE_SAMPLER(2),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
874
    { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
875
    { STATE_SAMPLER(3),                                   { STATE_SAMPLER(3),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
876
    { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
877
    { STATE_SAMPLER(4),                                   { STATE_SAMPLER(4),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
878
    { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
879
    { STATE_SAMPLER(5),                                   { STATE_SAMPLER(5),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
880
    { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
881
    { STATE_SAMPLER(6),                                   { STATE_SAMPLER(6),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
882
    { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   nvts_texdim         }, NV_TEXTURE_SHADER2              },
883 884
    { STATE_SAMPLER(7),                                   { STATE_SAMPLER(7),                                   sampler_texdim      }, WINED3D_GL_EXT_NONE             },
    {0 /* Terminate */,                                   { 0,                                                  0                   }, WINED3D_GL_EXT_NONE             },
885 886
};

887 888 889 890 891
const struct fragment_pipeline nvts_fragment_pipeline = {
    nvts_enable,
    nvrc_fragment_get_caps,
    nvrc_fragment_alloc,
    nvrc_fragment_free,
892
    nvts_color_fixup_supported,
893 894
    nvrc_fragmentstate_template,
    FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
895
};
896

897 898 899 900 901
const struct fragment_pipeline nvrc_fragment_pipeline = {
    nvrc_enable,
    nvrc_fragment_get_caps,
    nvrc_fragment_alloc,
    nvrc_fragment_free,
902
    nvts_color_fixup_supported,
903 904
    nvrc_fragmentstate_template,
    FALSE /* we cannot disable projected textures. The vertex pipe has to do it */
905
};