[PATCH resend 1/2] ddraw: Use WINED3D_SWAPCHAIN_NO_WINDOW_CHANGES only with DDSCL_NOWINDOWCHANGES or if window inactive.

Gabriel Ivăncescu gabrielopcode at gmail.com
Thu Dec 30 12:09:57 CST 2021


On 28/12/2021 18:15, Henri Verbeet wrote:
> On Mon, 27 Dec 2021 at 15:32, Gabriel Ivăncescu <gabrielopcode at gmail.com> wrote:
>> This is a regression from last year but I completely forgot about it. Last
>> time, it got no reviews, unfortunately, so it would be nice to have it
>> fixed during this year's code freeze.
>>
> I think this got deferred during code freeze last year, because window
> handling is simply very sensitive. It was then never resubmitted after
> code freeze.
> 

Ah, I did resend it in this form (the old form sent during code freeze 
was wrong), and now that I done more tests it does seem slightly off as 
well but more details below.

>> +    if ((cooplevel & DDSCL_NOWINDOWCHANGES) || window != GetActiveWindow())
>> +        swapchain_desc.flags |= WINED3D_SWAPCHAIN_NO_WINDOW_CHANGES;
>>
> That said, I also remember thinking that doing the GetActiveWindow()
> check here seems somewhat suspicious. The expected place for that kind
> of check would be in wined3d_swapchain_state_setup_fullscreen(), and
> the tests don't seem to provide a justification for doing it here
> instead. Of course doing it in
> wined3d_swapchain_state_setup_fullscreen() would raise the question of
> how this is supposed to behave in other D3D versions, but that seems a
> question worth raising anyway.
> 

Okay so I wrote tests for the different D3D versions and it seems it's 
somewhat version-specific, but the main problem is that I don't know how 
to fix it in wined3d side, because of the acquire_focus_window which 
changes the focus *before* the swapchain sets fullscreen. But first, 
here's roughly the results of how each version works:

ddraw: If it's not active when entering fullscreen, WS_EX_TOPMOST is not 
set (i.e. doesn't do window changes). This check is done only when 
entering fullscreen; if the coop level is reset again after to 
fullscreen while active, even while already being fullscreen, it will 
set WS_EX_TOPMOST, i.e. it does not "persist".

d3d9: Same as ddraw, where creating the device while not active will not 
make it topmost. Resetting the device while not active won't make it 
topmost either, but doing so while active (even if it was created 
inactive) will.

d3d8: Similar to d3d9, except that it persists. If it's created 
inactive, it will never set WS_EX_TOPMOST after that during any resets, 
even if it's active while it's being reset back to fullscreen.

dxgi: Doesn't care about inactive at all, always sets topmost (so 
current behavior is correct).


This leads me to think a solution outside of wined3d is preferable. 
However, there's more reasons to it. The problem, as stated, is 
wined3d_device_acquire_focus_window. This is done before the swapchain 
is created/sets fullscreen (during reset). And it focuses the window, 
which means that any checks during setup_fullscreen will always see it 
active/focused, making them pointless.

Checking whether it's active before acquire_focus_window is easy enough 
outside of wined3d, but would be pretty ugly in wined3d, having to track 
extra state and all.

Then there's the difference between versions, where it's easy enough to 
handle that outside of wined3d, while requiring some sort of new flags 
(?) for wined3d, especially given that dxgi's current behavior is 
correct and needs no changes at all.



More information about the wine-devel mailing list