diff options
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/egl/egl_manager.cpp | 89 | ||||
| -rw-r--r-- | drivers/egl/egl_manager.h | 2 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_gles3.cpp | 6 | ||||
| -rw-r--r-- | drivers/gles3/rasterizer_gles3.h | 2 | ||||
| -rw-r--r-- | drivers/gles3/shaders/scene.glsl | 3 | ||||
| -rw-r--r-- | drivers/gles3/storage/config.cpp | 27 | ||||
| -rw-r--r-- | drivers/gles3/storage/config.h | 4 | ||||
| -rw-r--r-- | drivers/gles3/storage/particles_storage.cpp | 4 |
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; } |
