[PATCH] winex11.drv: Fix drawing of layered windows with a client window.
Giovanni Mascellani
gmascellani at codeweavers.com
Thu Apr 29 04:27:46 CDT 2021
Hi,
Il 27/04/21 11:33, Rémi Bernon ha scritto:
> As far as I can tell from a quick test with OpenGL rendering, there is
> two different behavior on Windows:
>
> I'm only considering the layered attribute and calls on top-level
> windows, as I couldn't make it work on child windows, to the contrary
> to what MSDN says is supported on Windows > 8.
>
> 1) When UpdateLayeredWindow is called, the displayed image is the one
> that has been provided in the call, regardless of any later drawing
> call indeed, be it GDI or OpenGL. If the window has child windows,
> they aren't displayed either, regardless of the API they use too.
>
> 2) When SetLayeredWindowAttributes has been called, the window is
> displayed, with the transparency computed according to the attributes.
> If the window has child windows, they are displayed normally, but with
> the same transparency transformation. Drawing with GDI or OpenGL on
> the top-level or the child windows works as for a normal window,
> except for the transparency.
You're right, I was forgetting about SLWA. With this in mind, I can
reproduce the behaviors you describe, except that I didn't test with
child windows. On the other hand, I also checked that D3D9 are on the
same level as GDI and OpenGL (i.e., they are ignored after ULW). So, I
let me summarize again the Windows behavior. Windows can be of three
different mutually exclusive types: not layered, ULW-layered and
SLWA-layered. Creating a window with WS_EX_LAYERED makes it ULW-layered,
otherwise it is not layered (on Windows a ULW-layered window appears
immediately, even if it's empty, and it receives events; on Wine it
doesn't). Then the painting behavior is:
* If the window is not layered, ULW and SLWA return error and do
nothing. The windows receives WM_PAINT as usual. GDI, OpenGL, D3D9 work
as usual and are on the same level, meaning that each of them can
overwrite what the others painted. I suppose Vulkan and other D3D
versions are analogous. Setting WS_EX_LAYERED on the window makes it
ULW-layered. Window decorations are rendered as usual.
* If the window is ULW-layered, it doesn't receive WM_PAINT and all the
other APIs are ignored (at least, they don't draw; I don't know if they
produce side-effects, if they have any). The only way to put something
in the window is calling ULW. Clearing WS_EX_LAYERED on the window makes
it non layered, and calling SLWA makes it SLWA-layered (and generates a
WM_PAINT event). Window decorations are not rendered.
* If the window is SLWA-layered, it receives WM_PAINT as usual. All the
other APIs (i.e., not ULW) work as in the non layered case, except that
the post-processing set with SLWA (color keying and global alpha) is
applied. ULW returns error (there is no way to switch directly to
ULW-layered: you have to clear and set WS_EX_LAYERED) and clearing
WS_EX_LAYERED of course makes the window not layered. Calling again SLWA
(possibly with different settings) does not cause a new WM_PAINT event,
but correctly updates the window, which probably means that Windows
keeps an offscreen copy of the original buffer. Window decorations are
rendered as usual (and are affected by the SLWA alpha).
We already have a "layered" bit in x11drv_win_data, but I don't think we
have a bit to distinguish the two layered variants. I think we should
have one, which we would use to deny painting by other APIs when the
window is ULW-layered (and, conversely, to allow ULW to paint on the
client window, i.e., what my patch was trying to do; or maybe in this
case we should just unmap or destroy the client window). Does this look
sensible? (I'm not meaning that this bit is the only thing we need to be
like Windows, but that at least it is a step forward)
> Here I would expect the surface flush to only work once until a later
> GL swap buffer / VK present override it (although I'm not completely
> sure when the Expose events are generated).
>
> It may also work differently depending on if the client windows are
> off-screen or not (depending on whether it's a client window of a
> child or if the top-level has child windows).
>
> Although this patch possibly fixes some bad cases I think the layered
> window implementation is actually incorrect in a more general way.
>
> To make things simpler I think we should maybe make the off-screen
> GL/VK rendering the default and do the present ourselves on the
> top-level windows, and put the GL/VK on-screen /only/ when we're sure
> we can (which is hopefully still going to be quite often).
I am not sure I am following you. In which case would off-screen
rendering help?
Thanks, Giovanni.
More information about the wine-devel
mailing list