From 92fee8c04f94893c36543230f45cb38c4fbd486e Mon Sep 17 00:00:00 2001 From: =?utf8?q?Stefan=20D=C3=B6singer?= Date: Mon, 23 Mar 2015 18:59:07 +0100 Subject: [PATCH] wined3d: Improve color fixups in atifs shaders. The abilities of this hardware is too limited to support generic sign / swizzle fixups. A generic handler would consume 4 of the 8 available color instruction slots and 2 alpha instruction slots. The bump mapping handler code has its own way of handling the color fixups. It merges the fixup into the perturbation calculation without requiring extra shader instructions. In theory this is possible for the majority of d3d texture ops as well, but I don't think this is worth the effort. I expect that this code will only be used for the ddraw signed format test in practice. --- dlls/wined3d/ati_fragment_shader.c | 90 +++++++++++++++++++++++++++++++------- 1 file changed, 75 insertions(+), 15 deletions(-) diff --git a/dlls/wined3d/ati_fragment_shader.c b/dlls/wined3d/ati_fragment_shader.c index 1570a04945d..8dfb5688246 100644 --- a/dlls/wined3d/ati_fragment_shader.c +++ b/dlls/wined3d/ati_fragment_shader.c @@ -376,6 +376,69 @@ static GLuint find_tmpreg(const struct texture_stage_op op[MAX_TEXTURES]) } } +static const struct color_fixup_desc color_fixup_rg = +{ + 1, CHANNEL_SOURCE_X, + 1, CHANNEL_SOURCE_Y, + 0, CHANNEL_SOURCE_ONE, + 0, CHANNEL_SOURCE_ONE +}; +static const struct color_fixup_desc color_fixup_rgl = +{ + 1, CHANNEL_SOURCE_X, + 1, CHANNEL_SOURCE_Y, + 0, CHANNEL_SOURCE_Z, + 0, CHANNEL_SOURCE_W +}; +static const struct color_fixup_desc color_fixup_rgba = +{ + 1, CHANNEL_SOURCE_X, + 1, CHANNEL_SOURCE_Y, + 1, CHANNEL_SOURCE_Z, + 1, CHANNEL_SOURCE_W +}; + +static BOOL op_reads_texture(const struct texture_stage_op *op) +{ + return (op->carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE + || (op->carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE + || (op->carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE + || (op->aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE + || (op->aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE + || (op->aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE + || op->cop == WINED3D_TOP_BLEND_TEXTURE_ALPHA; +} + +static void atifs_color_fixup(const struct wined3d_gl_info *gl_info, struct color_fixup_desc fixup, GLuint reg) +{ + if(is_same_fixup(fixup, color_fixup_rg)) + { + wrap_op1(gl_info, GL_MOV_ATI, reg, GL_RED_BIT_ATI | GL_GREEN_BIT_ATI, GL_NONE, + reg, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI); + wrap_op1(gl_info, GL_MOV_ATI, reg, GL_BLUE_BIT_ATI, GL_NONE, + GL_ONE, GL_NONE, GL_NONE); + wrap_op1(gl_info, GL_MOV_ATI, reg, GL_ALPHA, GL_NONE, + GL_ONE, GL_NONE, GL_NONE); + } + else if(is_same_fixup(fixup, color_fixup_rgl)) + { + wrap_op1(gl_info, GL_MOV_ATI, reg, GL_RED_BIT_ATI | GL_GREEN_BIT_ATI, GL_NONE, + reg, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI); + } + else if (is_same_fixup(fixup, color_fixup_rgba)) + { + wrap_op1(gl_info, GL_MOV_ATI, reg, GL_NONE, GL_NONE, + reg, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI); + wrap_op1(gl_info, GL_MOV_ATI, reg, GL_ALPHA, GL_NONE, + reg, GL_NONE, GL_2X_BIT_ATI | GL_BIAS_BIT_ATI); + } + else + { + /* Should not happen - atifs_color_fixup_supported refuses other fixups. */ + ERR("Unsupported color fixup.\n"); + } +} + static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], const struct wined3d_gl_info *gl_info) { GLuint ret = GL_EXTCALL(glGenFragmentShadersATI(1)); @@ -491,13 +554,7 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con swizzle = GL_SWIZZLE_STQ_DQ_ATI; } - if ((op[stage].carg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE - || (op[stage].carg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE - || (op[stage].carg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE - || (op[stage].aarg0 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE - || (op[stage].aarg1 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE - || (op[stage].aarg2 & WINED3DTA_SELECTMASK) == WINED3DTA_TEXTURE - || op[stage].cop == WINED3D_TOP_BLEND_TEXTURE_ALPHA) + if (op_reads_texture(&op[stage])) { if (stage > 0 && (op[stage - 1].cop == WINED3D_TOP_BUMPENVMAP @@ -545,6 +602,12 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con dstreg = GL_REG_0_ATI; } + if (op[stage].cop == WINED3D_TOP_BUMPENVMAP || op[stage].cop == WINED3D_TOP_BUMPENVMAP_LUMINANCE) + { + /* Those are handled in the first pass of the shader (generation pass 1 and 2) already */ + continue; + } + arg0 = register_for_arg(op[stage].carg0, gl_info, stage, &argmod0, &rep0, tmparg); arg1 = register_for_arg(op[stage].carg1, gl_info, stage, &argmod1, &rep1, tmparg); arg2 = register_for_arg(op[stage].carg2, gl_info, stage, &argmod2, &rep2, tmparg); @@ -552,6 +615,9 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con argmodextra = GL_NONE; extrarg = GL_NONE; + if (op_reads_texture(&op[stage]) && !is_identity_fixup(op[stage].color_fixup)) + atifs_color_fixup(gl_info, op[stage].color_fixup, GL_REG_0_ATI + stage); + switch (op[stage].cop) { case WINED3D_TOP_SELECT_ARG2: @@ -683,11 +749,6 @@ static GLuint gen_ati_shader(const struct texture_stage_op op[MAX_TEXTURES], con arg2, rep2, argmod2); break; - case WINED3D_TOP_BUMPENVMAP: - case WINED3D_TOP_BUMPENVMAP_LUMINANCE: - /* Those are handled in the first pass of the shader(generation pass 1 and 2) already */ - break; - default: FIXME("Unhandled color operation %d on stage %d\n", op[stage].cop, stage); } @@ -1196,9 +1257,8 @@ static BOOL atifs_color_fixup_supported(struct color_fixup_desc fixup) } /* We only support sign fixup of the first two channels. */ - if (fixup.x_source == CHANNEL_SOURCE_X && fixup.y_source == CHANNEL_SOURCE_Y - && fixup.z_source == CHANNEL_SOURCE_Z && fixup.w_source == CHANNEL_SOURCE_W - && !fixup.z_sign_fixup && !fixup.w_sign_fixup) + if (is_identity_fixup(fixup) || is_same_fixup(fixup, color_fixup_rg) + || is_same_fixup(fixup, color_fixup_rgl) || is_same_fixup(fixup, color_fixup_rgba)) { TRACE("[OK]\n"); return TRUE; -- 2.11.4.GIT