Re: Does the timing of composition need to be moved from dcomp.dll to win32u?
zhengxianwei <[email protected]> Thu, 19 Jun 2025 16:28:44 +0800
| Newsgroups | gmane.comp.emulators.wine.devel |
|---|---|
| Message-ID | <CABeGAqWEfptLGVbWFv3dnV3334w2WUyypieNQQsU1_cDLjV5jg@mail.gmail.com> |
The part that confuses me here is that, in *win32u*, it doesn't seem convenient to manipulate data structures like *swapchain*. In *dcomp.dll*, I can use a large number of COM interface functions, such as IDXGISwapChain1_GetDesc and IDXGISwapChain1_GetBuffer. But is this allowed in *win32u*? If I were to heavily use COM interfaces within *win32u*, would that cause any issues? On Thu, Jun 19, 2025 at 3:48 PM Zhiyi Zhang <[email protected]> wrote: > > > On 6/19/25 14:13, zhengxianwei wrote: > > Zhiyi Zhang provided an implementation of DComp composition: > > > https://gitlab.winehq.org/zhiyi/wine/-/commit/ef4f90c2ae909f4a732f0ebeae3b7e98479cd63d > < > 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. > > > > 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? > > > > > > > > > >