1/****************************************************************************
2**
3** Copyright (C) 2013 Klaralvdalens Datakonsult AB (KDAB).
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtGui module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qopengltexture.h"
41#include "qopengltexture_p.h"
42#include "qopengltexturehelper_p.h"
43#include "qopenglfunctions.h"
44#include <QtGui/qcolor.h>
45#include <QtGui/qopenglcontext.h>
46#include <QtCore/qdebug.h>
47#include <private/qobject_p.h>
48#include <private/qopenglcontext_p.h>
49
50QT_BEGIN_NAMESPACE
51
52//this is to work around GL_TEXTURE_WRAP_R_OES which also has 0x8072 as value
53#if !defined(GL_TEXTURE_WRAP_R)
54 #define GL_TEXTURE_WRAP_R 0x8072
55#endif
56
57QOpenGLTexturePrivate::QOpenGLTexturePrivate(QOpenGLTexture::Target textureTarget,
58 QOpenGLTexture *qq)
59 : q_ptr(qq),
60 context(0),
61 target(textureTarget),
62 textureId(0),
63 format(QOpenGLTexture::NoFormat),
64 formatClass(QOpenGLTexture::NoFormatClass),
65 requestedMipLevels(1),
66 mipLevels(-1),
67 layers(1),
68 faces(1),
69 samples(0),
70 fixedSamplePositions(true),
71 baseLevel(0),
72 maxLevel(1000),
73 depthStencilMode(QOpenGLTexture::DepthMode),
74 comparisonFunction(QOpenGLTexture::CompareLessEqual),
75 comparisonMode(QOpenGLTexture::CompareNone),
76 minFilter(QOpenGLTexture::Nearest),
77 magFilter(QOpenGLTexture::Nearest),
78 maxAnisotropy(1.0f),
79 minLevelOfDetail(-1000.0f),
80 maxLevelOfDetail(1000.0f),
81 levelOfDetailBias(0.0f),
82 textureView(false),
83 autoGenerateMipMaps(true),
84 storageAllocated(false),
85 texFuncs(0),
86 functions(0)
87{
88 dimensions[0] = dimensions[1] = dimensions[2] = 1;
89
90 switch (target) {
91 case QOpenGLTexture::Target1D:
92 bindingTarget = QOpenGLTexture::BindingTarget1D;
93 break;
94 case QOpenGLTexture::Target1DArray:
95 bindingTarget = QOpenGLTexture::BindingTarget1DArray;
96 break;
97 case QOpenGLTexture::Target2D:
98 bindingTarget = QOpenGLTexture::BindingTarget2D;
99 break;
100 case QOpenGLTexture::Target2DArray:
101 bindingTarget = QOpenGLTexture::BindingTarget2DArray;
102 break;
103 case QOpenGLTexture::Target3D:
104 bindingTarget = QOpenGLTexture::BindingTarget3D;
105 break;
106 case QOpenGLTexture::TargetCubeMap:
107 bindingTarget = QOpenGLTexture::BindingTargetCubeMap;
108 faces = 6;
109 break;
110 case QOpenGLTexture::TargetCubeMapArray:
111 bindingTarget = QOpenGLTexture::BindingTargetCubeMapArray;
112 faces = 6;
113 break;
114 case QOpenGLTexture::Target2DMultisample:
115 bindingTarget = QOpenGLTexture::BindingTarget2DMultisample;
116 break;
117 case QOpenGLTexture::Target2DMultisampleArray:
118 bindingTarget = QOpenGLTexture::BindingTarget2DMultisampleArray;
119 break;
120 case QOpenGLTexture::TargetRectangle:
121 bindingTarget = QOpenGLTexture::BindingTargetRectangle;
122 break;
123 case QOpenGLTexture::TargetBuffer:
124 bindingTarget = QOpenGLTexture::BindingTargetBuffer;
125 break;
126 }
127
128 swizzleMask[0] = QOpenGLTexture::RedValue;
129 swizzleMask[1] = QOpenGLTexture::GreenValue;
130 swizzleMask[2] = QOpenGLTexture::BlueValue;
131 swizzleMask[3] = QOpenGLTexture::AlphaValue;
132
133 wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle
134 ? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat;
135}
136
137QOpenGLTexturePrivate::~QOpenGLTexturePrivate()
138{
139 destroy();
140}
141
142void QOpenGLTexturePrivate::initializeOpenGLFunctions()
143{
144 // If we already have a functions object, there is nothing to do
145 if (texFuncs)
146 return;
147
148 // See if the context already has a suitable resource we can use.
149 // If not create a functions object and add it to the context in case
150 // others wish to use it too
151 texFuncs = context->textureFunctions();
152 if (!texFuncs) {
153 texFuncs = new QOpenGLTextureHelper(context);
154 context->setTextureFunctions(texFuncs);
155 }
156}
157
158bool QOpenGLTexturePrivate::create()
159{
160 if (textureId != 0)
161 return true;
162
163 QOpenGLContext *ctx = QOpenGLContext::currentContext();
164 if (!ctx) {
165 qWarning("Requires a valid current OpenGL context.\n"
166 "Texture has not been created");
167 return false;
168 }
169 context = ctx;
170 functions = ctx->functions();
171
172 // Resolve any functions we will need based upon context version and create the texture
173 initializeOpenGLFunctions();
174
175 // What features do we have?
176 QOpenGLTexture::Feature feature = QOpenGLTexture::ImmutableStorage;
177 while (feature != QOpenGLTexture::MaxFeatureFlag) {
178 if (QOpenGLTexture::hasFeature(feature))
179 features |= feature;
180 feature = static_cast<QOpenGLTexture::Feature>(feature << 1);
181 }
182
183 functions->glGenTextures(1, &textureId);
184 return textureId != 0;
185}
186
187void QOpenGLTexturePrivate::destroy()
188{
189 if (!textureId) {
190 // not created or already destroyed
191 return;
192 }
193 QOpenGLContext *currentContext = QOpenGLContext::currentContext();
194 if (!currentContext) {
195 qWarning("QOpenGLTexturePrivate::destroy() called without a current context.\n"
196 "Texture has not been destroyed");
197 return;
198 }
199 if (!QOpenGLContext::areSharing(currentContext, context)) {
200
201 qWarning("QOpenGLTexturePrivate::destroy() called but texture context %p"
202 " is not shared with current context %p.\n"
203 "Texture has not been destroyed",
204 static_cast<const void *>(context),
205 static_cast<const void *>(currentContext));
206 return;
207 }
208
209 functions->glDeleteTextures(1, &textureId);
210
211 context = 0;
212 functions = 0;
213 textureId = 0;
214 format = QOpenGLTexture::NoFormat;
215 formatClass = QOpenGLTexture::NoFormatClass;
216 requestedMipLevels = 1;
217 mipLevels = -1;
218 layers = 1;
219 faces = 1;
220 samples = 0;
221 fixedSamplePositions = true,
222 baseLevel = 0;
223 maxLevel = 1000;
224 depthStencilMode = QOpenGLTexture::DepthMode;
225 minFilter = QOpenGLTexture::Nearest;
226 magFilter = QOpenGLTexture::Nearest;
227 maxAnisotropy = 1.0f;
228 minLevelOfDetail = -1000.0f;
229 maxLevelOfDetail = 1000.0f;
230 levelOfDetailBias = 0.0f;
231 textureView = false;
232 autoGenerateMipMaps = true;
233 storageAllocated = false;
234 texFuncs = 0;
235
236 swizzleMask[0] = QOpenGLTexture::RedValue;
237 swizzleMask[1] = QOpenGLTexture::GreenValue;
238 swizzleMask[2] = QOpenGLTexture::BlueValue;
239 swizzleMask[3] = QOpenGLTexture::AlphaValue;
240
241 wrapModes[0] = wrapModes[1] = wrapModes[2] = target == QOpenGLTexture::TargetRectangle
242 ? QOpenGLTexture::ClampToEdge : QOpenGLTexture::Repeat;
243}
244
245void QOpenGLTexturePrivate::bind()
246{
247 functions->glBindTexture(target, textureId);
248}
249
250void QOpenGLTexturePrivate::bind(uint unit, QOpenGLTexture::TextureUnitReset reset)
251{
252 GLint oldTextureUnit = 0;
253 if (reset == QOpenGLTexture::ResetTextureUnit)
254 functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
255
256 texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
257 functions->glBindTexture(target, textureId);
258
259 if (reset == QOpenGLTexture::ResetTextureUnit)
260 texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
261}
262
263void QOpenGLTexturePrivate::release()
264{
265 functions->glBindTexture(target, 0);
266}
267
268void QOpenGLTexturePrivate::release(uint unit, QOpenGLTexture::TextureUnitReset reset)
269{
270 GLint oldTextureUnit = 0;
271 if (reset == QOpenGLTexture::ResetTextureUnit)
272 functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
273
274 texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
275 functions->glBindTexture(target, 0);
276
277 if (reset == QOpenGLTexture::ResetTextureUnit)
278 texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
279}
280
281bool QOpenGLTexturePrivate::isBound() const
282{
283 GLint boundTextureId = 0;
284 functions->glGetIntegerv(bindingTarget, &boundTextureId);
285 return (static_cast<GLuint>(boundTextureId) == textureId);
286}
287
288bool QOpenGLTexturePrivate::isBound(uint unit) const
289{
290 GLint oldTextureUnit = 0;
291 functions->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
292
293 GLint boundTextureId = 0;
294 texFuncs->glActiveTexture(GL_TEXTURE0 + unit);
295 functions->glGetIntegerv(bindingTarget, &boundTextureId);
296 bool result = (static_cast<GLuint>(boundTextureId) == textureId);
297
298 texFuncs->glActiveTexture(GL_TEXTURE0 + oldTextureUnit);
299 return result;
300}
301
302int QOpenGLTexturePrivate::evaluateMipLevels() const
303{
304 switch (target) {
305 case QOpenGLTexture::Target1D:
306 case QOpenGLTexture::Target1DArray:
307 case QOpenGLTexture::Target2D:
308 case QOpenGLTexture::Target2DArray:
309 case QOpenGLTexture::Target3D:
310 case QOpenGLTexture::TargetCubeMap:
311 case QOpenGLTexture::TargetCubeMapArray:
312 return qMin(maximumMipLevelCount(), qMax(1, requestedMipLevels));
313
314 case QOpenGLTexture::TargetRectangle:
315 case QOpenGLTexture::Target2DMultisample:
316 case QOpenGLTexture::Target2DMultisampleArray:
317 case QOpenGLTexture::TargetBuffer:
318 default:
319 return 1;
320 }
321}
322
323static bool isSizedTextureFormat(QOpenGLTexture::TextureFormat internalFormat)
324{
325 switch (internalFormat) {
326 case QOpenGLTexture::NoFormat:
327 return false;
328
329 case QOpenGLTexture::R8_UNorm:
330 case QOpenGLTexture::RG8_UNorm:
331 case QOpenGLTexture::RGB8_UNorm:
332 case QOpenGLTexture::RGBA8_UNorm:
333 case QOpenGLTexture::R16_UNorm:
334 case QOpenGLTexture::RG16_UNorm:
335 case QOpenGLTexture::RGB16_UNorm:
336 case QOpenGLTexture::RGBA16_UNorm:
337 case QOpenGLTexture::R8_SNorm:
338 case QOpenGLTexture::RG8_SNorm:
339 case QOpenGLTexture::RGB8_SNorm:
340 case QOpenGLTexture::RGBA8_SNorm:
341 case QOpenGLTexture::R16_SNorm:
342 case QOpenGLTexture::RG16_SNorm:
343 case QOpenGLTexture::RGB16_SNorm:
344 case QOpenGLTexture::RGBA16_SNorm:
345 case QOpenGLTexture::R8U:
346 case QOpenGLTexture::RG8U:
347 case QOpenGLTexture::RGB8U:
348 case QOpenGLTexture::RGBA8U:
349 case QOpenGLTexture::R16U:
350 case QOpenGLTexture::RG16U:
351 case QOpenGLTexture::RGB16U:
352 case QOpenGLTexture::RGBA16U:
353 case QOpenGLTexture::R32U:
354 case QOpenGLTexture::RG32U:
355 case QOpenGLTexture::RGB32U:
356 case QOpenGLTexture::RGBA32U:
357 case QOpenGLTexture::R8I:
358 case QOpenGLTexture::RG8I:
359 case QOpenGLTexture::RGB8I:
360 case QOpenGLTexture::RGBA8I:
361 case QOpenGLTexture::R16I:
362 case QOpenGLTexture::RG16I:
363 case QOpenGLTexture::RGB16I:
364 case QOpenGLTexture::RGBA16I:
365 case QOpenGLTexture::R32I:
366 case QOpenGLTexture::RG32I:
367 case QOpenGLTexture::RGB32I:
368 case QOpenGLTexture::RGBA32I:
369 case QOpenGLTexture::R16F:
370 case QOpenGLTexture::RG16F:
371 case QOpenGLTexture::RGB16F:
372 case QOpenGLTexture::RGBA16F:
373 case QOpenGLTexture::R32F:
374 case QOpenGLTexture::RG32F:
375 case QOpenGLTexture::RGB32F:
376 case QOpenGLTexture::RGBA32F:
377 case QOpenGLTexture::RGB9E5:
378 case QOpenGLTexture::RG11B10F:
379 case QOpenGLTexture::RG3B2:
380 case QOpenGLTexture::R5G6B5:
381 case QOpenGLTexture::RGB5A1:
382 case QOpenGLTexture::RGBA4:
383 case QOpenGLTexture::RGB10A2:
384
385 case QOpenGLTexture::D16:
386 case QOpenGLTexture::D24:
387 case QOpenGLTexture::D32:
388 case QOpenGLTexture::D32F:
389
390 case QOpenGLTexture::D24S8:
391 case QOpenGLTexture::D32FS8X24:
392
393 case QOpenGLTexture::S8:
394
395 case QOpenGLTexture::RGB_DXT1:
396 case QOpenGLTexture::RGBA_DXT1:
397 case QOpenGLTexture::RGBA_DXT3:
398 case QOpenGLTexture::RGBA_DXT5:
399 case QOpenGLTexture::R_ATI1N_UNorm:
400 case QOpenGLTexture::R_ATI1N_SNorm:
401 case QOpenGLTexture::RG_ATI2N_UNorm:
402 case QOpenGLTexture::RG_ATI2N_SNorm:
403 case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
404 case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
405 case QOpenGLTexture::RGB_BP_UNorm:
406 case QOpenGLTexture::SRGB8:
407 case QOpenGLTexture::SRGB8_Alpha8:
408 case QOpenGLTexture::SRGB_DXT1:
409 case QOpenGLTexture::SRGB_Alpha_DXT1:
410 case QOpenGLTexture::SRGB_Alpha_DXT3:
411 case QOpenGLTexture::SRGB_Alpha_DXT5:
412 case QOpenGLTexture::SRGB_BP_UNorm:
413 case QOpenGLTexture::R11_EAC_UNorm:
414 case QOpenGLTexture::R11_EAC_SNorm:
415 case QOpenGLTexture::RG11_EAC_UNorm:
416 case QOpenGLTexture::RG11_EAC_SNorm:
417 case QOpenGLTexture::RGB8_ETC2:
418 case QOpenGLTexture::SRGB8_ETC2:
419 case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
420 case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
421 case QOpenGLTexture::RGBA8_ETC2_EAC:
422 case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
423 case QOpenGLTexture::RGBA_ASTC_4x4:
424 case QOpenGLTexture::RGBA_ASTC_5x4:
425 case QOpenGLTexture::RGBA_ASTC_5x5:
426 case QOpenGLTexture::RGBA_ASTC_6x5:
427 case QOpenGLTexture::RGBA_ASTC_6x6:
428 case QOpenGLTexture::RGBA_ASTC_8x5:
429 case QOpenGLTexture::RGBA_ASTC_8x6:
430 case QOpenGLTexture::RGBA_ASTC_8x8:
431 case QOpenGLTexture::RGBA_ASTC_10x5:
432 case QOpenGLTexture::RGBA_ASTC_10x6:
433 case QOpenGLTexture::RGBA_ASTC_10x8:
434 case QOpenGLTexture::RGBA_ASTC_10x10:
435 case QOpenGLTexture::RGBA_ASTC_12x10:
436 case QOpenGLTexture::RGBA_ASTC_12x12:
437 case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
438 case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
439 case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
440 case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
441 case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
442 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
443 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
444 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
445 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
446 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
447 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
448 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
449 case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
450 case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
451 return true;
452
453 case QOpenGLTexture::RGB8_ETC1:
454 return false;
455
456 case QOpenGLTexture::DepthFormat:
457 case QOpenGLTexture::AlphaFormat:
458
459 case QOpenGLTexture::RGBFormat:
460 case QOpenGLTexture::RGBAFormat:
461
462 case QOpenGLTexture::LuminanceFormat:
463
464 case QOpenGLTexture::LuminanceAlphaFormat:
465 return false;
466 }
467
468 Q_UNREACHABLE();
469 return false;
470}
471
472static bool isTextureTargetMultisample(QOpenGLTexture::Target target)
473{
474 switch (target) {
475 case QOpenGLTexture::Target1D:
476 case QOpenGLTexture::Target1DArray:
477 case QOpenGLTexture::Target2D:
478 case QOpenGLTexture::Target2DArray:
479 case QOpenGLTexture::Target3D:
480 case QOpenGLTexture::TargetCubeMap:
481 case QOpenGLTexture::TargetCubeMapArray:
482 return false;
483
484 case QOpenGLTexture::Target2DMultisample:
485 case QOpenGLTexture::Target2DMultisampleArray:
486 return true;
487
488 case QOpenGLTexture::TargetRectangle:
489 case QOpenGLTexture::TargetBuffer:
490 return false;
491 }
492
493 Q_UNREACHABLE();
494 return false;
495}
496
497bool QOpenGLTexturePrivate::isUsingImmutableStorage() const
498{
499 // Use immutable storage whenever possible, falling back to mutable
500 // Note that if multisample textures are not supported at all, we'll still fail into
501 // the mutable storage allocation
502 return isSizedTextureFormat(format)
503 && (isTextureTargetMultisample(target)
504 ? features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)
505 : features.testFlag(QOpenGLTexture::ImmutableStorage));
506}
507
508void QOpenGLTexturePrivate::allocateStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
509{
510 // Resolve the actual number of mipmap levels we can use
511 mipLevels = evaluateMipLevels();
512
513 if (isUsingImmutableStorage())
514 allocateImmutableStorage();
515 else
516 allocateMutableStorage(pixelFormat, pixelType);
517}
518
519static QOpenGLTexture::PixelFormat pixelFormatCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)
520{
521 switch (internalFormat) {
522 case QOpenGLTexture::NoFormat:
523 return QOpenGLTexture::NoSourceFormat;
524
525 case QOpenGLTexture::R8_UNorm:
526 return QOpenGLTexture::Red;
527
528 case QOpenGLTexture::RG8_UNorm:
529 return QOpenGLTexture::RG;
530
531 case QOpenGLTexture::RGB8_UNorm:
532 return QOpenGLTexture::RGB;
533
534 case QOpenGLTexture::RGBA8_UNorm:
535 return QOpenGLTexture::RGBA;
536
537 case QOpenGLTexture::R16_UNorm:
538 return QOpenGLTexture::Red;
539
540 case QOpenGLTexture::RG16_UNorm:
541 return QOpenGLTexture::RG;
542
543 case QOpenGLTexture::RGB16_UNorm:
544 return QOpenGLTexture::RGB;
545
546 case QOpenGLTexture::RGBA16_UNorm:
547 return QOpenGLTexture::RGBA;
548
549 case QOpenGLTexture::R8_SNorm:
550 return QOpenGLTexture::Red;
551
552 case QOpenGLTexture::RG8_SNorm:
553 return QOpenGLTexture::RG;
554
555 case QOpenGLTexture::RGB8_SNorm:
556 return QOpenGLTexture::RGB;
557
558 case QOpenGLTexture::RGBA8_SNorm:
559 return QOpenGLTexture::RGBA;
560
561 case QOpenGLTexture::R16_SNorm:
562 return QOpenGLTexture::Red;
563
564 case QOpenGLTexture::RG16_SNorm:
565 return QOpenGLTexture::RG;
566
567 case QOpenGLTexture::RGB16_SNorm:
568 return QOpenGLTexture::RGB;
569
570 case QOpenGLTexture::RGBA16_SNorm:
571 return QOpenGLTexture::RGBA;
572
573 case QOpenGLTexture::R8U:
574 return QOpenGLTexture::Red_Integer;
575
576 case QOpenGLTexture::RG8U:
577 return QOpenGLTexture::RG_Integer;
578
579 case QOpenGLTexture::RGB8U:
580 return QOpenGLTexture::RGB_Integer;
581
582 case QOpenGLTexture::RGBA8U:
583 return QOpenGLTexture::RGBA_Integer;
584
585 case QOpenGLTexture::R16U:
586 return QOpenGLTexture::Red_Integer;
587
588 case QOpenGLTexture::RG16U:
589 return QOpenGLTexture::RG_Integer;
590
591 case QOpenGLTexture::RGB16U:
592 return QOpenGLTexture::RGB_Integer;
593
594 case QOpenGLTexture::RGBA16U:
595 return QOpenGLTexture::RGBA_Integer;
596
597 case QOpenGLTexture::R32U:
598 return QOpenGLTexture::Red_Integer;
599
600 case QOpenGLTexture::RG32U:
601 return QOpenGLTexture::RG_Integer;
602
603 case QOpenGLTexture::RGB32U:
604 return QOpenGLTexture::RGB_Integer;
605
606 case QOpenGLTexture::RGBA32U:
607 return QOpenGLTexture::RGBA_Integer;
608
609 case QOpenGLTexture::R8I:
610 return QOpenGLTexture::Red_Integer;
611
612 case QOpenGLTexture::RG8I:
613 return QOpenGLTexture::RG_Integer;
614
615 case QOpenGLTexture::RGB8I:
616 return QOpenGLTexture::RGB_Integer;
617
618 case QOpenGLTexture::RGBA8I:
619 return QOpenGLTexture::RGBA_Integer;
620
621 case QOpenGLTexture::R16I:
622 return QOpenGLTexture::Red_Integer;
623
624 case QOpenGLTexture::RG16I:
625 return QOpenGLTexture::RG_Integer;
626
627 case QOpenGLTexture::RGB16I:
628 return QOpenGLTexture::RGB_Integer;
629
630 case QOpenGLTexture::RGBA16I:
631 return QOpenGLTexture::RGBA_Integer;
632
633 case QOpenGLTexture::R32I:
634 return QOpenGLTexture::Red_Integer;
635
636 case QOpenGLTexture::RG32I:
637 return QOpenGLTexture::RG_Integer;
638
639 case QOpenGLTexture::RGB32I:
640 return QOpenGLTexture::RGB_Integer;
641
642 case QOpenGLTexture::RGBA32I:
643 return QOpenGLTexture::RGBA_Integer;
644
645 case QOpenGLTexture::R16F:
646 return QOpenGLTexture::Red;
647
648 case QOpenGLTexture::RG16F:
649 return QOpenGLTexture::RG;
650
651 case QOpenGLTexture::RGB16F:
652 return QOpenGLTexture::RGB;
653
654 case QOpenGLTexture::RGBA16F:
655 return QOpenGLTexture::RGBA;
656
657 case QOpenGLTexture::R32F:
658 return QOpenGLTexture::Red;
659
660 case QOpenGLTexture::RG32F:
661 return QOpenGLTexture::RG;
662
663 case QOpenGLTexture::RGB32F:
664 return QOpenGLTexture::RGB;
665
666 case QOpenGLTexture::RGBA32F:
667 return QOpenGLTexture::RGBA;
668
669 case QOpenGLTexture::RGB9E5:
670 return QOpenGLTexture::RGB;
671
672 case QOpenGLTexture::RG11B10F:
673 return QOpenGLTexture::RGB;
674
675 case QOpenGLTexture::RG3B2:
676 return QOpenGLTexture::RGB;
677
678 case QOpenGLTexture::R5G6B5:
679 return QOpenGLTexture::RGB;
680
681 case QOpenGLTexture::RGB5A1:
682 return QOpenGLTexture::RGBA;
683
684 case QOpenGLTexture::RGBA4:
685 return QOpenGLTexture::RGBA;
686
687 case QOpenGLTexture::RGB10A2:
688 return QOpenGLTexture::RGBA;
689
690 case QOpenGLTexture::D16:
691 case QOpenGLTexture::D24:
692 case QOpenGLTexture::D32:
693 case QOpenGLTexture::D32F:
694 return QOpenGLTexture::Depth;
695
696 case QOpenGLTexture::D24S8:
697 case QOpenGLTexture::D32FS8X24:
698 return QOpenGLTexture::DepthStencil;
699
700 case QOpenGLTexture::S8:
701 return QOpenGLTexture::Stencil;
702
703 case QOpenGLTexture::RGB_DXT1:
704 case QOpenGLTexture::RGBA_DXT1:
705 case QOpenGLTexture::RGBA_DXT3:
706 case QOpenGLTexture::RGBA_DXT5:
707 case QOpenGLTexture::R_ATI1N_UNorm:
708 case QOpenGLTexture::R_ATI1N_SNorm:
709 case QOpenGLTexture::RG_ATI2N_UNorm:
710 case QOpenGLTexture::RG_ATI2N_SNorm:
711 case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
712 case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
713 case QOpenGLTexture::RGB_BP_UNorm:
714 case QOpenGLTexture::SRGB8:
715 case QOpenGLTexture::SRGB8_Alpha8:
716 case QOpenGLTexture::SRGB_DXT1:
717 case QOpenGLTexture::SRGB_Alpha_DXT1:
718 case QOpenGLTexture::SRGB_Alpha_DXT3:
719 case QOpenGLTexture::SRGB_Alpha_DXT5:
720 case QOpenGLTexture::SRGB_BP_UNorm:
721 case QOpenGLTexture::RGB8_ETC1:
722 return QOpenGLTexture::RGBA;
723
724 case QOpenGLTexture::R11_EAC_UNorm:
725 case QOpenGLTexture::R11_EAC_SNorm:
726 return QOpenGLTexture::Red;
727
728 case QOpenGLTexture::RG11_EAC_UNorm:
729 case QOpenGLTexture::RG11_EAC_SNorm:
730 return QOpenGLTexture::RG;
731
732 case QOpenGLTexture::RGB8_ETC2:
733 case QOpenGLTexture::SRGB8_ETC2:
734 return QOpenGLTexture::RGB;
735
736 case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
737 case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
738 return QOpenGLTexture::RGBA;
739
740 case QOpenGLTexture::RGBA8_ETC2_EAC:
741 case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
742 return QOpenGLTexture::RGBA;
743
744 case QOpenGLTexture::RGBA_ASTC_4x4:
745 case QOpenGLTexture::RGBA_ASTC_5x4:
746 case QOpenGLTexture::RGBA_ASTC_5x5:
747 case QOpenGLTexture::RGBA_ASTC_6x5:
748 case QOpenGLTexture::RGBA_ASTC_6x6:
749 case QOpenGLTexture::RGBA_ASTC_8x5:
750 case QOpenGLTexture::RGBA_ASTC_8x6:
751 case QOpenGLTexture::RGBA_ASTC_8x8:
752 case QOpenGLTexture::RGBA_ASTC_10x5:
753 case QOpenGLTexture::RGBA_ASTC_10x6:
754 case QOpenGLTexture::RGBA_ASTC_10x8:
755 case QOpenGLTexture::RGBA_ASTC_10x10:
756 case QOpenGLTexture::RGBA_ASTC_12x10:
757 case QOpenGLTexture::RGBA_ASTC_12x12:
758 case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
759 case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
760 case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
761 case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
762 case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
763 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
764 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
765 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
766 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
767 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
768 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
769 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
770 case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
771 case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
772 return QOpenGLTexture::RGBA;
773
774 case QOpenGLTexture::DepthFormat:
775 return QOpenGLTexture::Depth;
776
777 case QOpenGLTexture::AlphaFormat:
778 return QOpenGLTexture::Alpha;
779
780 case QOpenGLTexture::RGBFormat:
781 return QOpenGLTexture::RGB;
782
783 case QOpenGLTexture::RGBAFormat:
784 return QOpenGLTexture::RGBA;
785
786 case QOpenGLTexture::LuminanceFormat:
787 return QOpenGLTexture::Luminance;
788
789 case QOpenGLTexture::LuminanceAlphaFormat:
790 return QOpenGLTexture::LuminanceAlpha;
791 }
792
793 Q_UNREACHABLE();
794 return QOpenGLTexture::NoSourceFormat;
795}
796
797static QOpenGLTexture::PixelType pixelTypeCompatibleWithInternalFormat(QOpenGLTexture::TextureFormat internalFormat)
798{
799 switch (internalFormat) {
800 case QOpenGLTexture::NoFormat:
801 return QOpenGLTexture::NoPixelType;
802
803 case QOpenGLTexture::R8_UNorm:
804 case QOpenGLTexture::RG8_UNorm:
805 case QOpenGLTexture::RGB8_UNorm:
806 case QOpenGLTexture::RGBA8_UNorm:
807 case QOpenGLTexture::R16_UNorm:
808 case QOpenGLTexture::RG16_UNorm:
809 case QOpenGLTexture::RGB16_UNorm:
810 case QOpenGLTexture::RGBA16_UNorm:
811 return QOpenGLTexture::UInt8;
812
813 case QOpenGLTexture::R8_SNorm:
814 case QOpenGLTexture::RG8_SNorm:
815 case QOpenGLTexture::RGB8_SNorm:
816 case QOpenGLTexture::RGBA8_SNorm:
817 case QOpenGLTexture::R16_SNorm:
818 case QOpenGLTexture::RG16_SNorm:
819 case QOpenGLTexture::RGB16_SNorm:
820 case QOpenGLTexture::RGBA16_SNorm:
821 return QOpenGLTexture::Int8;
822
823 case QOpenGLTexture::R8U:
824 case QOpenGLTexture::RG8U:
825 case QOpenGLTexture::RGB8U:
826 case QOpenGLTexture::RGBA8U:
827 case QOpenGLTexture::R16U:
828 case QOpenGLTexture::RG16U:
829 case QOpenGLTexture::RGB16U:
830 case QOpenGLTexture::RGBA16U:
831 case QOpenGLTexture::R32U:
832 case QOpenGLTexture::RG32U:
833 case QOpenGLTexture::RGB32U:
834 case QOpenGLTexture::RGBA32U:
835 return QOpenGLTexture::UInt8;
836
837 case QOpenGLTexture::R8I:
838 case QOpenGLTexture::RG8I:
839 case QOpenGLTexture::RGB8I:
840 case QOpenGLTexture::RGBA8I:
841 case QOpenGLTexture::R16I:
842 case QOpenGLTexture::RG16I:
843 case QOpenGLTexture::RGB16I:
844 case QOpenGLTexture::RGBA16I:
845 case QOpenGLTexture::R32I:
846 case QOpenGLTexture::RG32I:
847 case QOpenGLTexture::RGB32I:
848 case QOpenGLTexture::RGBA32I:
849 return QOpenGLTexture::Int8;
850
851 case QOpenGLTexture::R16F:
852 case QOpenGLTexture::RG16F:
853 case QOpenGLTexture::RGB16F:
854 case QOpenGLTexture::RGBA16F:
855 return QOpenGLTexture::Float16;
856
857 case QOpenGLTexture::R32F:
858 case QOpenGLTexture::RG32F:
859 case QOpenGLTexture::RGB32F:
860 case QOpenGLTexture::RGBA32F:
861 return QOpenGLTexture::Float32;
862
863 case QOpenGLTexture::RGB9E5:
864 return QOpenGLTexture::UInt16_RGB5A1_Rev;
865
866 case QOpenGLTexture::RG11B10F:
867 return QOpenGLTexture::UInt32_RG11B10F;
868
869 case QOpenGLTexture::RG3B2:
870 return QOpenGLTexture::UInt8_RG3B2;
871
872 case QOpenGLTexture::R5G6B5:
873 return QOpenGLTexture::UInt16_R5G6B5;
874
875 case QOpenGLTexture::RGB5A1:
876 return QOpenGLTexture::UInt16_RGB5A1;
877
878 case QOpenGLTexture::RGBA4:
879 return QOpenGLTexture::UInt16_RGBA4;
880
881 case QOpenGLTexture::RGB10A2:
882 return QOpenGLTexture::UInt32_RGB10A2;
883
884 case QOpenGLTexture::D16:
885 return QOpenGLTexture::UInt16;
886
887 case QOpenGLTexture::D24:
888 case QOpenGLTexture::D32:
889 return QOpenGLTexture::UInt32;
890
891 case QOpenGLTexture::D32F:
892 return QOpenGLTexture::Float32;
893
894 case QOpenGLTexture::D24S8:
895 return QOpenGLTexture::UInt32_D24S8;
896
897 case QOpenGLTexture::D32FS8X24:
898 return QOpenGLTexture::Float32_D32_UInt32_S8_X24;
899
900 case QOpenGLTexture::S8:
901 return QOpenGLTexture::UInt8;
902
903 case QOpenGLTexture::RGB_DXT1:
904 case QOpenGLTexture::RGBA_DXT1:
905 case QOpenGLTexture::RGBA_DXT3:
906 case QOpenGLTexture::RGBA_DXT5:
907 case QOpenGLTexture::R_ATI1N_UNorm:
908 case QOpenGLTexture::R_ATI1N_SNorm:
909 case QOpenGLTexture::RG_ATI2N_UNorm:
910 case QOpenGLTexture::RG_ATI2N_SNorm:
911 case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
912 case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
913 case QOpenGLTexture::RGB_BP_UNorm:
914 case QOpenGLTexture::SRGB8:
915 case QOpenGLTexture::SRGB8_Alpha8:
916 case QOpenGLTexture::SRGB_DXT1:
917 case QOpenGLTexture::SRGB_Alpha_DXT1:
918 case QOpenGLTexture::SRGB_Alpha_DXT3:
919 case QOpenGLTexture::SRGB_Alpha_DXT5:
920 case QOpenGLTexture::SRGB_BP_UNorm:
921 case QOpenGLTexture::R11_EAC_UNorm:
922 case QOpenGLTexture::R11_EAC_SNorm:
923 case QOpenGLTexture::RG11_EAC_UNorm:
924 case QOpenGLTexture::RG11_EAC_SNorm:
925 case QOpenGLTexture::RGB8_ETC2:
926 case QOpenGLTexture::SRGB8_ETC2:
927 case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
928 case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
929 case QOpenGLTexture::RGBA8_ETC2_EAC:
930 case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
931 case QOpenGLTexture::RGB8_ETC1:
932 case QOpenGLTexture::RGBA_ASTC_4x4:
933 case QOpenGLTexture::RGBA_ASTC_5x4:
934 case QOpenGLTexture::RGBA_ASTC_5x5:
935 case QOpenGLTexture::RGBA_ASTC_6x5:
936 case QOpenGLTexture::RGBA_ASTC_6x6:
937 case QOpenGLTexture::RGBA_ASTC_8x5:
938 case QOpenGLTexture::RGBA_ASTC_8x6:
939 case QOpenGLTexture::RGBA_ASTC_8x8:
940 case QOpenGLTexture::RGBA_ASTC_10x5:
941 case QOpenGLTexture::RGBA_ASTC_10x6:
942 case QOpenGLTexture::RGBA_ASTC_10x8:
943 case QOpenGLTexture::RGBA_ASTC_10x10:
944 case QOpenGLTexture::RGBA_ASTC_12x10:
945 case QOpenGLTexture::RGBA_ASTC_12x12:
946 case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
947 case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
948 case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
949 case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
950 case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
951 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
952 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
953 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
954 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
955 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
956 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
957 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
958 case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
959 case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
960 return QOpenGLTexture::UInt8;
961
962 case QOpenGLTexture::DepthFormat:
963 return QOpenGLTexture::UInt32;
964
965 case QOpenGLTexture::AlphaFormat:
966 case QOpenGLTexture::RGBFormat:
967 case QOpenGLTexture::RGBAFormat:
968 case QOpenGLTexture::LuminanceFormat:
969 case QOpenGLTexture::LuminanceAlphaFormat:
970 return QOpenGLTexture::UInt8;
971 }
972
973 Q_UNREACHABLE();
974 return QOpenGLTexture::NoPixelType;
975}
976
977static bool isCompressedFormat(QOpenGLTexture::TextureFormat internalFormat)
978{
979 switch (internalFormat) {
980 case QOpenGLTexture::NoFormat:
981
982 case QOpenGLTexture::R8_UNorm:
983 case QOpenGLTexture::RG8_UNorm:
984 case QOpenGLTexture::RGB8_UNorm:
985 case QOpenGLTexture::RGBA8_UNorm:
986 case QOpenGLTexture::R16_UNorm:
987 case QOpenGLTexture::RG16_UNorm:
988 case QOpenGLTexture::RGB16_UNorm:
989 case QOpenGLTexture::RGBA16_UNorm:
990 case QOpenGLTexture::R8_SNorm:
991 case QOpenGLTexture::RG8_SNorm:
992 case QOpenGLTexture::RGB8_SNorm:
993 case QOpenGLTexture::RGBA8_SNorm:
994 case QOpenGLTexture::R16_SNorm:
995 case QOpenGLTexture::RG16_SNorm:
996 case QOpenGLTexture::RGB16_SNorm:
997 case QOpenGLTexture::RGBA16_SNorm:
998 case QOpenGLTexture::R8U:
999 case QOpenGLTexture::RG8U:
1000 case QOpenGLTexture::RGB8U:
1001 case QOpenGLTexture::RGBA8U:
1002 case QOpenGLTexture::R16U:
1003 case QOpenGLTexture::RG16U:
1004 case QOpenGLTexture::RGB16U:
1005 case QOpenGLTexture::RGBA16U:
1006 case QOpenGLTexture::R32U:
1007 case QOpenGLTexture::RG32U:
1008 case QOpenGLTexture::RGB32U:
1009 case QOpenGLTexture::RGBA32U:
1010 case QOpenGLTexture::R8I:
1011 case QOpenGLTexture::RG8I:
1012 case QOpenGLTexture::RGB8I:
1013 case QOpenGLTexture::RGBA8I:
1014 case QOpenGLTexture::R16I:
1015 case QOpenGLTexture::RG16I:
1016 case QOpenGLTexture::RGB16I:
1017 case QOpenGLTexture::RGBA16I:
1018 case QOpenGLTexture::R32I:
1019 case QOpenGLTexture::RG32I:
1020 case QOpenGLTexture::RGB32I:
1021 case QOpenGLTexture::RGBA32I:
1022 case QOpenGLTexture::R16F:
1023 case QOpenGLTexture::RG16F:
1024 case QOpenGLTexture::RGB16F:
1025 case QOpenGLTexture::RGBA16F:
1026 case QOpenGLTexture::R32F:
1027 case QOpenGLTexture::RG32F:
1028 case QOpenGLTexture::RGB32F:
1029 case QOpenGLTexture::RGBA32F:
1030 case QOpenGLTexture::RGB9E5:
1031 case QOpenGLTexture::RG11B10F:
1032 case QOpenGLTexture::RG3B2:
1033 case QOpenGLTexture::R5G6B5:
1034 case QOpenGLTexture::RGB5A1:
1035 case QOpenGLTexture::RGBA4:
1036 case QOpenGLTexture::RGB10A2:
1037
1038 case QOpenGLTexture::D16:
1039 case QOpenGLTexture::D24:
1040 case QOpenGLTexture::D32:
1041 case QOpenGLTexture::D32F:
1042
1043 case QOpenGLTexture::D24S8:
1044 case QOpenGLTexture::D32FS8X24:
1045
1046 case QOpenGLTexture::S8:
1047 return false;
1048
1049 case QOpenGLTexture::RGB_DXT1:
1050 case QOpenGLTexture::RGBA_DXT1:
1051 case QOpenGLTexture::RGBA_DXT3:
1052 case QOpenGLTexture::RGBA_DXT5:
1053 case QOpenGLTexture::R_ATI1N_UNorm:
1054 case QOpenGLTexture::R_ATI1N_SNorm:
1055 case QOpenGLTexture::RG_ATI2N_UNorm:
1056 case QOpenGLTexture::RG_ATI2N_SNorm:
1057 case QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT:
1058 case QOpenGLTexture::RGB_BP_SIGNED_FLOAT:
1059 case QOpenGLTexture::RGB_BP_UNorm:
1060 case QOpenGLTexture::SRGB8:
1061 case QOpenGLTexture::SRGB8_Alpha8:
1062 case QOpenGLTexture::SRGB_DXT1:
1063 case QOpenGLTexture::SRGB_Alpha_DXT1:
1064 case QOpenGLTexture::SRGB_Alpha_DXT3:
1065 case QOpenGLTexture::SRGB_Alpha_DXT5:
1066 case QOpenGLTexture::SRGB_BP_UNorm:
1067 case QOpenGLTexture::R11_EAC_UNorm:
1068 case QOpenGLTexture::R11_EAC_SNorm:
1069 case QOpenGLTexture::RG11_EAC_UNorm:
1070 case QOpenGLTexture::RG11_EAC_SNorm:
1071 case QOpenGLTexture::RGB8_ETC2:
1072 case QOpenGLTexture::SRGB8_ETC2:
1073 case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
1074 case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
1075 case QOpenGLTexture::RGBA8_ETC2_EAC:
1076 case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
1077 case QOpenGLTexture::RGB8_ETC1:
1078 case QOpenGLTexture::RGBA_ASTC_4x4:
1079 case QOpenGLTexture::RGBA_ASTC_5x4:
1080 case QOpenGLTexture::RGBA_ASTC_5x5:
1081 case QOpenGLTexture::RGBA_ASTC_6x5:
1082 case QOpenGLTexture::RGBA_ASTC_6x6:
1083 case QOpenGLTexture::RGBA_ASTC_8x5:
1084 case QOpenGLTexture::RGBA_ASTC_8x6:
1085 case QOpenGLTexture::RGBA_ASTC_8x8:
1086 case QOpenGLTexture::RGBA_ASTC_10x5:
1087 case QOpenGLTexture::RGBA_ASTC_10x6:
1088 case QOpenGLTexture::RGBA_ASTC_10x8:
1089 case QOpenGLTexture::RGBA_ASTC_10x10:
1090 case QOpenGLTexture::RGBA_ASTC_12x10:
1091 case QOpenGLTexture::RGBA_ASTC_12x12:
1092 case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
1093 case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
1094 case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
1095 case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
1096 case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
1097 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
1098 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
1099 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
1100 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
1101 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
1102 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
1103 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
1104 case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
1105 case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
1106 return true;
1107
1108 case QOpenGLTexture::DepthFormat:
1109 case QOpenGLTexture::AlphaFormat:
1110 case QOpenGLTexture::RGBFormat:
1111 case QOpenGLTexture::RGBAFormat:
1112 case QOpenGLTexture::LuminanceFormat:
1113 case QOpenGLTexture::LuminanceAlphaFormat:
1114 return false;
1115 }
1116
1117 Q_UNREACHABLE();
1118 return false;
1119}
1120
1121void QOpenGLTexturePrivate::allocateMutableStorage(QOpenGLTexture::PixelFormat pixelFormat, QOpenGLTexture::PixelType pixelType)
1122{
1123 // There is no way to allocate mutable storage for compressed textures in in
1124 // versions older than OpenGL 3.1 and OpenGL ES 3.0, because the older specs
1125 // do not mandate accepting null data pointers for glCompressedTexImage*D,
1126 // unlike glTexImage*D (which in turn does not accept compressed formats).
1127 if (isCompressedFormat(format)) {
1128 storageAllocated = true;
1129 return;
1130 }
1131
1132 switch (target) {
1133 case QOpenGLTexture::TargetBuffer:
1134 // Buffer textures get their storage from an external OpenGL buffer
1135 qWarning("Buffer textures do not allocate storage");
1136 return;
1137
1138 case QOpenGLTexture::Target1D:
1139 if (features.testFlag(QOpenGLTexture::Texture1D)) {
1140 for (int level = 0; level < mipLevels; ++level)
1141 texFuncs->glTextureImage1D(textureId, target, bindingTarget, level, format,
1142 mipLevelSize(level, dimensions[0]),
1143 0,
1144 pixelFormat, pixelType, 0);
1145 } else {
1146 qWarning("1D textures are not supported");
1147 return;
1148 }
1149 break;
1150
1151 case QOpenGLTexture::Target1DArray:
1152 if (features.testFlag(QOpenGLTexture::Texture1D)
1153 && features.testFlag(QOpenGLTexture::TextureArrays)) {
1154 for (int level = 0; level < mipLevels; ++level)
1155 texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format,
1156 mipLevelSize(level, dimensions[0]),
1157 layers,
1158 0,
1159 pixelFormat, pixelType, 0);
1160 } else {
1161 qWarning("1D array textures are not supported");
1162 return;
1163 }
1164 break;
1165
1166 case QOpenGLTexture::Target2D:
1167 case QOpenGLTexture::TargetRectangle:
1168 for (int level = 0; level < mipLevels; ++level)
1169 texFuncs->glTextureImage2D(textureId, target, bindingTarget, level, format,
1170 mipLevelSize(level, dimensions[0]),
1171 mipLevelSize(level, dimensions[1]),
1172 0,
1173 pixelFormat, pixelType, 0);
1174 break;
1175
1176 case QOpenGLTexture::TargetCubeMap: {
1177 // Cubemaps are the odd one out. We have to allocate storage for each
1178 // face and miplevel using the special cubemap face targets rather than
1179 // GL_TARGET_CUBEMAP.
1180 const QOpenGLTexture::CubeMapFace faceTargets[] = {
1181 QOpenGLTexture::CubeMapPositiveX, QOpenGLTexture::CubeMapNegativeX,
1182 QOpenGLTexture::CubeMapPositiveY, QOpenGLTexture::CubeMapNegativeY,
1183 QOpenGLTexture::CubeMapPositiveZ, QOpenGLTexture::CubeMapNegativeZ
1184 };
1185
1186 for (int faceTarget = 0; faceTarget < 6; ++faceTarget) {
1187 for (int level = 0; level < mipLevels; ++level) {
1188 texFuncs->glTextureImage2D(textureId, faceTargets[faceTarget], bindingTarget,
1189 level, format,
1190 mipLevelSize(level, dimensions[0]),
1191 mipLevelSize(level, dimensions[1]),
1192 0,
1193 pixelFormat, pixelType, 0);
1194 }
1195 }
1196 break;
1197 }
1198
1199 case QOpenGLTexture::Target2DArray:
1200 if (features.testFlag(QOpenGLTexture::TextureArrays)) {
1201 for (int level = 0; level < mipLevels; ++level)
1202 texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
1203 mipLevelSize(level, dimensions[0]),
1204 mipLevelSize(level, dimensions[1]),
1205 layers,
1206 0,
1207 pixelFormat, pixelType, 0);
1208 } else {
1209 qWarning("Array textures are not supported");
1210 return;
1211 }
1212 break;
1213
1214 case QOpenGLTexture::TargetCubeMapArray:
1215 // Cubemap arrays must specify number of layer-faces (6 * layers) as depth parameter
1216 if (features.testFlag(QOpenGLTexture::TextureCubeMapArrays)) {
1217 for (int level = 0; level < mipLevels; ++level)
1218 texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
1219 mipLevelSize(level, dimensions[0]),
1220 mipLevelSize(level, dimensions[1]),
1221 6 * layers,
1222 0,
1223 pixelFormat, pixelType, 0);
1224 } else {
1225 qWarning("Cubemap Array textures are not supported");
1226 return;
1227 }
1228 break;
1229
1230 case QOpenGLTexture::Target3D:
1231 if (features.testFlag(QOpenGLTexture::Texture3D)) {
1232 for (int level = 0; level < mipLevels; ++level)
1233 texFuncs->glTextureImage3D(textureId, target, bindingTarget, level, format,
1234 mipLevelSize(level, dimensions[0]),
1235 mipLevelSize(level, dimensions[1]),
1236 mipLevelSize(level, dimensions[2]),
1237 0,
1238 pixelFormat, pixelType, 0);
1239 } else {
1240 qWarning("3D textures are not supported");
1241 return;
1242 }
1243 break;
1244
1245 case QOpenGLTexture::Target2DMultisample:
1246 if (features.testFlag(QOpenGLTexture::TextureMultisample)) {
1247 texFuncs->glTextureImage2DMultisample(textureId, target, bindingTarget, samples, format,
1248 dimensions[0], dimensions[1],
1249 fixedSamplePositions);
1250 } else {
1251 qWarning("Multisample textures are not supported");
1252 return;
1253 }
1254 break;
1255
1256 case QOpenGLTexture::Target2DMultisampleArray:
1257 if (features.testFlag(QOpenGLTexture::TextureMultisample)
1258 && features.testFlag(QOpenGLTexture::TextureArrays)) {
1259 texFuncs->glTextureImage3DMultisample(textureId, target, bindingTarget, samples, format,
1260 dimensions[0], dimensions[1], layers,
1261 fixedSamplePositions);
1262 } else {
1263 qWarning("Multisample array textures are not supported");
1264 return;
1265 }
1266 break;
1267 }
1268
1269 storageAllocated = true;
1270}
1271
1272void QOpenGLTexturePrivate::allocateImmutableStorage()
1273{
1274 switch (target) {
1275 case QOpenGLTexture::TargetBuffer:
1276 // Buffer textures get their storage from an external OpenGL buffer
1277 qWarning("Buffer textures do not allocate storage");
1278 return;
1279
1280 case QOpenGLTexture::Target1D:
1281 if (features.testFlag(QOpenGLTexture::Texture1D)) {
1282 texFuncs->glTextureStorage1D(textureId, target, bindingTarget, mipLevels, format,
1283 dimensions[0]);
1284 } else {
1285 qWarning("1D textures are not supported");
1286 return;
1287 }
1288 break;
1289
1290 case QOpenGLTexture::Target1DArray:
1291 if (features.testFlag(QOpenGLTexture::Texture1D)
1292 && features.testFlag(QOpenGLTexture::TextureArrays)) {
1293 texFuncs->glTextureStorage2D(textureId, target, bindingTarget, mipLevels, format,
1294 dimensions[0], layers);
1295 } else {
1296 qWarning("1D array textures are not supported");
1297 return;
1298 }
1299 break;
1300
1301 case QOpenGLTexture::Target2D:
1302 case QOpenGLTexture::TargetCubeMap:
1303 case QOpenGLTexture::TargetRectangle:
1304 texFuncs->glTextureStorage2D(textureId, target, bindingTarget, mipLevels, format,
1305 dimensions[0], dimensions[1]);
1306 break;
1307
1308 case QOpenGLTexture::Target2DArray:
1309 if (features.testFlag(QOpenGLTexture::TextureArrays)) {
1310 texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
1311 dimensions[0], dimensions[1], layers);
1312 } else {
1313 qWarning("Array textures are not supported");
1314 return;
1315 }
1316 break;
1317
1318 case QOpenGLTexture::TargetCubeMapArray:
1319 // Cubemap arrays must specify number of layer-faces (6 * layers) as depth parameter
1320 if (features.testFlag(QOpenGLTexture::TextureCubeMapArrays)) {
1321 texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
1322 dimensions[0], dimensions[1], 6 * layers);
1323 } else {
1324 qWarning("Cubemap Array textures are not supported");
1325 return;
1326 }
1327 break;
1328
1329 case QOpenGLTexture::Target3D:
1330 if (features.testFlag(QOpenGLTexture::Texture3D)) {
1331 texFuncs->glTextureStorage3D(textureId, target, bindingTarget, mipLevels, format,
1332 dimensions[0], dimensions[1], dimensions[2]);
1333 } else {
1334 qWarning("3D textures are not supported");
1335 return;
1336 }
1337 break;
1338
1339 case QOpenGLTexture::Target2DMultisample:
1340 if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)) {
1341 texFuncs->glTextureStorage2DMultisample(textureId, target, bindingTarget, samples, format,
1342 dimensions[0], dimensions[1],
1343 fixedSamplePositions);
1344 } else {
1345 qWarning("Multisample textures are not supported");
1346 return;
1347 }
1348 break;
1349
1350 case QOpenGLTexture::Target2DMultisampleArray:
1351 if (features.testFlag(QOpenGLTexture::ImmutableMultisampleStorage)
1352 && features.testFlag(QOpenGLTexture::TextureArrays)) {
1353 texFuncs->glTextureStorage3DMultisample(textureId, target, bindingTarget, samples, format,
1354 dimensions[0], dimensions[1], layers,
1355 fixedSamplePositions);
1356 } else {
1357 qWarning("Multisample array textures are not supported");
1358 return;
1359 }
1360 break;
1361 }
1362
1363 storageAllocated = true;
1364}
1365
1366void QOpenGLTexturePrivate::setData(int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
1367 QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
1368 const void *data, const QOpenGLPixelTransferOptions * const options)
1369{
1370 switch (target) {
1371 case QOpenGLTexture::Target1D:
1372 Q_UNUSED(layer);
1373 Q_UNUSED(cubeFace);
1374 Q_UNUSED(layerCount);
1375 texFuncs->glTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
1376 0, mipLevelSize( mipLevel, dimensions[0] ),
1377 sourceFormat, sourceType, data, options);
1378 break;
1379
1380 case QOpenGLTexture::Target1DArray:
1381 Q_UNUSED(cubeFace);
1382 texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1383 0, layer,
1384 mipLevelSize(mipLevel, dimensions[0]),
1385 layerCount,
1386 sourceFormat, sourceType, data, options);
1387 break;
1388
1389 case QOpenGLTexture::Target2D:
1390 Q_UNUSED(layer);
1391 Q_UNUSED(cubeFace);
1392 Q_UNUSED(layerCount);
1393 texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1394 0, 0,
1395 mipLevelSize(mipLevel, dimensions[0]),
1396 mipLevelSize(mipLevel, dimensions[1]),
1397 sourceFormat, sourceType, data, options);
1398 break;
1399
1400 case QOpenGLTexture::Target2DArray:
1401 Q_UNUSED(cubeFace);
1402 texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1403 0, 0, layer,
1404 mipLevelSize(mipLevel, dimensions[0]),
1405 mipLevelSize(mipLevel, dimensions[1]),
1406 layerCount,
1407 sourceFormat, sourceType, data, options);
1408 break;
1409
1410 case QOpenGLTexture::Target3D:
1411 Q_UNUSED(cubeFace);
1412 Q_UNUSED(layerCount);
1413 texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1414 0, 0, layer,
1415 mipLevelSize(mipLevel, dimensions[0]),
1416 mipLevelSize(mipLevel, dimensions[1]),
1417 mipLevelSize(mipLevel, dimensions[2]),
1418 sourceFormat, sourceType, data, options);
1419 break;
1420
1421 case QOpenGLTexture::TargetCubeMap:
1422 Q_UNUSED(layer);
1423 Q_UNUSED(layerCount);
1424 texFuncs->glTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
1425 0, 0,
1426 mipLevelSize(mipLevel, dimensions[0]),
1427 mipLevelSize(mipLevel, dimensions[1]),
1428 sourceFormat, sourceType, data, options);
1429 break;
1430
1431 case QOpenGLTexture::TargetCubeMapArray: {
1432 int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
1433 int layerFace = 6 * layer + faceIndex;
1434 texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1435 0, 0, layerFace,
1436 mipLevelSize(mipLevel, dimensions[0]),
1437 mipLevelSize(mipLevel, dimensions[1]),
1438 layerCount,
1439 sourceFormat, sourceType, data, options);
1440 break;
1441 }
1442
1443 case QOpenGLTexture::TargetRectangle:
1444 Q_UNUSED(mipLevel);
1445 Q_UNUSED(layer);
1446 Q_UNUSED(cubeFace);
1447 Q_UNUSED(layerCount);
1448 texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, 0,
1449 0, 0,
1450 dimensions[0],
1451 dimensions[1],
1452 sourceFormat, sourceType, data, options);
1453 break;
1454
1455 case QOpenGLTexture::Target2DMultisample:
1456 case QOpenGLTexture::Target2DMultisampleArray:
1457 case QOpenGLTexture::TargetBuffer:
1458 // We don't upload pixel data for these targets
1459 qWarning("QOpenGLTexture::setData(): Texture target does not support pixel data upload");
1460 break;
1461 }
1462
1463 // If requested perform automatic mip map generation
1464 if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
1465 Q_Q(QOpenGLTexture);
1466 q->generateMipMaps();
1467 }
1468}
1469
1470void QOpenGLTexturePrivate::setData(int xOffset, int yOffset, int zOffset, int width, int height, int depth,
1471 int mipLevel, int layer, int layerCount, QOpenGLTexture::CubeMapFace cubeFace,
1472 QOpenGLTexture::PixelFormat sourceFormat, QOpenGLTexture::PixelType sourceType,
1473 const void *data, const QOpenGLPixelTransferOptions * const options)
1474{
1475 switch (target) {
1476 case QOpenGLTexture::Target1D:
1477 Q_UNUSED(layer);
1478 Q_UNUSED(cubeFace);
1479 Q_UNUSED(layerCount);
1480 Q_UNUSED(yOffset);
1481 Q_UNUSED(zOffset);
1482 Q_UNUSED(height);
1483 Q_UNUSED(depth);
1484 texFuncs->glTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
1485 xOffset, width,
1486 sourceFormat, sourceType, data, options);
1487 break;
1488
1489 case QOpenGLTexture::Target1DArray:
1490 Q_UNUSED(cubeFace);
1491 Q_UNUSED(yOffset);
1492 Q_UNUSED(zOffset);
1493 Q_UNUSED(height);
1494 Q_UNUSED(depth);
1495 texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1496 xOffset, layer,
1497 width,
1498 layerCount,
1499 sourceFormat, sourceType, data, options);
1500 break;
1501
1502 case QOpenGLTexture::Target2D:
1503 Q_UNUSED(layer);
1504 Q_UNUSED(cubeFace);
1505 Q_UNUSED(layerCount);
1506 Q_UNUSED(zOffset);
1507 Q_UNUSED(depth);
1508 texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1509 xOffset, yOffset,
1510 width, height,
1511 sourceFormat, sourceType, data, options);
1512 break;
1513
1514 case QOpenGLTexture::Target2DArray:
1515 Q_UNUSED(cubeFace);
1516 Q_UNUSED(zOffset);
1517 Q_UNUSED(depth);
1518 texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1519 xOffset, yOffset, layer,
1520 width, height, layerCount,
1521 sourceFormat, sourceType, data, options);
1522 break;
1523
1524 case QOpenGLTexture::Target3D:
1525 Q_UNUSED(cubeFace);
1526 Q_UNUSED(layerCount);
1527 texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1528 xOffset, yOffset, zOffset,
1529 width, height, depth,
1530 sourceFormat, sourceType, data, options);
1531 break;
1532
1533 case QOpenGLTexture::TargetCubeMap:
1534 Q_UNUSED(layer);
1535 Q_UNUSED(layerCount);
1536 Q_UNUSED(zOffset);
1537 Q_UNUSED(depth);
1538 texFuncs->glTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
1539 xOffset, yOffset,
1540 width, height,
1541 sourceFormat, sourceType, data, options);
1542 break;
1543
1544 case QOpenGLTexture::TargetCubeMapArray: {
1545 Q_UNUSED(zOffset);
1546 Q_UNUSED(depth);
1547 int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
1548 int layerFace = 6 * layer + faceIndex;
1549 texFuncs->glTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1550 xOffset, yOffset, layerFace,
1551 width, height,
1552 layerCount,
1553 sourceFormat, sourceType, data, options);
1554 break;
1555 }
1556
1557 case QOpenGLTexture::TargetRectangle:
1558 Q_UNUSED(mipLevel);
1559 Q_UNUSED(layer);
1560 Q_UNUSED(cubeFace);
1561 Q_UNUSED(layerCount);
1562 Q_UNUSED(zOffset);
1563 Q_UNUSED(depth);
1564 texFuncs->glTextureSubImage2D(textureId, target, bindingTarget, 0,
1565 xOffset, yOffset,
1566 width, height,
1567 sourceFormat, sourceType, data, options);
1568 break;
1569
1570 case QOpenGLTexture::Target2DMultisample:
1571 case QOpenGLTexture::Target2DMultisampleArray:
1572 case QOpenGLTexture::TargetBuffer:
1573 // We don't upload pixel data for these targets
1574 qWarning("QOpenGLTexture::setData(): Texture target does not support pixel data upload");
1575 break;
1576 }
1577
1578 // If requested perform automatic mip map generation
1579 if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
1580 Q_Q(QOpenGLTexture);
1581 q->generateMipMaps();
1582 }
1583}
1584
1585
1586void QOpenGLTexturePrivate::setCompressedData(int mipLevel, int layer, int layerCount,
1587 QOpenGLTexture::CubeMapFace cubeFace,
1588 int dataSize, const void *data,
1589 const QOpenGLPixelTransferOptions * const options)
1590{
1591 if (!isCompressedFormat(format)) {
1592 qWarning("Cannot set compressed data for non-compressed format 0x%x", format);
1593 return;
1594 }
1595
1596 const bool needsFullSpec = !isUsingImmutableStorage(); // was allocateStorage() a no-op?
1597
1598 switch (target) {
1599 case QOpenGLTexture::Target1D:
1600 Q_UNUSED(layer);
1601 Q_UNUSED(cubeFace);
1602 Q_UNUSED(layerCount);
1603 if (needsFullSpec) {
1604 texFuncs->glCompressedTextureImage1D(textureId, target, bindingTarget, mipLevel,
1605 format,
1606 mipLevelSize(mipLevel, dimensions[0]),
1607 0, dataSize, data, options);
1608 } else {
1609 texFuncs->glCompressedTextureSubImage1D(textureId, target, bindingTarget, mipLevel,
1610 0, mipLevelSize( mipLevel, dimensions[0] ),
1611 format, dataSize, data, options);
1612 }
1613 break;
1614
1615 case QOpenGLTexture::Target1DArray:
1616 Q_UNUSED(cubeFace);
1617 if (!needsFullSpec) {
1618 texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1619 0, layer,
1620 mipLevelSize(mipLevel, dimensions[0]),
1621 layerCount,
1622 format, dataSize, data, options);
1623 }
1624 break;
1625
1626 case QOpenGLTexture::Target2D:
1627 Q_UNUSED(layer);
1628 Q_UNUSED(cubeFace);
1629 Q_UNUSED(layerCount);
1630 if (needsFullSpec) {
1631 texFuncs->glCompressedTextureImage2D(textureId, target, bindingTarget, mipLevel,
1632 format,
1633 mipLevelSize(mipLevel, dimensions[0]),
1634 mipLevelSize(mipLevel, dimensions[1]),
1635 0, dataSize, data, options);
1636 } else {
1637 texFuncs->glCompressedTextureSubImage2D(textureId, target, bindingTarget, mipLevel,
1638 0, 0,
1639 mipLevelSize(mipLevel, dimensions[0]),
1640 mipLevelSize(mipLevel, dimensions[1]),
1641 format, dataSize, data, options);
1642 }
1643 break;
1644
1645 case QOpenGLTexture::Target2DArray:
1646 Q_UNUSED(cubeFace);
1647 if (!needsFullSpec) {
1648 texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1649 0, 0, layer,
1650 mipLevelSize(mipLevel, dimensions[0]),
1651 mipLevelSize(mipLevel, dimensions[1]),
1652 layerCount,
1653 format, dataSize, data, options);
1654 }
1655 break;
1656
1657 case QOpenGLTexture::Target3D:
1658 Q_UNUSED(cubeFace);
1659 Q_UNUSED(layerCount);
1660 if (needsFullSpec) {
1661 texFuncs->glCompressedTextureImage3D(textureId, target, bindingTarget, mipLevel,
1662 format,
1663 mipLevelSize(mipLevel, dimensions[0]),
1664 mipLevelSize(mipLevel, dimensions[1]),
1665 mipLevelSize(mipLevel, dimensions[2]),
1666 0, dataSize, data, options);
1667 } else {
1668 texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1669 0, 0, layer,
1670 mipLevelSize(mipLevel, dimensions[0]),
1671 mipLevelSize(mipLevel, dimensions[1]),
1672 mipLevelSize(mipLevel, dimensions[2]),
1673 format, dataSize, data, options);
1674 }
1675 break;
1676
1677 case QOpenGLTexture::TargetCubeMap:
1678 Q_UNUSED(layer);
1679 Q_UNUSED(layerCount);
1680 if (needsFullSpec) {
1681 texFuncs->glCompressedTextureImage2D(textureId, cubeFace, bindingTarget, mipLevel,
1682 format,
1683 mipLevelSize(mipLevel, dimensions[0]),
1684 mipLevelSize(mipLevel, dimensions[1]),
1685 0, dataSize, data, options);
1686 } else {
1687 texFuncs->glCompressedTextureSubImage2D(textureId, cubeFace, bindingTarget, mipLevel,
1688 0, 0,
1689 mipLevelSize(mipLevel, dimensions[0]),
1690 mipLevelSize(mipLevel, dimensions[1]),
1691 format, dataSize, data, options);
1692 }
1693 break;
1694
1695 case QOpenGLTexture::TargetCubeMapArray: {
1696 int faceIndex = cubeFace - QOpenGLTexture::CubeMapPositiveX;
1697 int layerFace = 6 * layer + faceIndex;
1698 if (!needsFullSpec) {
1699 texFuncs->glCompressedTextureSubImage3D(textureId, target, bindingTarget, mipLevel,
1700 0, 0, layerFace,
1701 mipLevelSize(mipLevel, dimensions[0]),
1702 mipLevelSize(mipLevel, dimensions[1]),
1703 layerCount,
1704 format, dataSize, data, options);
1705 }
1706 break;
1707 }
1708
1709 case QOpenGLTexture::TargetRectangle:
1710 case QOpenGLTexture::Target2DMultisample:
1711 case QOpenGLTexture::Target2DMultisampleArray:
1712 case QOpenGLTexture::TargetBuffer:
1713 // We don't upload pixel data for these targets
1714 qWarning("QOpenGLTexture::setCompressedData(): Texture target does not support pixel data upload");
1715 break;
1716 }
1717
1718 // If requested perform automatic mip map generation
1719 if (mipLevel == 0 && autoGenerateMipMaps && mipLevels > 1) {
1720 Q_Q(QOpenGLTexture);
1721 q->generateMipMaps();
1722 }
1723}
1724
1725void QOpenGLTexturePrivate::setWrapMode(QOpenGLTexture::WrapMode mode)
1726{
1727 switch (target) {
1728 case QOpenGLTexture::Target1D:
1729 case QOpenGLTexture::Target1DArray:
1730 case QOpenGLTexture::TargetBuffer:
1731 wrapModes[0] = mode;
1732 texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
1733 break;
1734
1735 case QOpenGLTexture::Target2D:
1736 case QOpenGLTexture::Target2DArray:
1737 case QOpenGLTexture::TargetCubeMap:
1738 case QOpenGLTexture::TargetCubeMapArray:
1739 case QOpenGLTexture::Target2DMultisample:
1740 case QOpenGLTexture::Target2DMultisampleArray:
1741 case QOpenGLTexture::TargetRectangle:
1742 wrapModes[0] = wrapModes[1] = mode;
1743 texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
1744 texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
1745 break;
1746
1747 case QOpenGLTexture::Target3D:
1748 wrapModes[0] = wrapModes[1] = wrapModes[2] = mode;
1749 texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
1750 texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
1751 texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_R, mode);
1752 break;
1753 }
1754}
1755
1756void QOpenGLTexturePrivate::setWrapMode(QOpenGLTexture::CoordinateDirection direction, QOpenGLTexture::WrapMode mode)
1757{
1758 switch (target) {
1759 case QOpenGLTexture::Target1D:
1760 case QOpenGLTexture::Target1DArray:
1761 case QOpenGLTexture::TargetBuffer:
1762 switch (direction) {
1763 case QOpenGLTexture::DirectionS:
1764 wrapModes[0] = mode;
1765 texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
1766 break;
1767
1768 case QOpenGLTexture::DirectionT:
1769 case QOpenGLTexture::DirectionR:
1770 qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target");
1771 break;
1772 }
1773 break;
1774
1775 case QOpenGLTexture::Target2D:
1776 case QOpenGLTexture::Target2DArray:
1777 case QOpenGLTexture::TargetCubeMap:
1778 case QOpenGLTexture::TargetCubeMapArray:
1779 case QOpenGLTexture::Target2DMultisample:
1780 case QOpenGLTexture::Target2DMultisampleArray:
1781 case QOpenGLTexture::TargetRectangle:
1782 switch (direction) {
1783 case QOpenGLTexture::DirectionS:
1784 wrapModes[0] = mode;
1785 texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_S, mode);
1786 break;
1787
1788 case QOpenGLTexture::DirectionT:
1789 wrapModes[1] = mode;
1790 texFuncs->glTextureParameteri(textureId, target, bindingTarget, GL_TEXTURE_WRAP_T, mode);
1791 break;
1792
1793 case QOpenGLTexture::DirectionR:
1794 qWarning("QOpenGLTexture::setWrapMode() direction not valid for this texture target");
1795 break;
1796 }
1797 break;
1798
1799 case QOpenGLTexture::Target3D:
1800 switch (direction) {
1801 case QOpenGLTexture::DirectionS:
1802 wrapModes[0] = mode;
1803 texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
1804 break;
1805
1806 case QOpenGLTexture::DirectionT:
1807 wrapModes[1] = mode;
1808 texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
1809 break;
1810
1811 case QOpenGLTexture::DirectionR:
1812 wrapModes[2] = mode;
1813 texFuncs->glTextureParameteri(textureId, target, bindingTarget, direction, mode);
1814 break;
1815 }
1816 break;
1817 }
1818}
1819
1820QOpenGLTexture::WrapMode QOpenGLTexturePrivate::wrapMode(QOpenGLTexture::CoordinateDirection direction) const
1821{
1822 switch (target) {
1823 case QOpenGLTexture::Target1D:
1824 case QOpenGLTexture::Target1DArray:
1825 case QOpenGLTexture::TargetBuffer:
1826 switch (direction) {
1827 case QOpenGLTexture::DirectionS:
1828 return wrapModes[0];
1829
1830 case QOpenGLTexture::DirectionT:
1831 case QOpenGLTexture::DirectionR:
1832 qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target");
1833 return QOpenGLTexture::Repeat;
1834 }
1835 break;
1836
1837 case QOpenGLTexture::Target2D:
1838 case QOpenGLTexture::Target2DArray:
1839 case QOpenGLTexture::TargetCubeMap:
1840 case QOpenGLTexture::TargetCubeMapArray:
1841 case QOpenGLTexture::Target2DMultisample:
1842 case QOpenGLTexture::Target2DMultisampleArray:
1843 case QOpenGLTexture::TargetRectangle:
1844 switch (direction) {
1845 case QOpenGLTexture::DirectionS:
1846 return wrapModes[0];
1847
1848 case QOpenGLTexture::DirectionT:
1849 return wrapModes[1];
1850
1851 case QOpenGLTexture::DirectionR:
1852 qWarning("QOpenGLTexture::wrapMode() direction not valid for this texture target");
1853 return QOpenGLTexture::Repeat;
1854 }
1855 break;
1856
1857 case QOpenGLTexture::Target3D:
1858 switch (direction) {
1859 case QOpenGLTexture::DirectionS:
1860 return wrapModes[0];
1861
1862 case QOpenGLTexture::DirectionT:
1863 return wrapModes[1];
1864
1865 case QOpenGLTexture::DirectionR:
1866 return wrapModes[2];
1867 }
1868 break;
1869 }
1870 // Should never get here
1871 Q_ASSERT(false);
1872 return QOpenGLTexture::Repeat;
1873}
1874
1875QOpenGLTexture *QOpenGLTexturePrivate::createTextureView(QOpenGLTexture::Target viewTarget,
1876 QOpenGLTexture::TextureFormat viewFormat,
1877 int minimumMipmapLevel, int maximumMipmapLevel,
1878 int minimumLayer, int maximumLayer) const
1879{
1880 // Do sanity checks - see http://www.opengl.org/wiki/GLAPI/glTextureView
1881
1882 // Check the targets are compatible
1883 bool viewTargetCompatible = false;
1884 switch (target) {
1885 case QOpenGLTexture::Target1D:
1886 case QOpenGLTexture::Target1DArray:
1887 viewTargetCompatible = (viewTarget == QOpenGLTexture::Target1D
1888 || viewTarget == QOpenGLTexture::Target1DArray);
1889 break;
1890
1891
1892 case QOpenGLTexture::Target2D:
1893 case QOpenGLTexture::Target2DArray:
1894 viewTargetCompatible = (viewTarget == QOpenGLTexture::Target2D
1895 || viewTarget == QOpenGLTexture::Target2DArray);
1896 break;
1897
1898 case QOpenGLTexture::Target3D:
1899 viewTargetCompatible = (viewTarget == QOpenGLTexture::Target3D);
1900 break;
1901
1902 case QOpenGLTexture::TargetCubeMap:
1903 case QOpenGLTexture::TargetCubeMapArray:
1904 viewTargetCompatible = (viewTarget == QOpenGLTexture::TargetCubeMap
1905 || viewTarget == QOpenGLTexture::Target2D
1906 || viewTarget == QOpenGLTexture::Target2DArray
1907 || viewTarget == QOpenGLTexture::TargetCubeMapArray);
1908 break;
1909
1910 case QOpenGLTexture::Target2DMultisample:
1911 case QOpenGLTexture::Target2DMultisampleArray:
1912 viewTargetCompatible = (viewTarget == QOpenGLTexture::Target2DMultisample
1913 || viewTarget == QOpenGLTexture::Target2DMultisampleArray);
1914 break;
1915
1916 case QOpenGLTexture::TargetRectangle:
1917 viewTargetCompatible = (viewTarget == QOpenGLTexture::TargetRectangle);
1918 break;
1919
1920 case QOpenGLTexture::TargetBuffer:
1921 // Cannot be used with texture views
1922 break;
1923 }
1924
1925 if (!viewTargetCompatible) {
1926 qWarning("QOpenGLTexture::createTextureView(): Incompatible source and view targets");
1927 return 0;
1928 }
1929
1930 // Check the formats are compatible
1931 bool viewFormatCompatible = false;
1932 switch (formatClass) {
1933 case QOpenGLTexture::NoFormatClass:
1934 break;
1935
1936 case QOpenGLTexture::FormatClass_128Bit:
1937 viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA32F
1938 || viewFormat == QOpenGLTexture::RGBA32U
1939 || viewFormat == QOpenGLTexture::RGBA32I);
1940 break;
1941
1942 case QOpenGLTexture::FormatClass_96Bit:
1943 viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB32F
1944 || viewFormat == QOpenGLTexture::RGB32U
1945 || viewFormat == QOpenGLTexture::RGB32I);
1946 break;
1947
1948 case QOpenGLTexture::FormatClass_64Bit:
1949 viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA16F
1950 || viewFormat == QOpenGLTexture::RG32F
1951 || viewFormat == QOpenGLTexture::RGBA16U
1952 || viewFormat == QOpenGLTexture::RG32U
1953 || viewFormat == QOpenGLTexture::RGBA16I
1954 || viewFormat == QOpenGLTexture::RG32I
1955 || viewFormat == QOpenGLTexture::RGBA16_UNorm
1956 || viewFormat == QOpenGLTexture::RGBA16_SNorm);
1957 break;
1958
1959 case QOpenGLTexture::FormatClass_48Bit:
1960 viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB16_UNorm
1961 || viewFormat == QOpenGLTexture::RGB16_SNorm
1962 || viewFormat == QOpenGLTexture::RGB16F
1963 || viewFormat == QOpenGLTexture::RGB16U
1964 || viewFormat == QOpenGLTexture::RGB16I);
1965 break;
1966
1967 case QOpenGLTexture::FormatClass_32Bit:
1968 viewFormatCompatible = (viewFormat == QOpenGLTexture::RG16F
1969 || viewFormat == QOpenGLTexture::RG11B10F
1970 || viewFormat == QOpenGLTexture::R32F
1971 || viewFormat == QOpenGLTexture::RGB10A2
1972 || viewFormat == QOpenGLTexture::RGBA8U
1973 || viewFormat == QOpenGLTexture::RG16U
1974 || viewFormat == QOpenGLTexture::R32U
1975 || viewFormat == QOpenGLTexture::RGBA8I
1976 || viewFormat == QOpenGLTexture::RG16I
1977 || viewFormat == QOpenGLTexture::R32I
1978 || viewFormat == QOpenGLTexture::RGBA8_UNorm
1979 || viewFormat == QOpenGLTexture::RG16_UNorm
1980 || viewFormat == QOpenGLTexture::RGBA8_SNorm
1981 || viewFormat == QOpenGLTexture::RG16_SNorm
1982 || viewFormat == QOpenGLTexture::SRGB8_Alpha8
1983 || viewFormat == QOpenGLTexture::RGB9E5);
1984 break;
1985
1986 case QOpenGLTexture::FormatClass_24Bit:
1987 viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB8_UNorm
1988 || viewFormat == QOpenGLTexture::RGB8_SNorm
1989 || viewFormat == QOpenGLTexture::SRGB8
1990 || viewFormat == QOpenGLTexture::RGB8U
1991 || viewFormat == QOpenGLTexture::RGB8I);
1992 break;
1993
1994 case QOpenGLTexture::FormatClass_16Bit:
1995 viewFormatCompatible = (viewFormat == QOpenGLTexture::R16F
1996 || viewFormat == QOpenGLTexture::RG8U
1997 || viewFormat == QOpenGLTexture::R16U
1998 || viewFormat == QOpenGLTexture::RG8I
1999 || viewFormat == QOpenGLTexture::R16I
2000 || viewFormat == QOpenGLTexture::RG8_UNorm
2001 || viewFormat == QOpenGLTexture::R16_UNorm
2002 || viewFormat == QOpenGLTexture::RG8_SNorm
2003 || viewFormat == QOpenGLTexture::R16_SNorm);
2004 break;
2005
2006 case QOpenGLTexture::FormatClass_8Bit:
2007 viewFormatCompatible = (viewFormat == QOpenGLTexture::R8U
2008 || viewFormat == QOpenGLTexture::R8I
2009 || viewFormat == QOpenGLTexture::R8_UNorm
2010 || viewFormat == QOpenGLTexture::R8_SNorm);
2011 break;
2012
2013 case QOpenGLTexture::FormatClass_RGTC1_R:
2014 viewFormatCompatible = (viewFormat == QOpenGLTexture::R_ATI1N_UNorm
2015 || viewFormat == QOpenGLTexture::R_ATI1N_SNorm);
2016 break;
2017
2018 case QOpenGLTexture::FormatClass_RGTC2_RG:
2019 viewFormatCompatible = (viewFormat == QOpenGLTexture::RG_ATI2N_UNorm
2020 || viewFormat == QOpenGLTexture::RG_ATI2N_SNorm);
2021 break;
2022
2023 case QOpenGLTexture::FormatClass_BPTC_Unorm:
2024 viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_BP_UNorm
2025 || viewFormat == QOpenGLTexture::SRGB_BP_UNorm);
2026 break;
2027
2028 case QOpenGLTexture::FormatClass_BPTC_Float:
2029 viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_BP_UNSIGNED_FLOAT
2030 || viewFormat == QOpenGLTexture::RGB_BP_SIGNED_FLOAT);
2031 break;
2032
2033 case QOpenGLTexture::FormatClass_S3TC_DXT1_RGB:
2034 viewFormatCompatible = (viewFormat == QOpenGLTexture::RGB_DXT1
2035 || viewFormat == QOpenGLTexture::SRGB_DXT1);
2036 break;
2037
2038 case QOpenGLTexture::FormatClass_S3TC_DXT1_RGBA:
2039 viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT1
2040 || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT1);
2041 break;
2042
2043 case QOpenGLTexture::FormatClass_S3TC_DXT3_RGBA:
2044 viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT3
2045 || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT3);
2046 break;
2047
2048 case QOpenGLTexture::FormatClass_S3TC_DXT5_RGBA:
2049 viewFormatCompatible = (viewFormat == QOpenGLTexture::RGBA_DXT5
2050 || viewFormat == QOpenGLTexture::SRGB_Alpha_DXT5);
2051 break;
2052
2053 case QOpenGLTexture::FormatClass_Unique:
2054 viewFormatCompatible = (viewFormat == format);
2055 break;
2056 }
2057
2058 if (!viewFormatCompatible) {
2059 qWarning("QOpenGLTexture::createTextureView(): Incompatible source and view formats");
2060 return 0;
2061 }
2062
2063
2064 // Create a view
2065 QOpenGLTexture *view = new QOpenGLTexture(viewTarget);
2066 view->setFormat(viewFormat);
2067 view->create();
2068 view->d_ptr->textureView = true;
2069 texFuncs->glTextureView(view->textureId(), viewTarget, textureId, viewFormat,
2070 minimumMipmapLevel, maximumMipmapLevel - minimumMipmapLevel + 1,
2071 minimumLayer, maximumLayer - minimumLayer + 1);
2072 return view;
2073}
2074
2075
2076/*!
2077 \class QOpenGLTexture
2078 \inmodule QtGui
2079 \since 5.2
2080 \wrapper
2081 \brief The QOpenGLTexture class encapsulates an OpenGL texture object.
2082
2083 QOpenGLTexture makes it easy to work with OpenGL textures and the myriad features
2084 and targets that they offer depending upon the capabilities of your OpenGL implementation.
2085
2086 The typical usage pattern for QOpenGLTexture is
2087 \list
2088 \li Instantiate the object specifying the texture target type
2089 \li Set properties that affect the storage requirements e.g. storage format, dimensions
2090 \li Allocate the server-side storage
2091 \li Optionally upload pixel data
2092 \li Optionally set any additional properties e.g. filtering and border options
2093 \li Render with texture or render to texture
2094 \endlist
2095
2096 In the common case of simply using a QImage as the source of texture pixel data
2097 most of the above steps are performed automatically.
2098
2099 \code
2100 // Prepare texture
2101 QOpenGLTexture *texture = new QOpenGLTexture(QImage(fileName).mirrored());
2102 texture->setMinificationFilter(QOpenGLTexture::LinearMipMapLinear);
2103 texture->setMagnificationFilter(QOpenGLTexture::Linear);
2104 ...
2105 // Render with texture
2106 texture->bind();
2107 glDrawArrays(...);
2108 \endcode
2109
2110 Note that the QImage is mirrored vertically to account for the fact that
2111 OpenGL and QImage use opposite directions for the y axis. Another option
2112 would be to transform your texture coordinates.
2113*/
2114
2115/*!
2116 \enum QOpenGLTexture::Filter
2117 This enum defines the filtering parameters for a QOpenGLTexture object.
2118 \value Nearest Equivalent to GL_NEAREST
2119 \value Linear Equivalent to GL_LINEAR
2120 \value NearestMipMapNearest Equivalent to GL_NEAREST_MIPMAP_NEAREST
2121 \value NearestMipMapLinear Equivalent to GL_NEAREST_MIPMAP_LINEAR
2122 \value LinearMipMapNearest Equivalent to GL_LINEAR_MIPMAP_NEAREST
2123 \value LinearMipMapLinear Equivalent to GL_LINEAR_MIPMAP_LINEAR
2124*/
2125
2126/*!
2127 \enum QOpenGLTexture::Target
2128 This enum defines the texture target of a QOpenGLTexture object.
2129
2130 \value Target1D A 1-dimensional texture.
2131 Equivalent to GL_TEXTURE_1D.
2132 \value Target1DArray An array of 1-dimensional textures.
2133 Equivalent to GL_TEXTURE_1D_ARRAY
2134 \value Target2D A 2-dimensional texture.
2135 Equivalent to GL_TEXTURE_2D
2136 \value Target2DArray An array of 1-dimensional textures.
2137 Equivalent to GL_TEXTURE_2D_ARRAY
2138 \value Target3D A 3-dimensional texture.
2139 Equivalent to GL_TEXTURE_3D
2140 \value TargetCubeMap A cubemap texture.
2141 Equivalent to GL_TEXTURE_CUBE_MAP
2142 \value TargetCubeMapArray An array of cubemap textures.
2143 Equivalent to GL_TEXTURE_CUBE_MAP_ARRAY
2144 \value Target2DMultisample A 2-dimensional texture with multisample support.
2145 Equivalent to GL_TEXTURE_2D_MULTISAMPLE
2146 \value Target2DMultisampleArray An array of 2-dimensional textures with multisample support.
2147 Equivalent to GL_TEXTURE_2D_MULTISAMPLE_ARRAY
2148 \value TargetRectangle A rectangular 2-dimensional texture.
2149 Equivalent to GL_TEXTURE_RECTANGLE
2150 \value TargetBuffer A texture with data from an OpenGL buffer object.
2151 Equivalent to GL_TEXTURE_BUFFER
2152*/
2153
2154/*!
2155 \enum QOpenGLTexture::BindingTarget
2156 This enum defines the possible binding targets of texture units.
2157
2158 \value BindingTarget1D Equivalent to GL_TEXTURE_BINDING_1D
2159 \value BindingTarget1DArray Equivalent to GL_TEXTURE_BINDING_1D_ARRAY
2160 \value BindingTarget2D Equivalent to GL_TEXTURE_BINDING_2D
2161 \value BindingTarget2DArray Equivalent to GL_TEXTURE_BINDING_2D_ARRAY
2162 \value BindingTarget3D Equivalent to GL_TEXTURE_BINDING_3D
2163 \value BindingTargetCubeMap Equivalent to GL_TEXTURE_BINDING_CUBE_MAP
2164 \value BindingTargetCubeMapArray Equivalent to GL_TEXTURE_BINDING_CUBE_MAP_ARRAY
2165 \value BindingTarget2DMultisample Equivalent to GL_TEXTURE_BINDING_2D_MULTISAMPLE
2166 \value BindingTarget2DMultisampleArray Equivalent to GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY
2167 \value BindingTargetRectangle Equivalent to GL_TEXTURE_BINDING_RECTANGLE
2168 \value BindingTargetBuffer Equivalent to GL_TEXTURE_BINDING_BUFFER
2169*/
2170
2171/*!
2172 \enum QOpenGLTexture::MipMapGeneration
2173 This enum defines the options to control mipmap generation.
2174
2175 \value GenerateMipMaps Mipmaps should be generated
2176 \value DontGenerateMipMaps Mipmaps should not be generated
2177*/
2178
2179/*!
2180 \enum QOpenGLTexture::TextureUnitReset
2181 This enum defines options ot control texture unit activation.
2182
2183 \value ResetTextureUnit The previous active texture unit will be reset
2184 \value DontResetTextureUnit The previous active texture unit will not be rest
2185*/
2186
2187/*!
2188 \enum QOpenGLTexture::TextureFormat
2189 This enum defines the possible texture formats. Depending upon your OpenGL
2190 implementation only a subset of these may be supported.
2191
2192 \value NoFormat Equivalent to GL_NONE
2193
2194 \value R8_UNorm Equivalent to GL_R8
2195 \value RG8_UNorm Equivalent to GL_RG8
2196 \value RGB8_UNorm Equivalent to GL_RGB8
2197 \value RGBA8_UNorm Equivalent to GL_RGBA8
2198
2199 \value R16_UNorm Equivalent to GL_R16
2200 \value RG16_UNorm Equivalent to GL_RG16
2201 \value RGB16_UNorm Equivalent to GL_RGB16
2202 \value RGBA16_UNorm Equivalent to GL_RGBA16
2203
2204 \value R8_SNorm Equivalent to GL_R8_SNORM
2205 \value RG8_SNorm Equivalent to GL_RG8_SNORM
2206 \value RGB8_SNorm Equivalent to GL_RGB8_SNORM
2207 \value RGBA8_SNorm Equivalent to GL_RGBA8_SNORM
2208
2209 \value R16_SNorm Equivalent to GL_R16_SNORM
2210 \value RG16_SNorm Equivalent to GL_RG16_SNORM
2211 \value RGB16_SNorm Equivalent to GL_RGB16_SNORM
2212 \value RGBA16_SNorm Equivalent to GL_RGBA16_SNORM
2213
2214 \value R8U Equivalent to GL_R8UI
2215 \value RG8U Equivalent to GL_RG8UI
2216 \value RGB8U Equivalent to GL_RGB8UI
2217 \value RGBA8U Equivalent to GL_RGBA8UI
2218
2219 \value R16U Equivalent to GL_R16UI
2220 \value RG16U Equivalent to GL_RG16UI
2221 \value RGB16U Equivalent to GL_RGB16UI
2222 \value RGBA16U Equivalent to GL_RGBA16UI
2223
2224 \value R32U Equivalent to GL_R32UI
2225 \value RG32U Equivalent to GL_RG32UI
2226 \value RGB32U Equivalent to GL_RGB32UI
2227 \value RGBA32U Equivalent to GL_RGBA32UI
2228
2229 \value R8I Equivalent to GL_R8I
2230 \value RG8I Equivalent to GL_RG8I
2231 \value RGB8I Equivalent to GL_RGB8I
2232 \value RGBA8I Equivalent to GL_RGBA8I
2233
2234 \value R16I Equivalent to GL_R16I
2235 \value RG16I Equivalent to GL_RG16I
2236 \value RGB16I Equivalent to GL_RGB16I
2237 \value RGBA16I Equivalent to GL_RGBA16I
2238
2239 \value R32I Equivalent to GL_R32I
2240 \value RG32I Equivalent to GL_RG32I
2241 \value RGB32I Equivalent to GL_RGB32I
2242 \value RGBA32I Equivalent to GL_RGBA32I
2243
2244 \value R16F Equivalent to GL_R16F
2245 \value RG16F Equivalent to GL_RG16F
2246 \value RGB16F Equivalent to GL_RGB16F
2247 \value RGBA16F Equivalent to GL_RGBA16F
2248
2249 \value R32F Equivalent to GL_R32F
2250 \value RG32F Equivalent to GL_RG32F
2251 \value RGB32F Equivalent to GL_RGB32F
2252 \value RGBA32F Equivalent to GL_RGBA32F
2253
2254 \value RGB9E5 Equivalent to GL_RGB9_E5
2255 \value RG11B10F Equivalent to GL_R11F_G11F_B10F
2256 \value RG3B2 Equivalent to GL_R3_G3_B2
2257 \value R5G6B5 Equivalent to GL_RGB565
2258 \value RGB5A1 Equivalent to GL_RGB5_A1
2259 \value RGBA4 Equivalent to GL_RGBA4
2260 \value RGB10A2 Equivalent to GL_RGB10_A2UI
2261
2262 \value D16 Equivalent to GL_DEPTH_COMPONENT16
2263 \value D24 Equivalent to GL_DEPTH_COMPONENT24
2264 \value D24S8 Equivalent to GL_DEPTH24_STENCIL8
2265 \value D32 Equivalent to GL_DEPTH_COMPONENT32
2266 \value D32F Equivalent to GL_DEPTH_COMPONENT32F
2267 \value D32FS8X24 Equivalent to GL_DEPTH32F_STENCIL8
2268 \value S8 Equivalent to GL_STENCIL_INDEX8. Introduced in Qt 5.4
2269
2270 \value RGB_DXT1 Equivalent to GL_COMPRESSED_RGB_S3TC_DXT1_EXT
2271 \value RGBA_DXT1 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT1_EXT
2272 \value RGBA_DXT3 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT3_EXT
2273 \value RGBA_DXT5 Equivalent to GL_COMPRESSED_RGBA_S3TC_DXT5_EXT
2274 \value R_ATI1N_UNorm Equivalent to GL_COMPRESSED_RED_RGTC1
2275 \value R_ATI1N_SNorm Equivalent to GL_COMPRESSED_SIGNED_RED_RGTC1
2276 \value RG_ATI2N_UNorm Equivalent to GL_COMPRESSED_RG_RGTC2
2277 \value RG_ATI2N_SNorm Equivalent to GL_COMPRESSED_SIGNED_RG_RGTC2
2278 \value RGB_BP_UNSIGNED_FLOAT Equivalent to GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_ARB
2279 \value RGB_BP_SIGNED_FLOAT Equivalent to GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_ARB
2280 \value RGB_BP_UNorm Equivalent to GL_COMPRESSED_RGBA_BPTC_UNORM_ARB
2281 \value R11_EAC_UNorm Equivalent to GL_COMPRESSED_R11_EAC
2282 \value R11_EAC_SNorm Equivalent to GL_COMPRESSED_SIGNED_R11_EAC
2283 \value RG11_EAC_UNorm Equivalent to GL_COMPRESSED_RG11_EAC
2284 \value RG11_EAC_SNorm Equivalent to GL_COMPRESSED_SIGNED_RG11_EAC
2285 \value RGB8_ETC2 Equivalent to GL_COMPRESSED_RGB8_ETC2
2286 \value SRGB8_ETC2 Equivalent to GL_COMPRESSED_SRGB8_ETC2
2287 \value RGB8_PunchThrough_Alpha1_ETC2 Equivalent to GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2
2288 \value SRGB8_PunchThrough_Alpha1_ETC2 Equivalent to GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2
2289 \value RGBA8_ETC2_EAC Equivalent to GL_COMPRESSED_RGBA8_ETC2_EAC
2290 \value SRGB8_Alpha8_ETC2_EAC Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC
2291 \value RGB8_ETC1 Equivalent to GL_ETC1_RGB8_OES
2292 \value RGBA_ASTC_4x4 Equivalent to GL_COMPRESSED_RGBA_ASTC_4x4_KHR
2293 \value RGBA_ASTC_5x4 Equivalent to GL_COMPRESSED_RGBA_ASTC_5x4_KHR
2294 \value RGBA_ASTC_5x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_5x5_KHR
2295 \value RGBA_ASTC_6x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_6x5_KHR
2296 \value RGBA_ASTC_6x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_6x6_KHR
2297 \value RGBA_ASTC_8x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x5_KHR
2298 \value RGBA_ASTC_8x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x6_KHR
2299 \value RGBA_ASTC_8x8 Equivalent to GL_COMPRESSED_RGBA_ASTC_8x8_KHR
2300 \value RGBA_ASTC_10x5 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x5_KHR
2301 \value RGBA_ASTC_10x6 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x6_KHR
2302 \value RGBA_ASTC_10x8 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x8_KHR
2303 \value RGBA_ASTC_10x10 Equivalent to GL_COMPRESSED_RGBA_ASTC_10x10_KHR
2304 \value RGBA_ASTC_12x10 Equivalent to GL_COMPRESSED_RGBA_ASTC_12x10_KHR
2305 \value RGBA_ASTC_12x12 Equivalent to GL_COMPRESSED_RGBA_ASTC_12x12_KHR
2306 \value SRGB8_Alpha8_ASTC_4x4 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR
2307 \value SRGB8_Alpha8_ASTC_5x4 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR
2308 \value SRGB8_Alpha8_ASTC_5x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR
2309 \value SRGB8_Alpha8_ASTC_6x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR
2310 \value SRGB8_Alpha8_ASTC_6x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR
2311 \value SRGB8_Alpha8_ASTC_8x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR
2312 \value SRGB8_Alpha8_ASTC_8x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR
2313 \value SRGB8_Alpha8_ASTC_8x8 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR
2314 \value SRGB8_Alpha8_ASTC_10x5 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR
2315 \value SRGB8_Alpha8_ASTC_10x6 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR
2316 \value SRGB8_Alpha8_ASTC_10x8 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR
2317 \value SRGB8_Alpha8_ASTC_10x10 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR
2318 \value SRGB8_Alpha8_ASTC_12x10 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR
2319 \value SRGB8_Alpha8_ASTC_12x12 Equivalent to GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR
2320
2321 \value SRGB8 Equivalent to GL_SRGB8
2322 \value SRGB8_Alpha8 Equivalent to GL_SRGB8_ALPHA8
2323 \value SRGB_DXT1 Equivalent to GL_COMPRESSED_SRGB_S3TC_DXT1_EXT
2324 \value SRGB_Alpha_DXT1 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT
2325 \value SRGB_Alpha_DXT3 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT
2326 \value SRGB_Alpha_DXT5 Equivalent to GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT
2327 \value SRGB_BP_UNorm Equivalent to GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_ARB
2328
2329 \value DepthFormat Equivalent to GL_DEPTH_COMPONENT (only OpenGL ES 3 or ES 2 with OES_depth_texture)
2330 \value AlphaFormat Equivalent to GL_ALPHA (OpenGL ES 2 only)
2331 \value RGBFormat Equivalent to GL_RGB (OpenGL ES 2 only)
2332 \value RGBAFormat Equivalent to GL_RGBA (OpenGL ES 2 only)
2333 \value LuminanceFormat Equivalent to GL_LUMINANCE (OpenGL ES 2 only)
2334 \value LuminanceAlphaFormat Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only)
2335*/
2336
2337/*!
2338 \enum QOpenGLTexture::CubeMapFace
2339 This enum defines the possible CubeMap faces.
2340
2341 \value CubeMapPositiveX Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_X
2342 \value CubeMapNegativeX Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_X
2343 \value CubeMapPositiveY Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_Y
2344 \value CubeMapNegativeY Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_Y
2345 \value CubeMapPositiveZ Equivalent to GL_TEXTURE_CUBE_MAP_POSITIVE_Z
2346 \value CubeMapNegativeZ Equivalent to GL_TEXTURE_CUBE_MAP_NEGATIVE_Z
2347*/
2348
2349/*!
2350 \enum QOpenGLTexture::PixelFormat
2351 This enum defines the possible client-side pixel formats for a pixel
2352 transfer operation.
2353
2354 \value NoSourceFormat Equivalent to GL_NONE
2355 \value Red Equivalent to GL_RED
2356 \value RG Equivalent to GL_RG
2357 \value RGB Equivalent to GL_RGB
2358 \value BGR Equivalent to GL_BGR
2359 \value RGBA Equivalent to GL_RGBA
2360 \value BGRA Equivalent to GL_BGRA
2361 \value Red_Integer Equivalent to GL_RED_INTEGER
2362 \value RG_Integer Equivalent to GL_RG_INTEGER
2363 \value RGB_Integer Equivalent to GL_RGB_INTEGER
2364 \value BGR_Integer Equivalent to GL_BGR_INTEGER
2365 \value RGBA_Integer Equivalent to GL_RGBA_INTEGER
2366 \value BGRA_Integer Equivalent to GL_BGRA_INTEGER
2367 \value Stencil Equivalent to GL_STENCIL_INDEX. Introduced in Qt 5.4
2368 \value Depth Equivalent to GL_DEPTH_COMPONENT
2369 \value DepthStencil Equivalent to GL_DEPTH_STENCIL
2370 \value Alpha Equivalent to GL_ALPHA (OpenGL ES 2 only)
2371 \value Luminance Equivalent to GL_LUMINANCE (OpenGL ES 2 only)
2372 \value LuminanceAlpha Equivalent to GL_LUMINANCE_ALPHA (OpenGL ES 2 only)
2373
2374*/
2375
2376/*!
2377 \enum QOpenGLTexture::PixelType
2378 This enum defines the possible pixel data types for a pixel transfer operation
2379
2380 \value NoPixelType Equivalent to GL_NONE
2381 \value Int8 Equivalent to GL_BYTE
2382 \value UInt8 Equivalent to GL_UNSIGNED_BYTE
2383 \value Int16 Equivalent to GL_SHORT
2384 \value UInt16 Equivalent to GL_UNSIGNED_SHORT
2385 \value Int32 Equivalent to GL_INT
2386 \value UInt32 Equivalent to GL_UNSIGNED_INT
2387 \value Float16 Equivalent to GL_HALF_FLOAT
2388 \value Float16OES Equivalent to GL_HALF_FLOAT_OES
2389 \value Float32 Equivalent to GL_FLOAT
2390 \value UInt32_RGB9_E5 Equivalent to GL_UNSIGNED_INT_5_9_9_9_REV
2391 \value UInt32_RG11B10F Equivalent to GL_UNSIGNED_INT_10F_11F_11F_REV
2392 \value UInt8_RG3B2 Equivalent to GL_UNSIGNED_BYTE_3_3_2
2393 \value UInt8_RG3B2_Rev Equivalent to GL_UNSIGNED_BYTE_2_3_3_REV
2394 \value UInt16_RGB5A1 Equivalent to GL_UNSIGNED_SHORT_5_5_5_1
2395 \value UInt16_RGB5A1_Rev Equivalent to GL_UNSIGNED_SHORT_1_5_5_5_REV
2396 \value UInt16_R5G6B5 Equivalent to GL_UNSIGNED_SHORT_5_6_5
2397 \value UInt16_R5G6B5_Rev Equivalent to GL_UNSIGNED_SHORT_5_6_5_REV
2398 \value UInt16_RGBA4 Equivalent to GL_UNSIGNED_SHORT_4_4_4_4
2399 \value UInt16_RGBA4_Rev Equivalent to GL_UNSIGNED_SHORT_4_4_4_4_REV
2400 \value UInt32_RGBA8 Equivalent to GL_UNSIGNED_INT_8_8_8_8
2401 \value UInt32_RGBA8_Rev Equivalent to GL_UNSIGNED_INT_8_8_8_8_REV
2402 \value UInt32_RGB10A2 Equivalent to GL_UNSIGNED_INT_10_10_10_2
2403 \value UInt32_RGB10A2_Rev Equivalent to GL_UNSIGNED_INT_2_10_10_10_REV
2404 \value UInt32_D24S8 Equivalent to GL_UNSIGNED_INT_24_8. Introduced in Qt 5.4
2405 \value Float32_D32_UInt32_S8_X24 Equivalent to GL_FLOAT_32_UNSIGNED_INT_24_8_REV. Introduced in Qt 5.4
2406*/
2407
2408/*!
2409 \enum QOpenGLTexture::Feature
2410 This enum defines the OpenGL texture-related features that can be tested for.
2411
2412 \value ImmutableStorage Support for immutable texture storage
2413 \value ImmutableMultisampleStorage Support for immutable texture storage with
2414 multisample targets
2415 \value TextureRectangle Support for the GL_TEXTURE_RECTANGLE target
2416 \value TextureArrays Support for texture targets with array layers
2417 \value Texture3D Support for the 3 dimensional texture target
2418 \value TextureMultisample Support for texture targets that have multisample capabilities
2419 \value TextureBuffer Support for textures that use OpenGL buffer objects
2420 as their data source
2421 \value TextureCubeMapArrays Support for cubemap array texture target
2422 \value Swizzle Support for texture component swizzle masks
2423 \value StencilTexturing Support for stencil texturing (i.e. looking up depth or stencil
2424 components of a combined depth/stencil format texture in GLSL shaders).
2425 \value AnisotropicFiltering Support for anisotropic texture filtering
2426 \value NPOTTextures Basic support for non-power-of-two textures
2427 \value NPOTTextureRepeat Full support for non-power-of-two textures including texture
2428 repeat modes
2429 \value Texture1D Support for the 1 dimensional texture target
2430 \value TextureComparisonOperators Support for texture comparison operators
2431 \value TextureMipMapLevel Support for setting the base and maximum mipmap levels
2432*/
2433
2434/*!
2435 \enum QOpenGLTexture::SwizzleComponent
2436 This enum defines the texture color components that can be assigned a swizzle mask.
2437
2438 \value SwizzleRed The red component. Equivalent to GL_TEXTURE_SWIZZLE_R
2439 \value SwizzleGreen The green component. Equivalent to GL_TEXTURE_SWIZZLE_G
2440 \value SwizzleBlue The blue component. Equivalent to GL_TEXTURE_SWIZZLE_B
2441 \value SwizzleAlpha The alpha component. Equivalent to GL_TEXTURE_SWIZZLE_A
2442*/
2443
2444/*!
2445 \enum QOpenGLTexture::SwizzleValue
2446 This enum defines the possible mask values for texture swizzling.
2447
2448 \value RedValue Maps the component to the red channel. Equivalent to GL_RED
2449 \value GreenValue Maps the component to the green channel. Equivalent to GL_GREEN
2450 \value BlueValue Maps the component to the blue channel. Equivalent to GL_BLUE
2451 \value AlphaValue Maps the component to the alpha channel. Equivalent to GL_ALPHA
2452 \value ZeroValue Maps the component to a fixed value of 0. Equivalent to GL_ZERO
2453 \value OneValue Maps the component to a fixed value of 1. Equivalent to GL_ONE
2454*/
2455
2456/*!
2457 \enum QOpenGLTexture::WrapMode
2458 This enum defines the possible texture coordinate wrapping modes.
2459
2460 \value Repeat Texture coordinate is repeated. Equivalent to GL_REPEAT
2461 \value MirroredRepeat Texture coordinate is reflected about 0 and 1. Equivalent to GL_MIRRORED_REPEAT
2462 \value ClampToEdge Clamps the texture coordinates to [0,1]. Equivalent to GL_CLAMP_TO_EDGE
2463 \value ClampToBorder As for ClampToEdge but also blends samples at 0 and 1 with a
2464 fixed border color. Equivalent to GL_CLAMP_TO_BORDER
2465*/
2466
2467/*!
2468 \enum QOpenGLTexture::CoordinateDirection
2469 This enum defines the possible texture coordinate directions
2470
2471 \value DirectionS The horizontal direction. Equivalent to GL_TEXTURE_WRAP_S
2472 \value DirectionT The vertical direction. Equivalent to GL_TEXTURE_WRAP_T
2473 \value DirectionR The depth direction. Equivalent to GL_TEXTURE_WRAP_R
2474*/
2475
2476/*!
2477 Creates a QOpenGLTexture object that can later be bound to \a target.
2478
2479 This does not create the underlying OpenGL texture object. Therefore,
2480 construction using this constructor does not require a valid current
2481 OpenGL context.
2482*/
2483QOpenGLTexture::QOpenGLTexture(Target target)
2484 : d_ptr(new QOpenGLTexturePrivate(target, this))
2485{
2486}
2487
2488/*!
2489 Creates a QOpenGLTexture object that can later be bound to the 2D texture
2490 target and contains the pixel data contained in \a image. If you wish
2491 to have a chain of mipmaps generated then set \a genMipMaps to \c true (this
2492 is the default).
2493
2494 This does create the underlying OpenGL texture object. Therefore,
2495 construction using this constructor does require a valid current
2496 OpenGL context.
2497*/
2498QOpenGLTexture::QOpenGLTexture(const QImage& image, MipMapGeneration genMipMaps)
2499 : QOpenGLTexture(QOpenGLTexture::Target2D)
2500{
2501 setData(image, genMipMaps);
2502}
2503
2504QOpenGLTexture::~QOpenGLTexture()
2505{
2506}
2507
2508/*!
2509 Returns the binding target of this texture.
2510
2511 \since 5.4
2512*/
2513QOpenGLTexture::Target QOpenGLTexture::target() const
2514{
2515 Q_D(const QOpenGLTexture);
2516 return d->target;
2517}
2518
2519/*!
2520 Creates the underlying OpenGL texture object. This requires a current valid
2521 OpenGL context. If the texture object already exists, this function does
2522 nothing.
2523
2524 Once the texture object is created you can obtain the object
2525 name from the textureId() function. This may be useful if you wish to make
2526 some raw OpenGL calls related to this texture.
2527
2528 Normally it should not be necessary to call this function directly as all
2529 functions that set properties of the texture object implicitly call create()
2530 on your behalf.
2531
2532 Returns \c true if the creation succeeded, otherwise returns \c false.
2533
2534 \sa destroy(), isCreated(), textureId()
2535*/
2536bool QOpenGLTexture::create()
2537{
2538 Q_D(QOpenGLTexture);
2539 return d->create();
2540}
2541
2542/*!
2543 Destroys the underlying OpenGL texture object. This requires a current valid
2544 OpenGL context.
2545
2546 \sa create(), isCreated(), textureId()
2547*/
2548void QOpenGLTexture::destroy()
2549{
2550 Q_D(QOpenGLTexture);
2551 return d->destroy();
2552}
2553
2554/*!
2555 Returns \c true if the underlying OpenGL texture object has been created.
2556
2557 \sa create(), destroy(), textureId()
2558*/
2559bool QOpenGLTexture::isCreated() const
2560{
2561 Q_D(const QOpenGLTexture);
2562 return d->textureId != 0;
2563}
2564
2565/*!
2566 Returns the name of the underlying OpenGL texture object or 0 if it has
2567 not yet been created.
2568
2569 \sa create(), destroy(), isCreated()
2570*/
2571GLuint QOpenGLTexture::textureId() const
2572{
2573 Q_D(const QOpenGLTexture);
2574 return d->textureId;
2575}
2576
2577/*!
2578 Binds this texture to the currently active texture unit ready for
2579 rendering. Note that you do not need to bind QOpenGLTexture objects
2580 in order to modify them as the implementation makes use of the
2581 EXT_direct_state_access extension where available and simulates it
2582 where it is not.
2583
2584 \sa release()
2585*/
2586void QOpenGLTexture::bind()
2587{
2588 Q_D(QOpenGLTexture);
2589 Q_ASSERT(d->textureId);
2590 d->bind();
2591}
2592
2593/*!
2594 Binds this texture to texture unit \a unit ready for
2595 rendering. Note that you do not need to bind QOpenGLTexture objects
2596 in order to modify them as the implementation makes use of the
2597 EXT_direct_state_access extension where available and simulates it
2598 where it is not.
2599
2600 If parameter \a reset is \c true then this function will restore
2601 the active unit to the texture unit that was active upon entry.
2602
2603 \sa release()
2604*/
2605void QOpenGLTexture::bind(uint unit, TextureUnitReset reset)
2606{
2607 Q_D(QOpenGLTexture);
2608 Q_ASSERT(d->textureId);
2609 d->bind(unit, reset);
2610}
2611
2612/*!
2613 Unbinds this texture from the currently active texture unit.
2614
2615 \sa bind()
2616*/
2617void QOpenGLTexture::release()
2618{
2619 Q_D(QOpenGLTexture);
2620 d->release();
2621}
2622
2623/*!
2624 Unbinds this texture from texture unit \a unit.
2625
2626 If parameter \a reset is \c true then this function
2627 will restore the active unit to the texture unit that was active
2628 upon entry.
2629*/
2630void QOpenGLTexture::release(uint unit, TextureUnitReset reset)
2631{
2632 Q_D(QOpenGLTexture);
2633 d->release(unit, reset);
2634}
2635
2636/*!
2637 Returns \c true if this texture is bound to the corresponding target
2638 of the currently active texture unit.
2639
2640 \sa bind(), release()
2641*/
2642bool QOpenGLTexture::isBound() const
2643{
2644 Q_D(const QOpenGLTexture);
2645 Q_ASSERT(d->textureId);
2646 return d->isBound();
2647}
2648
2649/*!
2650 Returns \c true if this texture is bound to the corresponding target
2651 of texture unit \a unit.
2652
2653 \sa bind(), release()
2654*/
2655bool QOpenGLTexture::isBound(uint unit)
2656{
2657 Q_D(const QOpenGLTexture);
2658 Q_ASSERT(d->textureId);
2659 return d->isBound(unit);
2660}
2661
2662/*!
2663 Returns the textureId of the texture that is bound to the \a target
2664 of the currently active texture unit.
2665*/
2666GLuint QOpenGLTexture::boundTextureId(BindingTarget target)
2667{
2668 QOpenGLContext *ctx = QOpenGLContext::currentContext();
2669 if (!ctx) {
2670 qWarning("QOpenGLTexture::boundTextureId() requires a valid current context");
2671 return 0;
2672 }
2673
2674 GLint textureId = 0;
2675 ctx->functions()->glGetIntegerv(target, &textureId);
2676 return static_cast<GLuint>(textureId);
2677}
2678
2679/*!
2680 Returns the textureId of the texture that is bound to the \a target
2681 of the texture unit \a unit.
2682*/
2683GLuint QOpenGLTexture::boundTextureId(uint unit, BindingTarget target)
2684{
2685 QOpenGLContext *ctx = QOpenGLContext::currentContext();
2686 if (!ctx) {
2687 qWarning("QOpenGLTexture::boundTextureId() requires a valid current context");
2688 return 0;
2689 }
2690
2691 QOpenGLFunctions *funcs = ctx->functions();
2692 funcs->initializeOpenGLFunctions();
2693
2694 GLint oldTextureUnit = 0;
2695 funcs->glGetIntegerv(GL_ACTIVE_TEXTURE, &oldTextureUnit);
2696
2697 funcs->glActiveTexture(unit);
2698 GLint textureId = 0;
2699 funcs->glGetIntegerv(target, &textureId);
2700 funcs->glActiveTexture(oldTextureUnit);
2701
2702 return static_cast<GLuint>(textureId);
2703}
2704
2705/*!
2706 Sets the format of this texture object to \a format. This function
2707 must be called before texture storage is allocated.
2708
2709 Note that all formats may not be supported. The exact set of supported
2710 formats is dependent upon your OpenGL implementation and version.
2711
2712 \sa format(), allocateStorage()
2713*/
2714void QOpenGLTexture::setFormat(TextureFormat format)
2715{
2716 Q_D(QOpenGLTexture);
2717 d->create();
2718 if (isStorageAllocated()) {
2719 qWarning("QOpenGLTexture::setFormat(): Cannot change format once storage has been allocated");
2720 return;
2721 }
2722
2723 d->format = format;
2724
2725 switch (format) {
2726 case NoFormat:
2727 d->formatClass = NoFormatClass;
2728 break;
2729
2730 case RGBA32F:
2731 case RGBA32U:
2732 case RGBA32I:
2733 d->formatClass = FormatClass_128Bit;
2734 break;
2735
2736 case RGB32F:
2737 case RGB32U:
2738 case RGB32I:
2739 d->formatClass = FormatClass_96Bit;
2740 break;
2741
2742 case RGBA16F:
2743 case RG32F:
2744 case RGBA16U:
2745 case RG32U:
2746 case RGBA16I:
2747 case RG32I:
2748 case RGBA16_UNorm:
2749 case RGBA16_SNorm:
2750 d->formatClass = FormatClass_64Bit;
2751 break;
2752
2753 case RGB16_UNorm:
2754 case RGB16_SNorm:
2755 case RGB16F:
2756 case RGB16U:
2757 case RGB16I:
2758 d->formatClass = FormatClass_48Bit;
2759 break;
2760
2761 case RG16F:
2762 case RG11B10F:
2763 case R32F:
2764 case RGB10A2:
2765 case RGBA8U:
2766 case RG16U:
2767 case R32U:
2768 case RGBA8I:
2769 case RG16I:
2770 case R32I:
2771 case RGBA8_UNorm:
2772 case RG16_UNorm:
2773 case RGBA8_SNorm:
2774 case RG16_SNorm:
2775 case SRGB8_Alpha8:
2776 case RGB9E5:
2777 d->formatClass = FormatClass_32Bit;
2778 break;
2779
2780 case RGB8_UNorm:
2781 case RGB8_SNorm:
2782 case SRGB8:
2783 case RGB8U:
2784 case RGB8I:
2785 d->formatClass = FormatClass_24Bit;
2786 break;
2787
2788 case R16F:
2789 case RG8U:
2790 case R16U:
2791 case RG8I:
2792 case R16I:
2793 case RG8_UNorm:
2794 case R16_UNorm:
2795 case RG8_SNorm:
2796 case R16_SNorm:
2797 d->formatClass = FormatClass_16Bit;
2798 break;
2799
2800 case R8U:
2801 case R8I:
2802 case R8_UNorm:
2803 case R8_SNorm:
2804 d->formatClass = FormatClass_8Bit;
2805 break;
2806
2807 case R_ATI1N_UNorm:
2808 case R_ATI1N_SNorm:
2809 d->formatClass = FormatClass_RGTC1_R;
2810 break;
2811
2812 case RG_ATI2N_UNorm:
2813 case RG_ATI2N_SNorm:
2814 d->formatClass = FormatClass_RGTC2_RG;
2815 break;
2816
2817 case RGB_BP_UNorm:
2818 case SRGB_BP_UNorm:
2819 d->formatClass = FormatClass_BPTC_Unorm;
2820 break;
2821
2822 case RGB_BP_UNSIGNED_FLOAT:
2823 case RGB_BP_SIGNED_FLOAT:
2824 d->formatClass = FormatClass_BPTC_Float;
2825 break;
2826
2827 case RGB_DXT1:
2828 case SRGB_DXT1:
2829 d->formatClass = FormatClass_S3TC_DXT1_RGB;
2830 break;
2831
2832 case RGBA_DXT1:
2833 case SRGB_Alpha_DXT1:
2834 d->formatClass = FormatClass_S3TC_DXT1_RGBA;
2835 break;
2836
2837 case RGBA_DXT3:
2838 case SRGB_Alpha_DXT3:
2839 d->formatClass = FormatClass_S3TC_DXT3_RGBA;
2840 break;
2841
2842 case RGBA_DXT5:
2843 case SRGB_Alpha_DXT5:
2844 d->formatClass = FormatClass_S3TC_DXT5_RGBA;
2845 break;
2846
2847 case QOpenGLTexture::R11_EAC_UNorm:
2848 case QOpenGLTexture::R11_EAC_SNorm:
2849 case QOpenGLTexture::RG11_EAC_UNorm:
2850 case QOpenGLTexture::RG11_EAC_SNorm:
2851 case QOpenGLTexture::RGB8_ETC2:
2852 case QOpenGLTexture::SRGB8_ETC2:
2853 case QOpenGLTexture::RGB8_PunchThrough_Alpha1_ETC2:
2854 case QOpenGLTexture::SRGB8_PunchThrough_Alpha1_ETC2:
2855 case QOpenGLTexture::RGBA8_ETC2_EAC:
2856 case QOpenGLTexture::SRGB8_Alpha8_ETC2_EAC:
2857 case QOpenGLTexture::RGB8_ETC1:
2858 case RG3B2:
2859 case R5G6B5:
2860 case RGB5A1:
2861 case RGBA4:
2862 case D16:
2863 case D24:
2864 case D24S8:
2865 case D32:
2866 case D32F:
2867 case D32FS8X24:
2868 case S8:
2869 case DepthFormat:
2870 case AlphaFormat:
2871 case RGBFormat:
2872 case RGBAFormat:
2873 case LuminanceFormat:
2874 case LuminanceAlphaFormat:
2875 case QOpenGLTexture::RGBA_ASTC_4x4:
2876 case QOpenGLTexture::RGBA_ASTC_5x4:
2877 case QOpenGLTexture::RGBA_ASTC_5x5:
2878 case QOpenGLTexture::RGBA_ASTC_6x5:
2879 case QOpenGLTexture::RGBA_ASTC_6x6:
2880 case QOpenGLTexture::RGBA_ASTC_8x5:
2881 case QOpenGLTexture::RGBA_ASTC_8x6:
2882 case QOpenGLTexture::RGBA_ASTC_8x8:
2883 case QOpenGLTexture::RGBA_ASTC_10x5:
2884 case QOpenGLTexture::RGBA_ASTC_10x6:
2885 case QOpenGLTexture::RGBA_ASTC_10x8:
2886 case QOpenGLTexture::RGBA_ASTC_10x10:
2887 case QOpenGLTexture::RGBA_ASTC_12x10:
2888 case QOpenGLTexture::RGBA_ASTC_12x12:
2889 case QOpenGLTexture::SRGB8_Alpha8_ASTC_4x4:
2890 case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x4:
2891 case QOpenGLTexture::SRGB8_Alpha8_ASTC_5x5:
2892 case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x5:
2893 case QOpenGLTexture::SRGB8_Alpha8_ASTC_6x6:
2894 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x5:
2895 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x6:
2896 case QOpenGLTexture::SRGB8_Alpha8_ASTC_8x8:
2897 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x5:
2898 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x6:
2899 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x8:
2900 case QOpenGLTexture::SRGB8_Alpha8_ASTC_10x10:
2901 case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x10:
2902 case QOpenGLTexture::SRGB8_Alpha8_ASTC_12x12:
2903 d->formatClass = FormatClass_Unique;
2904 break;
2905 }
2906}
2907
2908/*!
2909 Returns the format of this texture object.
2910
2911 \sa setFormat()
2912*/
2913QOpenGLTexture::TextureFormat QOpenGLTexture::format() const
2914{
2915 Q_D(const QOpenGLTexture);
2916 return d->format;
2917}
2918
2919static bool isNpot(int width, int height = 1, int depth = 1)
2920{
2921 return width & (width-1) || height & (height-1) || depth & (depth-1);
2922}
2923
2924/*!
2925 Sets the dimensions of this texture object to \a width,
2926 \a height, and \a depth. The default for each dimension is 1.
2927 The maximum allowable texture size is dependent upon your OpenGL
2928 implementation. Allocating storage for a texture less than the
2929 maximum size can still fail if your system is low on resources.
2930
2931 If a non-power-of-two \a width, \a height or \a depth is provided and your
2932 OpenGL implementation doesn't have support for repeating non-power-of-two
2933 textures, then the wrap mode is automatically set to ClampToEdge.
2934
2935 \sa width(), height(), depth()
2936*/
2937void QOpenGLTexture::setSize(int width, int height, int depth)
2938{
2939 Q_D(QOpenGLTexture);
2940 d->create();
2941 if (isStorageAllocated()) {
2942 qWarning("Cannot resize a texture that already has storage allocated.\n"
2943 "To do so, destroy() the texture and then create() and setSize()");
2944 return;
2945 }
2946
2947 if (isNpot(width, height, depth) && !hasFeature(Feature::NPOTTextureRepeat) && d->target != Target::TargetRectangle)
2948 d->setWrapMode(WrapMode::ClampToEdge);
2949
2950 switch (d->target) {
2951 case QOpenGLTexture::Target1D:
2952 case QOpenGLTexture::Target1DArray:
2953 case QOpenGLTexture::TargetBuffer:
2954 d->dimensions[0] = width;
2955 Q_UNUSED(height);
2956 Q_UNUSED(depth);
2957 break;
2958
2959 case QOpenGLTexture::Target2D:
2960 case QOpenGLTexture::Target2DArray:
2961 case QOpenGLTexture::TargetRectangle:
2962 case QOpenGLTexture::Target2DMultisample:
2963 case QOpenGLTexture::Target2DMultisampleArray:
2964 d->dimensions[0] = width;
2965 d->dimensions[1] = height;
2966 Q_UNUSED(depth);
2967 break;
2968
2969 case QOpenGLTexture::TargetCubeMap:
2970 case QOpenGLTexture::TargetCubeMapArray:
2971 if (width != height)
2972 qWarning("QAbstractOpenGLTexture::setSize(): Cube map textures must be square");
2973 d->dimensions[0] = d->dimensions[1] = width;
2974 Q_UNUSED(depth);
2975 break;
2976
2977 case QOpenGLTexture::Target3D:
2978 d->dimensions[0] = width;
2979 d->dimensions[1] = height;
2980 d->dimensions[2] = depth;
2981 break;
2982 }
2983}
2984
2985/*!
2986 Returns the width of a 1D, 2D or 3D texture.
2987
2988 \sa height(), depth(), setSize()
2989*/
2990int QOpenGLTexture::width() const
2991{
2992 Q_D(const QOpenGLTexture);
2993 return d->dimensions[0];
2994}
2995
2996/*!
2997 Returns the height of a 2D or 3D texture.
2998
2999 \sa width(), depth(), setSize()
3000*/
3001int QOpenGLTexture::height() const
3002{
3003 Q_D(const QOpenGLTexture);
3004 return d->dimensions[1];
3005}
3006
3007/*!
3008 Returns the depth of a 3D texture.
3009
3010 \sa width(), height(), setSize()
3011*/
3012int QOpenGLTexture::depth() const
3013{
3014 Q_D(const QOpenGLTexture);
3015 return d->dimensions[2];
3016}
3017
3018/*!
3019 For texture targets that support mipmaps, this function
3020 sets the requested number of mipmap \a levels to allocate storage
3021 for. This function should be called before storage is allocated
3022 for the texture.
3023
3024 If the texture target does not support mipmaps this function
3025 has no effect.
3026
3027 \sa mipLevels(), maximumMipLevels(), isStorageAllocated()
3028*/
3029void QOpenGLTexture::setMipLevels(int levels)
3030{
3031 Q_D(QOpenGLTexture);
3032 d->create();
3033 if (isStorageAllocated()) {
3034 qWarning("Cannot set mip levels on a texture that already has storage allocated.\n"
3035 "To do so, destroy() the texture and then create() and setMipLevels()");
3036 return;
3037 }
3038
3039 switch (d->target) {
3040 case QOpenGLTexture::Target1D:
3041 case QOpenGLTexture::Target1DArray:
3042 case QOpenGLTexture::Target2D:
3043 case QOpenGLTexture::Target2DArray:
3044 case QOpenGLTexture::TargetCubeMap:
3045 case QOpenGLTexture::TargetCubeMapArray:
3046 case QOpenGLTexture::Target3D:
3047 d->requestedMipLevels = levels;
3048 break;
3049
3050 case QOpenGLTexture::TargetBuffer:
3051 case QOpenGLTexture::TargetRectangle:
3052 case QOpenGLTexture::Target2DMultisample:
3053 case QOpenGLTexture::Target2DMultisampleArray:
3054 qWarning("QAbstractOpenGLTexture::setMipLevels(): This texture target does not support mipmaps");
3055 break;
3056 }
3057}
3058
3059/*!
3060 Returns the number of mipmap levels for this texture. If storage
3061 has not yet been allocated for this texture it returns the
3062 requested number of mipmap levels.
3063
3064 \sa setMipLevels(), maximumMipLevels(), isStorageAllocated()
3065*/
3066int QOpenGLTexture::mipLevels() const
3067{
3068 Q_D(const QOpenGLTexture);
3069 return isStorageAllocated() ? d->mipLevels : d->requestedMipLevels;
3070}
3071
3072/*!
3073 Returns the maximum number of mipmap levels that this texture
3074 can have given the current dimensions.
3075
3076 \sa setMipLevels(), mipLevels(), setSize()
3077*/
3078int QOpenGLTexture::maximumMipLevels() const
3079{
3080 Q_D(const QOpenGLTexture);
3081 return d->maximumMipLevelCount();
3082}
3083
3084/*!
3085 Sets the number of array \a layers to allocate storage for. This
3086 function should be called before storage is allocated for the texture.
3087
3088 For targets that do not support array layers this function has
3089 no effect.
3090
3091 \sa layers(), isStorageAllocated()
3092*/
3093void QOpenGLTexture::setLayers(int layers)
3094{
3095 Q_D(QOpenGLTexture);
3096 d->create();
3097 if (isStorageAllocated()) {
3098 qWarning("Cannot set layers on a texture that already has storage allocated.\n"
3099 "To do so, destroy() the texture and then create() and setLayers()");
3100 return;
3101 }
3102
3103 switch (d->target) {
3104 case QOpenGLTexture::Target1DArray:
3105 case QOpenGLTexture::Target2DArray:
3106 case QOpenGLTexture::TargetCubeMapArray:
3107 case QOpenGLTexture::Target2DMultisampleArray:
3108 d->layers = layers;
3109 break;
3110
3111 case QOpenGLTexture::Target1D:
3112 case QOpenGLTexture::Target2D:
3113 case QOpenGLTexture::Target3D:
3114 case QOpenGLTexture::TargetCubeMap:
3115 case QOpenGLTexture::TargetBuffer:
3116 case QOpenGLTexture::TargetRectangle:
3117 case QOpenGLTexture::Target2DMultisample:
3118 qWarning("Texture target does not support array layers");
3119 break;
3120 }
3121}
3122
3123/*!
3124 Returns the number of array layers for this texture. If
3125 storage has not yet been allocated for this texture then
3126 this function returns the requested number of array layers.
3127
3128 For texture targets that do not support array layers this
3129 will return 1.
3130
3131 \sa setLayers(), isStorageAllocated()
3132*/
3133int QOpenGLTexture::layers() const
3134{
3135 Q_D(const QOpenGLTexture);
3136 return d->layers;
3137}
3138
3139/*!
3140 Returns the number of faces for this texture. For cubemap
3141 and cubemap array type targets this will be 6.
3142
3143 For non-cubemap type targets this will return 1.
3144*/
3145int QOpenGLTexture::faces() const
3146{
3147 Q_D(const QOpenGLTexture);
3148 return d->faces;
3149}
3150
3151/*!
3152 Sets the number of \a samples to allocate storage for when rendering to
3153 a multisample capable texture target. This function should
3154 be called before storage is allocated for the texture.
3155
3156 For targets that do not support multisampling this function has
3157 no effect.
3158
3159 \sa samples(), isStorageAllocated()
3160*/
3161void QOpenGLTexture::setSamples(int samples)
3162{
3163 Q_D(QOpenGLTexture);
3164 d->create();
3165 if (isStorageAllocated()) {
3166 qWarning("Cannot set sample count on a texture that already has storage allocated.\n"
3167 "To do so, destroy() the texture and then create() and setSamples()");
3168 return;
3169 }
3170
3171 switch (d->target) {
3172 case QOpenGLTexture::Target2DMultisample:
3173 case QOpenGLTexture::Target2DMultisampleArray:
3174 d->samples = samples;
3175 break;
3176
3177 case QOpenGLTexture::Target1D:
3178 case QOpenGLTexture::Target2D:
3179 case QOpenGLTexture::Target3D:
3180 case QOpenGLTexture::Target1DArray:
3181 case QOpenGLTexture::Target2DArray:
3182 case QOpenGLTexture::TargetCubeMap:
3183 case QOpenGLTexture::TargetCubeMapArray:
3184 case QOpenGLTexture::TargetBuffer:
3185 case QOpenGLTexture::TargetRectangle:
3186
3187 qWarning("Texture target does not support multisampling");
3188 break;
3189 }
3190}
3191
3192/*!
3193 Returns the number of multisample sample points for this texture.
3194 If storage has not yet been allocated for this texture then
3195 this function returns the requested number of samples.
3196
3197 For texture targets that do not support multisampling this
3198 will return 0.
3199
3200 \sa setSamples(), isStorageAllocated()
3201*/
3202int QOpenGLTexture::samples() const
3203{
3204 Q_D(const QOpenGLTexture);
3205 return d->samples;
3206}
3207
3208/*!
3209 Sets whether the sample positions and number of samples used with
3210 a multisample capable texture target to \a fixed. If set to \c true
3211 the sample positions and number of samples used are the same for
3212 all texels in the image and will not depend upon the image size or
3213 internal format. This function should be called before storage is allocated
3214 for the texture.
3215
3216 For targets that do not support multisampling this function has
3217 no effect.
3218
3219 The default value is \c true.
3220
3221 \sa isFixedSamplePositions(), isStorageAllocated()
3222*/
3223void QOpenGLTexture::setFixedSamplePositions(bool fixed)
3224{
3225 Q_D(QOpenGLTexture);
3226 d->create();
3227 if (isStorageAllocated()) {
3228 qWarning("Cannot set sample positions on a texture that already has storage allocated.\n"
3229 "To do so, destroy() the texture and then create() and setFixedSamplePositions()");
3230 return;
3231 }
3232
3233 switch (d->target) {
3234 case QOpenGLTexture::Target2DMultisample:
3235 case QOpenGLTexture::Target2DMultisampleArray:
3236 d->fixedSamplePositions = fixed;
3237 break;
3238
3239 case QOpenGLTexture::Target1D:
3240 case QOpenGLTexture::Target2D:
3241 case QOpenGLTexture::Target3D:
3242 case QOpenGLTexture::Target1DArray:
3243 case QOpenGLTexture::Target2DArray:
3244 case QOpenGLTexture::TargetCubeMap:
3245 case QOpenGLTexture::TargetCubeMapArray:
3246 case QOpenGLTexture::TargetBuffer:
3247 case QOpenGLTexture::TargetRectangle:
3248
3249 qWarning