Does the timing of composition need to be moved from dcomp.dll to win32u?

zhengxianwei <[email protected]> Thu, 19 Jun 2025 14:13:02 +0800
Newsgroups gmane.comp.emulators.wine.devel
Message-ID <CABeGAqXZDxWSzbyx27yb_PB2LvFzVVK72TmnaZVzpqDy9xGkUg@mail.gmail.com>
Zhiyi Zhang provided an implementation of DComp composition:
https://gitlab.winehq.org/zhiyi/wine/-/commit/ef4f90c2ae909f4a732f0ebeae3b7e98479cd63d

I created a simple sample that renders three equally sized red circles with
varying alpha values on a plain white background window.

On Windows, it displays as follows.

[image: dcomp_test_window.png]

But on Linux, it display as follows.
[image: dcomp_test_wine.png]

One of the main issues here is that the background turns black. This is
because the foreground (swapchain) is not alpha-blended with the background
(GDI); instead, it is simply overlaid using BitBlt.

```

*    BitBlt(dst_dc, 0, 0, rect.right - rect.left, rect.bottom - rect.top,
src_dc, 0, 0, SRCCOPY);*
```

So I added an alpha_blend step here instead of simply using the original
BitBlt.

```
    s1 = src_data;
    d1 = dst_data;
    for (int i = 0; i < height; i++)
    {
        for (int j = 0; j < width; j++)
        {
            // src is alpha pre multiple
            float bg_alpha = ((255.f - s1[3])) / 255;
            d1[0] = (d1[0] * bg_alpha) + s1[0];
            d1[1] = (d1[1] * bg_alpha) + s1[1];
            d1[2] = (d1[2] * bg_alpha) + s1[2];

            s1 += 4;
            d1 += 4;
        }
    }

    //iret = SetDIBits(dst_hdc, dst_bitmap, 0, height, dst_data, &bmi,
DIB_RGB_COLORS);
    iret = SetDIBitsToDevice(dst_hdc, 0, 0, width, height,
        0, 0, 0, height, dst_data, &bmi, DIB_RGB_COLORS);
```
The new display effect is as follows.
[image: dcomp_test_wine_alpha_blend.png]
It looks like basic blending is working, but the alpha values of the
circles are lost. After analyzing the issue, I found the following cause.


I'll draw a diagram to briefly illustrate the cause of this issue.

My original expectation of the image generation process

[image: flush1.png]

But the actual process is as follows

[image: image.png]

After the bitmap is alpha-blended and displayed on the screen, it is
retrieved again in the next frame and repeatedly involved in alpha blending
— resulting in redundant computations.



I personally think that a more reasonable solution would be to insert
window_surface_composition within window_surface_flush to more thoroughly
resolve these kinds of issues

[image: image.png]


During window_surface_flush, composite the current surface with the
swapchain's surface into an offscreen surface, then flush that to the
screen. This way, the original window surface won't be affected.

I'm trying to fix this issue now — do you have any suggestions?
dcomp_test_window.png (image/png, 37.5 KB) - not displayed
dcomp_test_wine.png (image/png, 13.4 KB) - not displayed
dcomp_test_wine_alpha_blend.png (image/png, 13.1 KB) - not displayed
flush1.png (image/png, 12.2 KB) - not displayed
image.png (image/png, 11.6 KB) - not displayed
image.png (image/png, 15.8 KB) - not displayed