glfw icon indicating copy to clipboard operation
glfw copied to clipboard

Transparent background not reliable on laptop (Windows 11).

Open TimothyHoytBSME opened this issue 11 months ago • 15 comments

I'm using an undecorated window set to transparent background. Clearing GL to alpha 0 works if primary monitor is external, but if laptop's built-in monitor is set to primary, window becomes opaque.

I saw there were some old related issues, but they are not fully resolved.

Essentially, I want a splash screen or overlay with transparent areas within the window, that works with Windows composition. Are there really no solutions? Any way to detect in software if the transparency is working?

Any reliable solutions outside GLFW?

TimothyHoytBSME avatar May 02 '25 07:05 TimothyHoytBSME

I don't know a whole lot about the way Windows handles its windowing, but this seems to me like a hardware/OS issue. Unfortunately, I don't think there's anything GLFW could do to even detect this.

ghost avatar May 07 '25 03:05 ghost

@israfiel-a I'm not the first to encounter it, and I'm pretty sure it's the DWM trying to save power or whatever, but I too am not very familiar with these things. I'm hoping someone will know a way to fix or detect. Right now, any transparent background opengl window may or may not actually be transparent and there's no way to tell or control it. I tried various things with the Win32 api, but nothing worked. I think it's also an issue with other windowing libraries, so yes, an OS problem.

TimothyHoytBSME avatar May 07 '25 04:05 TimothyHoytBSME

I tried various things with the Win32 api, but nothing worked. I think it's also an issue with other windowing libraries, so yes, an OS problem.

what have you tried? SetLayeredWindowAttributes works fine for pure Win32 calls. checking glfw source, apparently glfw also use same exact function.

perhaps you want to post some code that you tried and didnt work.

I tried everything i could find, including all the obvious things like doing the exact same thing GLFW does under the hood. When an external monitor is set as primary, it works. When the attached monitor is set as primary, it doesn't, including when it's the only monitor. There's no need to list code that doesn't work that I have already deleted, as that will not provide or lead to a solution. This is a known issue with laptops and DWM as I've said, and I'm just hoping someone has found a solution. Someone who is familiar with the problem. If not, I will escalate to Microsoft (fat lot of good that'll do).

TimothyHoytBSME avatar May 09 '25 20:05 TimothyHoytBSME

When the attached monitor is set as primary, it doesn't, including when it's the only monitor. There's no need to list code that doesn't work that I have already deleted, as that will not provide or lead to a solution. This is a known issue with laptops and DWM as I've said

sorry but I dont see the things you mentioned. I have tested one of my software (closed source tool) on Windows 11 Laptop, transparency worked fine, I didnt see DWM interfering with my tool.

It's apparently only an issue on some laptops due to how the DWM is set up per machine, maybe for power management. I can link the old issue I found if you'd like. But if you have something working, I'd be curious if it worked on my machine.

TimothyHoytBSME avatar May 09 '25 22:05 TimothyHoytBSME

Here is one example of the issue

https://github.com/glfw/glfw/issues/1288

TimothyHoytBSME avatar May 09 '25 22:05 TimothyHoytBSME

To be fair, the GLFW docs specifically state that transparent framebuffer only works if the OS allows it, since it relies on the Win32 call. And this seems to be a very niche problem only on certain machines and drivers. It's just unfortunate. Like I said, It works in most cases, just not specifically my machine when the main screen is set to primary. It seems to disable the composition.

TimothyHoytBSME avatar May 09 '25 22:05 TimothyHoytBSME

#1288

my tool was running on Intel's igpu (CPU) just like the mentioned issue, worked fine.

I will post update when I have time to test again but force running on Integrated Nvidia GPU. (I have this gut feeling it will fail to run but time will tell)

Yeah I've encountered this same issue... I've tried almost everything you can imagine... just for some reason when using dual monitors, since it selects the iGPU as the display mode (dGPU for rendering in-app), it'll fail compositing with vk but not dx12 (I got it to work on dx12)... I'm still investigating into the issue myself and have been for a long time, currently talking with AMD support about it but I doubt it'll go anywhere (AMD is my iGPU it'll select)...

As for the formerly mentioned SetLayeredWindowAttributes... that does work, I've tried it, but sadly it doesn't do per-pixel alpha blending but instead the entire image...

If something comes up and I remember this, I might reply back... vk swapchain is a very annoying thing if you want to do anything nice with it.

Stanlyhalo avatar May 10 '25 02:05 Stanlyhalo

To add some context, I am using OpenGL, and even with just one screen, the built-in one, the composition fails. Any configuration with the built-in as primary fails. Even if I could verify in the application that it was failing, I could logically switch techniques, but all methods found say it's working when it's not, like testing the pixel color or pinging the Win32 layer status, all come back as if it is "transparent" but the background is actually black. Using up to date Nvidia drivers on rtx2070. I haven't tried the integrated graphics, but I need it performant. GPT also says it's the DWM and there's no solution. I just feel there has to be some obscure windows call to check the composition status or force it, but no dice.

TimothyHoytBSME avatar May 10 '25 03:05 TimothyHoytBSME

As for the formerly mentioned SetLayeredWindowAttributes... that does work, I've tried it, but sadly it doesn't do per-pixel alpha blending but instead the entire image...

use color keying instead of alpha.

...

Tim, indeed just as linked issue, force running on Nvidia GPU with TRANSPARENT_FRAMEBUFFER set to true, it shows black.

however I worked around it by not setting this hint, and instead I query window HWND (glfwGetWin32Window), set layered style manually, call SetLayeredWindowAttributes with colorkeying instead of alpha. (alpha affect whole window, colorkey affect individual pixels)

while it is hacky, it works fine, but care should be taken, the colorkey for SetLayeredWindowAttributes MUST be same as color used to clear color bit buffer, i.e. glClearColor. (something like fuchsia may be good)

edit: to update only specific part of your window, use UpdateLayeredWindow.

Thanks, that is the one solution I was hoping to avoid, but if it's the only one, I'll consider it. It just means I'll need A giant warning to anyone using my software to not use the color or to change it.

TimothyHoytBSME avatar May 10 '25 17:05 TimothyHoytBSME

You might want to check what is going on in the updateFramebufferTransparency function:

https://github.com/glfw/glfw/blob/master/src/win32_window.c#L372-L405

You can use the gears.c example code to test this, as it sets a transparent framebuffer.

This works for me on AMD and NVIDIA discrete GPUs, I do not have a laptop with iGPU / dGPU combo to test with.

dougbinks avatar May 12 '25 11:05 dougbinks

Gears.c just calls the standard glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GLFW_TRUE);

Which, again, works when I use a secondary monitor as primary, but not when main is primary. Both cases use discrete gpu. If I set a secondary as primary the transparency works even on my attached monitor. It is certainly a some sort of switching happening behind the scenes.

I think I've already tried directly checking the same functions as what's in the update transparency function, and they pass, but I'll try again.

TimothyHoytBSME avatar May 12 '25 18:05 TimothyHoytBSME