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