summaryrefslogtreecommitdiffstats
path: root/src/render/renderers
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2019-02-19 13:34:13 +0100
committerPaul Lemire <paul.lemire@kdab.com>2019-03-04 14:52:38 +0000
commit0a8742532fb1697203dd3d7d9c1c28b4cb052e2d (patch)
treee417fec5065df3d7e8d66f237ba56fb39435185d /src/render/renderers
parent299c0bc6d2ea5817ba32b3724290c349789be11b (diff)
Rework internal Texture Handling
- Remove internal GLTexture sharing - Remove dataFunctor data sharing - Simplify the overall texture process: 1) Look for dirty textures (either a property on QTexture or a referenced QTextureImage has changed) 2) Update GL Resources - Create a GLTexture for a given Texture if it doesn't exist - Update GLTexture to reflect Texture state - Perform actual GL texture creation and or upload (call functors at this point) - Cleanup GLTextures when matching Texture node has been destroyed This will provide an easier maintenance over time as it drastically simplifies the handling of textures and removes most of the coupling. Furthermore this will make it possible to send texture updates on a QTexture node to update texture content without having to declare QTextureImages which would not have been (or would have been a lot harder) to do. In practice, I doubt most people were even aware of the internal texture sharing in the first place. [ChangeLog][Qt3DRender] Textures: internal data sharing removed Change-Id: I02867c8105e29eb1e193884e3899062f795f32f4 Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/render/renderers')
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp166
-rw-r--r--src/render/renderers/opengl/renderer/renderer_p.h7
-rw-r--r--src/render/renderers/opengl/textures/gltexture.cpp102
-rw-r--r--src/render/renderers/opengl/textures/gltexture_p.h43
-rw-r--r--src/render/renderers/opengl/textures/gltexturemanager_p.h17
5 files changed, 137 insertions, 198 deletions
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index d8b1409e1..be08abbd0 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -199,7 +199,7 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_sendTextureChangesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendTextureChangesToFrontend(); }, JobTypes::SendTextureChangesToFrontend))
, m_sendSetFenceHandlesToFrontendJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { sendSetFenceHandlesToFrontend(); }, JobTypes::SendSetFenceHandlesToFrontend))
, m_introspectShaderJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { reloadDirtyShaders(); }, JobTypes::DirtyShaderGathering))
- , m_syncTextureLoadingJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncTextureLoading))
+ , m_syncLoadingJobs(Render::GenericLambdaJobPtr<std::function<void ()>>::create([] {}, JobTypes::SyncLoadingJobs))
, m_ownedContext(false)
, m_offscreenHelper(nullptr)
#if QT_CONFIG(qt3d_profile_jobs)
@@ -222,12 +222,8 @@ Renderer::Renderer(QRenderAspect::RenderType type)
m_rayCastingJob->addDependency(m_expandBoundingVolumeJob);
// m_calculateBoundingVolumeJob's dependency on m_updateTreeEnabledJob is set in renderBinJobs
- // Dirty texture gathering depends on m_syncTextureLoadingJob
- // m_syncTextureLoadingJob will depend on the texture loading jobs
- m_textureGathererJob->addDependency(m_syncTextureLoadingJob);
-
// Ensures all skeletons are loaded before we try to update them
- m_updateSkinningPaletteJob->addDependency(m_syncTextureLoadingJob);
+ m_updateSkinningPaletteJob->addDependency(m_syncLoadingJobs);
// All world stuff depends on the RenderEntity's localBoundingVolume
m_updateLevelOfDetailJob->addDependency(m_updateMeshTriangleListJob);
@@ -501,9 +497,11 @@ void Renderer::releaseGraphicsResources()
if (context->makeCurrent(offscreenSurface)) {
// Clean up the graphics context and any resources
- const QVector<GLTexture*> activeTextures = m_nodesManager->glTextureManager()->activeResources();
- for (GLTexture *tex : activeTextures)
- tex->destroyGLTexture();
+ const QVector<HGLTexture> activeTexturesHandles = m_nodesManager->glTextureManager()->activeHandles();
+ for (const HGLTexture &textureHandle : activeTexturesHandles) {
+ GLTexture *tex = m_nodesManager->glTextureManager()->data(textureHandle);
+ tex->destroy();
+ }
// Do the same thing with buffers
const QVector<HGLBuffer> activeBuffers = m_nodesManager->glBufferManager()->activeHandles();
@@ -1297,7 +1295,8 @@ void Renderer::updateGLResources()
if (texture == nullptr)
continue;
- // Create or Update GLTexture
+ // Create or Update GLTexture (the GLTexture instance is created if required
+ // and all things that can take place without a GL context are done here)
updateTexture(texture);
}
// We want to upload textures data at this point as the SubmissionThread and
@@ -1305,15 +1304,18 @@ void Renderer::updateGLResources()
// GLTexture
if (m_submissionContext != nullptr) {
GLTextureManager *glTextureManager = m_nodesManager->glTextureManager();
- const QVector<GLTexture *> glTextures = glTextureManager->activeResources();
+ const QVector<HGLTexture> glTextureHandles = glTextureManager->activeHandles();
// Upload texture data
- for (GLTexture *glTexture : glTextures) {
+ for (const HGLTexture &glTextureHandle : glTextureHandles) {
+ GLTexture *glTexture = glTextureManager->data(glTextureHandle);
+
+ // We create/update the actual GL texture using the GL context at this point
const GLTexture::TextureUpdateInfo info = glTexture->createOrUpdateGLTexture();
// GLTexture creation provides us width/height/format ... information
// for textures which had not initially specified these information (TargetAutomatic...)
// Gather these information and store them to be distributed by a change next frame
- const QNodeIdVector referenceTextureIds = glTextureManager->referencedTextureIds(glTexture);
+ const QNodeIdVector referenceTextureIds = { glTextureManager->texNodeIdForGLTexture.value(glTexture) };
// Store properties and referenceTextureIds
if (info.wasUpdated) {
Texture::TextureUpdateInfo updateInfo;
@@ -1324,14 +1326,10 @@ void Renderer::updateGLResources()
}
}
}
+
+ // Record ids of texture to cleanup while we are still blocking the aspect thread
+ m_textureIdsToCleanup += m_nodesManager->textureManager()->takeTexturesIdsToCleanup();
}
- // When Textures are cleaned up, their id is saved so that they can be
- // cleaned up in the render thread Note: we perform this step in second so
- // that the previous updateTexture call has a chance to find a shared
- // texture and avoid possible destroying recreating a new texture
- const QVector<Qt3DCore::QNodeId> cleanedUpTextureIds = m_nodesManager->textureManager()->takeTexturesIdsToCleanup();
- for (const Qt3DCore::QNodeId textureCleanedUpId: cleanedUpTextureIds)
- cleanupTexture(textureCleanedUpId);
}
// Render Thread
@@ -1339,92 +1337,56 @@ void Renderer::updateTexture(Texture *texture)
{
// Check that the current texture images are still in place, if not, do not update
const bool isValid = texture->isValid(m_nodesManager->textureImageManager());
- if (!isValid)
+ if (!isValid) {
+ qWarning() << Q_FUNC_INFO << "QTexture referencing invalid QTextureImages";
return;
-
- // For implementing unique, non-shared, non-cached textures.
- // for now, every texture is shared by default except if:
- // - texture is reference by a render attachment
- // - texture is referencing a shared texture id
- bool isUnique = texture->sharedTextureId() > 0;
-
- if (!isUnique) {
- // TO DO: Update the vector once per frame (or in a job)
- const QVector<HAttachment> activeRenderTargetOutputs = m_nodesManager->attachmentManager()->activeHandles();
- // A texture is unique if it's being reference by a render target output
- for (const HAttachment &attachmentHandle : activeRenderTargetOutputs) {
- RenderTargetOutput *attachment = m_nodesManager->attachmentManager()->data(attachmentHandle);
- if (attachment->textureUuid() == texture->peerId()) {
- isUnique = true;
- break;
- }
- }
}
+ // All textures are unique, if you instanciate twice the exact same texture
+ // this will create 2 identical GLTextures, no sharing will take place
+
// Try to find the associated GLTexture for the backend Texture
GLTextureManager *glTextureManager = m_nodesManager->glTextureManager();
GLTexture *glTexture = glTextureManager->lookupResource(texture->peerId());
- auto createOrUpdateGLTexture = [=] () {
- if (isUnique)
- glTextureManager->createUnique(texture);
- else
- glTextureManager->getOrCreateShared(texture);
- texture->unsetDirty();
- };
-
// No GLTexture associated yet -> create it
if (glTexture == nullptr) {
- createOrUpdateGLTexture();
- return;
+ glTexture = glTextureManager->getOrCreateResource(texture->peerId());
+ glTextureManager->texNodeIdForGLTexture.insert(glTexture, texture->peerId());
}
- // if this texture is a shared texture, we might need to look for a new TextureImpl
- // and abandon the old one
- if (glTextureManager->isShared(glTexture)) {
- glTextureManager->abandon(glTexture, texture->peerId());
- // Note: if isUnique is true, a once shared texture will become unique
- createOrUpdateGLTexture();
- return;
- }
-
- // this texture node is the only one referring to the GLTexture.
- // we could thus directly modify the texture. Instead, for non-unique textures,
- // we first see if there is already a matching texture present.
- if (!isUnique) {
- GLTexture *newSharedTex = glTextureManager->findMatchingShared(texture);
- if (newSharedTex && newSharedTex != glTexture) {
- glTextureManager->abandon(glTexture, texture->peerId());
- glTextureManager->adoptShared(newSharedTex, texture);
- texture->unsetDirty();
- return;
- }
- }
-
- // we hold a reference to a unique or exclusive access to a shared texture
- // we can thus modify the texture directly.
+ // Update GLTexture to match Texture instance
const Texture::DirtyFlags dirtyFlags = texture->dirtyFlags();
- if (dirtyFlags.testFlag(Texture::DirtySharedTextureId) &&
- !glTextureManager->setSharedTextureId(glTexture, texture->sharedTextureId()))
- qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setSharedTextureId failed, should be non-shared";
+ if (dirtyFlags.testFlag(Texture::DirtySharedTextureId))
+ glTexture->setSharedTextureId(texture->sharedTextureId());
- if (dirtyFlags.testFlag(Texture::DirtyProperties) &&
- !glTextureManager->setProperties(glTexture, texture->properties()))
- qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setProperties failed, should be non-shared";
+ if (dirtyFlags.testFlag(Texture::DirtyProperties))
+ glTexture->setProperties(texture->properties());
- if (dirtyFlags.testFlag(Texture::DirtyParameters) &&
- !glTextureManager->setParameters(glTexture, texture->parameters()))
- qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setParameters failed, should be non-shared";
+ if (dirtyFlags.testFlag(Texture::DirtyParameters))
+ glTexture->setParameters(texture->parameters());
// Will make the texture requestUpload
- if (dirtyFlags.testFlag(Texture::DirtyImageGenerators) &&
- !glTextureManager->setImages(glTexture, texture->textureImageIds()))
- qWarning() << "[Qt3DRender::TextureNode] updateTexture: TextureImpl.setGenerators failed, should be non-shared";
+ if (dirtyFlags.testFlag(Texture::DirtyImageGenerators)) {
+ const QNodeIdVector textureImageIds = texture->textureImageIds();
+ QVector<GLTexture::Image> images;
+ images.reserve(textureImageIds.size());
+ // TODO: Move this into GLTexture directly
+ for (const QNodeId textureImageId : textureImageIds) {
+ const TextureImage *img = m_nodesManager->textureImageManager()->lookupResource(textureImageId);
+ if (img == nullptr) {
+ qWarning() << Q_FUNC_INFO << "invalid TextureImage handle";
+ } else {
+ GLTexture::Image glImg {img->dataGenerator(), img->layer(), img->mipLevel(), img->face()};
+ images.push_back(glImg);
+ }
+ }
+ glTexture->setImages(images);
+ }
// 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";
+ if (dirtyFlags.testFlag(Texture::DirtyDataGenerator))
+ glTexture->setGenerator(texture->dataGenerator());
// Unset the dirty flag on the texture
texture->unsetDirty();
@@ -1436,8 +1398,11 @@ void Renderer::cleanupTexture(Qt3DCore::QNodeId cleanedUpTextureId)
GLTextureManager *glTextureManager = m_nodesManager->glTextureManager();
GLTexture *glTexture = glTextureManager->lookupResource(cleanedUpTextureId);
- if (glTexture != nullptr)
- glTextureManager->abandon(glTexture, cleanedUpTextureId);
+ // Destroying the GLTexture implicitely also destroy the GL resources
+ if (glTexture != nullptr) {
+ glTextureManager->releaseResource(cleanedUpTextureId);
+ glTextureManager->texNodeIdForGLTexture.remove(glTexture);
+ }
}
// Called by SubmitRenderView
@@ -1808,6 +1773,8 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
renderBinJobs.push_back(m_expandBoundingVolumeJob);
}
+ // TO DO: Conditionally add if skeletons dirty
+ renderBinJobs.push_back(m_syncLoadingJobs);
m_updateSkinningPaletteJob->setDirtyJoints(m_nodesManager->jointManager()->dirtyJoints());
renderBinJobs.push_back(m_updateSkinningPaletteJob);
renderBinJobs.push_back(m_updateLevelOfDetailJob);
@@ -1821,10 +1788,8 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
if (dirtyBitsForFrame & AbstractRenderer::BuffersDirty)
renderBinJobs.push_back(m_bufferGathererJob);
- if (dirtyBitsForFrame & AbstractRenderer::TexturesDirty) {
- renderBinJobs.push_back(m_syncTextureLoadingJob);
+ if (dirtyBitsForFrame & AbstractRenderer::TexturesDirty)
renderBinJobs.push_back(m_textureGathererJob);
- }
// Layer cache is dependent on layers, layer filters and the enabled flag
@@ -1920,9 +1885,9 @@ QAspectJobPtr Renderer::rayCastingJob()
return m_rayCastingJob;
}
-QAspectJobPtr Renderer::syncTextureLoadingJob()
+QAspectJobPtr Renderer::syncLoadingJobs()
{
- return m_syncTextureLoadingJob;
+ return m_syncLoadingJobs;
}
QAspectJobPtr Renderer::expandBoundingVolumeJob()
@@ -2244,12 +2209,11 @@ void Renderer::cleanGraphicsResources()
for (Qt3DCore::QNodeId bufferId : buffersToRelease)
m_submissionContext->releaseBuffer(bufferId);
- // Delete abandoned textures
- const QVector<GLTexture*> abandonedTextures = m_nodesManager->glTextureManager()->takeAbandonedTextures();
- for (GLTexture *tex : abandonedTextures) {
- tex->destroyGLTexture();
- delete tex;
- }
+ // When Textures are cleaned up, their id is saved so that they can be
+ // cleaned up in the render thread
+ const QVector<Qt3DCore::QNodeId> cleanedUpTextureIds = std::move(m_textureIdsToCleanup);
+ for (const Qt3DCore::QNodeId textureCleanedUpId: cleanedUpTextureIds)
+ cleanupTexture(textureCleanedUpId);
// Delete abandoned VAOs
m_abandonedVaosMutex.lock();
diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h
index 93d6fdbfa..a80a862f7 100644
--- a/src/render/renderers/opengl/renderer/renderer_p.h
+++ b/src/render/renderers/opengl/renderer/renderer_p.h
@@ -204,7 +204,7 @@ public:
QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override;
Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override;
Qt3DCore::QAspectJobPtr rayCastingJob() override;
- Qt3DCore::QAspectJobPtr syncTextureLoadingJob() override;
+ Qt3DCore::QAspectJobPtr syncLoadingJobs() override;
Qt3DCore::QAspectJobPtr expandBoundingVolumeJob() override;
QVector<Qt3DCore::QAspectJobPtr> createRenderBufferJobs() const;
@@ -218,7 +218,7 @@ public:
inline UpdateLevelOfDetailJobPtr updateLevelOfDetailJob() const { return m_updateLevelOfDetailJob; }
inline UpdateMeshTriangleListJobPtr updateMeshTriangleListJob() const { return m_updateMeshTriangleListJob; }
inline FilterCompatibleTechniqueJobPtr filterCompatibleTechniqueJob() const { return m_filterCompatibleTechniqueJob; }
- inline SynchronizerJobPtr textureLoadSyncJob() const { return m_syncTextureLoadingJob; }
+ inline SynchronizerJobPtr syncLoadingJobs() const { return m_syncLoadingJobs; }
inline UpdateSkinningPaletteJobPtr updateSkinningPaletteJob() const { return m_updateSkinningPaletteJob; }
inline IntrospectShadersJobPtr introspectShadersJob() const { return m_introspectShaderJob; }
inline Qt3DCore::QAspectJobPtr bufferGathererJob() const { return m_bufferGathererJob; }
@@ -382,7 +382,7 @@ private:
GenericLambdaJobPtr<std::function<void ()>> m_sendSetFenceHandlesToFrontendJob;
IntrospectShadersJobPtr m_introspectShaderJob;
- SynchronizerJobPtr m_syncTextureLoadingJob;
+ SynchronizerJobPtr m_syncLoadingJobs;
void lookForAbandonedVaos();
void lookForDirtyBuffers();
@@ -401,6 +401,7 @@ private:
QVector<HTexture> m_dirtyTextures;
QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> m_updatedTextureProperties;
QVector<QPair<Qt3DCore::QNodeId, GLFence>> m_updatedSetFences;
+ Qt3DCore::QNodeIdVector m_textureIdsToCleanup;
bool m_ownedContext;
diff --git a/src/render/renderers/opengl/textures/gltexture.cpp b/src/render/renderers/opengl/textures/gltexture.cpp
index 42deb4c2a..4561e5ebf 100644
--- a/src/render/renderers/opengl/textures/gltexture.cpp
+++ b/src/render/renderers/opengl/textures/gltexture.cpp
@@ -49,7 +49,6 @@
#include <Qt3DRender/qtexturedata.h>
#include <Qt3DRender/qtextureimagedata.h>
#include <Qt3DRender/private/managers_p.h>
-#include <Qt3DRender/private/texturedatamanager_p.h>
#include <Qt3DRender/private/qabstracttexture_p.h>
#include <Qt3DRender/private/renderbuffer_p.h>
#include <Qt3DRender/private/qtextureimagedata_p.h>
@@ -69,39 +68,42 @@ using namespace Qt3DCore;
namespace Qt3DRender {
namespace Render {
-GLTexture::GLTexture(TextureDataManager *texDataMgr,
- TextureImageDataManager *texImgDataMgr,
- const QTextureGeneratorPtr &texGen,
- bool unique)
- : m_unique(unique)
- , m_gl(nullptr)
+namespace {
+
+// This uploadGLData where the data is a fullsize subimage
+// as QOpenGLTexture doesn't allow partial subimage uploads
+void uploadGLData(QOpenGLTexture *glTex,
+ int level, int layer, QOpenGLTexture::CubeMapFace face,
+ const QByteArray &bytes, const QTextureImageDataPtr &data)
+{
+ if (data->isCompressed()) {
+ glTex->setCompressedData(level, layer, face, bytes.size(), bytes.constData());
+ } else {
+ QOpenGLPixelTransferOptions uploadOptions;
+ uploadOptions.setAlignment(1);
+ glTex->setData(level, layer, face, data->pixelFormat(), data->pixelType(), bytes.constData(), &uploadOptions);
+ }
+}
+
+} // anonymous
+
+
+GLTexture::GLTexture()
+ : m_gl(nullptr)
, m_renderBuffer(nullptr)
- , m_textureDataManager(texDataMgr)
- , m_textureImageDataManager(texImgDataMgr)
- , m_dataFunctor(texGen)
+ , m_dataFunctor()
, m_pendingDataFunctor(nullptr)
, m_sharedTextureId(-1)
, m_externalRendering(false)
{
- // make sure texture generator is executed
- // this is needed when Texture have the TargetAutomatic
- // to ensure they are loaded before trying to instantiate the QOpenGLTexture
- if (!texGen.isNull())
- m_textureDataManager->requestData(texGen, this);
}
GLTexture::~GLTexture()
{
- destroyGLTexture();
}
-void GLTexture::destroyResources()
-{
- if (m_dataFunctor)
- m_textureDataManager->releaseData(m_dataFunctor, this);
-}
-
-void GLTexture::destroyGLTexture()
+// Must be called from RenderThread with active GL context
+void GLTexture::destroy()
{
delete m_gl;
m_gl = nullptr;
@@ -109,13 +111,22 @@ void GLTexture::destroyGLTexture()
m_renderBuffer = nullptr;
m_dirtyFlags.store(0);
-
- destroyResources();
+ m_sharedTextureId = -1;
+ m_externalRendering = false;
+ m_dataFunctor.reset();
+ m_pendingDataFunctor = nullptr;
+
+ m_actualTarget = QAbstractTexture::Target1D;
+ m_properties = {};
+ m_parameters = {};
+ m_textureData.reset();
+ m_images.clear();
+ m_imageData.clear();
}
bool GLTexture::loadTextureDataFromGenerator()
{
- m_textureData = m_textureDataManager->getData(m_dataFunctor);
+ m_textureData = m_dataFunctor->operator()();
// if there is a texture generator, most properties will be defined by it
if (m_textureData) {
if (m_properties.target != QAbstractTexture::TargetAutomatic)
@@ -143,7 +154,7 @@ void GLTexture::loadTextureDataFromImages()
{
int maxMipLevel = 0;
for (const Image &img : qAsConst(m_images)) {
- const QTextureImageDataPtr imgData = m_textureImageDataManager->getData(img.generator);
+ const QTextureImageDataPtr imgData = img.generator->operator()();
// imgData may be null in the following cases:
// - Texture is created with TextureImages which have yet to be
// loaded (skybox where you don't yet know the path, source set by
@@ -285,7 +296,7 @@ RenderBuffer *GLTexture::getOrCreateRenderBuffer()
QMutexLocker locker(&m_textureMutex);
if (m_dataFunctor && !m_textureData) {
- m_textureData = m_textureDataManager->getData(m_dataFunctor);
+ m_textureData = m_dataFunctor->operator()();
if (m_textureData) {
if (m_properties.target != QAbstractTexture::TargetAutomatic)
qWarning() << "[Qt3DRender::GLTexture] [renderbuffer] When a texture provides a generator, it's target is expected to be TargetAutomatic";
@@ -318,6 +329,13 @@ RenderBuffer *GLTexture::getOrCreateRenderBuffer()
return m_renderBuffer;
}
+// This must be called from the RenderThread
+// So GLTexture release from the manager can only be done from that thread
+void GLTexture::cleanup()
+{
+ destroy();
+}
+
void GLTexture::setParameters(const TextureParameters &params)
{
QMutexLocker locker(&m_textureMutex);
@@ -359,19 +377,9 @@ void GLTexture::setImages(const QVector<Image> &images)
void GLTexture::setGenerator(const QTextureGeneratorPtr &generator)
{
- // Note: we do not compare if the generator is different
- // as in some cases we may want to reset the same generator to force a reload
- // e.g when using remote urls for textures
- if (m_dataFunctor)
- m_textureDataManager->releaseData(m_dataFunctor, this);
-
m_textureData.reset();
m_dataFunctor = generator;
-
- if (m_dataFunctor) {
- m_textureDataManager->requestData(m_dataFunctor, this);
- requestUpload();
- }
+ requestUpload();
}
void GLTexture::setSharedTextureId(int textureId)
@@ -471,19 +479,6 @@ QOpenGLTexture *GLTexture::buildGLTexture()
return glTex;
}
-static void uploadGLData(QOpenGLTexture *glTex,
- int level, int layer, QOpenGLTexture::CubeMapFace face,
- const QByteArray &bytes, const QTextureImageDataPtr &data)
-{
- if (data->isCompressed()) {
- glTex->setCompressedData(level, layer, face, bytes.size(), bytes.constData());
- } else {
- QOpenGLPixelTransferOptions uploadOptions;
- uploadOptions.setAlignment(1);
- glTex->setData(level, layer, face, data->pixelFormat(), data->pixelType(), bytes.constData(), &uploadOptions);
- }
-}
-
void GLTexture::uploadGLTextureData()
{
// Upload all QTexImageData set by the QTextureGenerator
@@ -518,6 +513,9 @@ void GLTexture::uploadGLTextureData()
static_cast<QOpenGLTexture::CubeMapFace>(m_images[i].face),
bytes, imgData);
}
+ // Free up image data once content has been uploaded
+ // Note: if data functor stores the data, this won't really free anything though
+ m_imageData.clear();
}
void GLTexture::updateGLTextureParameters()
diff --git a/src/render/renderers/opengl/textures/gltexture_p.h b/src/render/renderers/opengl/textures/gltexture_p.h
index 66f66926c..4dd78513a 100644
--- a/src/render/renderers/opengl/textures/gltexture_p.h
+++ b/src/render/renderers/opengl/textures/gltexture_p.h
@@ -96,11 +96,7 @@ class RenderBuffer;
class Q_AUTOTEST_EXPORT GLTexture
{
public:
- GLTexture(TextureDataManager *texDataMgr,
- TextureImageDataManager *texImgDataMgr,
- const QTextureGeneratorPtr &texGen,
- bool unique);
-
+ GLTexture();
~GLTexture();
/**
@@ -120,8 +116,6 @@ public:
inline bool operator!=(const Image &o) const { return !(*this == o); }
};
- inline bool isUnique() const { return m_unique; }
-
inline TextureProperties properties() const { return m_properties; }
inline TextureParameters parameters() const { return m_parameters; }
inline QTextureGeneratorPtr textureGenerator() const { return m_dataFunctor; }
@@ -157,17 +151,10 @@ public:
*/
RenderBuffer *getOrCreateRenderBuffer();
- /**
- * @brief Make sure to call this before calling the dtor
- */
- void destroyGLTexture();
- // Called by TextureDataManager when it has new texture data from
- // a generator that needs to be uploaded.
- void requestUpload()
- {
- setDirtyFlag(TextureData, true);
- }
+ void destroy();
+
+ void cleanup();
bool isDirty()
{
@@ -189,18 +176,6 @@ public:
return m_externalRendering;
}
-protected:
- template<class APITexture, class APITextureImage>
- friend class APITextureManager;
-
- /*
- * These methods are to be accessed from the GLTextureManager.
- * The renderer and the texture backend nodes can only modify Textures
- * through the GLTextureManager.
- *
- * The methods should only be called for unique textures, or textures
- * that are not shared between multiple nodes.
- */
void setParameters(const TextureParameters &params);
void setProperties(const TextureProperties &props);
void setImages(const QVector<Image> &images);
@@ -216,6 +191,12 @@ private:
SharedTextureId = 0x08 // texture id from shared context
};
+
+ void requestUpload()
+ {
+ setDirtyFlag(TextureData, true);
+ }
+
bool testDirtyFlag(DirtyFlag flag)
{
return m_dirtyFlags.load() & flag;
@@ -237,16 +218,12 @@ private:
void introspectPropertiesFromSharedTextureId();
void destroyResources();
- bool m_unique;
QAtomicInt m_dirtyFlags;
QMutex m_textureMutex;
QMutex m_externalRenderingMutex;
QOpenGLTexture *m_gl;
RenderBuffer *m_renderBuffer;
- TextureDataManager *m_textureDataManager;
- TextureImageDataManager *m_textureImageDataManager;
-
// target which is actually used for GL texture
QAbstractTexture::Target m_actualTarget;
TextureProperties m_properties;
diff --git a/src/render/renderers/opengl/textures/gltexturemanager_p.h b/src/render/renderers/opengl/textures/gltexturemanager_p.h
index 1c8b49911..335af136c 100644
--- a/src/render/renderers/opengl/textures/gltexturemanager_p.h
+++ b/src/render/renderers/opengl/textures/gltexturemanager_p.h
@@ -51,7 +51,7 @@
// We mean it.
//
-#include <Qt3DRender/private/apitexturemanager_p.h>
+#include <Qt3DCore/private/qresourcemanager_p.h>
#include <Qt3DRender/private/gltexture_p.h>
QT_BEGIN_NAMESPACE
@@ -59,21 +59,20 @@ QT_BEGIN_NAMESPACE
namespace Qt3DRender {
namespace Render {
-class Q_AUTOTEST_EXPORT GLTextureManager : public APITextureManager<GLTexture, GLTexture::Image>
+class Q_AUTOTEST_EXPORT GLTextureManager : public Qt3DCore::QResourceManager<
+ GLTexture,
+ Qt3DCore::QNodeId,
+ Qt3DCore::NonLockingPolicy>
{
public:
- explicit GLTextureManager(TextureImageManager *textureImageManager,
- TextureDataManager *textureDataManager,
- TextureImageDataManager *textureImageDataManager)
- : APITextureManager<GLTexture, GLTexture::Image>(textureImageManager,
- textureDataManager,
- textureImageDataManager)
- {}
+ QHash<GLTexture *, Qt3DCore::QNodeId> texNodeIdForGLTexture;
};
} // namespace Render
} // namespace Qt3DRender
+Q_DECLARE_RESOURCE_INFO(Qt3DRender::Render::GLTexture, Q_REQUIRES_CLEANUP)
+
QT_END_NAMESPACE
#endif // QT3DRENDER_RENDER_GLTEXTUREMANAGER_H