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 if (m_sourceItemReparented) {
730 m_sourceItem->setParentItem(
nullptr);
731 m_sourceItemReparented =
false;
735 m_sourceItem = sourceItem;
738 trySetSourceParent();
739 QQuickItemPrivate *sourcePrivate = QQuickItemPrivate::get(m_sourceItem);
740 sourcePrivate->addItemChangeListener(
this, QQuickItemPrivate::Geometry);
741 connect(m_sourceItem, SIGNAL(destroyed(QObject*)),
this, SLOT(sourceItemDestroyed(QObject*)));
742 sourcePrivate->ensureSubsceneDeliveryAgent();
746 const auto &manager = QQuick3DObjectPrivate::get(
this)->sceneManager;
747 manager->qsgDynamicTextures.removeAll(m_layer);
748 m_sceneManagerForLayer =
nullptr;
751 m_initializedSourceItem =
nullptr;
752 m_initializedSourceItemSize = QSize();
754 m_dirtyFlags.setFlag(DirtyFlag::SourceDirty);
755 m_dirtyFlags.setFlag(DirtyFlag::SourceItemDirty);
756 m_dirtyFlags.setFlag(DirtyFlag::TextureDataDirty);
757 emit sourceItemChanged();
1064QSSGRenderGraphObject *QQuick3DTexture::updateSpatialNode(QSSGRenderGraphObject *node)
1068 node =
new QSSGRenderImage(QQuick3DObjectPrivate::get(
this)->type);
1070 QQuick3DObject::updateSpatialNode(node);
1071 auto imageNode =
static_cast<QSSGRenderImage *>(node);
1073 if (m_dirtyFlags.testFlag(DirtyFlag::TransformDirty)) {
1074 m_dirtyFlags.setFlag(DirtyFlag::TransformDirty,
false);
1077 imageNode->m_flipU = m_flipU;
1078 imageNode->m_scale = QVector2D(m_scaleU, m_scaleV);
1079 imageNode->m_pivot = QVector2D(m_pivotU, m_pivotV);
1080 imageNode->m_rotation = m_rotationUV;
1081 imageNode->m_position = QVector2D(m_positionU, m_positionV);
1083 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::TransformDirty);
1086 bool nodeChanged =
false;
1087 if (m_dirtyFlags.testFlag(DirtyFlag::SourceDirty)) {
1088 m_dirtyFlags.setFlag(DirtyFlag::SourceDirty,
false);
1089 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1090 if (!m_source.isEmpty()) {
1091 const QQmlContext *context = qmlContext(
this);
1092 imageNode->m_imagePath = resolveImagePath(m_source, context);
1094 imageNode->m_imagePath = QSSGRenderPath();
1098 if (m_dirtyFlags.testFlag(DirtyFlag::IndexUVDirty)) {
1099 m_dirtyFlags.setFlag(DirtyFlag::IndexUVDirty,
false);
1100 imageNode->m_indexUV = m_indexUV;
1102 nodeChanged |= qUpdateIfNeeded(imageNode->m_mappingMode,
1103 QSSGRenderImage::MappingModes(m_mappingMode));
1104 nodeChanged |= qUpdateIfNeeded(imageNode->m_horizontalTilingMode,
1105 QSSGRenderTextureCoordOp(m_tilingModeHorizontal));
1106 nodeChanged |= qUpdateIfNeeded(imageNode->m_verticalTilingMode,
1107 QSSGRenderTextureCoordOp(m_tilingModeVertical));
1108 nodeChanged |= qUpdateIfNeeded(imageNode->m_depthTilingMode,
1109 QSSGRenderTextureCoordOp(m_tilingModeDepth));
1111 if (m_dirtyFlags.testFlag(DirtyFlag::SamplerDirty)) {
1112 m_dirtyFlags.setFlag(DirtyFlag::SamplerDirty,
false);
1113 nodeChanged |= qUpdateIfNeeded(imageNode->m_minFilterType,
1114 QSSGRenderTextureFilterOp(m_minFilter));
1115 nodeChanged |= qUpdateIfNeeded(imageNode->m_magFilterType,
1116 QSSGRenderTextureFilterOp(m_magFilter));
1117 nodeChanged |= qUpdateIfNeeded(imageNode->m_mipFilterType,
1118 QSSGRenderTextureFilterOp(m_mipFilter));
1119 nodeChanged |= qUpdateIfNeeded(imageNode->m_generateMipmaps,
1123 if (m_dirtyFlags.testFlag(DirtyFlag::TextureDataDirty)) {
1124 m_dirtyFlags.setFlag(DirtyFlag::TextureDataDirty,
false);
1125 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1127 imageNode->m_rawTextureData =
static_cast<QSSGRenderTextureData *>(QQuick3DObjectPrivate::get(m_textureData)->spatialNode);
1129 imageNode->m_rawTextureData =
nullptr;
1133 if (m_dirtyFlags.testFlag(DirtyFlag::ExtensionDirty)) {
1134 bool extDirty =
false;
1135 if (m_renderExtension) {
1136 auto *sn = QQuick3DObjectPrivate::get(m_renderExtension)->spatialNode;
1139 extDirty = (sn ==
nullptr);
1140 if (sn && QSSG_GUARD(QSSGRenderGraphObject::isExtension(sn->type)))
1141 imageNode->m_extensionsSource =
static_cast<QSSGRenderExtension *>(sn);
1144 m_dirtyFlags.setFlag(DirtyFlag::ExtensionDirty, extDirty);
1145 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1150 if (m_dirtyFlags.testFlag(DirtyFlag::SourceItemDirty)) {
1151 m_dirtyFlags.setFlag(DirtyFlag::SourceItemDirty,
false);
1152 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1154 QQuickWindow *window = m_sourceItem->window();
1161 window = QQuick3DObjectPrivate::get(
this)->sceneManager->window();
1163 QQuickItemPrivate::get(m_sourceItem)->refWindow(window);
1165 qWarning(
"Unable to get window, this will probably not work");
1171 const bool isHiddenView3D = !m_sourceItem->isVisible() && (qobject_cast<QQuick3DViewport *>(m_sourceItem) !=
nullptr);
1175 if (QSGTextureProvider *provider = m_sourceItem->textureProvider(); provider !=
nullptr && !isHiddenView3D) {
1176 imageNode->m_qsgTexture = provider->texture();
1178 disconnect(m_textureProviderConnection);
1179 m_textureProviderConnection = connect(provider, &QSGTextureProvider::textureChanged,
this, [
this, provider] () {
1185 auto imageNode =
static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(
this)->spatialNode);
1189 imageNode->m_qsgTexture = provider->texture();
1191 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::Dirty);
1196 QMetaObject::invokeMethod(
this, &QQuick3DTexture::update, Qt::AutoConnection);
1197 }, Qt::DirectConnection);
1199 disconnect(m_textureUpdateConnection);
1200 auto *sourcePrivate = QQuickItemPrivate::get(m_sourceItem);
1201 if (sourcePrivate->window) {
1202 QQuickItem *sourceItem = m_sourceItem;
1219 m_textureUpdateConnection = connect(sourcePrivate->window, &QQuickWindow::afterSynchronizing,
this, [
this, sourceItem]() {
1221 if (m_sourceItem != sourceItem) {
1222 disconnect(m_textureProviderConnection);
1223 disconnect(m_textureUpdateConnection);
1226 auto imageNode =
static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(
this)->spatialNode);
1230 if (QSGDynamicTexture *t = qobject_cast<QSGDynamicTexture *>(imageNode->m_qsgTexture)) {
1231 if (t->updateTexture())
1234 }, Qt::DirectConnection);
1236 qWarning(
"No window for item, texture updates are doomed");
1246 if (m_initializedSourceItem != m_sourceItem || m_initializedSourceItemSize != m_sourceItem->size()) {
1251 m_layer->setItem(
nullptr);
1253 m_initializedSourceItem = m_sourceItem;
1254 m_initializedSourceItemSize = m_sourceItem->size();
1258 connect(window, &QQuickWindow::afterSynchronizing,
this, [
this, window]() {
1259 auto imageNode =
static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(
this)->spatialNode);
1264 disconnect(window, &QQuickWindow::afterSynchronizing,
this,
nullptr);
1266 const auto &manager = QQuick3DObjectPrivate::get(
this)->sceneManager;
1267 manager->qsgDynamicTextures.removeAll(m_layer);
1272 QQuickItemPrivate *sourcePrivate = QQuickItemPrivate::get(m_sourceItem);
1273 QSGRenderContext *rc = sourcePrivate->sceneGraphRenderContext();
1274 Q_ASSERT(QThread::currentThread() == rc->thread());
1275 QSGLayer *layer = rc->sceneGraphContext()->createLayer(rc);
1276 connect(sourcePrivate->window, SIGNAL(sceneGraphInvalidated()), layer, SLOT(invalidated()), Qt::DirectConnection);
1278 QQuick3DSceneManager *manager = QQuick3DObjectPrivate::get(
this)->sceneManager;
1279 manager->qsgDynamicTextures << layer;
1280 m_sceneManagerForLayer = manager;
1282 connect(layer, &QObject::destroyed, manager, [manager, layer]()
1285 manager->qsgDynamicTextures.removeAll(layer);
1286 }, Qt::DirectConnection);
1288 QQuickItem *sourceItem = m_sourceItem;
1289 connect(layer, &QObject::destroyed,
this, [
this, sourceItem]()
1292 if (m_initializedSourceItem == sourceItem) {
1293 m_sceneManagerForLayer =
nullptr;
1294 m_initializedSourceItem =
nullptr;
1296 }, Qt::DirectConnection);
1307 m_textureUpdateConnection = connect(sourcePrivate->window, &QQuickWindow::afterSynchronizing,
1308 this, [
this, sourceItem]()
1313 if (m_sourceItem != sourceItem) {
1314 disconnect(m_textureUpdateConnection);
1317 if (m_layer->updateTexture())
1319 }, Qt::DirectConnection);
1322 m_layer->setItem(QQuickItemPrivate::get(m_sourceItem)->itemNode());
1324 QRectF sourceRect = QRectF(0, 0, m_sourceItem->width(), m_sourceItem->height());
1325 if (qFuzzyIsNull(sourceRect.width()))
1326 sourceRect.setWidth(256);
1327 if (qFuzzyIsNull(sourceRect.height()))
1328 sourceRect.setHeight(256);
1329 m_layer->setRect(sourceRect);
1331 QSize textureSize(qCeil(qAbs(sourceRect.width())), qCeil(qAbs(sourceRect.height())));
1332 const QSize minTextureSize = sourcePrivate->sceneGraphContext()->minimumFBOSize();
1333 while (textureSize.width() < minTextureSize.width())
1334 textureSize.rwidth() *= 2;
1335 while (textureSize.height() < minTextureSize.height())
1336 textureSize.rheight() *= 2;
1337 m_layer->setSize(textureSize);
1340 m_layer->updateTexture();
1342 imageNode->m_qsgTexture = m_layer;
1343 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::Dirty);
1344 }, Qt::DirectConnection);
1349 m_layer->setItem(
nullptr);
1353 imageNode->m_qsgTexture =
nullptr;
1358 if (m_dirtyFlags.testFlag(DirtyFlag::FlipVDirty)) {
1359 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
false);
1360 imageNode->m_flipV = effectiveFlipV(*imageNode);
1361 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::TransformDirty);
1365 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::Dirty);