diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c index 0a21fd92aa1..a89a4c2fe41 100644 --- a/dlls/wined3d/utils.c +++ b/dlls/wined3d/utils.c @@ -5,6 +5,7 @@ * Copyright 2003-2004 Raphael Junqueira * Copyright 2004 Christian Costa * Copyright 2005 Oliver Stieber + * Copyright 2006 Henri Verbeet * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,6 +27,8 @@ WINE_DEFAULT_DEBUG_CHANNEL(d3d); +#define GLINFO_LOCATION ((IWineD3DImpl *)(This->wineD3D))->gl_info + /***************************************************************************** * Pixel format array */ @@ -563,6 +566,360 @@ GLenum StencilFunc(DWORD func) { } } +static GLenum d3dta_to_combiner_input(DWORD d3dta, DWORD stage, INT texture_idx) { + switch (d3dta) { + case D3DTA_DIFFUSE: + return GL_PRIMARY_COLOR_NV; + + case D3DTA_CURRENT: + if (stage) return GL_SPARE0_NV; + else return GL_PRIMARY_COLOR_NV; + + case D3DTA_TEXTURE: + if (texture_idx > -1) return GL_TEXTURE0_ARB + texture_idx; + else return GL_PRIMARY_COLOR_NV; + + case D3DTA_TFACTOR: + return GL_CONSTANT_COLOR0_NV; + + case D3DTA_SPECULAR: + return GL_SECONDARY_COLOR_NV; + + case D3DTA_TEMP: + /* TODO: Support D3DTSS_RESULTARG */ + FIXME("D3DTA_TEMP, not properly supported."); + return GL_SPARE1_NV; + + case D3DTA_CONSTANT: + /* TODO: Support per stage constants (D3DTSS_CONSTANT, NV_register_combiners2) */ + FIXME("D3DTA_CONSTANT, not properly supported."); + return GL_CONSTANT_COLOR1_NV; + + default: + FIXME("Unrecognized texture arg %#lx\n", d3dta); + return GL_TEXTURE; + } +} + +static GLenum invert_mapping(GLenum mapping) { + if (mapping == GL_UNSIGNED_INVERT_NV) return GL_SIGNED_IDENTITY_NV; + else if (mapping == GL_SIGNED_IDENTITY_NV) return GL_UNSIGNED_INVERT_NV; + + 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 D3DTA_COMPLEMENT flag specifies the complement of the input should + * be used. */ + if (arg & D3DTA_COMPLEMENT) *mapping = GL_UNSIGNED_INVERT_NV; + else *mapping = GL_SIGNED_IDENTITY_NV; + + /* The D3DTA_ALPHAREPLICATE flag specifies the alpha component of the input + * should be used for all input components. */ + if (is_alpha || arg & D3DTA_ALPHAREPLICATE) *component_usage = GL_ALPHA; + else *component_usage = GL_RGB; + + *input = d3dta_to_combiner_input(arg & D3DTA_SELECTMASK, stage, texture_idx); +} + +typedef struct { + GLenum input[3]; + GLenum mapping[3]; + GLenum component_usage[3]; +} tex_op_args; + +void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx) { + IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl*)iface; + tex_op_args tex_op_args = {{0}, {0}, {0}}; + GLenum portion = is_alpha ? GL_ALPHA : GL_RGB; + GLenum target = GL_COMBINER0_NV + stage; + + TRACE("stage %d, is_alpha %d, op %s, arg1 %#lx, arg2 %#lx, arg3 %#lx, texture_idx %d\n", + stage, is_alpha, debug_d3dtop(op), arg1, arg2, arg3, texture_idx); + + 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); + + ENTER_GL(); + + switch(op) + { + case D3DTOP_DISABLE: + /* Only for alpha */ + if (!is_alpha) ERR("Shouldn't be called for D3DTSS_COLOROP (D3DTOP_DISABLE)\n"); + /* 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; + + case D3DTOP_SELECTARG1: + case D3DTOP_SELECTARG2: + /* Input, arg*1 */ + if (op == D3DTOP_SELECTARG1) { + 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])); + } else { + 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, GL_SPARE0_NV, GL_DISCARD_NV, + GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case D3DTOP_MODULATE: + case D3DTOP_MODULATE2X: + case D3DTOP_MODULATE4X: + /* 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 */ + if (op == D3DTOP_MODULATE) { + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, + GL_DISCARD_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + } else if (op == D3DTOP_MODULATE2X) { + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, + GL_DISCARD_NV, GL_SCALE_BY_TWO_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + } else if (op == D3DTOP_MODULATE4X) { + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_SPARE0_NV, GL_DISCARD_NV, + GL_DISCARD_NV, GL_SCALE_BY_FOUR_NV, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + } + break; + + case D3DTOP_ADD: + case D3DTOP_ADDSIGNED: + case D3DTOP_ADDSIGNED2X: + /* 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 */ + if (op == D3DTOP_ADD) { + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + } else if (op == D3DTOP_ADDSIGNED) { + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + GL_SPARE0_NV, GL_NONE, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE)); + } else if (op == D3DTOP_ADDSIGNED2X) { + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + GL_SPARE0_NV, GL_SCALE_BY_TWO_NV, GL_BIAS_BY_NEGATIVE_ONE_HALF_NV, GL_FALSE, GL_FALSE, GL_FALSE)); + } + break; + + case D3DTOP_SUBTRACT: + /* 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, + GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case D3DTOP_ADDSMOOTH: + /* 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, + GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case D3DTOP_BLENDDIFFUSEALPHA: + case D3DTOP_BLENDTEXTUREALPHA: + case D3DTOP_BLENDFACTORALPHA: + case D3DTOP_BLENDTEXTUREALPHAPM: + case D3DTOP_BLENDCURRENTALPHA: + { + GLenum alpha_src = GL_PRIMARY_COLOR_NV; + if (op == D3DTOP_BLENDDIFFUSEALPHA) alpha_src = d3dta_to_combiner_input(D3DTA_DIFFUSE, stage, texture_idx); + else if (op == D3DTOP_BLENDTEXTUREALPHA) alpha_src = d3dta_to_combiner_input(D3DTA_TEXTURE, stage, texture_idx); + else if (op == D3DTOP_BLENDFACTORALPHA) alpha_src = d3dta_to_combiner_input(D3DTA_TFACTOR, stage, texture_idx); + else if (op == D3DTOP_BLENDTEXTUREALPHAPM) alpha_src = d3dta_to_combiner_input(D3DTA_TEXTURE, stage, texture_idx); + else if (op == D3DTOP_BLENDCURRENTALPHA) alpha_src = d3dta_to_combiner_input(D3DTA_CURRENT, stage, texture_idx); + else FIXME("Unhandled D3DTOP %s, shouldn't happen\n", debug_d3dtop(op)); + + /* 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])); + if (op == D3DTOP_BLENDTEXTUREALPHAPM) + { + 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, + GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + } + + case D3DTOP_MODULATEALPHA_ADDCOLOR: + /* Input, arg1_alpha*arg2_rgb+arg1_rgb*1 */ + if (is_alpha) ERR("Only supported for D3DTSS_COLOROP (D3DTOP_MODULATEALPHA_ADDCOLOR)\n"); + 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, + GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case D3DTOP_MODULATECOLOR_ADDALPHA: + /* Input, arg1_rgb*arg2_rgb+arg1_alpha*1 */ + if (is_alpha) ERR("Only supported for D3DTSS_COLOROP (D3DTOP_MODULATECOLOR_ADDALPHA)\n"); + 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, + GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case D3DTOP_MODULATEINVALPHA_ADDCOLOR: + /* Input, (1-arg1_alpha)*arg2_rgb+arg1_rgb*1 */ + if (is_alpha) ERR("Only supported for D3DTSS_COLOROP (D3DTOP_MODULATEINVALPHA_ADDCOLOR)\n"); + 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, + GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case D3DTOP_MODULATEINVCOLOR_ADDALPHA: + /* Input, (1-arg1_rgb)*arg2_rgb+arg1_alpha*1 */ + if (is_alpha) ERR("Only supported for D3DTSS_COLOROP (D3DTOP_MODULATEINVCOLOR_ADDALPHA)\n"); + 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, + GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case D3DTOP_DOTPRODUCT3: + /* 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, GL_SPARE0_NV, GL_DISCARD_NV, + GL_DISCARD_NV, GL_NONE, GL_NONE, GL_TRUE, GL_FALSE, GL_FALSE)); + break; + + case D3DTOP_MULTIPLYADD: + /* Input, arg1*1+arg2*arg3 */ + 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, + tex_op_args.input[2], tex_op_args.mapping[2], tex_op_args.component_usage[2])); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + case D3DTOP_LERP: + /* Input, arg1*arg2+(1-arg1)*arg3 */ + 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], 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[2], tex_op_args.mapping[2], tex_op_args.component_usage[2])); + + /* Output */ + GL_EXTCALL(glCombinerOutputNV(target, portion, GL_DISCARD_NV, GL_DISCARD_NV, + GL_SPARE0_NV, GL_NONE, GL_NONE, GL_FALSE, GL_FALSE, GL_FALSE)); + break; + + default: + FIXME("Unhandled D3DTOP: stage %d, is_alpha %d, op %s (%#x), arg1 %#lx, arg2 %#lx, arg3 %#lx, texture_idx %d\n", + stage, is_alpha, debug_d3dtop(op), op, arg1, arg2, arg3, texture_idx); + } + + checkGLcall("set_tex_op_nvrc()\n"); + + LEAVE_GL(); +} + static void get_src_and_opr(DWORD arg, BOOL is_alpha, GLenum* source, GLenum* operand) { /* The D3DTA_ALPHAREPLICATE flag specifies the alpha component of the * input should be used for all input components. The D3DTA_COMPLEMENT diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h index 9543cb2a0bc..53dee67f6f1 100644 --- a/dlls/wined3d/wined3d_private.h +++ b/dlls/wined3d/wined3d_private.h @@ -1194,6 +1194,7 @@ const char* debug_d3dpool(WINED3DPOOL pool); GLenum StencilOp(DWORD op); GLenum StencilFunc(DWORD func); void set_tex_op(IWineD3DDevice *iface, BOOL isAlpha, int Stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3); +void set_tex_op_nvrc(IWineD3DDevice *iface, BOOL is_alpha, int stage, D3DTEXTUREOP op, DWORD arg1, DWORD arg2, DWORD arg3, INT texture_idx); void set_texture_matrix(const float *smat, DWORD flags, BOOL calculatedCoords); int D3DFmtMakeGlCfg(D3DFORMAT BackBufferFormat, D3DFORMAT StencilBufferFormat, int *attribs, int* nAttribs, BOOL alternate);