Or pass a user-level callback into win32u, and have it invoked inside win32u:composite? This might require adding a new syscall — not sure if that would make things simpler?
On Thu, Jun 19, 2025 at 3:48 PM Zhiyi Zhang zzhang@codeweavers.com wrote:
On 6/19/25 14:13, zhengxianwei wrote:
Zhiyi Zhang provided an implementation of DComp composition:
https://gitlab.winehq.org/zhiyi/wine/-/commit/ef4f90c2ae909f4a732f0ebeae3b7e... < https://gitlab.winehq.org/zhiyi/wine/-/commit/ef4f90c2ae909f4a732f0ebeae3b7e...
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.
dcomp_test_window.png
But on Linux, it display as follows. 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. 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
flush1.png
But the actual process is as follows
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.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.
Sounds reasonable.
I'm trying to fix this issue now — do you have any suggestions?