opengl/qopenglframebufferobject.cpp

Source codeSwitch to Preprocessed file
LineSource CodeCoverage
1/**************************************************************************** -
2** -
3** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). -
4** Contact: http://www.qt-project.org/legal -
5** -
6** This file is part of the QtGui 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 Digia. For licensing terms and -
14** conditions see http://qt.digia.com/licensing. For further information -
15** use the contact form at http://qt.digia.com/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 as published by the Free Software -
20** Foundation and appearing in the file LICENSE.LGPL included in the -
21** packaging of this file. Please review the following information to -
22** ensure the GNU Lesser General Public License version 2.1 requirements -
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -
24** -
25** In addition, as a special exception, Digia gives you certain additional -
26** rights. These rights are described in the Digia Qt LGPL Exception -
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -
28** -
29** GNU General Public License Usage -
30** Alternatively, this file may be used under the terms of the GNU -
31** General Public License version 3.0 as published by the Free Software -
32** Foundation and appearing in the file LICENSE.GPL included in the -
33** packaging of this file. Please review the following information to -
34** ensure the GNU General Public License version 3.0 requirements will be -
35** met: http://www.gnu.org/copyleft/gpl.html. -
36** -
37** -
38** $QT_END_LICENSE$ -
39** -
40****************************************************************************/ -
41 -
42#include "qopenglframebufferobject.h" -
43#include "qopenglframebufferobject_p.h" -
44 -
45#include <qdebug.h> -
46#include <private/qopengl_p.h> -
47#include <private/qopenglcontext_p.h> -
48#include <private/qopenglextensions_p.h> -
49#include <private/qfont_p.h> -
50 -
51#include <qwindow.h> -
52#include <qlibrary.h> -
53#include <qimage.h> -
54 -
55QT_BEGIN_NAMESPACE -
56 -
57#ifndef QT_NO_DEBUG -
58#define QT_RESET_GLERROR() \ -
59{ \ -
60 while (glGetError() != GL_NO_ERROR) {} \ -
61} -
62#define QT_CHECK_GLERROR() \ -
63{ \ -
64 GLenum err = glGetError(); \ -
65 if (err != GL_NO_ERROR) { \ -
66 qDebug("[%s line %d] OpenGL Error: %d", \ -
67 __FILE__, __LINE__, (int)err); \ -
68 } \ -
69} -
70#else -
71#define QT_RESET_GLERROR() {} -
72#define QT_CHECK_GLERROR() {} -
73#endif -
74 -
75// ####TODO Properly #ifdef this class to use #define symbols actually defined -
76// by OpenGL/ES includes -
77#ifndef GL_MAX_SAMPLES -
78#define GL_MAX_SAMPLES 0x8D57 -
79#endif -
80 -
81#ifndef GL_RENDERBUFFER_SAMPLES -
82#define GL_RENDERBUFFER_SAMPLES 0x8CAB -
83#endif -
84 -
85#ifndef GL_DEPTH24_STENCIL8 -
86#define GL_DEPTH24_STENCIL8 0x88F0 -
87#endif -
88 -
89#ifndef GL_DEPTH_COMPONENT24 -
90#define GL_DEPTH_COMPONENT24 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 QOpenGLFramebufferObjectFormat -
103 \brief The QOpenGLFramebufferObjectFormat class specifies the format of an OpenGL -
104 framebuffer object. -
105 \inmodule QtGui -
106 -
107 \since 5.0 -
108 -
109 \ingroup painting-3D -
110 -
111 A framebuffer object has several characteristics: -
112 \list -
113 \li \l{setSamples()}{Number of samples per pixels.} -
114 \li \l{setAttachment()}{Depth and/or stencil attachments.} -
115 \li \l{setTextureTarget()}{Texture target.} -
116 \li \l{setInternalTextureFormat()}{Internal texture format.} -
117 \endlist -
118 -
119 Note that the desired attachments or number of samples per pixels might not -
120 be supported by the hardware driver. Call QOpenGLFramebufferObject::format() -
121 after creating a QOpenGLFramebufferObject to find the exact format that was -
122 used to create the frame buffer object. -
123 -
124 \sa QOpenGLFramebufferObject -
125*/ -
126 -
127/*! -
128 \internal -
129*/ -
130void QOpenGLFramebufferObjectFormat::detach() -
131{ -
132 if (d->ref.load() != 1) {
never evaluated: d->ref.load() != 1
0
133 QOpenGLFramebufferObjectFormatPrivate *newd
never executed (the execution status of this line is deduced): QOpenGLFramebufferObjectFormatPrivate *newd
-
134 = new QOpenGLFramebufferObjectFormatPrivate(d);
never executed (the execution status of this line is deduced): = new QOpenGLFramebufferObjectFormatPrivate(d);
-
135 if (!d->ref.deref())
never evaluated: !d->ref.deref()
0
136 delete d;
never executed: delete d;
0
137 d = newd;
never executed (the execution status of this line is deduced): d = newd;
-
138 }
never executed: }
0
139}
never executed: }
0
140 -
141/*! -
142 Creates a QOpenGLFramebufferObjectFormat object for specifying -
143 the format of an OpenGL framebuffer object. -
144 -
145 By default the format specifies a non-multisample framebuffer object with no -
146 attachments, texture target \c GL_TEXTURE_2D, and internal format \c GL_RGBA8. -
147 On OpenGL/ES systems, the default internal format is \c GL_RGBA. -
148 -
149 \sa samples(), attachment(), internalTextureFormat() -
150*/ -
151 -
152QOpenGLFramebufferObjectFormat::QOpenGLFramebufferObjectFormat() -
153{ -
154 d = new QOpenGLFramebufferObjectFormatPrivate;
never executed (the execution status of this line is deduced): d = new QOpenGLFramebufferObjectFormatPrivate;
-
155}
never executed: }
0
156 -
157/*! -
158 Constructs a copy of \a other. -
159*/ -
160 -
161QOpenGLFramebufferObjectFormat::QOpenGLFramebufferObjectFormat(const QOpenGLFramebufferObjectFormat &other) -
162{ -
163 d = other.d;
never executed (the execution status of this line is deduced): d = other.d;
-
164 d->ref.ref();
never executed (the execution status of this line is deduced): d->ref.ref();
-
165}
never executed: }
0
166 -
167/*! -
168 Assigns \a other to this object. -
169*/ -
170 -
171QOpenGLFramebufferObjectFormat &QOpenGLFramebufferObjectFormat::operator=(const QOpenGLFramebufferObjectFormat &other) -
172{ -
173 if (d != other.d) {
never evaluated: d != other.d
0
174 other.d->ref.ref();
never executed (the execution status of this line is deduced): other.d->ref.ref();
-
175 if (!d->ref.deref())
never evaluated: !d->ref.deref()
0
176 delete d;
never executed: delete d;
0
177 d = other.d;
never executed (the execution status of this line is deduced): d = other.d;
-
178 }
never executed: }
0
179 return *this;
never executed: return *this;
0
180} -
181 -
182/*! -
183 Destroys the QOpenGLFramebufferObjectFormat. -
184*/ -
185QOpenGLFramebufferObjectFormat::~QOpenGLFramebufferObjectFormat() -
186{ -
187 if (!d->ref.deref())
never evaluated: !d->ref.deref()
0
188 delete d;
never executed: delete d;
0
189}
never executed: }
0
190 -
191/*! -
192 Sets the number of samples per pixel for a multisample framebuffer object -
193 to \a samples. The default sample count of 0 represents a regular -
194 non-multisample framebuffer object. -
195 -
196 If the desired amount of samples per pixel is not supported by the hardware -
197 then the maximum number of samples per pixel will be used. Note that -
198 multisample framebuffer objects can not be bound as textures. Also, the -
199 \c{GL_EXT_framebuffer_multisample} extension is required to create a -
200 framebuffer with more than one sample per pixel. -
201 -
202 \sa samples() -
203*/ -
204void QOpenGLFramebufferObjectFormat::setSamples(int samples) -
205{ -
206 detach();
never executed (the execution status of this line is deduced): detach();
-
207 d->samples = samples;
never executed (the execution status of this line is deduced): d->samples = samples;
-
208}
never executed: }
0
209 -
210/*! -
211 Returns the number of samples per pixel if a framebuffer object -
212 is a multisample framebuffer object. Otherwise, returns 0. -
213 The default value is 0. -
214 -
215 \sa setSamples() -
216*/ -
217int QOpenGLFramebufferObjectFormat::samples() const -
218{ -
219 return d->samples;
never executed: return d->samples;
0
220} -
221 -
222/*! -
223 Enables mipmapping if \a enabled is true; otherwise disables it. -
224 -
225 Mipmapping is disabled by default. -
226 -
227 If mipmapping is enabled, additional memory will be allocated for -
228 the mipmap levels. The mipmap levels can be updated by binding the -
229 texture and calling glGenerateMipmap(). Mipmapping cannot be enabled -
230 for multisampled framebuffer objects. -
231 -
232 \sa mipmap(), QOpenGLFramebufferObject::texture() -
233*/ -
234void QOpenGLFramebufferObjectFormat::setMipmap(bool enabled) -
235{ -
236 detach();
never executed (the execution status of this line is deduced): detach();
-
237 d->mipmap = enabled;
never executed (the execution status of this line is deduced): d->mipmap = enabled;
-
238}
never executed: }
0
239 -
240/*! -
241 Returns true if mipmapping is enabled. -
242 -
243 \sa setMipmap() -
244*/ -
245bool QOpenGLFramebufferObjectFormat::mipmap() const -
246{ -
247 return d->mipmap;
never executed: return d->mipmap;
0
248} -
249 -
250/*! -
251 Sets the attachment configuration of a framebuffer object to \a attachment. -
252 -
253 \sa attachment() -
254*/ -
255void QOpenGLFramebufferObjectFormat::setAttachment(QOpenGLFramebufferObject::Attachment attachment) -
256{ -
257 detach();
never executed (the execution status of this line is deduced): detach();
-
258 d->attachment = attachment;
never executed (the execution status of this line is deduced): d->attachment = attachment;
-
259}
never executed: }
0
260 -
261/*! -
262 Returns the configuration of the depth and stencil buffers attached to -
263 a framebuffer object. The default is QOpenGLFramebufferObject::NoAttachment. -
264 -
265 \sa setAttachment() -
266*/ -
267QOpenGLFramebufferObject::Attachment QOpenGLFramebufferObjectFormat::attachment() const -
268{ -
269 return d->attachment;
never executed: return d->attachment;
0
270} -
271 -
272/*! -
273 Sets the texture target of the texture attached to a framebuffer object to -
274 \a target. Ignored for multisample framebuffer objects. -
275 -
276 \sa textureTarget(), samples() -
277*/ -
278void QOpenGLFramebufferObjectFormat::setTextureTarget(GLenum target) -
279{ -
280 detach();
never executed (the execution status of this line is deduced): detach();
-
281 d->target = target;
never executed (the execution status of this line is deduced): d->target = target;
-
282}
never executed: }
0
283 -
284/*! -
285 Returns the texture target of the texture attached to a framebuffer object. -
286 Ignored for multisample framebuffer objects. The default is -
287 \c GL_TEXTURE_2D. -
288 -
289 \sa setTextureTarget(), samples() -
290*/ -
291GLenum QOpenGLFramebufferObjectFormat::textureTarget() const -
292{ -
293 return d->target;
never executed: return d->target;
0
294} -
295 -
296/*! -
297 Sets the internal format of a framebuffer object's texture or -
298 multisample framebuffer object's color buffer to -
299 \a internalTextureFormat. -
300 -
301 \sa internalTextureFormat() -
302*/ -
303void QOpenGLFramebufferObjectFormat::setInternalTextureFormat(GLenum internalTextureFormat) -
304{ -
305 detach();
never executed (the execution status of this line is deduced): detach();
-
306 d->internal_format = internalTextureFormat;
never executed (the execution status of this line is deduced): d->internal_format = internalTextureFormat;
-
307}
never executed: }
0
308 -
309/*! -
310 Returns the internal format of a framebuffer object's texture or -
311 multisample framebuffer object's color buffer. The default is -
312 \c GL_RGBA8 on desktop OpenGL systems, and \c GL_RGBA on -
313 OpenGL/ES systems. -
314 -
315 \sa setInternalTextureFormat() -
316*/ -
317GLenum QOpenGLFramebufferObjectFormat::internalTextureFormat() const -
318{ -
319 return d->internal_format;
never executed: return d->internal_format;
0
320} -
321 -
322/*! -
323 Returns true if all the options of this framebuffer object format -
324 are the same as \a other; otherwise returns false. -
325*/ -
326bool QOpenGLFramebufferObjectFormat::operator==(const QOpenGLFramebufferObjectFormat& other) const -
327{ -
328 if (d == other.d)
never evaluated: d == other.d
0
329 return true;
never executed: return true;
0
330 else -
331 return d->equals(other.d);
never executed: return d->equals(other.d);
0
332} -
333 -
334/*! -
335 Returns false if all the options of this framebuffer object format -
336 are the same as \a other; otherwise returns true. -
337*/ -
338bool QOpenGLFramebufferObjectFormat::operator!=(const QOpenGLFramebufferObjectFormat& other) const -
339{ -
340 return !(*this == other);
never executed: return !(*this == other);
0
341} -
342 -
343bool QOpenGLFramebufferObjectPrivate::checkFramebufferStatus(QOpenGLContext *ctx) const -
344{ -
345 if (!ctx)
never evaluated: !ctx
0
346 return false; // Context no longer exists.
never executed: return false;
0
347 GLenum status = ctx->functions()->glCheckFramebufferStatus(GL_FRAMEBUFFER);
never executed (the execution status of this line is deduced): GLenum status = ctx->functions()->glCheckFramebufferStatus(0x8D40);
-
348 switch(status) { -
349 case GL_NO_ERROR: -
350 case GL_FRAMEBUFFER_COMPLETE: -
351 return true;
never executed: return true;
0
352 case GL_FRAMEBUFFER_UNSUPPORTED: -
353 qDebug("QOpenGLFramebufferObject: Unsupported framebuffer format.");
never executed (the execution status of this line is deduced): QMessageLogger("opengl/qopenglframebufferobject.cpp", 353, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Unsupported framebuffer format.");
-
354 break;
never executed: break;
0
355 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: -
356 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete attachment.");
never executed (the execution status of this line is deduced): QMessageLogger("opengl/qopenglframebufferobject.cpp", 356, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Framebuffer incomplete attachment.");
-
357 break;
never executed: break;
0
358 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: -
359 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment.");
never executed (the execution status of this line is deduced): QMessageLogger("opengl/qopenglframebufferobject.cpp", 359, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Framebuffer incomplete, missing attachment.");
-
360 break;
never executed: break;
0
361#ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT -
362 case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT: -
363 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, duplicate attachment."); -
364 break; -
365#endif -
366#ifdef GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS -
367 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS: -
368 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attached images must have same dimensions."); -
369 break; -
370#endif -
371#ifdef GL_FRAMEBUFFER_INCOMPLETE_FORMATS -
372 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS: -
373 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attached images must have same format."); -
374 break; -
375#endif -
376#ifdef GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER -
377 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: -
378 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing draw buffer.");
never executed (the execution status of this line is deduced): QMessageLogger("opengl/qopenglframebufferobject.cpp", 378, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Framebuffer incomplete, missing draw buffer.");
-
379 break;
never executed: break;
0
380#endif -
381#ifdef GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER -
382 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: -
383 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, missing read buffer.");
never executed (the execution status of this line is deduced): QMessageLogger("opengl/qopenglframebufferobject.cpp", 383, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Framebuffer incomplete, missing read buffer.");
-
384 break;
never executed: break;
0
385#endif -
386#ifdef GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE -
387 case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: -
388 qDebug("QOpenGLFramebufferObject: Framebuffer incomplete, attachments must have same number of samples per pixel.");
never executed (the execution status of this line is deduced): QMessageLogger("opengl/qopenglframebufferobject.cpp", 388, __PRETTY_FUNCTION__).debug("QOpenGLFramebufferObject: Framebuffer incomplete, attachments must have same number of samples per pixel.");
-
389 break;
never executed: break;
0
390#endif -
391 default: -
392 qDebug() <<"QOpenGLFramebufferObject: An undefined error has occurred: "<< status;
never executed (the execution status of this line is deduced): QMessageLogger("opengl/qopenglframebufferobject.cpp", 392, __PRETTY_FUNCTION__).debug() <<"QOpenGLFramebufferObject: An undefined error has occurred: "<< status;
-
393 break;
never executed: break;
0
394 } -
395 return false;
never executed: return false;
0
396} -
397 -
398namespace -
399{ -
400 void freeFramebufferFunc(QOpenGLFunctions *funcs, GLuint id) -
401 { -
402 funcs->glDeleteFramebuffers(1, &id);
never executed (the execution status of this line is deduced): funcs->glDeleteFramebuffers(1, &id);
-
403 }
never executed: }
0
404 -
405 void freeRenderbufferFunc(QOpenGLFunctions *funcs, GLuint id) -
406 { -
407 funcs->glDeleteRenderbuffers(1, &id);
never executed (the execution status of this line is deduced): funcs->glDeleteRenderbuffers(1, &id);
-
408 }
never executed: }
0
409 -
410 void freeTextureFunc(QOpenGLFunctions *, GLuint id) -
411 { -
412 glDeleteTextures(1, &id);
never executed (the execution status of this line is deduced): glDeleteTextures(1, &id);
-
413 }
never executed: }
0
414} -
415 -
416void QOpenGLFramebufferObjectPrivate::init(QOpenGLFramebufferObject *, const QSize &sz, -
417 QOpenGLFramebufferObject::Attachment attachment, -
418 GLenum texture_target, GLenum internal_format, -
419 GLint samples, bool mipmap) -
420{ -
421 QOpenGLContext *ctx = QOpenGLContext::currentContext();
never executed (the execution status of this line is deduced): QOpenGLContext *ctx = QOpenGLContext::currentContext();
-
422 -
423 funcs.initializeOpenGLFunctions();
never executed (the execution status of this line is deduced): funcs.initializeOpenGLFunctions();
-
424 -
425 if (!funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers))
never evaluated: !funcs.hasOpenGLFeature(QOpenGLFunctions::Framebuffers)
0
426 return;
never executed: return;
0
427 -
428 size = sz;
never executed (the execution status of this line is deduced): size = sz;
-
429 target = texture_target;
never executed (the execution status of this line is deduced): target = texture_target;
-
430 // texture dimensions -
431 -
432 QT_RESET_GLERROR(); // reset error state -
433 GLuint fbo = 0;
never executed (the execution status of this line is deduced): GLuint fbo = 0;
-
434 -
435 funcs.glGenFramebuffers(1, &fbo);
never executed (the execution status of this line is deduced): funcs.glGenFramebuffers(1, &fbo);
-
436 funcs.glBindFramebuffer(GL_FRAMEBUFFER, fbo);
never executed (the execution status of this line is deduced): funcs.glBindFramebuffer(0x8D40, fbo);
-
437 -
438 GLuint texture = 0;
never executed (the execution status of this line is deduced): GLuint texture = 0;
-
439 GLuint color_buffer = 0;
never executed (the execution status of this line is deduced): GLuint color_buffer = 0;
-
440 -
441 QT_CHECK_GLERROR(); -
442 // init texture -
443 if (samples == 0) {
never evaluated: samples == 0
0
444 glGenTextures(1, &texture);
never executed (the execution status of this line is deduced): glGenTextures(1, &texture);
-
445 glBindTexture(target, texture);
never executed (the execution status of this line is deduced): glBindTexture(target, texture);
-
446 -
447 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
never executed (the execution status of this line is deduced): glTexParameteri(target, 0x2801, 0x2600);
-
448 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
never executed (the execution status of this line is deduced): glTexParameteri(target, 0x2800, 0x2600);
-
449 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
never executed (the execution status of this line is deduced): glTexParameteri(target, 0x2802, 0x812F);
-
450 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
never executed (the execution status of this line is deduced): glTexParameteri(target, 0x2803, 0x812F);
-
451 -
452 glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
never executed (the execution status of this line is deduced): glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
-
453 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
never executed (the execution status of this line is deduced): 0x1908, 0x1401, __null);
-
454 if (mipmap) {
never evaluated: mipmap
0
455 int width = size.width();
never executed (the execution status of this line is deduced): int width = size.width();
-
456 int height = size.height();
never executed (the execution status of this line is deduced): int height = size.height();
-
457 int level = 0;
never executed (the execution status of this line is deduced): int level = 0;
-
458 while (width > 1 || height > 1) {
never evaluated: width > 1
never evaluated: height > 1
0
459 width = qMax(1, width >> 1);
never executed (the execution status of this line is deduced): width = qMax(1, width >> 1);
-
460 height = qMax(1, height >> 1);
never executed (the execution status of this line is deduced): height = qMax(1, height >> 1);
-
461 ++level;
never executed (the execution status of this line is deduced): ++level;
-
462 glTexImage2D(target, level, internal_format, width, height, 0,
never executed (the execution status of this line is deduced): glTexImage2D(target, level, internal_format, width, height, 0,
-
463 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
never executed (the execution status of this line is deduced): 0x1908, 0x1401, __null);
-
464 }
never executed: }
0
465 }
never executed: }
0
466 funcs.glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
never executed (the execution status of this line is deduced): funcs.glFramebufferTexture2D(0x8D40, 0x8CE0,
-
467 target, texture, 0);
never executed (the execution status of this line is deduced): target, texture, 0);
-
468 -
469 QT_CHECK_GLERROR(); -
470 valid = checkFramebufferStatus(ctx);
never executed (the execution status of this line is deduced): valid = checkFramebufferStatus(ctx);
-
471 glBindTexture(target, 0);
never executed (the execution status of this line is deduced): glBindTexture(target, 0);
-
472 -
473 color_buffer = 0;
never executed (the execution status of this line is deduced): color_buffer = 0;
-
474 } else {
never executed: }
0
475 mipmap = false;
never executed (the execution status of this line is deduced): mipmap = false;
-
476 GLint maxSamples;
never executed (the execution status of this line is deduced): GLint maxSamples;
-
477 glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
never executed (the execution status of this line is deduced): glGetIntegerv(0x8D57, &maxSamples);
-
478 -
479 samples = qBound(0, int(samples), int(maxSamples));
never executed (the execution status of this line is deduced): samples = qBound(0, int(samples), int(maxSamples));
-
480 -
481 funcs.glGenRenderbuffers(1, &color_buffer);
never executed (the execution status of this line is deduced): funcs.glGenRenderbuffers(1, &color_buffer);
-
482 funcs.glBindRenderbuffer(GL_RENDERBUFFER, color_buffer);
never executed (the execution status of this line is deduced): funcs.glBindRenderbuffer(0x8D41, color_buffer);
-
483 if (funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample) && samples > 0) {
never evaluated: funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
never evaluated: samples > 0
0
484 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
never executed (the execution status of this line is deduced): funcs.glRenderbufferStorageMultisample(0x8D41, samples,
-
485 internal_format, size.width(), size.height());
never executed (the execution status of this line is deduced): internal_format, size.width(), size.height());
-
486 } else {
never executed: }
0
487 samples = 0;
never executed (the execution status of this line is deduced): samples = 0;
-
488 funcs.glRenderbufferStorage(GL_RENDERBUFFER, internal_format,
never executed (the execution status of this line is deduced): funcs.glRenderbufferStorage(0x8D41, internal_format,
-
489 size.width(), size.height());
never executed (the execution status of this line is deduced): size.width(), size.height());
-
490 }
never executed: }
0
491 -
492 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
never executed (the execution status of this line is deduced): funcs.glFramebufferRenderbuffer(0x8D40, 0x8CE0,
-
493 GL_RENDERBUFFER, color_buffer);
never executed (the execution status of this line is deduced): 0x8D41, color_buffer);
-
494 -
495 QT_CHECK_GLERROR(); -
496 valid = checkFramebufferStatus(ctx);
never executed (the execution status of this line is deduced): valid = checkFramebufferStatus(ctx);
-
497 -
498 if (valid)
never evaluated: valid
0
499 funcs.glGetRenderbufferParameteriv(GL_RENDERBUFFER, GL_RENDERBUFFER_SAMPLES, &samples);
never executed: funcs.glGetRenderbufferParameteriv(0x8D41, 0x8CAB, &samples);
0
500 }
never executed: }
0
501 -
502 format.setTextureTarget(target);
never executed (the execution status of this line is deduced): format.setTextureTarget(target);
-
503 format.setSamples(int(samples));
never executed (the execution status of this line is deduced): format.setSamples(int(samples));
-
504 format.setInternalTextureFormat(internal_format);
never executed (the execution status of this line is deduced): format.setInternalTextureFormat(internal_format);
-
505 format.setMipmap(mipmap);
never executed (the execution status of this line is deduced): format.setMipmap(mipmap);
-
506 -
507 initAttachments(ctx, attachment);
never executed (the execution status of this line is deduced): initAttachments(ctx, attachment);
-
508 -
509 funcs.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->current_fbo);
never executed (the execution status of this line is deduced): funcs.glBindFramebuffer(0x8D40, ctx->d_func()->current_fbo);
-
510 if (valid) {
never evaluated: valid
0
511 fbo_guard = new QOpenGLSharedResourceGuard(ctx, fbo, freeFramebufferFunc);
never executed (the execution status of this line is deduced): fbo_guard = new QOpenGLSharedResourceGuard(ctx, fbo, freeFramebufferFunc);
-
512 if (color_buffer)
never evaluated: color_buffer
0
513 color_buffer_guard = new QOpenGLSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc);
never executed: color_buffer_guard = new QOpenGLSharedResourceGuard(ctx, color_buffer, freeRenderbufferFunc);
0
514 else -
515 texture_guard = new QOpenGLSharedResourceGuard(ctx, texture, freeTextureFunc);
never executed: texture_guard = new QOpenGLSharedResourceGuard(ctx, texture, freeTextureFunc);
0
516 } else { -
517 if (color_buffer)
never evaluated: color_buffer
0
518 funcs.glDeleteRenderbuffers(1, &color_buffer);
never executed: funcs.glDeleteRenderbuffers(1, &color_buffer);
0
519 else -
520 glDeleteTextures(1, &texture);
never executed: glDeleteTextures(1, &texture);
0
521 funcs.glDeleteFramebuffers(1, &fbo);
never executed (the execution status of this line is deduced): funcs.glDeleteFramebuffers(1, &fbo);
-
522 }
never executed: }
0
523 QT_CHECK_GLERROR(); -
524} -
525 -
526void QOpenGLFramebufferObjectPrivate::initAttachments(QOpenGLContext *ctx, QOpenGLFramebufferObject::Attachment attachment) -
527{ -
528 int samples = format.samples();
never executed (the execution status of this line is deduced): int samples = format.samples();
-
529 -
530 // free existing attachments -
531 if (depth_buffer_guard) {
never evaluated: depth_buffer_guard
0
532 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
never executed (the execution status of this line is deduced): funcs.glFramebufferRenderbuffer(0x8D40, 0x8D00, 0x8D41, 0);
-
533 depth_buffer_guard->free();
never executed (the execution status of this line is deduced): depth_buffer_guard->free();
-
534 }
never executed: }
0
535 if (stencil_buffer_guard) {
never evaluated: stencil_buffer_guard
0
536 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, 0);
never executed (the execution status of this line is deduced): funcs.glFramebufferRenderbuffer(0x8D40, 0x8D20, 0x8D41, 0);
-
537 if (stencil_buffer_guard != depth_buffer_guard)
never evaluated: stencil_buffer_guard != depth_buffer_guard
0
538 stencil_buffer_guard->free();
never executed: stencil_buffer_guard->free();
0
539 }
never executed: }
0
540 -
541 depth_buffer_guard = 0;
never executed (the execution status of this line is deduced): depth_buffer_guard = 0;
-
542 stencil_buffer_guard = 0;
never executed (the execution status of this line is deduced): stencil_buffer_guard = 0;
-
543 -
544 GLuint depth_buffer = 0;
never executed (the execution status of this line is deduced): GLuint depth_buffer = 0;
-
545 GLuint stencil_buffer = 0;
never executed (the execution status of this line is deduced): GLuint stencil_buffer = 0;
-
546 -
547 // In practice, a combined depth-stencil buffer is supported by all desktop platforms, while a -
548 // separate stencil buffer is not. On embedded devices however, a combined depth-stencil buffer -
549 // might not be supported while separate buffers are, according to QTBUG-12861. -
550 -
551 if (attachment == QOpenGLFramebufferObject::CombinedDepthStencil
never evaluated: attachment == QOpenGLFramebufferObject::CombinedDepthStencil
0
552 && funcs.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil))
never evaluated: funcs.hasOpenGLExtension(QOpenGLExtensions::PackedDepthStencil)
0
553 { -
554 // depth and stencil buffer needs another extension -
555 funcs.glGenRenderbuffers(1, &depth_buffer);
never executed (the execution status of this line is deduced): funcs.glGenRenderbuffers(1, &depth_buffer);
-
556 funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
never executed (the execution status of this line is deduced): funcs.glBindRenderbuffer(0x8D41, depth_buffer);
-
557 Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
never executed (the execution status of this line is deduced): qt_noop();
-
558 if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
never evaluated: samples != 0
never evaluated: funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
0
559 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x88F0, size.width(), size.height());
0
560 GL_DEPTH24_STENCIL8, size.width(), size.height());
never executed: funcs.glRenderbufferStorageMultisample(0x8D41, samples, 0x88F0, size.width(), size.height());
0
561 else -
562 funcs.glRenderbufferStorage(GL_RENDERBUFFER,
never executed: funcs.glRenderbufferStorage(0x8D41, 0x88F0, size.width(), size.height());
0
563 GL_DEPTH24_STENCIL8, size.width(), size.height());
never executed: funcs.glRenderbufferStorage(0x8D41, 0x88F0, size.width(), size.height());
0
564 -
565 stencil_buffer = depth_buffer;
never executed (the execution status of this line is deduced): stencil_buffer = depth_buffer;
-
566 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
never executed (the execution status of this line is deduced): funcs.glFramebufferRenderbuffer(0x8D40, 0x8D00,
-
567 GL_RENDERBUFFER, depth_buffer);
never executed (the execution status of this line is deduced): 0x8D41, depth_buffer);
-
568 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
never executed (the execution status of this line is deduced): funcs.glFramebufferRenderbuffer(0x8D40, 0x8D20,
-
569 GL_RENDERBUFFER, stencil_buffer);
never executed (the execution status of this line is deduced): 0x8D41, stencil_buffer);
-
570 -
571 valid = checkFramebufferStatus(ctx);
never executed (the execution status of this line is deduced): valid = checkFramebufferStatus(ctx);
-
572 if (!valid) {
never evaluated: !valid
0
573 funcs.glDeleteRenderbuffers(1, &depth_buffer);
never executed (the execution status of this line is deduced): funcs.glDeleteRenderbuffers(1, &depth_buffer);
-
574 stencil_buffer = depth_buffer = 0;
never executed (the execution status of this line is deduced): stencil_buffer = depth_buffer = 0;
-
575 }
never executed: }
0
576 }
never executed: }
0
577 -
578 if (depth_buffer == 0 && (attachment == QOpenGLFramebufferObject::CombinedDepthStencil
never evaluated: depth_buffer == 0
never evaluated: attachment == QOpenGLFramebufferObject::CombinedDepthStencil
0
579 || (attachment == QOpenGLFramebufferObject::Depth)))
never evaluated: (attachment == QOpenGLFramebufferObject::Depth)
0
580 { -
581 funcs.glGenRenderbuffers(1, &depth_buffer);
never executed (the execution status of this line is deduced): funcs.glGenRenderbuffers(1, &depth_buffer);
-
582 funcs.glBindRenderbuffer(GL_RENDERBUFFER, depth_buffer);
never executed (the execution status of this line is deduced): funcs.glBindRenderbuffer(0x8D41, depth_buffer);
-
583 Q_ASSERT(funcs.glIsRenderbuffer(depth_buffer));
never executed (the execution status of this line is deduced): qt_noop();
-
584 if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) {
never evaluated: samples != 0
never evaluated: funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
0
585#ifdef QT_OPENGL_ES -
586 if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24)) { -
587 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, -
588 GL_DEPTH_COMPONENT24, size.width(), size.height()); -
589 } else { -
590 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, -
591 GL_DEPTH_COMPONENT16, size.width(), size.height()); -
592 } -
593#else -
594 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
never executed (the execution status of this line is deduced): funcs.glRenderbufferStorageMultisample(0x8D41, samples,
-
595 GL_DEPTH_COMPONENT, size.width(), size.height());
never executed (the execution status of this line is deduced): 0x1902, size.width(), size.height());
-
596#endif -
597 } else {
never executed: }
0
598#ifdef QT_OPENGL_ES -
599 if (funcs.hasOpenGLExtension(QOpenGLExtensions::Depth24)) { -
600 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT24, -
601 size.width(), size.height()); -
602 } else { -
603 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, -
604 size.width(), size.height()); -
605 } -
606#else -
607 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT, size.width(), size.height());
never executed (the execution status of this line is deduced): funcs.glRenderbufferStorage(0x8D41, 0x1902, size.width(), size.height());
-
608#endif -
609 }
never executed: }
0
610 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
never executed (the execution status of this line is deduced): funcs.glFramebufferRenderbuffer(0x8D40, 0x8D00,
-
611 GL_RENDERBUFFER, depth_buffer);
never executed (the execution status of this line is deduced): 0x8D41, depth_buffer);
-
612 valid = checkFramebufferStatus(ctx);
never executed (the execution status of this line is deduced): valid = checkFramebufferStatus(ctx);
-
613 if (!valid) {
never evaluated: !valid
0
614 funcs.glDeleteRenderbuffers(1, &depth_buffer);
never executed (the execution status of this line is deduced): funcs.glDeleteRenderbuffers(1, &depth_buffer);
-
615 depth_buffer = 0;
never executed (the execution status of this line is deduced): depth_buffer = 0;
-
616 }
never executed: }
0
617 }
never executed: }
0
618 -
619 if (stencil_buffer == 0 && (attachment == QOpenGLFramebufferObject::CombinedDepthStencil)) {
never evaluated: stencil_buffer == 0
never evaluated: (attachment == QOpenGLFramebufferObject::CombinedDepthStencil)
0
620 funcs.glGenRenderbuffers(1, &stencil_buffer);
never executed (the execution status of this line is deduced): funcs.glGenRenderbuffers(1, &stencil_buffer);
-
621 funcs.glBindRenderbuffer(GL_RENDERBUFFER, stencil_buffer);
never executed (the execution status of this line is deduced): funcs.glBindRenderbuffer(0x8D41, stencil_buffer);
-
622 Q_ASSERT(funcs.glIsRenderbuffer(stencil_buffer));
never executed (the execution status of this line is deduced): qt_noop();
-
623 if (samples != 0 && funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) {
never evaluated: samples != 0
never evaluated: funcs.hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)
0
624#ifdef QT_OPENGL_ES -
625 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples, -
626 GL_STENCIL_INDEX8, size.width(), size.height()); -
627#else -
628 funcs.glRenderbufferStorageMultisample(GL_RENDERBUFFER, samples,
never executed (the execution status of this line is deduced): funcs.glRenderbufferStorageMultisample(0x8D41, samples,
-
629 GL_STENCIL_INDEX, size.width(), size.height());
never executed (the execution status of this line is deduced): 0x1901, size.width(), size.height());
-
630#endif -
631 } else {
never executed: }
0
632#ifdef QT_OPENGL_ES -
633 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX8, -
634 size.width(), size.height()); -
635#else -
636 funcs.glRenderbufferStorage(GL_RENDERBUFFER, GL_STENCIL_INDEX,
never executed (the execution status of this line is deduced): funcs.glRenderbufferStorage(0x8D41, 0x1901,
-
637 size.width(), size.height());
never executed (the execution status of this line is deduced): size.width(), size.height());
-
638#endif -
639 }
never executed: }
0
640 funcs.glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
never executed (the execution status of this line is deduced): funcs.glFramebufferRenderbuffer(0x8D40, 0x8D20,
-
641 GL_RENDERBUFFER, stencil_buffer);
never executed (the execution status of this line is deduced): 0x8D41, stencil_buffer);
-
642 valid = checkFramebufferStatus(ctx);
never executed (the execution status of this line is deduced): valid = checkFramebufferStatus(ctx);
-
643 if (!valid) {
never evaluated: !valid
0
644 funcs.glDeleteRenderbuffers(1, &stencil_buffer);
never executed (the execution status of this line is deduced): funcs.glDeleteRenderbuffers(1, &stencil_buffer);
-
645 stencil_buffer = 0;
never executed (the execution status of this line is deduced): stencil_buffer = 0;
-
646 }
never executed: }
0
647 }
never executed: }
0
648 -
649 // The FBO might have become valid after removing the depth or stencil buffer. -
650 valid = checkFramebufferStatus(ctx);
never executed (the execution status of this line is deduced): valid = checkFramebufferStatus(ctx);
-
651 -
652 if (depth_buffer && stencil_buffer) {
never evaluated: depth_buffer
never evaluated: stencil_buffer
0
653 fbo_attachment = QOpenGLFramebufferObject::CombinedDepthStencil;
never executed (the execution status of this line is deduced): fbo_attachment = QOpenGLFramebufferObject::CombinedDepthStencil;
-
654 } else if (depth_buffer) {
never executed: }
never evaluated: depth_buffer
0
655 fbo_attachment = QOpenGLFramebufferObject::Depth;
never executed (the execution status of this line is deduced): fbo_attachment = QOpenGLFramebufferObject::Depth;
-
656 } else {
never executed: }
0
657 fbo_attachment = QOpenGLFramebufferObject::NoAttachment;
never executed (the execution status of this line is deduced): fbo_attachment = QOpenGLFramebufferObject::NoAttachment;
-
658 }
never executed: }
0
659 -
660 if (valid) {
never evaluated: valid
0
661 if (depth_buffer)
never evaluated: depth_buffer
0
662 depth_buffer_guard = new QOpenGLSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc);
never executed: depth_buffer_guard = new QOpenGLSharedResourceGuard(ctx, depth_buffer, freeRenderbufferFunc);
0
663 if (stencil_buffer) {
never evaluated: stencil_buffer
0
664 if (stencil_buffer == depth_buffer)
never evaluated: stencil_buffer == depth_buffer
0
665 stencil_buffer_guard = depth_buffer_guard;
never executed: stencil_buffer_guard = depth_buffer_guard;
0
666 else -
667 stencil_buffer_guard = new QOpenGLSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc);
never executed: stencil_buffer_guard = new QOpenGLSharedResourceGuard(ctx, stencil_buffer, freeRenderbufferFunc);
0
668 } -
669 } else {
never executed: }
0
670 if (depth_buffer)
never evaluated: depth_buffer
0
671 funcs.glDeleteRenderbuffers(1, &depth_buffer);
never executed: funcs.glDeleteRenderbuffers(1, &depth_buffer);
0
672 if (stencil_buffer && depth_buffer != stencil_buffer)
never evaluated: stencil_buffer
never evaluated: depth_buffer != stencil_buffer
0
673 funcs.glDeleteRenderbuffers(1, &stencil_buffer);
never executed: funcs.glDeleteRenderbuffers(1, &stencil_buffer);
0
674 }
never executed: }
0
675 QT_CHECK_GLERROR(); -
676 -
677 format.setAttachment(fbo_attachment);
never executed (the execution status of this line is deduced): format.setAttachment(fbo_attachment);
-
678}
never executed: }
0
679 -
680/*! -
681 \class QOpenGLFramebufferObject -
682 \brief The QOpenGLFramebufferObject class encapsulates an OpenGL framebuffer object. -
683 \since 5.0 -
684 \inmodule QtGui -
685 -
686 \ingroup painting-3D -
687 -
688 The QOpenGLFramebufferObject class encapsulates an OpenGL framebuffer -
689 object, defined by the \c{GL_EXT_framebuffer_object} extension. It provides -
690 a rendering surface that can be painted on with a QPainter with the help of -
691 QOpenGLPaintDevice, or rendered to using native OpenGL calls. This surface -
692 can be bound and used as a regular texture in your own OpenGL drawing code. -
693 By default, the QOpenGLFramebufferObject class generates a 2D OpenGL -
694 texture (using the \c{GL_TEXTURE_2D} target), which is used as the internal -
695 rendering target. -
696 -
697 \b{It is important to have a current OpenGL context when creating a -
698 QOpenGLFramebufferObject, otherwise initialization will fail.} -
699 -
700 Create the QOpenGLFrameBufferObject instance with the CombinedDepthStencil -
701 attachment if you want QPainter to render correctly. Note that you need to -
702 create a QOpenGLFramebufferObject with more than one sample per pixel for -
703 primitives to be antialiased when drawing using a QPainter. To create a -
704 multisample framebuffer object you should use one of the constructors that -
705 take a QOpenGLFramebufferObjectFormat parameter, and set the -
706 QOpenGLFramebufferObjectFormat::samples() property to a non-zero value. -
707 -
708 For multisample framebuffer objects a color render buffer is created, -
709 otherwise a texture with the specified texture target is created. -
710 The color render buffer or texture will have the specified internal -
711 format, and will be bound to the \c GL_COLOR_ATTACHMENT0 -
712 attachment in the framebuffer object. -
713 -
714 If you want to use a framebuffer object with multisampling enabled -
715 as a texture, you first need to copy from it to a regular framebuffer -
716 object using QOpenGLContext::blitFramebuffer(). -
717 -
718 It is possible to draw into a QOpenGLFramebufferObject using QPainter and -
719 QOpenGLPaintDevice in a separate thread. -
720*/ -
721 -
722 -
723/*! -
724 \enum QOpenGLFramebufferObject::Attachment -
725 -
726 This enum type is used to configure the depth and stencil buffers -
727 attached to the framebuffer object when it is created. -
728 -
729 \value NoAttachment No attachment is added to the framebuffer object. Note that the -
730 OpenGL depth and stencil tests won't work when rendering to a -
731 framebuffer object without any depth or stencil buffers. -
732 This is the default value. -
733 -
734 \value CombinedDepthStencil If the \c GL_EXT_packed_depth_stencil extension is present, -
735 a combined depth and stencil buffer is attached. -
736 If the extension is not present, only a depth buffer is attached. -
737 -
738 \value Depth A depth buffer is attached to the framebuffer object. -
739 -
740 \sa attachment() -
741*/ -
742 -
743 -
744/*! \fn QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, GLenum target) -
745 -
746 Constructs an OpenGL framebuffer object and binds a 2D OpenGL texture -
747 to the buffer of the size \a size. The texture is bound to the -
748 \c GL_COLOR_ATTACHMENT0 target in the framebuffer object. -
749 -
750 The \a target parameter is used to specify the OpenGL texture -
751 target. The default target is \c GL_TEXTURE_2D. Keep in mind that -
752 \c GL_TEXTURE_2D textures must have a power of 2 width and height -
753 (e.g. 256x512), unless you are using OpenGL 2.0 or higher. -
754 -
755 By default, no depth and stencil buffers are attached. This behavior -
756 can be toggled using one of the overloaded constructors. -
757 -
758 The default internal texture format is \c GL_RGBA8 for desktop -
759 OpenGL, and \c GL_RGBA for OpenGL/ES. -
760 -
761 It is important that you have a current OpenGL context set when -
762 creating the QOpenGLFramebufferObject, otherwise the initialization -
763 will fail. -
764 -
765 \sa size(), texture(), attachment() -
766*/ -
767 -
768QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, GLenum target) -
769 : d_ptr(new QOpenGLFramebufferObjectPrivate) -
770{ -
771 Q_D(QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): QOpenGLFramebufferObjectPrivate * const d = d_func();
-
772 d->init(this, size, NoAttachment, target, DEFAULT_FORMAT);
never executed (the execution status of this line is deduced): d->init(this, size, NoAttachment, target, 0x8058);
-
773}
never executed: }
0
774 -
775/*! \overload -
776 -
777 Constructs an OpenGL framebuffer object and binds a 2D OpenGL texture -
778 to the buffer of the given \a width and \a height. -
779 -
780 \sa size(), texture() -
781*/ -
782QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, GLenum target) -
783 : d_ptr(new QOpenGLFramebufferObjectPrivate) -
784{ -
785 Q_D(QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): QOpenGLFramebufferObjectPrivate * const d = d_func();
-
786 d->init(this, QSize(width, height), NoAttachment, target, DEFAULT_FORMAT);
never executed (the execution status of this line is deduced): d->init(this, QSize(width, height), NoAttachment, target, 0x8058);
-
787}
never executed: }
0
788 -
789/*! \overload -
790 -
791 Constructs an OpenGL framebuffer object of the given \a size based on the -
792 supplied \a format. -
793*/ -
794 -
795QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, const QOpenGLFramebufferObjectFormat &format) -
796 : d_ptr(new QOpenGLFramebufferObjectPrivate) -
797{ -
798 Q_D(QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): QOpenGLFramebufferObjectPrivate * const d = d_func();
-
799 d->init(this, size, format.attachment(), format.textureTarget(), format.internalTextureFormat(),
never executed (the execution status of this line is deduced): d->init(this, size, format.attachment(), format.textureTarget(), format.internalTextureFormat(),
-
800 format.samples(), format.mipmap());
never executed (the execution status of this line is deduced): format.samples(), format.mipmap());
-
801}
never executed: }
0
802 -
803/*! \overload -
804 -
805 Constructs an OpenGL framebuffer object of the given \a width and \a height -
806 based on the supplied \a format. -
807*/ -
808 -
809QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, const QOpenGLFramebufferObjectFormat &format) -
810 : d_ptr(new QOpenGLFramebufferObjectPrivate) -
811{ -
812 Q_D(QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): QOpenGLFramebufferObjectPrivate * const d = d_func();
-
813 d->init(this, QSize(width, height), format.attachment(), format.textureTarget(),
never executed (the execution status of this line is deduced): d->init(this, QSize(width, height), format.attachment(), format.textureTarget(),
-
814 format.internalTextureFormat(), format.samples(), format.mipmap());
never executed (the execution status of this line is deduced): format.internalTextureFormat(), format.samples(), format.mipmap());
-
815}
never executed: }
0
816 -
817/*! \overload -
818 -
819 Constructs an OpenGL framebuffer object and binds a texture to the -
820 buffer of the given \a width and \a height. -
821 -
822 The \a attachment parameter describes the depth/stencil buffer -
823 configuration, \a target the texture target and \a internal_format -
824 the internal texture format. The default texture target is \c -
825 GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8 -
826 for desktop OpenGL and \c GL_RGBA for OpenGL/ES. -
827 -
828 \sa size(), texture(), attachment() -
829*/ -
830QOpenGLFramebufferObject::QOpenGLFramebufferObject(int width, int height, Attachment attachment, -
831 GLenum target, GLenum internal_format) -
832 : d_ptr(new QOpenGLFramebufferObjectPrivate) -
833{ -
834 Q_D(QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): QOpenGLFramebufferObjectPrivate * const d = d_func();
-
835 d->init(this, QSize(width, height), attachment, target, internal_format);
never executed (the execution status of this line is deduced): d->init(this, QSize(width, height), attachment, target, internal_format);
-
836}
never executed: }
0
837 -
838/*! \overload -
839 -
840 Constructs an OpenGL framebuffer object and binds a texture to the -
841 buffer of the given \a size. -
842 -
843 The \a attachment parameter describes the depth/stencil buffer -
844 configuration, \a target the texture target and \a internal_format -
845 the internal texture format. The default texture target is \c -
846 GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8 -
847 for desktop OpenGL and \c GL_RGBA for OpenGL/ES. -
848 -
849 \sa size(), texture(), attachment() -
850*/ -
851QOpenGLFramebufferObject::QOpenGLFramebufferObject(const QSize &size, Attachment attachment, -
852 GLenum target, GLenum internal_format) -
853 : d_ptr(new QOpenGLFramebufferObjectPrivate) -
854{ -
855 Q_D(QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): QOpenGLFramebufferObjectPrivate * const d = d_func();
-
856 d->init(this, size, attachment, target, internal_format);
never executed (the execution status of this line is deduced): d->init(this, size, attachment, target, internal_format);
-
857}
never executed: }
0
858 -
859/*! -
860 \fn QOpenGLFramebufferObject::~QOpenGLFramebufferObject() -
861 -
862 Destroys the framebuffer object and frees any allocated resources. -
863*/ -
864QOpenGLFramebufferObject::~QOpenGLFramebufferObject() -
865{ -
866 Q_D(QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): QOpenGLFramebufferObjectPrivate * const d = d_func();
-
867 -
868 if (d->texture_guard)
never evaluated: d->texture_guard
0
869 d->texture_guard->free();
never executed: d->texture_guard->free();
0
870 if (d->color_buffer_guard)
never evaluated: d->color_buffer_guard
0
871 d->color_buffer_guard->free();
never executed: d->color_buffer_guard->free();
0
872 if (d->depth_buffer_guard)
never evaluated: d->depth_buffer_guard
0
873 d->depth_buffer_guard->free();
never executed: d->depth_buffer_guard->free();
0
874 if (d->stencil_buffer_guard && d->stencil_buffer_guard != d->depth_buffer_guard)
never evaluated: d->stencil_buffer_guard
never evaluated: d->stencil_buffer_guard != d->depth_buffer_guard
0
875 d->stencil_buffer_guard->free();
never executed: d->stencil_buffer_guard->free();
0
876 if (d->fbo_guard)
never evaluated: d->fbo_guard
0
877 d->fbo_guard->free();
never executed: d->fbo_guard->free();
0
878}
never executed: }
0
879 -
880/*! -
881 \fn bool QOpenGLFramebufferObject::isValid() const -
882 -
883 Returns true if the framebuffer object is valid. -
884 -
885 The framebuffer can become invalid if the initialization process -
886 fails, the user attaches an invalid buffer to the framebuffer -
887 object, or a non-power of two width/height is specified as the -
888 texture size if the texture target is \c{GL_TEXTURE_2D}. -
889 The non-power of two limitation does not apply if the OpenGL version -
890 is 2.0 or higher, or if the GL_ARB_texture_non_power_of_two extension -
891 is present. -
892 -
893 The framebuffer can also become invalid if the QOpenGLContext that -
894 the framebuffer was created within is destroyed and there are -
895 no other shared contexts that can take over ownership of the -
896 framebuffer. -
897*/ -
898bool QOpenGLFramebufferObject::isValid() const -
899{ -
900 Q_D(const QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): const QOpenGLFramebufferObjectPrivate * const d = d_func();
-
901 return d->valid && d->fbo_guard && d->fbo_guard->id();
never executed: return d->valid && d->fbo_guard && d->fbo_guard->id();
0
902} -
903 -
904/*! -
905 \fn bool QOpenGLFramebufferObject::bind() -
906 -
907 Switches rendering from the default, windowing system provided -
908 framebuffer to this framebuffer object. -
909 Returns true upon success, false otherwise. -
910 -
911 \sa release() -
912*/ -
913bool QOpenGLFramebufferObject::bind() -
914{ -
915 if (!isValid())
never evaluated: !isValid()
0
916 return false;
never executed: return false;
0
917 Q_D(QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): QOpenGLFramebufferObjectPrivate * const d = d_func();
-
918 QOpenGLContext *current = QOpenGLContext::currentContext();
never executed (the execution status of this line is deduced): QOpenGLContext *current = QOpenGLContext::currentContext();
-
919 if (!current)
never evaluated: !current
0
920 return false;
never executed: return false;
0
921#ifdef QT_DEBUG -
922 if (current->shareGroup() != d->fbo_guard->group()) -
923 qWarning("QOpenGLFramebufferObject::bind() called from incompatible context"); -
924#endif -
925 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
never executed (the execution status of this line is deduced): d->funcs.glBindFramebuffer(0x8D40, d->fbo());
-
926 d->valid = d->checkFramebufferStatus(current);
never executed (the execution status of this line is deduced): d->valid = d->checkFramebufferStatus(current);
-
927 if (d->valid && current)
never evaluated: d->valid
never evaluated: current
0
928 current->d_func()->current_fbo = d->fbo();
never executed: current->d_func()->current_fbo = d->fbo();
0
929 return d->valid;
never executed: return d->valid;
0
930} -
931 -
932/*! -
933 \fn bool QOpenGLFramebufferObject::release() -
934 -
935 Switches rendering back to the default, windowing system provided -
936 framebuffer. -
937 Returns true upon success, false otherwise. -
938 -
939 \sa bind() -
940*/ -
941bool QOpenGLFramebufferObject::release() -
942{ -
943 if (!isValid())
never evaluated: !isValid()
0
944 return false;
never executed: return false;
0
945 -
946 QOpenGLContext *current = QOpenGLContext::currentContext();
never executed (the execution status of this line is deduced): QOpenGLContext *current = QOpenGLContext::currentContext();
-
947 if (!current)
never evaluated: !current
0
948 return false;
never executed: return false;
0
949 -
950 Q_D(QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): QOpenGLFramebufferObjectPrivate * const d = d_func();
-
951#ifdef QT_DEBUG -
952 if (current->shareGroup() != d->fbo_guard->group()) -
953 qWarning("QOpenGLFramebufferObject::release() called from incompatible context"); -
954#endif -
955 -
956 if (current) {
never evaluated: current
0
957 current->d_func()->current_fbo = current->defaultFramebufferObject();
never executed (the execution status of this line is deduced): current->d_func()->current_fbo = current->defaultFramebufferObject();
-
958 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_func()->current_fbo);
never executed (the execution status of this line is deduced): d->funcs.glBindFramebuffer(0x8D40, current->d_func()->current_fbo);
-
959 }
never executed: }
0
960 -
961 return true;
never executed: return true;
0
962} -
963 -
964/*! -
965 \fn GLuint QOpenGLFramebufferObject::texture() const -
966 -
967 Returns the texture id for the texture attached as the default -
968 rendering target in this framebuffer object. This texture id can -
969 be bound as a normal texture in your own OpenGL code. -
970 -
971 If a multisample framebuffer object is used then the value returned -
972 from this function will be invalid. -
973*/ -
974GLuint QOpenGLFramebufferObject::texture() const -
975{ -
976 Q_D(const QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): const QOpenGLFramebufferObjectPrivate * const d = d_func();
-
977 return d->texture_guard ? d->texture_guard->id() : 0;
never executed: return d->texture_guard ? d->texture_guard->id() : 0;
0
978} -
979 -
980/*! -
981 \fn QSize QOpenGLFramebufferObject::size() const -
982 -
983 Returns the size of the texture attached to this framebuffer -
984 object. -
985*/ -
986QSize QOpenGLFramebufferObject::size() const -
987{ -
988 Q_D(const QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): const QOpenGLFramebufferObjectPrivate * const d = d_func();
-
989 return d->size;
never executed: return d->size;
0
990} -
991 -
992/*! -
993 \fn int QOpenGLFramebufferObject::width() const -
994 -
995 Returns the width of the framebuffer object attachments. -
996*/ -
997 -
998/*! -
999 \fn int QOpenGLFramebufferObject::height() const -
1000 -
1001 Returns the height of the framebuffer object attachments. -
1002*/ -
1003 -
1004/*! -
1005 Returns the format of this framebuffer object. -
1006*/ -
1007QOpenGLFramebufferObjectFormat QOpenGLFramebufferObject::format() const -
1008{ -
1009 Q_D(const QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): const QOpenGLFramebufferObjectPrivate * const d = d_func();
-
1010 return d->format;
never executed: return d->format;
0
1011} -
1012 -
1013Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha) -
1014{ -
1015 QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32_Premultiplied
never executed (the execution status of this line is deduced): QImage img(size, (alpha_format && include_alpha) ? QImage::Format_ARGB32_Premultiplied
-
1016 : QImage::Format_RGB32);
never executed (the execution status of this line is deduced): : QImage::Format_RGB32);
-
1017 int w = size.width();
never executed (the execution status of this line is deduced): int w = size.width();
-
1018 int h = size.height();
never executed (the execution status of this line is deduced): int h = size.height();
-
1019 -
1020#ifdef QT_OPENGL_ES -
1021 GLint fmt = GL_BGRA_EXT; -
1022#else -
1023 GLint fmt = GL_BGRA;
never executed (the execution status of this line is deduced): GLint fmt = 0x80E1;
-
1024#endif -
1025 while (glGetError());
never executed: ;
never evaluated: glGetError()
0
1026 glReadPixels(0, 0, w, h, fmt, GL_UNSIGNED_BYTE, img.bits());
never executed (the execution status of this line is deduced): glReadPixels(0, 0, w, h, fmt, 0x1401, img.bits());
-
1027 if (glGetError()) {
never evaluated: glGetError()
0
1028 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, img.bits());
never executed (the execution status of this line is deduced): glReadPixels(0, 0, w, h, 0x1908, 0x1401, img.bits());
-
1029 img = img.rgbSwapped();
never executed (the execution status of this line is deduced): img = img.rgbSwapped();
-
1030 }
never executed: }
0
1031 return img.mirrored();
never executed: return img.mirrored();
0
1032} -
1033 -
1034/*! -
1035 \fn QImage QOpenGLFramebufferObject::toImage() const -
1036 -
1037 Returns the contents of this framebuffer object as a QImage. -
1038*/ -
1039QImage QOpenGLFramebufferObject::toImage() const -
1040{ -
1041 Q_D(const QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): const QOpenGLFramebufferObjectPrivate * const d = d_func();
-
1042 if (!d->valid)
never evaluated: !d->valid
0
1043 return QImage();
never executed: return QImage();
0
1044 -
1045 // qt_gl_read_framebuffer doesn't work on a multisample FBO -
1046 if (format().samples() != 0) {
never evaluated: format().samples() != 0
0
1047 QOpenGLFramebufferObject temp(size(), QOpenGLFramebufferObjectFormat());
never executed (the execution status of this line is deduced): QOpenGLFramebufferObject temp(size(), QOpenGLFramebufferObjectFormat());
-
1048 -
1049 QRect rect(QPoint(0, 0), size());
never executed (the execution status of this line is deduced): QRect rect(QPoint(0, 0), size());
-
1050 blitFramebuffer(&temp, rect, const_cast<QOpenGLFramebufferObject *>(this), rect);
never executed (the execution status of this line is deduced): blitFramebuffer(&temp, rect, const_cast<QOpenGLFramebufferObject *>(this), rect);
-
1051 -
1052 return temp.toImage();
never executed: return temp.toImage();
0
1053 } -
1054 -
1055 bool wasBound = isBound();
never executed (the execution status of this line is deduced): bool wasBound = isBound();
-
1056 if (!wasBound)
never evaluated: !wasBound
0
1057 const_cast<QOpenGLFramebufferObject *>(this)->bind();
never executed: const_cast<QOpenGLFramebufferObject *>(this)->bind();
0
1058 QImage image = qt_gl_read_framebuffer(d->size, format().internalTextureFormat() != GL_RGB, true);
never executed (the execution status of this line is deduced): QImage image = qt_gl_read_framebuffer(d->size, format().internalTextureFormat() != 0x1907, true);
-
1059 if (!wasBound)
never evaluated: !wasBound
0
1060 const_cast<QOpenGLFramebufferObject *>(this)->release();
never executed: const_cast<QOpenGLFramebufferObject *>(this)->release();
0
1061 -
1062 return image;
never executed: return image;
0
1063} -
1064 -
1065/*! -
1066 \fn bool QOpenGLFramebufferObject::bindDefault() -
1067 \internal -
1068 -
1069 Switches rendering back to the default, windowing system provided -
1070 framebuffer. -
1071 Returns true upon success, false otherwise. -
1072 -
1073 \sa bind(), release() -
1074*/ -
1075bool QOpenGLFramebufferObject::bindDefault() -
1076{ -
1077 QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
never executed (the execution status of this line is deduced): QOpenGLContext *ctx = const_cast<QOpenGLContext *>(QOpenGLContext::currentContext());
-
1078 QOpenGLFunctions functions(ctx);
never executed (the execution status of this line is deduced): QOpenGLFunctions functions(ctx);
-
1079 -
1080 if (ctx) {
never evaluated: ctx
0
1081 ctx->d_func()->current_fbo = ctx->defaultFramebufferObject();
never executed (the execution status of this line is deduced): ctx->d_func()->current_fbo = ctx->defaultFramebufferObject();
-
1082 functions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->current_fbo);
never executed (the execution status of this line is deduced): functions.glBindFramebuffer(0x8D40, ctx->d_func()->current_fbo);
-
1083#ifdef QT_DEBUG -
1084 } else { -
1085 qWarning("QOpenGLFramebufferObject::bindDefault() called without current context."); -
1086#endif -
1087 }
never executed: }
0
1088 -
1089 return ctx != 0;
never executed: return ctx != 0;
0
1090} -
1091 -
1092/*! -
1093 \fn bool QOpenGLFramebufferObject::hasOpenGLFramebufferObjects() -
1094 -
1095 Returns true if the OpenGL \c{GL_EXT_framebuffer_object} extension -
1096 is present on this system; otherwise returns false. -
1097*/ -
1098bool QOpenGLFramebufferObject::hasOpenGLFramebufferObjects() -
1099{ -
1100 return QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::Framebuffers);
never executed: return QOpenGLFunctions(QOpenGLContext::currentContext()).hasOpenGLFeature(QOpenGLFunctions::Framebuffers);
0
1101} -
1102 -
1103/*! -
1104 \fn GLuint QOpenGLFramebufferObject::handle() const -
1105 -
1106 Returns the OpenGL framebuffer object handle for this framebuffer -
1107 object (returned by the \c{glGenFrameBuffersEXT()} function). This -
1108 handle can be used to attach new images or buffers to the -
1109 framebuffer. The user is responsible for cleaning up and -
1110 destroying these objects. -
1111*/ -
1112GLuint QOpenGLFramebufferObject::handle() const -
1113{ -
1114 Q_D(const QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): const QOpenGLFramebufferObjectPrivate * const d = d_func();
-
1115 return d->fbo();
never executed: return d->fbo();
0
1116} -
1117 -
1118/*! -
1119 Returns the status of the depth and stencil buffers attached to -
1120 this framebuffer object. -
1121*/ -
1122 -
1123QOpenGLFramebufferObject::Attachment QOpenGLFramebufferObject::attachment() const -
1124{ -
1125 Q_D(const QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): const QOpenGLFramebufferObjectPrivate * const d = d_func();
-
1126 if (d->valid)
never evaluated: d->valid
0
1127 return d->fbo_attachment;
never executed: return d->fbo_attachment;
0
1128 return NoAttachment;
never executed: return NoAttachment;
0
1129} -
1130 -
1131/*! -
1132 Sets the attachments of the framebuffer object to \a attachment. -
1133 -
1134 This can be used to free or reattach the depth and stencil buffer -
1135 attachments as needed. -
1136 */ -
1137void QOpenGLFramebufferObject::setAttachment(QOpenGLFramebufferObject::Attachment attachment) -
1138{ -
1139 Q_D(QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): QOpenGLFramebufferObjectPrivate * const d = d_func();
-
1140 if (attachment == d->fbo_attachment || !isValid())
never evaluated: attachment == d->fbo_attachment
never evaluated: !isValid()
0
1141 return;
never executed: return;
0
1142 QOpenGLContext *current = QOpenGLContext::currentContext();
never executed (the execution status of this line is deduced): QOpenGLContext *current = QOpenGLContext::currentContext();
-
1143 if (!current)
never evaluated: !current
0
1144 return;
never executed: return;
0
1145#ifdef QT_DEBUG -
1146 if (current->shareGroup() != d->fbo_guard->group()) -
1147 qWarning("QOpenGLFramebufferObject::setAttachment() called from incompatible context"); -
1148#endif -
1149 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, d->fbo());
never executed (the execution status of this line is deduced): d->funcs.glBindFramebuffer(0x8D40, d->fbo());
-
1150 d->initAttachments(current, attachment);
never executed (the execution status of this line is deduced): d->initAttachments(current, attachment);
-
1151 if (current->d_func()->current_fbo != d->fbo())
never evaluated: current->d_func()->current_fbo != d->fbo()
0
1152 d->funcs.glBindFramebuffer(GL_FRAMEBUFFER, current->d_func()->current_fbo);
never executed: d->funcs.glBindFramebuffer(0x8D40, current->d_func()->current_fbo);
0
1153}
never executed: }
0
1154 -
1155/*! -
1156 Returns true if the framebuffer object is currently bound to a context, -
1157 otherwise false is returned. -
1158*/ -
1159 -
1160bool QOpenGLFramebufferObject::isBound() const -
1161{ -
1162 Q_D(const QOpenGLFramebufferObject);
never executed (the execution status of this line is deduced): const QOpenGLFramebufferObjectPrivate * const d = d_func();
-
1163 QOpenGLContext *current = QOpenGLContext::currentContext();
never executed (the execution status of this line is deduced): QOpenGLContext *current = QOpenGLContext::currentContext();
-
1164 return current ? current->d_func()->current_fbo == d->fbo() : false;
never executed: return current ? current->d_func()->current_fbo == d->fbo() : false;
0
1165} -
1166 -
1167/*! -
1168 \fn bool QOpenGLFramebufferObject::hasOpenGLFramebufferBlit() -
1169 -
1170 Returns true if the OpenGL \c{GL_EXT_framebuffer_blit} extension -
1171 is present on this system; otherwise returns false. -
1172 -
1173 \sa blitFramebuffer() -
1174*/ -
1175bool QOpenGLFramebufferObject::hasOpenGLFramebufferBlit() -
1176{ -
1177 return QOpenGLExtensions(QOpenGLContext::currentContext()).hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
never executed: return QOpenGLExtensions(QOpenGLContext::currentContext()).hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit);
0
1178} -
1179 -
1180 -
1181/*! -
1182 \overload -
1183 -
1184 Convenience overload to blit between two framebuffer objects. -
1185*/ -
1186void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target, -
1187 QOpenGLFramebufferObject *source, -
1188 GLbitfield buffers, GLenum filter) -
1189{ -
1190 if (!target && !source)
never evaluated: !target
never evaluated: !source
0
1191 return;
never executed: return;
0
1192 -
1193 QSize targetSize;
never executed (the execution status of this line is deduced): QSize targetSize;
-
1194 QSize sourceSize;
never executed (the execution status of this line is deduced): QSize sourceSize;
-
1195 -
1196 if (target)
never evaluated: target
0
1197 targetSize = target->size();
never executed: targetSize = target->size();
0
1198 if (source)
never evaluated: source
0
1199 sourceSize = source->size();
never executed: sourceSize = source->size();
0
1200 -
1201 if (targetSize.isEmpty())
never evaluated: targetSize.isEmpty()
0
1202 targetSize = sourceSize;
never executed: targetSize = sourceSize;
0
1203 else if (sourceSize.isEmpty())
never evaluated: sourceSize.isEmpty()
0
1204 sourceSize = targetSize;
never executed: sourceSize = targetSize;
0
1205 -
1206 blitFramebuffer(target, QRect(QPoint(0, 0), targetSize),
never executed (the execution status of this line is deduced): blitFramebuffer(target, QRect(QPoint(0, 0), targetSize),
-
1207 source, QRect(QPoint(0, 0), sourceSize),
never executed (the execution status of this line is deduced): source, QRect(QPoint(0, 0), sourceSize),
-
1208 buffers, filter);
never executed (the execution status of this line is deduced): buffers, filter);
-
1209}
never executed: }
0
1210 -
1211/*! -
1212 Blits from the \a sourceRect rectangle in the \a source framebuffer -
1213 object to the \a targetRect rectangle in the \a target framebuffer object. -
1214 -
1215 If \a source or \a target is 0, the default framebuffer will be used -
1216 instead of a framebuffer object as source or target respectively. -
1217 -
1218 The \a buffers parameter should be a mask consisting of any combination of -
1219 \c GL_COLOR_BUFFER_BIT, \c GL_DEPTH_BUFFER_BIT, and -
1220 \c GL_STENCIL_BUFFER_BIT. Any buffer type that is not present both -
1221 in the source and target buffers is ignored. -
1222 -
1223 The \a sourceRect and \a targetRect rectangles may have different sizes; -
1224 in this case \a buffers should not contain \c GL_DEPTH_BUFFER_BIT or -
1225 \c GL_STENCIL_BUFFER_BIT. The \a filter parameter should be set to -
1226 \c GL_LINEAR or \c GL_NEAREST, and specifies whether linear or nearest -
1227 interpolation should be used when scaling is performed. -
1228 -
1229 If \a source equals \a target a copy is performed within the same buffer. -
1230 Results are undefined if the source and target rectangles overlap and -
1231 have different sizes. The sizes must also be the same if any of the -
1232 framebuffer objects are multisample framebuffers. -
1233 -
1234 Note that the scissor test will restrict the blit area if enabled. -
1235 -
1236 This function will have no effect unless hasOpenGLFramebufferBlit() returns -
1237 true. -
1238 -
1239 \sa hasOpenGLFramebufferBlit() -
1240*/ -
1241void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target, const QRect &targetRect, -
1242 QOpenGLFramebufferObject *source, const QRect &sourceRect, -
1243 GLbitfield buffers, -
1244 GLenum filter) -
1245{ -
1246 QOpenGLContext *ctx = QOpenGLContext::currentContext();
never executed (the execution status of this line is deduced): QOpenGLContext *ctx = QOpenGLContext::currentContext();
-
1247 if (!ctx)
never evaluated: !ctx
0
1248 return;
never executed: return;
0
1249 -
1250 QOpenGLExtensions extensions(ctx);
never executed (the execution status of this line is deduced): QOpenGLExtensions extensions(ctx);
-
1251 if (!extensions.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit))
never evaluated: !extensions.hasOpenGLExtension(QOpenGLExtensions::FramebufferBlit)
0
1252 return;
never executed: return;
0
1253 -
1254 const int sx0 = sourceRect.left();
never executed (the execution status of this line is deduced): const int sx0 = sourceRect.left();
-
1255 const int sx1 = sourceRect.left() + sourceRect.width();
never executed (the execution status of this line is deduced): const int sx1 = sourceRect.left() + sourceRect.width();
-
1256 const int sy0 = sourceRect.top();
never executed (the execution status of this line is deduced): const int sy0 = sourceRect.top();
-
1257 const int sy1 = sourceRect.top() + sourceRect.height();
never executed (the execution status of this line is deduced): const int sy1 = sourceRect.top() + sourceRect.height();
-
1258 -
1259 const int tx0 = targetRect.left();
never executed (the execution status of this line is deduced): const int tx0 = targetRect.left();
-
1260 const int tx1 = targetRect.left() + targetRect.width();
never executed (the execution status of this line is deduced): const int tx1 = targetRect.left() + targetRect.width();
-
1261 const int ty0 = targetRect.top();
never executed (the execution status of this line is deduced): const int ty0 = targetRect.top();
-
1262 const int ty1 = targetRect.top() + targetRect.height();
never executed (the execution status of this line is deduced): const int ty1 = targetRect.top() + targetRect.height();
-
1263 -
1264 extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : 0);
never executed (the execution status of this line is deduced): extensions.glBindFramebuffer(0x8CA8, source ? source->handle() : 0);
-
1265 extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : 0);
never executed (the execution status of this line is deduced): extensions.glBindFramebuffer(0x8CA9, target ? target->handle() : 0);
-
1266 -
1267 extensions.glBlitFramebuffer(sx0, sy0, sx1, sy1,
never executed (the execution status of this line is deduced): extensions.glBlitFramebuffer(sx0, sy0, sx1, sy1,
-
1268 tx0, ty0, tx1, ty1,
never executed (the execution status of this line is deduced): tx0, ty0, tx1, ty1,
-
1269 buffers, filter);
never executed (the execution status of this line is deduced): buffers, filter);
-
1270 -
1271 extensions.glBindFramebuffer(GL_FRAMEBUFFER, ctx->d_func()->current_fbo);
never executed (the execution status of this line is deduced): extensions.glBindFramebuffer(0x8D40, ctx->d_func()->current_fbo);
-
1272}
never executed: }
0
1273 -
1274QT_END_NAMESPACE -
1275 -
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial