qopenglwindow.cpp

Absolute File Name:/home/qt/qt5_coco/qt5/qtbase/src/gui/kernel/qopenglwindow.cpp
Source codeSwitch to Preprocessed file
LineSourceCount
1/****************************************************************************-
2**-
3** Copyright (C) 2016 The Qt Company Ltd.-
4** Contact: https://www.qt.io/licensing/-
5**-
6** This file is part of the QtGui module of the Qt Toolkit.-
7**-
8** $QT_BEGIN_LICENSE:LGPL$-
9** Commercial License Usage-
10** Licensees holding valid commercial Qt licenses may use this file in-
11** accordance with the commercial license agreement provided with the-
12** Software or, alternatively, in accordance with the terms contained in-
13** a written agreement between you and The Qt Company. For licensing terms-
14** and conditions see https://www.qt.io/terms-conditions. For further-
15** information use the contact form at https://www.qt.io/contact-us.-
16**-
17** GNU Lesser General Public License Usage-
18** Alternatively, this file may be used under the terms of the GNU Lesser-
19** General Public License version 3 as published by the Free Software-
20** Foundation and appearing in the file LICENSE.LGPL3 included in the-
21** packaging of this file. Please review the following information to-
22** ensure the GNU Lesser General Public License version 3 requirements-
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.-
24**-
25** GNU General Public License Usage-
26** Alternatively, this file may be used under the terms of the GNU-
27** General Public License version 2.0 or (at your option) the GNU General-
28** Public license version 3 or any later version approved by the KDE Free-
29** Qt Foundation. The licenses are as published by the Free Software-
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3-
31** included in the packaging of this file. Please review the following-
32** information to ensure the GNU General Public License requirements will-
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and-
34** https://www.gnu.org/licenses/gpl-3.0.html.-
35**-
36** $QT_END_LICENSE$-
37**-
38****************************************************************************/-
39-
40#include "qopenglwindow.h"-
41#include "qpaintdevicewindow_p.h"-
42#include <QtGui/QOpenGLFramebufferObject>-
43#include <QtGui/QOpenGLPaintDevice>-
44#include <QtGui/QOpenGLFunctions>-
45#include <QtGui/private/qopengltextureblitter_p.h>-
46#include <QtGui/private/qopenglextensions_p.h>-
47#include <QtGui/private/qopenglcontext_p.h>-
48#include <QtGui/QMatrix4x4>-
49#include <QtGui/QOffscreenSurface>-
50-
51QT_BEGIN_NAMESPACE-
52-
53/*!-
54 \class QOpenGLWindow-
55 \inmodule QtGui-
56 \since 5.4-
57 \brief The QOpenGLWindow class is a convenience subclass of QWindow to perform OpenGL painting.-
58-
59 QOpenGLWindow is an enhanced QWindow that allows easily creating windows that-
60 perform OpenGL rendering using an API that is compatible with QOpenGLWidget-
61 and is similar to the legacy QGLWidget. Unlike QOpenGLWidget, QOpenGLWindow-
62 has no dependency on the widgets module and offers better performance.-
63-
64 A typical application will subclass QOpenGLWindow and reimplement the following-
65 virtual functions:-
66-
67 \list-
68-
69 \li initializeGL() to perform OpenGL resource initialization-
70-
71 \li resizeGL() to set up the transformation matrices and other window size dependent resources-
72-
73 \li paintGL() to issue OpenGL commands or draw using QPainter-
74-
75 \endlist-
76-
77 To schedule a repaint, call the update() function. Note that this will not-
78 immediately result in a call to paintGL(). Calling update() multiple times in-
79 a row will not change the behavior in any way.-
80-
81 This is a slot so it can be connected to a \l QTimer::timeout() signal to-
82 perform animation. Note however that in the modern OpenGL world it is a much-
83 better choice to rely on synchronization to the vertical refresh rate of the-
84 display. See \l{QSurfaceFormat::setSwapInterval()}{setSwapInterval()} on a-
85 description of the swap interval. With a swap interval of \c 1, which is the-
86 case on most systems by default, the-
87 \l{QOpenGLContext::swapBuffers()}{swapBuffers()} call, that is executed-
88 internally by QOpenGLWindow after each repaint, will block and wait for-
89 vsync. This means that whenever the swap is done, an update can be scheduled-
90 again by calling update(), without relying on timers.-
91-
92 To request a specific configuration for the context, use setFormat()-
93 like for any other QWindow. This allows, among others, requesting a-
94 given OpenGL version and profile, or enabling depth and stencil-
95 buffers.-
96-
97 Unlike QWindow, QOpenGLWindow allows opening a painter on itself and perform-
98 QPainter-based drawing.-
99-
100 QOpenGLWindow supports multiple update behaviors. The default,-
101 \c NoPartialUpdate is equivalent to a regular, OpenGL-based QWindow or the-
102 legacy QGLWidget. In contrast, \c PartialUpdateBlit and \c PartialUpdateBlend are-
103 more in line with QOpenGLWidget's way of working, where there is always an-
104 extra, dedicated framebuffer object present. These modes allow, by-
105 sacrificing some performance, redrawing only a smaller area on each paint and-
106 having the rest of the content preserved from of the previous frame. This is-
107 useful for applications than render incrementally using QPainter, because-
108 this way they do not have to redraw the entire window content on each-
109 paintGL() call.-
110-
111 Similarly to QOpenGLWidget, QOpenGLWindow supports the Qt::AA_ShareOpenGLContexts-
112 attribute. When enabled, the OpenGL contexts of all QOpenGLWindow instances will share-
113 with each other. This allows accessing each other's shareable OpenGL resources.-
114-
115 For more information on graphics in Qt, see \l {Graphics}.-
116 */-
117-
118/*!-
119 \enum QOpenGLWindow::UpdateBehavior-
120-
121 This enum describes the update strategy of the QOpenGLWindow.-
122-
123 \value NoPartialUpdate Indicates that the entire window surface will-
124 redrawn on each update and so no additional framebuffers are needed.-
125 This is the setting used in most cases and is equivalent to how drawing-
126 directly via QWindow would function.-
127-
128 \value PartialUpdateBlit Indicates that the drawing performed in paintGL()-
129 does not cover the entire window. In this case an extra framebuffer object-
130 is created under the hood, and rendering performed in paintGL() will target-
131 this framebuffer. This framebuffer is then blitted onto the window surface's-
132 default framebuffer after each paint. This allows having QPainter-based drawing-
133 code in paintGL() which only repaints a smaller area at a time, because, unlike-
134 NoPartialUpdate, the previous content is preserved.-
135-
136 \value PartialUpdateBlend Similar to PartialUpdateBlit, but instead of using-
137 framebuffer blits, the contents of the extra framebuffer is rendered by-
138 drawing a textured quad with blending enabled. This, unlike PartialUpdateBlit,-
139 allows alpha blended content and works even when the glBlitFramebuffer is-
140 not available. Performance-wise this setting is likely to be somewhat slower-
141 than PartialUpdateBlit.-
142 */-
143-
144/*!-
145 \fn void QOpenGLWindow::frameSwapped()-
146-
147 This signal is emitted after the potentially blocking-
148 \l{QOpenGLContext::swapBuffers()}{buffer swap} has been done. Applications-
149 that wish to continuously repaint synchronized to the vertical refresh,-
150 should issue an update() upon this signal. This allows for a much smoother-
151 experience compared to the traditional usage of timers.-
152*/-
153-
154// GLES2 builds won't have these constants with the suffixless names-
155#ifndef GL_READ_FRAMEBUFFER-
156#define GL_READ_FRAMEBUFFER 0x8CA8-
157#endif-
158#ifndef GL_DRAW_FRAMEBUFFER-
159#define GL_DRAW_FRAMEBUFFER 0x8CA9-
160#endif-
161-
162class QOpenGLWindowPaintDevice : public QOpenGLPaintDevice-
163{-
164public:-
165 QOpenGLWindowPaintDevice(QOpenGLWindow *window) : m_window(window) { }
never executed: end of block
0
166 void ensureActiveTarget() Q_DECL_OVERRIDE;-
167-
168 QOpenGLWindow *m_window;-
169};-
170-
171class QOpenGLWindowPrivate : public QPaintDeviceWindowPrivate-
172{-
173 Q_DECLARE_PUBLIC(QOpenGLWindow)-
174public:-
175 QOpenGLWindowPrivate(QOpenGLContext *shareContext, QOpenGLWindow::UpdateBehavior updateBehavior)-
176 : updateBehavior(updateBehavior)-
177 , hasFboBlit(false)-
178 , shareContext(shareContext)-
179 {-
180 if (!shareContext)
!shareContextDescription
TRUEnever evaluated
FALSEnever evaluated
0
181 this->shareContext = qt_gl_global_share_context();
never executed: this->shareContext = qt_gl_global_share_context();
0
182 }
never executed: end of block
0
183-
184 ~QOpenGLWindowPrivate();-
185-
186 static QOpenGLWindowPrivate *get(QOpenGLWindow *w) { return w->d_func(); }
never executed: return w->d_func();
0
187-
188 void bindFBO();-
189 void initialize();-
190-
191 void beginPaint(const QRegion &region) Q_DECL_OVERRIDE;-
192 void endPaint() Q_DECL_OVERRIDE;-
193 void flush(const QRegion &region) Q_DECL_OVERRIDE;-
194-
195 QOpenGLWindow::UpdateBehavior updateBehavior;-
196 bool hasFboBlit;-
197 QScopedPointer<QOpenGLContext> context;-
198 QOpenGLContext *shareContext;-
199 QScopedPointer<QOpenGLFramebufferObject> fbo;-
200 QScopedPointer<QOpenGLWindowPaintDevice> paintDevice;-
201 QOpenGLTextureBlitter blitter;-
202 QColor backgroundColor;-
203 QScopedPointer<QOffscreenSurface> offscreenSurface;-
204};-
205-
206QOpenGLWindowPrivate::~QOpenGLWindowPrivate()-
207{-
208 Q_Q(QOpenGLWindow);-
209 if (q->isValid()) {
q->isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
210 q->makeCurrent(); // this works even when the platformwindow is destroyed-
211 paintDevice.reset(0);-
212 fbo.reset(0);-
213 blitter.destroy();-
214 q->doneCurrent();-
215 }
never executed: end of block
0
216}
never executed: end of block
0
217-
218void QOpenGLWindowPrivate::initialize()-
219{-
220 Q_Q(QOpenGLWindow);-
221-
222 if (context)
contextDescription
TRUEnever evaluated
FALSEnever evaluated
0
223 return;
never executed: return;
0
224-
225 context.reset(new QOpenGLContext);-
226 context->setShareContext(shareContext);-
227 context->setFormat(q->requestedFormat());-
228 if (!context->create())
!context->create()Description
TRUEnever evaluated
FALSEnever evaluated
0
229 qWarning("QOpenGLWindow::beginPaint: Failed to create context");
never executed: QMessageLogger(__FILE__, 229, __PRETTY_FUNCTION__).warning("QOpenGLWindow::beginPaint: Failed to create context");
0
230 if (!context->makeCurrent(q))
!context->makeCurrent(q)Description
TRUEnever evaluated
FALSEnever evaluated
0
231 qWarning("QOpenGLWindow::beginPaint: Failed to make context current");
never executed: QMessageLogger(__FILE__, 231, __PRETTY_FUNCTION__).warning("QOpenGLWindow::beginPaint: Failed to make context current");
0
232-
233 paintDevice.reset(new QOpenGLWindowPaintDevice(q));-
234 if (updateBehavior == QOpenGLWindow::PartialUpdateBlit)
updateBehavior...tialUpdateBlitDescription
TRUEnever evaluated
FALSEnever evaluated
0
235 hasFboBlit = QOpenGLFramebufferObject::hasOpenGLFramebufferBlit();
never executed: hasFboBlit = QOpenGLFramebufferObject::hasOpenGLFramebufferBlit();
0
236-
237 q->initializeGL();-
238}
never executed: end of block
0
239-
240void QOpenGLWindowPrivate::beginPaint(const QRegion &region)-
241{-
242 Q_UNUSED(region);-
243 Q_Q(QOpenGLWindow);-
244-
245 initialize();-
246 context->makeCurrent(q);-
247-
248 const int deviceWidth = q->width() * q->devicePixelRatio();-
249 const int deviceHeight = q->height() * q->devicePixelRatio();-
250 const QSize deviceSize(deviceWidth, deviceHeight);-
251 if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
updateBehavior...oPartialUpdateDescription
TRUEnever evaluated
FALSEnever evaluated
0
252 if (!fbo || fbo->size() != deviceSize) {
!fboDescription
TRUEnever evaluated
FALSEnever evaluated
fbo->size() != deviceSizeDescription
TRUEnever evaluated
FALSEnever evaluated
0
253 QOpenGLFramebufferObjectFormat fboFormat;-
254 fboFormat.setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil);-
255 const int samples = q->requestedFormat().samples();-
256 if (samples > 0) {
samples > 0Description
TRUEnever evaluated
FALSEnever evaluated
0
257 if (updateBehavior != QOpenGLWindow::PartialUpdateBlend)
updateBehavior...ialUpdateBlendDescription
TRUEnever evaluated
FALSEnever evaluated
0
258 fboFormat.setSamples(samples);
never executed: fboFormat.setSamples(samples);
0
259 else-
260 qWarning("QOpenGLWindow: PartialUpdateBlend does not support multisampling");
never executed: QMessageLogger(__FILE__, 260, __PRETTY_FUNCTION__).warning("QOpenGLWindow: PartialUpdateBlend does not support multisampling");
0
261 }-
262 fbo.reset(new QOpenGLFramebufferObject(deviceSize, fboFormat));-
263 markWindowAsDirty();-
264 }
never executed: end of block
0
265 } else {
never executed: end of block
0
266 markWindowAsDirty();-
267 }
never executed: end of block
0
268-
269 paintDevice->setSize(QSize(deviceWidth, deviceHeight));-
270 paintDevice->setDevicePixelRatio(q->devicePixelRatio());-
271 context->functions()->glViewport(0, 0, deviceWidth, deviceHeight);-
272-
273 context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());-
274-
275 q->paintUnderGL();-
276-
277 if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
updateBehavior...oPartialUpdateDescription
TRUEnever evaluated
FALSEnever evaluated
0
278 fbo->bind();
never executed: fbo->bind();
0
279}
never executed: end of block
0
280-
281void QOpenGLWindowPrivate::endPaint()-
282{-
283 Q_Q(QOpenGLWindow);-
284-
285 if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
updateBehavior...oPartialUpdateDescription
TRUEnever evaluated
FALSEnever evaluated
0
286 fbo->release();
never executed: fbo->release();
0
287-
288 context->functions()->glBindFramebuffer(GL_FRAMEBUFFER, context->defaultFramebufferObject());-
289-
290 if (updateBehavior == QOpenGLWindow::PartialUpdateBlit && hasFboBlit) {
updateBehavior...tialUpdateBlitDescription
TRUEnever evaluated
FALSEnever evaluated
hasFboBlitDescription
TRUEnever evaluated
FALSEnever evaluated
0
291 const int deviceWidth = q->width() * q->devicePixelRatio();-
292 const int deviceHeight = q->height() * q->devicePixelRatio();-
293 QOpenGLExtensions extensions(context.data());-
294 extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, fbo->handle());-
295 extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, context->defaultFramebufferObject());-
296 extensions.glBlitFramebuffer(0, 0, deviceWidth, deviceHeight,-
297 0, 0, deviceWidth, deviceHeight,-
298 GL_COLOR_BUFFER_BIT, GL_NEAREST);-
299 } else if (updateBehavior > QOpenGLWindow::NoPartialUpdate) {
never executed: end of block
updateBehavior...oPartialUpdateDescription
TRUEnever evaluated
FALSEnever evaluated
0
300 if (updateBehavior == QOpenGLWindow::PartialUpdateBlend) {
updateBehavior...ialUpdateBlendDescription
TRUEnever evaluated
FALSEnever evaluated
0
301 context->functions()->glEnable(GL_BLEND);-
302 context->functions()->glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);-
303 }
never executed: end of block
0
304 if (!blitter.isCreated())
!blitter.isCreated()Description
TRUEnever evaluated
FALSEnever evaluated
0
305 blitter.create();
never executed: blitter.create();
0
306-
307 QRect windowRect(QPoint(0, 0), fbo->size());-
308 QMatrix4x4 target = QOpenGLTextureBlitter::targetTransform(windowRect, windowRect);-
309 blitter.bind();-
310 blitter.blit(fbo->texture(), target, QOpenGLTextureBlitter::OriginBottomLeft);-
311 blitter.release();-
312-
313 if (updateBehavior == QOpenGLWindow::PartialUpdateBlend)
updateBehavior...ialUpdateBlendDescription
TRUEnever evaluated
FALSEnever evaluated
0
314 context->functions()->glDisable(GL_BLEND);
never executed: context->functions()->glDisable(0x0BE2);
0
315 }
never executed: end of block
0
316-
317 q->paintOverGL();-
318}
never executed: end of block
0
319-
320void QOpenGLWindowPrivate::bindFBO()-
321{-
322 if (updateBehavior > QOpenGLWindow::NoPartialUpdate)
updateBehavior...oPartialUpdateDescription
TRUEnever evaluated
FALSEnever evaluated
0
323 fbo->bind();
never executed: fbo->bind();
0
324 else-
325 QOpenGLFramebufferObject::bindDefault();
never executed: QOpenGLFramebufferObject::bindDefault();
0
326}-
327-
328void QOpenGLWindowPrivate::flush(const QRegion &region)-
329{-
330 Q_UNUSED(region);-
331 Q_Q(QOpenGLWindow);-
332 context->swapBuffers(q);-
333 emit q->frameSwapped();-
334}
never executed: end of block
0
335-
336void QOpenGLWindowPaintDevice::ensureActiveTarget()-
337{-
338 QOpenGLWindowPrivate::get(m_window)->bindFBO();-
339}
never executed: end of block
0
340-
341/*!-
342 Constructs a new QOpenGLWindow with the given \a parent and \a updateBehavior.-
343-
344 \sa QOpenGLWindow::UpdateBehavior-
345 */-
346QOpenGLWindow::QOpenGLWindow(QOpenGLWindow::UpdateBehavior updateBehavior, QWindow *parent)-
347 : QPaintDeviceWindow(*(new QOpenGLWindowPrivate(Q_NULLPTR, updateBehavior)), parent)-
348{-
349 setSurfaceType(QSurface::OpenGLSurface);-
350}
never executed: end of block
0
351-
352/*!-
353 Constructs a new QOpenGLWindow with the given \a parent and \a updateBehavior. The QOpenGLWindow's context will share with \a shareContext.-
354-
355 \sa QOpenGLWindow::UpdateBehavior shareContext-
356*/-
357QOpenGLWindow::QOpenGLWindow(QOpenGLContext *shareContext, UpdateBehavior updateBehavior, QWindow *parent)-
358 : QPaintDeviceWindow(*(new QOpenGLWindowPrivate(shareContext, updateBehavior)), parent)-
359{-
360 setSurfaceType(QSurface::OpenGLSurface);-
361}
never executed: end of block
0
362-
363/*!-
364 Destroys the QOpenGLWindow instance, freeing its resources.-
365-
366 The OpenGLWindow's context is made current in the destructor, allowing for-
367 safe destruction of any child object that may need to release OpenGL-
368 resources belonging to the context provided by this window.-
369-
370 \warning if you have objects wrapping OpenGL resources (such as-
371 QOpenGLBuffer, QOpenGLShaderProgram, etc.) as members of a QOpenGLWindow-
372 subclass, you may need to add a call to makeCurrent() in that subclass'-
373 destructor as well. Due to the rules of C++ object destruction, those objects-
374 will be destroyed \e{before} calling this function (but after that the-
375 destructor of the subclass has run), therefore making the OpenGL context-
376 current in this function happens too late for their safe disposal.-
377-
378 \sa makeCurrent-
379-
380 \since 5.5-
381*/-
382QOpenGLWindow::~QOpenGLWindow()-
383{-
384 makeCurrent();-
385}
never executed: end of block
0
386-
387/*!-
388 \return the update behavior for this QOpenGLWindow.-
389*/-
390QOpenGLWindow::UpdateBehavior QOpenGLWindow::updateBehavior() const-
391{-
392 Q_D(const QOpenGLWindow);-
393 return d->updateBehavior;
never executed: return d->updateBehavior;
0
394}-
395-
396/*!-
397 \return \c true if the window's OpenGL resources, like the context, have-
398 been successfully initialized. Note that the return value is always \c false-
399 until the window becomes exposed (shown).-
400*/-
401bool QOpenGLWindow::isValid() const-
402{-
403 Q_D(const QOpenGLWindow);-
404 return d->context && d->context->isValid();
never executed: return d->context && d->context->isValid();
0
405}-
406-
407/*!-
408 Prepares for rendering OpenGL content for this window by making the-
409 corresponding context current and binding the framebuffer object, if there is-
410 one, in that context context.-
411-
412 It is not necessary to call this function in most cases, because it is called-
413 automatically before invoking paintGL(). It is provided nonetheless to support-
414 advanced, multi-threaded scenarios where a thread different than the GUI or main-
415 thread may want to update the surface or framebuffer contents. See QOpenGLContext-
416 for more information on threading related issues.-
417-
418 This function is suitable for calling also when the underlying platform window-
419 is already destroyed. This means that it is safe to call this function from-
420 a QOpenGLWindow subclass' destructor. If there is no native window anymore,-
421 an offscreen surface is used instead. This ensures that OpenGL resource-
422 cleanup operations in the destructor will always work, as long as-
423 this function is called first.-
424-
425 \sa QOpenGLContext, context(), paintGL(), doneCurrent()-
426 */-
427void QOpenGLWindow::makeCurrent()-
428{-
429 Q_D(QOpenGLWindow);-
430-
431 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
432 return;
never executed: return;
0
433-
434 // The platform window may be destroyed at this stage and therefore-
435 // makeCurrent() may not safely be called with 'this'.-
436 if (handle()) {
handle()Description
TRUEnever evaluated
FALSEnever evaluated
0
437 d->context->makeCurrent(this);-
438 } else {
never executed: end of block
0
439 if (!d->offscreenSurface) {
!d->offscreenSurfaceDescription
TRUEnever evaluated
FALSEnever evaluated
0
440 d->offscreenSurface.reset(new QOffscreenSurface);-
441 d->offscreenSurface->setFormat(d->context->format());-
442 d->offscreenSurface->create();-
443 }
never executed: end of block
0
444 d->context->makeCurrent(d->offscreenSurface.data());-
445 }
never executed: end of block
0
446-
447 d->bindFBO();-
448}
never executed: end of block
0
449-
450/*!-
451 Releases the context.-
452-
453 It is not necessary to call this function in most cases, since the widget-
454 will make sure the context is bound and released properly when invoking-
455 paintGL().-
456-
457 \sa makeCurrent()-
458 */-
459void QOpenGLWindow::doneCurrent()-
460{-
461 Q_D(QOpenGLWindow);-
462-
463 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
464 return;
never executed: return;
0
465-
466 d->context->doneCurrent();-
467}
never executed: end of block
0
468-
469/*!-
470 \return The QOpenGLContext used by this window or \c 0 if not yet initialized.-
471 */-
472QOpenGLContext *QOpenGLWindow::context() const-
473{-
474 Q_D(const QOpenGLWindow);-
475 return d->context.data();
never executed: return d->context.data();
0
476}-
477-
478/*!-
479 \return The QOpenGLContext requested to be shared with this window's QOpenGLContext.-
480*/-
481QOpenGLContext *QOpenGLWindow::shareContext() const-
482{-
483 Q_D(const QOpenGLWindow);-
484 return d->shareContext;
never executed: return d->shareContext;
0
485}-
486-
487/*!-
488 The framebuffer object handle used by this window.-
489-
490 When the update behavior is set to \c NoPartialUpdate, there is no separate-
491 framebuffer object. In this case the returned value is the ID of the-
492 default framebuffer.-
493-
494 Otherwise the value of the ID of the framebuffer object or \c 0 if not-
495 yet initialized.-
496 */-
497GLuint QOpenGLWindow::defaultFramebufferObject() const-
498{-
499 Q_D(const QOpenGLWindow);-
500 if (d->updateBehavior > NoPartialUpdate && d->fbo)
d->updateBehav...oPartialUpdateDescription
TRUEnever evaluated
FALSEnever evaluated
d->fboDescription
TRUEnever evaluated
FALSEnever evaluated
0
501 return d->fbo->handle();
never executed: return d->fbo->handle();
0
502 else if (QOpenGLContext *ctx = QOpenGLContext::currentContext())
QOpenGLContext...rrentContext()Description
TRUEnever evaluated
FALSEnever evaluated
0
503 return ctx->defaultFramebufferObject();
never executed: return ctx->defaultFramebufferObject();
0
504 else-
505 return 0;
never executed: return 0;
0
506}-
507-
508extern Q_GUI_EXPORT QImage qt_gl_read_framebuffer(const QSize &size, bool alpha_format, bool include_alpha);-
509-
510/*!-
511 Returns a 32-bit RGB image of the framebuffer.-
512-
513 \note This is a potentially expensive operation because it relies on-
514 glReadPixels() to read back the pixels. This may be slow and can stall the-
515 GPU pipeline.-
516-
517 \note When used together with update behavior \c NoPartialUpdate, the returned-
518 image may not contain the desired content when called after the front and back-
519 buffers have been swapped (unless preserved swap is enabled in the underlying-
520 windowing system interface). In this mode the function reads from the back-
521 buffer and the contents of that may not match the content on the screen (the-
522 front buffer). In this case the only place where this function can safely be-
523 used is paintGL() or paintOverGL().-
524 */-
525QImage QOpenGLWindow::grabFramebuffer()-
526{-
527 if (!isValid())
!isValid()Description
TRUEnever evaluated
FALSEnever evaluated
0
528 return QImage();
never executed: return QImage();
0
529-
530 makeCurrent();-
531 return qt_gl_read_framebuffer(size() * devicePixelRatio(), false, false);
never executed: return qt_gl_read_framebuffer(size() * devicePixelRatio(), false, false);
0
532}-
533-
534/*!-
535 This virtual function is called once before the first call to paintGL() or-
536 resizeGL(). Reimplement it in a subclass.-
537-
538 This function should set up any required OpenGL resources and state.-
539-
540 There is no need to call makeCurrent() because this has already been done-
541 when this function is called. Note however that the framebuffer, in case-
542 partial update mode is used, is not yet available at this stage, so avoid-
543 issuing draw calls from here. Defer such calls to paintGL() instead.-
544-
545 \sa paintGL(), resizeGL()-
546 */-
547void QOpenGLWindow::initializeGL()-
548{-
549}-
550-
551/*!-
552 This virtual function is called whenever the widget has been resized.-
553 Reimplement it in a subclass. The new size is passed in \a w and \a h.-
554-
555 \note This is merely a convenience function in order to provide an API that is-
556 compatible with QOpenGLWidget. Unlike with QOpenGLWidget, derived classes are-
557 free to choose to override resizeEvent() instead of this function.-
558-
559 \note Avoid issuing OpenGL commands from this function as there may not be a-
560 context current when it is invoked. If it cannot be avoided, call makeCurrent().-
561-
562 \note Scheduling updates from here is not necessary. The windowing systems-
563 will send expose events that trigger an update automatically.-
564-
565 \sa initializeGL(), paintGL()-
566 */-
567void QOpenGLWindow::resizeGL(int w, int h)-
568{-
569 Q_UNUSED(w);-
570 Q_UNUSED(h);-
571}
never executed: end of block
0
572-
573/*!-
574 This virtual function is called whenever the window contents needs to be-
575 painted. Reimplement it in a subclass.-
576-
577 There is no need to call makeCurrent() because this has already-
578 been done when this function is called.-
579-
580 Before invoking this function, the context and the framebuffer, if there is-
581 one, are bound, and the viewport is set up by a call to glViewport(). No-
582 other state is set and no clearing or drawing is performed by the framework.-
583-
584 \note When using a partial update behavior, like \c PartialUpdateBlend, the-
585 output of the previous paintGL() call is preserved and, after the additional-
586 drawing perfomed in the current invocation of the function, the content is-
587 blitted or blended over the content drawn directly to the window in-
588 paintUnderGL().-
589-
590 \sa initializeGL(), resizeGL(), paintUnderGL(), paintOverGL(), UpdateBehavior-
591 */-
592void QOpenGLWindow::paintGL()-
593{-
594}-
595-
596/*!-
597 The virtual function is called before each invocation of paintGL().-
598-
599 When the update mode is set to \c NoPartialUpdate, there is no difference-
600 between this function and paintGL(), performing rendering in either of them-
601 leads to the same result.-
602-
603 The difference becomes significant when using \c PartialUpdateBlend, where an-
604 extra framebuffer object is used. There, paintGL() targets this additional-
605 framebuffer object, which preserves its contents, while paintUnderGL() and-
606 paintOverGL() target the default framebuffer, i.e. directly the window-
607 surface, the contents of which is lost after each displayed frame.-
608-
609 \note Avoid relying on this function when the update behavior is-
610 \c PartialUpdateBlit. This mode involves blitting the extra framebuffer used by-
611 paintGL() onto the default framebuffer after each invocation of paintGL(),-
612 thus overwriting all drawing generated in this function.-
613-
614 \sa paintGL(), paintOverGL(), UpdateBehavior-
615 */-
616void QOpenGLWindow::paintUnderGL()-
617{-
618}-
619-
620/*!-
621 This virtual function is called after each invocation of paintGL().-
622-
623 When the update mode is set to NoPartialUpdate, there is no difference-
624 between this function and paintGL(), performing rendering in either of them-
625 leads to the same result.-
626-
627 Like paintUnderGL(), rendering in this function targets the default-
628 framebuffer of the window, regardless of the update behavior. It gets called-
629 after paintGL() has returned and the blit (PartialUpdateBlit) or quad drawing-
630 (PartialUpdateBlend) has been done.-
631-
632 \sa paintGL(), paintUnderGL(), UpdateBehavior-
633 */-
634void QOpenGLWindow::paintOverGL()-
635{-
636}-
637-
638/*!-
639 Paint \a event handler. Calls paintGL().-
640-
641 \sa paintGL()-
642 */-
643void QOpenGLWindow::paintEvent(QPaintEvent *event)-
644{-
645 Q_UNUSED(event);-
646 paintGL();-
647}
never executed: end of block
0
648-
649/*!-
650 Resize \a event handler. Calls resizeGL().-
651-
652 \sa resizeGL()-
653 */-
654void QOpenGLWindow::resizeEvent(QResizeEvent *event)-
655{-
656 Q_UNUSED(event);-
657 Q_D(QOpenGLWindow);-
658 d->initialize();-
659 resizeGL(width(), height());-
660}
never executed: end of block
0
661-
662/*!-
663 \internal-
664 */-
665int QOpenGLWindow::metric(PaintDeviceMetric metric) const-
666{-
667 Q_D(const QOpenGLWindow);-
668-
669 switch (metric) {-
670 case PdmDepth:
never executed: case PdmDepth:
0
671 if (d->paintDevice)
d->paintDeviceDescription
TRUEnever evaluated
FALSEnever evaluated
0
672 return d->paintDevice->depth();
never executed: return d->paintDevice->depth();
0
673 break;
never executed: break;
0
674 default:
never executed: default:
0
675 break;
never executed: break;
0
676 }-
677 return QPaintDeviceWindow::metric(metric);
never executed: return QPaintDeviceWindow::metric(metric);
0
678}-
679-
680/*!-
681 \internal-
682 */-
683QPaintDevice *QOpenGLWindow::redirected(QPoint *) const-
684{-
685 Q_D(const QOpenGLWindow);-
686 if (QOpenGLContext::currentContext() == d->context.data())
QOpenGLContext...context.data()Description
TRUEnever evaluated
FALSEnever evaluated
0
687 return d->paintDevice.data();
never executed: return d->paintDevice.data();
0
688 return 0;
never executed: return 0;
0
689}-
690-
691QT_END_NAMESPACE-
Source codeSwitch to Preprocessed file

Generated by Squish Coco Non-Commercial 4.3.0-BETA-master-30-08-2018-4cb69e9