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