eglfs: Support multiple raster windows
Allow widget apps with popups and multiple top-level widgets to function on the eglfs platform. GL and Quick2 apps are not affected. Instead of trying to create a native window and EGL surface for each window, do it only for the window that is created first. This first window is forced to fullscreen as usual. Later windows however are treated differently: These will not have a native window, surface or context, and keep their normal size. All the textures belonging to the raster windows are then rendered in one step, using a stacking order maintained based on visibility changes and window activation. Note that this will only help apps that create a main window first and have everything else inside that window or on top of it as menus, dialogs, popups, etc. Change-Id: Ia435458ba81bf3c35cc8f61bcb2d2a50cf17f0e3 Reviewed-by: Gunnar Sletta <gunnar.sletta@digia.com> Reviewed-by: Andy Nichols <andy.nichols@digia.com>
This commit is contained in:
parent
cfd5284249
commit
f89f099c55
@ -2,12 +2,13 @@ QT += core-private gui-private platformsupport-private
|
|||||||
|
|
||||||
#DEFINES += QEGL_EXTRA_DEBUG
|
#DEFINES += QEGL_EXTRA_DEBUG
|
||||||
|
|
||||||
#Avoid X11 header collision
|
# Avoid X11 header collision
|
||||||
DEFINES += MESA_EGL_NO_X11_HEADERS
|
DEFINES += MESA_EGL_NO_X11_HEADERS
|
||||||
|
|
||||||
#To test the hooks on x11 (xlib), comment the above define too
|
# Uncomment these to enable the X hooks, allowing to test the platform
|
||||||
#EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_x11.cpp
|
# plugin in a regular X11 environment (as long as EGL is available).
|
||||||
#LIBS += -lX11 -lX11-xcb -lxcb
|
# EGLFS_PLATFORM_HOOKS_SOURCES += qeglfshooks_x11.cpp
|
||||||
|
# LIBS += -lX11 -lX11-xcb -lxcb
|
||||||
|
|
||||||
SOURCES += $$PWD/qeglfsintegration.cpp \
|
SOURCES += $$PWD/qeglfsintegration.cpp \
|
||||||
$$PWD/qeglfswindow.cpp \
|
$$PWD/qeglfswindow.cpp \
|
||||||
|
@ -51,15 +51,101 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
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)
|
QEglFSBackingStore::QEglFSBackingStore(QWindow *window)
|
||||||
: QPlatformBackingStore(window)
|
: QPlatformBackingStore(window)
|
||||||
, m_context(new QOpenGLContext)
|
, m_window(static_cast<QEglFSWindow *>(window->handle()))
|
||||||
|
, m_context(0)
|
||||||
, m_texture(0)
|
, m_texture(0)
|
||||||
, m_program(0)
|
, m_program(0)
|
||||||
{
|
{
|
||||||
m_context->setFormat(window->requestedFormat());
|
m_window->setBackingStore(this);
|
||||||
m_context->setScreen(window->screen());
|
|
||||||
m_context->create();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QEglFSBackingStore::~QEglFSBackingStore()
|
QEglFSBackingStore::~QEglFSBackingStore()
|
||||||
@ -73,82 +159,15 @@ QPaintDevice *QEglFSBackingStore::paintDevice()
|
|||||||
return &m_image;
|
return &m_image;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
void QEglFSBackingStore::updateTexture()
|
||||||
{
|
{
|
||||||
Q_UNUSED(region);
|
|
||||||
Q_UNUSED(offset);
|
|
||||||
|
|
||||||
makeCurrent();
|
|
||||||
|
|
||||||
QRectF sr = window->screen()->geometry();
|
|
||||||
glViewport(0, 0, sr.width(), sr.height());
|
|
||||||
|
|
||||||
#ifdef QEGL_EXTRA_DEBUG
|
|
||||||
qWarning("QEglBackingStore::flush %p", window);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
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"
|
|
||||||
"void main() {\n"
|
|
||||||
" gl_FragColor = texture2D(texture, textureCoord).bgra;\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_program->bind();
|
|
||||||
|
|
||||||
const GLfloat textureCoordinates[] = {
|
|
||||||
0, 1,
|
|
||||||
1, 1,
|
|
||||||
1, 0,
|
|
||||||
0, 0
|
|
||||||
};
|
|
||||||
|
|
||||||
QRectF r = window->geometry();
|
|
||||||
|
|
||||||
GLfloat x1 = (r.left() / sr.width()) * 2 - 1;
|
|
||||||
GLfloat x2 = (r.right() / sr.width()) * 2 - 1;
|
|
||||||
GLfloat y1 = (r.top() / sr.height()) * 2 - 1;
|
|
||||||
GLfloat y2 = (r.bottom() / sr.height()) * 2 - 1;
|
|
||||||
|
|
||||||
const GLfloat vertexCoordinates[] = {
|
|
||||||
x1, y1,
|
|
||||||
x2, y1,
|
|
||||||
x2, y2,
|
|
||||||
x1, y2
|
|
||||||
};
|
|
||||||
|
|
||||||
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, m_texture);
|
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||||
|
|
||||||
if (!m_dirty.isNull()) {
|
if (!m_dirty.isNull()) {
|
||||||
QRect imageRect = m_image.rect();
|
|
||||||
|
|
||||||
QRegion fixed;
|
QRegion fixed;
|
||||||
|
QRect imageRect = m_image.rect();
|
||||||
|
m_dirty |= imageRect;
|
||||||
|
|
||||||
foreach (const QRect &rect, m_dirty.rects()) {
|
foreach (const QRect &rect, m_dirty.rects()) {
|
||||||
// intersect with image rect to be sure
|
// intersect with image rect to be sure
|
||||||
QRect r = imageRect & rect;
|
QRect r = imageRect & rect;
|
||||||
@ -176,32 +195,80 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo
|
|||||||
|
|
||||||
m_dirty = QRegion();
|
m_dirty = QRegion();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
|
void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset)
|
||||||
|
{
|
||||||
|
Q_UNUSED(window);
|
||||||
|
Q_UNUSED(region);
|
||||||
|
Q_UNUSED(offset);
|
||||||
|
|
||||||
m_program->release();
|
#ifdef QEGL_EXTRA_DEBUG
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
qWarning("QEglBackingStore::flush %p", window);
|
||||||
glDisableVertexAttribArray(m_vertexCoordEntry);
|
#endif
|
||||||
glDisableVertexAttribArray(m_textureCoordEntry);
|
|
||||||
|
|
||||||
// draw the cursor
|
m_window->create();
|
||||||
if (QEglFSCursor *cursor = static_cast<QEglFSCursor *>(window->screen()->handle()->cursor()))
|
QEglFSWindow *rootWin = m_window->screen()->rootWindow();
|
||||||
cursor->paintOnScreen();
|
if (rootWin) {
|
||||||
|
makeRootCurrent(rootWin);
|
||||||
m_context->swapBuffers(window);
|
updateTexture();
|
||||||
|
QEglFSCompositor::instance()->schedule(rootWin);
|
||||||
m_context->doneCurrent();
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEglFSBackingStore::makeCurrent()
|
void QEglFSBackingStore::makeCurrent()
|
||||||
{
|
{
|
||||||
(static_cast<QEglFSWindow *>(window()->handle()))->create();
|
Q_ASSERT(m_window->hasNativeWindow());
|
||||||
m_context->makeCurrent(window());
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEglFSBackingStore::beginPaint(const QRegion &rgn)
|
void QEglFSBackingStore::beginPaint(const QRegion &rgn)
|
||||||
{
|
{
|
||||||
m_dirty = m_dirty | rgn;
|
m_dirty |= rgn;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEglFSBackingStore::resize(const QSize &size, const QRegion &staticContents)
|
void QEglFSBackingStore::resize(const QSize &size, const QRegion &staticContents)
|
||||||
@ -209,9 +276,12 @@ void QEglFSBackingStore::resize(const QSize &size, const QRegion &staticContents
|
|||||||
Q_UNUSED(staticContents);
|
Q_UNUSED(staticContents);
|
||||||
|
|
||||||
m_image = QImage(size, QImage::Format_RGB32);
|
m_image = QImage(size, QImage::Format_RGB32);
|
||||||
makeCurrent();
|
m_window->create();
|
||||||
|
makeRootCurrent(m_window->screen()->rootWindow());
|
||||||
|
|
||||||
if (m_texture)
|
if (m_texture)
|
||||||
glDeleteTextures(1, &m_texture);
|
glDeleteTextures(1, &m_texture);
|
||||||
|
|
||||||
glGenTextures(1, &m_texture);
|
glGenTextures(1, &m_texture);
|
||||||
glBindTexture(GL_TEXTURE_2D, m_texture);
|
glBindTexture(GL_TEXTURE_2D, m_texture);
|
||||||
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||||
|
@ -46,12 +46,35 @@
|
|||||||
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#include <QRegion>
|
#include <QRegion>
|
||||||
|
#include <QTimer>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
class QOpenGLContext;
|
class QOpenGLContext;
|
||||||
class QOpenGLPaintDevice;
|
class QOpenGLPaintDevice;
|
||||||
class QOpenGLShaderProgram;
|
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
|
class QEglFSBackingStore : public QPlatformBackingStore
|
||||||
{
|
{
|
||||||
@ -68,7 +91,10 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
void makeCurrent();
|
void makeCurrent();
|
||||||
|
static QOpenGLContext *makeRootCurrent(QEglFSWindow *rootWin);
|
||||||
|
void updateTexture();
|
||||||
|
|
||||||
|
QEglFSWindow *m_window;
|
||||||
QOpenGLContext *m_context;
|
QOpenGLContext *m_context;
|
||||||
QImage m_image;
|
QImage m_image;
|
||||||
uint m_texture;
|
uint m_texture;
|
||||||
@ -76,6 +102,8 @@ private:
|
|||||||
QOpenGLShaderProgram *m_program;
|
QOpenGLShaderProgram *m_program;
|
||||||
int m_vertexCoordEntry;
|
int m_vertexCoordEntry;
|
||||||
int m_textureCoordEntry;
|
int m_textureCoordEntry;
|
||||||
|
|
||||||
|
friend class QEglFSCompositor;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -62,12 +62,21 @@ QEglFSCursor::QEglFSCursor(QEglFSScreen *screen)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QEglFSCursor::~QEglFSCursor()
|
QEglFSCursor::~QEglFSCursor()
|
||||||
|
{
|
||||||
|
resetResources();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QEglFSCursor::resetResources()
|
||||||
{
|
{
|
||||||
if (QOpenGLContext::currentContext()) {
|
if (QOpenGLContext::currentContext()) {
|
||||||
glDeleteProgram(m_program);
|
glDeleteProgram(m_program);
|
||||||
glDeleteTextures(1, &m_cursor.customCursorTexture);
|
glDeleteTextures(1, &m_cursor.customCursorTexture);
|
||||||
glDeleteTextures(1, &m_cursorAtlas.texture);
|
glDeleteTextures(1, &m_cursorAtlas.texture);
|
||||||
}
|
}
|
||||||
|
m_program = 0;
|
||||||
|
m_cursor.customCursorTexture = 0;
|
||||||
|
m_cursor.customCursorPending = !m_cursor.customCursorImage.isNull();
|
||||||
|
m_cursorAtlas.texture = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLuint createShader(GLenum shaderType, const char *program)
|
static GLuint createShader(GLenum shaderType, const char *program)
|
||||||
@ -201,9 +210,9 @@ bool QEglFSCursor::setCurrentCursor(QCursor *cursor)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_cursor.shape == Qt::BitmapCursor) {
|
if (m_cursor.shape == Qt::BitmapCursor) {
|
||||||
m_cursor.customCursorImage = QImage(); // in case render() never uploaded it
|
m_cursor.customCursorImage = QImage();
|
||||||
|
m_cursor.customCursorPending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_cursor.shape = newShape;
|
m_cursor.shape = newShape;
|
||||||
if (newShape != Qt::BitmapCursor) { // standard cursor
|
if (newShape != Qt::BitmapCursor) { // standard cursor
|
||||||
const float ws = (float)m_cursorAtlas.cursorWidth / m_cursorAtlas.width,
|
const float ws = (float)m_cursorAtlas.cursorWidth / m_cursorAtlas.width,
|
||||||
@ -221,6 +230,7 @@ bool QEglFSCursor::setCurrentCursor(QCursor *cursor)
|
|||||||
m_cursor.texture = 0; // will get updated in the next render()
|
m_cursor.texture = 0; // will get updated in the next render()
|
||||||
m_cursor.size = image.size();
|
m_cursor.size = image.size();
|
||||||
m_cursor.customCursorImage = image;
|
m_cursor.customCursorImage = image;
|
||||||
|
m_cursor.customCursorPending = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -255,7 +265,7 @@ void QEglFSCursor::pointerEvent(const QMouseEvent &event)
|
|||||||
if (event.type() != QEvent::MouseMove)
|
if (event.type() != QEvent::MouseMove)
|
||||||
return;
|
return;
|
||||||
const QRect oldCursorRect = cursorRect();
|
const QRect oldCursorRect = cursorRect();
|
||||||
m_cursor.pos = event.pos();
|
m_cursor.pos = event.screenPos().toPoint();
|
||||||
update(oldCursorRect | cursorRect());
|
update(oldCursorRect | cursorRect());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -280,18 +290,17 @@ void QEglFSCursor::draw(const QRectF &r)
|
|||||||
|
|
||||||
if (!m_cursorAtlas.texture) {
|
if (!m_cursorAtlas.texture) {
|
||||||
createCursorTexture(&m_cursorAtlas.texture, m_cursorAtlas.image);
|
createCursorTexture(&m_cursorAtlas.texture, m_cursorAtlas.image);
|
||||||
m_cursorAtlas.image = QImage();
|
|
||||||
|
|
||||||
if (m_cursor.shape != Qt::BitmapCursor)
|
if (m_cursor.shape != Qt::BitmapCursor)
|
||||||
m_cursor.texture = m_cursorAtlas.texture;
|
m_cursor.texture = m_cursorAtlas.texture;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_cursor.shape == Qt::BitmapCursor && !m_cursor.customCursorImage.isNull()) {
|
if (m_cursor.shape == Qt::BitmapCursor && m_cursor.customCursorPending) {
|
||||||
// upload the custom cursor
|
// upload the custom cursor
|
||||||
createCursorTexture(&m_cursor.customCursorTexture, m_cursor.customCursorImage);
|
createCursorTexture(&m_cursor.customCursorTexture, m_cursor.customCursorImage);
|
||||||
m_cursor.texture = m_cursor.customCursorTexture;
|
m_cursor.texture = m_cursor.customCursorTexture;
|
||||||
m_cursor.customCursorImage = QImage();
|
m_cursor.customCursorPending = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_ASSERT(m_cursor.texture);
|
Q_ASSERT(m_cursor.texture);
|
||||||
|
@ -69,6 +69,8 @@ public:
|
|||||||
|
|
||||||
virtual void paintOnScreen();
|
virtual void paintOnScreen();
|
||||||
|
|
||||||
|
void resetResources();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
#ifndef QT_NO_CURSOR
|
#ifndef QT_NO_CURSOR
|
||||||
bool setCurrentCursor(QCursor *cursor);
|
bool setCurrentCursor(QCursor *cursor);
|
||||||
@ -80,7 +82,7 @@ protected:
|
|||||||
|
|
||||||
// current cursor information
|
// current cursor information
|
||||||
struct Cursor {
|
struct Cursor {
|
||||||
Cursor() : texture(0), shape(Qt::BlankCursor), customCursorTexture(0) { }
|
Cursor() : texture(0), shape(Qt::BlankCursor), customCursorTexture(0), customCursorPending(false) { }
|
||||||
uint texture; // a texture from 'image' or the atlas
|
uint texture; // a texture from 'image' or the atlas
|
||||||
Qt::CursorShape shape;
|
Qt::CursorShape shape;
|
||||||
QRectF textureRect; // normalized rect inside texture
|
QRectF textureRect; // normalized rect inside texture
|
||||||
@ -89,6 +91,7 @@ protected:
|
|||||||
QImage customCursorImage;
|
QImage customCursorImage;
|
||||||
QPoint pos; // current cursor position
|
QPoint pos; // current cursor position
|
||||||
uint customCursorTexture;
|
uint customCursorTexture;
|
||||||
|
bool customCursorPending;
|
||||||
} m_cursor;
|
} m_cursor;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -194,8 +194,11 @@ void EventReader::run()
|
|||||||
const xcb_atom_t *atoms = m_hooks->atoms();
|
const xcb_atom_t *atoms = m_hooks->atoms();
|
||||||
if (client->format == 32
|
if (client->format == 32
|
||||||
&& client->type == atoms[Atoms::WM_PROTOCOLS]
|
&& client->type == atoms[Atoms::WM_PROTOCOLS]
|
||||||
&& client->data.data32[0] == atoms[Atoms::WM_DELETE_WINDOW])
|
&& client->data.data32[0] == atoms[Atoms::WM_DELETE_WINDOW]) {
|
||||||
QWindowSystemInterface::handleCloseEvent(m_hooks->platformWindow()->window());
|
QWindow *window = m_hooks->platformWindow() ? m_hooks->platformWindow()->window() : 0;
|
||||||
|
if (window)
|
||||||
|
QWindowSystemInterface::handleCloseEvent(window);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
|
|
||||||
#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
|
#include <QtPlatformSupport/private/qgenericunixfontdatabase_p.h>
|
||||||
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
|
#include <QtPlatformSupport/private/qgenericunixeventdispatcher_p.h>
|
||||||
|
#include <QtPlatformSupport/private/qgenericunixservices_p.h>
|
||||||
#include <QtPlatformSupport/private/qeglconvenience_p.h>
|
#include <QtPlatformSupport/private/qeglconvenience_p.h>
|
||||||
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
|
#include <QtPlatformSupport/private/qeglplatformcontext_p.h>
|
||||||
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
|
#include <QtPlatformSupport/private/qeglpbuffer_p.h>
|
||||||
@ -77,7 +78,9 @@ QT_BEGIN_NAMESPACE
|
|||||||
static void *eglContextForContext(QOpenGLContext *context);
|
static void *eglContextForContext(QOpenGLContext *context);
|
||||||
|
|
||||||
QEglFSIntegration::QEglFSIntegration()
|
QEglFSIntegration::QEglFSIntegration()
|
||||||
: mEventDispatcher(createUnixEventDispatcher()), mFontDb(new QGenericUnixFontDatabase())
|
: mEventDispatcher(createUnixEventDispatcher()),
|
||||||
|
mFontDb(new QGenericUnixFontDatabase),
|
||||||
|
mServices(new QGenericUnixServices)
|
||||||
{
|
{
|
||||||
QGuiApplicationPrivate::instance()->setEventDispatcher(mEventDispatcher);
|
QGuiApplicationPrivate::instance()->setEventDispatcher(mEventDispatcher);
|
||||||
|
|
||||||
@ -161,7 +164,7 @@ QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOf
|
|||||||
|
|
||||||
QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const
|
QPlatformFontDatabase *QEglFSIntegration::fontDatabase() const
|
||||||
{
|
{
|
||||||
return mFontDb;
|
return mFontDb.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
QAbstractEventDispatcher *QEglFSIntegration::guiThreadEventDispatcher() const
|
QAbstractEventDispatcher *QEglFSIntegration::guiThreadEventDispatcher() const
|
||||||
@ -171,10 +174,18 @@ QAbstractEventDispatcher *QEglFSIntegration::guiThreadEventDispatcher() const
|
|||||||
|
|
||||||
QVariant QEglFSIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
|
QVariant QEglFSIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
|
||||||
{
|
{
|
||||||
if (hint == QPlatformIntegration::ShowIsFullScreen)
|
switch (hint)
|
||||||
return true;
|
{
|
||||||
|
case QPlatformIntegration::ShowIsFullScreen:
|
||||||
|
return mScreen->rootWindow() == 0;
|
||||||
|
default:
|
||||||
|
return QPlatformIntegration::styleHint(hint);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return QPlatformIntegration::styleHint(hint);
|
QPlatformServices *QEglFSIntegration::services() const
|
||||||
|
{
|
||||||
|
return mServices.data();
|
||||||
}
|
}
|
||||||
|
|
||||||
QPlatformNativeInterface *QEglFSIntegration::nativeInterface() const
|
QPlatformNativeInterface *QEglFSIntegration::nativeInterface() const
|
||||||
@ -187,7 +198,7 @@ void *QEglFSIntegration::nativeResourceForIntegration(const QByteArray &resource
|
|||||||
QByteArray lowerCaseResource = resource.toLower();
|
QByteArray lowerCaseResource = resource.toLower();
|
||||||
|
|
||||||
if (lowerCaseResource == "egldisplay")
|
if (lowerCaseResource == "egldisplay")
|
||||||
return static_cast<QEglFSScreen *>(mScreen)->display();
|
return mScreen->display();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -200,7 +211,7 @@ void *QEglFSIntegration::nativeResourceForWindow(const QByteArray &resource, QWi
|
|||||||
if (window && window->handle())
|
if (window && window->handle())
|
||||||
return static_cast<QEglFSScreen *>(window->handle()->screen())->display();
|
return static_cast<QEglFSScreen *>(window->handle()->screen())->display();
|
||||||
else
|
else
|
||||||
return static_cast<QEglFSScreen *>(mScreen)->display();
|
return mScreen->display();
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -65,6 +65,7 @@ public:
|
|||||||
QPlatformNativeInterface *nativeInterface() const;
|
QPlatformNativeInterface *nativeInterface() const;
|
||||||
|
|
||||||
QPlatformFontDatabase *fontDatabase() const;
|
QPlatformFontDatabase *fontDatabase() const;
|
||||||
|
QPlatformServices *services() const;
|
||||||
|
|
||||||
QAbstractEventDispatcher *guiThreadEventDispatcher() const;
|
QAbstractEventDispatcher *guiThreadEventDispatcher() const;
|
||||||
|
|
||||||
@ -87,8 +88,9 @@ public:
|
|||||||
private:
|
private:
|
||||||
EGLDisplay mDisplay;
|
EGLDisplay mDisplay;
|
||||||
QAbstractEventDispatcher *mEventDispatcher;
|
QAbstractEventDispatcher *mEventDispatcher;
|
||||||
QPlatformFontDatabase *mFontDb;
|
QScopedPointer<QPlatformFontDatabase> mFontDb;
|
||||||
QPlatformScreen *mScreen;
|
QScopedPointer<QPlatformServices> mServices;
|
||||||
|
QEglFSScreen *mScreen;
|
||||||
QPlatformInputContext *mInputContext;
|
QPlatformInputContext *mInputContext;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -48,7 +48,7 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
|
QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
|
||||||
: m_dpy(dpy)
|
: m_dpy(dpy)
|
||||||
, m_surface(0)
|
, m_surface(EGL_NO_SURFACE)
|
||||||
, m_cursor(0)
|
, m_cursor(0)
|
||||||
{
|
{
|
||||||
#ifdef QEGL_EXTRA_DEBUG
|
#ifdef QEGL_EXTRA_DEBUG
|
||||||
@ -110,4 +110,24 @@ void QEglFSScreen::setPrimarySurface(EGLSurface surface)
|
|||||||
m_surface = surface;
|
m_surface = surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QEglFSScreen::addWindow(QEglFSWindow *window)
|
||||||
|
{
|
||||||
|
if (!m_windows.contains(window))
|
||||||
|
m_windows.append(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
void QEglFSScreen::removeWindow(QEglFSWindow *window)
|
||||||
|
{
|
||||||
|
m_windows.removeOne(window);
|
||||||
|
}
|
||||||
|
|
||||||
|
QEglFSWindow *QEglFSScreen::rootWindow()
|
||||||
|
{
|
||||||
|
Q_FOREACH (QEglFSWindow *window, m_windows) {
|
||||||
|
if (window->isRasterRoot())
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -52,8 +52,9 @@ QT_BEGIN_NAMESPACE
|
|||||||
|
|
||||||
class QPlatformOpenGLContext;
|
class QPlatformOpenGLContext;
|
||||||
class QEglFSCursor;
|
class QEglFSCursor;
|
||||||
|
class QEglFSWindow;
|
||||||
|
|
||||||
class QEglFSScreen : public QPlatformScreen //huh: FullScreenScreen ;) just to follow namespace
|
class QEglFSScreen : public QPlatformScreen
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QEglFSScreen(EGLDisplay display);
|
QEglFSScreen(EGLDisplay display);
|
||||||
@ -73,6 +74,11 @@ public:
|
|||||||
EGLDisplay display() const { return m_dpy; }
|
EGLDisplay display() const { return m_dpy; }
|
||||||
EGLSurface primarySurface() const { return m_surface; }
|
EGLSurface primarySurface() const { return m_surface; }
|
||||||
|
|
||||||
|
QList<QEglFSWindow *> windows() const { return m_windows; }
|
||||||
|
void addWindow(QEglFSWindow *window);
|
||||||
|
void removeWindow(QEglFSWindow *window);
|
||||||
|
QEglFSWindow *rootWindow();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void setPrimarySurface(EGLSurface surface);
|
void setPrimarySurface(EGLSurface surface);
|
||||||
|
|
||||||
@ -82,6 +88,7 @@ private:
|
|||||||
EGLDisplay m_dpy;
|
EGLDisplay m_dpy;
|
||||||
EGLSurface m_surface;
|
EGLSurface m_surface;
|
||||||
QEglFSCursor *m_cursor;
|
QEglFSCursor *m_cursor;
|
||||||
|
QList<QEglFSWindow *> m_windows;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -41,6 +41,7 @@
|
|||||||
|
|
||||||
#include "qeglfswindow.h"
|
#include "qeglfswindow.h"
|
||||||
#include "qeglfshooks.h"
|
#include "qeglfshooks.h"
|
||||||
|
#include "qeglfscursor.h"
|
||||||
#include <qpa/qwindowsysteminterface.h>
|
#include <qpa/qwindowsysteminterface.h>
|
||||||
#include <qpa/qplatformintegration.h>
|
#include <qpa/qplatformintegration.h>
|
||||||
#include <private/qguiapplication_p.h>
|
#include <private/qguiapplication_p.h>
|
||||||
@ -55,12 +56,13 @@ QEglFSWindow::QEglFSWindow(QWindow *w)
|
|||||||
: QPlatformWindow(w)
|
: QPlatformWindow(w)
|
||||||
, m_surface(0)
|
, m_surface(0)
|
||||||
, m_window(0)
|
, m_window(0)
|
||||||
, has_window(false)
|
, m_wid(0)
|
||||||
|
, m_backingStore(0)
|
||||||
|
, m_flags(0)
|
||||||
{
|
{
|
||||||
#ifdef QEGL_EXTRA_DEBUG
|
#ifdef QEGL_EXTRA_DEBUG
|
||||||
qWarning("QEglWindow %p: %p 0x%x\n", this, w, uint(m_window));
|
qWarning("QEglWindow %p: %p 0x%x\n", this, w, uint(m_window));
|
||||||
#endif
|
#endif
|
||||||
w->setSurfaceType(QSurface::OpenGLSurface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QEglFSWindow::~QEglFSWindow()
|
QEglFSWindow::~QEglFSWindow()
|
||||||
@ -68,17 +70,23 @@ QEglFSWindow::~QEglFSWindow()
|
|||||||
destroy();
|
destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool supportsMultipleWindows()
|
static WId newWId()
|
||||||
{
|
{
|
||||||
return QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::MultipleWindows);
|
static WId id = 0;
|
||||||
|
|
||||||
|
if (id == std::numeric_limits<WId>::max())
|
||||||
|
qWarning("EGLFS: Out of window IDs");
|
||||||
|
|
||||||
|
return ++id;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEglFSWindow::create()
|
void QEglFSWindow::create()
|
||||||
{
|
{
|
||||||
if (has_window)
|
if (m_flags.testFlag(Created))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setWindowState(Qt::WindowFullScreen);
|
m_flags = Created;
|
||||||
|
m_wid = newWId();
|
||||||
|
|
||||||
if (window()->type() == Qt::Desktop) {
|
if (window()->type() == Qt::Desktop) {
|
||||||
QRect rect(QPoint(), QEglFSHooks::hooks()->screenSize());
|
QRect rect(QPoint(), QEglFSHooks::hooks()->screenSize());
|
||||||
@ -87,94 +95,142 @@ void QEglFSWindow::create()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!supportsMultipleWindows() && screen()->primarySurface()) {
|
// Save the original surface type before changing to OpenGLSurface.
|
||||||
qFatal("EGLFS: Multiple windows are not supported");
|
if (window()->surfaceType() == QSurface::RasterSurface)
|
||||||
return;
|
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))
|
||||||
|
return;
|
||||||
|
|
||||||
|
#ifndef Q_OS_ANDROID
|
||||||
|
// 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
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLDisplay display = (static_cast<QEglFSScreen *>(window()->screen()->handle()))->display();
|
window()->setSurfaceType(QSurface::OpenGLSurface);
|
||||||
|
setGeometry(screen()->availableGeometry());
|
||||||
|
QWindowSystemInterface::handleExposeEvent(window(), QRegion(screen()->availableGeometry()));
|
||||||
|
|
||||||
|
EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
|
||||||
QSurfaceFormat platformFormat = QEglFSHooks::hooks()->surfaceFormatFor(window()->requestedFormat());
|
QSurfaceFormat platformFormat = QEglFSHooks::hooks()->surfaceFormatFor(window()->requestedFormat());
|
||||||
m_config = QEglFSIntegration::chooseConfig(display, platformFormat);
|
m_config = QEglFSIntegration::chooseConfig(display, platformFormat);
|
||||||
m_format = q_glFormatFromConfig(display, m_config);
|
m_format = q_glFormatFromConfig(display, m_config);
|
||||||
|
|
||||||
resetSurface();
|
resetSurface();
|
||||||
|
|
||||||
|
m_flags |= HasNativeWindow;
|
||||||
|
if (screen()->primarySurface() == EGL_NO_SURFACE) {
|
||||||
|
screen()->setPrimarySurface(m_surface);
|
||||||
|
m_flags |= IsRasterRoot;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void QEglFSWindow::destroy()
|
||||||
|
{
|
||||||
|
if (m_flags.testFlag(HasNativeWindow)) {
|
||||||
|
QEglFSCursor *cursor = static_cast<QEglFSCursor *>(screen()->cursor());
|
||||||
|
if (cursor)
|
||||||
|
cursor->resetResources();
|
||||||
|
if (screen()->primarySurface() == m_surface)
|
||||||
|
screen()->setPrimarySurface(EGL_NO_SURFACE);
|
||||||
|
invalidateSurface();
|
||||||
|
}
|
||||||
|
m_flags = 0;
|
||||||
|
screen()->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()
|
void QEglFSWindow::invalidateSurface()
|
||||||
{
|
{
|
||||||
// Native surface has been deleted behind our backs
|
if (m_surface != EGL_NO_SURFACE) {
|
||||||
has_window = false;
|
EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
|
||||||
if (m_surface != 0) {
|
|
||||||
EGLDisplay display = (static_cast<QEglFSScreen *>(window()->screen()->handle()))->display();
|
|
||||||
eglDestroySurface(display, m_surface);
|
eglDestroySurface(display, m_surface);
|
||||||
m_surface = 0;
|
m_surface = EGL_NO_SURFACE;
|
||||||
}
|
}
|
||||||
|
QEglFSHooks::hooks()->destroyNativeWindow(m_window);
|
||||||
|
m_window = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEglFSWindow::resetSurface()
|
void QEglFSWindow::resetSurface()
|
||||||
{
|
{
|
||||||
EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
|
EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
|
||||||
|
|
||||||
m_window = QEglFSHooks::hooks()->createNativeWindow(this, QEglFSHooks::hooks()->screenSize(), m_format);
|
m_window = QEglFSHooks::hooks()->createNativeWindow(this, QEglFSHooks::hooks()->screenSize(), m_format);
|
||||||
has_window = true;
|
|
||||||
m_surface = eglCreateWindowSurface(display, m_config, m_window, NULL);
|
m_surface = eglCreateWindowSurface(display, m_config, m_window, NULL);
|
||||||
|
|
||||||
if (m_surface == EGL_NO_SURFACE) {
|
if (m_surface == EGL_NO_SURFACE) {
|
||||||
EGLint error = eglGetError();
|
EGLint error = eglGetError();
|
||||||
eglTerminate(display);
|
eglTerminate(display);
|
||||||
qFatal("EGL Error : Could not create the egl surface: error = 0x%x\n", error);
|
qFatal("EGL Error : Could not create the egl surface: error = 0x%x\n", error);
|
||||||
}
|
}
|
||||||
|
|
||||||
screen()->setPrimarySurface(m_surface);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEglFSWindow::destroy()
|
void QEglFSWindow::setVisible(bool visible)
|
||||||
{
|
{
|
||||||
if (m_surface) {
|
QList<QEglFSWindow *> windows = screen()->windows();
|
||||||
EGLDisplay display = static_cast<QEglFSScreen *>(screen())->display();
|
|
||||||
eglDestroySurface(display, m_surface);
|
|
||||||
|
|
||||||
if (!supportsMultipleWindows()) {
|
if (window()->type() != Qt::Desktop) {
|
||||||
// ours must be the primary surface
|
if (visible) {
|
||||||
screen()->setPrimarySurface(0);
|
screen()->addWindow(this);
|
||||||
|
} else {
|
||||||
|
screen()->removeWindow(this);
|
||||||
|
windows = screen()->windows();
|
||||||
|
// try activating the window below
|
||||||
|
if (windows.size())
|
||||||
|
windows.last()->requestActivateWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
m_surface = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (has_window) {
|
// trigger an update
|
||||||
QEglFSHooks::hooks()->destroyNativeWindow(m_window);
|
QEglFSWindow *rootWin = screen()->rootWindow();
|
||||||
has_window = false;
|
if (rootWin) {
|
||||||
|
QWindowSystemInterface::handleExposeEvent(rootWin->window(), rootWin->window()->geometry());
|
||||||
|
QWindowSystemInterface::flushWindowSystemEvents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QPlatformWindow::setVisible(visible);
|
||||||
}
|
}
|
||||||
|
|
||||||
void QEglFSWindow::setGeometry(const QRect &)
|
void QEglFSWindow::setGeometry(const QRect &r)
|
||||||
{
|
{
|
||||||
// We only support full-screen windows
|
QRect rect;
|
||||||
QRect rect(screen()->availableGeometry());
|
if (m_flags.testFlag(HasNativeWindow))
|
||||||
|
rect = screen()->availableGeometry();
|
||||||
|
else
|
||||||
|
rect = r;
|
||||||
|
|
||||||
QPlatformWindow::setGeometry(rect);
|
QPlatformWindow::setGeometry(rect);
|
||||||
QWindowSystemInterface::handleGeometryChange(window(), rect);
|
|
||||||
QWindowSystemInterface::handleExposeEvent(window(), QRegion(rect));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QEglFSWindow::setWindowState(Qt::WindowState)
|
if (rect != r)
|
||||||
{
|
QWindowSystemInterface::handleGeometryChange(window(), rect);
|
||||||
setGeometry(QRect());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
WId QEglFSWindow::winId() const
|
WId QEglFSWindow::winId() const
|
||||||
{
|
{
|
||||||
// Return a fake WId for desktop windows.
|
return m_wid;
|
||||||
if (window()->type() == Qt::Desktop)
|
}
|
||||||
return std::numeric_limits<WId>::max();
|
|
||||||
|
|
||||||
return WId(m_window);
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
QWindowSystemInterface::handleWindowActivated(window());
|
||||||
}
|
}
|
||||||
|
|
||||||
EGLSurface QEglFSWindow::surface() const
|
EGLSurface QEglFSWindow::surface() const
|
||||||
{
|
{
|
||||||
if (!supportsMultipleWindows())
|
return m_surface != EGL_NO_SURFACE ? m_surface : screen()->primarySurface();
|
||||||
return screen()->primarySurface();
|
|
||||||
return m_surface;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QSurfaceFormat QEglFSWindow::format() const
|
QSurfaceFormat QEglFSWindow::format() const
|
||||||
|
@ -49,6 +49,8 @@
|
|||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
class QEglFSBackingStore;
|
||||||
|
|
||||||
class QEglFSWindow : public QPlatformWindow
|
class QEglFSWindow : public QPlatformWindow
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -56,8 +58,9 @@ public:
|
|||||||
~QEglFSWindow();
|
~QEglFSWindow();
|
||||||
|
|
||||||
void setGeometry(const QRect &);
|
void setGeometry(const QRect &);
|
||||||
void setWindowState(Qt::WindowState state);
|
|
||||||
WId winId() const;
|
WId winId() const;
|
||||||
|
void setVisible(bool visible);
|
||||||
|
void requestActivateWindow();
|
||||||
|
|
||||||
EGLSurface surface() const;
|
EGLSurface surface() const;
|
||||||
QSurfaceFormat format() const;
|
QSurfaceFormat format() const;
|
||||||
@ -67,6 +70,12 @@ public:
|
|||||||
void create();
|
void create();
|
||||||
void destroy();
|
void destroy();
|
||||||
|
|
||||||
|
bool hasNativeWindow() const { return m_flags.testFlag(HasNativeWindow); }
|
||||||
|
bool isRasterRoot() const { return m_flags.testFlag(IsRasterRoot); }
|
||||||
|
|
||||||
|
QEglFSBackingStore *backingStore() { return m_backingStore; }
|
||||||
|
void setBackingStore(QEglFSBackingStore *backingStore) { m_backingStore = backingStore; }
|
||||||
|
|
||||||
virtual void invalidateSurface();
|
virtual void invalidateSurface();
|
||||||
virtual void resetSurface();
|
virtual void resetSurface();
|
||||||
|
|
||||||
@ -77,7 +86,19 @@ protected:
|
|||||||
private:
|
private:
|
||||||
EGLConfig m_config;
|
EGLConfig m_config;
|
||||||
QSurfaceFormat m_format;
|
QSurfaceFormat m_format;
|
||||||
bool has_window;
|
WId m_wid;
|
||||||
|
QEglFSBackingStore *m_backingStore;
|
||||||
|
|
||||||
|
enum Flag {
|
||||||
|
Created = 0x01,
|
||||||
|
HasNativeWindow = 0x02,
|
||||||
|
IsRaster = 0x04,
|
||||||
|
IsRasterRoot = 0x08
|
||||||
|
};
|
||||||
|
Q_DECLARE_FLAGS(Flags, Flag);
|
||||||
|
Flags m_flags;
|
||||||
};
|
};
|
||||||
|
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
#endif // QEGLFSWINDOW_H
|
#endif // QEGLFSWINDOW_H
|
||||||
|
Loading…
Reference in New Issue
Block a user