summaryrefslogtreecommitdiffstats
path: root/src/compositor
diff options
context:
space:
mode:
authorAndy Nichols <andy.nichols@nokia.com>2012-05-11 14:39:36 +0200
committerAndy Nichols <andy.nichols@nokia.com>2012-05-18 13:48:31 +0200
commit6816fb64eeefbafda994d7f5070c619637a62cec (patch)
tree64d09b713b3dc1398d43277b36a5caaf7c549545 /src/compositor
parentb55620a74ed21f0ef497deeaad9f011078b5ce39 (diff)
Add a custom WaylandSurfaceNode with its own materials
With the previous WaylandSurfaceNode based on QSGSimpleTextureNode, QSGTexture's created from SHM buffers would always have and use their alpha channels, despite the useTextureAlpha flag being set to false. Now when the useTextureAlpha flag is set to false, we use a material that ignores the textures alpha channel. Change-Id: I9cc33939f37856495f8885357f49de5ffdd81d1f Reviewed-by: Gunnar Sletta <gunnar.sletta@nokia.com> Reviewed-by: Samuel Rødal <samuel.rodal@nokia.com>
Diffstat (limited to 'src/compositor')
-rw-r--r--src/compositor/compositor_api/compositor_api.pri8
-rw-r--r--src/compositor/compositor_api/waylandsurfaceitem.cpp45
-rw-r--r--src/compositor/compositor_api/waylandsurfacenode.cpp104
-rw-r--r--src/compositor/compositor_api/waylandsurfacenode.h47
-rw-r--r--src/compositor/compositor_api/waylandsurfacetexturematerial.cpp77
-rw-r--r--src/compositor/compositor_api/waylandsurfacetexturematerial.h46
6 files changed, 284 insertions, 43 deletions
diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri
index 0f81d77f9..72b1949b2 100644
--- a/src/compositor/compositor_api/compositor_api.pri
+++ b/src/compositor/compositor_api/compositor_api.pri
@@ -3,12 +3,16 @@ INCLUDEPATH += $$PWD
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
diff --git a/src/compositor/compositor_api/waylandsurfaceitem.cpp b/src/compositor/compositor_api/waylandsurfaceitem.cpp
index 71bfd6196..e042125f1 100644
--- a/src/compositor/compositor_api/waylandsurfaceitem.cpp
+++ b/src/compositor/compositor_api/waylandsurfaceitem.cpp
@@ -39,6 +39,7 @@
****************************************************************************/
#include "waylandsurfaceitem.h"
+#include "waylandsurfacenode.h"
#include "waylandsurface.h"
#include "waylandcompositor.h"
#include "waylandinput.h"
@@ -50,51 +51,12 @@
#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
{
@@ -189,7 +151,7 @@ WaylandSurfaceItem::~WaylandSurfaceItem()
{
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)
@@ -421,7 +383,8 @@ QSGNode *WaylandSurfaceItem::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeDa
node->setRect(0, 0, width(), height());
}
- node->m_textureUpdated = true;
+ node->setTextureUpdated(true);
+
return node;
}
diff --git a/src/compositor/compositor_api/waylandsurfacenode.cpp b/src/compositor/compositor_api/waylandsurfacenode.cpp
new file mode 100644
index 000000000..e6571751c
--- /dev/null
+++ b/src/compositor/compositor_api/waylandsurfacenode.cpp
@@ -0,0 +1,104 @@
+#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;
+}
diff --git a/src/compositor/compositor_api/waylandsurfacenode.h b/src/compositor/compositor_api/waylandsurfacenode.h
new file mode 100644
index 000000000..3ea0afe51
--- /dev/null
+++ b/src/compositor/compositor_api/waylandsurfacenode.h
@@ -0,0 +1,47 @@
+#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
diff --git a/src/compositor/compositor_api/waylandsurfacetexturematerial.cpp b/src/compositor/compositor_api/waylandsurfacetexturematerial.cpp
new file mode 100644
index 000000000..80a3d2cfe
--- /dev/null
+++ b/src/compositor/compositor_api/waylandsurfacetexturematerial.cpp
@@ -0,0 +1,77 @@
+#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;
+}
diff --git a/src/compositor/compositor_api/waylandsurfacetexturematerial.h b/src/compositor/compositor_api/waylandsurfacetexturematerial.h
new file mode 100644
index 000000000..ace271e6f
--- /dev/null
+++ b/src/compositor/compositor_api/waylandsurfacetexturematerial.h
@@ -0,0 +1,46 @@
+#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