diff options
author | Andrew Knight <andrew.knight@intopalo.com> | 2015-08-12 12:43:54 +0300 |
---|---|---|
committer | Andrew Knight <andrew.knight@intopalo.com> | 2015-08-13 16:12:37 +0000 |
commit | 807ec8ea48281d5dbe365895fd9679da5b6753a5 (patch) | |
tree | b65ffb79da8e2941385b345dda7cc49f5638a0b0 /src/plugins/platforms/winrt/qwinrteglcontext.cpp | |
parent | ebc2b963aa9e8ce2e983ef08c9b503ccc1702fdb (diff) |
winrt: Refactor platform plugin for XAML support
By using XAML as the platform compositor, many benefits are possible:
- Better input context handling for tablets
- Better multiple window support (including non-fullscreen windows)
- Support for transparent windows and window opacity
- Integration with native platform controls
- Simpler orientation handling on Windows Phone with built-in transitions
This patch applies only the minimal parts to make XAML mode work just as
the raw D3D mode. It does this by:
- Moving all OpenGL parts into QWinRTEGLContext. This will allow us to
have non-OpenGL windows later (e.g. Direct2D raster surfaces).
- Moving more window-specific parts into QWinRTWindow. Each window creates
a SwapChainPanel which can then be used for ANGLE (or Direct2D) content.
- Moving non screen-specific parts into QWinRTIntegration.
- Having QWinRTScreen create the base XAML element Canvas.
- Running certain calls on the UI thread where necessary.
The following code parts were removed:
- The UIAutomationCore code in QWinRTInputContext, as this is incompatible
with XAML automation.
- The D3D Trim and device blacklist, as these have been fixed in ANGLE.
- Core dispatcher processing in QEventDispatcherWinRT. Now there is only
one native event dispatcher; it is always running and never needs to be
pumped.
Future commits should address:
- Maintaining the window stack list and visibility using the XAML Canvas.
- Allowing for windows (e.g. popups) to be sized and positioned instead
of fullscreen.
- Using the XAML automation API to improve the platform input context.
[ChangeLog][QPA][winrt] Windows Store apps are now composited inside a
XAML container, allowing for tighter integration with the native UI layer.
Change-Id: I285c6dea657c5dab2fda2b1bd8e8e5dd15882c72
Reviewed-by: Oliver Wolff <oliver.wolff@theqtcompany.com>
Diffstat (limited to 'src/plugins/platforms/winrt/qwinrteglcontext.cpp')
-rw-r--r-- | src/plugins/platforms/winrt/qwinrteglcontext.cpp | 133 |
1 files changed, 113 insertions, 20 deletions
diff --git a/src/plugins/platforms/winrt/qwinrteglcontext.cpp b/src/plugins/platforms/winrt/qwinrteglcontext.cpp index 42ffe8f716..44aab266ca 100644 --- a/src/plugins/platforms/winrt/qwinrteglcontext.cpp +++ b/src/plugins/platforms/winrt/qwinrteglcontext.cpp @@ -35,38 +35,131 @@ ****************************************************************************/ #include "qwinrteglcontext.h" +#include "qwinrtwindow.h" +#include <private/qeventdispatcher_winrt_p.h> +#include <functional> + +#include <EGL/egl.h> #define EGL_EGLEXT_PROTOTYPES -#include "EGL/eglext.h" +#include <EGL/eglext.h> + +#include <QOpenGLContext> +#include <QtPlatformSupport/private/qeglconvenience_p.h> QT_BEGIN_NAMESPACE -QWinRTEGLContext::QWinRTEGLContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display, EGLSurface surface, EGLConfig config) - : QEGLPlatformContext(format, share, display, &config), m_eglSurface(surface) +class QWinRTEGLContextPrivate +{ +public: + QSurfaceFormat format; + EGLDisplay eglDisplay; + EGLConfig eglConfig; + EGLContext eglContext; + QHash<QPlatformSurface *, EGLSurface> surfaceForWindow; +}; + +QWinRTEGLContext::QWinRTEGLContext(QOpenGLContext *context) + : d_ptr(new QWinRTEGLContextPrivate) +{ + Q_D(QWinRTEGLContext); + d->format = context->format(); + d->format.setRenderableType(QSurfaceFormat::OpenGLES); +} + +QWinRTEGLContext::~QWinRTEGLContext() { + Q_D(QWinRTEGLContext); + foreach (const EGLSurface &surface, d->surfaceForWindow) + eglDestroySurface(d->eglDisplay, surface); + if (d->eglContext != EGL_NO_CONTEXT) + eglDestroyContext(d->eglDisplay, d->eglContext); + if (d->eglDisplay != EGL_NO_DISPLAY) + eglTerminate(d->eglDisplay); } -void QWinRTEGLContext::swapBuffers(QPlatformSurface *surface) +void QWinRTEGLContext::initialize() { -#ifdef Q_OS_WINPHONE - const QSize size = surface->surface()->size(); - eglPostSubBufferNV(eglDisplay(), eglSurfaceForPlatformSurface(surface), - 0, 0, size.width(), size.height()); -#else - eglSwapBuffers(eglDisplay(), eglSurfaceForPlatformSurface(surface)); -#endif + Q_D(QWinRTEGLContext); + + eglBindAPI(EGL_OPENGL_ES_API); + d->eglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + if (d->eglDisplay == EGL_NO_DISPLAY) + qCritical("Failed to initialize EGL display: 0x%x", eglGetError()); + + if (!eglInitialize(d->eglDisplay, nullptr, nullptr)) + qCritical("Failed to initialize EGL: 0x%x", eglGetError()); + + d->eglConfig = q_configFromGLFormat(d->eglDisplay, d->format); + + const EGLint flags = d->format.testOption(QSurfaceFormat::DebugContext) + ? EGL_CONTEXT_OPENGL_DEBUG_BIT_KHR : 0; + const EGLint attributes[] = { + EGL_CONTEXT_CLIENT_VERSION, d->format.majorVersion(), + EGL_CONTEXT_MINOR_VERSION_KHR, d->format.minorVersion(), + EGL_CONTEXT_FLAGS_KHR, flags, + EGL_NONE + }; + d->eglContext = eglCreateContext(d->eglDisplay, d->eglConfig, nullptr, attributes); + if (d->eglContext == EGL_NO_CONTEXT) { + qWarning("QEGLPlatformContext: Failed to create context: %x", eglGetError()); + return; + } } -EGLSurface QWinRTEGLContext::eglSurfaceForPlatformSurface(QPlatformSurface *surface) +bool QWinRTEGLContext::makeCurrent(QPlatformSurface *windowSurface) { - if (surface->surface()->surfaceClass() == QSurface::Window) { - // All windows use the same surface - return m_eglSurface; - } else { - // TODO: return EGL surfaces for offscreen surfaces - qWarning("This plugin does not support offscreen surfaces."); - return EGL_NO_SURFACE; + Q_D(QWinRTEGLContext); + Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface); + + EGLSurface surface = d->surfaceForWindow.value(windowSurface); + if (surface == EGL_NO_SURFACE) { + QWinRTWindow *window = static_cast<QWinRTWindow *>(windowSurface); + HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([this, d, window, &surface]() { + surface = eglCreateWindowSurface(d->eglDisplay, d->eglConfig, + reinterpret_cast<EGLNativeWindowType>(window->winId()), + nullptr); + if (surface == EGL_NO_SURFACE) { + qCritical("Failed to create EGL window surface: 0x%x", eglGetError()); + return E_FAIL; + } + return S_OK; + }); + if (FAILED(hr)) + return false; + d->surfaceForWindow.insert(windowSurface, surface); } + + const bool ok = eglMakeCurrent(d->eglDisplay, surface, surface, d->eglContext); + if (!ok) { + qWarning("QEGLPlatformContext: eglMakeCurrent failed: %x", eglGetError()); + return false; + } + + eglSwapInterval(d->eglDisplay, d->format.swapInterval()); + return true; +} + +void QWinRTEGLContext::doneCurrent() +{ + Q_D(const QWinRTEGLContext); + const bool ok = eglMakeCurrent(d->eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if (!ok) + qWarning("QEGLPlatformContext: eglMakeCurrent failed: %x", eglGetError()); +} + +void QWinRTEGLContext::swapBuffers(QPlatformSurface *windowSurface) +{ + Q_D(QWinRTEGLContext); + Q_ASSERT(windowSurface->surface()->surfaceType() == QSurface::OpenGLSurface); + + eglSwapBuffers(d->eglDisplay, d->surfaceForWindow.value(windowSurface)); +} + +QSurfaceFormat QWinRTEGLContext::format() const +{ + Q_D(const QWinRTEGLContext); + return d->format; } QFunctionPointer QWinRTEGLContext::getProcAddress(const QByteArray &procName) @@ -221,7 +314,7 @@ QFunctionPointer QWinRTEGLContext::getProcAddress(const QByteArray &procName) if (i != standardFuncs.end()) return i.value(); - return QEGLPlatformContext::getProcAddress(procName); + return eglGetProcAddress(procName.constData()); } QT_END_NAMESPACE |