1// Copyright (C) 2016 Klaralvdalens Datakonsult AB (KDAB).
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QT3DRENDER_RENDER_OPENGL_GLTEXTURE_H
5#define QT3DRENDER_RENDER_OPENGL_GLTEXTURE_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists for the convenience
12// of other Qt classes. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <Qt3DRender/qtexture.h>
19#include <Qt3DRender/qtextureimagedata.h>
20#include <Qt3DRender/private/qtexturegenerator_p.h>
21#include <Qt3DRender/private/backendnode_p.h>
22#include <Qt3DRender/private/handle_types_p.h>
23#include <Qt3DRender/private/texture_p.h>
24#include <QOpenGLContext>
25#include <QFlags>
26#include <QMutex>
27#include <QSize>
28
29QT_BEGIN_NAMESPACE
30
31class QOpenGLTexture;
32
33namespace Qt3DRender {
34namespace Render {
35
36template<class APITexture, class APITextureImage>
37class APITextureManager;
38
39class TextureImageManager;
40class TextureDataManager;
41class TextureImageDataManager;
42
43namespace OpenGL {
44class RenderBuffer;
45
46/**
47 * @brief
48 * Actual implementation of the OpenGL texture object. Makes sure the
49 * QOpenGLTexture is up-to-date with the generators, properties and parameters
50 * that were set for this GLTexture.
51 *
52 * Can be shared among multiple QTexture backend nodes through the
53 * GLTextureManager, which will make sure that there are no two GLTextures
54 * sharing the same texture data.
55 *
56 * A GLTexture can be unique though. In that case, it will not be shared
57 * between QTextures, but private to one QTexture only.
58 *
59 * A GLTexture can also represent an OpenGL renderbuffer object. This is used
60 * only in certain special cases, mainly to provide a packed depth-stencil
61 * renderbuffer suitable as an FBO attachment with OpenGL ES 3.1 and earlier.
62 * Such a GLTexture will have no texture object under the hood, and therefore
63 * the only valid operation is getOrCreateRenderBuffer().
64 */
65class Q_AUTOTEST_EXPORT GLTexture
66{
67public:
68 GLTexture();
69 ~GLTexture();
70
71 enum DirtyFlag {
72 None = 0,
73 TextureData = (1 << 0), // texture data needs uploading to GPU
74 Properties = (1 << 1), // texture needs to be (re-)created
75 Parameters = (1 << 2), // texture parameters need to be (re-)set
76 SharedTextureId = (1 << 3), // texture id from shared context
77 TextureImageData = (1 << 4) // texture image data needs uploading
78 };
79
80 /**
81 * Helper class to hold the defining properties of TextureImages
82 */
83 struct Image {
84 QTextureImageDataGeneratorPtr generator;
85 int layer;
86 int mipLevel;
87 QAbstractTexture::CubeMapFace face;
88
89 inline bool operator==(const Image &o) const {
90 bool sameGenerators = (generator == o.generator)
91 || (!generator.isNull() && !o.generator.isNull() && *generator == *o.generator);
92 return sameGenerators && layer == o.layer && mipLevel == o.mipLevel && face == o.face;
93 }
94 inline bool operator!=(const Image &o) const { return !(*this == o); }
95 };
96
97 inline TextureProperties properties() const { return m_properties; }
98 inline TextureParameters parameters() const { return m_parameters; }
99 inline QTextureGeneratorPtr textureGenerator() const { return m_dataFunctor; }
100 inline int sharedTextureId() const { return m_sharedTextureId; }
101 inline const std::vector<Image> &images() const { return m_images; }
102
103 inline QSize size() const { return QSize(m_properties.width, m_properties.height); }
104 inline QOpenGLTexture *getGLTexture() const { return m_gl; }
105
106 /**
107 * @brief
108 * Returns the QOpenGLTexture for this GLTexture. If necessary,
109 * the GL texture will be created from the TextureImageDatas associated
110 * with the texture and image functors. If no functors are provided,
111 * the texture will be created without images.
112 *
113 * If the texture properties or parameters have changed, these changes
114 * will be applied to the resulting OpenGL texture.
115 */
116 struct TextureUpdateInfo
117 {
118 QOpenGLTexture *texture = nullptr;
119 bool wasUpdated = false;
120 TextureProperties properties;
121 };
122
123 TextureUpdateInfo createOrUpdateGLTexture();
124
125 /**
126 * @brief
127 * Returns the RenderBuffer for this GLTexture. If this is the first
128 * call, the OpenGL renderbuffer object will be created.
129 */
130 RenderBuffer *getOrCreateRenderBuffer();
131
132
133 void destroy();
134
135 void cleanup();
136
137 bool isDirty() const
138 {
139 return m_dirtyFlags != None;
140 }
141
142 bool hasTextureData() const { return !m_textureData.isNull(); }
143 bool hasImagesData() const { return !m_imageData.empty(); }
144
145 QFlags<DirtyFlag> dirtyFlags() const { return m_dirtyFlags; }
146
147 QMutex *externalRenderingLock()
148 {
149 return &m_externalRenderingMutex;
150 }
151
152 void setExternalRenderingEnabled(bool enable)
153 {
154 m_externalRendering = enable;
155 }
156
157 bool isExternalRenderingEnabled() const
158 {
159 return m_externalRendering;
160 }
161
162 // Purely for unit testing purposes
163 bool wasTextureRecreated() const
164 {
165 return m_wasTextureRecreated;
166 }
167
168 void setParameters(const TextureParameters &params);
169 void setProperties(const TextureProperties &props);
170 void setImages(const std::vector<Image> &images);
171 void setGenerator(const QTextureGeneratorPtr &generator);
172 void setSharedTextureId(int textureId);
173 void addTextureDataUpdates(const std::vector<QTextureDataUpdate> &updates);
174
175 const std::vector<QTextureDataUpdate> &textureDataUpdates() const { return m_pendingTextureDataUpdates; }
176 QTextureGeneratorPtr dataGenerator() const { return m_dataFunctor; }
177
178private:
179 void requestImageUpload()
180 {
181 m_dirtyFlags |= TextureImageData;
182 }
183
184 void requestUpload()
185 {
186 m_dirtyFlags |= TextureData;
187 }
188
189 bool testDirtyFlag(DirtyFlag flag)
190 {
191 return m_dirtyFlags.testFlag(flag);
192 }
193
194 void setDirtyFlag(DirtyFlag flag, bool value = true)
195 {
196 m_dirtyFlags.setFlag(flag, on: value);
197 }
198
199 QOpenGLTexture *buildGLTexture();
200 bool loadTextureDataFromGenerator();
201 void loadTextureDataFromImages();
202 void uploadGLTextureData();
203 void updateGLTextureParameters();
204 void introspectPropertiesFromSharedTextureId();
205 void destroyResources();
206
207 QFlags<DirtyFlag> m_dirtyFlags;
208 QMutex m_externalRenderingMutex;
209 QOpenGLTexture *m_gl;
210 RenderBuffer *m_renderBuffer;
211
212 // target which is actually used for GL texture
213 TextureProperties m_properties;
214 TextureParameters m_parameters;
215
216 QTextureGeneratorPtr m_dataFunctor;
217 QTextureGenerator *m_pendingDataFunctor;
218 std::vector<Image> m_images;
219
220 // cache actual image data generated by the functors
221 QTextureDataPtr m_textureData;
222 std::vector<QTextureImageDataPtr> m_imageData;
223 std::vector<QTextureDataUpdate> m_pendingTextureDataUpdates;
224
225 int m_sharedTextureId;
226 bool m_externalRendering;
227 bool m_wasTextureRecreated;
228};
229
230} // namespace OpenGL
231} // namespace Render
232} // namespace Qt3DRender
233
234QT_END_NAMESPACE
235
236#endif // QT3DRENDER_RENDER_OPENGL_GLTEXTURE_H
237

source code of qt3d/src/plugins/renderers/opengl/textures/gltexture_p.h