Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save jturcotte/0ad810b31200d77de3d6ef1ae3b10645 to your computer and use it in GitHub Desktop.
Save jturcotte/0ad810b31200d77de3d6ef1ae3b10645 to your computer and use it in GitHub Desktop.
Support EGL_ANGLE_surface_orientation to avoid an extra blit
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
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