Add generic OpenGL compositor and backingstore bits
By removing the EGL(FS) dependencies we get classes that can be used by any platform plugin that runs without a windowing system. Change-Id: If99b42de5a4da02bbef80863609b6d92c6734613 Reviewed-by: Jørgen Lind <jorgen.lind@theqtcompany.com>bb10
parent
e41713b21d
commit
37cce4cada
|
|
@ -16,16 +16,12 @@ contains(QT_CONFIG,egl) {
|
|||
$$PWD/qeglplatformcursor_p.h \
|
||||
$$PWD/qeglplatformwindow_p.h \
|
||||
$$PWD/qeglplatformscreen_p.h \
|
||||
$$PWD/qeglcompositor_p.h \
|
||||
$$PWD/qeglplatformbackingstore_p.h \
|
||||
$$PWD/qeglplatformintegration_p.h
|
||||
|
||||
SOURCES += \
|
||||
$$PWD/qeglplatformcursor.cpp \
|
||||
$$PWD/qeglplatformwindow.cpp \
|
||||
$$PWD/qeglplatformscreen.cpp \
|
||||
$$PWD/qeglcompositor.cpp \
|
||||
$$PWD/qeglplatformbackingstore.cpp \
|
||||
$$PWD/qeglplatformintegration.cpp
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@
|
|||
#include <QtPlatformSupport/private/qgenericunixservices_p.h>
|
||||
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
|
||||
#include <QtPlatformSupport/private/qfbvthandler_p.h>
|
||||
#include <QtPlatformSupport/private/qopenglcompositorbackingstore_p.h>
|
||||
|
||||
#if !defined(QT_NO_EVDEV) && (!defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK))
|
||||
#include <QtPlatformSupport/private/qevdevmousemanager_p.h>
|
||||
|
|
@ -59,7 +60,6 @@
|
|||
#include "qeglplatformintegration_p.h"
|
||||
#include "qeglplatformcontext_p.h"
|
||||
#include "qeglplatformwindow_p.h"
|
||||
#include "qeglplatformbackingstore_p.h"
|
||||
#include "qeglplatformscreen_p.h"
|
||||
#include "qeglplatformcursor_p.h"
|
||||
|
||||
|
|
@ -141,7 +141,9 @@ QPlatformFontDatabase *QEGLPlatformIntegration::fontDatabase() const
|
|||
|
||||
QPlatformBackingStore *QEGLPlatformIntegration::createPlatformBackingStore(QWindow *window) const
|
||||
{
|
||||
return new QEGLPlatformBackingStore(window);
|
||||
QOpenGLCompositorBackingStore *bs = new QOpenGLCompositorBackingStore(window);
|
||||
static_cast<QEGLPlatformWindow *>(window->handle())->setBackingStore(bs);
|
||||
return bs;
|
||||
}
|
||||
|
||||
QPlatformWindow *QEGLPlatformIntegration::createPlatformWindow(QWindow *window) const
|
||||
|
|
@ -156,10 +158,9 @@ QPlatformWindow *QEGLPlatformIntegration::createPlatformWindow(QWindow *window)
|
|||
|
||||
QPlatformOpenGLContext *QEGLPlatformIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
|
||||
{
|
||||
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(context->screen()->handle());
|
||||
// If there is a "root" window into which raster and QOpenGLWidget content is
|
||||
// composited, all other contexts must share with its context.
|
||||
QOpenGLContext *compositingContext = screen ? screen->compositingContext() : 0;
|
||||
QOpenGLContext *compositingContext = QOpenGLCompositor::instance()->context();
|
||||
QPlatformOpenGLContext *share = compositingContext ? compositingContext->handle() : context->shareHandle();
|
||||
QVariant nativeHandle = context->nativeHandle();
|
||||
QPlatformOpenGLContext *platformContext = createContext(context->format(),
|
||||
|
|
|
|||
|
|
@ -31,8 +31,8 @@
|
|||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglcompositor_p.h"
|
||||
#include "qeglplatformscreen_p.h"
|
||||
#include <QtPlatformSupport/private/qopenglcompositor_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
|
|
@ -42,19 +42,6 @@ QT_BEGIN_NAMESPACE
|
|||
\since 5.2
|
||||
\internal
|
||||
\ingroup qpa
|
||||
|
||||
This class provides a lightweight base for QPlatformScreen
|
||||
implementations. It covers basic window stack management which is
|
||||
necessary when compositing multiple raster (widget-based) windows
|
||||
together into one single native surface.
|
||||
|
||||
Reimplementing the virtuals are essential when using
|
||||
QEGLPlatformBackingStore. The context and the window returned from
|
||||
these are the ones that are used when compositing the textures
|
||||
generated from the raster (widget) based windows.
|
||||
|
||||
\note It is up to the QEGLPlatformWindow subclasses to use the
|
||||
functions, like addWindow(), removeWindow(), etc., provided here.
|
||||
*/
|
||||
|
||||
QEGLPlatformScreen::QEGLPlatformScreen(EGLDisplay dpy)
|
||||
|
|
@ -64,39 +51,7 @@ QEGLPlatformScreen::QEGLPlatformScreen(EGLDisplay dpy)
|
|||
|
||||
QEGLPlatformScreen::~QEGLPlatformScreen()
|
||||
{
|
||||
QEGLCompositor::destroy();
|
||||
}
|
||||
|
||||
void QEGLPlatformScreen::addWindow(QEGLPlatformWindow *window)
|
||||
{
|
||||
if (!m_windows.contains(window)) {
|
||||
m_windows.append(window);
|
||||
topWindowChanged(window);
|
||||
}
|
||||
}
|
||||
|
||||
void QEGLPlatformScreen::removeWindow(QEGLPlatformWindow *window)
|
||||
{
|
||||
m_windows.removeOne(window);
|
||||
if (!m_windows.isEmpty())
|
||||
topWindowChanged(m_windows.last());
|
||||
}
|
||||
|
||||
void QEGLPlatformScreen::moveToTop(QEGLPlatformWindow *window)
|
||||
{
|
||||
m_windows.removeOne(window);
|
||||
m_windows.append(window);
|
||||
topWindowChanged(window);
|
||||
}
|
||||
|
||||
void QEGLPlatformScreen::changeWindowIndex(QEGLPlatformWindow *window, int newIdx)
|
||||
{
|
||||
int idx = m_windows.indexOf(window);
|
||||
if (idx != -1 && idx != newIdx) {
|
||||
m_windows.move(idx, newIdx);
|
||||
if (newIdx == m_windows.size() - 1)
|
||||
topWindowChanged(m_windows.last());
|
||||
}
|
||||
QOpenGLCompositor::destroy();
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -60,22 +60,9 @@ public:
|
|||
QEGLPlatformScreen(EGLDisplay dpy);
|
||||
~QEGLPlatformScreen();
|
||||
|
||||
QList<QEGLPlatformWindow *> windows() const { return m_windows; }
|
||||
|
||||
void addWindow(QEGLPlatformWindow *window);
|
||||
void removeWindow(QEGLPlatformWindow *window);
|
||||
void moveToTop(QEGLPlatformWindow *window);
|
||||
void changeWindowIndex(QEGLPlatformWindow *window, int newIdx);
|
||||
|
||||
virtual void topWindowChanged(QEGLPlatformWindow *window) { Q_UNUSED(window); }
|
||||
|
||||
EGLDisplay display() const { return m_dpy; }
|
||||
|
||||
virtual QEGLPlatformWindow *compositingWindow() = 0;
|
||||
virtual QOpenGLContext *compositingContext() = 0;
|
||||
|
||||
private:
|
||||
QList<QEGLPlatformWindow *> m_windows;
|
||||
EGLDisplay m_dpy;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -32,9 +32,10 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <QtPlatformSupport/private/qopenglcompositor_p.h>
|
||||
#include <QtPlatformSupport/private/qopenglcompositorbackingstore_p.h>
|
||||
|
||||
#include "qeglplatformwindow_p.h"
|
||||
#include "qeglplatformbackingstore_p.h"
|
||||
#include "qeglplatformscreen_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
@ -47,7 +48,7 @@ QT_BEGIN_NAMESPACE
|
|||
\ingroup qpa
|
||||
|
||||
Lightweight class providing some basic platform window operations
|
||||
and interfacing with QEGLPlatformBackingStore.
|
||||
and interfacing with QOpenGLCompositorBackingStore.
|
||||
|
||||
Almost no QPlatformWindow functions are implemented here. This is
|
||||
intentional because different platform plugins may use different
|
||||
|
|
@ -57,13 +58,15 @@ QT_BEGIN_NAMESPACE
|
|||
enforce anything for these functions.
|
||||
|
||||
\note Subclasses are responsible for invoking this class'
|
||||
implementation of create(). When using QEGLPlatformScreen, the
|
||||
subclasses of this class are expected to utilize the window stack
|
||||
management functions (addWindow() etc.) provided there.
|
||||
implementation of create() and are expected to utilize the window
|
||||
stack management functions (addWindow() etc.) in
|
||||
QOpenGLCompositor.
|
||||
*/
|
||||
|
||||
QEGLPlatformWindow::QEGLPlatformWindow(QWindow *w)
|
||||
: QPlatformWindow(w),
|
||||
m_backingStore(0),
|
||||
m_raster(false),
|
||||
m_winId(0)
|
||||
{
|
||||
}
|
||||
|
|
@ -100,6 +103,11 @@ bool QEGLPlatformWindow::isRaster() const
|
|||
return m_raster || window()->surfaceType() == QSurface::RasterGLSurface;
|
||||
}
|
||||
|
||||
QWindow *QEGLPlatformWindow::sourceWindow() const
|
||||
{
|
||||
return window();
|
||||
}
|
||||
|
||||
const QPlatformTextureList *QEGLPlatformWindow::textures() const
|
||||
{
|
||||
if (m_backingStore)
|
||||
|
|
@ -108,10 +116,10 @@ const QPlatformTextureList *QEGLPlatformWindow::textures() const
|
|||
return 0;
|
||||
}
|
||||
|
||||
void QEGLPlatformWindow::composited()
|
||||
void QEGLPlatformWindow::endCompositing()
|
||||
{
|
||||
if (m_backingStore)
|
||||
m_backingStore->composited();
|
||||
m_backingStore->notifyComposited();
|
||||
}
|
||||
|
||||
WId QEGLPlatformWindow::winId() const
|
||||
|
|
|
|||
|
|
@ -46,33 +46,36 @@
|
|||
//
|
||||
|
||||
#include <qpa/qplatformwindow.h>
|
||||
#include <QtPlatformSupport/private/qopenglcompositor_p.h>
|
||||
#include <EGL/egl.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEGLPlatformBackingStore;
|
||||
class QOpenGLCompositorBackingStore;
|
||||
class QPlatformTextureList;
|
||||
|
||||
class QEGLPlatformWindow : public QPlatformWindow
|
||||
class QEGLPlatformWindow : public QPlatformWindow, public QOpenGLCompositorWindow
|
||||
{
|
||||
public:
|
||||
QEGLPlatformWindow(QWindow *w);
|
||||
|
||||
virtual void create();
|
||||
|
||||
QEGLPlatformBackingStore *backingStore() { return m_backingStore; }
|
||||
void setBackingStore(QEGLPlatformBackingStore *backingStore) { m_backingStore = backingStore; }
|
||||
const QPlatformTextureList *textures() const;
|
||||
void composited();
|
||||
QOpenGLCompositorBackingStore *backingStore() { return m_backingStore; }
|
||||
void setBackingStore(QOpenGLCompositorBackingStore *backingStore) { m_backingStore = backingStore; }
|
||||
bool isRaster() const;
|
||||
|
||||
QWindow *sourceWindow() const Q_DECL_OVERRIDE;
|
||||
const QPlatformTextureList *textures() const Q_DECL_OVERRIDE;
|
||||
void endCompositing() Q_DECL_OVERRIDE;
|
||||
|
||||
WId winId() const Q_DECL_OVERRIDE;
|
||||
void setOpacity(qreal opacity) Q_DECL_OVERRIDE;
|
||||
|
||||
virtual EGLNativeWindowType eglWindow() const = 0;
|
||||
|
||||
private:
|
||||
QEGLPlatformBackingStore *m_backingStore;
|
||||
QOpenGLCompositorBackingStore *m_backingStore;
|
||||
bool m_raster;
|
||||
WId m_winId;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
contains(QT_CONFIG, opengl) {
|
||||
SOURCES += $$PWD/qopenglcompositor.cpp \
|
||||
$$PWD/qopenglcompositorbackingstore.cpp
|
||||
|
||||
HEADERS += $$PWD/qopenglcompositor_p.h \
|
||||
$$PWD/qopenglcompositorbackingstore_p.h
|
||||
}
|
||||
|
|
@ -32,23 +32,46 @@
|
|||
****************************************************************************/
|
||||
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QOpenGLShaderProgram>
|
||||
#include <QtGui/QOpenGLFramebufferObject>
|
||||
#include <QtGui/private/qopengltextureblitter_p.h>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QMatrix4x4>
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
|
||||
#include "qeglcompositor_p.h"
|
||||
#include "qeglplatformwindow_p.h"
|
||||
#include "qeglplatformscreen_p.h"
|
||||
#include "qopenglcompositor_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static QEGLCompositor *compositor = 0;
|
||||
/*!
|
||||
\class QOpenGLCompositor
|
||||
\brief A generic OpenGL-based compositor
|
||||
\since 5.4
|
||||
\internal
|
||||
\ingroup qpa
|
||||
|
||||
QEGLCompositor::QEGLCompositor()
|
||||
This class provides a lightweight compositor that maintains the
|
||||
basic stacking order of windows and composites them by drawing
|
||||
textured quads via OpenGL.
|
||||
|
||||
It it meant to be used by platform plugins that run without a
|
||||
windowing system.
|
||||
|
||||
It is up to the platform plugin to manage the lifetime of the
|
||||
compositor (instance(), destroy()), set the correct destination
|
||||
context and window as early as possible (setTargetWindow()),
|
||||
register the composited windows as they are shown, activated,
|
||||
raised and lowered (addWindow(), moveToTop(), etc.), and to
|
||||
schedule repaints (update()).
|
||||
|
||||
\note To get support for QWidget-based windows, just use
|
||||
QOpenGLCompositorBackingStore. It will automatically create
|
||||
textures from the raster-rendered content and trigger the
|
||||
necessary repaints.
|
||||
*/
|
||||
|
||||
static QOpenGLCompositor *compositor = 0;
|
||||
|
||||
QOpenGLCompositor::QOpenGLCompositor()
|
||||
: m_context(0),
|
||||
m_window(0),
|
||||
m_blitter(0)
|
||||
m_targetWindow(0)
|
||||
{
|
||||
Q_ASSERT(!compositor);
|
||||
m_updateTimer.setSingleShot(true);
|
||||
|
|
@ -56,45 +79,51 @@ QEGLCompositor::QEGLCompositor()
|
|||
connect(&m_updateTimer, SIGNAL(timeout()), SLOT(renderAll()));
|
||||
}
|
||||
|
||||
QEGLCompositor::~QEGLCompositor()
|
||||
QOpenGLCompositor::~QOpenGLCompositor()
|
||||
{
|
||||
Q_ASSERT(compositor == this);
|
||||
if (m_blitter) {
|
||||
m_blitter->destroy();
|
||||
delete m_blitter;
|
||||
}
|
||||
m_blitter.destroy();
|
||||
compositor = 0;
|
||||
}
|
||||
|
||||
void QEGLCompositor::schedule(QOpenGLContext *context, QEGLPlatformWindow *window)
|
||||
void QOpenGLCompositor::setTarget(QOpenGLContext *context, QWindow *targetWindow)
|
||||
{
|
||||
m_context = context;
|
||||
m_window = window;
|
||||
m_targetWindow = targetWindow;
|
||||
}
|
||||
|
||||
void QOpenGLCompositor::update()
|
||||
{
|
||||
if (!m_updateTimer.isActive())
|
||||
m_updateTimer.start();
|
||||
}
|
||||
|
||||
void QEGLCompositor::renderAll()
|
||||
void QOpenGLCompositor::renderAll()
|
||||
{
|
||||
Q_ASSERT(m_context && m_window);
|
||||
m_context->makeCurrent(m_window->window());
|
||||
Q_ASSERT(m_context && m_targetWindow);
|
||||
m_context->makeCurrent(m_targetWindow);
|
||||
|
||||
if (!m_blitter) {
|
||||
m_blitter = new QOpenGLTextureBlitter;
|
||||
m_blitter->create();
|
||||
}
|
||||
m_blitter->bind();
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
|
||||
QList<QEGLPlatformWindow *> windows = screen->windows();
|
||||
for (int i = 0; i < windows.size(); ++i)
|
||||
render(windows.at(i));
|
||||
const QRect targetWindowRect(QPoint(0, 0), m_targetWindow->geometry().size());
|
||||
glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height());
|
||||
|
||||
m_blitter->release();
|
||||
m_context->swapBuffers(m_window->window());
|
||||
if (!m_blitter.isCreated())
|
||||
m_blitter.create();
|
||||
|
||||
for (int i = 0; i < windows.size(); ++i)
|
||||
windows.at(i)->composited();
|
||||
m_blitter.bind();
|
||||
|
||||
for (int i = 0; i < m_windows.size(); ++i)
|
||||
m_windows.at(i)->beginCompositing();
|
||||
|
||||
for (int i = 0; i < m_windows.size(); ++i)
|
||||
render(m_windows.at(i));
|
||||
|
||||
m_blitter.release();
|
||||
m_context->swapBuffers(m_targetWindow);
|
||||
|
||||
for (int i = 0; i < m_windows.size(); ++i)
|
||||
m_windows.at(i)->endCompositing();
|
||||
}
|
||||
|
||||
struct BlendStateBinder
|
||||
|
|
@ -120,41 +149,38 @@ struct BlendStateBinder
|
|||
bool m_blend;
|
||||
};
|
||||
|
||||
void QEGLCompositor::render(QEGLPlatformWindow *window)
|
||||
void QOpenGLCompositor::render(QOpenGLCompositorWindow *window)
|
||||
{
|
||||
const QPlatformTextureList *textures = window->textures();
|
||||
if (!textures)
|
||||
return;
|
||||
|
||||
const QRect targetWindowRect(QPoint(0, 0), window->screen()->geometry().size());
|
||||
glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height());
|
||||
|
||||
const QRect targetWindowRect(QPoint(0, 0), m_targetWindow->geometry().size());
|
||||
float currentOpacity = 1.0f;
|
||||
BlendStateBinder blend;
|
||||
|
||||
for (int i = 0; i < textures->count(); ++i) {
|
||||
uint textureId = textures->textureId(i);
|
||||
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i),
|
||||
targetWindowRect);
|
||||
const float opacity = window->window()->opacity();
|
||||
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
|
||||
const float opacity = window->sourceWindow()->opacity();
|
||||
if (opacity != currentOpacity) {
|
||||
currentOpacity = opacity;
|
||||
m_blitter->setOpacity(currentOpacity);
|
||||
m_blitter.setOpacity(currentOpacity);
|
||||
}
|
||||
|
||||
if (textures->count() > 1 && i == textures->count() - 1) {
|
||||
// Backingstore for a widget with QOpenGLWidget subwidgets
|
||||
blend.set(true);
|
||||
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
|
||||
m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
|
||||
} else if (textures->count() == 1) {
|
||||
// A regular QWidget window
|
||||
const bool translucent = window->window()->requestedFormat().alphaBufferSize() > 0;
|
||||
const bool translucent = window->sourceWindow()->requestedFormat().alphaBufferSize() > 0;
|
||||
blend.set(translucent);
|
||||
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
|
||||
m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
|
||||
} else if (!textures->stacksOnTop(i)) {
|
||||
// Texture from an FBO belonging to a QOpenGLWidget
|
||||
blend.set(false);
|
||||
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft);
|
||||
m_blitter.blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -162,24 +188,56 @@ void QEGLCompositor::render(QEGLPlatformWindow *window)
|
|||
if (textures->stacksOnTop(i)) {
|
||||
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i), targetWindowRect);
|
||||
blend.set(true);
|
||||
m_blitter->blit(textures->textureId(i), target, QOpenGLTextureBlitter::OriginBottomLeft);
|
||||
m_blitter.blit(textures->textureId(i), target, QOpenGLTextureBlitter::OriginBottomLeft);
|
||||
}
|
||||
}
|
||||
|
||||
m_blitter->setOpacity(1.0f);
|
||||
m_blitter.setOpacity(1.0f);
|
||||
}
|
||||
|
||||
QEGLCompositor *QEGLCompositor::instance()
|
||||
QOpenGLCompositor *QOpenGLCompositor::instance()
|
||||
{
|
||||
if (!compositor)
|
||||
compositor = new QEGLCompositor;
|
||||
compositor = new QOpenGLCompositor;
|
||||
return compositor;
|
||||
}
|
||||
|
||||
void QEGLCompositor::destroy()
|
||||
void QOpenGLCompositor::destroy()
|
||||
{
|
||||
delete compositor;
|
||||
compositor = 0;
|
||||
}
|
||||
|
||||
void QOpenGLCompositor::addWindow(QOpenGLCompositorWindow *window)
|
||||
{
|
||||
if (!m_windows.contains(window)) {
|
||||
m_windows.append(window);
|
||||
emit topWindowChanged(window);
|
||||
}
|
||||
}
|
||||
|
||||
void QOpenGLCompositor::removeWindow(QOpenGLCompositorWindow *window)
|
||||
{
|
||||
m_windows.removeOne(window);
|
||||
if (!m_windows.isEmpty())
|
||||
emit topWindowChanged(m_windows.last());
|
||||
}
|
||||
|
||||
void QOpenGLCompositor::moveToTop(QOpenGLCompositorWindow *window)
|
||||
{
|
||||
m_windows.removeOne(window);
|
||||
m_windows.append(window);
|
||||
emit topWindowChanged(window);
|
||||
}
|
||||
|
||||
void QOpenGLCompositor::changeWindowIndex(QOpenGLCompositorWindow *window, int newIdx)
|
||||
{
|
||||
int idx = m_windows.indexOf(window);
|
||||
if (idx != -1 && idx != newIdx) {
|
||||
m_windows.move(idx, newIdx);
|
||||
if (newIdx == m_windows.size() - 1)
|
||||
emit topWindowChanged(m_windows.last());
|
||||
}
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
@ -31,8 +31,8 @@
|
|||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QEGLCOMPOSITOR_H
|
||||
#define QEGLCOMPOSITOR_H
|
||||
#ifndef QOPENGLCOMPOSITOR_H
|
||||
#define QOPENGLCOMPOSITOR_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
|
|
@ -46,38 +46,62 @@
|
|||
//
|
||||
|
||||
#include <QtCore/QTimer>
|
||||
#include <QtGui/private/qopengltextureblitter_p.h>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QOpenGLContext;
|
||||
class QOpenGLTextureBlitter;
|
||||
class QEGLPlatformWindow;
|
||||
class QWindow;
|
||||
class QPlatformTextureList;
|
||||
|
||||
class QEGLCompositor : public QObject
|
||||
class QOpenGLCompositorWindow
|
||||
{
|
||||
public:
|
||||
virtual QWindow *sourceWindow() const = 0;
|
||||
virtual const QPlatformTextureList *textures() const = 0;
|
||||
virtual void beginCompositing() { }
|
||||
virtual void endCompositing() { }
|
||||
};
|
||||
|
||||
class QOpenGLCompositor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
void schedule(QOpenGLContext *context, QEGLPlatformWindow *window);
|
||||
|
||||
static QEGLCompositor *instance();
|
||||
static QOpenGLCompositor *instance();
|
||||
static void destroy();
|
||||
|
||||
void setTarget(QOpenGLContext *context, QWindow *window);
|
||||
QOpenGLContext *context() const { return m_context; }
|
||||
QWindow *targetWindow() const { return m_targetWindow; }
|
||||
|
||||
void update();
|
||||
|
||||
QList<QOpenGLCompositorWindow *> windows() const { return m_windows; }
|
||||
void addWindow(QOpenGLCompositorWindow *window);
|
||||
void removeWindow(QOpenGLCompositorWindow *window);
|
||||
void moveToTop(QOpenGLCompositorWindow *window);
|
||||
void changeWindowIndex(QOpenGLCompositorWindow *window, int newIdx);
|
||||
|
||||
signals:
|
||||
void topWindowChanged(QOpenGLCompositorWindow *window);
|
||||
|
||||
private slots:
|
||||
void renderAll();
|
||||
|
||||
private:
|
||||
QEGLCompositor();
|
||||
~QEGLCompositor();
|
||||
QOpenGLCompositor();
|
||||
~QOpenGLCompositor();
|
||||
|
||||
void render(QEGLPlatformWindow *window);
|
||||
void render(QOpenGLCompositorWindow *window);
|
||||
|
||||
QOpenGLContext *m_context;
|
||||
QEGLPlatformWindow *m_window;
|
||||
QWindow *m_targetWindow;
|
||||
QTimer m_updateTimer;
|
||||
QOpenGLTextureBlitter *m_blitter;
|
||||
QOpenGLTextureBlitter m_blitter;
|
||||
QList<QOpenGLCompositorWindow *> m_windows;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QEGLCOMPOSITOR_H
|
||||
#endif // QOPENGLCOMPOSITOR_H
|
||||
|
|
@ -31,62 +31,58 @@
|
|||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include <QtGui/QOpenGLShaderProgram>
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QWindow>
|
||||
#include <QtGui/QPainter>
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
|
||||
#include "qeglplatformbackingstore_p.h"
|
||||
#include "qeglcompositor_p.h"
|
||||
#include "qeglplatformwindow_p.h"
|
||||
#include "qeglplatformscreen_p.h"
|
||||
#include "qopenglcompositorbackingstore_p.h"
|
||||
#include "qopenglcompositor_p.h"
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
/*!
|
||||
\class QEGLPlatformBackingStore
|
||||
\brief A backing store implementation for EGL and GLES.
|
||||
\since 5.2
|
||||
\class QOpenGLCompositorBackingStore
|
||||
\brief A backing store implementation for OpenGL
|
||||
\since 5.4
|
||||
\internal
|
||||
\ingroup qpa
|
||||
|
||||
This implementation uploads raster-rendered widget windows into
|
||||
textures and composites them onto a single native window using
|
||||
QEGLCompositor. This means that multiple top-level widgets are
|
||||
supported without creating actual native windows for each of them.
|
||||
textures. It is meant to be used with QOpenGLCompositor that
|
||||
composites the textures onto a single native window using OpenGL.
|
||||
This means that multiple top-level widgets are supported without
|
||||
creating actual native windows for each of them.
|
||||
|
||||
The class is ready to be used as-is, the default
|
||||
QEGLPlatformIntegration::createPlatformBackingStore()
|
||||
implementation creates an instance which is ready to be used
|
||||
without further customization.
|
||||
\note It is important to call notifyComposited() from the
|
||||
corresponding platform window's endCompositing() callback
|
||||
(inherited from QOpenGLCompositorWindow).
|
||||
|
||||
If QEGLCompositor is not suitable, this backing store
|
||||
implementation can also be used without it. In this case a
|
||||
subclass must reimplement composite() and schedule an update in
|
||||
its custom compositor when this function is called. The textures
|
||||
are accessible via QEGLPlatformWindow::texture().
|
||||
\note When implementing QOpenGLCompositorWindow::textures() for
|
||||
windows of type RasterSurface or RasterGLSurface, simply return
|
||||
the list provided by this class' textures().
|
||||
*/
|
||||
|
||||
QEGLPlatformBackingStore::QEGLPlatformBackingStore(QWindow *window)
|
||||
QOpenGLCompositorBackingStore::QOpenGLCompositorBackingStore(QWindow *window)
|
||||
: QPlatformBackingStore(window),
|
||||
m_window(static_cast<QEGLPlatformWindow *>(window->handle())),
|
||||
m_window(window),
|
||||
m_bsTexture(0),
|
||||
m_textures(new QPlatformTextureList),
|
||||
m_lockedWidgetTextures(0)
|
||||
{
|
||||
m_window->setBackingStore(this);
|
||||
}
|
||||
|
||||
QEGLPlatformBackingStore::~QEGLPlatformBackingStore()
|
||||
QOpenGLCompositorBackingStore::~QOpenGLCompositorBackingStore()
|
||||
{
|
||||
delete m_textures;
|
||||
}
|
||||
|
||||
QPaintDevice *QEGLPlatformBackingStore::paintDevice()
|
||||
QPaintDevice *QOpenGLCompositorBackingStore::paintDevice()
|
||||
{
|
||||
return &m_image;
|
||||
}
|
||||
|
||||
void QEGLPlatformBackingStore::updateTexture()
|
||||
void QOpenGLCompositorBackingStore::updateTexture()
|
||||
{
|
||||
if (!m_bsTexture) {
|
||||
glGenTextures(1, &m_bsTexture);
|
||||
|
|
@ -134,7 +130,7 @@ void QEGLPlatformBackingStore::updateTexture()
|
|||
}
|
||||
}
|
||||
|
||||
void QEGLPlatformBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
void QOpenGLCompositorBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||
{
|
||||
// Called for ordinary raster windows. This is rare since RasterGLSurface
|
||||
// support is claimed which leads to having all QWidget windows marked as
|
||||
|
|
@ -144,35 +140,38 @@ void QEGLPlatformBackingStore::flush(QWindow *window, const QRegion ®ion, con
|
|||
Q_UNUSED(region);
|
||||
Q_UNUSED(offset);
|
||||
|
||||
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
|
||||
QEGLPlatformWindow *dstWin = screen->compositingWindow();
|
||||
if (!dstWin || !dstWin->isRaster())
|
||||
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
|
||||
QOpenGLContext *dstCtx = compositor->context();
|
||||
QWindow *dstWin = compositor->targetWindow();
|
||||
if (!dstWin)
|
||||
return;
|
||||
|
||||
screen->compositingContext()->makeCurrent(dstWin->window());
|
||||
dstCtx->makeCurrent(dstWin);
|
||||
updateTexture();
|
||||
m_textures->clear();
|
||||
m_textures->appendTexture(m_bsTexture, window->geometry());
|
||||
composite(screen->compositingContext(), dstWin);
|
||||
|
||||
compositor->update();
|
||||
}
|
||||
|
||||
void QEGLPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset,
|
||||
void QOpenGLCompositorBackingStore::composeAndFlush(QWindow *window, const QRegion ®ion, const QPoint &offset,
|
||||
QPlatformTextureList *textures, QOpenGLContext *context,
|
||||
bool translucentBackground)
|
||||
{
|
||||
// QOpenGLWidget content provided as textures. The raster content should go on top.
|
||||
// QOpenGLWidget/QQuickWidget content provided as textures. The raster content should go on top.
|
||||
|
||||
Q_UNUSED(region);
|
||||
Q_UNUSED(offset);
|
||||
Q_UNUSED(context);
|
||||
Q_UNUSED(translucentBackground);
|
||||
|
||||
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
|
||||
QEGLPlatformWindow *dstWin = screen->compositingWindow();
|
||||
if (!dstWin || !dstWin->isRaster())
|
||||
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
|
||||
QOpenGLContext *dstCtx = compositor->context();
|
||||
QWindow *dstWin = compositor->targetWindow();
|
||||
if (!dstWin)
|
||||
return;
|
||||
|
||||
screen->compositingContext()->makeCurrent(dstWin->window());
|
||||
dstCtx->makeCurrent(dstWin);
|
||||
|
||||
m_textures->clear();
|
||||
for (int i = 0; i < textures->count(); ++i)
|
||||
|
|
@ -184,15 +183,10 @@ void QEGLPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &r
|
|||
textures->lock(true);
|
||||
m_lockedWidgetTextures = textures;
|
||||
|
||||
composite(screen->compositingContext(), dstWin);
|
||||
compositor->update();
|
||||
}
|
||||
|
||||
void QEGLPlatformBackingStore::composite(QOpenGLContext *context, QEGLPlatformWindow *window)
|
||||
{
|
||||
QEGLCompositor::instance()->schedule(context, window);
|
||||
}
|
||||
|
||||
void QEGLPlatformBackingStore::composited()
|
||||
void QOpenGLCompositorBackingStore::notifyComposited()
|
||||
{
|
||||
if (m_lockedWidgetTextures) {
|
||||
QPlatformTextureList *textureList = m_lockedWidgetTextures;
|
||||
|
|
@ -201,7 +195,7 @@ void QEGLPlatformBackingStore::composited()
|
|||
}
|
||||
}
|
||||
|
||||
void QEGLPlatformBackingStore::beginPaint(const QRegion ®ion)
|
||||
void QOpenGLCompositorBackingStore::beginPaint(const QRegion ®ion)
|
||||
{
|
||||
m_dirty |= region;
|
||||
|
||||
|
|
@ -213,27 +207,28 @@ void QEGLPlatformBackingStore::beginPaint(const QRegion ®ion)
|
|||
}
|
||||
}
|
||||
|
||||
void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticContents)
|
||||
void QOpenGLCompositorBackingStore::resize(const QSize &size, const QRegion &staticContents)
|
||||
{
|
||||
Q_UNUSED(staticContents);
|
||||
|
||||
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
|
||||
QEGLPlatformWindow *dstWin = screen->compositingWindow();
|
||||
if (!dstWin || (!dstWin->isRaster() && dstWin->window()->surfaceType() != QSurface::RasterGLSurface))
|
||||
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
|
||||
QOpenGLContext *dstCtx = compositor->context();
|
||||
QWindow *dstWin = compositor->targetWindow();
|
||||
if (!dstWin)
|
||||
return;
|
||||
|
||||
m_image = QImage(size, QImage::Format_RGBA8888);
|
||||
|
||||
m_window->create();
|
||||
|
||||
screen->compositingContext()->makeCurrent(dstWin->window());
|
||||
dstCtx->makeCurrent(dstWin);
|
||||
if (m_bsTexture) {
|
||||
glDeleteTextures(1, &m_bsTexture);
|
||||
m_bsTexture = 0;
|
||||
}
|
||||
}
|
||||
|
||||
QImage QEGLPlatformBackingStore::toImage() const
|
||||
QImage QOpenGLCompositorBackingStore::toImage() const
|
||||
{
|
||||
return m_image;
|
||||
}
|
||||
|
|
@ -31,8 +31,8 @@
|
|||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QEGLPLATFORMBACKINGSTORE_H
|
||||
#define QEGLPLATFORMBACKINGSTORE_H
|
||||
#ifndef QOPENGLCOMPOSITORBACKINGSTORE_H
|
||||
#define QOPENGLCOMPOSITORBACKINGSTORE_H
|
||||
|
||||
//
|
||||
// W A R N I N G
|
||||
|
|
@ -46,7 +46,6 @@
|
|||
//
|
||||
|
||||
#include <qpa/qplatformbackingstore.h>
|
||||
|
||||
#include <QImage>
|
||||
#include <QRegion>
|
||||
|
||||
|
|
@ -54,13 +53,12 @@ QT_BEGIN_NAMESPACE
|
|||
|
||||
class QOpenGLContext;
|
||||
class QPlatformTextureList;
|
||||
class QEGLPlatformWindow;
|
||||
|
||||
class QEGLPlatformBackingStore : public QPlatformBackingStore
|
||||
class QOpenGLCompositorBackingStore : public QPlatformBackingStore
|
||||
{
|
||||
public:
|
||||
QEGLPlatformBackingStore(QWindow *window);
|
||||
~QEGLPlatformBackingStore();
|
||||
QOpenGLCompositorBackingStore(QWindow *window);
|
||||
~QOpenGLCompositorBackingStore();
|
||||
|
||||
QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
|
||||
|
||||
|
|
@ -76,14 +74,12 @@ public:
|
|||
|
||||
const QPlatformTextureList *textures() const { return m_textures; }
|
||||
|
||||
virtual void composite(QOpenGLContext *context, QEGLPlatformWindow *window);
|
||||
|
||||
void composited();
|
||||
void notifyComposited();
|
||||
|
||||
private:
|
||||
void updateTexture();
|
||||
|
||||
QEGLPlatformWindow *m_window;
|
||||
QWindow *m_window;
|
||||
QImage m_image;
|
||||
QRegion m_dirty;
|
||||
uint m_bsTexture;
|
||||
|
|
@ -93,4 +89,4 @@ private:
|
|||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QEGLPLATFORMBACKINGSTORE_H
|
||||
#endif // QOPENGLCOMPOSITORBACKINGSTORE_H
|
||||
|
|
@ -21,5 +21,6 @@ include(themes/themes.pri)
|
|||
include(accessibility/accessibility.pri)
|
||||
include(linuxaccessibility/linuxaccessibility.pri)
|
||||
include(clipboard/clipboard.pri)
|
||||
include(platformcompositor/platformcompositor.pri)
|
||||
|
||||
load(qt_module)
|
||||
|
|
|
|||
|
|
@ -41,9 +41,7 @@ QT_BEGIN_NAMESPACE
|
|||
QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
|
||||
: QEGLPlatformScreen(dpy),
|
||||
m_surface(EGL_NO_SURFACE),
|
||||
m_cursor(0),
|
||||
m_rootWindow(0),
|
||||
m_rootContext(0)
|
||||
m_cursor(0)
|
||||
{
|
||||
m_cursor = QEglFSHooks::hooks()->createCursor(this);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,12 +64,6 @@ public:
|
|||
|
||||
EGLSurface primarySurface() const { return m_surface; }
|
||||
|
||||
QEGLPlatformWindow *compositingWindow() Q_DECL_OVERRIDE { return m_rootWindow; }
|
||||
QOpenGLContext *compositingContext() Q_DECL_OVERRIDE { return m_rootContext; }
|
||||
|
||||
void setRootWindow(QEGLPlatformWindow *window) { m_rootWindow = window; }
|
||||
void setRootContext(QOpenGLContext *context) { m_rootContext = context; }
|
||||
|
||||
protected:
|
||||
void setPrimarySurface(EGLSurface surface);
|
||||
|
||||
|
|
@ -78,8 +72,6 @@ private:
|
|||
|
||||
EGLSurface m_surface;
|
||||
QPlatformCursor *m_cursor;
|
||||
QEGLPlatformWindow *m_rootWindow;
|
||||
QOpenGLContext *m_rootContext;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
|
|
|||
|
|
@ -39,7 +39,6 @@
|
|||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtPlatformSupport/private/qeglplatformcursor_p.h>
|
||||
#include <QtPlatformSupport/private/qeglconvenience_p.h>
|
||||
|
||||
#include <QtDebug>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
|
@ -73,9 +72,10 @@ void QEglFSWindow::create()
|
|||
// raster windows will not have their own native window, surface and context. Instead,
|
||||
// they will be composited onto the root window's surface.
|
||||
QEglFSScreen *screen = this->screen();
|
||||
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
|
||||
if (screen->primarySurface() != EGL_NO_SURFACE) {
|
||||
if (isRaster() && screen->compositingWindow()) {
|
||||
m_format = screen->compositingWindow()->format();
|
||||
if (isRaster() && compositor->targetWindow()) {
|
||||
m_format = compositor->targetWindow()->format();
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -107,8 +107,7 @@ void QEglFSWindow::create()
|
|||
context->setScreen(window()->screen());
|
||||
if (!context->create())
|
||||
qFatal("EGLFS: Failed to create compositing context");
|
||||
screen->setRootContext(context);
|
||||
screen->setRootWindow(this);
|
||||
compositor->setTarget(context, window());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -127,7 +126,7 @@ void QEglFSWindow::destroy()
|
|||
}
|
||||
|
||||
m_flags = 0;
|
||||
screen->removeWindow(this);
|
||||
QOpenGLCompositor::instance()->removeWindow(this);
|
||||
}
|
||||
|
||||
// The virtual functions resetSurface and invalidateSurface may get overridden
|
||||
|
|
@ -160,17 +159,18 @@ void QEglFSWindow::resetSurface()
|
|||
|
||||
void QEglFSWindow::setVisible(bool visible)
|
||||
{
|
||||
QList<QEGLPlatformWindow *> windows = screen()->windows();
|
||||
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
|
||||
QList<QOpenGLCompositorWindow *> windows = compositor->windows();
|
||||
QWindow *wnd = window();
|
||||
|
||||
if (wnd->type() != Qt::Desktop) {
|
||||
if (visible) {
|
||||
screen()->addWindow(this);
|
||||
compositor->addWindow(this);
|
||||
} else {
|
||||
screen()->removeWindow(this);
|
||||
windows = screen()->windows();
|
||||
compositor->removeWindow(this);
|
||||
windows = compositor->windows();
|
||||
if (windows.size())
|
||||
windows.last()->requestActivateWindow();
|
||||
windows.last()->sourceWindow()->requestActivate();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -210,7 +210,7 @@ QRect QEglFSWindow::geometry() const
|
|||
void QEglFSWindow::requestActivateWindow()
|
||||
{
|
||||
if (window()->type() != Qt::Desktop)
|
||||
screen()->moveToTop(this);
|
||||
QOpenGLCompositor::instance()->moveToTop(this);
|
||||
|
||||
QWindow *wnd = window();
|
||||
QWindowSystemInterface::handleWindowActivated(wnd);
|
||||
|
|
@ -221,20 +221,21 @@ void QEglFSWindow::raise()
|
|||
{
|
||||
QWindow *wnd = window();
|
||||
if (wnd->type() != Qt::Desktop) {
|
||||
screen()->moveToTop(this);
|
||||
QOpenGLCompositor::instance()->moveToTop(this);
|
||||
QWindowSystemInterface::handleExposeEvent(wnd, QRect(QPoint(0, 0), wnd->geometry().size()));
|
||||
}
|
||||
}
|
||||
|
||||
void QEglFSWindow::lower()
|
||||
{
|
||||
QList<QEGLPlatformWindow *> windows = screen()->windows();
|
||||
QOpenGLCompositor *compositor = QOpenGLCompositor::instance();
|
||||
QList<QOpenGLCompositorWindow *> windows = compositor->windows();
|
||||
if (window()->type() != Qt::Desktop && windows.count() > 1) {
|
||||
int idx = windows.indexOf(this);
|
||||
if (idx > 0) {
|
||||
screen()->changeWindowIndex(this, idx - 1);
|
||||
QWindowSystemInterface::handleExposeEvent(windows.last()->window(),
|
||||
QRect(QPoint(0, 0), windows.last()->geometry().size()));
|
||||
compositor->changeWindowIndex(this, idx - 1);
|
||||
QWindowSystemInterface::handleExposeEvent(windows.last()->sourceWindow(),
|
||||
QRect(QPoint(0, 0), windows.last()->sourceWindow()->geometry().size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue