summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/bind/core_bind.cpp12
-rw-r--r--core/bind/core_bind.h3
-rw-r--r--core/os/os.cpp1
-rw-r--r--core/os/os.h13
-rw-r--r--drivers/gles2/rasterizer_gles2.cpp49
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp48
-rw-r--r--main/main.cpp5
-rw-r--r--platform/osx/os_osx.h6
-rw-r--r--platform/osx/os_osx.mm42
-rw-r--r--platform/windows/os_windows.cpp121
-rw-r--r--platform/windows/os_windows.h13
-rw-r--r--platform/x11/context_gl_x11.cpp83
-rw-r--r--platform/x11/context_gl_x11.h1
-rw-r--r--platform/x11/detect.py6
-rw-r--r--platform/x11/os_x11.cpp31
-rw-r--r--platform/x11/os_x11.h6
16 files changed, 418 insertions, 22 deletions
diff --git a/core/bind/core_bind.cpp b/core/bind/core_bind.cpp
index 9c484f313e..3270b33f1c 100644
--- a/core/bind/core_bind.cpp
+++ b/core/bind/core_bind.cpp
@@ -336,6 +336,14 @@ void _OS::set_borderless_window(bool p_borderless) {
OS::get_singleton()->set_borderless_window(p_borderless);
}
+bool _OS::get_window_per_pixel_transparency_enabled() const {
+ return OS::get_singleton()->get_window_per_pixel_transparency_enabled();
+}
+
+void _OS::set_window_per_pixel_transparency_enabled(bool p_enabled) {
+ OS::get_singleton()->set_window_per_pixel_transparency_enabled(p_enabled);
+}
+
bool _OS::get_borderless_window() const {
return OS::get_singleton()->get_borderless_window();
}
@@ -1068,6 +1076,9 @@ void _OS::_bind_methods() {
ClassDB::bind_method(D_METHOD("set_borderless_window", "borderless"), &_OS::set_borderless_window);
ClassDB::bind_method(D_METHOD("get_borderless_window"), &_OS::get_borderless_window);
+ ClassDB::bind_method(D_METHOD("get_window_per_pixel_transparency_enabled"), &_OS::get_window_per_pixel_transparency_enabled);
+ ClassDB::bind_method(D_METHOD("set_window_per_pixel_transparency_enabled", "enabled"), &_OS::set_window_per_pixel_transparency_enabled);
+
ClassDB::bind_method(D_METHOD("set_ime_position", "position"), &_OS::set_ime_position);
ClassDB::bind_method(D_METHOD("set_screen_orientation", "orientation"), &_OS::set_screen_orientation);
@@ -1185,6 +1196,7 @@ void _OS::_bind_methods() {
ADD_PROPERTY(PropertyInfo(Variant::INT, "screen_orientation", PROPERTY_HINT_ENUM, "Landscape,Portrait,Reverse Landscape,Reverse Portrait,Sensor Landscape,Sensor Portrait,Sensor"), "set_screen_orientation", "get_screen_orientation");
ADD_GROUP("Window", "window_");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_borderless"), "set_borderless_window", "get_borderless_window");
+ ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_per_pixel_transparency_enabled"), "set_window_per_pixel_transparency_enabled", "get_window_per_pixel_transparency_enabled");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_fullscreen"), "set_window_fullscreen", "is_window_fullscreen");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_maximized"), "set_window_maximized", "is_window_maximized");
ADD_PROPERTY(PropertyInfo(Variant::BOOL, "window_minimized"), "set_window_minimized", "is_window_minimized");
diff --git a/core/bind/core_bind.h b/core/bind/core_bind.h
index 625cac25a0..a363f5970f 100644
--- a/core/bind/core_bind.h
+++ b/core/bind/core_bind.h
@@ -180,6 +180,9 @@ public:
virtual void set_borderless_window(bool p_borderless);
virtual bool get_borderless_window() const;
+ virtual bool get_window_per_pixel_transparency_enabled() const;
+ virtual void set_window_per_pixel_transparency_enabled(bool p_enabled);
+
virtual void set_ime_position(const Point2 &p_pos);
Error native_video_play(String p_path, float p_volume, String p_audio_track, String p_subtitle_track);
diff --git a/core/os/os.cpp b/core/os/os.cpp
index 854d554b10..5eed10e30c 100644
--- a/core/os/os.cpp
+++ b/core/os/os.cpp
@@ -672,6 +672,7 @@ OS::OS() {
_render_thread_mode = RENDER_THREAD_SAFE;
_allow_hidpi = false;
+ _allow_layered = false;
_stack_bottom = (void *)(&stack_bottom);
_logger = NULL;
diff --git a/core/os/os.h b/core/os/os.h
index f6404468b1..b36f94060c 100644
--- a/core/os/os.h
+++ b/core/os/os.h
@@ -65,6 +65,7 @@ class OS {
int _exit_code;
int _orientation;
bool _allow_hidpi;
+ bool _allow_layered;
bool _use_vsync;
char *last_error;
@@ -102,6 +103,8 @@ public:
bool maximized;
bool always_on_top;
bool use_vsync;
+ bool layered_splash;
+ bool layered;
float get_aspect() const { return (float)width / (float)height; }
VideoMode(int p_width = 1024, int p_height = 600, bool p_fullscreen = false, bool p_resizable = true, bool p_borderless_window = false, bool p_maximized = false, bool p_always_on_top = false, bool p_use_vsync = false) {
width = p_width;
@@ -112,6 +115,8 @@ public:
maximized = p_maximized;
always_on_top = p_always_on_top;
use_vsync = p_use_vsync;
+ layered = false;
+ layered_splash = false;
}
};
@@ -220,6 +225,13 @@ public:
virtual void set_borderless_window(bool p_borderless) {}
virtual bool get_borderless_window() { return 0; }
+ 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_position(const Point2 &p_pos) {}
virtual void set_ime_intermediate_text_callback(ImeCallback p_callback, void *p_inp) {}
@@ -481,6 +493,7 @@ public:
virtual void force_process_input(){};
bool has_feature(const String &p_feature);
+ bool is_layered_allowed() const { return _allow_layered; }
bool is_hidpi_allowed() const { return _allow_hidpi; }
OS();
virtual ~OS();
diff --git a/drivers/gles2/rasterizer_gles2.cpp b/drivers/gles2/rasterizer_gles2.cpp
index 9339167c8e..4626a5ed3c 100644
--- a/drivers/gles2/rasterizer_gles2.cpp
+++ b/drivers/gles2/rasterizer_gles2.cpp
@@ -316,7 +316,11 @@ void RasterizerGLES2::set_boot_image(const Ref<Image> &p_image, const Color &p_c
glViewport(0, 0, window_w, window_h);
glDisable(GL_BLEND);
glDepthMask(GL_FALSE);
- glClearColor(p_color.r, p_color.g, p_color.b, p_color.a);
+ if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ } else {
+ glClearColor(p_color.r, p_color.g, p_color.b, 1.0);
+ }
glClear(GL_COLOR_BUFFER_BIT);
canvas->canvas_begin();
@@ -340,6 +344,27 @@ void RasterizerGLES2::set_boot_image(const Ref<Image> &p_image, const Color &p_c
storage->free(texture);
+ if (OS::get_singleton()->is_layered_allowed()) {
+ if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
+#ifdef WINDOWS_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 {
+ //clear alpha
+ glColorMask(false, false, false, true);
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColorMask(true, true, true, true);
+ }
+ }
+
OS::get_singleton()->swap_buffers();
}
@@ -373,6 +398,28 @@ void RasterizerGLES2::blit_render_target_to_screen(RID p_render_target, const Re
}
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()) {
+#ifdef WINDOWS_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 {
+ //clear alpha
+ glColorMask(false, false, false, true);
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColorMask(true, true, true, true);
+ }
+ }
+
if (p_swap_buffers)
OS::get_singleton()->swap_buffers();
else
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 0fb69494f4..12e29827b0 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -290,7 +290,11 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
glViewport(0, 0, window_w, window_h);
glDisable(GL_BLEND);
glDepthMask(GL_FALSE);
- glClearColor(p_color.r, p_color.g, p_color.b, 1.0);
+ if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
+ glClearColor(0.0, 0.0, 0.0, 0.0);
+ } else {
+ glClearColor(p_color.r, p_color.g, p_color.b, 1.0);
+ }
glClear(GL_COLOR_BUFFER_BIT);
canvas->canvas_begin();
@@ -329,6 +333,27 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
storage->free(texture); // free since it's only one frame that stays there
+ if (OS::get_singleton()->is_layered_allowed()) {
+ if (OS::get_singleton()->get_window_per_pixel_transparency_enabled()) {
+#ifdef WINDOWS_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 {
+ //clear alpha
+ glColorMask(false, false, false, true);
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColorMask(true, true, true, true);
+ }
+ }
+
OS::get_singleton()->swap_buffers();
}
@@ -365,6 +390,27 @@ void RasterizerGLES3::blit_render_target_to_screen(RID p_render_target, const Re
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()) {
+#ifdef WINDOWS_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 {
+ //clear alpha
+ glColorMask(false, false, false, true);
+ glClearColor(0, 0, 0, 1);
+ glClear(GL_COLOR_BUFFER_BIT);
+ glColorMask(true, true, true, true);
+ }
+ }
+
if (p_swap_buffers)
OS::get_singleton()->swap_buffers();
else
diff --git a/main/main.cpp b/main/main.cpp
index 5959deb495..1c5540fd19 100644
--- a/main/main.cpp
+++ b/main/main.cpp
@@ -875,7 +875,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
OS::get_singleton()->_allow_hidpi = GLOBAL_DEF("display/window/dpi/allow_hidpi", false);
}
+ OS::get_singleton()->_allow_layered = GLOBAL_DEF("display/window/allow_per_pixel_transparency", false);
+
video_mode.use_vsync = GLOBAL_DEF("display/window/vsync/use_vsync", true);
+ video_mode.layered = GLOBAL_DEF("display/window/per_pixel_transparency", false);
+ video_mode.layered_splash = GLOBAL_DEF("display/window/per_pixel_transparency_splash", false);
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation", 2);
GLOBAL_DEF("rendering/quality/intended_usage/framebuffer_allocation.mobile", 3);
@@ -883,6 +887,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
if (editor || project_manager) {
// The editor and project manager always detect and use hiDPI if needed
OS::get_singleton()->_allow_hidpi = true;
+ OS::get_singleton()->_allow_layered = false;
}
Engine::get_singleton()->_pixel_snap = GLOBAL_DEF("rendering/quality/2d/use_pixel_snap", false);
diff --git a/platform/osx/os_osx.h b/platform/osx/os_osx.h
index fee25e98cb..c1022a1aca 100644
--- a/platform/osx/os_osx.h
+++ b/platform/osx/os_osx.h
@@ -99,6 +99,8 @@ public:
id pixelFormat;
id context;
+ bool layered_window;
+
CursorShape cursor_shape;
NSCursor *cursors[CURSOR_MAX];
MouseMode mouse_mode;
@@ -226,6 +228,10 @@ public:
virtual void set_borderless_window(bool p_borderless);
virtual bool get_borderless_window();
+
+ virtual bool get_window_per_pixel_transparency_enabled() const;
+ virtual void set_window_per_pixel_transparency_enabled(bool p_enabled);
+
virtual void set_ime_position(const Point2 &p_pos);
virtual void set_ime_intermediate_text_callback(ImeCallback p_callback, void *p_inp);
diff --git a/platform/osx/os_osx.mm b/platform/osx/os_osx.mm
index fbefd41bb7..eaf89f7d0f 100644
--- a/platform/osx/os_osx.mm
+++ b/platform/osx/os_osx.mm
@@ -1330,6 +1330,9 @@ Error OS_OSX::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
restore_rect = Rect2(get_window_position(), get_window_size());
+ if (p_desired.layered_splash) {
+ set_window_per_pixel_transparency_enabled(true);
+ }
return OK;
}
@@ -2042,6 +2045,8 @@ void OS_OSX::set_window_size(const Size2 p_size) {
void OS_OSX::set_window_fullscreen(bool p_enabled) {
if (zoomed != p_enabled) {
+ if (layered_window)
+ set_window_per_pixel_transparency_enabled(false);
[window_object toggleFullScreen:nil];
}
zoomed = p_enabled;
@@ -2123,6 +2128,39 @@ void OS_OSX::request_attention() {
[NSApp requestUserAttention:NSCriticalRequest];
}
+bool OS_OSX::get_window_per_pixel_transparency_enabled() const {
+
+ if (!is_layered_allowed()) return false;
+ return layered_window;
+}
+
+void OS_OSX::set_window_per_pixel_transparency_enabled(bool p_enabled) {
+
+ if (!is_layered_allowed()) return;
+ if (layered_window != p_enabled) {
+ if (p_enabled) {
+ set_borderless_window(true);
+ GLint opacity = 0;
+ [window_object setBackgroundColor:[NSColor clearColor]];
+ [window_object setOpaque:NO];
+ [window_object setHasShadow:NO];
+ [context setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity];
+ layered_window = true;
+ } else {
+ GLint opacity = 1;
+ [window_object setBackgroundColor:[NSColor colorWithCalibratedWhite:1 alpha:1]];
+ [window_object setOpaque:YES];
+ [window_object setHasShadow:YES];
+ [context setValues:&opacity forParameter:NSOpenGLCPSurfaceOpacity];
+ layered_window = false;
+ }
+ [context update];
+ NSRect frame = [window_object frame];
+ [window_object setFrame:NSMakeRect(frame.origin.x, frame.origin.y, 1, 1) display:YES];
+ [window_object setFrame:frame display:YES];
+ }
+}
+
void OS_OSX::set_borderless_window(bool p_borderless) {
// OrderOut prevents a lose focus bug with the window
@@ -2131,6 +2169,9 @@ void OS_OSX::set_borderless_window(bool p_borderless) {
if (p_borderless) {
[window_object setStyleMask:NSWindowStyleMaskBorderless];
} else {
+ if (layered_window)
+ set_window_per_pixel_transparency_enabled(false);
+
[window_object setStyleMask:NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable | NSWindowStyleMaskResizable];
// Force update of the window styles
@@ -2435,6 +2476,7 @@ OS_OSX::OS_OSX() {
im_position = Point2();
im_callback = NULL;
im_target = NULL;
+ layered_window = false;
autoreleasePool = [[NSAutoreleasePool alloc] init];
eventSource = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
diff --git a/platform/windows/os_windows.cpp b/platform/windows/os_windows.cpp
index 7b46608c55..54a5d91eb4 100644
--- a/platform/windows/os_windows.cpp
+++ b/platform/windows/os_windows.cpp
@@ -637,6 +637,28 @@ 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 = 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);
+ }
+ //return 0; // Jump Back
} break;
case WM_ENTERSIZEMOVE: {
@@ -1151,6 +1173,9 @@ Error OS_Windows::initialize(const VideoMode &p_desired, int p_video_driver, int
SetFocus(hWnd); // Sets Keyboard Focus To
}
+ if (p_desired.layered_splash) {
+ set_window_per_pixel_transparency_enabled(true);
+ }
return OK;
}
@@ -1542,6 +1567,9 @@ void OS_Windows::set_window_fullscreen(bool p_enabled) {
if (video_mode.fullscreen == p_enabled)
return;
+ if (layered_window)
+ set_window_per_pixel_transparency_enabled(false);
+
if (p_enabled) {
if (pre_fs_valid) {
@@ -1646,10 +1674,97 @@ bool OS_Windows::is_window_always_on_top() const {
return video_mode.always_on_top;
}
+bool OS_Windows::get_window_per_pixel_transparency_enabled() const {
+
+ if (!is_layered_allowed()) return false;
+ return layered_window;
+}
+
+void OS_Windows::set_window_per_pixel_transparency_enabled(bool p_enabled) {
+
+ if (!is_layered_allowed()) return;
+ if (layered_window != 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);
+
+ 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);
+ }
+ }
+}
+
+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;
+ if (!p_borderless && layered_window)
+ set_window_per_pixel_transparency_enabled(false);
+
video_mode.borderless_window = p_borderless;
_update_window_style();
@@ -2582,6 +2697,8 @@ Error OS_Windows::move_to_trash(const String &p_path) {
OS_Windows::OS_Windows(HINSTANCE _hInstance) {
key_event_pos = 0;
+ layered_window = false;
+ hBitmap = NULL;
force_quit = false;
alt_mem = false;
gr_mem = false;
@@ -2615,6 +2732,10 @@ OS_Windows::OS_Windows(HINSTANCE _hInstance) {
}
OS_Windows::~OS_Windows() {
+ if (is_layered_allowed() && layered_window) {
+ DeleteObject(hBitmap);
+ DeleteDC(hDC_dib);
+ }
#ifdef STDOUT_FILE
fclose(stdo);
#endif
diff --git a/platform/windows/os_windows.h b/platform/windows/os_windows.h
index 584f6fb334..221109318e 100644
--- a/platform/windows/os_windows.h
+++ b/platform/windows/os_windows.h
@@ -93,6 +93,12 @@ class OS_Windows : public OS {
HINSTANCE hInstance; // Holds The Instance Of The Application
HWND hWnd;
+ 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;
HCURSOR hCursor;
@@ -212,6 +218,13 @@ public:
virtual void set_borderless_window(bool p_borderless);
virtual bool get_borderless_window();
+ 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);
diff --git a/platform/x11/context_gl_x11.cpp b/platform/x11/context_gl_x11.cpp
index 1a7cbc0d6d..cd76667c64 100644
--- a/platform/x11/context_gl_x11.cpp
+++ b/platform/x11/context_gl_x11.cpp
@@ -116,32 +116,76 @@ Error ContextGL_X11::initialize() {
None
};
+ static int visual_attribs_layered[] = {
+ GLX_RENDER_TYPE, GLX_RGBA_BIT,
+ GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
+ GLX_DOUBLEBUFFER, true,
+ GLX_RED_SIZE, 8,
+ GLX_GREEN_SIZE, 8,
+ GLX_BLUE_SIZE, 8,
+ GLX_ALPHA_SIZE, 8,
+ GLX_DEPTH_SIZE, 24,
+ None
+ };
+
int fbcount;
- GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs, &fbcount);
- ERR_FAIL_COND_V(!fbc, ERR_UNCONFIGURED);
+ GLXFBConfig fbconfig;
+ XVisualInfo *vi = NULL;
+
+ if (OS::get_singleton()->is_layered_allowed()) {
+ GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs_layered, &fbcount);
+ ERR_FAIL_COND_V(!fbc, ERR_UNCONFIGURED);
+
+ for (int i = 0; i < fbcount; i++) {
+ vi = (XVisualInfo *)glXGetVisualFromFBConfig(x11_display, fbc[i]);
+ if (!vi)
+ continue;
+
+ XRenderPictFormat *pict_format = XRenderFindVisualFormat(x11_display, vi->visual);
+ if (!pict_format) {
+ XFree(vi);
+ vi = NULL;
+ continue;
+ }
+
+ fbconfig = fbc[i];
+ if (pict_format->direct.alphaMask > 0) {
+ break;
+ }
+ }
+ ERR_FAIL_COND_V(!fbconfig, ERR_UNCONFIGURED);
+
+ XSetWindowAttributes swa;
+
+ swa.colormap = XCreateColormap(x11_display, RootWindow(x11_display, vi->screen), vi->visual, AllocNone);
+ swa.border_pixel = 0;
+ swa.background_pixmap = None;
+ swa.background_pixel = 0;
+ swa.border_pixmap = None;
+ swa.event_mask = StructureNotifyMask;
+
+ x11_window = XCreateWindow(x11_display, RootWindow(x11_display, vi->screen), 0, 0, OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask | CWBackPixel, &swa);
- XVisualInfo *vi = glXGetVisualFromFBConfig(x11_display, fbc[0]);
+ } else {
+ GLXFBConfig *fbc = glXChooseFBConfig(x11_display, DefaultScreen(x11_display), visual_attribs, &fbcount);
+ ERR_FAIL_COND_V(!fbc, ERR_UNCONFIGURED);
- XSetWindowAttributes swa;
+ vi = glXGetVisualFromFBConfig(x11_display, fbc[0]);
- swa.colormap = XCreateColormap(x11_display, RootWindow(x11_display, vi->screen), vi->visual, AllocNone);
- swa.border_pixel = 0;
- swa.event_mask = StructureNotifyMask;
+ fbconfig = fbc[0];
- /*
- char* windowid = getenv("GODOT_WINDOWID");
- if (windowid) {
+ XSetWindowAttributes swa;
+
+ swa.colormap = XCreateColormap(x11_display, RootWindow(x11_display, vi->screen), vi->visual, AllocNone);
+ swa.border_pixel = 0;
+ swa.event_mask = StructureNotifyMask;
+
+ x11_window = XCreateWindow(x11_display, RootWindow(x11_display, vi->screen), 0, 0, OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa);
+ }
- //freopen("/home/punto/stdout", "w", stdout);
- //reopen("/home/punto/stderr", "w", stderr);
- x11_window = atol(windowid);
- } else {
- */
- x11_window = XCreateWindow(x11_display, RootWindow(x11_display, vi->screen), 0, 0, OS::get_singleton()->get_video_mode().width, OS::get_singleton()->get_video_mode().height, 0, vi->depth, InputOutput, vi->visual, CWBorderPixel | CWColormap | CWEventMask, &swa);
ERR_FAIL_COND_V(!x11_window, ERR_UNCONFIGURED);
set_class_hint(x11_display, x11_window);
XMapWindow(x11_display, x11_window);
- //};
int (*oldHandler)(Display *, XErrorEvent *) =
XSetErrorHandler(&ctxErrorHandler);
@@ -160,7 +204,7 @@ Error ContextGL_X11::initialize() {
None
};
- p->glx_context = glXCreateContextAttribsARB(x11_display, fbc[0], NULL, true, context_attribs);
+ p->glx_context = glXCreateContextAttribsARB(x11_display, fbconfig, NULL, true, context_attribs);
ERR_EXPLAIN("Could not obtain an OpenGL 3.0 context!");
ERR_FAIL_COND_V(!p->glx_context, ERR_UNCONFIGURED);
} break;
@@ -175,7 +219,7 @@ Error ContextGL_X11::initialize() {
None
};
- p->glx_context = glXCreateContextAttribsARB(x11_display, fbc[0], NULL, true, context_attribs);
+ p->glx_context = glXCreateContextAttribsARB(x11_display, fbconfig, NULL, true, context_attribs);
ERR_EXPLAIN("Could not obtain an OpenGL 3.3 context!");
ERR_FAIL_COND_V(ctxErrorOccurred || !p->glx_context, ERR_UNCONFIGURED);
} break;
@@ -195,7 +239,6 @@ Error ContextGL_X11::initialize() {
//glXMakeCurrent(x11_display, None, NULL);
XFree(vi);
- XFree(fbc);
return OK;
}
diff --git a/platform/x11/context_gl_x11.h b/platform/x11/context_gl_x11.h
index b54cc84fac..b8f3eb95d4 100644
--- a/platform/x11/context_gl_x11.h
+++ b/platform/x11/context_gl_x11.h
@@ -41,6 +41,7 @@
#include "drivers/gl_context/context_gl.h"
#include "os/os.h"
#include <X11/Xlib.h>
+#include <X11/extensions/Xrender.h>
struct ContextGL_X11_Private;
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 5820a926e9..ad2620c9f5 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -42,6 +42,11 @@ def can_build():
print("xrandr not found.. x11 disabled.")
return False
+ x11_error = os.system("pkg-config xrender --modversion > /dev/null ")
+ if (x11_error):
+ print("xrender not found.. x11 disabled.")
+ return False
+
return True
def get_opts():
@@ -141,6 +146,7 @@ def configure(env):
env.ParseConfig('pkg-config xcursor --cflags --libs')
env.ParseConfig('pkg-config xinerama --cflags --libs')
env.ParseConfig('pkg-config xrandr --cflags --libs')
+ env.ParseConfig('pkg-config xrender --cflags --libs')
if (env['touch']):
x11_error = os.system("pkg-config xi --modversion > /dev/null ")
diff --git a/platform/x11/os_x11.cpp b/platform/x11/os_x11.cpp
index 336068cb1e..d1b87dac6f 100644
--- a/platform/x11/os_x11.cpp
+++ b/platform/x11/os_x11.cpp
@@ -517,6 +517,10 @@ Error OS_X11::initialize(const VideoMode &p_desired, int p_video_driver, int p_a
power_manager = memnew(PowerX11);
+ if (p_desired.layered_splash) {
+ set_window_per_pixel_transparency_enabled(true);
+ }
+
XEvent xevent;
while (XPending(x11_display) > 0) {
XNextEvent(x11_display, &xevent);
@@ -707,6 +711,25 @@ Point2 OS_X11::get_mouse_position() const {
return last_mouse_pos;
}
+bool OS_X11::get_window_per_pixel_transparency_enabled() const {
+
+ if (!is_layered_allowed()) return false;
+ return layered_window;
+}
+
+void OS_X11::set_window_per_pixel_transparency_enabled(bool p_enabled) {
+
+ if (!is_layered_allowed()) return;
+ if (layered_window != p_enabled) {
+ if (p_enabled) {
+ set_borderless_window(true);
+ layered_window = true;
+ } else {
+ layered_window = false;
+ }
+ }
+}
+
void OS_X11::set_window_title(const String &p_title) {
XStoreName(x11_display, x11_window, p_title.utf8().get_data());
@@ -1006,9 +1029,13 @@ void OS_X11::set_window_size(const Size2 p_size) {
}
void OS_X11::set_window_fullscreen(bool p_enabled) {
+
if (current_videomode.fullscreen == p_enabled)
return;
+ if (layered_window)
+ set_window_per_pixel_transparency_enabled(false);
+
if (p_enabled && current_videomode.always_on_top) {
// Fullscreen + Always-on-top requires a maximized window on some window managers (Metacity)
set_window_maximized(true);
@@ -1254,6 +1281,9 @@ void OS_X11::set_borderless_window(bool p_borderless) {
if (current_videomode.borderless_window == p_borderless)
return;
+ if (!p_borderless && layered_window)
+ set_window_per_pixel_transparency_enabled(false);
+
current_videomode.borderless_window = p_borderless;
Hints hints;
@@ -2715,6 +2745,7 @@ OS_X11::OS_X11() {
AudioDriverManager::add_driver(&driver_alsa);
#endif
+ layered_window = false;
minimized = false;
xim_style = 0L;
mouse_mode = MOUSE_MODE_VISIBLE;
diff --git a/platform/x11/os_x11.h b/platform/x11/os_x11.h
index 0a39da77de..09ed9588c4 100644
--- a/platform/x11/os_x11.h
+++ b/platform/x11/os_x11.h
@@ -172,6 +172,8 @@ class OS_X11 : public OS_Unix {
PowerX11 *power_manager;
+ bool layered_window;
+
CrashHandler crash_handler;
int audio_driver_index;
@@ -263,6 +265,10 @@ public:
virtual void set_borderless_window(bool p_borderless);
virtual bool get_borderless_window();
+
+ virtual bool get_window_per_pixel_transparency_enabled() const;
+ virtual void set_window_per_pixel_transparency_enabled(bool p_enabled);
+
virtual void set_ime_position(const Point2 &p_pos);
virtual String get_unique_id() const;