Added initial scene-graph qml based compositor.
authorSamuel Rødal <samuel.rodal@nokia.com>
Tue, 15 Mar 2011 13:42:19 +0000 (14:42 +0100)
committerSamuel Rødal <samuel.rodal@nokia.com>
Tue, 15 Mar 2011 13:42:59 +0000 (14:42 +0100)
examples/qml-compositor/main.cpp [new file with mode: 0644]
examples/qml-compositor/qml-compositor.pro [new file with mode: 0644]
examples/qml-compositor/qml/QmlCompositor/Window.qml [new file with mode: 0644]
examples/qml-compositor/qml/QmlCompositor/main.qml [new file with mode: 0644]

diff --git a/examples/qml-compositor/main.cpp b/examples/qml-compositor/main.cpp
new file mode 100644 (file)
index 0000000..1e5e740
--- /dev/null
@@ -0,0 +1,284 @@
+/****************************************************************************
+**
+** This file is part of QtCompositor**
+**
+** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+**
+** Contact:  Nokia Corporation qt-info@nokia.com
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**
+** Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+#include "qtcompositor.h"
+
+#include "waylandsurface.h"
+
+#include <QApplication>
+#include <QTimer>
+#include <QPainter>
+#include <QMouseEvent>
+
+#include <QDeclarativeView>
+
+#ifdef QT_COMPOSITOR_WAYLAND_GL
+#include <QGLContext>
+#include <QGLWidget>
+#endif
+
+#include <QtDeclarative/adaptationlayer.h>
+#include <QSGContext>
+#include <QSGItem>
+#include <QSGTextureManager>
+#include <QSGTextureProvider>
+#include <QSGView>
+
+#include <private/qsgitem_p.h>
+#include <private/qsgrectangle_p.h>
+
+class WaylandSurfaceTextureProvider : public QSGTextureProvider
+{
+    Q_OBJECT
+public:
+    WaylandSurfaceTextureProvider(WaylandSurface *surface);
+    ~WaylandSurfaceTextureProvider();
+
+    QSGTextureRef texture() {
+        return m_textureRef;
+    }
+
+private slots:
+    void surfaceDamaged(const QRect &rect);
+
+private:
+    WaylandSurface *m_surface;
+
+    QSGTexture *m_texture;
+    QSGTextureRef m_textureRef;
+};
+
+WaylandSurfaceTextureProvider::WaylandSurfaceTextureProvider(WaylandSurface *surface)
+    : m_surface(surface)
+    , m_texture(new QSGTexture)
+    , m_textureRef(m_texture)
+{
+    connect(surface, SIGNAL(damaged(const QRect &)), this, SLOT(surfaceDamaged(const QRect &)));
+}
+
+WaylandSurfaceTextureProvider::~WaylandSurfaceTextureProvider()
+{
+}
+
+void WaylandSurfaceTextureProvider::surfaceDamaged(const QRect &)
+{
+    if (m_surface->type() == WaylandSurface::Texture) {
+        m_texture->setTextureId(m_surface->texture());
+        m_texture->setAlphaChannel(false);
+    } else {
+        if (m_texture->status() == QSGTexture::Null) {
+            GLuint textureId;
+            glGenTextures(1, &textureId);
+            glBindTexture(GL_TEXTURE_2D, textureId);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+            m_texture->setTextureId(textureId);
+        }
+
+        const QImage image = m_surface->image();
+
+        glBindTexture(GL_TEXTURE_2D, m_texture->textureId());
+        glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA_EXT, image.width(), image.height(), 0, GL_BGRA_EXT, GL_UNSIGNED_BYTE, image.bits());
+
+        m_texture->setAlphaChannel(image.hasAlphaChannel());
+    }
+
+    m_texture->setTextureSize(m_surface->geometry().size());
+    m_texture->setOwnsTexture(true);
+    m_texture->setHasMipmaps(false);
+    m_texture->setStatus(QSGTexture::Ready);
+
+    emit textureChanged();
+}
+
+class WindowItem : public QSGItem, public QSGTextureProviderInterface
+{
+    Q_OBJECT
+    Q_INTERFACES(QSGTextureProviderInterface)
+public:
+    WindowItem(WaylandSurface *surface, QSGItem *parent = 0);
+    ~WindowItem();
+
+    QSGTextureProvider *textureProvider() const
+    {
+        return m_textureProvider;
+    }
+
+    void mousePressEvent(QGraphicsSceneMouseEvent *event);
+    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
+
+private slots:
+    void surfaceMapped(const QRect &rect);
+
+protected:
+    Node *updatePaintNode(Node *oldNode, UpdatePaintNodeData *);
+
+private:
+    QPoint toSurface(const QPointF &pos) const;
+
+    WaylandSurface *m_surface;
+    WaylandSurfaceTextureProvider *m_textureProvider;
+};
+
+WindowItem::WindowItem(WaylandSurface *surface, QSGItem *parent)
+    : QSGItem(parent)
+    , m_surface(surface)
+    , m_textureProvider(new WaylandSurfaceTextureProvider(surface))
+{
+    setSmooth(true);
+    setFlag(ItemHasContents);
+    setAcceptedMouseButtons(Qt::LeftButton | Qt::RightButton);
+    connect(surface, SIGNAL(mapped(const QRect &)), this, SLOT(surfaceMapped(const QRect &)));
+    connect(m_textureProvider, SIGNAL(textureChanged()), this, SLOT(update()));
+}
+
+WindowItem::~WindowItem()
+{
+    delete m_textureProvider;
+}
+
+void WindowItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
+{
+    m_surface->setInputFocus();
+    m_surface->sendMousePressEvent(toSurface(event->pos()), event->button());
+}
+
+void WindowItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+{
+    m_surface->setInputFocus();
+    m_surface->sendMouseMoveEvent(toSurface(event->pos()));
+}
+
+void WindowItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
+{
+    m_surface->setInputFocus();
+    m_surface->sendMouseReleaseEvent(toSurface(event->pos()), event->button());
+}
+
+QPoint WindowItem::toSurface(const QPointF &pos) const
+{
+    return pos.toPoint();
+}
+
+void WindowItem::surfaceMapped(const QRect &rect)
+{
+    setWidth(rect.width());
+    setHeight(rect.height());
+
+    update();
+}
+
+Node *WindowItem::updatePaintNode(Node *oldNode, UpdatePaintNodeData *)
+{
+    TextureNodeInterface *node = static_cast<TextureNodeInterface *>(oldNode);
+    if (!node) {
+        node = QSGContext::current->createTextureNode();
+        node->setFlag(Node::UsePreprocess, false);
+        node->setTexture(m_textureProvider);
+    }
+
+    m_textureProvider->setHorizontalWrapMode(QSGTextureProvider::ClampToEdge);
+    m_textureProvider->setVerticalWrapMode(QSGTextureProvider::ClampToEdge);
+    m_textureProvider->setFiltering(QSGItemPrivate::get(this)->smooth
+                                    ? QSGTextureProvider::Linear : QSGTextureProvider::Nearest);
+
+    node->setTargetRect(QRectF(0, 0, width(), height()));
+    node->setSourceRect(QRectF(0, 0, 1, 1));
+    node->update();
+
+    return node;
+}
+
+
+class QmlCompositor : public QSGView, public WaylandCompositor
+{
+    Q_OBJECT
+public:
+    QmlCompositor() : WaylandCompositor(this) {
+        setMouseTracking(true);
+        setSource(QUrl(QLatin1String("qml/QmlCompositor/main.qml")));
+        winId();
+        if (platformWindow()) {
+            platformWindow()->glContext();
+        }
+    }
+
+signals:
+    void windowAdded(QVariant window);
+
+private slots:
+    void surfaceMapped(const QRect &rect) {
+        WaylandSurface *surface = qobject_cast<WaylandSurface *>(sender());
+        surface->setGeometry(rect);
+    }
+
+protected:
+    void surfaceCreated(WaylandSurface *surface) {
+        WindowItem *item = new WindowItem(surface, rootObject());
+        connect(surface, SIGNAL(mapped(const QRect &)), this, SLOT(surfaceMapped(const QRect &)));
+        emit windowAdded(QVariant::fromValue(static_cast<QSGItem *>(item)));
+    }
+
+    void paintEvent(QPaintEvent *event) {
+        QSGView::paintEvent(event);
+        frameFinished();
+        glFinish();
+    }
+};
+
+int main(int argc, char *argv[])
+{
+    QApplication app(argc, argv);
+
+    QmlCompositor compositor;
+    compositor.show();
+
+    compositor.rootContext()->setContextProperty("compositor", &compositor);
+
+    QObject::connect(&compositor, SIGNAL(windowAdded(QVariant)), compositor.rootObject(), SLOT(windowAdded(QVariant)));
+
+    return app.exec();
+
+}
+
+#include "main.moc"
diff --git a/examples/qml-compositor/qml-compositor.pro b/examples/qml-compositor/qml-compositor.pro
new file mode 100644 (file)
index 0000000..b98eba4
--- /dev/null
@@ -0,0 +1,31 @@
+qml_folder.source = qml/QmlCompositor
+qml_folder.target = qml
+DEPLOYMENTFOLDERS = qml_folder
+
+TEMPLATE = app
+TARGET = qml-compositor
+DEPENDPATH += .
+INCLUDEPATH += .
+
+# comment out the following CONFIG lines to disable DRM
+CONFIG += wayland_gl
+CONFIG += mesa_egl
+#CONFIG += dri2_xcb
+
+# comment out the following to not use pkg-config in the pri files
+CONFIG += use_pkgconfig
+
+DESTDIR=$$PWD/../../bin/
+
+LIBS += -L ../../lib
+
+include (../../src/qt-compositor/qt-compositor.pri)
+
+QT += declarative
+
+# Input
+SOURCES += main.cpp
+
+CONFIG += qt warn_on debug  create_prl link_prl
+OBJECTS_DIR = .obj/release-shared
+MOC_DIR = .moc/release-shared
diff --git a/examples/qml-compositor/qml/QmlCompositor/Window.qml b/examples/qml-compositor/qml/QmlCompositor/Window.qml
new file mode 100644 (file)
index 0000000..b486b16
--- /dev/null
@@ -0,0 +1,58 @@
+/****************************************************************************
+**
+** This file is part of QtCompositor**
+**
+** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+**
+** Contact:  Nokia Corporation qt-info@nokia.com
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**
+** Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+    id: container
+
+    x: -400;
+    y: 0;
+
+    Behavior on x {
+        enabled: true
+        NumberAnimation { easing.type: Easing.InCubic; duration: 1000; }
+    }
+
+    Behavior on y {
+        enabled: true
+        NumberAnimation { easing.type: Easing.InQuad; duration: 1000; }
+    }
+}
diff --git a/examples/qml-compositor/qml/QmlCompositor/main.qml b/examples/qml-compositor/qml/QmlCompositor/main.qml
new file mode 100644 (file)
index 0000000..9772c82
--- /dev/null
@@ -0,0 +1,74 @@
+/****************************************************************************
+**
+** This file is part of QtCompositor**
+**
+** Copyright © 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+**
+** Contact:  Nokia Corporation qt-info@nokia.com
+**
+** You may use this file under the terms of the BSD license as follows:
+**
+** Redistribution and use in source and binary forms, with or without
+** modification, are permitted provided that the following conditions are
+** met:
+**
+** Redistributions of source code must retain the above copyright
+** notice, this list of conditions and the following disclaimer.
+**
+** Redistributions in binary form must reproduce the above copyright
+** notice, this list of conditions and the following disclaimer in the
+** documentation and/or other materials provided with the distribution.
+**
+** Neither the name of Nokia Corporation and its Subsidiary(-ies) nor the
+** names of its contributors may be used to endorse or promote products
+** derived from this software without specific prior written permission.
+**
+** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+**
+****************************************************************************/
+
+import QtQuick 2.0
+
+Rectangle {
+    id: root
+
+    width: 800
+    height: 640
+
+    Image {
+        id: background
+        width: parent.width
+        height: parent.height
+        source: "background.jpg"
+        smooth: true
+    }
+
+    function windowAdded(window) {
+        var windowComponent = Qt.createComponent("Window.qml");
+        var windowContainer = windowComponent.createObject(root);
+
+        window.parent = windowContainer;
+
+        windowContainer.x = spawnX;
+        windowContainer.y = spawnY;
+
+        windowContainer.opacity = 1.0;
+
+        spawnX -= 40;
+        spawnY += 40;
+    }
+
+    property int spawnX: width - 400;
+    property int spawnY: 20;
+}