Re: How to implement

zhengxianwei <[email protected]> Tue, 3 Jun 2025 17:05:12 +0800
Newsgroups gmane.comp.emulators.wine.devel
Message-ID <CABeGAqXgx0CQFHpC-VTJdsYULfstXbg+y5wOZKndDvXETKxkpg@mail.gmail.com>
  Sorry, I forgot to add the title

How to Implement the Logic for Mixing DirectComposition with GDI?

On Tue, Jun 3, 2025 at 5:02 PM zhengxianwei <[email protected]> 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.
>
>