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