From 6816fb64eeefbafda994d7f5070c619637a62cec Mon Sep 17 00:00:00 2001 From: Andy Nichols Date: Fri, 11 May 2012 14:39:36 +0200 Subject: [PATCH] Add a custom WaylandSurfaceNode with its own materials MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit 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 Reviewed-by: Samuel Rødal --- src/compositor/compositor_api/compositor_api.pri | 8 +- .../compositor_api/waylandsurfaceitem.cpp | 45 +-------- .../compositor_api/waylandsurfacenode.cpp | 104 +++++++++++++++++++++ src/compositor/compositor_api/waylandsurfacenode.h | 47 ++++++++++ .../waylandsurfacetexturematerial.cpp | 77 +++++++++++++++ .../compositor_api/waylandsurfacetexturematerial.h | 46 +++++++++ 6 files changed, 284 insertions(+), 43 deletions(-) create mode 100644 src/compositor/compositor_api/waylandsurfacenode.cpp create mode 100644 src/compositor/compositor_api/waylandsurfacenode.h create mode 100644 src/compositor/compositor_api/waylandsurfacetexturematerial.cpp create mode 100644 src/compositor/compositor_api/waylandsurfacetexturematerial.h diff --git a/src/compositor/compositor_api/compositor_api.pri b/src/compositor/compositor_api/compositor_api.pri index 0f81d77..72b1949 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 71bfd61..e042125 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 #include -#include #include #include #include #include -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 0000000..e657175 --- /dev/null +++ b/src/compositor/compositor_api/waylandsurfacenode.cpp @@ -0,0 +1,104 @@ +#include "waylandsurfacenode.h" +#include "waylandsurfaceitem.h" + +#include +#include +#include +#include + +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 0000000..3ea0afe --- /dev/null +++ b/src/compositor/compositor_api/waylandsurfacenode.h @@ -0,0 +1,47 @@ +#ifndef WAYLANDSURFACENODE_H +#define WAYLANDSURFACENODE_H + +#include "waylandsurfacetexturematerial.h" + +#include +#include + +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 *m_textureMaterial; + QSGSimpleMaterial *m_opaqueTextureMaterial; + QSGSimpleMaterial *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 0000000..80a3d2c --- /dev/null +++ b/src/compositor/compositor_api/waylandsurfacetexturematerial.cpp @@ -0,0 +1,77 @@ +#include "waylandsurfacetexturematerial.h" +#include + +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 WaylandSurfaceTextureMaterial::attributes() const +{ + QList 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 WaylandSurfaceTextureOpaqueMaterial::attributes() const +{ + QList 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 0000000..ace271e --- /dev/null +++ b/src/compositor/compositor_api/waylandsurfacetexturematerial.h @@ -0,0 +1,46 @@ +#ifndef WAYLANDSURFACETEXTUREMATERIAL_H +#define WAYLANDSURFACETEXTUREMATERIAL_H + +#include +#include +#include + +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 +{ + QSG_DECLARE_SIMPLE_SHADER(WaylandSurfaceTextureMaterial, WaylandSurfaceTextureState) + public: + + QList attributes() const; + + void updateState(const WaylandSurfaceTextureState *newState, const WaylandSurfaceTextureState *oldState); +protected: + const char *vertexShader() const; + const char *fragmentShader() const; +}; + +class WaylandSurfaceTextureOpaqueMaterial : public QSGSimpleMaterialShader +{ + QSG_DECLARE_SIMPLE_SHADER(WaylandSurfaceTextureOpaqueMaterial, WaylandSurfaceTextureState) + public: + + QList attributes() const; + + void updateState(const WaylandSurfaceTextureState *newState, const WaylandSurfaceTextureState *oldState); +protected: + const char *vertexShader() const; + const char *fragmentShader() const; +}; + +#endif // WAYLANDSURFACETEXTUREMATERIAL_H -- 2.7.4