eglfs: Separate compositor and improve raster window support
Separating the compositor into a separate source file improves the chances of possible future reuse and paves the way to supporting multiple GL windows. Tooltips are now working too. Implemented a few window functions like raise() and lower(). Fixed the qFatal for multiple GL windows to be raised in non-SDK based Android builds too. Change-Id: Id94d2fb2a4382766f3d130eebe1e6f397a535852 Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com>
This commit is contained in:
parent
8d2c6206fd
commit
80cd06fd9d
@ -16,7 +16,8 @@ SOURCES += $$PWD/qeglfsintegration.cpp \
|
||||
$$PWD/qeglfsscreen.cpp \
|
||||
$$PWD/qeglfshooks_stub.cpp \
|
||||
$$PWD/qeglfscursor.cpp \
|
||||
$$PWD/qeglfscontext.cpp
|
||||
$$PWD/qeglfscontext.cpp \
|
||||
$$PWD/qeglfscompositor.cpp
|
||||
|
||||
HEADERS += $$PWD/qeglfsintegration.h \
|
||||
$$PWD/qeglfswindow.h \
|
||||
@ -24,7 +25,8 @@ HEADERS += $$PWD/qeglfsintegration.h \
|
||||
$$PWD/qeglfsscreen.h \
|
||||
$$PWD/qeglfscursor.h \
|
||||
$$PWD/qeglfshooks.h \
|
||||
$$PWD/qeglfscontext.h
|
||||
$$PWD/qeglfscontext.h \
|
||||
$$PWD/qeglfscompositor.h
|
||||
|
||||
QMAKE_LFLAGS += $$QMAKE_LFLAGS_NOUNDEF
|
||||
|
||||
|
@ -40,120 +40,24 @@
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglfsbackingstore.h"
|
||||
#include "qeglfscompositor.h"
|
||||
#include "qeglfscursor.h"
|
||||
#include "qeglfswindow.h"
|
||||
#include "qeglfscontext.h"
|
||||
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QOpenGLPaintDevice>
|
||||
#include <QtGui/QOpenGLShaderProgram>
|
||||
|
||||
#include <QtGui/QScreen>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QEglFSCompositor::QEglFSCompositor()
|
||||
: m_rootWindow(0)
|
||||
{
|
||||
m_updateTimer.setSingleShot(true);
|
||||
m_updateTimer.setInterval(0);
|
||||
connect(&m_updateTimer, SIGNAL(timeout()), SLOT(renderAll()));
|
||||
}
|
||||
|
||||
void QEglFSCompositor::schedule(QEglFSWindow *rootWindow)
|
||||
{
|
||||
m_rootWindow = rootWindow;
|
||||
if (!m_updateTimer.isActive())
|
||||
m_updateTimer.start();
|
||||
}
|
||||
|
||||
void QEglFSCompositor::renderAll()
|
||||
{
|
||||
Q_ASSERT(m_rootWindow);
|
||||
QOpenGLContext *context = QEglFSBackingStore::makeRootCurrent(m_rootWindow);
|
||||
|
||||
QEglFSScreen *screen = m_rootWindow->screen();
|
||||
QList<QEglFSWindow *> windows = screen->windows();
|
||||
for (int i = 0; i < windows.size(); ++i) {
|
||||
if (windows.at(i)->backingStore())
|
||||
render(windows.at(i), m_rootWindow);
|
||||
}
|
||||
|
||||
context->swapBuffers(m_rootWindow->window());
|
||||
context->doneCurrent();
|
||||
}
|
||||
|
||||
void QEglFSCompositor::render(QEglFSWindow *window, QEglFSWindow *rootWindow)
|
||||
{
|
||||
QEglFSBackingStore *rootBackingStore = rootWindow->backingStore();
|
||||
rootBackingStore->m_program->bind();
|
||||
|
||||
const GLfloat textureCoordinates[] = {
|
||||
0, 0,
|
||||
1, 0,
|
||||
1, 1,
|
||||
0, 1
|
||||
};
|
||||
|
||||
QRectF sr = window->screen()->geometry();
|
||||
QRect r = window->window()->geometry();
|
||||
QPoint tl = r.topLeft();
|
||||
QPoint br = r.bottomRight();
|
||||
|
||||
GLfloat x1 = (tl.x() / sr.width()) * 2 - 1;
|
||||
GLfloat x2 = (br.x() / sr.width()) * 2 - 1;
|
||||
GLfloat y1 = ((sr.height() - tl.y()) / sr.height()) * 2 - 1;
|
||||
GLfloat y2 = ((sr.height() - br.y()) / sr.height()) * 2 - 1;
|
||||
|
||||
const GLfloat vertexCoordinates[] = {
|
||||
x1, y1,
|
||||
x2, y1,
|
||||
x2, y2,
|
||||
x1, y2
|
||||
};
|
||||
|
||||
glViewport(0, 0, sr.width(), sr.height());
|
||||
|
||||
glEnableVertexAttribArray(rootBackingStore->m_vertexCoordEntry);
|
||||
glEnableVertexAttribArray(rootBackingStore->m_textureCoordEntry);
|
||||
|
||||
glVertexAttribPointer(rootBackingStore->m_vertexCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
|
||||
glVertexAttribPointer(rootBackingStore->m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, window->backingStore()->m_texture);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
rootBackingStore->m_program->release();
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisableVertexAttribArray(rootBackingStore->m_vertexCoordEntry);
|
||||
glDisableVertexAttribArray(rootBackingStore->m_textureCoordEntry);
|
||||
}
|
||||
|
||||
static QEglFSCompositor *compositor = 0;
|
||||
|
||||
QEglFSCompositor *QEglFSCompositor::instance()
|
||||
{
|
||||
if (!compositor)
|
||||
compositor = new QEglFSCompositor;
|
||||
return compositor;
|
||||
}
|
||||
|
||||
QEglFSBackingStore::QEglFSBackingStore(QWindow *window)
|
||||
: QPlatformBackingStore(window)
|
||||
, m_window(static_cast<QEglFSWindow *>(window->handle()))
|
||||
, m_context(0)
|
||||
, m_texture(0)
|
||||
, m_program(0)
|
||||
: QPlatformBackingStore(window),
|
||||
m_window(static_cast<QEglFSWindow *>(window->handle())),
|
||||
m_texture(0)
|
||||
{
|
||||
m_window->setBackingStore(this);
|
||||
}
|
||||
|
||||
QEglFSBackingStore::~QEglFSBackingStore()
|
||||
{
|
||||
delete m_program;
|
||||
delete m_context;
|
||||
}
|
||||
|
||||
QPaintDevice *QEglFSBackingStore::paintDevice()
|
||||
{
|
||||
return &m_image;
|
||||
@ -186,7 +90,8 @@ void QEglFSBackingStore::updateTexture()
|
||||
// if the sub-rect is full-width we can pass the image data directly to
|
||||
// OpenGL instead of copying, since there's no gap between scanlines
|
||||
if (rect.width() == imageRect.width()) {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, m_image.constScanLine(rect.y()));
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
m_image.constScanLine(rect.y()));
|
||||
} else {
|
||||
glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE,
|
||||
m_image.copy(rect).constBits());
|
||||
@ -207,63 +112,14 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo
|
||||
qWarning("QEglBackingStore::flush %p", window);
|
||||
#endif
|
||||
|
||||
m_window->create();
|
||||
QEglFSWindow *rootWin = m_window->screen()->rootWindow();
|
||||
if (rootWin) {
|
||||
makeRootCurrent(rootWin);
|
||||
updateTexture();
|
||||
QEglFSCompositor::instance()->schedule(rootWin);
|
||||
}
|
||||
}
|
||||
if (!rootWin)
|
||||
return;
|
||||
|
||||
void QEglFSBackingStore::makeCurrent()
|
||||
{
|
||||
Q_ASSERT(m_window->hasNativeWindow());
|
||||
|
||||
QWindow *wnd = window();
|
||||
if (!m_context) {
|
||||
m_context = new QOpenGLContext;
|
||||
m_context->setFormat(wnd->requestedFormat());
|
||||
m_context->setScreen(wnd->screen());
|
||||
m_context->create();
|
||||
}
|
||||
|
||||
m_context->makeCurrent(wnd);
|
||||
}
|
||||
|
||||
QOpenGLContext *QEglFSBackingStore::makeRootCurrent(QEglFSWindow *rootWin)
|
||||
{
|
||||
Q_ASSERT(rootWin->hasNativeWindow() && rootWin->isRasterRoot());
|
||||
|
||||
QEglFSBackingStore *rootBackingStore = rootWin->backingStore();
|
||||
rootBackingStore->makeCurrent();
|
||||
if (!rootBackingStore->m_program) {
|
||||
static const char *textureVertexProgram =
|
||||
"attribute highp vec2 vertexCoordEntry;\n"
|
||||
"attribute highp vec2 textureCoordEntry;\n"
|
||||
"varying highp vec2 textureCoord;\n"
|
||||
"void main() {\n"
|
||||
" textureCoord = textureCoordEntry;\n"
|
||||
" gl_Position = vec4(vertexCoordEntry, 0.0, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
static const char *textureFragmentProgram =
|
||||
"uniform sampler2D texture;\n"
|
||||
"varying highp vec2 textureCoord;\n"
|
||||
"void main() {\n"
|
||||
" gl_FragColor = texture2D(texture, textureCoord).bgra;\n"
|
||||
"}\n";
|
||||
|
||||
rootBackingStore->m_program = new QOpenGLShaderProgram;
|
||||
|
||||
rootBackingStore->m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
|
||||
rootBackingStore->m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
|
||||
rootBackingStore->m_program->link();
|
||||
|
||||
rootBackingStore->m_vertexCoordEntry = rootBackingStore->m_program->attributeLocation("vertexCoordEntry");
|
||||
rootBackingStore->m_textureCoordEntry = rootBackingStore->m_program->attributeLocation("textureCoordEntry");
|
||||
}
|
||||
return rootBackingStore->m_context;
|
||||
m_window->create();
|
||||
rootWin->screen()->rootContext()->makeCurrent(rootWin->window());
|
||||
updateTexture();
|
||||
QEglFSCompositor::instance()->schedule(rootWin->screen());
|
||||
}
|
||||
|
||||
void QEglFSBackingStore::beginPaint(const QRegion &rgn)
|
||||
@ -275,9 +131,14 @@ void QEglFSBackingStore::resize(const QSize &size, const QRegion &staticContents
|
||||
{
|
||||
Q_UNUSED(staticContents);
|
||||
|
||||
QEglFSWindow *rootWin = m_window->screen()->rootWindow();
|
||||
if (!rootWin)
|
||||
return;
|
||||
|
||||
m_image = QImage(size, QImage::Format_RGB32);
|
||||
m_window->create();
|
||||
makeRootCurrent(m_window->screen()->rootWindow());
|
||||
|
||||
rootWin->screen()->rootContext()->makeCurrent(rootWin->window());
|
||||
|
||||
if (m_texture)
|
||||
glDeleteTextures(1, &m_texture);
|
||||
|
@ -46,41 +46,16 @@
|
||||
|
||||
#include <QImage>
|
||||
#include <QRegion>
|
||||
#include <QTimer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QOpenGLContext;
|
||||
class QOpenGLPaintDevice;
|
||||
class QOpenGLShaderProgram;
|
||||
class QEglFSWindow;
|
||||
|
||||
class QEglFSCompositor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QEglFSCompositor();
|
||||
|
||||
void schedule(QEglFSWindow *rootWindow);
|
||||
|
||||
static QEglFSCompositor *instance();
|
||||
|
||||
private slots:
|
||||
void renderAll();
|
||||
|
||||
private:
|
||||
void render(QEglFSWindow *window, QEglFSWindow *rootWindow);
|
||||
|
||||
QEglFSWindow *m_rootWindow;
|
||||
QTimer m_updateTimer;
|
||||
};
|
||||
|
||||
class QEglFSBackingStore : public QPlatformBackingStore
|
||||
{
|
||||
public:
|
||||
QEglFSBackingStore(QWindow *window);
|
||||
~QEglFSBackingStore();
|
||||
|
||||
QPaintDevice *paintDevice();
|
||||
|
||||
@ -89,21 +64,15 @@ public:
|
||||
void flush(QWindow *window, const QRegion ®ion, const QPoint &offset);
|
||||
void resize(const QSize &size, const QRegion &staticContents);
|
||||
|
||||
uint texture() const { return m_texture; }
|
||||
|
||||
private:
|
||||
void makeCurrent();
|
||||
static QOpenGLContext *makeRootCurrent(QEglFSWindow *rootWin);
|
||||
void updateTexture();
|
||||
|
||||
QEglFSWindow *m_window;
|
||||
QOpenGLContext *m_context;
|
||||
QImage m_image;
|
||||
uint m_texture;
|
||||
QRegion m_dirty;
|
||||
QOpenGLShaderProgram *m_program;
|
||||
int m_vertexCoordEntry;
|
||||
int m_textureCoordEntry;
|
||||
|
||||
friend class QEglFSCompositor;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
198
src/plugins/platforms/eglfs/qeglfscompositor.cpp
Normal file
198
src/plugins/platforms/eglfs/qeglfscompositor.cpp
Normal file
@ -0,0 +1,198 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#include "qeglfscompositor.h"
|
||||
#include "qeglfswindow.h"
|
||||
#include "qeglfscontext.h"
|
||||
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtGui/QOpenGLShaderProgram>
|
||||
#include <QtGui/QOpenGLFramebufferObject>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static QEglFSCompositor *compositor = 0;
|
||||
|
||||
QEglFSCompositor::QEglFSCompositor()
|
||||
: m_screen(0),
|
||||
m_program(0)
|
||||
{
|
||||
Q_ASSERT(!compositor);
|
||||
m_updateTimer.setSingleShot(true);
|
||||
m_updateTimer.setInterval(0);
|
||||
connect(&m_updateTimer, SIGNAL(timeout()), SLOT(renderAll()));
|
||||
}
|
||||
|
||||
QEglFSCompositor::~QEglFSCompositor()
|
||||
{
|
||||
Q_ASSERT(compositor == this);
|
||||
delete m_program;
|
||||
compositor = 0;
|
||||
}
|
||||
|
||||
void QEglFSCompositor::schedule(QEglFSScreen *screen)
|
||||
{
|
||||
m_screen = screen;
|
||||
if (!m_updateTimer.isActive())
|
||||
m_updateTimer.start();
|
||||
}
|
||||
|
||||
void QEglFSCompositor::renderAll()
|
||||
{
|
||||
QEglFSWindow *rootWin = m_screen->rootWindow();
|
||||
if (!rootWin)
|
||||
return;
|
||||
|
||||
Q_ASSERT(rootWin->hasNativeWindow());
|
||||
QOpenGLContext *context = m_screen->rootContext();
|
||||
Q_ASSERT(context);
|
||||
|
||||
context->makeCurrent(rootWin->window());
|
||||
ensureProgram();
|
||||
m_program->bind();
|
||||
|
||||
QList<QEglFSWindow *> windows = m_screen->windows();
|
||||
for (int i = 0; i < windows.size(); ++i) {
|
||||
QEglFSWindow *window = windows.at(i);
|
||||
uint texture = window->texture();
|
||||
if (texture)
|
||||
render(window, texture, window->isRaster());
|
||||
}
|
||||
|
||||
m_program->release();
|
||||
context->swapBuffers(rootWin->window());
|
||||
}
|
||||
|
||||
void QEglFSCompositor::ensureProgram()
|
||||
{
|
||||
if (!m_program) {
|
||||
static const char *textureVertexProgram =
|
||||
"attribute highp vec2 vertexCoordEntry;\n"
|
||||
"attribute highp vec2 textureCoordEntry;\n"
|
||||
"varying highp vec2 textureCoord;\n"
|
||||
"void main() {\n"
|
||||
" textureCoord = textureCoordEntry;\n"
|
||||
" gl_Position = vec4(vertexCoordEntry, 0.0, 1.0);\n"
|
||||
"}\n";
|
||||
|
||||
static const char *textureFragmentProgram =
|
||||
"uniform sampler2D texture;\n"
|
||||
"varying highp vec2 textureCoord;\n"
|
||||
"uniform bool isRaster;\n"
|
||||
"void main() {\n"
|
||||
" lowp vec4 c = texture2D(texture, textureCoord);\n"
|
||||
" gl_FragColor = isRaster ? c.bgra : c.rgba;\n"
|
||||
"}\n";
|
||||
|
||||
m_program = new QOpenGLShaderProgram;
|
||||
|
||||
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
|
||||
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
|
||||
m_program->link();
|
||||
|
||||
m_vertexCoordEntry = m_program->attributeLocation("vertexCoordEntry");
|
||||
m_textureCoordEntry = m_program->attributeLocation("textureCoordEntry");
|
||||
m_isRasterEntry = m_program->uniformLocation("isRaster");
|
||||
}
|
||||
}
|
||||
|
||||
void QEglFSCompositor::render(QEglFSWindow *window, uint texture, bool raster)
|
||||
{
|
||||
const GLfloat textureCoordinates[] = {
|
||||
0, 0,
|
||||
1, 0,
|
||||
1, 1,
|
||||
0, 1
|
||||
};
|
||||
|
||||
QRectF sr = window->screen()->geometry();
|
||||
QRect r = window->window()->geometry();
|
||||
QPoint tl = r.topLeft();
|
||||
QPoint br = r.bottomRight();
|
||||
|
||||
GLfloat x1 = (tl.x() / sr.width()) * 2 - 1;
|
||||
GLfloat x2 = (br.x() / sr.width()) * 2 - 1;
|
||||
GLfloat y1 = ((sr.height() - tl.y()) / sr.height()) * 2 - 1;
|
||||
GLfloat y2 = ((sr.height() - br.y()) / sr.height()) * 2 - 1;
|
||||
|
||||
if (!raster)
|
||||
qSwap(y1, y2);
|
||||
|
||||
const GLfloat vertexCoordinates[] = {
|
||||
x1, y1,
|
||||
x2, y1,
|
||||
x2, y2,
|
||||
x1, y2
|
||||
};
|
||||
|
||||
glViewport(0, 0, sr.width(), sr.height());
|
||||
|
||||
glEnableVertexAttribArray(m_vertexCoordEntry);
|
||||
glEnableVertexAttribArray(m_textureCoordEntry);
|
||||
|
||||
glVertexAttribPointer(m_vertexCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
|
||||
glVertexAttribPointer(m_textureCoordEntry, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
|
||||
m_program->setUniformValue(m_isRasterEntry, raster);
|
||||
|
||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glDisableVertexAttribArray(m_vertexCoordEntry);
|
||||
glDisableVertexAttribArray(m_textureCoordEntry);
|
||||
}
|
||||
|
||||
QEglFSCompositor *QEglFSCompositor::instance()
|
||||
{
|
||||
if (!compositor)
|
||||
compositor = new QEglFSCompositor;
|
||||
return compositor;
|
||||
}
|
||||
|
||||
void QEglFSCompositor::destroy()
|
||||
{
|
||||
delete compositor;
|
||||
compositor = 0;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
83
src/plugins/platforms/eglfs/qeglfscompositor.h
Normal file
83
src/plugins/platforms/eglfs/qeglfscompositor.h
Normal file
@ -0,0 +1,83 @@
|
||||
/****************************************************************************
|
||||
**
|
||||
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
|
||||
** Contact: http://www.qt-project.org/legal
|
||||
**
|
||||
** This file is part of the plugins of the Qt Toolkit.
|
||||
**
|
||||
** $QT_BEGIN_LICENSE:LGPL$
|
||||
** Commercial License Usage
|
||||
** Licensees holding valid commercial Qt licenses may use this file in
|
||||
** accordance with the commercial license agreement provided with the
|
||||
** Software or, alternatively, in accordance with the terms contained in
|
||||
** a written agreement between you and Digia. For licensing terms and
|
||||
** conditions see http://qt.digia.com/licensing. For further information
|
||||
** use the contact form at http://qt.digia.com/contact-us.
|
||||
**
|
||||
** GNU Lesser General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU Lesser
|
||||
** General Public License version 2.1 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.LGPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU Lesser General Public License version 2.1 requirements
|
||||
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
||||
**
|
||||
** In addition, as a special exception, Digia gives you certain additional
|
||||
** rights. These rights are described in the Digia Qt LGPL Exception
|
||||
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
||||
**
|
||||
** GNU General Public License Usage
|
||||
** Alternatively, this file may be used under the terms of the GNU
|
||||
** General Public License version 3.0 as published by the Free Software
|
||||
** Foundation and appearing in the file LICENSE.GPL included in the
|
||||
** packaging of this file. Please review the following information to
|
||||
** ensure the GNU General Public License version 3.0 requirements will be
|
||||
** met: http://www.gnu.org/copyleft/gpl.html.
|
||||
**
|
||||
**
|
||||
** $QT_END_LICENSE$
|
||||
**
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef QEGLFSCOMPOSITOR_H
|
||||
#define QEGLFSCOMPOSITOR_H
|
||||
|
||||
#include <QTimer>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QEglFSScreen;
|
||||
class QEglFSWindow;
|
||||
class QOpenGLShaderProgram;
|
||||
|
||||
class QEglFSCompositor : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
void schedule(QEglFSScreen *screen);
|
||||
|
||||
static QEglFSCompositor *instance();
|
||||
static void destroy();
|
||||
|
||||
private slots:
|
||||
void renderAll();
|
||||
|
||||
private:
|
||||
QEglFSCompositor();
|
||||
~QEglFSCompositor();
|
||||
|
||||
void render(QEglFSWindow *window, uint texture, bool raster);
|
||||
void ensureProgram();
|
||||
|
||||
QEglFSScreen *m_screen;
|
||||
QTimer m_updateTimer;
|
||||
QOpenGLShaderProgram *m_program;
|
||||
int m_vertexCoordEntry;
|
||||
int m_textureCoordEntry;
|
||||
int m_isRasterEntry;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
||||
#endif // QEGLFSCOMPOSITOR_H
|
@ -43,6 +43,7 @@
|
||||
|
||||
#include "qeglfswindow.h"
|
||||
#include "qeglfsbackingstore.h"
|
||||
#include "qeglfscompositor.h"
|
||||
#include "qeglfshooks.h"
|
||||
|
||||
#include <QtGui/private/qguiapplication_p.h>
|
||||
@ -75,8 +76,6 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
static void *eglContextForContext(QOpenGLContext *context);
|
||||
|
||||
QEglFSIntegration::QEglFSIntegration()
|
||||
: mFontDb(new QGenericUnixFontDatabase)
|
||||
, mServices(new QGenericUnixServices)
|
||||
@ -108,8 +107,8 @@ QEglFSIntegration::QEglFSIntegration()
|
||||
|
||||
QEglFSIntegration::~QEglFSIntegration()
|
||||
{
|
||||
QEglFSCompositor::destroy();
|
||||
delete mScreen;
|
||||
|
||||
eglTerminate(mDisplay);
|
||||
QEglFSHooks::hooks()->platformDestroy();
|
||||
}
|
||||
@ -131,9 +130,11 @@ bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
|
||||
|
||||
QPlatformWindow *QEglFSIntegration::createPlatformWindow(QWindow *window) const
|
||||
{
|
||||
QWindowSystemInterface::flushWindowSystemEvents();
|
||||
QEglFSWindow *w = new QEglFSWindow(window);
|
||||
w->create();
|
||||
w->requestActivateWindow();
|
||||
if (window->type() != Qt::ToolTip)
|
||||
w->requestActivateWindow();
|
||||
return w;
|
||||
}
|
||||
|
||||
@ -263,15 +264,6 @@ void *QEglFSIntegration::nativeResourceForContext(const QByteArray &resource, QO
|
||||
return result;
|
||||
}
|
||||
|
||||
QPlatformNativeInterface::NativeResourceForContextFunction QEglFSIntegration::nativeResourceFunctionForContext(const QByteArray &resource)
|
||||
{
|
||||
QByteArray lowerCaseResource = resource.toLower();
|
||||
if (lowerCaseResource == "get_egl_context")
|
||||
return NativeResourceForContextFunction(eglContextForContext);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void *eglContextForContext(QOpenGLContext *context)
|
||||
{
|
||||
Q_ASSERT(context);
|
||||
@ -283,6 +275,15 @@ static void *eglContextForContext(QOpenGLContext *context)
|
||||
return handle->eglContext();
|
||||
}
|
||||
|
||||
QPlatformNativeInterface::NativeResourceForContextFunction QEglFSIntegration::nativeResourceFunctionForContext(const QByteArray &resource)
|
||||
{
|
||||
QByteArray lowerCaseResource = resource.toLower();
|
||||
if (lowerCaseResource == "get_egl_context")
|
||||
return NativeResourceForContextFunction(eglContextForContext);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
EGLConfig QEglFSIntegration::chooseConfig(EGLDisplay display, const QSurfaceFormat &format)
|
||||
{
|
||||
class Chooser : public QEglConfigChooser {
|
||||
|
@ -47,9 +47,10 @@
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
|
||||
: m_dpy(dpy)
|
||||
, m_surface(EGL_NO_SURFACE)
|
||||
, m_cursor(0)
|
||||
: m_dpy(dpy),
|
||||
m_surface(EGL_NO_SURFACE),
|
||||
m_cursor(0),
|
||||
m_rootContext(0)
|
||||
{
|
||||
#ifdef QEGL_EXTRA_DEBUG
|
||||
qWarning("QEglScreen %p\n", this);
|
||||
@ -121,10 +122,23 @@ void QEglFSScreen::removeWindow(QEglFSWindow *window)
|
||||
m_windows.removeOne(window);
|
||||
}
|
||||
|
||||
void QEglFSScreen::moveToTop(QEglFSWindow *window)
|
||||
{
|
||||
m_windows.removeOne(window);
|
||||
m_windows.append(window);
|
||||
}
|
||||
|
||||
void QEglFSScreen::changeWindowIndex(QEglFSWindow *window, int newIdx)
|
||||
{
|
||||
int idx = m_windows.indexOf(window);
|
||||
if (idx != -1 && idx != newIdx)
|
||||
m_windows.move(idx, newIdx);
|
||||
}
|
||||
|
||||
QEglFSWindow *QEglFSScreen::rootWindow()
|
||||
{
|
||||
Q_FOREACH (QEglFSWindow *window, m_windows) {
|
||||
if (window->isRasterRoot())
|
||||
if (window->hasNativeWindow())
|
||||
return window;
|
||||
}
|
||||
return 0;
|
||||
|
@ -50,9 +50,9 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QPlatformOpenGLContext;
|
||||
class QEglFSCursor;
|
||||
class QEglFSWindow;
|
||||
class QOpenGLContext;
|
||||
|
||||
class QEglFSScreen : public QPlatformScreen
|
||||
{
|
||||
@ -77,7 +77,11 @@ public:
|
||||
QList<QEglFSWindow *> windows() const { return m_windows; }
|
||||
void addWindow(QEglFSWindow *window);
|
||||
void removeWindow(QEglFSWindow *window);
|
||||
void moveToTop(QEglFSWindow *window);
|
||||
void changeWindowIndex(QEglFSWindow *window, int newIdx);
|
||||
QEglFSWindow *rootWindow();
|
||||
QOpenGLContext *rootContext() { return m_rootContext; }
|
||||
void setRootContext(QOpenGLContext *context) { m_rootContext = context; }
|
||||
|
||||
protected:
|
||||
void setPrimarySurface(EGLSurface surface);
|
||||
@ -89,6 +93,7 @@ private:
|
||||
EGLSurface m_surface;
|
||||
QEglFSCursor *m_cursor;
|
||||
QList<QEglFSWindow *> m_windows;
|
||||
QOpenGLContext *m_rootContext;
|
||||
};
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -42,9 +42,11 @@
|
||||
#include "qeglfswindow.h"
|
||||
#include "qeglfshooks.h"
|
||||
#include "qeglfscursor.h"
|
||||
#include "qeglfsbackingstore.h"
|
||||
#include <qpa/qwindowsysteminterface.h>
|
||||
#include <qpa/qplatformintegration.h>
|
||||
#include <private/qguiapplication_p.h>
|
||||
#include <QtGui/QOpenGLContext>
|
||||
|
||||
#include <QtPlatformSupport/private/qeglconvenience_p.h>
|
||||
|
||||
@ -99,18 +101,21 @@ void QEglFSWindow::create()
|
||||
if (window()->surfaceType() == QSurface::RasterSurface)
|
||||
m_flags |= IsRaster;
|
||||
|
||||
// Stop if there is already a raster root window backed by a native window and
|
||||
// surface. Other raster windows will not have their own native window, surface and
|
||||
// context. Instead, they will be composited onto the root window's surface.
|
||||
if (screen()->primarySurface() != EGL_NO_SURFACE) {
|
||||
if (m_flags.testFlag(IsRaster) && screen()->rootWindow()->m_flags.testFlag(IsRaster))
|
||||
// Stop if there is already a window backed by a native window and surface. Additional
|
||||
// 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();
|
||||
if (screen->primarySurface() != EGL_NO_SURFACE) {
|
||||
if (m_flags.testFlag(IsRaster) && screen->rootWindow()->m_flags.testFlag(IsRaster))
|
||||
return;
|
||||
|
||||
#ifndef Q_OS_ANDROID
|
||||
#if !defined(Q_OS_ANDROID) || defined(Q_OS_ANDROID_NO_SDK)
|
||||
// We can have either a single OpenGL window or multiple raster windows.
|
||||
// Other combinations cannot work.
|
||||
qFatal("EGLFS: OpenGL windows cannot be mixed with others.");
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
window()->setSurfaceType(QSurface::OpenGLSurface);
|
||||
@ -118,31 +123,40 @@ void QEglFSWindow::create()
|
||||
setGeometry(QRect()); // will become fullscreen
|
||||
QWindowSystemInterface::handleExposeEvent(window(), geometry());
|
||||
|
||||
EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
|
||||
EGLDisplay display = static_cast<QEglFSScreen *>(screen)->display();
|
||||
QSurfaceFormat platformFormat = QEglFSHooks::hooks()->surfaceFormatFor(window()->requestedFormat());
|
||||
m_config = QEglFSIntegration::chooseConfig(display, platformFormat);
|
||||
m_format = q_glFormatFromConfig(display, m_config);
|
||||
|
||||
resetSurface();
|
||||
|
||||
if (screen()->primarySurface() == EGL_NO_SURFACE) {
|
||||
screen()->setPrimarySurface(m_surface);
|
||||
m_flags |= IsRasterRoot;
|
||||
screen->setPrimarySurface(m_surface);
|
||||
|
||||
if (m_flags.testFlag(IsRaster)) {
|
||||
QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance());
|
||||
context->setFormat(window()->requestedFormat());
|
||||
context->setScreen(window()->screen());
|
||||
context->create();
|
||||
screen->setRootContext(context);
|
||||
}
|
||||
}
|
||||
|
||||
void QEglFSWindow::destroy()
|
||||
{
|
||||
QEglFSScreen *screen = this->screen();
|
||||
if (m_flags.testFlag(HasNativeWindow)) {
|
||||
QEglFSCursor *cursor = static_cast<QEglFSCursor *>(screen()->cursor());
|
||||
QEglFSCursor *cursor = static_cast<QEglFSCursor *>(screen->cursor());
|
||||
if (cursor)
|
||||
cursor->resetResources();
|
||||
if (screen()->primarySurface() == m_surface)
|
||||
screen()->setPrimarySurface(EGL_NO_SURFACE);
|
||||
|
||||
if (screen->primarySurface() == m_surface)
|
||||
screen->setPrimarySurface(EGL_NO_SURFACE);
|
||||
|
||||
invalidateSurface();
|
||||
}
|
||||
|
||||
m_flags = 0;
|
||||
screen()->removeWindow(this);
|
||||
screen->removeWindow(this);
|
||||
}
|
||||
|
||||
// The virtual functions resetSurface and invalidateSurface may get overridden
|
||||
@ -182,20 +196,15 @@ void QEglFSWindow::setVisible(bool visible)
|
||||
} else {
|
||||
screen()->removeWindow(this);
|
||||
windows = screen()->windows();
|
||||
// try activating the window below
|
||||
if (windows.size())
|
||||
windows.last()->requestActivateWindow();
|
||||
}
|
||||
}
|
||||
|
||||
// trigger an update
|
||||
QEglFSWindow *rootWin = screen()->rootWindow();
|
||||
if (rootWin) {
|
||||
QWindowSystemInterface::handleExposeEvent(rootWin->window(), rootWin->window()->geometry());
|
||||
QWindowSystemInterface::flushWindowSystemEvents();
|
||||
}
|
||||
QWindowSystemInterface::handleExposeEvent(window(), window()->geometry());
|
||||
|
||||
QPlatformWindow::setVisible(visible);
|
||||
if (visible)
|
||||
QWindowSystemInterface::flushWindowSystemEvents();
|
||||
}
|
||||
|
||||
void QEglFSWindow::setGeometry(const QRect &r)
|
||||
@ -230,13 +239,31 @@ WId QEglFSWindow::winId() const
|
||||
|
||||
void QEglFSWindow::requestActivateWindow()
|
||||
{
|
||||
if (window()->type() != Qt::Desktop) {
|
||||
// move to the end of the list, to be on top
|
||||
screen()->removeWindow(this);
|
||||
screen()->addWindow(this);
|
||||
}
|
||||
if (window()->type() != Qt::Desktop)
|
||||
screen()->moveToTop(this);
|
||||
|
||||
QWindowSystemInterface::handleWindowActivated(window());
|
||||
QWindowSystemInterface::handleExposeEvent(window(), window()->geometry());
|
||||
}
|
||||
|
||||
void QEglFSWindow::raise()
|
||||
{
|
||||
if (window()->type() != Qt::Desktop) {
|
||||
screen()->moveToTop(this);
|
||||
QWindowSystemInterface::handleExposeEvent(window(), window()->geometry());
|
||||
}
|
||||
}
|
||||
|
||||
void QEglFSWindow::lower()
|
||||
{
|
||||
QList<QEglFSWindow *> windows = screen()->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(), windows.last()->geometry());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
EGLSurface QEglFSWindow::surface() const
|
||||
@ -259,4 +286,12 @@ QEglFSScreen *QEglFSWindow::screen() const
|
||||
return static_cast<QEglFSScreen *>(QPlatformWindow::screen());
|
||||
}
|
||||
|
||||
uint QEglFSWindow::texture() const
|
||||
{
|
||||
if (m_backingStore)
|
||||
return m_backingStore->texture();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -62,6 +62,8 @@ public:
|
||||
WId winId() const;
|
||||
void setVisible(bool visible);
|
||||
void requestActivateWindow();
|
||||
void raise();
|
||||
void lower();
|
||||
|
||||
EGLSurface surface() const;
|
||||
QSurfaceFormat format() const;
|
||||
@ -73,11 +75,13 @@ public:
|
||||
void destroy();
|
||||
|
||||
bool hasNativeWindow() const { return m_flags.testFlag(HasNativeWindow); }
|
||||
bool isRasterRoot() const { return m_flags.testFlag(IsRasterRoot); }
|
||||
bool isRaster() const { return m_flags.testFlag(IsRaster); }
|
||||
|
||||
QEglFSBackingStore *backingStore() { return m_backingStore; }
|
||||
void setBackingStore(QEglFSBackingStore *backingStore) { m_backingStore = backingStore; }
|
||||
|
||||
uint texture() const;
|
||||
|
||||
virtual void invalidateSurface();
|
||||
virtual void resetSurface();
|
||||
|
||||
@ -93,9 +97,8 @@ private:
|
||||
|
||||
enum Flag {
|
||||
Created = 0x01,
|
||||
HasNativeWindow = 0x02,
|
||||
IsRaster = 0x04,
|
||||
IsRasterRoot = 0x08
|
||||
IsRaster = 0x02,
|
||||
HasNativeWindow = 0x04
|
||||
};
|
||||
Q_DECLARE_FLAGS(Flags, Flag);
|
||||
Flags m_flags;
|
||||
|
Loading…
Reference in New Issue
Block a user