summaryrefslogtreecommitdiffstats
path: root/src/plugins/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp')
-rw-r--r--src/plugins/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp228
1 files changed, 228 insertions, 0 deletions
diff --git a/src/plugins/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp b/src/plugins/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp
new file mode 100644
index 000000000..4577d3d10
--- /dev/null
+++ b/src/plugins/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp
@@ -0,0 +1,228 @@
+/****************************************************************************
+**
+** 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 <graphicscontext_p.h>
+#include <gltexture_p.h>
+#include <logging_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+namespace Render {
+namespace OpenGL {
+
+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 OpenGL
+} // namespace Render
+} // namespace Qt3DRender of namespace
+
+QT_END_NAMESPACE