Skip to content

Commit

Permalink
feat: add "compositionMode" property in ItemViewport
Browse files Browse the repository at this point in the history
Fix InWindowBlur not effect if the backdrop content has alpha channel.
  • Loading branch information
zccrs authored and 18202781743 committed Apr 29, 2024
1 parent b8a9035 commit c7276ae
Show file tree
Hide file tree
Showing 13 changed files with 236 additions and 5 deletions.
13 changes: 13 additions & 0 deletions docs/qml/noqml/dqmlglobalobject.zh_CN.dox
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,19 @@
\li \l{DTK::setPopupMode()}{DTK.setPopupMode()}
\endlist\m

@enum Dtk::Declarative::DTK::CompositionMode
@brief 合成模式,与 @sa QPainter::CompositionMode 等价。
@var DTK::CompositionMode::Source
@brief 与 @sa QPainter::CompositionMode_Source 等价
@var DTK::CompositionMode::SourceOver
@brief 与 @sa QPainter::CompositionMode_SourceOver 等价
@var DTK::CompositionMode::Destination
@brief 与 @sa QPainter::CompositionMode_Destination 等价
@var DTK::CompositionMode::DestinationOver
@brief 与 @sa QPainter::CompositionMode_DestinationOver 等价
@var DTK::CompositionMode::Clear
@brief 与 @sa QPainter::CompositionMode_Clear 等价

@property bool DTK::hasBlurWindow
@note 此属性为只读属性

Expand Down
5 changes: 5 additions & 0 deletions docs/qml/noqml/dquickitemviewport.zh_CN.dox
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,8 @@
则表示隐藏 sourceItem 的内容,即隐藏源控件的样式,展示 ItemViewport 的内容,即加工
后的内容。默认情况下,该属性为 false.

@property DTK::CompositionMode ItemViewport::compositionMode
@brief 用于控制合成时所使用的混合模式。
@details 此属性与 @sa QPainter::setCompositionMode 功能类似,请参考其文档介绍。

*/
13 changes: 13 additions & 0 deletions qt6/src/qml/FloatingPanel.qml
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,19 @@ Control {
hideSource: false
}

Loader {
anchors.fill: parent
active: Window.window && Window.window.color.a < 1
sourceComponent: D.ItemViewport {
anchors.fill: parent
fixed: true
sourceItem: blur.content
radius: control.radius
hideSource: false
compositionMode: DTK.CompositionMode.Source
}
}

Loader {
anchors.fill: backgroundRect
active: control.dropShadowColor
Expand Down
7 changes: 5 additions & 2 deletions qt6/src/shaders_ng/quickitemviewport-opaque.frag
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,13 @@ void main()
lowp vec4 mask_bottom_left = texture(mask, tex_bottom_left);
lowp vec4 mask_top_right = texture(mask, tex_top_right);
lowp vec4 mask_bottom_right = texture(mask, tex_bottom_right);
lowp vec4 mask_tex = mask_top_left * mask_bottom_left * mask_top_right * mask_bottom_right;

lowp vec4 tex = texture(qt_Texture, qt_TexCoord);
if (mask_tex.a < 1.0)
discard;

lowp vec4 tex = texture(qt_Texture, qt_TexCoord);
// 统一计算此像素点被模板遮盖后的颜色,此处不需要区分点是否在某个区域,不在此区域时取出的mask颜色的alpha值必为1
tex *= mask_top_left * mask_bottom_left * mask_top_right * mask_bottom_right;
tex *= mask_tex;
fragColor = tex * tex.a;
}
4 changes: 4 additions & 0 deletions qt6/src/shaders_ng/quickitemviewport.frag
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,10 @@ void main()
lowp vec4 mask_bottom_left = texture(mask, tex_bottom_left);
lowp vec4 mask_top_right = texture(mask, tex_top_right);
lowp vec4 mask_bottom_right = texture(mask, tex_bottom_right);
lowp vec4 mask_tex = mask_top_left * mask_bottom_left * mask_top_right * mask_bottom_right;

if (mask_tex.a == 0.0)
discard;

lowp vec4 tex = texture(qt_Texture, qt_TexCoord);

Expand Down
41 changes: 41 additions & 0 deletions src/dquickitemviewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,34 @@ QSGTextureProvider *DQuickItemViewport::textureProvider() const
return d->provider;
}

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QPainter::CompositionMode DQuickItemViewport::compositionMode() const
{
D_DC(DQuickItemViewport);
return d->compositionMode;
}

void DQuickItemViewport::setCompositionMode(QPainter::CompositionMode newCompositionMode)
{
D_D(DQuickItemViewport);
if (d->compositionMode == newCompositionMode)
return;

if (d->compositionMode == DQuickItemViewportPrivate::DefaultCompositionMode
|| newCompositionMode == DQuickItemViewportPrivate::DefaultCompositionMode) {
d->markDirty(DQuickItemViewportPrivate::DirtyContentNode);
}

d->compositionMode = newCompositionMode;
Q_EMIT compositionModeChanged();
}

void DQuickItemViewport::resetCompositionMode()
{
setCompositionMode(DQuickItemViewportPrivate::DefaultCompositionMode);
}
#endif

void DQuickItemViewport::invalidateSceneGraph()
{
D_D(DQuickItemViewport);
Expand Down Expand Up @@ -462,6 +490,13 @@ QSGNode *DQuickItemViewport::updatePaintNode(QSGNode *old, QQuickItem::UpdatePai
QSGImageNode *imageNode = preNode->imageNode;
DSoftwareRoundedImageNode *softwareNode = preNode->softwareNode;
const bool useMaskNode = d->needMaskNode();
const bool usingMaskNode = preNode->maskNode || preNode->softwareNode;

if (useMaskNode != usingMaskNode) {
Q_ASSERT(!preNode->maskNode);
Q_ASSERT(!preNode->softwareNode);
}

if (Q_UNLIKELY(!imageNode && !softwareNode) && Q_LIKELY(tp->texture())) {
if (useMaskNode) {
// 创建image node
Expand Down Expand Up @@ -502,11 +537,17 @@ QSGNode *DQuickItemViewport::updatePaintNode(QSGNode *old, QQuickItem::UpdatePai
maskNode->setSourceScale(d->getSoureSizeRatio());
maskNode->setMaskTexture(d->textureForRadiusMask());
maskNode->setMaskScale(d->getMaskSizeRatio());
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
maskNode->setCompositionMode(d->compositionMode);
#endif
}
} else if (softwareNode) {
softwareNode->setSmooth(smooth());
softwareNode->setRect(QRectF(QPointF(0, 0), size()));
softwareNode->setRadius(d->radius);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
softwareNode->setCompositionMode(d->compositionMode);
#endif
d->updateSourceRect(softwareNode);
}

Expand Down
15 changes: 15 additions & 0 deletions src/dquickitemviewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
#include <DObject>

#include <QQuickItem>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QPainter>
#endif

DQUICK_BEGIN_NAMESPACE

Expand All @@ -21,6 +24,9 @@ class DQuickItemViewport : public QQuickItem, public DCORE_NAMESPACE::DObject
Q_PROPERTY(float radius READ radius WRITE setRadius NOTIFY radiusChanged)
Q_PROPERTY(bool fixed READ fixed WRITE setFixed NOTIFY fixedChanged)
Q_PROPERTY(bool hideSource READ hideSource WRITE setHideSource NOTIFY hideSourceChanged)
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
Q_PROPERTY(QPainter::CompositionMode compositionMode READ compositionMode WRITE setCompositionMode NOTIFY compositionModeChanged RESET resetCompositionMode)
#endif
D_DECLARE_PRIVATE(DQuickItemViewport)
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QML_NAMED_ELEMENT(ItemViewport)
Expand Down Expand Up @@ -48,12 +54,21 @@ class DQuickItemViewport : public QQuickItem, public DCORE_NAMESPACE::DObject
bool isTextureProvider() const override { return true; }
QSGTextureProvider *textureProvider() const override;

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QPainter::CompositionMode compositionMode() const;
void setCompositionMode(QPainter::CompositionMode newCompositionMode);
void resetCompositionMode();
#endif

Q_SIGNALS:
void sourceItemChanged();
void sourceRectChanged();
void radiusChanged();
void fixedChanged();
void hideSourceChanged();
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void compositionModeChanged();
#endif

private Q_SLOTS:
void invalidateSceneGraph();
Expand Down
84 changes: 82 additions & 2 deletions src/private/dmaskeffectnode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ class OpaqueTextureMaterialShader : public QSGOpaqueTextureMaterialRhiShader
public:
OpaqueTextureMaterialShader();

bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
bool updateUniformData(RenderState &state, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;

void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial);
void updateSampledImage(RenderState &state, int binding, QSGTexture **texture, QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
bool updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial) override;
};
#endif

Expand Down Expand Up @@ -69,6 +71,7 @@ OpaqueTextureMaterialShader::OpaqueTextureMaterialShader()
#else
setShaderFileName(QSGMaterialShader::VertexStage, QStringLiteral(":/dtk/declarative/shaders_ng/quickitemviewport-opaque.vert.qsb"));
setShaderFileName(QSGMaterialShader::FragmentStage, QStringLiteral(":/dtk/declarative/shaders_ng/quickitemviewport-opaque.frag.qsb"));
setFlag(UpdatesGraphicsPipelineState);
#endif
}

Expand Down Expand Up @@ -212,6 +215,25 @@ void OpaqueTextureMaterialShader::updateSampledImage(RenderState &state, int bin
t->commitTextureOperations(state.rhi(), state.resourceUpdateBatch());
*texture = t;
}

bool OpaqueTextureMaterialShader::updateGraphicsPipelineState(RenderState &state, GraphicsPipelineState *ps,
QSGMaterial *newMaterial, QSGMaterial *oldMaterial)
{
auto material = static_cast<OpaqueTextureMaterial*>(newMaterial);
if (!material)
return QSGOpaqueTextureMaterialRhiShader::updateGraphicsPipelineState(state, ps, newMaterial, oldMaterial);

bool changed = false;

if (material->blendSrcColor() != ps->srcColor || material->blendDstColor() != ps->dstColor) {
ps->srcColor = material->blendSrcColor();
ps->dstColor = material->blendDstColor();
changed = true;
}

changed = QSGOpaqueTextureMaterialRhiShader::updateGraphicsPipelineState(state, ps, newMaterial, oldMaterial) || changed;
return changed;
}
#endif

TextureMaterialShader::TextureMaterialShader()
Expand Down Expand Up @@ -366,6 +388,46 @@ void MaskEffectNode::setSourceScale(QVector2D sourceScale)
markDirty(DirtyMaterial);
}

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void MaskEffectNode::setCompositionMode(QPainter::CompositionMode mode)
{
if (m_compositionMode == mode)
return;
m_compositionMode = mode;

QSGMaterialShader::GraphicsPipelineState::BlendFactor srcColor
= QSGMaterialShader::GraphicsPipelineState::BlendFactor::One;
QSGMaterialShader::GraphicsPipelineState::BlendFactor dstColor
= QSGMaterialShader::GraphicsPipelineState::BlendFactor::OneMinusSrcAlpha;

switch (mode) {
case QPainter::CompositionMode_Source:
dstColor = QSGMaterialShader::GraphicsPipelineState::BlendFactor::Zero;
break;
case QPainter::CompositionMode_Destination:
srcColor = QSGMaterialShader::GraphicsPipelineState::BlendFactor::Zero;
dstColor = QSGMaterialShader::GraphicsPipelineState::BlendFactor::One;
break;
case QPainter::CompositionMode_DestinationOver:
srcColor = QSGMaterialShader::GraphicsPipelineState::BlendFactor::OneMinusDstAlpha;
dstColor = QSGMaterialShader::GraphicsPipelineState::BlendFactor::One;
break;
case QPainter::CompositionMode_Clear:
srcColor = QSGMaterialShader::GraphicsPipelineState::BlendFactor::Zero;
dstColor = QSGMaterialShader::GraphicsPipelineState::BlendFactor::Zero;
break;
default: break;
}

m_material.setBlendSrcColor(srcColor);
m_material.setBlendDstColor(dstColor);
m_opaque_material.setBlendSrcColor(srcColor);
m_opaque_material.setBlendDstColor(dstColor);

markDirty(DirtyForceUpdate);
}
#endif

QSGTexture::AnisotropyLevel MaskEffectNode::anisotropyLevel() const
{
return m_material.anisotropyLevel();
Expand Down Expand Up @@ -549,4 +611,22 @@ void OpaqueTextureMaterial::setSourceScale(QVector2D sourceScale)
m_sourceScale = sourceScale;
}

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void OpaqueTextureMaterial::setBlendSrcColor(QSGMaterialShader::GraphicsPipelineState::BlendFactor factor)
{
if (m_blendSrcColor == factor)
return;

m_blendSrcColor = factor;
}

void OpaqueTextureMaterial::setBlendDstColor(QSGMaterialShader::GraphicsPipelineState::BlendFactor factor)
{
if (m_blendDstColor == factor)
return;

m_blendDstColor = factor;
}
#endif

DQUICK_END_NAMESPACE
23 changes: 23 additions & 0 deletions src/private/dmaskeffectnode_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include <QSGImageNode>
#include <QPointer>
#include <QPainter>

DQUICK_BEGIN_NAMESPACE

Expand Down Expand Up @@ -38,11 +39,26 @@ class OpaqueTextureMaterial : public QSGOpaqueTextureMaterial
void setSourceScale(QVector2D sourceScale);
QVector2D sourceScale() const { return m_sourceScale; }

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QSGMaterialShader::GraphicsPipelineState::BlendFactor blendSrcColor() const
{ return m_blendSrcColor; }

QSGMaterialShader::GraphicsPipelineState::BlendFactor blendDstColor() const
{ return m_blendDstColor; }

void setBlendSrcColor(QSGMaterialShader::GraphicsPipelineState::BlendFactor factor);
void setBlendDstColor(QSGMaterialShader::GraphicsPipelineState::BlendFactor factor);
#endif

private:
QPointer<QSGTexture> m_maskTexture = nullptr;
QVector2D m_maskScale;
QVector2D m_maskOffset;
QVector2D m_sourceScale;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QSGMaterialShader::GraphicsPipelineState::BlendFactor m_blendSrcColor = QSGMaterialShader::GraphicsPipelineState::One;
QSGMaterialShader::GraphicsPipelineState::BlendFactor m_blendDstColor = QSGMaterialShader::GraphicsPipelineState::OneMinusSrcAlpha;
#endif
};

class TextureMaterial : public OpaqueTextureMaterial
Expand Down Expand Up @@ -90,6 +106,9 @@ class MaskEffectNode : public QSGImageNode
void setMaskScale(QVector2D maskScale);
void setMaskOffset(QVector2D maskOffset);
void setSourceScale(QVector2D sourceScale);
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
void setCompositionMode(QPainter::CompositionMode mode);
#endif

QSGTexture::AnisotropyLevel anisotropyLevel() const;
private:
Expand All @@ -99,6 +118,10 @@ class MaskEffectNode : public QSGImageNode
QRectF m_rect;
QRectF m_sourceRect;
TextureCoordinatesTransformMode m_texCoordMode;
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QPainter::CompositionMode m_compositionMode = QPainter::CompositionMode_SourceOver;
#endif

uint m_isAtlasTexture : 1;
uint m_ownsTexture : 1;
};
Expand Down
14 changes: 14 additions & 0 deletions src/private/dqmlglobalobject_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@

#include <QQuickWindow>
#include <QQmlComponent>
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
#include <QPainter>
#endif

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
QT_BEGIN_NAMESPACE
Expand Down Expand Up @@ -175,6 +178,17 @@ class DQMLGlobalObject : public QObject, public DTK_CORE_NAMESPACE::DObject
};
Q_ENUM(PopupMode)

#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
enum class CompositionMode {
Source = QPainter::CompositionMode_Source,
SourceOver = QPainter::CompositionMode_SourceOver,
Destination = QPainter::CompositionMode_Destination,
DestinationOver = QPainter::CompositionMode_DestinationOver,
Clear = QPainter::CompositionMode_Clear,
};
Q_ENUM(CompositionMode)
#endif

bool hasBlurWindow() const;
bool hasComposite() const;
bool hasNoTitlebar() const;
Expand Down
Loading

0 comments on commit c7276ae

Please sign in to comment.