Doc: Fix docbuild when not using -developer-build.
[profile/ivi/qtbase.git] / src / opengl / qglpixelbuffer.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtOpenGL module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 /*!
43     \class QGLPixelBuffer
44     \brief The QGLPixelBuffer class encapsulates an OpenGL pbuffer.
45     \since 4.1
46
47     \ingroup painting-3D
48
49     Rendering into a pbuffer is normally done using full hardware
50     acceleration. This can be significantly faster than rendering
51     into a QPixmap.
52
53     There are three approaches to using this class:
54
55     \list 1
56     \li \b{We can draw into the pbuffer and convert it to a QImage
57        using toImage().} This is normally much faster than calling
58        QGLWidget::renderPixmap().
59
60     \li \b{We can draw into the pbuffer and copy the contents into
61        an OpenGL texture using updateDynamicTexture().} This allows
62        us to create dynamic textures and works on all systems
63        with pbuffer support.
64
65     \li \b{On systems that support it, we can bind the pbuffer to
66        an OpenGL texture.} The texture is then updated automatically
67        when the pbuffer contents change, eliminating the need for
68        additional copy operations. This is supported only on Windows
69        and Mac OS X systems that provide the \c render_texture
70        extension. Note that under Windows, a multi-sampled pbuffer
71        can't be used in conjunction with the \c render_texture
72        extension. If a multi-sampled pbuffer is requested under
73        Windows, the \c render_texture extension is turned off for that
74        pbuffer.
75
76
77     \endlist
78
79
80     \section1 Threading
81
82     As of Qt 4.8, it's possible to render into a QGLPixelBuffer using
83     a QPainter in a separate thread. Note that OpenGL 2.0 or OpenGL ES
84     2.0 is required for this to work.
85
86     Pbuffers are provided by the OpenGL \c pbuffer extension; call
87     hasOpenGLPbuffer() to find out if the system provides pbuffers.
88
89     \sa {opengl/pbuffers}{Pbuffers Example}
90 */
91
92 #include <QtCore/qglobal.h>
93
94 #include "gl2paintengineex/qpaintengineex_opengl2_p.h"
95
96 #include <qglpixelbuffer.h>
97 #include <private/qglpixelbuffer_p.h>
98 #include <private/qfont_p.h>
99 #include <qimage.h>
100
101 QT_BEGIN_NAMESPACE
102
103 extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool);
104
105
106 QGLContext* QGLPBufferGLPaintDevice::context() const
107 {
108     return pbuf->d_func()->qctx;
109 }
110
111 void QGLPBufferGLPaintDevice::endPaint() {
112     glFlush();
113     QGLPaintDevice::endPaint();
114 }
115
116 void QGLPBufferGLPaintDevice::setPBuffer(QGLPixelBuffer* pb)
117 {
118     pbuf = pb;
119 }
120
121 void QGLPixelBufferPrivate::common_init(const QSize &size, const QGLFormat &format, QGLWidget *shareWidget)
122 {
123     Q_Q(QGLPixelBuffer);
124     if(init(size, format, shareWidget)) {
125         req_size = size;
126         req_format = format;
127         req_shareWidget = shareWidget;
128         invalid = false;
129         qctx = new QGLContext(format);
130         qctx->d_func()->sharing = (shareWidget != 0);
131         if (shareWidget != 0 && shareWidget->d_func()->glcx) {
132             QGLContextGroup::addShare(qctx, shareWidget->d_func()->glcx);
133             shareWidget->d_func()->glcx->d_func()->sharing = true;
134         }
135
136         glDevice.setPBuffer(q);
137         qctx->d_func()->paintDevice = q;
138         qctx->d_func()->valid = true;
139     }
140 }
141
142 /*!
143     Constructs an OpenGL pbuffer of the given \a size. If no \a
144     format is specified, the \l{QGLFormat::defaultFormat()}{default
145     format} is used. If the \a shareWidget parameter points to a
146     valid QGLWidget, the pbuffer will share its context with \a
147     shareWidget.
148
149     If you intend to bind this pbuffer as a dynamic texture, the width
150     and height components of \c size must be powers of two (e.g., 512
151     x 128).
152
153     \sa size(), format()
154 */
155 QGLPixelBuffer::QGLPixelBuffer(const QSize &size, const QGLFormat &format, QGLWidget *shareWidget)
156     : d_ptr(new QGLPixelBufferPrivate(this))
157 {
158     Q_D(QGLPixelBuffer);
159     d->common_init(size, format, shareWidget);
160 }
161
162
163 /*! \overload
164
165     Constructs an OpenGL pbuffer with the \a width and \a height. If
166     no \a format is specified, the
167     \l{QGLFormat::defaultFormat()}{default format} is used. If the \a
168     shareWidget parameter points to a valid QGLWidget, the pbuffer
169     will share its context with \a shareWidget.
170
171     If you intend to bind this pbuffer as a dynamic texture, the width
172     and height components of \c size must be powers of two (e.g., 512
173     x 128).
174
175     \sa size(), format()
176 */
177 QGLPixelBuffer::QGLPixelBuffer(int width, int height, const QGLFormat &format, QGLWidget *shareWidget)
178     : d_ptr(new QGLPixelBufferPrivate(this))
179 {
180     Q_D(QGLPixelBuffer);
181     d->common_init(QSize(width, height), format, shareWidget);
182 }
183
184
185 /*! \fn QGLPixelBuffer::~QGLPixelBuffer()
186
187     Destroys the pbuffer and frees any allocated resources.
188 */
189 QGLPixelBuffer::~QGLPixelBuffer()
190 {
191     Q_D(QGLPixelBuffer);
192
193     // defined in qpaintengine_opengl.cpp
194     QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext());
195     if (current != d->qctx)
196         makeCurrent();
197     d->cleanup();
198     delete d->qctx;
199     if (current && current != d->qctx)
200         current->makeCurrent();
201 }
202
203 /*! \fn bool QGLPixelBuffer::makeCurrent()
204
205     Makes this pbuffer the current OpenGL rendering context. Returns
206     true on success; otherwise returns false.
207
208     \sa QGLContext::makeCurrent(), doneCurrent()
209 */
210
211 bool QGLPixelBuffer::makeCurrent()
212 {
213     Q_D(QGLPixelBuffer);
214     if (d->invalid)
215         return false;
216     d->qctx->makeCurrent();
217     return true;
218 }
219
220 /*! \fn bool QGLPixelBuffer::doneCurrent()
221
222     Makes no context the current OpenGL context. Returns true on
223     success; otherwise returns false.
224 */
225
226 bool QGLPixelBuffer::doneCurrent()
227 {
228     Q_D(QGLPixelBuffer);
229     if (d->invalid)
230         return false;
231     d->qctx->doneCurrent();
232     return true;
233 }
234
235 /*!
236     \fn GLuint QGLPixelBuffer::generateDynamicTexture() const
237
238     Generates and binds a 2D GL texture that is the same size as the
239     pbuffer, and returns the texture's ID. This can be used in
240     conjunction with bindToDynamicTexture() and
241     updateDynamicTexture().
242
243     \sa size()
244 */
245
246 /*! \fn bool QGLPixelBuffer::bindToDynamicTexture(GLuint texture_id)
247
248     Binds the texture specified by \a texture_id to this pbuffer.
249     Returns true on success; otherwise returns false.
250
251     The texture must be of the same size and format as the pbuffer.
252
253     To unbind the texture, call releaseFromDynamicTexture(). While
254     the texture is bound, it is updated automatically when the
255     pbuffer contents change, eliminating the need for additional copy
256     operations.
257
258     Example:
259
260     \snippet code/src_opengl_qglpixelbuffer.cpp 0
261
262     \warning This function uses the \c {render_texture} extension,
263     which is currently not supported under X11. An alternative that
264     works on all systems (including X11) is to manually copy the
265     pbuffer contents to a texture using updateDynamicTexture().
266
267     \warning For the bindToDynamicTexture() call to succeed on the
268     Mac OS X, the pbuffer needs a shared context, i.e. the
269     QGLPixelBuffer must be created with a share widget.
270
271     \sa generateDynamicTexture(), releaseFromDynamicTexture()
272 */
273
274 /*! \fn void QGLPixelBuffer::releaseFromDynamicTexture()
275
276     Releases the pbuffer from any previously bound texture.
277
278     \sa bindToDynamicTexture()
279 */
280
281 /*! \fn bool QGLPixelBuffer::hasOpenGLPbuffers()
282
283     Returns true if the OpenGL \c pbuffer extension is present on
284     this system; otherwise returns false.
285 */
286
287 /*!
288     Copies the pbuffer contents into the texture specified with \a
289     texture_id.
290
291     The texture must be of the same size and format as the pbuffer.
292
293     Example:
294
295     \snippet code/src_opengl_qglpixelbuffer.cpp 1
296
297     An alternative on Windows and Mac OS X systems that support the
298     \c render_texture extension is to use bindToDynamicTexture() to
299     get dynamic updates of the texture.
300
301     \sa generateDynamicTexture(), bindToDynamicTexture()
302 */
303 void QGLPixelBuffer::updateDynamicTexture(GLuint texture_id) const
304 {
305     Q_D(const QGLPixelBuffer);
306     if (d->invalid)
307         return;
308     glBindTexture(GL_TEXTURE_2D, texture_id);
309 #ifndef QT_OPENGL_ES
310     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 0, 0, d->req_size.width(), d->req_size.height(), 0);
311 #else
312     glCopyTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, 0, 0, d->req_size.width(), d->req_size.height(), 0);
313 #endif
314 }
315
316 /*!
317     Returns the size of the pbuffer.
318 */
319 QSize QGLPixelBuffer::size() const
320 {
321     Q_D(const QGLPixelBuffer);
322     return d->req_size;
323 }
324
325 /*!
326     Returns the contents of the pbuffer as a QImage.
327 */
328 QImage QGLPixelBuffer::toImage() const
329 {
330     Q_D(const QGLPixelBuffer);
331     if (d->invalid)
332         return QImage();
333
334     const_cast<QGLPixelBuffer *>(this)->makeCurrent();
335     return qt_gl_read_framebuffer(d->req_size, d->format.alpha(), true);
336 }
337
338 /*!
339     Returns the native pbuffer handle.
340 */
341 Qt::HANDLE QGLPixelBuffer::handle() const
342 {
343     Q_D(const QGLPixelBuffer);
344     if (d->invalid)
345         return 0;
346     return (Qt::HANDLE) d->pbuf;
347 }
348
349 /*!
350     Returns true if this pbuffer is valid; otherwise returns false.
351 */
352 bool QGLPixelBuffer::isValid() const
353 {
354     Q_D(const QGLPixelBuffer);
355     return !d->invalid;
356 }
357
358 Q_GLOBAL_STATIC(QGLEngineThreadStorage<QGL2PaintEngineEx>, qt_buffer_2_engine)
359
360 /*! \reimp */
361 QPaintEngine *QGLPixelBuffer::paintEngine() const
362 {
363     return qt_buffer_2_engine()->engine();
364 }
365
366 /*! \reimp */
367 int QGLPixelBuffer::metric(PaintDeviceMetric metric) const
368 {
369     Q_D(const QGLPixelBuffer);
370
371     float dpmx = qt_defaultDpiX()*100./2.54;
372     float dpmy = qt_defaultDpiY()*100./2.54;
373     int w = d->req_size.width();
374     int h = d->req_size.height();
375     switch (metric) {
376     case PdmWidth:
377         return w;
378
379     case PdmHeight:
380         return h;
381
382     case PdmWidthMM:
383         return qRound(w * 1000 / dpmx);
384
385     case PdmHeightMM:
386         return qRound(h * 1000 / dpmy);
387
388     case PdmNumColors:
389         return 0;
390
391     case PdmDepth:
392         return 32;//d->depth;
393
394     case PdmDpiX:
395         return qRound(dpmx * 0.0254);
396
397     case PdmDpiY:
398         return qRound(dpmy * 0.0254);
399
400     case PdmPhysicalDpiX:
401         return qRound(dpmx * 0.0254);
402
403     case PdmPhysicalDpiY:
404         return qRound(dpmy * 0.0254);
405
406     default:
407         qWarning("QGLPixelBuffer::metric(), Unhandled metric type: %d\n", metric);
408         break;
409     }
410     return 0;
411 }
412
413 /*!
414     Generates and binds a 2D GL texture to the current context, based
415     on \a image. The generated texture id is returned and can be used
416     in later glBindTexture() calls.
417
418     The \a target parameter specifies the texture target.
419
420     Equivalent to calling QGLContext::bindTexture().
421
422     \sa deleteTexture()
423 */
424 GLuint QGLPixelBuffer::bindTexture(const QImage &image, GLenum target)
425 {
426     Q_D(QGLPixelBuffer);
427 #ifndef QT_OPENGL_ES
428     return d->qctx->bindTexture(image, target, GLint(GL_RGBA8));
429 #else
430     return d->qctx->bindTexture(image, target, GL_RGBA);
431 #endif
432 }
433
434 /*! \overload
435
436     Generates and binds a 2D GL texture based on \a pixmap.
437
438     Equivalent to calling QGLContext::bindTexture().
439
440     \sa deleteTexture()
441 */
442 GLuint QGLPixelBuffer::bindTexture(const QPixmap &pixmap, GLenum target)
443 {
444     Q_D(QGLPixelBuffer);
445 #ifndef QT_OPENGL_ES
446     return d->qctx->bindTexture(pixmap, target, GLint(GL_RGBA8));
447 #else
448     return d->qctx->bindTexture(pixmap, target, GL_RGBA);
449 #endif
450 }
451
452 /*! \overload
453
454     Reads the DirectDrawSurface (DDS) compressed file \a fileName and
455     generates a 2D GL texture from it.
456
457     Equivalent to calling QGLContext::bindTexture().
458
459     \sa deleteTexture()
460 */
461 GLuint QGLPixelBuffer::bindTexture(const QString &fileName)
462 {
463     Q_D(QGLPixelBuffer);
464     return d->qctx->bindTexture(fileName);
465 }
466
467 /*!
468     Removes the texture identified by \a texture_id from the texture cache.
469
470     Equivalent to calling QGLContext::deleteTexture().
471  */
472 void QGLPixelBuffer::deleteTexture(GLuint texture_id)
473 {
474     Q_D(QGLPixelBuffer);
475     d->qctx->deleteTexture(texture_id);
476 }
477
478 /*!
479     \since 4.4
480
481     Draws the given texture, \a textureId, to the given target rectangle,
482     \a target, in OpenGL model space. The \a textureTarget should be a 2D
483     texture target.
484
485     Equivalent to the corresponding QGLContext::drawTexture().
486 */
487 void QGLPixelBuffer::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
488 {
489     Q_D(QGLPixelBuffer);
490     d->qctx->drawTexture(target, textureId, textureTarget);
491 }
492
493 /*!
494     \since 4.4
495
496     Draws the given texture, \a textureId, at the given \a point in OpenGL model
497     space. The textureTarget parameter should be a 2D texture target.
498
499     Equivalent to the corresponding QGLContext::drawTexture().
500 */
501 void QGLPixelBuffer::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
502 {
503     Q_D(QGLPixelBuffer);
504     d->qctx->drawTexture(point, textureId, textureTarget);
505 }
506
507 /*!
508     Returns the format of the pbuffer. The format may be different
509     from the one that was requested.
510 */
511 QGLFormat QGLPixelBuffer::format() const
512 {
513     Q_D(const QGLPixelBuffer);
514     return d->format;
515 }
516
517 /*! \fn int QGLPixelBuffer::devType() const
518     \internal
519 */
520
521 QT_END_NAMESPACE