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

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