Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qopenglframebufferobject.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
6
7#include <qdebug.h>
8#include <private/qopengl_p.h>
9#include <private/qopenglcontext_p.h>
10#include <private/qopenglextensions_p.h>
11#include <private/qfont_p.h>
12
13#include <qwindow.h>
14#include <qimage.h>
15#include <QtCore/qbytearray.h>
16
17#include <qtopengl_tracepoints_p.h>
18
20
22 "#include <private/qopengl2pexvertexarray_p.h>" \
23 "#include <private/qopengltextureuploader_p.h>" \
24 "#include <qopenglframebufferobject.h>"
25);
28Q_TRACE_METADATA(qtopengl, "ENUM { } QOpenGLFramebufferObject::Attachment; ");
29
30#ifndef QT_NO_DEBUG
31#define QT_RESET_GLERROR() \
32{ \
33 while (true) {\
34 GLenum error = QOpenGLContext::currentContext()->functions()->glGetError(); \
35 if (error == GL_NO_ERROR || error == GL_CONTEXT_LOST) \
36 break; \
37 } \
38}
39#define QT_CHECK_GLERROR() \
40{ \
41 GLenum err = QOpenGLContext::currentContext()->functions()->glGetError(); \
42 if (err != GL_NO_ERROR && err != GL_CONTEXT_LOST) { \
43 qDebug("[%s line %d] OpenGL Error: %d", \
44 __FILE__, __LINE__, (int)err); \
45 } \
46}
47#else
48#define QT_RESET_GLERROR() {}
49#define QT_CHECK_GLERROR() {}
50#endif
51
52#ifndef GL_MAX_SAMPLES
53#define GL_MAX_SAMPLES 0x8D57
54#endif
55
56#ifndef GL_RENDERBUFFER_SAMPLES
57#define GL_RENDERBUFFER_SAMPLES 0x8CAB
58#endif
59
60#ifndef GL_DEPTH24_STENCIL8
61#define GL_DEPTH24_STENCIL8 0x88F0
62#endif
63
64#ifndef GL_DEPTH_COMPONENT24
65#define GL_DEPTH_COMPONENT24 0x81A6
66#endif
67
68#ifndef GL_DEPTH_COMPONENT24_OES
69#define GL_DEPTH_COMPONENT24_OES 0x81A6
70#endif
71
72#ifndef GL_READ_FRAMEBUFFER
73#define GL_READ_FRAMEBUFFER 0x8CA8
74#endif
75
76#ifndef GL_DRAW_FRAMEBUFFER
77#define GL_DRAW_FRAMEBUFFER 0x8CA9
78#endif
79
80#ifndef GL_RGB8
81#define GL_RGB8 0x8051
82#endif
83
84#ifndef GL_RGB10
85#define GL_RGB10 0x8052
86#endif
87
88#ifndef GL_RGB16
89#define GL_RGB16 0x8054
90#endif
91
92#ifndef GL_RGBA8
93#define GL_RGBA8 0x8058
94#endif
95
96#ifndef GL_RGB10_A2
97#define GL_RGB10_A2 0x8059
98#endif
99
100#ifndef GL_RGBA16
101#define GL_RGBA16 0x805B
102#endif
103
104#ifndef GL_BGRA
105#define GL_BGRA 0x80E1
106#endif
107
108#ifndef GL_UNSIGNED_INT_8_8_8_8_REV
109#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367
110#endif
111
112#ifndef GL_UNSIGNED_INT_2_10_10_10_REV
113#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368
114#endif
115
116#ifndef GL_CONTEXT_LOST
117#define GL_CONTEXT_LOST 0x0507
118#endif
119
120#ifndef GL_DEPTH_STENCIL_ATTACHMENT
121#define GL_DEPTH_STENCIL_ATTACHMENT 0x821A
122#endif
123
124#ifndef GL_DEPTH_STENCIL
125#define GL_DEPTH_STENCIL 0x84F9
126#endif
127
128#ifndef GL_HALF_FLOAT
129#define GL_HALF_FLOAT 0x140B
130#endif
131
132#ifndef GL_RGBA32F
133#define GL_RGBA32F 0x8814
134#endif
135
136#ifndef GL_RGB32F
137#define GL_RGB32F 0x8815
138#endif
139
140#ifndef GL_RGBA16F
141#define GL_RGBA16F 0x881A
142#endif
143
144#ifndef GL_RGB16F
145#define GL_RGB16F 0x881B
146#endif
147
148
178void QOpenGLFramebufferObjectFormat::detach()
179{
180 if (d->ref.loadRelaxed() != 1) {
183 if (!d->ref.deref())
184 delete d;
185 d = newd;
186 }
187}
188
204
214
220{
221 if (d != other.d) {
222 other.d->ref.ref();
223 if (!d->ref.deref())
224 delete d;
225 d = other.d;
226 }
227 return *this;
228}
229
238
253{
254 detach();
255 d->samples = samples;
256}
257
266{
267 return d->samples;
268}
269
283{
284 detach();
285 d->mipmap = enabled;
286}
287
294{
295 return d->mipmap;
296}
297
308
319
331
343
356
369
375{
376 if (d == other.d)
377 return true;
378 else
379 return d->equals(other.d);
380}
381
390
392{
393 if (!ctx)
394 return false; // Context no longer exists.
395 GLenum status = ctx->functions()->glCheckFramebufferStatus(GL_FRAMEBUFFER);
396 switch(status) {
397 case GL_NO_ERROR:
399 return true;
401 qDebug("QOpenGLFramebufferObject: Unsupported framebuffer format.");
402 break;
404 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete attachment.");
405 break;
407 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment.");
408 break;
409#ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT
410 case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT:
411 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, duplicate attachment.");
412 break;
413#endif
414#ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS
415 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:
416 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attached images must have same dimensions.");
417 break;
418#endif
419#ifdef GL_FRAMEBUFFER_INCOMPLETE_FORMATS
420 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS:
421 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attached images must have same format.");
422 break;
423#endif
424#ifdef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
426 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing draw buffer.");
427 break;
428#endif
429#ifdef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER
431 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing read buffer.");
432 break;
433#endif
434#ifdef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
436 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attachments must have same number of samples per pixel.");
437 break;
438#endif
439 default:
440 qDebug() <<"QOpenGLFramebufferObject: An undefined error has occurred: "<< status;
441 break;
442 }
443 return false;
444}
445
446namespace
447{
448 void freeFramebufferFunc(QOpenGLFunctions *funcs, GLuint id)
449 {
450 funcs->glDeleteFramebuffers(1, &id);
451 }
452
453 void freeRenderbufferFunc(QOpenGLFunctions *funcs, GLuint id)
454 {
455 funcs->glDeleteRenderbuffers(1, &id);
456 }
457
458 void freeTextureFunc(QOpenGLFunctions *funcs, GLuint id)
459 {
460 funcs->glDeleteTextures(1, &id);
461 }
462}
463
465 QOpenGLFramebufferObject *qfbo, const QSize &size,
467 GLenum texture_target, GLenum internal_format,
468 GLint samples, bool mipmap)
469{
470 Q_TRACE_SCOPE(QOpenGLFramebufferObjectPrivate_init, qfbo, size, attachment, texture_target, internal_format, samples, mipmap);
471 Q_UNUSED(qfbo);
472
474
476
478 return;
479
480 // Fall back to using a normal non-msaa FBO if we don't have support for MSAA
483 samples = 0;
484 } else if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
485 GLint maxSamples;
486 funcs.glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
487 samples = qBound(0, int(samples), int(maxSamples));
488 }
489
490 colorAttachments.append(ColorAttachment(size, internal_format));
491
492 dsSize = size;
493
494 samples = qMax(0, samples);
496
497 target = texture_target;
498
499 QT_RESET_GLERROR(); // reset error state
500 GLuint fbo = 0;
501
504
505 QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true;
506
508
509 format.setTextureTarget(target);
510 format.setInternalTextureFormat(internal_format);
511 format.setMipmap(mipmap);
512
513 if (samples == 0)
514 initTexture(0);
515 else
517
518 format.setSamples(int(samples));
519
521
522 if (valid)
523 fbo_guard = new QOpenGLSharedResourceGuard(ctx, fbo, freeFramebufferFunc);
524 else
526
528}
529
531{
533 GLuint texture = 0;
534
537
538 funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
539 funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
540 funcs.glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
541 funcs.glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
542
544
545 GLuint pixelType = GL_UNSIGNED_BYTE;
546 if (color.internalFormat == GL_RGB10_A2 || color.internalFormat == GL_RGB10)
548 else if (color.internalFormat == GL_RGB16 || color.internalFormat == GL_RGBA16)
549 pixelType = GL_UNSIGNED_SHORT;
550 else if (color.internalFormat == GL_RGB16F || color.internalFormat == GL_RGBA16F)
551 pixelType = GL_HALF_FLOAT;
552
553 bool isOpaque = false;
554 switch (color.internalFormat) {
555 case GL_RGB8:
556 case GL_RGB16:
557 case GL_RGB16F:
558 case GL_RGB32F:
559 isOpaque = true;
560 break;
561 case GL_RGB10:
562 // opaque but the pixel type (INT_2_10_10_10) has alpha and so requires RGBA texture format
563 break;
564 }
565 const GLuint textureFormat = isOpaque ? GL_RGB : GL_RGBA;
566
567 funcs.glTexImage2D(target, 0, color.internalFormat, color.size.width(), color.size.height(), 0,
568 textureFormat, pixelType, nullptr);
569 if (format.mipmap()) {
570 int width = color.size.width();
571 int height = color.size.height();
572 int level = 0;
573 while (width > 1 || height > 1) {
574 width = qMax(1, width >> 1);
575 height = qMax(1, height >> 1);
576 ++level;
577 funcs.glTexImage2D(target, level, color.internalFormat, width, height, 0, textureFormat,
578 pixelType, nullptr);
579 }
580 }
582 target, texture, 0);
583
587 if (valid) {
588 color.guard = new QOpenGLSharedResourceGuard(ctx, texture, freeTextureFunc);
589 } else {
591 }
592}
593
595{
597 GLuint color_buffer = 0;
598
600
601 GLenum storageFormat = color.internalFormat;
602 // ES requires a sized format. The older desktop extension does not. Correct the format on ES.
603 if (ctx->isOpenGLES()) {
604 if (color.internalFormat == GL_RGBA) {
606 storageFormat = GL_RGBA8;
607 else
608 storageFormat = GL_RGBA4;
609 } else if (color.internalFormat == GL_RGB10) {
610 // GL_RGB10 is not allowed in ES for glRenderbufferStorage.
611 storageFormat = GL_RGB10_A2;
612 }
613 }
614
615 funcs.glGenRenderbuffers(1, &color_buffer);
617 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, *samples, storageFormat, color.size.width(), color.size.height());
619 GL_RENDERBUFFER, color_buffer);
620
623 if (valid) {
624 // Query the actual number of samples. This can be greater than the requested
625 // value since the typically supported values are 0, 4, 8, ..., and the
626 // requests are mapped to the next supported value.
628 color.guard = new QOpenGLSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc);
629 } else {
630 funcs.glDeleteRenderbuffers(1, &color_buffer);
631 }
632}
633
636{
637 // Use the same sample count for all attachments. format.samples() already contains
638 // the actual number of samples for the color attachment and is not suitable. Use
639 // requestedSamples instead.
640 const int samples = requestedSamples;
641
642 // free existing attachments
643 if (depth_buffer_guard) {
644#ifdef Q_OS_WASM
646#else
648#endif
650 }
655 }
656
657 depth_buffer_guard = nullptr;
658 stencil_buffer_guard = nullptr;
659
660 GLuint depth_buffer = 0;
661 GLuint stencil_buffer = 0;
662
663 // In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a
664 // separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer
665 // might not be supported while separate buffers are, according to QTBUG-12861.
666#ifdef Q_OS_WASM
667 // WebGL doesn't allow separately attach buffers to
668 // STENCIL_ATTACHMENT and DEPTH_ATTACHMENT
669 // QTBUG-69913
671 funcs.glGenRenderbuffers(1, &depth_buffer);
673 Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
674
675 if (samples != 0 ) {
678 } else {
681 }
682
684 GL_RENDERBUFFER, depth_buffer);
685
687 if (!valid) {
688 funcs.glDeleteRenderbuffers(1, &depth_buffer);
689 depth_buffer = 0;
690 }
691 }
692#else
695 {
696 // depth and stencil buffer needs another extension
697 funcs.glGenRenderbuffers(1, &depth_buffer);
699 Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
703 else
706
707 stencil_buffer = depth_buffer;
709 GL_RENDERBUFFER, depth_buffer);
711 GL_RENDERBUFFER, stencil_buffer);
712
714 if (!valid) {
715 funcs.glDeleteRenderbuffers(1, &depth_buffer);
716 stencil_buffer = depth_buffer = 0;
717 }
718 }
719
722 {
723 funcs.glGenRenderbuffers(1, &depth_buffer);
725 Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
727 if (ctx->isOpenGLES()) {
731 else
734 } else {
736 GL_DEPTH_COMPONENT, dsSize.width(), dsSize.height());
737 }
738 } else {
739 if (ctx->isOpenGLES()) {
743 } else {
746 }
747 } else {
749 }
750 }
752 GL_RENDERBUFFER, depth_buffer);
754 if (!valid) {
755 funcs.glDeleteRenderbuffers(1, &depth_buffer);
756 depth_buffer = 0;
757 }
758 }
759
760 if (stencil_buffer == 0 && (attachment == QOpenGLFramebufferObject::CombinedDepthStencil)) {
761 funcs.glGenRenderbuffers(1, &stencil_buffer);
763 Q_ASSERT(funcs.glIsRenderbuffer(stencil_buffer));
764
765#if QT_CONFIG(opengles2)
767#else
769#endif
770
773 else
775
777 GL_RENDERBUFFER, stencil_buffer);
779 if (!valid) {
780 funcs.glDeleteRenderbuffers(1, &stencil_buffer);
781 stencil_buffer = 0;
782 }
783 }
784#endif //Q_OS_WASM
785
786 // The FBO might have become valid after removing the depth or stencil buffer.
788
789#ifdef Q_OS_WASM
790 if (depth_buffer) {
791#else
792 if (depth_buffer && stencil_buffer) {
793#endif
795 } else if (depth_buffer) {
797 } else {
799 }
800
801 if (valid) {
802 if (depth_buffer)
803 depth_buffer_guard = new QOpenGLSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc);
804 if (stencil_buffer) {
805 if (stencil_buffer == depth_buffer)
807 else
808 stencil_buffer_guard = new QOpenGLSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc);
809 }
810 } else {
811 if (depth_buffer)
812 funcs.glDeleteRenderbuffers(1, &depth_buffer);
813 if (stencil_buffer && depth_buffer != stencil_buffer)
814 funcs.glDeleteRenderbuffers(1, &stencil_buffer);
815 }
817
818 format.setAttachment(fbo_attachment);
819}
820
890{
891 if (!internalFormat)
892#if QT_CONFIG(opengles2)
894#else
896#endif
897 return internalFormat;
898}
899
930
942
951{
953 d->init(this, size, format.attachment(), format.textureTarget(), format.internalTextureFormat(),
954 format.samples(), format.mipmap());
955}
956
967
988
1009
1015{
1017 if (isBound())
1018 release();
1019
1020 for (const auto &color : std::as_const(d->colorAttachments)) {
1021 if (color.guard)
1022 color.guard->free();
1023 }
1024 d->colorAttachments.clear();
1025
1026 if (d->depth_buffer_guard)
1027 d->depth_buffer_guard->free();
1028 if (d->stencil_buffer_guard && d->stencil_buffer_guard != d->depth_buffer_guard)
1029 d->stencil_buffer_guard->free();
1030 if (d->fbo_guard)
1031 d->fbo_guard->free();
1032
1034 if (contextPrv && contextPrv->qgl_current_fbo == this) {
1035 contextPrv->qgl_current_fbo_invalid = true;
1036 contextPrv->qgl_current_fbo = nullptr;
1037 }
1038}
1039
1070{
1072
1073 if (!QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(QOpenGLFunctions::MultipleRenderTargets)) {
1074 qWarning("Multiple render targets not supported, ignoring extra color attachment request");
1075 return;
1076 }
1077
1079 d->colorAttachments.append(color);
1080 const int idx = d->colorAttachments.size() - 1;
1081
1082 if (d->requestedSamples == 0) {
1083 d->initTexture(idx);
1084 } else {
1085 GLint samples = d->requestedSamples;
1086 d->initColorBuffer(idx, &samples);
1087 }
1088}
1089
1103
1123{
1124 Q_D(const QOpenGLFramebufferObject);
1125 return d->valid && d->fbo_guard && d->fbo_guard->id();
1126}
1127
1142{
1143 if (!isValid())
1144 return false;
1147 if (!current)
1148 return false;
1149#ifdef QT_DEBUG
1150 if (current->shareGroup() != d->fbo_guard->group())
1151 qWarning("QOpenGLFramebufferObject::bind() called from incompatible context");
1152#endif
1153
1154 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
1155
1156 QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;
1157 QOpenGLContextPrivate::get(current)->qgl_current_fbo = this;
1158
1159 if (d->format.samples() == 0) {
1160 // Create new textures to replace the ones stolen via takeTexture().
1161 for (int i = 0; i < d->colorAttachments.size(); ++i) {
1162 if (!d->colorAttachments.at(i).guard)
1163 d->initTexture(i);
1164 }
1165 }
1166
1167 return d->valid;
1168}
1169
1180{
1181 if (!isValid())
1182 return false;
1183
1185 if (!current)
1186 return false;
1187
1189#ifdef QT_DEBUG
1190 if (current->shareGroup() != d->fbo_guard->group())
1191 qWarning("QOpenGLFramebufferObject::release() called from incompatible context");
1192#endif
1193
1194 if (current) {
1195 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->defaultFramebufferObject());
1196
1198 contextPrv->qgl_current_fbo_invalid = true;
1199 contextPrv->qgl_current_fbo = nullptr;
1200 }
1201
1202 return true;
1203}
1204
1221{
1222 Q_D(const QOpenGLFramebufferObject);
1223 return d->colorAttachments[0].guard ? d->colorAttachments[0].guard->id() : 0;
1224}
1225
1236{
1237 Q_D(const QOpenGLFramebufferObject);
1238 QList<GLuint> ids;
1239 if (d->format.samples() != 0)
1240 return ids;
1241 ids.reserve(d->colorAttachments.size());
1242 for (const auto &color : d->colorAttachments)
1243 ids.append(color.guard ? color.guard->id() : 0);
1244 return ids;
1245}
1246
1269
1290{
1292 GLuint id = 0;
1293 if (isValid() && d->format.samples() == 0 && d->colorAttachments.size() > colorAttachmentIndex) {
1295 if (current && current->shareGroup() == d->fbo_guard->group() && isBound())
1296 release();
1297 auto &guard = d->colorAttachments[colorAttachmentIndex].guard;
1298 id = guard ? guard->id() : 0;
1299 // Do not call free() on texture_guard, just null it out.
1300 // This way the texture will not be deleted when the guard is destroyed.
1301 guard = nullptr;
1302 }
1303 return id;
1304}
1305
1311{
1312 Q_D(const QOpenGLFramebufferObject);
1313 return d->dsSize;
1314}
1315
1323{
1324 Q_D(const QOpenGLFramebufferObject);
1325 QList<QSize> sz;
1326 sz.reserve(d->colorAttachments.size());
1327 for (const auto &color : d->colorAttachments)
1328 sz.append(color.size);
1329 return sz;
1330}
1331
1348{
1349 Q_D(const QOpenGLFramebufferObject);
1350 return d->format;
1351}
1352
1353static inline QImage qt_gl_read_framebuffer_rgba8(const QSize &size, bool include_alpha, QOpenGLContext *context)
1354{
1355 QOpenGLFunctions *funcs = context->functions();
1356 const int w = size.width();
1357 const int h = size.height();
1358 bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2);
1359 if (isOpenGL12orBetter) {
1361 if (!img.isNull())
1362 funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, img.bits());
1363 return img;
1364 }
1365
1366 // For OpenGL ES stick with the byte ordered format / RGBA readback format
1367 // since that is the only spec mandated way. (also, skip the
1368 // GL_IMPLEMENTATION_COLOR_READ_FORMAT mess since there is nothing saying a
1369 // BGRA capable impl would return BGRA from there)
1370
1372 if (!rgbaImage.isNull())
1373 funcs->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rgbaImage.bits());
1374 return rgbaImage;
1375}
1376
1377static inline QImage qt_gl_read_framebuffer_rgb10a2(const QSize &size, bool include_alpha, QOpenGLContext *context)
1378{
1379 // We assume OpenGL 1.2+ or ES 3.0+ here.
1381 if (!img.isNull())
1382 context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, img.bits());
1383 return img;
1384}
1385
1386static inline QImage qt_gl_read_framebuffer_rgba16(const QSize &size, bool include_alpha, QOpenGLContext *context)
1387{
1388 // We assume OpenGL 1.2+ or ES 3.0+ here.
1390 if (!img.isNull())
1391 context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_SHORT, img.bits());
1392 return img;
1393}
1394
1395static inline QImage qt_gl_read_framebuffer_rgba16f(const QSize &size, bool include_alpha, QOpenGLContext *context)
1396{
1397 // We assume OpenGL (ES) 3.0+ here.
1399 if (!img.isNull())
1400 context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_HALF_FLOAT, img.bits());
1401 return img;
1402}
1403
1404static inline QImage qt_gl_read_framebuffer_rgba32f(const QSize &size, bool include_alpha, QOpenGLContext *context)
1405{
1407 if (!img.isNull())
1408 context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_FLOAT, img.bits());
1409 return img;
1410}
1411
1412static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format, bool include_alpha, bool flip)
1413{
1415 QOpenGLFunctions *funcs = ctx->functions();
1416 while (true) {
1417 GLenum error = funcs->glGetError();
1418 if (error == GL_NO_ERROR || error == GL_CONTEXT_LOST)
1419 break;
1420 }
1421 switch (internal_format) {
1422 case GL_RGB:
1423 case GL_RGB8:
1424 return qt_gl_read_framebuffer_rgba8(size, false, ctx).mirrored(false, flip);
1425 case GL_RGB10:
1426 return qt_gl_read_framebuffer_rgb10a2(size, false, ctx).mirrored(false, flip);
1427 case GL_RGB10_A2:
1428 return qt_gl_read_framebuffer_rgb10a2(size, include_alpha, ctx).mirrored(false, flip);
1429 case GL_RGB16:
1430 return qt_gl_read_framebuffer_rgba16(size, false, ctx).mirrored(false, flip);
1431 case GL_RGBA16:
1432 return qt_gl_read_framebuffer_rgba16(size, include_alpha, ctx).mirrored(false, flip);
1433 case GL_RGB16F:
1434 return qt_gl_read_framebuffer_rgba16f(size, false, ctx).mirrored(false, flip);
1435 case GL_RGBA16F:
1436 return qt_gl_read_framebuffer_rgba16f(size, include_alpha, ctx).mirrored(false, flip);
1437 case GL_RGB32F:
1438 return qt_gl_read_framebuffer_rgba32f(size, false, ctx).mirrored(false, flip);
1439 case GL_RGBA32F:
1440 return qt_gl_read_framebuffer_rgba32f(size, include_alpha, ctx).mirrored(false, flip);
1441 case GL_RGBA:
1442 case GL_RGBA8:
1443 default:
1444 return qt_gl_read_framebuffer_rgba8(size, include_alpha, ctx).mirrored(false, flip);
1445 }
1446
1447 Q_UNREACHABLE_RETURN(QImage());
1448}
1449
1450Q_OPENGL_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)
1451{
1452 return qt_gl_read_framebuffer(size, alpha_format ? GL_RGBA : GL_RGB, include_alpha, true);
1453}
1454
1494{
1495 return toImage(flipped, 0);
1496}
1497
1511QImage QOpenGLFramebufferObject::toImage(bool flipped, int colorAttachmentIndex) const
1512{
1513 Q_D(const QOpenGLFramebufferObject);
1514 if (!d->valid)
1515 return QImage();
1516
1518 if (!ctx) {
1519 qWarning("QOpenGLFramebufferObject::toImage() called without a current context");
1520 return QImage();
1521 }
1522
1523 if (d->colorAttachments.size() <= colorAttachmentIndex) {
1524 qWarning("QOpenGLFramebufferObject::toImage() called for missing color attachment");
1525 return QImage();
1526 }
1527
1528 GLuint prevFbo = 0;
1529 ctx->functions()->glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &prevFbo);
1530
1531 if (prevFbo != d->fbo())
1532 const_cast<QOpenGLFramebufferObject *>(this)->bind();
1533
1534 QImage image;
1535 QOpenGLExtraFunctions *extraFuncs = ctx->extraFunctions();
1536 // qt_gl_read_framebuffer doesn't work on a multisample FBO
1537 if (format().samples() != 0) {
1538 QRect rect(QPoint(0, 0), size());
1540 if (extraFuncs->hasOpenGLFeature(QOpenGLFunctions::MultipleRenderTargets)) {
1541 fmt.setInternalTextureFormat(d->colorAttachments[colorAttachmentIndex].internalFormat);
1542 QOpenGLFramebufferObject temp(d->colorAttachments[colorAttachmentIndex].size, fmt);
1543 blitFramebuffer(&temp, rect, const_cast<QOpenGLFramebufferObject *>(this), rect,
1544 GL_COLOR_BUFFER_BIT, GL_NEAREST,
1545 colorAttachmentIndex, 0);
1546 image = temp.toImage(flipped);
1547 } else {
1548 fmt.setInternalTextureFormat(d->colorAttachments[0].internalFormat);
1550 blitFramebuffer(&temp, rect, const_cast<QOpenGLFramebufferObject *>(this), rect);
1551 image = temp.toImage(flipped);
1552 }
1553 } else {
1554 if (extraFuncs->hasOpenGLFeature(QOpenGLFunctions::MultipleRenderTargets)) {
1555 extraFuncs->glReadBuffer(GL_COLOR_ATTACHMENT0 + colorAttachmentIndex);
1556 image = qt_gl_read_framebuffer(d->colorAttachments[colorAttachmentIndex].size,
1557 d->colorAttachments[colorAttachmentIndex].internalFormat,
1558 true, flipped);
1559 extraFuncs->glReadBuffer(GL_COLOR_ATTACHMENT0);
1560 } else {
1561 image = qt_gl_read_framebuffer(d->colorAttachments[0].size,
1562 d->colorAttachments[0].internalFormat,
1563 true, flipped);
1564 }
1565 }
1566
1567 if (prevFbo != d->fbo())
1568 ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, prevFbo);
1569
1570 return image;
1571}
1572
1583{
1585
1586 if (ctx) {
1587 ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());
1588 QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true;
1589 QOpenGLContextPrivate::get(ctx)->qgl_current_fbo = nullptr;
1590 }
1591#ifdef QT_DEBUG
1592 else
1593 qWarning("QOpenGLFramebufferObject::bindDefault() called without current context.");
1594#endif
1595
1596 return ctx != nullptr;
1597}
1598
1609
1620{
1621 Q_D(const QOpenGLFramebufferObject);
1622 return d->fbo();
1623}
1624
1631{
1632 Q_D(const QOpenGLFramebufferObject);
1633 if (d->valid)
1634 return d->fbo_attachment;
1635 return NoAttachment;
1636}
1637
1647{
1649 if (attachment == d->fbo_attachment || !isValid())
1650 return;
1652 if (!current)
1653 return;
1654#ifdef QT_DEBUG
1655 if (current->shareGroup() != d->fbo_guard->group())
1656 qWarning("QOpenGLFramebufferObject::setAttachment() called from incompatible context");
1657#endif
1658 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
1659 QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;
1660 d->initDepthStencilAttachments(current, attachment);
1661}
1662
1668{
1669 Q_D(const QOpenGLFramebufferObject);
1671 if (!ctx)
1672 return false;
1673 GLint fbo = 0;
1674 ctx->functions()->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);
1675 return GLuint(fbo) == d->fbo();
1676}
1677
1690
1691
1700{
1701 if (!target && !source)
1702 return;
1703
1704 QSize targetSize;
1705 QSize sourceSize;
1706
1707 if (target)
1708 targetSize = target->size();
1709 if (source)
1710 sourceSize = source->size();
1711
1712 if (targetSize.isEmpty())
1713 targetSize = sourceSize;
1714 else if (sourceSize.isEmpty())
1715 sourceSize = targetSize;
1716
1717 blitFramebuffer(target, QRect(QPoint(0, 0), targetSize),
1718 source, QRect(QPoint(0, 0), sourceSize),
1719 buffers, filter);
1720}
1721
1727 QOpenGLFramebufferObject *source, const QRect &sourceRect,
1729 GLenum filter)
1730{
1731 blitFramebuffer(target, targetRect, source, sourceRect, buffers, filter, 0, 0);
1732}
1733
1799 QOpenGLFramebufferObject *source, const QRect &sourceRect,
1801 GLenum filter,
1802 int readColorAttachmentIndex,
1803 int drawColorAttachmentIndex,
1805{
1807 if (!ctx)
1808 return;
1809
1810 QOpenGLExtensions extensions(ctx);
1812 return;
1813
1814 GLuint prevFbo = 0;
1815 if (restorePolicy == RestoreFrameBufferBinding)
1816 ctx->functions()->glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &prevFbo);
1817
1818 const int sx0 = sourceRect.left();
1819 const int sx1 = sourceRect.left() + sourceRect.width();
1820 const int sy0 = sourceRect.top();
1821 const int sy1 = sourceRect.top() + sourceRect.height();
1822
1823 const int tx0 = targetRect.left();
1824 const int tx1 = targetRect.left() + targetRect.width();
1825 const int ty0 = targetRect.top();
1826 const int ty1 = targetRect.top() + targetRect.height();
1827
1828 const GLuint defaultFboId = ctx->defaultFramebufferObject();
1829
1830 extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : defaultFboId);
1831 extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : defaultFboId);
1832
1833 const bool supportsMRT = extensions.hasOpenGLFeature(QOpenGLFunctions::MultipleRenderTargets);
1834 if (supportsMRT) {
1835 extensions.glReadBuffer(GL_COLOR_ATTACHMENT0 + readColorAttachmentIndex);
1836 if (target) {
1837 GLenum drawBuf = GL_COLOR_ATTACHMENT0 + drawColorAttachmentIndex;
1838 extensions.glDrawBuffers(1, &drawBuf);
1839 }
1840 }
1841
1842 extensions.glBlitFramebuffer(sx0, sy0, sx1, sy1,
1843 tx0, ty0, tx1, ty1,
1844 buffers, filter);
1845
1846 if (supportsMRT)
1848
1849 switch (restorePolicy) {
1851 ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, prevFbo); // sets both READ and DRAW
1852 break;
1853
1855 ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject()); // sets both READ and DRAW
1856 break;
1857
1859 break;
1860 }
1861}
1862
1873 QOpenGLFramebufferObject *source, const QRect &sourceRect,
1875 GLenum filter,
1876 int readColorAttachmentIndex,
1877 int drawColorAttachmentIndex)
1878{
1879 blitFramebuffer(target, targetRect, source, sourceRect,
1880 buffers, filter,
1881 readColorAttachmentIndex,
1882 drawColorAttachmentIndex,
1884}
1885
bool ref() noexcept
bool deref() noexcept
T loadRelaxed() const noexcept
\inmodule QtGui
Definition qimage.h:37
@ Format_RGBA32FPx4_Premultiplied
Definition qimage.h:77
@ Format_RGB32
Definition qimage.h:46
@ Format_RGBX32FPx4
Definition qimage.h:75
@ Format_RGBA64_Premultiplied
Definition qimage.h:69
@ Format_RGBA8888_Premultiplied
Definition qimage.h:60
@ Format_RGBA16FPx4_Premultiplied
Definition qimage.h:74
@ Format_RGBX64
Definition qimage.h:67
@ Format_A2BGR30_Premultiplied
Definition qimage.h:62
@ Format_RGBX16FPx4
Definition qimage.h:72
@ Format_BGR30
Definition qimage.h:61
@ Format_ARGB32_Premultiplied
Definition qimage.h:48
@ Format_RGBX8888
Definition qimage.h:58
static QOpenGLContextPrivate * get(QOpenGLContext *context)
\inmodule QtGui
QOpenGLContextGroup * shareGroup() const
Returns the share group this context belongs to.
GLuint defaultFramebufferObject() const
Call this to get the default framebuffer object for the current surface.
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
QOpenGLFunctions * functions() const
Get the QOpenGLFunctions instance for this context.
bool hasOpenGLExtension(QOpenGLExtensions::OpenGLExtension extension) const
Returns true if extension is present on this system's OpenGL implementation; false otherwise.
The QOpenGLExtraFunctions class provides cross-platform access to the OpenGL ES 3....
void glBlitFramebuffer(GLint srcX0, GLint srcY0, GLint srcX1, GLint srcY1, GLint dstX0, GLint dstY0, GLint dstX1, GLint dstY1, GLbitfield mask, GLenum filter)
Convenience function that calls glBlitFramebuffer(srcX0, srcY0, srcX1, srcY1, dstX0,...
void glRenderbufferStorageMultisample(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height)
Convenience function that calls glRenderbufferStorageMultisample(target, samples, internalformat,...
void glDrawBuffers(GLsizei n, const GLenum *bufs)
Convenience function that calls glDrawBuffers(n, bufs).
void glReadBuffer(GLenum mode)
Convenience function that calls glReadBuffer(src).
QOpenGLFramebufferObject::Attachment attachment
bool equals(const QOpenGLFramebufferObjectFormatPrivate *other)
The QOpenGLFramebufferObjectFormat class specifies the format of an OpenGL framebuffer object.
void setInternalTextureFormat(GLenum internalTextureFormat)
Sets the internal format of a framebuffer object's texture or multisample framebuffer object's color ...
QOpenGLFramebufferObjectFormat & operator=(const QOpenGLFramebufferObjectFormat &other)
Assigns other to this object.
bool operator!=(const QOpenGLFramebufferObjectFormat &other) const
Returns false if all the options of this framebuffer object format are the same as other; otherwise r...
QOpenGLFramebufferObjectFormat()
Creates a QOpenGLFramebufferObjectFormat object for specifying the format of an OpenGL framebuffer ob...
bool mipmap() const
Returns true if mipmapping is enabled.
GLenum textureTarget() const
Returns the texture target of the texture attached to a framebuffer object.
void setSamples(int samples)
Sets the number of samples per pixel for a multisample framebuffer object to samples.
QOpenGLFramebufferObject::Attachment attachment() const
Returns the configuration of the depth and stencil buffers attached to a framebuffer object.
int samples() const
Returns the number of samples per pixel if a framebuffer object is a multisample framebuffer object.
void setAttachment(QOpenGLFramebufferObject::Attachment attachment)
Sets the attachment configuration of a framebuffer object to attachment.
bool operator==(const QOpenGLFramebufferObjectFormat &other) const
Returns true if all the options of this framebuffer object format are the same as other; otherwise re...
void setMipmap(bool enabled)
Enables mipmapping if enabled is true; otherwise disables it.
~QOpenGLFramebufferObjectFormat()
Destroys the QOpenGLFramebufferObjectFormat.
GLenum internalTextureFormat() const
Returns the internal format of a framebuffer object's texture or multisample framebuffer object's col...
void setTextureTarget(GLenum target)
Sets the texture target of the texture attached to a framebuffer object to target.
bool checkFramebufferStatus(QOpenGLContext *ctx) const
void initDepthStencilAttachments(QOpenGLContext *ctx, QOpenGLFramebufferObject::Attachment attachment)
QOpenGLSharedResourceGuard * fbo_guard
QOpenGLFramebufferObject::Attachment fbo_attachment
void init(QOpenGLFramebufferObject *q, const QSize &size, QOpenGLFramebufferObject::Attachment attachment, GLenum texture_target, GLenum internal_format, GLint samples=0, bool mipmap=false)
void initColorBuffer(int idx, GLint *samples)
QOpenGLSharedResourceGuard * depth_buffer_guard
QVarLengthArray< ColorAttachment, 8 > colorAttachments
QOpenGLSharedResourceGuard * stencil_buffer_guard
The QOpenGLFramebufferObject class encapsulates an OpenGL framebuffer object.
Attachment attachment() const
Returns the status of the depth and stencil buffers attached to this framebuffer object.
static void blitFramebuffer(QOpenGLFramebufferObject *target, const QRect &targetRect, QOpenGLFramebufferObject *source, const QRect &sourceRect, GLbitfield buffers, GLenum filter, int readColorAttachmentIndex, int drawColorAttachmentIndex, FramebufferRestorePolicy restorePolicy)
virtual ~QOpenGLFramebufferObject()
Destroys the framebuffer object and frees any allocated resources.
Attachment
This enum type is used to configure the depth and stencil buffers attached to the framebuffer object ...
static bool bindDefault()
Switches rendering back to the default, windowing system provided framebuffer.
void setAttachment(Attachment attachment)
Sets the attachments of the framebuffer object to attachment.
GLuint takeTexture()
Returns the texture id for the texture attached to this framebuffer object.
static bool hasOpenGLFramebufferBlit()
Returns true if the OpenGL {GL_EXT_framebuffer_blit} extension is present on this system; otherwise r...
void addColorAttachment(const QSize &size, GLenum internalFormat=0)
Creates and attaches an additional texture or renderbuffer of size width and height.
QOpenGLFramebufferObjectFormat format() const
Returns the format of this framebuffer object.
bool release()
Switches rendering back to the default, windowing system provided framebuffer.
QOpenGLFramebufferObject(const QSize &size, GLenum target=GL_TEXTURE_2D)
Constructs an OpenGL framebuffer object and binds a 2D OpenGL texture to the buffer of the size size.
bool isBound() const
Returns true if the framebuffer object is currently bound to the current context, otherwise false is ...
GLuint handle() const
Returns the OpenGL framebuffer object handle for this framebuffer object (returned by the {glGenFrame...
QImage toImage(bool flipped=true) const
Returns the contents of this framebuffer object as a QImage.
static bool hasOpenGLFramebufferObjects()
Returns true if the OpenGL {GL_EXT_framebuffer_object} extension is present on this system; otherwise...
GLuint texture() const
Returns the texture id for the texture attached as the default rendering target in this framebuffer o...
QList< GLuint > textures() const
Returns the texture id for all attached textures.
bool bind()
Switches rendering from the default, windowing system provided framebuffer to this framebuffer object...
bool isValid() const
Returns true if the framebuffer object is valid.
The QOpenGLFunctions class provides cross-platform access to the OpenGL ES 2.0 API.
GLboolean glIsRenderbuffer(GLuint renderbuffer)
Convenience function that calls glIsRenderbuffer(renderbuffer).
void glDeleteFramebuffers(GLsizei n, const GLuint *framebuffers)
Convenience function that calls glDeleteFramebuffers(n, framebuffers).
void glGenTextures(GLsizei n, GLuint *textures)
Convenience function that calls glGenTextures(n, textures).
void glDeleteRenderbuffers(GLsizei n, const GLuint *renderbuffers)
Convenience function that calls glDeleteRenderbuffers(n, renderbuffers).
void glTexImage2D(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels)
Convenience function that calls glTexImage2D(target, level, internalformat, width,...
void glGetRenderbufferParameteriv(GLenum target, GLenum pname, GLint *params)
Convenience function that calls glGetRenderbufferParameteriv(target, pname, params).
void glGenRenderbuffers(GLsizei n, GLuint *renderbuffers)
Convenience function that calls glGenRenderbuffers(n, renderbuffers).
void glBindRenderbuffer(GLenum target, GLuint renderbuffer)
Convenience function that calls glBindRenderbuffer(target, renderbuffer).
void glTexParameteri(GLenum target, GLenum pname, GLint param)
Convenience function that calls glTexParameteri(target, pname, param).
void glBindTexture(GLenum target, GLuint texture)
Convenience function that calls glBindTexture(target, texture).
void glFramebufferTexture2D(GLenum target, GLenum attachment, GLenum textarget, GLuint texture, GLint level)
Convenience function that calls glFramebufferTexture2D(target, attachment, textarget,...
void glDeleteTextures(GLsizei n, const GLuint *textures)
Convenience function that calls glDeleteTextures(n, textures).
void glBindFramebuffer(GLenum target, GLuint framebuffer)
Convenience function that calls glBindFramebuffer(target, framebuffer).
void initializeOpenGLFunctions()
Initializes OpenGL function resolution for the current context.
void glFramebufferRenderbuffer(GLenum target, GLenum attachment, GLenum renderbuffertarget, GLuint renderbuffer)
Convenience function that calls glFramebufferRenderbuffer(target, attachment, renderbuffertarget,...
void glGenFramebuffers(GLsizei n, GLuint *framebuffers)
Convenience function that calls glGenFramebuffers(n, framebuffers).
bool hasOpenGLFeature(QOpenGLFunctions::OpenGLFeature feature) const
Returns true if feature is present on this system's OpenGL implementation; false otherwise.
void glGetIntegerv(GLenum pname, GLint *params)
Convenience function that calls glGetIntegerv(pname, params).
void glRenderbufferStorage(GLenum target, GLenum internalformat, GLsizei width, GLsizei height)
Convenience function that calls glRenderbufferStorage(target, internalformat, width,...
The QOpenGLSharedResourceGuard class is a convenience sub-class of QOpenGLSharedResource to be used t...
\inmodule QtCore\reentrant
Definition qpoint.h:25
\inmodule QtCore\reentrant
Definition qrect.h:30
constexpr int height() const noexcept
Returns the height of the rectangle.
Definition qrect.h:239
constexpr int top() const noexcept
Returns the y-coordinate of the rectangle's top edge.
Definition qrect.h:176
constexpr int left() const noexcept
Returns the x-coordinate of the rectangle's left edge.
Definition qrect.h:173
constexpr int width() const noexcept
Returns the width of the rectangle.
Definition qrect.h:236
\inmodule QtCore
Definition qsize.h:25
constexpr int height() const noexcept
Returns the height.
Definition qsize.h:133
constexpr int width() const noexcept
Returns the width.
Definition qsize.h:130
constexpr bool isEmpty() const noexcept
Returns true if either of the width and height is less than or equal to 0; otherwise returns false.
Definition qsize.h:124
EGLContext ctx
static VulkanServerBufferGlFunctions * funcs
rect
[4]
Combined button and popup list for selecting options.
Definition image.cpp:4
static void * context
DBusConnection const char DBusError * error
#define qDebug
[1]
Definition qlogging.h:164
#define qWarning
Definition qlogging.h:166
constexpr const T & qBound(const T &min, const T &val, const T &max)
Definition qminmax.h:44
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
typedef GLint(GL_APIENTRYP PFNGLGETPROGRAMRESOURCELOCATIONINDEXEXTPROC)(GLuint program
GLuint const GLuint * buffers
GLsizei samples
GLenum GLuint GLint level
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLenum GLenum GLsizei const GLuint * ids
GLenum GLuint id
[7]
GLenum GLenum GLsizei const GLuint GLboolean enabled
GLint GLsizei width
GLuint color
[2]
typedef GLenum(GL_APIENTRYP PFNGLGETGRAPHICSRESETSTATUSKHRPROC)(void)
GLenum target
GLenum GLuint texture
GLint GLint GLint GLint GLint GLint GLint GLbitfield GLenum filter
GLenum attachment
GLint GLsizei GLsizei GLenum format
GLsizei GLenum internalFormat
GLfloat GLfloat GLfloat GLfloat h
GLsizei GLsizei GLchar * source
#define GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE
#define GL_RENDERBUFFER_SAMPLES
#define GL_DEPTH24_STENCIL8
#define GL_DEPTH_COMPONENT16
Definition qopenglext.h:328
GLint void * img
Definition qopenglext.h:233
#define GL_RGBA16F
Definition qopenglext.h:913
#define GL_RGB16F
Definition qopenglext.h:914
#define GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT
#define GL_COLOR_ATTACHMENT0
#define GL_DEPTH_STENCIL_ATTACHMENT
#define GL_STENCIL_INDEX8
#define GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT
typedef GLbitfield(APIENTRYP PFNGLQUERYMATRIXXOESPROC)(GLfixed *mantissa
#define GL_FRAMEBUFFER_COMPLETE
#define GL_DRAW_FRAMEBUFFER
#define GL_MAX_SAMPLES
#define GL_RENDERBUFFER
#define GL_FRAMEBUFFER_UNSUPPORTED
#define GL_FRAMEBUFFER
#define GL_HALF_FLOAT
#define GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER
#define GL_DEPTH_STENCIL
#define GL_FRAMEBUFFER_BINDING
#define GL_READ_FRAMEBUFFER
#define GL_DEPTH_ATTACHMENT
#define GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER
#define GL_DEPTH_COMPONENT24
Definition qopenglext.h:329
#define GL_RGB32F
Definition qopenglext.h:912
#define GL_CLAMP_TO_EDGE
Definition qopenglext.h:100
#define GL_STENCIL_ATTACHMENT
static QImage qt_gl_read_framebuffer_rgba8(const QSize &size, bool include_alpha, QOpenGLContext *context)
static QImage qt_gl_read_framebuffer_rgb10a2(const QSize &size, bool include_alpha, QOpenGLContext *context)
#define GL_RGB10
static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format, bool include_alpha, bool flip)
#define GL_RGBA8
#define GL_RGBA16F
static QImage qt_gl_read_framebuffer_rgba16f(const QSize &size, bool include_alpha, QOpenGLContext *context)
#define GL_RGB16
#define GL_RGB16F
#define QT_RESET_GLERROR()
static GLenum effectiveInternalFormat(GLenum internalFormat)
#define GL_BGRA
#define GL_RGB8
#define QT_CHECK_GLERROR()
#define GL_RGB10_A2
#define GL_HALF_FLOAT
static QImage qt_gl_read_framebuffer_rgba16(const QSize &size, bool include_alpha, QOpenGLContext *context)
#define GL_RGBA32F
#define GL_RGBA16
#define GL_RGB32F
static QImage qt_gl_read_framebuffer_rgba32f(const QSize &size, bool include_alpha, QOpenGLContext *context)
#define GL_UNSIGNED_INT_8_8_8_8_REV
#define GL_UNSIGNED_INT_2_10_10_10_REV
#define GL_CONTEXT_LOST
#define GL_UNSIGNED_INT_2_10_10_10_REV
#define Q_ASSERT(cond)
Definition qrandom.cpp:47
#define GL_RGBA8
#define GL_STENCIL_INDEX
#define GLuint
#define GL_FLOAT
#define GL_UNSIGNED_BYTE
#define GL_RGBA
#define Q_UNUSED(x)
#define Q_TRACE_PARAM_REPLACE(in, out)
Definition qtrace_p.h:231
#define Q_TRACE_METADATA(provider, metadata)
Definition qtrace_p.h:234
#define Q_TRACE_PREFIX(provider, prefix)
Definition qtrace_p.h:233
#define Q_TRACE_SCOPE(x,...)
Definition qtrace_p.h:146
#define Q_TRACE_INSTRUMENT(provider)
Definition qtrace_p.h:230
QVideoFrameFormat::PixelFormat fmt
#define enabled
QStorageInfo storage
[1]
QSharedPointer< T > other(t)
[5]