summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/egl/egl_manager.cpp89
-rw-r--r--drivers/egl/egl_manager.h2
-rw-r--r--drivers/gles3/rasterizer_gles3.cpp6
-rw-r--r--drivers/gles3/rasterizer_gles3.h2
-rw-r--r--drivers/gles3/shaders/scene.glsl3
-rw-r--r--drivers/gles3/storage/config.cpp27
-rw-r--r--drivers/gles3/storage/config.h4
-rw-r--r--drivers/gles3/storage/particles_storage.cpp4
8 files changed, 106 insertions, 31 deletions
diff --git a/drivers/egl/egl_manager.cpp b/drivers/egl/egl_manager.cpp
index 6073856747..9c1d08331d 100644
--- a/drivers/egl/egl_manager.cpp
+++ b/drivers/egl/egl_manager.cpp
@@ -33,10 +33,22 @@
#ifdef EGL_ENABLED
#if defined(EGL_STATIC)
-#define KHRONOS_STATIC 1
+
#define GLAD_EGL_VERSION_1_5 true
+
+#ifdef EGL_EXT_platform_base
+#define GLAD_EGL_EXT_platform_base 1
+#endif
+
+#define KHRONOS_STATIC 1
extern "C" EGLAPI void EGLAPIENTRY eglSetBlobCacheFuncsANDROID(EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get);
+extern "C" EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platform, void *native_display, const EGLint *attrib_list);
#undef KHRONOS_STATIC
+
+#endif // defined(EGL_STATIC)
+
+#ifndef EGL_EXT_platform_base
+#define GLAD_EGL_EXT_platform_base 0
#endif
// Creates and caches a GLDisplay. Returns -1 on error.
@@ -56,10 +68,23 @@ int EGLManager::_get_gldisplay_id(void *p_display) {
if (GLAD_EGL_VERSION_1_5) {
Vector<EGLAttrib> attribs = _get_platform_display_attributes();
new_gldisplay.egl_display = eglGetPlatformDisplay(_get_platform_extension_enum(), new_gldisplay.display, (attribs.size() > 0) ? attribs.ptr() : nullptr);
+ } else if (GLAD_EGL_EXT_platform_base) {
+#ifdef EGL_EXT_platform_base
+ // eglGetPlatformDisplayEXT wants its attributes as EGLint, so we'll truncate
+ // what we already have. It's a bit naughty but I'm really not sure what else
+ // we could do here.
+ Vector<EGLint> attribs;
+ for (const EGLAttrib &attrib : _get_platform_display_attributes()) {
+ attribs.push_back((EGLint)attrib);
+ }
+
+ new_gldisplay.egl_display = eglGetPlatformDisplayEXT(_get_platform_extension_enum(), new_gldisplay.display, (attribs.size() > 0) ? attribs.ptr() : nullptr);
+#endif // EGL_EXT_platform_base
} else {
NativeDisplayType *native_display_type = (NativeDisplayType *)new_gldisplay.display;
new_gldisplay.egl_display = eglGetDisplay(*native_display_type);
}
+
ERR_FAIL_COND_V(eglGetError() != EGL_SUCCESS, -1);
ERR_FAIL_COND_V_MSG(new_gldisplay.egl_display == EGL_NO_DISPLAY, -1, "Can't create an EGL display.");
@@ -326,30 +351,51 @@ EGLContext EGLManager::get_context(DisplayServer::WindowID p_window_id) {
return display.egl_context;
}
-Error EGLManager::initialize() {
+Error EGLManager::initialize(void *p_native_display) {
#if defined(GLAD_ENABLED) && !defined(EGL_STATIC)
- // Passing a null display loads just the bare minimum to create one. We'll have
- // to create a temporary test display and reload EGL with it to get a good idea
- // of what version is supported on this machine. Currently we're looking for
- // 1.5, the latest at the time of writing, which is actually pretty old.
- if (!gladLoaderLoadEGL(nullptr)) {
+ // Loading EGL with a new display gets us just the bare minimum API. We'll then
+ // have to temporarily get a proper display and reload EGL once again to
+ // initialize everything else.
+ if (!gladLoaderLoadEGL(EGL_NO_DISPLAY)) {
ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't load EGL.");
}
- // NOTE: EGL_DEFAULT_DISPLAY returns whatever the O.S. deems suitable. I have
- // no idea if this may cause problems with multiple display servers and if we
- // should handle different EGL contexts in another way.
- EGLDisplay tmp_display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
- ERR_FAIL_COND_V(tmp_display == EGL_NO_DISPLAY, ERR_UNAVAILABLE);
+ EGLDisplay tmp_display = EGL_NO_DISPLAY;
+
+ if (GLAD_EGL_EXT_platform_base) {
+#ifdef EGL_EXT_platform_base
+ // eglGetPlatformDisplayEXT wants its attributes as EGLint.
+ Vector<EGLint> attribs;
+ for (const EGLAttrib &attrib : _get_platform_display_attributes()) {
+ attribs.push_back((EGLint)attrib);
+ }
+ tmp_display = eglGetPlatformDisplayEXT(_get_platform_extension_enum(), p_native_display, attribs.ptr());
+#endif // EGL_EXT_platform_base
+ } else {
+ WARN_PRINT("EGL: EGL_EXT_platform_base not found during init, using default platform.");
+ EGLNativeDisplayType *native_display_type = (EGLNativeDisplayType *)p_native_display;
+ tmp_display = eglGetDisplay(*native_display_type);
+ }
+
+ if (tmp_display == EGL_NO_DISPLAY) {
+ eglTerminate(tmp_display);
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't get a valid initial EGL display.");
+ }
eglInitialize(tmp_display, nullptr, nullptr);
int version = gladLoaderLoadEGL(tmp_display);
+ if (!version) {
+ eglTerminate(tmp_display);
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, "Can't load EGL.");
+ }
+
+ int major = GLAD_VERSION_MAJOR(version);
+ int minor = GLAD_VERSION_MINOR(version);
- ERR_FAIL_COND_V_MSG(!version, ERR_UNAVAILABLE, "Can't load EGL.");
- print_verbose(vformat("Loaded EGL %d.%d", GLAD_VERSION_MAJOR(version), GLAD_VERSION_MINOR(version)));
+ print_verbose(vformat("Loaded EGL %d.%d", major, minor));
- ERR_FAIL_COND_V_MSG(!GLAD_EGL_VERSION_1_4, ERR_UNAVAILABLE, "EGL version is too old!");
+ ERR_FAIL_COND_V_MSG(!GLAD_EGL_VERSION_1_4, ERR_UNAVAILABLE, vformat("EGL version is too old! %d.%d < 1.4", major, minor));
eglTerminate(tmp_display);
#endif
@@ -378,13 +424,14 @@ Error EGLManager::initialize() {
}
#endif
- String extensions_string = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
- // The above method should always work. If it doesn't, something's very wrong.
- ERR_FAIL_COND_V(eglGetError() != EGL_SUCCESS, ERR_BUG);
+ String client_extensions_string = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
- const char *platform = _get_platform_extension_name();
- if (!extensions_string.split(" ").has(platform)) {
- ERR_FAIL_V_MSG(ERR_UNAVAILABLE, vformat("EGL platform extension \"%s\" not found.", platform));
+ // If the above method fails, we don't support client extensions, so there's nothing to check.
+ if (eglGetError() == EGL_SUCCESS) {
+ const char *platform = _get_platform_extension_name();
+ if (!client_extensions_string.split(" ").has(platform)) {
+ ERR_FAIL_V_MSG(ERR_UNAVAILABLE, vformat("EGL platform extension \"%s\" not found.", platform));
+ }
}
return OK;
diff --git a/drivers/egl/egl_manager.h b/drivers/egl/egl_manager.h
index 83779349f0..a4502c0687 100644
--- a/drivers/egl/egl_manager.h
+++ b/drivers/egl/egl_manager.h
@@ -107,7 +107,7 @@ public:
EGLContext get_context(DisplayServer::WindowID p_window_id);
- Error initialize();
+ Error initialize(void *p_native_display = nullptr);
EGLManager();
virtual ~EGLManager();
diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp
index 993197e371..071765a03c 100644
--- a/drivers/gles3/rasterizer_gles3.cpp
+++ b/drivers/gles3/rasterizer_gles3.cpp
@@ -195,9 +195,9 @@ void RasterizerGLES3::initialize() {
Engine::get_singleton()->print_header(vformat("OpenGL API %s - Compatibility - Using Device: %s - %s", RS::get_singleton()->get_video_adapter_api_version(), RS::get_singleton()->get_video_adapter_vendor(), RS::get_singleton()->get_video_adapter_name()));
// FLIP XY Bug: Are more devices affected?
- // Confirmed so far: all Adreno 3xx
+ // Confirmed so far: all Adreno 3xx with old driver (until 2018)
// ok on some tested Adreno devices: 4xx, 5xx and 6xx
- flip_xy_bugfix = GLES3::Config::get_singleton()->adreno_3xx_compatibility;
+ flip_xy_workaround = GLES3::Config::get_singleton()->flip_xy_workaround;
}
void RasterizerGLES3::finalize() {
@@ -411,7 +411,7 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
// Adreno (TM) 3xx devices have a bug that create wrong Landscape rotation of 180 degree
// Reversing both the X and Y axis is equivalent to rotating 180 degrees
bool flip_x = false;
- if (flip_xy_bugfix && screen_rect_end.x > screen_rect_end.y) {
+ if (flip_xy_workaround && screen_rect_end.x > screen_rect_end.y) {
flip_y = !flip_y;
flip_x = !flip_x;
}
diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h
index 09d3c7bd52..0d0c26016d 100644
--- a/drivers/gles3/rasterizer_gles3.h
+++ b/drivers/gles3/rasterizer_gles3.h
@@ -56,7 +56,7 @@ private:
float delta = 0;
double time_total = 0.0;
- bool flip_xy_bugfix = false;
+ bool flip_xy_workaround = false;
static bool gles_over_gl;
diff --git a/drivers/gles3/shaders/scene.glsl b/drivers/gles3/shaders/scene.glsl
index 2b372cb88d..be7a6aba57 100644
--- a/drivers/gles3/shaders/scene.glsl
+++ b/drivers/gles3/shaders/scene.glsl
@@ -1523,6 +1523,9 @@ void main() {
#CODE : FRAGMENT
}
+ // Keep albedo values in positive number range as negative values "wraparound" into positive numbers resulting in wrong colors
+ albedo = max(albedo, vec3(0.0));
+
#ifdef LIGHT_VERTEX_USED
vertex = light_vertex;
#ifdef USE_MULTIVIEW
diff --git a/drivers/gles3/storage/config.cpp b/drivers/gles3/storage/config.cpp
index 6b5e227782..07e6d04cb7 100644
--- a/drivers/gles3/storage/config.cpp
+++ b/drivers/gles3/storage/config.cpp
@@ -169,8 +169,31 @@ Config::Config() {
//Adreno 3xx Compatibility
const String rendering_device_name = String::utf8((const char *)glGetString(GL_RENDERER));
- //TODO: Check the number between 300 and 399(?)
- adreno_3xx_compatibility = (rendering_device_name.left(13) == "Adreno (TM) 3");
+ if (rendering_device_name.left(13) == "Adreno (TM) 3") {
+ flip_xy_workaround = true;
+ disable_particles_workaround = true;
+
+ // ignore driver version 331+
+ const String gl_version = String::utf8((const char *)glGetString(GL_VERSION));
+ // Adreno 3xx examples (https://opengles.gpuinfo.org/listreports.php):
+ // ===========================================================================
+ // OpenGL ES 3.0 V@84.0 AU@ (CL@)
+ // OpenGL ES 3.0 V@127.0 AU@ (GIT@I96aee987eb)
+ // OpenGL ES 3.0 V@140.0 AU@ (GIT@Ifd751822f5)
+ // OpenGL ES 3.0 V@251.0 AU@08.00.00.312.030 (GIT@Ie4790512f3)
+ // OpenGL ES 3.0 V@269.0 AU@ (GIT@I109c45a694)
+ // OpenGL ES 3.0 V@331.0 (GIT@35e467f, Ice9844a736) (Date:04/15/19)
+ // OpenGL ES 3.0 V@415.0 (GIT@d39f783, I79de86aa2c, 1591296226) (Date:06/04/20)
+ // OpenGL ES 3.0 V@0502.0 (GIT@09fef447e8, I1fe547a144, 1661493934) (Date:08/25/22)
+ String driver_version = gl_version.get_slice("V@", 1).get_slice(" ", 0);
+ if (driver_version.is_valid_float() && driver_version.to_float() >= 331.0) {
+ flip_xy_workaround = false;
+
+ //TODO: also 'GPUParticles'?
+ //https://github.com/godotengine/godot/issues/92662#issuecomment-2161199477
+ //disable_particles_workaround = false;
+ }
+ }
}
Config::~Config() {
diff --git a/drivers/gles3/storage/config.h b/drivers/gles3/storage/config.h
index c3ab65f0bc..ee7b1b26ed 100644
--- a/drivers/gles3/storage/config.h
+++ b/drivers/gles3/storage/config.h
@@ -91,7 +91,9 @@ public:
bool rt_msaa_multiview_supported = false;
bool multiview_supported = false;
- bool adreno_3xx_compatibility = false;
+ // Adreno 3XX compatibility
+ bool disable_particles_workaround = false; // set to 'true' to disable 'GPUParticles'
+ bool flip_xy_workaround = false;
#ifdef ANDROID_ENABLED
PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC eglFramebufferTextureMultiviewOVR = nullptr;
diff --git a/drivers/gles3/storage/particles_storage.cpp b/drivers/gles3/storage/particles_storage.cpp
index fee90599e0..b600681280 100644
--- a/drivers/gles3/storage/particles_storage.cpp
+++ b/drivers/gles3/storage/particles_storage.cpp
@@ -122,7 +122,7 @@ void ParticlesStorage::particles_set_mode(RID p_particles, RS::ParticlesMode p_m
}
void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting) {
- ERR_FAIL_COND_MSG(GLES3::Config::get_singleton()->adreno_3xx_compatibility, "Due to driver bugs, GPUParticles are not supported on Adreno 3XX devices. Please use CPUParticles instead.");
+ ERR_FAIL_COND_MSG(GLES3::Config::get_singleton()->disable_particles_workaround, "Due to driver bugs, GPUParticles are not supported on Adreno 3XX devices. Please use CPUParticles instead.");
Particles *particles = particles_owner.get_or_null(p_particles);
ERR_FAIL_NULL(particles);
@@ -131,7 +131,7 @@ void ParticlesStorage::particles_set_emitting(RID p_particles, bool p_emitting)
}
bool ParticlesStorage::particles_get_emitting(RID p_particles) {
- if (GLES3::Config::get_singleton()->adreno_3xx_compatibility) {
+ if (GLES3::Config::get_singleton()->disable_particles_workaround) {
return false;
}