[PATCH] winex11.drv: Fix drawing of layered windows with a client window.
Joshua Ashton
joshua at froggi.es
Tue Apr 27 04:35:39 CDT 2021
On 4/27/21 10:33 AM, Rémi Bernon wrote:
> On 4/27/21 10:51 AM, Giovanni Mascellani wrote:
>> Testing on Windows 10, it seems that when a window has both a surface
>> (because it is layered) and a client window (because a d3d9 or analogous
>> device was created for it), the surface takes the priority, i.e., gdi
>> and d3d9 are ignored, and just the layered bitmap is painted.
>>
>> Before this change, expose events lead to redrawing the surface only
>> on the whole window, but not on the client window. This implies that
>> if a d3d9 device is created for a layered window, it takes the priority
>> in the client window region, contradicting the behavior observed on
>> Windows.
>>
>> Signed-off-by: Giovanni Mascellani <gmascellani at codeweavers.com>
>> ---
>> dlls/winex11.drv/event.c | 24 ++++++++++++------------
>> 1 file changed, 12 insertions(+), 12 deletions(-)
>>
>> diff --git a/dlls/winex11.drv/event.c b/dlls/winex11.drv/event.c
>> index 99943478729..38c8bd825bb 100644
>> --- a/dlls/winex11.drv/event.c
>> +++ b/dlls/winex11.drv/event.c
>> @@ -938,21 +938,21 @@ static BOOL X11DRV_Expose( HWND hwnd, XEvent *xev )
>> rect.right = pos.x + event->width;
>> rect.bottom = pos.y + event->height;
>> - if (event->window != data->client_window)
>> + if (event->window == data->client_window)
>> + OffsetRect( &rect, data->client_rect.left -
>> data->whole_rect.left,
>> + data->client_rect.top - data->whole_rect.top );
>> + if (data->surface)
>> {
>> - if (data->surface)
>> - {
>> - surface_region = expose_surface( data->surface, &rect );
>> - if (!surface_region) flags = 0;
>> - else OffsetRgn( surface_region, data->whole_rect.left -
>> data->client_rect.left,
>> - data->whole_rect.top -
>> data->client_rect.top );
>> + surface_region = expose_surface( data->surface, &rect );
>> + if (!surface_region) flags = 0;
>> + else OffsetRgn( surface_region, data->whole_rect.left -
>> data->client_rect.left,
>> + data->whole_rect.top - data->client_rect.top );
>> - if (data->vis.visualid != default_visual.visualid)
>> - data->surface->funcs->flush( data->surface );
>> - }
>> - OffsetRect( &rect, data->whole_rect.left -
>> data->client_rect.left,
>> - data->whole_rect.top - data->client_rect.top );
>> + if (data->vis.visualid != default_visual.visualid)
>> + data->surface->funcs->flush( data->surface );
>> }
>> + OffsetRect( &rect, data->whole_rect.left - data->client_rect.left,
>> + data->whole_rect.top - data->client_rect.top );
>> if (event->window != root_window)
>> {
>>
>
> 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.
>
>
> 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).
What would be the performance implications of this?
- Joshie 🐸✨
More information about the wine-devel
mailing list