Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 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
June 2022
- 68 participants
- 3274 messages
[PATCH v4 1/1] riched20/tests: Test for ITextDocument::Undo and ITextDocument::Redo.
by Jinoh Kang
From: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
---
dlls/riched20/tests/richole.c | 462 ++++++++++++++++++++++++++++++++++
1 file changed, 462 insertions(+)
diff --git a/dlls/riched20/tests/richole.c b/dlls/riched20/tests/richole.c
index 6a361bc3fa4..3bf88d2ba34 100644
--- a/dlls/riched20/tests/richole.c
+++ b/dlls/riched20/tests/richole.c
@@ -4955,6 +4955,466 @@ static void test_clipboard(void)
ITextRange_Release(range);
}
+static void subtest_undo(const char *dummy_text)
+{
+ static const char *text_seq[] = {
+ "",
+ "1-alpha",
+ "2-beta",
+ "3-gamma",
+ "4-delta",
+ "5-epsilon",
+ "6-zeta",
+ "7-eta",
+ };
+ static LONG seq[] = { -1, -2, -3, -1, 1, 2, 3, 1, -5, 2, -1, 3, 1, 0 };
+ LONG i = 0, stack_pos = 0;
+ IRichEditOle *reole = NULL;
+ ITextDocument *doc = NULL;
+ ITextSelection *selection;
+ char buffer[1024] = "";
+ HRESULT hr;
+ HWND hwnd;
+ LONG count = 0;
+
+ winetest_push_context("(%Iu)", dummy_text ? strlen(dummy_text) : 0);
+
+ create_interfaces(&hwnd, &reole, &doc, &selection);
+
+ for (i = -2; i <= 2; i++)
+ {
+ if (i != tomFalse && i != tomTrue)
+ {
+ hr = ITextDocument_Undo(doc, i, NULL);
+ todo_wine
+ ok(hr == (i >= 1 ? S_OK : S_FALSE), "(%ld(a)0) Undo: %#lx\n", i, hr);
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Undo(doc, i, &count);
+ todo_wine
+ ok(hr == (i >= 1 ? S_OK : S_FALSE), "(%ld(a)0) Undo: %#lx\n", i, hr);
+ todo_wine
+ ok(count == (i >= 1 ? i : 0), "(%ld(a)0) Expected %ld, got %ld\n", i, i >= 0 ? i : 0, count);
+ }
+
+ hr = ITextDocument_Redo(doc, i, NULL);
+ todo_wine
+ ok(hr == (i == 0 ? S_OK : S_FALSE), "(%ld(a)0) Redo: %#lx\n", i, hr);
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Redo(doc, i, &count);
+ todo_wine
+ ok(hr == (i == 0 ? S_OK : S_FALSE), "(%ld(a)0) Redo: %#lx\n", i, hr);
+ todo_wine
+ ok(count == 0, "(%ld(a)0) got %ld\n", i, count);
+ }
+
+ while (stack_pos < ARRAY_SIZE(text_seq) - 1)
+ {
+ stack_pos++;
+ if (dummy_text)
+ {
+ hr = ITextDocument_Undo(doc, tomSuspend, NULL);
+ todo_wine
+ ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr);
+ if (SUCCEEDED(hr))
+ {
+ SendMessageA(hwnd, EM_SETSEL, 0, 0);
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)dummy_text);
+ SendMessageA(hwnd, EM_SETSEL, 0, strlen(dummy_text));
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)"");
+ hr = ITextDocument_Undo(doc, tomResume, NULL);
+ todo_wine
+ ok(hr == S_FALSE, "(@%ld) Undo: %#lx\n", stack_pos, hr);
+ }
+ }
+ SendMessageA(hwnd, EM_SETSEL, 0, -1);
+ SendMessageA(hwnd, EM_REPLACESEL, TRUE, (LPARAM)text_seq[stack_pos]);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(seq); i++)
+ {
+ LONG expect_count;
+
+ memset(buffer, 0, sizeof(buffer));
+ SendMessageA(hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ todo_wine_if(stack_pos != ARRAY_SIZE(text_seq) - 1)
+ ok(strcmp(buffer, text_seq[stack_pos]) == 0, "Expected %s, got %s\n",
+ wine_dbgstr_a(text_seq[stack_pos]), wine_dbgstr_a(buffer));
+
+ if (!seq[i]) break;
+
+ count = 0xcccccccc;
+ expect_count = labs(stack_pos - min(max(stack_pos + seq[i], 0), (LONG)ARRAY_SIZE(seq) - 1));
+ if (seq[i] < 0)
+ {
+ hr = ITextDocument_Undo(doc, -seq[i], &count);
+ todo_wine
+ ok(hr == S_OK, "(%ld@%ld) Undo: %#lx\n", i, stack_pos, hr);
+ todo_wine
+ ok(count == expect_count, "(%ld@%ld) Expected %ld, got %ld\n", i, stack_pos, expect_count, count);
+ stack_pos -= count;
+ }
+ else
+ {
+ hr = ITextDocument_Redo(doc, seq[i], &count);
+ todo_wine
+ ok(hr == (expect_count ? S_OK : S_FALSE), "(%ld@%ld) Redo: %#lx\n", i, stack_pos, hr);
+ todo_wine
+ ok(count == expect_count, "(%ld@%ld) Expected %ld, got %ld\n", i, stack_pos, expect_count, count);
+ stack_pos += count;
+ }
+
+ if (FAILED(hr) || count <= 0) break;
+ }
+
+ release_interfaces(&hwnd, &reole, &doc, &selection);
+ winetest_pop_context();
+}
+
+static void test_undo(void)
+{
+ subtest_undo(NULL);
+ subtest_undo("dummy 12345");
+}
+
+#define ok_msg_result(h,m,w,l,r) ok_msg_result_(__LINE__,#m,h,m,w,l,r)
+static void ok_msg_result_(int line, const char *desc, HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam, LRESULT expect)
+{
+ LRESULT lresult = SendMessageA(hwnd, message, wparam, lparam);
+ ok_(__FILE__,line)(lresult == expect, "%s: Expected %Id, got %Id\n", desc, expect, lresult);
+}
+
+enum editorUndoState {
+ firstUndoState = 0,
+ undoStateActive = 0,
+ undoStateSuspended = 1,
+ undoStateDisabled = 2,
+ numUndoStates = 3,
+};
+
+enum editorUndoStateAction {
+ firstUndoAction = 0,
+ undoActionNoOp = 0,
+ undoActionEnable = 1,
+ undoActionDisable = 2,
+ undoActionSuspend = 3,
+ undoActionResume = 4,
+ numUndoActions = 5
+};
+
+enum editorUndoStateTestFlags {
+ undoTestUseWindowMessages = 0x1,
+ undoTestResetUndoLimit = 0x2,
+ undoTestDoFirstUndo = 0x4,
+ undoTestDoFirstRedo = 0x8,
+ undoTestMaxFlag = 0x10,
+};
+
+struct undo_test
+{
+ HWND hwnd;
+ ITextDocument *doc;
+ int test_flags;
+ enum editorUndoState undo_ctl_state;
+ LONG_PTR undo_limit;
+ BOOL last_undo_status;
+ BOOL last_redo_status;
+};
+
+static HRESULT perform_editor_undo_state_action(struct undo_test *inst, enum editorUndoStateAction action, LONG *count)
+{
+ HRESULT hr = S_OK;
+
+ if (count) *count = 0xcccccccc;
+
+ switch (action)
+ {
+ case undoActionNoOp:
+ if (count) *count = 0;
+ break;
+ case undoActionEnable:
+ if (inst->test_flags & undoTestResetUndoLimit)
+ {
+ LONG_PTR cur_undo_limit = SendMessageA(inst->hwnd, EM_SETUNDOLIMIT, inst->undo_limit, 0);
+ ok(cur_undo_limit == inst->undo_limit, "Expected undo limit %Id, got %Id\n",
+ inst->undo_limit, cur_undo_limit);
+ if (count) *count = 0;
+ }
+ else
+ {
+ hr = ITextDocument_Undo(inst->doc, tomTrue, count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ }
+ if (SUCCEEDED(hr) && inst->undo_ctl_state == undoStateDisabled)
+ {
+ inst->undo_ctl_state = undoStateActive;
+ inst->last_undo_status = TRUE;
+ }
+ break;
+ case undoActionDisable:
+ hr = ITextDocument_Undo(inst->doc, tomFalse, count);
+ todo_wine
+ ok(hr == S_OK, "Undo: %#lx\n", hr);
+ if (SUCCEEDED(hr))
+ {
+ inst->undo_ctl_state = undoStateDisabled;
+ inst->last_undo_status = FALSE;
+ inst->last_redo_status = FALSE;
+ }
+ break;
+ case undoActionSuspend:
+ hr = ITextDocument_Undo(inst->doc, tomSuspend, count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ if (SUCCEEDED(hr) && inst->undo_ctl_state == undoStateActive)
+ {
+ inst->undo_ctl_state = undoStateSuspended;
+ }
+ break;
+ case undoActionResume:
+ hr = ITextDocument_Undo(inst->doc, tomResume, count);
+ todo_wine
+ ok(hr == S_FALSE, "Undo: %#lx\n", hr);
+ if (SUCCEEDED(hr))
+ {
+ inst->undo_ctl_state = undoStateActive;
+ }
+ break;
+ default:
+ ok(0, "unreachable\n");
+ break;
+ }
+
+ if (count)
+ {
+ todo_wine
+ ok(*count == 0, "Got %ld\n", *count);
+ }
+ return hr;
+}
+
+static HRESULT set_editor_undo_state(struct undo_test *inst, enum editorUndoState state)
+{
+ HRESULT hr = S_OK;
+ switch (state)
+ {
+ case undoStateActive:
+ if (FAILED(hr = perform_editor_undo_state_action(inst, undoActionEnable, NULL))) break;
+ if (FAILED(hr = perform_editor_undo_state_action(inst, undoActionResume, NULL))) break;
+ break;
+ case undoStateSuspended:
+ if (FAILED(hr = perform_editor_undo_state_action(inst, undoActionEnable, NULL))) break;
+ if (FAILED(hr = perform_editor_undo_state_action(inst, undoActionSuspend, NULL))) break;
+ break;
+ case undoStateDisabled:
+ if (FAILED(hr = perform_editor_undo_state_action(inst, undoActionDisable, NULL))) break;
+ break;
+ default:
+ ok(0, "unreachable\n");
+ break;
+ }
+ ok(inst->undo_ctl_state == state, "expected state %d, got %d\n", state, inst->undo_ctl_state);
+ todo_wine
+ ok(SUCCEEDED(hr), "cannot set state to %d: %#lx\n", undoStateActive, hr);
+ return hr;
+}
+
+static BOOL perform_undo(struct undo_test *inst)
+{
+ LONG count;
+ HRESULT hr;
+ LRESULT lres;
+
+ if (inst->test_flags & undoTestUseWindowMessages)
+ {
+ lres = SendMessageA(inst->hwnd, EM_UNDO, 0, 0);
+ ok(lres == FALSE || lres == TRUE, "unexpected LRESULT %#Ix\n", lres);
+ return lres;
+ }
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Undo(inst->doc, 1, &count);
+ todo_wine
+ ok(SUCCEEDED(hr), "got hr %#lx\n", hr);
+ todo_wine
+ ok(count == (hr == S_OK), "expected count %d, got %ld\n", hr == S_OK, count);
+ return hr == S_OK && count > 0;
+}
+
+static BOOL perform_redo(struct undo_test *inst)
+{
+ LONG count;
+ HRESULT hr;
+ LRESULT lres;
+
+ if (inst->test_flags & undoTestUseWindowMessages)
+ {
+ lres = SendMessageA(inst->hwnd, EM_REDO, 0, 0);
+ ok(lres == FALSE || lres == TRUE, "unexpected LRESULT %#Ix\n", lres);
+ return lres;
+ }
+
+ count = 0xcccccccc;
+ hr = ITextDocument_Redo(inst->doc, 1, &count);
+ todo_wine
+ ok(SUCCEEDED(hr), "got hr %#lx\n", hr);
+ todo_wine
+ ok(count == (hr == S_OK), "expected count %d, got %ld\n", hr == S_OK, count);
+ return hr == S_OK && count > 0;
+}
+
+static HRESULT subtest_undo_control(struct undo_test *inst, enum editorUndoStateAction action)
+{
+ LONG undo_count, redo_count, count;
+ static const char text_foo[] = "foo";
+ static const char text_bar[] = "bar";
+ static const char *last_text, *last_text2;
+ char buffer[1024] = "";
+ BOOL result;
+ HRESULT hr;
+
+ SendMessageA(inst->hwnd, EM_EMPTYUNDOBUFFER, 0, 0);
+ undo_count = redo_count = 0;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+
+ SendMessageA(inst->hwnd, WM_SETTEXT, 0, (LPARAM)(last_text = ""));
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ last_text = "";
+ ok(strcmp(buffer, last_text) == 0,
+ "Expected %s, got %s\n", wine_dbgstr_a(""), wine_dbgstr_a(buffer));
+
+ SendMessageA(inst->hwnd, EM_SETSEL, 0, -1);
+ SendMessageA(inst->hwnd, EM_REPLACESEL, TRUE, (LPARAM)(last_text = text_foo));
+ if (inst->undo_ctl_state == undoStateActive) undo_count++, redo_count = 0;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text) == 0, "Expected %s, got %s\n", wine_dbgstr_a(text_foo), wine_dbgstr_a(buffer));
+
+ hr = perform_editor_undo_state_action(inst, action, &count);
+ ok(SUCCEEDED(hr), "failed to transition\n");
+ if (FAILED(hr)) return hr;
+ if (inst->undo_ctl_state == undoStateDisabled) undo_count = redo_count = 0;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+
+ if (inst->test_flags & undoTestDoFirstUndo)
+ {
+ BOOL expect = FALSE;
+ result = perform_undo(inst);
+ if (inst->undo_ctl_state == undoStateActive)
+ {
+ if (undo_count > 0) inst->last_undo_status = TRUE;
+ expect = inst->last_undo_status;
+ }
+ ok(result == expect, "state %d: expected %d, got %d\n", inst->undo_ctl_state, expect, result);
+ if (result && undo_count > 0) undo_count--, redo_count++, last_text = "";
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text) == 0, "Expected %s, got %s\n", wine_dbgstr_a(last_text), wine_dbgstr_a(buffer));
+ }
+
+ if (inst->test_flags & undoTestDoFirstRedo)
+ {
+ BOOL expect = FALSE;
+ result = perform_redo(inst);
+ if (inst->undo_ctl_state == undoStateActive)
+ {
+ if (redo_count > 0) inst->last_redo_status = TRUE;
+ expect = inst->last_redo_status;
+ }
+ ok(result == expect, "state %d: expected %d, got %d\n", inst->undo_ctl_state, expect, result);
+ if (result && redo_count > 0) undo_count++, redo_count--, last_text = text_foo;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text) == 0, "Expected %s, got %s\n", wine_dbgstr_a(last_text), wine_dbgstr_a(buffer));
+ }
+
+ SendMessageA(inst->hwnd, EM_SETSEL, 0, -1);
+ SendMessageA(inst->hwnd, EM_REPLACESEL, TRUE, (LPARAM)(last_text2 = text_bar));
+ if (inst->undo_ctl_state == undoStateActive) undo_count++, redo_count = 0;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text2) == 0, "Expected %s, got %s\n", wine_dbgstr_a(last_text2), wine_dbgstr_a(buffer));
+
+ result = perform_undo(inst);
+ if (undo_count > 0) inst->last_undo_status = TRUE;
+ ok((inst->undo_ctl_state == undoStateActive) == result, "state %d: got %d\n", inst->undo_ctl_state, result);
+ if (result && undo_count > 0) undo_count--, redo_count++, last_text2 = last_text;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text2) == 0, "Expected %s, got %s\n", wine_dbgstr_a(last_text2), wine_dbgstr_a(buffer));
+
+ result = perform_redo(inst);
+ if (redo_count > 0) inst->last_redo_status = TRUE;
+ ok((inst->undo_ctl_state == undoStateActive) == result, "state %d: got %d\n", inst->undo_ctl_state, result);
+ if (result && redo_count > 0) undo_count++, redo_count--, last_text2 = text_bar;
+ ok_msg_result(inst->hwnd, EM_CANUNDO, 0, 0, undo_count > 0);
+ ok_msg_result(inst->hwnd, EM_CANREDO, 0, 0, redo_count > 0);
+ SendMessageA(inst->hwnd, WM_GETTEXT, ARRAY_SIZE(buffer), (LPARAM)buffer);
+ ok(strcmp(buffer, last_text2) == 0, "Expected %s, got %s\n", wine_dbgstr_a(last_text2), wine_dbgstr_a(buffer));
+
+ return S_OK;
+}
+
+static void test_undo_control(void)
+{
+ enum editorUndoState state0;
+ enum editorUndoStateAction action0, action1;
+ IRichEditOle *reole = NULL;
+ ITextSelection *selection;
+ struct undo_test inst = { NULL };
+ HRESULT hr;
+
+ create_interfaces(&inst.hwnd, &reole, &inst.doc, &selection);
+ inst.undo_ctl_state = undoStateActive;
+ inst.last_undo_status = TRUE;
+ inst.last_redo_status = TRUE;
+ inst.undo_limit = SendMessageA(inst.hwnd, EM_SETUNDOLIMIT, 100, 0);
+ ok(inst.undo_limit >= 1, "Message EM_SETUNDOLIMIT returned %#Ix\n", inst.undo_limit);
+
+ hr = set_editor_undo_state(&inst, undoStateActive);
+ if (SUCCEEDED(hr))
+ {
+ for (inst.test_flags = 0; inst.test_flags < undoTestMaxFlag; inst.test_flags++)
+ {
+ for (state0 = firstUndoState; state0 < numUndoStates; state0++)
+ {
+ for (action0 = firstUndoAction; action0 < numUndoActions; action0++)
+ {
+ for (action1 = firstUndoAction; action1 < numUndoActions; action1++)
+ {
+ winetest_push_context("%x:%d:%d >?:%d", inst.test_flags, state0, action0, action1);
+ hr = set_editor_undo_state(&inst, state0);
+ winetest_pop_context();
+
+ if (FAILED(hr)) continue;
+
+ winetest_push_context("%x:%d:%d+>?:%d", inst.test_flags, state0, action0, action1);
+ hr = subtest_undo_control(&inst, action0);
+ winetest_pop_context();
+
+ if (FAILED(hr)) continue;
+
+ winetest_push_context("%x:%d:%d>%d:%d+", inst.test_flags, state0, action0, inst.undo_ctl_state, action1);
+ subtest_undo_control(&inst, action1);
+ winetest_pop_context();
+ }
+ }
+ }
+ }
+ }
+
+ release_interfaces(&inst.hwnd, &reole, &inst.doc, &selection);
+}
+
START_TEST(richole)
{
/* Must explicitly LoadLibrary(). The test has no references to functions in
@@ -4996,4 +5456,6 @@ START_TEST(richole)
test_MoveEnd_story();
test_character_movement();
test_clipboard();
+ test_undo();
+ test_undo_control();
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/320
June 30, 2022
[PATCH v4 0/1] MR320: riched20/tests: Test for ITextDocument::Undo and ITextDocument::Redo (#53289).
by Jinoh Kang (@iamahuman)
Signed-off-by: Jinoh Kang <jinoh.kang.kr(a)gmail.com>
--
v4: riched20/tests: Test for ITextDocument::Undo and ITextDocument::Redo.
https://gitlab.winehq.org/wine/wine/-/merge_requests/320
June 30, 2022
Re: [PATCH v5 0/5] MR302: winegstreamer: Some wg_transform H264 fixes for Mortal Kombat 11 and Yakuza 4.
by Rémi Bernon
v4: Refactor wg_transform allocator requests and input buffer atomic queue, drop `wg_transform_set_format` patches for now.
v5: Remove a leftover output_wg_sample from wg_transform struct.
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/302#note_3036
June 30, 2022
[PATCH 1/1] winevulkan: Update to VK spec version 1.3.219.
by Georg Lehmann
From: Georg Lehmann <dadschoorse(a)gmail.com>
Signed-off-by: Georg Lehmann <dadschoorse(a)gmail.com>
---
dlls/winevulkan/make_vulkan | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/winevulkan/make_vulkan b/dlls/winevulkan/make_vulkan
index 69e2f0cd256..52052f15bdd 100755
--- a/dlls/winevulkan/make_vulkan
+++ b/dlls/winevulkan/make_vulkan
@@ -64,7 +64,7 @@ from enum import Enum
LOGGER = logging.Logger("vulkan")
LOGGER.addHandler(logging.StreamHandler())
-VK_XML_VERSION = "1.3.217"
+VK_XML_VERSION = "1.3.219"
WINE_VK_VERSION = (1, 3)
# Filenames to create.
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/350
June 30, 2022
[PATCH 0/1] MR350: winevulkan: Update to VK spec version 1.3.219.
by Georg Lehmann (@DadSchoorse)
--
https://gitlab.winehq.org/wine/wine/-/merge_requests/350
June 30, 2022
[PATCH v5 5/5] winegstreamer: Use an atomic queue for wg_transform input buffers.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
And push them one by one until an output buffer is generated, to avoid
generating multiple output buffers without a backing wg_sample.
This makes zero-copy more efficient for games which queue multiple input
buffers before checking output, such as Yakuza 4.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=45988
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47084
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49715
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52183
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/wg_transform.c | 56 +++++++++++++++----------------
1 file changed, 28 insertions(+), 28 deletions(-)
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index 557e085ea31..3bdd5cbb481 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -51,8 +51,9 @@ struct wg_transform
GstPad *my_src, *my_sink;
GstPad *their_sink, *their_src;
GstSegment segment;
- GstBufferList *input;
+
guint input_max_length;
+ GstAtomicQueue *input_queue;
guint output_plane_align;
GstAtomicQueue *output_queue;
@@ -215,9 +216,11 @@ NTSTATUS wg_transform_destroy(void *args)
{
struct wg_transform *transform = args;
GstSample *sample;
+ GstBuffer *buffer;
- if (transform->input)
- gst_buffer_list_unref(transform->input);
+ while ((buffer = gst_atomic_queue_pop(transform->input_queue)))
+ gst_buffer_unref(buffer);
+ gst_atomic_queue_unref(transform->input_queue);
gst_element_set_state(transform->container, GST_STATE_NULL);
@@ -327,7 +330,7 @@ NTSTATUS wg_transform_create(void *args)
return STATUS_NO_MEMORY;
if (!(transform->container = gst_bin_new("wg_transform")))
goto out;
- if (!(transform->input = gst_buffer_list_new()))
+ if (!(transform->input_queue = gst_atomic_queue_new(8)))
goto out;
if (!(transform->output_queue = gst_atomic_queue_new(8)))
goto out;
@@ -494,8 +497,8 @@ out:
wg_allocator_destroy(transform->allocator);
if (transform->output_queue)
gst_atomic_queue_unref(transform->output_queue);
- if (transform->input)
- gst_buffer_list_unref(transform->input);
+ if (transform->input_queue)
+ gst_atomic_queue_unref(transform->input_queue);
if (transform->container)
{
gst_element_set_state(transform->container, GST_STATE_NULL);
@@ -521,7 +524,7 @@ NTSTATUS wg_transform_push_data(void *args)
GstBuffer *buffer;
guint length;
- length = gst_buffer_list_length(transform->input);
+ length = gst_atomic_queue_length(transform->input_queue);
if (length >= transform->input_max_length)
{
GST_INFO("Refusing %u bytes, %u buffers already queued", sample->size, length);
@@ -547,7 +550,7 @@ NTSTATUS wg_transform_push_data(void *args)
GST_BUFFER_DURATION(buffer) = sample->duration * 100;
if (!(sample->flags & WG_SAMPLE_FLAG_SYNC_POINT))
GST_BUFFER_FLAG_SET(buffer, GST_BUFFER_FLAG_DELTA_UNIT);
- gst_buffer_list_insert(transform->input, -1, buffer);
+ gst_atomic_queue_push(transform->input_queue, buffer);
params->result = S_OK;
return STATUS_SUCCESS;
@@ -702,9 +705,7 @@ NTSTATUS wg_transform_read_data(void *args)
struct wg_transform *transform = params->transform;
struct wg_sample *sample = params->sample;
struct wg_format *format = params->format;
- GstFlowReturn ret = GST_FLOW_OK;
GstBuffer *output_buffer;
- GstBufferList *input;
GstCaps *output_caps;
bool discard_data;
NTSTATUS status;
@@ -712,30 +713,29 @@ NTSTATUS wg_transform_read_data(void *args)
/* Provide the sample for transform_request_sample to pick it up */
wg_allocator_set_next_sample(transform->allocator, sample);
- if (!gst_buffer_list_length(transform->input))
- GST_DEBUG("Not input buffer queued");
- else if ((input = gst_buffer_list_new()))
- {
- ret = gst_pad_push_list(transform->my_src, transform->input);
- transform->input = input;
- }
- else
+ while (!transform->output_sample)
{
- GST_ERROR("Failed to allocate new input queue");
- ret = GST_FLOW_ERROR;
+ GstFlowReturn ret = GST_FLOW_OK;
+ GstBuffer *input_buffer;
+
+ if ((input_buffer = gst_atomic_queue_pop(transform->input_queue))
+ && (ret = gst_pad_push(transform->my_src, input_buffer)))
+ {
+ GST_ERROR("Failed to push transform input, error %d", ret);
+ wg_allocator_set_next_sample(transform->allocator, NULL);
+ wg_allocator_release_sample(transform->allocator, sample, false);
+ return STATUS_UNSUCCESSFUL;
+ }
+
+ transform->output_sample = gst_atomic_queue_pop(transform->output_queue);
+ if (!input_buffer)
+ break;
}
/* Remove the sample so transform_request_sample cannot use it */
wg_allocator_set_next_sample(transform->allocator, NULL);
- if (ret)
- {
- GST_ERROR("Failed to push transform input, error %d", ret);
- wg_allocator_release_sample(transform->allocator, sample, false);
- return STATUS_UNSUCCESSFUL;
- }
-
- if (!transform->output_sample && !(transform->output_sample = gst_atomic_queue_pop(transform->output_queue)))
+ if (!transform->output_sample)
{
sample->size = 0;
params->result = MF_E_TRANSFORM_NEED_MORE_INPUT;
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 30, 2022
[PATCH v5 4/5] winegstreamer: Release requested samples if they are too small.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/wg_allocator.c | 11 +++++++----
1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/dlls/winegstreamer/wg_allocator.c b/dlls/winegstreamer/wg_allocator.c
index 53ea5d08c8e..46343db8aae 100644
--- a/dlls/winegstreamer/wg_allocator.c
+++ b/dlls/winegstreamer/wg_allocator.c
@@ -80,9 +80,6 @@ static struct wg_sample *default_request_sample(gsize size, void *context)
return NULL;
allocator->next_sample = NULL;
- if (sample->max_size < size)
- return NULL;
-
return sample;
}
@@ -165,6 +162,7 @@ static GstMemory *wg_allocator_alloc(GstAllocator *gst_allocator, gsize size,
GstAllocationParams *params)
{
WgAllocator *allocator = (WgAllocator *)gst_allocator;
+ struct wg_sample *sample;
WgMemory *memory;
GST_LOG("allocator %p, size %#zx, params %p", allocator, size, params);
@@ -177,7 +175,12 @@ static GstMemory *wg_allocator_alloc(GstAllocator *gst_allocator, gsize size,
GST_OBJECT_LOCK(allocator);
- memory->sample = allocator->request_sample(size, allocator->request_sample_context);
+ sample = allocator->request_sample(size, allocator->request_sample_context);
+ if (sample->max_size < size)
+ InterlockedDecrement(&sample->refcount);
+ else
+ memory->sample = sample;
+
list_add_tail(&allocator->memory_list, &memory->entry);
GST_OBJECT_UNLOCK(allocator);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 30, 2022
[PATCH v5 3/5] winegstreamer: Introduce a new wg_allocator_set_next_sample helper.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Using the allocator lock and replacing the transform_request_sample
callback with a default wg_allocator callback.
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/unix_private.h | 2 ++
dlls/winegstreamer/wg_allocator.c | 42 +++++++++++++++++++++++++++++--
dlls/winegstreamer/wg_transform.c | 24 +++---------------
3 files changed, 46 insertions(+), 22 deletions(-)
diff --git a/dlls/winegstreamer/unix_private.h b/dlls/winegstreamer/unix_private.h
index e9f472986ae..2bfdc6f9f5b 100644
--- a/dlls/winegstreamer/unix_private.h
+++ b/dlls/winegstreamer/unix_private.h
@@ -44,5 +44,7 @@ extern GstAllocator *wg_allocator_create(wg_allocator_request_sample_cb request_
extern void wg_allocator_destroy(GstAllocator *allocator) DECLSPEC_HIDDEN;
extern void wg_allocator_release_sample(GstAllocator *allocator, struct wg_sample *sample,
bool discard_data) DECLSPEC_HIDDEN;
+extern void wg_allocator_set_next_sample(GstAllocator *allocator,
+ struct wg_sample *sample) DECLSPEC_HIDDEN;
#endif /* __WINE_WINEGSTREAMER_UNIX_PRIVATE_H */
diff --git a/dlls/winegstreamer/wg_allocator.c b/dlls/winegstreamer/wg_allocator.c
index 16e961a57d4..53ea5d08c8e 100644
--- a/dlls/winegstreamer/wg_allocator.c
+++ b/dlls/winegstreamer/wg_allocator.c
@@ -54,6 +54,7 @@ typedef struct
{
GstAllocator parent;
+ struct wg_sample *next_sample;
wg_allocator_request_sample_cb request_sample;
void *request_sample_context;
@@ -68,6 +69,23 @@ typedef struct
G_DEFINE_TYPE(WgAllocator, wg_allocator, GST_TYPE_ALLOCATOR);
+static struct wg_sample *default_request_sample(gsize size, void *context)
+{
+ WgAllocator *allocator = context;
+ struct wg_sample *sample;
+
+ GST_LOG("size %#zx, context %p", size, context);
+
+ if (!(sample = allocator->next_sample))
+ return NULL;
+ allocator->next_sample = NULL;
+
+ if (sample->max_size < size)
+ return NULL;
+
+ return sample;
+}
+
static gpointer wg_allocator_map(GstMemory *gst_memory, GstMapInfo *info, gsize maxsize)
{
WgAllocator *allocator = (WgAllocator *)gst_memory->allocator;
@@ -210,8 +228,14 @@ GstAllocator *wg_allocator_create(wg_allocator_request_sample_cb request_sample,
if (!(allocator = g_object_new(wg_allocator_get_type(), NULL)))
return NULL;
- allocator->request_sample = request_sample;
- allocator->request_sample_context = request_sample_context;
+ if ((allocator->request_sample = request_sample))
+ allocator->request_sample_context = request_sample_context;
+ else
+ {
+ allocator->request_sample = default_request_sample;
+ allocator->request_sample_context = allocator;
+ }
+
return GST_ALLOCATOR(allocator);
}
@@ -282,3 +306,17 @@ void wg_allocator_release_sample(GstAllocator *gst_allocator, struct wg_sample *
GST_ERROR("Couldn't find memory for sample %p", sample);
GST_OBJECT_UNLOCK(allocator);
}
+
+void wg_allocator_set_next_sample(GstAllocator *gst_allocator, struct wg_sample *sample)
+{
+ WgAllocator *allocator = (WgAllocator *)gst_allocator;
+
+ GST_LOG("allocator %p, sample %p", allocator, sample);
+
+ GST_OBJECT_LOCK(allocator);
+ if (allocator->next_sample)
+ InterlockedDecrement(&allocator->next_sample->refcount);
+ if ((allocator->next_sample = sample))
+ InterlockedIncrement(&allocator->next_sample->refcount);
+ GST_OBJECT_UNLOCK(allocator);
+}
diff --git a/dlls/winegstreamer/wg_transform.c b/dlls/winegstreamer/wg_transform.c
index e05432f6ac7..557e085ea31 100644
--- a/dlls/winegstreamer/wg_transform.c
+++ b/dlls/winegstreamer/wg_transform.c
@@ -53,8 +53,8 @@ struct wg_transform
GstSegment segment;
GstBufferList *input;
guint input_max_length;
+
guint output_plane_align;
- struct wg_sample *output_wg_sample;
GstAtomicQueue *output_queue;
GstSample *output_sample;
bool output_caps_changed;
@@ -307,20 +307,6 @@ static bool transform_append_element(struct wg_transform *transform, GstElement
return success;
}
-static struct wg_sample *transform_request_sample(gsize size, void *context)
-{
- struct wg_transform *transform = context;
- struct wg_sample *sample;
-
- GST_LOG("size %#zx, context %p", size, transform);
-
- sample = InterlockedExchangePointer((void **)&transform->output_wg_sample, NULL);
- if (!sample || sample->max_size < size)
- return NULL;
-
- return sample;
-}
-
NTSTATUS wg_transform_create(void *args)
{
struct wg_transform_create_params *params = args;
@@ -345,7 +331,7 @@ NTSTATUS wg_transform_create(void *args)
goto out;
if (!(transform->output_queue = gst_atomic_queue_new(8)))
goto out;
- if (!(transform->allocator = wg_allocator_create(transform_request_sample, transform)))
+ if (!(transform->allocator = wg_allocator_create(NULL, NULL)))
goto out;
transform->input_max_length = 1;
transform->output_plane_align = 0;
@@ -724,8 +710,7 @@ NTSTATUS wg_transform_read_data(void *args)
NTSTATUS status;
/* Provide the sample for transform_request_sample to pick it up */
- InterlockedIncrement(&sample->refcount);
- InterlockedExchangePointer((void **)&transform->output_wg_sample, sample);
+ wg_allocator_set_next_sample(transform->allocator, sample);
if (!gst_buffer_list_length(transform->input))
GST_DEBUG("Not input buffer queued");
@@ -741,8 +726,7 @@ NTSTATUS wg_transform_read_data(void *args)
}
/* Remove the sample so transform_request_sample cannot use it */
- if (InterlockedExchangePointer((void **)&transform->output_wg_sample, NULL))
- InterlockedDecrement(&sample->refcount);
+ wg_allocator_set_next_sample(transform->allocator, NULL);
if (ret)
{
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 30, 2022
[PATCH v5 2/5] winegstreamer: Use the GstObject lock instead of a new allocator mutex.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/winegstreamer/wg_allocator.c | 37 ++++++++++++++-----------------
1 file changed, 17 insertions(+), 20 deletions(-)
diff --git a/dlls/winegstreamer/wg_allocator.c b/dlls/winegstreamer/wg_allocator.c
index c31751ce83f..16e961a57d4 100644
--- a/dlls/winegstreamer/wg_allocator.c
+++ b/dlls/winegstreamer/wg_allocator.c
@@ -57,8 +57,7 @@ typedef struct
wg_allocator_request_sample_cb request_sample;
void *request_sample_context;
- pthread_mutex_t mutex;
- pthread_cond_t release_cond;
+ GCond release_cond;
struct list memory_list;
} WgAllocator;
@@ -79,7 +78,7 @@ static gpointer wg_allocator_map(GstMemory *gst_memory, GstMapInfo *info, gsize
GST_LOG("memory %p, info %p, maxsize %#zx", memory, info, maxsize);
- pthread_mutex_lock(&allocator->mutex);
+ GST_OBJECT_LOCK(allocator);
if (!memory->sample)
info->data = memory->unix_map_info.data;
@@ -91,7 +90,7 @@ static gpointer wg_allocator_map(GstMemory *gst_memory, GstMapInfo *info, gsize
if (info->flags & GST_MAP_WRITE)
memory->written = max(memory->written, maxsize);
- pthread_mutex_unlock(&allocator->mutex);
+ GST_OBJECT_UNLOCK(allocator);
GST_INFO("Mapped memory %p to %p", memory, info->data);
return info->data;
@@ -107,15 +106,15 @@ static void wg_allocator_unmap(GstMemory *gst_memory, GstMapInfo *info)
GST_LOG("memory %p, info %p", memory, info);
- pthread_mutex_lock(&allocator->mutex);
+ GST_OBJECT_LOCK(allocator);
if (memory->sample && info->data == memory->sample->data)
{
InterlockedDecrement(&memory->sample->refcount);
- pthread_cond_signal(&allocator->release_cond);
+ g_cond_signal(&allocator->release_cond);
}
- pthread_mutex_unlock(&allocator->mutex);
+ GST_OBJECT_UNLOCK(allocator);
}
static void wg_allocator_init(WgAllocator *allocator)
@@ -129,8 +128,7 @@ static void wg_allocator_init(WgAllocator *allocator)
GST_OBJECT_FLAG_SET(allocator, GST_ALLOCATOR_FLAG_CUSTOM_ALLOC);
- pthread_mutex_init(&allocator->mutex, NULL);
- pthread_cond_init(&allocator->release_cond, NULL);
+ g_cond_init(&allocator->release_cond);
list_init(&allocator->memory_list);
}
@@ -140,8 +138,7 @@ static void wg_allocator_finalize(GObject *object)
GST_LOG("allocator %p", allocator);
- pthread_cond_destroy(&allocator->release_cond);
- pthread_mutex_destroy(&allocator->mutex);
+ g_cond_clear(&allocator->release_cond);
G_OBJECT_CLASS(wg_allocator_parent_class)->finalize(object);
}
@@ -160,12 +157,12 @@ static GstMemory *wg_allocator_alloc(GstAllocator *gst_allocator, gsize size,
memory->unix_memory = gst_allocator_alloc(NULL, size, params);
gst_memory_map(memory->unix_memory, &memory->unix_map_info, GST_MAP_WRITE);
- pthread_mutex_lock(&allocator->mutex);
+ GST_OBJECT_LOCK(allocator);
memory->sample = allocator->request_sample(size, allocator->request_sample_context);
list_add_tail(&allocator->memory_list, &memory->entry);
- pthread_mutex_unlock(&allocator->mutex);
+ GST_OBJECT_UNLOCK(allocator);
GST_INFO("Allocated memory %p, sample %p, unix_memory %p, data %p", memory,
memory->sample, memory->unix_memory, memory->unix_map_info.data);
@@ -179,7 +176,7 @@ static void wg_allocator_free(GstAllocator *gst_allocator, GstMemory *gst_memory
GST_LOG("allocator %p, memory %p", allocator, memory);
- pthread_mutex_lock(&allocator->mutex);
+ GST_OBJECT_LOCK(allocator);
if (memory->sample)
InterlockedDecrement(&memory->sample->refcount);
@@ -187,7 +184,7 @@ static void wg_allocator_free(GstAllocator *gst_allocator, GstMemory *gst_memory
list_remove(&memory->entry);
- pthread_mutex_unlock(&allocator->mutex);
+ GST_OBJECT_UNLOCK(allocator);
gst_memory_unmap(memory->unix_memory, &memory->unix_map_info);
gst_memory_unref(memory->unix_memory);
@@ -228,7 +225,7 @@ static void release_memory_sample(WgAllocator *allocator, WgMemory *memory, bool
while (sample->refcount > 1)
{
GST_WARNING("Waiting for sample %p to be unmapped", sample);
- pthread_cond_wait(&allocator->release_cond, &allocator->mutex);
+ g_cond_wait(&allocator->release_cond, GST_OBJECT_GET_LOCK(allocator));
}
InterlockedDecrement(&sample->refcount);
@@ -249,10 +246,10 @@ void wg_allocator_destroy(GstAllocator *gst_allocator)
GST_LOG("allocator %p", allocator);
- pthread_mutex_lock(&allocator->mutex);
+ GST_OBJECT_LOCK(allocator);
LIST_FOR_EACH_ENTRY(memory, &allocator->memory_list, WgMemory, entry)
release_memory_sample(allocator, memory, true);
- pthread_mutex_unlock(&allocator->mutex);
+ GST_OBJECT_UNLOCK(allocator);
g_object_unref(allocator);
@@ -278,10 +275,10 @@ void wg_allocator_release_sample(GstAllocator *gst_allocator, struct wg_sample *
GST_LOG("allocator %p, sample %p, discard_data %u", allocator, sample, discard_data);
- pthread_mutex_lock(&allocator->mutex);
+ GST_OBJECT_LOCK(allocator);
if ((memory = find_sample_memory(allocator, sample)))
release_memory_sample(allocator, memory, discard_data);
else if (sample->refcount)
GST_ERROR("Couldn't find memory for sample %p", sample);
- pthread_mutex_unlock(&allocator->mutex);
+ GST_OBJECT_UNLOCK(allocator);
}
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 30, 2022
[PATCH v5 1/5] mf/tests: Add todo_wine for newer FFmpeg versions.
by Rémi Bernon
From: Rémi Bernon <rbernon(a)codeweavers.com>
Signed-off-by: Rémi Bernon <rbernon(a)codeweavers.com>
---
dlls/mf/tests/mf.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/dlls/mf/tests/mf.c b/dlls/mf/tests/mf.c
index 2f3ee3151da..5f26b1a6238 100644
--- a/dlls/mf/tests/mf.c
+++ b/dlls/mf/tests/mf.c
@@ -5911,7 +5911,7 @@ static void check_sample_pcm16_(int line, IMFSample *sample, const BYTE *expect_
if (expect - value + 512 > 1024) break;
}
- todo_wine_if(todo)
+ todo_wine_if(todo && i < length / 2)
ok_(__FILE__, line)(i == length, "unexpected buffer data\n");
if (output_file) WriteFile(output_file, buffer, length, &length, NULL);
@@ -6544,6 +6544,9 @@ static void test_wma_decoder(void)
hr = IMFTransform_ProcessOutput(transform, 0, 1, &output, &status);
winetest_pop_context();
+
+ /* some FFmpeg version request more input to complete decoding */
+ if (hr == MF_E_TRANSFORM_NEED_MORE_INPUT && i == 2) break;
}
todo_wine
ok(wmadec_data_len == 0, "missing %#lx bytes\n", wmadec_data_len);
--
GitLab
https://gitlab.winehq.org/wine/wine/-/merge_requests/302
June 30, 2022