Add basic backingstore implementation to kms
authorLaszlo Agocs <laszlo.p.agocs@nokia.com>
Sat, 21 Jul 2012 11:20:33 +0000 (14:20 +0300)
committerQt by Nokia <qt-info@nokia.com>
Mon, 23 Jul 2012 17:57:07 +0000 (19:57 +0200)
This allows using the kms plugin in QWidget apps having a single
(preferably fullscreen) top-level widget.

Based on eglfs' implementation. Dirty rectangle tracking is missing,
should be added later.

There is no composition so multiple TLWs will not work nicely.

Change-Id: Ia78589d1a375925ebdcc46aa20fc1619ec14d6cc
Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
Reviewed-by: Elvis Lee <kwangwoong.lee@lge.com>
src/plugins/platforms/kms/qkmsbackingstore.cpp
src/plugins/platforms/kms/qkmsbackingstore.h

index d32f9f1..9fb828a 100644 (file)
 
 #include "qkmsbackingstore.h"
 
+#include <QtGui/QOpenGLContext>
+#include <QtGui/QOpenGLShaderProgram>
+#include <QtGui/QScreen>
+
 QT_BEGIN_NAMESPACE
 
 QKmsBackingStore::QKmsBackingStore(QWindow *window)
     : QPlatformBackingStore(window)
+    , m_context(new QOpenGLContext)
+    , m_texture(0)
+    , m_program(0)
 {
+    m_context->setFormat(window->requestedFormat());
+    m_context->setScreen(window->screen());
+    m_context->create();
+    window->setSurfaceType(QSurface::OpenGLSurface);
+}
+
+QKmsBackingStore::~QKmsBackingStore()
+{
+    delete m_program;
+    if (m_texture)
+        glDeleteTextures(1, &m_texture);
+
+    delete m_context;
 }
 
 QPaintDevice *QKmsBackingStore::paintDevice()
@@ -53,20 +73,115 @@ QPaintDevice *QKmsBackingStore::paintDevice()
     return &m_image;
 }
 
-void QKmsBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+void QKmsBackingStore::beginPaint(const QRegion &)
+{
+}
+
+void QKmsBackingStore::endPaint()
 {
-    //'window' can be a child window, in which case 'region' is in child window coordinates and
-    // offset is the (child) window's offset in relation to the window surface.
+}
 
+void QKmsBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
+{
     Q_UNUSED(region)
     Q_UNUSED(offset)
-    Q_UNUSED(window)
+
+    m_context->makeCurrent(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";
+
+        static const char *textureFragmentProgram =
+            "uniform sampler2D texture;\n"
+            "varying highp vec2 textureCoord;\n"
+            "void main() {\n"
+            "   gl_FragColor = texture2D(texture, textureCoord).bgra;\n"
+            "}\n";
+
+        m_program = new QOpenGLShaderProgram;
+
+        m_program->addShaderFromSourceCode(QOpenGLShader::Vertex, textureVertexProgram);
+        m_program->addShaderFromSourceCode(QOpenGLShader::Fragment, textureFragmentProgram);
+        m_program->bindAttributeLocation("vertexCoordEntry", 0);
+        m_program->bindAttributeLocation("textureCoordEntry", 1);
+        m_program->link();
+    }
+
+    m_program->bind();
+
+    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 = -1 * ((r.top() / sr.height()) * 2 - 1);
+    GLfloat y2 = -1 * ((r.bottom() / sr.height()) * 2 - 1);
+
+    const GLfloat vertexCoordinates[] = {
+        x1, y1,
+        x2, y1,
+        x2, y2,
+        x1, y2
+    };
+
+    const GLfloat textureCoordinates[] = {
+        0, 0,
+        1, 0,
+        1, 1,
+        0, 1
+    };
+
+    glEnableVertexAttribArray(0);
+    glEnableVertexAttribArray(1);
+
+    glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, vertexCoordinates);
+    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, textureCoordinates);
+
+    glBindTexture(GL_TEXTURE_2D, m_texture);
+
+    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, m_image.width(), m_image.height(),
+                 0, GL_RGBA, GL_UNSIGNED_BYTE, m_image.constScanLine(0));
+
+    glDrawArrays(GL_TRIANGLE_FAN, 0, 4);
+
+    m_program->release();
+    glBindTexture(GL_TEXTURE_2D, 0);
+    glDisableVertexAttribArray(0);
+    glDisableVertexAttribArray(1);
+
+    m_context->swapBuffers(window);
+
+    m_context->doneCurrent();
 }
 
 void QKmsBackingStore::resize(const QSize &size, const QRegion &staticContents)
 {
     Q_UNUSED(staticContents)
+
     m_image = QImage(size, QImage::Format_RGB32);
+
+    m_context->makeCurrent(window());
+
+    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);
+
 }
 
 QT_END_NAMESPACE
index 59d9c9a..6357019 100644 (file)
 
 QT_BEGIN_NAMESPACE
 
+class QOpenGLContext;
+class QOpenGLShaderProgram;
+
 class QKmsBackingStore : public QPlatformBackingStore
 {
 public:
     QKmsBackingStore(QWindow *window);
+    ~QKmsBackingStore();
 
     QPaintDevice *paintDevice();
+
+    void beginPaint(const QRegion &);
+    void endPaint();
+
     void flush(QWindow *window, const QRegion &region, const QPoint &offset);
     void resize(const QSize &size, const QRegion &staticContents);
 
 private:
+    QOpenGLContext *m_context;
     QImage m_image;
+    uint m_texture;
+    QOpenGLShaderProgram *m_program;
 };
 
 QT_END_NAMESPACE