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>
This commit is contained in:
Samuel Rødal 2012-04-16 21:24:41 +02:00 committed by Qt by Nokia
parent 0e317af13f
commit c2cd2a0cb8
2 changed files with 138 additions and 2 deletions

View File

@ -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 &region, const QPoint &offset)
@ -74,27 +85,135 @@ void QEglFSBackingStore::flush(QWindow *window, const QRegion &region, 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

View File

@ -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