wined3d: Put the color_correction calls into the instruction handlers.

The color correction cannot be done behind the back of the individual
instruction handlers because it might conflict with the instruction's
color modifications and the D3D provided writemask.
oldstable
Stefan Dösinger 2009-02-16 14:58:52 +01:00 committed by Alexandre Julliard
parent 5e0d4c774c
commit 5cf764aec2
5 changed files with 81 additions and 137 deletions

View File

@ -567,56 +567,6 @@ static void vshader_program_add_param(const SHADER_OPCODE_ARG *arg, const DWORD
}
}
static void shader_hw_sample(const SHADER_OPCODE_ARG *arg, DWORD sampler_idx, const char *dst_str,
const char *coord_reg, BOOL projected, BOOL bias)
{
SHADER_BUFFER* buffer = arg->buffer;
DWORD sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
const char *tex_type;
switch(sampler_type) {
case WINED3DSTT_1D:
tex_type = "1D";
break;
case WINED3DSTT_2D:
{
IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) arg->shader;
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
if(device->stateBlock->textures[sampler_idx] &&
IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) {
tex_type = "RECT";
} else {
tex_type = "2D";
}
break;
}
case WINED3DSTT_VOLUME:
tex_type = "3D";
break;
case WINED3DSTT_CUBE:
tex_type = "CUBE";
break;
default:
ERR("Unexpected texture type %d\n", sampler_type);
tex_type = "";
}
if (bias) {
/* Shouldn't be possible, but let's check for it */
if(projected) 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, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type);
} else if (projected) {
shader_addline(buffer, "TXP %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type);
} else {
shader_addline(buffer, "TEX %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type);
}
}
static const char *shader_arb_get_fixup_swizzle(enum fixup_channel_source channel_source)
{
switch(channel_source)
@ -634,7 +584,7 @@ static const char *shader_arb_get_fixup_swizzle(enum fixup_channel_source channe
}
static void gen_color_correction(SHADER_BUFFER *buffer, const char *reg, DWORD dst_mask,
const char *one, const char *two, struct color_fixup_desc fixup)
const char *one, const char *two, struct color_fixup_desc fixup)
{
DWORD mask;
@ -685,11 +635,58 @@ static void gen_color_correction(SHADER_BUFFER *buffer, const char *reg, DWORD d
}
}
static void shader_arb_color_correction(const struct SHADER_OPCODE_ARG* arg, struct color_fixup_desc fixup)
static void shader_hw_sample(const SHADER_OPCODE_ARG *arg, DWORD sampler_idx, const char *dst_str,
const char *coord_reg, BOOL projected, BOOL bias)
{
char reg[256];
pshader_get_register_name(arg->shader, arg->dst, reg);
gen_color_correction(arg->buffer, reg, arg->dst & WINED3DSP_WRITEMASK_ALL, "one", "coefmul.x", fixup);
SHADER_BUFFER* buffer = arg->buffer;
DWORD sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
const char *tex_type;
IWineD3DBaseShaderImpl *This = (IWineD3DBaseShaderImpl *) arg->shader;
IWineD3DDeviceImpl *device = (IWineD3DDeviceImpl *) This->baseShader.device;
switch(sampler_type) {
case WINED3DSTT_1D:
tex_type = "1D";
break;
case WINED3DSTT_2D:
if(device->stateBlock->textures[sampler_idx] &&
IWineD3DBaseTexture_GetTextureDimensions(device->stateBlock->textures[sampler_idx]) == GL_TEXTURE_RECTANGLE_ARB) {
tex_type = "RECT";
} else {
tex_type = "2D";
}
break;
case WINED3DSTT_VOLUME:
tex_type = "3D";
break;
case WINED3DSTT_CUBE:
tex_type = "CUBE";
break;
default:
ERR("Unexpected texture type %d\n", sampler_type);
tex_type = "";
}
if (bias) {
/* Shouldn't be possible, but let's check for it */
if(projected) 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, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type);
} else if (projected) {
shader_addline(buffer, "TXP %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type);
} else {
shader_addline(buffer, "TEX %s, %s, texture[%u], %s;\n", dst_str, coord_reg, sampler_idx, tex_type);
}
if(shader_is_pshader_version(arg->reg_maps->shader_version)) {
IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) arg->shader;
gen_color_correction(buffer, dst_str, arg->dst & WINED3DSP_WRITEMASK_ALL, "one", "coefmul.x",
ps->cur_args->color_fixup[sampler_idx]);
}
}
static void pshader_gen_input_modifier_line (
@ -2262,7 +2259,6 @@ const shader_backend_t arb_program_shader_backend = {
shader_arb_update_float_vertex_constants,
shader_arb_update_float_pixel_constants,
shader_arb_load_constants,
shader_arb_color_correction,
shader_arb_destroy,
shader_arb_alloc,
shader_arb_free,

View File

@ -754,66 +754,6 @@ static void shader_dump_param(const DWORD param, const DWORD addr_token, int inp
}
}
static void shader_color_correction(IWineD3DBaseShaderImpl *shader,
IWineD3DDeviceImpl *device, const struct SHADER_OPCODE_ARG *arg, DWORD shader_version)
{
IWineD3DBaseTextureImpl *texture;
struct color_fixup_desc fixup;
BOOL recorded = FALSE;
DWORD sampler_idx;
UINT i;
switch(arg->opcode->opcode)
{
case WINED3DSIO_TEX:
if (WINED3DSHADER_VERSION_MAJOR(shader_version) < 2) sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
else sampler_idx = arg->src[1] & WINED3DSP_REGNUM_MASK;
break;
case WINED3DSIO_TEXLDL:
FIXME("Add color fixup for vertex texture WINED3DSIO_TEXLDL\n");
return;
case WINED3DSIO_TEXDP3TEX:
case WINED3DSIO_TEXM3x3TEX:
case WINED3DSIO_TEXM3x3SPEC:
case WINED3DSIO_TEXM3x3VSPEC:
case WINED3DSIO_TEXBEM:
case WINED3DSIO_TEXREG2AR:
case WINED3DSIO_TEXREG2GB:
case WINED3DSIO_TEXREG2RGB:
sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
break;
default:
/* Not a texture sampling instruction, nothing to do */
return;
};
texture = (IWineD3DBaseTextureImpl *)device->stateBlock->textures[sampler_idx];
if (texture) fixup = texture->baseTexture.shader_color_fixup;
else fixup = COLOR_FIXUP_IDENTITY;
/* before doing anything, record the sampler with the format in the format conversion list,
* but check if it's not there already */
for (i = 0; i < shader->baseShader.num_sampled_samplers; ++i)
{
if (shader->baseShader.sampled_samplers[i] == sampler_idx)
{
recorded = TRUE;
break;
}
}
if (!recorded)
{
shader->baseShader.sampled_samplers[shader->baseShader.num_sampled_samplers] = sampler_idx;
++shader->baseShader.num_sampled_samplers;
}
device->shader_backend->shader_color_correction(arg, fixup);
}
/* Shared code in order to generate the bulk of the shader string.
* NOTE: A description of how to parse tokens can be found on msdn */
void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
@ -915,9 +855,6 @@ void shader_generate_main(IWineD3DBaseShader *iface, SHADER_BUFFER* buffer,
/* Call appropriate function for output target */
hw_fct(&hw_arg);
/* Add color correction if needed */
shader_color_correction(This, device, &hw_arg, shader_version);
/* Process instruction modifiers for GLSL apps ( _sat, etc. ) */
/* FIXME: This should be internal to the shader backend.
* Also, right now this is the only reason "shader_mode" exists. */
@ -1124,7 +1061,6 @@ static void shader_none_deselect_depth_blt(IWineD3DDevice *iface) {}
static void shader_none_update_float_vertex_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
static void shader_none_update_float_pixel_constants(IWineD3DDevice *iface, UINT start, UINT count) {}
static void shader_none_load_constants(IWineD3DDevice *iface, char usePS, char useVS) {}
static void shader_none_color_correction(const struct SHADER_OPCODE_ARG *arg, struct color_fixup_desc fixup) {}
static void shader_none_destroy(IWineD3DBaseShader *iface) {}
static HRESULT shader_none_alloc(IWineD3DDevice *iface) {return WINED3D_OK;}
static void shader_none_free(IWineD3DDevice *iface) {}
@ -1174,7 +1110,6 @@ const shader_backend_t none_shader_backend = {
shader_none_update_float_vertex_constants,
shader_none_update_float_pixel_constants,
shader_none_load_constants,
shader_none_color_correction,
shader_none_destroy,
shader_none_alloc,
shader_none_free,

View File

@ -2345,6 +2345,7 @@ static void pshader_glsl_tex(const SHADER_OPCODE_ARG *arg)
sample_function.name, sampler_idx, coord_param.param_str, dst_swizzle);
}
}
shader_glsl_color_correction(arg, This->cur_args->color_fixup[sampler_idx]);
}
static void shader_glsl_texldl(const SHADER_OPCODE_ARG *arg)
@ -2373,11 +2374,14 @@ static void shader_glsl_texldl(const SHADER_OPCODE_ARG *arg)
if (shader_is_pshader_version(arg->reg_maps->shader_version))
{
IWineD3DPixelShaderImpl *ps = (IWineD3DPixelShaderImpl *) This;
/* The GLSL spec claims the Lod sampling functions are only supported in vertex shaders.
* However, they seem to work just fine in fragment shaders as well. */
WARN("Using %sLod in fragment shader.\n", sample_function.name);
shader_addline(arg->buffer, "%sLod(Psampler%u, %s, %s)%s);\n",
sample_function.name, sampler_idx, coord_param.param_str, lod_param.param_str, dst_swizzle);
shader_glsl_color_correction(arg, ps->cur_args->color_fixup[sampler_idx]);
} else {
shader_addline(arg->buffer, "%sLod(Vsampler%u, %s, %s)%s);\n",
sample_function.name, sampler_idx, coord_param.param_str, lod_param.param_str, dst_swizzle);
@ -2442,6 +2446,7 @@ static void pshader_glsl_texdp3tex(const SHADER_OPCODE_ARG *arg)
DWORD sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
DWORD src_mask = WINED3DSP_WRITEMASK_0 | WINED3DSP_WRITEMASK_1 | WINED3DSP_WRITEMASK_2;
DWORD sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], src_mask, &src0_param);
@ -2473,6 +2478,7 @@ static void pshader_glsl_texdp3tex(const SHADER_OPCODE_ARG *arg)
default:
FIXME("Unexpected mask bitcount %d\n", count_bits(sample_function.coord_mask));
}
shader_glsl_color_correction(arg, This->cur_args->color_fixup[sampler_idx]);
}
/** Process the WINED3DSIO_TEXDP3 instruction in GLSL:
@ -2600,6 +2606,7 @@ static void pshader_glsl_texm3x3tex(const SHADER_OPCODE_ARG *arg)
/* Sample the texture using the calculated coordinates */
shader_addline(arg->buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask);
shader_glsl_color_correction(arg, This->cur_args->color_fixup[reg]);
current_state->current_row = 0;
}
@ -2654,6 +2661,7 @@ static void pshader_glsl_texm3x3spec(const SHADER_OPCODE_ARG *arg)
/* Sample the texture */
shader_addline(buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask);
shader_glsl_color_correction(arg, shader->cur_args->color_fixup[reg]);
current_state->current_row = 0;
}
@ -2689,6 +2697,7 @@ static void pshader_glsl_texm3x3vspec(const SHADER_OPCODE_ARG *arg)
/* Sample the texture using the calculated coordinates */
shader_addline(buffer, "%s(Psampler%u, tmp0.xyz)%s);\n", sample_function.name, reg, dst_mask);
shader_glsl_color_correction(arg, shader->cur_args->color_fixup[reg]);
current_state->current_row = 0;
}
@ -2743,13 +2752,19 @@ static void pshader_glsl_texbem(const SHADER_OPCODE_ARG *arg)
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_0|WINED3DSP_WRITEMASK_1, &coord_param);
if(arg->opcode->opcode == WINED3DSIO_TEXBEML) {
glsl_src_param_t luminance_param;
shader_glsl_append_dst(arg->buffer, arg);
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], WINED3DSP_WRITEMASK_2, &luminance_param);
shader_addline(arg->buffer, "(%s(Psampler%u, T%u%s + vec4(bumpenvmat%d * %s, 0.0, 0.0)%s )*(%s * luminancescale%d + luminanceoffset%d))%s);\n",
shader_addline(arg->buffer, "%s(Psampler%u, T%u%s + vec4(bumpenvmat%d * %s, 0.0, 0.0)%s )%s);\n",
sample_function.name, sampler_idx, sampler_idx, coord_mask, sampler_idx, coord_param.param_str, coord_mask,
luminance_param.param_str, sampler_idx, sampler_idx, dst_swizzle);
dst_swizzle);
shader_glsl_color_correction(arg, This->cur_args->color_fixup[sampler_idx]);
shader_glsl_append_dst(arg->buffer, arg);
shader_addline(arg->buffer, "(temp*(%s * luminancescale%d + luminanceoffset%d)));\n",
luminance_param.param_str, sampler_idx, sampler_idx);
} else {
shader_addline(arg->buffer, "%s(Psampler%u, T%u%s + vec4(bumpenvmat%d * %s, 0.0, 0.0)%s )%s);\n",
sample_function.name, sampler_idx, sampler_idx, coord_mask, sampler_idx, coord_param.param_str, coord_mask, dst_swizzle);
shader_glsl_color_correction(arg, This->cur_args->color_fixup[sampler_idx]); /* FIXME */
}
}
@ -2805,6 +2820,7 @@ static void pshader_glsl_texreg2rgb(const SHADER_OPCODE_ARG *arg)
DWORD sampler_idx = arg->dst & WINED3DSP_REGNUM_MASK;
DWORD sampler_type = arg->reg_maps->samplers[sampler_idx] & WINED3DSP_TEXTURETYPE_MASK;
glsl_sample_function_t sample_function;
IWineD3DPixelShaderImpl* This = (IWineD3DPixelShaderImpl*) arg->shader;
shader_glsl_append_dst(arg->buffer, arg);
shader_glsl_get_write_mask(arg->dst, dst_mask);
@ -2813,6 +2829,7 @@ static void pshader_glsl_texreg2rgb(const SHADER_OPCODE_ARG *arg)
shader_glsl_add_src_param(arg, arg->src[0], arg->src_addr[0], sample_function.coord_mask, &src0_param);
shader_addline(arg->buffer, "%s(Psampler%u, %s)%s);\n", sample_function.name, sampler_idx, src0_param.param_str, dst_mask);
shader_glsl_color_correction(arg, This->cur_args->color_fixup[sampler_idx]);
}
/** Process the WINED3DSIO_TEXKILL instruction in GLSL.
@ -4120,7 +4137,6 @@ const shader_backend_t glsl_shader_backend = {
shader_glsl_update_float_vertex_constants,
shader_glsl_update_float_pixel_constants,
shader_glsl_load_constants,
shader_glsl_color_correction,
shader_glsl_destroy,
shader_glsl_alloc,
shader_glsl_free,

View File

@ -428,14 +428,13 @@ static GLuint pixelshader_compile(IWineD3DPixelShaderImpl *This, const struct ps
pixelshader_update_samplers(&This->baseShader.reg_maps,
((IWineD3DDeviceImpl *)This->baseShader.device)->stateBlock->textures);
/* Reset fields tracking stateblock values being hardcoded in the shader */
This->baseShader.num_sampled_samplers = 0;
/* Generate the HW shader */
TRACE("(%p) : Generating hardware program\n", This);
This->cur_args = args;
shader_buffer_init(&buffer);
retval = device->shader_backend->shader_generate_pshader((IWineD3DPixelShader *)This, &buffer, args);
shader_buffer_free(&buffer);
This->cur_args = NULL;
return retval;
}
@ -456,20 +455,20 @@ const IWineD3DPixelShaderVtbl IWineD3DPixelShader_Vtbl =
};
void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImpl *stateblock, struct ps_compile_args *args) {
UINT i, sampler;
UINT i;
IWineD3DBaseTextureImpl *tex;
memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set */
args->srgb_correction = stateblock->renderState[WINED3DRS_SRGBWRITEENABLE] ? 1 : 0;
for(i = 0; i < shader->baseShader.num_sampled_samplers; i++) {
sampler = shader->baseShader.sampled_samplers[i];
tex = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler];
for(i = 0; i < MAX_FRAGMENT_SAMPLERS; i++) {
if(shader->baseShader.reg_maps.samplers[i] == 0) continue;
tex = (IWineD3DBaseTextureImpl *) stateblock->textures[i];
if(!tex) {
args->color_fixup[sampler] = COLOR_FIXUP_IDENTITY;
args->color_fixup[i] = COLOR_FIXUP_IDENTITY;
continue;
}
args->color_fixup[sampler] = tex->baseTexture.shader_color_fixup;
args->color_fixup[i] = tex->baseTexture.shader_color_fixup;
}
if (shader->baseShader.reg_maps.shader_version >= WINED3DPS_VERSION(3,0))
{

View File

@ -479,7 +479,6 @@ typedef struct {
void (*shader_update_float_vertex_constants)(IWineD3DDevice *iface, UINT start, UINT count);
void (*shader_update_float_pixel_constants)(IWineD3DDevice *iface, UINT start, UINT count);
void (*shader_load_constants)(IWineD3DDevice *iface, char usePS, char useVS);
void (*shader_color_correction)(const struct SHADER_OPCODE_ARG *arg, struct color_fixup_desc fixup);
void (*shader_destroy)(IWineD3DBaseShader *iface);
HRESULT (*shader_alloc_private)(IWineD3DDevice *iface);
void (*shader_free_private)(IWineD3DDevice *iface);
@ -2274,9 +2273,6 @@ typedef struct IWineD3DBaseShaderClass
struct list constantsI;
shader_reg_maps reg_maps;
UINT sampled_samplers[MAX_COMBINED_SAMPLERS];
UINT num_sampled_samplers;
UINT recompile_count;
/* Pointer to the parent device */
@ -2447,6 +2443,8 @@ typedef struct IWineD3DPixelShaderImpl {
char numbumpenvmatconsts;
struct stb_const_desc luminanceconst[MAX_TEXTURES];
char vpos_uniform;
const struct ps_compile_args *cur_args;
} IWineD3DPixelShaderImpl;
extern const SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[];