source: trunk/src/opengl/qglframebufferobject.cpp@ 494

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

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

File size: 24.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#include "qglframebufferobject.h"
43
44#include <qdebug.h>
45#include <private/qgl_p.h>
46#include <private/qpaintengine_opengl_p.h>
47#include <qglframebufferobject.h>
48#include <qlibrary.h>
49#include <qimage.h>
50
51QT_BEGIN_NAMESPACE
52
53extern QImage qt_gl_read_framebuffer(const QSize&, bool, bool);
54
55#define QGL_FUNC_CONTEXT QGLContext *ctx = d_ptr->ctx;
56
57#define QT_CHECK_GLERROR() \
58{ \
59 GLenum err = glGetError(); \
60 if (err != GL_NO_ERROR) { \
61 qDebug("[%s line %d] GL Error: %d", \
62 __FILE__, __LINE__, (int)err); \
63 } \
64}
65
66class QGLFramebufferObjectPrivate
67{
68public:
69 QGLFramebufferObjectPrivate() : depth_stencil_buffer(0), valid(false), bound(false), ctx(0) {}
70 ~QGLFramebufferObjectPrivate() {}
71
72 void init(const QSize& sz, QGLFramebufferObject::Attachment attachment,
73 GLenum internal_format, GLenum texture_target);
74 bool checkFramebufferStatus() const;
75 GLuint texture;
76 GLuint fbo;
77 GLuint depth_stencil_buffer;
78 GLenum target;
79 QSize size;
80 uint valid : 1;
81 uint bound : 1;
82 QGLFramebufferObject::Attachment fbo_attachment;
83 QGLContext *ctx; // for Windows extension ptrs
84};
85
86bool QGLFramebufferObjectPrivate::checkFramebufferStatus() const
87{
88 GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT);
89 switch(status) {
90 case GL_NO_ERROR:
91 case GL_FRAMEBUFFER_COMPLETE_EXT:
92 return true;
93 break;
94 case GL_FRAMEBUFFER_UNSUPPORTED_EXT:
95 qDebug("QGLFramebufferObject: Unsupported framebuffer format.");
96 break;
97 case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT_EXT:
98 qDebug("QGLFramebufferObject: Framebuffer incomplete attachment.");
99 break;
100 case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT_EXT:
101 qDebug("QGLFramebufferObject: Framebuffer incomplete, missing attachment.");
102 break;
103#ifdef GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT
104 case GL_FRAMEBUFFER_INCOMPLETE_DUPLICATE_ATTACHMENT_EXT:
105 qDebug("QGLFramebufferObject: Framebuffer incomplete, duplicate attachment.");
106 break;
107#endif
108 case GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS_EXT:
109 qDebug("QGLFramebufferObject: Framebuffer incomplete, attached images must have same dimensions.");
110 break;
111 case GL_FRAMEBUFFER_INCOMPLETE_FORMATS_EXT:
112 qDebug("QGLFramebufferObject: Framebuffer incomplete, attached images must have same format.");
113 break;
114 case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER_EXT:
115 qDebug("QGLFramebufferObject: Framebuffer incomplete, missing draw buffer.");
116 break;
117 case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER_EXT:
118 qDebug("QGLFramebufferObject: Framebuffer incomplete, missing read buffer.");
119 break;
120 default:
121 qDebug() <<"QGLFramebufferObject: An undefined error has occurred: "<< status;
122 break;
123 }
124 return false;
125}
126
127void QGLFramebufferObjectPrivate::init(const QSize &sz, QGLFramebufferObject::Attachment attachment,
128 GLenum texture_target, GLenum internal_format)
129{
130 ctx = const_cast<QGLContext *>(QGLContext::currentContext());
131 bool ext_detected = (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
132 if (!ext_detected || (ext_detected && !qt_resolve_framebufferobject_extensions(ctx)))
133 return;
134
135 size = sz;
136 target = texture_target;
137 // texture dimensions
138
139 while (glGetError() != GL_NO_ERROR) {} // reset error state
140 glGenFramebuffersEXT(1, &fbo);
141 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo);
142
143 QT_CHECK_GLERROR();
144 // init texture
145 glGenTextures(1, &texture);
146 glBindTexture(target, texture);
147 glTexImage2D(target, 0, internal_format, size.width(), size.height(), 0,
148 GL_RGBA, GL_UNSIGNED_BYTE, NULL);
149#ifndef QT_OPENGL_ES
150 glTexParameteri(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
151 glTexParameteri(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
152 glTexParameteri(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
153 glTexParameteri(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
154#else
155 glTexParameterf(target, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
156 glTexParameterf(target, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
157 glTexParameterf(target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
158 glTexParameterf(target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
159#endif
160 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT,
161 target, texture, 0);
162
163 QT_CHECK_GLERROR();
164 valid = checkFramebufferStatus();
165
166 if (attachment == QGLFramebufferObject::CombinedDepthStencil
167 && (QGLExtensions::glExtensions & QGLExtensions::PackedDepthStencil)) {
168 // depth and stencil buffer needs another extension
169 glGenRenderbuffersEXT(1, &depth_stencil_buffer);
170 Q_ASSERT(!glIsRenderbufferEXT(depth_stencil_buffer));
171 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
172 Q_ASSERT(glIsRenderbufferEXT(depth_stencil_buffer));
173 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, size.width(), size.height());
174 GLint i = 0;
175 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
176 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
177 GL_RENDERBUFFER_EXT, depth_stencil_buffer);
178 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
179 GL_RENDERBUFFER_EXT, depth_stencil_buffer);
180 fbo_attachment = QGLFramebufferObject::CombinedDepthStencil;
181 valid = checkFramebufferStatus();
182 if (!valid)
183 glDeleteRenderbuffersEXT(1, &depth_stencil_buffer);
184 } else if (attachment == QGLFramebufferObject::Depth
185 || attachment == QGLFramebufferObject::CombinedDepthStencil)
186 {
187 glGenRenderbuffersEXT(1, &depth_stencil_buffer);
188 Q_ASSERT(!glIsRenderbufferEXT(depth_stencil_buffer));
189 glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, depth_stencil_buffer);
190 Q_ASSERT(glIsRenderbufferEXT(depth_stencil_buffer));
191#ifdef QT_OPENGL_ES
192#define GL_DEPTH_COMPONENT16 0x81A5
193 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT16, size.width(), size.height());
194#else
195 glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, size.width(), size.height());
196#endif
197 GLint i = 0;
198 glGetRenderbufferParameterivEXT(GL_RENDERBUFFER_EXT, GL_RENDERBUFFER_DEPTH_SIZE_EXT, &i);
199 glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
200 GL_RENDERBUFFER_EXT, depth_stencil_buffer);
201 fbo_attachment = QGLFramebufferObject::Depth;
202 valid = checkFramebufferStatus();
203 if (!valid)
204 glDeleteRenderbuffersEXT(1, &depth_stencil_buffer);
205 } else {
206 fbo_attachment = QGLFramebufferObject::NoAttachment;
207 }
208
209 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
210 if (!valid) {
211 glDeleteTextures(1, &texture);
212 glDeleteFramebuffersEXT(1, &fbo);
213 }
214 QT_CHECK_GLERROR();
215}
216
217/*!
218 \class QGLFramebufferObject
219 \brief The QGLFramebufferObject class encapsulates an OpenGL framebuffer object.
220 \since 4.2
221
222 \ingroup multimedia
223
224 The QGLFramebufferObject class encapsulates an OpenGL framebuffer
225 object, defined by the \c{GL_EXT_framebuffer_object} extension. In
226 addition it provides a rendering surface that can be painted on
227 with a QPainter, rendered to using native GL calls, or both. This
228 surface can be bound and used as a regular texture in your own GL
229 drawing code. By default, the QGLFramebufferObject class
230 generates a 2D GL texture (using the \c{GL_TEXTURE_2D} target),
231 which is used as the internal rendering target.
232
233 \bold{It is important to have a current GL context when creating a
234 QGLFramebufferObject, otherwise initialization will fail.}
235
236 OpenGL framebuffer objects and pbuffers (see
237 \l{QGLPixelBuffer}{QGLPixelBuffer}) can both be used to render to
238 offscreen surfaces, but there are a number of advantages with
239 using framebuffer objects instead of pbuffers:
240
241 \list 1
242 \o A framebuffer object does not require a separate rendering
243 context, so no context switching will occur when switching
244 rendering targets. There is an overhead involved in switching
245 targets, but in general it is cheaper than a context switch to a
246 pbuffer.
247
248 \o Rendering to dynamic textures (i.e. render-to-texture
249 functionality) works on all platforms. No need to do explicit copy
250 calls from a render buffer into a texture, as was necessary on
251 systems that did not support the \c{render_texture} extension.
252
253 \o It is possible to attach several rendering buffers (or texture
254 objects) to the same framebuffer object, and render to all of them
255 without doing a context switch.
256
257 \o The OpenGL framebuffer extension is a pure GL extension with no
258 system dependant WGL, CGL, or GLX parts. This makes using
259 framebuffer objects more portable.
260 \endlist
261
262 Note that primitives drawn to a QGLFramebufferObject with QPainter
263 will only be antialiased if the QPainter::HighQualityAntialiasing
264 render hint is set. This is because there is currently no support
265 for the \c{GL_EXT_framebuffer_multisample} extension, which is
266 required to do multisample based antialiasing. Also note that the
267 QPainter::HighQualityAntialiasing render hint requires the
268 \c{GL_ARB_fragment_program} extension to work in OpenGL.
269
270 \sa {Framebuffer Object Example}
271*/
272
273
274/*!
275 \enum QGLFramebufferObject::Attachment
276 \since 4.3
277
278 This enum type is used to configure the depth and stencil buffers
279 attached to the framebuffer object when it is created.
280
281 \value NoAttachment No attachment is added to the framebuffer object. Note that the
282 OpenGL depth and stencil tests won't work when rendering to a
283 framebuffer object without any depth or stencil buffers.
284 This is the default value.
285
286 \value CombinedDepthStencil If the \c GL_EXT_packed_depth_stencil extension is present,
287 a combined depth and stencil buffer is attached.
288 If the extension is not present, only a depth buffer is attached.
289
290 \value Depth A depth buffer is attached to the framebuffer object.
291
292 \sa attachment()
293*/
294
295
296/*! \fn QGLFramebufferObject::QGLFramebufferObject(const QSize &size, GLenum target)
297
298 Constructs an OpenGL framebuffer object and binds a 2D GL texture
299 to the buffer of the size \a size. The texture is bound to the
300 \c GL_COLOR_ATTACHMENT0 target in the framebuffer object.
301
302 The \a target parameter is used to specify the GL texture
303 target. The default target is \c GL_TEXTURE_2D. Keep in mind that
304 \c GL_TEXTURE_2D textures must have a power of 2 width and height
305 (e.g. 256x512), unless you are using OpenGL 2.0 or higher.
306
307 By default, no depth and stencil buffers are attached. This behavior
308 can be toggled using one of the overloaded constructors.
309
310 The default internal texture format is \c GL_RGBA8.
311
312 It is important that you have a current GL context set when
313 creating the QGLFramebufferObject, otherwise the initialization
314 will fail.
315
316 \sa size(), texture(), attachment()
317*/
318
319#ifndef QT_OPENGL_ES
320#define DEFAULT_FORMAT GL_RGBA8
321#else
322#define DEFAULT_FORMAT GL_RGBA
323#endif
324
325QGLFramebufferObject::QGLFramebufferObject(const QSize &size, GLenum target)
326 : d_ptr(new QGLFramebufferObjectPrivate)
327{
328 Q_D(QGLFramebufferObject);
329 d->init(size, NoAttachment, target, DEFAULT_FORMAT);
330}
331
332#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
333/*! \internal */
334QGLFramebufferObject::QGLFramebufferObject(const QSize &size, QMacCompatGLenum target)
335 : d_ptr(new QGLFramebufferObjectPrivate)
336{
337 Q_D(QGLFramebufferObject);
338 d->init(size, NoAttachment, target, DEFAULT_FORMAT);
339}
340#endif
341
342/*! \overload
343
344 Constructs an OpenGL framebuffer object and binds a 2D GL texture
345 to the buffer of the given \a width and \a height.
346
347 \sa size(), texture()
348*/
349QGLFramebufferObject::QGLFramebufferObject(int width, int height, GLenum target)
350 : d_ptr(new QGLFramebufferObjectPrivate)
351{
352 Q_D(QGLFramebufferObject);
353 d->init(QSize(width, height), NoAttachment, target, DEFAULT_FORMAT);
354}
355
356#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
357/*! \internal */
358QGLFramebufferObject::QGLFramebufferObject(int width, int height, QMacCompatGLenum target)
359 : d_ptr(new QGLFramebufferObjectPrivate)
360{
361 Q_D(QGLFramebufferObject);
362 d->init(QSize(width, height), NoAttachment, target, DEFAULT_FORMAT);
363}
364#endif
365
366/*! \overload
367
368 Constructs an OpenGL framebuffer object and binds a texture to the
369 buffer of the given \a width and \a height.
370
371 The \a attachment parameter describes the depth/stencil buffer
372 configuration, \a target the texture target and \a internal_format
373 the internal texture format. The default texture target is \c
374 GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8.
375
376 \sa size(), texture(), attachment()
377*/
378QGLFramebufferObject::QGLFramebufferObject(int width, int height, Attachment attachment,
379 GLenum target, GLenum internal_format)
380 : d_ptr(new QGLFramebufferObjectPrivate)
381{
382 Q_D(QGLFramebufferObject);
383 d->init(QSize(width, height), attachment, target, internal_format);
384}
385
386#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
387/*! \internal */
388QGLFramebufferObject::QGLFramebufferObject(int width, int height, Attachment attachment,
389 QMacCompatGLenum target, QMacCompatGLenum internal_format)
390 : d_ptr(new QGLFramebufferObjectPrivate)
391{
392 Q_D(QGLFramebufferObject);
393 d->init(QSize(width, height), attachment, target, internal_format);
394}
395#endif
396
397/*! \overload
398
399 Constructs an OpenGL framebuffer object and binds a texture to the
400 buffer of the given \a size.
401
402 The \a attachment parameter describes the depth/stencil buffer
403 configuration, \a target the texture target and \a internal_format
404 the internal texture format. The default texture target is \c
405 GL_TEXTURE_2D, while the default internal format is \c GL_RGBA8.
406
407 \sa size(), texture(), attachment()
408*/
409QGLFramebufferObject::QGLFramebufferObject(const QSize &size, Attachment attachment,
410 GLenum target, GLenum internal_format)
411 : d_ptr(new QGLFramebufferObjectPrivate)
412{
413 Q_D(QGLFramebufferObject);
414 d->init(size, attachment, target, internal_format);
415}
416
417#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
418/*! \internal */
419QGLFramebufferObject::QGLFramebufferObject(const QSize &size, Attachment attachment,
420 QMacCompatGLenum target, QMacCompatGLenum internal_format)
421 : d_ptr(new QGLFramebufferObjectPrivate)
422{
423 Q_D(QGLFramebufferObject);
424 d->init(size, attachment, target, internal_format);
425}
426#endif
427
428/*!
429 \fn QGLFramebufferObject::~QGLFramebufferObject()
430
431 Destroys the framebuffer object and frees any allocated resources.
432*/
433QGLFramebufferObject::~QGLFramebufferObject()
434{
435 Q_D(QGLFramebufferObject);
436 QGL_FUNC_CONTEXT;
437
438 if (isValid()
439 && (d->ctx == QGLContext::currentContext()
440 || qgl_share_reg()->checkSharing(d->ctx, QGLContext::currentContext())))
441 {
442 glDeleteTextures(1, &d->texture);
443 if (d->depth_stencil_buffer)
444 glDeleteRenderbuffersEXT(1, &d->depth_stencil_buffer);
445 glDeleteFramebuffersEXT(1, &d->fbo);
446 }
447 delete d_ptr;
448}
449
450/*!
451 \fn bool QGLFramebufferObject::isValid() const
452
453 Returns true if the framebuffer object is valid.
454
455 The framebuffer can become invalid if the initialization process
456 fails, the user attaches an invalid buffer to the framebuffer
457 object, or a non-power of 2 width/height is specified as the
458 texture size if the texture target is \c{GL_TEXTURE_2D}.
459*/
460bool QGLFramebufferObject::isValid() const
461{
462 Q_D(const QGLFramebufferObject);
463 return d->valid;
464}
465
466/*!
467 \fn bool QGLFramebufferObject::bind()
468
469 Switches rendering from the default, windowing system provided
470 framebuffer to this framebuffer object.
471 Returns true upon success, false otherwise.
472*/
473bool QGLFramebufferObject::bind()
474{
475 if (!isValid())
476 return false;
477 Q_D(QGLFramebufferObject);
478 QGL_FUNC_CONTEXT;
479 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, d->fbo);
480 d->bound = d->valid = d->checkFramebufferStatus();
481 return d->valid;
482}
483
484/*!
485 \fn bool QGLFramebufferObject::release()
486
487 Switches rendering back to the default, windowing system provided
488 framebuffer.
489 Returns true upon success, false otherwise.
490*/
491bool QGLFramebufferObject::release()
492{
493 if (!isValid())
494 return false;
495 Q_D(QGLFramebufferObject);
496 QGL_FUNC_CONTEXT;
497 glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
498 d->valid = d->checkFramebufferStatus();
499 d->bound = false;
500 return d->valid;
501}
502
503/*!
504 \fn GLuint QGLFramebufferObject::texture() const
505
506 Returns the texture id for the texture attached as the default
507 rendering target in this framebuffer object. This texture id can
508 be bound as a normal texture in your own GL code.
509*/
510GLuint QGLFramebufferObject::texture() const
511{
512 Q_D(const QGLFramebufferObject);
513 return d->texture;
514}
515
516/*!
517 \fn QSize QGLFramebufferObject::size() const
518
519 Returns the size of the texture attached to this framebuffer
520 object.
521*/
522QSize QGLFramebufferObject::size() const
523{
524 Q_D(const QGLFramebufferObject);
525 return d->size;
526}
527
528/*!
529 \fn QImage QGLFramebufferObject::toImage() const
530
531 Returns the contents of this framebuffer object as a QImage.
532*/
533QImage QGLFramebufferObject::toImage() const
534{
535 Q_D(const QGLFramebufferObject);
536 if (!d->valid)
537 return QImage();
538
539 const_cast<QGLFramebufferObject *>(this)->bind();
540 QImage image = qt_gl_read_framebuffer(d->size, d->ctx->format().alpha(), true);
541 const_cast<QGLFramebufferObject *>(this)->release();
542
543 return image;
544}
545
546#if !defined(QT_OPENGL_ES_2)
547Q_GLOBAL_STATIC(QOpenGLPaintEngine, qt_buffer_paintengine)
548#endif
549
550/*! \reimp */
551QPaintEngine *QGLFramebufferObject::paintEngine() const
552{
553#if !defined(QT_OPENGL_ES_2)
554 return qt_buffer_paintengine();
555#else
556 return 0;
557#endif
558}
559
560/*!
561 \fn bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
562
563 Returns true if the OpenGL \c{GL_EXT_framebuffer_object} extension
564 is present on this system; otherwise returns false.
565*/
566bool QGLFramebufferObject::hasOpenGLFramebufferObjects()
567{
568 QGLWidget dmy; // needed to detect and init the QGLExtensions object
569 return (QGLExtensions::glExtensions & QGLExtensions::FramebufferObject);
570}
571
572/*!
573 \since 4.4
574
575 Draws the given texture, \a textureId, to the given target rectangle,
576 \a target, in OpenGL model space. The \a textureTarget should be a 2D
577 texture target.
578
579 The framebuffer object should be bound when calling this function.
580
581 Equivalent to the corresponding QGLContext::drawTexture().
582*/
583void QGLFramebufferObject::drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget)
584{
585 Q_D(QGLFramebufferObject);
586 d->ctx->drawTexture(target, textureId, textureTarget);
587}
588
589#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
590/*! \internal */
591void QGLFramebufferObject::drawTexture(const QRectF &target, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
592{
593 Q_D(QGLFramebufferObject);
594 d->ctx->drawTexture(target, textureId, textureTarget);
595}
596#endif
597
598/*!
599 \since 4.4
600
601 Draws the given texture, \a textureId, at the given \a point in OpenGL
602 model space. The \a textureTarget should be a 2D texture target.
603
604 The framebuffer object should be bound when calling this function.
605
606 Equivalent to the corresponding QGLContext::drawTexture().
607*/
608void QGLFramebufferObject::drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget)
609{
610 Q_D(QGLFramebufferObject);
611 d->ctx->drawTexture(point, textureId, textureTarget);
612}
613
614#ifdef Q_MAC_COMPAT_GL_FUNCTIONS
615/*! \internal */
616void QGLFramebufferObject::drawTexture(const QPointF &point, QMacCompatGLuint textureId, QMacCompatGLenum textureTarget)
617{
618 Q_D(QGLFramebufferObject);
619 d->ctx->drawTexture(point, textureId, textureTarget);
620}
621#endif
622
623extern int qt_defaultDpi();
624
625/*! \reimp */
626int QGLFramebufferObject::metric(PaintDeviceMetric metric) const
627{
628 Q_D(const QGLFramebufferObject);
629
630 float dpmx = qt_defaultDpi()*100./2.54;
631 float dpmy = qt_defaultDpi()*100./2.54;
632 int w = d->size.width();
633 int h = d->size.height();
634 switch (metric) {
635 case PdmWidth:
636 return w;
637
638 case PdmHeight:
639 return h;
640
641 case PdmWidthMM:
642 return qRound(w * 1000 / dpmx);
643
644 case PdmHeightMM:
645 return qRound(h * 1000 / dpmy);
646
647 case PdmNumColors:
648 return 0;
649
650 case PdmDepth:
651 return 32;//d->depth;
652
653 case PdmDpiX:
654 return (int)(dpmx * 0.0254);
655
656 case PdmDpiY:
657 return (int)(dpmy * 0.0254);
658
659 case PdmPhysicalDpiX:
660 return (int)(dpmx * 0.0254);
661
662 case PdmPhysicalDpiY:
663 return (int)(dpmy * 0.0254);
664
665 default:
666 qWarning("QGLFramebufferObject::metric(), Unhandled metric type: %d.\n", metric);
667 break;
668 }
669 return 0;
670}
671
672/*!
673 \fn GLuint QGLFramebufferObject::handle() const
674
675 Returns the GL framebuffer object handle for this framebuffer
676 object (returned by the \c{glGenFrameBuffersEXT()} function). This
677 handle can be used to attach new images or buffers to the
678 framebuffer. The user is responsible for cleaning up and
679 destroying these objects.
680*/
681GLuint QGLFramebufferObject::handle() const
682{
683 Q_D(const QGLFramebufferObject);
684 return d->fbo;
685}
686
687/*! \fn int QGLFramebufferObject::devType() const
688
689 \reimp
690*/
691
692
693/*!
694 Returns the status of the depth and stencil buffers attached to
695 this framebuffer object.
696*/
697
698QGLFramebufferObject::Attachment QGLFramebufferObject::attachment() const
699{
700 Q_D(const QGLFramebufferObject);
701 if (d->valid)
702 return d->fbo_attachment;
703 return NoAttachment;
704}
705
706/*!
707 \since 4.5
708
709 Returns true if the framebuffer object is currently bound to a context,
710 otherwise false is returned.
711*/
712
713bool QGLFramebufferObject::isBound() const
714{
715 Q_D(const QGLFramebufferObject);
716 return d->bound;
717}
718
719QT_END_NAMESPACE
Note: See TracBrowser for help on using the repository browser.