[PATCH v3 0/1] MR10726: dsound: Merge capability flags when returning existing primary buffer.
When a primary buffer already exists and a second CreateSoundBuffer call requests DSBCAPS_PRIMARYBUFFER, Wine returns the existing buffer but discards the new caller's dwFlags. This prevents the caller from using capabilities it requested. Star Wars Episode I Racer (AppID 808910) creates a primary buffer with DSBCAPS_CTRL3D for in-game audio, then its Smush video engine requests the primary buffer with DSBCAPS_CTRLVOLUME for cutscene audio. GetVolume returns DSERR_CONTROLUNAVAIL and the cutscene audio path silently fails, resulting in no sound during cutscenes. Tested with the game on Proton Experimental by swapping the DLL built from this branch, cutscene audio plays correctly with the fix applied. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=41047 -- v3: dsound/tests: test if primary buffer is independent on windos https://gitlab.winehq.org/wine/wine/-/merge_requests/10726
From: Jon Koops <jonkoops@gmail.com> Signed-off-by: Jon Koops <jonkoops@gmail.com> --- dlls/dsound/tests/dsound.c | 90 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/dlls/dsound/tests/dsound.c b/dlls/dsound/tests/dsound.c index a7d6fa0fc3b..4821701353c 100644 --- a/dlls/dsound/tests/dsound.c +++ b/dlls/dsound/tests/dsound.c @@ -2192,6 +2192,95 @@ static void test_implicit_mta(void) ok(test_apt_data.type == APTTYPE_UNITIALIZED, "got apt type %d.\n", test_apt_data.type); } +static void test_primary_independent(void) +{ + HRESULT rc; + LPDIRECTSOUND dso1=NULL; + LPDIRECTSOUND dso2=NULL; + LPDIRECTSOUNDBUFFER primary1=NULL; + LPDIRECTSOUNDBUFFER primary2=NULL; + DSBUFFERDESC bufdesc; + DSBCAPS bufcaps; + LONG vol; + + rc=DirectSoundCreate(NULL,&dso1,NULL); + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, + "DirectSoundCreate() failed: %08lx\n",rc); + if (rc!=DS_OK) + return; + + rc=DirectSoundCreate(NULL,&dso2,NULL); + ok(rc==DS_OK||rc==DSERR_NODRIVER||rc==DSERR_ALLOCATED||rc==E_FAIL, + "DirectSoundCreate() failed: %08lx\n",rc); + if (rc!=DS_OK) { + IDirectSound_Release(dso1); + return; + } + + rc=IDirectSound_SetCooperativeLevel(dso1,get_hwnd(),DSSCL_PRIORITY); + ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(dso1) failed: %08lx\n",rc); + if (rc!=DS_OK) + goto EXIT; + + rc=IDirectSound_SetCooperativeLevel(dso2,get_hwnd(),DSSCL_PRIORITY); + ok(rc==DS_OK,"IDirectSound_SetCooperativeLevel(dso2) failed: %08lx\n",rc); + if (rc!=DS_OK) + goto EXIT; + + /* Create a primary buffer on dso1 with CTRL3D but without CTRLVOLUME */ + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRL3D; + rc=IDirectSound_CreateSoundBuffer(dso1,&bufdesc,&primary1,NULL); + ok(rc==DS_OK && primary1!=NULL, + "IDirectSound_CreateSoundBuffer(dso1) failed: %08lx\n",rc); + if (rc!=DS_OK || primary1==NULL) + goto EXIT; + + /* Create a primary buffer on dso2 with CTRLVOLUME */ + ZeroMemory(&bufdesc, sizeof(bufdesc)); + bufdesc.dwSize=sizeof(bufdesc); + bufdesc.dwFlags=DSBCAPS_PRIMARYBUFFER|DSBCAPS_CTRLVOLUME; + rc=IDirectSound_CreateSoundBuffer(dso2,&bufdesc,&primary2,NULL); + ok(rc==DS_OK && primary2!=NULL, + "IDirectSound_CreateSoundBuffer(dso2) failed: %08lx\n",rc); + if (rc!=DS_OK || primary2==NULL) + goto RELEASE1; + + /* Check whether the two IDirectSound objects share a primary buffer */ + todo_wine + ok(primary1!=primary2, + "Two IDirectSound objects should have independent primary buffers\n"); + + /* GetVolume on dso2's primary buffer should succeed */ + todo_wine + { + rc=IDirectSoundBuffer_GetVolume(primary2,&vol); + ok(rc==DS_OK, + "IDirectSoundBuffer_GetVolume(primary2) failed: %08lx\n",rc); + } + + /* Verify dso2's primary buffer has CTRLVOLUME */ + ZeroMemory(&bufcaps, sizeof(bufcaps)); + bufcaps.dwSize=sizeof(bufcaps); + rc=IDirectSoundBuffer_GetCaps(primary2,&bufcaps); + ok(rc==DS_OK,"IDirectSoundBuffer_GetCaps(primary2) failed: %08lx\n",rc); + if (rc==DS_OK) { + todo_wine + ok(bufcaps.dwFlags & DSBCAPS_CTRLVOLUME, + "primary2 should have DSBCAPS_CTRLVOLUME: %08lx\n",bufcaps.dwFlags); + } + + IDirectSoundBuffer_Release(primary2); + +RELEASE1: + IDirectSoundBuffer_Release(primary1); + +EXIT: + IDirectSound_Release(dso2); + IDirectSound_Release(dso1); +} + START_TEST(dsound) { CoInitialize(NULL); @@ -2201,6 +2290,7 @@ START_TEST(dsound) IDirectSound_tests(); dsound_tests(); test_hw_buffers(); + test_primary_independent(); CoUninitialize(); } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10726
Ok, so tests confirm. The DirectSoundCreate calls produce independent primary buffer, Wine seems to re-use the same buffer, but Windows gives each IDirectSound its own buffer. This goes a bit beyond my current knowledge of the codebase, so I will need to spend some time working this out. I'll see if I can write up a separate test case first, and put that in a PR without a fix, at least that way someone can pick it up to fix, even if I might not be able to. Closing this PR. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10726#note_137440
This merge request was closed by Jon Koops. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10726
Moved the testing effort over to https://gitlab.winehq.org/wine/wine/-/merge_requests/10728 -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10726#note_137447
participants (2)
-
Jon Koops -
Jon Koops (@jonkoops)