summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/render/backend/renderer.cpp10
-rw-r--r--src/render/frontend/qrenderaspect.cpp5
-rw-r--r--src/render/graphicshelpers/graphicscontext.cpp7
-rw-r--r--src/render/texture/gltexture.cpp91
-rw-r--r--src/render/texture/gltexture_p.h2
-rw-r--r--src/render/texture/texturedatamanager_p.h35
-rw-r--r--src/render/texture/textureimage.cpp29
-rw-r--r--src/render/texture/textureimage_p.h13
-rw-r--r--tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp2
-rw-r--r--tests/auto/render/textures/textures.pro1
-rw-r--r--tests/auto/render/textures/tst_textures.cpp289
11 files changed, 372 insertions, 112 deletions
diff --git a/src/render/backend/renderer.cpp b/src/render/backend/renderer.cpp
index 2dda73679..bdc024308 100644
--- a/src/render/backend/renderer.cpp
+++ b/src/render/backend/renderer.cpp
@@ -1221,10 +1221,12 @@ void Renderer::updateTexture(Texture *texture)
!glTextureManager->setParameters(glTexture, texture->parameters()))
qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setParameters failed, should be non-shared";
+ // Will make the texture requestUpload
if (dirtyFlags.testFlag(Texture::DirtyImageGenerators) &&
!glTextureManager->setImages(glTexture, texture->textureImages()))
qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setGenerators failed, should be non-shared";
+ // Will make the texture requestUpload
if (dirtyFlags.testFlag(Texture::DirtyDataGenerator) &&
!glTextureManager->setGenerator(glTexture, texture->dataGenerator()))
qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setGenerator failed, should be non-shared";
@@ -1379,7 +1381,7 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
if (!executeCommandsSubmission(renderView))
m_lastFrameCorrect.store(0); // something went wrong; make sure to render the next frame!
- // executeCommands takes care of restoring the stateset to the value
+ // executeCommandsSubmission takes care of restoring the stateset to the value
// of gc->currentContext() at the moment it was called (either
// renderViewStateSet or m_defaultRenderStateSet)
if (!renderView->renderCaptureNodeId().isNull()) {
@@ -1836,8 +1838,12 @@ bool Renderer::executeCommandsSubmission(const RenderView *rv)
{
Profiling::GLTimeRecorder recorder(Profiling::UniformUpdate);
//// Update program uniforms
- if (!m_graphicsContext->setParameters(command->m_parameterPack))
+ if (!m_graphicsContext->setParameters(command->m_parameterPack)) {
allCommandsIssued = false;
+ // If we have failed to set uniform (e.g unable to bind a texture)
+ // we won't perform the draw call which could show invalid content
+ continue;
+ }
}
//// OpenGL State
diff --git a/src/render/frontend/qrenderaspect.cpp b/src/render/frontend/qrenderaspect.cpp
index e5cce4c7b..1314a7c36 100644
--- a/src/render/frontend/qrenderaspect.cpp
+++ b/src/render/frontend/qrenderaspect.cpp
@@ -254,7 +254,10 @@ void QRenderAspectPrivate::registerBackendTypes()
// Textures
q->registerBackendType<QAbstractTexture>(QSharedPointer<Render::TextureFunctor>::create(m_renderer, m_nodeManagers->textureManager(), m_nodeManagers->textureImageManager()));
- q->registerBackendType<QAbstractTextureImage>(QSharedPointer<Render::TextureImageFunctor>::create(m_renderer, m_nodeManagers->textureManager(), m_nodeManagers->textureImageManager()));
+ q->registerBackendType<QAbstractTextureImage>(QSharedPointer<Render::TextureImageFunctor>::create(m_renderer,
+ m_nodeManagers->textureManager(),
+ m_nodeManagers->textureImageManager(),
+ m_nodeManagers->textureImageDataManager()));
// Material system
q->registerBackendType<QEffect>(QSharedPointer<Render::NodeFunctor<Render::Effect, Render::EffectManager> >::create(m_renderer));
diff --git a/src/render/graphicshelpers/graphicscontext.cpp b/src/render/graphicshelpers/graphicscontext.cpp
index d742865c4..7fa112b12 100644
--- a/src/render/graphicshelpers/graphicscontext.cpp
+++ b/src/render/graphicshelpers/graphicscontext.cpp
@@ -1205,7 +1205,6 @@ bool GraphicsContext::setParameters(ShaderParameterPack &parameterPack)
{
// Activate textures and update TextureUniform in the pack
// with the correct textureUnit
- bool allValid = true;
// Set the pinned texture of the previous material texture
// to pinable so that we should easily find an available texture unit
@@ -1225,10 +1224,8 @@ bool GraphicsContext::setParameters(ShaderParameterPack &parameterPack)
Q_ASSERT(texUniform.valueType() == UniformValue::TextureValue);
const int texUnit = activateTexture(TextureScopeMaterial, t);
texUniform.data<int>()[namedTex.uniformArrayIndex] = texUnit;
- // if the texture data from generators may not be available yet,
- // make sure that the next frame is rendered
if (texUnit == -1)
- allValid = false;
+ return false;
}
}
}
@@ -1283,7 +1280,7 @@ bool GraphicsContext::setParameters(ShaderParameterPack &parameterPack)
applyUniform(uniform, v);
}
// if not all data is valid, the next frame will be rendered immediately
- return allValid;
+ return true;
}
void GraphicsContext::readBuffer(GLenum mode)
diff --git a/src/render/texture/gltexture.cpp b/src/render/texture/gltexture.cpp
index 2fd61f3db..e94122f67 100644
--- a/src/render/texture/gltexture.cpp
+++ b/src/render/texture/gltexture.cpp
@@ -87,10 +87,6 @@ GLTexture::~GLTexture()
void GLTexture::destroyResources()
{
- // release texture data
- for (const Image &img : qAsConst(m_images))
- m_textureImageDataManager->releaseData(img.generator, this);
-
if (m_dataFunctor)
m_textureDataManager->releaseData(m_dataFunctor, this);
}
@@ -111,7 +107,6 @@ QOpenGLTexture* GLTexture::getOrCreateGLTexture()
{
QMutexLocker locker(&m_textureMutex);
bool needUpload = false;
- bool texturedDataInvalid = false;
// on the first invocation in the render thread, make sure to
// evaluate the texture data generator output
@@ -156,31 +151,23 @@ QOpenGLTexture* GLTexture::getOrCreateGLTexture()
for (const Image &img : qAsConst(m_images)) {
const QTextureImageDataPtr imgData = m_textureImageDataManager->getData(img.generator);
- if (imgData) {
- m_imageData << imgData;
-
- maxMipLevel = qMax(maxMipLevel, img.mipLevel);
-
- // If the texture doesn't have a texture generator, we will
- // derive some properties from the first TextureImage (layer=0, miplvl=0, face=0)
- if (!m_textureData && img.layer == 0 && img.mipLevel == 0 && img.face == QAbstractTexture::CubeMapPositiveX) {
- if (imgData->width() != -1 && imgData->height() != -1 && imgData->depth() != -1) {
- m_properties.width = imgData->width();
- m_properties.height = imgData->height();
- m_properties.depth = imgData->depth();
- }
-
- // Set the format of the texture if the texture format is set to Automatic
- if (m_properties.format == QAbstractTexture::Automatic) {
- m_properties.format = static_cast<QAbstractTexture::TextureFormat>(imgData->format());
- }
-
- setDirtyFlag(Properties, true);
+ Q_ASSERT(imgData);
+ m_imageData.push_back(imgData);
+ maxMipLevel = qMax(maxMipLevel, img.mipLevel);
+
+ // If the texture doesn't have a texture generator, we will
+ // derive some properties from the first TextureImage (layer=0, miplvl=0, face=0)
+ if (!m_textureData && img.layer == 0 && img.mipLevel == 0 && img.face == QAbstractTexture::CubeMapPositiveX) {
+ if (imgData->width() != -1 && imgData->height() != -1 && imgData->depth() != -1) {
+ m_properties.width = imgData->width();
+ m_properties.height = imgData->height();
+ m_properties.depth = imgData->depth();
+ }
+ // Set the format of the texture if the texture format is set to Automatic
+ if (m_properties.format == QAbstractTexture::Automatic) {
+ m_properties.format = static_cast<QAbstractTexture::TextureFormat>(imgData->format());
}
- } else {
- // No QTextureImageData generated from functor yet, texture will be invalid for this frame
- // but will be correctly loaded at frame n+1
- texturedDataInvalid = true;
+ setDirtyFlag(Properties, true);
}
}
@@ -195,9 +182,6 @@ QOpenGLTexture* GLTexture::getOrCreateGLTexture()
if (m_properties.format == QAbstractTexture::Automatic)
return nullptr;
- if (texturedDataInvalid)
- return nullptr;
-
// if the properties changed, we need to re-allocate the texture
if (testDirtyFlag(Properties)) {
delete m_gl;
@@ -210,13 +194,12 @@ QOpenGLTexture* GLTexture::getOrCreateGLTexture()
return nullptr;
m_gl->allocateStorage();
if (!m_gl->isStorageAllocated()) {
- qWarning() << Q_FUNC_INFO << "texture storage allocation failed";
return nullptr;
}
}
// need to (re-)upload texture data?
- if (needUpload && !texturedDataInvalid) {
+ if (needUpload) {
uploadGLTextureData();
setDirtyFlag(TextureData, false);
}
@@ -294,47 +277,17 @@ void GLTexture::setImages(const QVector<Image> &images)
bool same = (images.size() == m_images.size());
if (same) {
for (int i = 0; i < images.size(); i++) {
- if (images[i] != m_images[i])
+ if (images[i] != m_images[i]) {
same = false;
+ break;
+ }
}
}
- // de-reference all old texture image generators that will no longer be used.
- // we need to check all generators against each other to make sure we don't
- // de-ref a texture that would still be in use, thus maybe causing it to
- // be deleted
- if (!same) {
- for (const Image &oldImg : qAsConst(m_images)) {
- bool stillHaveThatImage = false;
-
- for (const Image &newImg : images) {
- if (oldImg.generator == newImg.generator) {
- stillHaveThatImage = true;
- break;
- }
- }
-
- if (!stillHaveThatImage)
- m_textureImageDataManager->releaseData(oldImg.generator, this);
- }
+ if (!same) {
m_images = images;
-
- // Don't mark the texture data as dirty yet. We defer this until the
- // generators have been executed and the data is made available to the
- // TextureDataManager.
-
- // make sure the generators are executed
- bool newEntriesCreated = false;
- for (const Image& img : qAsConst(images)) {
- newEntriesCreated |= m_textureImageDataManager->requestData(img.generator, this);
- }
-
- if (!newEntriesCreated) {
- // request a data upload (very important in case the image data already
- // exists and wouldn't trigger an update)
- requestUpload();
- }
+ requestUpload();
}
}
diff --git a/src/render/texture/gltexture_p.h b/src/render/texture/gltexture_p.h
index a8f5705e8..cde0a6973 100644
--- a/src/render/texture/gltexture_p.h
+++ b/src/render/texture/gltexture_p.h
@@ -170,8 +170,8 @@ public:
{
return &m_textureMutex;
}
-protected:
+protected:
template<class APITexture, class APITextureImage>
friend class APITextureManager;
diff --git a/src/render/texture/texturedatamanager_p.h b/src/render/texture/texturedatamanager_p.h
index 13ceca0ee..ef330264c 100644
--- a/src/render/texture/texturedatamanager_p.h
+++ b/src/render/texture/texturedatamanager_p.h
@@ -81,7 +81,7 @@ namespace Render {
* If the last texture disassociates from a generator, the QTextureData will
* be deleted.
*/
-template <class GeneratorPtr, class DataPtr, class APITexture>
+template <class GeneratorPtr, class DataPtr, class ReferencedType>
class GeneratorDataManager
{
public:
@@ -94,7 +94,7 @@ public:
*
* Returns true if the Entry for a given generator had to be created
*/
- bool requestData(const GeneratorPtr &generator, APITexture *tex)
+ bool requestData(const GeneratorPtr &generator, ReferencedType r)
{
QMutexLocker lock(&m_mutex);
@@ -103,8 +103,8 @@ public:
if (needsToBeCreated)
entry = createEntry(generator);
Q_ASSERT(entry);
- if (!entry->referencingTextures.contains(tex))
- entry->referencingTextures.push_back(tex);
+ if (!entry->referencingObjects.contains(r))
+ entry->referencingObjects.push_back(r);
return needsToBeCreated;
}
@@ -112,7 +112,7 @@ public:
* Dereference given generator from texture. If no other textures still reference
* the generator, the associated data will be deleted
*/
- void releaseData(const GeneratorPtr &generator, APITexture *tex)
+ void releaseData(const GeneratorPtr &generator, ReferencedType r)
{
QMutexLocker lock(&m_mutex);
@@ -120,9 +120,9 @@ public:
for (auto it = m_data.begin(); it != end; ++it) {
Entry &entry = *it;
if (*entry.generator == *generator) {
- entry.referencingTextures.removeAll(tex);
+ entry.referencingObjects.removeAll(r);
// delete, if that was the last reference
- if (entry.referencingTextures.empty()) {
+ if (entry.referencingObjects.empty()) {
m_data.erase(it);
return;
}
@@ -166,22 +166,21 @@ public:
Entry *entry = findEntry(generator);
if (!entry) {
qWarning() << "[TextureDataManager] assignData() called with non-existent generator";
- } else {
- entry->data = data;
-
- // Mark each texture that references this data as being dirty
- // so that the submission thread knows to upload
- for (auto texture : qAsConst(entry->referencingTextures)) {
- texture->requestUpload();
- }
+ return;
}
+ entry->data = data;
+ }
+
+ bool contains(const GeneratorPtr &generator)
+ {
+ return findEntry(generator) != nullptr;
}
private:
struct Entry {
GeneratorPtr generator;
- QVector<APITexture*> referencingTextures;
+ QVector<ReferencedType> referencingObjects;
DataPtr data;
};
@@ -211,12 +210,12 @@ private:
};
class Q_AUTOTEST_EXPORT TextureDataManager
- : public GeneratorDataManager<QTextureGeneratorPtr, QTextureDataPtr, GLTexture>
+ : public GeneratorDataManager<QTextureGeneratorPtr, QTextureDataPtr, GLTexture*>
{
};
class Q_AUTOTEST_EXPORT TextureImageDataManager
- : public GeneratorDataManager<QTextureImageDataGeneratorPtr, QTextureImageDataPtr, GLTexture>
+ : public GeneratorDataManager<QTextureImageDataGeneratorPtr, QTextureImageDataPtr, Qt3DCore::QNodeId>
{
};
diff --git a/src/render/texture/textureimage.cpp b/src/render/texture/textureimage.cpp
index b732be2d9..b718f237b 100644
--- a/src/render/texture/textureimage.cpp
+++ b/src/render/texture/textureimage.cpp
@@ -42,6 +42,7 @@
#include <Qt3DRender/qtextureimage.h>
#include <Qt3DRender/private/managers_p.h>
#include <Qt3DRender/private/qabstracttextureimage_p.h>
+#include <Qt3DRender/private/texturedatamanager_p.h>
QT_BEGIN_NAMESPACE
@@ -56,6 +57,7 @@ TextureImage::TextureImage()
, m_mipLevel(0)
, m_face(QAbstractTexture::CubeMapPositiveX)
, m_textureManager(nullptr)
+ , m_textureImageDataManager(nullptr)
{
}
@@ -65,6 +67,13 @@ TextureImage::~TextureImage()
void TextureImage::cleanup()
{
+ if (m_generator) {
+ m_textureImageDataManager->releaseData(m_generator, peerId());
+ m_generator.reset();
+ }
+ m_layer = 0;
+ m_mipLevel = 0;
+ m_face = QAbstractTexture::CubeMapPositiveX;
}
void TextureImage::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr &change)
@@ -85,7 +94,11 @@ void TextureImage::initializeFromPeer(const Qt3DCore::QNodeCreatedChangeBasePtr
Q_ASSERT(texture);
// Notify the Texture that it has a new TextureImage and needs an update
texture->addTextureImage(peerId());
+
}
+ // Request functor upload
+ if (m_generator)
+ m_textureImageDataManager->requestData(m_generator, peerId());
}
void TextureImage::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
@@ -100,30 +113,35 @@ void TextureImage::sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e)
} else if (propertyChange->propertyName() == QByteArrayLiteral("face")) {
m_face = static_cast<QAbstractTexture::CubeMapFace>(propertyChange->value().toInt());
} else if (propertyChange->propertyName() == QByteArrayLiteral("dataGenerator")) {
+ // Release ref to generator
+ if (m_generator)
+ m_textureImageDataManager->releaseData(m_generator, peerId());
m_generator = propertyChange->value().value<QTextureImageDataGeneratorPtr>();
+ // Request functor upload
+ if (m_generator)
+ m_textureImageDataManager->requestData(m_generator, peerId());
}
// Notify the Texture that we were updated and request it to schedule an update job
Texture *txt = m_textureManager->data(m_textureProvider);
if (txt != nullptr)
txt->addDirtyFlag(Texture::DirtyImageGenerators);
+
}
markDirty(AbstractRenderer::AllDirty);
BackendNode::sceneChangeEvent(e);
}
-void TextureImage::setTextureManager(TextureManager *manager)
-{
- m_textureManager = manager;
-}
TextureImageFunctor::TextureImageFunctor(AbstractRenderer *renderer,
TextureManager *textureManager,
- TextureImageManager *textureImageManager)
+ TextureImageManager *textureImageManager,
+ TextureImageDataManager *textureImageDataManager)
: m_renderer(renderer)
, m_textureManager(textureManager)
, m_textureImageManager(textureImageManager)
+ , m_textureImageDataManager(textureImageDataManager)
{
}
@@ -131,6 +149,7 @@ Qt3DCore::QBackendNode *TextureImageFunctor::create(const Qt3DCore::QNodeCreated
{
TextureImage *backend = m_textureImageManager->getOrCreateResource(change->subjectId());
backend->setTextureManager(m_textureManager);
+ backend->setTextureImageDataManager(m_textureImageDataManager);
backend->setRenderer(m_renderer);
return backend;
}
diff --git a/src/render/texture/textureimage_p.h b/src/render/texture/textureimage_p.h
index e898b2f1a..b7a1fae8e 100644
--- a/src/render/texture/textureimage_p.h
+++ b/src/render/texture/textureimage_p.h
@@ -64,7 +64,7 @@ namespace Render {
class TextureManager;
class TextureImageManager;
-class TextureDataManager;
+class TextureImageDataManager;
/**
* Backend class for QAbstractTextureImage.
@@ -78,7 +78,11 @@ public:
void cleanup();
- void setTextureManager(TextureManager *manager);
+ void setTextureManager(TextureManager *manager) { m_textureManager = manager; }
+ void setTextureImageDataManager(TextureImageDataManager *dataManager) { m_textureImageDataManager = dataManager; }
+
+ TextureManager *textureManager() const { return m_textureManager; }
+ TextureImageDataManager *textureImageDataManager() const { return m_textureImageDataManager; }
void sceneChangeEvent(const Qt3DCore::QSceneChangePtr &e) override;
@@ -96,6 +100,7 @@ private:
QTextureImageDataGeneratorPtr m_generator;
TextureManager *m_textureManager;
+ TextureImageDataManager *m_textureImageDataManager;
HTexture m_textureProvider;
};
@@ -104,7 +109,8 @@ class TextureImageFunctor : public Qt3DCore::QBackendNodeMapper
public:
explicit TextureImageFunctor(AbstractRenderer *renderer,
TextureManager *textureManager,
- TextureImageManager *textureImageManager);
+ TextureImageManager *textureImageManager,
+ TextureImageDataManager *textureImageDataManager);
Qt3DCore::QBackendNode *create(const Qt3DCore::QNodeCreatedChangeBasePtr &change) const final;
Qt3DCore::QBackendNode *get(Qt3DCore::QNodeId id) const final;
@@ -114,6 +120,7 @@ private:
AbstractRenderer *m_renderer;
TextureManager *m_textureManager;
TextureImageManager *m_textureImageManager;
+ TextureImageDataManager *m_textureImageDataManager;
};
#ifndef QT_NO_DEBUG_STREAM
diff --git a/tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp b/tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp
index 5ba43aedc..eb7177adf 100644
--- a/tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp
+++ b/tests/auto/render/texturedatamanager/tst_texturedatamanager.cpp
@@ -73,7 +73,7 @@ struct FakeAPITexture
void requestUpload() {}
};
-using Manager = Qt3DRender::Render::GeneratorDataManager<FakeGeneratorPtr, FakeDataPtr, FakeAPITexture>;
+using Manager = Qt3DRender::Render::GeneratorDataManager<FakeGeneratorPtr, FakeDataPtr, FakeAPITexture*>;
} // anonymous
diff --git a/tests/auto/render/textures/textures.pro b/tests/auto/render/textures/textures.pro
index 0366adfe7..8a7553a54 100644
--- a/tests/auto/render/textures/textures.pro
+++ b/tests/auto/render/textures/textures.pro
@@ -9,3 +9,4 @@ CONFIG += testcase
SOURCES += tst_textures.cpp
include(../../core/common/common.pri)
+include(../commons/commons.pri)
diff --git a/tests/auto/render/textures/tst_textures.cpp b/tests/auto/render/textures/tst_textures.cpp
index 8005e998a..f50131e12 100644
--- a/tests/auto/render/textures/tst_textures.cpp
+++ b/tests/auto/render/textures/tst_textures.cpp
@@ -43,6 +43,8 @@
#include <Qt3DRender/private/gltexture_p.h>
#include <Qt3DRender/private/qtexture_p.h>
+#include <testrenderer.h>
+
/**
* @brief Dummy QTextureImageDataGenerator
*/
@@ -122,12 +124,12 @@ public:
{
}
-protected:
- int m_genId;
Qt3DRender::QTextureImageDataGeneratorPtr dataGenerator() const
{
return Qt3DRender::QTextureImageDataGeneratorPtr(new TestImageDataGenerator(m_genId));
}
+protected:
+ int m_genId;
};
class tst_RenderTextures : public Qt3DCore::QBackendNodeTester
@@ -149,7 +151,8 @@ class tst_RenderTextures : public Qt3DCore::QBackendNodeTester
Qt3DRender::Render::Texture *createBackendTexture(Qt3DRender::QAbstractTexture *frontend,
Qt3DRender::Render::TextureManager *texMgr,
- Qt3DRender::Render::TextureImageManager *texImgMgr)
+ Qt3DRender::Render::TextureImageManager *texImgMgr,
+ Qt3DRender::Render::TextureImageDataManager *texImgDataManager)
{
Qt3DRender::Render::Texture *backend = texMgr->getOrCreateResource(frontend->id());
backend->setTextureImageManager(texImgMgr);
@@ -161,6 +164,7 @@ class tst_RenderTextures : public Qt3DCore::QBackendNodeTester
if (!texImgMgr->contains(texImgFrontend->id())) {
Qt3DRender::Render::TextureImage *texImgBackend = texImgMgr->getOrCreateResource(texImgFrontend->id());
texImgBackend->setTextureManager(texMgr);
+ texImgBackend->setTextureImageDataManager(texImgDataManager);
simulateInitialization(texImgFrontend, texImgBackend);
}
backend->addTextureImage(texImgFrontend->id());
@@ -182,8 +186,14 @@ private Q_SLOTS:
Qt3DRender::QAbstractTexture *tex1b = createQTexture(-1, {1,2}, true);
// WHEN
- Qt3DRender::Render::Texture *bt1a = createBackendTexture(tex1a, mgrs->textureManager(), mgrs->textureImageManager());
- Qt3DRender::Render::Texture *bt1b = createBackendTexture(tex1b, mgrs->textureManager(), mgrs->textureImageManager());
+ Qt3DRender::Render::Texture *bt1a = createBackendTexture(tex1a,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ mgrs->textureImageDataManager());
+ Qt3DRender::Render::Texture *bt1b = createBackendTexture(tex1b,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ mgrs->textureImageDataManager());
renderer.updateTexture(bt1a);
renderer.updateTexture(bt1b);
@@ -209,7 +219,10 @@ private Q_SLOTS:
// WHEN
QVector<Qt3DRender::Render::Texture*> backend;
for (auto *t : textures) {
- Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t, mgrs->textureManager(), mgrs->textureImageManager());
+ Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ mgrs->textureImageDataManager());
backend.push_back(backendTexture);
renderer.updateTexture(backendTexture);
}
@@ -256,7 +269,10 @@ private Q_SLOTS:
// WHEN
QVector<Qt3DRender::Render::Texture*> backend;
for (auto *t : textures) {
- Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t, mgrs->textureManager(), mgrs->textureImageManager());
+ Qt3DRender::Render::Texture *backendTexture = createBackendTexture(t,
+ mgrs->textureManager(),
+ mgrs->textureImageManager(),
+ mgrs->textureImageDataManager());
backend.push_back(backendTexture);
renderer.updateTexture(backendTexture);
}
@@ -308,6 +324,265 @@ private Q_SLOTS:
QVERIFY(texDataMgr->getData(tg1a) != texDataMgr->getData(tg2));
}
+ void checkTextureImageInitialState()
+ {
+ // GIVEN
+ Qt3DRender::Render::TextureImage img;
+
+ // THEN
+ QCOMPARE(img.layer(), 0);
+ QCOMPARE(img.mipLevel(), 0);
+ QCOMPARE(img.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX);
+ QVERIFY(img.dataGenerator().isNull());
+ QVERIFY(img.textureManager() == nullptr);
+ QVERIFY(img.textureImageDataManager() == nullptr);
+ }
+
+ void checkTextureImageCleanupState()
+ {
+ // GIVEN
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager();
+ Qt3DRender::Render::TextureImageDataManager *texImgDataMgr = mgrs->textureImageDataManager();
+
+ TestTextureImage img(1);
+ img.setLayer(2);
+ img.setMipLevel(3);
+
+ // WHEN
+ Qt3DRender::Render::TextureImage texImgBackend;
+ texImgBackend.setTextureManager(texMgr);
+ texImgBackend.setTextureImageDataManager(texImgDataMgr);
+ simulateInitialization(&img, &texImgBackend);
+ texImgBackend.cleanup();
+
+ // THEN
+ QCOMPARE(texImgBackend.layer(), 0);
+ QCOMPARE(texImgBackend.mipLevel(), 0);
+ QCOMPARE(texImgBackend.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX);
+ QVERIFY(texImgBackend.dataGenerator().isNull());
+ QVERIFY(texImgBackend.textureManager() != nullptr);
+ QVERIFY(texImgBackend.textureImageDataManager() != nullptr);
+ }
+
+ void checkTextureImageInitializeFromPeer()
+ {
+ // GIVEN
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager();
+ Qt3DRender::Render::TextureImageDataManager *texImgDataMgr = mgrs->textureImageDataManager();
+
+ TestTextureImage img(1);
+
+ {
+ // WHEN
+ img.setLayer(2);
+ img.setMipLevel(3);
+
+ Qt3DRender::Render::TextureImage texImgBackend;
+ texImgBackend.setTextureManager(texMgr);
+ texImgBackend.setTextureImageDataManager(texImgDataMgr);
+ simulateInitialization(&img, &texImgBackend);
+
+ // THEN
+ QCOMPARE(texImgBackend.isEnabled(), true);
+ QCOMPARE(texImgBackend.peerId(), img.id());
+ QCOMPARE(texImgBackend.layer(), 2);
+ QCOMPARE(texImgBackend.mipLevel(), 3);
+ QCOMPARE(texImgBackend.face(), Qt3DRender::QAbstractTexture::CubeMapPositiveX);
+ QVERIFY(!texImgBackend.dataGenerator().isNull());
+ }
+
+ {
+ // WHEN
+ img.setEnabled(false);
+
+ Qt3DRender::Render::TextureImage texImgBackend;
+ texImgBackend.setTextureManager(texMgr);
+ texImgBackend.setTextureImageDataManager(texImgDataMgr);
+ simulateInitialization(&img, &texImgBackend);
+
+ // THEN
+ QCOMPARE(texImgBackend.isEnabled(), false);
+ QCOMPARE(texImgBackend.peerId(), img.id());
+ }
+ }
+
+ void checkTextureImageSceneChangeEvents()
+ {
+ // GIVEN
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager();
+ Qt3DRender::Render::TextureImageDataManager *texImgDataMgr = mgrs->textureImageDataManager();
+ Qt3DRender::Render::TextureImage backendImage;
+ TestRenderer renderer;
+ backendImage.setRenderer(&renderer);
+ backendImage.setTextureManager(texMgr);
+ backendImage.setTextureImageDataManager(texImgDataMgr);
+
+ {
+ // WHEN
+ const bool newValue = false;
+ const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
+ change->setPropertyName("enabled");
+ change->setValue(newValue);
+ backendImage.sceneChangeEvent(change);
+
+ // THEN
+ QCOMPARE(backendImage.isEnabled(), newValue);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ }
+
+ {
+ // WHEN
+ const int newValue = 7;
+ const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
+ change->setPropertyName("layer");
+ change->setValue(newValue);
+ backendImage.sceneChangeEvent(change);
+
+ // THEN
+ QCOMPARE(backendImage.layer(), newValue);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ }
+
+ {
+ // WHEN
+ const int newValue = 3;
+ const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
+ change->setPropertyName("mipLevel");
+ change->setValue(newValue);
+ backendImage.sceneChangeEvent(change);
+
+ // THEN
+ QCOMPARE(backendImage.mipLevel(), newValue);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ }
+
+ {
+ // WHEN
+ const Qt3DRender::QAbstractTexture::CubeMapFace newValue = Qt3DRender::QAbstractTexture::CubeMapNegativeX;
+ const auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
+ change->setPropertyName("face");
+ change->setValue(newValue);
+ backendImage.sceneChangeEvent(change);
+
+ // THEN
+ QCOMPARE(backendImage.face(), newValue);
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ }
+
+ {
+ // WHEN
+ Qt3DRender::QTextureImageDataGeneratorPtr generator1(new TestImageDataGenerator(883));
+ auto change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
+ change->setPropertyName("dataGenerator");
+ change->setValue(QVariant::fromValue(generator1));
+ backendImage.sceneChangeEvent(change);
+
+ // THEN
+ QCOMPARE(backendImage.dataGenerator(), generator1);
+ QVERIFY(texImgDataMgr->contains(generator1));
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+
+ // WHEN
+ Qt3DRender::QTextureImageDataGeneratorPtr generator2(new TestImageDataGenerator(1584));
+ change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
+ change->setPropertyName("dataGenerator");
+ change->setValue(QVariant::fromValue(generator2));
+ backendImage.sceneChangeEvent(change);
+
+ // THEN
+ QVERIFY(!texImgDataMgr->contains(generator1));
+ QVERIFY(texImgDataMgr->contains(generator2));
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+
+ // WHEN
+ Qt3DRender::QTextureImageDataGeneratorPtr generator3;
+ change = Qt3DCore::QPropertyUpdatedChangePtr::create(Qt3DCore::QNodeId());
+ change->setPropertyName("dataGenerator");
+ change->setValue(QVariant::fromValue(generator3));
+ backendImage.sceneChangeEvent(change);
+
+ // THEN
+ QVERIFY(!texImgDataMgr->contains(generator1));
+ QVERIFY(!texImgDataMgr->contains(generator2));
+ QVERIFY(backendImage.dataGenerator().isNull());
+ QVERIFY(renderer.dirtyBits() & Qt3DRender::Render::AbstractRenderer::AllDirty);
+ renderer.clearDirtyBits(Qt3DRender::Render::AbstractRenderer::AllDirty);
+ }
+ }
+
+ void checkTextureImageProperlyReleaseGenerator()
+ {
+ QScopedPointer<Qt3DRender::Render::NodeManagers> mgrs(new Qt3DRender::Render::NodeManagers());
+ Qt3DRender::Render::Renderer renderer(Qt3DRender::QRenderAspect::Synchronous);
+ Qt3DRender::Render::TextureManager *texMgr = mgrs->textureManager();
+ Qt3DRender::Render::TextureImageManager *texImgMgr = mgrs->textureImageManager();
+ Qt3DRender::Render::TextureImageDataManager *texImgDataMgr = mgrs->textureImageDataManager();
+ renderer.setNodeManagers(mgrs.data());
+
+ // GIVEN
+ Qt3DRender::QAbstractTexture* frontendTexture = createQTexture(1, {1}, true);
+
+ Qt3DRender::Render::Texture *backendTexture = texMgr->getOrCreateResource(frontendTexture->id());
+ backendTexture->setTextureImageManager(texImgMgr);
+ simulateInitialization(frontendTexture, backendTexture);
+
+ // THEN
+ QCOMPARE(backendTexture->textureImages().size(), 0);
+ QCOMPARE(frontendTexture->textureImages().size(), 1);
+
+ // WHEN
+ TestTextureImage *texImgFrontend = static_cast<TestTextureImage *>(frontendTexture->textureImages().first());
+ const Qt3DRender::QTextureImageDataGeneratorPtr frontendGenerator = texImgFrontend->dataGenerator();
+
+ // THEN
+ QVERIFY(!frontendGenerator.isNull());
+ QCOMPARE(texImgDataMgr->pendingGenerators().size(), 0);
+ QVERIFY(!texImgDataMgr->contains(frontendGenerator));
+ QVERIFY(texImgDataMgr->getData(frontendGenerator).isNull());
+
+ // WHEN
+ Qt3DRender::Render::TextureImage *texImgBackend = texImgMgr->getOrCreateResource(texImgFrontend->id());
+ texImgBackend->setTextureManager(texMgr);
+ texImgBackend->setTextureImageDataManager(texImgDataMgr);
+ simulateInitialization(texImgFrontend, texImgBackend);
+
+ // THEN
+ qDebug() << frontendGenerator << texImgBackend->dataGenerator();
+ const Qt3DRender::QTextureImageDataGeneratorPtr backendGenerator = texImgFrontend->dataGenerator();
+ QVERIFY(frontendGenerator != backendGenerator);
+ QVERIFY(*frontendGenerator == *backendGenerator);
+ QVERIFY(texImgDataMgr->contains(frontendGenerator));
+ QVERIFY(texImgDataMgr->contains(backendGenerator));
+ QVERIFY(texImgDataMgr->getData(frontendGenerator).isNull());
+ QCOMPARE(texImgDataMgr->pendingGenerators().size(), 1);
+
+ // WHEN
+ texImgDataMgr->assignData(frontendGenerator, (*frontendGenerator)());
+
+ // THEN
+ QVERIFY(!texImgDataMgr->getData(frontendGenerator).isNull());
+ QVERIFY(!texImgDataMgr->getData(backendGenerator).isNull());
+ QVERIFY(texImgDataMgr->getData(backendGenerator) == texImgDataMgr->getData(frontendGenerator));
+
+ // WHEN
+ texImgBackend->cleanup();
+
+ // THEN
+ QVERIFY(!texImgDataMgr->contains(frontendGenerator));
+ QVERIFY(!texImgDataMgr->contains(backendGenerator));
+ QCOMPARE(texImgDataMgr->pendingGenerators().size(), 0);
+ QVERIFY(texImgDataMgr->getData(frontendGenerator).isNull());
+ QVERIFY(texImgDataMgr->getData(backendGenerator).isNull());
+ }
};
QTEST_MAIN(tst_RenderTextures)