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

source code of qtbase/src/gui/opengl/qopengltexture.cpp