summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJere Tuliniemi <jere.tuliniemi@qt.io>2019-09-10 11:00:57 +0300
committerJere Tuliniemi <jere.tuliniemi@qt.io>2019-09-17 12:35:55 +0300
commitfe29ee5c5b0c1edbfabccf211bd8d73bb61672dc (patch)
tree21fb79747816ff315ed0f5526321bea2e616b326
parentef8b07e32a9ecc8375c1031ba5c7119ac75b81f0 (diff)
Support QQuickImageProvider in the runtime
With QQuickImageProvider the user can make a callback method returning a custom QPixmap or QImage to the engine without accessing the filesystem. Texture sourcepaths are set using an image url scheme. For example "image://colors/blue" where "image://" tells the runtime to look for an image provider, "colors" is the image provider id and rest are the image id the provider uses to create the image. Task-number: QT3DS-3761 Change-Id: I830649359f9969e957a972a0c08d0ede6e46ee78 Reviewed-by: Antti Määttä <antti.maatta@qt.io> Reviewed-by: Miikka Heikkinen <miikka.heikkinen@qt.io>
-rw-r--r--src/api/studio3d/q3dscommandqueue.cpp3
-rw-r--r--src/api/studio3d/q3dscommandqueue_p.h1
-rw-r--r--src/api/studio3d/q3dspresentation.cpp18
-rw-r--r--src/api/studio3d/q3dspresentation.h3
-rw-r--r--src/api/studio3dqml/q3dsrenderer.cpp4
-rw-r--r--src/engine/Qt3DSRuntimeView.cpp10
-rw-r--r--src/engine/Qt3DSRuntimeView.h1
-rw-r--r--src/runtime/Qt3DSIScriptBridge.h4
-rw-r--r--src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp3
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp21
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h8
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp3
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp34
-rw-r--r--src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h7
-rw-r--r--src/viewer/Qt3DSViewerApp.cpp8
-rw-r--r--src/viewer/Qt3DSViewerApp.h6
16 files changed, 124 insertions, 10 deletions
diff --git a/src/api/studio3d/q3dscommandqueue.cpp b/src/api/studio3d/q3dscommandqueue.cpp
index 06bd73f..b2d0937 100644
--- a/src/api/studio3d/q3dscommandqueue.cpp
+++ b/src/api/studio3d/q3dscommandqueue.cpp
@@ -311,6 +311,9 @@ void CommandQueue::copyCommands(CommandQueue &fromQueue)
queueCommand(source.m_elementPath, source.m_commandType, source.m_data);
fromQueue.commandAt(i).m_data = nullptr; // This queue takes ownership of data
break;
+ case CommandType_AddImageProvider:
+ queueCommand(source.m_elementPath, source.m_commandType, source.m_data);
+ break;
case CommandType_RequestSlideInfo:
case CommandType_UnloadSlide:
case CommandType_PreloadSlide:
diff --git a/src/api/studio3d/q3dscommandqueue_p.h b/src/api/studio3d/q3dscommandqueue_p.h
index 2f98ed6..0b7b833 100644
--- a/src/api/studio3d/q3dscommandqueue_p.h
+++ b/src/api/studio3d/q3dscommandqueue_p.h
@@ -77,6 +77,7 @@ enum CommandType {
CommandType_DeleteMeshes,
CommandType_PreloadSlide,
CommandType_UnloadSlide,
+ CommandType_AddImageProvider,
// Requests
CommandType_RequestSlideInfo,
diff --git a/src/api/studio3d/q3dspresentation.cpp b/src/api/studio3d/q3dspresentation.cpp
index e782cfe..0536310 100644
--- a/src/api/studio3d/q3dspresentation.cpp
+++ b/src/api/studio3d/q3dspresentation.cpp
@@ -941,6 +941,24 @@ void Q3DSPresentation::setAttribute(const QString &elementPath, const QString &a
}
/*!
+ Sets the \a provider to use for images requested via the \e
+ image: url scheme, with host \a providerId. The runtime
+ takes ownership of \a provider.
+
+ Texture sourcepaths can then be set using the image url scheme. For example
+ "image://colors/blue" where "image://" tells the runtime to look for an
+ image provider, "colors" is the image provider id and rest are the image
+ id the provider uses to create the image.
+*/
+void Q3DSPresentation::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
+{
+ if (d_ptr->m_viewerApp)
+ d_ptr->m_viewerApp->addImageProvider(providerId, provider);
+ else if (d_ptr->m_commandQueue)
+ d_ptr->m_commandQueue->queueCommand(providerId, CommandType_AddImageProvider, provider);
+}
+
+/*!
Activate or deactivate the presentation identified by \a id depending
on the value of \a active.
*/
diff --git a/src/api/studio3d/q3dspresentation.h b/src/api/studio3d/q3dspresentation.h
index af84073..1c53f98 100644
--- a/src/api/studio3d/q3dspresentation.h
+++ b/src/api/studio3d/q3dspresentation.h
@@ -47,6 +47,7 @@ class Q3DSGeometry;
class QMouseEvent;
class QWheelEvent;
class QKeyEvent;
+class QQmlImageProviderBase;
class Q_STUDIO3D_EXPORT Q3DSPresentation : public QObject
{
@@ -123,6 +124,8 @@ public:
void deleteMeshes(const QStringList &meshNames);
QStringList createdMeshes() const;
+ void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider);
+
public Q_SLOTS:
void setSource(const QUrl &source);
void setVariantList(const QStringList &variantList);
diff --git a/src/api/studio3dqml/q3dsrenderer.cpp b/src/api/studio3dqml/q3dsrenderer.cpp
index 5a99aad..7d63b30 100644
--- a/src/api/studio3dqml/q3dsrenderer.cpp
+++ b/src/api/studio3dqml/q3dsrenderer.cpp
@@ -482,6 +482,10 @@ void Q3DSRenderer::processCommands()
case CommandType_UnloadSlide:
m_runtime->unloadSlide(cmd.m_elementPath);
break;
+ case CommandType_AddImageProvider:
+ m_runtime->addImageProvider(cmd.m_elementPath,
+ static_cast<QQmlImageProviderBase *>(cmd.m_data));
+ break;
case CommandType_RequestSlideInfo: {
int current = 0;
int previous = 0;
diff --git a/src/engine/Qt3DSRuntimeView.cpp b/src/engine/Qt3DSRuntimeView.cpp
index 3ab577c..c5448e3 100644
--- a/src/engine/Qt3DSRuntimeView.cpp
+++ b/src/engine/Qt3DSRuntimeView.cpp
@@ -225,6 +225,7 @@ public:
void deleteMaterials(const QStringList &materialNames) override;
void createMesh(const QString &name, qt3dsimp::Mesh *mesh) override;
void deleteMeshes(const QStringList &meshNames) override;
+ void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider) override;
void SetAttribute(const char *elementPath, const char *attributeName,
const char *value) override;
bool GetAttribute(const char *elementPath, const char *attributeName, void *value) override;
@@ -733,6 +734,15 @@ void CRuntimeView::deleteMeshes(const QStringList &meshNames)
}
}
+void CRuntimeView::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
+{
+ if (m_Application) {
+ IBufferManager &bufferManager
+ = m_RuntimeFactory->GetQt3DSRenderContext().GetBufferManager();
+ bufferManager.addImageProvider(providerId, provider);
+ }
+}
+
void CRuntimeView::SetAttribute(const char *elementPath, const char *attributeName,
const char *value)
{
diff --git a/src/engine/Qt3DSRuntimeView.h b/src/engine/Qt3DSRuntimeView.h
index 1ddc48b..482e69a 100644
--- a/src/engine/Qt3DSRuntimeView.h
+++ b/src/engine/Qt3DSRuntimeView.h
@@ -226,6 +226,7 @@ public:
virtual void deleteMaterials(const QStringList &materialNames) = 0;
virtual void createMesh(const QString &name, qt3dsimp::Mesh *mesh) = 0;
virtual void deleteMeshes(const QStringList &meshNames) = 0;
+ virtual void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider) = 0;
virtual void SetAttribute(const char *elementPath, const char *attributeName,
const char *value) = 0;
virtual bool GetAttribute(const char *elementPath, const char *attributeName, void *value) = 0;
diff --git a/src/runtime/Qt3DSIScriptBridge.h b/src/runtime/Qt3DSIScriptBridge.h
index 16bf299..b9df2b3 100644
--- a/src/runtime/Qt3DSIScriptBridge.h
+++ b/src/runtime/Qt3DSIScriptBridge.h
@@ -39,6 +39,10 @@
#include <QtCore/qvector.h>
#include <QtCore/qstringlist.h>
+QT_BEGIN_NAMESPACE
+class QQmlImageProviderBase;
+QT_END_NAMESPACE
+
namespace qt3dsimp {
struct Mesh;
}
diff --git a/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp b/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp
index 2e1e6a0..086453c 100644
--- a/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp
+++ b/src/runtimerender/graphobjects/Qt3DSRenderDynamicObject.cpp
@@ -133,6 +133,9 @@ void SDynamicObject::SetStrPropertyValueT(dynamic::SPropertyDefinition &inDefini
inDefinition.m_ImagePath = inStrTable.RegisterStr(ioWorkspace.c_str());
} else {
SetPropertyValueT(inDefinition, inStrTable.RegisterStr(inValue));
+ // If the image path is not adjusted here, an invalid textures flashes for one frame
+ // before the proper texture is set by the custom material render task
+ inDefinition.m_ImagePath = inStrTable.RegisterStr(inValue);
}
} else if (inDefinition.m_DataType == NVRenderShaderDataTypes::NVRenderImage2DPtr) {
SetPropertyValueT(inDefinition, inStrTable.RegisterStr(inValue));
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
index b140e85..f3f85f4 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.cpp
@@ -119,6 +119,7 @@ struct SBufferManager : public IBufferManager
nvvector<qt3ds::render::NVRenderVertexBufferEntry> m_EntryBuffer;
bool m_GPUSupportsDXT;
bool m_reloadableResources;
+ QHash<QString, QSharedPointer<QQmlImageProviderBase> > m_imageProviders;
QHash<QString, ReloadableTexturePtr> m_reloadableTextures;
@@ -377,7 +378,7 @@ struct SBufferManager : public IBufferManager
SStackPerfTimer __perfTimer(m_PerfTimer, "Image Decompression");
theLoadedImage = SLoadedTexture::Load(
inImagePath.c_str(), m_Context->GetFoundation(), *m_InputStreamFactory,
- true, m_Context->GetRenderContextType());
+ true, m_Context->GetRenderContextType(), false, this);
// Hackish solution to custom materials not finding their textures if they are used
// in sub-presentations.
if (!theLoadedImage) {
@@ -390,7 +391,7 @@ struct SBufferManager : public IBufferManager
theLoadedImage = SLoadedTexture::Load(
searchPath.toUtf8(), m_Context->GetFoundation(),
*m_InputStreamFactory, true,
- m_Context->GetRenderContextType());
+ m_Context->GetRenderContextType(), false, this);
searchPath.prepend(QLatin1String("../"));
}
} else {
@@ -407,7 +408,7 @@ struct SBufferManager : public IBufferManager
theLoadedImage = SLoadedTexture::Load(
searchPath.toUtf8(), m_Context->GetFoundation(),
*m_InputStreamFactory, true,
- m_Context->GetRenderContextType());
+ m_Context->GetRenderContextType(), false, this);
searchPath = splitPath.at(0);
for (int i = 0; i < loops; i++)
searchPath.append(QLatin1String("../"));
@@ -1024,6 +1025,19 @@ struct SBufferManager : public IBufferManager
return theMesh.first->second;
}
+ void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider) override
+ {
+ QString providerIdLower = providerId.toLower();
+ QSharedPointer<QQmlImageProviderBase> sp(provider);
+ m_imageProviders.insert(std::move(providerIdLower), std::move(sp));
+ }
+
+ QQmlImageProviderBase *imageProvider(const QString &providerId) override
+ {
+ const QString providerIdLower = providerId.toLower();
+ return m_imageProviders.value(providerIdLower).data();
+ }
+
void ReleaseMesh(SRenderMesh &inMesh)
{
for (QT3DSU32 subsetIdx = 0, subsetEnd = inMesh.m_Subsets.size(); subsetIdx < subsetEnd;
@@ -1068,6 +1082,7 @@ struct SBufferManager : public IBufferManager
Mutex::ScopedLock __locker(m_LoadedImageSetMutex);
m_LoadedImageSet.clear();
}
+ m_imageProviders.clear();
}
void InvalidateBuffer(CRegisteredString inSourcePath) override
{
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
index 7930158..b8cd49b 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderBufferManager.h
@@ -37,6 +37,10 @@
#include "Qt3DSRenderImageTextureData.h"
#include "foundation/Qt3DSBounds3.h"
+QT_BEGIN_NAMESPACE
+class QQmlImageProviderBase;
+QT_END_NAMESPACE
+
namespace qt3dsimp {
struct Mesh;
}
@@ -105,6 +109,10 @@ namespace render {
QT3DSU32 inNumVerts, QT3DSU32 inVertStride, QT3DSU32 *inIndexData,
QT3DSU32 inIndexCount, qt3ds::NVBounds3 inBounds) = 0;
+ virtual void addImageProvider(const QString &providerId,
+ QQmlImageProviderBase *provider) = 0;
+ virtual QQmlImageProviderBase *imageProvider(const QString &providerId) = 0;
+
// Remove *all* buffers from the buffer manager;
virtual void Clear() = 0;
virtual void InvalidateBuffer(CRegisteredString inSourcePath) = 0;
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp
index 72495cd..d272911 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderImageBatchLoader.cpp
@@ -388,7 +388,8 @@ void SLoadingImage::LoadImage(void *inImg)
theThis->m_SourcePath.c_str(), theThis->m_Batch->m_Loader.m_Foundation,
theThis->m_Batch->m_Loader.m_InputStreamFactory, true,
theThis->m_Batch->m_contextType,
- theThis->m_Batch->m_preferKTX);
+ theThis->m_Batch->m_preferKTX,
+ &theThis->m_Batch->m_Loader.m_BufferManager);
// if ( theTexture )
// theTexture->EnsureMultiplerOfFour( theThis->m_Batch->m_Loader.m_Foundation,
//theThis->m_SourcePath.c_str() );
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
index ff221f9..afb6661 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.cpp
@@ -37,19 +37,41 @@
#include "foundation/Qt3DSBroadcastingAllocator.h"
#include "Qt3DSRenderImageScaler.h"
#include "Qt3DSTextRenderer.h"
-#include <QImage>
+#include "Qt3DSRenderBufferManager.h"
+#include <QtQuick/qquickimageprovider.h>
+#include <QtGui/qimage.h>
using namespace qt3ds::render;
SLoadedTexture *SLoadedTexture::LoadQImage(const QString &inPath, QT3DSI32 flipVertical,
NVFoundationBase &fnd,
- NVRenderContextType renderContextType)
+ NVRenderContextType renderContextType,
+ IBufferManager *bufferManager)
{
Q_UNUSED(flipVertical)
Q_UNUSED(renderContextType)
SLoadedTexture *retval(NULL);
NVAllocatorCallback &alloc(fnd.getAllocator());
- QImage image(inPath);
+
+ QImage image;
+ const QUrl url(inPath);
+ if (bufferManager && url.scheme() == QLatin1String("image")) {
+ QQuickImageProvider *provider = static_cast<QQuickImageProvider *>(
+ bufferManager->imageProvider(url.host()));
+ if (!provider)
+ return nullptr;
+ QString imageId = url.toString(QUrl::RemoveScheme | QUrl::RemoveAuthority).mid(1);
+ QSize outSize;
+ if (provider->imageType() == QQuickImageProvider::Pixmap)
+ image = provider->requestPixmap(imageId, &outSize, QSize()).toImage();
+ else if (provider->imageType() == QQuickImageProvider::Image)
+ image = provider->requestImage(imageId, &outSize, QSize());
+ if (outSize.isEmpty())
+ return nullptr;
+ } else {
+ image = QImage(inPath);
+ }
+
const QImage::Format format = image.format();
switch (format) {
case QImage::Format_RGBA64:
@@ -682,11 +704,15 @@ void SLoadedTexture::ReleaseDecompressedTexture(STextureData inImage)
SLoadedTexture *SLoadedTexture::Load(const QString &inPath, NVFoundationBase &inFoundation,
IInputStreamFactory &inFactory, bool inFlipY,
- NVRenderContextType renderContextType, bool preferKTX)
+ NVRenderContextType renderContextType, bool preferKTX,
+ IBufferManager *bufferManager)
{
if (inPath.isEmpty())
return nullptr;
+ if (QUrl(inPath).scheme() == QLatin1String("image"))
+ return LoadQImage(inPath, inFlipY, inFoundation, renderContextType, bufferManager);
+
// Check KTX path first
QString path = inPath;
QString ktxSource = inPath;
diff --git a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
index 10200ad..cb0b2b6 100644
--- a/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
+++ b/src/runtimerender/resourcemanager/Qt3DSRenderLoadedTexture.h
@@ -155,7 +155,9 @@ namespace render {
static SLoadedTexture *Load(const QString &inPath, NVFoundationBase &inAllocator,
IInputStreamFactory &inFactory, bool inFlipY = true,
NVRenderContextType renderContextType
- = NVRenderContextValues::NullContext, bool preferKTX = false);
+ = NVRenderContextValues::NullContext,
+ bool preferKTX = false,
+ IBufferManager *bufferManager = nullptr);
static SLoadedTexture *LoadDDS(IInStream &inStream, QT3DSI32 flipVertical,
NVFoundationBase &fnd,
NVRenderContextType renderContextType);
@@ -173,7 +175,8 @@ namespace render {
static SLoadedTexture *LoadQImage(const QString &inPath, QT3DSI32 flipVertical,
NVFoundationBase &fnd,
- NVRenderContextType renderContextType);
+ NVRenderContextType renderContextType,
+ IBufferManager *bufferManager = nullptr);
private:
// Implemented in the bmp loader.
diff --git a/src/viewer/Qt3DSViewerApp.cpp b/src/viewer/Qt3DSViewerApp.cpp
index 0e73734..5916061 100644
--- a/src/viewer/Qt3DSViewerApp.cpp
+++ b/src/viewer/Qt3DSViewerApp.cpp
@@ -1043,6 +1043,14 @@ void Q3DSViewerApp::deleteMeshes(const QStringList &meshNames)
m_Impl.m_view->deleteMeshes(meshNames);
}
+void Q3DSViewerApp::addImageProvider(const QString &providerId, QQmlImageProviderBase *provider)
+{
+ if (!m_Impl.m_view)
+ return;
+
+ m_Impl.m_view->addImageProvider(providerId, provider);
+}
+
Q3DSViewerApp &Q3DSViewerApp::Create(void *glContext, Q3DStudio::IAudioPlayer *inAudioPlayer,
QElapsedTimer *startupTimer)
{
diff --git a/src/viewer/Qt3DSViewerApp.h b/src/viewer/Qt3DSViewerApp.h
index e12057b..d5b02e4 100644
--- a/src/viewer/Qt3DSViewerApp.h
+++ b/src/viewer/Qt3DSViewerApp.h
@@ -43,6 +43,10 @@
#include <QtCore/qstringlist.h>
#include <QtGui/qsurfaceformat.h>
+QT_BEGIN_NAMESPACE
+class QQmlImageProviderBase;
+QT_END_NAMESPACE
+
namespace Q3DStudio {
class IRuntimeView;
class IWindowSystem;
@@ -489,6 +493,8 @@ public:
void createMeshes(const QHash<QString, Q3DSViewer::MeshData> &meshData);
void deleteMeshes(const QStringList &meshNames);
+ void addImageProvider(const QString &providerId, QQmlImageProviderBase *provider);
+
QString error();
void setPresentationId(const QString &id);