diff --git a/drivers/egl/egl_manager.cpp b/drivers/egl/egl_manager.cpp index 9c1d08331d2..d0ebe1491d2 100644 --- a/drivers/egl/egl_manager.cpp +++ b/drivers/egl/egl_manager.cpp @@ -30,6 +30,8 @@ #include "egl_manager.h" +#include "drivers/gles3/rasterizer_gles3.h" + #ifdef EGL_ENABLED #if defined(EGL_STATIC) @@ -51,6 +53,16 @@ extern "C" EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platfo #define GLAD_EGL_EXT_platform_base 0 #endif +#ifdef WINDOWS_ENABLED +// Unofficial ANGLE extension: EGL_ANGLE_surface_orientation +#ifndef EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE +#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7 +#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8 +#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001 +#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002 +#endif +#endif + // Creates and caches a GLDisplay. Returns -1 on error. int EGLManager::_get_gldisplay_id(void *p_display) { // Look for a cached GLDisplay. @@ -115,6 +127,18 @@ int EGLManager::_get_gldisplay_id(void *p_display) { } #endif +#ifdef WINDOWS_ENABLED + String client_extensions_string = eglQueryString(new_gldisplay.egl_display, EGL_EXTENSIONS); + if (eglGetError() == EGL_SUCCESS) { + Vector egl_extensions = client_extensions_string.split(" "); + + if (egl_extensions.has("EGL_ANGLE_surface_orientation")) { + new_gldisplay.has_EGL_ANGLE_surface_orientation = true; + print_verbose("EGL: EGL_ANGLE_surface_orientation is supported."); + } + } +#endif + displays.push_back(new_gldisplay); // Return the new GLDisplay's ID. @@ -237,8 +261,29 @@ Error EGLManager::window_create(DisplayServer::WindowID p_window_id, void *p_dis GLWindow &glwindow = windows[p_window_id]; glwindow.gldisplay_id = gldisplay_id; + Vector egl_attribs; + +#ifdef WINDOWS_ENABLED + if (gldisplay.has_EGL_ANGLE_surface_orientation) { + EGLint optimal_orientation; + if (eglGetConfigAttrib(gldisplay.egl_display, gldisplay.egl_config, EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE, &optimal_orientation)) { + // We only need to support inverting Y for optimizing ANGLE on D3D11. + if (optimal_orientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE && !(optimal_orientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE)) { + egl_attribs.push_back(EGL_SURFACE_ORIENTATION_ANGLE); + egl_attribs.push_back(EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE); + } + } else { + ERR_PRINT(vformat("Failed to get EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE, error: 0x%08X", eglGetError())); + } + } + + if (!egl_attribs.is_empty()) { + egl_attribs.push_back(EGL_NONE); + } +#endif + if (GLAD_EGL_VERSION_1_5) { - glwindow.egl_surface = eglCreatePlatformWindowSurface(gldisplay.egl_display, gldisplay.egl_config, p_native_window, nullptr); + glwindow.egl_surface = eglCreatePlatformWindowSurface(gldisplay.egl_display, gldisplay.egl_config, p_native_window, egl_attribs.ptr()); } else { EGLNativeWindowType *native_window_type = (EGLNativeWindowType *)p_native_window; glwindow.egl_surface = eglCreateWindowSurface(gldisplay.egl_display, gldisplay.egl_config, *native_window_type, nullptr); @@ -250,6 +295,20 @@ Error EGLManager::window_create(DisplayServer::WindowID p_window_id, void *p_dis glwindow.initialized = true; +#ifdef WINDOWS_ENABLED + if (gldisplay.has_EGL_ANGLE_surface_orientation) { + EGLint orientation; + if (eglQuerySurface(gldisplay.egl_display, glwindow.egl_surface, EGL_SURFACE_ORIENTATION_ANGLE, &orientation)) { + if (orientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE && !(orientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE)) { + glwindow.flipped_y = true; + print_verbose("EGL: Using optimal surface orientation: Invert Y"); + } + } else { + ERR_PRINT(vformat("Failed to get EGL_SURFACE_ORIENTATION_ANGLE, error: 0x%08X", eglGetError())); + } + } +#endif + window_make_current(p_window_id); return OK; @@ -316,6 +375,10 @@ void EGLManager::window_make_current(DisplayServer::WindowID p_window_id) { GLDisplay ¤t_display = displays[current_window->gldisplay_id]; eglMakeCurrent(current_display.egl_display, current_window->egl_surface, current_window->egl_surface, current_display.egl_context); + +#ifdef WINDOWS_ENABLED + RasterizerGLES3::set_screen_flipped_y(glwindow.flipped_y); +#endif } void EGLManager::set_use_vsync(bool p_use) { diff --git a/drivers/egl/egl_manager.h b/drivers/egl/egl_manager.h index a4502c06871..f1b3dc99b78 100644 --- a/drivers/egl/egl_manager.h +++ b/drivers/egl/egl_manager.h @@ -53,11 +53,18 @@ private: EGLDisplay egl_display = EGL_NO_DISPLAY; EGLContext egl_context = EGL_NO_CONTEXT; EGLConfig egl_config = nullptr; + +#ifdef WINDOWS_ENABLED + bool has_EGL_ANGLE_surface_orientation = false; +#endif }; // EGL specific window data. struct GLWindow { bool initialized = false; +#ifdef WINDOWS_ENABLED + bool flipped_y = false; +#endif // An handle to the GLDisplay associated with this window. int gldisplay_id = -1; diff --git a/drivers/gles3/rasterizer_gles3.cpp b/drivers/gles3/rasterizer_gles3.cpp index 37e7256d764..39aff2fc5e4 100644 --- a/drivers/gles3/rasterizer_gles3.cpp +++ b/drivers/gles3/rasterizer_gles3.cpp @@ -82,6 +82,10 @@ #define strcpy strcpy_s #endif +#ifdef WINDOWS_ENABLED +bool RasterizerGLES3::screen_flipped_y = false; +#endif + bool RasterizerGLES3::gles_over_gl = true; void RasterizerGLES3::begin_frame(double frame_step) { @@ -380,6 +384,12 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display flip_y = false; } +#ifdef WINDOWS_ENABLED + if (screen_flipped_y) { + flip_y = !flip_y; + } +#endif + GLuint read_fbo = 0; glGenFramebuffers(1, &read_fbo); glBindFramebuffer(GL_READ_FRAMEBUFFER, read_fbo); @@ -476,9 +486,14 @@ void RasterizerGLES3::set_boot_image(const Ref &p_image, const Color &p_c screenrect.position += ((Size2(win_size.width, win_size.height) - screenrect.size) / 2.0).floor(); } - // Flip Y. - screenrect.position.y = win_size.y - screenrect.position.y; - screenrect.size.y = -screenrect.size.y; +#ifdef WINDOWS_ENABLED + if (!screen_flipped_y) +#endif + { + // Flip Y. + screenrect.position.y = win_size.y - screenrect.position.y; + screenrect.size.y = -screenrect.size.y; + } // Normalize texture coordinates to window size. screenrect.position /= win_size; diff --git a/drivers/gles3/rasterizer_gles3.h b/drivers/gles3/rasterizer_gles3.h index 80a4a792bb2..0cf656e490f 100644 --- a/drivers/gles3/rasterizer_gles3.h +++ b/drivers/gles3/rasterizer_gles3.h @@ -58,6 +58,10 @@ private: double time_total = 0.0; bool flip_xy_workaround = false; +#ifdef WINDOWS_ENABLED + static bool screen_flipped_y; +#endif + static bool gles_over_gl; protected: @@ -117,6 +121,12 @@ public: low_end = true; } +#ifdef WINDOWS_ENABLED + static void set_screen_flipped_y(bool p_flipped) { + screen_flipped_y = p_flipped; + } +#endif + _ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; } _ALWAYS_INLINE_ double get_frame_delta_time() const { return delta; } _ALWAYS_INLINE_ double get_total_time() const { return time_total; }