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