714void QQuick3DTexture::setSourceItem(QQuickItem *sourceItem)
716 if (m_sourceItem == sourceItem)
719 disconnect(m_textureProviderConnection);
720 disconnect(m_textureUpdateConnection);
723 QQuickItemPrivate *sourcePrivate = QQuickItemPrivate::get(m_sourceItem);
725 const bool hide = m_sourceItemReparented;
726 sourcePrivate->derefFromEffectItem(hide);
727 m_sourceItemRefed =
false;
729 sourcePrivate->removeItemChangeListener(
this, QQuickItemPrivate::Geometry);
730 disconnect(m_sourceItem, SIGNAL(destroyed(QObject*)),
this, SLOT(sourceItemDestroyed(QObject*)));
731 disconnect(m_sourceItem, &QQuickItem::windowChanged,
this, &QQuick3DTexture::sourceItemWindowChanged);
732 if (m_sourceItemReparented) {
733 m_sourceItem->setParentItem(
nullptr);
734 m_sourceItemReparented =
false;
738 m_sourceItem = sourceItem;
741 trySetSourceParent();
742 QQuickItemPrivate *sourcePrivate = QQuickItemPrivate::get(m_sourceItem);
743 sourcePrivate->addItemChangeListener(
this, QQuickItemPrivate::Geometry);
744 connect(m_sourceItem, SIGNAL(destroyed(QObject*)),
this, SLOT(sourceItemDestroyed(QObject*)));
745 connect(m_sourceItem, &QQuickItem::windowChanged,
this, &QQuick3DTexture::sourceItemWindowChanged);
746 sourcePrivate->ensureSubsceneDeliveryAgent();
750 const auto &manager = QQuick3DObjectPrivate::get(
this)->sceneManager;
751 manager->qsgDynamicTextures.removeAll(m_layer);
752 m_sceneManagerForLayer =
nullptr;
755 m_initializedSourceItem =
nullptr;
756 m_initializedSourceItemSize = QSize();
758 m_dirtyFlags.setFlag(DirtyFlag::SourceDirty);
759 m_dirtyFlags.setFlag(DirtyFlag::SourceItemDirty);
760 m_dirtyFlags.setFlag(DirtyFlag::TextureDataDirty);
761 emit sourceItemChanged();
1068QSSGRenderGraphObject *QQuick3DTexture::updateSpatialNode(QSSGRenderGraphObject *node)
1072 node =
new QSSGRenderImage(QQuick3DObjectPrivate::get(
this)->type);
1074 QQuick3DObject::updateSpatialNode(node);
1075 auto imageNode =
static_cast<QSSGRenderImage *>(node);
1077 if (m_dirtyFlags.testFlag(DirtyFlag::TransformDirty)) {
1078 m_dirtyFlags.setFlag(DirtyFlag::TransformDirty,
false);
1081 imageNode->m_flipU = m_flipU;
1082 imageNode->m_scale = QVector2D(m_scaleU, m_scaleV);
1083 imageNode->m_pivot = QVector2D(m_pivotU, m_pivotV);
1084 imageNode->m_rotation = m_rotationUV;
1085 imageNode->m_position = QVector2D(m_positionU, m_positionV);
1087 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::TransformDirty);
1090 bool nodeChanged =
false;
1091 if (m_dirtyFlags.testFlag(DirtyFlag::SourceDirty)) {
1092 m_dirtyFlags.setFlag(DirtyFlag::SourceDirty,
false);
1093 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1094 if (!m_source.isEmpty()) {
1095 const QQmlContext *context = qmlContext(
this);
1096 imageNode->m_imagePath = resolveImagePath(m_source, context);
1098 imageNode->m_imagePath = QSSGRenderPath();
1102 if (m_dirtyFlags.testFlag(DirtyFlag::IndexUVDirty)) {
1103 m_dirtyFlags.setFlag(DirtyFlag::IndexUVDirty,
false);
1104 imageNode->m_indexUV = m_indexUV;
1106 nodeChanged |= qUpdateIfNeeded(imageNode->m_mappingMode,
1107 QSSGRenderImage::MappingModes(m_mappingMode));
1108 nodeChanged |= qUpdateIfNeeded(imageNode->m_horizontalTilingMode,
1109 QSSGRenderTextureCoordOp(m_tilingModeHorizontal));
1110 nodeChanged |= qUpdateIfNeeded(imageNode->m_verticalTilingMode,
1111 QSSGRenderTextureCoordOp(m_tilingModeVertical));
1112 nodeChanged |= qUpdateIfNeeded(imageNode->m_depthTilingMode,
1113 QSSGRenderTextureCoordOp(m_tilingModeDepth));
1115 if (m_dirtyFlags.testFlag(DirtyFlag::SamplerDirty)) {
1116 m_dirtyFlags.setFlag(DirtyFlag::SamplerDirty,
false);
1117 nodeChanged |= qUpdateIfNeeded(imageNode->m_minFilterType,
1118 QSSGRenderTextureFilterOp(m_minFilter));
1119 nodeChanged |= qUpdateIfNeeded(imageNode->m_magFilterType,
1120 QSSGRenderTextureFilterOp(m_magFilter));
1121 nodeChanged |= qUpdateIfNeeded(imageNode->m_mipFilterType,
1122 QSSGRenderTextureFilterOp(m_mipFilter));
1123 nodeChanged |= qUpdateIfNeeded(imageNode->m_generateMipmaps,
1127 if (m_dirtyFlags.testFlag(DirtyFlag::TextureDataDirty)) {
1128 m_dirtyFlags.setFlag(DirtyFlag::TextureDataDirty,
false);
1129 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1131 imageNode->m_rawTextureData =
static_cast<QSSGRenderTextureData *>(QQuick3DObjectPrivate::get(m_textureData)->spatialNode);
1133 imageNode->m_rawTextureData =
nullptr;
1137 if (m_dirtyFlags.testFlag(DirtyFlag::ExtensionDirty)) {
1138 bool extDirty =
false;
1139 if (m_renderExtension) {
1140 auto *sn = QQuick3DObjectPrivate::get(m_renderExtension)->spatialNode;
1143 extDirty = (sn ==
nullptr);
1144 if (sn && QSSG_GUARD(QSSGRenderGraphObject::isExtension(sn->type)))
1145 imageNode->m_extensionsSource =
static_cast<QSSGRenderExtension *>(sn);
1149 markDirty(DirtyFlag::ExtensionDirty,
true);
1150 m_dirtyFlags.setFlag(DirtyFlag::ExtensionDirty, extDirty);
1151 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1156 if (m_dirtyFlags.testFlag(DirtyFlag::SourceItemDirty)) {
1157 m_dirtyFlags.setFlag(DirtyFlag::SourceItemDirty,
false);
1158 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
true);
1160 QQuickWindow *window = m_sourceItem->window();
1167 window = QQuick3DObjectPrivate::get(
this)->sceneManager->window();
1169 QQuickItemPrivate::get(m_sourceItem)->refWindow(window);
1171 qWarning(
"Unable to get window, this will probably not work");
1177 const bool isHiddenView3D = !m_sourceItem->isVisible() && (qobject_cast<QQuick3DViewport *>(m_sourceItem) !=
nullptr);
1181 if (QSGTextureProvider *provider = m_sourceItem->textureProvider(); provider !=
nullptr && !isHiddenView3D) {
1182 imageNode->m_qsgTexture = provider->texture();
1184 disconnect(m_textureProviderConnection);
1185 m_textureProviderConnection = connect(provider, &QSGTextureProvider::textureChanged,
this, [
this, provider] () {
1191 auto imageNode =
static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(
this)->spatialNode);
1195 imageNode->m_qsgTexture = provider->texture();
1197 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::Dirty);
1202 QMetaObject::invokeMethod(
this, &QQuick3DTexture::update, Qt::AutoConnection);
1203 }, Qt::DirectConnection);
1205 disconnect(m_textureUpdateConnection);
1206 auto *sourcePrivate = QQuickItemPrivate::get(m_sourceItem);
1207 if (sourcePrivate->window) {
1208 QQuickItem *sourceItem = m_sourceItem;
1225 m_textureUpdateConnection = connect(sourcePrivate->window, &QQuickWindow::afterSynchronizing,
this, [
this, sourceItem]() {
1227 if (m_sourceItem != sourceItem) {
1228 disconnect(m_textureProviderConnection);
1229 disconnect(m_textureUpdateConnection);
1232 auto imageNode =
static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(
this)->spatialNode);
1236 if (QSGDynamicTexture *t = qobject_cast<QSGDynamicTexture *>(imageNode->m_qsgTexture)) {
1237 if (t->updateTexture())
1240 }, Qt::DirectConnection);
1242 qWarning(
"No window for item, texture updates are doomed");
1252 if (m_initializedSourceItem != m_sourceItem || m_initializedSourceItemSize != m_sourceItem->size()) {
1257 m_layer->setItem(
nullptr);
1259 m_initializedSourceItem = m_sourceItem;
1260 m_initializedSourceItemSize = m_sourceItem->size();
1264 connect(window, &QQuickWindow::afterSynchronizing,
this, [
this, window]() {
1265 auto imageNode =
static_cast<QSSGRenderImage *>(QQuick3DObjectPrivate::get(
this)->spatialNode);
1270 disconnect(window, &QQuickWindow::afterSynchronizing,
this,
nullptr);
1272 const auto &manager = QQuick3DObjectPrivate::get(
this)->sceneManager;
1273 manager->qsgDynamicTextures.removeAll(m_layer);
1278 QQuickItemPrivate *sourcePrivate = QQuickItemPrivate::get(m_sourceItem);
1279 QSGRenderContext *rc = sourcePrivate->sceneGraphRenderContext();
1280 Q_ASSERT(QThread::currentThread() == rc->thread());
1281 QSGLayer *layer = rc->sceneGraphContext()->createLayer(rc);
1282 connect(sourcePrivate->window, SIGNAL(sceneGraphInvalidated()), layer, SLOT(invalidated()), Qt::DirectConnection);
1284 QQuick3DSceneManager *manager = QQuick3DObjectPrivate::get(
this)->sceneManager;
1285 manager->qsgDynamicTextures << layer;
1286 m_sceneManagerForLayer = manager;
1288 connect(layer, &QObject::destroyed, manager, [manager, layer]()
1291 manager->qsgDynamicTextures.removeAll(layer);
1292 }, Qt::DirectConnection);
1294 QQuickItem *sourceItem = m_sourceItem;
1295 connect(layer, &QObject::destroyed,
this, [
this, sourceItem]()
1298 if (m_initializedSourceItem == sourceItem) {
1299 m_sceneManagerForLayer =
nullptr;
1300 m_initializedSourceItem =
nullptr;
1302 }, Qt::DirectConnection);
1313 m_textureUpdateConnection = connect(sourcePrivate->window, &QQuickWindow::afterSynchronizing,
1314 this, [
this, sourceItem]()
1319 if (m_sourceItem != sourceItem) {
1320 disconnect(m_textureUpdateConnection);
1323 if (m_layer->updateTexture())
1325 }, Qt::DirectConnection);
1328 m_layer->setItem(QQuickItemPrivate::get(m_sourceItem)->itemNode());
1330 QRectF sourceRect = QRectF(0, 0, m_sourceItem->width(), m_sourceItem->height());
1331 if (qFuzzyIsNull(sourceRect.width()))
1332 sourceRect.setWidth(256);
1333 if (qFuzzyIsNull(sourceRect.height()))
1334 sourceRect.setHeight(256);
1335 m_layer->setRect(sourceRect);
1337 QSize textureSize(qCeil(qAbs(sourceRect.width())), qCeil(qAbs(sourceRect.height())));
1338 const QSize minTextureSize = sourcePrivate->sceneGraphContext()->minimumFBOSize();
1339 while (textureSize.width() < minTextureSize.width())
1340 textureSize.rwidth() *= 2;
1341 while (textureSize.height() < minTextureSize.height())
1342 textureSize.rheight() *= 2;
1343 m_layer->setSize(textureSize);
1346 m_layer->updateTexture();
1348 imageNode->m_qsgTexture = m_layer;
1349 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::Dirty);
1350 }, Qt::DirectConnection);
1355 m_layer->setItem(
nullptr);
1359 imageNode->m_qsgTexture =
nullptr;
1364 if (m_dirtyFlags.testFlag(DirtyFlag::FlipVDirty)) {
1365 m_dirtyFlags.setFlag(DirtyFlag::FlipVDirty,
false);
1366 imageNode->m_flipV = effectiveFlipV(*imageNode);
1367 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::TransformDirty);
1371 imageNode->m_flags.setFlag(QSSGRenderImage::Flag::Dirty);