qopenglframebufferobject.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/opengl/qopenglframebufferobject.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2015 The Qt Company Ltd.-
4** Contact: http://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL21$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see http://www.qt.io/terms-conditions. For further-
15** information use the contact form at http://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 2.1 or version 3 as published by the Free-
20** Software Foundation and appearing in the file LICENSE.LGPLv21 and-
21** LICENSE.LGPLv3 included in the packaging of this file. Please review the-
22** following information to ensure the GNU Lesser General Public License-
23** requirements will be met: https://www.gnu.org/licenses/lgpl.html and-
24** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.-
25**-
26** As a special exception, The Qt Company gives you certain additional-
27** rights. These rights are described in The Qt Company LGPL Exception-
28** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.-
29**-
30** $QT_END_LICENSE$-
31**-
32****************************************************************************/-
33-
34#include "qopenglframebufferobject.h"-
35#include "qopenglframebufferobject_p.h"-
36-
37#include <qdebug.h>-
38#include <private/qopengl_p.h>-
39#include <private/qopenglcontext_p.h>-
40#include <private/qopenglextensions_p.h>-
41#include <private/qfont_p.h>-
42-
43#include <qwindow.h>-
44#include <qlibrary.h>-
45#include <qimage.h>-
46#include <QtCore/qbytearray.h>-
47-
48QT_BEGIN_NAMESPACE-
49-
50#ifndef QT_NO_DEBUG-
51#define QT_RESET_GLERROR() \-
52{ \-
53 while (QOpenGLContext::currentContext()->functions()->glGetError() != GL_NO_ERROR) {} \-
54}-
55#define QT_CHECK_GLERROR() \-
56{ \-
57 GLenum err = QOpenGLContext::currentContext()->functions()->glGetError(); \-
58 if (err != GL_NO_ERROR) { \-
59 qDebug("[%s line %d] OpenGL Error: %d", \-
60 __FILE__, __LINE__, (int)err); \-
61 } \-
62}-
63#else-
64#define QT_RESET_GLERROR() {}-
65#define QT_CHECK_GLERROR() {}-
66#endif-
67-
68#ifndef GL_MAX_SAMPLES-
69#define GL_MAX_SAMPLES 0x8D57-
70#endif-
71-
72#ifndef GL_RENDERBUFFER_SAMPLES-
73#define GL_RENDERBUFFER_SAMPLES 0x8CAB-
74#endif-
75-
76#ifndef GL_DEPTH24_STENCIL8-
77#define GL_DEPTH24_STENCIL8 0x88F0-
78#endif-
79-
80#ifndef GL_DEPTH_COMPONENT24-
81#define GL_DEPTH_COMPONENT24 0x81A6-
82#endif-
83-
84#ifndef GL_DEPTH_COMPONENT24_OES-
85#define GL_DEPTH_COMPONENT24_OES 0x81A6-
86#endif-
87-
88#ifndef GL_READ_FRAMEBUFFER-
89#define GL_READ_FRAMEBUFFER 0x8CA8-
90#endif-
91-
92#ifndef GL_DRAW_FRAMEBUFFER-
93#define GL_DRAW_FRAMEBUFFER 0x8CA9-
94#endif-
95-
96#ifndef GL_RGB8-
97#define GL_RGB8 0x8051-
98#endif-
99-
100#ifndef GL_RGB10-
101#define GL_RGB10 0x8052-
102#endif-
103-
104#ifndef GL_RGBA8-
105#define GL_RGBA8 0x8058-
106#endif-
107-
108#ifndef GL_RGB10_A2-
109#define GL_RGB10_A2 0x8059-
110#endif-
111-
112#ifndef GL_BGRA-
113#define GL_BGRA 0x80E1-
114#endif-
115-
116#ifndef GL_UNSIGNED_INT_8_8_8_8_REV-
117#define GL_UNSIGNED_INT_8_8_8_8_REV 0x8367-
118#endif-
119-
120#ifndef GL_UNSIGNED_INT_2_10_10_10_REV-
121#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368-
122#endif-
123-
124-
125/*!-
126 \class QOpenGLFramebufferObjectFormat-
127 \brief The QOpenGLFramebufferObjectFormat class specifies the format of an OpenGL-
128 framebuffer object.-
129 \inmodule QtGui-
130-
131 \since 5.0-
132-
133 \ingroup painting-3D-
134-
135 A framebuffer object has several characteristics:-
136 \list-
137 \li \l{setSamples()}{Number of samples per pixels.}-
138 \li \l{setAttachment()}{Depth and/or stencil attachments.}-
139 \li \l{setTextureTarget()}{Texture target.}-
140 \li \l{setInternalTextureFormat()}{Internal texture format.}-
141 \endlist-
142-
143 Note that the desired attachments or number of samples per pixels might not-
144 be supported by the hardware driver. Call QOpenGLFramebufferObject::format()-
145 after creating a QOpenGLFramebufferObject to find the exact format that was-
146 used to create the frame buffer object.-
147-
148 \sa QOpenGLFramebufferObject-
149*/-
150-
151/*!-
152 \internal-
153*/-
154void QOpenGLFramebufferObjectFormat::detach()-
155{-
156 if (d->ref.load() != 1) {
d->ref.load() != 1Description
TRUEnever evaluated
FALSEnever evaluated
0
157 QOpenGLFramebufferObjectFormatPrivate *newd-
158 = new QOpenGLFramebufferObjectFormatPrivate(d);-
159 if (!d->ref.deref())
!d->ref.deref()Description
TRUEnever evaluated
FALSEnever evaluated
0
160 delete d;
never executed: delete d;
0
161 d = newd;-
162 }
never executed: end of block
0
163}
never executed: end of block
0
164-
165/*!-
166 Creates a QOpenGLFramebufferObjectFormat object for specifying-
167 the format of an OpenGL framebuffer object.-
168-
169 By default the format specifies a non-multisample framebuffer object with no-
170 depth/stencil attachments, texture target \c GL_TEXTURE_2D, and internal format \c GL_RGBA8.-
171 On OpenGL/ES systems, the default internal format is \c GL_RGBA.-
172-
173 \sa samples(), attachment(), internalTextureFormat()-
174*/-
175-
176QOpenGLFramebufferObjectFormat::QOpenGLFramebufferObjectFormat()-
177{-
178 d = new QOpenGLFramebufferObjectFormatPrivate;-
179}
never executed: end of block
0
180-
181/*!-
182 Constructs a copy of \a other.-
183*/-
184-
185QOpenGLFramebufferObjectFormat::QOpenGLFramebufferObjectFormat(const QOpenGLFramebufferObjectFormat &other)-
186{-
187 d = other.d;-
188 d->ref.ref();-
189}
never executed: end of block
0
190-
191/*!-
192 Assigns \a other to this object.-
193*/-
194-
195QOpenGLFramebufferObjectFormat &QOpenGLFramebufferObjectFormat::operator=(const QOpenGLFramebufferObjectFormat &other)-
196{-
197 if (d != other.d) {
d != other.dDescription
TRUEnever evaluated
FALSEnever evaluated
0
198 other.d->ref.ref();-
199 if (!d->ref.deref())
!d->ref.deref()Description
TRUEnever evaluated
FALSEnever evaluated
0
200 delete d;
never executed: delete d;
0
201 d = other.d;-
202 }
never executed: end of block
0
203 return *this;
never executed: return *this;
0
204}-
205-
206/*!-
207 Destroys the QOpenGLFramebufferObjectFormat.-
208*/-
209QOpenGLFramebufferObjectFormat::~QOpenGLFramebufferObjectFormat()-
210{-
211 if (!d->ref.deref())
!d->ref.deref()Description
TRUEnever evaluated
FALSEnever evaluated
0
212 delete d;
never executed: delete d;
0
213}
never executed: end of block
0
214-
215/*!-
216 Sets the number of samples per pixel for a multisample framebuffer object-
217 to \a samples. The default sample count of 0 represents a regular-
218 non-multisample framebuffer object.-
219-
220 If the desired amount of samples per pixel is not supported by the hardware-
221 then the maximum number of samples per pixel will be used. Note that-
222 multisample framebuffer objects can not be bound as textures. Also, the-
223 \c{GL_EXT_framebuffer_multisample} extension is required to create a-
224 framebuffer with more than one sample per pixel.-
225-
226 \sa samples()-
227*/-
228void QOpenGLFramebufferObjectFormat::setSamples(int samples)-
229{-
230 detach();-
231 d->samples = samples;-
232}
never executed: end of block
0
233-
234/*!-
235 Returns the number of samples per pixel if a framebuffer object-
236 is a multisample framebuffer object. Otherwise, returns 0.-
237 The default value is 0.-
238-
239 \sa setSamples()-
240*/-
241int QOpenGLFramebufferObjectFormat::samples() const-
242{-
243 return d->samples;
never executed: return d->samples;
0
244}-
245-
246/*!-
247 Enables mipmapping if \a enabled is true; otherwise disables it.-
248-
249 Mipmapping is disabled by default.-
250-
251 If mipmapping is enabled, additional memory will be allocated for-
252 the mipmap levels. The mipmap levels can be updated by binding the-
253 texture and calling glGenerateMipmap(). Mipmapping cannot be enabled-
254 for multisampled framebuffer objects.-
255-
256 \sa mipmap(), QOpenGLFramebufferObject::texture()-
257*/-
258void QOpenGLFramebufferObjectFormat::setMipmap(bool enabled)-
259{-
260 detach();-
261 d->mipmap = enabled;-
262}
never executed: end of block
0
263-
264/*!-
265 Returns \c true if mipmapping is enabled.-
266-
267 \sa setMipmap()-
268*/-
269bool QOpenGLFramebufferObjectFormat::mipmap() const-
270{-
271 return d->mipmap;
never executed: return d->mipmap;
0
272}-
273-
274/*!-
275 Sets the attachment configuration of a framebuffer object to \a attachment.-
276-
277 \sa attachment()-
278*/-
279void QOpenGLFramebufferObjectFormat::setAttachment(QOpenGLFramebufferObject::Attachment attachment)-
280{-
281 detach();-
282 d->attachment = attachment;-
283}
never executed: end of block
0
284-
285/*!-
286 Returns the configuration of the depth and stencil buffers attached to-
287 a framebuffer object. The default is QOpenGLFramebufferObject::NoAttachment.-
288-
289 \sa setAttachment()-
290*/-
291QOpenGLFramebufferObject::Attachment QOpenGLFramebufferObjectFormat::attachment() const-
292{-
293 return d->attachment;
never executed: return d->attachment;
0
294}-
295-
296/*!-
297 Sets the texture target of the texture attached to a framebuffer object to-
298 \a target. Ignored for multisample framebuffer objects.-
299-
300 \sa textureTarget(), samples()-
301*/-
302void QOpenGLFramebufferObjectFormat::setTextureTarget(GLenum target)-
303{-
304 detach();-
305 d->target = target;-
306}
never executed: end of block
0
307-
308/*!-
309 Returns the texture target of the texture attached to a framebuffer object.-
310 Ignored for multisample framebuffer objects. The default is-
311 \c GL_TEXTURE_2D.-
312-
313 \sa setTextureTarget(), samples()-
314*/-
315GLenum QOpenGLFramebufferObjectFormat::textureTarget() const-
316{-
317 return d->target;
never executed: return d->target;
0
318}-
319-
320/*!-
321 Sets the internal format of a framebuffer object's texture or-
322 multisample framebuffer object's color buffer to-
323 \a internalTextureFormat.-
324-
325 \sa internalTextureFormat()-
326*/-
327void QOpenGLFramebufferObjectFormat::setInternalTextureFormat(GLenum internalTextureFormat)-
328{-
329 detach();-
330 d->internal_format = internalTextureFormat;-
331}
never executed: end of block
0
332-
333/*!-
334 Returns the internal format of a framebuffer object's texture or-
335 multisample framebuffer object's color buffer. The default is-
336 \c GL_RGBA8 on desktop OpenGL systems, and \c GL_RGBA on-
337 OpenGL/ES systems.-
338-
339 \sa setInternalTextureFormat()-
340*/-
341GLenum QOpenGLFramebufferObjectFormat::internalTextureFormat() const-
342{-
343 return d->internal_format;
never executed: return d->internal_format;
0
344}-
345-
346/*!-
347 Returns \c true if all the options of this framebuffer object format-
348 are the same as \a other; otherwise returns \c false.-
349*/-
350bool QOpenGLFramebufferObjectFormat::operator==(const QOpenGLFramebufferObjectFormat& other) const-
351{-
352 if (d == other.d)
d == other.dDescription
TRUEnever evaluated
FALSEnever evaluated
0
353 return true;
never executed: return true;
0
354 else-
355 return d->equals(other.d);
never executed: return d->equals(other.d);
0
356}-
357-
358/*!-
359 Returns \c false if all the options of this framebuffer object format-
360 are the same as \a other; otherwise returns \c true.-
361*/-
362bool QOpenGLFramebufferObjectFormat::operator!=(const QOpenGLFramebufferObjectFormat& other) const-
363{-
364 return !(*this == other);
never executed: return !(*this == other);
0
365}-
366-
367bool QOpenGLFramebufferObjectPrivate::checkFramebufferStatus(QOpenGLContext *ctx) const-
368{-
369 if (!ctx)
!ctxDescription
TRUEnever evaluated
FALSEnever evaluated
0
370 return false; // Context no longer exists.
never executed: return false;
0
371 GLenum status = ctx->functions()->glCheckFramebufferStatus(GL_FRAMEBUFFER);-
372 switch(status) {-
373 case GL_NO_ERROR:
never executed: case 0:
0
374 case GL_FRAMEBUFFER_COMPLETE:
never executed: case 0x8CD5:
0
375 return true;
never executed: return true;
0
376 case GL_FRAMEBUFFER_UNSUPPORTED:
never executed: case 0x8CDD:
0
377 qDebug("QOpenGLFramebufferObject: Unsupported framebuffer format.");-
378 break;
never executed: break;
0
379 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
never executed: case 0x8CD6:
0
380 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete attachment.");-
381 break;
never executed: break;
0
382 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
never executed: case 0x8CD7:
0
383 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment.");-
384 break;
never executed: break;
0
385#ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT-
386 case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT:-
387 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, duplicate attachment.");-
388 break;-
389#endif-
390#ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS-
391 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:-
392 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attached images must have same dimensions.");-
393 break;-
394#endif-
395#ifdef GL_FRAMEBUFFER_INCOMPLETE_FORMATS-
396 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS:-
397 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attached images must have same format.");-
398 break;-
399#endif-
400#ifdef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER-
401 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
never executed: case 0x8CDB:
0
402 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing draw buffer.");-
403 break;
never executed: break;
0
404#endif-
405#ifdef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER-
406 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
never executed: case 0x8CDC:
0
407 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing read buffer.");-
408 break;
never executed: break;
0
409#endif-
410#ifdef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE-
411 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
never executed: case 0x8D56:
0
412 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attachments must have same number of samples per pixel.");-
413 break;
never executed: break;
0
414#endif-
415 default:
never executed: default:
0
416 qDebug() <<"QOpenGLFramebufferObject: An undefined error has occurred: "<< status;-
417 break;
never executed: break;
0
418 }-
419 return false;
never executed: return false;
0
420}-
421-
422namespace-
423{-
424 void freeFramebufferFunc(QOpenGLFunctions *funcs, GLuint id)-
425 {-
426 funcs->glDeleteFramebuffers(1, &id);-
427 }
never executed: end of block
0
428-
429 void freeRenderbufferFunc(QOpenGLFunctions *funcs, GLuint id)-
430 {-
431 funcs->glDeleteRenderbuffers(1, &id);-
432 }
never executed: end of block
0
433-
434 void freeTextureFunc(QOpenGLFunctions *funcs, GLuint id)-
435 {-
436 funcs->glDeleteTextures(1, &id);-
437 }
never executed: end of block
0
438}-
439-
440void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSize &size,-
441 QOpenGLFramebufferObject::Attachment attachment,-
442 GLenum texture_target, GLenum internal_format,-
443 GLint samples, bool mipmap)-
444{-
445 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
446-
447 funcs.initializeOpenGLFunctions();-
448-
449 if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
!funcs.hasOpen...:Framebuffers)Description
TRUEnever evaluated
FALSEnever evaluated
0
450 return;
never executed: return;
0
451-
452 // Fall back to using a normal non-msaa FBO if we don't have support for MSAA-
453 if (!funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
!funcs.hasOpen...erMultisample)Description
TRUEnever evaluated
FALSEnever evaluated
0
454 || !funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit)) {
!funcs.hasOpen...amebufferBlit)Description
TRUEnever evaluated
FALSEnever evaluated
0
455 samples = 0;-
456 } else if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) {
never executed: end of block
!ctx->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
ctx->format()....Version() >= 3Description
TRUEnever evaluated
FALSEnever evaluated
0
457 GLint maxSamples;-
458 funcs.glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);-
459 samples = qBound(0, int(samples), int(maxSamples));-
460 }
never executed: end of block
0
461-
462 colorAttachments.append(ColorAttachment(size, internal_format));-
463-
464 dsSize = size;-
465-
466 samples = qMax(0, samples);-
467 requestedSamples = samples;-
468-
469 target = texture_target;-
470-
471 QT_RESET_GLERROR(); // reset error state
never executed: end of block
QOpenGLContext...etError() != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
472 GLuint fbo = 0;-
473-
474 funcs.glGenFramebuffers(1, &fbo);-
475 funcs.glBindFramebuffer(GL_FRAMEBUFFER, fbo);-
476-
477 QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true;-
478-
479 QT_CHECK_GLERROR();
never executed: end of block
err != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
480-
481 format.setTextureTarget(target);-
482 format.setInternalTextureFormat(internal_format);-
483 format.setMipmap(mipmap);-
484-
485 if (samples == 0)
samples == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
486 initTexture(0);
never executed: initTexture(0);
0
487 else-
488 initColorBuffer(0, &samples);
never executed: initColorBuffer(0, &samples);
0
489-
490 format.setSamples(int(samples));-
491-
492 initDepthStencilAttachments(ctx, attachment);-
493-
494 if (valid)
validDescription
TRUEnever evaluated
FALSEnever evaluated
0
495 fbo_guard = new QOpenGLSharedResourceGuard(ctx, fbo, freeFramebufferFunc);
never executed: fbo_guard = new QOpenGLSharedResourceGuard(ctx, fbo, freeFramebufferFunc);
0
496 else-
497 funcs.glDeleteFramebuffers(1, &fbo);
never executed: funcs.glDeleteFramebuffers(1, &fbo);
0
498-
499 QT_CHECK_GLERROR();
never executed: end of block
err != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
500}
never executed: end of block
0
501-
502void QOpenGLFramebufferObjectPrivate::initTexture(int idx)-
503{-
504 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
505 GLuint texture = 0;-
506-
507 funcs.glGenTextures(1, &texture);-
508 funcs.glBindTexture(target, texture);-
509-
510 funcs.glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);-
511 funcs.glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);-
512 funcs.glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);-
513 funcs.glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);-
514-
515 ColorAttachment &color(colorAttachments[idx]);-
516-
517 GLuint pixelType = GL_UNSIGNED_BYTE;-
518 if (color.internalFormat == GL_RGB10_A2 || color.internalFormat == GL_RGB10)
color.internalFormat == 0x8059Description
TRUEnever evaluated
FALSEnever evaluated
color.internalFormat == 0x8052Description
TRUEnever evaluated
FALSEnever evaluated
0
519 pixelType = GL_UNSIGNED_INT_2_10_10_10_REV;
never executed: pixelType = 0x8368;
0
520-
521 funcs.glTexImage2D(target, 0, color.internalFormat, color.size.width(), color.size.height(), 0,-
522 GL_RGBA, pixelType, NULL);-
523 if (format.mipmap()) {
format.mipmap()Description
TRUEnever evaluated
FALSEnever evaluated
0
524 int width = color.size.width();-
525 int height = color.size.height();-
526 int level = 0;-
527 while (width > 1 || height > 1) {
width > 1Description
TRUEnever evaluated
FALSEnever evaluated
height > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
528 width = qMax(1, width >> 1);-
529 height = qMax(1, height >> 1);-
530 ++level;-
531 funcs.glTexImage2D(target, level, color.internalFormat, width, height, 0,-
532 GL_RGBA, pixelType, NULL);-
533 }
never executed: end of block
0
534 }
never executed: end of block
0
535 funcs.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + idx,-
536 target, texture, 0);-
537-
538 QT_CHECK_GLERROR();
never executed: end of block
err != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
539 funcs.glBindTexture(target, 0);-
540 valid = checkFramebufferStatus(ctx);-
541 if (valid) {
validDescription
TRUEnever evaluated
FALSEnever evaluated
0
542 color.guard = new QOpenGLSharedResourceGuard(ctx, texture, freeTextureFunc);-
543 } else {
never executed: end of block
0
544 funcs.glDeleteTextures(1, &texture);-
545 }
never executed: end of block
0
546}-
547-
548void QOpenGLFramebufferObjectPrivate::initColorBuffer(int idx, GLint *samples)-
549{-
550 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
551 GLuint color_buffer = 0;-
552-
553 ColorAttachment &color(colorAttachments[idx]);-
554-
555 GLenum storageFormat = color.internalFormat;-
556 // ES requires a sized format. The older desktop extension does not. Correct the format on ES.-
557 if (ctx->isOpenGLES() && color.internalFormat == GL_RGBA) {
ctx->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
color.internalFormat == 0x1908Description
TRUEnever evaluated
FALSEnever evaluated
0
558 if (funcs.hasOpenGLExtension(QOpenGLExtensions::Sized8Formats))
funcs.hasOpenG...Sized8Formats)Description
TRUEnever evaluated
FALSEnever evaluated
0
559 storageFormat = GL_RGBA8;
never executed: storageFormat = 0x8058;
0
560 else-
561 storageFormat = GL_RGBA4;
never executed: storageFormat = 0x8056;
0
562 }-
563-
564 funcs.glGenRenderbuffers(1, &color_buffer);-
565 funcs.glBindRenderbuffer(GL_RENDERBUFFER, color_buffer);-
566 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, *samples, storageFormat, color.size.width(), color.size.height());-
567 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + idx,-
568 GL_RENDERBUFFER, color_buffer);-
569-
570 QT_CHECK_GLERROR();
never executed: end of block
err != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
571 valid = checkFramebufferStatus(ctx);-
572 if (valid) {
validDescription
TRUEnever evaluated
FALSEnever evaluated
0
573 // Query the actual number of samples. This can be greater than the requested-
574 // value since the typically supported values are 0, 4, 8, ..., and the-
575 // requests are mapped to the next supported value.-
576 funcs.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, samples);-
577 color.guard = new QOpenGLSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc);-
578 } else {
never executed: end of block
0
579 funcs.glDeleteRenderbuffers(1, &color_buffer);-
580 }
never executed: end of block
0
581}-
582-
583void QOpenGLFramebufferObjectPrivate::initDepthStencilAttachments(QOpenGLContext *ctx,-
584 QOpenGLFramebufferObject::Attachment attachment)-
585{-
586 // Use the same sample count for all attachments. format.samples() already contains-
587 // the actual number of samples for the color attachment and is not suitable. Use-
588 // requestedSamples instead.-
589 const int samples = requestedSamples;-
590-
591 // free existing attachments-
592 if (depth_buffer_guard) {
depth_buffer_guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
593 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);-
594 depth_buffer_guard->free();-
595 }
never executed: end of block
0
596 if (stencil_buffer_guard) {
stencil_buffer_guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
597 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);-
598 if (stencil_buffer_guard != depth_buffer_guard)
stencil_buffer...h_buffer_guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
599 stencil_buffer_guard->free();
never executed: stencil_buffer_guard->free();
0
600 }
never executed: end of block
0
601-
602 depth_buffer_guard = 0;-
603 stencil_buffer_guard = 0;-
604-
605 GLuint depth_buffer = 0;-
606 GLuint stencil_buffer = 0;-
607-
608 // In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a-
609 // separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer-
610 // might not be supported while separate buffers are, according to QTBUG-12861.-
611-
612 if (attachment == QOpenGLFramebufferObject::CombinedDepthStencil
attachment == ...edDepthStencilDescription
TRUEnever evaluated
FALSEnever evaluated
0
613 && funcs.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil))
funcs.hasOpenG...dDepthStencil)Description
TRUEnever evaluated
FALSEnever evaluated
0
614 {-
615 // depth and stencil buffer needs another extension-
616 funcs.glGenRenderbuffers(1, &depth_buffer);-
617 funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);-
618 Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));-
619 if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
samples != 0Description
TRUEnever evaluated
FALSEnever evaluated
funcs.hasOpenG...erMultisample)Description
TRUEnever evaluated
FALSEnever evaluated
0
620 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x88F0, dsSize.width(), dsSize.height());
0
621 GL_DEPTH24_STENCIL8, dsSize.width(), dsSize.height());
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x88F0, dsSize.width(), dsSize.height());
0
622 else-
623 funcs.glRenderbufferStorage(GL_RENDERBUFFER,
never executed: funcs.glRenderbufferStorage(0x8D41, 0x88F0, dsSize.width(), dsSize.height());
0
624 GL_DEPTH24_STENCIL8, dsSize.width(), dsSize.height());
never executed: funcs.glRenderbufferStorage(0x8D41, 0x88F0, dsSize.width(), dsSize.height());
0
625-
626 stencil_buffer = depth_buffer;-
627 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,-
628 GL_RENDERBUFFER, depth_buffer);-
629 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,-
630 GL_RENDERBUFFER, stencil_buffer);-
631-
632 valid = checkFramebufferStatus(ctx);-
633 if (!valid) {
!validDescription
TRUEnever evaluated
FALSEnever evaluated
0
634 funcs.glDeleteRenderbuffers(1, &depth_buffer);-
635 stencil_buffer = depth_buffer = 0;-
636 }
never executed: end of block
0
637 }
never executed: end of block
0
638-
639 if (depth_buffer == 0 && (attachment == QOpenGLFramebufferObject::CombinedDepthStencil
depth_buffer == 0Description
TRUEnever evaluated
FALSEnever evaluated
attachment == ...edDepthStencilDescription
TRUEnever evaluated
FALSEnever evaluated
0
640 || (attachment == QOpenGLFramebufferObject::Depth)))
(attachment ==...Object::Depth)Description
TRUEnever evaluated
FALSEnever evaluated
0
641 {-
642 funcs.glGenRenderbuffers(1, &depth_buffer);-
643 funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);-
644 Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));-
645 if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) {
samples != 0Description
TRUEnever evaluated
FALSEnever evaluated
funcs.hasOpenG...erMultisample)Description
TRUEnever evaluated
FALSEnever evaluated
0
646 if (ctx->isOpenGLES()) {
ctx->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
647 if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24))
funcs.hasOpenG...ions::Depth24)Description
TRUEnever evaluated
FALSEnever evaluated
0
648 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x81A6, dsSize.width(), dsSize.height());
0
649 GL_DEPTH_COMPONENT24, dsSize.width(), dsSize.height());
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x81A6, dsSize.width(), dsSize.height());
0
650 else-
651 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x81A5, dsSize.width(), dsSize.height());
0
652 GL_DEPTH_COMPONENT16, dsSize.width(), dsSize.height());
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x81A5, dsSize.width(), dsSize.height());
0
653 } else {-
654 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,-
655 GL_DEPTH_COMPONENT, dsSize.width(), dsSize.height());-
656 }
never executed: end of block
0
657 } else {-
658 if (ctx->isOpenGLES()) {
ctx->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
659 if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24)) {
funcs.hasOpenG...ions::Depth24)Description
TRUEnever evaluated
FALSEnever evaluated
0
660 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24,-
661 dsSize.width(), dsSize.height());-
662 } else {
never executed: end of block
0
663 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,-
664 dsSize.width(), dsSize.height());-
665 }
never executed: end of block
0
666 } else {-
667 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, dsSize.width(), dsSize.height());-
668 }
never executed: end of block
0
669 }-
670 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,-
671 GL_RENDERBUFFER, depth_buffer);-
672 valid = checkFramebufferStatus(ctx);-
673 if (!valid) {
!validDescription
TRUEnever evaluated
FALSEnever evaluated
0
674 funcs.glDeleteRenderbuffers(1, &depth_buffer);-
675 depth_buffer = 0;-
676 }
never executed: end of block
0
677 }
never executed: end of block
0
678-
679 if (stencil_buffer == 0 && (attachment == QOpenGLFramebufferObject::CombinedDepthStencil)) {
stencil_buffer == 0Description
TRUEnever evaluated
FALSEnever evaluated
(attachment ==...dDepthStencil)Description
TRUEnever evaluated
FALSEnever evaluated
0
680 funcs.glGenRenderbuffers(1, &stencil_buffer);-
681 funcs.glBindRenderbuffer(GL_RENDERBUFFER, stencil_buffer);-
682 Q_ASSERT(funcs.glIsRenderbuffer(stencil_buffer));-
683-
684#ifdef QT_OPENGL_ES-
685 GLenum storage = GL_STENCIL_INDEX8;-
686#else-
687 GLenum storage = ctx->isOpenGLES() ? GL_STENCIL_INDEX8 : GL_STENCIL_INDEX;
ctx->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
688#endif-
689-
690 if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
samples != 0Description
TRUEnever evaluated
FALSEnever evaluated
funcs.hasOpenG...erMultisample)Description
TRUEnever evaluated
FALSEnever evaluated
0
691 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, storage, dsSize.width(), dsSize.height());
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, storage, dsSize.width(), dsSize.height());
0
692 else-
693 funcs.glRenderbufferStorage(GL_RENDERBUFFER, storage, dsSize.width(), dsSize.height());
never executed: funcs.glRenderbufferStorage(0x8D41, storage, dsSize.width(), dsSize.height());
0
694-
695 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,-
696 GL_RENDERBUFFER, stencil_buffer);-
697 valid = checkFramebufferStatus(ctx);-
698 if (!valid) {
!validDescription
TRUEnever evaluated
FALSEnever evaluated
0
699 funcs.glDeleteRenderbuffers(1, &stencil_buffer);-
700 stencil_buffer = 0;-
701 }
never executed: end of block
0
702 }
never executed: end of block
0
703-
704 // The FBO might have become valid after removing the depth or stencil buffer.-
705 valid = checkFramebufferStatus(ctx);-
706-
707 if (depth_buffer && stencil_buffer) {
depth_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
stencil_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
708 fbo_attachment = QOpenGLFramebufferObject::CombinedDepthStencil;-
709 } else if (depth_buffer) {
never executed: end of block
depth_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
710 fbo_attachment = QOpenGLFramebufferObject::Depth;-
711 } else {
never executed: end of block
0
712 fbo_attachment = QOpenGLFramebufferObject::NoAttachment;-
713 }
never executed: end of block
0
714-
715 if (valid) {
validDescription
TRUEnever evaluated
FALSEnever evaluated
0
716 if (depth_buffer)
depth_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
717 depth_buffer_guard = new QOpenGLSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc);
never executed: depth_buffer_guard = new QOpenGLSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc);
0
718 if (stencil_buffer) {
stencil_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
719 if (stencil_buffer == depth_buffer)
stencil_buffer == depth_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
720 stencil_buffer_guard = depth_buffer_guard;
never executed: stencil_buffer_guard = depth_buffer_guard;
0
721 else-
722 stencil_buffer_guard = new QOpenGLSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc);
never executed: stencil_buffer_guard = new QOpenGLSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc);
0
723 }-
724 } else {
never executed: end of block
0
725 if (depth_buffer)
depth_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
726 funcs.glDeleteRenderbuffers(1, &depth_buffer);
never executed: funcs.glDeleteRenderbuffers(1, &depth_buffer);
0
727 if (stencil_buffer && depth_buffer != stencil_buffer)
stencil_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
depth_buffer != stencil_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
728 funcs.glDeleteRenderbuffers(1, &stencil_buffer);
never executed: funcs.glDeleteRenderbuffers(1, &stencil_buffer);
0
729 }
never executed: end of block
0
730 QT_CHECK_GLERROR();
never executed: end of block
err != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
731-
732 format.setAttachment(fbo_attachment);-
733}
never executed: end of block
0
734-
735/*!-
736 \class QOpenGLFramebufferObject-
737 \brief The QOpenGLFramebufferObject class encapsulates an OpenGL framebuffer object.-
738 \since 5.0-
739 \inmodule QtGui-
740-
741 \ingroup painting-3D-
742-
743 The QOpenGLFramebufferObject class encapsulates an OpenGL framebuffer-
744 object, defined by the \c{GL_EXT_framebuffer_object} extension. It provides-
745 a rendering surface that can be painted on with a QPainter with the help of-
746 QOpenGLPaintDevice, or rendered to using native OpenGL calls. This surface-
747 can be bound and used as a regular texture in your own OpenGL drawing code.-
748 By default, the QOpenGLFramebufferObject class generates a 2D OpenGL-
749 texture (using the \c{GL_TEXTURE_2D} target), which is used as the internal-
750 rendering target.-
751-
752 \b{It is important to have a current OpenGL context when creating a-
753 QOpenGLFramebufferObject, otherwise initialization will fail.}-
754-
755 Create the QOpenGLFrameBufferObject instance with the CombinedDepthStencil-
756 attachment if you want QPainter to render correctly. Note that you need to-
757 create a QOpenGLFramebufferObject with more than one sample per pixel for-
758 primitives to be antialiased when drawing using a QPainter. To create a-
759 multisample framebuffer object you should use one of the constructors that-
760 take a QOpenGLFramebufferObjectFormat parameter, and set the-
761 QOpenGLFramebufferObjectFormat::samples() property to a non-zero value.-
762-
763 For multisample framebuffer objects a color render buffer is created,-
764 otherwise a texture with the specified texture target is created.-
765 The color render buffer or texture will have the specified internal-
766 format, and will be bound to the \c GL_COLOR_ATTACHMENT0-
767 attachment in the framebuffer object.-
768-
769 Multiple render targets are also supported, in case the OpenGL-
770 implementation supports this. Here there will be multiple textures (or, in-
771 case of multisampling, renderbuffers) present and each of them will get-
772 attached to \c GL_COLOR_ATTACHMENT0, \c 1, \c 2, ...-
773-
774 If you want to use a framebuffer object with multisampling enabled-
775 as a texture, you first need to copy from it to a regular framebuffer-
776 object using QOpenGLContext::blitFramebuffer().-
777-
778 It is possible to draw into a QOpenGLFramebufferObject using QPainter and-
779 QOpenGLPaintDevice in a separate thread.-
780*/-
781-
782-
783/*!-
784 \enum QOpenGLFramebufferObject::Attachment-
785-
786 This enum type is used to configure the depth and stencil buffers-
787 attached to the framebuffer object when it is created.-
788-
789 \value NoAttachment No attachment is added to the framebuffer object. Note that the-
790 OpenGL depth and stencil tests won't work when rendering to a-
791 framebuffer object without any depth or stencil buffers.-
792 This is the default value.-
793-
794 \value CombinedDepthStencil If the \c GL_EXT_packed_depth_stencil extension is present,-
795 a combined depth and stencil buffer is attached.-
796 If the extension is not present, only a depth buffer is attached.-
797-
798 \value Depth A depth buffer is attached to the framebuffer object.-
799-
800 \sa attachment()-
801*/-
802-
803static inline GLenum effectiveInternalFormat(GLenum internalFormat)-
804{-
805 if (!internalFormat)
!internalFormatDescription
TRUEnever evaluated
FALSEnever evaluated
0
806#ifdef QT_OPENGL_ES_2-
807 internalFormat = GL_RGBA;-
808#else-
809 internalFormat = QOpenGLContext::currentContext()->isOpenGLES() ? GL_RGBA : GL_RGBA8;
never executed: internalFormat = QOpenGLContext::currentContext()->isOpenGLES() ? 0x1908 : 0x8058;
QOpenGLContext...->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
810#endif-
811 return internalFormat;
never executed: return internalFormat;
0
812}-
813-
814/*! \fn QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, GLenum target)-
815-
816 Constructs an OpenGL framebuffer object and binds a 2D OpenGL texture-
817 to the buffer of the size \a size. The texture is bound to the-
818 \c GL_COLOR_ATTACHMENT0 target in the framebuffer object.-
819-
820 The \a target parameter is used to specify the OpenGL texture-
821 target. The default target is \c GL_TEXTURE_2D. Keep in mind that-
822 \c GL_TEXTURE_2D textures must have a power of 2 width and height-
823 (e.g. 256x512), unless you are using OpenGL 2.0 or higher.-
824-
825 By default, no depth and stencil buffers are attached. This behavior-
826 can be toggled using one of the overloaded constructors.-
827-
828 The default internal texture format is \c GL_RGBA8 for desktop-
829 OpenGL, and \c GL_RGBA for OpenGL/ES.-
830-
831 It is important that you have a current OpenGL context set when-
832 creating the QOpenGLFramebufferObject, otherwise the initialization-
833 will fail.-
834-
835 \sa size(), texture(), attachment()-
836*/-
837-
838QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, GLenum target)-
839 : d_ptr(new QOpenGLFramebufferObjectPrivate)-
840{-
841 Q_D(QOpenGLFramebufferObject);-
842 d->init(this, size, NoAttachment, target, effectiveInternalFormat(0));-
843}
never executed: end of block
0
844-
845/*! \overload-
846-
847 Constructs an OpenGL framebuffer object and binds a 2D OpenGL texture-
848 to the buffer of the given \a width and \a height.-
849-
850 \sa size(), texture()-
851*/-
852QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, GLenum target)-
853 : d_ptr(new QOpenGLFramebufferObjectPrivate)-
854{-
855 Q_D(QOpenGLFramebufferObject);-
856 d->init(this, QSize(width, height), NoAttachment, target, effectiveInternalFormat(0));-
857}
never executed: end of block
0
858-
859/*! \overload-
860-
861 Constructs an OpenGL framebuffer object of the given \a size based on the-
862 supplied \a format.-
863*/-
864-
865QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, const QOpenGLFramebufferObjectFormat &format)-
866 : d_ptr(new QOpenGLFramebufferObjectPrivate)-
867{-
868 Q_D(QOpenGLFramebufferObject);-
869 d->init(this, size, format.attachment(), format.textureTarget(), format.internalTextureFormat(),-
870 format.samples(), format.mipmap());-
871}
never executed: end of block
0
872-
873/*! \overload-
874-
875 Constructs an OpenGL framebuffer object of the given \a width and \a height-
876 based on the supplied \a format.-
877*/-
878-
879QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, const QOpenGLFramebufferObjectFormat &format)-
880 : d_ptr(new QOpenGLFramebufferObjectPrivate)-
881{-
882 Q_D(QOpenGLFramebufferObject);-
883 d->init(this, QSize(width, height), format.attachment(), format.textureTarget(),-
884 format.internalTextureFormat(), format.samples(), format.mipmap());-
885}
never executed: end of block
0
886-
887/*! \overload-
888-
889 Constructs an OpenGL framebuffer object and binds a texture to the-
890 buffer of the given \a width and \a height.-
891-
892 The \a attachment parameter describes the depth/stencil buffer-
893 configuration, \a target the texture target and \a internalFormat-
894 the internal texture format. The default texture target is \c-
895 GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8-
896 for desktop OpenGL and \c GL_RGBA for OpenGL/ES.-
897-
898 \sa size(), texture(), attachment()-
899*/-
900QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, Attachment attachment,-
901 GLenum target, GLenum internalFormat)-
902 : d_ptr(new QOpenGLFramebufferObjectPrivate)-
903{-
904 Q_D(QOpenGLFramebufferObject);-
905 d->init(this, QSize(width, height), attachment, target, effectiveInternalFormat(internalFormat));-
906}
never executed: end of block
0
907-
908/*! \overload-
909-
910 Constructs an OpenGL framebuffer object and binds a texture to the-
911 buffer of the given \a size.-
912-
913 The \a attachment parameter describes the depth/stencil buffer-
914 configuration, \a target the texture target and \a internalFormat-
915 the internal texture format. The default texture target is \c-
916 GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8-
917 for desktop OpenGL and \c GL_RGBA for OpenGL/ES.-
918-
919 \sa size(), texture(), attachment()-
920*/-
921QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, Attachment attachment,-
922 GLenum target, GLenum internalFormat)-
923 : d_ptr(new QOpenGLFramebufferObjectPrivate)-
924{-
925 Q_D(QOpenGLFramebufferObject);-
926 d->init(this, size, attachment, target, effectiveInternalFormat(internalFormat));-
927}
never executed: end of block
0
928-
929/*!-
930 \fn QOpenGLFramebufferObject::~QOpenGLFramebufferObject()-
931-
932 Destroys the framebuffer object and frees any allocated resources.-
933*/-
934QOpenGLFramebufferObject::~QOpenGLFramebufferObject()-
935{-
936 Q_D(QOpenGLFramebufferObject);-
937 if (isBound())
isBound()Description
TRUEnever evaluated
FALSEnever evaluated
0
938 release();
never executed: release();
0
939-
940 foreach (const QOpenGLFramebufferObjectPrivate::ColorAttachment &color, d->colorAttachments) {-
941 if (color.guard)
color.guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
942 color.guard->free();
never executed: color.guard->free();
0
943 }
never executed: end of block
0
944 d->colorAttachments.clear();-
945-
946 if (d->depth_buffer_guard)
d->depth_buffer_guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
947 d->depth_buffer_guard->free();
never executed: d->depth_buffer_guard->free();
0
948 if (d->stencil_buffer_guard && d->stencil_buffer_guard != d->depth_buffer_guard)
d->stencil_buffer_guardDescription
TRUEnever evaluated
FALSEnever evaluated
d->stencil_buf...h_buffer_guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
949 d->stencil_buffer_guard->free();
never executed: d->stencil_buffer_guard->free();
0
950 if (d->fbo_guard)
d->fbo_guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
951 d->fbo_guard->free();
never executed: d->fbo_guard->free();
0
952-
953 QOpenGLContextPrivate *contextPrv = QOpenGLContextPrivate::get(QOpenGLContext::currentContext());-
954 if (contextPrv && contextPrv->qgl_current_fbo == this) {
contextPrvDescription
TRUEnever evaluated
FALSEnever evaluated
contextPrv->qg...nt_fbo == thisDescription
TRUEnever evaluated
FALSEnever evaluated
0
955 contextPrv->qgl_current_fbo_invalid = true;-
956 contextPrv->qgl_current_fbo = Q_NULLPTR;-
957 }
never executed: end of block
0
958}
never executed: end of block
0
959-
960/*!-
961 Creates and attaches an additional texture or renderbuffer of \a size width-
962 and height.-
963-
964 There is always an attachment at GL_COLOR_ATTACHMENT0. Call this function-
965 to set up additional attachments at GL_COLOR_ATTACHMENT1,-
966 GL_COLOR_ATTACHMENT2, ...-
967-
968 When \a internalFormat is not \c 0, it specifies the internal format of the-
969 texture or renderbuffer. Otherwise a default of GL_RGBA or GL_RGBA8 is-
970 used.-
971-
972 \note This is only functional when multiple render targets are supported by-
973 the OpenGL implementation. When that is not the case, the function will not-
974 add any additional color attachments. Call-
975 QOpenGLFunctions::hasOpenGLFeature() with-
976 QOpenGLFunctions::MultipleRenderTargets at runtime to check if MRT is-
977 supported.-
978-
979 \note The internal format of the color attachments may differ but there may-
980 be limitations on the supported combinations, depending on the drivers.-
981-
982 \note The size of the color attachments may differ but rendering is limited-
983 to the area that fits all the attachments, according to the OpenGL-
984 specification. Some drivers may not be fully conformant in this respect,-
985 however.-
986-
987 \since 5.6-
988 */-
989void QOpenGLFramebufferObject::addColorAttachment(const QSize &size, GLenum internalFormat)-
990{-
991 Q_D(QOpenGLFramebufferObject);-
992-
993 if (!QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(QOpenGLFunctions::MultipleRenderTargets)) {
!QOpenGLContex...RenderTargets)Description
TRUEnever evaluated
FALSEnever evaluated
0
994 qWarning("Multiple render targets not supported, ignoring extra color attachment request");-
995 return;
never executed: return;
0
996 }-
997-
998 QOpenGLFramebufferObjectPrivate::ColorAttachment color(size, effectiveInternalFormat(internalFormat));-
999 d->colorAttachments.append(color);-
1000 const int idx = d->colorAttachments.count() - 1;-
1001-
1002 if (d->requestedSamples == 0) {
d->requestedSamples == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1003 d->initTexture(idx);-
1004 } else {
never executed: end of block
0
1005 GLint samples = d->requestedSamples;-
1006 d->initColorBuffer(idx, &samples);-
1007 }
never executed: end of block
0
1008}-
1009-
1010/*! \overload-
1011-
1012 Creates and attaches an additional texture or renderbuffer of size \a width and \a height.-
1013-
1014 When \a internalFormat is not \c 0, it specifies the internal format of the texture or-
1015 renderbuffer. Otherwise a default of GL_RGBA or GL_RGBA8 is used.-
1016-
1017 \since 5.6-
1018 */-
1019void QOpenGLFramebufferObject::addColorAttachment(int width, int height, GLenum internalFormat)-
1020{-
1021 addColorAttachment(QSize(width, height), internalFormat);-
1022}
never executed: end of block
0
1023-
1024/*!-
1025 \fn bool QOpenGLFramebufferObject::isValid() const-
1026-
1027 Returns \c true if the framebuffer object is valid.-
1028-
1029 The framebuffer can become invalid if the initialization process-
1030 fails, the user attaches an invalid buffer to the framebuffer-
1031 object, or a non-power of two width/height is specified as the-
1032 texture size if the texture target is \c{GL_TEXTURE_2D}.-
1033 The non-power of two limitation does not apply if the OpenGL version-
1034 is 2.0 or higher, or if the GL_ARB_texture_non_power_of_two extension-
1035 is present.-
1036-
1037 The framebuffer can also become invalid if the QOpenGLContext that-
1038 the framebuffer was created within is destroyed and there are-
1039 no other shared contexts that can take over ownership of the-
1040 framebuffer.-
1041*/-
1042bool QOpenGLFramebufferObject::isValid() const-
1043{-
1044 Q_D(const QOpenGLFramebufferObject);-
1045 return d->valid && d->fbo_guard && d->fbo_guard->id();
never executed: return d->valid && d->fbo_guard && d->fbo_guard->id();
d->validDescription
TRUEnever evaluated
FALSEnever evaluated
d->fbo_guardDescription
TRUEnever evaluated
FALSEnever evaluated
d->fbo_guard->id()Description
TRUEnever evaluated
FALSEnever evaluated
0
1046}-
1047-
1048/*!-
1049 \fn bool QOpenGLFramebufferObject::bind()-
1050-
1051 Switches rendering from the default, windowing system provided-
1052 framebuffer to this framebuffer object.-
1053 Returns \c true upon success, false otherwise.-
1054-
1055 \note If takeTexture() was called, a new texture is created and associated-
1056 with the framebuffer object. This is potentially expensive and changes the-
1057 context state (the currently bound texture).-
1058-
1059 \sa release()-
1060*/-
1061bool QOpenGLFramebufferObject::bind()-
1062{-
1063 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1064 return false;
never executed: return false;
0
1065 Q_D(QOpenGLFramebufferObject);-
1066 QOpenGLContext *current = QOpenGLContext::currentContext();-
1067 if (!current)
!currentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1068 return false;
never executed: return false;
0
1069#ifdef QT_DEBUG-
1070 if (current->shareGroup() != d->fbo_guard->group())
current->share...guard->group()Description
TRUEnever evaluated
FALSEnever evaluated
0
1071 qWarning("QOpenGLFramebufferObject::bind() called from incompatible context");
never executed: QMessageLogger(__FILE__, 1071, __PRETTY_FUNCTION__).warning("QOpenGLFramebufferObject::bind() called from incompatible context");
0
1072#endif-
1073-
1074 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());-
1075-
1076 QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;-
1077 QOpenGLContextPrivate::get(current)->qgl_current_fbo = this;-
1078-
1079 if (d->format.samples() == 0) {
d->format.samples() == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1080 // Create new textures to replace the ones stolen via takeTexture().-
1081 for (int i = 0; i < d->colorAttachments.count(); ++i) {
i < d->colorAt...hments.count()Description
TRUEnever evaluated
FALSEnever evaluated
0
1082 if (!d->colorAttachments[i].guard)
!d->colorAttachments[i].guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
1083 d->initTexture(i);
never executed: d->initTexture(i);
0
1084 }
never executed: end of block
0
1085 }
never executed: end of block
0
1086-
1087 return d->valid;
never executed: return d->valid;
0
1088}-
1089-
1090/*!-
1091 \fn bool QOpenGLFramebufferObject::release()-
1092-
1093 Switches rendering back to the default, windowing system provided-
1094 framebuffer.-
1095 Returns \c true upon success, false otherwise.-
1096-
1097 \sa bind()-
1098*/-
1099bool QOpenGLFramebufferObject::release()-
1100{-
1101 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1102 return false;
never executed: return false;
0
1103-
1104 QOpenGLContext *current = QOpenGLContext::currentContext();-
1105 if (!current)
!currentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1106 return false;
never executed: return false;
0
1107-
1108 Q_D(QOpenGLFramebufferObject);-
1109#ifdef QT_DEBUG-
1110 if (current->shareGroup() != d->fbo_guard->group())
current->share...guard->group()Description
TRUEnever evaluated
FALSEnever evaluated
0
1111 qWarning("QOpenGLFramebufferObject::release() called from incompatible context");
never executed: QMessageLogger(__FILE__, 1111, __PRETTY_FUNCTION__).warning("QOpenGLFramebufferObject::release() called from incompatible context");
0
1112#endif-
1113-
1114 if (current) {
currentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1115 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->defaultFramebufferObject());-
1116-
1117 QOpenGLContextPrivate *contextPrv = QOpenGLContextPrivate::get(current);-
1118 contextPrv->qgl_current_fbo_invalid = true;-
1119 contextPrv->qgl_current_fbo = Q_NULLPTR;-
1120 }
never executed: end of block
0
1121-
1122 return true;
never executed: return true;
0
1123}-
1124-
1125/*!-
1126 \fn GLuint QOpenGLFramebufferObject::texture() const-
1127-
1128 Returns the texture id for the texture attached as the default-
1129 rendering target in this framebuffer object. This texture id can-
1130 be bound as a normal texture in your own OpenGL code.-
1131-
1132 If a multisample framebuffer object is used then the value returned-
1133 from this function will be invalid.-
1134-
1135 When multiple textures are attached, the return value is the ID of-
1136 the first one.-
1137-
1138 \sa takeTexture(), textures()-
1139*/-
1140GLuint QOpenGLFramebufferObject::texture() const-
1141{-
1142 Q_D(const QOpenGLFramebufferObject);-
1143 return d->colorAttachments[0].guard ? d->colorAttachments[0].guard->id() : 0;
never executed: return d->colorAttachments[0].guard ? d->colorAttachments[0].guard->id() : 0;
d->colorAttachments[0].guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
1144}-
1145-
1146/*!-
1147 Returns the texture id for all attached textures.-
1148-
1149 If a multisample framebuffer object is used, then an empty vector is returned.-
1150-
1151 \since 5.6-
1152-
1153 \sa takeTexture(), texture()-
1154*/-
1155QVector<GLuint> QOpenGLFramebufferObject::textures() const-
1156{-
1157 Q_D(const QOpenGLFramebufferObject);-
1158 QVector<GLuint> ids;-
1159 if (d->format.samples() != 0)
d->format.samples() != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1160 return ids;
never executed: return ids;
0
1161 ids.reserve(d->colorAttachments.count());-
1162 foreach (const QOpenGLFramebufferObjectPrivate::ColorAttachment &color, d->colorAttachments)-
1163 ids.append(color.guard ? color.guard->id() : 0);
never executed: ids.append(color.guard ? color.guard->id() : 0);
0
1164 return ids;
never executed: return ids;
0
1165}-
1166-
1167/*!-
1168 \fn GLuint QOpenGLFramebufferObject::takeTexture()-
1169-
1170 Returns the texture id for the texture attached to this framebuffer-
1171 object. The ownership of the texture is transferred to the caller.-
1172-
1173 If the framebuffer object is currently bound, an implicit release()-
1174 will be done. During the next call to bind() a new texture will be-
1175 created.-
1176-
1177 If a multisample framebuffer object is used, then there is no-
1178 texture and the return value from this function will be invalid.-
1179 Similarly, incomplete framebuffer objects will also return 0.-
1180-
1181 \since 5.3-
1182-
1183 \sa texture(), bind(), release()-
1184 */-
1185GLuint QOpenGLFramebufferObject::takeTexture()-
1186{-
1187 return takeTexture(0);
never executed: return takeTexture(0);
0
1188}-
1189-
1190/*! \overload-
1191-
1192 Returns the texture id for the texture attached to the color attachment of-
1193 index \a colorAttachmentIndex of this framebuffer object. The ownership of-
1194 the texture is transferred to the caller.-
1195-
1196 When \a colorAttachmentIndex is \c 0, the behavior is identical to the-
1197 parameter-less variant of this function.-
1198-
1199 If the framebuffer object is currently bound, an implicit release()-
1200 will be done. During the next call to bind() a new texture will be-
1201 created.-
1202-
1203 If a multisample framebuffer object is used, then there is no-
1204 texture and the return value from this function will be invalid.-
1205 Similarly, incomplete framebuffer objects will also return 0.-
1206-
1207 \since 5.6-
1208 */-
1209GLuint QOpenGLFramebufferObject::takeTexture(int colorAttachmentIndex)-
1210{-
1211 Q_D(QOpenGLFramebufferObject);-
1212 GLuint id = 0;-
1213 if (isValid() && d->format.samples() == 0 && d->colorAttachments.count() > colorAttachmentIndex) {
isValid()Description
TRUEnever evaluated
FALSEnever evaluated
d->format.samples() == 0Description
TRUEnever evaluated
FALSEnever evaluated
d->colorAttach...ttachmentIndexDescription
TRUEnever evaluated
FALSEnever evaluated
0
1214 QOpenGLContext *current = QOpenGLContext::currentContext();-
1215 if (current && current->shareGroup() == d->fbo_guard->group() && isBound())
currentDescription
TRUEnever evaluated
FALSEnever evaluated
current->share...guard->group()Description
TRUEnever evaluated
FALSEnever evaluated
isBound()Description
TRUEnever evaluated
FALSEnever evaluated
0
1216 release();
never executed: release();
0
1217 id = d->colorAttachments[colorAttachmentIndex].guard ? d->colorAttachments[colorAttachmentIndex].guard->id() : 0;
d->colorAttach...ntIndex].guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
1218 // Do not call free() on texture_guard, just null it out.-
1219 // This way the texture will not be deleted when the guard is destroyed.-
1220 d->colorAttachments[colorAttachmentIndex].guard = 0;-
1221 }
never executed: end of block
0
1222 return id;
never executed: return id;
0
1223}-
1224-
1225/*!-
1226 \return the size of the color and depth/stencil attachments attached to-
1227 this framebuffer object.-
1228*/-
1229QSize QOpenGLFramebufferObject::size() const-
1230{-
1231 Q_D(const QOpenGLFramebufferObject);-
1232 return d->dsSize;
never executed: return d->dsSize;
0
1233}-
1234-
1235/*!-
1236 \return the sizes of all color attachments attached to this framebuffer-
1237 object.-
1238-
1239 \since 5.6-
1240*/-
1241QVector<QSize> QOpenGLFramebufferObject::sizes() const-
1242{-
1243 Q_D(const QOpenGLFramebufferObject);-
1244 QVector<QSize> sz;-
1245 sz.reserve(d->colorAttachments.size());-
1246 foreach (const QOpenGLFramebufferObjectPrivate::ColorAttachment &color, d->colorAttachments)-
1247 sz.append(color.size);
never executed: sz.append(color.size);
0
1248 return sz;
never executed: return sz;
0
1249}-
1250-
1251/*!-
1252 \fn int QOpenGLFramebufferObject::width() const-
1253-
1254 Returns the width of the framebuffer object attachments.-
1255*/-
1256-
1257/*!-
1258 \fn int QOpenGLFramebufferObject::height() const-
1259-
1260 Returns the height of the framebuffer object attachments.-
1261*/-
1262-
1263/*!-
1264 Returns the format of this framebuffer object.-
1265*/-
1266QOpenGLFramebufferObjectFormat QOpenGLFramebufferObject::format() const-
1267{-
1268 Q_D(const QOpenGLFramebufferObject);-
1269 return d->format;
never executed: return d->format;
0
1270}-
1271-
1272static inline QImage qt_gl_read_framebuffer_rgba8(const QSize &size, bool include_alpha, QOpenGLContext *context)-
1273{-
1274 QOpenGLFunctions *funcs = context->functions();-
1275 const int w = size.width();-
1276 const int h = size.height();-
1277 bool isOpenGL12orBetter = !context->isOpenGLES() && (context->format().majorVersion() >= 2 || context->format().minorVersion() >= 2);
!context->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
context->forma...Version() >= 2Description
TRUEnever evaluated
FALSEnever evaluated
context->forma...Version() >= 2Description
TRUEnever evaluated
FALSEnever evaluated
0
1278 if (isOpenGL12orBetter) {
isOpenGL12orBetterDescription
TRUEnever evaluated
FALSEnever evaluated
0
1279 QImage img(size, include_alpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);-
1280 funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, img.bits());-
1281 return img;
never executed: return img;
0
1282 }-
1283-
1284#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN-
1285 // Without GL_UNSIGNED_INT_8_8_8_8_REV, GL_BGRA only makes sense on little endian.-
1286 const bool has_bgra_ext = context->isOpenGLES()
context->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
1287 ? context->hasExtension(QByteArrayLiteral("GL_EXT_read_format_bgra"))
never executed: return ba;
0
1288 : context->hasExtension(QByteArrayLiteral("GL_EXT_bgra"));
never executed: return ba;
0
1289-
1290#ifndef Q_OS_IOS-
1291 const char *renderer = reinterpret_cast<const char *>(funcs->glGetString(GL_RENDERER));-
1292 const char *ver = reinterpret_cast<const char *>(funcs->glGetString(GL_VERSION));-
1293-
1294 // Blacklist GPU chipsets that have problems with their BGRA support.-
1295 const bool blackListed = (qstrcmp(renderer, "PowerVR Rogue G6200") == 0
qstrcmp(render...e G6200") == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1296 && ::strstr(ver, "1.3") != 0) ||
::strstr(ver, "1.3") != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1297 (qstrcmp(renderer, "Mali-T760") == 0
qstrcmp(render...li-T760") == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1298 && ::strstr(ver, "3.1") != 0) ||
::strstr(ver, "3.1") != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1299 (qstrcmp(renderer, "Mali-T720") == 0
qstrcmp(render...li-T720") == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1300 && ::strstr(ver, "3.1") != 0) ||
::strstr(ver, "3.1") != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1301 qstrcmp(renderer, "PowerVR SGX 554") == 0;
qstrcmp(render...SGX 554") == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1302#else-
1303 const bool blackListed = true;-
1304#endif-
1305 const bool supports_bgra = has_bgra_ext && !blackListed;
has_bgra_extDescription
TRUEnever evaluated
FALSEnever evaluated
!blackListedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1306-
1307 if (supports_bgra) {
supports_bgraDescription
TRUEnever evaluated
FALSEnever evaluated
0
1308 QImage img(size, include_alpha ? QImage::Format_ARGB32_Premultiplied : QImage::Format_RGB32);-
1309 funcs->glReadPixels(0, 0, w, h, GL_BGRA, GL_UNSIGNED_BYTE, img.bits());-
1310 return img;
never executed: return img;
0
1311 }-
1312#endif-
1313 QImage rgbaImage(size, include_alpha ? QImage::Format_RGBA8888_Premultiplied : QImage::Format_RGBX8888);-
1314 funcs->glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, rgbaImage.bits());-
1315 return rgbaImage;
never executed: return rgbaImage;
0
1316}-
1317-
1318static inline QImage qt_gl_read_framebuffer_rgb10a2(const QSize &size, bool include_alpha, QOpenGLContext *context)-
1319{-
1320 // We assume OpenGL 1.2+ or ES 3.0+ here.-
1321 QImage img(size, include_alpha ? QImage::Format_A2BGR30_Premultiplied : QImage::Format_BGR30);-
1322 context->functions()->glReadPixels(0, 0, size.width(), size.height(), GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, img.bits());-
1323 return img;
never executed: return img;
0
1324}-
1325-
1326static QImage qt_gl_read_framebuffer(const QSize &size, GLenum internal_format, bool include_alpha, bool flip)-
1327{-
1328 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
1329 QOpenGLFunctions *funcs = ctx->functions();-
1330 while (funcs->glGetError());
never executed: ;
funcs->glGetError()Description
TRUEnever evaluated
FALSEnever evaluated
0
1331-
1332 switch (internal_format) {-
1333 case GL_RGB:
never executed: case 0x1907:
0
1334 case GL_RGB8:
never executed: case 0x8051:
0
1335 return qt_gl_read_framebuffer_rgba8(size, false, ctx).mirrored(false, flip);
never executed: return qt_gl_read_framebuffer_rgba8(size, false, ctx).mirrored(false, flip);
0
1336 case GL_RGB10:
never executed: case 0x8052:
0
1337 return qt_gl_read_framebuffer_rgb10a2(size, false, ctx).mirrored(false, flip);
never executed: return qt_gl_read_framebuffer_rgb10a2(size, false, ctx).mirrored(false, flip);
0
1338 case GL_RGB10_A2:
never executed: case 0x8059:
0
1339 return qt_gl_read_framebuffer_rgb10a2(size, include_alpha, ctx).mirrored(false, flip);
never executed: return qt_gl_read_framebuffer_rgb10a2(size, include_alpha, ctx).mirrored(false, flip);
0
1340 case GL_RGBA:
never executed: case 0x1908:
0
1341 case GL_RGBA8:
never executed: case 0x8058:
0
1342 default:
never executed: default:
0
1343 return qt_gl_read_framebuffer_rgba8(size, include_alpha, ctx).mirrored(false, flip);
never executed: return qt_gl_read_framebuffer_rgba8(size, include_alpha, ctx).mirrored(false, flip);
0
1344 }-
1345-
1346 Q_UNREACHABLE();
dead code: do { ((!(false)) ? qt_assert_x("Q_UNREACHABLE()", "Q_UNREACHABLE was reached",__FILE__,1346) : qt_noop()); __builtin_unreachable(); } while (0);
-
1347 return QImage();
dead code: return QImage();
-
1348}-
1349-
1350Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha)-
1351{-
1352 return qt_gl_read_framebuffer(size, alpha_format ? GL_RGBA : GL_RGB, include_alpha, true);
never executed: return qt_gl_read_framebuffer(size, alpha_format ? 0x1908 : 0x1907, include_alpha, true);
0
1353}-
1354-
1355/*!-
1356 \fn QImage QOpenGLFramebufferObject::toImage(bool flipped) const-
1357-
1358 Returns the contents of this framebuffer object as a QImage.-
1359-
1360 If \a flipped is true the image is flipped from OpenGL coordinates to raster coordinates.-
1361 If used together with QOpenGLPaintDevice, \a flipped should be the opposite of the value-
1362 of QOpenGLPaintDevice::paintFlipped().-
1363-
1364 The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used-
1365 only when internalTextureFormat() is set to \c GL_RGB.-
1366-
1367 If the rendering in the framebuffer was not done with premultiplied alpha in mind,-
1368 create a wrapper QImage with a non-premultiplied format. This is necessary before-
1369 performing operations like QImage::save() because otherwise the image data would get-
1370 unpremultiplied, even though it was not premultiplied in the first place. To create-
1371 such a wrapper without performing a copy of the pixel data, do the following:-
1372-
1373 \code-
1374 QImage fboImage(fbo.toImage());-
1375 QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);-
1376 \endcode-
1377-
1378 Since Qt 5.2 the function will fall back to premultiplied RGBA8888 or RGBx8888 when-
1379 reading to (A)RGB32 is not supported. Since 5.4 an A2BGR30 image is returned if the-
1380 internal format is RGB10_A2.-
1381-
1382 For multisampled framebuffer objects the samples are resolved using the-
1383 \c{GL_EXT_framebuffer_blit} extension. If the extension is not available, the contents-
1384 of the returned image is undefined.-
1385-
1386 For singlesampled framebuffers the contents is retrieved via \c glReadPixels. This is-
1387 a potentially expensive and inefficient operation. Therefore it is recommended that-
1388 this function is used as seldom as possible.-
1389-
1390 \sa QOpenGLPaintDevice::paintFlipped()-
1391*/-
1392-
1393QImage QOpenGLFramebufferObject::toImage(bool flipped) const-
1394{-
1395 return toImage(flipped, 0);
never executed: return toImage(flipped, 0);
0
1396}-
1397-
1398/*!-
1399 \fn QImage QOpenGLFramebufferObject::toImage() const-
1400 \overload-
1401-
1402 Returns the contents of this framebuffer object as a QImage. This method flips-
1403 the image from OpenGL coordinates to raster coordinates.-
1404*/-
1405// ### Qt 6: Remove this method and make it a default argument instead.-
1406QImage QOpenGLFramebufferObject::toImage() const-
1407{-
1408 return toImage(true, 0);
never executed: return toImage(true, 0);
0
1409}-
1410-
1411/*! \overload-
1412-
1413 Returns the contents of the color attachment of index \a-
1414 colorAttachmentIndex of this framebuffer object as a QImage. This method-
1415 flips the image from OpenGL coordinates to raster coordinates when \a-
1416 flipped is set to \c true.-
1417-
1418 \note This overload is only fully functional when multiple render targets are-
1419 supported by the OpenGL implementation. When that is not the case, only one-
1420 color attachment will be set up.-
1421-
1422 \since 5.6-
1423*/-
1424QImage QOpenGLFramebufferObject::toImage(bool flipped, int colorAttachmentIndex) const-
1425{-
1426 Q_D(const QOpenGLFramebufferObject);-
1427 if (!d->valid)
!d->validDescription
TRUEnever evaluated
FALSEnever evaluated
0
1428 return QImage();
never executed: return QImage();
0
1429-
1430 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
1431 if (!ctx) {
!ctxDescription
TRUEnever evaluated
FALSEnever evaluated
0
1432 qWarning("QOpenGLFramebufferObject::toImage() called without a current context");-
1433 return QImage();
never executed: return QImage();
0
1434 }-
1435-
1436 if (d->colorAttachments.count() <= colorAttachmentIndex) {
d->colorAttach...ttachmentIndexDescription
TRUEnever evaluated
FALSEnever evaluated
0
1437 qWarning("QOpenGLFramebufferObject::toImage() called for missing color attachment");-
1438 return QImage();
never executed: return QImage();
0
1439 }-
1440-
1441 GLuint prevFbo = 0;-
1442 ctx->functions()->glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &prevFbo);-
1443-
1444 if (prevFbo != d->fbo())
prevFbo != d->fbo()Description
TRUEnever evaluated
FALSEnever evaluated
0
1445 const_cast<QOpenGLFramebufferObject *>(this)->bind();
never executed: const_cast<QOpenGLFramebufferObject *>(this)->bind();
0
1446-
1447 QImage image;-
1448 QOpenGLExtraFunctions *extraFuncs = ctx->extraFunctions();-
1449 // qt_gl_read_framebuffer doesn't work on a multisample FBO-
1450 if (format().samples() != 0) {
format().samples() != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1451 QRect rect(QPoint(0, 0), size());-
1452 if (extraFuncs->hasOpenGLFeature(QOpenGLFunctions::MultipleRenderTargets)) {
extraFuncs->ha...RenderTargets)Description
TRUEnever evaluated
FALSEnever evaluated
0
1453 QOpenGLFramebufferObject temp(d->colorAttachments[colorAttachmentIndex].size, QOpenGLFramebufferObjectFormat());-
1454 blitFramebuffer(&temp, rect, const_cast<QOpenGLFramebufferObject *>(this), rect,-
1455 GL_COLOR_BUFFER_BIT, GL_NEAREST,-
1456 colorAttachmentIndex, 0);-
1457 image = temp.toImage(flipped);-
1458 } else {
never executed: end of block
0
1459 QOpenGLFramebufferObject temp(size(), QOpenGLFramebufferObjectFormat());-
1460 blitFramebuffer(&temp, rect, const_cast<QOpenGLFramebufferObject *>(this), rect);-
1461 image = temp.toImage(flipped);-
1462 }
never executed: end of block
0
1463 } else {-
1464 if (extraFuncs->hasOpenGLFeature(QOpenGLFunctions::MultipleRenderTargets)) {
extraFuncs->ha...RenderTargets)Description
TRUEnever evaluated
FALSEnever evaluated
0
1465 extraFuncs->glReadBuffer(GL_COLOR_ATTACHMENT0 + colorAttachmentIndex);-
1466 image = qt_gl_read_framebuffer(d->colorAttachments[colorAttachmentIndex].size,-
1467 d->colorAttachments[colorAttachmentIndex].internalFormat,-
1468 true, flipped);-
1469 extraFuncs->glReadBuffer(GL_COLOR_ATTACHMENT0);-
1470 } else {
never executed: end of block
0
1471 image = qt_gl_read_framebuffer(d->colorAttachments[0].size,-
1472 d->colorAttachments[0].internalFormat,-
1473 true, flipped);-
1474 }
never executed: end of block
0
1475 }-
1476-
1477 if (prevFbo != d->fbo())
prevFbo != d->fbo()Description
TRUEnever evaluated
FALSEnever evaluated
0
1478 ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, prevFbo);
never executed: ctx->functions()->glBindFramebuffer(0x8D40, prevFbo);
0
1479-
1480 return image;
never executed: return image;
0
1481}-
1482-
1483/*!-
1484 \fn bool QOpenGLFramebufferObject::bindDefault()-
1485-
1486 Switches rendering back to the default, windowing system provided-
1487 framebuffer.-
1488 Returns \c true upon success, false otherwise.-
1489-
1490 \sa bind(), release()-
1491*/-
1492bool QOpenGLFramebufferObject::bindDefault()-
1493{-
1494 QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());-
1495-
1496 if (ctx) {
ctxDescription
TRUEnever evaluated
FALSEnever evaluated
0
1497 ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, ctx->defaultFramebufferObject());-
1498 QOpenGLContextPrivate::get(ctx)->qgl_current_fbo_invalid = true;-
1499 QOpenGLContextPrivate::get(ctx)->qgl_current_fbo = Q_NULLPTR;-
1500 }
never executed: end of block
0
1501#ifdef QT_DEBUG-
1502 else-
1503 qWarning("QOpenGLFramebufferObject::bindDefault() called without current context.");
never executed: QMessageLogger(__FILE__, 1503, __PRETTY_FUNCTION__).warning("QOpenGLFramebufferObject::bindDefault() called without current context.");
0
1504#endif-
1505-
1506 return ctx != 0;
never executed: return ctx != 0;
0
1507}-
1508-
1509/*!-
1510 \fn bool QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()-
1511-
1512 Returns \c true if the OpenGL \c{GL_EXT_framebuffer_object} extension-
1513 is present on this system; otherwise returns \c false.-
1514*/-
1515bool QOpenGLFramebufferObject::hasOpenGLFramebufferObjects()-
1516{-
1517 return QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(QOpenGLFunctions::Framebuffers);
never executed: return QOpenGLContext::currentContext()->functions()->hasOpenGLFeature(QOpenGLFunctions::Framebuffers);
0
1518}-
1519-
1520/*!-
1521 \fn GLuint QOpenGLFramebufferObject::handle() const-
1522-
1523 Returns the OpenGL framebuffer object handle for this framebuffer-
1524 object (returned by the \c{glGenFrameBuffersEXT()} function). This-
1525 handle can be used to attach new images or buffers to the-
1526 framebuffer. The user is responsible for cleaning up and-
1527 destroying these objects.-
1528*/-
1529GLuint QOpenGLFramebufferObject::handle() const-
1530{-
1531 Q_D(const QOpenGLFramebufferObject);-
1532 return d->fbo();
never executed: return d->fbo();
0
1533}-
1534-
1535/*!-
1536 Returns the status of the depth and stencil buffers attached to-
1537 this framebuffer object.-
1538*/-
1539-
1540QOpenGLFramebufferObject::Attachment QOpenGLFramebufferObject::attachment() const-
1541{-
1542 Q_D(const QOpenGLFramebufferObject);-
1543 if (d->valid)
d->validDescription
TRUEnever evaluated
FALSEnever evaluated
0
1544 return d->fbo_attachment;
never executed: return d->fbo_attachment;
0
1545 return NoAttachment;
never executed: return NoAttachment;
0
1546}-
1547-
1548/*!-
1549 Sets the attachments of the framebuffer object to \a attachment.-
1550-
1551 This can be used to free or reattach the depth and stencil buffer-
1552 attachments as needed.-
1553-
1554 \note This function alters the current framebuffer binding.-
1555 */-
1556void QOpenGLFramebufferObject::setAttachment(QOpenGLFramebufferObject::Attachment attachment)-
1557{-
1558 Q_D(QOpenGLFramebufferObject);-
1559 if (attachment == d->fbo_attachment || !isValid())
attachment == ...fbo_attachmentDescription
TRUEnever evaluated
FALSEnever evaluated
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1560 return;
never executed: return;
0
1561 QOpenGLContext *current = QOpenGLContext::currentContext();-
1562 if (!current)
!currentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1563 return;
never executed: return;
0
1564#ifdef QT_DEBUG-
1565 if (current->shareGroup() != d->fbo_guard->group())
current->share...guard->group()Description
TRUEnever evaluated
FALSEnever evaluated
0
1566 qWarning("QOpenGLFramebufferObject::setAttachment() called from incompatible context");
never executed: QMessageLogger(__FILE__, 1566, __PRETTY_FUNCTION__).warning("QOpenGLFramebufferObject::setAttachment() called from incompatible context");
0
1567#endif-
1568 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());-
1569 QOpenGLContextPrivate::get(current)->qgl_current_fbo_invalid = true;-
1570 d->initDepthStencilAttachments(current, attachment);-
1571}
never executed: end of block
0
1572-
1573/*!-
1574 Returns \c true if the framebuffer object is currently bound to the current context,-
1575 otherwise false is returned.-
1576*/-
1577bool QOpenGLFramebufferObject::isBound() const-
1578{-
1579 Q_D(const QOpenGLFramebufferObject);-
1580 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
1581 if (!ctx)
!ctxDescription
TRUEnever evaluated
FALSEnever evaluated
0
1582 return false;
never executed: return false;
0
1583 GLint fbo = 0;-
1584 ctx->functions()->glGetIntegerv(GL_FRAMEBUFFER_BINDING, &fbo);-
1585 return GLuint(fbo) == d->fbo();
never executed: return GLuint(fbo) == d->fbo();
0
1586}-
1587-
1588/*!-
1589 \fn bool QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()-
1590-
1591 Returns \c true if the OpenGL \c{GL_EXT_framebuffer_blit} extension-
1592 is present on this system; otherwise returns \c false.-
1593-
1594 \sa blitFramebuffer()-
1595*/-
1596bool QOpenGLFramebufferObject::hasOpenGLFramebufferBlit()-
1597{-
1598 return QOpenGLExtensions(QOpenGLContext::currentContext()).hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
never executed: return QOpenGLExtensions(QOpenGLContext::currentContext()).hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
0
1599}-
1600-
1601-
1602/*!-
1603 \overload-
1604-
1605 Convenience overload to blit between two framebuffer objects.-
1606*/-
1607void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target,-
1608 QOpenGLFramebufferObject *source,-
1609 GLbitfield buffers, GLenum filter)-
1610{-
1611 if (!target && !source)
!targetDescription
TRUEnever evaluated
FALSEnever evaluated
!sourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1612 return;
never executed: return;
0
1613-
1614 QSize targetSize;-
1615 QSize sourceSize;-
1616-
1617 if (target)
targetDescription
TRUEnever evaluated
FALSEnever evaluated
0
1618 targetSize = target->size();
never executed: targetSize = target->size();
0
1619 if (source)
sourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1620 sourceSize = source->size();
never executed: sourceSize = source->size();
0
1621-
1622 if (targetSize.isEmpty())
targetSize.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1623 targetSize = sourceSize;
never executed: targetSize = sourceSize;
0
1624 else if (sourceSize.isEmpty())
sourceSize.isEmpty()Description
TRUEnever evaluated
FALSEnever evaluated
0
1625 sourceSize = targetSize;
never executed: sourceSize = targetSize;
0
1626-
1627 blitFramebuffer(target, QRect(QPoint(0, 0), targetSize),-
1628 source, QRect(QPoint(0, 0), sourceSize),-
1629 buffers, filter);-
1630}
never executed: end of block
0
1631-
1632/*! \overload-
1633 *-
1634 Convenience overload to blit between two framebuffer objects.-
1635*/-
1636void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target, const QRect &targetRect,-
1637 QOpenGLFramebufferObject *source, const QRect &sourceRect,-
1638 GLbitfield buffers,-
1639 GLenum filter)-
1640{-
1641 blitFramebuffer(target, targetRect, source, sourceRect, buffers, filter, 0, 0);-
1642}
never executed: end of block
0
1643-
1644/*!-
1645 Blits from the \a sourceRect rectangle in the \a source framebuffer-
1646 object to the \a targetRect rectangle in the \a target framebuffer object.-
1647-
1648 If \a source or \a target is 0, the default framebuffer will be used-
1649 instead of a framebuffer object as source or target respectively.-
1650-
1651 This function will have no effect unless hasOpenGLFramebufferBlit() returns-
1652 true.-
1653-
1654 The \a buffers parameter should be a mask consisting of any combination of-
1655 \c GL_COLOR_BUFFER_BIT, \c GL_DEPTH_BUFFER_BIT, and-
1656 \c GL_STENCIL_BUFFER_BIT. Any buffer type that is not present both-
1657 in the source and target buffers is ignored.-
1658-
1659 The \a sourceRect and \a targetRect rectangles may have different sizes;-
1660 in this case \a buffers should not contain \c GL_DEPTH_BUFFER_BIT or-
1661 \c GL_STENCIL_BUFFER_BIT. The \a filter parameter should be set to-
1662 \c GL_LINEAR or \c GL_NEAREST, and specifies whether linear or nearest-
1663 interpolation should be used when scaling is performed.-
1664-
1665 If \a source equals \a target a copy is performed within the same buffer.-
1666 Results are undefined if the source and target rectangles overlap and-
1667 have different sizes. The sizes must also be the same if any of the-
1668 framebuffer objects are multisample framebuffers.-
1669-
1670 \note The scissor test will restrict the blit area if enabled.-
1671-
1672 When multiple render targets are in use, \a readColorAttachmentIndex and \a-
1673 drawColorAttachmentIndex specify the index of the color attachments in the-
1674 source and destination framebuffers.-
1675-
1676 \sa hasOpenGLFramebufferBlit()-
1677*/-
1678void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target, const QRect &targetRect,-
1679 QOpenGLFramebufferObject *source, const QRect &sourceRect,-
1680 GLbitfield buffers,-
1681 GLenum filter,-
1682 int readColorAttachmentIndex,-
1683 int drawColorAttachmentIndex)-
1684{-
1685 QOpenGLContext *ctx = QOpenGLContext::currentContext();-
1686 if (!ctx)
!ctxDescription
TRUEnever evaluated
FALSEnever evaluated
0
1687 return;
never executed: return;
0
1688-
1689 QOpenGLExtensions extensions(ctx);-
1690 if (!extensions.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit))
!extensions.ha...amebufferBlit)Description
TRUEnever evaluated
FALSEnever evaluated
0
1691 return;
never executed: return;
0
1692-
1693 GLuint prevFbo = 0;-
1694 ctx->functions()->glGetIntegerv(GL_FRAMEBUFFER_BINDING, (GLint *) &prevFbo);-
1695-
1696 const int sx0 = sourceRect.left();-
1697 const int sx1 = sourceRect.left() + sourceRect.width();-
1698 const int sy0 = sourceRect.top();-
1699 const int sy1 = sourceRect.top() + sourceRect.height();-
1700-
1701 const int tx0 = targetRect.left();-
1702 const int tx1 = targetRect.left() + targetRect.width();-
1703 const int ty0 = targetRect.top();-
1704 const int ty1 = targetRect.top() + targetRect.height();-
1705-
1706 const GLuint defaultFboId = ctx->defaultFramebufferObject();-
1707-
1708 extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : defaultFboId);-
1709 extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : defaultFboId);-
1710-
1711 if (extensions.hasOpenGLFeature(QOpenGLFunctions::MultipleRenderTargets)) {
extensions.has...RenderTargets)Description
TRUEnever evaluated
FALSEnever evaluated
0
1712 extensions.glReadBuffer(GL_COLOR_ATTACHMENT0 + readColorAttachmentIndex);-
1713 if (target) {
targetDescription
TRUEnever evaluated
FALSEnever evaluated
0
1714 GLenum drawBuf = GL_COLOR_ATTACHMENT0 + drawColorAttachmentIndex;-
1715 extensions.glDrawBuffers(1, &drawBuf);-
1716 }
never executed: end of block
0
1717 }
never executed: end of block
0
1718-
1719 extensions.glBlitFramebuffer(sx0, sy0, sx1, sy1,-
1720 tx0, ty0, tx1, ty1,-
1721 buffers, filter);-
1722-
1723 if (extensions.hasOpenGLFeature(QOpenGLFunctions::MultipleRenderTargets))
extensions.has...RenderTargets)Description
TRUEnever evaluated
FALSEnever evaluated
0
1724 extensions.glReadBuffer(GL_COLOR_ATTACHMENT0);
never executed: extensions.glReadBuffer(0x8CE0);
0
1725-
1726 ctx->functions()->glBindFramebuffer(GL_FRAMEBUFFER, prevFbo); // sets both READ and DRAW-
1727}
never executed: end of block
0
1728-
1729QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9