Last active
November 18, 2016 11:30
-
-
Save jturcotte/0ad810b31200d77de3d6ef1ae3b10645 to your computer and use it in GitHub Desktop.
Support EGL_ANGLE_surface_orientation to avoid an extra blit
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From cf4dbaadeff8be28607c74c9d4bfea010af92d95 Mon Sep 17 00:00:00 2001 | |
From: Jocelyn Turcotte <[email protected]> | |
Date: Fri, 24 Jun 2016 16:22:09 +0200 | |
Subject: [PATCH] Support EGL_ANGLE_surface_orientation to avoid an extra blit | |
on each frame | |
This adds an UseOptimalOrientation option to QSurfaceFormat to let | |
EGL tell ANGLE that the application will take care of using Y-flipped | |
coordinates instead of having to do it through an intermediate surface | |
at the end. | |
Since this also has implication for Qt applications, this behavior is | |
opt-in and should only be enabled if any GL code handled from the | |
application side is ready to also flip all Y coordinates when | |
QOpenGLContext::currentContext()->format().orientationFlags() is set | |
accordingly. | |
The API needed to support this is rather heavy for a non-cross-platform | |
feature, the scenegraph-ng refactoring to support DirectX directly might | |
be a better long-term solution. | |
--- | |
src/gui/kernel/qsurfaceformat.cpp | 11 +++++++++ | |
src/gui/kernel/qsurfaceformat.h | 11 ++++++++- | |
.../platforms/windows/qwindowseglcontext.cpp | 28 +++++++++++++++++++--- | |
src/plugins/platforms/windows/qwindowseglcontext.h | 2 +- | |
.../platforms/windows/qwindowsopenglcontext.h | 2 +- | |
src/plugins/platforms/windows/qwindowswindow.cpp | 2 +- | |
6 files changed, 49 insertions(+), 7 deletions(-) | |
diff --git a/src/gui/kernel/qsurfaceformat.cpp b/src/gui/kernel/qsurfaceformat.cpp | |
index d7dc0fa..32f101c 100644 | |
--- a/src/gui/kernel/qsurfaceformat.cpp | |
+++ b/src/gui/kernel/qsurfaceformat.cpp | |
@@ -108,6 +108,7 @@ public: | |
int major; | |
int minor; | |
int swapInterval; | |
+ QSurfaceFormat::OrientationFlags orientationFlags; | |
}; | |
/*! | |
@@ -734,6 +735,16 @@ int QSurfaceFormat::swapInterval() const | |
return d->swapInterval; | |
} | |
+QSurfaceFormat::OrientationFlags QSurfaceFormat::orientationFlags() const | |
+{ | |
+ return d->orientationFlags; | |
+} | |
+ | |
+void QSurfaceFormat::setOrientationFlags(QSurfaceFormat::OrientationFlags orientationFlags) | |
+{ | |
+ d->orientationFlags = orientationFlags; | |
+} | |
+ | |
Q_GLOBAL_STATIC(QSurfaceFormat, qt_default_surface_format) | |
/*! | |
diff --git a/src/gui/kernel/qsurfaceformat.h b/src/gui/kernel/qsurfaceformat.h | |
index 2461636..ecd5501 100644 | |
--- a/src/gui/kernel/qsurfaceformat.h | |
+++ b/src/gui/kernel/qsurfaceformat.h | |
@@ -57,7 +57,8 @@ public: | |
StereoBuffers = 0x0001, | |
DebugContext = 0x0002, | |
DeprecatedFunctions = 0x0004, | |
- ResetNotification = 0x0008 | |
+ ResetNotification = 0x0008, | |
+ UseOptimalOrientation = 0x0010 | |
}; | |
Q_ENUM(FormatOption) | |
Q_DECLARE_FLAGS(FormatOptions, FormatOption) | |
@@ -85,6 +86,11 @@ public: | |
}; | |
Q_ENUM(OpenGLContextProfile) | |
+ enum OrientationFlag { | |
+ MirrorVertically = 0x0001, | |
+ }; | |
+ Q_DECLARE_FLAGS(OrientationFlags, OrientationFlag) | |
+ | |
QSurfaceFormat(); | |
/*implicit*/ QSurfaceFormat(FormatOptions options); | |
QSurfaceFormat(const QSurfaceFormat &other); | |
@@ -145,6 +151,9 @@ public: | |
int swapInterval() const; | |
void setSwapInterval(int interval); | |
+ QSurfaceFormat::OrientationFlags orientationFlags() const; | |
+ void setOrientationFlags(QSurfaceFormat::OrientationFlags orientationFlags); | |
+ | |
static void setDefaultFormat(const QSurfaceFormat &format); | |
static QSurfaceFormat defaultFormat(); | |
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.cpp b/src/plugins/platforms/windows/qwindowseglcontext.cpp | |
index a4738dc..8249dcb 100644 | |
--- a/src/plugins/platforms/windows/qwindowseglcontext.cpp | |
+++ b/src/plugins/platforms/windows/qwindowseglcontext.cpp | |
@@ -297,11 +297,25 @@ QWindowsOpenGLContext *QWindowsEGLStaticContext::createContext(QOpenGLContext *c | |
return new QWindowsEGLContext(this, context->format(), context->shareHandle()); | |
} | |
-void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) | |
+void *QWindowsEGLStaticContext::createWindowSurface(void *nativeWindow, void *nativeConfig, const QSurfaceFormat format, int *err) | |
{ | |
*err = 0; | |
+ | |
+ std::vector<EGLint> attrib_list; | |
+#ifdef EGL_ANGLE_surface_orientation | |
+ if (format.testOption(QSurfaceFormat::UseOptimalOrientation)) { | |
+ EGLint surfaceOrientation = 0; | |
+ libEGL.eglGetConfigAttrib(m_display, nativeConfig, EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE, &surfaceOrientation); | |
+ if (surfaceOrientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) { | |
+ attrib_list.push_back(EGL_SURFACE_ORIENTATION_ANGLE); | |
+ attrib_list.push_back(EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE); | |
+ } | |
+ } | |
+#endif | |
+ attrib_list.push_back(EGL_NONE); | |
EGLSurface surface = libEGL.eglCreateWindowSurface(m_display, nativeConfig, | |
- static_cast<EGLNativeWindowType>(nativeWindow), 0); | |
+ static_cast<EGLNativeWindowType>(nativeWindow), | |
+ &attrib_list[0]); | |
if (surface == EGL_NO_SURFACE) { | |
*err = libEGL.eglGetError(); | |
qWarning("%s: Could not create the EGL window surface: 0x%x", __FUNCTION__, *err); | |
@@ -350,6 +364,14 @@ QSurfaceFormat QWindowsEGLStaticContext::formatFromConfig(EGLDisplay display, EG | |
format.setStereo(false); | |
format.setSwapInterval(referenceFormat.swapInterval()); | |
+#ifdef EGL_ANGLE_surface_orientation | |
+ if (referenceFormat.testOption(QSurfaceFormat::UseOptimalOrientation)) { | |
+ EGLint surfaceOrientation = 0; | |
+ libEGL.eglGetConfigAttrib(display, config, EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE, &surfaceOrientation); | |
+ format.setOrientationFlags((surfaceOrientation & EGL_SURFACE_ORIENTATION_INVERT_Y_ANGLE) ? QSurfaceFormat::MirrorVertically : QSurfaceFormat::OrientationFlags()); | |
+ } | |
+#endif | |
+ | |
// Clear the EGL error state because some of the above may | |
// have errored out because the attribute is not applicable | |
// to the surface type. Such errors don't matter. | |
@@ -445,7 +467,7 @@ QWindowsEGLContext::QWindowsEGLContext(QWindowsEGLStaticContext *staticContext, | |
} | |
} | |
m_format.setProfile(QSurfaceFormat::NoProfile); | |
- m_format.setOptions(QSurfaceFormat::FormatOptions()); | |
+ m_format.setOptions(m_format.options() & QSurfaceFormat::UseOptimalOrientation); | |
QWindowsEGLStaticContext::libEGL.eglMakeCurrent(prevDisplay, prevSurfaceDraw, prevSurfaceRead, prevContext); | |
} | |
QWindowsEGLStaticContext::libEGL.eglDestroySurface(m_eglDisplay, pbuffer); | |
diff --git a/src/plugins/platforms/windows/qwindowseglcontext.h b/src/plugins/platforms/windows/qwindowseglcontext.h | |
index 48a19f8..14e9c63 100644 | |
--- a/src/plugins/platforms/windows/qwindowseglcontext.h | |
+++ b/src/plugins/platforms/windows/qwindowseglcontext.h | |
@@ -121,7 +121,7 @@ public: | |
void *moduleHandle() const Q_DECL_OVERRIDE { return libGLESv2.moduleHandle(); } | |
QOpenGLContext::OpenGLModuleType moduleType() const Q_DECL_OVERRIDE { return QOpenGLContext::LibGLES; } | |
- void *createWindowSurface(void *nativeWindow, void *nativeConfig, int *err) Q_DECL_OVERRIDE; | |
+ void *createWindowSurface(void *nativeWindow, void *nativeConfig, const QSurfaceFormat format, int *err) Q_DECL_OVERRIDE; | |
void destroyWindowSurface(void *nativeSurface) Q_DECL_OVERRIDE; | |
QSurfaceFormat formatFromConfig(EGLDisplay display, EGLConfig config, const QSurfaceFormat &referenceFormat); | |
diff --git a/src/plugins/platforms/windows/qwindowsopenglcontext.h b/src/plugins/platforms/windows/qwindowsopenglcontext.h | |
index 85f4f71..af2f695 100644 | |
--- a/src/plugins/platforms/windows/qwindowsopenglcontext.h | |
+++ b/src/plugins/platforms/windows/qwindowsopenglcontext.h | |
@@ -62,7 +62,7 @@ public: | |
// If the windowing system interface needs explicitly created window surfaces (like EGL), | |
// reimplement these. | |
- virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, int * /*err*/) { return 0; } | |
+ virtual void *createWindowSurface(void * /*nativeWindow*/, void * /*nativeConfig*/, const QSurfaceFormat /*format*/, int * /*err*/) { return 0; } | |
virtual void destroyWindowSurface(void * /*nativeSurface*/) { } | |
private: | |
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp | |
index 0ebed59..035d175 100644 | |
--- a/src/plugins/platforms/windows/qwindowswindow.cpp | |
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp | |
@@ -2332,7 +2332,7 @@ void *QWindowsWindow::surface(void *nativeConfig, int *err) | |
#else | |
if (!m_surface) { | |
if (QWindowsStaticOpenGLContext *staticOpenGLContext = QWindowsIntegration::staticOpenGLContext()) | |
- m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, err); | |
+ m_surface = staticOpenGLContext->createWindowSurface(m_data.hwnd, nativeConfig, m_format, err); | |
} | |
return m_surface; | |
-- | |
1.9.5.msysgit.0 | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
From cd62ef173eb2827ff765ba8095f3318f07aebed1 Mon Sep 17 00:00:00 2001 | |
From: Jocelyn Turcotte <[email protected]> | |
Date: Fri, 24 Jun 2016 16:23:19 +0200 | |
Subject: [PATCH] Handle QSurfaceFormat::MirrorVertically in QtQuick2 | |
--- | |
src/quick/items/qquickwindow.cpp | 8 +++++++- | |
src/quick/scenegraph/qsgdefaultcontext.cpp | 2 ++ | |
2 files changed, 9 insertions(+), 1 deletion(-) | |
diff --git a/src/quick/items/qquickwindow.cpp b/src/quick/items/qquickwindow.cpp | |
index a0a07f4..a0da42f 100644 | |
--- a/src/quick/items/qquickwindow.cpp | |
+++ b/src/quick/items/qquickwindow.cpp | |
@@ -459,7 +459,13 @@ void QQuickWindowPrivate::renderSceneGraph(const QSize &size) | |
renderer->setDeviceRect(rect); | |
renderer->setViewportRect(rect); | |
} | |
- renderer->setProjectionMatrixToRect(QRect(QPoint(0, 0), size)); | |
+ QRectF projRect(QPoint(0, 0), size); | |
+ bool mirrorVertically = QOpenGLContext::currentContext()->format().orientationFlags() & QSurfaceFormat::MirrorVertically; | |
+ QRectF mirrored(projRect.left(), | |
+ mirrorVertically ? projRect.bottom() : projRect.top(), | |
+ projRect.width(), | |
+ mirrorVertically ? -projRect.height() : projRect.height()); | |
+ renderer->setProjectionMatrixToRect(mirrored); | |
renderer->setDevicePixelRatio(devicePixelRatio); | |
context->renderNextFrame(renderer, fboId); | |
diff --git a/src/quick/scenegraph/qsgdefaultcontext.cpp b/src/quick/scenegraph/qsgdefaultcontext.cpp | |
index 405f1d8..f712d8b 100644 | |
--- a/src/quick/scenegraph/qsgdefaultcontext.cpp | |
+++ b/src/quick/scenegraph/qsgdefaultcontext.cpp | |
@@ -221,6 +221,8 @@ QSurfaceFormat QSGDefaultContext::defaultSurfaceFormat() const | |
static bool enableDebug = qEnvironmentVariableIsSet("QSG_OPENGL_DEBUG"); | |
format.setDepthBufferSize(useDepth ? 24 : 0); | |
format.setStencilBufferSize(useStencil ? 8 : 0); | |
+ // XXX: Uncomment to enable application-side Y-coordinates-flipping by default | |
+ // format.setOption(QSurfaceFormat::UseOptimalOrientation); | |
if (enableDebug) | |
format.setOption(QSurfaceFormat::DebugContext); | |
if (QQuickWindow::hasDefaultAlphaBuffer()) | |
-- | |
1.9.5.msysgit.0 | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment