Re: How to implement
zhengxianwei <[email protected]> Tue, 3 Jun 2025 20:05:30 +0800
| Newsgroups | gmane.comp.emulators.wine.devel |
|---|---|
| Message-ID | <CABeGAqUU97fCnD1RLKkuPaPdqb4Jp+WheCN9N_V4B_kcVpB5nw@mail.gmail.com> |
On Tue, Jun 3, 2025 at 5:27 PM Rémi Bernon <[email protected]> wrote: > 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. > > Thank you very much! I never realized there were so many DirectComposition-related interfaces in win32u. I’ll need to analyze them further — this will probably require a lot of reverse engineering and testing. > > 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. > *For the first version, I plan to focus on making sure the interfaces are usable and don’t crash, even if there are visual imperfections — that’s acceptable for now.* *However, I want the overall architecture to be as complete as possible, even though that might not be entirely realistic, since Wine’s current design doesn’t account for multi-process composition.* *For anything unnecessary, I’ll just keep it as a stub and only implement the most essential parts.* > > 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. > *I plan to ignore multi-process window composition for now and focus only on handling everything within a single process.* *Additionally, to simplify things, I’ll probably minimize GPU-related handling as much as possible.* > > 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. > > I really appreciate your perspective — thank you for pointing out these potential risks. Cheers, > > > [^1]: dmabuf on Linux or IOSurface on macOS > -- > Rémi Bernon <[email protected]> > > >