[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