Win32: Disable fb transparency when it is broken
On Windows 7, when GLFW framebuffer transparency and the DWM are enabled but DWM transparency is disabled (i.e. when the Transparency setting is disabled under Personalization > Color), the contents of the framebuffer is combined with the last frame using additive blending instead of replacing the previous contents. This commit limits GLFW framebuffer transparency on Windows 7 to when DWM transparency is enabled, removing the previous workaround of setting a layered window color key that led to rendering artifacts. Fixes #1512.
This commit is contained in:
parent
a2674a9034
commit
05dd2fa298
@ -143,6 +143,8 @@ information on what to include when reporting a bug.
|
|||||||
- [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access
|
- [Win32] Added the `GLFW_WIN32_KEYBOARD_MENU` window hint for enabling access
|
||||||
to the window menu
|
to the window menu
|
||||||
- [Win32] Added a version info resource to the GLFW DLL
|
- [Win32] Added a version info resource to the GLFW DLL
|
||||||
|
- [Win32] Disabled framebuffer transparency on Windows 7 when DWM windows are
|
||||||
|
opaque (#1512)
|
||||||
- [Win32] Bugfix: `GLFW_INCLUDE_VULKAN` plus `VK_USE_PLATFORM_WIN32_KHR` caused
|
- [Win32] Bugfix: `GLFW_INCLUDE_VULKAN` plus `VK_USE_PLATFORM_WIN32_KHR` caused
|
||||||
symbol redefinition (#1524)
|
symbol redefinition (#1524)
|
||||||
- [Win32] Bugfix: The cursor position event was emitted before its cursor enter
|
- [Win32] Bugfix: The cursor position event was emitted before its cursor enter
|
||||||
|
@ -97,6 +97,13 @@ GLFW no longer depends on the CoreVideo framework on macOS and it no longer
|
|||||||
needs to be specified during compilation or linking.
|
needs to be specified during compilation or linking.
|
||||||
|
|
||||||
|
|
||||||
|
@subsubsection caveat_fbtransparency_34 Framebuffer transparency requires DWM transparency
|
||||||
|
|
||||||
|
GLFW no longer supports framebuffer transparency enabled via @ref
|
||||||
|
GLFW_TRANSPARENT_FRAMEBUFFER on Windows 7 if DWM transparency is off
|
||||||
|
(the Transparency setting under Personalization > Window Color).
|
||||||
|
|
||||||
|
|
||||||
@subsection deprecations_34 Deprecations in version 3.4
|
@subsection deprecations_34 Deprecations in version 3.4
|
||||||
|
|
||||||
@subsection removals_34 Removals in 3.4
|
@subsection removals_34 Removals in 3.4
|
||||||
|
@ -234,13 +234,6 @@ alpha channel will be used to combine the framebuffer with the background. This
|
|||||||
does not affect window decorations. Possible values are `GLFW_TRUE` and
|
does not affect window decorations. Possible values are `GLFW_TRUE` and
|
||||||
`GLFW_FALSE`.
|
`GLFW_FALSE`.
|
||||||
|
|
||||||
@par
|
|
||||||
@win32 GLFW sets a color key for the window to work around repainting issues
|
|
||||||
with a transparent framebuffer. The chosen color value is RGB 255,0,255
|
|
||||||
(magenta). This will make pixels with that exact color fully transparent
|
|
||||||
regardless of their alpha values. If this is a problem, make these pixels any
|
|
||||||
other color before buffer swap.
|
|
||||||
|
|
||||||
@anchor GLFW_FOCUS_ON_SHOW_hint
|
@anchor GLFW_FOCUS_ON_SHOW_hint
|
||||||
__GLFW_FOCUS_ON_SHOW__ specifies whether the window will be given input
|
__GLFW_FOCUS_ON_SHOW__ specifies whether the window will be given input
|
||||||
focus when @ref glfwShowWindow is called. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
focus when @ref glfwShowWindow is called. Possible values are `GLFW_TRUE` and `GLFW_FALSE`.
|
||||||
|
@ -143,6 +143,8 @@ static GLFWbool loadLibraries(void)
|
|||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmFlush");
|
||||||
_glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
|
_glfw.win32.dwmapi.EnableBlurBehindWindow = (PFN_DwmEnableBlurBehindWindow)
|
||||||
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmEnableBlurBehindWindow");
|
||||||
|
_glfw.win32.dwmapi.GetColorizationColor = (PFN_DwmGetColorizationColor)
|
||||||
|
GetProcAddress(_glfw.win32.dwmapi.instance, "DwmGetColorizationColor");
|
||||||
}
|
}
|
||||||
|
|
||||||
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
|
_glfw.win32.shcore.instance = LoadLibraryA("shcore.dll");
|
||||||
|
@ -77,6 +77,9 @@
|
|||||||
#ifndef WM_DWMCOMPOSITIONCHANGED
|
#ifndef WM_DWMCOMPOSITIONCHANGED
|
||||||
#define WM_DWMCOMPOSITIONCHANGED 0x031E
|
#define WM_DWMCOMPOSITIONCHANGED 0x031E
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef WM_DWMCOLORIZATIONCOLORCHANGED
|
||||||
|
#define WM_DWMCOLORIZATIONCOLORCHANGED 0x0320
|
||||||
|
#endif
|
||||||
#ifndef WM_COPYGLOBALDATA
|
#ifndef WM_COPYGLOBALDATA
|
||||||
#define WM_COPYGLOBALDATA 0x0049
|
#define WM_COPYGLOBALDATA 0x0049
|
||||||
#endif
|
#endif
|
||||||
@ -244,9 +247,11 @@ typedef BOOL (WINAPI * PFN_AdjustWindowRectExForDpi)(LPRECT,DWORD,BOOL,DWORD,UIN
|
|||||||
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
typedef HRESULT (WINAPI * PFN_DwmIsCompositionEnabled)(BOOL*);
|
||||||
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
typedef HRESULT (WINAPI * PFN_DwmFlush)(VOID);
|
||||||
typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
|
typedef HRESULT(WINAPI * PFN_DwmEnableBlurBehindWindow)(HWND,const DWM_BLURBEHIND*);
|
||||||
|
typedef HRESULT (WINAPI * PFN_DwmGetColorizationColor)(DWORD*,BOOL*);
|
||||||
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
|
#define DwmIsCompositionEnabled _glfw.win32.dwmapi.IsCompositionEnabled
|
||||||
#define DwmFlush _glfw.win32.dwmapi.Flush
|
#define DwmFlush _glfw.win32.dwmapi.Flush
|
||||||
#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
|
#define DwmEnableBlurBehindWindow _glfw.win32.dwmapi.EnableBlurBehindWindow
|
||||||
|
#define DwmGetColorizationColor _glfw.win32.dwmapi.GetColorizationColor
|
||||||
|
|
||||||
// shcore.dll function pointer typedefs
|
// shcore.dll function pointer typedefs
|
||||||
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
typedef HRESULT (WINAPI * PFN_SetProcessDpiAwareness)(PROCESS_DPI_AWARENESS);
|
||||||
@ -368,6 +373,7 @@ typedef struct _GLFWlibraryWin32
|
|||||||
PFN_DwmIsCompositionEnabled IsCompositionEnabled;
|
PFN_DwmIsCompositionEnabled IsCompositionEnabled;
|
||||||
PFN_DwmFlush Flush;
|
PFN_DwmFlush Flush;
|
||||||
PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
|
PFN_DwmEnableBlurBehindWindow EnableBlurBehindWindow;
|
||||||
|
PFN_DwmGetColorizationColor GetColorizationColor;
|
||||||
} dwmapi;
|
} dwmapi;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
@ -377,12 +377,17 @@ static void updateWindowStyles(const _GLFWwindow* window)
|
|||||||
//
|
//
|
||||||
static void updateFramebufferTransparency(const _GLFWwindow* window)
|
static void updateFramebufferTransparency(const _GLFWwindow* window)
|
||||||
{
|
{
|
||||||
BOOL enabled;
|
BOOL composition, opaque;
|
||||||
|
DWORD color;
|
||||||
|
|
||||||
if (!IsWindowsVistaOrGreater())
|
if (!IsWindowsVistaOrGreater())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
|
if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (IsWindows8OrGreater() ||
|
||||||
|
(SUCCEEDED(DwmGetColorizationColor(&color, &opaque)) && !opaque))
|
||||||
{
|
{
|
||||||
HRGN region = CreateRectRgn(0, 0, -1, -1);
|
HRGN region = CreateRectRgn(0, 0, -1, -1);
|
||||||
DWM_BLURBEHIND bb = {0};
|
DWM_BLURBEHIND bb = {0};
|
||||||
@ -390,42 +395,18 @@ static void updateFramebufferTransparency(const _GLFWwindow* window)
|
|||||||
bb.hRgnBlur = region;
|
bb.hRgnBlur = region;
|
||||||
bb.fEnable = TRUE;
|
bb.fEnable = TRUE;
|
||||||
|
|
||||||
if (SUCCEEDED(DwmEnableBlurBehindWindow(window->win32.handle, &bb)))
|
DwmEnableBlurBehindWindow(window->win32.handle, &bb);
|
||||||
{
|
|
||||||
// Decorated windows don't repaint the transparent background
|
|
||||||
// leaving a trail behind animations
|
|
||||||
// HACK: Making the window layered with a transparency color key
|
|
||||||
// seems to fix this. Normally, when specifying
|
|
||||||
// a transparency color key to be used when composing the
|
|
||||||
// layered window, all pixels painted by the window in this
|
|
||||||
// color will be transparent. That doesn't seem to be the
|
|
||||||
// case anymore, at least when used with blur behind window
|
|
||||||
// plus negative region.
|
|
||||||
LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
|
||||||
exStyle |= WS_EX_LAYERED;
|
|
||||||
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
|
|
||||||
|
|
||||||
// Using a color key not equal to black to fix the trailing
|
|
||||||
// issue. When set to black, something is making the hit test
|
|
||||||
// not resize with the window frame.
|
|
||||||
SetLayeredWindowAttributes(window->win32.handle,
|
|
||||||
RGB(255, 0, 255), 255, LWA_COLORKEY);
|
|
||||||
}
|
|
||||||
|
|
||||||
DeleteObject(region);
|
DeleteObject(region);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
LONG exStyle = GetWindowLongW(window->win32.handle, GWL_EXSTYLE);
|
// HACK: Disable framebuffer transparency on Windows 7 when the
|
||||||
if (exStyle & WS_EX_TRANSPARENT)
|
// colorization color is opaque, because otherwise the window
|
||||||
SetLayeredWindowAttributes(window->win32.handle, 0, 0, 0);
|
// contents is blended additively with the previous frame instead
|
||||||
else
|
// of replacing it
|
||||||
{
|
DWM_BLURBEHIND bb = {0};
|
||||||
exStyle &= ~WS_EX_LAYERED;
|
bb.dwFlags = DWM_BB_ENABLE;
|
||||||
SetWindowLongW(window->win32.handle, GWL_EXSTYLE, exStyle);
|
DwmEnableBlurBehindWindow(window->win32.handle, &bb);
|
||||||
RedrawWindow(window->win32.handle, NULL, NULL,
|
|
||||||
RDW_ERASE | RDW_INVALIDATE | RDW_FRAME);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1109,6 +1090,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
case WM_DWMCOMPOSITIONCHANGED:
|
case WM_DWMCOMPOSITIONCHANGED:
|
||||||
|
case WM_DWMCOLORIZATIONCOLORCHANGED:
|
||||||
{
|
{
|
||||||
if (window->win32.transparent)
|
if (window->win32.transparent)
|
||||||
updateFramebufferTransparency(window);
|
updateFramebufferTransparency(window);
|
||||||
@ -1834,7 +1816,8 @@ int _glfwPlatformWindowHovered(_GLFWwindow* window)
|
|||||||
|
|
||||||
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
BOOL enabled;
|
BOOL composition, opaque;
|
||||||
|
DWORD color;
|
||||||
|
|
||||||
if (!window->win32.transparent)
|
if (!window->win32.transparent)
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
@ -1842,7 +1825,20 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
|
|||||||
if (!IsWindowsVistaOrGreater())
|
if (!IsWindowsVistaOrGreater())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
|
||||||
return SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled;
|
if (FAILED(DwmIsCompositionEnabled(&composition)) || !composition)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
|
||||||
|
if (!IsWindows8OrGreater())
|
||||||
|
{
|
||||||
|
// HACK: Disable framebuffer transparency on Windows 7 when the
|
||||||
|
// colorization color is opaque, because otherwise the window
|
||||||
|
// contents is blended additively with the previous frame instead
|
||||||
|
// of replacing it
|
||||||
|
if (FAILED(DwmGetColorizationColor(&color, &opaque)) || opaque)
|
||||||
|
return GLFW_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, GLFWbool enabled)
|
||||||
@ -1877,11 +1873,11 @@ void _glfwPlatformSetWindowMousePassthrough(_GLFWwindow* window, GLFWbool enable
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
exStyle &= ~WS_EX_TRANSPARENT;
|
exStyle &= ~WS_EX_TRANSPARENT;
|
||||||
// NOTE: Window opacity and framebuffer transparency also need to
|
// NOTE: Window opacity also needs the layered window style so do not
|
||||||
// control the layered style so avoid stepping on their feet
|
// remove it if the window is alpha blended
|
||||||
if (exStyle & WS_EX_LAYERED)
|
if (exStyle & WS_EX_LAYERED)
|
||||||
{
|
{
|
||||||
if (!(flags & (LWA_ALPHA | LWA_COLORKEY)))
|
if (!(flags & LWA_ALPHA))
|
||||||
exStyle &= ~WS_EX_LAYERED;
|
exStyle &= ~WS_EX_LAYERED;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user