source: trunk/src/opengl/qglpixelbuffer.cpp@ 365

Last change on this file since 365 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 16.1 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtOpenGL module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
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 multimedia
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 \o \bold{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 \o \bold{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 \o \bold{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.
71 \endlist
72
73 Pbuffers are provided by the OpenGL \c pbuffer extension; call
74 hasOpenGLPbuffer() to find out if the system provides pbuffers.
75
76 \sa {opengl/pbuffers}{Pbuffers Example}
77*/
78
79
80#include <qglpixelbuffer.h>
81#include <private/qglpixelbuffer_p.h>
82#include <qimage.h>
83
84#if !defined(QT_OPENGL_ES_2)
85#include <private/qpaintengine_opengl_p.h>
86#endif
87
88QT_BEGIN_NAMESPACE
89
90#if !defined(QT_OPENGL_ES_2)
91extern void qgl_cleanup_glyph_cache(QGLContext *);
92#else
93void qgl_cleanup_glyph_cache(QGLContext *) {}
94#endif
95
96extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool);
97
98void QGLPixelBufferPrivate::common_init(const QSize &size, const QGLFormat &format, QGLWidget *shareWidget)
99{
100 Q_Q(QGLPixelBuffer);
101 if(init(size, format, shareWidget)) {
102 req_size = size;
103 req_format = format;
104 req_shareWidget = shareWidget;
105 invalid = false;
106 qctx = new QGLContext(format);
107 qctx->d_func()->sharing = (shareWidget != 0);
108 if (shareWidget != 0 && shareWidget->d_func()->glcx)
109 qgl_share_reg()->addShare(qctx, shareWidget->d_func()->glcx);
110
111 qctx->d_func()->paintDevice = q;
112 qctx->d_func()->valid = true;
113#if defined(Q_WS_WIN) && !defined(QT_OPENGL_ES)
114 qctx->d_func()->dc = dc;
115 qctx->d_func()->rc = ctx;
116#elif (defined(Q_WS_X11) && !defined(QT_OPENGL_ES))
117 qctx->d_func()->cx = ctx;
118 qctx->d_func()->pbuf = (void *) pbuf;
119 qctx->d_func()->vi = 0;
120#elif defined(Q_WS_MAC)
121 qctx->d_func()->cx = ctx;
122 qctx->d_func()->vi = 0;
123#elif defined(QT_OPENGL_ES)
124 qctx->d_func()->eglContext = ctx;
125#endif
126 }
127}
128
129/*!
130 Constructs an OpenGL pbuffer of the given \a size. If no \a
131 format is specified, the \l{QGLFormat::defaultFormat()}{default
132 format} is used. If the \a shareWidget parameter points to a
133 valid QGLWidget, the pbuffer will share its context with \a
134 shareWidget.
135
136 If you intend to bind this pbuffer as a dynamic texture, the width
137 and height components of \c size must be powers of two (e.g., 512
138 x 128).
139
140 \sa size(), format()
141*/
142QGLPixelBuffer::QGLPixelBuffer(const QSize &size, const QGLFormat &format, QGLWidget *shareWidget)
143 : d_ptr(new QGLPixelBufferPrivate(this))
144{
145 Q_D(QGLPixelBuffer);
146 d->common_init(size, format, shareWidget);
147}
148
149
150/*! \overload
151
152 Constructs an OpenGL pbuffer with the \a width and \a height. If
153 no \a format is specified, the
154 \l{QGLFormat::defaultFormat()}{default format} is used. If the \a
155 shareWidget parameter points to a valid QGLWidget, the pbuffer
156 will share its context with \a shareWidget.
157
158 If you intend to bind this pbuffer as a dynamic texture, the width
159 and height components of \c size must be powers of two (e.g., 512
160 x 128).
161
162 \sa size(), format()
163*/
164QGLPixelBuffer::QGLPixelBuffer(int width, int height, const QGLFormat &format, QGLWidget *shareWidget)
165 : d_ptr(new QGLPixelBufferPrivate(this))
166{
167 Q_D(QGLPixelBuffer);
168 d->common_init(QSize(width, height), format, shareWidget);
169}
170
171
172/*! \fn QGLPixelBuffer::~QGLPixelBuffer()
173
174 Destroys the pbuffer and frees any allocated resources.
175*/
176QGLPixelBuffer::~QGLPixelBuffer()
177{
178 Q_D(QGLPixelBuffer);
179
180 // defined in qpaintengine_opengl.cpp
181 QGLContext *current = const_cast<QGLContext *>(QGLContext::currentContext());
182 if (current != d->qctx)
183 makeCurrent();
184 qgl_cleanup_glyph_cache(d->qctx);
185 d->cleanup();
186 delete d->qctx;
187 if (current && current != d->qctx)
188 current->makeCurrent();
189 delete d_ptr;
190}
191
192/*! \fn bool QGLPixelBuffer::makeCurrent()
193
194 Makes this pbuffer the current OpenGL rendering context. Returns
195 true on success; otherwise returns false.
196
197 \sa QGLContext::makeCurrent(), doneCurrent()
198*/
199
200bool QGLPixelBuffer::makeCurrent()
201{
202 Q_D(QGLPixelBuffer);
203 if (d->invalid)
204 return false;
205 d->qctx->makeCurrent();
206 return true;
207}
208
209/*! \fn bool QGLPixelBuffer::doneCurrent()
210
211 Makes no context the current OpenGL context. Returns true on
212 success; otherwise returns false.
213*/
214
215bool QGLPixelBuffer::doneCurrent()
216{
217 Q_D(QGLPixelBuffer);
218 if (d->invalid)
219 return false;
220 d->qctx->doneCurrent();
221 return true;
222}
223
224/*!
225 Generates and binds a 2D GL texture that is the same size as the
226 pbuffer, and returns the texture's ID. This can be used in
227 conjunction with bindToDynamicTexture() and
228 updateDynamicTexture().
229
230 \sa size()
231*/
232
233#if (defined(Q_WS_X11) || defined(Q_WS_WIN)) && !defined(QT_OPENGL_ES)
234GLuint QGLPixelBuffer::generateDynamicTexture() const
235{
236 Q_D(const QGLPixelBuffer);
237 GLuint texture;
238 glGenTextures(1, &texture);
239 glBindTexture(GL_TEXTURE_2D, texture);
240 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, d->req_size.width(), d->req_size.height(), 0, GL_RGBA, GL_FLOAT, 0);
241 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
242 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
243 return texture;
244}
245#endif
246