From c2cd2a0cb8b471165c0e690fe5c70a0e0bbcf5ae Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Samuel=20R=C3=B8dal?= Date: Mon, 16 Apr 2012 21:24:41 +0200 Subject: 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 --- src/plugins/platforms/eglfs/qeglfsbackingstore.cpp | 123 ++++++++++++++++++++- 1 file changed, 121 insertions(+), 2 deletions(-) (limited to 'src/plugins/platforms/eglfs/qeglfsbackingstore.cpp') 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 #include +#include + +#include 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 -- cgit v1.2.3