QOpenGLWidget and new-style compositing on eglfs

Integrate with QOpenGLTextureBlitter, QOpenGLWidget and friends.

Change-Id: Ic2867b713a21a3d2820d546174fc9164b3dd220c
Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Reviewed-by: Gunnar Sletta <gunnar.sletta@jollamobile.com>
Reviewed-by: Paul Olav Tvete <paul.tvete@digia.com>
This commit is contained in:
Laszlo Agocs 2014-02-11 14:59:30 +01:00 committed by The Qt Project
parent 5b422304a9
commit ff11af4fbc
19 changed files with 273 additions and 173 deletions

View File

@ -156,6 +156,12 @@ void QPlatformTextureList::appendTexture(GLuint textureId, const QRect &geometry
bi.rect = geometry; bi.rect = geometry;
d->textures.append(bi); d->textures.append(bi);
} }
void QPlatformTextureList::clear()
{
Q_D(QPlatformTextureList);
d->textures.clear();
}
#endif // QT_NO_OPENGL #endif // QT_NO_OPENGL
/*! /*!

View File

@ -81,12 +81,14 @@ public:
~QPlatformTextureList(); ~QPlatformTextureList();
int count() const; int count() const;
bool isEmpty() const { return count() == 0; }
GLuint textureId(int index) const; GLuint textureId(int index) const;
QRect geometry(int index) const; QRect geometry(int index) const;
void lock(bool on); void lock(bool on);
bool isLocked() const; bool isLocked() const;
void appendTexture(GLuint textureId, const QRect &geometry); void appendTexture(GLuint textureId, const QRect &geometry);
void clear();
Q_SIGNALS: Q_SIGNALS:
void locked(bool); void locked(bool);

View File

@ -42,6 +42,8 @@
#include <QtGui/QOpenGLContext> #include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLShaderProgram> #include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLFramebufferObject> #include <QtGui/QOpenGLFramebufferObject>
#include <QtGui/private/qopengltextureblitter_p.h>
#include <qpa/qplatformbackingstore.h>
#include "qeglcompositor_p.h" #include "qeglcompositor_p.h"
#include "qeglplatformwindow_p.h" #include "qeglplatformwindow_p.h"
@ -54,7 +56,7 @@ static QEGLCompositor *compositor = 0;
QEGLCompositor::QEGLCompositor() QEGLCompositor::QEGLCompositor()
: m_context(0), : m_context(0),
m_window(0), m_window(0),
m_program(0) m_blitter(0)
{ {
Q_ASSERT(!compositor); Q_ASSERT(!compositor);
m_updateTimer.setSingleShot(true); m_updateTimer.setSingleShot(true);
@ -65,7 +67,10 @@ QEGLCompositor::QEGLCompositor()
QEGLCompositor::~QEGLCompositor() QEGLCompositor::~QEGLCompositor()
{ {
Q_ASSERT(compositor == this); Q_ASSERT(compositor == this);
delete m_program; if (m_blitter) {
m_blitter->destroy();
delete m_blitter;
}
compositor = 0; compositor = 0;
} }
@ -81,102 +86,53 @@ void QEGLCompositor::renderAll()
{ {
Q_ASSERT(m_context && m_window); Q_ASSERT(m_context && m_window);
m_context->makeCurrent(m_window->window()); m_context->makeCurrent(m_window->window());
ensureProgram();
m_program->bind(); if (!m_blitter) {
m_blitter = new QOpenGLTextureBlitter;
m_blitter->create();
}
m_blitter->bind();
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen()); QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
QList<QEGLPlatformWindow *> windows = screen->windows(); QList<QEGLPlatformWindow *> windows = screen->windows();
for (int i = 0; i < windows.size(); ++i) { for (int i = 0; i < windows.size(); ++i)
QEGLPlatformWindow *window = windows.at(i); render(windows.at(i));
uint texture = window->texture();
if (texture)
render(window, texture, window->isRaster());
}
m_program->release(); m_blitter->release();
m_context->swapBuffers(m_window->window()); m_context->swapBuffers(m_window->window());
for (int i = 0; i < windows.size(); ++i)
windows.at(i)->composited();
} }
void QEGLCompositor::ensureProgram() void QEGLCompositor::render(QEGLPlatformWindow *window)
{ {
if (!m_program) { const QPlatformTextureList *textures = window->textures();
static const char *textureVertexProgram = if (!textures)
"attribute highp vec2 vertexCoordEntry;\n" return;
"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 = const QRect targetWindowRect(QPoint(0, 0), window->screen()->geometry().size());
"uniform sampler2D texture;\n" glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height());
"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; for (int i = 0; i < textures->count(); ++i) {
uint textureId = textures->textureId(i);
glBindTexture(GL_TEXTURE_2D, textureId);
QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(textures->geometry(i),
targetWindowRect,
QOpenGLTextureBlitter::OriginTopLeft);
m_blitter->setSwizzleRB(window->isRaster());
m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram); if (textures->count() > 1 && i == textures->count() - 1) {
m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram); glEnable(GL_BLEND);
m_program->link(); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
m_vertexCoordEntry = m_program->attributeLocation("vertexCoordEntry"); glDisable(GL_BLEND);
m_textureCoordEntry = m_program->attributeLocation("textureCoordEntry"); } else if (textures->count() == 1) {
m_isRasterEntry = m_program->uniformLocation("isRaster"); m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
} else {
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginBottomLeft);
} }
} }
void QEGLCompositor::render(QEGLPlatformWindow *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();
// Map to [-1,1]
GLfloat x1 = (tl.x() / sr.width()) * 2 - 1;
GLfloat y1 = ((sr.height() - tl.y()) / sr.height()) * 2 - 1;
GLfloat x2 = ((br.x() + 1) / sr.width()) * 2 - 1;
GLfloat y2 = ((sr.height() - (br.y() + 1)) / 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());
m_program->enableAttributeArray(m_vertexCoordEntry);
m_program->enableAttributeArray(m_textureCoordEntry);
m_program->setAttributeArray(m_vertexCoordEntry, vertexCoordinates, 2);
m_program->setAttributeArray(m_textureCoordEntry, textureCoordinates, 2);
glBindTexture(GL_TEXTURE_2D, texture);
m_program->setUniformValue(m_isRasterEntry, raster);
glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
glBindTexture(GL_TEXTURE_2D, 0);
m_program->enableAttributeArray(m_textureCoordEntry);
m_program->enableAttributeArray(m_vertexCoordEntry);
} }
QEGLCompositor *QEGLCompositor::instance() QEGLCompositor *QEGLCompositor::instance()

View File

@ -46,8 +46,8 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QOpenGLShaderProgram;
class QOpenGLContext; class QOpenGLContext;
class QOpenGLTextureBlitter;
class QEGLPlatformWindow; class QEGLPlatformWindow;
class QEGLCompositor : public QObject class QEGLCompositor : public QObject
@ -67,16 +67,12 @@ private:
QEGLCompositor(); QEGLCompositor();
~QEGLCompositor(); ~QEGLCompositor();
void render(QEGLPlatformWindow *window, uint texture, bool raster); void render(QEGLPlatformWindow *window);
void ensureProgram();
QOpenGLContext *m_context; QOpenGLContext *m_context;
QEGLPlatformWindow *m_window; QEGLPlatformWindow *m_window;
QTimer m_updateTimer; QTimer m_updateTimer;
QOpenGLShaderProgram *m_program; QOpenGLTextureBlitter *m_blitter;
int m_vertexCoordEntry;
int m_textureCoordEntry;
int m_isRasterEntry;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -76,11 +76,18 @@ QT_BEGIN_NAMESPACE
QEGLPlatformBackingStore::QEGLPlatformBackingStore(QWindow *window) QEGLPlatformBackingStore::QEGLPlatformBackingStore(QWindow *window)
: QPlatformBackingStore(window), : QPlatformBackingStore(window),
m_window(static_cast<QEGLPlatformWindow *>(window->handle())), m_window(static_cast<QEGLPlatformWindow *>(window->handle())),
m_texture(0) m_bsTexture(0),
m_textures(new QPlatformTextureList),
m_lockedWidgetTextures(0)
{ {
m_window->setBackingStore(this); m_window->setBackingStore(this);
} }
QEGLPlatformBackingStore::~QEGLPlatformBackingStore()
{
delete m_textures;
}
QPaintDevice *QEGLPlatformBackingStore::paintDevice() QPaintDevice *QEGLPlatformBackingStore::paintDevice()
{ {
return &m_image; return &m_image;
@ -88,7 +95,18 @@ QPaintDevice *QEGLPlatformBackingStore::paintDevice()
void QEGLPlatformBackingStore::updateTexture() void QEGLPlatformBackingStore::updateTexture()
{ {
glBindTexture(GL_TEXTURE_2D, m_texture); if (!m_bsTexture) {
glGenTextures(1, &m_bsTexture);
glBindTexture(GL_TEXTURE_2D, m_bsTexture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
// QOpenGLTextureBlitter requires GL_REPEAT for the time being
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
} else {
glBindTexture(GL_TEXTURE_2D, m_bsTexture);
}
if (!m_dirty.isNull()) { if (!m_dirty.isNull()) {
QRegion fixed; QRegion fixed;
@ -126,24 +144,56 @@ void QEGLPlatformBackingStore::updateTexture()
void QEGLPlatformBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset) void QEGLPlatformBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
{ {
Q_UNUSED(window); // Called for ordinary raster windows. This is rare since RasterGLSurface
// support is claimed which leads to having all QWidget windows marked as
// RasterGLSurface instead of just Raster. These go through
// compositeAndFlush() instead of this function.
Q_UNUSED(region); Q_UNUSED(region);
Q_UNUSED(offset); Q_UNUSED(offset);
#ifdef QEGL_EXTRA_DEBUG
qWarning("QEglBackingStore::flush %p", window);
#endif
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen()); QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
QEGLPlatformWindow *dstWin = screen->compositingWindow(); QEGLPlatformWindow *dstWin = screen->compositingWindow();
if (!dstWin || !dstWin->isRaster()) if (!dstWin || !dstWin->isRaster())
return; return;
m_window->create(); screen->compositingContext()->makeCurrent(dstWin->window());
QOpenGLContext *context = screen->compositingContext();
context->makeCurrent(dstWin->window());
updateTexture(); updateTexture();
composite(context, dstWin); m_textures->clear();
m_textures->appendTexture(m_bsTexture, window->geometry());
composite(screen->compositingContext(), dstWin);
}
void QEGLPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
QPlatformTextureList *textures, QOpenGLContext *context)
{
// QOpenGLWidget content provided as textures. The raster content should go on top.
Q_UNUSED(region);
Q_UNUSED(offset);
Q_UNUSED(context);
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
QEGLPlatformWindow *dstWin = screen->compositingWindow();
if (!dstWin || !dstWin->isRaster())
return;
screen->compositingContext()->makeCurrent(dstWin->window());
m_textures->clear();
for (int i = 0; i < textures->count(); ++i) {
uint textureId = textures->textureId(i);
QRect geom = textures->geometry(i);
m_textures->appendTexture(textureId, geom);
}
updateTexture();
m_textures->appendTexture(m_bsTexture, window->geometry());
textures->lock(true);
m_lockedWidgetTextures = textures;
composite(screen->compositingContext(), dstWin);
} }
void QEGLPlatformBackingStore::composite(QOpenGLContext *context, QEGLPlatformWindow *window) void QEGLPlatformBackingStore::composite(QOpenGLContext *context, QEGLPlatformWindow *window)
@ -151,6 +201,15 @@ void QEGLPlatformBackingStore::composite(QOpenGLContext *context, QEGLPlatformWi
QEGLCompositor::instance()->schedule(context, window); QEGLCompositor::instance()->schedule(context, window);
} }
void QEGLPlatformBackingStore::composited()
{
if (m_lockedWidgetTextures) {
QPlatformTextureList *textureList = m_lockedWidgetTextures;
m_lockedWidgetTextures = 0; // may reenter so null before unlocking
textureList->lock(false);
}
}
void QEGLPlatformBackingStore::beginPaint(const QRegion &rgn) void QEGLPlatformBackingStore::beginPaint(const QRegion &rgn)
{ {
m_dirty |= rgn; m_dirty |= rgn;
@ -162,25 +221,22 @@ void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticCo
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen()); QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
QEGLPlatformWindow *dstWin = screen->compositingWindow(); QEGLPlatformWindow *dstWin = screen->compositingWindow();
if (!dstWin || !dstWin->isRaster()) if (!dstWin || (!dstWin->isRaster() && dstWin->window()->surfaceType() != QSurface::RasterGLSurface))
return; return;
m_image = QImage(size, QImage::Format_RGB32); m_image = QImage(size, QImage::Format_RGB32);
m_window->create(); m_window->create();
screen->compositingContext()->makeCurrent(dstWin->window()); screen->compositingContext()->makeCurrent(dstWin->window());
if (m_bsTexture) {
glDeleteTextures(1, &m_bsTexture);
m_bsTexture = 0;
}
}
if (m_texture) QImage QEGLPlatformBackingStore::toImage() const
glDeleteTextures(1, &m_texture); {
return m_image;
glGenTextures(1, &m_texture);
glBindTexture(GL_TEXTURE_2D, m_texture);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
} }
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -50,31 +50,41 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QOpenGLContext; class QOpenGLContext;
class QPlatformTextureList;
class QEGLPlatformWindow; class QEGLPlatformWindow;
class QEGLPlatformBackingStore : public QPlatformBackingStore class QEGLPlatformBackingStore : public QPlatformBackingStore
{ {
public: public:
QEGLPlatformBackingStore(QWindow *window); QEGLPlatformBackingStore(QWindow *window);
~QEGLPlatformBackingStore();
QPaintDevice *paintDevice(); QPaintDevice *paintDevice() Q_DECL_OVERRIDE;
void beginPaint(const QRegion &); void beginPaint(const QRegion &) Q_DECL_OVERRIDE;
void flush(QWindow *window, const QRegion &region, const QPoint &offset); void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
void resize(const QSize &size, const QRegion &staticContents); void resize(const QSize &size, const QRegion &staticContents) Q_DECL_OVERRIDE;
uint texture() const { return m_texture; } QImage toImage() const Q_DECL_OVERRIDE;
void composeAndFlush(QWindow *window, const QRegion &region, const QPoint &offset,
QPlatformTextureList *textures, QOpenGLContext *context) Q_DECL_OVERRIDE;
const QPlatformTextureList *textures() const { return m_textures; }
virtual void composite(QOpenGLContext *context, QEGLPlatformWindow *window); virtual void composite(QOpenGLContext *context, QEGLPlatformWindow *window);
void composited();
private: private:
void updateTexture(); void updateTexture();
QEGLPlatformWindow *m_window; QEGLPlatformWindow *m_window;
QImage m_image; QImage m_image;
uint m_texture;
QRegion m_dirty; QRegion m_dirty;
uint m_bsTexture;
QPlatformTextureList *m_textures;
QPlatformTextureList *m_lockedWidgetTextures;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -127,11 +127,8 @@ void QEGLPlatformContext::init(const QSurfaceFormat &format, QPlatformOpenGLCont
bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface) bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface)
{ {
Q_ASSERT(surface->surface()->surfaceType() == QSurface::OpenGLSurface); Q_ASSERT(surface->surface()->supportsOpenGL());
#ifdef QEGL_EXTRA_DEBUG
qWarning("QEglContext::makeCurrent: %p\n",this);
#endif
bindApi(m_format); bindApi(m_format);
EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface); EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
@ -192,9 +189,6 @@ bool QEGLPlatformContext::makeCurrent(QPlatformSurface *surface)
QEGLPlatformContext::~QEGLPlatformContext() QEGLPlatformContext::~QEGLPlatformContext()
{ {
#ifdef QEGL_EXTRA_DEBUG
qWarning("QEglContext::~QEglContext(): %p\n",this);
#endif
if (m_eglContext != EGL_NO_CONTEXT) { if (m_eglContext != EGL_NO_CONTEXT) {
eglDestroyContext(m_eglDisplay, m_eglContext); eglDestroyContext(m_eglDisplay, m_eglContext);
m_eglContext = EGL_NO_CONTEXT; m_eglContext = EGL_NO_CONTEXT;
@ -203,9 +197,6 @@ QEGLPlatformContext::~QEGLPlatformContext()
void QEGLPlatformContext::doneCurrent() void QEGLPlatformContext::doneCurrent()
{ {
#ifdef QEGL_EXTRA_DEBUG
qWarning("QEglContext::doneCurrent:%p\n",this);
#endif
bindApi(m_format); bindApi(m_format);
bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); bool ok = eglMakeCurrent(m_eglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (!ok) if (!ok)
@ -214,9 +205,6 @@ void QEGLPlatformContext::doneCurrent()
void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface) void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface)
{ {
#ifdef QEGL_EXTRA_DEBUG
qWarning("QEglContext::swapBuffers:%p\n",this);
#endif
bindApi(m_format); bindApi(m_format);
EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface); EGLSurface eglSurface = eglSurfaceForPlatformSurface(surface);
bool ok = eglSwapBuffers(m_eglDisplay, eglSurface); bool ok = eglSwapBuffers(m_eglDisplay, eglSurface);
@ -226,9 +214,6 @@ void QEGLPlatformContext::swapBuffers(QPlatformSurface *surface)
void (*QEGLPlatformContext::getProcAddress(const QByteArray &procName)) () void (*QEGLPlatformContext::getProcAddress(const QByteArray &procName)) ()
{ {
#ifdef QEGL_EXTRA_DEBUG
qWarning("QEglContext::getProcAddress%p\n",this);
#endif
bindApi(m_format); bindApi(m_format);
return eglGetProcAddress(procName.constData()); return eglGetProcAddress(procName.constData());
} }

View File

@ -41,6 +41,7 @@
#include <QtGui/QWindow> #include <QtGui/QWindow>
#include <QtGui/QOpenGLContext> #include <QtGui/QOpenGLContext>
#include <QtGui/QOffscreenSurface>
#include <QtGui/QGuiApplication> #include <QtGui/QGuiApplication>
#include <qpa/qwindowsysteminterface.h> #include <qpa/qwindowsysteminterface.h>
#include <qpa/qplatforminputcontextfactory_p.h> #include <qpa/qplatforminputcontextfactory_p.h>
@ -79,8 +80,7 @@ QT_BEGIN_NAMESPACE
The backing store, native interface accessors, font database, The backing store, native interface accessors, font database,
basic capability flags, etc. are provided out of the box, no basic capability flags, etc. are provided out of the box, no
further customization is needed. Subclasses are still responsible further customization is needed.
however for context and offscreen surface creation.
\note It is critical that this class' implementation of \note It is critical that this class' implementation of
initialize() is called. Therefore subclasses should either avoid initialize() is called. Therefore subclasses should either avoid
@ -155,6 +155,23 @@ QPlatformWindow *QEGLPlatformIntegration::createPlatformWindow(QWindow *window)
return w; return w;
} }
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;
return createContext(context->format(),
compositingContext ? compositingContext->handle() : context->shareHandle(),
display());
}
QPlatformOffscreenSurface *QEGLPlatformIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
{
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(surface->screen()->handle());
return createOffscreenSurface(screen->display(), surface->requestedFormat(), surface);
}
bool QEGLPlatformIntegration::hasCapability(QPlatformIntegration::Capability cap) const bool QEGLPlatformIntegration::hasCapability(QPlatformIntegration::Capability cap) const
{ {
switch (cap) { switch (cap) {
@ -162,6 +179,7 @@ bool QEGLPlatformIntegration::hasCapability(QPlatformIntegration::Capability cap
case OpenGL: return true; case OpenGL: return true;
case ThreadedOpenGL: return true; case ThreadedOpenGL: return true;
case WindowManagement: return false; case WindowManagement: return false;
case RasterGLSurface: return true;
default: return QPlatformIntegration::hasCapability(cap); default: return QPlatformIntegration::hasCapability(cap);
} }
} }

View File

@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE
class QEGLPlatformScreen; class QEGLPlatformScreen;
class QEGLPlatformWindow; class QEGLPlatformWindow;
class QEGLPlatformContext;
class QFbVtHandler; class QFbVtHandler;
class QEGLPlatformIntegration : public QPlatformIntegration, public QPlatformNativeInterface class QEGLPlatformIntegration : public QPlatformIntegration, public QPlatformNativeInterface
@ -70,6 +71,8 @@ public:
QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE;
QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE; QPlatformBackingStore *createPlatformBackingStore(QWindow *window) const Q_DECL_OVERRIDE;
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
@ -83,6 +86,13 @@ public:
protected: protected:
virtual QEGLPlatformScreen *createScreen() const = 0; virtual QEGLPlatformScreen *createScreen() const = 0;
virtual QEGLPlatformWindow *createWindow(QWindow *window) const = 0; virtual QEGLPlatformWindow *createWindow(QWindow *window) const = 0;
virtual QEGLPlatformContext *createContext(const QSurfaceFormat &format,
QPlatformOpenGLContext *shareContext,
EGLDisplay display) const = 0;
virtual QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display,
const QSurfaceFormat &format,
QOffscreenSurface *surface) const = 0;
virtual EGLNativeDisplayType nativeDisplay() const { return EGL_DEFAULT_DISPLAY; } virtual EGLNativeDisplayType nativeDisplay() const { return EGL_DEFAULT_DISPLAY; }
void createInputHandlers(); void createInputHandlers();

View File

@ -92,6 +92,7 @@ void QEGLPlatformWindow::create()
// Save the original surface type before changing to OpenGLSurface. // Save the original surface type before changing to OpenGLSurface.
m_raster = (window()->surfaceType() == QSurface::RasterSurface); m_raster = (window()->surfaceType() == QSurface::RasterSurface);
if (m_raster) // change to OpenGL, but not for RasterGLSurface
window()->setSurfaceType(QSurface::OpenGLSurface); window()->setSurfaceType(QSurface::OpenGLSurface);
if (window()->type() == Qt::Desktop) { if (window()->type() == Qt::Desktop) {
@ -102,14 +103,25 @@ void QEGLPlatformWindow::create()
} }
} }
uint QEGLPlatformWindow::texture() const bool QEGLPlatformWindow::isRaster() const
{
return m_raster || window()->surfaceType() == QSurface::RasterGLSurface;
}
const QPlatformTextureList *QEGLPlatformWindow::textures() const
{ {
if (m_backingStore) if (m_backingStore)
return m_backingStore->texture(); return m_backingStore->textures();
return 0; return 0;
} }
void QEGLPlatformWindow::composited()
{
if (m_backingStore)
m_backingStore->composited();
}
WId QEGLPlatformWindow::winId() const WId QEGLPlatformWindow::winId() const
{ {
return m_winId; return m_winId;

View File

@ -48,6 +48,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QEGLPlatformBackingStore; class QEGLPlatformBackingStore;
class QPlatformTextureList;
class QEGLPlatformWindow : public QPlatformWindow class QEGLPlatformWindow : public QPlatformWindow
{ {
@ -58,8 +59,9 @@ public:
QEGLPlatformBackingStore *backingStore() { return m_backingStore; } QEGLPlatformBackingStore *backingStore() { return m_backingStore; }
void setBackingStore(QEGLPlatformBackingStore *backingStore) { m_backingStore = backingStore; } void setBackingStore(QEGLPlatformBackingStore *backingStore) { m_backingStore = backingStore; }
uint texture() const; const QPlatformTextureList *textures() const;
bool isRaster() const { return m_raster; } void composited();
bool isRaster() const;
WId winId() const Q_DECL_OVERRIDE; WId winId() const Q_DECL_OVERRIDE;

View File

@ -1,7 +1,5 @@
QT += core-private gui-private platformsupport-private QT += core-private gui-private platformsupport-private
#DEFINES += QEGL_EXTRA_DEBUG
# Avoid X11 header collision # Avoid X11 header collision
DEFINES += MESA_EGL_NO_X11_HEADERS DEFINES += MESA_EGL_NO_X11_HEADERS

View File

@ -88,17 +88,6 @@ bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
return QEGLPlatformIntegration::hasCapability(cap); return QEGLPlatformIntegration::hasCapability(cap);
} }
QPlatformOpenGLContext *QEglFSIntegration::createPlatformOpenGLContext(QOpenGLContext *context) const
{
return new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(context->format()), context->shareHandle(), display());
}
QPlatformOffscreenSurface *QEglFSIntegration::createPlatformOffscreenSurface(QOffscreenSurface *surface) const
{
QEglFSScreen *screen = static_cast<QEglFSScreen *>(surface->screen()->handle());
return new QEGLPbuffer(screen->display(), QEglFSHooks::hooks()->surfaceFormatFor(surface->requestedFormat()), surface);
}
void QEglFSIntegration::initialize() void QEglFSIntegration::initialize()
{ {
QEglFSHooks::hooks()->platformInit(); QEglFSHooks::hooks()->platformInit();
@ -124,6 +113,20 @@ QEGLPlatformWindow *QEglFSIntegration::createWindow(QWindow *window) const
return new QEglFSWindow(window); return new QEglFSWindow(window);
} }
QEGLPlatformContext *QEglFSIntegration::createContext(const QSurfaceFormat &format,
QPlatformOpenGLContext *shareContext,
EGLDisplay display) const
{
return new QEglFSContext(QEglFSHooks::hooks()->surfaceFormatFor(format), shareContext, display);
}
QPlatformOffscreenSurface *QEglFSIntegration::createOffscreenSurface(EGLDisplay display,
const QSurfaceFormat &format,
QOffscreenSurface *surface) const
{
return new QEGLPbuffer(display, QEglFSHooks::hooks()->surfaceFormatFor(format), surface);
}
QVariant QEglFSIntegration::styleHint(QPlatformIntegration::StyleHint hint) const QVariant QEglFSIntegration::styleHint(QPlatformIntegration::StyleHint hint) const
{ {
switch (hint) switch (hint)

View File

@ -54,9 +54,6 @@ public:
QEglFSIntegration(); QEglFSIntegration();
~QEglFSIntegration(); ~QEglFSIntegration();
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
void initialize() Q_DECL_OVERRIDE; void initialize() Q_DECL_OVERRIDE;
bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
@ -67,6 +64,12 @@ public:
protected: protected:
QEGLPlatformScreen *createScreen() const Q_DECL_OVERRIDE; QEGLPlatformScreen *createScreen() const Q_DECL_OVERRIDE;
QEGLPlatformWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE; QEGLPlatformWindow *createWindow(QWindow *window) const Q_DECL_OVERRIDE;
QEGLPlatformContext *createContext(const QSurfaceFormat &format,
QPlatformOpenGLContext *shareContext,
EGLDisplay display) const Q_DECL_OVERRIDE;
QPlatformOffscreenSurface *createOffscreenSurface(EGLDisplay display,
const QSurfaceFormat &format,
QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
EGLNativeDisplayType nativeDisplay() const Q_DECL_OVERRIDE; EGLNativeDisplayType nativeDisplay() const Q_DECL_OVERRIDE;
private: private:

View File

@ -53,10 +53,6 @@ QEglFSScreen::QEglFSScreen(EGLDisplay dpy)
m_rootWindow(0), m_rootWindow(0),
m_rootContext(0) m_rootContext(0)
{ {
#ifdef QEGL_EXTRA_DEBUG
qWarning("QEglScreen %p\n", this);
#endif
m_cursor = QEglFSHooks::hooks()->createCursor(this); m_cursor = QEglFSHooks::hooks()->createCursor(this);
} }

View File

@ -58,9 +58,6 @@ QEglFSWindow::QEglFSWindow(QWindow *w)
, m_window(0) , m_window(0)
, m_flags(0) , m_flags(0)
{ {
#ifdef QEGL_EXTRA_DEBUG
qWarning("QEglWindow %p: %p 0x%x\n", this, w, uint(m_window));
#endif
} }
QEglFSWindow::~QEglFSWindow() QEglFSWindow::~QEglFSWindow()
@ -114,7 +111,8 @@ void QEglFSWindow::create()
QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance()); QOpenGLContext *context = new QOpenGLContext(QGuiApplication::instance());
context->setFormat(window()->requestedFormat()); context->setFormat(window()->requestedFormat());
context->setScreen(window()->screen()); context->setScreen(window()->screen());
context->create(); if (!context->create())
qFatal("EGLFS: Failed to create compositing context");
screen->setRootContext(context); screen->setRootContext(context);
screen->setRootWindow(this); screen->setRootWindow(this);
} }

View File

@ -736,7 +736,8 @@ QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
dirtyOnScreenWidgets(0), dirtyOnScreenWidgets(0),
widgetTextures(0), widgetTextures(0),
fullUpdatePending(0), fullUpdatePending(0),
updateRequestSent(0) updateRequestSent(0),
textureListWatcher(0)
{ {
store = tlw->backingStore(); store = tlw->backingStore();
Q_ASSERT(store); Q_ASSERT(store);
@ -962,6 +963,25 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo
} }
#endif #endif
QPlatformTextureListWatcher::QPlatformTextureListWatcher(QWidgetBackingStore *backingStore)
: m_locked(false),
m_backingStore(backingStore)
{
}
void QPlatformTextureListWatcher::watch(QPlatformTextureList *textureList)
{
connect(textureList, SIGNAL(locked(bool)), SLOT(onLockStatusChanged(bool)));
m_locked = textureList->isLocked();
}
void QPlatformTextureListWatcher::onLockStatusChanged(bool locked)
{
m_locked = locked;
if (!locked)
m_backingStore->sync();
}
/*! /*!
Synchronizes the backing store, i.e. dirty areas are repainted and flushed. Synchronizes the backing store, i.e. dirty areas are repainted and flushed.
*/ */
@ -985,6 +1005,17 @@ void QWidgetBackingStore::sync()
return; return;
} }
if (textureListWatcher && !textureListWatcher->isLocked()) {
textureListWatcher->deleteLater();
textureListWatcher = 0;
} else if (widgetTextures && widgetTextures->isLocked()) {
if (!textureListWatcher)
textureListWatcher = new QPlatformTextureListWatcher(this);
if (!textureListWatcher->isLocked())
textureListWatcher->watch(widgetTextures);
return;
}
doSync(); doSync();
} }
@ -1077,7 +1108,7 @@ void QWidgetBackingStore::doSync()
delete widgetTextures; delete widgetTextures;
widgetTextures = 0; widgetTextures = 0;
if (tlw->d_func()->textureChildSeen) { if (tlw->d_func()->textureChildSeen) {
widgetTextures = new QPlatformTextureList; // TODO: implement support for locking widgetTextures = new QPlatformTextureList;
findTextureWidgetsRecursively(tlw, tlw, widgetTextures); findTextureWidgetsRecursively(tlw, tlw, widgetTextures);
} }
fullUpdatePending = false; fullUpdatePending = false;

View File

@ -61,6 +61,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QPlatformTextureList; class QPlatformTextureList;
class QWidgetBackingStore;
struct BeginPaintInfo { struct BeginPaintInfo {
inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), backingStoreRecreated(0) {} inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), backingStoreRecreated(0) {}
@ -69,6 +70,23 @@ struct BeginPaintInfo {
uint backingStoreRecreated : 1; uint backingStoreRecreated : 1;
}; };
class QPlatformTextureListWatcher : public QObject
{
Q_OBJECT
public:
QPlatformTextureListWatcher(QWidgetBackingStore *backingStore);
void watch(QPlatformTextureList *textureList);
bool isLocked() const { return m_locked; }
private slots:
void onLockStatusChanged(bool locked);
private:
bool m_locked;
QWidgetBackingStore *m_backingStore;
};
class Q_AUTOTEST_EXPORT QWidgetBackingStore class Q_AUTOTEST_EXPORT QWidgetBackingStore
{ {
public: public:
@ -111,6 +129,8 @@ private:
QPoint tlwOffset; QPoint tlwOffset;
QPlatformTextureListWatcher *textureListWatcher;
void sendUpdateRequest(QWidget *widget, bool updateImmediately); void sendUpdateRequest(QWidget *widget, bool updateImmediately);
static bool flushPaint(QWidget *widget, const QRegion &rgn); static bool flushPaint(QWidget *widget, const QRegion &rgn);

View File

@ -58,8 +58,6 @@
#include <QtCore/qmath.h> #include <QtCore/qmath.h>
#include <qopengl.h> #include <qopengl.h>
#include <GL/glext.h>
class OpenGLWidgetPrivate class OpenGLWidgetPrivate
{ {
public: public: