eglfs: Handle custom platform window implementations better
Backends may want to subclass QEglFSWindow and reimplement resetSurface() and similar. Make it possible to do this by moving window creation to the device integration interface, similarly to screens. In addition to customizing the windows, some backends may want to disable the dependency on surfaceless contexts when using offscreen windows (i.e. pbuffer surfaces). Make this possible too. Change-Id: Ic5a426e07f821c7a800217b8799f91770ba6a6d8 Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@theqtcompany.com> Reviewed-by: Louai Al-Khanji <louai.al-khanji@theqtcompany.com>
This commit is contained in:
parent
b63c3d4d9a
commit
6046458dee
@ -88,7 +88,6 @@ public:
|
||||
protected:
|
||||
virtual bool filterConfig(EGLConfig config) const;
|
||||
|
||||
private:
|
||||
QSurfaceFormat m_format;
|
||||
EGLDisplay m_display;
|
||||
EGLint m_surfaceType;
|
||||
|
@ -49,13 +49,15 @@ QT_BEGIN_NAMESPACE
|
||||
and return a new instance of this class.
|
||||
*/
|
||||
|
||||
QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface)
|
||||
QEGLPbuffer::QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface,
|
||||
QEGLPlatformContext::Flags flags)
|
||||
: QPlatformOffscreenSurface(offscreenSurface)
|
||||
, m_format(format)
|
||||
, m_display(display)
|
||||
, m_pbuffer(EGL_NO_SURFACE)
|
||||
{
|
||||
bool hasSurfaceless = q_hasEglExtension(display, "EGL_KHR_surfaceless_context");
|
||||
bool hasSurfaceless = !flags.testFlag(QEGLPlatformContext::NoSurfaceless)
|
||||
&& q_hasEglExtension(display, "EGL_KHR_surfaceless_context");
|
||||
|
||||
// Disable surfaceless contexts on Mesa for now. As of 10.6.0 and Intel at least, some
|
||||
// operations (glReadPixels) are unable to work without a surface since they at some
|
||||
|
@ -47,13 +47,15 @@
|
||||
|
||||
#include <EGL/egl.h>
|
||||
#include <qpa/qplatformoffscreensurface.h>
|
||||
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEGLPbuffer : public QPlatformOffscreenSurface
|
||||
{
|
||||
public:
|
||||
QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface);
|
||||
QEGLPbuffer(EGLDisplay display, const QSurfaceFormat &format, QOffscreenSurface *offscreenSurface,
|
||||
QEGLPlatformContext::Flags flags = 0);
|
||||
~QEGLPbuffer();
|
||||
|
||||
QSurfaceFormat format() const Q_DECL_OVERRIDE { return m_format; }
|
||||
|
@ -106,11 +106,12 @@ QT_BEGIN_NAMESPACE
|
||||
#endif
|
||||
|
||||
QEGLPlatformContext::QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
|
||||
EGLConfig *config, const QVariant &nativeHandle)
|
||||
EGLConfig *config, const QVariant &nativeHandle, Flags flags)
|
||||
: m_eglDisplay(display)
|
||||
, m_swapInterval(-1)
|
||||
, m_swapIntervalEnvChecked(false)
|
||||
, m_swapIntervalFromEnv(-1)
|
||||
, m_flags(flags)
|
||||
{
|
||||
if (nativeHandle.isNull()) {
|
||||
m_eglConfig = config ? *config : q_configFromGLFormat(display, format);
|
||||
@ -291,7 +292,7 @@ void QEGLPlatformContext::updateFormatFromGL()
|
||||
// drivers (Mesa) when certain attributes are present (multisampling).
|
||||
EGLSurface tempSurface = EGL_NO_SURFACE;
|
||||
EGLContext tempContext = EGL_NO_CONTEXT;
|
||||
if (!q_hasEglExtension(m_eglDisplay, "EGL_KHR_surfaceless_context"))
|
||||
if (m_flags.testFlag(NoSurfaceless) || !q_hasEglExtension(m_eglDisplay, "EGL_KHR_surfaceless_context"))
|
||||
tempSurface = createTemporaryOffscreenSurface();
|
||||
|
||||
EGLBoolean ok = eglMakeCurrent(m_eglDisplay, tempSurface, tempSurface, m_eglContext);
|
||||
|
@ -56,8 +56,14 @@ QT_BEGIN_NAMESPACE
|
||||
class QEGLPlatformContext : public QPlatformOpenGLContext
|
||||
{
|
||||
public:
|
||||
enum Flag {
|
||||
NoSurfaceless = 0x01
|
||||
};
|
||||
Q_DECLARE_FLAGS(Flags, Flag)
|
||||
|
||||
QEGLPlatformContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
|
||||
EGLConfig *config = 0, const QVariant &nativeHandle = QVariant());
|
||||
EGLConfig *config = 0, const QVariant &nativeHandle = QVariant(),
|
||||
Flags flags = 0);
|
||||
~QEGLPlatformContext();
|
||||
|
||||
void initialize() Q_DECL_OVERRIDE;
|
||||
@ -93,10 +99,13 @@ private:
|
||||
int m_swapInterval;
|
||||
bool m_swapIntervalEnvChecked;
|
||||
int m_swapIntervalFromEnv;
|
||||
Flags m_flags;
|
||||
bool m_ownsContext;
|
||||
QVector<EGLint> m_contextAttrs;
|
||||
};
|
||||
|
||||
Q_DECLARE_OPERATORS_FOR_FLAGS(QEGLPlatformContext::Flags)
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif //QEGLPLATFORMCONTEXT_H
|
||||
|
@ -44,7 +44,8 @@ QT_BEGIN_NAMESPACE
|
||||
|
||||
QEglFSContext::QEglFSContext(const QSurfaceFormat &format, QPlatformOpenGLContext *share, EGLDisplay display,
|
||||
EGLConfig *config, const QVariant &nativeHandle)
|
||||
: QEGLPlatformContext(format, share, display, config, nativeHandle),
|
||||
: QEGLPlatformContext(format, share, display, config, nativeHandle,
|
||||
qt_egl_device_integration()->supportsSurfacelessContexts() ? Flags(0) : QEGLPlatformContext::NoSurfaceless),
|
||||
m_tempWindow(0)
|
||||
{
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "qeglfsdeviceintegration.h"
|
||||
#include "qeglfsintegration.h"
|
||||
#include "qeglfscursor.h"
|
||||
#include "qeglfswindow.h"
|
||||
#include <QtPlatformSupport/private/qeglconvenience_p.h>
|
||||
#include <QGuiApplication>
|
||||
#include <private/qguiapplication_p.h>
|
||||
@ -175,6 +176,11 @@ EGLNativeDisplayType QEGLDeviceIntegration::platformDisplay() const
|
||||
return EGL_DEFAULT_DISPLAY;
|
||||
}
|
||||
|
||||
EGLDisplay QEGLDeviceIntegration::createDisplay(EGLNativeDisplayType nativeDisplay)
|
||||
{
|
||||
return eglGetDisplay(nativeDisplay);
|
||||
}
|
||||
|
||||
bool QEGLDeviceIntegration::usesDefaultScreen()
|
||||
{
|
||||
return true;
|
||||
@ -238,6 +244,11 @@ qreal QEGLDeviceIntegration::refreshRate() const
|
||||
return q_refreshRateFromFb(framebuffer);
|
||||
}
|
||||
|
||||
EGLint QEGLDeviceIntegration::surfaceType() const
|
||||
{
|
||||
return EGL_WINDOW_BIT;
|
||||
}
|
||||
|
||||
QSurfaceFormat QEGLDeviceIntegration::surfaceFormatFor(const QSurfaceFormat &inputFormat) const
|
||||
{
|
||||
QSurfaceFormat format = inputFormat;
|
||||
@ -257,6 +268,11 @@ bool QEGLDeviceIntegration::filterConfig(EGLDisplay, EGLConfig) const
|
||||
return true;
|
||||
}
|
||||
|
||||
QEglFSWindow *QEGLDeviceIntegration::createWindow(QWindow *window) const
|
||||
{
|
||||
return new QEglFSWindow(window);
|
||||
}
|
||||
|
||||
EGLNativeWindowType QEGLDeviceIntegration::createNativeWindow(QPlatformWindow *platformWindow,
|
||||
const QSize &size,
|
||||
const QSurfaceFormat &format)
|
||||
@ -313,4 +329,9 @@ bool QEGLDeviceIntegration::supportsPBuffers() const
|
||||
return true;
|
||||
}
|
||||
|
||||
bool QEGLDeviceIntegration::supportsSurfacelessContexts() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -56,6 +56,7 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QPlatformSurface;
|
||||
class QEglFSWindow;
|
||||
|
||||
#define QEGLDeviceIntegrationFactoryInterface_iid "org.qt-project.qt.qpa.egl.QEGLDeviceIntegrationFactoryInterface.5.5"
|
||||
|
||||
@ -67,6 +68,7 @@ public:
|
||||
virtual void platformInit();
|
||||
virtual void platformDestroy();
|
||||
virtual EGLNativeDisplayType platformDisplay() const;
|
||||
virtual EGLDisplay createDisplay(EGLNativeDisplayType nativeDisplay);
|
||||
virtual bool usesDefaultScreen();
|
||||
virtual void screenInit();
|
||||
virtual void screenDestroy();
|
||||
@ -79,6 +81,8 @@ public:
|
||||
virtual QImage::Format screenFormat() const;
|
||||
virtual qreal refreshRate() const;
|
||||
virtual QSurfaceFormat surfaceFormatFor(const QSurfaceFormat &inputFormat) const;
|
||||
virtual EGLint surfaceType() const;
|
||||
virtual QEglFSWindow *createWindow(QWindow *window) const;
|
||||
virtual EGLNativeWindowType createNativeWindow(QPlatformWindow *platformWindow,
|
||||
const QSize &size,
|
||||
const QSurfaceFormat &format);
|
||||
@ -92,6 +96,7 @@ public:
|
||||
virtual QByteArray fbDeviceName() const;
|
||||
virtual int framebufferIndex() const;
|
||||
virtual bool supportsPBuffers() const;
|
||||
virtual bool supportsSurfacelessContexts() const;
|
||||
};
|
||||
|
||||
class Q_EGLFS_EXPORT QEGLDeviceIntegrationPlugin : public QObject
|
||||
|
@ -117,7 +117,7 @@ void QEglFSIntegration::initialize()
|
||||
{
|
||||
qt_egl_device_integration()->platformInit();
|
||||
|
||||
m_display = eglGetDisplay(nativeDisplay());
|
||||
m_display = qt_egl_device_integration()->createDisplay(nativeDisplay());
|
||||
if (m_display == EGL_NO_DISPLAY)
|
||||
qFatal("Could not open egl display");
|
||||
|
||||
@ -179,7 +179,7 @@ QPlatformBackingStore *QEglFSIntegration::createPlatformBackingStore(QWindow *wi
|
||||
QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const
|
||||
{
|
||||
QWindowSystemInterface::flushWindowSystemEvents();
|
||||
QEglFSWindow *w = new QEglFSWindow(window);
|
||||
QEglFSWindow *w = qt_egl_device_integration()->createWindow(window);
|
||||
w->create();
|
||||
if (window->type() != Qt::ToolTip)
|
||||
w->requestActivateWindow();
|
||||
@ -213,10 +213,14 @@ QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOf
|
||||
{
|
||||
EGLDisplay dpy = surface->screen() ? static_cast<QEglFSScreen *>(surface->screen()->handle())->display() : display();
|
||||
QSurfaceFormat fmt = qt_egl_device_integration()->surfaceFormatFor(surface->requestedFormat());
|
||||
if (qt_egl_device_integration()->supportsPBuffers())
|
||||
return new QEGLPbuffer(dpy, fmt, surface);
|
||||
else
|
||||
if (qt_egl_device_integration()->supportsPBuffers()) {
|
||||
QEGLPlatformContext::Flags flags = 0;
|
||||
if (!qt_egl_device_integration()->supportsSurfacelessContexts())
|
||||
flags |= QEGLPlatformContext::NoSurfaceless;
|
||||
return new QEGLPbuffer(dpy, fmt, surface, flags);
|
||||
} else {
|
||||
return new QEglFSOffscreenWindow(dpy, fmt, surface);
|
||||
}
|
||||
// Never return null. Multiple QWindows are not supported by this plugin.
|
||||
}
|
||||
|
||||
@ -433,6 +437,7 @@ EGLConfig QEglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceForm
|
||||
};
|
||||
|
||||
Chooser chooser(display);
|
||||
chooser.setSurfaceType(qt_egl_device_integration()->surfaceType());
|
||||
chooser.setSurfaceFormat(format);
|
||||
return chooser.chooseConfig();
|
||||
}
|
||||
|
@ -51,7 +51,7 @@ QEglFSWindow::QEglFSWindow(QWindow *w)
|
||||
m_backingStore(0),
|
||||
m_raster(false),
|
||||
m_winId(0),
|
||||
m_surface(0),
|
||||
m_surface(EGL_NO_SURFACE),
|
||||
m_window(0),
|
||||
m_flags(0)
|
||||
{
|
||||
@ -120,13 +120,14 @@ void QEglFSWindow::create()
|
||||
setGeometry(QRect()); // will become fullscreen
|
||||
QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(0, 0), geometry().size()));
|
||||
|
||||
EGLDisplay display = static_cast<QEglFSScreen *>(screen)->display();
|
||||
QSurfaceFormat platformFormat = qt_egl_device_integration()->surfaceFormatFor(window()->requestedFormat());
|
||||
m_config = QEglFSIntegration::chooseConfig(display, platformFormat);
|
||||
m_format = q_glFormatFromConfig(display, m_config, platformFormat);
|
||||
|
||||
resetSurface();
|
||||
|
||||
if (m_surface == EGL_NO_SURFACE) {
|
||||
EGLint error = eglGetError();
|
||||
eglTerminate(screen->display());
|
||||
qFatal("EGL Error : Could not create the egl surface: error = 0x%x\n", error);
|
||||
}
|
||||
|
||||
screen->setPrimarySurface(m_surface);
|
||||
|
||||
if (isRaster()) {
|
||||
@ -158,15 +159,10 @@ void QEglFSWindow::destroy()
|
||||
QOpenGLCompositor::instance()->removeWindow(this);
|
||||
}
|
||||
|
||||
// The virtual functions resetSurface and invalidateSurface may get overridden
|
||||
// in derived classes, for example in the Android port, to perform the native
|
||||
// window and surface creation differently.
|
||||
|
||||
void QEglFSWindow::invalidateSurface()
|
||||
{
|
||||
if (m_surface != EGL_NO_SURFACE) {
|
||||
EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
|
||||
eglDestroySurface(display, m_surface);
|
||||
eglDestroySurface(screen()->display(), m_surface);
|
||||
m_surface = EGL_NO_SURFACE;
|
||||
}
|
||||
qt_egl_device_integration()->destroyNativeWindow(m_window);
|
||||
@ -175,15 +171,13 @@ void QEglFSWindow::invalidateSurface()
|
||||
|
||||
void QEglFSWindow::resetSurface()
|
||||
{
|
||||
QEglFSScreen *nativeScreen = static_cast<QEglFSScreen *>(screen());
|
||||
EGLDisplay display = nativeScreen->display();
|
||||
m_window = qt_egl_device_integration()->createNativeWindow(this, nativeScreen->geometry().size(), m_format);
|
||||
EGLDisplay display = screen()->display();
|
||||
QSurfaceFormat platformFormat = qt_egl_device_integration()->surfaceFormatFor(window()->requestedFormat());
|
||||
|
||||
m_config = QEglFSIntegration::chooseConfig(display, platformFormat);
|
||||
m_format = q_glFormatFromConfig(display, m_config, platformFormat);
|
||||
m_window = qt_egl_device_integration()->createNativeWindow(this, screen()->geometry().size(), m_format);
|
||||
m_surface = eglCreateWindowSurface(display, m_config, m_window, NULL);
|
||||
if (m_surface == EGL_NO_SURFACE) {
|
||||
EGLint error = eglGetError();
|
||||
eglTerminate(display);
|
||||
qFatal("EGL Error : Could not create the egl surface: error = 0x%x\n", error);
|
||||
}
|
||||
}
|
||||
|
||||
void QEglFSWindow::setVisible(bool visible)
|
||||
|
@ -89,7 +89,7 @@ public:
|
||||
const QPlatformTextureList *textures() const Q_DECL_OVERRIDE;
|
||||
void endCompositing() Q_DECL_OVERRIDE;
|
||||
|
||||
private:
|
||||
protected:
|
||||
QOpenGLCompositorBackingStore *m_backingStore;
|
||||
bool m_raster;
|
||||
WId m_winId;
|
||||
|
Loading…
Reference in New Issue
Block a user