712void QQuick3DTexture::setSourceItem(QQuickItem *sourceItem)
714 if (m_sourceItem == sourceItem)
717 disconnect(m_textureProviderConnection);
718 disconnect(m_textureUpdateConnection);
721 QQuickItemPrivate *sourcePrivate = QQuickItemPrivate::get(m_sourceItem);
723 const bool hide = m_sourceItemReparented;
724 sourcePrivate->derefFromEffectItem(hide);
725 m_sourceItemRefed =
false;
727 sourcePrivate->removeItemChangeListener(
this, QQuickItemPrivate::Geometry);
728 disconnect(m_sourceItem, SIGNAL(destroyed(QObject*)),
this, SLOT(sourceItemDestroyed(QObject*)));
729 disconnect(m_sourceItem, &QQuickItem::windowChanged,
this, &QQuick3DTexture::sourceItemWindowChanged);
730 if (m_sourceItemReparented) {
731 m_sourceItem->setParentItem(
nullptr);
732 m_sourceItemReparented =
false;
736 m_sourceItem = sourceItem;
739 trySetSourceParent();
740 QQuickItemPrivate *sourcePrivate = QQuickItemPrivate::get(m_sourceItem);
741 sourcePrivate->addItemChangeListener(
this, QQuickItemPrivate::Geometry);
742 connect(m_sourceItem, SIGNAL(destroyed(QObject*)),
this, SLOT(sourceItemDestroyed(QObject*)));
743 connect(m_sourceItem, &QQuickItem::windowChanged,
this, &QQuick3DTexture::sourceItemWindowChanged);
744 sourcePrivate->ensureSubsceneDeliveryAgent();
748 const auto &manager = QQuick3DObjectPrivate::get(
this)->sceneManager;
749 manager->qsgDynamicTextures.removeAll(m_layer);
750 m_sceneManagerForLayer =
nullptr;
753 m_initializedSourceItem =
nullptr;
754 m_initializedSourceItemSize = QSize();
756 m_dirtyFlags.setFlag(DirtyFlag::SourceDirty);
757 m_dirtyFlags.setFlag(DirtyFlag::SourceItemDirty);
758 m_dirtyFlags.setFlag(DirtyFlag::TextureDataDirty);
759 emit sourceItemChanged();
1066QSSGRenderGraphObject *QQuick3DTexture::updateSpatialNode(QSSGRenderGraphObject *node)
1070 node =
new QSSGRenderImage(QQuick3DObjectPrivate::get(
this)->type);
1072 QQuick3DObject::updateSpatialNode(node);
1073 auto imageNode =
static_cast<QSSGRenderImage *>(node);
1075 if (m_dirtyFlags.testFlag(DirtyFlag::TransformDirty)) {
1076 m_dirtyFlags.setFlag(DirtyFlag::TransformDirty,
false);
1079 imageNode->m_flipU = m_flipU;
1080 imageNode->m_scale = QVector2D(m_scaleU, m_scaleV);
1081 imageNode->m_pivot = QVector2D(m_pivotU, m_pivotV);
1082 imageNode->m_rotation = m_rotationUV;
1083 imageNode->m_position = QVector2D(m_positionU, m_positionV);
1085 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::TransformDirty);
1088 bool nodeChanged =
false;
1089 if (m_dirtyFlags.testFlag(DirtyFlag::SourceDirty)) {
1090 m_dirtyFlags.setFlag(DirtyFlag::SourceDirty,
false);
1091 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1092 if (!m_source.isEmpty()) {
1093 const QQmlContext *context = qmlContext(
this);
1094 imageNode->m_imagePath = resolveImagePath(m_source, context);
1096 imageNode->m_imagePath = QSSGRenderPath();
1100 if (m_dirtyFlags.testFlag(DirtyFlag::IndexUVDirty)) {
1101 m_dirtyFlags.setFlag(DirtyFlag::IndexUVDirty,
false);
1102 imageNode->m_indexUV = m_indexUV;
1104 nodeChanged |= qUpdateIfNeeded(imageNode->m_mappingMode,
1105 QSSGRenderImage::MappingModes(m_mappingMode));
1106 nodeChanged |= qUpdateIfNeeded(imageNode->m_horizontalTilingMode,
1107 QSSGRenderTextureCoordOp(m_tilingModeHorizontal));
1108 nodeChanged |= qUpdateIfNeeded(imageNode->m_verticalTilingMode,
1109 QSSGRenderTextureCoordOp(m_tilingModeVertical));
1110 nodeChanged |= qUpdateIfNeeded(imageNode->m_depthTilingMode,
1111 QSSGRenderTextureCoordOp(m_tilingModeDepth));
1113 if (m_dirtyFlags.testFlag(DirtyFlag::SamplerDirty)) {
1114 m_dirtyFlags.setFlag(DirtyFlag::SamplerDirty,
false);
1115 nodeChanged |= qUpdateIfNeeded(imageNode->m_minFilterType,
1116 QSSGRenderTextureFilterOp(m_minFilter));
1117 nodeChanged |= qUpdateIfNeeded(imageNode->m_magFilterType,
1118 QSSGRenderTextureFilterOp(m_magFilter));
1119 nodeChanged |= qUpdateIfNeeded(imageNode->m_mipFilterType,
1120 QSSGRenderTextureFilterOp(m_mipFilter));
1121 nodeChanged |= qUpdateIfNeeded(imageNode->m_generateMipmaps,
1125 if (m_dirtyFlags.testFlag(DirtyFlag::TextureDataDirty)) {
1126 m_dirtyFlags.setFlag(DirtyFlag::TextureDataDirty,
false);
1127 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1129 imageNode->m_rawTextureData =
static_cast<QSSGRenderTextureData *>(QQuick3DObjectPrivate::get(m_textureData)->spatialNode);
1131 imageNode->m_rawTextureData =
nullptr;
1135 if (m_dirtyFlags.testFlag(DirtyFlag::ExtensionDirty)) {
1136 bool extDirty =
false;
1137 if (m_renderExtension) {
1138 auto *sn = QQuick3DObjectPrivate::get(m_renderExtension)->spatialNode;
1141 extDirty = (sn ==
nullptr);
1142 if (sn && QSSG_GUARD(QSSGRenderGraphObject::isExtension(sn->type)))
1143 imageNode->m_extensionsSource =
static_cast<QSSGRenderExtension *>(sn);
1146 m_dirtyFlags.setFlag(DirtyFlag::ExtensionDirty, extDirty);
1147 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1152 if (m_dirtyFlags.testFlag(DirtyFlag::SourceItemDirty)) {
1153 m_dirtyFlags.setFlag(DirtyFlag::SourceItemDirty,
false);
1154 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1156 QQuickWindow *window = m_sourceItem->window();
1163 window = QQuick3DObjectPrivate::get(
this)->sceneManager->window();
1165 QQuickItemPrivate::get(m_sourceItem)->refWindow(window);
1167 qWarning(
"Unable to get window, this will probably not work");
1173 const bool isHiddenView3D = !m_sourceItem->isVisible() && (qobject_cast<QQuick3DViewport *>(m_sourceItem) !=
nullptr);
1177 if (QSGTextureProvider *provider = m_sourceItem->textureProvider(); provider !=
nullptr && !isHiddenView3D) {
1178 imageNode->m_qsgTexture = provider->texture();
1180 disconnect(m_textureProviderConnection);
1181 m_textureProviderConnection = connect(provider, &QSGTextureProvider::textureChanged,
this, [
this, provider] () {
1187 auto imageNode =
static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(
this)->spatialNode);
1191 imageNode->m_qsgTexture = provider->texture();
1193 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::Dirty);
1198 QMetaObject::invokeMethod(
this, &QQuick3DTexture::update, Qt::AutoConnection);
1199 }, Qt::DirectConnection);
1201 disconnect(m_textureUpdateConnection);
1202 auto *sourcePrivate = QQuickItemPrivate::get(m_sourceItem);
1203 if (sourcePrivate->window) {
1204 QQuickItem *sourceItem = m_sourceItem;
1221 m_textureUpdateConnection = connect(sourcePrivate->window, &QQuickWindow::afterSynchronizing,
this, [
this, sourceItem]() {
1223 if (m_sourceItem != sourceItem) {
1224 disconnect(m_textureProviderConnection);
1225 disconnect(m_textureUpdateConnection);
1228 auto imageNode =
static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(
this)->spatialNode);
1232 if (QSGDynamicTexture *t = qobject_cast<QSGDynamicTexture *>(imageNode->m_qsgTexture)) {
1233 if (t->updateTexture())
1236 }, Qt::DirectConnection);
1238 qWarning(
"No window for item, texture updates are doomed");
1248 if (m_initializedSourceItem != m_sourceItem || m_initializedSourceItemSize != m_sourceItem->size()) {
1253 m_layer->setItem(
nullptr);
1255 m_initializedSourceItem = m_sourceItem;
1256 m_initializedSourceItemSize = m_sourceItem->size();
1260 connect(window, &QQuickWindow::afterSynchronizing,
this, [
this, window]() {
1261 auto imageNode =
static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(
this)->spatialNode);
1266 disconnect(window, &QQuickWindow::afterSynchronizing,
this,
nullptr);
1268 const auto &manager = QQuick3DObjectPrivate::get(
this)->sceneManager;
1269 manager->qsgDynamicTextures.removeAll(m_layer);
1274 QQuickItemPrivate *sourcePrivate = QQuickItemPrivate::get(m_sourceItem);
1275 QSGRenderContext *rc = sourcePrivate->sceneGraphRenderContext();
1276 Q_ASSERT(QThread::currentThread() == rc->thread());
1277 QSGLayer *layer = rc->sceneGraphContext()->createLayer(rc);
1278 connect(sourcePrivate->window, SIGNAL(sceneGraphInvalidated()), layer, SLOT(invalidated()), Qt::DirectConnection);
1280 QQuick3DSceneManager *manager = QQuick3DObjectPrivate::get(
this)->sceneManager;
1281 manager->qsgDynamicTextures << layer;
1282 m_sceneManagerForLayer = manager;
1284 connect(layer, &QObject::destroyed, manager, [manager, layer]()
1287 manager->qsgDynamicTextures.removeAll(layer);
1288 }, Qt::DirectConnection);
1290 QQuickItem *sourceItem = m_sourceItem;
1291 connect(layer, &QObject::destroyed,
this, [
this, sourceItem]()
1294 if (m_initializedSourceItem == sourceItem) {
1295 m_sceneManagerForLayer =
nullptr;
1296 m_initializedSourceItem =
nullptr;
1298 }, Qt::DirectConnection);
1309 m_textureUpdateConnection = connect(sourcePrivate->window, &QQuickWindow::afterSynchronizing,
1310 this, [
this, sourceItem]()
1315 if (m_sourceItem != sourceItem) {
1316 disconnect(m_textureUpdateConnection);
1319 if (m_layer->updateTexture())
1321 }, Qt::DirectConnection);
1324 m_layer->setItem(QQuickItemPrivate::get(m_sourceItem)->itemNode());
1326 QRectF sourceRect = QRectF(0, 0, m_sourceItem->width(), m_sourceItem->height());
1327 if (qFuzzyIsNull(sourceRect.width()))
1328 sourceRect.setWidth(256);
1329 if (qFuzzyIsNull(sourceRect.height()))
1330 sourceRect.setHeight(256);
1331 m_layer->setRect(sourceRect);
1333 QSize textureSize(qCeil(qAbs(sourceRect.width())), qCeil(qAbs(sourceRect.height())));
1334 const QSize minTextureSize = sourcePrivate->sceneGraphContext()->minimumFBOSize();
1335 while (textureSize.width() < minTextureSize.width())
1336 textureSize.rwidth() *= 2;
1337 while (textureSize.height() < minTextureSize.height())
1338 textureSize.rheight() *= 2;
1339 m_layer->setSize(textureSize);
1342 m_layer->updateTexture();
1344 imageNode->m_qsgTexture = m_layer;
1345 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::Dirty);
1346 }, Qt::DirectConnection);
1351 m_layer->setItem(
nullptr);
1355 imageNode->m_qsgTexture =
nullptr;
1360 if (m_dirtyFlags.testFlag(DirtyFlag::FlipVDirty)) {
1361 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
false);
1362 imageNode->m_flipV = effectiveFlipV(*imageNode);
1363 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::TransformDirty);
1367 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::Dirty);