Wine-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
March 2020
- 72 participants
- 969 discussions
Signed-off-by: Zebediah Figura <z.figura12(a)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
4
6
[RFC PATCH] winevulkan: Fill in device LUID from corresponding DXGI adapter.
by Brendan Shanks 13 Mar '20
by Brendan Shanks 13 Mar '20
13 Mar '20
---
Red Dead Redemption 2 relies on the deviceLUID returned by
vkGetPhysicalDeviceProperties2() matching up with the LUID reported by
other Windows APIs. This patch uses DXGI to enumerate adapters, and uses
the LUID of the D3D adapter matching the UUID provided through Vulkan.
The patch works, but I could see problems arising in case EnumAdapters()
was backed by Vulkan and called vkGetPhysicalDeviceProperties2() itself.
Would it be preferable to cache the UUID/LUID pairs in wine_vk_init()?
Or should DXGI not be used at all, in favor of reading these out of the
registry (with changes needed to wined3d)?
dlls/winevulkan/Makefile.in | 2 +-
dlls/winevulkan/make_vulkan | 2 +
dlls/winevulkan/vulkan.c | 89 +++++++++++++++++++++++++++++++++
dlls/winevulkan/vulkan_thunks.c | 10 +---
dlls/winevulkan/vulkan_thunks.h | 4 ++
5 files changed, 98 insertions(+), 9 deletions(-)
diff --git a/dlls/winevulkan/Makefile.in b/dlls/winevulkan/Makefile.in
index e0bca6fad7..c112581e1e 100644
--- a/dlls/winevulkan/Makefile.in
+++ b/dlls/winevulkan/Makefile.in
@@ -1,6 +1,6 @@
MODULE = winevulkan.dll
IMPORTLIB = winevulkan
-IMPORTS = user32 gdi32
+IMPORTS = dxgi user32 gdi32
C_SRCS = \
vulkan.c \
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index 3593410041..1879d640e0 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -165,6 +165,8 @@ FUNCTION_OVERRIDES = {
"vkGetPhysicalDeviceExternalFenceProperties" : {"dispatch" : False, "driver" : False, "thunk" : False},
"vkGetPhysicalDeviceExternalSemaphoreProperties" : {"dispatch" : False, "driver" : False, "thunk" : False},
"vkGetPhysicalDeviceImageFormatProperties2" : {"dispatch" : True, "driver" : False, "thunk" : True, "private_thunk" : True},
+ "vkGetPhysicalDeviceProperties2" : {"dispatch" : True, "driver" : False, "thunk" : False, "private_thunk" : True},
+ "vkGetPhysicalDeviceProperties2KHR" : {"dispatch" : True, "driver" : False, "thunk" : False, "private_thunk" : True},
# Device functions
"vkAllocateCommandBuffers" : {"dispatch" : True, "driver" : False, "thunk" : False},
diff --git a/dlls/winevulkan/vulkan.c b/dlls/winevulkan/vulkan.c
index 59472bcef8..2ef39ada79 100644
--- a/dlls/winevulkan/vulkan.c
+++ b/dlls/winevulkan/vulkan.c
@@ -19,10 +19,16 @@
#include <stdarg.h>
+#define COBJMACROS
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
+#include "initguid.h"
+#include "dxgi.h"
+#include "wine/wined3d.h"
+#include "wine/winedxgi.h"
+
#include "vulkan_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(vulkan);
@@ -1261,6 +1267,89 @@ void WINAPI wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDev
properties->externalSemaphoreFeatures = 0;
}
+static BOOL get_luid_for_device_uuid(const UUID *uuid, LUID *luid)
+{
+ UINT i = 0;
+ BOOL found = FALSE;
+ IDXGIFactory *factory = NULL;
+ IDXGIAdapter *adapter = NULL;
+
+ if (FAILED(CreateDXGIFactory(&IID_IDXGIFactory, (void **)&factory))) return FALSE;
+
+ while (!found && IDXGIFactory_EnumAdapters(factory, i, &adapter) != DXGI_ERROR_NOT_FOUND)
+ {
+ IWineDXGIAdapter *wine_adapter = NULL;
+ if (SUCCEEDED(IUnknown_QueryInterface(adapter, &IID_IWineDXGIAdapter, (void **)&wine_adapter)))
+ {
+ struct wine_dxgi_adapter_info adapter_info;
+ if (SUCCEEDED(IWineDXGIAdapter_get_adapter_info(wine_adapter, &adapter_info)))
+ {
+ if (IsEqualGUID(uuid, &adapter_info.device_uuid))
+ {
+ *luid = adapter_info.luid;
+ found = TRUE;
+ }
+ }
+
+ IWineDXGIAdapter_Release(wine_adapter);
+ }
+
+ IDXGIAdapter_Release(adapter);
+ i++;
+ }
+
+ if (factory) IDXGIFactory_Release(factory);
+ return found;
+}
+
+void WINAPI wine_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physical_device,
+ VkPhysicalDeviceProperties2 *properties)
+{
+ VkPhysicalDeviceIDProperties *idprops;
+
+ TRACE("%p, %p\n", physical_device, properties);
+ thunk_vkGetPhysicalDeviceProperties2(physical_device, properties);
+
+ if ((idprops = wine_vk_find_struct(properties, PHYSICAL_DEVICE_ID_PROPERTIES)))
+ {
+ UUID *deviceUUID = (UUID *)idprops->deviceUUID;
+ LUID *luid = (LUID *)idprops->deviceLUID;
+ if (get_luid_for_device_uuid(deviceUUID, luid))
+ {
+ idprops->deviceNodeMask = 1;
+ idprops->deviceLUIDValid = VK_TRUE;
+ }
+ else
+ {
+ WARN("Failed to find corresponding adapter LUID for device UUID %s.\n", debugstr_guid(deviceUUID));
+ }
+ }
+}
+
+void WINAPI wine_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physical_device,
+ VkPhysicalDeviceProperties2 *properties)
+{
+ VkPhysicalDeviceIDProperties *idprops;
+
+ TRACE("%p, %p\n", physical_device, properties);
+ thunk_vkGetPhysicalDeviceProperties2KHR(physical_device, properties);
+
+ if ((idprops = wine_vk_find_struct(properties, PHYSICAL_DEVICE_ID_PROPERTIES)))
+ {
+ UUID *deviceUUID = (UUID *)idprops->deviceUUID;
+ LUID *luid = (LUID *)idprops->deviceLUID;
+ if (get_luid_for_device_uuid(deviceUUID, luid))
+ {
+ idprops->deviceNodeMask = 1;
+ idprops->deviceLUIDValid = VK_TRUE;
+ }
+ else
+ {
+ WARN("Failed to find corresponding adapter LUID for device UUID %s.\n", debugstr_guid(deviceUUID));
+ }
+ }
+}
+
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved)
{
TRACE("%p, %u, %p\n", hinst, reason, reserved);
diff --git a/dlls/winevulkan/vulkan_thunks.c b/dlls/winevulkan/vulkan_thunks.c
index fecf9ab502..89878f189a 100644
--- a/dlls/winevulkan/vulkan_thunks.c
+++ b/dlls/winevulkan/vulkan_thunks.c
@@ -4268,34 +4268,28 @@ void WINAPI wine_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
#endif
}
-void WINAPI wine_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties)
+void thunk_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties)
{
#if defined(USE_STRUCT_CONVERSION)
VkPhysicalDeviceProperties2_host pProperties_host;
- TRACE("%p, %p\n", physicalDevice, pProperties);
-
convert_VkPhysicalDeviceProperties2_win_to_host(pProperties, &pProperties_host);
physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2(physicalDevice->phys_dev, &pProperties_host);
convert_VkPhysicalDeviceProperties2_host_to_win(&pProperties_host, pProperties);
#else
- TRACE("%p, %p\n", physicalDevice, pProperties);
physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2(physicalDevice->phys_dev, pProperties);
#endif
}
-static void WINAPI wine_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties)
+void thunk_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties)
{
#if defined(USE_STRUCT_CONVERSION)
VkPhysicalDeviceProperties2_host pProperties_host;
- TRACE("%p, %p\n", physicalDevice, pProperties);
-
convert_VkPhysicalDeviceProperties2_win_to_host(pProperties, &pProperties_host);
physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2KHR(physicalDevice->phys_dev, &pProperties_host);
convert_VkPhysicalDeviceProperties2_host_to_win(&pProperties_host, pProperties);
#else
- TRACE("%p, %p\n", physicalDevice, pProperties);
physicalDevice->instance->funcs.p_vkGetPhysicalDeviceProperties2KHR(physicalDevice->phys_dev, pProperties);
#endif
}
diff --git a/dlls/winevulkan/vulkan_thunks.h b/dlls/winevulkan/vulkan_thunks.h
index 01c1efb277..9896112176 100644
--- a/dlls/winevulkan/vulkan_thunks.h
+++ b/dlls/winevulkan/vulkan_thunks.h
@@ -64,11 +64,15 @@ void WINAPI wine_vkGetPhysicalDeviceExternalSemaphoreProperties(VkPhysicalDevice
void WINAPI wine_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceExternalSemaphoreInfo *pExternalSemaphoreInfo, VkExternalSemaphoreProperties *pExternalSemaphoreProperties) DECLSPEC_HIDDEN;
VkResult WINAPI wine_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties);
VkResult WINAPI wine_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) DECLSPEC_HIDDEN;
+void WINAPI wine_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties);
+void WINAPI wine_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN;
VkResult WINAPI wine_vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence);
/* Private thunks */
VkResult thunk_vkGetPhysicalDeviceImageFormatProperties2(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) DECLSPEC_HIDDEN;
VkResult thunk_vkGetPhysicalDeviceImageFormatProperties2KHR(VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo, VkImageFormatProperties2 *pImageFormatProperties) DECLSPEC_HIDDEN;
+void thunk_vkGetPhysicalDeviceProperties2(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN;
+void thunk_vkGetPhysicalDeviceProperties2KHR(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties2 *pProperties) DECLSPEC_HIDDEN;
typedef struct VkAcquireNextImageInfoKHR_host
{
--
2.24.1
6
11
[PATCH v2] wldap32: Add support for ldap_bind_s(LDAP_AUTH_NEGOTIATE).
by Dmitry Timoshkov 13 Mar '20
by Dmitry Timoshkov 13 Mar '20
13 Mar '20
v2: Support ANSI credentials.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
configure.ac | 1 +
dlls/wldap32/bind.c | 134 +++++++++++++++++++++++++++++----
dlls/wldap32/winldap_private.h | 2 +
dlls/wldap32/wldap32.h | 32 ++++++++
include/config.h.in | 3 +
6 files changed, 202 insertions(+), 44 deletions(-)
diff --git a/configure.ac b/configure.ac
index 7c3c6d2b67..7c2d803ef5 100644
--- a/configure.ac
+++ b/configure.ac
@@ -483,6 +483,7 @@ AC_CHECK_HEADERS(\
port.h \
pthread.h \
pwd.h \
+ sasl/sasl.h \
sched.h \
scsi/scsi.h \
scsi/scsi_ioctl.h \
diff --git a/dlls/wldap32/bind.c b/dlls/wldap32/bind.c
index 27fb286f50..0ce8a89006 100644
--- a/dlls/wldap32/bind.c
+++ b/dlls/wldap32/bind.c
@@ -25,10 +25,14 @@
#ifdef HAVE_LDAP_H
#include <ldap.h>
#endif
+#ifdef HAVE_SASL_SASL_H
+#include <sasl/sasl.h>
+#endif
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
+#include "rpc.h"
#include "winldap_private.h"
#include "wldap32.h"
@@ -156,20 +160,70 @@ ULONG CDECL ldap_bind_sA( WLDAP32_LDAP *ld, PCHAR dn, PCHAR cred, ULONG method )
if (!dnW) goto exit;
}
if (cred) {
- credW = strAtoW( cred );
- if (!credW) goto exit;
+ if (method == LDAP_AUTH_SIMPLE)
+ {
+ credW = strAtoW( cred );
+ if (!credW) goto exit;
+ }
+ else
+ credW = (WCHAR *)cred /* SEC_WINNT_AUTH_IDENTITY_A */;
}
ret = ldap_bind_sW( ld, dnW, credW, method );
exit:
strfreeW( dnW );
- strfreeW( credW );
+ if (credW != (WCHAR *)cred) strfreeW( credW );
#endif
return ret;
}
+#ifdef HAVE_SASL_SASL_H
+
+static int sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *interact )
+{
+ SEC_WINNT_AUTH_IDENTITY_A *id = defaults;
+ sasl_interact_t *sasl = interact;
+
+ TRACE( "%p,%08x,%p,%p\n", ld, flags, defaults, interact );
+
+ while (sasl->id != SASL_CB_LIST_END)
+ {
+ TRACE("sasl->id = %04lx\n", sasl->id);
+
+ if (sasl->id == SASL_CB_GETREALM)
+ {
+ sasl->result = id->Domain;
+ sasl->len = id->DomainLength;
+ }
+ else if (sasl->id == SASL_CB_USER)
+ {
+ sasl->result = id->User;
+ sasl->len = id->UserLength;
+ }
+ else if (sasl->id == SASL_CB_PASS)
+ {
+ sasl->result = id->Password;
+ sasl->len = id->PasswordLength;
+ }
+
+ sasl++;
+ }
+
+ return LDAP_SUCCESS;
+}
+
+#else
+
+static int sasl_interact( LDAP *ld, unsigned flags, void *defaults, void *interact )
+{
+ FIXME( "%p,%08x,%p,%p: stub\n", ld, flags, defaults, interact );
+ return LDAP_SUCCESS;
+}
+
+#endif /* HAVE_SASL_SASL_H */
+
/***********************************************************************
* ldap_bind_sW (WLDAP32.@)
*
@@ -197,21 +251,71 @@ ULONG CDECL ldap_bind_sW( WLDAP32_LDAP *ld, PWCHAR dn, PWCHAR cred, ULONG method
TRACE( "(%p, %s, %p, 0x%08x)\n", ld, debugstr_w(dn), cred, method );
if (!ld) return WLDAP32_LDAP_PARAM_ERROR;
- if (method != LDAP_AUTH_SIMPLE) return WLDAP32_LDAP_PARAM_ERROR;
- if (dn) {
- dnU = strWtoU( dn );
- if (!dnU) goto exit;
+ if (method == LDAP_AUTH_SIMPLE)
+ {
+ if (dn)
+ {
+ dnU = strWtoU( dn );
+ if (!dnU) goto exit;
+ }
+ if (cred)
+ {
+ credU = strWtoU( cred );
+ if (!credU) goto exit;
+
+ pwd.bv_len = strlen( credU );
+ pwd.bv_val = credU;
+ }
+
+ ret = map_error( ldap_sasl_bind_s( ld, dnU, LDAP_SASL_SIMPLE, &pwd, NULL, NULL, NULL ));
}
- if (cred) {
- credU = strWtoU( cred );
- if (!credU) goto exit;
-
- pwd.bv_len = strlen( credU );
- pwd.bv_val = credU;
+ else if (method == WLDAP32_LDAP_AUTH_NEGOTIATE)
+ {
+ SEC_WINNT_AUTH_IDENTITY_A idU;
+ SEC_WINNT_AUTH_IDENTITY_W idW;
+ SEC_WINNT_AUTH_IDENTITY_W *id = (SEC_WINNT_AUTH_IDENTITY_W *)cred;
+
+ memset( &idU, 0, sizeof(idU) );
+
+ if (id)
+ {
+ if (id->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI)
+ {
+ idW.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
+ idW.Domain = (unsigned short *)strnAtoW( (char *)id->Domain, id->DomainLength, &idW.DomainLength );
+ idW.User = (unsigned short *)strnAtoW( (char *)id->User, id->UserLength, &idW.UserLength );
+ idW.Password = (unsigned short *)strnAtoW( (char *)id->Password, id->PasswordLength, &idW.PasswordLength );
+
+ id = &idW;
+ }
+
+ idU.Domain = (unsigned char *)strnWtoU( id->Domain, id->DomainLength, &idU.DomainLength );
+ idU.User = (unsigned char *)strnWtoU( id->User, id->UserLength, &idU.UserLength );
+ idU.Password = (unsigned char *)strnWtoU( id->Password, id->PasswordLength, &idU.PasswordLength );
+ }
+
+ ret = map_error( ldap_sasl_interactive_bind_s( ld,
+ NULL /* server will ignore DN anyway */,
+ NULL /* query supportedSASLMechanisms */,
+ NULL, NULL, LDAP_SASL_QUIET, sasl_interact, &idU ));
+
+ if (id && (id->Flags & SEC_WINNT_AUTH_IDENTITY_ANSI))
+ {
+ strfreeW( (WCHAR *)idW.Domain );
+ strfreeW( (WCHAR *)idW.User );
+ strfreeW( (WCHAR *)idW.Password );
+ }
+
+ strfreeU( (char *)idU.Domain );
+ strfreeU( (char *)idU.User );
+ strfreeU( (char *)idU.Password );
+ }
+ else
+ {
+ FIXME( "method %#x not supported\n", method );
+ return WLDAP32_LDAP_PARAM_ERROR;
}
-
- ret = map_error( ldap_sasl_bind_s( ld, dnU, LDAP_SASL_SIMPLE, &pwd, NULL, NULL, NULL ));
exit:
strfreeU( dnU );
diff --git a/dlls/wldap32/winldap_private.h b/dlls/wldap32/winldap_private.h
index 74223029b7..df257dafec 100644
--- a/dlls/wldap32/winldap_private.h
+++ b/dlls/wldap32/winldap_private.h
@@ -101,6 +101,8 @@ typedef struct berelement
#define WLDAP32_LDAP_OPT_SECURITY_CONTEXT 0x99
#define WLDAP32_LDAP_OPT_ROOTDSE_CACHE 0x9a
+#define WLDAP32_LDAP_AUTH_NEGOTIATE 0x486
+
typedef struct ldap
{
struct
diff --git a/dlls/wldap32/wldap32.h b/dlls/wldap32/wldap32.h
index 1d4052002a..c329a5b76b 100644
--- a/dlls/wldap32/wldap32.h
+++ b/dlls/wldap32/wldap32.h
@@ -93,6 +93,38 @@ static inline LPWSTR strUtoW( char *str )
return ret;
}
+static inline LPWSTR strnAtoW( LPCSTR str, DWORD inlen, DWORD *outlen )
+{
+ LPWSTR ret = NULL;
+ *outlen = 0;
+ if (str)
+ {
+ DWORD len = MultiByteToWideChar( CP_ACP, 0, str, inlen, NULL, 0 );
+ if ((ret = heap_alloc( len * sizeof(WCHAR) )))
+ {
+ MultiByteToWideChar( CP_ACP, 0, str, inlen, ret, len );
+ *outlen = len;
+ }
+ }
+ return ret;
+}
+
+static inline char *strnWtoU( LPCWSTR str, DWORD inlen, DWORD *outlen )
+{
+ LPSTR ret = NULL;
+ *outlen = 0;
+ if (str)
+ {
+ DWORD len = WideCharToMultiByte( CP_UTF8, 0, str, inlen, NULL, 0, NULL, NULL );
+ if ((ret = heap_alloc( len )))
+ {
+ WideCharToMultiByte( CP_UTF8, 0, str, inlen, ret, len, NULL, NULL );
+ *outlen = len;
+ }
+ }
+ return ret;
+}
+
static inline void strfreeA( LPSTR str )
{
heap_free( str );
diff --git a/include/config.h.in b/include/config.h.in
index de434d6ed2..e48e398ca8 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -776,6 +776,9 @@
/* Define to 1 if you have the `roundf' function. */
#undef HAVE_ROUNDF
+/* Define to 1 if you have the <sasl/sasl.h> header file. */
+#undef HAVE_SASL_SASL_H
+
/* Define to 1 if you have the <sched.h> header file. */
#undef HAVE_SCHED_H
--
2.20.1
1
0
Signed-off-by: Zebediah Figura <z.figura12(a)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
3
4
v2: If secure open object fails fallback to simple bind as per MSDN.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/activeds/activeds_main.c | 10 +++++++---
dlls/adsldp/tests/ldap.c | 5 +++++
2 files changed, 12 insertions(+), 3 deletions(-)
diff --git a/dlls/activeds/activeds_main.c b/dlls/activeds/activeds_main.c
index 564acab93e..6a825f0913 100644
--- a/dlls/activeds/activeds_main.c
+++ b/dlls/activeds/activeds_main.c
@@ -61,10 +61,14 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
/*****************************************************
* ADsGetObject [ACTIVEDS.3]
*/
-HRESULT WINAPI ADsGetObject(LPCWSTR lpszPathName, REFIID riid, VOID** ppObject)
+HRESULT WINAPI ADsGetObject(LPCWSTR path, REFIID riid, void **obj)
{
- FIXME("(%s)->(%s,%p)!stub\n",debugstr_w(lpszPathName), debugstr_guid(riid), ppObject);
- return E_NOTIMPL;
+ HRESULT hr;
+
+ hr = ADsOpenObject(path, NULL, NULL, ADS_SECURE_AUTHENTICATION, riid, obj);
+ if (hr != S_OK)
+ hr = ADsOpenObject(path, NULL, NULL, 0, riid, obj);
+ return hr;
}
/*****************************************************
diff --git a/dlls/adsldp/tests/ldap.c b/dlls/adsldp/tests/ldap.c
index e0e562e8bf..28e41e4d95 100644
--- a/dlls/adsldp/tests/ldap.c
+++ b/dlls/adsldp/tests/ldap.c
@@ -104,6 +104,11 @@ static void test_LDAP(void)
if (hr == S_OK)
IADs_Release(ads);
+ hr = ADsGetObject(path, &IID_IDispatch, (void **)&disp);
+ ok(hr == test[i].hr || hr == test[i].hr_ads_get, "%d: got %#x, expected %#x\n", i, hr, test[i].hr);
+ if (hr == S_OK)
+ IDispatch_Release(disp);
+
SysFreeString(path);
SysFreeString(user);
SysFreeString(password);
--
2.20.1
1
0
13 Mar '20
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/activeds/activeds_main.c | 6 +++---
dlls/adsldp/tests/Makefile.in | 2 +-
dlls/adsldp/tests/ldap.c | 6 ++++++
3 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/dlls/activeds/activeds_main.c b/dlls/activeds/activeds_main.c
index c997cab912..564acab93e 100644
--- a/dlls/activeds/activeds_main.c
+++ b/dlls/activeds/activeds_main.c
@@ -127,10 +127,10 @@ HRESULT WINAPI ADsOpenObject(LPCWSTR path, LPCWSTR user, LPCWSTR password, DWORD
if (!path || !riid || !obj)
return E_INVALIDARG;
- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\ADs\\Providers", 0, KEY_READ, &hkey))
- return E_ADS_BAD_PATHNAME;
+ hr = E_FAIL;
- hr = E_ADS_BAD_PATHNAME;
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Microsoft\\ADs\\Providers", 0, KEY_READ, &hkey))
+ return hr;
for (;;)
{
diff --git a/dlls/adsldp/tests/Makefile.in b/dlls/adsldp/tests/Makefile.in
index 52141139d5..26b937aa68 100644
--- a/dlls/adsldp/tests/Makefile.in
+++ b/dlls/adsldp/tests/Makefile.in
@@ -1,5 +1,5 @@
TESTDLL = adsldp.dll
-IMPORTS = ole32 oleaut32 secur32 advapi32 uuid
+IMPORTS = ole32 oleaut32 secur32 advapi32 activeds uuid
C_SRCS = \
ldap.c \
diff --git a/dlls/adsldp/tests/ldap.c b/dlls/adsldp/tests/ldap.c
index 6f8c00aa89..e0e562e8bf 100644
--- a/dlls/adsldp/tests/ldap.c
+++ b/dlls/adsldp/tests/ldap.c
@@ -28,6 +28,7 @@
#include "objbase.h"
#include "iads.h"
#include "adserr.h"
+#include "adshlp.h"
#include "wine/test.h"
@@ -98,6 +99,11 @@ static void test_LDAP(void)
if (hr == S_OK)
IDispatch_Release(disp);
+ hr = ADsOpenObject(path, user, password, test[i].flags, &IID_IADs, (void **)&ads);
+ ok(hr == test[i].hr || hr == test[i].hr_ads_get, "%d: got %#x, expected %#x\n", i, hr, test[i].hr);
+ if (hr == S_OK)
+ IADs_Release(ads);
+
SysFreeString(path);
SysFreeString(user);
SysFreeString(password);
--
2.20.1
1
0
13 Mar '20
v2: Fix test failures.
v3: actually fail on ADS_SECURE_AUTHENTICATION.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/adsldp/Makefile.in | 3 +-
dlls/adsldp/adsldp.c | 29 ++++++++++--
dlls/adsldp/adsldp_private.h | 24 ++++++++++
dlls/adsldp/ldap.c | 91 ++++++++++++++++++++++++++++++++++++
dlls/adsldp/tests/ldap.c | 31 +++++++++---
5 files changed, 166 insertions(+), 12 deletions(-)
create mode 100644 dlls/adsldp/adsldp_private.h
create mode 100644 dlls/adsldp/ldap.c
diff --git a/dlls/adsldp/Makefile.in b/dlls/adsldp/Makefile.in
index e9c87e68f1..3e5a5e310e 100644
--- a/dlls/adsldp/Makefile.in
+++ b/dlls/adsldp/Makefile.in
@@ -5,7 +5,8 @@ DELAYIMPORTS = netapi32 wldap32
EXTRADLLFLAGS = -mno-cygwin
C_SRCS = \
- adsldp.c
+ adsldp.c \
+ ldap.c
IDL_SRCS = \
adsldp.idl
diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c
index 30bd1672f6..bc4e9780b0 100644
--- a/dlls/adsldp/adsldp.c
+++ b/dlls/adsldp/adsldp.c
@@ -36,6 +36,8 @@
#include "lmapibuf.h"
#include "winldap.h"
+#include "adsldp_private.h"
+
#include "wine/heap.h"
#include "wine/debug.h"
@@ -700,7 +702,7 @@ static HRESULT parse_path(WCHAR *path, BSTR *host, ULONG *port, BSTR *object)
}
static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, BSTR user, BSTR password,
- LONG reserved, IDispatch **obj)
+ LONG flags, IDispatch **obj)
{
BSTR host, object;
ULONG port;
@@ -709,7 +711,7 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B
HRESULT hr;
ULONG err;
- FIXME("%p,%s,%s,%08x,%p: semi-stub\n", iface, debugstr_w(path), debugstr_w(user), reserved, obj);
+ FIXME("%p,%s,%s,%p,%08x,%p: semi-stub\n", iface, debugstr_w(path), debugstr_w(user), password, flags, obj);
hr = parse_path(path, &host, &port, &object);
if (hr != S_OK) return hr;
@@ -760,7 +762,7 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B
err = ldap_set_optionW(ld, LDAP_OPT_PROTOCOL_VERSION, &version);
if (err != LDAP_SUCCESS)
{
- hr = HRESULT_FROM_WIN32(err);
+ hr = HRESULT_FROM_WIN32(map_ldap_error(err));
ldap_unbind(ld);
goto fail;
}
@@ -768,10 +770,29 @@ static HRESULT WINAPI openobj_OpenDSObject(IADsOpenDSObject *iface, BSTR path, B
err = ldap_connect(ld, NULL);
if (err != LDAP_SUCCESS)
{
- hr = HRESULT_FROM_WIN32(err);
+ hr = HRESULT_FROM_WIN32(map_ldap_error(err));
+ ldap_unbind(ld);
+ goto fail;
+ }
+
+ if (flags & ADS_SECURE_AUTHENTICATION)
+ {
+ FIXME("ADS_SECURE_AUTHENTICATION is not supported\n");
+ hr = ERROR_DS_AUTH_METHOD_NOT_SUPPORTED;
ldap_unbind(ld);
goto fail;
}
+ else
+ {
+ err = ldap_simple_bind_sW(ld, user, password);
+ if (err != LDAP_SUCCESS)
+ {
+ TRACE("ldap_simple_bind_sW error %#x\n", err);
+ hr = HRESULT_FROM_WIN32(map_ldap_error(err));
+ ldap_unbind(ld);
+ goto fail;
+ }
+ }
}
hr = LDAPNamespace_create(&IID_IADs, (void **)&ads);
diff --git a/dlls/adsldp/adsldp_private.h b/dlls/adsldp/adsldp_private.h
new file mode 100644
index 0000000000..8748d0496d
--- /dev/null
+++ b/dlls/adsldp/adsldp_private.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2020 Dmitry Timoshkov
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _ADSLDP_PRIVATE_H
+#define _ADSLDP_PRIVATE_H
+
+DWORD map_ldap_error(DWORD) DECLSPEC_HIDDEN;
+
+#endif
diff --git a/dlls/adsldp/ldap.c b/dlls/adsldp/ldap.c
new file mode 100644
index 0000000000..c23f46267e
--- /dev/null
+++ b/dlls/adsldp/ldap.c
@@ -0,0 +1,91 @@
+/*
+ * Copyright 2020 Dmitry Timoshkov
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include <stdarg.h>
+
+#include "windef.h"
+#include "winbase.h"
+#include "winerror.h"
+#include "winldap.h"
+
+DWORD map_ldap_error(DWORD err)
+{
+ switch (err)
+ {
+ case LDAP_SUCCESS: return ERROR_SUCCESS;
+ case LDAP_OPERATIONS_ERROR: return ERROR_DS_OPERATIONS_ERROR;
+ case LDAP_PROTOCOL_ERROR: return ERROR_DS_PROTOCOL_ERROR;
+ case LDAP_TIMELIMIT_EXCEEDED: return ERROR_DS_TIMELIMIT_EXCEEDED;
+ case LDAP_SIZELIMIT_EXCEEDED: return ERROR_DS_SIZELIMIT_EXCEEDED;
+ case LDAP_COMPARE_FALSE: return ERROR_DS_COMPARE_FALSE;
+ case LDAP_COMPARE_TRUE: return ERROR_DS_COMPARE_TRUE;
+ case LDAP_AUTH_METHOD_NOT_SUPPORTED: return ERROR_DS_AUTH_METHOD_NOT_SUPPORTED;
+ case LDAP_STRONG_AUTH_REQUIRED: return ERROR_DS_STRONG_AUTH_REQUIRED;
+ case LDAP_REFERRAL_V2: return ERROR_DS_REFERRAL;
+ case LDAP_REFERRAL: return ERROR_DS_REFERRAL;
+ case LDAP_ADMIN_LIMIT_EXCEEDED: return ERROR_DS_ADMIN_LIMIT_EXCEEDED;
+ case LDAP_UNAVAILABLE_CRIT_EXTENSION: return ERROR_DS_UNAVAILABLE_CRIT_EXTENSION;
+ case LDAP_CONFIDENTIALITY_REQUIRED: return ERROR_DS_CONFIDENTIALITY_REQUIRED;
+ case LDAP_NO_SUCH_ATTRIBUTE: return ERROR_DS_NO_ATTRIBUTE_OR_VALUE;
+ case LDAP_UNDEFINED_TYPE: return ERROR_DS_ATTRIBUTE_TYPE_UNDEFINED;
+ case LDAP_INAPPROPRIATE_MATCHING: return ERROR_DS_INAPPROPRIATE_MATCHING;
+ case LDAP_CONSTRAINT_VIOLATION: return ERROR_DS_CONSTRAINT_VIOLATION;
+ case LDAP_ATTRIBUTE_OR_VALUE_EXISTS: return ERROR_DS_ATTRIBUTE_OR_VALUE_EXISTS;
+ case LDAP_INVALID_SYNTAX: return ERROR_DS_INVALID_ATTRIBUTE_SYNTAX;
+ case LDAP_NO_SUCH_OBJECT: return ERROR_DS_NO_SUCH_OBJECT;
+ case LDAP_ALIAS_PROBLEM: return ERROR_DS_ALIAS_PROBLEM;
+ case LDAP_INVALID_DN_SYNTAX: return ERROR_DS_INVALID_DN_SYNTAX;
+ case LDAP_IS_LEAF: return ERROR_DS_IS_LEAF;
+ case LDAP_ALIAS_DEREF_PROBLEM: return ERROR_DS_ALIAS_DEREF_PROBLEM;
+ case LDAP_INAPPROPRIATE_AUTH: return ERROR_DS_INAPPROPRIATE_AUTH;
+ case LDAP_INVALID_CREDENTIALS: return ERROR_DS_SEC_DESC_INVALID;
+ case LDAP_INSUFFICIENT_RIGHTS: return ERROR_DS_INSUFF_ACCESS_RIGHTS;
+ case LDAP_BUSY: return ERROR_DS_BUSY;
+ case LDAP_UNAVAILABLE: return ERROR_DS_UNAVAILABLE;
+ case LDAP_UNWILLING_TO_PERFORM: return ERROR_DS_UNWILLING_TO_PERFORM;
+ case LDAP_LOOP_DETECT: return ERROR_DS_LOOP_DETECT;
+ case LDAP_SORT_CONTROL_MISSING: return ERROR_DS_SORT_CONTROL_MISSING;
+ case LDAP_OFFSET_RANGE_ERROR: return ERROR_DS_OFFSET_RANGE_ERROR;
+ case LDAP_NAMING_VIOLATION: return ERROR_DS_NAMING_VIOLATION;
+ case LDAP_OBJECT_CLASS_VIOLATION: return ERROR_DS_OBJ_CLASS_VIOLATION;
+ case LDAP_NOT_ALLOWED_ON_NONLEAF: return ERROR_DS_CANT_ON_NON_LEAF;
+ case LDAP_NOT_ALLOWED_ON_RDN: return ERROR_DS_CANT_ON_RDN;
+ case LDAP_ALREADY_EXISTS: return ERROR_ALREADY_EXISTS;
+ case LDAP_NO_OBJECT_CLASS_MODS: return ERROR_DS_CANT_MOD_OBJ_CLASS;
+ case LDAP_RESULTS_TOO_LARGE: return ERROR_DS_OBJECT_RESULTS_TOO_LARGE;
+ case LDAP_AFFECTS_MULTIPLE_DSAS: return ERROR_DS_AFFECTS_MULTIPLE_DSAS;
+ case LDAP_SERVER_DOWN: return ERROR_DS_SERVER_DOWN;
+ case LDAP_LOCAL_ERROR: return ERROR_DS_LOCAL_ERROR;
+ case LDAP_ENCODING_ERROR: return ERROR_DS_ENCODING_ERROR;
+ case LDAP_DECODING_ERROR: return ERROR_DS_DECODING_ERROR;
+ case LDAP_TIMEOUT: return ERROR_TIMEOUT;
+ case LDAP_AUTH_UNKNOWN: return ERROR_DS_AUTH_UNKNOWN;
+ case LDAP_FILTER_ERROR: return ERROR_DS_FILTER_UNKNOWN;
+ case LDAP_USER_CANCELLED: return ERROR_CANCELLED;
+ case LDAP_PARAM_ERROR: return ERROR_DS_PARAM_ERROR;
+ case LDAP_NO_MEMORY: return ERROR_NOT_ENOUGH_MEMORY;
+ case LDAP_CONNECT_ERROR: return ERROR_CONNECTION_UNAVAIL;
+ case LDAP_NOT_SUPPORTED: return ERROR_DS_NOT_SUPPORTED;
+ case LDAP_CONTROL_NOT_FOUND: return ERROR_DS_CONTROL_NOT_FOUND;
+ case LDAP_NO_RESULTS_RETURNED: return ERROR_DS_NO_RESULTS_RETURNED;
+ case LDAP_MORE_RESULTS_TO_RETURN: return ERROR_MORE_DATA;
+ case LDAP_CLIENT_LOOP: return ERROR_DS_CLIENT_LOOP;
+ case LDAP_REFERRAL_LIMIT_EXCEEDED: return ERROR_DS_REFERRAL_LIMIT_EXCEEDED;
+ default: return err;
+ }
+}
diff --git a/dlls/adsldp/tests/ldap.c b/dlls/adsldp/tests/ldap.c
index 0ecba26817..6f8c00aa89 100644
--- a/dlls/adsldp/tests/ldap.c
+++ b/dlls/adsldp/tests/ldap.c
@@ -40,6 +40,8 @@ static const struct
{
const WCHAR *path;
HRESULT hr, hr_ads_open, hr_ads_get;
+ const WCHAR *user, *password;
+ LONG flags;
} test[] =
{
{ L"invalid", MK_E_SYNTAX, E_ADS_BAD_PATHNAME, E_FAIL },
@@ -55,6 +57,9 @@ static const struct
{ L"LDAP://ldap.forumsys.com/rootDSE", S_OK },
{ L"LDAP://ldap.forumsys.com/rootDSE/", E_ADS_BAD_PATHNAME },
{ L"LDAP://ldap.forumsys.com/rootDSE/invalid", E_ADS_BAD_PATHNAME },
+ { L"LDAP://ldap.forumsys.com/rootDSE", S_OK, S_OK, S_OK, NULL, NULL, 0 },
+ { L"LDAP://ldap.forumsys.com/rootDSE", S_OK, S_OK, S_OK, L"CN=read-only-admin,DC=example,DC=com", L"password", 0 },
+
/*{ L"LDAP://invalid", __HRESULT_FROM_WIN32(ERROR_DS_INVALID_DN_SYNTAX) }, takes way too much time */
};
@@ -65,7 +70,8 @@ static void test_LDAP(void)
IADs *ads;
IADsOpenDSObject *ads_open;
IDispatch *disp;
- BSTR path;
+ BSTR path, user, password;
+ int i;
hr = CoCreateInstance(&CLSID_LDAPNamespace, 0, CLSCTX_INPROC_SERVER, &IID_IADs, (void **)&ads);
ok(hr == S_OK, "got %#x\n", hr);
@@ -80,14 +86,25 @@ static void test_LDAP(void)
hr = IUnknown_QueryInterface(unk, &IID_IADsOpenDSObject, (void **)&ads_open);
ok(hr == S_OK, "got %#x\n", hr);
- IADsOpenDSObject_Release(ads_open);
- path = SysAllocString(L"LDAP:");
- hr = IADsOpenDSObject_OpenDSObject(ads_open, path, NULL, NULL, ADS_SECURE_AUTHENTICATION, &disp);
- SysFreeString(path);
- ok(hr == S_OK, "got %#x\n", hr);
- IDispatch_Release(disp);
+ for (i = 0; i < ARRAY_SIZE(test); i++)
+ {
+ path = SysAllocString(test[i].path);
+ user = test[i].user ? SysAllocString(test[i].user) : NULL;
+ password = test[i].password ? SysAllocString(test[i].password) : NULL;
+ hr = IADsOpenDSObject_OpenDSObject(ads_open, path, user, password, test[i].flags, &disp);
+ ok(hr == test[i].hr || hr == test[i].hr_ads_open, "%d: got %#x, expected %#x\n", i, hr, test[i].hr);
+ if (hr == S_OK)
+ IDispatch_Release(disp);
+
+ SysFreeString(path);
+ SysFreeString(user);
+ SysFreeString(password);
+ }
+
+
+ IADsOpenDSObject_Release(ads_open);
IUnknown_Release(unk);
}
--
2.20.1
1
0
[PATCH 1/4] adsldp: If secure open object fails fallback to simple bind.
by Dmitry Timoshkov 13 Mar '20
by Dmitry Timoshkov 13 Mar '20
13 Mar '20
This matches ADsGetObject() behaviour described in MSDN.
Signed-off-by: Dmitry Timoshkov <dmitry(a)baikal.ru>
---
dlls/adsldp/adsldp.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/dlls/adsldp/adsldp.c b/dlls/adsldp/adsldp.c
index acebf717aa..30bd1672f6 100644
--- a/dlls/adsldp/adsldp.c
+++ b/dlls/adsldp/adsldp.c
@@ -111,6 +111,8 @@ static HRESULT WINAPI ldap_ParseDisplayName(IParseDisplayName *iface, IBindCtx *
if (hr != S_OK) return hr;
hr = IADsOpenDSObject_OpenDSObject(ads_open, name, NULL, NULL, ADS_SECURE_AUTHENTICATION, &disp);
+ if (hr != S_OK)
+ hr = IADsOpenDSObject_OpenDSObject(ads_open, name, NULL, NULL, 0, &disp);
if (hr == S_OK)
{
hr = CreatePointerMoniker((IUnknown *)disp, mk);
--
2.20.1
1
0
13 Mar '20
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/d3dcompiler_43/tests/hlsl_d3d9.c | 112 ++++++++++++++++++++++++++
1 file changed, 112 insertions(+)
diff --git a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
index 7f391833f39..0e50084fb91 100644
--- a/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
+++ b/dlls/d3dcompiler_43/tests/hlsl_d3d9.c
@@ -730,6 +730,117 @@ static void test_array_dimensions(void)
release_test_context(&test_context);
}
+static void check_constant_desc(const char *prefix, const D3DXCONSTANT_DESC *desc, const D3DXCONSTANT_DESC *expect)
+{
+ ok(!strcmp(desc->Name, expect->Name), "%s: got Name %s.\n", prefix, debugstr_a(desc->Name));
+ ok(desc->RegisterSet == expect->RegisterSet, "%s: got RegisterSet %#x.\n", prefix, desc->RegisterSet);
+ ok(desc->RegisterCount == expect->RegisterCount, "%s: got RegisterCount %u.\n", prefix, desc->RegisterCount);
+ ok(desc->Class == expect->Class, "%s: got Class %#x.\n", prefix, desc->Class);
+ ok(desc->Type == expect->Type, "%s: got Type %#x.\n", prefix, desc->Type);
+ ok(desc->Rows == expect->Rows, "%s: got Rows %u.\n", prefix, desc->Rows);
+ ok(desc->Columns == expect->Columns, "%s: got Columns %u.\n", prefix, desc->Columns);
+ ok(desc->Elements == expect->Elements, "%s: got Elements %u.\n", prefix, desc->Elements);
+ ok(desc->StructMembers == expect->StructMembers, "%s: got StructMembers %u.\n", prefix, desc->StructMembers);
+ ok(desc->Bytes == expect->Bytes, "%s: got Bytes %u.\n", prefix, desc->Bytes);
+ ok(!desc->DefaultValue, "%s: got DefaultValue %p.\n", prefix, desc->DefaultValue);
+}
+
+static void test_constant_table(void)
+{
+ static const char *source =
+ "uniform float4 a;\n"
+ "uniform float b;\n"
+ "uniform float unused;\n"
+ "uniform float3x1 c;\n"
+ "uniform row_major float3x1 d;\n"
+ "uniform uint e;\n"
+ "uniform struct\n"
+ "{\n"
+ " float2x2 a;\n"
+ " float b;\n"
+ " float c;\n"
+ "} f;\n"
+ "uniform float g[5];\n"
+ "float4 main(uniform float4 h) : COLOR\n"
+ "{\n"
+ " return a + b + c._31 + d._31 + f.c + g[e] + h;\n"
+ "}";
+
+ D3DXCONSTANTTABLE_DESC table_desc;
+ ID3DXConstantTable *constants;
+ D3DXHANDLE handle, field;
+ D3DXCONSTANT_DESC desc;
+ ID3D10Blob *ps_code;
+ unsigned int i, j;
+ HRESULT hr;
+ UINT count;
+
+ static const D3DXCONSTANT_DESC expect_constants[] =
+ {
+ {"$h", D3DXRS_FLOAT4, 0, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 1, 0, 16},
+ {"a", D3DXRS_FLOAT4, 0, 1, D3DXPC_VECTOR, D3DXPT_FLOAT, 1, 4, 1, 0, 16},
+ {"b", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4},
+ {"c", D3DXRS_FLOAT4, 0, 1, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 3, 1, 1, 0, 12},
+ {"d", D3DXRS_FLOAT4, 0, 3, D3DXPC_MATRIX_ROWS, D3DXPT_FLOAT, 3, 1, 1, 0, 12},
+ {"e", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_INT, 1, 1, 1, 0, 4},
+ {"f", D3DXRS_FLOAT4, 0, 4, D3DXPC_STRUCT, D3DXPT_VOID, 1, 6, 1, 3, 24},
+ {"g", D3DXRS_FLOAT4, 0, 5, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 5, 0, 20},
+ };
+
+ static const D3DXCONSTANT_DESC expect_fields[] =
+ {
+ {"a", D3DXRS_FLOAT4, 0, 2, D3DXPC_MATRIX_COLUMNS, D3DXPT_FLOAT, 2, 2, 1, 0, 16},
+ {"b", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4},
+ {"c", D3DXRS_FLOAT4, 0, 1, D3DXPC_SCALAR, D3DXPT_FLOAT, 1, 1, 1, 0, 4},
+ };
+
+ todo_wine ps_code = compile_shader(source, "ps_2_0");
+ if (!ps_code)
+ return;
+
+ hr = pD3DXGetShaderConstantTable(ID3D10Blob_GetBufferPointer(ps_code), &constants);
+ ok(hr == D3D_OK, "Got hr %#x.\n", hr);
+
+ hr = ID3DXConstantTable_GetDesc(constants, &table_desc);
+ ok(hr == D3D_OK, "Got hr %#x.\n", hr);
+ ok(table_desc.Version == D3DPS_VERSION(2, 0), "Got Version %#x.\n", table_desc.Version);
+ ok(table_desc.Constants == 8, "Got %u constants.\n", table_desc.Constants);
+
+ for (i = 0; i < table_desc.Constants; ++i)
+ {
+ char prefix[30];
+
+ handle = ID3DXConstantTable_GetConstant(constants, NULL, i);
+ ok(!!handle, "Failed to get constant.\n");
+ memset(&desc, 0xcc, sizeof(desc));
+ count = 1;
+ hr = ID3DXConstantTable_GetConstantDesc(constants, handle, &desc, &count);
+ ok(hr == D3D_OK, "Got hr %#x.\n", hr);
+ ok(count == 1, "Got count %u.\n", count);
+ sprintf(prefix, "Test %u", i);
+ check_constant_desc(prefix, &desc, &expect_constants[i]);
+
+ if (!strcmp(desc.Name, "f"))
+ {
+ for (j = 0; j < ARRAY_SIZE(expect_fields); ++j)
+ {
+ field = ID3DXConstantTable_GetConstant(constants, handle, j);
+ ok(!!field, "Failed to get constant.\n");
+ memset(&desc, 0xcc, sizeof(desc));
+ count = 1;
+ hr = ID3DXConstantTable_GetConstantDesc(constants, field, &desc, &count);
+ ok(hr == D3D_OK, "Got hr %#x.\n", hr);
+ ok(count == 1, "Got count %u.\n", count);
+ sprintf(prefix, "Test %u, %u", i, j);
+ check_constant_desc(prefix, &desc, &expect_fields[j]);
+ }
+ }
+ }
+
+ ID3DXConstantTable_Release(constants);
+ ID3D10Blob_Release(ps_code);
+}
+
static void test_fail(void)
{
static const char *tests[] =
@@ -874,5 +985,6 @@ START_TEST(hlsl_d3d9)
test_comma();
test_return();
test_array_dimensions();
+ test_constant_table();
test_fail();
}
--
2.25.1
2
9
[PATCH 1/7] quartz/tests: Add a test for aggregation on the seeking passthrough object.
by Zebediah Figura 13 Mar '20
by Zebediah Figura 13 Mar '20
13 Mar '20
Signed-off-by: Zebediah Figura <zfigura(a)codeweavers.com>
---
dlls/quartz/tests/Makefile.in | 1 +
dlls/quartz/tests/passthrough.c | 133 ++++++++++++++++++++++++++++++++
2 files changed, 134 insertions(+)
create mode 100644 dlls/quartz/tests/passthrough.c
diff --git a/dlls/quartz/tests/Makefile.in b/dlls/quartz/tests/Makefile.in
index fe1a45e8ec5..46b3728ab82 100644
--- a/dlls/quartz/tests/Makefile.in
+++ b/dlls/quartz/tests/Makefile.in
@@ -11,6 +11,7 @@ C_SRCS = \
filtermapper.c \
memallocator.c \
mpegsplit.c \
+ passthrough.c \
systemclock.c \
videorenderer.c \
vmr7.c \
diff --git a/dlls/quartz/tests/passthrough.c b/dlls/quartz/tests/passthrough.c
new file mode 100644
index 00000000000..6042bc7f5ab
--- /dev/null
+++ b/dlls/quartz/tests/passthrough.c
@@ -0,0 +1,133 @@
+/*
+ * Seeking passthrough unit tests
+ *
+ * Copyright 2020 Zebediah Figura for CodeWeavers
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#define COBJMACROS
+#include "dshow.h"
+#include "wine/test.h"
+
+static ULONG get_refcount(void *iface)
+{
+ IUnknown *unknown = iface;
+ IUnknown_AddRef(unknown);
+ return IUnknown_Release(unknown);
+}
+
+static const GUID test_iid = {0x33333333};
+static LONG outer_ref = 1;
+
+static HRESULT WINAPI outer_QueryInterface(IUnknown *iface, REFIID iid, void **out)
+{
+ if (IsEqualGUID(iid, &IID_IUnknown)
+ || IsEqualGUID(iid, &IID_ISeekingPassThru)
+ || IsEqualGUID(iid, &test_iid))
+ {
+ *out = (IUnknown *)0xdeadbeef;
+ return S_OK;
+ }
+ ok(0, "unexpected call %s\n", wine_dbgstr_guid(iid));
+ return E_NOINTERFACE;
+}
+
+static ULONG WINAPI outer_AddRef(IUnknown *iface)
+{
+ return InterlockedIncrement(&outer_ref);
+}
+
+static ULONG WINAPI outer_Release(IUnknown *iface)
+{
+ return InterlockedDecrement(&outer_ref);
+}
+
+static const IUnknownVtbl outer_vtbl =
+{
+ outer_QueryInterface,
+ outer_AddRef,
+ outer_Release,
+};
+
+static IUnknown test_outer = {&outer_vtbl};
+
+static void test_aggregation(void)
+{
+ ISeekingPassThru *passthrough, *passthrough2;
+ IUnknown *unk, *unk2;
+ HRESULT hr;
+ ULONG ref;
+
+ passthrough = (ISeekingPassThru *)0xdeadbeef;
+ hr = CoCreateInstance(&CLSID_SeekingPassThru, &test_outer, CLSCTX_INPROC_SERVER,
+ &IID_ISeekingPassThru, (void **)&passthrough);
+ ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
+ ok(!passthrough, "Got interface %p.\n", passthrough);
+
+ hr = CoCreateInstance(&CLSID_SeekingPassThru, &test_outer, CLSCTX_INPROC_SERVER,
+ &IID_IUnknown, (void **)&unk);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
+ ok(unk != &test_outer, "Returned IUnknown should not be outer IUnknown.\n");
+ ref = get_refcount(unk);
+ ok(ref == 1, "Got unexpected refcount %d.\n", ref);
+
+ ref = IUnknown_AddRef(unk);
+ ok(ref == 2, "Got unexpected refcount %d.\n", ref);
+ ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
+
+ ref = IUnknown_Release(unk);
+ ok(ref == 1, "Got unexpected refcount %d.\n", ref);
+ ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
+
+ hr = IUnknown_QueryInterface(unk, &IID_IUnknown, (void **)&unk2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(unk2 == unk, "Got unexpected IUnknown %p.\n", unk2);
+ IUnknown_Release(unk2);
+
+ hr = IUnknown_QueryInterface(unk, &IID_ISeekingPassThru, (void **)&passthrough);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = ISeekingPassThru_QueryInterface(passthrough, &IID_IUnknown, (void **)&unk2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ todo_wine ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
+
+ hr = ISeekingPassThru_QueryInterface(passthrough, &IID_ISeekingPassThru, (void **)&passthrough2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(passthrough2 == (ISeekingPassThru *)0xdeadbeef, "Got unexpected ISeekingPassThru %p.\n", passthrough2);
+
+ hr = IUnknown_QueryInterface(unk, &test_iid, (void **)&unk2);
+ ok(hr == E_NOINTERFACE, "Got hr %#x.\n", hr);
+ ok(!unk2, "Got unexpected IUnknown %p.\n", unk2);
+
+ hr = ISeekingPassThru_QueryInterface(passthrough, &test_iid, (void **)&unk2);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ok(unk2 == (IUnknown *)0xdeadbeef, "Got unexpected IUnknown %p.\n", unk2);
+
+ ISeekingPassThru_Release(passthrough);
+ ref = IUnknown_Release(unk);
+ todo_wine ok(!ref, "Got unexpected refcount %d.\n", ref);
+ todo_wine ok(outer_ref == 1, "Got unexpected refcount %d.\n", outer_ref);
+}
+
+START_TEST(passthrough)
+{
+ CoInitialize(NULL);
+
+ test_aggregation();
+
+ CoUninitialize();
+}
--
2.25.1
2
9