[PATCH 1/2] wined3d: Implement independent blend.

Zebediah Figura z.figura12 at gmail.com
Thu Mar 12 22:00:49 CDT 2020


Signed-off-by: Zebediah Figura <z.figura12 at gmail.com>
---
 dlls/d3d10core/tests/d3d10core.c |   3 +-
 dlls/d3d11/state.c               |  22 ++--
 dlls/d3d11/tests/d3d11.c         |   7 +-
 dlls/wined3d/adapter_gl.c        |   7 +
 dlls/wined3d/device.c            |  21 +--
 dlls/wined3d/shader.c            |   2 +-
 dlls/wined3d/state.c             | 214 ++++++++++++++++++++++++-------
 dlls/wined3d/utils.c             |   4 +-
 dlls/wined3d/wined3d_gl.h        |   1 +
 include/wine/wined3d.h           |  19 ++-
 10 files changed, 220 insertions(+), 80 deletions(-)

diff --git a/dlls/d3d10core/tests/d3d10core.c b/dlls/d3d10core/tests/d3d10core.c
index 6b19379900..0aa998c6a6 100644
--- a/dlls/d3d10core/tests/d3d10core.c
+++ b/dlls/d3d10core/tests/d3d10core.c
@@ -18276,8 +18276,7 @@ static void test_independent_blend(void)
     {
         get_texture_readback(rts[i], 0, &rb);
         color = get_readback_color(&rb, 320, 240);
-        todo_wine_if (i & 1)
-            ok(color == ((i & 1) ? 0x80008080 : 0x8000ff00), "%u: Got unexpected color 0x%08x.\n", i, color);
+        ok(color == ((i & 1) ? 0x80008080 : 0x8000ff00), "%u: Got unexpected color 0x%08x.\n", i, color);
         release_resource_readback(&rb);
 
         ID3D10Texture2D_Release(rts[i]);
diff --git a/dlls/d3d11/state.c b/dlls/d3d11/state.c
index 3bd10dd547..85ee67e272 100644
--- a/dlls/d3d11/state.c
+++ b/dlls/d3d11/state.c
@@ -350,10 +350,6 @@ HRESULT d3d_blend_state_create(struct d3d_device *device, const D3D11_BLEND_DESC
                     tmp_desc.RenderTarget[i].RenderTargetWriteMask, i);
     }
 
-    /* glEnableIndexedEXT(GL_BLEND, ...) */
-    if (tmp_desc.IndependentBlendEnable)
-        FIXME("Per-rendertarget blend not implemented.\n");
-
     wined3d_mutex_lock();
     if ((entry = wine_rb_get(&device->blend_states, &tmp_desc)))
     {
@@ -389,13 +385,17 @@ HRESULT d3d_blend_state_create(struct d3d_device *device, const D3D11_BLEND_DESC
     }
 
     wined3d_desc.alpha_to_coverage = desc->AlphaToCoverageEnable;
-    wined3d_desc.enable = desc->RenderTarget[0].BlendEnable;
-    wined3d_desc.src = desc->RenderTarget[0].SrcBlend;
-    wined3d_desc.dst = desc->RenderTarget[0].DestBlend;
-    wined3d_desc.op = desc->RenderTarget[0].BlendOp;
-    wined3d_desc.src_alpha = desc->RenderTarget[0].SrcBlendAlpha;
-    wined3d_desc.dst_alpha = desc->RenderTarget[0].DestBlendAlpha;
-    wined3d_desc.op_alpha = desc->RenderTarget[0].BlendOpAlpha;
+    wined3d_desc.independent = desc->IndependentBlendEnable;
+    for (i = 0; i < D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT; ++i)
+    {
+        wined3d_desc.rt[i].enable = desc->RenderTarget[i].BlendEnable;
+        wined3d_desc.rt[i].src = desc->RenderTarget[i].SrcBlend;
+        wined3d_desc.rt[i].dst = desc->RenderTarget[i].DestBlend;
+        wined3d_desc.rt[i].op = desc->RenderTarget[i].BlendOp;
+        wined3d_desc.rt[i].src_alpha = desc->RenderTarget[i].SrcBlendAlpha;
+        wined3d_desc.rt[i].dst_alpha = desc->RenderTarget[i].DestBlendAlpha;
+        wined3d_desc.rt[i].op_alpha = desc->RenderTarget[i].BlendOpAlpha;
+    }
 
     /* We cannot fail after creating a wined3d_blend_state object. It
      * would lead to double free. */
diff --git a/dlls/d3d11/tests/d3d11.c b/dlls/d3d11/tests/d3d11.c
index 22c7b0d4fb..60c6e92cd9 100644
--- a/dlls/d3d11/tests/d3d11.c
+++ b/dlls/d3d11/tests/d3d11.c
@@ -29919,7 +29919,7 @@ static void test_independent_blend(void)
                     D3D11_BLEND_ZERO, D3D11_BLEND_ONE, D3D11_BLEND_OP_ADD, D3D11_COLOR_WRITE_ENABLE_ALL},
             {TRUE, D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_INV_BLEND_FACTOR, D3D11_BLEND_OP_SUBTRACT,
                     D3D11_BLEND_ONE, D3D11_BLEND_ONE, D3D11_BLEND_OP_REV_SUBTRACT, D3D11_COLOR_WRITE_ENABLE_ALL},
-            {FALSE},
+            {FALSE, 0, 0, 0, 0, 0, 0, D3D11_COLOR_WRITE_ENABLE_ALL},
             {TRUE, D3D11_BLEND_DEST_COLOR, D3D11_BLEND_SRC_COLOR, D3D11_BLEND_OP_ADD,
                     D3D11_BLEND_INV_SRC_ALPHA, D3D11_BLEND_INV_DEST_ALPHA, D3D11_BLEND_OP_SUBTRACT,
                     D3D11_COLOR_WRITE_ENABLE_ALL},
@@ -29927,7 +29927,7 @@ static void test_independent_blend(void)
     };
 
     static const DWORD expected_colors[] =
-            {0x66426e1c, 0xb34c3319, 0xa6214a05, 0x66333319, 0xb34c4829, 0x4d19000a, 0xb333801a, 0x081f3305};
+            {0x66426e1c, 0xb34c3319, 0xa6214a05, 0x66333319, 0xb34c4829, 0x4d19000a, 0x664c3319, 0x081f3305};
 
     static const float clear_color[] = {0.1f, 0.5f, 0.2f, 0.7f};
     static const float blend_factor[] = {0.8f, 0.4f, 0.6f, 0.2f};
@@ -29967,8 +29967,7 @@ static void test_independent_blend(void)
     {
         get_texture_readback(rts[i], 0, &rb);
         color = get_readback_color(&rb, 320, 240, 0);
-        todo_wine_if (i)
-            ok(compare_color(color, expected_colors[i], 1), "%u: Got unexpected color 0x%08x.\n", i, color);
+        ok(compare_color(color, expected_colors[i], 1), "%u: Got unexpected color 0x%08x.\n", i, color);
         release_resource_readback(&rb);
     }
 
diff --git a/dlls/wined3d/adapter_gl.c b/dlls/wined3d/adapter_gl.c
index c04656173d..1860dd4bd0 100644
--- a/dlls/wined3d/adapter_gl.c
+++ b/dlls/wined3d/adapter_gl.c
@@ -74,6 +74,7 @@ static const struct wined3d_extension_map gl_extension_map[] =
     {"GL_ARB_depth_texture",                ARB_DEPTH_TEXTURE             },
     {"GL_ARB_derivative_control",           ARB_DERIVATIVE_CONTROL        },
     {"GL_ARB_draw_buffers",                 ARB_DRAW_BUFFERS              },
+    {"GL_ARB_draw_buffers_blend",           ARB_DRAW_BUFFERS_BLEND        },
     {"GL_ARB_draw_elements_base_vertex",    ARB_DRAW_ELEMENTS_BASE_VERTEX },
     {"GL_ARB_draw_indirect",                ARB_DRAW_INDIRECT             },
     {"GL_ARB_draw_instanced",               ARB_DRAW_INSTANCED            },
@@ -1310,6 +1311,7 @@ static enum wined3d_feature_level feature_level_from_caps(const struct wined3d_g
 
     if (gl_info->supported[WINED3D_GL_VERSION_3_2]
             && gl_info->supported[ARB_POLYGON_OFFSET_CLAMP]
+            && gl_info->supported[ARB_DRAW_BUFFERS_BLEND]
             && gl_info->supported[ARB_SAMPLER_OBJECTS])
     {
         if (shader_model >= 5
@@ -2679,8 +2681,12 @@ static void load_gl_funcs(struct wined3d_gl_info *gl_info)
     USE_GL_FUNC(glBindVertexArray)                             /* OpenGL 3.0 */
     USE_GL_FUNC(glBlendColor)                                  /* OpenGL 1.4 */
     USE_GL_FUNC(glBlendEquation)                               /* OpenGL 1.4 */
+    USE_GL_FUNC(glBlendEquationi)                              /* OpenGL 4.0 */
     USE_GL_FUNC(glBlendEquationSeparate)                       /* OpenGL 2.0 */
+    USE_GL_FUNC(glBlendEquationSeparatei)                      /* OpenGL 4.0 */
+    USE_GL_FUNC(glBlendFunci)                                  /* OpenGL 4.0 */
     USE_GL_FUNC(glBlendFuncSeparate)                           /* OpenGL 1.4 */
+    USE_GL_FUNC(glBlendFuncSeparatei)                          /* OpenGL 4.0 */
     USE_GL_FUNC(glBufferData)                                  /* OpenGL 1.5 */
     USE_GL_FUNC(glBufferSubData)                               /* OpenGL 1.5 */
     USE_GL_FUNC(glColorMaski)                                  /* OpenGL 3.0 */
@@ -3370,6 +3376,7 @@ static BOOL wined3d_adapter_init_gl_caps(struct wined3d_adapter *adapter,
         {ARB_TIMER_QUERY,                  MAKEDWORD_VERSION(3, 3)},
         {ARB_VERTEX_TYPE_2_10_10_10_REV,   MAKEDWORD_VERSION(3, 3)},
 
+        {ARB_DRAW_BUFFERS_BLEND,           MAKEDWORD_VERSION(4, 0)},
         {ARB_DRAW_INDIRECT,                MAKEDWORD_VERSION(4, 0)},
         {ARB_GPU_SHADER5,                  MAKEDWORD_VERSION(4, 0)},
         {ARB_SAMPLE_SHADING,               MAKEDWORD_VERSION(4, 0)},
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index d94b1e2f2d..889aac0506 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3657,23 +3657,24 @@ void CDECL wined3d_device_apply_stateblock(struct wined3d_device *device,
 
         memset(&desc, 0, sizeof(desc));
         desc.alpha_to_coverage = state->alpha_to_coverage;
+        desc.independent = FALSE;
         if (state->rs[WINED3D_RS_ADAPTIVETESS_Y] == WINED3DFMT_ATOC)
             desc.alpha_to_coverage = TRUE;
-        desc.enable = state->rs[WINED3D_RS_ALPHABLENDENABLE];
-        desc.src = state->rs[WINED3D_RS_SRCBLEND];
-        desc.dst = state->rs[WINED3D_RS_DESTBLEND];
-        desc.op = state->rs[WINED3D_RS_BLENDOP];
+        desc.rt[0].enable = state->rs[WINED3D_RS_ALPHABLENDENABLE];
+        desc.rt[0].src = state->rs[WINED3D_RS_SRCBLEND];
+        desc.rt[0].dst = state->rs[WINED3D_RS_DESTBLEND];
+        desc.rt[0].op = state->rs[WINED3D_RS_BLENDOP];
         if (state->rs[WINED3D_RS_SEPARATEALPHABLENDENABLE])
         {
-            desc.src_alpha = state->rs[WINED3D_RS_SRCBLENDALPHA];
-            desc.dst_alpha = state->rs[WINED3D_RS_DESTBLENDALPHA];
-            desc.op_alpha = state->rs[WINED3D_RS_BLENDOPALPHA];
+            desc.rt[0].src_alpha = state->rs[WINED3D_RS_SRCBLENDALPHA];
+            desc.rt[0].dst_alpha = state->rs[WINED3D_RS_DESTBLENDALPHA];
+            desc.rt[0].op_alpha = state->rs[WINED3D_RS_BLENDOPALPHA];
         }
         else
         {
-            desc.src_alpha = state->rs[WINED3D_RS_SRCBLEND];
-            desc.dst_alpha = state->rs[WINED3D_RS_DESTBLEND];
-            desc.op_alpha = state->rs[WINED3D_RS_BLENDOP];
+            desc.rt[0].src_alpha = state->rs[WINED3D_RS_SRCBLEND];
+            desc.rt[0].dst_alpha = state->rs[WINED3D_RS_DESTBLEND];
+            desc.rt[0].op_alpha = state->rs[WINED3D_RS_BLENDOP];
         }
 
         if (wined3d_bitmap_is_set(changed->renderState, WINED3D_RS_BLENDFACTOR))
diff --git a/dlls/wined3d/shader.c b/dlls/wined3d/shader.c
index 13e55cff8a..d9ef1a96e2 100644
--- a/dlls/wined3d/shader.c
+++ b/dlls/wined3d/shader.c
@@ -3909,7 +3909,7 @@ void find_ps_compile_args(const struct wined3d_state *state, const struct wined3
         static unsigned int warned = 0;
 
         args->srgb_correction = 1;
-        if (state->blend_state && state->blend_state->desc.enable && !warned++)
+        if (state->blend_state && state->blend_state->desc.rt[0].enable && !warned++)
             WARN("Blending into a sRGB render target with no GL_ARB_framebuffer_sRGB "
                     "support, expect rendering artifacts.\n");
     }
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 19f47f834e..ad3ce37501 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -426,17 +426,17 @@ static void blendop(const struct wined3d_state *state, const struct wined3d_gl_i
     }
 
     /* BLENDOPALPHA requires GL_EXT_blend_equation_separate, so make sure it is around */
-    if (b->desc.op_alpha && !gl_info->supported[EXT_BLEND_EQUATION_SEPARATE])
+    if (b->desc.rt[0].op_alpha && !gl_info->supported[EXT_BLEND_EQUATION_SEPARATE])
     {
         WARN("Unsupported in local OpenGL implementation: glBlendEquationSeparate.\n");
         return;
     }
 
-    blend_equation = gl_blend_op(gl_info, b->desc.op);
-    blend_equation_alpha = gl_blend_op(gl_info, b->desc.op_alpha);
+    blend_equation = gl_blend_op(gl_info, b->desc.rt[0].op);
+    blend_equation_alpha = gl_blend_op(gl_info, b->desc.rt[0].op_alpha);
     TRACE("blend_equation %#x, blend_equation_alpha %#x.\n", blend_equation, blend_equation_alpha);
 
-    if (b->desc.op != b->desc.op_alpha)
+    if (b->desc.rt[0].op != b->desc.rt[0].op_alpha)
     {
         GL_EXTCALL(glBlendEquationSeparate(blend_equation, blend_equation_alpha));
         checkGLcall("glBlendEquationSeparate");
@@ -525,43 +525,78 @@ static void gl_blend_from_d3d(GLenum *src_blend, GLenum *dst_blend,
     }
 }
 
-static void state_blend(struct wined3d_context *context, const struct wined3d_state *state)
+static void state_blend_factor_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    WARN("Unsupported in local OpenGL implementation: glBlendColor.\n");
+}
+
+static void state_blend_factor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+{
+    const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info;
+    const struct wined3d_color *factor = &state->blend_factor;
+
+    TRACE("Setting blend factor to %s.\n", debug_color(factor));
+
+    GL_EXTCALL(glBlendColor(factor->r, factor->g, factor->b, factor->a));
+    checkGLcall("glBlendColor");
+}
+
+static BOOL is_blend_enabled(struct wined3d_context *context, const struct wined3d_state *state, UINT index)
+{
+    const struct wined3d_blend_state *b = state->blend_state;
+
+    if (!state->fb->render_targets[index])
+        return FALSE;
+
+    if (!b->desc.rt[index].enable)
+        return FALSE;
+
+    /* Disable blending in all cases even without pixel shaders.
+     * With blending on we could face a big performance penalty.
+     * The d3d9 visual test confirms the behavior. */
+    if (context->render_offscreen
+            && !(state->fb->render_targets[index]->format_flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
+        return FALSE;
+
+    return TRUE;
+}
+
+static void blend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     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_format *rt_format;
     GLenum src_blend, dst_blend;
-    unsigned int rt_fmt_flags;
-    BOOL enable_blend;
 
-    enable_blend = state->fb->render_targets[0] && b && b->desc.enable;
-    if (enable_blend)
+    if (gl_info->supported[ARB_MULTISAMPLE])
     {
-        rt_format = state->fb->render_targets[0]->format;
-        rt_fmt_flags = state->fb->render_targets[0]->format_flags;
-
-        /* Disable blending in all cases even without pixelshaders.
-         * With blending on we could face a big performance penalty.
-         * The d3d9 visual test confirms the behavior. */
-        if (context->render_offscreen && !(rt_fmt_flags & WINED3DFMT_FLAG_POSTPIXELSHADER_BLENDING))
-            enable_blend = FALSE;
+        if (b && b->desc.alpha_to_coverage)
+            gl_info->gl_ops.gl.p_glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+        else
+            gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+        checkGLcall("glEnable GL_SAMPLE_ALPHA_TO_COVERAGE");
     }
 
-    if (!enable_blend)
+    if (b && b->desc.independent)
+        WARN("Independent blend is not supported by this GL implementation.\n");
+
+    if (!b || !is_blend_enabled(context, state, 0))
     {
         gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
-        checkGLcall("glDisable(GL_BLEND)");
+        checkGLcall("glDisable GL_BLEND");
         return;
     }
 
     gl_info->gl_ops.gl.p_glEnable(GL_BLEND);
-    checkGLcall("glEnable(GL_BLEND)");
+    checkGLcall("glEnable GL_BLEND");
+
+    rt_format = state->fb->render_targets[0]->format;
 
-    gl_blend_from_d3d(&src_blend, &dst_blend, b->desc.src, b->desc.dst, rt_format);
+    gl_blend_from_d3d(&src_blend, &dst_blend, b->desc.rt[0].src, b->desc.rt[0].dst, rt_format);
 
     blendop(state, gl_info);
 
-    if (b->desc.src != b->desc.src_alpha || b->desc.dst != b->desc.dst_alpha)
+    if (b->desc.rt[0].src != b->desc.rt[0].src_alpha || b->desc.rt[0].dst != b->desc.rt[0].dst_alpha)
     {
         GLenum src_blend_alpha, dst_blend_alpha;
 
@@ -572,7 +607,7 @@ static void state_blend(struct wined3d_context *context, const struct wined3d_st
             return;
         }
 
-        gl_blend_from_d3d(&src_blend_alpha, &dst_blend_alpha, b->desc.src_alpha, b->desc.dst_alpha, rt_format);
+        gl_blend_from_d3d(&src_blend_alpha, &dst_blend_alpha, b->desc.rt[0].src_alpha, b->desc.rt[0].dst_alpha, rt_format);
 
         GL_EXTCALL(glBlendFuncSeparate(src_blend, dst_blend, src_blend_alpha, dst_blend_alpha));
         checkGLcall("glBlendFuncSeparate");
@@ -590,37 +625,128 @@ static void state_blend(struct wined3d_context *context, const struct wined3d_st
         context_apply_state(context, state, STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP));
 }
 
-static void state_blend_factor_w(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
-{
-    WARN("Unsupported in local OpenGL implementation: glBlendColor.\n");
-}
-
-static void state_blend_factor(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+static void blend_db2(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info;
-    const struct wined3d_color *factor = &state->blend_factor;
+    GLenum src_blend, dst_blend, src_blend_alpha, dst_blend_alpha;
+    const struct wined3d_blend_state *b = state->blend_state;
+    const struct wined3d_format *rt_format;
+    unsigned int i;
 
-    TRACE("Setting blend factor to %s.\n", debug_color(factor));
+    if (b && b->desc.alpha_to_coverage)
+        gl_info->gl_ops.gl.p_glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+    else
+        gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+    checkGLcall("glEnable GL_SAMPLE_ALPHA_TO_COVERAGE");
 
-    GL_EXTCALL(glBlendColor(factor->r, factor->g, factor->b, factor->a));
-    checkGLcall("glBlendColor");
+    if (!b)
+    {
+        gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+        checkGLcall("glDisable GL_BLEND");
+        return;
+    }
+
+    if (!b->desc.independent)
+    {
+        blend(context, state, state_id);
+        return;
+    }
+
+    rt_format = state->fb->render_targets[0]->format;
+    gl_blend_from_d3d(&src_blend, &dst_blend, b->desc.rt[0].src, b->desc.rt[0].dst, rt_format);
+    gl_blend_from_d3d(&src_blend_alpha, &dst_blend_alpha, b->desc.rt[0].src_alpha, b->desc.rt[0].dst_alpha, rt_format);
+
+    GL_EXTCALL(glBlendFuncSeparate(src_blend, dst_blend, src_blend_alpha, dst_blend_alpha));
+    checkGLcall("glBlendFuncSeparate");
+
+    GL_EXTCALL(glBlendEquationSeparate(gl_blend_op(gl_info, b->desc.rt[0].op),
+            gl_blend_op(gl_info, b->desc.rt[0].op_alpha)));
+    checkGLcall("glBlendEquationSeparate");
+
+    for (i = 0; i < WINED3D_MAX_RENDER_TARGETS; ++i)
+    {
+        if (!is_blend_enabled(context, state, i))
+        {
+            GL_EXTCALL(glDisablei(GL_BLEND, i));
+            checkGLcall("glDisablei GL_BLEND");
+            continue;
+        }
+
+        GL_EXTCALL(glEnablei(GL_BLEND, i));
+        checkGLcall("glEnablei GL_BLEND");
+
+        if (b->desc.rt[i].src != b->desc.rt[0].src
+                || b->desc.rt[i].dst != b->desc.rt[0].dst
+                || b->desc.rt[i].op != b->desc.rt[0].op
+                || b->desc.rt[i].src_alpha != b->desc.rt[0].src_alpha
+                || b->desc.rt[i].dst_alpha != b->desc.rt[0].dst_alpha
+                || b->desc.rt[i].op_alpha != b->desc.rt[0].op_alpha)
+            WARN("Independent blend equations and blend functions are not supported by this GL implementation.\n");
+    }
+
+    /* Colorkey fixup for stage 0 alphaop depends on blend state, so it may need
+     * updating. */
+    if (state->render_states[WINED3D_RS_COLORKEYENABLE])
+        context_apply_state(context, state, STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP));
 }
 
-static void blend(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
+static void blend_dbb(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
 {
     const struct wined3d_gl_info *gl_info = wined3d_context_gl(context)->gl_info;
     const struct wined3d_blend_state *b = state->blend_state;
+    unsigned int i;
 
-    if (gl_info->supported[ARB_MULTISAMPLE])
+    if (b && b->desc.alpha_to_coverage)
+        gl_info->gl_ops.gl.p_glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+    else
+        gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
+    checkGLcall("glEnable GL_SAMPLE_ALPHA_TO_COVERAGE");
+
+    if (!b)
     {
-        if (b && b->desc.alpha_to_coverage)
-            gl_info->gl_ops.gl.p_glEnable(GL_SAMPLE_ALPHA_TO_COVERAGE);
-        else
-            gl_info->gl_ops.gl.p_glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
-        checkGLcall("glEnable GL_SAMPLE_ALPHA_TO_COVERAGE");
+        gl_info->gl_ops.gl.p_glDisable(GL_BLEND);
+        checkGLcall("glDisable GL_BLEND");
+        return;
+    }
+
+    if (!b->desc.independent)
+    {
+        blend(context, state, state_id);
+        return;
+    }
+
+    for (i = 0; i < WINED3D_MAX_RENDER_TARGETS; ++i)
+    {
+        GLenum src_blend, dst_blend, src_blend_alpha, dst_blend_alpha;
+        const struct wined3d_format *rt_format;
+
+        if (!is_blend_enabled(context, state, i))
+        {
+            GL_EXTCALL(glDisablei(GL_BLEND, i));
+            checkGLcall("glDisablei GL_BLEND");
+            continue;
+        }
+
+        GL_EXTCALL(glEnablei(GL_BLEND, i));
+        checkGLcall("glEnablei GL_BLEND");
+
+        rt_format = state->fb->render_targets[i]->format;
+        gl_blend_from_d3d(&src_blend, &dst_blend, b->desc.rt[i].src, b->desc.rt[i].dst, rt_format);
+        gl_blend_from_d3d(&src_blend_alpha, &dst_blend_alpha,
+                b->desc.rt[i].src_alpha, b->desc.rt[i].dst_alpha, rt_format);
+
+        GL_EXTCALL(glBlendFuncSeparatei(i, src_blend, dst_blend, src_blend_alpha, dst_blend_alpha));
+        checkGLcall("glBlendFuncSeparatei");
+
+        GL_EXTCALL(glBlendEquationSeparatei(i, gl_blend_op(gl_info, b->desc.rt[i].op),
+                gl_blend_op(gl_info, b->desc.rt[i].op_alpha)));
+        checkGLcall("glBlendEquationSeparatei");
     }
 
-    state_blend(context, state);
+    /* Colorkey fixup for stage 0 alphaop depends on blend state, so it may need
+     * updating. */
+    if (state->render_states[WINED3D_RS_COLORKEYENABLE])
+        context_apply_state(context, state, STATE_TEXTURESTAGE(0, WINED3D_TSS_ALPHA_OP));
 }
 
 void state_alpha_test(struct wined3d_context *context, const struct wined3d_state *state, DWORD state_id)
@@ -3225,7 +3351,7 @@ void tex_alphaop(struct wined3d_context *context, const struct wined3d_state *st
                 }
                 else if (op == WINED3D_TOP_SELECT_ARG1 && arg1 != WINED3DTA_TEXTURE)
                 {
-                    if (state->blend_state && state->blend_state->desc.enable)
+                    if (state->blend_state && state->blend_state->desc.rt[0].enable)
                     {
                         arg2 = WINED3DTA_TEXTURE;
                         op = WINED3D_TOP_MODULATE;
@@ -3234,7 +3360,7 @@ void tex_alphaop(struct wined3d_context *context, const struct wined3d_state *st
                 }
                 else if (op == WINED3D_TOP_SELECT_ARG2 && arg2 != WINED3DTA_TEXTURE)
                 {
-                    if (state->blend_state && state->blend_state->desc.enable)
+                    if (state->blend_state && state->blend_state->desc.rt[0].enable)
                     {
                         arg1 = WINED3DTA_TEXTURE;
                         op = WINED3D_TOP_MODULATE;
@@ -4499,6 +4625,8 @@ const struct wined3d_state_entry_template misc_state_template[] =
     { STATE_STREAM_OUTPUT,                                { STATE_STREAM_OUTPUT,                                state_so,           }, WINED3D_GL_VERSION_3_2          },
     { STATE_STREAM_OUTPUT,                                { STATE_STREAM_OUTPUT,                                state_so_warn,      }, WINED3D_GL_EXT_NONE             },
     { STATE_RENDER(WINED3D_RS_EDGEANTIALIAS),             { STATE_RENDER(WINED3D_RS_EDGEANTIALIAS),             state_line_antialias}, WINED3D_GL_EXT_NONE             },
+    { STATE_BLEND,                                        { STATE_BLEND,                                        blend_dbb           }, ARB_DRAW_BUFFERS_BLEND          },
+    { STATE_BLEND,                                        { STATE_BLEND,                                        blend_db2           }, EXT_DRAW_BUFFERS2               },
     { STATE_BLEND,                                        { STATE_BLEND,                                        blend               }, WINED3D_GL_EXT_NONE             },
     { STATE_BLEND_FACTOR,                                 { STATE_BLEND_FACTOR,                                 state_blend_factor  }, EXT_BLEND_COLOR                 },
     { STATE_BLEND_FACTOR,                                 { STATE_BLEND_FACTOR,                                 state_blend_factor_w}, WINED3D_GL_EXT_NONE             },
diff --git a/dlls/wined3d/utils.c b/dlls/wined3d/utils.c
index 82a4e2ca0d..54866da533 100644
--- a/dlls/wined3d/utils.c
+++ b/dlls/wined3d/utils.c
@@ -6134,7 +6134,7 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
                     }
                     else if (aop == WINED3D_TOP_SELECT_ARG1 && aarg1 != WINED3DTA_TEXTURE)
                     {
-                        if (state->blend_state && state->blend_state->desc.enable)
+                        if (state->blend_state && state->blend_state->desc.rt[0].enable)
                         {
                             aarg2 = WINED3DTA_TEXTURE;
                             aop = WINED3D_TOP_MODULATE;
@@ -6143,7 +6143,7 @@ void gen_ffp_frag_op(const struct wined3d_context *context, const struct wined3d
                     }
                     else if (aop == WINED3D_TOP_SELECT_ARG2 && aarg2 != WINED3DTA_TEXTURE)
                     {
-                        if (state->blend_state && state->blend_state->desc.enable)
+                        if (state->blend_state && state->blend_state->desc.rt[0].enable)
                         {
                             aarg1 = WINED3DTA_TEXTURE;
                             aop = WINED3D_TOP_MODULATE;
diff --git a/dlls/wined3d/wined3d_gl.h b/dlls/wined3d/wined3d_gl.h
index 2cb25a3776..6b1c99e6da 100644
--- a/dlls/wined3d/wined3d_gl.h
+++ b/dlls/wined3d/wined3d_gl.h
@@ -57,6 +57,7 @@ enum wined3d_gl_extension
     ARB_DEPTH_TEXTURE,
     ARB_DERIVATIVE_CONTROL,
     ARB_DRAW_BUFFERS,
+    ARB_DRAW_BUFFERS_BLEND,
     ARB_DRAW_ELEMENTS_BASE_VERTEX,
     ARB_DRAW_INDIRECT,
     ARB_DRAW_INSTANCED,
diff --git a/include/wine/wined3d.h b/include/wine/wined3d.h
index 9ec097ea5f..16800a8e40 100644
--- a/include/wine/wined3d.h
+++ b/include/wine/wined3d.h
@@ -1605,6 +1605,7 @@ enum wined3d_shader_type
 #define WINED3D_MAX_CONSTS_I                                    16
 #define WINED3D_MAX_VS_CONSTS_F                                 256
 #define WINED3D_MAX_PS_CONSTS_F                                 224
+#define WINED3D_MAX_RENDER_TARGETS                              8
 
 struct wined3d_display_mode
 {
@@ -2029,13 +2030,17 @@ struct wined3d_buffer_desc
 struct wined3d_blend_state_desc
 {
     BOOL alpha_to_coverage;
-    BOOL enable;
-    enum wined3d_blend src;
-    enum wined3d_blend dst;
-    enum wined3d_blend_op op;
-    enum wined3d_blend src_alpha;
-    enum wined3d_blend dst_alpha;
-    enum wined3d_blend_op op_alpha;
+    BOOL independent;
+    struct
+    {
+        BOOL enable;
+        enum wined3d_blend src;
+        enum wined3d_blend dst;
+        enum wined3d_blend_op op;
+        enum wined3d_blend src_alpha;
+        enum wined3d_blend dst_alpha;
+        enum wined3d_blend_op op_alpha;
+    } rt[WINED3D_MAX_RENDER_TARGETS];
 };
 
 struct wined3d_rasterizer_state_desc
-- 
2.25.1




More information about the wine-devel mailing list