Use DWMEnableBlurBehindWindow instead of WS_EX_LAYERED
Affects per-pixel transparency The current method renders to the screen by copying the GLES output to a DIB for transparency using the CPU instead of rendering directly to the window via the GPU. This is slower and also forces the window to be borderless as WS_EX_LAYERED affects the non-client region as well. This change uses DWMEnableBlurBehindWindow which allows using the standard glClearColor() background alpha and is also performed through the GPU, eliminating CPU bottlenecks
This commit is contained in:
parent
aa57bb0473
commit
9584f24be5
5 changed files with 15 additions and 123 deletions
|
@ -247,10 +247,6 @@ public:
|
|||
virtual bool get_window_per_pixel_transparency_enabled() const { return false; }
|
||||
virtual void set_window_per_pixel_transparency_enabled(bool p_enabled) {}
|
||||
|
||||
virtual uint8_t *get_layered_buffer_data() { return NULL; }
|
||||
virtual Size2 get_layered_buffer_size() { return Size2(0, 0); }
|
||||
virtual void swap_layered_buffer() {}
|
||||
|
||||
virtual void set_ime_active(const bool p_active) {}
|
||||
virtual void set_ime_position(const Point2 &p_pos) {}
|
||||
virtual Point2 get_ime_selection() const { return Point2(); }
|
||||
|
|
|
@ -448,18 +448,7 @@ void RasterizerGLES2::output_lens_distorted_to_screen(RID p_render_target, const
|
|||
void RasterizerGLES2::end_frame(bool p_swap_buffers) {
|
||||
|
||||
if (OS::get_singleton()->is_layered_allowed()) {
|
||||
if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
|
||||
#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED)
|
||||
Size2 wndsize = OS::get_singleton()->get_layered_buffer_size();
|
||||
uint8_t *data = OS::get_singleton()->get_layered_buffer_data();
|
||||
if (data) {
|
||||
glReadPixels(0, 0, wndsize.x, wndsize.y, GL_BGRA, GL_UNSIGNED_BYTE, data);
|
||||
OS::get_singleton()->swap_layered_buffer();
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if (!OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
|
||||
//clear alpha
|
||||
glColorMask(false, false, false, true);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
|
|
|
@ -372,18 +372,7 @@ void RasterizerGLES3::output_lens_distorted_to_screen(RID p_render_target, const
|
|||
void RasterizerGLES3::end_frame(bool p_swap_buffers) {
|
||||
|
||||
if (OS::get_singleton()->is_layered_allowed()) {
|
||||
if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
|
||||
#if (defined WINDOWS_ENABLED) && !(defined UWP_ENABLED)
|
||||
Size2 wndsize = OS::get_singleton()->get_layered_buffer_size();
|
||||
uint8_t *data = OS::get_singleton()->get_layered_buffer_data();
|
||||
if (data) {
|
||||
glReadPixels(0, 0, wndsize.x, wndsize.y, GL_BGRA, GL_UNSIGNED_BYTE, data);
|
||||
OS::get_singleton()->swap_layered_buffer();
|
||||
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
} else {
|
||||
if (!OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
|
||||
//clear alpha
|
||||
glColorMask(false, false, false, true);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
|
|
|
@ -974,27 +974,6 @@ LRESULT OS_Windows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|||
maximized = false;
|
||||
minimized = false;
|
||||
}
|
||||
if (is_layered_allowed() && layered_window) {
|
||||
DeleteObject(hBitmap);
|
||||
|
||||
RECT r;
|
||||
GetWindowRect(hWnd, &r);
|
||||
dib_size = Size2i(r.right - r.left, r.bottom - r.top);
|
||||
|
||||
BITMAPINFO bmi;
|
||||
ZeroMemory(&bmi, sizeof(BITMAPINFO));
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = dib_size.x;
|
||||
bmi.bmiHeader.biHeight = dib_size.y;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biSizeImage = dib_size.x * dib_size.y * 4;
|
||||
hBitmap = CreateDIBSection(hDC_dib, &bmi, DIB_RGB_COLORS, (void **)&dib_data, NULL, 0x0);
|
||||
SelectObject(hDC_dib, hBitmap);
|
||||
|
||||
ZeroMemory(dib_data, dib_size.x * dib_size.y * 4);
|
||||
}
|
||||
//return 0; // Jump Back
|
||||
} break;
|
||||
|
||||
|
@ -2233,77 +2212,29 @@ void OS_Windows::set_window_per_pixel_transparency_enabled(bool p_enabled) {
|
|||
if (p_enabled) {
|
||||
set_borderless_window(true);
|
||||
//enable per-pixel alpha
|
||||
hDC_dib = CreateCompatibleDC(GetDC(hWnd));
|
||||
|
||||
SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) | WS_EX_LAYERED);
|
||||
|
||||
RECT r;
|
||||
GetWindowRect(hWnd, &r);
|
||||
dib_size = Size2(r.right - r.left, r.bottom - r.top);
|
||||
|
||||
BITMAPINFO bmi;
|
||||
ZeroMemory(&bmi, sizeof(BITMAPINFO));
|
||||
bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
|
||||
bmi.bmiHeader.biWidth = dib_size.x;
|
||||
bmi.bmiHeader.biHeight = dib_size.y;
|
||||
bmi.bmiHeader.biPlanes = 1;
|
||||
bmi.bmiHeader.biBitCount = 32;
|
||||
bmi.bmiHeader.biCompression = BI_RGB;
|
||||
bmi.bmiHeader.biSizeImage = dib_size.x * dib_size.y * 4;
|
||||
hBitmap = CreateDIBSection(hDC_dib, &bmi, DIB_RGB_COLORS, (void **)&dib_data, NULL, 0x0);
|
||||
SelectObject(hDC_dib, hBitmap);
|
||||
|
||||
ZeroMemory(dib_data, dib_size.x * dib_size.y * 4);
|
||||
DWM_BLURBEHIND bb = { 0 };
|
||||
HRGN hRgn = CreateRectRgn(0, 0, -1, -1);
|
||||
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
|
||||
bb.hRgnBlur = hRgn;
|
||||
bb.fEnable = TRUE;
|
||||
DwmEnableBlurBehindWindow(hWnd, &bb);
|
||||
|
||||
layered_window = true;
|
||||
} else {
|
||||
//disable per-pixel alpha
|
||||
layered_window = false;
|
||||
|
||||
SetWindowLong(hWnd, GWL_EXSTYLE, GetWindowLong(hWnd, GWL_EXSTYLE) & ~WS_EX_LAYERED);
|
||||
|
||||
//cleanup
|
||||
DeleteObject(hBitmap);
|
||||
DeleteDC(hDC_dib);
|
||||
DWM_BLURBEHIND bb = { 0 };
|
||||
HRGN hRgn = CreateRectRgn(0, 0, -1, -1);
|
||||
bb.dwFlags = DWM_BB_ENABLE | DWM_BB_BLURREGION;
|
||||
bb.hRgnBlur = hRgn;
|
||||
bb.fEnable = FALSE;
|
||||
DwmEnableBlurBehindWindow(hWnd, &bb);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t *OS_Windows::get_layered_buffer_data() {
|
||||
|
||||
return (is_layered_allowed() && layered_window) ? dib_data : NULL;
|
||||
}
|
||||
|
||||
Size2 OS_Windows::get_layered_buffer_size() {
|
||||
|
||||
return (is_layered_allowed() && layered_window) ? dib_size : Size2();
|
||||
}
|
||||
|
||||
void OS_Windows::swap_layered_buffer() {
|
||||
|
||||
if (is_layered_allowed() && layered_window) {
|
||||
|
||||
//premultiply alpha
|
||||
for (int y = 0; y < dib_size.y; y++) {
|
||||
for (int x = 0; x < dib_size.x; x++) {
|
||||
float alpha = (float)dib_data[y * (int)dib_size.x * 4 + x * 4 + 3] / (float)0xFF;
|
||||
dib_data[y * (int)dib_size.x * 4 + x * 4 + 0] *= alpha;
|
||||
dib_data[y * (int)dib_size.x * 4 + x * 4 + 1] *= alpha;
|
||||
dib_data[y * (int)dib_size.x * 4 + x * 4 + 2] *= alpha;
|
||||
}
|
||||
}
|
||||
//swap layered window buffer
|
||||
POINT ptSrc = { 0, 0 };
|
||||
SIZE sizeWnd = { (long)dib_size.x, (long)dib_size.y };
|
||||
BLENDFUNCTION bf;
|
||||
bf.BlendOp = AC_SRC_OVER;
|
||||
bf.BlendFlags = 0;
|
||||
bf.AlphaFormat = AC_SRC_ALPHA;
|
||||
bf.SourceConstantAlpha = 0xFF;
|
||||
UpdateLayeredWindow(hWnd, NULL, NULL, &sizeWnd, hDC_dib, &ptSrc, 0, &bf, ULW_ALPHA);
|
||||
}
|
||||
}
|
||||
|
||||
void OS_Windows::set_borderless_window(bool p_borderless) {
|
||||
if (video_mode.borderless_window == p_borderless)
|
||||
return;
|
||||
|
@ -3477,7 +3408,6 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) {
|
|||
drop_events = false;
|
||||
key_event_pos = 0;
|
||||
layered_window = false;
|
||||
hBitmap = NULL;
|
||||
force_quit = false;
|
||||
alt_mem = false;
|
||||
gr_mem = false;
|
||||
|
@ -3534,11 +3464,6 @@ OS_Windows::~OS_Windows() {
|
|||
wintab_WTClose(wtctx);
|
||||
wtctx = 0;
|
||||
}
|
||||
|
||||
if (is_layered_allowed() && layered_window) {
|
||||
DeleteObject(hBitmap);
|
||||
DeleteDC(hDC_dib);
|
||||
}
|
||||
#ifdef STDOUT_FILE
|
||||
fclose(stdo);
|
||||
#endif
|
||||
|
|
|
@ -49,6 +49,7 @@
|
|||
#include "drivers/xaudio2/audio_driver_xaudio2.h"
|
||||
#endif
|
||||
|
||||
#include <dwmapi.h>
|
||||
#include <fcntl.h>
|
||||
#include <io.h>
|
||||
#include <stdio.h>
|
||||
|
@ -297,10 +298,6 @@ class OS_Windows : public OS {
|
|||
HWND hWnd;
|
||||
Point2 last_pos;
|
||||
|
||||
HBITMAP hBitmap; //DIB section for layered window
|
||||
uint8_t *dib_data;
|
||||
Size2 dib_size;
|
||||
HDC hDC_dib;
|
||||
bool layered_window;
|
||||
|
||||
uint32_t move_timer_id;
|
||||
|
@ -452,10 +449,6 @@ public:
|
|||
virtual bool get_window_per_pixel_transparency_enabled() const;
|
||||
virtual void set_window_per_pixel_transparency_enabled(bool p_enabled);
|
||||
|
||||
virtual uint8_t *get_layered_buffer_data();
|
||||
virtual Size2 get_layered_buffer_size();
|
||||
virtual void swap_layered_buffer();
|
||||
|
||||
virtual Error open_dynamic_library(const String p_path, void *&p_library_handle, bool p_also_set_library_path = false);
|
||||
virtual Error close_dynamic_library(void *p_library_handle);
|
||||
virtual Error get_dynamic_library_symbol_handle(void *p_library_handle, const String p_name, void *&p_symbol_handle, bool p_optional = false);
|
||||
|
|
Loading…
Reference in a new issue