summaryrefslogtreecommitdiffstats
path: root/src/render/renderers/opengl
diff options
context:
space:
mode:
Diffstat (limited to 'src/render/renderers/opengl')
-rw-r--r--src/render/renderers/opengl/graphicshelpers/glfence_p.h73
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperes2.cpp27
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperes2_p.h6
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperes3.cpp52
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperes3_p.h6
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl2.cpp28
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl2_p.h6
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp32
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2_p.h6
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp32
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3_p.h6
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp35
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpergl4_p.h6
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelperinterface_p.h9
-rw-r--r--src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri1
-rw-r--r--src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp29
-rw-r--r--src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h9
-rw-r--r--src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp23
-rw-r--r--src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext_p.h4
-rw-r--r--src/render/renderers/opengl/jobs/filtercompatibletechniquejob_p.h2
-rw-r--r--src/render/renderers/opengl/jobs/materialparametergathererjob_p.h2
-rw-r--r--src/render/renderers/opengl/jobs/renderviewjobutils.cpp12
-rw-r--r--src/render/renderers/opengl/renderer/renderer.cpp159
-rw-r--r--src/render/renderers/opengl/renderer/renderer_p.h17
-rw-r--r--src/render/renderers/opengl/renderer/renderview.cpp5
-rw-r--r--src/render/renderers/opengl/renderer/renderview_p.h10
-rw-r--r--src/render/renderers/opengl/textures/gltexture.cpp260
-rw-r--r--src/render/renderers/opengl/textures/gltexture_p.h8
28 files changed, 769 insertions, 96 deletions
diff --git a/src/render/renderers/opengl/graphicshelpers/glfence_p.h b/src/render/renderers/opengl/graphicshelpers/glfence_p.h
new file mode 100644
index 000000000..366065048
--- /dev/null
+++ b/src/render/renderers/opengl/graphicshelpers/glfence_p.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 GLFENCE_P_H
+#define GLFENCE_P_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 <QtGlobal>
+
+QT_BEGIN_NAMESPACE
+
+namespace Qt3DRender {
+
+namespace Render {
+
+// GLsync is a pointer to a struct (unlike the rest of GL which used int ids)
+// We cannot reference GLsync as it's only available since 3.2 We use FenceId
+// to wrap that around and trust the GLHelpers will convert them accordingly.
+using GLFence = void *;
+
+} // namespace Render
+} // namespace Qt3DRender
+
+QT_END_NAMESPACE
+
+
+#endif // GLFENCE_P_H
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes2.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelperes2.cpp
index c5753195b..71540b1ad 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes2.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes2.cpp
@@ -318,6 +318,33 @@ void GraphicsHelperES2::drawBuffer(GLenum mode)
qWarning() << "glDrawBuffer is not supported with OpenGL ES 2";
}
+void *GraphicsHelperES2::fenceSync()
+{
+ qWarning() << "Fences are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)";
+ return nullptr;
+}
+
+void GraphicsHelperES2::clientWaitSync(void *, GLuint64 )
+{
+ qWarning() << "Fences are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)";
+}
+
+void GraphicsHelperES2::waitSync(void *)
+{
+ qWarning() << "Fences are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)";
+}
+
+bool GraphicsHelperES2::wasSyncSignaled(void *)
+{
+ qWarning() << "Fences are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)";
+ return false;
+}
+
+void GraphicsHelperES2::deleteSync(void *)
+{
+ qWarning() << "Fences are not supported by OpenGL ES 2.0 (since OpenGL ES 3.0)";
+}
+
void GraphicsHelperES2::blendEquation(GLenum mode)
{
m_funcs->glBlendEquation(mode);
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes2_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelperes2_p.h
index 1c6df41b6..8c8dd34e9 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes2_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes2_p.h
@@ -132,6 +132,12 @@ public:
void readBuffer(GLenum mode) override;
void drawBuffer(GLenum mode) override;
+ void *fenceSync() override;
+ void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) override;
+ void waitSync(void *sync) override;
+ bool wasSyncSignaled(void *sync) override;
+ void deleteSync(void *sync) override;
+
void glUniform1fv(GLint location, GLsizei count, const GLfloat *value) override;
void glUniform2fv(GLint location, GLsizei count, const GLfloat *value) override;
void glUniform3fv(GLint location, GLsizei count, const GLfloat *value) override;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3.cpp
index 34c1e7448..5e5d2e001 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3.cpp
@@ -147,6 +147,26 @@ QT_BEGIN_NAMESPACE
#define GL_READ_FRAMEBUFFER 0x8CA8
#endif
+#ifndef GL_SIGNALED
+#define GL_SIGNALED 0x9119
+#endif
+
+#ifndef GL_SYNC_STATUS
+#define GL_SYNC_STATUS 0x9114
+#endif
+
+#ifndef GL_TIMEOUT_IGNORED
+#define GL_TIMEOUT_IGNORED 0xFFFFFFFFFFFFFFFFull
+#endif
+
+#ifndef GL_SYNC_GPU_COMMANDS_COMPLETE
+#define GL_SYNC_GPU_COMMANDS_COMPLETE 0x9117
+#endif
+
+#ifndef GL_SYNC_FLUSH_COMMANDS_BIT
+#define GL_SYNC_FLUSH_COMMANDS_BIT 0x00000001
+#endif
+
namespace Qt3DRender {
namespace Render {
@@ -307,6 +327,7 @@ bool GraphicsHelperES3::supportsFeature(GraphicsHelperInterface::Feature feature
case BlitFramebuffer:
case UniformBufferObject:
case MapBuffer:
+ case Fences:
return true;
default:
return false;
@@ -439,6 +460,37 @@ uint GraphicsHelperES3::uniformByteSize(const ShaderUniform &description)
return arrayStride ? rawByteSize * arrayStride : rawByteSize;
}
+void *GraphicsHelperES3::fenceSync()
+{
+ return m_extraFuncs->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+}
+
+void GraphicsHelperES3::clientWaitSync(void *sync, GLuint64 nanoSecTimeout)
+{
+ m_extraFuncs->glClientWaitSync(static_cast<GLsync>(sync), GL_SYNC_FLUSH_COMMANDS_BIT, nanoSecTimeout);
+}
+
+void GraphicsHelperES3::waitSync(void *sync)
+{
+ m_extraFuncs->glWaitSync(static_cast<GLsync>(sync), 0, GL_TIMEOUT_IGNORED);
+}
+
+bool GraphicsHelperES3::wasSyncSignaled(void *sync)
+{
+ GLint v;
+ m_extraFuncs->glGetSynciv(static_cast<GLsync>(sync),
+ GL_SYNC_STATUS,
+ sizeof(v),
+ nullptr,
+ &v);
+ return v == GL_SIGNALED;
+}
+
+void GraphicsHelperES3::deleteSync(void *sync)
+{
+ m_extraFuncs->glDeleteSync(static_cast<GLsync>(sync));
+}
+
void GraphicsHelperES3::blitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
{
m_extraFuncs->glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0, dstY0, dstX1, dstY1, mask, filter);
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_p.h
index d4467cf7f..dc5cef10c 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperes3_p.h
@@ -90,6 +90,12 @@ public:
UniformType uniformTypeFromGLType(GLenum glType) override;
uint uniformByteSize(const ShaderUniform &description) override;
+ void *fenceSync() override;
+ void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) override;
+ void waitSync(void *sync) override;
+ bool wasSyncSignaled(void *sync) override;
+ void deleteSync(void *sync) override;
+
protected:
QOpenGLExtraFunctions *m_extraFuncs = nullptr;
};
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2.cpp
index 6da8a9b6f..b6f3412b2 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2.cpp
@@ -272,6 +272,33 @@ void GraphicsHelperGL2::drawBuffer(GLenum mode)
m_funcs->glDrawBuffer(mode);
}
+void *GraphicsHelperGL2::fenceSync()
+{
+ qWarning() << "Fences are not supported by OpenGL 2.0 (since OpenGL 3.2)";
+ return nullptr;
+}
+
+void GraphicsHelperGL2::clientWaitSync(void *, GLuint64 )
+{
+ qWarning() << "Fences are not supported by OpenGL 2.0 (since OpenGL 3.2)";
+}
+
+void GraphicsHelperGL2::waitSync(void *)
+{
+ qWarning() << "Fences are not supported by OpenGL 2.0 (since OpenGL 3.2)";
+}
+
+bool GraphicsHelperGL2::wasSyncSignaled(void *)
+{
+ qWarning() << "Fences are not supported by OpenGL 2.0 (since OpenGL 3.2)";
+ return false;
+}
+
+void GraphicsHelperGL2::deleteSync(void *)
+{
+ qWarning() << "Fences are not supported by OpenGL 2.0 (since OpenGL 3.2)";
+}
+
void GraphicsHelperGL2::blendEquation(GLenum mode)
{
m_funcs->glBlendEquation(mode);
@@ -412,6 +439,7 @@ bool GraphicsHelperGL2::supportsFeature(GraphicsHelperInterface::Feature feature
case MRT:
return (m_fboFuncs != nullptr);
case TextureDimensionRetrieval:
+ case MapBuffer:
return true;
default:
return false;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2_p.h
index 2db75004f..b142b2623 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl2_p.h
@@ -132,6 +132,12 @@ public:
void readBuffer(GLenum mode) override;
void drawBuffer(GLenum mode) override;
+ void *fenceSync() override;
+ void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) override;
+ void waitSync(void *sync) override;
+ bool wasSyncSignaled(void *sync) override;
+ void deleteSync(void *sync) override;
+
void glUniform1fv(GLint location, GLsizei count, const GLfloat *value) override;
void glUniform2fv(GLint location, GLsizei count, const GLfloat *value) override;
void glUniform3fv(GLint location, GLsizei count, const GLfloat *value) override;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp
index a35c4e37f..5ff1a2ba5 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2.cpp
@@ -334,6 +334,37 @@ void GraphicsHelperGL3_2::drawBuffer(GLenum mode)
m_funcs->glDrawBuffer(mode);
}
+void *GraphicsHelperGL3_2::fenceSync()
+{
+ return m_funcs->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+}
+
+void GraphicsHelperGL3_2::clientWaitSync(void *sync, GLuint64 nanoSecTimeout)
+{
+ m_funcs->glClientWaitSync(static_cast<GLsync>(sync), GL_SYNC_FLUSH_COMMANDS_BIT, nanoSecTimeout);
+}
+
+void GraphicsHelperGL3_2::waitSync(void *sync)
+{
+ m_funcs->glWaitSync(static_cast<GLsync>(sync), 0, GL_TIMEOUT_IGNORED);
+}
+
+bool GraphicsHelperGL3_2::wasSyncSignaled(void *sync)
+{
+ GLint v;
+ m_funcs->glGetSynciv(static_cast<GLsync>(sync),
+ GL_SYNC_STATUS,
+ sizeof(v),
+ nullptr,
+ &v);
+ return v == GL_SIGNALED;
+}
+
+void GraphicsHelperGL3_2::deleteSync(void *sync)
+{
+ m_funcs->glDeleteSync(static_cast<GLsync>(sync));
+}
+
void GraphicsHelperGL3_2::blendEquation(GLenum mode)
{
m_funcs->glBlendEquation(mode);
@@ -481,6 +512,7 @@ bool GraphicsHelperGL3_2::supportsFeature(GraphicsHelperInterface::Feature featu
case TextureDimensionRetrieval:
case BindableFragmentOutputs:
case BlitFramebuffer:
+ case Fences:
return true;
case Tessellation:
return !m_tessFuncs.isNull();
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2_p.h
index 133295fd7..9e81345ad 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_2_p.h
@@ -134,6 +134,12 @@ public:
void readBuffer(GLenum mode) override;
void drawBuffer(GLenum mode) override;
+ void *fenceSync() override;
+ void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) override;
+ void waitSync(void *sync) override;
+ bool wasSyncSignaled(void *sync) override;
+ void deleteSync(void *sync) override;
+
void glUniform1fv(GLint location, GLsizei count, const GLfloat *value) override;
void glUniform2fv(GLint location, GLsizei count, const GLfloat *value) override;
void glUniform3fv(GLint location, GLsizei count, const GLfloat *value) override;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp
index b2512d84a..81081943d 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3.cpp
@@ -330,6 +330,37 @@ void GraphicsHelperGL3_3::drawBuffer(GLenum mode)
m_funcs->glDrawBuffer(mode);
}
+void *GraphicsHelperGL3_3::fenceSync()
+{
+ return m_funcs->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+}
+
+void GraphicsHelperGL3_3::clientWaitSync(void *sync, GLuint64 nanoSecTimeout)
+{
+ m_funcs->glClientWaitSync(static_cast<GLsync>(sync), GL_SYNC_FLUSH_COMMANDS_BIT, nanoSecTimeout);
+}
+
+void GraphicsHelperGL3_3::waitSync(void *sync)
+{
+ m_funcs->glWaitSync(static_cast<GLsync>(sync), 0, GL_TIMEOUT_IGNORED);
+}
+
+bool GraphicsHelperGL3_3::wasSyncSignaled(void *sync)
+{
+ GLint v;
+ m_funcs->glGetSynciv(static_cast<GLsync>(sync),
+ GL_SYNC_STATUS,
+ sizeof(v),
+ nullptr,
+ &v);
+ return v == GL_SIGNALED;
+}
+
+void GraphicsHelperGL3_3::deleteSync(void *sync)
+{
+ m_funcs->glDeleteSync(static_cast<GLsync>(sync));
+}
+
void GraphicsHelperGL3_3::blendEquation(GLenum mode)
{
m_funcs->glBlendEquation(mode);
@@ -477,6 +508,7 @@ bool GraphicsHelperGL3_3::supportsFeature(GraphicsHelperInterface::Feature featu
case TextureDimensionRetrieval:
case BindableFragmentOutputs:
case BlitFramebuffer:
+ case Fences:
return true;
case Tessellation:
return !m_tessFuncs.isNull();
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3_p.h
index 0ecdd3620..c480e5258 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl3_3_p.h
@@ -134,6 +134,12 @@ public:
void readBuffer(GLenum mode) override;
void drawBuffer(GLenum mode) override;
+ void *fenceSync() override;
+ void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) override;
+ void waitSync(void *sync) override;
+ bool wasSyncSignaled(void *sync) override;
+ void deleteSync(void *sync) override;
+
void glUniform1fv(GLint location, GLsizei count, const GLfloat *value) override;
void glUniform2fv(GLint location, GLsizei count, const GLfloat *value) override;
void glUniform3fv(GLint location, GLsizei count, const GLfloat *value) override;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp
index ce1b8ac2b..22cbf7428 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4.cpp
@@ -400,6 +400,39 @@ void GraphicsHelperGL4::drawBuffer(GLenum mode)
m_funcs->glDrawBuffer(mode);
}
+void *GraphicsHelperGL4::fenceSync()
+{
+ return m_funcs->glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
+}
+
+void GraphicsHelperGL4::clientWaitSync(void *sync, GLuint64 nanoSecTimeout)
+{
+ qDebug() << Q_FUNC_INFO << sync << static_cast<GLsync>(sync);
+ GLenum e = m_funcs->glClientWaitSync(static_cast<GLsync>(sync), GL_SYNC_FLUSH_COMMANDS_BIT, nanoSecTimeout);
+ qDebug() << e;
+}
+
+void GraphicsHelperGL4::waitSync(void *sync)
+{
+ m_funcs->glWaitSync(static_cast<GLsync>(sync), 0, GL_TIMEOUT_IGNORED);
+}
+
+bool GraphicsHelperGL4::wasSyncSignaled(void *sync)
+{
+ GLint v = 0;
+ m_funcs->glGetSynciv(static_cast<GLsync>(sync),
+ GL_SYNC_STATUS,
+ sizeof(v),
+ nullptr,
+ &v);
+ return v == GL_SIGNALED;
+}
+
+void GraphicsHelperGL4::deleteSync(void *sync)
+{
+ m_funcs->glDeleteSync(static_cast<GLsync>(sync));
+}
+
void GraphicsHelperGL4::glUniform1fv(GLint location, GLsizei count, const GLfloat *values)
{
m_funcs->glUniform1fv(location, count, values);
@@ -746,6 +779,8 @@ bool GraphicsHelperGL4::supportsFeature(GraphicsHelperInterface::Feature feature
case DrawBuffersBlend:
case BlitFramebuffer:
case IndirectDrawing:
+ case MapBuffer:
+ case Fences:
return true;
default:
return false;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4_p.h
index 3020b16d8..da62f4212 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelpergl4_p.h
@@ -132,6 +132,12 @@ public:
void readBuffer(GLenum mode) override;
void drawBuffer(GLenum mode) override;
+ void *fenceSync() override;
+ void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) override;
+ void waitSync(void *sync) override;
+ bool wasSyncSignaled(void *sync) override;
+ void deleteSync(void *sync) override;
+
void glUniform1fv(GLint location, GLsizei count, const GLfloat *value) override;
void glUniform2fv(GLint location, GLsizei count, const GLfloat *value) override;
void glUniform3fv(GLint location, GLsizei count, const GLfloat *value) override;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelperinterface_p.h b/src/render/renderers/opengl/graphicshelpers/graphicshelperinterface_p.h
index e41325cb7..2a1688b7f 100644
--- a/src/render/renderers/opengl/graphicshelpers/graphicshelperinterface_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/graphicshelperinterface_p.h
@@ -82,7 +82,8 @@ public:
DrawBuffersBlend,
BlitFramebuffer,
IndirectDrawing,
- MapBuffer
+ MapBuffer,
+ Fences
};
enum FBOBindMode {
@@ -155,6 +156,12 @@ public:
virtual void readBuffer(GLenum mode) = 0;
virtual void drawBuffer(GLenum mode) = 0;
+ virtual void *fenceSync() = 0;
+ virtual void clientWaitSync(void *sync, GLuint64 nanoSecTimeout) = 0;
+ virtual void waitSync(void *sync) = 0;
+ virtual bool wasSyncSignaled(void *sync) = 0;
+ virtual void deleteSync(void *sync) = 0;
+
virtual void glUniform1fv(GLint location, GLsizei count, const GLfloat *value) = 0;
virtual void glUniform2fv(GLint location, GLsizei count, const GLfloat *value) = 0;
virtual void glUniform3fv(GLint location, GLsizei count, const GLfloat *value) = 0;
diff --git a/src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri b/src/render/renderers/opengl/graphicshelpers/graphicshelpers.pri
index c40f52374..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 \
diff --git a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
index 59c2d4286..51f7cebd1 100644
--- a/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext.cpp
@@ -1088,6 +1088,33 @@ void SubmissionContext::clearStencilValue(int stencil)
}
}
+GLFence SubmissionContext::fenceSync()
+{
+ return m_glHelper->fenceSync();
+}
+
+void SubmissionContext::clientWaitSync(GLFence sync, GLuint64 nanoSecTimeout)
+{
+ qDebug() << Q_FUNC_INFO << sync;
+ m_glHelper->clientWaitSync(sync, nanoSecTimeout);
+}
+
+void SubmissionContext::waitSync(GLFence sync)
+{
+ qDebug() << Q_FUNC_INFO << sync;
+ m_glHelper->waitSync(sync);
+}
+
+bool SubmissionContext::wasSyncSignaled(GLFence sync)
+{
+ return m_glHelper->wasSyncSignaled(sync);
+}
+
+void SubmissionContext::deleteSync(GLFence sync)
+{
+ m_glHelper->deleteSync(sync);
+}
+
// It will be easier if the QGraphicContext applies the QUniformPack
// than the other way around
bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack)
@@ -1113,7 +1140,7 @@ bool SubmissionContext::setParameters(ShaderParameterPack &parameterPack)
if (t != nullptr) {
UniformValue &texUniform = uniformValues[namedTex.glslNameId];
if (texUniform.valueType() == UniformValue::TextureValue) {
- const int texUnit = m_textureContext.activateTexture(TextureSubmissionContext::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 9b9bd7fa8..844e62f15 100644
--- a/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/submissioncontext_p.h
@@ -60,6 +60,7 @@
#include <Qt3DRender/qattribute.h>
#include <Qt3DRender/private/handle_types_p.h>
#include <Qt3DRender/private/shadercache_p.h>
+#include <Qt3DRender/private/glfence_p.h>
QT_BEGIN_NAMESPACE
@@ -147,6 +148,14 @@ public:
void clearDepthValue(float depth);
void clearStencilValue(int stencil);
+
+ // Fences
+ GLFence fenceSync();
+ void clientWaitSync(GLFence sync, GLuint64 nanoSecTimeout);
+ void waitSync(GLFence sync);
+ bool wasSyncSignaled(GLFence sync);
+ void deleteSync(GLFence sync);
+
private:
void initialize();
diff --git a/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp b/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp
index 35fc1dc7c..67d0f9976 100644
--- a/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp
+++ b/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext.cpp
@@ -104,7 +104,9 @@ void TextureSubmissionContext::endDrawing()
TextureExtRendererLocker::unlock(m_activeTextures[i].texture);
}
-int TextureSubmissionContext::activateTexture(TextureSubmissionContext::TextureScope scope, GLTexture *tex)
+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
@@ -115,11 +117,20 @@ int TextureSubmissionContext::activateTexture(TextureSubmissionContext::TextureS
if (onUnit == -1)
return -1;
- // Texture must have been created and updated at this point
- QOpenGLTexture *glTex = tex->getGLTexture();
- if (glTex == nullptr)
- return -1;
- glTex->bind(uint(onUnit));
+ 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);
diff --git a/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext_p.h b/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext_p.h
index d0c1565b2..3c84fe558 100644
--- a/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext_p.h
+++ b/src/render/renderers/opengl/graphicshelpers/texturesubmissioncontext_p.h
@@ -57,6 +57,8 @@
QT_BEGIN_NAMESPACE
+class QOpenGLContext;
+
namespace Qt3DRender {
namespace Render {
@@ -78,7 +80,7 @@ public:
void initialize(GraphicsContext *context);
void endDrawing();
- int activateTexture(TextureScope scope, GLTexture* tex);
+ int activateTexture(TextureScope scope, QOpenGLContext *gl, GLTexture* tex);
void deactivateTexture(GLTexture *tex);
void deactivateTexturesWithScope(TextureScope ts);
diff --git a/src/render/renderers/opengl/jobs/filtercompatibletechniquejob_p.h b/src/render/renderers/opengl/jobs/filtercompatibletechniquejob_p.h
index 4f7a7146c..27b3d4ed2 100644
--- a/src/render/renderers/opengl/jobs/filtercompatibletechniquejob_p.h
+++ b/src/render/renderers/opengl/jobs/filtercompatibletechniquejob_p.h
@@ -64,7 +64,7 @@ namespace Render {
class TechniqueManager;
class Renderer;
-class QT3DRENDERSHARED_PRIVATE_EXPORT FilterCompatibleTechniqueJob : public Qt3DCore::QAspectJob
+class Q_3DRENDERSHARED_PRIVATE_EXPORT FilterCompatibleTechniqueJob : public Qt3DCore::QAspectJob
{
public:
FilterCompatibleTechniqueJob();
diff --git a/src/render/renderers/opengl/jobs/materialparametergathererjob_p.h b/src/render/renderers/opengl/jobs/materialparametergathererjob_p.h
index fbfac3364..6ba060841 100644
--- a/src/render/renderers/opengl/jobs/materialparametergathererjob_p.h
+++ b/src/render/renderers/opengl/jobs/materialparametergathererjob_p.h
@@ -70,7 +70,7 @@ class Renderer;
// TO be executed for each FrameGraph branch with a given RenderPassFilter/TechniqueFilter
-class QT3DRENDERSHARED_PRIVATE_EXPORT MaterialParameterGathererJob : public Qt3DCore::QAspectJob
+class Q_3DRENDERSHARED_PRIVATE_EXPORT MaterialParameterGathererJob : public Qt3DCore::QAspectJob
{
public:
MaterialParameterGathererJob();
diff --git a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
index 629e7e935..9dd7faacc 100644
--- a/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
+++ b/src/render/renderers/opengl/jobs/renderviewjobutils.cpp
@@ -68,6 +68,7 @@
#include <Qt3DRender/private/techniquemanager_p.h>
#include <Qt3DRender/private/memorybarrier_p.h>
#include <Qt3DRender/private/blitframebuffer_p.h>
+#include <Qt3DRender/private/waitfence_p.h>
QT_BEGIN_NAMESPACE
@@ -272,6 +273,17 @@ void setRenderViewConfigFromFrameGraphLeafNode(RenderView *rv, const FrameGraphN
break;
}
+ case FrameGraphNode::WaitFence: {
+ const Render::WaitFence *waitFence = static_cast<const Render::WaitFence *>(node);
+ rv->appendWaitFence(waitFence->data());
+ break;
+ }
+
+ case FrameGraphNode::SetFence: {
+ rv->appendInsertFenceId(node->peerId());
+ break;
+ }
+
default:
// Should never get here
qCWarning(Backend) << "Unhandled FrameGraphNode type";
diff --git a/src/render/renderers/opengl/renderer/renderer.cpp b/src/render/renderers/opengl/renderer/renderer.cpp
index e9c582458..e7fa4615c 100644
--- a/src/render/renderers/opengl/renderer/renderer.cpp
+++ b/src/render/renderers/opengl/renderer/renderer.cpp
@@ -91,6 +91,7 @@
#include <Qt3DRender/private/renderviewbuilder_p.h>
#include <Qt3DRender/private/commandthread_p.h>
#include <Qt3DRender/private/glcommands_p.h>
+#include <Qt3DRender/private/setfence_p.h>
#include <Qt3DRender/qcameralens.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
@@ -196,6 +197,7 @@ Renderer::Renderer(QRenderAspect::RenderType type)
, m_vaoGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForAbandonedVaos(); }, JobTypes::DirtyVaoGathering))
, m_textureGathererJob(Render::GenericLambdaJobPtr<std::function<void ()>>::create([this] { lookForDirtyTextures(); }, JobTypes::DirtyTextureGathering))
, 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_updateEntityHierarchyJob(Render::UpdateEntityHierarchyJobPtr::create())
@@ -393,6 +395,9 @@ void Renderer::initialize()
[this] { releaseGraphicsResources(); });
}
+ qCDebug(Backend) << "Qt3D shared context:" << ctx->shareContext();
+ qCDebug(Backend) << "Qt global shared context:" << qt_gl_global_share_context();
+
if (!ctx->shareContext()) {
m_shareContext = new QOpenGLContext;
m_shareContext->setFormat(ctx->format());
@@ -1097,7 +1102,7 @@ void Renderer::lookForDirtyTextures()
}
// Dirty meaning that something has changed on the texture
- // either properties, parameters, generator or a texture image
+ // either properties, parameters, shared texture id, generator or a texture image
if (texture->dirtyFlags() != Texture::NotDirty)
m_dirtyTextures.push_back(handle);
// Note: texture dirty flags are reset when actually updating the
@@ -1183,7 +1188,7 @@ void Renderer::reloadDirtyShaders()
// Executed in a job
void Renderer::sendTextureChangesToFrontend()
{
- const QVector<QPair<TextureProperties, Qt3DCore::QNodeIdVector>> updateTextureProperties = std::move(m_updatedTextureProperties);
+ const QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> updateTextureProperties = std::move(m_updatedTextureProperties);
for (const auto &pair : updateTextureProperties) {
// Prepare change notification
@@ -1202,6 +1207,22 @@ void Renderer::sendTextureChangesToFrontend()
}
}
+// Executed in a job
+void Renderer::sendSetFenceHandlesToFrontend()
+{
+ const QVector<QPair<Qt3DCore::QNodeId, GLFence>> updatedSetFence = std::move(m_updatedSetFences);
+ FrameGraphManager *fgManager = m_nodesManager->frameGraphManager();
+ for (const auto &pair : updatedSetFence) {
+ FrameGraphNode *fgNode = fgManager->lookupNode(pair.first);
+ if (fgNode != nullptr) { // Node could have been deleted before we got a chance to notify it
+ Q_ASSERT(fgNode->nodeType() == FrameGraphNode::SetFence);
+ SetFence *setFenceNode = static_cast<SetFence *>(fgNode);
+ setFenceNode->setHandleType(QSetFence::OpenGLFenceId);
+ setFenceNode->setHandle(QVariant::fromValue(pair.second));
+ }
+ }
+}
+
// Render Thread (or QtQuick RenderThread when using Scene3D)
// Scene3D: When using Scene3D rendering, we can't assume that when
// updateGLResources is called, the resource handles points to still existing
@@ -1215,6 +1236,25 @@ void Renderer::sendTextureChangesToFrontend()
void Renderer::updateGLResources()
{
{
+ // Update active fence objects:
+ // - Destroy fences that have reached their signaled state
+ GLFenceManager *fenceManager = m_nodesManager->glFenceManager();
+ const auto end = fenceManager->end();
+ auto it = fenceManager->begin();
+ while (it != end) {
+ const GLFence fence = it.value();
+ if (m_submissionContext->wasSyncSignaled(fence)) {
+ // Fence was signaled, we delete it
+ // before removing the entry from the manager
+ m_submissionContext->deleteSync(fence);
+ it = fenceManager->erase(it);
+ } else {
+ ++it;
+ }
+ }
+ }
+
+ {
Profiling::GLTimeRecorder recorder(Profiling::BufferUpload);
const QVector<HBuffer> dirtyBufferHandles = std::move(m_dirtyBuffers);
for (const HBuffer &handle: dirtyBufferHandles) {
@@ -1280,8 +1320,13 @@ void Renderer::updateGLResources()
// Gather these information and store them to be distributed by a change next frame
const QNodeIdVector referenceTextureIds = glTextureManager->referencedTextureIds(glTexture);
// Store properties and referenceTextureIds
- if (info.wasUpdated)
- m_updatedTextureProperties.push_back({info.properties, referenceTextureIds});
+ if (info.wasUpdated) {
+ Texture::TextureUpdateInfo updateInfo;
+ updateInfo.properties = info.properties;
+ updateInfo.handleType = QAbstractTexture::OpenGLTextureId;
+ updateInfo.handle = info.texture ? QVariant(info.texture->textureId()) : QVariant();
+ m_updatedTextureProperties.push_back({updateInfo, referenceTextureIds});
+ }
}
}
}
@@ -1303,18 +1348,21 @@ void Renderer::updateTexture(Texture *texture)
return;
// For implementing unique, non-shared, non-cached textures.
- // for now, every texture is shared by default
+ // 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;
- bool isUnique = false;
-
- // 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;
+ 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;
+ }
}
}
@@ -1361,6 +1409,9 @@ void Renderer::updateTexture(Texture *texture)
// we hold a reference to a unique or exclusive access to a shared texture
// we can thus modify the texture directly.
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::DirtyProperties) &&
!glTextureManager->setProperties(glTexture, texture->properties()))
@@ -1394,6 +1445,7 @@ void Renderer::cleanupTexture(Qt3DCore::QNodeId cleanedUpTextureId)
glTextureManager->abandon(glTexture, cleanedUpTextureId);
}
+// Called by SubmitRenderView
void Renderer::downloadGLBuffers()
{
lookForDownloadableBuffers();
@@ -1478,6 +1530,45 @@ Renderer::ViewSubmissionResultData Renderer::submitRenderViews(const QVector<Ren
if (renderView->memoryBarrier() != QMemoryBarrier::None)
m_submissionContext->memoryBarrier(renderView->memoryBarrier());
+
+ // Insert Fence into command stream if needed
+ const Qt3DCore::QNodeIdVector insertFenceIds = renderView->insertFenceIds();
+ GLFenceManager *fenceManager = m_nodesManager->glFenceManager();
+ for (const Qt3DCore::QNodeId insertFenceId : insertFenceIds) {
+ // If the fence is not in the manager, then it hasn't been inserted
+ // into the command stream yet.
+ if (fenceManager->find(insertFenceId) == fenceManager->end()) {
+ // Insert fence into command stream
+ GLFence glFence = m_submissionContext->fenceSync();
+ // Record glFence
+ fenceManager->insert(insertFenceId, glFence);
+ // Add entry for notification changes to be sent
+ m_updatedSetFences.push_back({insertFenceId, glFence});
+ }
+ // If it is in the manager, then it hasn't been signaled yet,
+ // nothing we can do but try at the next frame
+ }
+
+ // Wait for fences if needed
+ const QVector<QWaitFenceData> waitFences = renderView->waitFences();
+ for (const QWaitFenceData &waitFence : waitFences) {
+ // TO DO
+ if (waitFence.handleType != QWaitFence::OpenGLFenceId) {
+ qWarning() << "WaitFence handleType should be OpenGLFenceId when using the Qt 3D OpenGL renderer";
+ continue;
+ }
+ GLFence fence = reinterpret_cast<GLFence>(waitFence.handle.value<qintptr>());
+ if (fence == nullptr)
+ continue;
+
+ if (waitFence.waitOnCPU) {
+ m_submissionContext->clientWaitSync(fence,
+ waitFence.timeout);
+ } else {
+ m_submissionContext->waitSync(fence);
+ }
+ }
+
// Note: the RenderStateSet is allocated once per RV if needed
// and it contains a list of StateVariant value types
RenderStateSet *renderViewStateSet = renderView->stateSet();
@@ -1642,6 +1733,33 @@ void Renderer::skipNextFrame()
m_submitRenderViewsSemaphore.release(1);
}
+// Jobs we may have to run even if no rendering will happen
+QVector<QAspectJobPtr> Renderer::preRenderingJobs()
+{
+ QVector<QAspectJobPtr> jobs;
+
+ // Do we need to notify any texture about property changes?
+ if (m_updatedTextureProperties.size() > 0)
+ jobs.push_back(m_sendTextureChangesToFrontendJob);
+
+ // Do we need to notify frontend about fence change?
+ if (m_updatedSetFences.size() > 0)
+ jobs.push_back(m_sendSetFenceHandlesToFrontendJob);
+
+ const QVector<Qt3DCore::QNodeId> pendingCaptureIds = takePendingRenderCaptureSendRequests();
+ if (pendingCaptureIds.size() > 0) {
+ m_sendRenderCaptureJob->setPendingCaptureRequests(pendingCaptureIds);
+ jobs.push_back(m_sendRenderCaptureJob);
+ }
+ if (m_sendBufferCaptureJob->hasRequests())
+ jobs.push_back(m_sendBufferCaptureJob);
+
+ jobs.append(pickBoundingVolumeJob());
+ jobs.append(rayCastingJob());
+
+ return jobs;
+}
+
// Waits to be told to create jobs for the next frame
// Called by QRenderAspect jobsToExecute context of QAspectThread
// Returns all the jobs (and with proper dependency chain) required
@@ -1703,17 +1821,6 @@ QVector<Qt3DCore::QAspectJobPtr> Renderer::renderBinJobs()
renderBinJobs.push_back(m_updateLevelOfDetailJob);
renderBinJobs.push_back(m_cleanupJob);
- const QVector<Qt3DCore::QNodeId> pendingCaptureIds = takePendingRenderCaptureSendRequests();
- if (pendingCaptureIds.size() > 0) {
- m_sendRenderCaptureJob->setPendingCaptureRequests(pendingCaptureIds);
- renderBinJobs.push_back(m_sendRenderCaptureJob);
- }
-
- // Do we need to notify any texture about property changes?
- if (m_updatedTextureProperties.size() > 0)
- renderBinJobs.push_back(m_sendTextureChangesToFrontendJob);
-
- renderBinJobs.push_back(m_sendBufferCaptureJob);
renderBinJobs.append(bufferJobs);
// Jobs to prepare GL Resource upload
diff --git a/src/render/renderers/opengl/renderer/renderer_p.h b/src/render/renderers/opengl/renderer/renderer_p.h
index 6443215a4..5b5f5c4f4 100644
--- a/src/render/renderers/opengl/renderer/renderer_p.h
+++ b/src/render/renderers/opengl/renderer/renderer_p.h
@@ -81,6 +81,7 @@
#include <Qt3DRender/private/updateentityhierarchyjob_p.h>
#include <Qt3DRender/private/renderercache_p.h>
#include <Qt3DRender/private/texture_p.h>
+#include <Qt3DRender/private/glfence_p.h>
#include <QHash>
#include <QMatrix4x4>
@@ -97,6 +98,10 @@
#include <functional>
+#if defined(QT_BUILD_INTERNAL)
+class tst_Renderer;
+#endif
+
QT_BEGIN_NAMESPACE
class QSurface;
@@ -153,7 +158,7 @@ typedef QSharedPointer<UpdateLevelOfDetailJob> UpdateLevelOfDetailJobPtr;
using SynchronizerJobPtr = GenericLambdaJobPtr<std::function<void()>>;
using IntrospectShadersJobPtr = GenericLambdaJobPtr<std::function<void()>>;
-class QT3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer
+class Q_3DRENDERSHARED_PRIVATE_EXPORT Renderer : public AbstractRenderer
{
public:
explicit Renderer(QRenderAspect::RenderType type);
@@ -197,6 +202,7 @@ public:
bool shouldRender() override;
void skipNextFrame() override;
+ QVector<Qt3DCore::QAspectJobPtr> preRenderingJobs() override;
QVector<Qt3DCore::QAspectJobPtr> renderBinJobs() override;
Qt3DCore::QAspectJobPtr pickBoundingVolumeJob() override;
Qt3DCore::QAspectJobPtr rayCastingJob() override;
@@ -376,6 +382,7 @@ private:
GenericLambdaJobPtr<std::function<void ()>> m_vaoGathererJob;
GenericLambdaJobPtr<std::function<void ()>> m_textureGathererJob;
GenericLambdaJobPtr<std::function<void ()>> m_sendTextureChangesToFrontendJob;
+ GenericLambdaJobPtr<std::function<void ()>> m_sendSetFenceHandlesToFrontendJob;
IntrospectShadersJobPtr m_introspectShaderJob;
SynchronizerJobPtr m_syncTextureLoadingJob;
@@ -386,6 +393,7 @@ private:
void lookForDirtyTextures();
void reloadDirtyShaders();
void sendTextureChangesToFrontend();
+ void sendSetFenceHandlesToFrontend();
QMutex m_abandonedVaosMutex;
QVector<HVao> m_abandonedVaos;
@@ -394,7 +402,8 @@ private:
QVector<HBuffer> m_downloadableBuffers;
QVector<HShader> m_dirtyShaders;
QVector<HTexture> m_dirtyTextures;
- QVector<QPair<TextureProperties, Qt3DCore::QNodeIdVector>> m_updatedTextureProperties;
+ QVector<QPair<Texture::TextureUpdateInfo, Qt3DCore::QNodeIdVector>> m_updatedTextureProperties;
+ QVector<QPair<Qt3DCore::QNodeId, GLFence>> m_updatedSetFences;
bool m_ownedContext;
@@ -406,6 +415,10 @@ private:
friend class Qt3DRender::Debug::CommandExecuter;
#endif
+#ifdef QT_BUILD_INTERNAL
+ friend class ::tst_Renderer;
+#endif
+
QMetaObject::Connection m_contextConnection;
RendererCache m_cache;
};
diff --git a/src/render/renderers/opengl/renderer/renderview.cpp b/src/render/renderers/opengl/renderer/renderview.cpp
index 47e6a8fb1..de25f55d1 100644
--- a/src/render/renderers/opengl/renderer/renderview.cpp
+++ b/src/render/renderers/opengl/renderer/renderview.cpp
@@ -715,6 +715,11 @@ QVector<RenderCommand *> RenderView::buildComputeRenderCommands(const QVector<En
if ((computeJob = entity->renderComponent<ComputeCommand>()) != nullptr
&& computeJob->isEnabled()) {
+ // Note: if frameCount has reached 0 in the previous frame, isEnabled
+ // would be false
+ if (computeJob->runType() == QComputeCommand::Manual)
+ computeJob->updateFrameCount();
+
const Qt3DCore::QNodeId materialComponentId = entity->componentUuid<Material>();
const QVector<RenderPassParameterData> renderPassData = m_parameters.value(materialComponentId);
diff --git a/src/render/renderers/opengl/renderer/renderview_p.h b/src/render/renderers/opengl/renderer/renderview_p.h
index cb3c74917..7ebcdb6bd 100644
--- a/src/render/renderers/opengl/renderer/renderview_p.h
+++ b/src/render/renderers/opengl/renderer/renderview_p.h
@@ -65,6 +65,7 @@
#include <Qt3DRender/private/qmemorybarrier_p.h>
#include <Qt3DRender/private/qrendercapture_p.h>
#include <Qt3DRender/private/qblitframebuffer_p.h>
+#include <Qt3DRender/private/qwaitfence_p.h>
#include <Qt3DCore/private/qframeallocator_p.h>
#include <Qt3DRender/private/aligned_malloc_p.h>
@@ -174,6 +175,13 @@ public:
inline void appendProximityFilterId(const Qt3DCore::QNodeId proximityFilterId) { m_data.m_proximityFilterIds.push_back(proximityFilterId); }
inline Qt3DCore::QNodeIdVector proximityFilterIds() const { return m_data.m_proximityFilterIds; }
+ inline void appendInsertFenceId(const Qt3DCore::QNodeId setFenceId) { m_insertFenceIds.push_back(setFenceId); }
+ // We prefix with get to avoid confusion when it is called
+ inline Qt3DCore::QNodeIdVector insertFenceIds() const { return m_insertFenceIds; }
+
+ inline void appendWaitFence(const QWaitFenceData &data) { m_waitFences.push_back(data); }
+ inline QVector<QWaitFenceData> waitFences() const { return m_waitFences; }
+
inline void setRenderPassFilter(const RenderPassFilter *rpFilter) Q_DECL_NOTHROW { m_data.m_passFilter = rpFilter; }
inline const RenderPassFilter *renderPassFilter() const Q_DECL_NOTHROW { return m_data.m_passFilter; }
@@ -320,6 +328,8 @@ private:
bool m_frustumCulling:1;
int m_workGroups[3];
QMemoryBarrier::Operations m_memoryBarrier;
+ QVector<Qt3DCore::QNodeId> m_insertFenceIds;
+ QVector<QWaitFenceData> m_waitFences;
// We do not use pointers to RenderNodes or Drawable's here so that the
// render aspect is free to change the drawables on the next frame whilst
diff --git a/src/render/renderers/opengl/textures/gltexture.cpp b/src/render/renderers/opengl/textures/gltexture.cpp
index ce212de03..42deb4c2a 100644
--- a/src/render/renderers/opengl/textures/gltexture.cpp
+++ b/src/render/renderers/opengl/textures/gltexture.cpp
@@ -57,6 +57,11 @@
#include <Qt3DCore/qpropertynodeaddedchange.h>
#include <Qt3DCore/qpropertynoderemovedchange.h>
+#if !defined(QT_OPENGL_ES_2)
+#include <QOpenGLFunctions_3_1>
+#include <QOpenGLFunctions_4_5_Core>
+#endif
+
QT_BEGIN_NAMESPACE
using namespace Qt3DCore;
@@ -75,6 +80,7 @@ GLTexture::GLTexture(TextureDataManager *texDataMgr,
, m_textureImageDataManager(texImgDataMgr)
, m_dataFunctor(texGen)
, m_pendingDataFunctor(nullptr)
+ , m_sharedTextureId(-1)
, m_externalRendering(false)
{
// make sure texture generator is executed
@@ -181,39 +187,44 @@ GLTexture::TextureUpdateInfo GLTexture::createOrUpdateGLTexture()
m_properties.status = QAbstractTexture::Error;
- // on the first invocation in the render thread, make sure to
- // evaluate the texture data generator output
- // (this might change some property values)
- if (m_dataFunctor && !m_textureData) {
- const bool successfullyLoadedTextureData = loadTextureDataFromGenerator();
- if (successfullyLoadedTextureData) {
- setDirtyFlag(Properties, true);
- needUpload = true;
- } else {
- if (m_pendingDataFunctor != m_dataFunctor.get()) {
- qWarning() << "[Qt3DRender::GLTexture] No QTextureData generated from Texture Generator yet. Texture will be invalid for this frame";
- m_pendingDataFunctor = m_dataFunctor.get();
+ const bool hasSharedTextureId = m_sharedTextureId > 0;
+
+ // Only load texture data if we are not using a sharedTextureId
+ if (!hasSharedTextureId) {
+ // on the first invocation in the render thread, make sure to
+ // evaluate the texture data generator output
+ // (this might change some property values)
+ if (m_dataFunctor && !m_textureData) {
+ const bool successfullyLoadedTextureData = loadTextureDataFromGenerator();
+ if (successfullyLoadedTextureData) {
+ setDirtyFlag(Properties, true);
+ needUpload = true;
+ } else {
+ if (m_pendingDataFunctor != m_dataFunctor.get()) {
+ qWarning() << "[Qt3DRender::GLTexture] No QTextureData generated from Texture Generator yet. Texture will be invalid for this frame";
+ m_pendingDataFunctor = m_dataFunctor.get();
+ }
+ textureInfo.properties.status = QAbstractTexture::Loading;
+ return textureInfo;
}
- textureInfo.properties.status = QAbstractTexture::Loading;
- return textureInfo;
}
- }
- // additional texture images may be defined through image data generators
- if (testDirtyFlag(TextureData)) {
- m_imageData.clear();
- loadTextureDataFromImages();
- needUpload = true;
- }
+ // additional texture images may be defined through image data generators
+ if (testDirtyFlag(TextureData)) {
+ m_imageData.clear();
+ loadTextureDataFromImages();
+ needUpload = true;
+ }
- // don't try to create the texture if the format was not set
- if (m_properties.format == QAbstractTexture::Automatic) {
- textureInfo.properties.status = QAbstractTexture::Error;
- return textureInfo;
+ // don't try to create the texture if the format was not set
+ if (m_properties.format == QAbstractTexture::Automatic) {
+ textureInfo.properties.status = QAbstractTexture::Error;
+ return textureInfo;
+ }
}
// if the properties changed, we need to re-allocate the texture
- if (testDirtyFlag(Properties)) {
+ if (testDirtyFlag(Properties) || testDirtyFlag(SharedTextureId)) {
delete m_gl;
m_gl = nullptr;
textureInfo.wasUpdated = true;
@@ -223,40 +234,48 @@ GLTexture::TextureUpdateInfo GLTexture::createOrUpdateGLTexture()
needUpload = true;
}
+ m_properties.status = QAbstractTexture::Ready;
- if (!m_gl) {
- m_gl = buildGLTexture();
+ if (hasSharedTextureId && testDirtyFlag(SharedTextureId)) {
+ // Update m_properties by doing introspection on the texture
+ introspectPropertiesFromSharedTextureId();
+ } else {
+ // We only build a QOpenGLTexture if we have no shared textureId set
if (!m_gl) {
- textureInfo.properties.status = QAbstractTexture::Error;
- return textureInfo;
- }
+ m_gl = buildGLTexture();
+ if (!m_gl) {
+ textureInfo.properties.status = QAbstractTexture::Error;
+ return textureInfo;
+ }
- m_gl->allocateStorage();
- if (!m_gl->isStorageAllocated()) {
- textureInfo.properties.status = QAbstractTexture::Error;
- return textureInfo;
+ m_gl->allocateStorage();
+ if (!m_gl->isStorageAllocated()) {
+ textureInfo.properties.status = QAbstractTexture::Error;
+ return textureInfo;
+ }
}
- }
- m_properties.status = QAbstractTexture::Ready;
- textureInfo.properties = m_properties;
- textureInfo.texture = m_gl;
+ textureInfo.texture = m_gl;
- // need to (re-)upload texture data?
- if (needUpload) {
- uploadGLTextureData();
- setDirtyFlag(TextureData, false);
- }
+ // need to (re-)upload texture data?
+ if (needUpload) {
+ uploadGLTextureData();
+ setDirtyFlag(TextureData, false);
+ }
- // need to set texture parameters?
- if (testDirtyFlag(Properties) || testDirtyFlag(Parameters)) {
- updateGLTextureParameters();
+ // need to set texture parameters?
+ if (testDirtyFlag(Properties) || testDirtyFlag(Parameters)) {
+ updateGLTextureParameters();
+ }
}
+ textureInfo.properties = m_properties;
+
// un-set properties and parameters. The TextureData flag might have been set by another thread
// in the meantime, so don't clear that.
setDirtyFlag(Properties, false);
setDirtyFlag(Parameters, false);
+ setDirtyFlag(SharedTextureId, false);
return textureInfo;
}
@@ -355,6 +374,14 @@ void GLTexture::setGenerator(const QTextureGeneratorPtr &generator)
}
}
+void GLTexture::setSharedTextureId(int textureId)
+{
+ if (m_sharedTextureId != textureId) {
+ m_sharedTextureId = textureId;
+ setDirtyFlag(SharedTextureId);
+ }
+}
+
// Return nullptr if
// - context cannot be obtained
// - texture hasn't yet been loaded
@@ -403,8 +430,8 @@ QOpenGLTexture *GLTexture::buildGLTexture()
// is written against GLES 1.0.
if (m_properties.format == QAbstractTexture::RGB8_ETC1) {
if ((ctx->isOpenGLES() && ctx->format().majorVersion() >= 3)
- || ctx->hasExtension(QByteArrayLiteral("GL_OES_compressed_ETC2_RGB8_texture"))
- || ctx->hasExtension(QByteArrayLiteral("GL_ARB_ES3_compatibility")))
+ || ctx->hasExtension(QByteArrayLiteral("GL_OES_compressed_ETC2_RGB8_texture"))
+ || ctx->hasExtension(QByteArrayLiteral("GL_ARB_ES3_compatibility")))
format = m_properties.format = QAbstractTexture::RGB8_ETC2;
}
@@ -414,14 +441,14 @@ QOpenGLTexture *GLTexture::buildGLTexture()
glTex->setSize(m_properties.width, m_properties.height, m_properties.depth);
// Set layers count if texture array
if (m_actualTarget == QAbstractTexture::Target1DArray ||
- m_actualTarget == QAbstractTexture::Target2DArray ||
- m_actualTarget == QAbstractTexture::Target2DMultisampleArray ||
- m_actualTarget == QAbstractTexture::TargetCubeMapArray) {
+ m_actualTarget == QAbstractTexture::Target2DArray ||
+ m_actualTarget == QAbstractTexture::Target2DMultisampleArray ||
+ m_actualTarget == QAbstractTexture::TargetCubeMapArray) {
glTex->setLayers(m_properties.layers);
}
if (m_actualTarget == QAbstractTexture::Target2DMultisample ||
- m_actualTarget == QAbstractTexture::Target2DMultisampleArray) {
+ m_actualTarget == QAbstractTexture::Target2DMultisampleArray) {
// Set samples count if multisampled texture
// (multisampled textures don't have mipmaps)
glTex->setSamples(m_properties.samples);
@@ -497,8 +524,8 @@ void GLTexture::updateGLTextureParameters()
{
m_gl->setWrapMode(QOpenGLTexture::DirectionS, static_cast<QOpenGLTexture::WrapMode>(m_parameters.wrapModeX));
if (m_actualTarget != QAbstractTexture::Target1D &&
- m_actualTarget != QAbstractTexture::Target1DArray &&
- m_actualTarget != QAbstractTexture::TargetBuffer)
+ m_actualTarget != QAbstractTexture::Target1DArray &&
+ m_actualTarget != QAbstractTexture::TargetBuffer)
m_gl->setWrapMode(QOpenGLTexture::DirectionT, static_cast<QOpenGLTexture::WrapMode>(m_parameters.wrapModeY));
if (m_actualTarget == QAbstractTexture::Target3D)
m_gl->setWrapMode(QOpenGLTexture::DirectionR, static_cast<QOpenGLTexture::WrapMode>(m_parameters.wrapModeZ));
@@ -512,6 +539,129 @@ void GLTexture::updateGLTextureParameters()
}
}
+void GLTexture::introspectPropertiesFromSharedTextureId()
+{
+ // We know that the context is active when this function is called
+ QOpenGLContext *ctx = QOpenGLContext::currentContext();
+ if (!ctx) {
+ qWarning() << Q_FUNC_INFO << "requires an OpenGL context";
+ return;
+ }
+ QOpenGLFunctions *gl = ctx->functions();
+
+ // If the user has set the target format himself, we won't try to deduce it
+ if (m_properties.target != QAbstractTexture::TargetAutomatic)
+ return;
+
+ const QAbstractTexture::Target targets[] = {
+ QAbstractTexture::Target2D,
+ QAbstractTexture::TargetCubeMap,
+#ifndef QT_OPENGL_ES_2
+ QAbstractTexture::Target1D,
+ QAbstractTexture::Target1DArray,
+ QAbstractTexture::Target3D,
+ QAbstractTexture::Target2DArray,
+ QAbstractTexture::TargetCubeMapArray,
+ QAbstractTexture::Target2DMultisample,
+ QAbstractTexture::Target2DMultisampleArray,
+ QAbstractTexture::TargetRectangle,
+ QAbstractTexture::TargetBuffer,
+#endif
+ };
+
+#ifndef QT_OPENGL_ES_2
+ // Try to find texture target with GL 4.5 functions
+ const QPair<int, int> ctxGLVersion = ctx->format().version();
+ if (ctxGLVersion.first > 4 || (ctxGLVersion.first == 4 && ctxGLVersion.second >= 5)) {
+ // Only for GL 4.5+
+ QOpenGLFunctions_4_5_Core *gl5 = ctx->versionFunctions<QOpenGLFunctions_4_5_Core>();
+#ifdef GL_TEXTURE_TARGET
+ if (gl5 != nullptr)
+ gl5->glGetTextureParameteriv(m_sharedTextureId, GL_TEXTURE_TARGET, reinterpret_cast<int *>(&m_properties.target));
+#endif
+ }
+#endif
+
+ // If GL 4.5 function unavailable or not working, try a slower way
+ if (m_properties.target == QAbstractTexture::TargetAutomatic) {
+ // // OpenGL offers no proper way of querying for the target of a texture given its id
+ gl->glActiveTexture(GL_TEXTURE0);
+
+ const GLenum targetBindings[] = {
+ GL_TEXTURE_BINDING_2D,
+ GL_TEXTURE_BINDING_CUBE_MAP,
+#ifndef QT_OPENGL_ES_2
+ GL_TEXTURE_BINDING_1D,
+ GL_TEXTURE_BINDING_1D_ARRAY,
+ GL_TEXTURE_BINDING_3D,
+ GL_TEXTURE_BINDING_2D_ARRAY,
+ GL_TEXTURE_BINDING_CUBE_MAP_ARRAY,
+ GL_TEXTURE_BINDING_2D_MULTISAMPLE,
+ GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY,
+ GL_TEXTURE_BINDING_RECTANGLE,
+ GL_TEXTURE_BINDING_BUFFER
+#endif
+ };
+
+ Q_ASSERT(sizeof(targetBindings) / sizeof(targetBindings[0] == sizeof(targets) / sizeof(targets[0])));
+
+ for (uint i = 0; i < sizeof(targetBindings) / sizeof(targetBindings[0]); ++i) {
+ const int target = targets[i];
+ gl->glBindTexture(target, m_sharedTextureId);
+ int boundId = 0;
+ gl->glGetIntegerv(targetBindings[i], &boundId);
+ gl->glBindTexture(target, 0);
+ if (boundId == m_sharedTextureId) {
+ m_properties.target = static_cast<QAbstractTexture::Target>(target);
+ break;
+ }
+ }
+ }
+
+ // Return early if we weren't able to find texture target
+ if (std::find(std::begin(targets), std::end(targets), m_properties.target) == std::end(targets)) {
+ qWarning() << "Unable to determine texture target for shared GL texture";
+ return;
+ }
+
+ // Bind texture once we know its target
+ gl->glBindTexture(m_properties.target, m_sharedTextureId);
+
+ // TO DO: Improve by using glGetTextureParameters when available which
+ // support direct state access
+#ifndef GL_TEXTURE_MAX_LEVEL
+#define GL_TEXTURE_MAX_LEVEL 0x813D
+#endif
+
+#ifndef GL_TEXTURE_WRAP_R
+#define GL_TEXTURE_WRAP_R 0x8072
+#endif
+
+ gl->glGetTexParameteriv(int(m_properties.target), GL_TEXTURE_MAX_LEVEL, reinterpret_cast<int *>(&m_properties.mipLevels));
+ gl->glGetTexParameteriv(int(m_properties.target), GL_TEXTURE_MIN_FILTER, reinterpret_cast<int *>(&m_parameters.minificationFilter));
+ gl->glGetTexParameteriv(int(m_properties.target), GL_TEXTURE_MAG_FILTER, reinterpret_cast<int *>(&m_parameters.magnificationFilter));
+ gl->glGetTexParameteriv(int(m_properties.target), GL_TEXTURE_WRAP_R, reinterpret_cast<int *>(&m_parameters.wrapModeX));
+ gl->glGetTexParameteriv(int(m_properties.target), GL_TEXTURE_WRAP_S, reinterpret_cast<int *>(&m_parameters.wrapModeY));
+ gl->glGetTexParameteriv(int(m_properties.target), GL_TEXTURE_WRAP_T, reinterpret_cast<int *>(&m_parameters.wrapModeZ));
+
+#ifndef QT_OPENGL_ES_2
+ // Try to retrieve dimensions (not available on ES 2.0)
+ if (!ctx->isOpenGLES()) {
+ QOpenGLFunctions_3_1 *gl3 = ctx->versionFunctions<QOpenGLFunctions_3_1>();
+ if (!gl3) {
+ qWarning() << "Failed to retrieve shared texture dimensions";
+ return;
+ }
+
+ gl3->glGetTexLevelParameteriv(int(m_properties.target), 0, GL_TEXTURE_WIDTH, reinterpret_cast<int *>(&m_properties.width));
+ gl3->glGetTexLevelParameteriv(int(m_properties.target), 0, GL_TEXTURE_HEIGHT, reinterpret_cast<int *>(&m_properties.height));
+ gl3->glGetTexLevelParameteriv(int(m_properties.target), 0, GL_TEXTURE_DEPTH, reinterpret_cast<int *>(&m_properties.depth));
+ gl3->glGetTexLevelParameteriv(int(m_properties.target), 0, GL_TEXTURE_INTERNAL_FORMAT, reinterpret_cast<int *>(&m_properties.format));
+ }
+#endif
+
+ gl->glBindTexture(m_properties.target, 0);
+}
} // namespace Render
} // namespace Qt3DRender
diff --git a/src/render/renderers/opengl/textures/gltexture_p.h b/src/render/renderers/opengl/textures/gltexture_p.h
index ca9c0d5db..66f66926c 100644
--- a/src/render/renderers/opengl/textures/gltexture_p.h
+++ b/src/render/renderers/opengl/textures/gltexture_p.h
@@ -125,6 +125,7 @@ public:
inline TextureProperties properties() const { return m_properties; }
inline TextureParameters parameters() const { return m_parameters; }
inline QTextureGeneratorPtr textureGenerator() const { return m_dataFunctor; }
+ inline int sharedTextureId() const { return m_sharedTextureId; }
inline QVector<Image> images() const { return m_images; }
inline QSize size() const { return QSize(m_properties.width, m_properties.height); }
@@ -204,14 +205,15 @@ protected:
void setProperties(const TextureProperties &props);
void setImages(const QVector<Image> &images);
void setGenerator(const QTextureGeneratorPtr &generator);
+ void setSharedTextureId(int textureId);
private:
enum DirtyFlag {
TextureData = 0x01, // one or more image generators have been executed, data needs uploading to GPU
Properties = 0x02, // texture needs to be (re-)created
- Parameters = 0x04 // texture parameters need to be (re-)set
-
+ Parameters = 0x04, // texture parameters need to be (re-)set
+ SharedTextureId = 0x08 // texture id from shared context
};
bool testDirtyFlag(DirtyFlag flag)
@@ -232,6 +234,7 @@ private:
void loadTextureDataFromImages();
void uploadGLTextureData();
void updateGLTextureParameters();
+ void introspectPropertiesFromSharedTextureId();
void destroyResources();
bool m_unique;
@@ -257,6 +260,7 @@ private:
QTextureDataPtr m_textureData;
QVector<QTextureImageDataPtr> m_imageData;
+ int m_sharedTextureId;
bool m_externalRendering;
};