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;
d->textures.append(bi);
}
void QPlatformTextureList::clear()
{
Q_D(QPlatformTextureList);
d->textures.clear();
}
#endif // QT_NO_OPENGL
/*!

View File

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

View File

@ -42,6 +42,8 @@
#include <QtGui/QOpenGLContext>
#include <QtGui/QOpenGLShaderProgram>
#include <QtGui/QOpenGLFramebufferObject>
#include <QtGui/private/qopengltextureblitter_p.h>
#include <qpa/qplatformbackingstore.h>
#include "qeglcompositor_p.h"
#include "qeglplatformwindow_p.h"
@ -54,7 +56,7 @@ static QEGLCompositor *compositor = 0;
QEGLCompositor::QEGLCompositor()
: m_context(0),
m_window(0),
m_program(0)
m_blitter(0)
{
Q_ASSERT(!compositor);
m_updateTimer.setSingleShot(true);
@ -65,7 +67,10 @@ QEGLCompositor::QEGLCompositor()
QEGLCompositor::~QEGLCompositor()
{
Q_ASSERT(compositor == this);
delete m_program;
if (m_blitter) {
m_blitter->destroy();
delete m_blitter;
}
compositor = 0;
}
@ -81,104 +86,55 @@ void QEGLCompositor::renderAll()
{
Q_ASSERT(m_context && m_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());
QList<QEGLPlatformWindow *> windows = screen->windows();
for (int i = 0; i < windows.size(); ++i) {
QEGLPlatformWindow *window = windows.at(i);
uint texture = window->texture();
if (texture)
render(window, texture, window->isRaster());
}
for (int i = 0; i < windows.size(); ++i)
render(windows.at(i));
m_program->release();
m_blitter->release();
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) {
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";
const QPlatformTextureList *textures = window->textures();
if (!textures)
return;
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";
const QRect targetWindowRect(QPoint(0, 0), window->screen()->geometry().size());
glViewport(0, 0, targetWindowRect.width(), targetWindowRect.height());
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);
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");
if (textures->count() > 1 && i == textures->count() - 1) {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
m_blitter->blit(textureId, target, QOpenGLTextureBlitter::OriginTopLeft);
glDisable(GL_BLEND);
} else if (textures->count() == 1) {
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()
{
if (!compositor)

View File

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

View File

@ -76,11 +76,18 @@ QT_BEGIN_NAMESPACE
QEGLPlatformBackingStore::QEGLPlatformBackingStore(QWindow *window)
: QPlatformBackingStore(window),
m_window(static_cast<QEGLPlatformWindow *>(window->handle())),
m_texture(0)
m_bsTexture(0),
m_textures(new QPlatformTextureList),
m_lockedWidgetTextures(0)
{
m_window->setBackingStore(this);
}
QEGLPlatformBackingStore::~QEGLPlatformBackingStore()
{
delete m_textures;
}
QPaintDevice *QEGLPlatformBackingStore::paintDevice()
{
return &m_image;
@ -88,7 +95,18 @@ QPaintDevice *QEGLPlatformBackingStore::paintDevice()
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()) {
QRegion fixed;
@ -126,24 +144,56 @@ void QEGLPlatformBackingStore::updateTexture()
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(offset);
#ifdef QEGL_EXTRA_DEBUG
qWarning("QEglBackingStore::flush %p", window);
#endif
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
QEGLPlatformWindow *dstWin = screen->compositingWindow();
if (!dstWin || !dstWin->isRaster())
return;
m_window->create();
QOpenGLContext *context = screen->compositingContext();
context->makeCurrent(dstWin->window());
screen->compositingContext()->makeCurrent(dstWin->window());
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)
@ -151,6 +201,15 @@ void QEGLPlatformBackingStore::composite(QOpenGLContext *context, QEGLPlatformWi
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)
{
m_dirty |= rgn;
@ -162,25 +221,22 @@ void QEGLPlatformBackingStore::resize(const QSize &size, const QRegion &staticCo
QEGLPlatformScreen *screen = static_cast<QEGLPlatformScreen *>(m_window->screen());
QEGLPlatformWindow *dstWin = screen->compositingWindow();
if (!dstWin || !dstWin->isRaster())
if (!dstWin || (!dstWin->isRaster() && dstWin->window()->surfaceType() != QSurface::RasterGLSurface))
return;
m_image = QImage(size, QImage::Format_RGB32);
m_window->create();
screen->compositingContext()->makeCurrent(dstWin->window());
if (m_bsTexture) {
glDeleteTextures(1, &m_bsTexture);
m_bsTexture = 0;
}
}
if (m_texture)
glDeleteTextures(1, &m_texture);
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);
QImage QEGLPlatformBackingStore::toImage() const
{
return m_image;
}
QT_END_NAMESPACE

View File

@ -50,31 +50,41 @@
QT_BEGIN_NAMESPACE
class QOpenGLContext;
class QPlatformTextureList;
class QEGLPlatformWindow;
class QEGLPlatformBackingStore : public QPlatformBackingStore
{
public:
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 resize(const QSize &size, const QRegion &staticContents);
void flush(QWindow *window, const QRegion &region, const QPoint &offset) Q_DECL_OVERRIDE;
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);
void composited();
private:
void updateTexture();
QEGLPlatformWindow *m_window;
QImage m_image;
uint m_texture;
QRegion m_dirty;
uint m_bsTexture;
QPlatformTextureList *m_textures;
QPlatformTextureList *m_lockedWidgetTextures;
};
QT_END_NAMESPACE

View File

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

View File

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

View File

@ -50,6 +50,7 @@ QT_BEGIN_NAMESPACE
class QEGLPlatformScreen;
class QEGLPlatformWindow;
class QEGLPlatformContext;
class QFbVtHandler;
class QEGLPlatformIntegration : public QPlatformIntegration, public QPlatformNativeInterface
@ -70,6 +71,8 @@ public:
QPlatformWindow *createPlatformWindow(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;
@ -83,6 +86,13 @@ public:
protected:
virtual QEGLPlatformScreen *createScreen() 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; }
void createInputHandlers();

View File

@ -92,7 +92,8 @@ void QEGLPlatformWindow::create()
// Save the original surface type before changing to OpenGLSurface.
m_raster = (window()->surfaceType() == QSurface::RasterSurface);
window()->setSurfaceType(QSurface::OpenGLSurface);
if (m_raster) // change to OpenGL, but not for RasterGLSurface
window()->setSurfaceType(QSurface::OpenGLSurface);
if (window()->type() == Qt::Desktop) {
QRect fullscreenRect(QPoint(), screen()->availableGeometry().size());
@ -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)
return m_backingStore->texture();
return m_backingStore->textures();
return 0;
}
void QEGLPlatformWindow::composited()
{
if (m_backingStore)
m_backingStore->composited();
}
WId QEGLPlatformWindow::winId() const
{
return m_winId;

View File

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

View File

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

View File

@ -88,17 +88,6 @@ bool QEglFSIntegration::hasCapability(QPlatformIntegration::Capability cap) cons
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()
{
QEglFSHooks::hooks()->platformInit();
@ -124,6 +113,20 @@ QEGLPlatformWindow *QEglFSIntegration::createWindow(QWindow *window) const
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
{
switch (hint)

View File

@ -54,9 +54,6 @@ public:
QEglFSIntegration();
~QEglFSIntegration();
QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE;
QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE;
void initialize() Q_DECL_OVERRIDE;
bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE;
@ -67,6 +64,12 @@ public:
protected:
QEGLPlatformScreen *createScreen() 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;
private:

View File

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

View File

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

View File

@ -736,7 +736,8 @@ QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
dirtyOnScreenWidgets(0),
widgetTextures(0),
fullUpdatePending(0),
updateRequestSent(0)
updateRequestSent(0),
textureListWatcher(0)
{
store = tlw->backingStore();
Q_ASSERT(store);
@ -962,6 +963,25 @@ static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatfo
}
#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.
*/
@ -985,6 +1005,17 @@ void QWidgetBackingStore::sync()
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();
}
@ -1077,7 +1108,7 @@ void QWidgetBackingStore::doSync()
delete widgetTextures;
widgetTextures = 0;
if (tlw->d_func()->textureChildSeen) {
widgetTextures = new QPlatformTextureList; // TODO: implement support for locking
widgetTextures = new QPlatformTextureList;
findTextureWidgetsRecursively(tlw, tlw, widgetTextures);
}
fullUpdatePending = false;

View File

@ -61,6 +61,7 @@
QT_BEGIN_NAMESPACE
class QPlatformTextureList;
class QWidgetBackingStore;
struct BeginPaintInfo {
inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), backingStoreRecreated(0) {}
@ -69,6 +70,23 @@ struct BeginPaintInfo {
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
{
public:
@ -111,6 +129,8 @@ private:
QPoint tlwOffset;
QPlatformTextureListWatcher *textureListWatcher;
void sendUpdateRequest(QWidget *widget, bool updateImmediately);
static bool flushPaint(QWidget *widget, const QRegion &rgn);

View File

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