qglframebufferobject.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/opengl/qglframebufferobject.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 QtOpenGL 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 "qglframebufferobject.h"-
35#include "qglframebufferobject_p.h"-
36-
37#include <qdebug.h>-
38#include <private/qgl_p.h>-
39#include <private/qfont_p.h>-
40#include "gl2paintengineex/qpaintengineex_opengl2_p.h"-
41-
42#include <qlibrary.h>-
43#include <qimage.h>-
44#include <qwindow.h>-
45-
46QT_BEGIN_NAMESPACE-
47-
48extern QImage qt_gl_read_frame_buffer(const QSize&, bool, bool);-
49-
50#define QGL_FUNC_CONTEXT const QGLContext *ctx = QGLContext::currentContext();-
51#define QGL_FUNCP_CONTEXT const QGLContext *ctx = QGLContext::currentContext();-
52-
53#ifndef QT_NO_DEBUG-
54#define QT_RESET_GLERROR() \-
55{ \-
56 while (QOpenGLContext::currentContext()->functions()->glGetError() != GL_NO_ERROR) {} \-
57}-
58#define QT_CHECK_GLERROR() \-
59{ \-
60 GLenum err = QOpenGLContext::currentContext()->functions()->glGetError(); \-
61 if (err != GL_NO_ERROR) { \-
62 qDebug("[%s line %d] GL Error: %d", \-
63 __FILE__, __LINE__, (int)err); \-
64 } \-
65}-
66#else-
67#define QT_RESET_GLERROR() {}-
68#define QT_CHECK_GLERROR() {}-
69#endif-
70-
71// ####TODO Properly #ifdef this class to use #define symbols actually defined-
72// by OpenGL/ES includes-
73#ifndef GL_MAX_SAMPLES-
74#define GL_MAX_SAMPLES 0x8D57-
75#endif-
76-
77#ifndef GL_RENDERBUFFER_SAMPLES-
78#define GL_RENDERBUFFER_SAMPLES 0x8CAB-
79#endif-
80-
81#ifndef GL_DEPTH24_STENCIL8-
82#define GL_DEPTH24_STENCIL8 0x88F0-
83#endif-
84-
85#ifndef GL_DEPTH_COMPONENT24-
86#define GL_DEPTH_COMPONENT24 0x81A6-
87#endif-
88-
89#ifndef GL_DEPTH_COMPONENT24_OES-
90#define GL_DEPTH_COMPONENT24_OES 0x81A6-
91#endif-
92-
93#ifndef GL_READ_FRAMEBUFFER-
94#define GL_READ_FRAMEBUFFER 0x8CA8-
95#endif-
96-
97#ifndef GL_DRAW_FRAMEBUFFER-
98#define GL_DRAW_FRAMEBUFFER 0x8CA9-
99#endif-
100-
101/*!-
102 \class QGLFramebufferObjectFormat-
103 \inmodule QtOpenGL-
104 \brief The QGLFramebufferObjectFormat class specifies the format of an OpenGL-
105 framebuffer object.-
106-
107 \since 4.6-
108 \obsolete-
109-
110 \ingroup painting-3D-
111-
112 A framebuffer object has several characteristics:-
113 \list-
114 \li \l{setSamples()}{Number of samples per pixels.}-
115 \li \l{setAttachment()}{Depth and/or stencil attachments.}-
116 \li \l{setTextureTarget()}{Texture target.}-
117 \li \l{setInternalTextureFormat()}{Internal texture format.}-
118 \endlist-
119-
120 Note that the desired attachments or number of samples per pixels might not-
121 be supported by the hardware driver. Call QGLFramebufferObject::format()-
122 after creating a QGLFramebufferObject to find the exact format that was-
123 used to create the frame buffer object.-
124-
125 \note This class has been deprecated in favor of QOpenGLFramebufferObjectFormat.-
126-
127 \sa QGLFramebufferObject-
128*/-
129-
130/*!-
131 \internal-
132*/-
133void QGLFramebufferObjectFormat::detach()-
134{-
135 if (d->ref.load() != 1) {
d->ref.load() != 1Description
TRUEnever evaluated
FALSEnever evaluated
0
136 QGLFramebufferObjectFormatPrivate *newd-
137 = new QGLFramebufferObjectFormatPrivate(d);-
138 if (!d->ref.deref())
!d->ref.deref()Description
TRUEnever evaluated
FALSEnever evaluated
0
139 delete d;
never executed: delete d;
0
140 d = newd;-
141 }
never executed: end of block
0
142}
never executed: end of block
0
143-
144/*!-
145 Creates a QGLFramebufferObjectFormat object for specifying-
146 the format of an OpenGL framebuffer object.-
147-
148 By default the format specifies a non-multisample framebuffer object with no-
149 attachments, texture target \c GL_TEXTURE_2D, and internal format \c GL_RGBA8.-
150 On OpenGL/ES systems, the default internal format is \c GL_RGBA.-
151-
152 \sa samples(), attachment(), internalTextureFormat()-
153*/-
154-
155QGLFramebufferObjectFormat::QGLFramebufferObjectFormat()-
156{-
157 d = new QGLFramebufferObjectFormatPrivate;-
158}
never executed: end of block
0
159-
160/*!-
161 Constructs a copy of \a other.-
162*/-
163-
164QGLFramebufferObjectFormat::QGLFramebufferObjectFormat(const QGLFramebufferObjectFormat &other)-
165{-
166 d = other.d;-
167 d->ref.ref();-
168}
never executed: end of block
0
169-
170/*!-
171 Assigns \a other to this object.-
172*/-
173-
174QGLFramebufferObjectFormat &QGLFramebufferObjectFormat::operator=(const QGLFramebufferObjectFormat &other)-
175{-
176 if (d != other.d) {
d != other.dDescription
TRUEnever evaluated
FALSEnever evaluated
0
177 other.d->ref.ref();-
178 if (!d->ref.deref())
!d->ref.deref()Description
TRUEnever evaluated
FALSEnever evaluated
0
179 delete d;
never executed: delete d;
0
180 d = other.d;-
181 }
never executed: end of block
0
182 return *this;
never executed: return *this;
0
183}-
184-
185/*!-
186 Destroys the QGLFramebufferObjectFormat.-
187*/-
188QGLFramebufferObjectFormat::~QGLFramebufferObjectFormat()-
189{-
190 if (!d->ref.deref())
!d->ref.deref()Description
TRUEnever evaluated
FALSEnever evaluated
0
191 delete d;
never executed: delete d;
0
192}
never executed: end of block
0
193-
194/*!-
195 Sets the number of samples per pixel for a multisample framebuffer object-
196 to \a samples. The default sample count of 0 represents a regular-
197 non-multisample framebuffer object.-
198-
199 If the desired amount of samples per pixel is not supported by the hardware-
200 then the maximum number of samples per pixel will be used. Note that-
201 multisample framebuffer objects can not be bound as textures. Also, the-
202 \c{GL_EXT_framebuffer_multisample} extension is required to create a-
203 framebuffer with more than one sample per pixel.-
204-
205 \sa samples()-
206*/-
207void QGLFramebufferObjectFormat::setSamples(int samples)-
208{-
209 detach();-
210 d->samples = samples;-
211}
never executed: end of block
0
212-
213/*!-
214 Returns the number of samples per pixel if a framebuffer object-
215 is a multisample framebuffer object. Otherwise, returns 0.-
216 The default value is 0.-
217-
218 \sa setSamples()-
219*/-
220int QGLFramebufferObjectFormat::samples() const-
221{-
222 return d->samples;
never executed: return d->samples;
0
223}-
224-
225/*!-
226 \since 4.8-
227-
228 Enables mipmapping if \a enabled is true; otherwise disables it.-
229-
230 Mipmapping is disabled by default.-
231-
232 If mipmapping is enabled, additional memory will be allocated for-
233 the mipmap levels. The mipmap levels can be updated by binding the-
234 texture and calling glGenerateMipmap(). Mipmapping cannot be enabled-
235 for multisampled framebuffer objects.-
236-
237 \sa mipmap(), QGLFramebufferObject::texture()-
238*/-
239void QGLFramebufferObjectFormat::setMipmap(bool enabled)-
240{-
241 detach();-
242 d->mipmap = enabled;-
243}
never executed: end of block
0
244-
245/*!-
246 \since 4.8-
247-
248 Returns \c true if mipmapping is enabled.-
249-
250 \sa setMipmap()-
251*/-
252bool QGLFramebufferObjectFormat::mipmap() const-
253{-
254 return d->mipmap;
never executed: return d->mipmap;
0
255}-
256-
257/*!-
258 Sets the attachment configuration of a framebuffer object to \a attachment.-
259-
260 \sa attachment()-
261*/-
262void QGLFramebufferObjectFormat::setAttachment(QGLFramebufferObject::Attachment attachment)-
263{-
264 detach();-
265 d->attachment = attachment;-
266}
never executed: end of block
0
267-
268/*!-
269 Returns the configuration of the depth and stencil buffers attached to-
270 a framebuffer object. The default is QGLFramebufferObject::NoAttachment.-
271-
272 \sa setAttachment()-
273*/-
274QGLFramebufferObject::Attachment QGLFramebufferObjectFormat::attachment() const-
275{-
276 return d->attachment;
never executed: return d->attachment;
0
277}-
278-
279/*!-
280 Sets the texture target of the texture attached to a framebuffer object to-
281 \a target. Ignored for multisample framebuffer objects.-
282-
283 \sa textureTarget(), samples()-
284*/-
285void QGLFramebufferObjectFormat::setTextureTarget(GLenum target)-
286{-
287 detach();-
288 d->target = target;-
289}
never executed: end of block
0
290-
291/*!-
292 Returns the texture target of the texture attached to a framebuffer object.-
293 Ignored for multisample framebuffer objects. The default is-
294 \c GL_TEXTURE_2D.-
295-
296 \sa setTextureTarget(), samples()-
297*/-
298GLenum QGLFramebufferObjectFormat::textureTarget() const-
299{-
300 return d->target;
never executed: return d->target;
0
301}-
302-
303/*!-
304 Sets the internal format of a framebuffer object's texture or-
305 multisample framebuffer object's color buffer to-
306 \a internalTextureFormat.-
307-
308 \sa internalTextureFormat()-
309*/-
310void QGLFramebufferObjectFormat::setInternalTextureFormat(GLenum internalTextureFormat)-
311{-
312 detach();-
313 d->internal_format = internalTextureFormat;-
314}
never executed: end of block
0
315-
316/*!-
317 Returns the internal format of a framebuffer object's texture or-
318 multisample framebuffer object's color buffer. The default is-
319 \c GL_RGBA8 on desktop OpenGL systems, and \c GL_RGBA on-
320 OpenGL/ES systems.-
321-
322 \sa setInternalTextureFormat()-
323*/-
324GLenum QGLFramebufferObjectFormat::internalTextureFormat() const-
325{-
326 return d->internal_format;
never executed: return d->internal_format;
0
327}-
328-
329/*!-
330 Returns \c true if all the options of this framebuffer object format-
331 are the same as \a other; otherwise returns \c false.-
332*/-
333bool QGLFramebufferObjectFormat::operator==(const QGLFramebufferObjectFormat& other) const-
334{-
335 if (d == other.d)
d == other.dDescription
TRUEnever evaluated
FALSEnever evaluated
0
336 return true;
never executed: return true;
0
337 else-
338 return d->equals(other.d);
never executed: return d->equals(other.d);
0
339}-
340-
341/*!-
342 Returns \c false if all the options of this framebuffer object format-
343 are the same as \a other; otherwise returns \c true.-
344*/-
345bool QGLFramebufferObjectFormat::operator!=(const QGLFramebufferObjectFormat& other) const-
346{-
347 return !(*this == other);
never executed: return !(*this == other);
0
348}-
349-
350void QGLFBOGLPaintDevice::setFBO(QGLFramebufferObject* f,-
351 QGLFramebufferObject::Attachment attachment)-
352{-
353 fbo = f;-
354 m_thisFBO = fbo->d_func()->fbo(); // This shouldn't be needed-
355-
356 // The context that the fbo was created in may not have depth-
357 // and stencil buffers, but the fbo itself might.-
358 fboFormat = QGLContext::currentContext()->format();-
359 if (attachment == QGLFramebufferObject::CombinedDepthStencil) {
attachment == ...edDepthStencilDescription
TRUEnever evaluated
FALSEnever evaluated
0
360 fboFormat.setDepth(true);-
361 fboFormat.setStencil(true);-
362 } else if (attachment == QGLFramebufferObject::Depth) {
never executed: end of block
attachment == ...rObject::DepthDescription
TRUEnever evaluated
FALSEnever evaluated
0
363 fboFormat.setDepth(true);-
364 fboFormat.setStencil(false);-
365 } else {
never executed: end of block
0
366 fboFormat.setDepth(false);-
367 fboFormat.setStencil(false);-
368 }
never executed: end of block
0
369-
370 GLenum format = f->format().internalTextureFormat();-
371 reqAlpha = (format != GL_RGB
format != 0x1907Description
TRUEnever evaluated
FALSEnever evaluated
0
372#ifdef GL_RGB5-
373 && format != GL_RGB5
format != 0x8050Description
TRUEnever evaluated
FALSEnever evaluated
0
374#endif-
375#ifdef GL_RGB8-
376 && format != GL_RGB8
format != 0x8051Description
TRUEnever evaluated
FALSEnever evaluated
0
377#endif-
378 );-
379}
never executed: end of block
0
380-
381QGLContext *QGLFBOGLPaintDevice::context() const-
382{-
383 return const_cast<QGLContext *>(QGLContext::currentContext());
never executed: return const_cast<QGLContext *>(QGLContext::currentContext());
0
384}-
385-
386bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const-
387{-
388 QGL_FUNCP_CONTEXT;-
389 if (!ctx)
!ctxDescription
TRUEnever evaluated
FALSEnever evaluated
0
390 return false; // Context no longer exists.
never executed: return false;
0
391 GLenum status = ctx->contextHandle()->functions()->glCheckFramebufferStatus(GL_FRAMEBUFFER);-
392 switch(status) {-
393 case GL_NO_ERROR:
never executed: case 0:
0
394 case GL_FRAMEBUFFER_COMPLETE:
never executed: case 0x8CD5:
0
395 return true;
never executed: return true;
0
396 case GL_FRAMEBUFFER_UNSUPPORTED:
never executed: case 0x8CDD:
0
397 qDebug("QGLFramebufferObject: Unsupported framebuffer format.");-
398 break;
never executed: break;
0
399 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT:
never executed: case 0x8CD6:
0
400 qDebug("QGLFramebufferObject: Framebuffer incomplete attachment.");-
401 break;
never executed: break;
0
402 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT:
never executed: case 0x8CD7:
0
403 qDebug("QGLFramebufferObject: Framebuffer incomplete, missing attachment.");-
404 break;
never executed: break;
0
405#ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT-
406 case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT:-
407 qDebug("QGLFramebufferObject: Framebuffer incomplete, duplicate attachment.");-
408 break;-
409#endif-
410#ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS-
411 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS:-
412 qDebug("QGLFramebufferObject: Framebuffer incomplete, attached images must have same dimensions.");-
413 break;-
414#endif-
415#ifdef GL_FRAMEBUFFER_INCOMPLETE_FORMATS-
416 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS:-
417 qDebug("QGLFramebufferObject: Framebuffer incomplete, attached images must have same format.");-
418 break;-
419#endif-
420#ifdef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER-
421 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER:
never executed: case 0x8CDB:
0
422 qDebug("QGLFramebufferObject: Framebuffer incomplete, missing draw buffer.");-
423 break;
never executed: break;
0
424#endif-
425#ifdef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER-
426 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER:
never executed: case 0x8CDC:
0
427 qDebug("QGLFramebufferObject: Framebuffer incomplete, missing read buffer.");-
428 break;
never executed: break;
0
429#endif-
430#ifdef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE-
431 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE:
never executed: case 0x8D56:
0
432 qDebug("QGLFramebufferObject: Framebuffer incomplete, attachments must have same number of samples per pixel.");-
433 break;
never executed: break;
0
434#endif-
435 default:
never executed: default:
0
436 qDebug() <<"QGLFramebufferObject: An undefined error has occurred: "<< status;-
437 break;
never executed: break;
0
438 }-
439 return false;
never executed: return false;
0
440}-
441-
442namespace-
443{-
444 void freeFramebufferFunc(QGLContext *ctx, GLuint id)-
445 {-
446 Q_ASSERT(ctx);-
447 ctx->contextHandle()->functions()->glDeleteFramebuffers(1, &id);-
448 }
never executed: end of block
0
449-
450 void freeRenderbufferFunc(QGLContext *ctx, GLuint id)-
451 {-
452 Q_ASSERT(ctx);-
453 ctx->contextHandle()->functions()->glDeleteRenderbuffers(1, &id);-
454 }
never executed: end of block
0
455-
456 void freeTextureFunc(QGLContext *ctx, GLuint id)-
457 {-
458 Q_UNUSED(ctx);-
459 ctx->contextHandle()->functions()->glDeleteTextures(1, &id);-
460 }
never executed: end of block
0
461}-
462-
463void QGLFramebufferObjectPrivate::init(QGLFramebufferObject *q, const QSize &sz,-
464 QGLFramebufferObject::Attachment attachment,-
465 GLenum texture_target, GLenum internal_format,-
466 GLint samples, bool mipmap)-
467{-
468 QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());-
469-
470 funcs.initializeOpenGLFunctions();-
471-
472 if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
!funcs.hasOpen...:Framebuffers)Description
TRUEnever evaluated
FALSEnever evaluated
0
473 return;
never executed: return;
0
474-
475 ctx->d_ptr->refreshCurrentFbo();-
476-
477 size = sz;-
478 target = texture_target;-
479 // texture dimensions-
480-
481 QT_RESET_GLERROR(); // reset error state
never executed: end of block
QOpenGLContext...etError() != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
482 GLuint fbo = 0;-
483 funcs.glGenFramebuffers(1, &fbo);-
484 funcs.glBindFramebuffer(GL_FRAMEBUFFER, fbo);-
485-
486 GLuint texture = 0;-
487 GLuint color_buffer = 0;-
488 GLuint depth_buffer = 0;-
489 GLuint stencil_buffer = 0;-
490-
491 QT_CHECK_GLERROR();
never executed: end of block
err != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
492 // init texture-
493 if (samples == 0) {
samples == 0Description
TRUEnever evaluated
FALSEnever evaluated
0
494 funcs.glGenTextures(1, &texture);-
495 funcs.glBindTexture(target, texture);-
496 funcs.glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,-
497 GL_RGBA, GL_UNSIGNED_BYTE, NULL);-
498 if (mipmap) {
mipmapDescription
TRUEnever evaluated
FALSEnever evaluated
0
499 int width = size.width();-
500 int height = size.height();-
501 int level = 0;-
502 while (width > 1 || height > 1) {
width > 1Description
TRUEnever evaluated
FALSEnever evaluated
height > 1Description
TRUEnever evaluated
FALSEnever evaluated
0
503 width = qMax(1, width >> 1);-
504 height = qMax(1, height >> 1);-
505 ++level;-
506 funcs.glTexImage2D(target, level, internal_format, width, height, 0,-
507 GL_RGBA, GL_UNSIGNED_BYTE, NULL);-
508 }
never executed: end of block
0
509 }
never executed: end of block
0
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 funcs.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,-
515 target, texture, 0);-
516-
517 QT_CHECK_GLERROR();
never executed: end of block
err != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
518 valid = checkFramebufferStatus();-
519 funcs.glBindTexture(target, 0);-
520-
521 color_buffer = 0;-
522 } else {
never executed: end of block
0
523 mipmap = false;-
524 GLint maxSamples;-
525 funcs.glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);-
526-
527 samples = qBound(0, int(samples), int(maxSamples));-
528-
529 funcs.glGenRenderbuffers(1, &color_buffer);-
530 funcs.glBindRenderbuffer(GL_RENDERBUFFER, color_buffer);-
531 if (funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample) && samples > 0) {
funcs.hasOpenG...erMultisample)Description
TRUEnever evaluated
FALSEnever evaluated
samples > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
532 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,-
533 internal_format, size.width(), size.height());-
534 } else {
never executed: end of block
0
535 samples = 0;-
536 funcs.glRenderbufferStorage(GL_RENDERBUFFER, internal_format,-
537 size.width(), size.height());-
538 }
never executed: end of block
0
539-
540 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,-
541 GL_RENDERBUFFER, color_buffer);-
542-
543 QT_CHECK_GLERROR();
never executed: end of block
err != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
544 valid = checkFramebufferStatus();-
545-
546 if (valid)
validDescription
TRUEnever evaluated
FALSEnever evaluated
0
547 funcs.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
never executed: funcs.glGetRenderbufferParameteriv(0x8D41, 0x8CAB, &samples);
0
548 }
never executed: end of block
0
549-
550 // In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a-
551 // separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer-
552 // might not be supported while separate buffers are, according to QTBUG-12861.-
553-
554 if (attachment == QGLFramebufferObject::CombinedDepthStencil
attachment == ...edDepthStencilDescription
TRUEnever evaluated
FALSEnever evaluated
0
555 && funcs.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil)) {
funcs.hasOpenG...dDepthStencil)Description
TRUEnever evaluated
FALSEnever evaluated
0
556 // depth and stencil buffer needs another extension-
557 funcs.glGenRenderbuffers(1, &depth_buffer);-
558 funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);-
559 Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));-
560 if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
samples != 0Description
TRUEnever evaluated
FALSEnever evaluated
funcs.hasOpenG...erMultisample)Description
TRUEnever evaluated
FALSEnever evaluated
0
561 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x88F0, size.width(), size.height());
0
562 GL_DEPTH24_STENCIL8, size.width(), size.height());
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x88F0, size.width(), size.height());
0
563 else-
564 funcs.glRenderbufferStorage(GL_RENDERBUFFER,
never executed: funcs.glRenderbufferStorage(0x8D41, 0x88F0, size.width(), size.height());
0
565 GL_DEPTH24_STENCIL8, size.width(), size.height());
never executed: funcs.glRenderbufferStorage(0x8D41, 0x88F0, size.width(), size.height());
0
566-
567 stencil_buffer = depth_buffer;-
568 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,-
569 GL_RENDERBUFFER, depth_buffer);-
570 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,-
571 GL_RENDERBUFFER, stencil_buffer);-
572-
573 valid = checkFramebufferStatus();-
574 if (!valid) {
!validDescription
TRUEnever evaluated
FALSEnever evaluated
0
575 funcs.glDeleteRenderbuffers(1, &depth_buffer);-
576 stencil_buffer = depth_buffer = 0;-
577 }
never executed: end of block
0
578 }
never executed: end of block
0
579-
580 if (depth_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil
depth_buffer == 0Description
TRUEnever evaluated
FALSEnever evaluated
attachment == ...edDepthStencilDescription
TRUEnever evaluated
FALSEnever evaluated
0
581 || (attachment == QGLFramebufferObject::Depth)))
(attachment ==...Object::Depth)Description
TRUEnever evaluated
FALSEnever evaluated
0
582 {-
583 funcs.glGenRenderbuffers(1, &depth_buffer);-
584 funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);-
585 Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));-
586 if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) {
samples != 0Description
TRUEnever evaluated
FALSEnever evaluated
funcs.hasOpenG...erMultisample)Description
TRUEnever evaluated
FALSEnever evaluated
0
587#ifdef QT_OPENGL_ES-
588 if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24)) {-
589 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,-
590 GL_DEPTH_COMPONENT24_OES, size.width(), size.height());-
591 } else {-
592 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,-
593 GL_DEPTH_COMPONENT16, size.width(), size.height());-
594 }-
595#else-
596 if (ctx->contextHandle()->isOpenGLES()) {
ctx->contextHa...->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
597 if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24))
funcs.hasOpenG...ions::Depth24)Description
TRUEnever evaluated
FALSEnever evaluated
0
598 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x81A6, size.width(), size.height());
0
599 GL_DEPTH_COMPONENT24, size.width(), size.height());
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x81A6, size.width(), size.height());
0
600 else-
601 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x81A5, size.width(), size.height());
0
602 GL_DEPTH_COMPONENT16, size.width(), size.height());
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x81A5, size.width(), size.height());
0
603 } else {-
604 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,-
605 GL_DEPTH_COMPONENT, size.width(), size.height());-
606 }
never executed: end of block
0
607#endif-
608 } else {-
609#ifdef QT_OPENGL_ES-
610 if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24)) {-
611 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24_OES,-
612 size.width(), size.height());-
613 } else {-
614 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,-
615 size.width(), size.height());-
616 }-
617#else-
618 if (ctx->contextHandle()->isOpenGLES()) {
ctx->contextHa...->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
619 if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24)) {
funcs.hasOpenG...ions::Depth24)Description
TRUEnever evaluated
FALSEnever evaluated
0
620 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24,-
621 size.width(), size.height());-
622 } else {
never executed: end of block
0
623 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,-
624 size.width(), size.height());-
625 }
never executed: end of block
0
626 } else {-
627 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.width(), size.height());-
628 }
never executed: end of block
0
629#endif-
630 }-
631 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,-
632 GL_RENDERBUFFER, depth_buffer);-
633 valid = checkFramebufferStatus();-
634 if (!valid) {
!validDescription
TRUEnever evaluated
FALSEnever evaluated
0
635 funcs.glDeleteRenderbuffers(1, &depth_buffer);-
636 depth_buffer = 0;-
637 }
never executed: end of block
0
638 }
never executed: end of block
0
639-
640 if (stencil_buffer == 0 && (attachment == QGLFramebufferObject::CombinedDepthStencil)) {
stencil_buffer == 0Description
TRUEnever evaluated
FALSEnever evaluated
(attachment ==...dDepthStencil)Description
TRUEnever evaluated
FALSEnever evaluated
0
641 funcs.glGenRenderbuffers(1, &stencil_buffer);-
642 funcs.glBindRenderbuffer(GL_RENDERBUFFER, stencil_buffer);-
643 Q_ASSERT(funcs.glIsRenderbuffer(stencil_buffer));-
644-
645#ifdef QT_OPENGL_ES-
646 GLenum storage = GL_STENCIL_INDEX8;-
647#else-
648 GLenum storage = ctx->contextHandle()->isOpenGLES() ? GL_STENCIL_INDEX8 : GL_STENCIL_INDEX;
ctx->contextHa...->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
649#endif-
650-
651 if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
samples != 0Description
TRUEnever evaluated
FALSEnever evaluated
funcs.hasOpenG...erMultisample)Description
TRUEnever evaluated
FALSEnever evaluated
0
652 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, storage, size.width(), size.height());
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, storage, size.width(), size.height());
0
653 else-
654 funcs.glRenderbufferStorage(GL_RENDERBUFFER, storage, size.width(), size.height());
never executed: funcs.glRenderbufferStorage(0x8D41, storage, size.width(), size.height());
0
655-
656 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,-
657 GL_RENDERBUFFER, stencil_buffer);-
658 valid = checkFramebufferStatus();-
659 if (!valid) {
!validDescription
TRUEnever evaluated
FALSEnever evaluated
0
660 funcs.glDeleteRenderbuffers(1, &stencil_buffer);-
661 stencil_buffer = 0;-
662 }
never executed: end of block
0
663 }
never executed: end of block
0
664-
665 // The FBO might have become valid after removing the depth or stencil buffer.-
666 valid = checkFramebufferStatus();-
667-
668 if (depth_buffer && stencil_buffer) {
depth_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
stencil_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
669 fbo_attachment = QGLFramebufferObject::CombinedDepthStencil;-
670 } else if (depth_buffer) {
never executed: end of block
depth_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
671 fbo_attachment = QGLFramebufferObject::Depth;-
672 } else {
never executed: end of block
0
673 fbo_attachment = QGLFramebufferObject::NoAttachment;-
674 }
never executed: end of block
0
675-
676 funcs.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->current_fbo);-
677 if (valid) {
validDescription
TRUEnever evaluated
FALSEnever evaluated
0
678 fbo_guard = createSharedResourceGuard(ctx, fbo, freeFramebufferFunc);-
679 if (color_buffer)
color_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
680 color_buffer_guard = createSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc);
never executed: color_buffer_guard = createSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc);
0
681 else-
682 texture_guard = createSharedResourceGuard(ctx, texture, freeTextureFunc);
never executed: texture_guard = createSharedResourceGuard(ctx, texture, freeTextureFunc);
0
683 if (depth_buffer)
depth_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
684 depth_buffer_guard = createSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc);
never executed: depth_buffer_guard = createSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc);
0
685 if (stencil_buffer) {
stencil_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
686 if (stencil_buffer == depth_buffer)
stencil_buffer == depth_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
687 stencil_buffer_guard = depth_buffer_guard;
never executed: stencil_buffer_guard = depth_buffer_guard;
0
688 else-
689 stencil_buffer_guard = createSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc);
never executed: stencil_buffer_guard = createSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc);
0
690 }-
691 } else {
never executed: end of block
0
692 if (color_buffer)
color_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
693 funcs.glDeleteRenderbuffers(1, &color_buffer);
never executed: funcs.glDeleteRenderbuffers(1, &color_buffer);
0
694 else-
695 funcs.glDeleteTextures(1, &texture);
never executed: funcs.glDeleteTextures(1, &texture);
0
696 if (depth_buffer)
depth_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
697 funcs.glDeleteRenderbuffers(1, &depth_buffer);
never executed: funcs.glDeleteRenderbuffers(1, &depth_buffer);
0
698 if (stencil_buffer && depth_buffer != stencil_buffer)
stencil_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
depth_buffer != stencil_bufferDescription
TRUEnever evaluated
FALSEnever evaluated
0
699 funcs.glDeleteRenderbuffers(1, &stencil_buffer);
never executed: funcs.glDeleteRenderbuffers(1, &stencil_buffer);
0
700 funcs.glDeleteFramebuffers(1, &fbo);-
701 }
never executed: end of block
0
702 QT_CHECK_GLERROR();
never executed: end of block
err != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
703-
704 format.setTextureTarget(target);-
705 format.setSamples(int(samples));-
706 format.setAttachment(fbo_attachment);-
707 format.setInternalTextureFormat(internal_format);-
708 format.setMipmap(mipmap);-
709-
710 glDevice.setFBO(q, attachment);-
711}
never executed: end of block
0
712-
713/*!-
714 \class QGLFramebufferObject-
715 \inmodule QtOpenGL-
716 \brief The QGLFramebufferObject class encapsulates an OpenGL framebuffer object.-
717 \since 4.2-
718-
719 \obsolete-
720-
721 \ingroup painting-3D-
722-
723 The QGLFramebufferObject class encapsulates an OpenGL framebuffer-
724 object, defined by the \c{GL_EXT_framebuffer_object} extension. In-
725 addition it provides a rendering surface that can be painted on-
726 with a QPainter, rendered to using native GL calls, or both. This-
727 surface can be bound and used as a regular texture in your own GL-
728 drawing code. By default, the QGLFramebufferObject class-
729 generates a 2D GL texture (using the \c{GL_TEXTURE_2D} target),-
730 which is used as the internal rendering target.-
731-
732 \b{It is important to have a current GL context when creating a-
733 QGLFramebufferObject, otherwise initialization will fail.}-
734-
735 OpenGL framebuffer objects and pbuffers (see-
736 \l{QGLPixelBuffer}{QGLPixelBuffer}) can both be used to render to-
737 offscreen surfaces, but there are a number of advantages with-
738 using framebuffer objects instead of pbuffers:-
739-
740 \list 1-
741 \li A framebuffer object does not require a separate rendering-
742 context, so no context switching will occur when switching-
743 rendering targets. There is an overhead involved in switching-
744 targets, but in general it is cheaper than a context switch to a-
745 pbuffer.-
746-
747 \li Rendering to dynamic textures (i.e. render-to-texture-
748 functionality) works on all platforms. No need to do explicit copy-
749 calls from a render buffer into a texture, as was necessary on-
750 systems that did not support the \c{render_texture} extension.-
751-
752 \li It is possible to attach several rendering buffers (or texture-
753 objects) to the same framebuffer object, and render to all of them-
754 without doing a context switch.-
755-
756 \li The OpenGL framebuffer extension is a pure GL extension with no-
757 system dependant WGL, CGL, or GLX parts. This makes using-
758 framebuffer objects more portable.-
759 \endlist-
760-
761 When using a QPainter to paint to a QGLFramebufferObject you should take-
762 care that the QGLFramebufferObject is created with the CombinedDepthStencil-
763 attachment for QPainter to be able to render correctly.-
764 Note that you need to create a QGLFramebufferObject with more than one-
765 sample per pixel for primitives to be antialiased when drawing using a-
766 QPainter. To create a multisample framebuffer object you should use one of-
767 the constructors that take a QGLFramebufferObjectFormat parameter, and set-
768 the QGLFramebufferObjectFormat::samples() property to a non-zero value.-
769-
770 When painting to a QGLFramebufferObject using QPainter, the state of-
771 the current GL context will be altered by the paint engine to reflect-
772 its needs. Applications should not rely upon the GL state being reset-
773 to its original conditions, particularly the current shader program,-
774 GL viewport, texture units, and drawing modes.-
775-
776 For multisample framebuffer objects a color render buffer is created,-
777 otherwise a texture with the specified texture target is created.-
778 The color render buffer or texture will have the specified internal-
779 format, and will be bound to the \c GL_COLOR_ATTACHMENT0-
780 attachment in the framebuffer object.-
781-
782 If you want to use a framebuffer object with multisampling enabled-
783 as a texture, you first need to copy from it to a regular framebuffer-
784 object using QGLContext::blitFramebuffer().-
785-
786 \section1 Threading-
787-
788 As of Qt 4.8, it's possible to draw into a QGLFramebufferObject-
789 using a QPainter in a separate thread. Note that OpenGL 2.0 or-
790 OpenGL ES 2.0 is required for this to work.-
791-
792 \note This class has been deprecated in favor of QOpenGLFramebufferObject.-
793*/-
794-
795-
796/*!-
797 \enum QGLFramebufferObject::Attachment-
798 \since 4.3-
799-
800 This enum type is used to configure the depth and stencil buffers-
801 attached to the framebuffer object when it is created.-
802-
803 \value NoAttachment No attachment is added to the framebuffer object. Note that the-
804 OpenGL depth and stencil tests won't work when rendering to a-
805 framebuffer object without any depth or stencil buffers.-
806 This is the default value.-
807-
808 \value CombinedDepthStencil If the \c GL_EXT_packed_depth_stencil extension is present,-
809 a combined depth and stencil buffer is attached.-
810 If the extension is not present, only a depth buffer is attached.-
811-
812 \value Depth A depth buffer is attached to the framebuffer object.-
813-
814 \sa attachment()-
815*/-
816-
817-
818/*! \fn QGLFramebufferObject::QGLFramebufferObject(const QSize &size, GLenum target)-
819-
820 Constructs an OpenGL framebuffer object and binds a 2D GL texture-
821 to the buffer of the size \a size. The texture is bound to the-
822 \c GL_COLOR_ATTACHMENT0 target in the framebuffer object.-
823-
824 The \a target parameter is used to specify the GL texture-
825 target. The default target is \c GL_TEXTURE_2D. Keep in mind that-
826 \c GL_TEXTURE_2D textures must have a power of 2 width and height-
827 (e.g. 256x512), unless you are using OpenGL 2.0 or higher.-
828-
829 By default, no depth and stencil buffers are attached. This behavior-
830 can be toggled using one of the overloaded constructors.-
831-
832 The default internal texture format is \c GL_RGBA8 for desktop-
833 OpenGL, and \c GL_RGBA for OpenGL/ES.-
834-
835 It is important that you have a current GL context set when-
836 creating the QGLFramebufferObject, otherwise the initialization-
837 will fail.-
838-
839 \sa size(), texture(), attachment()-
840*/-
841-
842QGLFramebufferObject::QGLFramebufferObject(const QSize &size, GLenum target)-
843 : d_ptr(new QGLFramebufferObjectPrivate)-
844{-
845 Q_D(QGLFramebufferObject);-
846 d->init(this, size, NoAttachment, target,-
847#ifndef QT_OPENGL_ES_2-
848 QOpenGLContext::currentContext()->isOpenGLES() ? GL_RGBA : GL_RGBA8-
849#else-
850 GL_RGBA-
851#endif-
852 );-
853}
never executed: end of block
0
854-
855/*! \overload-
856-
857 Constructs an OpenGL framebuffer object and binds a 2D GL texture-
858 to the buffer of the given \a width and \a height.-
859-
860 \sa size(), texture()-
861*/-
862QGLFramebufferObject::QGLFramebufferObject(int width, int height, GLenum target)-
863 : d_ptr(new QGLFramebufferObjectPrivate)-
864{-
865 Q_D(QGLFramebufferObject);-
866 d->init(this, QSize(width, height), NoAttachment, target,-
867#ifndef QT_OPENGL_ES_2-
868 QOpenGLContext::currentContext()->isOpenGLES() ? GL_RGBA : GL_RGBA8-
869#else-
870 GL_RGBA-
871#endif-
872 );-
873}
never executed: end of block
0
874-
875/*! \overload-
876-
877 Constructs an OpenGL framebuffer object of the given \a size based on the-
878 supplied \a format.-
879*/-
880-
881QGLFramebufferObject::QGLFramebufferObject(const QSize &size, const QGLFramebufferObjectFormat &format)-
882 : d_ptr(new QGLFramebufferObjectPrivate)-
883{-
884 Q_D(QGLFramebufferObject);-
885 d->init(this, size, format.attachment(), format.textureTarget(), format.internalTextureFormat(),-
886 format.samples(), format.mipmap());-
887}
never executed: end of block
0
888-
889/*! \overload-
890-
891 Constructs an OpenGL framebuffer object of the given \a width and \a height-
892 based on the supplied \a format.-
893*/-
894-
895QGLFramebufferObject::QGLFramebufferObject(int width, int height, const QGLFramebufferObjectFormat &format)-
896 : d_ptr(new QGLFramebufferObjectPrivate)-
897{-
898 Q_D(QGLFramebufferObject);-
899 d->init(this, QSize(width, height), format.attachment(), format.textureTarget(),-
900 format.internalTextureFormat(), format.samples(), format.mipmap());-
901}
never executed: end of block
0
902-
903/*! \overload-
904-
905 Constructs an OpenGL framebuffer object and binds a texture to the-
906 buffer of the given \a width and \a height.-
907-
908 The \a attachment parameter describes the depth/stencil buffer-
909 configuration, \a target the texture target and \a internal_format-
910 the internal texture format. The default texture target is \c-
911 GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8-
912 for desktop OpenGL and \c GL_RGBA for OpenGL/ES.-
913-
914 \sa size(), texture(), attachment()-
915*/-
916QGLFramebufferObject::QGLFramebufferObject(int width, int height, Attachment attachment,-
917 GLenum target, GLenum internal_format)-
918 : d_ptr(new QGLFramebufferObjectPrivate)-
919{-
920 Q_D(QGLFramebufferObject);-
921 if (!internal_format)
!internal_formatDescription
TRUEnever evaluated
FALSEnever evaluated
0
922#ifdef QT_OPENGL_ES_2-
923 internal_format = GL_RGBA;-
924#else-
925 internal_format = QOpenGLContext::currentContext()->isOpenGLES() ? GL_RGBA : GL_RGBA8;
never executed: internal_format = QOpenGLContext::currentContext()->isOpenGLES() ? 0x1908 : 0x8058;
QOpenGLContext...->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
926#endif-
927 d->init(this, QSize(width, height), attachment, target, internal_format);-
928}
never executed: end of block
0
929-
930/*! \overload-
931-
932 Constructs an OpenGL framebuffer object and binds a texture to the-
933 buffer of the given \a size.-
934-
935 The \a attachment parameter describes the depth/stencil buffer-
936 configuration, \a target the texture target and \a internal_format-
937 the internal texture format. The default texture target is \c-
938 GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8-
939 for desktop OpenGL and \c GL_RGBA for OpenGL/ES.-
940-
941 \sa size(), texture(), attachment()-
942*/-
943QGLFramebufferObject::QGLFramebufferObject(const QSize &size, Attachment attachment,-
944 GLenum target, GLenum internal_format)-
945 : d_ptr(new QGLFramebufferObjectPrivate)-
946{-
947 Q_D(QGLFramebufferObject);-
948 if (!internal_format)
!internal_formatDescription
TRUEnever evaluated
FALSEnever evaluated
0
949#ifdef QT_OPENGL_ES_2-
950 internal_format = GL_RGBA;-
951#else-
952 internal_format = QOpenGLContext::currentContext()->isOpenGLES() ? GL_RGBA : GL_RGBA8;
never executed: internal_format = QOpenGLContext::currentContext()->isOpenGLES() ? 0x1908 : 0x8058;
QOpenGLContext...->isOpenGLES()Description
TRUEnever evaluated
FALSEnever evaluated
0
953#endif-
954 d->init(this, size, attachment, target, internal_format);-
955}
never executed: end of block
0
956-
957/*!-
958 \fn QGLFramebufferObject::~QGLFramebufferObject()-
959-
960 Destroys the framebuffer object and frees any allocated resources.-
961*/-
962QGLFramebufferObject::~QGLFramebufferObject()-
963{-
964 Q_D(QGLFramebufferObject);-
965-
966 delete d->engine;-
967-
968 if (d->texture_guard)
d->texture_guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
969 d->texture_guard->free();
never executed: d->texture_guard->free();
0
970 if (d->color_buffer_guard)
d->color_buffer_guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
971 d->color_buffer_guard->free();
never executed: d->color_buffer_guard->free();
0
972 if (d->depth_buffer_guard)
d->depth_buffer_guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
973 d->depth_buffer_guard->free();
never executed: d->depth_buffer_guard->free();
0
974 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
975 d->stencil_buffer_guard->free();
never executed: d->stencil_buffer_guard->free();
0
976 if (d->fbo_guard)
d->fbo_guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
977 d->fbo_guard->free();
never executed: d->fbo_guard->free();
0
978}
never executed: end of block
0
979-
980/*!-
981 \fn bool QGLFramebufferObject::isValid() const-
982-
983 Returns \c true if the framebuffer object is valid.-
984-
985 The framebuffer can become invalid if the initialization process-
986 fails, the user attaches an invalid buffer to the framebuffer-
987 object, or a non-power of two width/height is specified as the-
988 texture size if the texture target is \c{GL_TEXTURE_2D}.-
989 The non-power of two limitation does not apply if the OpenGL version-
990 is 2.0 or higher, or if the GL_ARB_texture_non_power_of_two extension-
991 is present.-
992-
993 The framebuffer can also become invalid if the QGLContext that-
994 the framebuffer was created within is destroyed and there are-
995 no other shared contexts that can take over ownership of the-
996 framebuffer.-
997*/-
998bool QGLFramebufferObject::isValid() const-
999{-
1000 Q_D(const QGLFramebufferObject);-
1001 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
1002}-
1003-
1004/*!-
1005 \fn bool QGLFramebufferObject::bind()-
1006-
1007 Switches rendering from the default, windowing system provided-
1008 framebuffer to this framebuffer object.-
1009 Returns \c true upon success, false otherwise.-
1010-
1011 \sa release()-
1012*/-
1013bool QGLFramebufferObject::bind()-
1014{-
1015 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1016 return false;
never executed: return false;
0
1017 Q_D(QGLFramebufferObject);-
1018 QGL_FUNC_CONTEXT;-
1019 if (!ctx)
!ctxDescription
TRUEnever evaluated
FALSEnever evaluated
0
1020 return false; // Context no longer exists.
never executed: return false;
0
1021 const QGLContext *current = QGLContext::currentContext();-
1022#ifdef QT_DEBUG-
1023 if (!current ||
!currentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1024 QGLContextPrivate::contextGroup(current) != QGLContextPrivate::contextGroup(ctx))
QGLContextPriv...textGroup(ctx)Description
TRUEnever evaluated
FALSEnever evaluated
0
1025 {-
1026 qWarning("QGLFramebufferObject::bind() called from incompatible context");-
1027 }
never executed: end of block
0
1028#endif-
1029 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());-
1030 d->valid = d->checkFramebufferStatus();-
1031 if (d->valid && current)
d->validDescription
TRUEnever evaluated
FALSEnever evaluated
currentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1032 current->d_ptr->setCurrentFbo(d->fbo());
never executed: current->d_ptr->setCurrentFbo(d->fbo());
0
1033 return d->valid;
never executed: return d->valid;
0
1034}-
1035-
1036/*!-
1037 \fn bool QGLFramebufferObject::release()-
1038-
1039 Switches rendering back to the default, windowing system provided-
1040 framebuffer.-
1041 Returns \c true upon success, false otherwise.-
1042-
1043 \sa bind()-
1044*/-
1045bool QGLFramebufferObject::release()-
1046{-
1047 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
1048 return false;
never executed: return false;
0
1049 Q_D(QGLFramebufferObject);-
1050 QGL_FUNC_CONTEXT;-
1051 if (!ctx)
!ctxDescription
TRUEnever evaluated
FALSEnever evaluated
0
1052 return false; // Context no longer exists.
never executed: return false;
0
1053-
1054 const QGLContext *current = QGLContext::currentContext();-
1055-
1056#ifdef QT_DEBUG-
1057 if (!current ||
!currentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1058 QGLContextPrivate::contextGroup(current) != QGLContextPrivate::contextGroup(ctx))
QGLContextPriv...textGroup(ctx)Description
TRUEnever evaluated
FALSEnever evaluated
0
1059 {-
1060 qWarning("QGLFramebufferObject::release() called from incompatible context");-
1061 }
never executed: end of block
0
1062#endif-
1063-
1064 if (current) {
currentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1065 current->d_ptr->setCurrentFbo(current->d_ptr->default_fbo);-
1066 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_ptr->default_fbo);-
1067 }
never executed: end of block
0
1068-
1069 return true;
never executed: return true;
0
1070}-
1071-
1072/*!-
1073 \fn GLuint QGLFramebufferObject::texture() const-
1074-
1075 Returns the texture id for the texture attached as the default-
1076 rendering target in this framebuffer object. This texture id can-
1077 be bound as a normal texture in your own GL code.-
1078-
1079 If a multisample framebuffer object is used then the value returned-
1080 from this function will be invalid.-
1081*/-
1082GLuint QGLFramebufferObject::texture() const-
1083{-
1084 Q_D(const QGLFramebufferObject);-
1085 return d->texture_guard ? d->texture_guard->id() : 0;
never executed: return d->texture_guard ? d->texture_guard->id() : 0;
d->texture_guardDescription
TRUEnever evaluated
FALSEnever evaluated
0
1086}-
1087-
1088/*!-
1089 \fn QSize QGLFramebufferObject::size() const-
1090-
1091 Returns the size of the texture attached to this framebuffer-
1092 object.-
1093*/-
1094QSize QGLFramebufferObject::size() const-
1095{-
1096 Q_D(const QGLFramebufferObject);-
1097 return d->size;
never executed: return d->size;
0
1098}-
1099-
1100/*!-
1101 Returns the format of this framebuffer object.-
1102*/-
1103QGLFramebufferObjectFormat QGLFramebufferObject::format() const-
1104{-
1105 Q_D(const QGLFramebufferObject);-
1106 return d->format;
never executed: return d->format;
0
1107}-
1108-
1109/*!-
1110 \fn QImage QGLFramebufferObject::toImage() const-
1111-
1112 Returns the contents of this framebuffer object as a QImage.-
1113-
1114 The returned image has a format of premultiplied ARGB32 or RGB32. The latter is used-
1115 only when internalTextureFormat() is set to \c GL_RGB.-
1116-
1117 If the rendering in the framebuffer was not done with premultiplied alpha in mind,-
1118 create a wrapper QImage with a non-premultiplied format. This is necessary before-
1119 performing operations like QImage::save() because otherwise the image data would get-
1120 unpremultiplied, even though it was not premultiplied in the first place. To create-
1121 such a wrapper without performing a copy of the pixel data, do the following:-
1122-
1123 \code-
1124 QImage fboImage(fbo.toImage());-
1125 QImage image(fboImage.constBits(), fboImage.width(), fboImage.height(), QImage::Format_ARGB32);-
1126 \endcode-
1127-
1128 On QNX the back buffer is not preserved when a buffer swap occures. So this function-
1129 might return old content.-
1130*/-
1131QImage QGLFramebufferObject::toImage() const-
1132{-
1133 Q_D(const QGLFramebufferObject);-
1134 if (!d->valid)
!d->validDescription
TRUEnever evaluated
FALSEnever evaluated
0
1135 return QImage();
never executed: return QImage();
0
1136-
1137 // qt_gl_read_frame_buffer doesn't work on a multisample FBO-
1138 if (format().samples() != 0) {
format().samples() != 0Description
TRUEnever evaluated
FALSEnever evaluated
0
1139 QGLFramebufferObject temp(size(), QGLFramebufferObjectFormat());-
1140-
1141 QRect rect(QPoint(0, 0), size());-
1142 blitFramebuffer(&temp, rect, const_cast<QGLFramebufferObject *>(this), rect);-
1143-
1144 return temp.toImage();
never executed: return temp.toImage();
0
1145 }-
1146-
1147 bool wasBound = isBound();-
1148 if (!wasBound)
!wasBoundDescription
TRUEnever evaluated
FALSEnever evaluated
0
1149 const_cast<QGLFramebufferObject *>(this)->bind();
never executed: const_cast<QGLFramebufferObject *>(this)->bind();
0
1150 QImage image = qt_gl_read_frame_buffer(d->size, format().internalTextureFormat() != GL_RGB, true);-
1151 if (!wasBound)
!wasBoundDescription
TRUEnever evaluated
FALSEnever evaluated
0
1152 const_cast<QGLFramebufferObject *>(this)->release();
never executed: const_cast<QGLFramebufferObject *>(this)->release();
0
1153-
1154 return image;
never executed: return image;
0
1155}-
1156-
1157Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine)
never executed: end of block
never executed: guard.store(QtGlobalStatic::Destroyed);
never executed: return &holder.value;
guard.load() =...c::InitializedDescription
TRUEnever evaluated
FALSEnever evaluated
0
1158-
1159/*! \reimp */-
1160QPaintEngine *QGLFramebufferObject::paintEngine() const-
1161{-
1162 Q_D(const QGLFramebufferObject);-
1163 if (d->engine)
d->engineDescription
TRUEnever evaluated
FALSEnever evaluated
0
1164 return d->engine;
never executed: return d->engine;
0
1165-
1166 QPaintEngine *engine = qt_buffer_2_engine()->engine();-
1167 if (engine->isActive() && engine->paintDevice() != this) {
engine->isActive()Description
TRUEnever evaluated
FALSEnever evaluated
engine->paintDevice() != thisDescription
TRUEnever evaluated
FALSEnever evaluated
0
1168 d->engine = new QGL2PaintEngineEx;-
1169 return d->engine;
never executed: return d->engine;
0
1170 }-
1171 return engine;
never executed: return engine;
0
1172}-
1173-
1174/*!-
1175 \fn bool QGLFramebufferObject::bindDefault()-
1176-
1177 Switches rendering back to the default, windowing system provided-
1178 framebuffer.-
1179 Returns \c true upon success, false otherwise.-
1180-
1181 \sa bind(), release()-
1182*/-
1183bool QGLFramebufferObject::bindDefault()-
1184{-
1185 QGLContext *ctx = const_cast<QGLContext *>(QGLContext::currentContext());-
1186-
1187 if (ctx) {
ctxDescription
TRUEnever evaluated
FALSEnever evaluated
0
1188 QOpenGLFunctions functions(ctx->contextHandle());-
1189 if (!functions.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
!functions.has...:Framebuffers)Description
TRUEnever evaluated
FALSEnever evaluated
0
1190 return false;
never executed: return false;
0
1191-
1192 ctx->d_ptr->setCurrentFbo(ctx->d_ptr->default_fbo);-
1193 functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->default_fbo);-
1194#ifdef QT_DEBUG-
1195 } else {
never executed: end of block
0
1196 qWarning("QGLFramebufferObject::bindDefault() called without current context.");-
1197#endif-
1198 }
never executed: end of block
0
1199-
1200 return ctx != 0;
never executed: return ctx != 0;
0
1201}-
1202-
1203/*!-
1204 \fn bool QGLFramebufferObject::hasOpenGLFramebufferObjects()-
1205-
1206 Returns \c true if the OpenGL \c{GL_EXT_framebuffer_object} extension-
1207 is present on this system; otherwise returns \c false.-
1208*/-
1209bool QGLFramebufferObject::hasOpenGLFramebufferObjects()-
1210{-
1211 return qgl_hasFeature(QOpenGLFunctions::Framebuffers);
never executed: return qgl_hasFeature(QOpenGLFunctions::Framebuffers);
0
1212}-
1213-
1214/*!-
1215 \since 4.4-
1216-
1217 Draws the given texture, \a textureId, to the given target rectangle,-
1218 \a target, in OpenGL model space. The \a textureTarget should be a 2D-
1219 texture target.-
1220-
1221 The framebuffer object should be bound when calling this function.-
1222-
1223 Equivalent to the corresponding QGLContext::drawTexture().-
1224*/-
1225void QGLFramebufferObject::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)-
1226{-
1227 const_cast<QGLContext *>(QGLContext::currentContext())->drawTexture(target, textureId, textureTarget);-
1228}
never executed: end of block
0
1229-
1230/*!-
1231 \since 4.4-
1232-
1233 Draws the given texture, \a textureId, at the given \a point in OpenGL-
1234 model space. The \a textureTarget should be a 2D texture target.-
1235-
1236 The framebuffer object should be bound when calling this function.-
1237-
1238 Equivalent to the corresponding QGLContext::drawTexture().-
1239*/-
1240void QGLFramebufferObject::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)-
1241{-
1242 const_cast<QGLContext *>(QGLContext::currentContext())->drawTexture(point, textureId, textureTarget);-
1243}
never executed: end of block
0
1244-
1245/*! \reimp */-
1246int QGLFramebufferObject::metric(PaintDeviceMetric metric) const-
1247{-
1248 Q_D(const QGLFramebufferObject);-
1249-
1250 float dpmx = qt_defaultDpiX()*100./2.54;-
1251 float dpmy = qt_defaultDpiY()*100./2.54;-
1252 int w = d->size.width();-
1253 int h = d->size.height();-
1254 switch (metric) {-
1255 case PdmWidth:
never executed: case PdmWidth:
0
1256 return w;
never executed: return w;
0
1257-
1258 case PdmHeight:
never executed: case PdmHeight:
0
1259 return h;
never executed: return h;
0
1260-
1261 case PdmWidthMM:
never executed: case PdmWidthMM:
0
1262 return qRound(w * 1000 / dpmx);
never executed: return qRound(w * 1000 / dpmx);
0
1263-
1264 case PdmHeightMM:
never executed: case PdmHeightMM:
0
1265 return qRound(h * 1000 / dpmy);
never executed: return qRound(h * 1000 / dpmy);
0
1266-
1267 case PdmNumColors:
never executed: case PdmNumColors:
0
1268 return 0;
never executed: return 0;
0
1269-
1270 case PdmDepth:
never executed: case PdmDepth:
0
1271 return 32;//d->depth;
never executed: return 32;
0
1272-
1273 case PdmDpiX:
never executed: case PdmDpiX:
0
1274 return qRound(dpmx * 0.0254);
never executed: return qRound(dpmx * 0.0254);
0
1275-
1276 case PdmDpiY:
never executed: case PdmDpiY:
0
1277 return qRound(dpmy * 0.0254);
never executed: return qRound(dpmy * 0.0254);
0
1278-
1279 case PdmPhysicalDpiX:
never executed: case PdmPhysicalDpiX:
0
1280 return qRound(dpmx * 0.0254);
never executed: return qRound(dpmx * 0.0254);
0
1281-
1282 case PdmPhysicalDpiY:
never executed: case PdmPhysicalDpiY:
0
1283 return qRound(dpmy * 0.0254);
never executed: return qRound(dpmy * 0.0254);
0
1284-
1285 case QPaintDevice::PdmDevicePixelRatio:
never executed: case QPaintDevice::PdmDevicePixelRatio:
0
1286 return 1;
never executed: return 1;
0
1287-
1288 case QPaintDevice::PdmDevicePixelRatioScaled:
never executed: case QPaintDevice::PdmDevicePixelRatioScaled:
0
1289 return 1 * QPaintDevice::devicePixelRatioFScale();
never executed: return 1 * QPaintDevice::devicePixelRatioFScale();
0
1290-
1291 default:
never executed: default:
0
1292 qWarning("QGLFramebufferObject::metric(), Unhandled metric type: %d.\n", metric);-
1293 break;
never executed: break;
0
1294 }-
1295 return 0;
never executed: return 0;
0
1296}-
1297-
1298/*!-
1299 \fn GLuint QGLFramebufferObject::handle() const-
1300-
1301 Returns the GL framebuffer object handle for this framebuffer-
1302 object (returned by the \c{glGenFrameBuffersEXT()} function). This-
1303 handle can be used to attach new images or buffers to the-
1304 framebuffer. The user is responsible for cleaning up and-
1305 destroying these objects.-
1306*/-
1307GLuint QGLFramebufferObject::handle() const-
1308{-
1309 Q_D(const QGLFramebufferObject);-
1310 return d->fbo();
never executed: return d->fbo();
0
1311}-
1312-
1313/*! \fn int QGLFramebufferObject::devType() const-
1314 \internal-
1315*/-
1316-
1317-
1318/*!-
1319 Returns the status of the depth and stencil buffers attached to-
1320 this framebuffer object.-
1321*/-
1322-
1323QGLFramebufferObject::Attachment QGLFramebufferObject::attachment() const-
1324{-
1325 Q_D(const QGLFramebufferObject);-
1326 if (d->valid)
d->validDescription
TRUEnever evaluated
FALSEnever evaluated
0
1327 return d->fbo_attachment;
never executed: return d->fbo_attachment;
0
1328 return NoAttachment;
never executed: return NoAttachment;
0
1329}-
1330-
1331/*!-
1332 \since 4.5-
1333-
1334 Returns \c true if the framebuffer object is currently bound to a context,-
1335 otherwise false is returned.-
1336*/-
1337-
1338bool QGLFramebufferObject::isBound() const-
1339{-
1340 Q_D(const QGLFramebufferObject);-
1341 const QGLContext *current = QGLContext::currentContext();-
1342 if (current) {
currentDescription
TRUEnever evaluated
FALSEnever evaluated
0
1343 current->d_ptr->refreshCurrentFbo();-
1344 return current->d_ptr->current_fbo == d->fbo();
never executed: return current->d_ptr->current_fbo == d->fbo();
0
1345 }-
1346-
1347 return false;
never executed: return false;
0
1348}-
1349-
1350/*!-
1351 \fn bool QGLFramebufferObject::hasOpenGLFramebufferBlit()-
1352-
1353 \since 4.6-
1354-
1355 Returns \c true if the OpenGL \c{GL_EXT_framebuffer_blit} extension-
1356 is present on this system; otherwise returns \c false.-
1357-
1358 \sa blitFramebuffer()-
1359*/-
1360bool QGLFramebufferObject::hasOpenGLFramebufferBlit()-
1361{-
1362 return QOpenGLExtensions(QOpenGLContext::currentContext()).hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
never executed: return QOpenGLExtensions(QOpenGLContext::currentContext()).hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
0
1363}-
1364-
1365/*!-
1366 \since 4.6-
1367-
1368 Blits from the \a sourceRect rectangle in the \a source framebuffer-
1369 object to the \a targetRect rectangle in the \a target framebuffer object.-
1370-
1371 If \a source or \a target is 0, the default framebuffer will be used-
1372 instead of a framebuffer object as source or target respectively.-
1373-
1374 The \a buffers parameter should be a mask consisting of any combination of-
1375 \c GL_COLOR_BUFFER_BIT, \c GL_DEPTH_BUFFER_BIT, and-
1376 \c GL_STENCIL_BUFFER_BIT. Any buffer type that is not present both-
1377 in the source and target buffers is ignored.-
1378-
1379 The \a sourceRect and \a targetRect rectangles may have different sizes;-
1380 in this case \a buffers should not contain \c GL_DEPTH_BUFFER_BIT or-
1381 \c GL_STENCIL_BUFFER_BIT. The \a filter parameter should be set to-
1382 \c GL_LINEAR or \c GL_NEAREST, and specifies whether linear or nearest-
1383 interpolation should be used when scaling is performed.-
1384-
1385 If \a source equals \a target a copy is performed within the same buffer.-
1386 Results are undefined if the source and target rectangles overlap and-
1387 have different sizes. The sizes must also be the same if any of the-
1388 framebuffer objects are multisample framebuffers.-
1389-
1390 Note that the scissor test will restrict the blit area if enabled.-
1391-
1392 This function will have no effect unless hasOpenGLFramebufferBlit() returns-
1393 true.-
1394-
1395 \sa hasOpenGLFramebufferBlit()-
1396*/-
1397void QGLFramebufferObject::blitFramebuffer(QGLFramebufferObject *target, const QRect &targetRect,-
1398 QGLFramebufferObject *source, const QRect &sourceRect,-
1399 GLbitfield buffers,-
1400 GLenum filter)-
1401{-
1402 const QGLContext *ctx = QGLContext::currentContext();-
1403 if (!ctx || !ctx->contextHandle())
!ctxDescription
TRUEnever evaluated
FALSEnever evaluated
!ctx->contextHandle()Description
TRUEnever evaluated
FALSEnever evaluated
0
1404 return;
never executed: return;
0
1405-
1406 QOpenGLExtensions functions(ctx->contextHandle());-
1407 if (!functions.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit))
!functions.has...amebufferBlit)Description
TRUEnever evaluated
FALSEnever evaluated
0
1408 return;
never executed: return;
0
1409-
1410 QSurface *surface = ctx->contextHandle()->surface();-
1411-
1412 const int height = static_cast<QWindow *>(surface)->height();-
1413-
1414 const int sh = source ? source->height() : height;
sourceDescription
TRUEnever evaluated
FALSEnever evaluated
0
1415 const int th = target ? target->height() : height;
targetDescription
TRUEnever evaluated
FALSEnever evaluated
0
1416-
1417 const int sx0 = sourceRect.left();-
1418 const int sx1 = sourceRect.left() + sourceRect.width();-
1419 const int sy0 = sh - (sourceRect.top() + sourceRect.height());-
1420 const int sy1 = sh - sourceRect.top();-
1421-
1422 const int tx0 = targetRect.left();-
1423 const int tx1 = targetRect.left() + targetRect.width();-
1424 const int ty0 = th - (targetRect.top() + targetRect.height());-
1425 const int ty1 = th - targetRect.top();-
1426-
1427 ctx->d_ptr->refreshCurrentFbo();-
1428-
1429 functions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : 0);-
1430 functions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : 0);-
1431-
1432 functions.glBlitFramebuffer(sx0, sy0, sx1, sy1,-
1433 tx0, ty0, tx1, ty1,-
1434 buffers, filter);-
1435-
1436 functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_ptr->current_fbo);-
1437}
never executed: end of block
0
1438-
1439QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

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