summaryrefslogtreecommitdiffstats
path: root/src/render/renderers/opengl/graphicshelpers
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2019-04-02 15:08:50 +0200
committerPaul Lemire <paul.lemire@kdab.com>2019-04-02 15:25:12 +0200
commitf3259300bde381b10cb737735fe19b039c969782 (patch)
tree43c70cfe34cbf08947752653e98ccb777c1c9521 /src/render/renderers/opengl/graphicshelpers
parent6f7ac29268df048b5f23ad26c47efcbfdfdb3585 (diff)
parent59d26d3e9411150c7ed0fb0cf68d48988c8dbf59 (diff)
Merge branch '5.12' into 5.13
Diffstat (limited to 'src/render/renderers/opengl/graphicshelpers')
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp10
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicscontext_p.h1
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri6
-rw-r--r--src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp205
-rw-r--r--src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h39
-rw-r--r--src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp225
-rw-r--r--src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext_p.h106
7 files changed, 365 insertions, 227 deletions
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
index 59b5701f8..2b8076336 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicscontext.cpp
@@ -130,6 +130,7 @@ GraphicsContext::GraphicsContext()
, m_glHelper(nullptr)
, m_shaderCache(nullptr)
, m_debugLogger(nullptr)
+ , m_currentVAO(nullptr)
{
}
@@ -199,15 +200,20 @@ bool GraphicsContext::makeCurrent(QSurface *surface)
return false;
}
+ initializeHelpers(surface);
+
+ return true;
+}
+
+void GraphicsContext::initializeHelpers(QSurface *surface)
+{
// Set the correct GL Helper depending on the surface
// If no helper exists, create one
-
m_glHelper = m_glHelpers.value(surface);
if (!m_glHelper) {
m_glHelper = resolveHighestOpenGLFunctions();
m_glHelpers.insert(surface, m_glHelper);
}
- return true;
}
void GraphicsContext::doneCurrent()
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicscontext_p.h b/src/render/renderers/opengl/graphicshelpers/graphicscontext_p.h
index 7bc79996c..73d1f316c 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicscontext_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicscontext_p.h
@@ -177,6 +177,7 @@ public:
bool supportsVAO() const { return m_supportsVAO; }
void initialize();
+ void initializeHelpers(QSurface *surface);
GraphicsHelperInterface *resolveHighestOpenGLFunctions();
bool m_initialized;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri b/src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri
index 5c9479d2b..ad08038c9 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri
@@ -3,6 +3,7 @@
INCLUDEPATH += $$PWD
HEADERS += \
+ $$PWD/glfence_p.h \
$$PWD/graphicscontext_p.h \
$$PWD/graphicshelperinterface_p.h \
$$PWD/graphicshelperes2_p.h \
@@ -14,7 +15,7 @@ HEADERS += \
$$PWD/graphicshelpergl4_p.h \
$$PWD/graphicshelpergl3_2_p.h \
$$PWD/submissioncontext_p.h \
- $$PWD/glfence_p.h
+ $$PWD/texturesubmissioncontext_p.h
SOURCES += \
$$PWD/graphicscontext.cpp \
@@ -26,4 +27,5 @@ SOURCES += \
$$PWD/graphicshelpergl3_3.cpp \
$$PWD/graphicshelpergl4.cpp \
$$PWD/graphicshelpergl3_2.cpp \
- $$PWD/submissioncontext.cpp
+ $$PWD/submissioncontext.cpp \
+ $$PWD/texturesubmissioncontext.cpp
diff --git a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
index d1ac853ea..51f7cebd1 100644
--- a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
@@ -49,6 +49,7 @@
#include <Qt3DRender/private/buffer_p.h>
#include <Qt3DRender/private/attribute_p.h>
#include <Qt3DRender/private/rendercommand_p.h>
+#include <Qt3DRender/private/renderstates_p.h>
#include <Qt3DRender/private/renderstateset_p.h>
#include <Qt3DRender/private/rendertarget_p.h>
#include <Qt3DRender/private/graphicshelperinterface_p.h>
@@ -96,40 +97,18 @@ namespace Qt3DRender {
namespace Render {
-class TextureExtRendererLocker
+static QHash<unsigned int, SubmissionContext*> static_contexts;
+
+unsigned int nextFreeContextId()
{
-public:
- static void lock(GLTexture *tex)
- {
- if (!tex->isExternalRenderingEnabled())
- return;
- if (s_lockHash.keys().contains(tex)) {
- ++s_lockHash[tex];
- } else {
- tex->externalRenderingLock()->lock();
- s_lockHash[tex] = 1;
- }
- }
- static void unlock(GLTexture *tex)
- {
- if (!tex->isExternalRenderingEnabled())
- return;
- if (!s_lockHash.keys().contains(tex))
- return;
-
- --s_lockHash[tex];
- if (s_lockHash[tex] == 0) {
- s_lockHash.remove(tex);
- tex->externalRenderingLock()->unlock();
- }
+ for (unsigned int i=0; i < 0xffff; ++i) {
+ if (!static_contexts.contains(i))
+ return i;
}
-private:
- static QHash<GLTexture*, int> s_lockHash;
-};
-
-QHash<GLTexture*, int> TextureExtRendererLocker::s_lockHash = QHash<GLTexture*, int>();
-static QHash<unsigned int, SubmissionContext*> static_contexts;
+ qFatal("Couldn't find free context ID");
+ return 0;
+}
namespace {
@@ -366,16 +345,6 @@ void applyStateHelper<LineWidth>(const LineWidth *state, SubmissionContext *gc)
} // anonymous
-unsigned int nextFreeContextId()
-{
- for (unsigned int i=0; i < 0xffff; ++i) {
- if (!static_contexts.contains(i))
- return i;
- }
-
- qFatal("Couldn't find free context ID");
- return 0;
-}
SubmissionContext::SubmissionContext()
: GraphicsContext()
@@ -394,7 +363,6 @@ SubmissionContext::SubmissionContext()
, m_stateSet(nullptr)
, m_renderer(nullptr)
, m_uboTempArray(QByteArray(1024, 0))
- , m_currentVAO(nullptr)
{
static_contexts[m_id] = this;
}
@@ -410,7 +378,7 @@ SubmissionContext::~SubmissionContext()
void SubmissionContext::initialize()
{
GraphicsContext::initialize();
- m_activeTextures.resize(maxTextureUnitsCount());
+ m_textureContext.initialize(this);
}
void SubmissionContext::resolveRenderTargetFormat()
@@ -462,10 +430,6 @@ bool SubmissionContext::beginDrawing(QSurface *surface)
// TODO: cache surface format somewhere rather than doing this every time render surface changes
resolveRenderTargetFormat();
- // Sets or Create the correct m_glHelper
- // for the current surface
- activateGLHelper();
-
#if defined(QT3D_RENDER_ASPECT_OPENGL_DEBUG)
GLint err = m_gl->functions()->glGetError();
if (err != 0) {
@@ -475,22 +439,18 @@ bool SubmissionContext::beginDrawing(QSurface *surface)
if (!isInitialized())
initialize();
+ initializeHelpers(m_surface);
// need to reset these values every frame, may get overwritten elsewhere
m_gl->functions()->glClearColor(m_currClearColorValue.redF(), m_currClearColorValue.greenF(), m_currClearColorValue.blueF(), m_currClearColorValue.alphaF());
m_gl->functions()->glClearDepthf(m_currClearDepthValue);
m_gl->functions()->glClearStencil(m_currClearStencilValue);
-
if (m_activeShader) {
m_activeShader = nullptr;
m_activeShaderDNA = 0;
}
- // reset active textures
- for (int u = 0; u < m_activeTextures.size(); ++u)
- m_activeTextures[u].texture = nullptr;
-
m_boundArrayBuffer = nullptr;
static int callCount = 0;
@@ -508,10 +468,7 @@ void SubmissionContext::endDrawing(bool swapBuffers)
m_gl->swapBuffers(m_surface);
if (m_ownCurrent)
m_gl->doneCurrent();
- decayTextureScores();
- for (int i = 0; i < m_activeTextures.size(); ++i)
- if (m_activeTextures[i].texture)
- TextureExtRendererLocker::unlock(m_activeTextures[i].texture);
+ m_textureContext.endDrawing();
}
void SubmissionContext::activateRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, const AttachmentPack &attachments, GLuint defaultFboId)
@@ -815,20 +772,6 @@ void SubmissionContext::setOpenGLContext(QOpenGLContext* ctx)
m_gl = ctx;
}
-void SubmissionContext::activateGLHelper()
-{
- // Sets the correct GL Helper depending on the surface
- // If no helper exists, create one
- m_glHelper = m_glHelpers.value(m_surface);
- if (!m_glHelper) {
- m_glHelper = resolveHighestOpenGLFunctions();
- m_glHelpers.insert(m_surface, m_glHelper);
- // Note: OpenGLContext is current at this point
- m_gl->functions()->glDisable(GL_DITHER);
- }
-}
-
-
// Called only from RenderThread
bool SubmissionContext::activateShader(ProgramDNA shaderDNA)
{
@@ -910,126 +853,10 @@ void SubmissionContext::setActiveMaterial(Material *rmat)
if (m_material == rmat)
return;
- deactivateTexturesWithScope(TextureScopeMaterial);
+ m_textureContext.deactivateTexturesWithScope(TextureSubmissionContext::TextureScopeMaterial);
m_material = rmat;
}
-int SubmissionContext::activateTexture(TextureScope scope, GLTexture *tex, int onUnit)
-{
- // Returns the texture unit to use for the texture
- // This always return a valid unit, unless there are more textures than
- // texture unit available for the current material
- onUnit = assignUnitForTexture(tex);
-
- // check we didn't overflow the available units
- if (onUnit == -1)
- return -1;
-
- // actually re-bind if required, the tex->dna on the unit not being the same
- // Note: tex->dna() could be 0 if the texture has not been created yet
- if (m_activeTextures[onUnit].texture != tex) {
- // Texture must have been created and updated at this point
-
- const int sharedTextureId = tex->sharedTextureId();
-
- // We have a valid texture id provided by a shared context
- if (sharedTextureId > 0) {
- m_gl->functions()->glActiveTexture(GL_TEXTURE0 + onUnit);
- const QAbstractTexture::Target target = tex->properties().target;
- // For now we know that target values correspond to the GL values
- m_gl->functions()->glBindTexture(target, tex->sharedTextureId());
- } else {
- QOpenGLTexture *glTex = tex->getGLTexture();
- if (glTex == nullptr)
- return -1;
- glTex->bind(onUnit);
- }
-
- if (m_activeTextures[onUnit].texture)
- TextureExtRendererLocker::unlock(m_activeTextures[onUnit].texture);
- m_activeTextures[onUnit].texture = tex;
- TextureExtRendererLocker::lock(tex);
- }
-
-#if defined(QT3D_RENDER_ASPECT_OPENGL_DEBUG)
- int err = m_gl->functions()->glGetError();
- if (err)
- qCWarning(Backend) << "GL error after activating texture" << QString::number(err, 16)
- << tex->getGLTexture()->textureId() << "on unit" << onUnit;
-#endif
-
- m_activeTextures[onUnit].score = 200;
- m_activeTextures[onUnit].pinned = true;
- m_activeTextures[onUnit].scope = scope;
-
- return onUnit;
-}
-
-void SubmissionContext::deactivateTexturesWithScope(TextureScope ts)
-{
- for (int u=0; u<m_activeTextures.size(); ++u) {
- if (!m_activeTextures[u].pinned)
- continue; // inactive, ignore
-
- if (m_activeTextures[u].scope == ts) {
- m_activeTextures[u].pinned = false;
- m_activeTextures[u].score = qMax(m_activeTextures[u].score, 1) - 1;
- }
- } // of units iteration
-}
-
-void SubmissionContext::deactivateTexture(GLTexture* tex)
-{
- for (int u=0; u<m_activeTextures.size(); ++u) {
- if (m_activeTextures[u].texture == tex) {
- Q_ASSERT(m_activeTextures[u].pinned);
- m_activeTextures[u].pinned = false;
- return;
- }
- } // of units iteration
-
- qCWarning(Backend) << Q_FUNC_INFO << "texture not active:" << tex;
-}
-
-/*!
- \internal
- Returns a texture unit for a texture, -1 if all texture units are assigned.
- Tries to use the texture unit with the texture that hasn't been used for the longest time
- if the texture happens not to be already pinned on a texture unit.
- */
-GLint SubmissionContext::assignUnitForTexture(GLTexture *tex)
-{
- int lowestScoredUnit = -1;
- int lowestScore = 0xfffffff;
-
- for (int u=0; u<m_activeTextures.size(); ++u) {
- if (m_activeTextures[u].texture == tex)
- return u;
-
- // No texture is currently active on the texture unit
- // we save the texture unit with the texture that has been on there
- // the longest time while not being used
- if (!m_activeTextures[u].pinned) {
- int score = m_activeTextures[u].score;
- if (score < lowestScore) {
- lowestScore = score;
- lowestScoredUnit = u;
- }
- }
- } // of units iteration
-
- if (lowestScoredUnit == -1)
- qCWarning(Backend) << Q_FUNC_INFO << "No free texture units!";
-
- return lowestScoredUnit;
-}
-
-void SubmissionContext::decayTextureScores()
-{
- for (int u = 0; u < m_activeTextures.size(); u++)
- m_activeTextures[u].score = qMax(m_activeTextures[u].score - 1, 0);
-}
-
void SubmissionContext::setCurrentStateSet(RenderStateSet *ss)
{
if (ss == m_stateSet)
@@ -1301,7 +1128,7 @@ bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack)
// to pinable so that we should easily find an available texture unit
NodeManagers *manager = m_renderer->nodeManagers();
- deactivateTexturesWithScope(TextureScopeMaterial);
+ m_textureContext.deactivateTexturesWithScope(TextureSubmissionContext::TextureScopeMaterial);
// Update the uniforms with the correct texture unit id's
PackUniformHash &uniformValues = parameterPack.uniforms();
@@ -1313,7 +1140,7 @@ bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack)
if (t != nullptr) {
UniformValue &texUniform = uniformValues[namedTex.glslNameId];
if (texUniform.valueType() == UniformValue::TextureValue) {
- const int texUnit = activateTexture(TextureScopeMaterial, t);
+ const int texUnit = m_textureContext.activateTexture(TextureSubmissionContext::TextureScopeMaterial, m_gl, t);
texUniform.data<int>()[namedTex.uniformArrayIndex] = texUnit;
if (texUnit == -1) {
if (namedTex.glslNameId != irradianceId &&
diff --git a/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h b/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h
index dbfaef148..844e62f15 100644
--- a/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h
@@ -54,6 +54,7 @@
#include <Qt3DRender/private/graphicscontext_p.h>
+#include <Qt3DRender/private/texturesubmissioncontext_p.h>
#include <Qt3DRender/qclearbuffers.h>
#include <Qt3DRender/private/glbuffer_p.h>
#include <Qt3DRender/qattribute.h>
@@ -82,13 +83,6 @@ class Buffer;
class ShaderManager;
struct StateVariant;
-enum TextureScope
-{
- TextureScopeMaterial = 0,
- TextureScopeTechnique
- // per-pass for deferred rendering?
-};
-
typedef QPair<QString, int> NamedUniformLocation;
class Q_AUTOTEST_EXPORT SubmissionContext : public GraphicsContext
@@ -102,7 +96,6 @@ public:
bool beginDrawing(QSurface *surface);
void endDrawing(bool swapBuffers);
- void activateGLHelper();
void releaseOpenGL();
void setOpenGLContext(QOpenGLContext* ctx);
@@ -126,11 +119,6 @@ public:
QRenderTargetOutput::AttachmentPoint outputAttachmentPoint,
QBlitFramebuffer::InterpolationMethod interpolationMethod);
-
- // Material
- Material* activeMaterial() const { return m_material; }
- void setActiveMaterial(Material* rmat);
-
// Attributes
void specifyAttribute(const Attribute *attribute,
Buffer *buffer,
@@ -147,10 +135,6 @@ public:
// Parameters
bool setParameters(ShaderParameterPack &parameterPack);
- // Textures
- int activateTexture(TextureScope scope, GLTexture* tex, int onUnit = -1);
- void deactivateTexture(GLTexture *tex);
-
// RenderState
void setCurrentStateSet(RenderStateSet* ss);
RenderStateSet *currentStateSet() const;
@@ -175,10 +159,9 @@ public:
private:
void initialize();
- // Textures
- void decayTextureScores();
- GLint assignUnitForTexture(GLTexture* tex);
- void deactivateTexturesWithScope(TextureScope ts);
+ // Material
+ Material* activeMaterial() const { return m_material; }
+ void setActiveMaterial(Material* rmat);
// FBO
void bindFrameBufferAttachmentHelper(GLuint fboId, const AttachmentPack &attachments);
@@ -187,7 +170,6 @@ private:
GLuint createRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, const AttachmentPack &attachments);
GLuint updateRenderTarget(Qt3DCore::QNodeId renderTargetNodeId, const AttachmentPack &attachments, bool isActiveRenderTarget);
-
// Buffers
HGLBuffer createGLBufferFor(Buffer *buffer, GLBuffer::Type type);
void uploadDataToGLBuffer(Buffer *buffer, GLBuffer *b, bool releaseBuffer = false);
@@ -207,17 +189,6 @@ private:
QHash<GLuint, QSize> m_renderTargetsSize;
QAbstractTexture::TextureFormat m_renderTargetFormat;
- QHash<QSurface *, GraphicsHelperInterface*> m_glHelpers;
-
- // active textures, indexed by texture unit
- struct ActiveTexture {
- GLTexture *texture = nullptr;
- int score = 0;
- TextureScope scope = TextureScopeMaterial;
- bool pinned = false;
- };
- QVector<ActiveTexture> m_activeTextures;
-
// cache some current state, to make sure we don't issue unnecessary GL calls
int m_currClearStencilValue;
float m_currClearDepthValue;
@@ -232,10 +203,10 @@ private:
Renderer *m_renderer;
QByteArray m_uboTempArray;
+ TextureSubmissionContext m_textureContext;
// Attributes
friend class OpenGLVertexArrayObject;
- OpenGLVertexArrayObject *m_currentVAO;
struct VAOVertexAttribute
{
diff --git a/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp
new file mode 100644
index 000000000..67d0f9976
--- /dev/null
+++ b/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp
@@ -0,0 +1,225 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "texturesubmissioncontext_p.h"
+
+#include <Qt3DRender/private/graphicscontext_p.h>
+#include <Qt3DRender/private/gltexture_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+
+class TextureExtRendererLocker
+{
+public:
+ static void lock(GLTexture *tex)
+ {
+ if (!tex->isExternalRenderingEnabled())
+ return;
+ if (s_lockHash.keys().contains(tex)) {
+ ++s_lockHash[tex];
+ } else {
+ tex->externalRenderingLock()->lock();
+ s_lockHash[tex] = 1;
+ }
+ }
+ static void unlock(GLTexture *tex)
+ {
+ if (!tex->isExternalRenderingEnabled())
+ return;
+ if (!s_lockHash.keys().contains(tex))
+ return;
+
+ --s_lockHash[tex];
+ if (s_lockHash[tex] == 0) {
+ s_lockHash.remove(tex);
+ tex->externalRenderingLock()->unlock();
+ }
+ }
+private:
+ static QHash<GLTexture*, int> s_lockHash;
+};
+
+QHash<GLTexture*, int> TextureExtRendererLocker::s_lockHash = QHash<GLTexture*, int>();
+
+
+TextureSubmissionContext::TextureSubmissionContext()
+{
+
+}
+
+TextureSubmissionContext::~TextureSubmissionContext()
+{
+
+}
+
+void TextureSubmissionContext::initialize(GraphicsContext *context)
+{
+ m_activeTextures.resize(context->maxTextureUnitsCount());
+}
+
+void TextureSubmissionContext::endDrawing()
+{
+ decayTextureScores();
+ for (int i = 0; i < m_activeTextures.size(); ++i)
+ if (m_activeTextures[i].texture)
+ TextureExtRendererLocker::unlock(m_activeTextures[i].texture);
+}
+
+int TextureSubmissionContext::activateTexture(TextureSubmissionContext::TextureScope scope,
+ QOpenGLContext *m_gl,
+ GLTexture *tex)
+{
+ // Returns the texture unit to use for the texture
+ // This always return a valid unit, unless there are more textures than
+ // texture unit available for the current material
+ const int onUnit = assignUnitForTexture(tex);
+
+ // check we didn't overflow the available units
+ if (onUnit == -1)
+ return -1;
+
+ const int sharedTextureId = tex->sharedTextureId();
+ // We have a valid texture id provided by a shared context
+ if (sharedTextureId > 0) {
+ m_gl->functions()->glActiveTexture(GL_TEXTURE0 + onUnit);
+ const QAbstractTexture::Target target = tex->properties().target;
+ // For now we know that target values correspond to the GL values
+ m_gl->functions()->glBindTexture(target, tex->sharedTextureId());
+ } else {
+ // Texture must have been created and updated at this point
+ QOpenGLTexture *glTex = tex->getGLTexture();
+ if (glTex == nullptr)
+ return -1;
+ glTex->bind(uint(onUnit));
+ }
+ if (m_activeTextures[onUnit].texture != tex) {
+ if (m_activeTextures[onUnit].texture)
+ TextureExtRendererLocker::unlock(m_activeTextures[onUnit].texture);
+ m_activeTextures[onUnit].texture = tex;
+ TextureExtRendererLocker::lock(tex);
+ }
+
+#if defined(QT3D_RENDER_ASPECT_OPENGL_DEBUG)
+ int err = m_gl->functions()->glGetError();
+ if (err)
+ qCWarning(Backend) << "GL error after activating texture" << QString::number(err, 16)
+ << tex->getGLTexture()->textureId() << "on unit" << onUnit;
+#endif
+
+ m_activeTextures[onUnit].score = 200;
+ m_activeTextures[onUnit].pinned = true;
+ m_activeTextures[onUnit].scope = scope;
+
+ return onUnit;
+}
+
+void TextureSubmissionContext::deactivateTexturesWithScope(TextureSubmissionContext::TextureScope ts)
+{
+ for (int u=0; u<m_activeTextures.size(); ++u) {
+ if (!m_activeTextures[u].pinned)
+ continue; // inactive, ignore
+
+ if (m_activeTextures[u].scope == ts) {
+ m_activeTextures[u].pinned = false;
+ m_activeTextures[u].score = qMax(m_activeTextures[u].score, 1) - 1;
+ }
+ } // of units iteration
+}
+
+void TextureSubmissionContext::deactivateTexture(GLTexture* tex)
+{
+ for (int u=0; u<m_activeTextures.size(); ++u) {
+ if (m_activeTextures[u].texture == tex) {
+ Q_ASSERT(m_activeTextures[u].pinned);
+ m_activeTextures[u].pinned = false;
+ return;
+ }
+ } // of units iteration
+
+ qCWarning(Backend) << Q_FUNC_INFO << "texture not active:" << tex;
+}
+
+/*!
+ \internal
+ Returns a texture unit for a texture, -1 if all texture units are assigned.
+ Tries to use the texture unit with the texture that hasn't been used for the longest time
+ if the texture happens not to be already pinned on a texture unit.
+ */
+int TextureSubmissionContext::assignUnitForTexture(GLTexture *tex)
+{
+ int lowestScoredUnit = -1;
+ int lowestScore = 0xfffffff;
+
+ for (int u=0; u<m_activeTextures.size(); ++u) {
+ if (m_activeTextures[u].texture == tex)
+ return u;
+ }
+
+ for (int u=0; u<m_activeTextures.size(); ++u) {
+ // No texture is currently active on the texture unit
+ // we save the texture unit with the texture that has been on there
+ // the longest time while not being used
+ if (!m_activeTextures[u].pinned) {
+ int score = m_activeTextures[u].score;
+ if (score < lowestScore) {
+ lowestScore = score;
+ lowestScoredUnit = u;
+ }
+ }
+ } // of units iteration
+
+ if (lowestScoredUnit == -1)
+ qCWarning(Backend) << Q_FUNC_INFO << "No free texture units!";
+
+ return lowestScoredUnit;
+}
+
+void TextureSubmissionContext::decayTextureScores()
+{
+ for (int u = 0; u < m_activeTextures.size(); u++)
+ m_activeTextures[u].score = qMax(m_activeTextures[u].score - 1, 0);
+}
+
+} // namespace Render
+} // namespace Qt3DRender of namespace
+
+QT_END_NAMESPACE
diff --git a/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext_p.h b/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext_p.h
new file mode 100644
index 000000000..3c84fe558
--- /dev/null
+++ b/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext_p.h
@@ -0,0 +1,106 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 Klaralvdalens Datakonsult AB (KDAB).
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the Qt3D module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QT3DRENDER_RENDER_TEXTURESUBMISSIONCONTEXT_H
+#define QT3DRENDER_RENDER_TEXTURESUBMISSIONCONTEXT_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#include <qglobal.h>
+#include <QVector>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLContext;
+
+namespace Qt3DRender {
+namespace Render {
+
+class GraphicsContext;
+class GLTexture;
+
+class Q_AUTOTEST_EXPORT TextureSubmissionContext
+{
+public:
+ enum TextureScope
+ {
+ TextureScopeMaterial = 0,
+ TextureScopeTechnique
+ // per-pass for deferred rendering?
+ };
+
+ TextureSubmissionContext();
+ ~TextureSubmissionContext();
+
+ void initialize(GraphicsContext *context);
+ void endDrawing();
+ int activateTexture(TextureScope scope, QOpenGLContext *gl, GLTexture* tex);
+ void deactivateTexture(GLTexture *tex);
+ void deactivateTexturesWithScope(TextureScope ts);
+
+private:
+ void decayTextureScores();
+ int assignUnitForTexture(GLTexture* tex);
+
+ // active textures, indexed by texture unit
+ struct ActiveTexture {
+ GLTexture *texture = nullptr;
+ int score = 0;
+ TextureScope scope = TextureScopeMaterial;
+ bool pinned = false;
+ };
+ QVector<ActiveTexture> m_activeTextures;
+};
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+#endif // QT3DRENDER_RENDER_TEXTURESUBMISSIONCONTEXT_H