Re: How to implement

Rémi Bernon <[email protected]> Tue, 3 Jun 2025 11:26:57 +0200
Newsgroups gmane.comp.emulators.wine.devel
Message-ID <[email protected]>
On 6/3/25 11:02, zhengxianwei wrote:
> Hello,
> 
> I would like to implement part of the logic within dcomp.dll in order to
> properly support applications that depend on it.
> 
> I found that Zhiyi Zhang has implemented some data structures and interface
> stubs:
> 
> https://gitlab.winehq.org/zhiyi/wine/-/commits/directcomposition?ref_type=heads
> 
> Among these, the only method with actual logic appears to be
> IDCompositionDevice::Commit.
> 
> However, after reviewing the implementation, I suspect there may be an
> issue with the current approach.
> 
> It seems that Zhiyi Zhang starts a separate thread for each
> IDCompositionDevice, and this thread runs at a fixed refresh rate.
> 
> But this approach appears to introduce a problem: from the window's (HWND)
> perspective, there are now *two threads* concurrently updating its device
> context.
> 
> This results in a frame sequence similar to the following (note: the frame
> intervals are illustrative only):
> 
> gdi_frame | dcomp_frame | gdi_frame | gdi_frame | dcomp_frame
> 
> In this model, GDI-generated frames and DComp-generated frames are
> interleaved.
> 
> Is my understanding correct?
> 
> If so, I believe this method may lead to *inaccurate rendering results*,
> although I am not entirely certain about the exact consequences (as I am
> not an expert in this area).
> 
> Therefore, I have decided to pursue an approach that produces a *standardized
> frame stream* like the following:
> 
> gdi_mix_dcomp_frame |  gdi_mix_dcomp_frame | gdi_mix_dcomp_frame
> 
> 
>    In other words, I plan to merge GDI and DComp content before presenting
> each frame, ensuring consistency in the final output.
> 
> I’ve reviewed the normal GDI frame refresh process, and it seems to follow
> this path:
> 
> 
> --> flush_window_surfaces
>      --> window_surface_flush
>          --> x11drv_surface_flush
> 
> 
> I’m planning to insert the following logic inside x11drv_surface_flush:
> 
> 
> if (is_hwnd_bind_to_dcomp(hwnd))
> {
>      struct Surface *final = get_comp_surface(hwnd);
> 
>      blend_dcomp_surface_over_gdi(dest_surface, final);
> 
> }
> 
> 
> However, there’s still a question regarding *how to access the DComp data*
> inside x11drv_surface_flush.
> 
> One option is to do the composition inside IDCompositionDevice::Commit()
> like this:
> void IDCompositionDevice_Commit()
> {
>      composite_proc();
>      ...
>      ...
>      push_frame_to_x11drv();
> 
> }
> 
> 
> Another option is to *directly call into DComp APIs from within x11drv* to
> retrieve the surface data on demand.
> 
> However, *both approaches feel somewhat unnatural*, and from what I can
> tell, Windows seems to establish some kind of *internal channel* to pass
> the composed content to the compositor.
> 
> Is there a better or more canonical way to do this?
> 
> Any suggestions or guidance would be greatly appreciated.
> 
> 

Hi!

This will likely require some work within win32u, to change the way GDI 
is being drawn and presented and to implement the compositing engine 
there, where the code can access the internal surfaces.

There are plenty of NtDComposition exports from win32u, which will need 
to be tested, to understand how they are supposed to be combined. Then 
they would be used from dcomp.dll, which is probably a higher level API.


Then fwiw, although I'm not looking at dcomp specifically, I am 
currently making some large changes in win32u to facilitate all this, 
especially with VK/GL/GDI interop.

I believe the code is currently far from being ready to implement any 
kind of compositing, and we will need more changes to be able to 
manipulate GPU surfaces[^1] directly.

More specifically we currently lack any way to export these surfaces 
from their individual APIs and processes, and import them into a 
different API or process to composite together.

Incidentally, this is also very much related to D3D shared resources, 
which is the Windows side representation of these GPU surfaces, and 
which I expect dcomp.dll can make use of too and would thus require.

So overall, and sorry to say it, but I think it's a bit too soon to have 
a try at an actual implementation (or rather, there will be a lot of 
conflicting changes going on upstream). Then writing tests for dcomp.dll 
and for these NtDComposition functions to figure how they interact, 
would be interesting nevertheless.

Cheers,


[^1]: dmabuf on Linux or IOSurface on macOS
-- 
Rémi Bernon <[email protected]>