wined3d: Implement dual source blending.
Based on a patch by Michael Müller. Signed-off-by: Zebediah Figura <z.figura12@gmail.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
92d6a8bf8f
commit
df569853bf
|
@ -3444,6 +3444,8 @@ static uint32_t find_draw_buffers_mask(const struct wined3d_context_gl *context_
|
||||||
|
|
||||||
rt_mask = ps ? ps->reg_maps.rt_mask : 1;
|
rt_mask = ps ? ps->reg_maps.rt_mask : 1;
|
||||||
rt_mask &= (1u << gl_info->limits.buffers) - 1;
|
rt_mask &= (1u << gl_info->limits.buffers) - 1;
|
||||||
|
if (state->blend_state && state->blend_state->dual_source)
|
||||||
|
rt_mask = 1;
|
||||||
|
|
||||||
mask = rt_mask;
|
mask = rt_mask;
|
||||||
while (mask)
|
while (mask)
|
||||||
|
|
|
@ -7772,7 +7772,10 @@ static GLuint shader_glsl_generate_fragment_shader(const struct wined3d_context_
|
||||||
{
|
{
|
||||||
const struct wined3d_shader_signature *output_signature = &shader->output_signature;
|
const struct wined3d_shader_signature *output_signature = &shader->output_signature;
|
||||||
|
|
||||||
shader_addline(buffer, "vec4 ps_out[%u];\n", gl_info->limits.buffers);
|
if (args->dual_source_blend)
|
||||||
|
shader_addline(buffer, "vec4 ps_out[2];\n");
|
||||||
|
else
|
||||||
|
shader_addline(buffer, "vec4 ps_out[%u];\n", gl_info->limits.buffers);
|
||||||
if (output_signature->element_count)
|
if (output_signature->element_count)
|
||||||
{
|
{
|
||||||
for (i = 0; i < output_signature->element_count; ++i)
|
for (i = 0; i < output_signature->element_count; ++i)
|
||||||
|
@ -7787,7 +7790,12 @@ static GLuint shader_glsl_generate_fragment_shader(const struct wined3d_context_
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (shader_glsl_use_explicit_attrib_location(gl_info))
|
if (shader_glsl_use_explicit_attrib_location(gl_info))
|
||||||
shader_addline(buffer, "layout(location = %u) ", output->semantic_idx);
|
{
|
||||||
|
if (args->dual_source_blend)
|
||||||
|
shader_addline(buffer, "layout(location = 0, index = %u) ", output->semantic_idx);
|
||||||
|
else
|
||||||
|
shader_addline(buffer, "layout(location = %u) ", output->semantic_idx);
|
||||||
|
}
|
||||||
shader_addline(buffer, "out %s4 color_out%u;\n",
|
shader_addline(buffer, "out %s4 color_out%u;\n",
|
||||||
component_type_info[output->component_type].glsl_vector_type, output->semantic_idx);
|
component_type_info[output->component_type].glsl_vector_type, output->semantic_idx);
|
||||||
}
|
}
|
||||||
|
@ -7800,7 +7808,12 @@ static GLuint shader_glsl_generate_fragment_shader(const struct wined3d_context_
|
||||||
{
|
{
|
||||||
i = wined3d_bit_scan(&mask);
|
i = wined3d_bit_scan(&mask);
|
||||||
if (shader_glsl_use_explicit_attrib_location(gl_info))
|
if (shader_glsl_use_explicit_attrib_location(gl_info))
|
||||||
shader_addline(buffer, "layout(location = %u) ", i);
|
{
|
||||||
|
if (args->dual_source_blend)
|
||||||
|
shader_addline(buffer, "layout(location = 0, index = %u) ", i);
|
||||||
|
else
|
||||||
|
shader_addline(buffer, "layout(location = %u) ", i);
|
||||||
|
}
|
||||||
shader_addline(buffer, "out vec4 color_out%u;\n", i);
|
shader_addline(buffer, "out vec4 color_out%u;\n", i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10385,7 +10398,10 @@ static void set_glsl_shader_program(const struct wined3d_context_gl *context_gl,
|
||||||
for (i = 0; i < MAX_RENDER_TARGET_VIEWS; ++i)
|
for (i = 0; i < MAX_RENDER_TARGET_VIEWS; ++i)
|
||||||
{
|
{
|
||||||
string_buffer_sprintf(tmp_name, "color_out%u", i);
|
string_buffer_sprintf(tmp_name, "color_out%u", i);
|
||||||
GL_EXTCALL(glBindFragDataLocation(program_id, i, tmp_name->buffer));
|
if (state->blend_state && state->blend_state->dual_source)
|
||||||
|
GL_EXTCALL(glBindFragDataLocationIndexed(program_id, 0, i, tmp_name->buffer));
|
||||||
|
else
|
||||||
|
GL_EXTCALL(glBindFragDataLocation(program_id, i, tmp_name->buffer));
|
||||||
checkGLcall("glBindFragDataLocation");
|
checkGLcall("glBindFragDataLocation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4167,6 +4167,8 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
|
||||||
if (rtv && rtv->format->id == WINED3DFMT_A8_UNORM && !is_identity_fixup(rtv->format->color_fixup))
|
if (rtv && rtv->format->id == WINED3DFMT_A8_UNORM && !is_identity_fixup(rtv->format->color_fixup))
|
||||||
args->rt_alpha_swizzle |= 1u << i;
|
args->rt_alpha_swizzle |= 1u << i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
args->dual_source_blend = state->blend_state && state->blend_state->dual_source;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT pixel_shader_init(struct wined3d_shader *shader, struct wined3d_device *device,
|
static HRESULT pixel_shader_init(struct wined3d_shader *shader, struct wined3d_device *device,
|
||||||
|
|
|
@ -74,6 +74,11 @@ void * CDECL wined3d_blend_state_get_parent(const struct wined3d_blend_state *st
|
||||||
return state->parent;
|
return state->parent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static BOOL is_dual_source(enum wined3d_blend state)
|
||||||
|
{
|
||||||
|
return state >= WINED3D_BLEND_SRC1COLOR && state <= WINED3D_BLEND_INVSRC1ALPHA;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT CDECL wined3d_blend_state_create(struct wined3d_device *device,
|
HRESULT CDECL wined3d_blend_state_create(struct wined3d_device *device,
|
||||||
const struct wined3d_blend_state_desc *desc, void *parent,
|
const struct wined3d_blend_state_desc *desc, void *parent,
|
||||||
const struct wined3d_parent_ops *parent_ops, struct wined3d_blend_state **state)
|
const struct wined3d_parent_ops *parent_ops, struct wined3d_blend_state **state)
|
||||||
|
@ -92,6 +97,12 @@ HRESULT CDECL wined3d_blend_state_create(struct wined3d_device *device,
|
||||||
object->parent_ops = parent_ops;
|
object->parent_ops = parent_ops;
|
||||||
object->device = device;
|
object->device = device;
|
||||||
|
|
||||||
|
object->dual_source = desc->rt[0].enable
|
||||||
|
&& (is_dual_source(desc->rt[0].src)
|
||||||
|
|| is_dual_source(desc->rt[0].dst)
|
||||||
|
|| is_dual_source(desc->rt[0].src_alpha)
|
||||||
|
|| is_dual_source(desc->rt[0].dst_alpha));
|
||||||
|
|
||||||
TRACE("Created blend state %p.\n", object);
|
TRACE("Created blend state %p.\n", object);
|
||||||
*state = object;
|
*state = object;
|
||||||
|
|
||||||
|
@ -650,6 +661,7 @@ static void blend_db2(struct wined3d_context *context, const struct wined3d_stat
|
||||||
GLenum src_blend, dst_blend, src_blend_alpha, dst_blend_alpha;
|
GLenum src_blend, dst_blend, src_blend_alpha, dst_blend_alpha;
|
||||||
const struct wined3d_blend_state *b = state->blend_state;
|
const struct wined3d_blend_state *b = state->blend_state;
|
||||||
const struct wined3d_format *rt_format;
|
const struct wined3d_format *rt_format;
|
||||||
|
BOOL dual_source = b && b->dual_source;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (b && b->desc.alpha_to_coverage)
|
if (b && b->desc.alpha_to_coverage)
|
||||||
|
@ -658,6 +670,13 @@ static void blend_db2(struct wined3d_context *context, const struct wined3d_stat
|
||||||
gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||||
checkGLcall("glEnable GL_SAMPLE_ALPHA_TO_COVERAGE");
|
checkGLcall("glEnable GL_SAMPLE_ALPHA_TO_COVERAGE");
|
||||||
|
|
||||||
|
if (context->last_was_dual_source_blend != dual_source)
|
||||||
|
{
|
||||||
|
/* Dual source blending changes the location of the output varyings. */
|
||||||
|
context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
|
||||||
|
context->last_was_dual_source_blend = dual_source;
|
||||||
|
}
|
||||||
|
|
||||||
if (!b || !b->desc.independent)
|
if (!b || !b->desc.independent)
|
||||||
{
|
{
|
||||||
blend(context, state, state_id);
|
blend(context, state, state_id);
|
||||||
|
@ -708,6 +727,7 @@ static void blend_dbb(struct wined3d_context *context, const struct wined3d_stat
|
||||||
{
|
{
|
||||||
const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info;
|
const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info;
|
||||||
const struct wined3d_blend_state *b = state->blend_state;
|
const struct wined3d_blend_state *b = state->blend_state;
|
||||||
|
BOOL dual_source = b && b->dual_source;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
|
||||||
if (b && b->desc.alpha_to_coverage)
|
if (b && b->desc.alpha_to_coverage)
|
||||||
|
@ -716,6 +736,13 @@ static void blend_dbb(struct wined3d_context *context, const struct wined3d_stat
|
||||||
gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||||
checkGLcall("glEnable GL_SAMPLE_ALPHA_TO_COVERAGE");
|
checkGLcall("glEnable GL_SAMPLE_ALPHA_TO_COVERAGE");
|
||||||
|
|
||||||
|
if (context->last_was_dual_source_blend != dual_source)
|
||||||
|
{
|
||||||
|
/* Dual source blending changes the location of the output varyings. */
|
||||||
|
context->shader_update_mask |= 1u << WINED3D_SHADER_TYPE_PIXEL;
|
||||||
|
context->last_was_dual_source_blend = dual_source;
|
||||||
|
}
|
||||||
|
|
||||||
if (!b || !b->desc.independent)
|
if (!b || !b->desc.independent)
|
||||||
{
|
{
|
||||||
blend(context, state, state_id);
|
blend(context, state, state_id);
|
||||||
|
|
|
@ -1394,7 +1394,8 @@ struct ps_compile_args
|
||||||
DWORD alpha_test_func : 3;
|
DWORD alpha_test_func : 3;
|
||||||
DWORD render_offscreen : 1;
|
DWORD render_offscreen : 1;
|
||||||
DWORD rt_alpha_swizzle : 8; /* MAX_RENDER_TARGET_VIEWS, 8 */
|
DWORD rt_alpha_swizzle : 8; /* MAX_RENDER_TARGET_VIEWS, 8 */
|
||||||
DWORD padding : 18;
|
DWORD dual_source_blend : 1;
|
||||||
|
DWORD padding : 17;
|
||||||
};
|
};
|
||||||
|
|
||||||
enum fog_src_type
|
enum fog_src_type
|
||||||
|
@ -1954,7 +1955,7 @@ struct wined3d_context
|
||||||
DWORD last_was_ffp_blit : 1;
|
DWORD last_was_ffp_blit : 1;
|
||||||
DWORD last_was_blit : 1;
|
DWORD last_was_blit : 1;
|
||||||
DWORD last_was_ckey : 1;
|
DWORD last_was_ckey : 1;
|
||||||
DWORD namedArraysLoaded : 1;
|
DWORD last_was_dual_source_blend : 1;
|
||||||
DWORD texShaderBumpMap : 8; /* WINED3D_MAX_TEXTURES, 8 */
|
DWORD texShaderBumpMap : 8; /* WINED3D_MAX_TEXTURES, 8 */
|
||||||
DWORD lastWasPow2Texture : 8; /* WINED3D_MAX_TEXTURES, 8 */
|
DWORD lastWasPow2Texture : 8; /* WINED3D_MAX_TEXTURES, 8 */
|
||||||
DWORD fixed_function_usage_map : 8; /* WINED3D_MAX_TEXTURES, 8 */
|
DWORD fixed_function_usage_map : 8; /* WINED3D_MAX_TEXTURES, 8 */
|
||||||
|
@ -1971,7 +1972,8 @@ struct wined3d_context
|
||||||
DWORD destroyed : 1;
|
DWORD destroyed : 1;
|
||||||
DWORD destroy_delayed : 1;
|
DWORD destroy_delayed : 1;
|
||||||
DWORD clip_distance_mask : 8; /* WINED3D_MAX_CLIP_DISTANCES, 8 */
|
DWORD clip_distance_mask : 8; /* WINED3D_MAX_CLIP_DISTANCES, 8 */
|
||||||
DWORD padding : 14;
|
DWORD namedArraysLoaded : 1;
|
||||||
|
DWORD padding : 13;
|
||||||
|
|
||||||
DWORD constant_update_mask;
|
DWORD constant_update_mask;
|
||||||
DWORD numbered_array_mask;
|
DWORD numbered_array_mask;
|
||||||
|
@ -3140,6 +3142,7 @@ struct wined3d_blend_state
|
||||||
{
|
{
|
||||||
LONG refcount;
|
LONG refcount;
|
||||||
struct wined3d_blend_state_desc desc;
|
struct wined3d_blend_state_desc desc;
|
||||||
|
BOOL dual_source;
|
||||||
|
|
||||||
void *parent;
|
void *parent;
|
||||||
const struct wined3d_parent_ops *parent_ops;
|
const struct wined3d_parent_ops *parent_ops;
|
||||||
|
|
Loading…
Reference in New Issue