1 /****************************************************************************
2 **
3 ** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
4 ** Copyright (C) 2020 The Qt Company Ltd.
5 ** Contact: https://www.qt.io/licensing/
6 **
7 ** This file is part of the QtGui module of the Qt Toolkit.
8 **
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** Commercial License Usage
11 ** Licensees holding valid commercial Qt licenses may use this file in
12 ** accordance with the commercial license agreement provided with the
13 ** Software or, alternatively, in accordance with the terms contained in
14 ** a written agreement between you and The Qt Company. For licensing terms
15 ** and conditions see https://www.qt.io/terms-conditions. For further
16 ** information use the contact form at https://www.qt.io/contact-us.
17 **
18 ** GNU Lesser General Public License Usage
19 ** Alternatively, this file may be used under the terms of the GNU Lesser
20 ** General Public License version 3 as published by the Free Software
21 ** Foundation and appearing in the file LICENSE.LGPL3 included in the
22 ** packaging of this file. Please review the following information to
23 ** ensure the GNU Lesser General Public License version 3 requirements
24 ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
25 **
26 ** GNU General Public License Usage
27 ** Alternatively, this file may be used under the terms of the GNU
28 ** General Public License version 2.0 or (at your option) the GNU General
29 ** Public license version 3 or any later version approved by the KDE Free
30 ** Qt Foundation. The licenses are as published by the Free Software
31 ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
32 ** included in the packaging of this file. Please review the following
33 ** information to ensure the GNU General Public License requirements will
34 ** be met: https://www.gnu.org/licenses/gpl-2.0.html and
35 ** https://www.gnu.org/licenses/gpl-3.0.html.
36 **
37 ** $QT_END_LICENSE$
38 **
39 ****************************************************************************/
40 
41 #include "qopengltexture.h"
42 #include "qopengltexture_p.h"
43 #include "qopengltexturehelper_p.h"
44 #include "qopenglfunctions.h"
45 #include <QtGui/qcolor.h>
46 #include <QtGui/qopenglcontext.h>
47 #include <QtCore/qdebug.h>
48 #include <private/qobject_p.h>
49 #include <private/qopenglcontext_p.h>
50 
51 QT_BEGIN_NAMESPACE
52 
53 //this is to work around GL_TEXTURE_WRAP_R_OES which also has 0x8072 as value
54 #if !defined(GL_TEXTURE_WRAP_R)
55     #define GL_TEXTURE_WRAP_R 0x8072
56 #endif
57 
QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarget,QOpenGLTexture * qq)58 QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarget,
59                                              QOpenGLTexture *qq)
60     : q_ptr(qq),
61       context(nullptr),
62       target(textureTarget),
63       textureId(0),
64       format(QOpenGLTexture::NoFormat),
65       formatClass(QOpenGLTexture::NoFormatClass),
66       requestedMipLevels(1),
67       mipLevels(-1),
68       layers(1),
69       faces(1),
70       samples(0),
71       fixedSamplePositions(true),
72       baseLevel(0),
73       maxLevel(1000),
74       depthStencilMode(QOpenGLTexture::DepthMode),
75       comparisonFunction(QOpenGLTexture::CompareLessEqual),
76       comparisonMode(QOpenGLTexture::CompareNone),
77       minFilter(QOpenGLTexture::Nearest),
78       magFilter(QOpenGLTexture::Nearest),
79       maxAnisotropy(1.0f),
80       minLevelOfDetail(-1000.0f),
81       maxLevelOfDetail(1000.0f),
82       levelOfDetailBias(0.0f),
83       textureView(false),
84       autoGenerateMipMaps(true),
85       storageAllocated(false),
86       texFuncs(nullptr),
87       functions(nullptr)
88 {
89     dimensions[0] = dimensions[1] = dimensions[2] = 1;
90 
91     switch (target) {
92     case QOpenGLTexture::Target1D:
93         bindingTarget = QOpenGLTexture::BindingTarget1D;
94         break;
95     case QOpenGLTexture::Target1DArray:
96         bindingTarget = QOpenGLTexture::BindingTarget1DArray;
97         break;
98     case QOpenGLTexture::Target2D:
99         bindingTarget = QOpenGLTexture::BindingTarget2D;
100         break;
101     case QOpenGLTexture::Target2DArray:
102         bindingTarget = QOpenGLTexture::BindingTarget2DArray;
103         break;
104     case QOpenGLTexture::Target3D:
105         bindingTarget = QOpenGLTexture::BindingTarget3D;
106         break;
107     case QOpenGLTexture::TargetCubeMap:
108         bindingTarget = QOpenGLTexture::BindingTargetCubeMap;
109         faces = 6;
110         break;
111     case QOpenGLTexture::TargetCubeMapArray:
112         bindingTarget = QOpenGLTexture::BindingTargetCubeMapArray;
113         faces = 6;
114         break;
115     case QOpenGLTexture::Target2DMultisample:
116         bindingTarget = QOpenGLTexture::BindingTarget2DMultisample;
117         break;
118     case QOpenGLTexture::Target2DMultisampleArray:
119         bindingTarget = QOpenGLTexture::BindingTarget2DMultisampleArray;
120         break;
121     case QOpenGLTexture::TargetRectangle:
122         bindingTarget = QOpenGLTexture::BindingTargetRectangle;
123         break;
124     case QOpenGLTexture::TargetBuffer:
125         bindingTarget = QOpenGLTexture::BindingTargetBuffer;
126         break;
127     }
128 
129     swizzleMask[0] = QOpenGLTexture::RedValue;
130     swizzleMask[1] = QOpenGLTexture::GreenValue;
131     swizzleMask[2] = QOpenGLTexture::BlueValue;
132     swizzleMask[3] = QOpenGLTexture::AlphaValue;
133 
134     wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle
135         ? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat;
136 }
137 
~QOpenGLTexturePrivate()138 QOpenGLTexturePrivate::~QOpenGLTexturePrivate()
139 {
140     destroy();
141 }
142 
initializeOpenGLFunctions()143 void QOpenGLTexturePrivate::initializeOpenGLFunctions()
144 {
145     // If we already have a functions object, there is nothing to do
146     if (texFuncs)
147         return;
148 
149     // See if the context already has a suitable resource we can use.
150     // If not create a functions object and add it to the context in case
151     // others wish to use it too
152     texFuncs = context->textureFunctions();
153     if (!texFuncs) {
154         texFuncs = new QOpenGLTextureHelper(context);
155         context->setTextureFunctions(texFuncs);
156     }
157 }
158 
create()159 bool QOpenGLTexturePrivate::create()
160 {
161     if (textureId != 0)
162         return true;
163 
164     QOpenGLContext *ctx = QOpenGLContext::currentContext();
165     if (!ctx) {
166         qWarning("Requires a valid current OpenGL context.\n"
167                  "Texture has not been created");
168         return false;
169     }
170     context = ctx;
171     functions = ctx->functions();
172 
173     // Resolve any functions we will need based upon context version and create the texture
174     initializeOpenGLFunctions();
175 
176     // What features do we have?
177     QOpenGLTexture::Feature feature = QOpenGLTexture::ImmutableStorage;
178     while (feature != QOpenGLTexture::MaxFeatureFlag) {
179         if (QOpenGLTexture::hasFeature(feature))
180             features |= feature;
181         feature = static_cast<QOpenGLTexture::Feature>(feature << 1);
182     }
183 
184     functions->glGenTextures(1, &textureId);
185     return textureId != 0;
186 }
187 
destroy()188 void QOpenGLTexturePrivate::destroy()
189 {
190     if (!textureId) {
191         // not created or already destroyed
192         return;
193     }
194     QOpenGLContext *currentContext = QOpenGLContext::currentContext();
195     if (!currentContext) {
196         qWarning("QOpenGLTexturePrivate::destroy() called without a current context.\n"
197                  "Texture has not been destroyed");
198         return;
199     }
200     if (!QOpenGLContext::areSharing(currentContext, context)) {
201 
202         qWarning("QOpenGLTexturePrivate::destroy() called but texture context %p"
203                  " is not shared with current context %p.\n"
204                  "Texture has not been destroyed",
205                  static_cast<const void *>(context),
206                  static_cast<const void *>(currentContext));
207         return;
208     }
209 
210     functions->glDeleteTextures(1, &textureId);
211 
212     context = nullptr;
213     functions = nullptr;
214     textureId = 0;
215     format = QOpenGLTexture::NoFormat;
216     formatClass = QOpenGLTexture::NoFormatClass;
217     requestedMipLevels = 1;
218     mipLevels = -1;
219     layers = 1;
220     faces = 1;
221     samples = 0;
222     fixedSamplePositions = true,
223     baseLevel = 0;
224     maxLevel = 1000;
225     depthStencilMode = QOpenGLTexture::DepthMode;
226     minFilter = QOpenGLTexture::Nearest;
227     magFilter = QOpenGLTexture::Nearest;
228     maxAnisotropy = 1.0f;
229     minLevelOfDetail = -1000.0f;
230     maxLevelOfDetail = 1000.0f;
231     levelOfDetailBias = 0.0f;
232     textureView = false;
233     autoGenerateMipMaps = true;
234     storageAllocated = false;
235     texFuncs = nullptr;
236 
237     swizzleMask[0] = QOpenGLTexture::RedValue;
238     swizzleMask[1] = QOpenGLTexture::GreenValue;
239     swizzleMask[2] = QOpenGLTexture::BlueValue;
240     swizzleMask[3] = QOpenGLTexture::AlphaValue;
241 
242     wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle
243         ? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat;
244 }
245 
bind()246 void QOpenGLTexturePrivate::bind()
247 {
248     functions->glBindTexture(target, textureId);
249 }
250 
bind(uint unit,QOpenGLTexture::TextureUnitReset reset)251 void QOpenGLTexturePrivate::bind(uint unit, QOpenGLTexture::TextureUnitReset reset)
252 {
253     GLint oldTextureUnit = 0;
254     if (reset == QOpenGLTexture::ResetTextureUnit)
255         functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
256 
257     texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
258     functions->glBindTexture(target, textureId);
259 
260     if (reset == QOpenGLTexture::ResetTextureUnit)
261         texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
262 }
263 
release()264 void QOpenGLTexturePrivate::release()
265 {
266     functions->glBindTexture(target, 0);
267 }
268 
release(uint unit,QOpenGLTexture::TextureUnitReset reset)269 void QOpenGLTexturePrivate::release(uint unit, QOpenGLTexture::TextureUnitReset reset)
270 {
271     GLint oldTextureUnit = 0;
272     if (reset == QOpenGLTexture::ResetTextureUnit)
273         functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
274 
275     texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
276     functions->glBindTexture(target, 0);
277 
278     if (reset == QOpenGLTexture::ResetTextureUnit)
279         texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
280 }
281 
isBound() const282 bool QOpenGLTexturePrivate::isBound() const
283 {
284     GLint boundTextureId = 0;
285     functions->glGetIntegerv(bindingTarget, &boundTextureId);
286     return (static_cast<GLuint>(boundTextureId) == textureId);
287 }
288 
isBound(uint unit) const289 bool QOpenGLTexturePrivate::isBound(uint unit) const
290 {
291     GLint oldTextureUnit = 0;
292     functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
293 
294     GLint boundTextureId = 0;
295     texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
296     functions->glGetIntegerv(bindingTarget, &boundTextureId);
297     bool result = (static_cast<GLuint>(boundTextureId) == textureId);
298 
299     texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
300     return result;
301 }
302 
evaluateMipLevels() const303 int QOpenGLTexturePrivate::evaluateMipLevels() const
304 {
305     switch (target) {
306     case QOpenGLTexture::Target1D:
307     case QOpenGLTexture::Target1DArray:
308     case QOpenGLTexture::Target2D:
309     case QOpenGLTexture::Target2DArray:
310     case QOpenGLTexture::Target3D:
311     case QOpenGLTexture::TargetCubeMap:
312     case QOpenGLTexture::TargetCubeMapArray:
313         return qMin(maximumMipLevelCount(), qMax(1, requestedMipLevels));
314 
315     case QOpenGLTexture::TargetRectangle:
316     case QOpenGLTexture::Target2DMultisample:
317     case QOpenGLTexture::Target2DMultisampleArray:
318     case QOpenGLTexture::TargetBuffer:
319     default:
320         return 1;
321     }
322 }
323 
isSizedTextureFormat(QOpenGLTexture::TextureFormat internalFormat)324 static bool isSizedTextureFormat(QOpenGLTexture::TextureFormat internalFormat)
325 {
326     switch (internalFormat) {
327     case QOpenGLTexture::NoFormat:
328         return false;
329 
330     case QOpenGLTexture::R8_UNorm:
331     case QOpenGLTexture::RG8_UNorm:
332     case QOpenGLTexture::RGB8_UNorm:
333     case QOpenGLTexture::RGBA8_UNorm:
334     case QOpenGLTexture::R16_UNorm:
335     case QOpenGLTexture::RG16_UNorm:
336     case QOpenGLTexture::RGB16_UNorm:
337     case QOpenGLTexture::RGBA16_UNorm:
338     case QOpenGLTexture::R8_SNorm:
339     case QOpenGLTexture::RG8_SNorm:
340     case QOpenGLTexture::RGB8_SNorm:
341     case QOpenGLTexture::RGBA8_SNorm:
342     case QOpenGLTexture::R16_SNorm:
343     case QOpenGLTexture::RG16_SNorm:
344     case QOpenGLTexture::RGB16_SNorm:
345     case QOpenGLTexture::RGBA16_SNorm:
346     case QOpenGLTexture::R8U:
347     case QOpenGLTexture::RG8U:
348     case QOpenGLTexture::RGB8U:
349     case QOpenGLTexture::RGBA8U:
350     case QOpenGLTexture::R16U:
351     case QOpenGLTexture::RG16U:
352     case QOpenGLTexture::RGB16U:
353     case QOpenGLTexture::RGBA16U:
354     case QOpenGLTexture::R32U:
355     case QOpenGLTexture::RG32U:
356     case QOpenGLTexture::RGB32U:
357     case QOpenGLTexture::RGBA32U:
358     case QOpenGLTexture::R8I:
359     case QOpenGLTexture::RG8I:
360     case QOpenGLTexture::RGB8I:
361     case QOpenGLTexture::RGBA8I:
362     case QOpenGLTexture::R16I:
363     case QOpenGLTexture::RG16I:
364     case QOpenGLTexture::RGB16I:
365     case QOpenGLTexture::RGBA16I:
366     case QOpenGLTexture::R32I:
367     case QOpenGLTexture::RG32I:
368     case QOpenGLTexture::RGB32I:
369     case QOpenGLTexture::RGBA32I:
370     case QOpenGLTexture::R16F:
371     case QOpenGLTexture::RG16F:
372     case QOpenGLTexture::RGB16F:
373     case QOpenGLTexture::RGBA16F:
374     case QOpenGLTexture::R32F:
375     case QOpenGLTexture::RG32F:
376     case QOpenGLTexture::RGB32F:
377     case QOpenGLTexture::RGBA32F:
378     case QOpenGLTexture::RGB9E5:
379     case QOpenGLTexture::RG11B10F:
380     case QOpenGLTexture::RG3B2:
381     case QOpenGLTexture::R5G6B5:
382     case QOpenGLTexture::RGB5A1:
383     case QOpenGLTexture::RGBA4:
384     case QOpenGLTexture::RGB10A2:
385 
386     case QOpenGLTexture::D16:
387     case QOpenGLTexture::D24:
388     case QOpenGLTexture::D32:
389     case QOpenGLTexture::D32F:
390 
391     case QOpenGLTexture::D24S8:
392     case QOpenGLTexture::D32FS8X24:
393 
394     case QOpenGLTexture::S8:
395 
396     case QOpenGLTexture::RGB_DXT1:
397     case QOpenGLTexture::RGBA_DXT1:
398     case QOpenGLTexture::RGBA_DXT3:
399     case QOpenGLTexture::RGBA_DXT5:
400     case QOpenGLTexture::R_ATI1N_UNorm:
401     case QOpenGLTexture::R_ATI1N_SNorm:
402     case QOpenGLTexture::RG_ATI2N_UNorm:
403     case QOpenGLTexture::RG_ATI2N_SNorm:
404     case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
405     case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
406     case QOpenGLTexture::RGB_BP_UNorm:
407     case QOpenGLTexture::SRGB8:
408     case QOpenGLTexture::SRGB8_Alpha8:
409     case QOpenGLTexture::SRGB_DXT1:
410     case QOpenGLTexture::SRGB_Alpha_DXT1:
411     case QOpenGLTexture::SRGB_Alpha_DXT3:
412     case QOpenGLTexture::SRGB_Alpha_DXT5:
413     case QOpenGLTexture::SRGB_BP_UNorm:
414     case QOpenGLTexture::R11_EAC_UNorm:
415     case QOpenGLTexture::R11_EAC_SNorm:
416     case QOpenGLTexture::RG11_EAC_UNorm:
417     case QOpenGLTexture::RG11_EAC_SNorm:
418     case QOpenGLTexture::RGB8_ETC2:
419     case QOpenGLTexture::SRGB8_ETC2:
420     case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
421     case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
422     case QOpenGLTexture::RGBA8_ETC2_EAC:
423     case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
424     case QOpenGLTexture::RGBA_ASTC_4x4:
425     case QOpenGLTexture::RGBA_ASTC_5x4:
426     case QOpenGLTexture::RGBA_ASTC_5x5:
427     case QOpenGLTexture::RGBA_ASTC_6x5:
428     case QOpenGLTexture::RGBA_ASTC_6x6:
429     case QOpenGLTexture::RGBA_ASTC_8x5:
430     case QOpenGLTexture::RGBA_ASTC_8x6:
431     case QOpenGLTexture::RGBA_ASTC_8x8:
432     case QOpenGLTexture::RGBA_ASTC_10x5:
433     case QOpenGLTexture::RGBA_ASTC_10x6:
434     case QOpenGLTexture::RGBA_ASTC_10x8:
435     case QOpenGLTexture::RGBA_ASTC_10x10:
436     case QOpenGLTexture::RGBA_ASTC_12x10:
437     case QOpenGLTexture::RGBA_ASTC_12x12:
438     case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
439     case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
440     case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
441     case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
442     case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
443     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
444     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
445     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
446     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
447     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
448     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
449     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
450     case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
451     case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
452         return true;
453 
454     case QOpenGLTexture::RGB8_ETC1:
455         return false;
456 
457     case QOpenGLTexture::DepthFormat:
458     case QOpenGLTexture::AlphaFormat:
459 
460     case QOpenGLTexture::RGBFormat:
461     case QOpenGLTexture::RGBAFormat:
462 
463     case QOpenGLTexture::LuminanceFormat:
464 
465     case QOpenGLTexture::LuminanceAlphaFormat:
466         return false;
467     }
468 
469     Q_UNREACHABLE();
470     return false;
471 }
472 
isTextureTargetMultisample(QOpenGLTexture::Target target)473 static bool isTextureTargetMultisample(QOpenGLTexture::Target target)
474 {
475     switch (target) {
476     case QOpenGLTexture::Target1D:
477     case QOpenGLTexture::Target1DArray:
478     case QOpenGLTexture::Target2D:
479     case QOpenGLTexture::Target2DArray:
480     case QOpenGLTexture::Target3D:
481     case QOpenGLTexture::TargetCubeMap:
482     case QOpenGLTexture::TargetCubeMapArray:
483         return false;
484 
485     case QOpenGLTexture::Target2DMultisample:
486     case QOpenGLTexture::Target2DMultisampleArray:
487         return true;
488 
489     case QOpenGLTexture::TargetRectangle:
490     case QOpenGLTexture::TargetBuffer:
491         return false;
492     }
493 
494     Q_UNREACHABLE();
495     return false;
496 }
497 
isUsingImmutableStorage() const498 bool QOpenGLTexturePrivate::isUsingImmutableStorage() const
499 {
500     // Use immutable storage whenever possible, falling back to mutable
501     // Note that if multisample textures are not supported at all, we'll still fail into
502     // the mutable storage allocation
503     return isSizedTextureFormat(format)
504             && (isTextureTargetMultisample(target)
505                 ? features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)
506                 : features.testFlag(QOpenGLTexture::ImmutableStorage));
507 }
508 
allocateStorage(QOpenGLTexture::PixelFormat pixelFormat,QOpenGLTexture::PixelType pixelType)509 void QOpenGLTexturePrivate::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
510 {
511     // Resolve the actual number of mipmap levels we can use
512     mipLevels = evaluateMipLevels();
513 
514     if (isUsingImmutableStorage())
515         allocateImmutableStorage();
516     else
517         allocateMutableStorage(pixelFormat, pixelType);
518 }
519 
pixelFormatCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)520 static QOpenGLTexture::PixelFormat pixelFormatCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)
521 {
522     switch (internalFormat) {
523     case QOpenGLTexture::NoFormat:
524         return QOpenGLTexture::NoSourceFormat;
525 
526     case QOpenGLTexture::R8_UNorm:
527         return QOpenGLTexture::Red;
528 
529     case QOpenGLTexture::RG8_UNorm:
530         return QOpenGLTexture::RG;
531 
532     case QOpenGLTexture::RGB8_UNorm:
533         return QOpenGLTexture::RGB;
534 
535     case QOpenGLTexture::RGBA8_UNorm:
536         return QOpenGLTexture::RGBA;
537 
538     case QOpenGLTexture::R16_UNorm:
539         return QOpenGLTexture::Red;
540 
541     case QOpenGLTexture::RG16_UNorm:
542         return QOpenGLTexture::RG;
543 
544     case QOpenGLTexture::RGB16_UNorm:
545         return QOpenGLTexture::RGB;
546 
547     case QOpenGLTexture::RGBA16_UNorm:
548         return QOpenGLTexture::RGBA;
549 
550     case QOpenGLTexture::R8_SNorm:
551         return QOpenGLTexture::Red;
552 
553     case QOpenGLTexture::RG8_SNorm:
554         return QOpenGLTexture::RG;
555 
556     case QOpenGLTexture::RGB8_SNorm:
557         return QOpenGLTexture::RGB;
558 
559     case QOpenGLTexture::RGBA8_SNorm:
560         return QOpenGLTexture::RGBA;
561 
562     case QOpenGLTexture::R16_SNorm:
563         return QOpenGLTexture::Red;
564 
565     case QOpenGLTexture::RG16_SNorm:
566         return QOpenGLTexture::RG;
567 
568     case QOpenGLTexture::RGB16_SNorm:
569         return QOpenGLTexture::RGB;
570 
571     case QOpenGLTexture::RGBA16_SNorm:
572         return QOpenGLTexture::RGBA;
573 
574     case QOpenGLTexture::R8U:
575         return QOpenGLTexture::Red_Integer;
576 
577     case QOpenGLTexture::RG8U:
578         return QOpenGLTexture::RG_Integer;
579 
580     case QOpenGLTexture::RGB8U:
581         return QOpenGLTexture::RGB_Integer;
582 
583     case QOpenGLTexture::RGBA8U:
584         return QOpenGLTexture::RGBA_Integer;
585 
586     case QOpenGLTexture::R16U:
587         return QOpenGLTexture::Red_Integer;
588 
589     case QOpenGLTexture::RG16U:
590         return QOpenGLTexture::RG_Integer;
591 
592     case QOpenGLTexture::RGB16U:
593         return QOpenGLTexture::RGB_Integer;
594 
595     case QOpenGLTexture::RGBA16U:
596         return QOpenGLTexture::RGBA_Integer;
597 
598     case QOpenGLTexture::R32U:
599         return QOpenGLTexture::Red_Integer;
600 
601     case QOpenGLTexture::RG32U:
602         return QOpenGLTexture::RG_Integer;
603 
604     case QOpenGLTexture::RGB32U:
605         return QOpenGLTexture::RGB_Integer;
606 
607     case QOpenGLTexture::RGBA32U:
608         return QOpenGLTexture::RGBA_Integer;
609 
610     case QOpenGLTexture::R8I:
611         return QOpenGLTexture::Red_Integer;
612 
613     case QOpenGLTexture::RG8I:
614         return QOpenGLTexture::RG_Integer;
615 
616     case QOpenGLTexture::RGB8I:
617         return QOpenGLTexture::RGB_Integer;
618 
619     case QOpenGLTexture::RGBA8I:
620         return QOpenGLTexture::RGBA_Integer;
621 
622     case QOpenGLTexture::R16I:
623         return QOpenGLTexture::Red_Integer;
624 
625     case QOpenGLTexture::RG16I:
626         return QOpenGLTexture::RG_Integer;
627 
628     case QOpenGLTexture::RGB16I:
629         return QOpenGLTexture::RGB_Integer;
630 
631     case QOpenGLTexture::RGBA16I:
632         return QOpenGLTexture::RGBA_Integer;
633 
634     case QOpenGLTexture::R32I:
635         return QOpenGLTexture::Red_Integer;
636 
637     case QOpenGLTexture::RG32I:
638         return QOpenGLTexture::RG_Integer;
639 
640     case QOpenGLTexture::RGB32I:
641         return QOpenGLTexture::RGB_Integer;
642 
643     case QOpenGLTexture::RGBA32I:
644         return QOpenGLTexture::RGBA_Integer;
645 
646     case QOpenGLTexture::R16F:
647         return QOpenGLTexture::Red;
648 
649     case QOpenGLTexture::RG16F:
650         return QOpenGLTexture::RG;
651 
652     case QOpenGLTexture::RGB16F:
653         return QOpenGLTexture::RGB;
654 
655     case QOpenGLTexture::RGBA16F:
656         return QOpenGLTexture::RGBA;
657 
658     case QOpenGLTexture::R32F:
659         return QOpenGLTexture::Red;
660 
661     case QOpenGLTexture::RG32F:
662         return QOpenGLTexture::RG;
663 
664     case QOpenGLTexture::RGB32F:
665         return QOpenGLTexture::RGB;
666 
667     case QOpenGLTexture::RGBA32F:
668         return QOpenGLTexture::RGBA;
669 
670     case QOpenGLTexture::RGB9E5:
671         return QOpenGLTexture::RGB;
672 
673     case QOpenGLTexture::RG11B10F:
674         return QOpenGLTexture::RGB;
675 
676     case QOpenGLTexture::RG3B2:
677         return QOpenGLTexture::RGB;
678 
679     case QOpenGLTexture::R5G6B5:
680         return QOpenGLTexture::RGB;
681 
682     case QOpenGLTexture::RGB5A1:
683         return QOpenGLTexture::RGBA;
684 
685     case QOpenGLTexture::RGBA4:
686         return QOpenGLTexture::RGBA;
687 
688     case QOpenGLTexture::RGB10A2:
689         return QOpenGLTexture::RGBA;
690 
691     case QOpenGLTexture::D16:
692     case QOpenGLTexture::D24:
693     case QOpenGLTexture::D32:
694     case QOpenGLTexture::D32F:
695         return QOpenGLTexture::Depth;
696 
697     case QOpenGLTexture::D24S8:
698     case QOpenGLTexture::D32FS8X24:
699         return QOpenGLTexture::DepthStencil;
700 
701     case QOpenGLTexture::S8:
702         return QOpenGLTexture::Stencil;
703 
704     case QOpenGLTexture::RGB_DXT1:
705     case QOpenGLTexture::RGBA_DXT1:
706     case QOpenGLTexture::RGBA_DXT3:
707     case QOpenGLTexture::RGBA_DXT5:
708     case QOpenGLTexture::R_ATI1N_UNorm:
709     case QOpenGLTexture::R_ATI1N_SNorm:
710     case QOpenGLTexture::RG_ATI2N_UNorm:
711     case QOpenGLTexture::RG_ATI2N_SNorm:
712     case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
713     case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
714     case QOpenGLTexture::RGB_BP_UNorm:
715     case QOpenGLTexture::SRGB8:
716     case QOpenGLTexture::SRGB8_Alpha8:
717     case QOpenGLTexture::SRGB_DXT1:
718     case QOpenGLTexture::SRGB_Alpha_DXT1:
719     case QOpenGLTexture::SRGB_Alpha_DXT3:
720     case QOpenGLTexture::SRGB_Alpha_DXT5:
721     case QOpenGLTexture::SRGB_BP_UNorm:
722     case QOpenGLTexture::RGB8_ETC1:
723         return QOpenGLTexture::RGBA;
724 
725     case QOpenGLTexture::R11_EAC_UNorm:
726     case QOpenGLTexture::R11_EAC_SNorm:
727         return QOpenGLTexture::Red;
728 
729     case QOpenGLTexture::RG11_EAC_UNorm:
730     case QOpenGLTexture::RG11_EAC_SNorm:
731         return QOpenGLTexture::RG;
732 
733     case QOpenGLTexture::RGB8_ETC2:
734     case QOpenGLTexture::SRGB8_ETC2:
735         return QOpenGLTexture::RGB;
736 
737     case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
738     case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
739         return QOpenGLTexture::RGBA;
740 
741     case QOpenGLTexture::RGBA8_ETC2_EAC:
742     case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
743         return QOpenGLTexture::RGBA;
744 
745     case QOpenGLTexture::RGBA_ASTC_4x4:
746     case QOpenGLTexture::RGBA_ASTC_5x4:
747     case QOpenGLTexture::RGBA_ASTC_5x5:
748     case QOpenGLTexture::RGBA_ASTC_6x5:
749     case QOpenGLTexture::RGBA_ASTC_6x6:
750     case QOpenGLTexture::RGBA_ASTC_8x5:
751     case QOpenGLTexture::RGBA_ASTC_8x6:
752     case QOpenGLTexture::RGBA_ASTC_8x8:
753     case QOpenGLTexture::RGBA_ASTC_10x5:
754     case QOpenGLTexture::RGBA_ASTC_10x6:
755     case QOpenGLTexture::RGBA_ASTC_10x8:
756     case QOpenGLTexture::RGBA_ASTC_10x10:
757     case QOpenGLTexture::RGBA_ASTC_12x10:
758     case QOpenGLTexture::RGBA_ASTC_12x12:
759     case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
760     case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
761     case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
762     case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
763     case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
764     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
765     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
766     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
767     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
768     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
769     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
770     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
771     case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
772     case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
773         return QOpenGLTexture::RGBA;
774 
775     case QOpenGLTexture::DepthFormat:
776         return QOpenGLTexture::Depth;
777 
778     case QOpenGLTexture::AlphaFormat:
779         return QOpenGLTexture::Alpha;
780 
781     case QOpenGLTexture::RGBFormat:
782         return QOpenGLTexture::RGB;
783 
784     case QOpenGLTexture::RGBAFormat:
785         return QOpenGLTexture::RGBA;
786 
787     case QOpenGLTexture::LuminanceFormat:
788         return QOpenGLTexture::Luminance;
789 
790     case QOpenGLTexture::LuminanceAlphaFormat:
791         return QOpenGLTexture::LuminanceAlpha;
792     }
793 
794     Q_UNREACHABLE();
795     return QOpenGLTexture::NoSourceFormat;
796 }
797 
pixelTypeCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)798 static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)
799 {
800     switch (internalFormat) {
801     case QOpenGLTexture::NoFormat:
802         return QOpenGLTexture::NoPixelType;
803 
804     case QOpenGLTexture::R8_UNorm:
805     case QOpenGLTexture::RG8_UNorm:
806     case QOpenGLTexture::RGB8_UNorm:
807     case QOpenGLTexture::RGBA8_UNorm:
808     case QOpenGLTexture::R16_UNorm:
809     case QOpenGLTexture::RG16_UNorm:
810     case QOpenGLTexture::RGB16_UNorm:
811     case QOpenGLTexture::RGBA16_UNorm:
812         return QOpenGLTexture::UInt8;
813 
814     case QOpenGLTexture::R8_SNorm:
815     case QOpenGLTexture::RG8_SNorm:
816     case QOpenGLTexture::RGB8_SNorm:
817     case QOpenGLTexture::RGBA8_SNorm:
818     case QOpenGLTexture::R16_SNorm:
819     case QOpenGLTexture::RG16_SNorm:
820     case QOpenGLTexture::RGB16_SNorm:
821     case QOpenGLTexture::RGBA16_SNorm:
822         return QOpenGLTexture::Int8;
823 
824     case QOpenGLTexture::R8U:
825     case QOpenGLTexture::RG8U:
826     case QOpenGLTexture::RGB8U:
827     case QOpenGLTexture::RGBA8U:
828     case QOpenGLTexture::R16U:
829     case QOpenGLTexture::RG16U:
830     case QOpenGLTexture::RGB16U:
831     case QOpenGLTexture::RGBA16U:
832     case QOpenGLTexture::R32U:
833     case QOpenGLTexture::RG32U:
834     case QOpenGLTexture::RGB32U:
835     case QOpenGLTexture::RGBA32U:
836         return QOpenGLTexture::UInt8;
837 
838     case QOpenGLTexture::R8I:
839     case QOpenGLTexture::RG8I:
840     case QOpenGLTexture::RGB8I:
841     case QOpenGLTexture::RGBA8I:
842     case QOpenGLTexture::R16I:
843     case QOpenGLTexture::RG16I:
844     case QOpenGLTexture::RGB16I:
845     case QOpenGLTexture::RGBA16I:
846     case QOpenGLTexture::R32I:
847     case QOpenGLTexture::RG32I:
848     case QOpenGLTexture::RGB32I:
849     case QOpenGLTexture::RGBA32I:
850         return QOpenGLTexture::Int8;
851 
852     case QOpenGLTexture::R16F:
853     case QOpenGLTexture::RG16F:
854     case QOpenGLTexture::RGB16F:
855     case QOpenGLTexture::RGBA16F:
856         return QOpenGLTexture::Float16;
857 
858     case QOpenGLTexture::R32F:
859     case QOpenGLTexture::RG32F:
860     case QOpenGLTexture::RGB32F:
861     case QOpenGLTexture::RGBA32F:
862         return QOpenGLTexture::Float32;
863 
864     case QOpenGLTexture::RGB9E5:
865         return QOpenGLTexture::UInt16_RGB5A1_Rev;
866 
867     case QOpenGLTexture::RG11B10F:
868         return QOpenGLTexture::UInt32_RG11B10F;
869 
870     case QOpenGLTexture::RG3B2:
871         return QOpenGLTexture::UInt8_RG3B2;
872 
873     case QOpenGLTexture::R5G6B5:
874         return QOpenGLTexture::UInt16_R5G6B5;
875 
876     case QOpenGLTexture::RGB5A1:
877         return QOpenGLTexture::UInt16_RGB5A1;
878 
879     case QOpenGLTexture::RGBA4:
880         return QOpenGLTexture::UInt16_RGBA4;
881 
882     case QOpenGLTexture::RGB10A2:
883         return QOpenGLTexture::UInt32_RGB10A2;
884 
885     case QOpenGLTexture::D16:
886         return QOpenGLTexture::UInt16;
887 
888     case QOpenGLTexture::D24:
889     case QOpenGLTexture::D32:
890         return QOpenGLTexture::UInt32;
891 
892     case QOpenGLTexture::D32F:
893         return QOpenGLTexture::Float32;
894 
895     case QOpenGLTexture::D24S8:
896         return QOpenGLTexture::UInt32_D24S8;
897 
898     case QOpenGLTexture::D32FS8X24:
899         return QOpenGLTexture::Float32_D32_UInt32_S8_X24;
900 
901     case QOpenGLTexture::S8:
902         return QOpenGLTexture::UInt8;
903 
904     case QOpenGLTexture::RGB_DXT1:
905     case QOpenGLTexture::RGBA_DXT1:
906     case QOpenGLTexture::RGBA_DXT3:
907     case QOpenGLTexture::RGBA_DXT5:
908     case QOpenGLTexture::R_ATI1N_UNorm:
909     case QOpenGLTexture::R_ATI1N_SNorm:
910     case QOpenGLTexture::RG_ATI2N_UNorm:
911     case QOpenGLTexture::RG_ATI2N_SNorm:
912     case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
913     case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
914     case QOpenGLTexture::RGB_BP_UNorm:
915     case QOpenGLTexture::SRGB8:
916     case QOpenGLTexture::SRGB8_Alpha8:
917     case QOpenGLTexture::SRGB_DXT1:
918     case QOpenGLTexture::SRGB_Alpha_DXT1:
919     case QOpenGLTexture::SRGB_Alpha_DXT3:
920     case QOpenGLTexture::SRGB_Alpha_DXT5:
921     case QOpenGLTexture::SRGB_BP_UNorm:
922     case QOpenGLTexture::R11_EAC_UNorm:
923     case QOpenGLTexture::R11_EAC_SNorm:
924     case QOpenGLTexture::RG11_EAC_UNorm:
925     case QOpenGLTexture::RG11_EAC_SNorm:
926     case QOpenGLTexture::RGB8_ETC2:
927     case QOpenGLTexture::SRGB8_ETC2:
928     case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
929     case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
930     case QOpenGLTexture::RGBA8_ETC2_EAC:
931     case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
932     case QOpenGLTexture::RGB8_ETC1:
933     case QOpenGLTexture::RGBA_ASTC_4x4:
934     case QOpenGLTexture::RGBA_ASTC_5x4:
935     case QOpenGLTexture::RGBA_ASTC_5x5:
936     case QOpenGLTexture::RGBA_ASTC_6x5:
937     case QOpenGLTexture::RGBA_ASTC_6x6:
938     case QOpenGLTexture::RGBA_ASTC_8x5:
939     case QOpenGLTexture::RGBA_ASTC_8x6:
940     case QOpenGLTexture::RGBA_ASTC_8x8:
941     case QOpenGLTexture::RGBA_ASTC_10x5:
942     case QOpenGLTexture::RGBA_ASTC_10x6:
943     case QOpenGLTexture::RGBA_ASTC_10x8:
944     case QOpenGLTexture::RGBA_ASTC_10x10:
945     case QOpenGLTexture::RGBA_ASTC_12x10:
946     case QOpenGLTexture::RGBA_ASTC_12x12:
947     case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
948     case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
949     case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
950     case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
951     case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
952     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
953     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
954     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
955     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
956     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
957     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
958     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
959     case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
960     case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
961         return QOpenGLTexture::UInt8;
962 
963     case QOpenGLTexture::DepthFormat:
964         return QOpenGLTexture::UInt32;
965 
966     case QOpenGLTexture::AlphaFormat:
967     case QOpenGLTexture::RGBFormat:
968     case QOpenGLTexture::RGBAFormat:
969     case QOpenGLTexture::LuminanceFormat:
970     case QOpenGLTexture::LuminanceAlphaFormat:
971         return QOpenGLTexture::UInt8;
972     }
973 
974     Q_UNREACHABLE();
975     return QOpenGLTexture::NoPixelType;
976 }
977 
isCompressedFormat(QOpenGLTexture::TextureFormat internalFormat)978 static bool isCompressedFormat(QOpenGLTexture::TextureFormat internalFormat)
979 {
980     switch (internalFormat) {
981     case QOpenGLTexture::NoFormat:
982 
983     case QOpenGLTexture::R8_UNorm:
984     case QOpenGLTexture::RG8_UNorm:
985     case QOpenGLTexture::RGB8_UNorm:
986     case QOpenGLTexture::RGBA8_UNorm:
987     case QOpenGLTexture::R16_UNorm:
988     case QOpenGLTexture::RG16_UNorm:
989     case QOpenGLTexture::RGB16_UNorm:
990     case QOpenGLTexture::RGBA16_UNorm:
991     case QOpenGLTexture::R8_SNorm:
992     case QOpenGLTexture::RG8_SNorm:
993     case QOpenGLTexture::RGB8_SNorm:
994     case QOpenGLTexture::RGBA8_SNorm:
995     case QOpenGLTexture::R16_SNorm:
996     case QOpenGLTexture::RG16_SNorm:
997     case QOpenGLTexture::RGB16_SNorm:
998     case QOpenGLTexture::RGBA16_SNorm:
999     case QOpenGLTexture::R8U:
1000     case QOpenGLTexture::RG8U:
1001     case QOpenGLTexture::RGB8U:
1002     case QOpenGLTexture::RGBA8U:
1003     case QOpenGLTexture::R16U:
1004     case QOpenGLTexture::RG16U:
1005     case QOpenGLTexture::RGB16U:
1006     case QOpenGLTexture::RGBA16U:
1007     case QOpenGLTexture::R32U:
1008     case QOpenGLTexture::RG32U:
1009     case QOpenGLTexture::RGB32U:
1010     case QOpenGLTexture::RGBA32U:
1011     case QOpenGLTexture::R8I:
1012     case QOpenGLTexture::RG8I:
1013     case QOpenGLTexture::RGB8I:
1014     case QOpenGLTexture::RGBA8I:
1015     case QOpenGLTexture::R16I:
1016     case QOpenGLTexture::RG16I:
1017     case QOpenGLTexture::RGB16I:
1018     case QOpenGLTexture::RGBA16I:
1019     case QOpenGLTexture::R32I:
1020     case QOpenGLTexture::RG32I:
1021     case QOpenGLTexture::RGB32I:
1022     case QOpenGLTexture::RGBA32I:
1023     case QOpenGLTexture::R16F:
1024     case QOpenGLTexture::RG16F:
1025     case QOpenGLTexture::RGB16F:
1026     case QOpenGLTexture::RGBA16F:
1027     case QOpenGLTexture::R32F:
1028     case QOpenGLTexture::RG32F:
1029     case QOpenGLTexture::RGB32F:
1030     case QOpenGLTexture::RGBA32F:
1031     case QOpenGLTexture::RGB9E5:
1032     case QOpenGLTexture::RG11B10F:
1033     case QOpenGLTexture::RG3B2:
1034     case QOpenGLTexture::R5G6B5:
1035     case QOpenGLTexture::RGB5A1:
1036     case QOpenGLTexture::RGBA4:
1037     case QOpenGLTexture::RGB10A2:
1038 
1039     case QOpenGLTexture::D16:
1040     case QOpenGLTexture::D24:
1041     case QOpenGLTexture::D32:
1042     case QOpenGLTexture::D32F:
1043 
1044     case QOpenGLTexture::D24S8:
1045     case QOpenGLTexture::D32FS8X24:
1046 
1047     case QOpenGLTexture::S8:
1048         return false;
1049 
1050     case QOpenGLTexture::RGB_DXT1:
1051     case QOpenGLTexture::RGBA_DXT1:
1052     case QOpenGLTexture::RGBA_DXT3:
1053     case QOpenGLTexture::RGBA_DXT5:
1054     case QOpenGLTexture::R_ATI1N_UNorm:
1055     case QOpenGLTexture::R_ATI1N_SNorm:
1056     case QOpenGLTexture::RG_ATI2N_UNorm:
1057     case QOpenGLTexture::RG_ATI2N_SNorm:
1058     case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
1059     case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
1060     case QOpenGLTexture::RGB_BP_UNorm:
1061     case QOpenGLTexture::SRGB8:
1062     case QOpenGLTexture::SRGB8_Alpha8:
1063     case QOpenGLTexture::SRGB_DXT1:
1064     case QOpenGLTexture::SRGB_Alpha_DXT1:
1065     case QOpenGLTexture::SRGB_Alpha_DXT3:
1066     case QOpenGLTexture::SRGB_Alpha_DXT5:
1067     case QOpenGLTexture::SRGB_BP_UNorm:
1068     case QOpenGLTexture::R11_EAC_UNorm:
1069     case QOpenGLTexture::R11_EAC_SNorm:
1070     case QOpenGLTexture::RG11_EAC_UNorm:
1071     case QOpenGLTexture::RG11_EAC_SNorm:
1072     case QOpenGLTexture::RGB8_ETC2:
1073     case QOpenGLTexture::SRGB8_ETC2:
1074     case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
1075     case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
1076     case QOpenGLTexture::RGBA8_ETC2_EAC:
1077     case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
1078     case QOpenGLTexture::RGB8_ETC1:
1079     case QOpenGLTexture::RGBA_ASTC_4x4:
1080     case QOpenGLTexture::RGBA_ASTC_5x4:
1081     case QOpenGLTexture::RGBA_ASTC_5x5:
1082     case QOpenGLTexture::RGBA_ASTC_6x5:
1083     case QOpenGLTexture::RGBA_ASTC_6x6:
1084     case QOpenGLTexture::RGBA_ASTC_8x5:
1085     case QOpenGLTexture::RGBA_ASTC_8x6:
1086     case QOpenGLTexture::RGBA_ASTC_8x8:
1087     case QOpenGLTexture::RGBA_ASTC_10x5:
1088     case QOpenGLTexture::RGBA_ASTC_10x6:
1089     case QOpenGLTexture::RGBA_ASTC_10x8:
1090     case QOpenGLTexture::RGBA_ASTC_10x10:
1091     case QOpenGLTexture::RGBA_ASTC_12x10:
1092     case QOpenGLTexture::RGBA_ASTC_12x12:
1093     case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
1094     case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
1095     case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
1096     case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
1097     case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
1098     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
1099     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
1100     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
1101     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
1102     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
1103     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
1104     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
1105     case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
1106     case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
1107         return true;
1108 
1109     case QOpenGLTexture::DepthFormat:
1110     case QOpenGLTexture::AlphaFormat:
1111     case QOpenGLTexture::RGBFormat:
1112     case QOpenGLTexture::RGBAFormat:
1113     case QOpenGLTexture::LuminanceFormat:
1114     case QOpenGLTexture::LuminanceAlphaFormat:
1115         return false;
1116     }
1117 
1118     Q_UNREACHABLE();
1119     return false;
1120 }
1121 
allocateMutableStorage(QOpenGLTexture::PixelFormat pixelFormat,QOpenGLTexture::PixelType pixelType)1122 void QOpenGLTexturePrivate::allocateMutableStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
1123 {
1124     // There is no way to allocate mutable storage for compressed textures in in
1125     // versions older than OpenGL 3.1 and OpenGL ES 3.0, because the older specs
1126     // do not mandate accepting null data pointers for glCompressedTexImage*D,
1127     // unlike glTexImage*D (which in turn does not accept compressed formats).
1128     if (isCompressedFormat(format)) {
1129         storageAllocated = true;
1130         return;
1131     }
1132 
1133     switch (target) {
1134     case QOpenGLTexture::TargetBuffer:
1135         // Buffer textures get their storage from an external OpenGL buffer
1136         qWarning("Buffer textures do not allocate storage");
1137         return;
1138 
1139     case QOpenGLTexture::Target1D:
1140         if (features.testFlag(QOpenGLTexture::Texture1D)) {
1141             for (int level = 0; level < mipLevels; ++level)
1142                 texFuncs->glTextureImage1D(textureId, target, bindingTarget, level, format,
1143                                            mipLevelSize(level, dimensions[0]),
1144                                            0,
1145                                            pixelFormat, pixelType, nullptr);
1146         } else {
1147             qWarning("1D textures are not supported");
1148             return;
1149         }
1150         break;
1151 
1152     case QOpenGLTexture::Target1DArray:
1153         if (features.testFlag(QOpenGLTexture::Texture1D)
1154                 && features.testFlag(QOpenGLTexture::TextureArrays)) {
1155             for (int level = 0; level < mipLevels; ++level)
1156                 texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format,
1157                                            mipLevelSize(level, dimensions[0]),
1158                                            layers,
1159                                            0,
1160                                            pixelFormat, pixelType, nullptr);
1161         } else {
1162             qWarning("1D array textures are not supported");
1163             return;
1164         }
1165         break;
1166 
1167     case QOpenGLTexture::Target2D:
1168     case QOpenGLTexture::TargetRectangle:
1169         for (int level = 0; level < mipLevels; ++level)
1170             texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format,
1171                                        mipLevelSize(level, dimensions[0]),
1172                                        mipLevelSize(level, dimensions[1]),
1173                                        0,
1174                                        pixelFormat, pixelType, nullptr);
1175         break;
1176 
1177     case QOpenGLTexture::TargetCubeMap: {
1178         // Cubemaps are the odd one out. We have to allocate storage for each
1179         // face and miplevel using the special cubemap face targets rather than
1180         // GL_TARGET_CUBEMAP.
1181         const QOpenGLTexture::CubeMapFace faceTargets[] = {
1182             QOpenGLTexture::CubeMapPositiveX, QOpenGLTexture::CubeMapNegativeX,
1183             QOpenGLTexture::CubeMapPositiveY, QOpenGLTexture::CubeMapNegativeY,
1184             QOpenGLTexture::CubeMapPositiveZ, QOpenGLTexture::CubeMapNegativeZ
1185         };
1186 
1187         for (int faceTarget = 0; faceTarget < 6; ++faceTarget) {
1188             for (int level = 0; level < mipLevels; ++level) {
1189                 texFuncs->glTextureImage2D(textureId, faceTargets[faceTarget], bindingTarget,
1190                                            level, format,
1191                                            mipLevelSize(level, dimensions[0]),
1192                                            mipLevelSize(level, dimensions[1]),
1193                                            0,
1194                                            pixelFormat, pixelType, nullptr);
1195             }
1196         }
1197         break;
1198     }
1199 
1200     case QOpenGLTexture::Target2DArray:
1201         if (features.testFlag(QOpenGLTexture::TextureArrays)) {
1202             for (int level = 0; level < mipLevels; ++level)
1203                 texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
1204                                            mipLevelSize(level, dimensions[0]),
1205                                            mipLevelSize(level, dimensions[1]),
1206                                            layers,
1207                                            0,
1208                                            pixelFormat, pixelType, nullptr);
1209         } else {
1210             qWarning("Array textures are not supported");
1211             return;
1212         }
1213         break;
1214 
1215     case QOpenGLTexture::TargetCubeMapArray:
1216         // Cubemap arrays must specify number of layer-faces (6 * layers) as depth parameter
1217         if (features.testFlag(QOpenGLTexture::TextureCubeMapArrays)) {
1218             for (int level = 0; level < mipLevels; ++level)
1219                 texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
1220                                            mipLevelSize(level, dimensions[0]),
1221                                            mipLevelSize(level, dimensions[1]),
1222                                            6 * layers,
1223                                            0,
1224                                            pixelFormat, pixelType, nullptr);
1225         } else {
1226             qWarning("Cubemap Array textures are not supported");
1227             return;
1228         }
1229         break;
1230 
1231     case QOpenGLTexture::Target3D:
1232         if (features.testFlag(QOpenGLTexture::Texture3D)) {
1233             for (int level = 0; level < mipLevels; ++level)
1234                 texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
1235                                            mipLevelSize(level, dimensions[0]),
1236                                            mipLevelSize(level, dimensions[1]),
1237                                            mipLevelSize(level, dimensions[2]),
1238                                            0,
1239                                            pixelFormat, pixelType, nullptr);
1240         } else {
1241             qWarning("3D textures are not supported");
1242             return;
1243         }
1244         break;
1245 
1246     case QOpenGLTexture::Target2DMultisample:
1247         if (features.testFlag(QOpenGLTexture::TextureMultisample)) {
1248             texFuncs->glTextureImage2DMultisample(textureId, target, bindingTarget, samples, format,
1249                                                   dimensions[0], dimensions[1],
1250                                                   fixedSamplePositions);
1251         } else {
1252             qWarning("Multisample textures are not supported");
1253             return;
1254         }
1255         break;
1256 
1257     case QOpenGLTexture::Target2DMultisampleArray:
1258         if (features.testFlag(QOpenGLTexture::TextureMultisample)
1259                 && features.testFlag(QOpenGLTexture::TextureArrays)) {
1260             texFuncs->glTextureImage3DMultisample(textureId, target, bindingTarget, samples, format,
1261                                                   dimensions[0], dimensions[1], layers,
1262                                                   fixedSamplePositions);
1263         } else {
1264             qWarning("Multisample array textures are not supported");
1265             return;
1266         }
1267         break;
1268     }
1269 
1270     storageAllocated = true;
1271 }
1272 
allocateImmutableStorage()1273 void QOpenGLTexturePrivate::allocateImmutableStorage()
1274 {
1275     switch (target) {
1276     case QOpenGLTexture::TargetBuffer:
1277         // Buffer textures get their storage from an external OpenGL buffer
1278         qWarning("Buffer textures do not allocate storage");
1279         return;
1280 
1281     case QOpenGLTexture::Target1D:
1282         if (features.testFlag(QOpenGLTexture::Texture1D)) {
1283             texFuncs->glTextureStorage1D(textureId, target, bindingTarget, mipLevels, format,
1284                                          dimensions[0]);
1285         } else {
1286             qWarning("1D textures are not supported");
1287             return;
1288         }
1289         break;
1290 
1291     case QOpenGLTexture::Target1DArray:
1292         if (features.testFlag(QOpenGLTexture::Texture1D)
1293                 && features.testFlag(QOpenGLTexture::TextureArrays)) {
1294             texFuncs->glTextureStorage2D(textureId, target, bindingTarget, mipLevels, format,
1295                                          dimensions[0], layers);
1296         } else {
1297             qWarning("1D array textures are not supported");
1298             return;
1299         }
1300         break;
1301 
1302     case QOpenGLTexture::Target2D:
1303     case QOpenGLTexture::TargetCubeMap:
1304     case QOpenGLTexture::TargetRectangle:
1305         texFuncs->glTextureStorage2D(textureId, target, bindingTarget, mipLevels, format,
1306                                      dimensions[0], dimensions[1]);
1307         break;
1308 
1309     case QOpenGLTexture::Target2DArray:
1310         if (features.testFlag(QOpenGLTexture::TextureArrays)) {
1311             texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
1312                                          dimensions[0], dimensions[1], layers);
1313         } else {
1314             qWarning("Array textures are not supported");
1315             return;
1316         }
1317         break;
1318 
1319     case QOpenGLTexture::TargetCubeMapArray:
1320         // Cubemap arrays must specify number of layer-faces (6 * layers) as depth parameter
1321         if (features.testFlag(QOpenGLTexture::TextureCubeMapArrays)) {
1322             texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
1323                                          dimensions[0], dimensions[1], 6 * layers);
1324         } else {
1325             qWarning("Cubemap Array textures are not supported");
1326             return;
1327         }
1328         break;
1329 
1330     case QOpenGLTexture::Target3D:
1331         if (features.testFlag(QOpenGLTexture::Texture3D)) {
1332             texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
1333                                          dimensions[0], dimensions[1], dimensions[2]);
1334         } else {
1335             qWarning("3D textures are not supported");
1336             return;
1337         }
1338         break;
1339 
1340     case QOpenGLTexture::Target2DMultisample:
1341         if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)) {
1342             texFuncs->glTextureStorage2DMultisample(textureId, target, bindingTarget, samples, format,
1343                                                     dimensions[0], dimensions[1],
1344                                                     fixedSamplePositions);
1345         } else {
1346             qWarning("Multisample textures are not supported");
1347             return;
1348         }
1349         break;
1350 
1351     case QOpenGLTexture::Target2DMultisampleArray:
1352         if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)
1353                 && features.testFlag(QOpenGLTexture::TextureArrays)) {
1354             texFuncs->glTextureStorage3DMultisample(textureId, target, bindingTarget, samples, format,
1355                                                     dimensions[0], dimensions[1], layers,
1356                                                     fixedSamplePositions);
1357         } else {
1358             qWarning("Multisample array textures are not supported");
1359             return;
1360         }
1361         break;
1362     }
1363 
1364     storageAllocated = true;
1365 }
1366 
setData(int mipLevel,int layer,int layerCount,QOpenGLTexture::CubeMapFace cubeFace,QOpenGLTexture::PixelFormat sourceFormat,QOpenGLTexture::PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)1367 void QOpenGLTexturePrivate::setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
1368                                     QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
1369                                     const void *data, const QOpenGLPixelTransferOptions * const options)
1370 {
1371     switch (target) {
1372     case QOpenGLTexture::Target1D:
1373         Q_UNUSED(layer);
1374         Q_UNUSED(cubeFace);
1375         Q_UNUSED(layerCount);
1376         texFuncs->glTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
1377                                       0, mipLevelSize( mipLevel, dimensions[0] ),
1378                                       sourceFormat, sourceType, data, options);
1379         break;
1380 
1381     case QOpenGLTexture::Target1DArray:
1382         Q_UNUSED(cubeFace);
1383         texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1384                                       0, layer,
1385                                       mipLevelSize(mipLevel, dimensions[0]),
1386                                       layerCount,
1387                                       sourceFormat, sourceType, data, options);
1388         break;
1389 
1390     case QOpenGLTexture::Target2D:
1391         Q_UNUSED(layer);
1392         Q_UNUSED(cubeFace);
1393         Q_UNUSED(layerCount);
1394         texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1395                                       0, 0,
1396                                       mipLevelSize(mipLevel, dimensions[0]),
1397                                       mipLevelSize(mipLevel, dimensions[1]),
1398                                       sourceFormat, sourceType, data, options);
1399         break;
1400 
1401     case QOpenGLTexture::Target2DArray:
1402         Q_UNUSED(cubeFace);
1403         texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1404                                       0, 0, layer,
1405                                       mipLevelSize(mipLevel, dimensions[0]),
1406                                       mipLevelSize(mipLevel, dimensions[1]),
1407                                       layerCount,
1408                                       sourceFormat, sourceType, data, options);
1409         break;
1410 
1411     case QOpenGLTexture::Target3D:
1412         Q_UNUSED(cubeFace);
1413         Q_UNUSED(layerCount);
1414         texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1415                                       0, 0, layer,
1416                                       mipLevelSize(mipLevel, dimensions[0]),
1417                                       mipLevelSize(mipLevel, dimensions[1]),
1418                                       mipLevelSize(mipLevel, dimensions[2]),
1419                                       sourceFormat, sourceType, data, options);
1420         break;
1421 
1422     case QOpenGLTexture::TargetCubeMap:
1423         Q_UNUSED(layer);
1424         Q_UNUSED(layerCount);
1425         texFuncs->glTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
1426                                       0, 0,
1427                                       mipLevelSize(mipLevel, dimensions[0]),
1428                                       mipLevelSize(mipLevel, dimensions[1]),
1429                                       sourceFormat, sourceType, data, options);
1430         break;
1431 
1432     case QOpenGLTexture::TargetCubeMapArray: {
1433         int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
1434         int layerFace = 6 * layer + faceIndex;
1435         texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1436                                       0, 0, layerFace,
1437                                       mipLevelSize(mipLevel, dimensions[0]),
1438                                       mipLevelSize(mipLevel, dimensions[1]),
1439                                       layerCount,
1440                                       sourceFormat, sourceType, data, options);
1441         break;
1442     }
1443 
1444     case QOpenGLTexture::TargetRectangle:
1445         Q_UNUSED(mipLevel);
1446         Q_UNUSED(layer);
1447         Q_UNUSED(cubeFace);
1448         Q_UNUSED(layerCount);
1449         texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, 0,
1450                                       0, 0,
1451                                       dimensions[0],
1452                                       dimensions[1],
1453                                       sourceFormat, sourceType, data, options);
1454         break;
1455 
1456     case QOpenGLTexture::Target2DMultisample:
1457     case QOpenGLTexture::Target2DMultisampleArray:
1458     case QOpenGLTexture::TargetBuffer:
1459         // We don't upload pixel data for these targets
1460         qWarning("QOpenGLTexture::setData(): Texture target does not support pixel data upload");
1461         break;
1462     }
1463 
1464     // If requested perform automatic mip map generation
1465     if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
1466         Q_Q(QOpenGLTexture);
1467         q->generateMipMaps();
1468     }
1469 }
1470 
setData(int xOffset,int yOffset,int zOffset,int width,int height,int depth,int mipLevel,int layer,int layerCount,QOpenGLTexture::CubeMapFace cubeFace,QOpenGLTexture::PixelFormat sourceFormat,QOpenGLTexture::PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)1471 void QOpenGLTexturePrivate::setData(int xOffset, int yOffset, int zOffset, int width, int height, int depth,
1472                                     int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
1473                                     QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
1474                                     const void *data, const QOpenGLPixelTransferOptions * const options)
1475 {
1476     switch (target) {
1477     case QOpenGLTexture::Target1D:
1478         Q_UNUSED(layer);
1479         Q_UNUSED(cubeFace);
1480         Q_UNUSED(layerCount);
1481         Q_UNUSED(yOffset);
1482         Q_UNUSED(zOffset);
1483         Q_UNUSED(height);
1484         Q_UNUSED(depth);
1485         texFuncs->glTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
1486                                       xOffset, width,
1487                                       sourceFormat, sourceType, data, options);
1488         break;
1489 
1490     case QOpenGLTexture::Target1DArray:
1491         Q_UNUSED(cubeFace);
1492         Q_UNUSED(yOffset);
1493         Q_UNUSED(zOffset);
1494         Q_UNUSED(height);
1495         Q_UNUSED(depth);
1496         texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1497                                       xOffset, layer,
1498                                       width,
1499                                       layerCount,
1500                                       sourceFormat, sourceType, data, options);
1501         break;
1502 
1503     case QOpenGLTexture::Target2D:
1504         Q_UNUSED(layer);
1505         Q_UNUSED(cubeFace);
1506         Q_UNUSED(layerCount);
1507         Q_UNUSED(zOffset);
1508         Q_UNUSED(depth);
1509         texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1510                                       xOffset, yOffset,
1511                                       width, height,
1512                                       sourceFormat, sourceType, data, options);
1513         break;
1514 
1515     case QOpenGLTexture::Target2DArray:
1516         Q_UNUSED(cubeFace);
1517         Q_UNUSED(zOffset);
1518         Q_UNUSED(depth);
1519         texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1520                                       xOffset, yOffset, layer,
1521                                       width, height, layerCount,
1522                                       sourceFormat, sourceType, data, options);
1523         break;
1524 
1525     case QOpenGLTexture::Target3D:
1526         Q_UNUSED(cubeFace);
1527         Q_UNUSED(layerCount);
1528         texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1529                                       xOffset, yOffset, zOffset,
1530                                       width, height, depth,
1531                                       sourceFormat, sourceType, data, options);
1532         break;
1533 
1534     case QOpenGLTexture::TargetCubeMap:
1535         Q_UNUSED(layer);
1536         Q_UNUSED(layerCount);
1537         Q_UNUSED(zOffset);
1538         Q_UNUSED(depth);
1539         texFuncs->glTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
1540                                       xOffset, yOffset,
1541                                       width, height,
1542                                       sourceFormat, sourceType, data, options);
1543         break;
1544 
1545     case QOpenGLTexture::TargetCubeMapArray: {
1546         Q_UNUSED(zOffset);
1547         Q_UNUSED(depth);
1548         int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
1549         int layerFace = 6 * layer + faceIndex;
1550         texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1551                                       xOffset, yOffset, layerFace,
1552                                       width, height,
1553                                       layerCount,
1554                                       sourceFormat, sourceType, data, options);
1555         break;
1556     }
1557 
1558     case QOpenGLTexture::TargetRectangle:
1559         Q_UNUSED(mipLevel);
1560         Q_UNUSED(layer);
1561         Q_UNUSED(cubeFace);
1562         Q_UNUSED(layerCount);
1563         Q_UNUSED(zOffset);
1564         Q_UNUSED(depth);
1565         texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, 0,
1566                                       xOffset, yOffset,
1567                                       width, height,
1568                                       sourceFormat, sourceType, data, options);
1569         break;
1570 
1571     case QOpenGLTexture::Target2DMultisample:
1572     case QOpenGLTexture::Target2DMultisampleArray:
1573     case QOpenGLTexture::TargetBuffer:
1574         // We don't upload pixel data for these targets
1575         qWarning("QOpenGLTexture::setData(): Texture target does not support pixel data upload");
1576         break;
1577     }
1578 
1579     // If requested perform automatic mip map generation
1580     if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
1581         Q_Q(QOpenGLTexture);
1582         q->generateMipMaps();
1583     }
1584 }
1585 
1586 
setCompressedData(int mipLevel,int layer,int layerCount,QOpenGLTexture::CubeMapFace cubeFace,int dataSize,const void * data,const QOpenGLPixelTransferOptions * const options)1587 void QOpenGLTexturePrivate::setCompressedData(int mipLevel, int layer, int layerCount,
1588                                               QOpenGLTexture::CubeMapFace cubeFace,
1589                                               int dataSize, const void *data,
1590                                               const QOpenGLPixelTransferOptions * const options)
1591 {
1592     if (!isCompressedFormat(format)) {
1593         qWarning("Cannot set compressed data for non-compressed format 0x%x", format);
1594         return;
1595     }
1596 
1597     const bool needsFullSpec = !isUsingImmutableStorage(); // was allocateStorage() a no-op?
1598 
1599     switch (target) {
1600     case QOpenGLTexture::Target1D:
1601         Q_UNUSED(layer);
1602         Q_UNUSED(cubeFace);
1603         Q_UNUSED(layerCount);
1604         if (needsFullSpec) {
1605             texFuncs->glCompressedTextureImage1D(textureId, target, bindingTarget, mipLevel,
1606                                                  format,
1607                                                  mipLevelSize(mipLevel, dimensions[0]),
1608                                                  0, dataSize, data, options);
1609         } else {
1610             texFuncs->glCompressedTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
1611                                                     0, mipLevelSize( mipLevel, dimensions[0] ),
1612                                                     format, dataSize, data, options);
1613         }
1614         break;
1615 
1616     case QOpenGLTexture::Target1DArray:
1617         Q_UNUSED(cubeFace);
1618         if (!needsFullSpec) {
1619             texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1620                                                     0, layer,
1621                                                     mipLevelSize(mipLevel, dimensions[0]),
1622                                                     layerCount,
1623                                                     format, dataSize, data, options);
1624         }
1625         break;
1626 
1627     case QOpenGLTexture::Target2D:
1628         Q_UNUSED(layer);
1629         Q_UNUSED(cubeFace);
1630         Q_UNUSED(layerCount);
1631         if (needsFullSpec) {
1632             texFuncs->glCompressedTextureImage2D(textureId, target, bindingTarget, mipLevel,
1633                                                  format,
1634                                                  mipLevelSize(mipLevel, dimensions[0]),
1635                                                  mipLevelSize(mipLevel, dimensions[1]),
1636                                                  0, dataSize, data, options);
1637         } else {
1638             texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1639                                                     0, 0,
1640                                                     mipLevelSize(mipLevel, dimensions[0]),
1641                                                     mipLevelSize(mipLevel, dimensions[1]),
1642                                                     format, dataSize, data, options);
1643         }
1644         break;
1645 
1646     case QOpenGLTexture::Target2DArray:
1647         Q_UNUSED(cubeFace);
1648         if (!needsFullSpec) {
1649             texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1650                                                     0, 0, layer,
1651                                                     mipLevelSize(mipLevel, dimensions[0]),
1652                                                     mipLevelSize(mipLevel, dimensions[1]),
1653                                                     layerCount,
1654                                                     format, dataSize, data, options);
1655         }
1656         break;
1657 
1658     case QOpenGLTexture::Target3D:
1659         Q_UNUSED(cubeFace);
1660         Q_UNUSED(layerCount);
1661         if (needsFullSpec) {
1662             texFuncs->glCompressedTextureImage3D(textureId, target, bindingTarget, mipLevel,
1663                                                  format,
1664                                                  mipLevelSize(mipLevel, dimensions[0]),
1665                                                  mipLevelSize(mipLevel, dimensions[1]),
1666                                                  mipLevelSize(mipLevel, dimensions[2]),
1667                                                  0, dataSize, data, options);
1668         } else {
1669             texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1670                                                     0, 0, layer,
1671                                                     mipLevelSize(mipLevel, dimensions[0]),
1672                                                     mipLevelSize(mipLevel, dimensions[1]),
1673                                                     mipLevelSize(mipLevel, dimensions[2]),
1674                                                     format, dataSize, data, options);
1675         }
1676         break;
1677 
1678     case QOpenGLTexture::TargetCubeMap:
1679         Q_UNUSED(layer);
1680         Q_UNUSED(layerCount);
1681         if (needsFullSpec) {
1682             texFuncs->glCompressedTextureImage2D(textureId, cubeFace, bindingTarget, mipLevel,
1683                                                  format,
1684                                                  mipLevelSize(mipLevel, dimensions[0]),
1685                                                  mipLevelSize(mipLevel, dimensions[1]),
1686                                                  0, dataSize, data, options);
1687         } else {
1688             texFuncs->glCompressedTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
1689                                                     0, 0,
1690                                                     mipLevelSize(mipLevel, dimensions[0]),
1691                                                     mipLevelSize(mipLevel, dimensions[1]),
1692                                                     format, dataSize, data, options);
1693         }
1694         break;
1695 
1696     case QOpenGLTexture::TargetCubeMapArray: {
1697         int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
1698         int layerFace = 6 * layer + faceIndex;
1699         if (!needsFullSpec) {
1700             texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1701                                                     0, 0, layerFace,
1702                                                     mipLevelSize(mipLevel, dimensions[0]),
1703                                                     mipLevelSize(mipLevel, dimensions[1]),
1704                                                     layerCount,
1705                                                     format, dataSize, data, options);
1706         }
1707         break;
1708     }
1709 
1710     case QOpenGLTexture::TargetRectangle:
1711     case QOpenGLTexture::Target2DMultisample:
1712     case QOpenGLTexture::Target2DMultisampleArray:
1713     case QOpenGLTexture::TargetBuffer:
1714         // We don't upload pixel data for these targets
1715         qWarning("QOpenGLTexture::setCompressedData(): Texture target does not support pixel data upload");
1716         break;
1717     }
1718 
1719     // If requested perform automatic mip map generation
1720     if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
1721         Q_Q(QOpenGLTexture);
1722         q->generateMipMaps();
1723     }
1724 }
1725 
setWrapMode(QOpenGLTexture::WrapMode mode)1726 void QOpenGLTexturePrivate::setWrapMode(QOpenGLTexture::WrapMode mode)
1727 {
1728     switch (target) {
1729     case QOpenGLTexture::Target1D:
1730     case QOpenGLTexture::Target1DArray:
1731     case QOpenGLTexture::TargetBuffer:
1732         wrapModes[0] = mode;
1733         texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
1734         break;
1735 
1736     case QOpenGLTexture::Target2D:
1737     case QOpenGLTexture::Target2DArray:
1738     case QOpenGLTexture::TargetCubeMap:
1739     case QOpenGLTexture::TargetCubeMapArray:
1740     case QOpenGLTexture::Target2DMultisample:
1741     case QOpenGLTexture::Target2DMultisampleArray:
1742     case QOpenGLTexture::TargetRectangle:
1743         wrapModes[0] = wrapModes[1] = mode;
1744         texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
1745         texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
1746         break;
1747 
1748     case QOpenGLTexture::Target3D:
1749         wrapModes[0] = wrapModes[1] = wrapModes[2] = mode;
1750         texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
1751         texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
1752         texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_R, mode);
1753         break;
1754     }
1755 }
1756 
setWrapMode(QOpenGLTexture::CoordinateDirection direction,QOpenGLTexture::WrapMode mode)1757 void QOpenGLTexturePrivate::setWrapMode(QOpenGLTexture::CoordinateDirection direction, QOpenGLTexture::WrapMode mode)
1758 {
1759     switch (target) {
1760     case QOpenGLTexture::Target1D:
1761     case QOpenGLTexture::Target1DArray:
1762     case QOpenGLTexture::TargetBuffer:
1763         switch (direction) {
1764         case QOpenGLTexture::DirectionS:
1765             wrapModes[0] = mode;
1766             texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
1767             break;
1768 
1769         case QOpenGLTexture::DirectionT:
1770         case QOpenGLTexture::DirectionR:
1771             qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target");
1772             break;
1773         }
1774         break;
1775 
1776     case QOpenGLTexture::Target2D:
1777     case QOpenGLTexture::Target2DArray:
1778     case QOpenGLTexture::TargetCubeMap:
1779     case QOpenGLTexture::TargetCubeMapArray:
1780     case QOpenGLTexture::Target2DMultisample:
1781     case QOpenGLTexture::Target2DMultisampleArray:
1782     case QOpenGLTexture::TargetRectangle:
1783         switch (direction) {
1784         case QOpenGLTexture::DirectionS:
1785             wrapModes[0] = mode;
1786             texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
1787             break;
1788 
1789         case QOpenGLTexture::DirectionT:
1790             wrapModes[1] = mode;
1791             texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
1792             break;
1793 
1794         case QOpenGLTexture::DirectionR:
1795             qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target");
1796             break;
1797         }
1798         break;
1799 
1800     case QOpenGLTexture::Target3D:
1801         switch (direction) {
1802         case QOpenGLTexture::DirectionS:
1803             wrapModes[0] = mode;
1804             texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
1805             break;
1806 
1807         case QOpenGLTexture::DirectionT:
1808             wrapModes[1] = mode;
1809             texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
1810             break;
1811 
1812         case QOpenGLTexture::DirectionR:
1813             wrapModes[2] = mode;
1814             texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
1815             break;
1816         }
1817         break;
1818     }
1819 }
1820 
wrapMode(QOpenGLTexture::CoordinateDirection direction) const1821 QOpenGLTexture::WrapMode QOpenGLTexturePrivate::wrapMode(QOpenGLTexture::CoordinateDirection direction) const
1822 {
1823     switch (target) {
1824     case QOpenGLTexture::Target1D:
1825     case QOpenGLTexture::Target1DArray:
1826     case QOpenGLTexture::TargetBuffer:
1827         switch (direction) {
1828         case QOpenGLTexture::DirectionS:
1829             return wrapModes[0];
1830 
1831         case QOpenGLTexture::DirectionT:
1832         case QOpenGLTexture::DirectionR:
1833             qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target");
1834             return QOpenGLTexture::Repeat;
1835         }
1836         break;
1837 
1838     case QOpenGLTexture::Target2D:
1839     case QOpenGLTexture::Target2DArray:
1840     case QOpenGLTexture::TargetCubeMap:
1841     case QOpenGLTexture::TargetCubeMapArray:
1842     case QOpenGLTexture::Target2DMultisample:
1843     case QOpenGLTexture::Target2DMultisampleArray:
1844     case QOpenGLTexture::TargetRectangle:
1845         switch (direction) {
1846         case QOpenGLTexture::DirectionS:
1847             return wrapModes[0];
1848 
1849         case QOpenGLTexture::DirectionT:
1850             return wrapModes[1];
1851 
1852         case QOpenGLTexture::DirectionR:
1853             qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target");
1854             return QOpenGLTexture::Repeat;
1855         }
1856         break;
1857 
1858     case QOpenGLTexture::Target3D:
1859         switch (direction) {
1860         case QOpenGLTexture::DirectionS:
1861             return wrapModes[0];
1862 
1863         case QOpenGLTexture::DirectionT:
1864             return wrapModes[1];
1865 
1866         case QOpenGLTexture::DirectionR:
1867             return wrapModes[2];
1868         }
1869         break;
1870     }
1871     // Should never get here
1872     Q_ASSERT(false);
1873     return QOpenGLTexture::Repeat;
1874 }
1875 
createTextureView(QOpenGLTexture::Target viewTarget,QOpenGLTexture::TextureFormat viewFormat,int minimumMipmapLevel,int maximumMipmapLevel,int minimumLayer,int maximumLayer) const1876 QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target viewTarget,
1877                                                          QOpenGLTexture::TextureFormat viewFormat,
1878                                                          int minimumMipmapLevel, int maximumMipmapLevel,
1879                                                          int minimumLayer, int maximumLayer) const
1880 {
1881     // Do sanity checks - see http://www.opengl.org/wiki/GLAPI/glTextureView
1882 
1883     // Check the targets are compatible
1884     bool viewTargetCompatible = false;
1885     switch (target) {
1886     case QOpenGLTexture::Target1D:
1887     case QOpenGLTexture::Target1DArray:
1888         viewTargetCompatible = (viewTarget == QOpenGLTexture::Target1D
1889                              || viewTarget == QOpenGLTexture::Target1DArray);
1890         break;
1891 
1892 
1893     case QOpenGLTexture::Target2D:
1894     case QOpenGLTexture::Target2DArray:
1895         viewTargetCompatible = (viewTarget == QOpenGLTexture::Target2D
1896                              || viewTarget == QOpenGLTexture::Target2DArray);
1897         break;
1898 
1899     case QOpenGLTexture::Target3D:
1900         viewTargetCompatible = (viewTarget == QOpenGLTexture::Target3D);
1901         break;
1902 
1903     case QOpenGLTexture::TargetCubeMap:
1904     case QOpenGLTexture::TargetCubeMapArray:
1905         viewTargetCompatible = (viewTarget == QOpenGLTexture::TargetCubeMap
1906                              || viewTarget == QOpenGLTexture::Target2D
1907                              || viewTarget == QOpenGLTexture::Target2DArray
1908                              || viewTarget == QOpenGLTexture::TargetCubeMapArray);
1909         break;
1910 
1911     case QOpenGLTexture::Target2DMultisample:
1912     case QOpenGLTexture::Target2DMultisampleArray:
1913         viewTargetCompatible = (viewTarget == QOpenGLTexture::Target2DMultisample
1914                              || viewTarget == QOpenGLTexture::Target2DMultisampleArray);
1915         break;
1916 
1917     case QOpenGLTexture::TargetRectangle:
1918         viewTargetCompatible = (viewTarget == QOpenGLTexture::TargetRectangle);
1919         break;
1920 
1921     case QOpenGLTexture::TargetBuffer:
1922         // Cannot be used with texture views
1923         break;
1924     }
1925 
1926     if (!viewTargetCompatible) {
1927         qWarning("QOpenGLTexture::createTextureView(): Incompatible source and view targets");
1928         return nullptr;
1929     }
1930 
1931     // Check the formats are compatible
1932     bool viewFormatCompatible = false;
1933     switch (formatClass) {
1934     case QOpenGLTexture::NoFormatClass:
1935         break;
1936 
1937     case QOpenGLTexture::FormatClass_128Bit:
1938         viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA32F
1939                              || viewFormat == QOpenGLTexture::RGBA32U
1940                              || viewFormat == QOpenGLTexture::RGBA32I);
1941         break;
1942 
1943     case QOpenGLTexture::FormatClass_96Bit:
1944         viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB32F
1945                              || viewFormat == QOpenGLTexture::RGB32U
1946                              || viewFormat == QOpenGLTexture::RGB32I);
1947         break;
1948 
1949     case QOpenGLTexture::FormatClass_64Bit:
1950         viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA16F
1951                              || viewFormat == QOpenGLTexture::RG32F
1952                              || viewFormat == QOpenGLTexture::RGBA16U
1953                              || viewFormat == QOpenGLTexture::RG32U
1954                              || viewFormat == QOpenGLTexture::RGBA16I
1955                              || viewFormat == QOpenGLTexture::RG32I
1956                              || viewFormat == QOpenGLTexture::RGBA16_UNorm
1957                              || viewFormat == QOpenGLTexture::RGBA16_SNorm);
1958         break;
1959 
1960     case QOpenGLTexture::FormatClass_48Bit:
1961         viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB16_UNorm
1962                              || viewFormat == QOpenGLTexture::RGB16_SNorm
1963                              || viewFormat == QOpenGLTexture::RGB16F
1964                              || viewFormat == QOpenGLTexture::RGB16U
1965                              || viewFormat == QOpenGLTexture::RGB16I);
1966         break;
1967 
1968     case QOpenGLTexture::FormatClass_32Bit:
1969         viewFormatCompatible = (viewFormat == QOpenGLTexture::RG16F
1970                              || viewFormat == QOpenGLTexture::RG11B10F
1971                              || viewFormat == QOpenGLTexture::R32F
1972                              || viewFormat == QOpenGLTexture::RGB10A2
1973                              || viewFormat == QOpenGLTexture::RGBA8U
1974                              || viewFormat == QOpenGLTexture::RG16U
1975                              || viewFormat == QOpenGLTexture::R32U
1976                              || viewFormat == QOpenGLTexture::RGBA8I
1977                              || viewFormat == QOpenGLTexture::RG16I
1978                              || viewFormat == QOpenGLTexture::R32I
1979                              || viewFormat == QOpenGLTexture::RGBA8_UNorm
1980                              || viewFormat == QOpenGLTexture::RG16_UNorm
1981                              || viewFormat == QOpenGLTexture::RGBA8_SNorm
1982                              || viewFormat == QOpenGLTexture::RG16_SNorm
1983                              || viewFormat == QOpenGLTexture::SRGB8_Alpha8
1984                              || viewFormat == QOpenGLTexture::RGB9E5);
1985         break;
1986 
1987     case QOpenGLTexture::FormatClass_24Bit:
1988         viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB8_UNorm
1989                              || viewFormat == QOpenGLTexture::RGB8_SNorm
1990                              || viewFormat == QOpenGLTexture::SRGB8
1991                              || viewFormat == QOpenGLTexture::RGB8U
1992                              || viewFormat == QOpenGLTexture::RGB8I);
1993         break;
1994 
1995     case QOpenGLTexture::FormatClass_16Bit:
1996         viewFormatCompatible = (viewFormat == QOpenGLTexture::R16F
1997                              || viewFormat == QOpenGLTexture::RG8U
1998                              || viewFormat == QOpenGLTexture::R16U
1999                              || viewFormat == QOpenGLTexture::RG8I
2000                              || viewFormat == QOpenGLTexture::R16I
2001                              || viewFormat == QOpenGLTexture::RG8_UNorm
2002                              || viewFormat == QOpenGLTexture::R16_UNorm
2003                              || viewFormat == QOpenGLTexture::RG8_SNorm
2004                              || viewFormat == QOpenGLTexture::R16_SNorm);
2005         break;
2006 
2007     case QOpenGLTexture::FormatClass_8Bit:
2008         viewFormatCompatible = (viewFormat == QOpenGLTexture::R8U
2009                              || viewFormat == QOpenGLTexture::R8I
2010                              || viewFormat == QOpenGLTexture::R8_UNorm
2011                              || viewFormat == QOpenGLTexture::R8_SNorm);
2012         break;
2013 
2014     case QOpenGLTexture::FormatClass_RGTC1_R:
2015         viewFormatCompatible = (viewFormat == QOpenGLTexture::R_ATI1N_UNorm
2016                              || viewFormat == QOpenGLTexture::R_ATI1N_SNorm);
2017         break;
2018 
2019     case QOpenGLTexture::FormatClass_RGTC2_RG:
2020         viewFormatCompatible = (viewFormat == QOpenGLTexture::RG_ATI2N_UNorm
2021                              || viewFormat == QOpenGLTexture::RG_ATI2N_SNorm);
2022         break;
2023 
2024     case QOpenGLTexture::FormatClass_BPTC_Unorm:
2025         viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_BP_UNorm
2026                              || viewFormat == QOpenGLTexture::SRGB_BP_UNorm);
2027         break;
2028 
2029     case QOpenGLTexture::FormatClass_BPTC_Float:
2030         viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT
2031                              || viewFormat == QOpenGLTexture::RGB_BP_SIGNED_FLOAT);
2032         break;
2033 
2034     case QOpenGLTexture::FormatClass_S3TC_DXT1_RGB:
2035         viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_DXT1
2036                              || viewFormat == QOpenGLTexture::SRGB_DXT1);
2037         break;
2038 
2039     case QOpenGLTexture::FormatClass_S3TC_DXT1_RGBA:
2040         viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT1
2041                              || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT1);
2042         break;
2043 
2044     case QOpenGLTexture::FormatClass_S3TC_DXT3_RGBA:
2045         viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT3
2046                              || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT3);
2047         break;
2048 
2049     case QOpenGLTexture::FormatClass_S3TC_DXT5_RGBA:
2050         viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT5
2051                              || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT5);
2052         break;
2053 
2054     case QOpenGLTexture::FormatClass_Unique:
2055         viewFormatCompatible = (viewFormat == format);
2056         break;
2057     }
2058 
2059     if (!viewFormatCompatible) {
2060         qWarning("QOpenGLTexture::createTextureView(): Incompatible source and view formats");
2061         return nullptr;
2062     }
2063 
2064 
2065     // Create a view
2066     QOpenGLTexture *view = new QOpenGLTexture(viewTarget);
2067     view->setFormat(viewFormat);
2068     view->create();
2069     view->d_ptr->textureView = true;
2070     texFuncs->glTextureView(view->textureId(), viewTarget, textureId, viewFormat,
2071                             minimumMipmapLevel, maximumMipmapLevel - minimumMipmapLevel + 1,
2072                             minimumLayer, maximumLayer - minimumLayer + 1);
2073     return view;
2074 }
2075 
2076 
2077 /*!
2078     \class QOpenGLTexture
2079     \inmodule QtGui
2080     \since 5.2
2081     \wrapper
2082     \brief The QOpenGLTexture class encapsulates an OpenGL texture object.
2083 
2084     QOpenGLTexture makes it easy to work with OpenGL textures and the myriad features
2085     and targets that they offer depending upon the capabilities of your OpenGL implementation.
2086 
2087     The typical usage pattern for QOpenGLTexture is
2088     \list
2089         \li Instantiate the object specifying the texture target type
2090         \li Set properties that affect the storage requirements e.g. storage format, dimensions
2091         \li Allocate the server-side storage
2092         \li Optionally upload pixel data
2093         \li Optionally set any additional properties e.g. filtering and border options
2094         \li Render with texture or render to texture
2095     \endlist
2096 
2097     In the common case of simply using a QImage as the source of texture pixel data
2098     most of the above steps are performed automatically.
2099 
2100     \code
2101     // Prepare texture
2102     QOpenGLTexture *texture = new QOpenGLTexture(QImage(fileName).mirrored());
2103     texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
2104     texture->setMagnificationFilter(QOpenGLTexture::Linear);
2105     ...
2106     // Render with texture
2107     texture->bind();
2108     glDrawArrays(...);
2109     \endcode
2110 
2111     Note that the QImage is mirrored vertically to account for the fact that
2112     OpenGL and QImage use opposite directions for the y axis. Another option
2113     would be to transform your texture coordinates.
2114 */
2115 
2116 /*!
2117     \enum QOpenGLTexture::Filter
2118     This enum defines the filtering parameters for a QOpenGLTexture object.
2119     \value Nearest Equivalent to GL_NEAREST
2120     \value Linear Equivalent to GL_LINEAR
2121     \value NearestMipMapNearest Equivalent to GL_NEAREST_MIPMAP_NEAREST
2122     \value NearestMipMapLinear Equivalent to GL_NEAREST_MIPMAP_LINEAR
2123     \value LinearMipMapNearest Equivalent to GL_LINEAR_MIPMAP_NEAREST
2124     \value LinearMipMapLinear Equivalent to GL_LINEAR_MIPMAP_LINEAR
2125 */
2126 
2127 /*!
2128     \enum QOpenGLTexture::Target
2129     This enum defines the texture target of a QOpenGLTexture object.
2130     For more information on creating array textures, see \l{Array Texture}.
2131 
2132     \value Target1D A 1-dimensional texture.
2133            Equivalent to GL_TEXTURE_1D.
2134     \value Target1DArray An array of 1-dimensional textures.
2135            Equivalent to GL_TEXTURE_1D_ARRAY
2136     \value Target2D A 2-dimensional texture.
2137            Equivalent to GL_TEXTURE_2D
2138     \value Target2DArray An array of 2-dimensional textures.
2139            Equivalent to GL_TEXTURE_2D_ARRAY
2140     \value Target3D A 3-dimensional texture.
2141            Equivalent to GL_TEXTURE_3D
2142     \value TargetCubeMap A cubemap texture.
2143            Equivalent to GL_TEXTURE_CUBE_MAP
2144     \value TargetCubeMapArray An array of cubemap textures.
2145            Equivalent to GL_TEXTURE_CUBE_MAP_ARRAY
2146     \value Target2DMultisample A 2-dimensional texture with multisample support.
2147            Equivalent to GL_TEXTURE_2D_MULTISAMPLE
2148     \value Target2DMultisampleArray An array of 2-dimensional textures with multisample support.
2149            Equivalent to GL_TEXTURE_2D_MULTISAMPLE_ARRAY
2150     \value TargetRectangle A rectangular 2-dimensional texture.
2151            Equivalent to GL_TEXTURE_RECTANGLE
2152     \value TargetBuffer A texture with data from an OpenGL buffer object.
2153            Equivalent to GL_TEXTURE_BUFFER
2154 */
2155 
2156 /*!
2157     \enum QOpenGLTexture::BindingTarget
2158     This enum defines the possible binding targets of texture units.
2159 
2160     \value BindingTarget1D Equivalent to GL_TEXTURE_BINDING_1D
2161     \value BindingTarget1DArray Equivalent to GL_TEXTURE_BINDING_1D_ARRAY
2162     \value BindingTarget2D Equivalent to GL_TEXTURE_BINDING_2D
2163     \value BindingTarget2DArray Equivalent to GL_TEXTURE_BINDING_2D_ARRAY
2164     \value BindingTarget3D Equivalent to GL_TEXTURE_BINDING_3D
2165     \value BindingTargetCubeMap Equivalent to GL_TEXTURE_BINDING_CUBE_MAP
2166     \value BindingTargetCubeMapArray Equivalent to GL_TEXTURE_BINDING_CUBE_MAP_ARRAY
2167     \value BindingTarget2DMultisample Equivalent to GL_TEXTURE_BINDING_2D_MULTISAMPLE
2168     \value BindingTarget2DMultisampleArray Equivalent to GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY
2169     \value BindingTargetRectangle Equivalent to GL_TEXTURE_BINDING_RECTANGLE
2170     \value BindingTargetBuffer Equivalent to GL_TEXTURE_BINDING_BUFFER
2171 */
2172 
2173 /*!
2174     \enum QOpenGLTexture::MipMapGeneration
2175     This enum defines the options to control mipmap generation.
2176 
2177     \value GenerateMipMaps Mipmaps should be generated
2178     \value DontGenerateMipMaps Mipmaps should not be generated
2179 */
2180 
2181 /*!
2182     \enum QOpenGLTexture::TextureUnitReset
2183     This enum defines options ot control texture unit activation.
2184 
2185     \value ResetTextureUnit The previous active texture unit will be reset
2186     \value DontResetTextureUnit The previous active texture unit will not be rest
2187 */
2188 
2189 /*!
2190     \enum QOpenGLTexture::TextureFormat
2191     This enum defines the possible texture formats. Depending upon your OpenGL
2192     implementation only a subset of these may be supported.
2193 
2194     \value NoFormat Equivalent to GL_NONE
2195 
2196     \value R8_UNorm Equivalent to GL_R8
2197     \value RG8_UNorm Equivalent to GL_RG8
2198     \value RGB8_UNorm Equivalent to GL_RGB8
2199     \value RGBA8_UNorm Equivalent to GL_RGBA8
2200 
2201     \value R16_UNorm Equivalent to GL_R16
2202     \value RG16_UNorm Equivalent to GL_RG16
2203     \value RGB16_UNorm Equivalent to GL_RGB16
2204     \value RGBA16_UNorm Equivalent to GL_RGBA16
2205 
2206     \value R8_SNorm Equivalent to GL_R8_SNORM
2207     \value RG8_SNorm Equivalent to GL_RG8_SNORM
2208     \value RGB8_SNorm Equivalent to GL_RGB8_SNORM
2209     \value RGBA8_SNorm Equivalent to GL_RGBA8_SNORM
2210 
2211     \value R16_SNorm Equivalent to GL_R16_SNORM
2212     \value RG16_SNorm Equivalent to GL_RG16_SNORM
2213     \value RGB16_SNorm Equivalent to GL_RGB16_SNORM
2214     \value RGBA16_SNorm Equivalent to GL_RGBA16_SNORM
2215 
2216     \value R8U Equivalent to GL_R8UI
2217     \value RG8U Equivalent to GL_RG8UI
2218     \value RGB8U Equivalent to GL_RGB8UI
2219     \value RGBA8U Equivalent to GL_RGBA8UI
2220 
2221     \value R16U Equivalent to GL_R16UI
2222     \value RG16U Equivalent to GL_RG16UI
2223     \value RGB16U Equivalent to GL_RGB16UI
2224     \value RGBA16U Equivalent to GL_RGBA16UI
2225 
2226     \value R32U Equivalent to GL_R32UI
2227     \value RG32U Equivalent to GL_RG32UI
2228     \value RGB32U Equivalent to GL_RGB32UI
2229     \value RGBA32U Equivalent to GL_RGBA32UI
2230 
2231     \value R8I Equivalent to GL_R8I
2232     \value RG8I Equivalent to GL_RG8I
2233     \value RGB8I Equivalent to GL_RGB8I
2234     \value RGBA8I Equivalent to GL_RGBA8I
2235 
2236     \value R16I Equivalent to GL_R16I
2237     \value RG16I Equivalent to GL_RG16I
2238     \value RGB16I Equivalent to GL_RGB16I
2239     \value RGBA16I Equivalent to GL_RGBA16I
2240 
2241     \value R32I Equivalent to GL_R32I
2242     \value RG32I Equivalent to GL_RG32I
2243     \value RGB32I Equivalent to GL_RGB32I
2244     \value RGBA32I Equivalent to GL_RGBA32I
2245 
2246     \value R16F Equivalent to GL_R16F
2247     \value RG16F Equivalent to GL_RG16F
2248     \value RGB16F Equivalent to GL_RGB16F
2249     \value RGBA16F Equivalent to GL_RGBA16F
2250 
2251     \value R32F Equivalent to GL_R32F
2252     \value RG32F Equivalent to GL_RG32F
2253     \value RGB32F Equivalent to GL_RGB32F
2254     \value RGBA32F Equivalent to GL_RGBA32F
2255 
2256     \value RGB9E5 Equivalent to GL_RGB9_E5
2257     \value RG11B10F Equivalent to GL_R11F_G11F_B10F
2258     \value RG3B2 Equivalent to GL_R3_G3_B2
2259     \value R5G6B5 Equivalent to GL_RGB565
2260     \value RGB5A1 Equivalent to GL_RGB5_A1
2261     \value RGBA4 Equivalent to GL_RGBA4
2262     \value RGB10A2 Equivalent to GL_RGB10_A2UI
2263 
2264     \value D16 Equivalent to GL_DEPTH_COMPONENT16
2265     \value D24 Equivalent to GL_DEPTH_COMPONENT24
2266     \value D24S8 Equivalent to GL_DEPTH24_STENCIL8
2267     \value D32 Equivalent to GL_DEPTH_COMPONENT32
2268     \value D32F Equivalent to GL_DEPTH_COMPONENT32F
2269     \value D32FS8X24 Equivalent to GL_DEPTH32F_STENCIL8
2270     \value S8 Equivalent to GL_STENCIL_INDEX8. Introduced in Qt 5.4
2271 
2272     \value RGB_DXT1 Equivalent to GL_COMPRESSED_RGB_S3TC_DXT1_EXT
2273     \value RGBA_DXT1 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2274     \value RGBA_DXT3 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2275     \value RGBA_DXT5 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
2276     \value R_ATI1N_UNorm Equivalent to GL_COMPRESSED_RED_RGTC1
2277     \value R_ATI1N_SNorm Equivalent to GL_COMPRESSED_SIGNED_RED_RGTC1
2278     \value RG_ATI2N_UNorm Equivalent to GL_COMPRESSED_RG_RGTC2
2279     \value RG_ATI2N_SNorm Equivalent to GL_COMPRESSED_SIGNED_RG_RGTC2
2280     \value RGB_BP_UNSIGNED_FLOAT Equivalent to GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB
2281     \value RGB_BP_SIGNED_FLOAT Equivalent to GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB
2282     \value RGB_BP_UNorm Equivalent to GL_COMPRESSED_RGBA_BPTC_UNORM_ARB
2283     \value R11_EAC_UNorm Equivalent to GL_COMPRESSED_R11_EAC
2284     \value R11_EAC_SNorm Equivalent to GL_COMPRESSED_SIGNED_R11_EAC
2285     \value RG11_EAC_UNorm Equivalent to GL_COMPRESSED_RG11_EAC
2286     \value RG11_EAC_SNorm Equivalent to GL_COMPRESSED_SIGNED_RG11_EAC
2287     \value RGB8_ETC2 Equivalent to GL_COMPRESSED_RGB8_ETC2
2288     \value SRGB8_ETC2 Equivalent to GL_COMPRESSED_SRGB8_ETC2
2289     \value RGB8_PunchThrough_Alpha1_ETC2 Equivalent to GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
2290     \value SRGB8_PunchThrough_Alpha1_ETC2 Equivalent to GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
2291     \value RGBA8_ETC2_EAC Equivalent to GL_COMPRESSED_RGBA8_ETC2_EAC
2292     \value SRGB8_Alpha8_ETC2_EAC Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
2293     \value RGB8_ETC1 Equivalent to GL_ETC1_RGB8_OES
2294     \value RGBA_ASTC_4x4 Equivalent to GL_COMPRESSED_RGBA_ASTC_4x4_KHR
2295     \value RGBA_ASTC_5x4 Equivalent to GL_COMPRESSED_RGBA_ASTC_5x4_KHR
2296     \value RGBA_ASTC_5x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_5x5_KHR
2297     \value RGBA_ASTC_6x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_6x5_KHR
2298     \value RGBA_ASTC_6x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_6x6_KHR
2299     \value RGBA_ASTC_8x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x5_KHR
2300     \value RGBA_ASTC_8x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x6_KHR
2301     \value RGBA_ASTC_8x8 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x8_KHR
2302     \value RGBA_ASTC_10x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x5_KHR
2303     \value RGBA_ASTC_10x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x6_KHR
2304     \value RGBA_ASTC_10x8 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x8_KHR
2305     \value RGBA_ASTC_10x10 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x10_KHR
2306     \value RGBA_ASTC_12x10 Equivalent to GL_COMPRESSED_RGBA_ASTC_12x10_KHR
2307     \value RGBA_ASTC_12x12 Equivalent to GL_COMPRESSED_RGBA_ASTC_12x12_KHR
2308     \value SRGB8_Alpha8_ASTC_4x4 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
2309     \value SRGB8_Alpha8_ASTC_5x4 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
2310     \value SRGB8_Alpha8_ASTC_5x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
2311     \value SRGB8_Alpha8_ASTC_6x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
2312     \value SRGB8_Alpha8_ASTC_6x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
2313     \value SRGB8_Alpha8_ASTC_8x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
2314     \value SRGB8_Alpha8_ASTC_8x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
2315     \value SRGB8_Alpha8_ASTC_8x8 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
2316     \value SRGB8_Alpha8_ASTC_10x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
2317     \value SRGB8_Alpha8_ASTC_10x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
2318     \value SRGB8_Alpha8_ASTC_10x8 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
2319     \value SRGB8_Alpha8_ASTC_10x10 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
2320     \value SRGB8_Alpha8_ASTC_12x10 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
2321     \value SRGB8_Alpha8_ASTC_12x12 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
2322 
2323     \value SRGB8 Equivalent to GL_SRGB8
2324     \value SRGB8_Alpha8 Equivalent to GL_SRGB8_ALPHA8
2325     \value SRGB_DXT1 Equivalent to GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
2326     \value SRGB_Alpha_DXT1 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
2327     \value SRGB_Alpha_DXT3 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
2328     \value SRGB_Alpha_DXT5 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
2329     \value SRGB_BP_UNorm Equivalent to GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB
2330 
2331     \value DepthFormat Equivalent to GL_DEPTH_COMPONENT (only OpenGL ES 3 or ES 2 with OES_depth_texture)
2332     \value AlphaFormat Equivalent to GL_ALPHA (OpenGL ES 2 only)
2333     \value RGBFormat Equivalent to GL_RGB (OpenGL ES 2 only)
2334     \value RGBAFormat Equivalent to GL_RGBA (OpenGL ES 2 only)
2335     \value LuminanceFormat Equivalent to GL_LUMINANCE (OpenGL ES 2 only)
2336     \value LuminanceAlphaFormat Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only)
2337 */
2338 
2339 /*!
2340     \enum QOpenGLTexture::CubeMapFace
2341     This enum defines the possible CubeMap faces.
2342 
2343     \value CubeMapPositiveX Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_X
2344     \value CubeMapNegativeX Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_X
2345     \value CubeMapPositiveY Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_Y
2346     \value CubeMapNegativeY Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
2347     \value CubeMapPositiveZ Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_Z
2348     \value CubeMapNegativeZ Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
2349 */
2350 
2351 /*!
2352     \enum QOpenGLTexture::PixelFormat
2353     This enum defines the possible client-side pixel formats for a pixel
2354     transfer operation.
2355 
2356     \value NoSourceFormat Equivalent to GL_NONE
2357     \value Red Equivalent to GL_RED
2358     \value RG Equivalent to GL_RG
2359     \value RGB Equivalent to GL_RGB
2360     \value BGR Equivalent to GL_BGR
2361     \value RGBA Equivalent to GL_RGBA
2362     \value BGRA Equivalent to GL_BGRA
2363     \value Red_Integer Equivalent to GL_RED_INTEGER
2364     \value RG_Integer Equivalent to GL_RG_INTEGER
2365     \value RGB_Integer Equivalent to GL_RGB_INTEGER
2366     \value BGR_Integer Equivalent to GL_BGR_INTEGER
2367     \value RGBA_Integer Equivalent to GL_RGBA_INTEGER
2368     \value BGRA_Integer Equivalent to GL_BGRA_INTEGER
2369     \value Stencil Equivalent to GL_STENCIL_INDEX. Introduced in Qt 5.4
2370     \value Depth Equivalent to GL_DEPTH_COMPONENT
2371     \value DepthStencil Equivalent to GL_DEPTH_STENCIL
2372     \value Alpha Equivalent to GL_ALPHA (OpenGL ES 2 only)
2373     \value Luminance Equivalent to GL_LUMINANCE (OpenGL ES 2 only)
2374     \value LuminanceAlpha Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only)
2375 
2376 */
2377 
2378 /*!
2379     \enum QOpenGLTexture::PixelType
2380     This enum defines the possible pixel data types for a pixel transfer operation
2381 
2382     \value NoPixelType Equivalent to GL_NONE
2383     \value Int8 Equivalent to GL_BYTE
2384     \value UInt8 Equivalent to GL_UNSIGNED_BYTE
2385     \value Int16 Equivalent to GL_SHORT
2386     \value UInt16 Equivalent to GL_UNSIGNED_SHORT
2387     \value Int32 Equivalent to GL_INT
2388     \value UInt32 Equivalent to GL_UNSIGNED_INT
2389     \value Float16 Equivalent to GL_HALF_FLOAT
2390     \value Float16OES Equivalent to GL_HALF_FLOAT_OES
2391     \value Float32 Equivalent to GL_FLOAT
2392     \value UInt32_RGB9_E5 Equivalent to GL_UNSIGNED_INT_5_9_9_9_REV
2393     \value UInt32_RG11B10F Equivalent to GL_UNSIGNED_INT_10F_11F_11F_REV
2394     \value UInt8_RG3B2 Equivalent to GL_UNSIGNED_BYTE_3_3_2
2395     \value UInt8_RG3B2_Rev Equivalent to GL_UNSIGNED_BYTE_2_3_3_REV
2396     \value UInt16_RGB5A1 Equivalent to GL_UNSIGNED_SHORT_5_5_5_1
2397     \value UInt16_RGB5A1_Rev Equivalent to GL_UNSIGNED_SHORT_1_5_5_5_REV
2398     \value UInt16_R5G6B5 Equivalent to GL_UNSIGNED_SHORT_5_6_5
2399     \value UInt16_R5G6B5_Rev Equivalent to GL_UNSIGNED_SHORT_5_6_5_REV
2400     \value UInt16_RGBA4 Equivalent to GL_UNSIGNED_SHORT_4_4_4_4
2401     \value UInt16_RGBA4_Rev Equivalent to GL_UNSIGNED_SHORT_4_4_4_4_REV
2402     \value UInt32_RGBA8 Equivalent to GL_UNSIGNED_INT_8_8_8_8
2403     \value UInt32_RGBA8_Rev Equivalent to GL_UNSIGNED_INT_8_8_8_8_REV
2404     \value UInt32_RGB10A2 Equivalent to GL_UNSIGNED_INT_10_10_10_2
2405     \value UInt32_RGB10A2_Rev Equivalent to GL_UNSIGNED_INT_2_10_10_10_REV
2406     \value UInt32_D24S8 Equivalent to GL_UNSIGNED_INT_24_8. Introduced in Qt 5.4
2407     \value Float32_D32_UInt32_S8_X24 Equivalent to GL_FLOAT_32_UNSIGNED_INT_24_8_REV. Introduced in Qt 5.4
2408 */
2409 
2410 /*!
2411     \enum QOpenGLTexture::Feature
2412     This enum defines the OpenGL texture-related features that can be tested for.
2413 
2414     \value ImmutableStorage Support for immutable texture storage
2415     \value ImmutableMultisampleStorage Support for immutable texture storage with
2416            multisample targets
2417     \value TextureRectangle Support for the GL_TEXTURE_RECTANGLE target
2418     \value TextureArrays Support for texture targets with array layers
2419     \value Texture3D Support for the 3 dimensional texture target
2420     \value TextureMultisample Support for texture targets that have multisample capabilities
2421     \value TextureBuffer Support for textures that use OpenGL buffer objects
2422            as their data source
2423     \value TextureCubeMapArrays Support for cubemap array texture target
2424     \value Swizzle Support for texture component swizzle masks
2425     \value StencilTexturing Support for stencil texturing (i.e. looking up depth or stencil
2426            components of a combined depth/stencil format texture in GLSL shaders).
2427     \value AnisotropicFiltering Support for anisotropic texture filtering
2428     \value NPOTTextures Basic support for non-power-of-two textures
2429     \value NPOTTextureRepeat Full support for non-power-of-two textures including texture
2430            repeat modes
2431     \value Texture1D Support for the 1 dimensional texture target
2432     \value TextureComparisonOperators Support for texture comparison operators
2433     \value TextureMipMapLevel Support for setting the base and maximum mipmap levels
2434 */
2435 
2436 /*!
2437     \enum QOpenGLTexture::SwizzleComponent
2438     This enum defines the texture color components that can be assigned a swizzle mask.
2439 
2440     \value SwizzleRed The red component. Equivalent to GL_TEXTURE_SWIZZLE_R
2441     \value SwizzleGreen The green component. Equivalent to GL_TEXTURE_SWIZZLE_G
2442     \value SwizzleBlue The blue component. Equivalent to GL_TEXTURE_SWIZZLE_B
2443     \value SwizzleAlpha The alpha component. Equivalent to GL_TEXTURE_SWIZZLE_A
2444 */
2445 
2446 /*!
2447     \enum QOpenGLTexture::SwizzleValue
2448     This enum defines the possible mask values for texture swizzling.
2449 
2450     \value RedValue Maps the component to the red channel. Equivalent to GL_RED
2451     \value GreenValue Maps the component to the green channel. Equivalent to GL_GREEN
2452     \value BlueValue Maps the component to the blue channel. Equivalent to GL_BLUE
2453     \value AlphaValue Maps the component to the alpha channel. Equivalent to GL_ALPHA
2454     \value ZeroValue Maps the component to a fixed value of 0. Equivalent to GL_ZERO
2455     \value OneValue Maps the component to a fixed value of 1. Equivalent to GL_ONE
2456 */
2457 
2458 /*!
2459     \enum QOpenGLTexture::WrapMode
2460     This enum defines the possible texture coordinate wrapping modes.
2461 
2462     \value Repeat Texture coordinate is repeated. Equivalent to GL_REPEAT
2463     \value MirroredRepeat Texture coordinate is reflected about 0 and 1. Equivalent to GL_MIRRORED_REPEAT
2464     \value ClampToEdge Clamps the texture coordinates to [0,1]. Equivalent to GL_CLAMP_TO_EDGE
2465     \value ClampToBorder As for ClampToEdge but also blends samples at 0 and 1 with a
2466            fixed border color. Equivalent to GL_CLAMP_TO_BORDER
2467 */
2468 
2469 /*!
2470     \enum QOpenGLTexture::CoordinateDirection
2471     This enum defines the possible texture coordinate directions
2472 
2473     \value DirectionS The horizontal direction. Equivalent to GL_TEXTURE_WRAP_S
2474     \value DirectionT The vertical direction. Equivalent to GL_TEXTURE_WRAP_T
2475     \value DirectionR The depth direction. Equivalent to GL_TEXTURE_WRAP_R
2476 */
2477 
2478 /*!
2479     Creates a QOpenGLTexture object that can later be bound to \a target.
2480 
2481     This does not create the underlying OpenGL texture object. Therefore,
2482     construction using this constructor does not require a valid current
2483     OpenGL context.
2484 */
QOpenGLTexture(Target target)2485 QOpenGLTexture::QOpenGLTexture(Target target)
2486     : d_ptr(new QOpenGLTexturePrivate(target, this))
2487 {
2488 }
2489 
2490 /*!
2491     Creates a QOpenGLTexture object that can later be bound to the 2D texture
2492     target and contains the pixel data contained in \a image. If you wish
2493     to have a chain of mipmaps generated then set \a genMipMaps to \c true (this
2494     is the default).
2495 
2496     This does create the underlying OpenGL texture object. Therefore,
2497     construction using this constructor does require a valid current
2498     OpenGL context.
2499 */
QOpenGLTexture(const QImage & image,MipMapGeneration genMipMaps)2500 QOpenGLTexture::QOpenGLTexture(const QImage& image, MipMapGeneration genMipMaps)
2501     : QOpenGLTexture(QOpenGLTexture::Target2D)
2502 {
2503     setData(image, genMipMaps);
2504 }
2505 
~QOpenGLTexture()2506 QOpenGLTexture::~QOpenGLTexture()
2507 {
2508 }
2509 
2510 /*!
2511     Returns the binding target of this texture.
2512 
2513     \since 5.4
2514 */
target() const2515 QOpenGLTexture::Target QOpenGLTexture::target() const
2516 {
2517     Q_D(const QOpenGLTexture);
2518     return d->target;
2519 }
2520 
2521 /*!
2522     Creates the underlying OpenGL texture object. This requires a current valid
2523     OpenGL context. If the texture object already exists, this function does
2524     nothing.
2525 
2526     Once the texture object is created you can obtain the object
2527     name from the textureId() function. This may be useful if you wish to make
2528     some raw OpenGL calls related to this texture.
2529 
2530     Normally it should not be necessary to call this function directly as all
2531     functions that set properties of the texture object implicitly call create()
2532     on your behalf.
2533 
2534     Returns \c true if the creation succeeded, otherwise returns \c false.
2535 
2536     \sa destroy(), isCreated(), textureId()
2537 */
create()2538 bool QOpenGLTexture::create()
2539 {
2540     Q_D(QOpenGLTexture);
2541     return d->create();
2542 }
2543 
2544 /*!
2545     Destroys the underlying OpenGL texture object. This requires a current valid
2546     OpenGL context.
2547 
2548     \sa create(), isCreated(), textureId()
2549 */
destroy()2550 void QOpenGLTexture::destroy()
2551 {
2552     Q_D(QOpenGLTexture);
2553     return d->destroy();
2554 }
2555 
2556 /*!
2557     Returns \c true if the underlying OpenGL texture object has been created.
2558 
2559     \sa create(), destroy(), textureId()
2560 */
isCreated() const2561 bool QOpenGLTexture::isCreated() const
2562 {
2563     Q_D(const QOpenGLTexture);
2564     return d->textureId != 0;
2565 }
2566 
2567 /*!
2568     Returns the name of the underlying OpenGL texture object or 0 if it has
2569     not yet been created.
2570 
2571     \sa create(), destroy(), isCreated()
2572 */
textureId() const2573 GLuint QOpenGLTexture::textureId() const
2574 {
2575     Q_D(const QOpenGLTexture);
2576     return d->textureId;
2577 }
2578 
2579 /*!
2580     Binds this texture to the currently active texture unit ready for
2581     rendering. Note that you do not need to bind QOpenGLTexture objects
2582     in order to modify them as the implementation makes use of the
2583     EXT_direct_state_access extension where available and simulates it
2584     where it is not.
2585 
2586     \sa release()
2587 */
bind()2588 void QOpenGLTexture::bind()
2589 {
2590     Q_D(QOpenGLTexture);
2591     Q_ASSERT(d->textureId);
2592     d->bind();
2593 }
2594 
2595 /*!
2596     Binds this texture to texture unit \a unit ready for
2597     rendering. Note that you do not need to bind QOpenGLTexture objects
2598     in order to modify them as the implementation makes use of the
2599     EXT_direct_state_access extension where available and simulates it
2600     where it is not.
2601 
2602     If parameter \a reset is \c true then this function will restore
2603     the active unit to the texture unit that was active upon entry.
2604 
2605     \sa release()
2606 */
bind(uint unit,TextureUnitReset reset)2607 void QOpenGLTexture::bind(uint unit, TextureUnitReset reset)
2608 {
2609     Q_D(QOpenGLTexture);
2610     Q_ASSERT(d->textureId);
2611     d->bind(unit, reset);
2612 }
2613 
2614 /*!
2615     Unbinds this texture from the currently active texture unit.
2616 
2617     \sa bind()
2618 */
release()2619 void QOpenGLTexture::release()
2620 {
2621     Q_D(QOpenGLTexture);
2622     d->release();
2623 }
2624 
2625 /*!
2626     Unbinds this texture from texture unit \a unit.
2627 
2628     If parameter \a reset is \c true then this function
2629     will restore the active unit to the texture unit that was active
2630     upon entry.
2631 */
release(uint unit,TextureUnitReset reset)2632 void QOpenGLTexture::release(uint unit, TextureUnitReset reset)
2633 {
2634     Q_D(QOpenGLTexture);
2635     d->release(unit, reset);
2636 }
2637 
2638 /*!
2639     Returns \c true if this texture is bound to the corresponding target
2640     of the currently active texture unit.
2641 
2642     \sa bind(), release()
2643 */
isBound() const2644 bool QOpenGLTexture::isBound() const
2645 {
2646     Q_D(const QOpenGLTexture);
2647     Q_ASSERT(d->textureId);
2648     return d->isBound();
2649 }
2650 
2651 /*!
2652     Returns \c true if this texture is bound to the corresponding target
2653     of texture unit \a unit.
2654 
2655     \sa bind(), release()
2656 */
isBound(uint unit)2657 bool QOpenGLTexture::isBound(uint unit)
2658 {
2659     Q_D(const QOpenGLTexture);
2660     Q_ASSERT(d->textureId);
2661     return d->isBound(unit);
2662 }
2663 
2664 /*!
2665     Returns the textureId of the texture that is bound to the \a target
2666     of the currently active texture unit.
2667 */
boundTextureId(BindingTarget target)2668 GLuint QOpenGLTexture::boundTextureId(BindingTarget target)
2669 {
2670     QOpenGLContext *ctx = QOpenGLContext::currentContext();
2671     if (!ctx) {
2672         qWarning("QOpenGLTexture::boundTextureId() requires a valid current context");
2673         return 0;
2674     }
2675 
2676     GLint textureId = 0;
2677     ctx->functions()->glGetIntegerv(target, &textureId);
2678     return static_cast<GLuint>(textureId);
2679 }
2680 
2681 /*!
2682     Returns the textureId of the texture that is bound to the \a target
2683     of the texture unit \a unit.
2684 */
boundTextureId(uint unit,BindingTarget target)2685 GLuint QOpenGLTexture::boundTextureId(uint unit, BindingTarget target)
2686 {
2687     QOpenGLContext *ctx = QOpenGLContext::currentContext();
2688     if (!ctx) {
2689         qWarning("QOpenGLTexture::boundTextureId() requires a valid current context");
2690         return 0;
2691     }
2692 
2693     QOpenGLFunctions *funcs = ctx->functions();
2694     funcs->initializeOpenGLFunctions();
2695 
2696     GLint oldTextureUnit = 0;
2697     funcs->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
2698 
2699     funcs->glActiveTexture(unit);
2700     GLint textureId = 0;
2701     funcs->glGetIntegerv(target, &textureId);
2702     funcs->glActiveTexture(oldTextureUnit);
2703 
2704     return static_cast<GLuint>(textureId);
2705 }
2706 
2707 /*!
2708     Sets the format of this texture object to \a format. This function
2709     must be called before texture storage is allocated.
2710 
2711     Note that all formats may not be supported. The exact set of supported
2712     formats is dependent upon your OpenGL implementation and version.
2713 
2714     \sa format(), allocateStorage()
2715 */
setFormat(TextureFormat format)2716 void QOpenGLTexture::setFormat(TextureFormat format)
2717 {
2718     Q_D(QOpenGLTexture);
2719     d->create();
2720     if (isStorageAllocated()) {
2721         qWarning("QOpenGLTexture::setFormat(): Cannot change format once storage has been allocated");
2722         return;
2723     }
2724 
2725     d->format = format;
2726 
2727     switch (format) {
2728     case NoFormat:
2729         d->formatClass = NoFormatClass;
2730         break;
2731 
2732     case RGBA32F:
2733     case RGBA32U:
2734     case RGBA32I:
2735         d->formatClass = FormatClass_128Bit;
2736         break;
2737 
2738     case RGB32F:
2739     case RGB32U:
2740     case RGB32I:
2741         d->formatClass = FormatClass_96Bit;
2742         break;
2743 
2744     case RGBA16F:
2745     case RG32F:
2746     case RGBA16U:
2747     case RG32U:
2748     case RGBA16I:
2749     case RG32I:
2750     case RGBA16_UNorm:
2751     case RGBA16_SNorm:
2752         d->formatClass = FormatClass_64Bit;
2753         break;
2754 
2755     case RGB16_UNorm:
2756     case RGB16_SNorm:
2757     case RGB16F:
2758     case RGB16U:
2759     case RGB16I:
2760         d->formatClass = FormatClass_48Bit;
2761         break;
2762 
2763     case RG16F:
2764     case RG11B10F:
2765     case R32F:
2766     case RGB10A2:
2767     case RGBA8U:
2768     case RG16U:
2769     case R32U:
2770     case RGBA8I:
2771     case RG16I:
2772     case R32I:
2773     case RGBA8_UNorm:
2774     case RG16_UNorm:
2775     case RGBA8_SNorm:
2776     case RG16_SNorm:
2777     case SRGB8_Alpha8:
2778     case RGB9E5:
2779         d->formatClass = FormatClass_32Bit;
2780         break;
2781 
2782     case RGB8_UNorm:
2783     case RGB8_SNorm:
2784     case SRGB8:
2785     case RGB8U:
2786     case RGB8I:
2787         d->formatClass = FormatClass_24Bit;
2788         break;
2789 
2790     case R16F:
2791     case RG8U:
2792     case R16U:
2793     case RG8I:
2794     case R16I:
2795     case RG8_UNorm:
2796     case R16_UNorm:
2797     case RG8_SNorm:
2798     case R16_SNorm:
2799         d->formatClass = FormatClass_16Bit;
2800         break;
2801 
2802     case R8U:
2803     case R8I:
2804     case R8_UNorm:
2805     case R8_SNorm:
2806         d->formatClass = FormatClass_8Bit;
2807         break;
2808 
2809     case R_ATI1N_UNorm:
2810     case R_ATI1N_SNorm:
2811         d->formatClass = FormatClass_RGTC1_R;
2812         break;
2813 
2814     case RG_ATI2N_UNorm:
2815     case RG_ATI2N_SNorm:
2816         d->formatClass = FormatClass_RGTC2_RG;
2817         break;
2818 
2819     case RGB_BP_UNorm:
2820     case SRGB_BP_UNorm:
2821         d->formatClass = FormatClass_BPTC_Unorm;
2822         break;
2823 
2824     case RGB_BP_UNSIGNED_FLOAT:
2825     case RGB_BP_SIGNED_FLOAT:
2826         d->formatClass = FormatClass_BPTC_Float;
2827         break;
2828 
2829     case RGB_DXT1:
2830     case SRGB_DXT1:
2831         d->formatClass = FormatClass_S3TC_DXT1_RGB;
2832         break;
2833 
2834     case RGBA_DXT1:
2835     case SRGB_Alpha_DXT1:
2836         d->formatClass = FormatClass_S3TC_DXT1_RGBA;
2837         break;
2838 
2839     case RGBA_DXT3:
2840     case SRGB_Alpha_DXT3:
2841         d->formatClass = FormatClass_S3TC_DXT3_RGBA;
2842         break;
2843 
2844     case RGBA_DXT5:
2845     case SRGB_Alpha_DXT5:
2846         d->formatClass = FormatClass_S3TC_DXT5_RGBA;
2847         break;
2848 
2849     case QOpenGLTexture::R11_EAC_UNorm:
2850     case QOpenGLTexture::R11_EAC_SNorm:
2851     case QOpenGLTexture::RG11_EAC_UNorm:
2852     case QOpenGLTexture::RG11_EAC_SNorm:
2853     case QOpenGLTexture::RGB8_ETC2:
2854     case QOpenGLTexture::SRGB8_ETC2:
2855     case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
2856     case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
2857     case QOpenGLTexture::RGBA8_ETC2_EAC:
2858     case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
2859     case QOpenGLTexture::RGB8_ETC1:
2860     case RG3B2:
2861     case R5G6B5:
2862     case RGB5A1:
2863     case RGBA4:
2864     case D16:
2865     case D24:
2866     case D24S8:
2867     case D32:
2868     case D32F:
2869     case D32FS8X24:
2870     case S8:
2871     case DepthFormat:
2872     case AlphaFormat:
2873     case RGBFormat:
2874     case RGBAFormat:
2875     case LuminanceFormat:
2876     case LuminanceAlphaFormat:
2877     case QOpenGLTexture::RGBA_ASTC_4x4:
2878     case QOpenGLTexture::RGBA_ASTC_5x4:
2879     case QOpenGLTexture::RGBA_ASTC_5x5:
2880     case QOpenGLTexture::RGBA_ASTC_6x5:
2881     case QOpenGLTexture::RGBA_ASTC_6x6:
2882     case QOpenGLTexture::RGBA_ASTC_8x5:
2883     case QOpenGLTexture::RGBA_ASTC_8x6:
2884     case QOpenGLTexture::RGBA_ASTC_8x8:
2885     case QOpenGLTexture::RGBA_ASTC_10x5:
2886     case QOpenGLTexture::RGBA_ASTC_10x6:
2887     case QOpenGLTexture::RGBA_ASTC_10x8:
2888     case QOpenGLTexture::RGBA_ASTC_10x10:
2889     case QOpenGLTexture::RGBA_ASTC_12x10:
2890     case QOpenGLTexture::RGBA_ASTC_12x12:
2891     case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
2892     case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
2893     case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
2894     case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
2895     case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
2896     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
2897     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
2898     case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
2899     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
2900     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
2901     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
2902     case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
2903     case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
2904     case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
2905         d->formatClass = FormatClass_Unique;
2906         break;
2907     }
2908 }
2909 
2910 /*!
2911     Returns the format of this texture object.
2912 
2913     \sa setFormat()
2914 */
format() const2915 QOpenGLTexture::TextureFormat QOpenGLTexture::format() const
2916 {
2917     Q_D(const QOpenGLTexture);
2918     return d->format;
2919 }
2920 
isNpot(int width,int height=1,int depth=1)2921 static bool isNpot(int width, int height = 1, int depth = 1)
2922 {
2923     return width & (width-1) || height & (height-1) || depth & (depth-1);
2924 }
2925 
2926 /*!
2927     Sets the dimensions of this texture object to \a width,
2928     \a height, and \a depth. The default for each dimension is 1.
2929     The maximum allowable texture size is dependent upon your OpenGL
2930     implementation. Allocating storage for a texture less than the
2931     maximum size can still fail if your system is low on resources.
2932 
2933     If a non-power-of-two \a width, \a height or \a depth is provided and your
2934     OpenGL implementation doesn't have support for repeating non-power-of-two
2935     textures, then the wrap mode is automatically set to ClampToEdge.
2936 
2937     \sa width(), height(), depth()
2938 */
setSize(int width,int height,int depth)2939 void QOpenGLTexture::setSize(int width, int height, int depth)
2940 {
2941     Q_D(QOpenGLTexture);
2942     d->create();
2943     if (isStorageAllocated()) {
2944         qWarning("Cannot resize a texture that already has storage allocated.\n"
2945                  "To do so, destroy() the texture and then create() and setSize()");
2946         return;
2947     }
2948 
2949     if (isNpot(width, height, depth) && !hasFeature(Feature::NPOTTextureRepeat) && d->target != Target::TargetRectangle)
2950         d->setWrapMode(WrapMode::ClampToEdge);
2951 
2952     switch (d->target) {
2953     case QOpenGLTexture::Target1D:
2954     case QOpenGLTexture::Target1DArray:
2955     case QOpenGLTexture::TargetBuffer:
2956         d->dimensions[0] = width;
2957         Q_UNUSED(height);
2958         Q_UNUSED(depth);
2959         break;
2960 
2961     case QOpenGLTexture::Target2D:
2962     case QOpenGLTexture::Target2DArray:
2963     case QOpenGLTexture::TargetRectangle:
2964     case QOpenGLTexture::Target2DMultisample:
2965     case QOpenGLTexture::Target2DMultisampleArray:
2966         d->dimensions[0] = width;
2967         d->dimensions[1] = height;
2968         Q_UNUSED(depth);
2969         break;
2970 
2971     case QOpenGLTexture::TargetCubeMap:
2972     case QOpenGLTexture::TargetCubeMapArray:
2973         if (width != height)
2974             qWarning("QAbstractOpenGLTexture::setSize(): Cube map textures must be square");
2975         d->dimensions[0] = d->dimensions[1] = width;
2976         Q_UNUSED(depth);
2977         break;
2978 
2979     case QOpenGLTexture::Target3D:
2980         d->dimensions[0] = width;
2981         d->dimensions[1] = height;
2982         d->dimensions[2] = depth;
2983         break;
2984     }
2985 }
2986 
2987 /*!
2988     Returns the width of a 1D, 2D or 3D texture.
2989 
2990     \sa height(), depth(), setSize()
2991 */
width() const2992 int QOpenGLTexture::width() const
2993 {
2994     Q_D(const QOpenGLTexture);
2995     return d->dimensions[0];
2996 }
2997 
2998 /*!
2999     Returns the height of a 2D or 3D texture.
3000 
3001     \sa width(), depth(), setSize()
3002 */
height() const3003 int QOpenGLTexture::height() const
3004 {
3005     Q_D(const QOpenGLTexture);
3006     return d->dimensions[1];
3007 }
3008 
3009 /*!
3010     Returns the depth of a 3D texture.
3011 
3012     \sa width(), height(), setSize()
3013 */
depth() const3014 int QOpenGLTexture::depth() const
3015 {
3016     Q_D(const QOpenGLTexture);
3017     return d->dimensions[2];
3018 }
3019 
3020 /*!
3021     For texture targets that support mipmaps, this function
3022     sets the requested number of mipmap \a levels to allocate storage
3023     for. This function should be called before storage is allocated
3024     for the texture.
3025 
3026     If the texture target does not support mipmaps this function
3027     has no effect.
3028 
3029     \sa mipLevels(), maximumMipLevels(), isStorageAllocated()
3030 */
setMipLevels(int levels)3031 void QOpenGLTexture::setMipLevels(int levels)
3032 {
3033     Q_D(QOpenGLTexture);
3034     d->create();
3035     if (isStorageAllocated()) {
3036         qWarning("Cannot set mip levels on a texture that already has storage allocated.\n"
3037                  "To do so, destroy() the texture and then create() and setMipLevels()");
3038         return;
3039     }
3040 
3041     switch (d->target) {
3042     case QOpenGLTexture::Target1D:
3043     case QOpenGLTexture::Target1DArray:
3044     case QOpenGLTexture::Target2D:
3045     case QOpenGLTexture::Target2DArray:
3046     case QOpenGLTexture::TargetCubeMap:
3047     case QOpenGLTexture::TargetCubeMapArray:
3048     case QOpenGLTexture::Target3D:
3049         d->requestedMipLevels = levels;
3050         break;
3051 
3052     case QOpenGLTexture::TargetBuffer:
3053     case QOpenGLTexture::TargetRectangle:
3054     case QOpenGLTexture::Target2DMultisample:
3055     case QOpenGLTexture::Target2DMultisampleArray:
3056         qWarning("QAbstractOpenGLTexture::setMipLevels(): This texture target does not support mipmaps");
3057         break;
3058     }
3059 }
3060 
3061 /*!
3062     Returns the number of mipmap levels for this texture. If storage
3063     has not yet been allocated for this texture it returns the
3064     requested number of mipmap levels.
3065 
3066     \sa setMipLevels(), maximumMipLevels(), isStorageAllocated()
3067 */
mipLevels() const3068 int QOpenGLTexture::mipLevels() const
3069 {
3070     Q_D(const QOpenGLTexture);
3071     return isStorageAllocated() ? d->mipLevels : d->requestedMipLevels;
3072 }
3073 
3074 /*!
3075     Returns the maximum number of mipmap levels that this texture
3076     can have given the current dimensions.
3077 
3078     \sa setMipLevels(), mipLevels(), setSize()
3079 */
maximumMipLevels() const3080 int QOpenGLTexture::maximumMipLevels() const
3081 {
3082     Q_D(const QOpenGLTexture);
3083     return d->maximumMipLevelCount();
3084 }
3085 
3086 /*!
3087     Sets the number of array \a layers to allocate storage for. This
3088     function should be called before storage is allocated for the texture.
3089 
3090     For targets that do not support array layers this function has
3091     no effect.
3092 
3093     \sa layers(), isStorageAllocated()
3094 */
setLayers(int layers)3095 void QOpenGLTexture::setLayers(int layers)
3096 {
3097     Q_D(QOpenGLTexture);
3098     d->create();
3099     if (isStorageAllocated()) {
3100         qWarning("Cannot set layers on a texture that already has storage allocated.\n"
3101                  "To do so, destroy() the texture and then create() and setLayers()");
3102         return;
3103     }
3104 
3105     switch (d->target) {
3106     case QOpenGLTexture::Target1DArray:
3107     case QOpenGLTexture::Target2DArray:
3108     case QOpenGLTexture::TargetCubeMapArray:
3109     case QOpenGLTexture::Target2DMultisampleArray:
3110         d->layers = layers;
3111         break;
3112 
3113     case QOpenGLTexture::Target1D:
3114     case QOpenGLTexture::Target2D:
3115     case QOpenGLTexture::Target3D:
3116     case QOpenGLTexture::TargetCubeMap:
3117     case QOpenGLTexture::TargetBuffer:
3118     case QOpenGLTexture::TargetRectangle:
3119     case QOpenGLTexture::Target2DMultisample:
3120         qWarning("Texture target does not support array layers");
3121         break;
3122     }
3123 }
3124 
3125 /*!
3126     Returns the number of array layers for this texture. If
3127     storage has not yet been allocated for this texture then
3128     this function returns the requested number of array layers.
3129 
3130     For texture targets that do not support array layers this
3131     will return 1.
3132 
3133     \sa setLayers(), isStorageAllocated()
3134 */
layers() const3135 int QOpenGLTexture::layers() const
3136 {
3137     Q_D(const QOpenGLTexture);
3138     return d->layers;
3139 }
3140 
3141 /*!
3142     Returns the number of faces for this texture. For cubemap
3143     and cubemap array type targets this will be 6.
3144 
3145     For non-cubemap type targets this will return 1.
3146 */
faces() const3147 int QOpenGLTexture::faces() const
3148 {
3149     Q_D(const QOpenGLTexture);
3150     return d->faces;
3151 }
3152 
3153 /*!
3154     Sets the number of \a samples to allocate storage for when rendering to
3155     a multisample capable texture target. This function should
3156     be called before storage is allocated for the texture.
3157 
3158     For targets that do not support multisampling this function has
3159     no effect.
3160 
3161     \sa samples(), isStorageAllocated()
3162 */
setSamples(int samples)3163 void QOpenGLTexture::setSamples(int samples)
3164 {
3165     Q_D(QOpenGLTexture);
3166     d->create();
3167     if (isStorageAllocated()) {
3168         qWarning("Cannot set sample count on a texture that already has storage allocated.\n"
3169                  "To do so, destroy() the texture and then create() and setSamples()");
3170         return;
3171     }
3172 
3173     switch (d->target) {
3174     case QOpenGLTexture::Target2DMultisample:
3175     case QOpenGLTexture::Target2DMultisampleArray:
3176         d->samples = samples;
3177         break;
3178 
3179     case QOpenGLTexture::Target1D:
3180     case QOpenGLTexture::Target2D:
3181     case QOpenGLTexture::Target3D:
3182     case QOpenGLTexture::Target1DArray:
3183     case QOpenGLTexture::Target2DArray:
3184     case QOpenGLTexture::TargetCubeMap:
3185     case QOpenGLTexture::TargetCubeMapArray:
3186     case QOpenGLTexture::TargetBuffer:
3187     case QOpenGLTexture::TargetRectangle:
3188 
3189         qWarning("Texture target does not support multisampling");
3190         break;
3191     }
3192 }
3193 
3194 /*!
3195     Returns the number of multisample sample points for this texture.
3196     If storage has not yet been allocated for this texture then
3197     this function returns the requested number of samples.
3198 
3199     For texture targets that do not support multisampling this
3200     will return 0.
3201 
3202     \sa setSamples(), isStorageAllocated()
3203 */
samples() const3204 int QOpenGLTexture::samples() const
3205 {
3206     Q_D(const QOpenGLTexture);
3207     return d->samples;
3208 }
3209 
3210 /*!
3211     Sets whether the sample positions and number of samples used with
3212     a multisample capable texture target to \a fixed. If set to \c true
3213     the sample positions and number of samples used are the same for
3214     all texels in the image and will not depend upon the image size or
3215     internal format. This function should be called before storage is allocated
3216     for the texture.
3217 
3218     For targets that do not support multisampling this function has
3219     no effect.
3220 
3221     The default value is \c true.
3222 
3223     \sa isFixedSamplePositions(), isStorageAllocated()
3224 */
setFixedSamplePositions(bool fixed)3225 void QOpenGLTexture::setFixedSamplePositions(bool fixed)
3226 {
3227     Q_D(QOpenGLTexture);
3228     d->create();
3229     if (isStorageAllocated()) {
3230         qWarning("Cannot set sample positions on a texture that already has storage allocated.\n"
3231                  "To do so, destroy() the texture and then create() and setFixedSamplePositions()");
3232         return;
3233     }
3234 
3235     switch (d->target) {
3236     case QOpenGLTexture::Target2DMultisample:
3237     case QOpenGLTexture::Target2DMultisampleArray:
3238         d->fixedSamplePositions = fixed;
3239         break;
3240 
3241     case QOpenGLTexture::Target1D:
3242     case QOpenGLTexture::Target2D:
3243     case QOpenGLTexture::Target3D:
3244     case QOpenGLTexture::Target1DArray:
3245     case QOpenGLTexture::Target2DArray:
3246     case QOpenGLTexture::TargetCubeMap:
3247     case QOpenGLTexture::TargetCubeMapArray:
3248     case QOpenGLTexture::TargetBuffer:
3249     case QOpenGLTexture::TargetRectangle:
3250 
3251         qWarning("Texture target does not support multisampling");
3252         break;
3253     }
3254 }
3255 
3256 /*!
3257     Returns whether this texture uses a fixed pattern of multisample
3258     samples. If storage has not yet been allocated for this texture then
3259     this function returns the requested fixed sample position setting.
3260 
3261     For texture targets that do not support multisampling this
3262     will return \c true.
3263 
3264     \sa setFixedSamplePositions(), isStorageAllocated()
3265 */
isFixedSamplePositions() const3266 bool QOpenGLTexture::isFixedSamplePositions() const
3267 {
3268     Q_D(const QOpenGLTexture);
3269     return d->fixedSamplePositions;
3270 }
3271 
3272 /*!
3273     Allocates server-side storage for this texture object taking
3274     into account, the format, dimensions, mipmap levels, array
3275     layers and cubemap faces.
3276 
3277     Once storage has been allocated it is no longer possible to change
3278     these properties.
3279 
3280     If supported QOpenGLTexture makes use of immutable texture
3281     storage.
3282 
3283     Once storage has been allocated for the texture then pixel data
3284     can be uploaded via one of the setData() overloads.
3285 
3286     \note If immutable texture storage is not available,
3287     then a default pixel format and pixel type will be used to
3288     create the mutable storage. You can use the other
3289     allocateStorage() overload to specify exactly the pixel format
3290     and the pixel type to use when allocating mutable storage;
3291     this is particulary useful under certain OpenGL ES implementations
3292     (notably, OpenGL ES 2), where the pixel format and the pixel type
3293     used at allocation time must perfectly match the format
3294     and the type passed to any subsequent setData() call.
3295 
3296     \sa isStorageAllocated(), setData()
3297 */
allocateStorage()3298 void QOpenGLTexture::allocateStorage()
3299 {
3300     Q_D(QOpenGLTexture);
3301     if (d->create()) {
3302         const QOpenGLTexture::PixelFormat pixelFormat = pixelFormatCompatibleWithInternalFormat(d->format);
3303         const QOpenGLTexture::PixelType pixelType = pixelTypeCompatibleWithInternalFormat(d->format);
3304         d->allocateStorage(pixelFormat, pixelType);
3305     }
3306 }
3307 
3308 /*!
3309     \since 5.5
3310 
3311     Allocates server-side storage for this texture object taking
3312     into account, the format, dimensions, mipmap levels, array
3313     layers and cubemap faces.
3314 
3315     Once storage has been allocated it is no longer possible to change
3316     these properties.
3317 
3318     If supported QOpenGLTexture makes use of immutable texture
3319     storage. However, if immutable texture storage is not available,
3320     then the specified \a pixelFormat and \a pixelType will be used
3321     to allocate mutable storage; note that in certain OpenGL implementations
3322     (notably, OpenGL ES 2) they must perfectly match the format
3323     and the type passed to any subsequent setData() call.
3324 
3325     Once storage has been allocated for the texture then pixel data
3326     can be uploaded via one of the setData() overloads.
3327 
3328     \sa isStorageAllocated(), setData()
3329 */
allocateStorage(QOpenGLTexture::PixelFormat pixelFormat,QOpenGLTexture::PixelType pixelType)3330 void QOpenGLTexture::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
3331 {
3332     Q_D(QOpenGLTexture);
3333     if (d->create())
3334         d->allocateStorage(pixelFormat, pixelType);
3335 }
3336 
3337 /*!
3338     Returns \c true if server-side storage for this texture as been
3339     allocated.
3340 
3341     The texture format, dimensions, mipmap levels and array layers
3342     cannot be altered once storage ihas been allocated.
3343 
3344     \sa allocateStorage(), setSize(), setMipLevels(), setLayers(), setFormat()
3345 */
isStorageAllocated() const3346 bool QOpenGLTexture::isStorageAllocated() const
3347 {
3348     Q_D(const QOpenGLTexture);
3349     return d->storageAllocated;
3350 }
3351 
3352 /*!
3353     Attempts to create a texture view onto this texture. A texture
3354     view is somewhat analogous to a view in SQL in that it presents
3355     a restricted or reinterpreted view of the original data. Texture
3356     views do not allocate any more server-side storage, insted relying
3357     on the storage buffer of the source texture.
3358 
3359     Texture views are only available when using immutable storage. For
3360     more information on texture views see
3361     http://www.opengl.org/wiki/Texture_Storage#Texture_views.
3362 
3363     The \a target argument specifies the target to use for the view.
3364     Only some targets can be used depending upon the target of the original
3365     target. For e.g. a view onto a Target1DArray texture can specify
3366     either Target1DArray or Target1D but for the latter the number of
3367     array layers specified with \a minimumLayer and \a maximumLayer must
3368     be exactly 1.
3369 
3370     Simpliar constraints apply for the \a viewFormat. See the above link
3371     and the specification for more details.
3372 
3373     The \a minimumMipmapLevel, \a maximumMipmapLevel, \a minimumLayer,
3374     and \a maximumLayer arguments serve to restrict the parts of the
3375     texture accessible by the texture view.
3376 
3377     If creation of the texture view fails this function will return
3378     0. If the function succeeds it will return a pointer to a new
3379     QOpenGLTexture object that will return \c true from its isTextureView()
3380     function.
3381 
3382     \sa isTextureView()
3383 */
createTextureView(Target target,TextureFormat viewFormat,int minimumMipmapLevel,int maximumMipmapLevel,int minimumLayer,int maximumLayer) const3384 QOpenGLTexture *QOpenGLTexture::createTextureView(Target target,
3385                                                   TextureFormat viewFormat,
3386                                                   int minimumMipmapLevel, int maximumMipmapLevel,
3387                                                   int minimumLayer, int maximumLayer) const
3388 {
3389     Q_D(const QOpenGLTexture);
3390     if (!isStorageAllocated()) {
3391         qWarning("Cannot set create a texture view of a texture that does not have storage allocated.");
3392         return nullptr;
3393     }
3394     Q_ASSERT(maximumMipmapLevel >= minimumMipmapLevel);
3395     Q_ASSERT(maximumLayer >= minimumLayer);
3396     return d->createTextureView(target, viewFormat,
3397                                 minimumMipmapLevel, maximumMipmapLevel,
3398                                 minimumLayer, maximumLayer);
3399 }
3400 
3401 /*!
3402     Returns \c true if this texture object is actually a view onto another
3403     texture object.
3404 
3405     \sa createTextureView()
3406 */
isTextureView() const3407 bool QOpenGLTexture::isTextureView() const
3408 {
3409     Q_D(const QOpenGLTexture);
3410     Q_ASSERT(d->textureId);
3411     return d->textureView;
3412 }
3413 
3414 /*!
3415     Uploads pixel \a data for this texture object \a mipLevel, array \a layer, and \a cubeFace.
3416     Storage must have been allocated before uploading pixel data. Some overloads of setData()
3417     will set appropriate dimensions, mipmap levels, and array layers and then allocate storage
3418     for you if they have enough information to do so. This will be noted in the function
3419     documentation.
3420 
3421     The structure of the pixel data pointed to by \a data is specified by \a sourceFormat
3422     and \a sourceType. The pixel data upload can optionally be controlled by \a options.
3423 
3424     If using a compressed format() then you should use setCompressedData() instead of this
3425     function.
3426 
3427     \since 5.3
3428     \sa setCompressedData()
3429 */
setData(int mipLevel,int layer,CubeMapFace cubeFace,PixelFormat sourceFormat,PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)3430 void QOpenGLTexture::setData(int mipLevel, int layer, CubeMapFace cubeFace,
3431                              PixelFormat sourceFormat, PixelType sourceType,
3432                              const void *data, const QOpenGLPixelTransferOptions * const options)
3433 {
3434     Q_D(QOpenGLTexture);
3435     Q_ASSERT(d->textureId);
3436     if (!isStorageAllocated()) {
3437         qWarning("Cannot set data on a texture that does not have storage allocated.\n"
3438                  "To do so call allocateStorage() before this function");
3439         return;
3440     }
3441     d->setData(mipLevel, layer, 1, cubeFace, sourceFormat, sourceType, data, options);
3442 }
3443 
3444 /*!
3445     \since 5.9
3446     \overload
3447 
3448     Parameter \a layerCount is the number of layers in a texture array
3449     that are being uploaded/populated by this call.
3450 */
setData(int mipLevel,int layer,int layerCount,QOpenGLTexture::CubeMapFace cubeFace,QOpenGLTexture::PixelFormat sourceFormat,QOpenGLTexture::PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)3451 void QOpenGLTexture::setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType, const void *data, const QOpenGLPixelTransferOptions * const options)
3452 {
3453     Q_D(QOpenGLTexture);
3454     Q_ASSERT(d->textureId);
3455     if (!isStorageAllocated()) {
3456         qWarning("Cannot set data on a texture that does not have storage allocated.\n"
3457                  "To do so call allocateStorage() before this function");
3458         return;
3459     }
3460     d->setData(mipLevel, layer, layerCount, cubeFace, sourceFormat, sourceType, data, options);
3461 }
3462 
3463 /*!
3464     \since 5.3
3465     \overload
3466 */
setData(int mipLevel,int layer,PixelFormat sourceFormat,PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)3467 void QOpenGLTexture::setData(int mipLevel, int layer,
3468                              PixelFormat sourceFormat, PixelType sourceType,
3469                              const void *data, const QOpenGLPixelTransferOptions * const options)
3470 {
3471     Q_D(QOpenGLTexture);
3472     Q_ASSERT(d->textureId);
3473     d->setData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
3474 }
3475 
3476 /*!
3477     \since 5.3
3478     \overload
3479 */
setData(int mipLevel,PixelFormat sourceFormat,PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)3480 void QOpenGLTexture::setData(int mipLevel,
3481                              PixelFormat sourceFormat, PixelType sourceType,
3482                              const void *data, const QOpenGLPixelTransferOptions * const options)
3483 {
3484     Q_D(QOpenGLTexture);
3485     Q_ASSERT(d->textureId);
3486     d->setData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
3487 }
3488 
3489 /*!
3490     \since 5.3
3491     \overload
3492 */
setData(PixelFormat sourceFormat,PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)3493 void QOpenGLTexture::setData(PixelFormat sourceFormat, PixelType sourceType,
3494                              const void *data, const QOpenGLPixelTransferOptions * const options)
3495 {
3496     Q_D(QOpenGLTexture);
3497     Q_ASSERT(d->textureId);
3498     d->setData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
3499 }
3500 
3501 /*!
3502     \since 5.14
3503     \overload
3504 
3505     This overload is to be used to update a part of the texture. Parameters \a
3506     xOffset, \a yOffset, \a zOffset specify the texel offsets within the
3507     texture. Parameters \a width, \a height and \a depth specify the dimensions
3508     of the sub image.
3509 
3510     The structure of the pixel data pointed to by \a data is specified by \a
3511     sourceFormat and \a sourceType. The pixel data upload can optionally be
3512     controlled by \a options.
3513 */
setData(int xOffset,int yOffset,int zOffset,int width,int height,int depth,PixelFormat sourceFormat,PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)3514 void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
3515                              int width, int height, int depth,
3516                              PixelFormat sourceFormat, PixelType sourceType,
3517                              const void *data, const QOpenGLPixelTransferOptions * const options)
3518 {
3519     Q_D(QOpenGLTexture);
3520     Q_ASSERT(d->textureId);
3521     d->setData(xOffset, yOffset, zOffset,
3522                width, height, depth,
3523                0, 0, 1,
3524                QOpenGLTexture::CubeMapPositiveX, sourceFormat,
3525                sourceType, data, options);
3526 }
3527 
3528 /*!
3529     \since 5.14
3530     \overload
3531 
3532     This overload is to be used to update a part of the texture. Parameters \a
3533     xOffset, \a yOffset, \a zOffset specify the texel offsets within the
3534     texture. Parameters \a width, \a height and \a depth specify the dimensions
3535     of the sub image. The mip map level the sub image we want to
3536     update is specified with \a mipLevel.
3537 
3538     The structure of the pixel data pointed to by \a data is specified by \a
3539     sourceFormat and \a sourceType. The pixel data upload can optionally be
3540     controlled by \a options.
3541 */
setData(int xOffset,int yOffset,int zOffset,int width,int height,int depth,int mipLevel,PixelFormat sourceFormat,PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)3542 void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
3543                              int width, int height, int depth,
3544                              int mipLevel,
3545                              PixelFormat sourceFormat, PixelType sourceType,
3546                              const void *data, const QOpenGLPixelTransferOptions * const options)
3547 {
3548     Q_D(QOpenGLTexture);
3549     Q_ASSERT(d->textureId);
3550     d->setData(xOffset, yOffset, zOffset,
3551                width, height, depth,
3552                mipLevel, 0, 1,
3553                QOpenGLTexture::CubeMapPositiveX, sourceFormat,
3554                sourceType, data, options);
3555 }
3556 
3557 /*!
3558     \since 5.14
3559     \overload
3560 
3561     This overload is to be used to update a part of the texture. Parameters \a
3562     xOffset, \a yOffset, \a zOffset specify the texel offsets within the
3563     texture. Parameters \a width, \a height and \a depth specify the dimensions
3564     of the sub image. The mip map level and layerof the sub image we want to
3565     update are specified with \a mipLevel and \a layer.
3566 
3567     The structure of the pixel data pointed to by \a data is specified by \a
3568     sourceFormat and \a sourceType. The pixel data upload can optionally be
3569     controlled by \a options.
3570 */
setData(int xOffset,int yOffset,int zOffset,int width,int height,int depth,int mipLevel,int layer,PixelFormat sourceFormat,PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)3571 void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
3572                              int width, int height, int depth,
3573                              int mipLevel, int layer,
3574                              PixelFormat sourceFormat, PixelType sourceType,
3575                              const void *data, const QOpenGLPixelTransferOptions * const options)
3576 {
3577     Q_D(QOpenGLTexture);
3578     Q_ASSERT(d->textureId);
3579     d->setData(xOffset, yOffset, zOffset,
3580                width, height, depth,
3581                mipLevel, layer, 1,
3582                QOpenGLTexture::CubeMapPositiveX, sourceFormat,
3583                sourceType, data, options);
3584 }
3585 
3586 /*!
3587     \since 5.14
3588     \overload
3589 
3590     This overload is to be used to update a part of the texture. Parameters \a
3591     xOffset, \a yOffset, \a zOffset specify the texel offsets within the
3592     texture. Parameters \a width, \a height and \a depth specify the dimensions
3593     of the sub image.The mip map level, layer and cube map face of the sub
3594     image we want to update are specified with \a mipLevel, \a layer and \a
3595     face.
3596 
3597     The structure of the pixel data pointed to by \a data is specified by \a
3598     sourceFormat and \a sourceType. The pixel data upload can optionally be
3599     controlled by \a options.
3600 */
setData(int xOffset,int yOffset,int zOffset,int width,int height,int depth,int mipLevel,int layer,CubeMapFace face,PixelFormat sourceFormat,PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)3601 void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
3602                              int width, int height, int depth,
3603                              int mipLevel, int layer,
3604                              CubeMapFace face,
3605                              PixelFormat sourceFormat, PixelType sourceType,
3606                              const void *data, const QOpenGLPixelTransferOptions * const options)
3607 {
3608     Q_D(QOpenGLTexture);
3609     Q_ASSERT(d->textureId);
3610     d->setData(xOffset, yOffset, zOffset,
3611                width, height, depth,
3612                mipLevel, layer, 1,
3613                face, sourceFormat,
3614                sourceType, data, options);
3615 }
3616 
3617 /*!
3618     \since 5.14
3619     \overload
3620 
3621     This overload is to be used to update a part of the texture. Parameters \a
3622     xOffset, \a yOffset, \a zOffset specify the texel offsets within the
3623     texture. Parameters \a width, \a height and \a depth specify the dimensions
3624     of the sub image.The mip map level, starting layer, cube map face and
3625     number of layers of the sub image we want to update are specified with \a
3626     mipLevel, \a layer, \a face and \a layerCount.
3627 
3628     The structure of the pixel data pointed to by \a data is specified by \a
3629     sourceFormat and \a sourceType. The pixel data upload can optionally be
3630     controlled by \a options.
3631 */
setData(int xOffset,int yOffset,int zOffset,int width,int height,int depth,int mipLevel,int layer,CubeMapFace face,int layerCount,PixelFormat sourceFormat,PixelType sourceType,const void * data,const QOpenGLPixelTransferOptions * const options)3632 void QOpenGLTexture::setData(int xOffset, int yOffset, int zOffset,
3633                              int width, int height, int depth,
3634                              int mipLevel, int layer,
3635                              CubeMapFace face, int layerCount,
3636                              PixelFormat sourceFormat, PixelType sourceType,
3637                              const void *data, const QOpenGLPixelTransferOptions * const options)
3638 {
3639     Q_D(QOpenGLTexture);
3640     Q_ASSERT(d->textureId);
3641     d->setData(xOffset, yOffset, zOffset,
3642                width, height, depth,
3643                mipLevel, layer, layerCount,
3644                face, sourceFormat,
3645                sourceType, data, options);
3646 }
3647 
3648 #if QT_DEPRECATED_SINCE(5, 3)
3649 /*!
3650     \obsolete
3651     \overload
3652 
3653     \sa setCompressedData()
3654 */
setData(int mipLevel,int layer,CubeMapFace cubeFace,PixelFormat sourceFormat,PixelType sourceType,void * data,const QOpenGLPixelTransferOptions * const options)3655 void QOpenGLTexture::setData(int mipLevel, int layer, CubeMapFace cubeFace,
3656                              PixelFormat sourceFormat, PixelType sourceType,
3657                              void *data, const QOpenGLPixelTransferOptions * const options)
3658 {
3659     Q_D(QOpenGLTexture);
3660     Q_ASSERT(d->textureId);
3661     if (!isStorageAllocated()) {
3662         qWarning("Cannot set data on a texture that does not have storage allocated.\n"
3663                  "To do so call allocateStorage() before this function");
3664         return;
3665     }
3666     d->setData(mipLevel, layer, 1, cubeFace, sourceFormat, sourceType, data, options);
3667 }
3668 
3669 /*!
3670     \obsolete
3671     \overload
3672 */
setData(int mipLevel,int layer,PixelFormat sourceFormat,PixelType sourceType,void * data,const QOpenGLPixelTransferOptions * const options)3673 void QOpenGLTexture::setData(int mipLevel, int layer,
3674                              PixelFormat sourceFormat, PixelType sourceType,
3675                              void *data, const QOpenGLPixelTransferOptions * const options)
3676 {
3677     Q_D(QOpenGLTexture);
3678     Q_ASSERT(d->textureId);
3679     d->setData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
3680 }
3681 
3682 /*!
3683     \obsolete
3684     \overload
3685 */
setData(int mipLevel,PixelFormat sourceFormat,PixelType sourceType,void * data,const QOpenGLPixelTransferOptions * const options)3686 void QOpenGLTexture::setData(int mipLevel,
3687                              PixelFormat sourceFormat, PixelType sourceType,
3688                              void *data, const QOpenGLPixelTransferOptions * const options)
3689 {
3690     Q_D(QOpenGLTexture);
3691     Q_ASSERT(d->textureId);
3692     d->setData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
3693 }
3694 
3695 /*!
3696     \obsolete
3697     \overload
3698 */
setData(PixelFormat sourceFormat,PixelType sourceType,void * data,const QOpenGLPixelTransferOptions * const options)3699 void QOpenGLTexture::setData(PixelFormat sourceFormat, PixelType sourceType,
3700                              void *data, const QOpenGLPixelTransferOptions * const options)
3701 {
3702     Q_D(QOpenGLTexture);
3703     Q_ASSERT(d->textureId);
3704     d->setData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, sourceFormat, sourceType, data, options);
3705 }
3706 #endif
3707 
3708 /*!
3709     This overload of setData() will allocate storage for you.
3710     The pixel data is contained in \a image. Mipmaps are generated by default.
3711     Set \a genMipMaps to \l DontGenerateMipMaps to turn off mipmap generation.
3712 
3713     \overload
3714 */
setData(const QImage & image,MipMapGeneration genMipMaps)3715 void QOpenGLTexture::setData(const QImage& image, MipMapGeneration genMipMaps)
3716 {
3717     QOpenGLContext *context = QOpenGLContext::currentContext();
3718     if (!context) {
3719         qWarning("QOpenGLTexture::setData() requires a valid current context");
3720         return;
3721     }
3722 
3723     if (image.isNull()) {
3724         qWarning("QOpenGLTexture::setData() tried to set a null image");
3725         return;
3726     }
3727 
3728     if (context->isOpenGLES() && context->format().majorVersion() < 3)
3729         setFormat(QOpenGLTexture::RGBAFormat);
3730     else
3731         setFormat(QOpenGLTexture::RGBA8_UNorm);
3732 
3733     setSize(image.width(), image.height());
3734     setMipLevels(genMipMaps == GenerateMipMaps ? maximumMipLevels() : 1);
3735     allocateStorage(QOpenGLTexture::RGBA, QOpenGLTexture::UInt8);
3736 
3737     // Upload pixel data and generate mipmaps
3738     QImage glImage = image.convertToFormat(QImage::Format_RGBA8888);
3739     QOpenGLPixelTransferOptions uploadOptions;
3740     uploadOptions.setAlignment(1);
3741     setData(0, QOpenGLTexture::RGBA, QOpenGLTexture::UInt8, glImage.constBits(), &uploadOptions);
3742 }
3743 
3744 /*!
3745     Uploads compressed pixel \a data to \a mipLevel, array \a layer, and \a cubeFace.
3746     The pixel transfer can optionally be controlled with \a options. The \a dataSize
3747     argument should specify the size of the data pointed to by \a data.
3748 
3749     If not using a compressed format() then you should use setData() instead of this
3750     function.
3751 
3752     \since 5.3
3753 */
setCompressedData(int mipLevel,int layer,CubeMapFace cubeFace,int dataSize,const void * data,const QOpenGLPixelTransferOptions * const options)3754 void QOpenGLTexture::setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace,
3755                                        int dataSize, const void *data,
3756                                        const QOpenGLPixelTransferOptions * const options)
3757 {
3758     Q_D(QOpenGLTexture);
3759     Q_ASSERT(d->textureId);
3760     if (!isStorageAllocated()) {
3761         qWarning("Cannot set data on a texture that does not have storage allocated.\n"
3762                  "To do so call allocateStorage() before this function");
3763         return;
3764     }
3765     d->setCompressedData(mipLevel, layer, 1, cubeFace, dataSize, data, options);
3766 }
3767 
3768 /*!
3769     \since 5.9
3770     \overload
3771 
3772     Parameter \a layerCount is the number of layers in a texture array
3773     that are being uploaded/populated by this call.
3774 */
setCompressedData(int mipLevel,int layer,int layerCount,QOpenGLTexture::CubeMapFace cubeFace,int dataSize,const void * data,const QOpenGLPixelTransferOptions * const options)3775 void QOpenGLTexture::setCompressedData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace, int dataSize, const void *data, const QOpenGLPixelTransferOptions * const options)
3776 {
3777     Q_D(QOpenGLTexture);
3778     Q_ASSERT(d->textureId);
3779     if (!isStorageAllocated()) {
3780         qWarning("Cannot set data on a texture that does not have storage allocated.\n"
3781                  "To do so call allocateStorage() before this function");
3782         return;
3783     }
3784     d->setCompressedData(mipLevel, layer, layerCount, cubeFace, dataSize, data, options);
3785 }
3786 
3787 /*!
3788     \overload
3789 */
setCompressedData(int mipLevel,int layer,int dataSize,const void * data,const QOpenGLPixelTransferOptions * const options)3790 void QOpenGLTexture::setCompressedData(int mipLevel, int layer, int dataSize, const void *data,
3791                                        const QOpenGLPixelTransferOptions * const options)
3792 {
3793     Q_D(QOpenGLTexture);
3794     Q_ASSERT(d->textureId);
3795     d->setCompressedData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
3796 }
3797 
3798 /*!
3799     \overload
3800 */
setCompressedData(int mipLevel,int dataSize,const void * data,const QOpenGLPixelTransferOptions * const options)3801 void QOpenGLTexture::setCompressedData(int mipLevel, int dataSize, const void *data,
3802                                        const QOpenGLPixelTransferOptions * const options)
3803 {
3804     Q_D(QOpenGLTexture);
3805     Q_ASSERT(d->textureId);
3806     d->setCompressedData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
3807 }
3808 
3809 /*!
3810     \overload
3811 */
setCompressedData(int dataSize,const void * data,const QOpenGLPixelTransferOptions * const options)3812 void QOpenGLTexture::setCompressedData(int dataSize, const void *data,
3813                                        const QOpenGLPixelTransferOptions * const options)
3814 {
3815     Q_D(QOpenGLTexture);
3816     Q_ASSERT(d->textureId);
3817     d->setCompressedData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
3818 }
3819 
3820 #if QT_DEPRECATED_SINCE(5, 3)
3821 /*!
3822     \obsolete
3823     \overload
3824 */
setCompressedData(int mipLevel,int layer,CubeMapFace cubeFace,int dataSize,void * data,const QOpenGLPixelTransferOptions * const options)3825 void QOpenGLTexture::setCompressedData(int mipLevel, int layer, CubeMapFace cubeFace,
3826                                        int dataSize, void *data,
3827                                        const QOpenGLPixelTransferOptions * const options)
3828 {
3829     Q_D(QOpenGLTexture);
3830     Q_ASSERT(d->textureId);
3831     if (!isStorageAllocated()) {
3832         qWarning("Cannot set data on a texture that does not have storage allocated.\n"
3833                  "To do so call allocateStorage() before this function");
3834         return;
3835     }
3836     d->setCompressedData(mipLevel, layer, 1, cubeFace, dataSize, data, options);
3837 }
3838 
3839 /*!
3840     \obsolete
3841     \overload
3842 */
setCompressedData(int mipLevel,int layer,int dataSize,void * data,const QOpenGLPixelTransferOptions * const options)3843 void QOpenGLTexture::setCompressedData(int mipLevel, int layer, int dataSize, void *data,
3844                                        const QOpenGLPixelTransferOptions * const options)
3845 {
3846     Q_D(QOpenGLTexture);
3847     Q_ASSERT(d->textureId);
3848     d->setCompressedData(mipLevel, layer, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
3849 }
3850 
3851 /*!
3852     \obsolete
3853     \overload
3854 */
setCompressedData(int mipLevel,int dataSize,void * data,const QOpenGLPixelTransferOptions * const options)3855 void QOpenGLTexture::setCompressedData(int mipLevel, int dataSize, void *data,
3856                                        const QOpenGLPixelTransferOptions * const options)
3857 {
3858     Q_D(QOpenGLTexture);
3859     Q_ASSERT(d->textureId);
3860     d->setCompressedData(mipLevel, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
3861 }
3862 
3863 /*!
3864     \obsolete
3865     \overload
3866 */
setCompressedData(int dataSize,void * data,const QOpenGLPixelTransferOptions * const options)3867 void QOpenGLTexture::setCompressedData(int dataSize, void *data,
3868                                        const QOpenGLPixelTransferOptions * const options)
3869 {
3870     Q_D(QOpenGLTexture);
3871     Q_ASSERT(d->textureId);
3872     d->setCompressedData(0, 0, 1, QOpenGLTexture::CubeMapPositiveX, dataSize, data, options);
3873 }
3874 #endif
3875 
3876 /*!
3877     Returns \c true if your OpenGL implementation and version supports the texture
3878     feature \a feature.
3879 */
hasFeature(Feature feature)3880 bool QOpenGLTexture::hasFeature(Feature feature)
3881 {
3882     QOpenGLContext *ctx = QOpenGLContext::currentContext();
3883     if (!ctx) {
3884         qWarning("QOpenGLTexture::hasFeature() requires a valid current context");
3885         return false;
3886     }
3887 
3888     QSurfaceFormat f = ctx->format();
3889 
3890     bool supported = false;
3891 
3892 #if !defined(QT_OPENGL_ES_2)
3893     if (!ctx->isOpenGLES()) {
3894         switch (feature) {
3895         case ImmutableMultisampleStorage:
3896             supported = f.version() >= qMakePair(4, 3)
3897                     || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_storage_multisample"));
3898             break;
3899 
3900         case TextureBuffer:
3901             supported = f.version() >= qMakePair(3, 0)
3902                     || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_buffer_object"));
3903             break;
3904 
3905         case StencilTexturing:
3906             supported = f.version() >= qMakePair(4, 3)
3907                     || ctx->hasExtension(QByteArrayLiteral("GL_ARB_stencil_texturing"));
3908             break;
3909 
3910         case ImmutableStorage:
3911             supported = f.version() >= qMakePair(4, 2)
3912                     || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_storage"))
3913                     || ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_storage"));
3914             break;
3915 
3916         case TextureCubeMapArrays:
3917             supported = f.version() >= qMakePair(4, 0)
3918                     || ctx->hasExtension(QByteArrayLiteral("ARB_texture_cube_map_array"));
3919             break;
3920 
3921         case Swizzle:
3922             supported = f.version() >= qMakePair(3, 3)
3923                     || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_swizzle"));
3924             break;
3925 
3926         case TextureMultisample:
3927             supported = f.version() >= qMakePair(3, 2)
3928                     || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_multisample"));
3929             break;
3930 
3931         case TextureArrays:
3932             supported = f.version() >= qMakePair(3, 0)
3933                     || ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_array"));
3934             break;
3935 
3936         case TextureRectangle:
3937             supported = f.version() >= qMakePair(2, 1)
3938                     || ctx->hasExtension(QByteArrayLiteral("ARB_texture_rectangle"));
3939             break;
3940 
3941         case Texture3D:
3942             supported = f.version() >= qMakePair(1, 3);
3943             break;
3944 
3945         case AnisotropicFiltering:
3946             supported = ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_filter_anisotropic"));
3947             break;
3948 
3949         case NPOTTextures:
3950         case NPOTTextureRepeat:
3951             supported = ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two"));
3952             break;
3953 
3954         case Texture1D:
3955             supported = f.version() >= qMakePair(1, 1);
3956             break;
3957 
3958         case TextureComparisonOperators:
3959             // GL 1.4 and GL_ARB_shadow alone support only LEQUAL and GEQUAL;
3960             // since we're talking about history anyhow avoid to be extra pedantic
3961             // in the feature set, and simply claim supported if we have the full set of operators
3962             // (which has been added into 1.5 / GL_EXT_shadow_funcs).
3963             supported = f.version() >= qMakePair(1, 5)
3964                     || (ctx->hasExtension(QByteArrayLiteral("GL_ARB_shadow"))
3965                         && ctx->hasExtension(QByteArrayLiteral("GL_EXT_shadow_funcs")));
3966             break;
3967 
3968         case TextureMipMapLevel:
3969             supported = f.version() >= qMakePair(1, 2);
3970             break;
3971 
3972         case MaxFeatureFlag:
3973             break;
3974         }
3975     }
3976 
3977     if (ctx->isOpenGLES())
3978 #endif
3979     {
3980         const char *renderer = reinterpret_cast<const char *>(ctx->functions()->glGetString(GL_RENDERER));
3981         switch (feature) {
3982         case ImmutableStorage:
3983             supported = (f.version() >= qMakePair(3, 0) || ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_storage")))
3984                 && !(renderer && strstr(renderer, "Mali")); // do not use on Mali: QTBUG-45106
3985             break;
3986 
3987         case ImmutableMultisampleStorage:
3988             supported = f.version() >= qMakePair(3, 1);
3989             break;
3990 
3991         case TextureRectangle:
3992             break;
3993 
3994         case TextureArrays:
3995             supported = f.version() >= qMakePair(3, 0);
3996             break;
3997 
3998         case Texture3D:
3999             supported = f.version() >= qMakePair(3, 0)
4000                     || ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_3D"));
4001             break;
4002 
4003         case TextureMultisample:
4004             supported = f.version() >= qMakePair(3, 1);
4005             break;
4006 
4007         case TextureBuffer:
4008             break;
4009 
4010         case TextureCubeMapArrays:
4011             break;
4012 
4013         case Swizzle:
4014             supported = f.version() >= qMakePair(3, 0);
4015             break;
4016 
4017         case StencilTexturing:
4018             break;
4019 
4020         case AnisotropicFiltering:
4021             supported = ctx->hasExtension(QByteArrayLiteral("GL_EXT_texture_filter_anisotropic"));
4022             break;
4023 
4024         case NPOTTextures:
4025         case NPOTTextureRepeat:
4026             supported = f.version() >= qMakePair(3,0)
4027                     || ctx->hasExtension(QByteArrayLiteral("GL_OES_texture_npot"))
4028                     || ctx->hasExtension(QByteArrayLiteral("GL_ARB_texture_non_power_of_two"));
4029             break;
4030 
4031         case Texture1D:
4032             break;
4033 
4034         case TextureComparisonOperators:
4035             supported = f.version() >= qMakePair(3, 0)
4036                     || ctx->hasExtension(QByteArrayLiteral("GL_EXT_shadow_samplers"));
4037             break;
4038 
4039         case TextureMipMapLevel:
4040             supported = f.version() >= qMakePair(3, 0);
4041             break;
4042 
4043         case MaxFeatureFlag:
4044             break;
4045         }
4046     }
4047 
4048     return supported;
4049 }
4050 
4051 /*!
4052     Sets the base mipmap level used for all texture lookups with this texture to \a baseLevel.
4053 
4054     \note This function has no effect on Qt built for OpenGL ES 2.
4055     \sa mipBaseLevel(), setMipMaxLevel(), setMipLevelRange()
4056 */
setMipBaseLevel(int baseLevel)4057 void QOpenGLTexture::setMipBaseLevel(int baseLevel)
4058 {
4059     Q_D(QOpenGLTexture);
4060     d->create();
4061     if (!d->features.testFlag(TextureMipMapLevel)) {
4062         qWarning("QOpenGLTexture::setMipBaseLevel: requires OpenGL >= 1.2 or OpenGL ES >= 3.0");
4063         return;
4064     }
4065     Q_ASSERT(d->textureId);
4066     Q_ASSERT(d->texFuncs);
4067     Q_ASSERT(baseLevel <= d->maxLevel);
4068     d->baseLevel = baseLevel;
4069     d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BASE_LEVEL, baseLevel);
4070 }
4071 
4072 /*!
4073     Returns the mipmap base level used for all texture lookups with this texture.
4074     The default is 0.
4075 
4076     \sa setMipBaseLevel(), mipMaxLevel(), mipLevelRange()
4077 */
mipBaseLevel() const4078 int QOpenGLTexture::mipBaseLevel() const
4079 {
4080     Q_D(const QOpenGLTexture);
4081     return d->baseLevel;
4082 }
4083 
4084 /*!
4085     Sets the maximum mipmap level used for all texture lookups with this texture to \a maxLevel.
4086 
4087     \note This function has no effect on Qt built for OpenGL ES 2.
4088     \sa mipMaxLevel(), setMipBaseLevel(), setMipLevelRange()
4089 */
setMipMaxLevel(int maxLevel)4090 void QOpenGLTexture::setMipMaxLevel(int maxLevel)
4091 {
4092     Q_D(QOpenGLTexture);
4093     d->create();
4094     if (!d->features.testFlag(TextureMipMapLevel)) {
4095         qWarning("QOpenGLTexture::setMipMaxLevel: requires OpenGL >= 1.2 or OpenGL ES >= 3.0");
4096         return;
4097     }
4098     Q_ASSERT(d->textureId);
4099     Q_ASSERT(d->texFuncs);
4100     Q_ASSERT(d->baseLevel <= maxLevel);
4101     d->maxLevel = maxLevel;
4102     d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LEVEL, maxLevel);
4103 }
4104 
4105 /*!
4106     Returns the mipmap maximum level used for all texture lookups with this texture.
4107 
4108     \sa setMipMaxLevel(), mipBaseLevel(), mipLevelRange()
4109 */
mipMaxLevel() const4110 int QOpenGLTexture::mipMaxLevel() const
4111 {
4112     Q_D(const QOpenGLTexture);
4113     return d->maxLevel;
4114 }
4115 
4116 /*!
4117     Sets the range of mipmap levels that can be used for texture lookups with this texture
4118     to range from \a baseLevel to \a maxLevel.
4119 
4120     \note This function has no effect on Qt built for OpenGL ES 2.
4121     \sa setMipBaseLevel(), setMipMaxLevel(), mipLevelRange()
4122 */
setMipLevelRange(int baseLevel,int maxLevel)4123 void QOpenGLTexture::setMipLevelRange(int baseLevel, int maxLevel)
4124 {
4125     Q_D(QOpenGLTexture);
4126     d->create();
4127     if (!d->features.testFlag(TextureMipMapLevel)) {
4128         qWarning("QOpenGLTexture::setMipLevelRange: requires OpenGL >= 1.2 or OpenGL ES >= 3.0");
4129         return;
4130     }
4131     Q_ASSERT(d->textureId);
4132     Q_ASSERT(d->texFuncs);
4133     Q_ASSERT(baseLevel <= maxLevel);
4134     d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BASE_LEVEL, baseLevel);
4135     d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LEVEL, maxLevel);
4136 }
4137 
4138 /*!
4139     Returns the range of mipmap levels that can be used for texture lookups with this texture.
4140 
4141     \sa mipBaseLevel(), mipMaxLevel()
4142 */
mipLevelRange() const4143 QPair<int, int> QOpenGLTexture::mipLevelRange() const
4144 {
4145     Q_D(const QOpenGLTexture);
4146     return qMakePair(d->baseLevel, d->maxLevel);
4147 }
4148 
4149 /*!
4150     If \a enabled is \c true, enables automatic mipmap generation for this texture object
4151     to occur whenever the level 0 mipmap data is set via setData().
4152 
4153     The automatic mipmap generation is enabled by default.
4154 
4155     \note Mipmap generation is not supported for compressed textures with OpenGL ES 2.0.
4156 
4157     \sa isAutoMipMapGenerationEnabled(), generateMipMaps()
4158 */
setAutoMipMapGenerationEnabled(bool enabled)4159 void QOpenGLTexture::setAutoMipMapGenerationEnabled(bool enabled)
4160 {
4161     Q_D(QOpenGLTexture);
4162     d->autoGenerateMipMaps = enabled;
4163 }
4164 
4165 /*!
4166     Returns whether auto mipmap generation is enabled for this texture object.
4167 
4168     \sa setAutoMipMapGenerationEnabled(), generateMipMaps()
4169 */
isAutoMipMapGenerationEnabled() const4170 bool QOpenGLTexture::isAutoMipMapGenerationEnabled() const
4171 {
4172     Q_D(const QOpenGLTexture);
4173     return d->autoGenerateMipMaps;
4174 }
4175 
4176 /*!
4177     Generates mipmaps for this texture object from mipmap level 0. If you are
4178     using a texture target and filtering option that requires mipmaps and you
4179     have disabled automatic mipmap generation then you need to call this function
4180     or the overload to create the mipmap chain.
4181 
4182     \note Mipmap generation is not supported for compressed textures with OpenGL ES.
4183 
4184     \sa setAutoMipMapGenerationEnabled(), setMipLevels(), mipLevels()
4185 */
generateMipMaps()4186 void QOpenGLTexture::generateMipMaps()
4187 {
4188     Q_D(QOpenGLTexture);
4189     Q_ASSERT(d->texFuncs);
4190     Q_ASSERT(d->textureId);
4191     if (isCompressedFormat(d->format)) {
4192         if (QOpenGLContext *ctx = QOpenGLContext::currentContext())
4193             if (ctx->isOpenGLES())
4194                 return;
4195     }
4196     d->texFuncs->glGenerateTextureMipmap(d->textureId, d->target, d->bindingTarget);
4197 }
4198 
4199 /*!
4200     Generates mipmaps for this texture object from mipmap level \a baseLevel. If you are
4201     using a texture target and filtering option that requires mipmaps and you
4202     have disabled automatic mipmap generation then you need to call this function
4203     or the overload to create the mipmap chain.
4204 
4205     The generation of mipmaps to above \a baseLevel is achieved by setting the mipmap
4206     base level to \a baseLevel and then generating the mipmap chain. If \a resetBaseLevel
4207     is \c true, then the baseLevel of the texture will be reset to its previous value.
4208 
4209     \sa setAutoMipMapGenerationEnabled(), setMipLevels(), mipLevels()
4210 */
generateMipMaps(int baseLevel,bool resetBaseLevel)4211 void QOpenGLTexture::generateMipMaps(int baseLevel, bool resetBaseLevel)
4212 {
4213     Q_D(QOpenGLTexture);
4214     Q_ASSERT(d->texFuncs);
4215     Q_ASSERT(d->textureId);
4216     if (isCompressedFormat(d->format)) {
4217         if (QOpenGLContext *ctx = QOpenGLContext::currentContext())
4218             if (ctx->isOpenGLES())
4219                 return;
4220     }
4221     int oldBaseLevel;
4222     if (resetBaseLevel)
4223         oldBaseLevel = mipBaseLevel();
4224     setMipBaseLevel(baseLevel);
4225     d->texFuncs->glGenerateTextureMipmap(d->textureId, d->target, d->bindingTarget);
4226     if (resetBaseLevel)
4227         setMipBaseLevel(oldBaseLevel);
4228 }
4229 
4230 /*!
4231     GLSL shaders are able to reorder the components of the vec4 returned by texture
4232     functions. It is also desirable to be able to control this reordering from CPU
4233     side code. This is made possible by swizzle masks since OpenGL 3.3.
4234 
4235     Each component of the texture can be mapped to one of the SwizzleValue options.
4236 
4237     This function maps \a component to the output \a value.
4238 
4239     \note This function has no effect on Mac and Qt built for OpenGL ES 2.
4240     \sa swizzleMask()
4241 */
setSwizzleMask(SwizzleComponent component,SwizzleValue value)4242 void QOpenGLTexture::setSwizzleMask(SwizzleComponent component, SwizzleValue value)
4243 {
4244 #if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2)
4245     if (!QOpenGLContext::currentContext()->isOpenGLES()) {
4246         Q_D(QOpenGLTexture);
4247         d->create();
4248         Q_ASSERT(d->texFuncs);
4249         Q_ASSERT(d->textureId);
4250         if (!d->features.testFlag(Swizzle)) {
4251             qWarning("QOpenGLTexture::setSwizzleMask() requires OpenGL >= 3.3");
4252             return;
4253         }
4254         d->swizzleMask[component - SwizzleRed] = value;
4255         d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, component, value);
4256         return;
4257     }
4258 #else
4259     Q_UNUSED(component);
4260     Q_UNUSED(value);
4261 #endif
4262     qWarning("QOpenGLTexture: Texture swizzling is not supported");
4263 }
4264 
4265 /*!
4266     Parameters \a {r}, \a {g}, \a {b}, and \a {a}  are values used for setting
4267     the colors red, green, blue, and the alpha value.
4268     \overload
4269 */
setSwizzleMask(SwizzleValue r,SwizzleValue g,SwizzleValue b,SwizzleValue a)4270 void QOpenGLTexture::setSwizzleMask(SwizzleValue r, SwizzleValue g,
4271                                     SwizzleValue b, SwizzleValue a)
4272 {
4273 #if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2)
4274     if (!QOpenGLContext::currentContext()->isOpenGLES()) {
4275         Q_D(QOpenGLTexture);
4276         d->create();
4277         Q_ASSERT(d->texFuncs);
4278         Q_ASSERT(d->textureId);
4279         if (!d->features.testFlag(Swizzle)) {
4280             qWarning("QOpenGLTexture::setSwizzleMask() requires OpenGL >= 3.3");
4281             return;
4282         }
4283         GLint swizzleMask[] = {GLint(r), GLint(g), GLint(b), GLint(a)};
4284         d->swizzleMask[0] = r;
4285         d->swizzleMask[1] = g;
4286         d->swizzleMask[2] = b;
4287         d->swizzleMask[3] = a;
4288         d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_SWIZZLE_RGBA, swizzleMask);
4289         return;
4290     }
4291 #else
4292     Q_UNUSED(r);
4293     Q_UNUSED(g);
4294     Q_UNUSED(b);
4295     Q_UNUSED(a);
4296 #endif
4297     qWarning("QOpenGLTexture: Texture swizzling is not supported");
4298 }
4299 
4300 /*!
4301     Returns the swizzle mask for texture \a component.
4302 */
swizzleMask(SwizzleComponent component) const4303 QOpenGLTexture::SwizzleValue QOpenGLTexture::swizzleMask(SwizzleComponent component) const
4304 {
4305     Q_D(const QOpenGLTexture);
4306     return d->swizzleMask[component - SwizzleRed];
4307 }
4308 
4309 /*!
4310     \enum QOpenGLTexture::DepthStencilMode
4311     \since 5.4
4312     This enum specifies which component of a depth/stencil texture is
4313     accessed when the texture is sampled.
4314 
4315     \value DepthMode Equivalent to GL_DEPTH_COMPONENT.
4316     \value StencilMode Equivalent to GL_STENCIL_INDEX.
4317 */
4318 
4319 /*!
4320     If using a texture that has a combined depth/stencil format this function sets
4321     which component of the texture is accessed to \a mode.
4322 
4323     When the parameter is set to DepthMode, then accessing it from the
4324     shader will access the depth component as a single float, as normal. But when
4325     the parameter is set to StencilMode, the shader will access the stencil component.
4326 
4327     \note This function has no effect on Mac and Qt built for OpenGL ES 2.
4328     \since 5.4
4329     \sa depthStencilMode()
4330 */
setDepthStencilMode(QOpenGLTexture::DepthStencilMode mode)4331 void QOpenGLTexture::setDepthStencilMode(QOpenGLTexture::DepthStencilMode mode)
4332 {
4333 #if !defined(Q_OS_MAC) && !defined(QT_OPENGL_ES_2)
4334     if (!QOpenGLContext::currentContext()->isOpenGLES()) {
4335         Q_D(QOpenGLTexture);
4336         d->create();
4337         Q_ASSERT(d->texFuncs);
4338         Q_ASSERT(d->textureId);
4339         if (!d->features.testFlag(StencilTexturing)) {
4340             qWarning("QOpenGLTexture::setDepthStencilMode() requires OpenGL >= 4.3 or GL_ARB_stencil_texturing");
4341             return;
4342         }
4343         d->depthStencilMode = mode;
4344         d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_DEPTH_STENCIL_TEXTURE_MODE, mode);
4345         return;
4346     }
4347 #else
4348     Q_UNUSED(mode);
4349 #endif
4350     qWarning("QOpenGLTexture: DepthStencil Mode is not supported");
4351 }
4352 
4353 /*!
4354     Returns the depth stencil mode for textures using a combined depth/stencil format.
4355 
4356     \since 5.4
4357     \sa setDepthStencilMode()
4358 */
depthStencilMode() const4359 QOpenGLTexture::DepthStencilMode QOpenGLTexture::depthStencilMode() const
4360 {
4361     Q_D(const QOpenGLTexture);
4362     return d->depthStencilMode;
4363 }
4364 
4365 /*!
4366     \enum QOpenGLTexture::ComparisonFunction
4367     \since 5.5
4368     This enum specifies which comparison operator is used when texture comparison
4369     is enabled on this texture.
4370 
4371     \value CompareLessEqual Equivalent to GL_LEQUAL.
4372     \value CompareGreaterEqual Equivalent to GL_GEQUAL.
4373     \value CompareLess Equivalent to GL_LESS.
4374     \value CompareGreater Equivalent to GL_GREATER.
4375     \value CompareEqual Equivalent to GL_EQUAL.
4376     \value CommpareNotEqual Equivalent to GL_NOTEQUAL.
4377     \value CompareAlways Equivalent to GL_ALWAYS.
4378     \value CompareNever Equivalent to GL_NEVER.
4379 
4380 */
4381 
4382 /*!
4383     \since 5.5
4384 
4385     Sets the texture comparison function on this texture to \a function. The texture
4386     comparison function is used by shadow samplers when sampling a depth texture.
4387 
4388     \sa comparisonFunction()
4389 */
setComparisonFunction(QOpenGLTexture::ComparisonFunction function)4390 void QOpenGLTexture::setComparisonFunction(QOpenGLTexture::ComparisonFunction function)
4391 {
4392     Q_D(QOpenGLTexture);
4393     d->create();
4394     if (!d->features.testFlag(TextureComparisonOperators)) {
4395         qWarning("QOpenGLTexture::setComparisonFunction: requires OpenGL >= 1.5 or OpenGL ES >= 3.0");
4396         return;
4397     }
4398     d->comparisonFunction = function;
4399     d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_COMPARE_FUNC, function);
4400 }
4401 
4402 /*!
4403     \since 5.5
4404 
4405     Returns the texture comparison operator set on this texture. By default, a
4406     texture has a CompareLessEqual comparison function.
4407 
4408     \sa setComparisonFunction()
4409 */
comparisonFunction() const4410 QOpenGLTexture::ComparisonFunction QOpenGLTexture::comparisonFunction() const
4411 {
4412     Q_D(const QOpenGLTexture);
4413     return d->comparisonFunction;
4414 }
4415 
4416 /*!
4417     \enum QOpenGLTexture::ComparisonMode
4418     \since 5.5
4419     This enum specifies which comparison mode is used when sampling this texture.
4420 
4421     \value CompareRefToTexture Equivalent to GL_COMPARE_REF_TO_TEXTURE.
4422     \value CompareNone Equivalent to GL_NONE.
4423 */
4424 
4425 /*!
4426     \since 5.5
4427 
4428     Sets the texture comparison mode on this texture to \a mode. The texture
4429     comparison mode is used by shadow samplers when sampling a depth texture.
4430 
4431     \sa comparisonMode()
4432 */
setComparisonMode(QOpenGLTexture::ComparisonMode mode)4433 void QOpenGLTexture::setComparisonMode(QOpenGLTexture::ComparisonMode mode)
4434 {
4435     Q_D(QOpenGLTexture);
4436     d->create();
4437     if (!d->features.testFlag(TextureComparisonOperators)) {
4438         qWarning("QOpenGLTexture::setComparisonMode: requires OpenGL >= 1.5 or OpenGL ES >= 3.0");
4439         return;
4440     }
4441     d->comparisonMode = mode;
4442     d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_COMPARE_MODE, mode);
4443 }
4444 
4445 /*!
4446     \since 5.5
4447 
4448     Returns the texture comparison mode set on this texture. By default, a
4449     texture has a CompareNone comparison mode (i.e. comparisons are disabled).
4450 
4451     \sa setComparisonMode()
4452 */
comparisonMode() const4453 QOpenGLTexture::ComparisonMode QOpenGLTexture::comparisonMode() const
4454 {
4455     Q_D(const QOpenGLTexture);
4456     return d->comparisonMode;
4457 }
4458 
4459 /*!
4460     Sets the filter used for minification to \a filter.
4461 
4462     \sa minificationFilter(), setMagnificationFilter(), setMinMagFilters()
4463 */
setMinificationFilter(QOpenGLTexture::Filter filter)4464 void QOpenGLTexture::setMinificationFilter(QOpenGLTexture::Filter filter)
4465 {
4466     Q_D(QOpenGLTexture);
4467     d->create();
4468     Q_ASSERT(d->texFuncs);
4469     Q_ASSERT(d->textureId);
4470     d->minFilter = filter;
4471     d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_FILTER, filter);
4472 }
4473 
4474 /*!
4475     Returns the minification filter.
4476 
4477     \sa setMinificationFilter()
4478 */
minificationFilter() const4479 QOpenGLTexture::Filter QOpenGLTexture::minificationFilter() const
4480 {
4481     Q_D(const QOpenGLTexture);
4482     return d->minFilter;
4483 }
4484 
4485 /*!
4486     Sets the magnification filter to \a filter.
4487 
4488     \sa magnificationFilter(), setMinificationFilter(), setMinMagFilters()
4489 */
setMagnificationFilter(QOpenGLTexture::Filter filter)4490 void QOpenGLTexture::setMagnificationFilter(QOpenGLTexture::Filter filter)
4491 {
4492     Q_D(QOpenGLTexture);
4493     d->create();
4494     Q_ASSERT(d->texFuncs);
4495     Q_ASSERT(d->textureId);
4496     d->magFilter = filter;
4497     d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAG_FILTER, filter);
4498 }
4499 
4500 /*!
4501     Returns the magnification filter.
4502 
4503     \sa setMagnificationFilter()
4504 */
magnificationFilter() const4505 QOpenGLTexture::Filter QOpenGLTexture::magnificationFilter() const
4506 {
4507     Q_D(const QOpenGLTexture);
4508     return d->magFilter;
4509 }
4510 
4511 /*!
4512     Sets the minification filter to \a minificationFilter and the magnification filter
4513     to \a magnificationFilter.
4514 
4515     \sa minMagFilters(), setMinificationFilter(), setMagnificationFilter()
4516 */
setMinMagFilters(QOpenGLTexture::Filter minificationFilter,QOpenGLTexture::Filter magnificationFilter)4517 void QOpenGLTexture::setMinMagFilters(QOpenGLTexture::Filter minificationFilter,
4518                                       QOpenGLTexture::Filter magnificationFilter)
4519 {
4520     Q_D(QOpenGLTexture);
4521     d->create();
4522     Q_ASSERT(d->texFuncs);
4523     Q_ASSERT(d->textureId);
4524     d->minFilter = minificationFilter;
4525     d->magFilter = magnificationFilter;
4526     d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_FILTER, minificationFilter);
4527     d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAG_FILTER, magnificationFilter);
4528 }
4529 
4530 /*!
4531     Returns the current minification and magnification filters.
4532 
4533     \sa setMinMagFilters()
4534 */
minMagFilters() const4535 QPair<QOpenGLTexture::Filter, QOpenGLTexture::Filter> QOpenGLTexture::minMagFilters() const
4536 {
4537     Q_D(const QOpenGLTexture);
4538     return QPair<QOpenGLTexture::Filter, QOpenGLTexture::Filter>(d->minFilter, d->magFilter);
4539 }
4540 
4541 /*!
4542     If your OpenGL implementation supports the GL_EXT_texture_filter_anisotropic extension
4543     this function sets the maximum anisotropy level to \a anisotropy.
4544 
4545     \sa maximumAnisotropy()
4546 */
setMaximumAnisotropy(float anisotropy)4547 void QOpenGLTexture::setMaximumAnisotropy(float anisotropy)
4548 {
4549     Q_D(QOpenGLTexture);
4550     d->create();
4551     Q_ASSERT(d->texFuncs);
4552     Q_ASSERT(d->textureId);
4553     if (!d->features.testFlag(AnisotropicFiltering)) {
4554         qWarning("QOpenGLTexture::setMaximumAnisotropy() requires GL_EXT_texture_filter_anisotropic");
4555         return;
4556     }
4557     d->maxAnisotropy = anisotropy;
4558     d->texFuncs->glTextureParameteri(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_ANISOTROPY_EXT, anisotropy);
4559 }
4560 
4561 /*!
4562     Returns the maximum level of anisotropy to be accounted for when performing texture lookups.
4563     This requires the GL_EXT_texture_filter_anisotropic extension.
4564 
4565     \sa setMaximumAnisotropy()
4566 */
maximumAnisotropy() const4567 float QOpenGLTexture::maximumAnisotropy() const
4568 {
4569     Q_D(const QOpenGLTexture);
4570     return d->maxAnisotropy;
4571 }
4572 
4573 /*!
4574     Sets the wrap (or repeat mode) for all texture dimentions to \a mode.
4575 
4576     \sa wrapMode()
4577 */
setWrapMode(QOpenGLTexture::WrapMode mode)4578 void QOpenGLTexture::setWrapMode(QOpenGLTexture::WrapMode mode)
4579 {
4580     Q_D(QOpenGLTexture);
4581     d->create();
4582     Q_ASSERT(d->texFuncs);
4583     Q_ASSERT(d->textureId);
4584     d->setWrapMode(mode);
4585 }
4586 
4587 /*!
4588     Holds the texture dimension \a direction.
4589     \overload
4590 */
setWrapMode(QOpenGLTexture::CoordinateDirection direction,QOpenGLTexture::WrapMode mode)4591 void QOpenGLTexture::setWrapMode(QOpenGLTexture::CoordinateDirection direction, QOpenGLTexture::WrapMode mode)
4592 {
4593     Q_D(QOpenGLTexture);
4594     d->create();
4595     Q_ASSERT(d->texFuncs);
4596     Q_ASSERT(d->textureId);
4597     d->setWrapMode(direction, mode);
4598 }
4599 
4600 /*!
4601     Returns the wrap mode for the texture dimension \a direction.
4602 
4603     \sa setWrapMode()
4604 */
wrapMode(QOpenGLTexture::CoordinateDirection direction) const4605 QOpenGLTexture::WrapMode QOpenGLTexture::wrapMode(QOpenGLTexture::CoordinateDirection direction) const
4606 {
4607     Q_D(const QOpenGLTexture);
4608     return d->wrapMode(direction);
4609 }
4610 
4611 /*!
4612     Sets the border color of the texture to \a color.
4613 
4614     \note This function has no effect on Mac and Qt built for OpenGL ES 2.
4615     \sa borderColor()
4616 */
setBorderColor(QColor color)4617 void QOpenGLTexture::setBorderColor(QColor color)
4618 {
4619     setBorderColor(static_cast<float>(color.redF()), static_cast<float>(color.greenF()),
4620                    static_cast<float>(color.blueF()), static_cast<float>(color.alphaF()));
4621 }
4622 
4623 /*!
4624     Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and \a {a} to the
4625     alpha value.
4626     \overload
4627 */
setBorderColor(float r,float g,float b,float a)4628 void QOpenGLTexture::setBorderColor(float r, float g, float b, float a)
4629 {
4630 #if !defined(QT_OPENGL_ES_2)
4631     if (!QOpenGLContext::currentContext()->isOpenGLES()) {
4632         Q_D(QOpenGLTexture);
4633         d->create();
4634         Q_ASSERT(d->texFuncs);
4635         Q_ASSERT(d->textureId);
4636         float values[4];
4637         values[0] = r;
4638         values[1] = g;
4639         values[2] = b;
4640         values[3] = a;
4641         d->borderColor.clear();
4642         for (int i = 0; i < 4; ++i)
4643             d->borderColor.append(QVariant(values[i]));
4644         d->texFuncs->glTextureParameterfv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values);
4645         return;
4646     }
4647 #else
4648     Q_UNUSED(r);
4649     Q_UNUSED(g);
4650     Q_UNUSED(b);
4651     Q_UNUSED(a);
4652 #endif
4653     qWarning("QOpenGLTexture: Border color is not supported");
4654 }
4655 
4656 /*!
4657     Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and the alpha
4658     value to \a {a}.
4659     \overload
4660 */
setBorderColor(int r,int g,int b,int a)4661 void QOpenGLTexture::setBorderColor(int r, int g, int b, int a)
4662 {
4663 #if !defined(QT_OPENGL_ES_2)
4664     if (!QOpenGLContext::currentContext()->isOpenGLES()) {
4665         Q_D(QOpenGLTexture);
4666         d->create();
4667         Q_ASSERT(d->texFuncs);
4668         Q_ASSERT(d->textureId);
4669         int values[4];
4670         values[0] = r;
4671         values[1] = g;
4672         values[2] = b;
4673         values[3] = a;
4674         d->borderColor.clear();
4675         for (int i = 0; i < 4; ++i)
4676             d->borderColor.append(QVariant(values[i]));
4677         d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values);
4678         return;
4679     }
4680 #else
4681     Q_UNUSED(r);
4682     Q_UNUSED(g);
4683     Q_UNUSED(b);
4684     Q_UNUSED(a);
4685 #endif
4686     qWarning("QOpenGLTexture: Border color is not supported");
4687 
4688     // TODO Handle case of using glTextureParameterIiv() based on format
4689 }
4690 
4691 /*!
4692     Sets the color red to \a {r}, green to \a {g}, blue to \a {b}, and the alpha
4693     value to \a {a}.
4694     \overload
4695 */
setBorderColor(uint r,uint g,uint b,uint a)4696 void QOpenGLTexture::setBorderColor(uint r, uint g, uint b, uint a)
4697 {
4698 #if !defined(QT_OPENGL_ES_2)
4699     if (!QOpenGLContext::currentContext()->isOpenGLES()) {
4700         Q_D(QOpenGLTexture);
4701         d->create();
4702         Q_ASSERT(d->texFuncs);
4703         Q_ASSERT(d->textureId);
4704         int values[4];
4705         values[0] = int(r);
4706         values[1] = int(g);
4707         values[2] = int(b);
4708         values[3] = int(a);
4709         d->borderColor.clear();
4710         for (int i = 0; i < 4; ++i)
4711             d->borderColor.append(QVariant(values[i]));
4712         d->texFuncs->glTextureParameteriv(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_BORDER_COLOR, values);
4713         return;
4714     }
4715 #else
4716     Q_UNUSED(r);
4717     Q_UNUSED(g);
4718     Q_UNUSED(b);
4719     Q_UNUSED(a);
4720 #endif
4721     qWarning("QOpenGLTexture: Border color is not supported");
4722 
4723     // TODO Handle case of using glTextureParameterIuiv() based on format
4724 }
4725 
4726 /*!
4727     Returns the borderColor of this texture.
4728 
4729     \sa setBorderColor()
4730 */
borderColor() const4731 QColor QOpenGLTexture::borderColor() const
4732 {
4733     Q_D(const QOpenGLTexture);
4734     QColor c(0.0f, 0.0f, 0.0f, 0.0f);
4735     if (!d->borderColor.isEmpty()) {
4736         c.setRedF(d->borderColor.at(0).toFloat());
4737         c.setGreenF(d->borderColor.at(1).toFloat());
4738         c.setBlueF(d->borderColor.at(2).toFloat());
4739         c.setAlphaF(d->borderColor.at(3).toFloat());
4740     }
4741     return c;
4742 }
4743 
4744 /*!
4745     Writes the texture border color into the first four elements
4746     of the array pointed to by \a border.
4747 
4748     \sa setBorderColor()
4749 */
borderColor(float * border) const4750 void QOpenGLTexture::borderColor(float *border) const
4751 {
4752     Q_D(const QOpenGLTexture);
4753     Q_ASSERT(border);
4754     if (d->borderColor.isEmpty()) {
4755         for (int i = 0; i < 4; ++i)
4756             border[i] = 0.0f;
4757     } else {
4758         for (int i = 0; i < 4; ++i)
4759             border[i] = d->borderColor.at(i).toFloat();
4760     }
4761 }
4762 
4763 /*!
4764     Writes the texture border color into the first four elements
4765     of the array pointed to by \a border.
4766 
4767     \overload
4768 */
borderColor(int * border) const4769 void QOpenGLTexture::borderColor(int *border) const
4770 {
4771     Q_D(const QOpenGLTexture);
4772     Q_ASSERT(border);
4773     if (d->borderColor.isEmpty()) {
4774         for (int i = 0; i < 4; ++i)
4775             border[i] = 0;
4776     } else {
4777         for (int i = 0; i < 4; ++i)
4778             border[i] = d->borderColor.at(i).toInt();
4779     }
4780 }
4781 
4782 /*!
4783     Writes the texture border color into the first four elements
4784     of the array pointed to by \a border.
4785 
4786     \overload
4787 */
borderColor(unsigned int * border) const4788 void QOpenGLTexture::borderColor(unsigned int *border) const
4789 {
4790     Q_D(const QOpenGLTexture);
4791     Q_ASSERT(border);
4792     if (d->borderColor.isEmpty()) {
4793         for (int i = 0; i < 4; ++i)
4794             border[i] = 0;
4795     } else {
4796         for (int i = 0; i < 4; ++i)
4797             border[i] = d->borderColor.at(i).toUInt();
4798     }
4799 }
4800 
4801 /*!
4802     Sets the minimum level of detail to \a value. This limits the selection of highest
4803     resolution mipmap (lowest mipmap level). The default value is -1000.
4804 
4805     \note This function has no effect on Qt built for OpenGL ES 2.
4806     \sa minimumLevelOfDetail(), setMaximumLevelOfDetail(), setLevelOfDetailRange()
4807 */
setMinimumLevelOfDetail(float value)4808 void QOpenGLTexture::setMinimumLevelOfDetail(float value)
4809 {
4810 #if !defined(QT_OPENGL_ES_2)
4811     if (!QOpenGLContext::currentContext()->isOpenGLES()) {
4812         Q_D(QOpenGLTexture);
4813         d->create();
4814         Q_ASSERT(d->texFuncs);
4815         Q_ASSERT(d->textureId);
4816         Q_ASSERT(value < d->maxLevelOfDetail);
4817         d->minLevelOfDetail = value;
4818         d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_LOD, value);
4819         return;
4820     }
4821 #else
4822     Q_UNUSED(value);
4823 #endif
4824     qWarning("QOpenGLTexture: Detail level is not supported");
4825 }
4826 
4827 /*!
4828     Returns the minimum level of detail parameter.
4829 
4830     \sa setMinimumLevelOfDetail(), maximumLevelOfDetail(), levelOfDetailRange()
4831 */
minimumLevelOfDetail() const4832 float QOpenGLTexture::minimumLevelOfDetail() const
4833 {
4834     Q_D(const QOpenGLTexture);
4835     return d->minLevelOfDetail;
4836 }
4837 
4838 /*!
4839     Sets the maximum level of detail to \a value. This limits the selection of lowest
4840     resolution mipmap (highest mipmap level). The default value is 1000.
4841 
4842     \note This function has no effect on Qt built for OpenGL ES 2.
4843     \sa maximumLevelOfDetail(), setMinimumLevelOfDetail(), setLevelOfDetailRange()
4844 */
setMaximumLevelOfDetail(float value)4845 void QOpenGLTexture::setMaximumLevelOfDetail(float value)
4846 {
4847 #if !defined(QT_OPENGL_ES_2)
4848     if (!QOpenGLContext::currentContext()->isOpenGLES()) {
4849         Q_D(QOpenGLTexture);
4850         d->create();
4851         Q_ASSERT(d->texFuncs);
4852         Q_ASSERT(d->textureId);
4853         Q_ASSERT(value > d->minLevelOfDetail);
4854         d->maxLevelOfDetail = value;
4855         d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LOD, value);
4856         return;
4857     }
4858 #else
4859     Q_UNUSED(value);
4860 #endif
4861     qWarning("QOpenGLTexture: Detail level is not supported");
4862 }
4863 
4864 /*!
4865     Returns the maximum level of detail parameter.
4866 
4867     \sa setMaximumLevelOfDetail(), minimumLevelOfDetail(), levelOfDetailRange()
4868 */
maximumLevelOfDetail() const4869 float QOpenGLTexture::maximumLevelOfDetail() const
4870 {
4871     Q_D(const QOpenGLTexture);
4872     return d->maxLevelOfDetail;
4873 }
4874 
4875 /*!
4876     Sets the minimum level of detail parameters to \a min and the maximum level
4877     to \a max.
4878     \note This function has no effect on Qt built for OpenGL ES 2.
4879     \sa levelOfDetailRange(), setMinimumLevelOfDetail(), setMaximumLevelOfDetail()
4880 */
setLevelOfDetailRange(float min,float max)4881 void QOpenGLTexture::setLevelOfDetailRange(float min, float max)
4882 {
4883 #if !defined(QT_OPENGL_ES_2)
4884     if (!QOpenGLContext::currentContext()->isOpenGLES()) {
4885         Q_D(QOpenGLTexture);
4886         d->create();
4887         Q_ASSERT(d->texFuncs);
4888         Q_ASSERT(d->textureId);
4889         Q_ASSERT(min < max);
4890         d->minLevelOfDetail = min;
4891         d->maxLevelOfDetail = max;
4892         d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MIN_LOD, min);
4893         d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_MAX_LOD, max);
4894         return;
4895     }
4896 #else
4897     Q_UNUSED(min);
4898     Q_UNUSED(max);
4899 #endif
4900     qWarning("QOpenGLTexture: Detail level is not supported");
4901 }
4902 
4903 /*!
4904     Returns the minimum and maximum level of detail parameters.
4905 
4906     \sa setLevelOfDetailRange(), minimumLevelOfDetail(), maximumLevelOfDetail()
4907 */
levelOfDetailRange() const4908 QPair<float, float> QOpenGLTexture::levelOfDetailRange() const
4909 {
4910     Q_D(const QOpenGLTexture);
4911     return qMakePair(d->minLevelOfDetail, d->maxLevelOfDetail);
4912 }
4913 
4914 /*!
4915     Sets the level of detail bias to \a bias.
4916     Level of detail bias affects the point at which mipmapping levels change.
4917     Increasing values for level of detail bias makes the overall images blurrier
4918     or smoother. Decreasing values make the overall images sharper.
4919 
4920     \note This function has no effect on Qt built for OpenGL ES 2.
4921     \sa levelofDetailBias()
4922 */
setLevelofDetailBias(float bias)4923 void QOpenGLTexture::setLevelofDetailBias(float bias)
4924 {
4925 #if !defined(QT_OPENGL_ES_2)
4926     if (!QOpenGLContext::currentContext()->isOpenGLES()) {
4927         Q_D(QOpenGLTexture);
4928         d->create();
4929         Q_ASSERT(d->texFuncs);
4930         Q_ASSERT(d->textureId);
4931         d->levelOfDetailBias = bias;
4932         d->texFuncs->glTextureParameterf(d->textureId, d->target, d->bindingTarget, GL_TEXTURE_LOD_BIAS, bias);
4933         return;
4934     }
4935 #else
4936     Q_UNUSED(bias);
4937 #endif
4938     qWarning("QOpenGLTexture: Detail level is not supported");
4939 }
4940 
4941 /*!
4942     Returns the level of detail bias parameter.
4943 
4944     \sa setLevelofDetailBias()
4945 */
levelofDetailBias() const4946 float QOpenGLTexture::levelofDetailBias() const
4947 {
4948     Q_D(const QOpenGLTexture);
4949     return d->levelOfDetailBias;
4950 }
4951 
4952 #ifndef QT_NO_DEBUG_STREAM
operator <<(QDebug debug,const QOpenGLTexture * t)4953 QDebug operator<<(QDebug debug, const QOpenGLTexture *t)
4954 {
4955     QDebugStateSaver saver(debug);
4956     debug.nospace();
4957     debug << "QOpenGLTexture(";
4958     if (t) {
4959         const QOpenGLTexturePrivate *d = t->d_ptr.data();
4960         debug << d->target << ", bindingTarget=" << d->bindingTarget
4961             << ", size=[" << d->dimensions[0]
4962             << ", " << d->dimensions[1];
4963         if (d->target == QOpenGLTexture::Target3D)
4964             debug << ", " << d->dimensions[2];
4965         debug << "], format=" << d->format << ", formatClass=" << d->formatClass;
4966         if (t->isCreated())
4967             debug << ", textureId=" << d->textureId;
4968         if (t->isBound())
4969             debug << ", [bound]";
4970         if (t->isTextureView())
4971             debug << ", [view]";
4972         if (d->fixedSamplePositions)
4973             debug << ", [fixedSamplePositions]";
4974         debug << ", mipLevels=" << d->requestedMipLevels << ", layers=" << d->layers
4975             << ", faces=" << d->faces << ", samples=" << d->samples
4976             << ", depthStencilMode=" << d->depthStencilMode << ", comparisonFunction="
4977             << d->comparisonFunction << ", comparisonMode=" << d->comparisonMode
4978             << ", features=" << d->features << ", minificationFilter=" << d->minFilter
4979             << ", magnificationFilter=" << d->magFilter << ", wrapMode=" << d->wrapModes[0];
4980     } else {
4981         debug << '0';
4982     }
4983     debug << ')';
4984     return debug;
4985 }
4986 #endif // QT_NO_DEBUG_STREAM
4987 
4988 QT_END_NAMESPACE
4989