HEADERS += \
$$PWD/waylandcompositor.h \
$$PWD/waylandsurface.h \
- $$PWD/waylandinput.h
+ $$PWD/waylandinput.h \
+ $$PWD/waylandsurfacenode.h \
+ $$PWD/waylandsurfacetexturematerial.h
SOURCES += \
$$PWD/waylandcompositor.cpp \
$$PWD/waylandsurface.cpp \
- $$PWD/waylandinput.cpp
+ $$PWD/waylandinput.cpp \
+ $$PWD/waylandsurfacenode.cpp \
+ $$PWD/waylandsurfacetexturematerial.cpp
QT += core-private
****************************************************************************/
#include "waylandsurfaceitem.h"
+#include "waylandsurfacenode.h"
#include "waylandsurface.h"
#include "waylandcompositor.h"
#include "waylandinput.h"
#include <QtGui/QGuiApplication>
#include <QtGui/QScreen>
-#include <QtQuick/QSGSimpleTextureNode>
#include <QtQuick/QSGSimpleRectNode>
#include <QtQuick/QQuickCanvas>
#include <QtCore/QMutexLocker>
#include <QtCore/QMutex>
-class WaylandSurfaceNode : public QSGSimpleTextureNode
-{
-public:
- WaylandSurfaceNode(WaylandSurfaceItem *item)
- : m_item(item), m_textureUpdated(false)
- {
- if (m_item)
- m_item->m_node = this;
- setFlag(UsePreprocess,true);
- }
- ~WaylandSurfaceNode() {
- QMutexLocker locker(WaylandSurfaceItem::mutex);
- if (m_item)
- m_item->m_node = 0;
- }
- void preprocess() {
- QMutexLocker locker(WaylandSurfaceItem::mutex);
-
- //Update if the item is dirty and we haven't done an updateTexture for this frame
- if (m_item && m_item->m_damaged && !m_textureUpdated) {
- m_item->updateTexture();
- updateTexture();
- }
- //Reset value for next frame: we have not done updatePaintNode yet
- m_textureUpdated = false;
- }
-
- void updateTexture() {
- Q_ASSERT(m_item && m_item->textureProvider());
-
- QSGTexture *texture = m_item->textureProvider()->texture();
- setTexture(texture);
- setFiltering(texture->filtering());
- }
-
- WaylandSurfaceItem *m_item;
- bool m_textureUpdated;
-};
class WaylandSurfaceTextureProvider : public QSGTextureProvider
{
{
QMutexLocker locker(mutex);
if (m_node)
- m_node->m_item = 0;
+ m_node->setItem(0);
if (m_surface)
m_surface->setSurfaceItem(0);
if (m_provider)
node->setRect(0, 0, width(), height());
}
- node->m_textureUpdated = true;
+ node->setTextureUpdated(true);
+
return node;
}
--- /dev/null
+#include "waylandsurfacenode.h"
+#include "waylandsurfaceitem.h"
+
+#include <QtCore/QMutexLocker>
+#include <QtQuick/QSGTexture>
+#include <QtQuick/QSGSimpleTextureNode>
+#include <QtQuick/QSGFlatColorMaterial>
+
+WaylandSurfaceNode::WaylandSurfaceNode(WaylandSurfaceItem *item)
+ : m_item(item)
+ , m_textureUpdated(false)
+ , m_useTextureAlpha(false)
+ , m_geometry(QSGGeometry::defaultAttributes_TexturedPoint2D(), 4)
+{
+ m_textureMaterial = WaylandSurfaceTextureMaterial::createMaterial();
+ m_opaqueTextureMaterial = WaylandSurfaceTextureOpaqueMaterial::createMaterial();
+
+ m_currentMaterial = m_opaqueTextureMaterial;
+
+ setGeometry(&m_geometry);
+ setMaterial(m_currentMaterial);
+
+ if (m_item)
+ m_item->m_node = this;
+ setFlag(UsePreprocess,true);
+}
+
+
+WaylandSurfaceNode::~WaylandSurfaceNode()
+{
+ QMutexLocker locker(WaylandSurfaceItem::mutex);
+ if (m_item)
+ m_item->m_node = 0;
+ delete m_textureMaterial;
+ delete m_opaqueTextureMaterial;
+}
+
+void WaylandSurfaceNode::preprocess()
+{
+ QMutexLocker locker(WaylandSurfaceItem::mutex);
+
+ //Update if the item is dirty and we haven't done an updateTexture for this frame
+ if (m_item && m_item->m_damaged && !m_textureUpdated) {
+ m_item->updateTexture();
+ updateTexture();
+ }
+ //Reset value for next frame: we have not done updatePaintNode yet
+ m_textureUpdated = false;
+}
+
+void WaylandSurfaceNode::updateTexture()
+{
+ Q_ASSERT(m_item && m_item->textureProvider());
+
+ //If m_item->useTextureAlpha has changed to true use m_texureMaterial
+ //otherwise use m_opaqueTextureMaterial.
+ if (m_item->useTextureAlpha() != m_useTextureAlpha) {
+ m_useTextureAlpha = m_item->useTextureAlpha();
+ if (m_useTextureAlpha) {
+ m_currentMaterial = m_textureMaterial;
+ } else {
+ m_currentMaterial = m_opaqueTextureMaterial;
+ }
+ setMaterial(m_currentMaterial);
+ }
+
+ QSGTexture *texture = m_item->textureProvider()->texture();
+ setTexture(texture);
+}
+
+void WaylandSurfaceNode::setRect(const QRectF &rect)
+{
+ if (m_rect == rect)
+ return;
+ m_rect = rect;
+
+ if (texture()) {
+ QSize ts = texture()->textureSize();
+ QRectF sourceRect(0, 0, ts.width(), ts.height());
+ QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_rect, texture()->convertToNormalizedSourceRect(sourceRect));
+ }
+}
+
+void WaylandSurfaceNode::setTexture(QSGTexture *texture)
+{
+ if (m_currentMaterial->state()->texture() == texture)
+ return;
+ m_currentMaterial->state()->setTexture(texture);
+
+ QSize ts = texture->textureSize();
+ QRectF sourceRect(0, 0, ts.width(), ts.height());
+ QSGGeometry::updateTexturedRectGeometry(&m_geometry, m_rect, texture->convertToNormalizedSourceRect(sourceRect));
+ markDirty(DirtyMaterial);
+}
+
+QSGTexture *WaylandSurfaceNode::texture() const
+{
+ return m_currentMaterial->state()->texture();
+}
+
+void WaylandSurfaceNode::setItem(WaylandSurfaceItem *item)
+{
+ m_item = item;
+}
--- /dev/null
+#ifndef WAYLANDSURFACENODE_H
+#define WAYLANDSURFACENODE_H
+
+#include "waylandsurfacetexturematerial.h"
+
+#include <QtQuick/QSGGeometryNode>
+#include <QtQuick/QSGOpaqueTextureMaterial>
+
+class WaylandSurfaceItem;
+class QSGTexture;
+
+class WaylandSurfaceNode : public QSGGeometryNode
+{
+public:
+ WaylandSurfaceNode(WaylandSurfaceItem *item = 0);
+ ~WaylandSurfaceNode();
+
+ void preprocess();
+ void updateTexture();
+
+ void setRect(const QRectF &rect);
+ inline void setRect(qreal x, qreal y, qreal w, qreal h) { setRect(QRectF(x, y, w, h)); }
+
+ void setTexture(QSGTexture *texture);
+ QSGTexture *texture() const;
+
+ bool isTextureUpdated() const { return m_textureUpdated; }
+ void setTextureUpdated(bool textureUpdated) { m_textureUpdated = textureUpdated; }
+
+ WaylandSurfaceItem *item() const { return m_item; }
+ void setItem(WaylandSurfaceItem *item);
+
+private:
+
+ WaylandSurfaceItem *m_item;
+ bool m_textureUpdated;
+ bool m_useTextureAlpha;
+
+ QSGGeometry m_geometry;
+ QSGSimpleMaterial<WaylandSurfaceTextureState> *m_textureMaterial;
+ QSGSimpleMaterial<WaylandSurfaceTextureState> *m_opaqueTextureMaterial;
+ QSGSimpleMaterial<WaylandSurfaceTextureState> *m_currentMaterial;
+
+ QRectF m_rect;
+};
+
+#endif // WAYLANDSURFACENODE_H
--- /dev/null
+#include "waylandsurfacetexturematerial.h"
+#include <QtGui/QOpenGLContext>
+
+static const char wayland_surface_texture_material_vertex[] =
+ "uniform highp mat4 qt_Matrix; \n"
+ "attribute highp vec4 qt_VertexPosition; \n"
+ "attribute highp vec2 qt_VertexTexCoord; \n"
+ "varying highp vec2 qt_TexCoord; \n"
+ "void main() { \n"
+ " qt_TexCoord = qt_VertexTexCoord; \n"
+ " gl_Position = qt_Matrix * qt_VertexPosition; \n"
+ "}";
+
+
+static const char wayland_surface_texture_opaque_material_fragment[] =
+ "varying highp vec2 qt_TexCoord; \n"
+ "uniform sampler2D qt_Texture; \n"
+ "uniform lowp float qt_Opacity; \n"
+ "void main() { \n"
+ " gl_FragColor = vec4(texture2D(qt_Texture, qt_TexCoord).rgb, 1.0) * qt_Opacity; \n"
+ "}";
+
+static const char wayland_surface_texture_material_fragment[] =
+ "varying highp vec2 qt_TexCoord; \n"
+ "uniform sampler2D qt_Texture; \n"
+ "uniform lowp float qt_Opacity; \n"
+ "void main() { \n"
+ " gl_FragColor = texture2D(qt_Texture, qt_TexCoord) * qt_Opacity; \n"
+ "}";
+
+QList<QByteArray> WaylandSurfaceTextureMaterial::attributes() const
+{
+ QList<QByteArray> attributeList;
+ attributeList << "qt_VertexPosition";
+ attributeList << "qt_VertexTexCoord";
+ return attributeList;
+}
+
+void WaylandSurfaceTextureMaterial::updateState(const WaylandSurfaceTextureState *newState, const WaylandSurfaceTextureState *oldState)
+{
+ Q_UNUSED(oldState);
+ newState->texture()->bind();
+}
+
+const char *WaylandSurfaceTextureMaterial::vertexShader() const
+{
+ return wayland_surface_texture_material_vertex;
+}
+
+const char *WaylandSurfaceTextureMaterial::fragmentShader() const
+{
+ return wayland_surface_texture_material_fragment;
+}
+
+QList<QByteArray> WaylandSurfaceTextureOpaqueMaterial::attributes() const
+{
+ QList<QByteArray> attributeList;
+ attributeList << "qt_VertexPosition";
+ attributeList << "qt_VertexTexCoord";
+ return attributeList;
+}
+
+void WaylandSurfaceTextureOpaqueMaterial::updateState(const WaylandSurfaceTextureState *newState, const WaylandSurfaceTextureState *oldState)
+{
+ Q_UNUSED(oldState);
+ newState->texture()->bind();
+}
+
+const char *WaylandSurfaceTextureOpaqueMaterial::vertexShader() const
+{
+ return wayland_surface_texture_material_vertex;
+}
+
+const char *WaylandSurfaceTextureOpaqueMaterial::fragmentShader() const
+{
+ return wayland_surface_texture_opaque_material_fragment;
+}
--- /dev/null
+#ifndef WAYLANDSURFACETEXTUREMATERIAL_H
+#define WAYLANDSURFACETEXTUREMATERIAL_H
+
+#include <QtQuick/QSGSimpleMaterial>
+#include <QtQuick/QSGTexture>
+#include <QtGui/QOpenGLFunctions>
+
+class WaylandSurfaceTextureState {
+public:
+ WaylandSurfaceTextureState()
+ : m_texture(0)
+ {}
+ void setTexture(QSGTexture *texture) { m_texture = texture; }
+ QSGTexture *texture() const { return m_texture; }
+
+private:
+ QSGTexture *m_texture;
+};
+
+class WaylandSurfaceTextureMaterial : public QSGSimpleMaterialShader<WaylandSurfaceTextureState>
+{
+ QSG_DECLARE_SIMPLE_SHADER(WaylandSurfaceTextureMaterial, WaylandSurfaceTextureState)
+ public:
+
+ QList<QByteArray> attributes() const;
+
+ void updateState(const WaylandSurfaceTextureState *newState, const WaylandSurfaceTextureState *oldState);
+protected:
+ const char *vertexShader() const;
+ const char *fragmentShader() const;
+};
+
+class WaylandSurfaceTextureOpaqueMaterial : public QSGSimpleMaterialShader<WaylandSurfaceTextureState>
+{
+ QSG_DECLARE_SIMPLE_SHADER(WaylandSurfaceTextureOpaqueMaterial, WaylandSurfaceTextureState)
+ public:
+
+ QList<QByteArray> attributes() const;
+
+ void updateState(const WaylandSurfaceTextureState *newState, const WaylandSurfaceTextureState *oldState);
+protected:
+ const char *vertexShader() const;
+ const char *fragmentShader() const;
+};
+
+#endif // WAYLANDSURFACETEXTUREMATERIAL_H