Revive eglfs' raster window support
A number of consequences of the new rhi-based backingstore
composition were not handled. Most importantly, the fact
that RasterGLSurface is not a thing anymore in practice
causes challenges because we can no longer decide just
based on the surfaceType what a QWindow with OpenGLSurface
would be. (a plain GL window or a GL window with a backing
store?) Also, the backingstore needs to be able to initialize
its backing QRhi by itself, because with eglfs going through
OpenGL is the only way.
Amends 68a4c5da9a
Fixes: QTBUG-102750
Change-Id: Ia1ca59d01e3012264a76b50e591612fdcc2a0bd6
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: Andy Nichols <andy.nichols@qt.io>
This commit is contained in:
parent
9861fd09cb
commit
8161726619
@ -94,14 +94,17 @@ QOpenGLCompositor::~QOpenGLCompositor()
|
||||
compositor = 0;
|
||||
}
|
||||
|
||||
void QOpenGLCompositor::setTarget(QOpenGLContext *context, QWindow *targetWindow,
|
||||
const QRect &nativeTargetGeometry)
|
||||
void QOpenGLCompositor::setTargetWindow(QWindow *targetWindow, const QRect &nativeTargetGeometry)
|
||||
{
|
||||
m_context = context;
|
||||
m_targetWindow = targetWindow;
|
||||
m_nativeTargetGeometry = nativeTargetGeometry;
|
||||
}
|
||||
|
||||
void QOpenGLCompositor::setTargetContext(QOpenGLContext *context)
|
||||
{
|
||||
m_context = context;
|
||||
}
|
||||
|
||||
void QOpenGLCompositor::setRotation(int degrees)
|
||||
{
|
||||
m_rotation = degrees;
|
||||
|
@ -83,7 +83,8 @@ public:
|
||||
static QOpenGLCompositor *instance();
|
||||
static void destroy();
|
||||
|
||||
void setTarget(QOpenGLContext *context, QWindow *window, const QRect &nativeTargetGeometry);
|
||||
void setTargetWindow(QWindow *window, const QRect &nativeTargetGeometry);
|
||||
void setTargetContext(QOpenGLContext *context);
|
||||
void setRotation(int degrees);
|
||||
QOpenGLContext *context() const { return m_context; }
|
||||
QWindow *targetWindow() const { return m_targetWindow; }
|
||||
|
@ -40,7 +40,6 @@
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QPainter>
|
||||
#include <QtGui/QOffscreenSurface>
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
#include <private/qwindow_p.h>
|
||||
#include <private/qrhi_p.h>
|
||||
@ -90,31 +89,12 @@ QOpenGLCompositorBackingStore::QOpenGLCompositorBackingStore(QWindow *window)
|
||||
|
||||
QOpenGLCompositorBackingStore::~QOpenGLCompositorBackingStore()
|
||||
{
|
||||
if (m_bsTexture) {
|
||||
QOpenGLContext *ctx = QOpenGLContext::currentContext();
|
||||
// With render-to-texture-widgets QWidget makes sure the TLW's shareContext() is
|
||||
// made current before destroying backingstores. That is however not the case for
|
||||
// windows with regular widgets only.
|
||||
QScopedPointer<QOffscreenSurface> tempSurface;
|
||||
if (!ctx) {
|
||||
ctx = QOpenGLCompositor::instance()->context();
|
||||
if (ctx) {
|
||||
tempSurface.reset(new QOffscreenSurface);
|
||||
tempSurface->setFormat(ctx->format());
|
||||
tempSurface->create();
|
||||
ctx->makeCurrent(tempSurface.data());
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bsTextureContext && ctx && ctx->shareGroup() == m_bsTextureContext->shareGroup()) {
|
||||
delete m_bsTextureWrapper;
|
||||
glDeleteTextures(1, &m_bsTexture);
|
||||
} else {
|
||||
qWarning("QOpenGLCompositorBackingStore: Texture is not valid in the current context");
|
||||
}
|
||||
|
||||
if (tempSurface && ctx)
|
||||
ctx->doneCurrent();
|
||||
if (m_bsTexture && m_rhi) {
|
||||
delete m_bsTextureWrapper;
|
||||
// Contexts are sharing resources, won't matter which one is
|
||||
// current here, use the rhi's shortcut.
|
||||
m_rhi->makeThreadLocalNativeContextCurrent();
|
||||
glDeleteTextures(1, &m_bsTexture);
|
||||
}
|
||||
|
||||
delete m_textures; // this does not actually own any GL resources
|
||||
@ -137,8 +117,6 @@ void QOpenGLCompositorBackingStore::updateTexture()
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
m_bsTextureWrapper = m_rhi->newTexture(QRhiTexture::RGBA8, m_image.size());
|
||||
m_bsTextureWrapper->createFrom({m_bsTexture, 0});
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, m_bsTexture);
|
||||
}
|
||||
@ -185,6 +163,11 @@ void QOpenGLCompositorBackingStore::updateTexture()
|
||||
|
||||
m_dirty = QRegion();
|
||||
}
|
||||
|
||||
if (!m_bsTextureWrapper) {
|
||||
m_bsTextureWrapper = m_rhi->newTexture(QRhiTexture::RGBA8, m_image.size());
|
||||
m_bsTextureWrapper->createFrom({m_bsTexture, 0});
|
||||
}
|
||||
}
|
||||
|
||||
void QOpenGLCompositorBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
@ -194,15 +177,25 @@ void QOpenGLCompositorBackingStore::flush(QWindow *window, const QRegion ®ion
|
||||
Q_UNUSED(region);
|
||||
Q_UNUSED(offset);
|
||||
|
||||
m_rhi = rhi();
|
||||
if (!m_rhi) {
|
||||
setRhiConfig(QPlatformBackingStoreRhiConfig(QPlatformBackingStoreRhiConfig::OpenGL));
|
||||
m_rhi = rhi();
|
||||
}
|
||||
Q_ASSERT(m_rhi);
|
||||
|
||||
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
|
||||
QOpenGLContext *dstCtx = compositor->context();
|
||||
Q_ASSERT(dstCtx);
|
||||
if (!dstCtx)
|
||||
return;
|
||||
|
||||
QWindow *dstWin = compositor->targetWindow();
|
||||
if (!dstWin)
|
||||
return;
|
||||
|
||||
dstCtx->makeCurrent(dstWin);
|
||||
if (!dstCtx->makeCurrent(dstWin))
|
||||
return;
|
||||
|
||||
updateTexture();
|
||||
m_textures->clear();
|
||||
m_textures->appendTexture(nullptr, m_bsTextureWrapper, window->geometry());
|
||||
@ -223,16 +216,23 @@ QPlatformBackingStore::FlushResult QOpenGLCompositorBackingStore::rhiFlush(QWind
|
||||
Q_UNUSED(translucentBackground);
|
||||
|
||||
m_rhi = rhi();
|
||||
if (!m_rhi) {
|
||||
setRhiConfig(QPlatformBackingStoreRhiConfig(QPlatformBackingStoreRhiConfig::OpenGL));
|
||||
m_rhi = rhi();
|
||||
}
|
||||
Q_ASSERT(m_rhi);
|
||||
|
||||
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
|
||||
QOpenGLContext *dstCtx = compositor->context();
|
||||
Q_ASSERT(dstCtx); // setTarget() must have been called before, e.g. from QEGLFSWindow
|
||||
if (!dstCtx)
|
||||
return FlushFailed;
|
||||
|
||||
QWindow *dstWin = compositor->targetWindow();
|
||||
if (!dstWin)
|
||||
return FlushFailed;
|
||||
|
||||
dstCtx->makeCurrent(dstWin);
|
||||
if (!dstCtx->makeCurrent(dstWin))
|
||||
return FlushFailed;
|
||||
|
||||
QWindowPrivate::get(window)->lastComposeTime.start();
|
||||
|
||||
|
@ -274,7 +274,7 @@ void QOpenGLVertexArrayObjectPrivate::destroy()
|
||||
vao = 0;
|
||||
}
|
||||
|
||||
if (oldContext && oldContextSurface) {
|
||||
if (oldContext && oldContextSurface && oldContextSurface->surfaceHandle()) {
|
||||
if (!oldContext->makeCurrent(oldContextSurface))
|
||||
qWarning("QOpenGLVertexArrayObject::destroy() failed to restore current context");
|
||||
}
|
||||
|
@ -201,7 +201,8 @@ QPixmap QEglFSScreen::grabWindow(WId wid, int x, int y, int width, int height) c
|
||||
|
||||
QImage img;
|
||||
|
||||
if (static_cast<QEglFSWindow *>(windows.first()->sourceWindow()->handle())->isRaster()) {
|
||||
QEglFSWindow *primaryWin = static_cast<QEglFSWindow *>(windows.first()->sourceWindow()->handle());
|
||||
if (primaryWin->isRaster() || primaryWin->backingStore()) {
|
||||
// Request the compositor to render everything into an FBO and read it back. This
|
||||
// is of course slow, but it's safe and reliable. It will not include the mouse
|
||||
// cursor, which is a plus.
|
||||
|
@ -110,7 +110,7 @@ void QEglFSWindow::create()
|
||||
#ifndef QT_NO_OPENGL
|
||||
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
|
||||
if (screen->primarySurface() != EGL_NO_SURFACE) {
|
||||
if (Q_UNLIKELY(!isRaster() || !compositor->targetWindow())) {
|
||||
if (Q_UNLIKELY(isRaster() != (compositor->targetWindow() != nullptr))) {
|
||||
# ifndef Q_OS_ANDROID
|
||||
// We can have either a single OpenGL window or multiple raster windows.
|
||||
// Other combinations cannot work.
|
||||
@ -137,21 +137,30 @@ void QEglFSWindow::create()
|
||||
screen->setPrimarySurface(m_surface);
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
if (isRaster()) {
|
||||
compositor->setTargetWindow(window(), screen->rawGeometry());
|
||||
compositor->setRotation(qEnvironmentVariableIntValue("QT_QPA_EGLFS_ROTATION"));
|
||||
#endif
|
||||
}
|
||||
|
||||
void QEglFSWindow::setBackingStore(QOpenGLCompositorBackingStore *backingStore)
|
||||
{
|
||||
#ifndef QT_NO_OPENGL
|
||||
if (!m_rasterCompositingContext) {
|
||||
m_rasterCompositingContext = new QOpenGLContext;
|
||||
m_rasterCompositingContext->setShareContext(qt_gl_global_share_context());
|
||||
m_rasterCompositingContext->setFormat(m_format);
|
||||
m_rasterCompositingContext->setScreen(window()->screen());
|
||||
if (Q_UNLIKELY(!m_rasterCompositingContext->create()))
|
||||
qFatal("EGLFS: Failed to create compositing context");
|
||||
compositor->setTarget(m_rasterCompositingContext, window(), screen->rawGeometry());
|
||||
compositor->setRotation(qEnvironmentVariableIntValue("QT_QPA_EGLFS_ROTATION"));
|
||||
// If there is a "root" window into which raster and QOpenGLWidget content is
|
||||
// composited, all other contexts must share with its context.
|
||||
if (!qt_gl_global_share_context())
|
||||
qt_gl_set_global_share_context(m_rasterCompositingContext);
|
||||
}
|
||||
#endif // QT_NO_OPENGL
|
||||
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
|
||||
compositor->setTargetContext(m_rasterCompositingContext);
|
||||
#endif
|
||||
m_backingStore = backingStore;
|
||||
}
|
||||
|
||||
void QEglFSWindow::destroy()
|
||||
@ -352,7 +361,7 @@ WId QEglFSWindow::winId() const
|
||||
|
||||
void QEglFSWindow::setOpacity(qreal)
|
||||
{
|
||||
if (!isRaster())
|
||||
if (!isRaster() && !backingStore())
|
||||
qWarning("QEglFSWindow: Cannot set opacity for non-raster windows");
|
||||
|
||||
// Nothing to do here. The opacity is stored in the QWindow.
|
||||
|
@ -103,12 +103,11 @@ public:
|
||||
void invalidateSurface() override;
|
||||
virtual void resetSurface();
|
||||
|
||||
bool isRaster() const;
|
||||
|
||||
#ifndef QT_NO_OPENGL
|
||||
QOpenGLCompositorBackingStore *backingStore() { return m_backingStore; }
|
||||
void setBackingStore(QOpenGLCompositorBackingStore *backingStore) { m_backingStore = backingStore; }
|
||||
#endif
|
||||
bool isRaster() const;
|
||||
#ifndef QT_NO_OPENGL
|
||||
void setBackingStore(QOpenGLCompositorBackingStore *backingStore);
|
||||
QWindow *sourceWindow() const override;
|
||||
const QPlatformTextureList *textures() const override;
|
||||
void endCompositing() override;
|
||||
|
Loading…
Reference in New Issue
Block a user