diff options
author | Samuel Rødal <samuel.rodal@nokia.com> | 2012-04-16 21:24:41 +0200 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2012-04-16 21:42:19 +0200 |
commit | c2cd2a0cb8b471165c0e690fe5c70a0e0bbcf5ae (patch) | |
tree | 500addd228c8246a5bb6f376ea73c738fecf2abc /src/plugins/platforms/eglfs | |
parent | 0e317af13f24d88a88c41f5efbd3fe9180ec6bee (diff) |
Implemented raster based backing store for EGLFS plugin.
This improves quality of rendering for QWidget-based applications a bit.
Change-Id: I6b832d1de7e722f4dbe4e82882f5db35f0b8c30c
Reviewed-by: Girish Ramakrishnan <girish.1.ramakrishnan@nokia.com>
Diffstat (limited to 'src/plugins/platforms/eglfs')
-rw-r--r-- | src/plugins/platforms/eglfs/qeglfsbackingstore.cpp | 123 | ||||
-rw-r--r-- | src/plugins/platforms/eglfs/qeglfsbackingstore.h | 17 |
2 files changed, 138 insertions, 2 deletions
diff --git a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp index 8e9e5f76e0..48ac680043 100644 --- a/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp +++ b/src/plugins/platforms/eglfs/qeglfsbackingstore.cpp @@ -43,12 +43,19 @@ #include <QtGui/QOpenGLContext> #include <QtGui/QOpenGLPaintDevice> +#include <QtGui/QOpenGLShaderProgram> + +#include <QtGui/QScreen> QT_BEGIN_NAMESPACE QEglFSBackingStore::QEglFSBackingStore(QWindow *window) : QPlatformBackingStore(window) , m_context(new QOpenGLContext) +#ifdef EGLFS_BACKINGSTORE_USE_IMAGE + , m_texture(0) + , m_program(0) +#endif { m_context->setFormat(window->requestedFormat()); m_context->setScreen(window->screen()); @@ -62,7 +69,11 @@ QEglFSBackingStore::~QEglFSBackingStore() QPaintDevice *QEglFSBackingStore::paintDevice() { +#ifdef EGLFS_BACKINGSTORE_USE_IMAGE + return &m_image; +#else return m_device; +#endif } void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPoint &offset) @@ -74,27 +85,135 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion ®ion, const QPo qWarning("QEglBackingStore::flush %p", window); #endif +#ifdef EGLFS_BACKINGSTORE_USE_IMAGE + 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);\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(); + QRectF sr = window->screen()->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); + + foreach (const QRect &rect, m_dirty.rects()) { + if (rect == m_image.rect()) { + glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, m_image.constBits()); + } else { + glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + m_image.copy(rect).constBits()); + } + } + + m_dirty = QRegion(); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glBindTexture(GL_TEXTURE_2D, 0); + + glDisableVertexAttribArray(m_vertexCoordEntry); + glDisableVertexAttribArray(m_textureCoordEntry); +#endif + m_context->swapBuffers(window); } -void QEglFSBackingStore::beginPaint(const QRegion &) +void QEglFSBackingStore::makeCurrent() { // needed to prevent QOpenGLContext::makeCurrent() from failing window()->setSurfaceType(QSurface::OpenGLSurface); m_context->makeCurrent(window()); +} + +void QEglFSBackingStore::beginPaint(const QRegion &rgn) +{ + makeCurrent(); + +#ifdef EGLFS_BACKINGSTORE_USE_IMAGE + m_dirty = m_dirty | rgn; +#else + Q_UNUSED(rgn); m_device = new QOpenGLPaintDevice(window()->size()); +#endif } void QEglFSBackingStore::endPaint() { +#ifndef EGLFS_BACKINGSTORE_USE_IMAGE delete m_device; +#endif } void QEglFSBackingStore::resize(const QSize &size, const QRegion &staticContents) { - Q_UNUSED(size); Q_UNUSED(staticContents); + +#ifdef EGLFS_BACKINGSTORE_USE_IMAGE + m_image = QImage(size, QImage::Format_RGB32); + makeCurrent(); + 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); +#else + Q_UNUSED(size); +#endif } QT_END_NAMESPACE diff --git a/src/plugins/platforms/eglfs/qeglfsbackingstore.h b/src/plugins/platforms/eglfs/qeglfsbackingstore.h index 97ea322420..f723bca685 100644 --- a/src/plugins/platforms/eglfs/qeglfsbackingstore.h +++ b/src/plugins/platforms/eglfs/qeglfsbackingstore.h @@ -44,10 +44,16 @@ #include <QtGui/qplatformbackingstore_qpa.h> +#include <QImage> +#include <QRegion> + +#define EGLFS_BACKINGSTORE_USE_IMAGE + QT_BEGIN_NAMESPACE class QOpenGLContext; class QOpenGLPaintDevice; +class QOpenGLShaderProgram; class QEglFSBackingStore : public QPlatformBackingStore { @@ -64,8 +70,19 @@ public: void resize(const QSize &size, const QRegion &staticContents); private: + void makeCurrent(); + QOpenGLContext *m_context; +#ifdef EGLFS_BACKINGSTORE_USE_IMAGE + QImage m_image; + uint m_texture; + QRegion m_dirty; + QOpenGLShaderProgram *m_program; + int m_vertexCoordEntry; + int m_textureCoordEntry; +#else QOpenGLPaintDevice *m_device; +#endif }; QT_END_NAMESPACE |