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:
parent
5b422304a9
commit
ff11af4fbc
@ -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
|
||||
|
||||
/*!
|
||||
|
@ -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);
|
||||
|
@ -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,102 +86,53 @@ 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()
|
||||
|
@ -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
|
||||
|
@ -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 ®ion, 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 ®ion, 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
|
||||
|
@ -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 ®ion, const QPoint &offset);
|
||||
void resize(const QSize &size, const QRegion &staticContents);
|
||||
void flush(QWindow *window, const QRegion ®ion, 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 ®ion, 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
|
||||
|
@ -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());
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -92,6 +92,7 @@ void QEGLPlatformWindow::create()
|
||||
|
||||
// Save the original surface type before changing to OpenGLSurface.
|
||||
m_raster = (window()->surfaceType() == QSurface::RasterSurface);
|
||||
if (m_raster) // change to OpenGL, but not for RasterGLSurface
|
||||
window()->setSurfaceType(QSurface::OpenGLSurface);
|
||||
|
||||
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)
|
||||
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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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:
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -58,8 +58,6 @@
|
||||
#include <QtCore/qmath.h>
|
||||
#include <qopengl.h>
|
||||
|
||||
#include <GL/glext.h>
|
||||
|
||||
class OpenGLWidgetPrivate
|
||||
{
|
||||
public:
|
||||
|
Loading…
Reference in New Issue
Block a user