[X11] Add support for using EGL/GLES instead of GLX.

This commit is contained in:
bruvzg 2023-09-22 10:55:55 +03:00
parent f5696c311c
commit af00c4a54a
No known key found for this signature in database
GPG key ID: 7960FCF39844EC38
10 changed files with 215 additions and 15 deletions

View file

@ -4473,7 +4473,7 @@ String EditorNode::_get_system_info() const {
}
if (driver_name == "vulkan") {
driver_name = "Vulkan";
} else if (driver_name == "opengl3") {
} else if (driver_name.begins_with("opengl3")) {
driver_name = "GLES3";
}

View file

@ -1746,9 +1746,11 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
{
String driver_hints = "";
String driver_hints_angle = "";
String driver_hints_egl = "";
#ifdef GLES3_ENABLED
driver_hints = "opengl3";
driver_hints_angle = "opengl3,opengl3_angle";
driver_hints_egl = "opengl3,opengl3_es";
#endif
String default_driver = driver_hints.get_slice(",", 0);
@ -1759,11 +1761,12 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
GLOBAL_DEF_RST("rendering/gl_compatibility/driver", default_driver);
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.windows", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver);
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.linuxbsd", PROPERTY_HINT_ENUM, driver_hints), default_driver);
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.linuxbsd", PROPERTY_HINT_ENUM, driver_hints_egl), default_driver);
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.web", PROPERTY_HINT_ENUM, driver_hints), default_driver);
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.android", PROPERTY_HINT_ENUM, driver_hints), default_driver);
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.ios", PROPERTY_HINT_ENUM, driver_hints), default_driver);
GLOBAL_DEF_RST(PropertyInfo(Variant::STRING, "rendering/gl_compatibility/driver.macos", PROPERTY_HINT_ENUM, driver_hints_angle), default_driver_macos);
GLOBAL_DEF_RST("rendering/gl_compatibility/nvidia_disable_threaded_optimization", true);
GLOBAL_DEF_RST("rendering/gl_compatibility/fallback_to_angle", true);
@ -1841,7 +1844,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
// Set a default renderer if none selected. Try to choose one that matches the driver.
if (rendering_method.is_empty()) {
if (rendering_driver == "opengl3" || rendering_driver == "opengl3_angle") {
if (rendering_driver == "opengl3" || rendering_driver == "opengl3_angle" || rendering_driver == "opengl3_es") {
rendering_method = "gl_compatibility";
} else {
rendering_method = "forward_plus";
@ -1860,6 +1863,7 @@ Error Main::setup(const char *execpath, int argc, char *argv[], bool p_second_ph
if (rendering_method == "gl_compatibility") {
available_drivers.push_back("opengl3");
available_drivers.push_back("opengl3_angle");
available_drivers.push_back("opengl3_es");
}
#endif
if (available_drivers.is_empty()) {

View file

@ -35,6 +35,10 @@
#define GL_API_ENABLED // Allow using desktop GL.
#endif
#ifndef GLES_API_ENABLED
#define GLES_API_ENABLED // Allow using GLES.
#endif
#include "thirdparty/glad/glad/egl.h"
#include "thirdparty/glad/glad/gl.h"

View file

@ -25,7 +25,9 @@ if env["vulkan"]:
if env["opengl3"]:
env.Append(CPPDEFINES=["GLAD_GLX_NO_X11"])
source_files.append(["gl_manager_x11.cpp", "detect_prime_x11.cpp", "#thirdparty/glad/glx.c"])
source_files.append(
["gl_manager_x11_egl.cpp", "gl_manager_x11.cpp", "detect_prime_x11.cpp", "#thirdparty/glad/glx.c"]
)
objects = []

View file

@ -1495,6 +1495,9 @@ void DisplayServerX11::delete_sub_window(WindowID p_id) {
if (gl_manager) {
gl_manager->window_destroy(p_id);
}
if (gl_manager_egl) {
gl_manager_egl->window_destroy(p_id);
}
#endif
if (wd.xic) {
@ -1534,6 +1537,9 @@ int64_t DisplayServerX11::window_get_native_handle(HandleType p_handle_type, Win
if (gl_manager) {
return (int64_t)gl_manager->get_glx_context(p_window);
}
if (gl_manager_egl) {
return (int64_t)gl_manager_egl->get_context(p_window);
}
return 0;
}
#endif
@ -1711,6 +1717,9 @@ void DisplayServerX11::gl_window_make_current(DisplayServer::WindowID p_window_i
if (gl_manager) {
gl_manager->window_make_current(p_window_id);
}
if (gl_manager_egl) {
gl_manager_egl->window_make_current(p_window_id);
}
#endif
}
@ -2012,6 +2021,9 @@ void DisplayServerX11::window_set_size(const Size2i p_size, WindowID p_window) {
if (gl_manager) {
gl_manager->window_resize(p_window, xwa.width, xwa.height);
}
if (gl_manager_egl) {
gl_manager_egl->window_resize(p_window, xwa.width, xwa.height);
}
#endif
}
@ -3721,6 +3733,9 @@ void DisplayServerX11::_window_changed(XEvent *event) {
if (gl_manager) {
gl_manager->window_resize(window_id, wd.size.width, wd.size.height);
}
if (gl_manager_egl) {
gl_manager_egl->window_resize(window_id, wd.size.width, wd.size.height);
}
#endif
if (!wd.rect_changed_callback.is_null()) {
@ -4855,6 +4870,9 @@ void DisplayServerX11::release_rendering_thread() {
if (gl_manager) {
gl_manager->release_current();
}
if (gl_manager_egl) {
gl_manager_egl->release_current();
}
#endif
}
@ -4863,6 +4881,9 @@ void DisplayServerX11::make_rendering_thread() {
if (gl_manager) {
gl_manager->make_current();
}
if (gl_manager_egl) {
gl_manager_egl->make_current();
}
#endif
}
@ -4871,6 +4892,9 @@ void DisplayServerX11::swap_buffers() {
if (gl_manager) {
gl_manager->swap_buffers();
}
if (gl_manager_egl) {
gl_manager_egl->swap_buffers();
}
#endif
}
@ -5024,6 +5048,9 @@ void DisplayServerX11::window_set_vsync_mode(DisplayServer::VSyncMode p_vsync_mo
if (gl_manager) {
gl_manager->set_use_vsync(p_vsync_mode != DisplayServer::VSYNC_DISABLED);
}
if (gl_manager_egl) {
gl_manager_egl->set_use_vsync(p_vsync_mode != DisplayServer::VSYNC_DISABLED);
}
#endif
}
@ -5038,6 +5065,9 @@ DisplayServer::VSyncMode DisplayServerX11::window_get_vsync_mode(WindowID p_wind
if (gl_manager) {
return gl_manager->is_using_vsync() ? DisplayServer::VSYNC_ENABLED : DisplayServer::VSYNC_DISABLED;
}
if (gl_manager_egl) {
return gl_manager_egl->is_using_vsync() ? DisplayServer::VSYNC_ENABLED : DisplayServer::VSYNC_DISABLED;
}
#endif
return DisplayServer::VSYNC_ENABLED;
}
@ -5050,6 +5080,7 @@ Vector<String> DisplayServerX11::get_rendering_drivers_func() {
#endif
#ifdef GLES3_ENABLED
drivers.push_back("opengl3");
drivers.push_back("opengl3_es");
#endif
return drivers;
@ -5092,6 +5123,21 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't acquire visual info from display.");
vi_selected = true;
}
if (gl_manager_egl) {
XVisualInfo visual_info_template;
int visual_id = gl_manager_egl->display_get_native_visual_id(x11_display);
ERR_FAIL_COND_V_MSG(visual_id < 0, INVALID_WINDOW_ID, "Unable to get a visual id.");
visual_info_template.visualid = (VisualID)visual_id;
int number_of_visuals = 0;
XVisualInfo *vi_list = XGetVisualInfo(x11_display, VisualIDMask, &visual_info_template, &number_of_visuals);
ERR_FAIL_COND_V(number_of_visuals <= 0, INVALID_WINDOW_ID);
visualInfo = vi_list[0];
XFree(vi_list);
}
#endif
if (!vi_selected) {
@ -5364,8 +5410,12 @@ DisplayServerX11::WindowID DisplayServerX11::_create_window(WindowMode p_mode, V
if (gl_manager) {
Error err = gl_manager->window_create(id, wd.x11_window, x11_display, win_rect.size.width, win_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Can't create an OpenGL window");
window_set_vsync_mode(p_vsync_mode, id);
}
if (gl_manager_egl) {
Error err = gl_manager_egl->window_create(id, x11_display, &wd.x11_window, win_rect.size.width, win_rect.size.height);
ERR_FAIL_COND_V_MSG(err != OK, INVALID_WINDOW_ID, "Failed to create an OpenGLES window.");
}
window_set_vsync_mode(p_vsync_mode, id);
#endif
//set_class_hint(x11_display, wd.x11_window);
@ -5766,7 +5816,7 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
#endif
// Initialize context and rendering device.
#if defined(GLES3_ENABLED)
if (rendering_driver == "opengl3") {
if (rendering_driver == "opengl3" || rendering_driver == "opengl3_es") {
if (getenv("DRI_PRIME") == nullptr) {
int use_prime = -1;
@ -5807,7 +5857,8 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
setenv("DRI_PRIME", "1", 1);
}
}
}
if (rendering_driver == "opengl3") {
GLManager_X11::ContextType opengl_api_type = GLManager_X11::GLES_3_0_COMPATIBLE;
gl_manager = memnew(GLManager_X11(p_resolution, opengl_api_type));
@ -5820,14 +5871,20 @@ DisplayServerX11::DisplayServerX11(const String &p_rendering_driver, WindowMode
}
driver_found = true;
if (true) {
RasterizerGLES3::make_current(true);
} else {
memdelete(gl_manager);
gl_manager = nullptr;
RasterizerGLES3::make_current(true);
}
if (rendering_driver == "opengl3_es") {
gl_manager_egl = memnew(GLManagerEGL_X11);
if (gl_manager_egl->initialize() != OK) {
memdelete(gl_manager_egl);
gl_manager_egl = nullptr;
r_error = ERR_UNAVAILABLE;
return;
}
driver_found = true;
RasterizerGLES3::make_current(false);
}
#endif
if (!driver_found) {
@ -6044,6 +6101,9 @@ DisplayServerX11::~DisplayServerX11() {
if (gl_manager) {
gl_manager->window_destroy(E.key);
}
if (gl_manager_egl) {
gl_manager_egl->window_destroy(E.key);
}
#endif
WindowData &wd = E.value;
@ -6094,6 +6154,10 @@ DisplayServerX11::~DisplayServerX11() {
memdelete(gl_manager);
gl_manager = nullptr;
}
if (gl_manager_egl) {
memdelete(gl_manager_egl);
gl_manager_egl = nullptr;
}
#endif
if (xrandr_handle) {

View file

@ -54,6 +54,7 @@
#if defined(GLES3_ENABLED)
#include "x11/gl_manager_x11.h"
#include "x11/gl_manager_x11_egl.h"
#endif
#if defined(VULKAN_ENABLED)
@ -138,6 +139,7 @@ class DisplayServerX11 : public DisplayServer {
#if defined(GLES3_ENABLED)
GLManager_X11 *gl_manager = nullptr;
GLManagerEGL_X11 *gl_manager_egl = nullptr;
#endif
#if defined(VULKAN_ENABLED)
VulkanContextX11 *context_vulkan = nullptr;

View file

@ -0,0 +1,63 @@
/**************************************************************************/
/* gl_manager_x11_egl.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#include "gl_manager_x11_egl.h"
#if defined(X11_ENABLED) && defined(GLES3_ENABLED)
#include <stdio.h>
#include <stdlib.h>
const char *GLManagerEGL_X11::_get_platform_extension_name() const {
return "EGL_KHR_platform_x11";
}
EGLenum GLManagerEGL_X11::_get_platform_extension_enum() const {
return EGL_PLATFORM_X11_KHR;
}
Vector<EGLAttrib> GLManagerEGL_X11::_get_platform_display_attributes() const {
return Vector<EGLAttrib>();
}
EGLenum GLManagerEGL_X11::_get_platform_api_enum() const {
return EGL_OPENGL_ES_API;
}
Vector<EGLint> GLManagerEGL_X11::_get_platform_context_attribs() const {
Vector<EGLint> ret;
ret.push_back(EGL_CONTEXT_CLIENT_VERSION);
ret.push_back(3);
ret.push_back(EGL_NONE);
return ret;
}
#endif // WINDOWS_ENABLED && GLES3_ENABLED

View file

@ -0,0 +1,61 @@
/**************************************************************************/
/* gl_manager_x11_egl.h */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
#ifndef GL_MANAGER_X11_EGL_H
#define GL_MANAGER_X11_EGL_H
#if defined(X11_ENABLED) && defined(GLES3_ENABLED)
#include "core/error/error_list.h"
#include "core/os/os.h"
#include "core/templates/local_vector.h"
#include "drivers/egl/egl_manager.h"
#include "servers/display_server.h"
#include <X11/Xlib.h>
class GLManagerEGL_X11 : public EGLManager {
private:
virtual const char *_get_platform_extension_name() const override;
virtual EGLenum _get_platform_extension_enum() const override;
virtual EGLenum _get_platform_api_enum() const override;
virtual Vector<EGLAttrib> _get_platform_display_attributes() const override;
virtual Vector<EGLint> _get_platform_context_attribs() const override;
public:
void window_resize(DisplayServer::WindowID p_window_id, int p_width, int p_height) {}
GLManagerEGL_X11(){};
~GLManagerEGL_X11(){};
};
#endif // X11_ENABLED && GLES3_ENABLED
#endif // GL_MANAGER_X11_EGL_H

View file

@ -732,7 +732,7 @@ void RendererViewport::draw_viewports() {
// commit our eyes
Vector<BlitToScreen> blits = xr_interface->post_draw_viewport(vp->render_target, vp->viewport_to_screen_rect);
if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID) {
if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3" || OS::get_singleton()->get_current_rendering_driver_name() == "opengl3_angle") {
if (OS::get_singleton()->get_current_rendering_driver_name().begins_with("opengl3")) {
if (blits.size() > 0) {
RSG::rasterizer->blit_render_targets_to_screen(vp->viewport_to_screen, blits.ptr(), blits.size());
}
@ -771,7 +771,7 @@ void RendererViewport::draw_viewports() {
blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
}
if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3" || OS::get_singleton()->get_current_rendering_driver_name() == "opengl3_angle") {
if (OS::get_singleton()->get_current_rendering_driver_name().begins_with("opengl3")) {
Vector<BlitToScreen> blit_to_screen_vec;
blit_to_screen_vec.push_back(blit);
RSG::rasterizer->blit_render_targets_to_screen(vp->viewport_to_screen, blit_to_screen_vec.ptr(), 1);

View file

@ -91,7 +91,7 @@ void RenderingServerDefault::_draw(bool p_swap_buffers, double frame_step) {
RSG::viewport->draw_viewports();
RSG::canvas_render->update();
if (OS::get_singleton()->get_current_rendering_driver_name() != "opengl3" && OS::get_singleton()->get_current_rendering_driver_name() != "opengl3_angle") {
if (!OS::get_singleton()->get_current_rendering_driver_name().begins_with("opengl3")) {
// Already called for gl_compatibility renderer.
RSG::rasterizer->end_frame(p_swap_buffers);
}