892void QQuickMultiEffect::geometryChange(
const QRectF &newGeometry,
const QRectF &oldGeometry)
894 Q_D(QQuickMultiEffect);
895 QQuickItem::geometryChange(newGeometry, oldGeometry);
896 if (width() > 0 && height() > 0)
897 d->handleGeometryChange(newGeometry, oldGeometry);
995void QQuickMultiEffectPrivate::setBrightness(qreal brightness)
997 Q_Q(QQuickMultiEffect);
998 if (brightness == m_brightness)
1001 m_brightness = brightness;
1003 m_shaderEffect->setProperty(
"brightness", m_brightness);
1006 Q_EMIT q->brightnessChanged();
1033void QQuickMultiEffectPrivate::setSaturation(qreal saturation)
1035 Q_Q(QQuickMultiEffect);
1036 if (saturation == m_saturation)
1039 m_saturation = saturation;
1041 m_shaderEffect->setProperty(
"saturation", m_saturation);
1044 Q_EMIT q->saturationChanged();
1052void QQuickMultiEffectPrivate::setColorization(qreal colorization)
1054 Q_Q(QQuickMultiEffect);
1055 if (colorization == m_colorization)
1058 m_colorization = colorization;
1059 updateColorizationColor();
1062 Q_EMIT q->colorizationChanged();
1070void QQuickMultiEffectPrivate::setColorizationColor(
const QColor &color)
1072 Q_Q(QQuickMultiEffect);
1073 if (color == m_colorizationColor)
1076 m_colorizationColor = color;
1077 updateColorizationColor();
1080 Q_EMIT q->colorizationColorChanged();
1149void QQuickMultiEffectPrivate::setBlurMultiplier(qreal blurMultiplier)
1151 Q_Q(QQuickMultiEffect);
1152 if (blurMultiplier == m_blurMultiplier)
1155 m_blurMultiplier = blurMultiplier;
1156 updateSourcePadding();
1157 updateBlurItemSizes(
true);
1158 updateBlurWeights();
1159 updateShadowBlurWeights();
1162 Q_EMIT q->blurMultiplierChanged();
1208void QQuickMultiEffectPrivate::setShadowBlur(qreal shadowBlur)
1210 Q_Q(QQuickMultiEffect);
1211 if (shadowBlur == m_shadowBlur)
1214 m_shadowBlur = shadowBlur;
1215 updateShadowBlurWeights();
1218 Q_EMIT q->shadowBlurChanged();
1280void QQuickMultiEffectPrivate::setShadowScale(qreal shadowScale)
1282 Q_Q(QQuickMultiEffect);
1283 if (shadowScale == m_shadowScale)
1286 m_shadowScale = shadowScale;
1287 updateCenterOffset();
1289 m_shaderEffect->setProperty(
"shadowScale", 1.0 / m_shadowScale);
1292 Q_EMIT q->shadowScaleChanged();
1318void QQuickMultiEffectPrivate::setMaskSource(QQuickItem *item)
1320 Q_Q(QQuickMultiEffect);
1321 if (item == m_maskSourceItem)
1324 m_maskSourceItem = item;
1325 if (m_shaderEffect) {
1326 auto maskSourceVariant = QVariant::fromValue<QQuickItem*>(m_maskSourceItem);
1327 m_shaderEffect->setProperty(
"maskSrc", maskSourceVariant);
1331 Q_EMIT q->maskSourceChanged();
1339void QQuickMultiEffectPrivate::setMaskThresholdMin(qreal threshold)
1341 Q_Q(QQuickMultiEffect);
1342 if (threshold == m_maskThresholdMin)
1345 m_maskThresholdMin = threshold;
1346 updateMaskThresholdSpread();
1349 Q_EMIT q->maskThresholdMinChanged();
1357void QQuickMultiEffectPrivate::setMaskSpreadAtMin(qreal spread)
1359 Q_Q(QQuickMultiEffect);
1360 if (spread == m_maskSpreadAtMin)
1363 m_maskSpreadAtMin = spread;
1364 updateMaskThresholdSpread();
1367 Q_EMIT q->maskSpreadAtMinChanged();
1375void QQuickMultiEffectPrivate::setMaskThresholdMax(qreal threshold)
1377 Q_Q(QQuickMultiEffect);
1378 if (threshold == m_maskThresholdMax)
1381 m_maskThresholdMax = threshold;
1382 updateMaskThresholdSpread();
1385 Q_EMIT q->maskThresholdMaxChanged();
1393void QQuickMultiEffectPrivate::setMaskSpreadAtMax(qreal spread)
1395 Q_Q(QQuickMultiEffect);
1396 if (spread == m_maskSpreadAtMax)
1399 m_maskSpreadAtMax = spread;
1400 updateMaskThresholdSpread();
1403 Q_EMIT q->maskSpreadAtMaxChanged();
1411void QQuickMultiEffectPrivate::setMaskInverted(
bool inverted)
1413 Q_Q(QQuickMultiEffect);
1414 if (inverted == m_maskInverted)
1417 m_maskInverted = inverted;
1419 m_shaderEffect->setProperty(
"maskInverted",
float(m_maskInverted));
1422 Q_EMIT q->maskInvertedChanged();
1425QRectF QQuickMultiEffectPrivate::itemRect()
const
1427 if (!m_shaderEffect || !m_shaderSource)
1430 QRectF sourceRect = m_shaderSource->sourceRect();
1431 if (sourceRect.width() > 0 && sourceRect.height() > 0)
1434 return m_shaderEffect->boundingRect();
1454void QQuickMultiEffectPrivate::initialize()
1456 Q_Q(QQuickMultiEffect);
1459 if (!q->isComponentComplete())
1463 if (q->width() <= 0 || q->height() <= 0)
1466 m_shaderEffect =
new QQuickShaderEffect(q);
1467 m_shaderSource =
new QGfxSourceProxyME(q);
1468 QObject::connect(m_shaderSource, &QGfxSourceProxyME::outputChanged, q, [
this] { proxyOutputChanged(); });
1469 QObject::connect(m_shaderSource, &QGfxSourceProxyME::activeChanged, q, &QQuickMultiEffect::hasProxySourceChanged);
1471 m_shaderEffect->setParentItem(q);
1472 m_shaderEffect->setSize(q->size());
1474 m_shaderSource->setParentItem(q);
1475 m_shaderSource->setSize(q->size());
1476 m_shaderSource->setInput(m_sourceItem);
1478 updateCenterOffset();
1479 updateMaskThresholdSpread();
1480 updateBlurWeights();
1481 updateShadowBlurWeights();
1482 updateColorizationColor();
1483 updateShadowColor();
1484 updateShadowOffset();
1487 auto sourceVariant = QVariant::fromValue<QQuickItem*>(m_shaderSource->output());
1488 m_shaderEffect->setProperty(
"src", sourceVariant);
1489 m_shaderEffect->setProperty(
"brightness", m_brightness);
1490 m_shaderEffect->setProperty(
"contrast", m_contrast);
1491 m_shaderEffect->setProperty(
"saturation", m_saturation);
1492 m_shaderEffect->setProperty(
"shadowScale", 1.0 / m_shadowScale);
1493 auto maskSourceVariant = QVariant::fromValue<QQuickItem*>(m_maskSourceItem);
1494 m_shaderEffect->setProperty(
"maskSrc", maskSourceVariant);
1495 m_shaderEffect->setProperty(
"maskInverted",
float(m_maskInverted));
1498 updateBlurItemSizes();
1499 updateSourcePadding();
1501 updateEffectShaders();
1503 m_initialized =
true;
1506void QQuickMultiEffectPrivate::updateMaskThresholdSpread()
1508 if (!m_shaderEffect)
1513 const qreal c0 = 0.0001;
1514 const qreal c1 = 1.0 - c0;
1515 const qreal mt1 = m_maskThresholdMin + c0;
1516 const qreal ms1 = m_maskSpreadAtMin + 1.0;
1517 const qreal mt2 = c1 - m_maskThresholdMax;
1518 const qreal ms2 = m_maskSpreadAtMax + 1.0;
1519 const QVector4D maskThresholdSpread = QVector4D(
1520 mt1 * ms1 - (ms1 - c1),
1522 mt2 * ms2 - (ms2 - c1),
1524 m_shaderEffect->setProperty(
"mask", maskThresholdSpread);
1527void QQuickMultiEffectPrivate::updateCenterOffset()
1529 if (!m_shaderEffect)
1532 const qreal scale = 1.0 / m_shadowScale;
1533 QVector2D centerOffset((1.0 - scale) * (0.5 + 0.5 * (m_paddingRect.x() - m_paddingRect.width()) / m_shaderEffect->width()),
1534 (1.0 - scale) * (0.5 + 0.5 * (m_paddingRect.y() - m_paddingRect.height()) / m_shaderEffect->height()));
1535 m_shaderEffect->setProperty(
"centerOffset", centerOffset);
1547void QQuickMultiEffectPrivate::updateColorizationColor()
1549 if (!m_shaderEffect)
1552 float alpha = std::clamp(
float(m_colorizationColor.alphaF() * m_colorization), 0.0f, 1.0f);
1553 QVector4D colorizationColor(m_colorizationColor.redF(),
1554 m_colorizationColor.greenF(),
1555 m_colorizationColor.blueF(),
1557 m_shaderEffect->setProperty(
"colorizationColor", colorizationColor);
1560void QQuickMultiEffectPrivate::updateShadowColor()
1562 if (!m_shaderEffect)
1566 float alpha = std::clamp(
float(m_shadowOpacity), 0.0f, 1.0f);
1567 QVector4D shadowColor(m_shadowColor.redF() * alpha,
1568 m_shadowColor.greenF() * alpha,
1569 m_shadowColor.blueF() * alpha,
1570 m_shadowColor.alphaF() * alpha);
1571 m_shaderEffect->setProperty(
"shadowColor", shadowColor);
1584void QQuickMultiEffectPrivate::getBlurWeights(
float blurLod, QVector4D &blurWeight1, QVector2D &blurWeight2)
1586 float bw1 = blurWeight(std::fabs(blurLod - 0.1f));
1587 float bw2 = blurWeight(std::fabs(blurLod - 0.3f));
1588 float bw3 = blurWeight(std::fabs(blurLod - 0.5f));
1589 float bw4 = blurWeight(std::fabs(blurLod - 0.7f));
1590 float bw5 = blurWeight(std::fabs(blurLod - 0.9f));
1591 float bw6 = blurWeight(std::fabs(blurLod - 1.1f));
1592 float bsum = bw1 + bw2 + bw3 + bw4 + bw5 + bw6;
1593 blurWeight1 = QVector4D(bw1 / bsum, bw2 / bsum, bw3 / bsum, bw4 / bsum);
1594 blurWeight2 = QVector2D(bw5 / bsum, bw6 / bsum);
1597void QQuickMultiEffectPrivate::updateBlurWeights()
1599 if (!m_shaderEffect)
1601 float blurLod = calculateLod(m_blur);
1602 getBlurWeights(blurLod, m_blurWeight1, m_blurWeight2);
1603 m_shaderEffect->setProperty(
"blurWeight1", m_blurWeight1);
1604 m_shaderEffect->setProperty(
"blurWeight2", m_blurWeight2);
1607void QQuickMultiEffectPrivate::updateShadowBlurWeights()
1609 if (!m_shaderEffect)
1611 float blurLod = calculateLod(m_shadowBlur);
1612 getBlurWeights(blurLod, m_shadowBlurWeight1, m_shadowBlurWeight2);
1613 m_shaderEffect->setProperty(
"shadowBlurWeight1", m_shadowBlurWeight1);
1614 m_shaderEffect->setProperty(
"shadowBlurWeight2", m_shadowBlurWeight2);
1617void QQuickMultiEffectPrivate::updateBlurItemSizes(
bool forceUpdate)
1619 if (m_blurEffects.isEmpty() || !m_shaderSource || !m_sourceItem)
1624 QSizeF sourceSize = itemRect().size();
1625 QSizeF firstItemSize(std::ceil(sourceSize.width() / 16) * 8,
1626 std::ceil(sourceSize.height() / 16) * 8);
1628 if (!forceUpdate && m_firstBlurItemSize == firstItemSize)
1631 qCDebug(lcQuickEffect) <<
"Source size:" << sourceSize;
1632 m_firstBlurItemSize = firstItemSize;
1634 for (
int i = 0; i < m_blurEffects.size(); i++) {
1635 auto *blurEffect = m_blurEffects[i];
1636 QSizeF itemSize = (i == 0) ? firstItemSize : m_blurEffects[i - 1]->size() * 0.5;
1637 qCDebug(lcQuickEffect) <<
"Blur item" << i <<
":" << itemSize;
1638 blurEffect->setSize(itemSize);
1640 const QVector2D offset((1.0 + m_blurMultiplier) / itemSize.width(),
1641 (1.0 + m_blurMultiplier) / itemSize.height());
1642 blurEffect->setProperty(
"offset", offset);
1646void QQuickMultiEffectPrivate::updateEffectShaders()
1648 Q_Q(QQuickMultiEffect);
1649 if (!q->isComponentComplete() || !m_shaderEffect)
1652 QString vShader = QStringLiteral(
"multieffect_c");
1653 if (m_shadowEnabled)
1654 vShader += QStringLiteral(
"s");
1656 QString fShader = QStringLiteral(
"multieffect_c");
1658 fShader += QStringLiteral(
"m");
1659 if (m_blurEnabled && m_blurMax > 0)
1660 fShader += QStringLiteral(
"b");
1661 if (m_shadowEnabled)
1662 fShader += QStringLiteral(
"s");
1664 fShader += QString::number(m_blurLevel);
1666 bool shaderChanged =
false;
1667 if (fShader != m_fragShader) {
1668 shaderChanged =
true;
1669 m_fragShader = fShader;
1670 QUrl fs = QUrl(QStringLiteral(
"qrc:/data/shaders/%1.frag.qsb").arg(m_fragShader));
1671 m_shaderEffect->setFragmentShader(fs);
1672 Q_EMIT q->fragmentShaderChanged();
1674 if (vShader != m_vertShader) {
1675 shaderChanged =
true;
1676 m_vertShader = vShader;
1677 QUrl vs = QUrl(QStringLiteral(
"qrc:/data/shaders/%1.vert.qsb").arg(m_vertShader));
1678 m_shaderEffect->setVertexShader(vs);
1679 Q_EMIT q->vertexShaderChanged();
1681 if (shaderChanged) {
1682 qCDebug(lcQuickEffect) <<
this <<
"Shaders: " << m_fragShader << m_vertShader;
1683 Q_EMIT q->shaderChanged();
1687void QQuickMultiEffectPrivate::updateBlurLevel(
bool forceUpdate)
1690 if ((m_blurEnabled || m_shadowEnabled) && m_blurMax > 0) {
1693 else if (m_blurMax > 16)
1699 if (blurLevel != m_blurLevel || (blurLevel > 0 && m_blurEffects.isEmpty()) || forceUpdate) {
1702 updateBlurItemsAmount(blurLevel);
1704 if (blurLevel > m_blurLevel)
1705 updateBlurItemSizes(
true);
1707 m_blurLevel = blurLevel;
1710void QQuickMultiEffectPrivate::updateBlurItemsAmount(
int blurLevel)
1712 Q_Q(QQuickMultiEffect);
1713 if (!m_shaderEffect)
1716 const auto engine = qmlEngine(q);
1721 int itemsAmount = blurLevel == 0 ? 0 : blurLevel + 2;
1723 if (m_blurEffects.size() < itemsAmount) {
1727 QUrl blurVs = QUrl(QStringLiteral(
"qrc:/data/shaders/bluritems.vert.qsb"));
1728 QUrl blurFs = QUrl(QStringLiteral(
"qrc:/data/shaders/bluritems.frag.qsb"));
1729 QQmlComponent blurComponent(engine, QUrl(QStringLiteral(
"qrc:/data/BlurItem.qml")));
1730 for (
int i = m_blurEffects.size(); i < itemsAmount; i++) {
1731 auto blurEffect = qobject_cast<QQuickShaderEffect*>(blurComponent.create());
1732 blurEffect->setParent(q);
1733 blurEffect->setParentItem(q);
1734 auto sourceVariant = QVariant::fromValue<QQuickItem*>(blurEffect);
1735 QString sourceProperty = QStringLiteral(
"blurSrc%1").arg(i + 1);
1736 m_shaderEffect->setProperty(sourceProperty.toUtf8(), sourceVariant);
1739 blurEffect->setProperty(
"source", sourceVariant);
1740 QQuickItemPrivate *priv = QQuickItemPrivate::get(blurEffect);
1741 priv->layer()->setEnabled(
true);
1742 priv->layer()->setSmooth(
true);
1743 blurEffect->setVertexShader(blurVs);
1744 blurEffect->setFragmentShader(blurFs);
1745 m_blurEffects << blurEffect;
1750 if (!m_dummyShaderSource)
1751 m_dummyShaderSource =
new QQuickShaderEffectSource(q);
1752 for (
int i = 0; i < m_blurEffects.size(); i++) {
1753 auto *blurEffect = m_blurEffects[i];
1754 auto sourceItem = (i >= itemsAmount) ?
1755 static_cast<QQuickItem *>(m_dummyShaderSource) : (i == 0) ?
1756 static_cast<QQuickItem *>(m_shaderSource->output()) :
1757 static_cast<QQuickItem *>(m_blurEffects[i - 1]);
1758 auto sourceVariant = QVariant::fromValue<QQuickItem*>(sourceItem);
1759 blurEffect->setProperty(
"source", sourceVariant);
1763void QQuickMultiEffectPrivate::updateSourcePadding()
1765 Q_Q(QQuickMultiEffect);
1766 if (!m_shaderEffect || !m_shaderSource)
1769 const bool blurItemsNeeded = (m_blurEnabled || m_shadowEnabled) && (m_blurMax > 0);
1770 const int itemPadding = m_autoPaddingEnabled && blurItemsNeeded ? m_blurMax * (1.0 + m_blurMultiplier) : 0;
1773 if (m_paddingRect != QRectF() || itemPadding > 0) {
1774 QRectF effectRect(-m_paddingRect.x() - itemPadding,
1775 -m_paddingRect.y() - itemPadding,
1776 q->width() + m_paddingRect.x() + m_paddingRect.width() + (itemPadding * 2),
1777 q->height() + m_paddingRect.y() + m_paddingRect.height() + (itemPadding * 2));
1778 m_shaderEffect->setX(effectRect.x());
1779 m_shaderEffect->setY(effectRect.y());
1780 m_shaderEffect->setWidth(effectRect.width());
1781 m_shaderEffect->setHeight(effectRect.height());
1784 m_shaderSource->setSize(m_shaderEffect->size());
1789 const qreal baseWidth = m_sourceItem && m_sourceItem->width() > 0 ? m_sourceItem->width() : q->width();
1790 const qreal baseHeight = m_sourceItem && m_sourceItem->height() > 0 ? m_sourceItem->height() : q->height();
1793 const qreal widthMultiplier = q->width() > 0 ? baseWidth / q->width() : 1.0;
1794 const qreal heightMultiplier = q->height() > 0 ? baseHeight / q->height() : 1.0;
1795 const qreal xPadding = itemPadding * widthMultiplier;
1796 const qreal yPadding = itemPadding * heightMultiplier;
1797 QRectF rect = QRectF(m_paddingRect.x() * widthMultiplier,
1798 m_paddingRect.y() * heightMultiplier,
1799 m_paddingRect.width() * widthMultiplier,
1800 m_paddingRect.height() * heightMultiplier);
1801 QRectF sourceRect = QRectF(-rect.x() - xPadding,
1802 -rect.y() - yPadding,
1803 baseWidth + rect.x() + rect.width() + xPadding * 2,
1804 baseHeight + rect.y() + rect.height() + yPadding * 2);
1805 m_shaderSource->setSourceRect(sourceRect);
1807 m_shaderEffect->setX(0);
1808 m_shaderEffect->setY(0);
1809 m_shaderEffect->setSize(q->size());
1810 m_shaderSource->setSize(q->size());
1811 m_shaderSource->setSourceRect(QRectF());
1814 updateShadowOffset();
1815 updateProxyActiveCheck();
1816 updateBlurItemSizes();
1817 Q_EMIT q->paddingRectChanged();
1818 Q_EMIT q->itemRectChanged();
1819 Q_EMIT q->itemSizeChanged();