1// Copyright (C) 2020 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_RHI_GLTEXTURE_H
5#define QT3DRENDER_RENDER_RHI_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 <QFlags>
25#include <QMutex>
26#include <QSize>
27
28QT_BEGIN_NAMESPACE
29
30class QRhiTexture;
31class QRhiSampler;
32
33namespace Qt3DRender {
34namespace Render {
35
36template<class APITexture, class APITextureImage>
37class APITextureManager;
38
39class TextureImageManager;
40class TextureDataManager;
41class TextureImageDataManager;
42
43namespace Rhi {
44class RenderBuffer;
45class SubmissionContext;
46
47/**
48 * @brief
49 * Actual implementation of the OpenGL texture object. Makes sure the
50 * QOpenGLTexture is up-to-date with the generators, properties and parameters
51 * that were set for this RHITexture.
52 *
53 * Can be shared among multiple QTexture backend nodes through the
54 * RHITextureManager, which will make sure that there are no two GLTextures
55 * sharing the same texture data.
56 *
57 * A RHITexture can be unique though. In that case, it will not be shared
58 * between QTextures, but private to one QTexture only.
59 *
60 * A RHITexture can also represent an OpenGL renderbuffer object. This is used
61 * only in certain special cases, mainly to provide a packed depth-stencil
62 * renderbuffer suitable as an FBO attachment with OpenGL ES 3.1 and earlier.
63 * Such a RHITexture will have no texture object under the hood, and therefore
64 * the only valid operation is getOrCreateRenderBuffer().
65 */
66class Q_AUTOTEST_EXPORT RHITexture
67{
68public:
69 RHITexture();
70 ~RHITexture();
71
72 enum DirtyFlag {
73 None = 0,
74 TextureData = (1 << 0), // texture data needs uploading to GPU
75 Properties = (1 << 1), // texture needs to be (re-)created
76 Parameters = (1 << 2), // texture parameters need to be (re-)set
77 SharedTextureId = (1 << 3), // texture id from shared context
78 TextureImageData = (1 << 4) // texture image data needs uploading
79 };
80
81 /**
82 * Helper class to hold the defining properties of TextureImages
83 */
84 struct Image
85 {
86 QTextureImageDataGeneratorPtr generator;
87 int layer;
88 int mipLevel;
89 QAbstractTexture::CubeMapFace face;
90
91 inline bool operator==(const Image &o) const
92 {
93 bool sameGenerators = (generator == o.generator)
94 || (!generator.isNull() && !o.generator.isNull() && *generator == *o.generator);
95 return sameGenerators && layer == o.layer && mipLevel == o.mipLevel && face == o.face;
96 }
97 inline bool operator!=(const Image &o) const { return !(*this == o); }
98 };
99
100 inline TextureProperties properties() const { return m_properties; }
101 inline TextureParameters parameters() const { return m_parameters; }
102 inline QTextureGeneratorPtr textureGenerator() const { return m_dataFunctor; }
103 inline int sharedTextureId() const { return m_sharedTextureId; }
104 inline const std::vector<Image> &images() const { return m_images; }
105
106 inline QSize size() const { return QSize(m_properties.width, m_properties.height); }
107 inline QRhiTexture *getRhiTexture() const { return m_rhi; }
108 inline QRhiSampler *getRhiSampler() const { return m_rhiSampler; }
109
110 /**
111 * @brief
112 * Returns the QOpenGLTexture for this RHITexture. If necessary,
113 * the GL texture will be created from the TextureImageDatas associated
114 * with the texture and image functors. If no functors are provided,
115 * the texture will be created without images.
116 *
117 * If the texture properties or parameters have changed, these changes
118 * will be applied to the resulting OpenGL texture.
119 */
120 struct TextureUpdateInfo
121 {
122 QRhiTexture *texture = nullptr;
123 bool wasUpdated = false;
124 TextureProperties properties;
125 };
126
127 TextureUpdateInfo createOrUpdateRhiTexture(SubmissionContext *ctx);
128
129 /**
130 * @brief
131 * Returns the RenderBuffer for this RHITexture. If this is the first
132 * call, the OpenGL renderbuffer object will be created.
133 */
134 RenderBuffer *getOrCreateRenderBuffer();
135
136 void destroy();
137
138 void cleanup();
139
140 bool isDirty() const { return m_dirtyFlags != None; }
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() { return &m_externalRenderingMutex; }
148
149 void setExternalRenderingEnabled(bool enable) { m_externalRendering = enable; }
150
151 bool isExternalRenderingEnabled() const { return m_externalRendering; }
152
153 // Purely for unit testing purposes
154 bool wasTextureRecreated() const { return m_wasTextureRecreated; }
155
156 void setParameters(const TextureParameters &params);
157 void setProperties(const TextureProperties &props);
158 void setImages(const std::vector<Image> &images);
159 void setGenerator(const QTextureGeneratorPtr &generator);
160 void setSharedTextureId(int textureId);
161 void addTextureDataUpdates(const std::vector<QTextureDataUpdate> &updates);
162
163 const std::vector<QTextureDataUpdate> &textureDataUpdates() const { return m_pendingTextureDataUpdates; }
164 QTextureGeneratorPtr dataGenerator() const { return m_dataFunctor; }
165
166private:
167 void requestImageUpload() { m_dirtyFlags |= TextureImageData; }
168
169 void requestUpload() { m_dirtyFlags |= TextureData; }
170
171 bool testDirtyFlag(DirtyFlag flag) { return m_dirtyFlags.testFlag(flag); }
172
173 void setDirtyFlag(DirtyFlag flag, bool value = true) { m_dirtyFlags.setFlag(flag, on: value); }
174
175 QRhiTexture *buildRhiTexture(SubmissionContext *ctx);
176 bool loadTextureDataFromGenerator();
177 void loadTextureDataFromImages();
178 void uploadRhiTextureData(SubmissionContext *ctx);
179 void updateRhiTextureParameters(SubmissionContext *ctx);
180 void introspectPropertiesFromSharedTextureId();
181 void destroyResources();
182
183 QFlags<DirtyFlag> m_dirtyFlags;
184 QMutex m_externalRenderingMutex;
185 QRhiTexture *m_rhi;
186 QRhiSampler *m_rhiSampler;
187 RenderBuffer *m_renderBuffer;
188
189 // target which is actually used for GL texture
190 TextureProperties m_properties;
191 TextureParameters m_parameters;
192
193 QTextureGeneratorPtr m_dataFunctor;
194 QTextureGenerator *m_pendingDataFunctor;
195 std::vector<Image> m_images;
196
197 // cache actual image data generated by the functors
198 QTextureDataPtr m_textureData;
199 std::vector<QTextureImageDataPtr> m_imageData;
200 std::vector<QTextureDataUpdate> m_pendingTextureDataUpdates;
201
202 int m_sharedTextureId;
203 bool m_externalRendering;
204 bool m_wasTextureRecreated;
205};
206
207} // namespace Rhi
208} // namespace Render
209} // namespace Qt3DRender
210
211QT_END_NAMESPACE
212
213#endif // QT3DRENDER_RENDER_RHI_GLTEXTURE_H
214

source code of qt3d/src/plugins/renderers/rhi/textures/texture_p.h