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

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