Skip to content

Commit 16dfaa5

Browse files
committed
Merge pull request godotengine#94952 from alvinhochun/angle-d3d11-flip-y
Optimize ANGLE on D3D11 to remove an extra blit
2 parents 9d5a732 + de4ba29 commit 16dfaa5

File tree

4 files changed

+99
-4
lines changed

4 files changed

+99
-4
lines changed

drivers/egl/egl_manager.cpp

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030

3131
#include "egl_manager.h"
3232

33+
#include "drivers/gles3/rasterizer_gles3.h"
34+
3335
#ifdef EGL_ENABLED
3436

3537
#if defined(EGL_STATIC)
@@ -51,6 +53,16 @@ extern "C" EGLAPI EGLDisplay EGLAPIENTRY eglGetPlatformDisplayEXT(EGLenum platfo
5153
#define GLAD_EGL_EXT_platform_base 0
5254
#endif
5355

56+
#ifdef WINDOWS_ENABLED
57+
// Unofficial ANGLE extension: EGL_ANGLE_surface_orientation
58+
#ifndef EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE
59+
#define EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE 0x33A7
60+
#define EGL_SURFACE_ORIENTATION_ANGLE 0x33A8
61+
#define EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE 0x0001
62+
#define EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE 0x0002
63+
#endif
64+
#endif
65+
5466
// Creates and caches a GLDisplay. Returns -1 on error.
5567
int EGLManager::_get_gldisplay_id(void *p_display) {
5668
// Look for a cached GLDisplay.
@@ -115,6 +127,18 @@ int EGLManager::_get_gldisplay_id(void *p_display) {
115127
}
116128
#endif
117129

130+
#ifdef WINDOWS_ENABLED
131+
String client_extensions_string = eglQueryString(new_gldisplay.egl_display, EGL_EXTENSIONS);
132+
if (eglGetError() == EGL_SUCCESS) {
133+
Vector<String> egl_extensions = client_extensions_string.split(" ");
134+
135+
if (egl_extensions.has("EGL_ANGLE_surface_orientation")) {
136+
new_gldisplay.has_EGL_ANGLE_surface_orientation = true;
137+
print_verbose("EGL: EGL_ANGLE_surface_orientation is supported.");
138+
}
139+
}
140+
#endif
141+
118142
displays.push_back(new_gldisplay);
119143

120144
// Return the new GLDisplay's ID.
@@ -237,8 +261,29 @@ Error EGLManager::window_create(DisplayServer::WindowID p_window_id, void *p_dis
237261
GLWindow &glwindow = windows[p_window_id];
238262
glwindow.gldisplay_id = gldisplay_id;
239263

264+
Vector<EGLAttrib> egl_attribs;
265+
266+
#ifdef WINDOWS_ENABLED
267+
if (gldisplay.has_EGL_ANGLE_surface_orientation) {
268+
EGLint optimal_orientation;
269+
if (eglGetConfigAttrib(gldisplay.egl_display, gldisplay.egl_config, EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE, &optimal_orientation)) {
270+
// We only need to support inverting Y for optimizing ANGLE on D3D11.
271+
if (optimal_orientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE && !(optimal_orientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE)) {
272+
egl_attribs.push_back(EGL_SURFACE_ORIENTATION_ANGLE);
273+
egl_attribs.push_back(EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE);
274+
}
275+
} else {
276+
ERR_PRINT(vformat("Failed to get EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE, error: 0x%08X", eglGetError()));
277+
}
278+
}
279+
280+
if (!egl_attribs.is_empty()) {
281+
egl_attribs.push_back(EGL_NONE);
282+
}
283+
#endif
284+
240285
if (GLAD_EGL_VERSION_1_5) {
241-
glwindow.egl_surface = eglCreatePlatformWindowSurface(gldisplay.egl_display, gldisplay.egl_config, p_native_window, nullptr);
286+
glwindow.egl_surface = eglCreatePlatformWindowSurface(gldisplay.egl_display, gldisplay.egl_config, p_native_window, egl_attribs.ptr());
242287
} else {
243288
EGLNativeWindowType *native_window_type = (EGLNativeWindowType *)p_native_window;
244289
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
250295

251296
glwindow.initialized = true;
252297

298+
#ifdef WINDOWS_ENABLED
299+
if (gldisplay.has_EGL_ANGLE_surface_orientation) {
300+
EGLint orientation;
301+
if (eglQuerySurface(gldisplay.egl_display, glwindow.egl_surface, EGL_SURFACE_ORIENTATION_ANGLE, &orientation)) {
302+
if (orientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE && !(orientation & EGL_SURFACE_ORIENTATION_INVERT_X_ANGLE)) {
303+
glwindow.flipped_y = true;
304+
print_verbose("EGL: Using optimal surface orientation: Invert Y");
305+
}
306+
} else {
307+
ERR_PRINT(vformat("Failed to get EGL_SURFACE_ORIENTATION_ANGLE, error: 0x%08X", eglGetError()));
308+
}
309+
}
310+
#endif
311+
253312
window_make_current(p_window_id);
254313

255314
return OK;
@@ -316,6 +375,10 @@ void EGLManager::window_make_current(DisplayServer::WindowID p_window_id) {
316375
GLDisplay &current_display = displays[current_window->gldisplay_id];
317376

318377
eglMakeCurrent(current_display.egl_display, current_window->egl_surface, current_window->egl_surface, current_display.egl_context);
378+
379+
#ifdef WINDOWS_ENABLED
380+
RasterizerGLES3::set_screen_flipped_y(glwindow.flipped_y);
381+
#endif
319382
}
320383

321384
void EGLManager::set_use_vsync(bool p_use) {

drivers/egl/egl_manager.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,18 @@ class EGLManager {
5353
EGLDisplay egl_display = EGL_NO_DISPLAY;
5454
EGLContext egl_context = EGL_NO_CONTEXT;
5555
EGLConfig egl_config = nullptr;
56+
57+
#ifdef WINDOWS_ENABLED
58+
bool has_EGL_ANGLE_surface_orientation = false;
59+
#endif
5660
};
5761

5862
// EGL specific window data.
5963
struct GLWindow {
6064
bool initialized = false;
65+
#ifdef WINDOWS_ENABLED
66+
bool flipped_y = false;
67+
#endif
6168

6269
// An handle to the GLDisplay associated with this window.
6370
int gldisplay_id = -1;

drivers/gles3/rasterizer_gles3.cpp

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,10 @@
8686
#define strcpy strcpy_s
8787
#endif
8888

89+
#ifdef WINDOWS_ENABLED
90+
bool RasterizerGLES3::screen_flipped_y = false;
91+
#endif
92+
8993
bool RasterizerGLES3::gles_over_gl = true;
9094

9195
void RasterizerGLES3::begin_frame(double frame_step) {
@@ -389,6 +393,12 @@ void RasterizerGLES3::_blit_render_target_to_screen(RID p_render_target, Display
389393
flip_y = false;
390394
}
391395

396+
#ifdef WINDOWS_ENABLED
397+
if (screen_flipped_y) {
398+
flip_y = !flip_y;
399+
}
400+
#endif
401+
392402
GLuint read_fbo = 0;
393403
glGenFramebuffers(1, &read_fbo);
394404
glBindFramebuffer(GL_READ_FRAMEBUFFER, read_fbo);
@@ -485,9 +495,14 @@ void RasterizerGLES3::set_boot_image(const Ref<Image> &p_image, const Color &p_c
485495
screenrect.position += ((Size2(win_size.width, win_size.height) - screenrect.size) / 2.0).floor();
486496
}
487497

488-
// Flip Y.
489-
screenrect.position.y = win_size.y - screenrect.position.y;
490-
screenrect.size.y = -screenrect.size.y;
498+
#ifdef WINDOWS_ENABLED
499+
if (!screen_flipped_y)
500+
#endif
501+
{
502+
// Flip Y.
503+
screenrect.position.y = win_size.y - screenrect.position.y;
504+
screenrect.size.y = -screenrect.size.y;
505+
}
491506

492507
// Normalize texture coordinates to window size.
493508
screenrect.position /= win_size;

drivers/gles3/rasterizer_gles3.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,10 @@ class RasterizerGLES3 : public RendererCompositor {
5858
double time_total = 0.0;
5959
bool flip_xy_workaround = false;
6060

61+
#ifdef WINDOWS_ENABLED
62+
static bool screen_flipped_y;
63+
#endif
64+
6165
static bool gles_over_gl;
6266

6367
protected:
@@ -118,6 +122,12 @@ class RasterizerGLES3 : public RendererCompositor {
118122
low_end = true;
119123
}
120124

125+
#ifdef WINDOWS_ENABLED
126+
static void set_screen_flipped_y(bool p_flipped) {
127+
screen_flipped_y = p_flipped;
128+
}
129+
#endif
130+
121131
_ALWAYS_INLINE_ uint64_t get_frame_number() const { return frame; }
122132
_ALWAYS_INLINE_ double get_frame_delta_time() const { return delta; }
123133
_ALWAYS_INLINE_ double get_total_time() const { return time_total; }

0 commit comments

Comments
 (0)