Module: wine Branch: master Commit: 5b911ed461c6f7f059668bac66bd49ddcd694045 URL: http://source.winehq.org/git/wine.git/?a=commit;h=5b911ed461c6f7f059668bac66...
Author: Matteo Bruni mbruni@codeweavers.com Date: Tue May 19 23:32:32 2015 +0200
wined3d: Fix fragment shaders sampling directly into oC[n] in the ARB backend.
---
dlls/wined3d/arb_program_shader.c | 118 ++++++++++++++++++++++++++------------ 1 file changed, 81 insertions(+), 37 deletions(-)
diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index a45d25f..1e8784e 100644 --- a/dlls/wined3d/arb_program_shader.c +++ b/dlls/wined3d/arb_program_shader.c @@ -1271,55 +1271,86 @@ static const char *shader_arb_get_fixup_swizzle(enum fixup_channel_source channe } }
-static void gen_color_correction(struct wined3d_string_buffer *buffer, const char *reg, - DWORD dst_mask, const char *one, const char *two, struct color_fixup_desc fixup) +struct color_fixup_masks { - DWORD mask; + DWORD source; + DWORD sign; +}; + +static struct color_fixup_masks calc_color_correction(struct color_fixup_desc fixup, DWORD dst_mask) +{ + struct color_fixup_masks masks = {0, 0};
if (is_complex_fixup(fixup)) { enum complex_fixup complex_fixup = get_complex_fixup(fixup); FIXME("Complex fixup (%#x) not supported\n", complex_fixup); - return; + return masks; }
- mask = 0; - if (fixup.x_source != CHANNEL_SOURCE_X) mask |= WINED3DSP_WRITEMASK_0; - if (fixup.y_source != CHANNEL_SOURCE_Y) mask |= WINED3DSP_WRITEMASK_1; - if (fixup.z_source != CHANNEL_SOURCE_Z) mask |= WINED3DSP_WRITEMASK_2; - if (fixup.w_source != CHANNEL_SOURCE_W) mask |= WINED3DSP_WRITEMASK_3; - mask &= dst_mask; + if (fixup.x_source != CHANNEL_SOURCE_X) + masks.source |= WINED3DSP_WRITEMASK_0; + if (fixup.y_source != CHANNEL_SOURCE_Y) + masks.source |= WINED3DSP_WRITEMASK_1; + if (fixup.z_source != CHANNEL_SOURCE_Z) + masks.source |= WINED3DSP_WRITEMASK_2; + if (fixup.w_source != CHANNEL_SOURCE_W) + masks.source |= WINED3DSP_WRITEMASK_3; + masks.source &= dst_mask; + + if (fixup.x_sign_fixup) + masks.sign |= WINED3DSP_WRITEMASK_0; + if (fixup.y_sign_fixup) + masks.sign |= WINED3DSP_WRITEMASK_1; + if (fixup.z_sign_fixup) + masks.sign |= WINED3DSP_WRITEMASK_2; + if (fixup.w_sign_fixup) + masks.sign |= WINED3DSP_WRITEMASK_3; + masks.sign &= dst_mask; + + return masks; +} + +static void gen_color_correction(struct wined3d_string_buffer *buffer, const char *dst, + const char *src, const char *one, const char *two, + struct color_fixup_desc fixup, struct color_fixup_masks masks) +{ + const char *sign_fixup_src = dst;
- if (mask) + if (masks.source) { - shader_addline(buffer, "SWZ %s, %s, %s, %s, %s, %s;\n", reg, reg, + if (masks.sign) + sign_fixup_src = "TA"; + + shader_addline(buffer, "SWZ %s, %s, %s, %s, %s, %s;\n", sign_fixup_src, src, shader_arb_get_fixup_swizzle(fixup.x_source), shader_arb_get_fixup_swizzle(fixup.y_source), shader_arb_get_fixup_swizzle(fixup.z_source), shader_arb_get_fixup_swizzle(fixup.w_source)); } + else if (masks.sign) + { + sign_fixup_src = src; + }
- mask = 0; - if (fixup.x_sign_fixup) mask |= WINED3DSP_WRITEMASK_0; - if (fixup.y_sign_fixup) mask |= WINED3DSP_WRITEMASK_1; - if (fixup.z_sign_fixup) mask |= WINED3DSP_WRITEMASK_2; - if (fixup.w_sign_fixup) mask |= WINED3DSP_WRITEMASK_3; - mask &= dst_mask; - - if (mask) + if (masks.sign) { char reg_mask[6]; char *ptr = reg_mask;
- if (mask != WINED3DSP_WRITEMASK_ALL) + if (masks.sign != WINED3DSP_WRITEMASK_ALL) { *ptr++ = '.'; - if (mask & WINED3DSP_WRITEMASK_0) *ptr++ = 'x'; - if (mask & WINED3DSP_WRITEMASK_1) *ptr++ = 'y'; - if (mask & WINED3DSP_WRITEMASK_2) *ptr++ = 'z'; - if (mask & WINED3DSP_WRITEMASK_3) *ptr++ = 'w'; + if (masks.sign & WINED3DSP_WRITEMASK_0) + *ptr++ = 'x'; + if (masks.sign & WINED3DSP_WRITEMASK_1) + *ptr++ = 'y'; + if (masks.sign & WINED3DSP_WRITEMASK_2) + *ptr++ = 'z'; + if (masks.sign & WINED3DSP_WRITEMASK_3) + *ptr++ = 'w'; } *ptr = '\0';
- shader_addline(buffer, "MAD %s%s, %s, %s, -%s;\n", reg, reg_mask, reg, two, one); + shader_addline(buffer, "MAD %s%s, %s, %s, -%s;\n", dst, reg_mask, sign_fixup_src, two, one); } }
@@ -1378,6 +1409,8 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD const struct wined3d_shader *shader; const struct wined3d_device *device; const struct wined3d_gl_info *gl_info; + const char *tex_dst = dst_str; + struct color_fixup_masks masks;
/* D3D vertex shader sampler IDs are vertex samplers(0-3), not global d3d samplers */ if(!pshader) sampler_idx += MAX_FRAGMENT_SAMPLERS; @@ -1433,18 +1466,27 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD sampler_idx = priv->cur_vs_args->vertex.samplers[sampler_idx - MAX_FRAGMENT_SAMPLERS]; }
+ if (pshader) + { + masks = calc_color_correction(priv->cur_ps_args->super.color_fixup[sampler_idx], + ins->dst[0].write_mask); + + if (masks.source || masks.sign) + tex_dst = "TA"; + } + if (flags & TEX_DERIV) { if(flags & TEX_PROJ) FIXME("Projected texture sampling with custom derivatives\n"); if(flags & TEX_BIAS) FIXME("Biased texture sampling with custom derivatives\n"); - shader_addline(buffer, "TXD%s %s, %s, %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, - dsx, dsy,sampler_idx, tex_type); + shader_addline(buffer, "TXD%s %s, %s, %s, %s, texture[%u], %s;\n", mod, tex_dst, coord_reg, + dsx, dsy, sampler_idx, tex_type); } else if(flags & TEX_LOD) { if(flags & TEX_PROJ) FIXME("Projected texture sampling with explicit lod\n"); if(flags & TEX_BIAS) FIXME("Biased texture sampling with explicit lod\n"); - shader_addline(buffer, "TXL%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, + shader_addline(buffer, "TXL%s %s, %s, texture[%u], %s;\n", mod, tex_dst, coord_reg, sampler_idx, tex_type); } else if (flags & TEX_BIAS) @@ -1452,11 +1494,11 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD /* Shouldn't be possible, but let's check for it */ if(flags & TEX_PROJ) FIXME("Biased and Projected texture sampling\n"); /* TXB takes the 4th component of the source vector automatically, as d3d. Nothing more to do */ - shader_addline(buffer, "TXB%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type); + shader_addline(buffer, "TXB%s %s, %s, texture[%u], %s;\n", mod, tex_dst, coord_reg, sampler_idx, tex_type); } else if (flags & TEX_PROJ) { - shader_addline(buffer, "TXP%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type); + shader_addline(buffer, "TXP%s %s, %s, texture[%u], %s;\n", mod, tex_dst, coord_reg, sampler_idx, tex_type); } else { @@ -1466,18 +1508,18 @@ static void shader_hw_sample(const struct wined3d_shader_instruction *ins, DWORD shader_addline(buffer, "MUL TA, np2fixup[%u].%s, %s;\n", idx >> 1, (idx % 2) ? "zwxy" : "xyzw", coord_reg);
- shader_addline(buffer, "TEX%s %s, TA, texture[%u], %s;\n", mod, dst_str, sampler_idx, tex_type); + shader_addline(buffer, "TEX%s %s, TA, texture[%u], %s;\n", mod, tex_dst, sampler_idx, tex_type); } else - shader_addline(buffer, "TEX%s %s, %s, texture[%u], %s;\n", mod, dst_str, coord_reg, sampler_idx, tex_type); + shader_addline(buffer, "TEX%s %s, %s, texture[%u], %s;\n", mod, tex_dst, coord_reg, sampler_idx, tex_type); }
if (pshader) { - gen_color_correction(buffer, dst_str, ins->dst[0].write_mask, + gen_color_correction(buffer, dst_str, tex_dst, arb_get_helper_value(WINED3D_SHADER_TYPE_PIXEL, ARB_ONE), arb_get_helper_value(WINED3D_SHADER_TYPE_PIXEL, ARB_TWO), - priv->cur_ps_args->super.color_fixup[sampler_idx]); + priv->cur_ps_args->super.color_fixup[sampler_idx], masks); } }
@@ -6238,6 +6280,7 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con BOOL op_equal; const char *final_combiner_src = "ret"; BOOL custom_linear_fog = FALSE; + struct color_fixup_masks masks;
if (!string_buffer_init(&buffer)) { @@ -6426,8 +6469,9 @@ static GLuint gen_arbfp_ffp_shader(const struct ffp_frag_settings *settings, con }
sprintf(colorcor_dst, "tex%u", stage); - gen_color_correction(&buffer, colorcor_dst, WINED3DSP_WRITEMASK_ALL, "const.x", "const.y", - settings->op[stage].color_fixup); + masks = calc_color_correction(settings->op[stage].color_fixup, WINED3DSP_WRITEMASK_ALL); + gen_color_correction(&buffer, colorcor_dst, colorcor_dst, "const.x", "const.y", + settings->op[stage].color_fixup, masks); }
if (settings->color_key_enabled)