167QQuickShaderEffectSource::~QQuickShaderEffectSource()
170 window()->scheduleRenderJob(
new QQuickShaderEffectSourceCleanup(m_texture, m_provider),
171 QQuickWindow::AfterSynchronizingStage);
175 Q_ASSERT(!m_texture);
176 Q_ASSERT(!m_provider);
180 QQuickItemPrivate *sd = QQuickItemPrivate::get(m_sourceItem);
181 sd->removeItemChangeListener(
this, QQuickItemPrivate::Geometry);
182 sd->derefFromEffectItem(m_hideSource);
208QSGTextureProvider *QQuickShaderEffectSource::textureProvider()
const
210 const QQuickItemPrivate *d = QQuickItemPrivate::get(
this);
211 if (!d->window || !d->sceneGraphRenderContext() || QThread::currentThread() != d->sceneGraphRenderContext()->thread()) {
212 qWarning(
"QQuickShaderEffectSource::textureProvider: can only be queried on the rendering thread of an exposed window");
217 const_cast<QQuickShaderEffectSource *>(
this)->m_provider =
new QQuickShaderEffectSourceTextureProvider();
218 const_cast<QQuickShaderEffectSource *>(
this)->ensureTexture();
219 connect(m_texture, SIGNAL(updateRequested()), m_provider, SIGNAL(textureChanged()));
221 get_wrap_mode(m_wrapMode, &m_provider->horizontalWrap, &m_provider->verticalWrap);
222 m_provider->mipmapFiltering = mipmap() ? QSGTexture::Linear : QSGTexture::None;
223 m_provider->filtering = smooth() ? QSGTexture::Linear : QSGTexture::Nearest;
224 m_provider->sourceTexture = m_texture;
282void QQuickShaderEffectSource::setSourceItem(QQuickItem *item)
284 if (item == m_sourceItem)
287 QQuickItemPrivate *d = QQuickItemPrivate::get(m_sourceItem);
288 d->derefFromEffectItem(m_hideSource);
289 d->removeItemChangeListener(
this, QQuickItemPrivate::Geometry);
290 disconnect(m_sourceItem, SIGNAL(destroyed(QObject*)),
this, SLOT(sourceItemDestroyed(QObject*)));
298 if (window() == m_sourceItem->window()
299 || (window() ==
nullptr && m_sourceItem->window())
300 || (m_sourceItem->window() ==
nullptr && window())) {
301 QQuickItemPrivate *d = QQuickItemPrivate::get(item);
307 d->refWindow(window());
308 else if (m_sourceItem->window())
309 d->refWindow(m_sourceItem->window());
310 d->refFromEffectItem(m_hideSource);
311 d->addItemChangeListener(
this, QQuickItemPrivate::Geometry);
312 connect(m_sourceItem, SIGNAL(destroyed(QObject*)),
this, SLOT(sourceItemDestroyed(QObject*)));
314 qWarning(
"ShaderEffectSource: sourceItem and ShaderEffectSource must both be children of the same window.");
315 m_sourceItem =
nullptr;
319 emit sourceItemChanged();
599static void get_wrap_mode(QQuickShaderEffectSource::WrapMode mode, QSGTexture::WrapMode *hWrap, QSGTexture::WrapMode *vWrap)
602 case QQuickShaderEffectSource::RepeatHorizontally:
603 *hWrap = QSGTexture::Repeat;
604 *vWrap = QSGTexture::ClampToEdge;
606 case QQuickShaderEffectSource::RepeatVertically:
607 *vWrap = QSGTexture::Repeat;
608 *hWrap = QSGTexture::ClampToEdge;
610 case QQuickShaderEffectSource::Repeat:
611 *hWrap = *vWrap = QSGTexture::Repeat;
615 *hWrap = *vWrap = QSGTexture::ClampToEdge;
658QSGNode *QQuickShaderEffectSource::updatePaintNode(QSGNode *oldNode, UpdatePaintNodeData *)
660 if (!m_sourceItem || m_sourceItem->width() <= 0 || m_sourceItem->height() <= 0) {
662 m_texture->setItem(
nullptr);
669 m_texture->setLive(m_live);
670 m_texture->setItem(QQuickItemPrivate::get(m_sourceItem)->itemNode());
671 QRectF sourceRect = m_sourceRect.width() == 0 || m_sourceRect.height() == 0
672 ? QRectF(0, 0, m_sourceItem->width(), m_sourceItem->height())
674 m_texture->setRect(sourceRect);
675 QQuickItemPrivate *d =
static_cast<QQuickItemPrivate *>(QObjectPrivate::get(
this));
676 const float dpr = d->effectiveDevicePixelRatio();
677 QSize textureSize = m_textureSize.isEmpty()
678 ? QSize(qCeil(qAbs(sourceRect.width())), qCeil(qAbs(sourceRect.height()))) * dpr
680 Q_ASSERT(!textureSize.isEmpty());
682 const QSize minTextureSize = d->sceneGraphContext()->minimumFBOSize();
684 while (textureSize.width() < minTextureSize.width())
685 textureSize.rwidth() *= 2;
686 while (textureSize.height() < minTextureSize.height())
687 textureSize.rheight() *= 2;
689 m_texture->setDevicePixelRatio(d->effectiveDevicePixelRatio());
690 m_texture->setSize(textureSize);
691 m_texture->setRecursive(m_recursive);
692 m_texture->setFormat(toLayerFormat(m_format));
693 m_texture->setHasMipmaps(m_mipmap);
694 m_texture->setMirrorHorizontal(m_textureMirroring & MirrorHorizontally);
695 m_texture->setMirrorVertical(m_textureMirroring & MirrorVertically);
696 m_texture->setSamples(m_samples);
699 m_texture->scheduleUpdate();
702 QSGTexture::Filtering filtering = QQuickItemPrivate::get(
this)->smooth
704 : QSGTexture::Nearest;
705 QSGTexture::Filtering mmFiltering = m_mipmap ? filtering : QSGTexture::None;
706 QSGTexture::WrapMode hWrap, vWrap;
707 get_wrap_mode(m_wrapMode, &hWrap, &vWrap);
710 m_provider->mipmapFiltering = mmFiltering;
711 m_provider->filtering = filtering;
712 m_provider->horizontalWrap = hWrap;
713 m_provider->verticalWrap = vWrap;
717 if (width() <= 0 || height() <= 0) {
722 QSGInternalImageNode *node =
static_cast<QSGInternalImageNode *>(oldNode);
724 node = d->sceneGraphContext()->createInternalImageNode(d->sceneGraphRenderContext());
725 node->setFlag(QSGNode::UsePreprocess);
726 node->setTexture(m_texture);
727 QQuickShaderSourceAttachedNode *attached =
new QQuickShaderSourceAttachedNode;
728 node->appendChildNode(attached);
729 connect(m_texture, SIGNAL(updateRequested()), attached, SLOT(markTextureDirty()));
733 if (m_live && m_recursive)
734 node->markDirty(QSGNode::DirtyMaterial);
736 node->setMipmapFiltering(mmFiltering);
737 node->setFiltering(filtering);
738 node->setHorizontalWrapMode(hWrap);
739 node->setVerticalWrapMode(vWrap);
742 qreal fx = std::modf(x(), &dummy);
743 qreal fy = std::modf(y(), &dummy);
744 QRectF targetRect(0, 0, qCeil(fx) + qCeil(width()), qCeil(fy) + qCeil(height()));
745 node->setTargetRect(targetRect);
746 node->setInnerTargetRect(targetRect);