Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qquickframebufferobject.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
5
6#include <QOpenGLFramebufferObject>
7#include <QOpenGLFunctions>
8#include <private/qquickitem_p.h>
9#include <private/qsgadaptationlayer_p.h>
10#include <qsgtextureprovider.h>
11#include <rhi/qrhi.h>
12
13#include <QSGSimpleTextureNode>
14#include <QSGRendererInterface>
15#include <QQuickOpenGLUtils>
16
18
34
95
109{
111 if (d->followsItemSize == follows)
112 return;
113 d->followsItemSize = follows;
114 emit textureFollowsItemSizeChanged(d->followsItemSize);
115}
116
118{
119 Q_D(const QQuickFramebufferObject);
120 return d->followsItemSize;
121}
122
136{
138 if (d->mirrorVertically == enable)
139 return;
140 d->mirrorVertically = enable;
141 emit mirrorVerticallyChanged(d->mirrorVertically);
142 update();
143}
144
146{
147 Q_D(const QQuickFramebufferObject);
148 return d->mirrorVertically;
149}
150
154void QQuickFramebufferObject::geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
155{
156 QQuickItem::geometryChange(newGeometry, oldGeometry);
157
159 if (newGeometry.size() != oldGeometry.size() && d->followsItemSize)
160 update();
161}
162
164{
166
167public:
179
181 {
182 delete renderer;
183 delete texture();
184 delete fbo;
185 delete msDisplayFbo;
186 }
187
189 {
190 renderPending = true;
191 window->update();
192 }
193
194 QSGTexture *texture() const override
195 {
197 }
198
199public Q_SLOTS:
200 void render()
201 {
202 if (renderPending) {
203 renderPending = false;
204
205 window->beginExternalCommands();
207
208 fbo->bind();
209 QOpenGLContext::currentContext()->functions()->glViewport(0, 0, fbo->width(), fbo->height());
210 renderer->render();
211 fbo->bindDefault();
212
213 if (msDisplayFbo)
215
216 window->endExternalCommands();
217
220 }
221 }
222
224 {
225 if (window->effectiveDevicePixelRatio() != devicePixelRatio) {
227 quickFbo->update();
228 }
229 }
230
231public:
237
240
242};
243
244static inline bool isOpenGL(QSGRenderContext *rc)
245{
247 return rif && rif->graphicsApi() == QSGRendererInterface::OpenGL;
248}
249
254{
256
257 // We only abort if we never had a node before. This is so that we
258 // don't recreate the renderer object if the thing becomes tiny. In
259 // terms of API it would be horrible if the renderer would go away
260 // that easily so with this logic, the renderer only goes away when
261 // the scenegraph is invalidated or it is removed from the scene.
262 if (!n && (width() <= 0 || height() <= 0))
263 return nullptr;
264
266
267 if (!n) {
268 if (!isOpenGL(d->sceneGraphRenderContext()))
269 return nullptr;
270 if (!d->node)
271 d->node = new QSGFramebufferObjectNode;
272 n = d->node;
273 }
274
275 if (!n->renderer) {
276 n->window = window();
277 n->renderer = createRenderer();
278 n->renderer->data = n;
279 n->quickFbo = this;
280 connect(window(), SIGNAL(beforeRendering()), n, SLOT(render()));
281 connect(window(), SIGNAL(screenChanged(QScreen*)), n, SLOT(handleScreenChange()));
282 }
283
284 n->renderer->synchronize(this);
285
286 QSize minFboSize = d->sceneGraphContext()->minimumFBOSize();
287 QSize desiredFboSize(qMax<int>(minFboSize.width(), width()),
288 qMax<int>(minFboSize.height(), height()));
289
290 n->devicePixelRatio = window()->effectiveDevicePixelRatio();
291 desiredFboSize *= n->devicePixelRatio;
292
293 if (n->fbo && ((d->followsItemSize && n->fbo->size() != desiredFboSize) || n->invalidatePending)) {
294 delete n->texture();
295 delete n->fbo;
296 n->fbo = nullptr;
297 delete n->msDisplayFbo;
298 n->msDisplayFbo = nullptr;
299 n->invalidatePending = false;
300 }
301
302 if (!n->fbo) {
303 n->fbo = n->renderer->createFramebufferObject(desiredFboSize);
304
305 GLuint displayTexture = n->fbo->texture();
306
307 if (n->fbo->format().samples() > 0) {
308 n->msDisplayFbo = new QOpenGLFramebufferObject(n->fbo->size());
309 displayTexture = n->msDisplayFbo->texture();
310 }
311
312 QSGTexture *wrapper = QNativeInterface::QSGOpenGLTexture::fromNative(displayTexture,
313 window(),
314 n->fbo->size(),
315 QQuickWindow::TextureHasAlphaChannel);
316 n->setTexture(wrapper);
317 }
318
319 n->setTextureCoordinatesTransform(d->mirrorVertically ? QSGSimpleTextureNode::MirrorVertically : QSGSimpleTextureNode::NoTransform);
320 n->setFiltering(d->smooth ? QSGTexture::Linear : QSGTexture::Nearest);
321 n->setRect(0, 0, width(), height());
322
323 n->scheduleRender();
324
325 return n;
326}
327
332{
333 return true;
334}
335
340{
341 // When Item::layer::enabled == true, QQuickItem will be a texture
342 // provider. In this case we should prefer to return the layer rather
343 // than the fbo texture.
346
347 Q_D(const QQuickFramebufferObject);
348 QQuickWindow *w = window();
349 if (!w || !w->isSceneGraphInitialized() || QThread::currentThread() != QQuickWindowPrivate::get(w)->context->thread()) {
350 qWarning("QQuickFramebufferObject::textureProvider: can only be queried on the rendering thread of an exposed window");
351 return nullptr;
352 }
353 if (!isOpenGL(d->sceneGraphRenderContext()))
354 return nullptr;
355 if (!d->node)
356 d->node = new QSGFramebufferObjectNode;
357 return d->node;
358}
359
364{
365 // When release resources is called on the GUI thread, we only need to
366 // forget about the node. Since it is the node we returned from updatePaintNode
367 // it will be managed by the scene graph.
369 d->node = nullptr;
370}
371
372void QQuickFramebufferObject::invalidateSceneGraph()
373{
375 d->node = nullptr;
376}
377
397
416
424
465
471{
472 if (data)
473 ((QSGFramebufferObjectNode *) data)->invalidatePending = true;
474}
475
500
511{
512 if (data)
513 ((QSGFramebufferObjectNode *) data)->scheduleRender();
514}
515
517
518#include "qquickframebufferobject.moc"
519#include "moc_qquickframebufferobject.cpp"
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
Definition qobject.cpp:2960
static QOpenGLContext * currentContext()
Returns the last context which called makeCurrent in the current thread, or \nullptr,...
The QOpenGLFramebufferObject class encapsulates an OpenGL framebuffer object.
int height() const
Returns the height of the framebuffer object attachments.
static void blitFramebuffer(QOpenGLFramebufferObject *target, const QRect &targetRect, QOpenGLFramebufferObject *source, const QRect &sourceRect, GLbitfield buffers, GLenum filter, int readColorAttachmentIndex, int drawColorAttachmentIndex, FramebufferRestorePolicy restorePolicy)
int width() const
Returns the width of the framebuffer object attachments.
static bool bindDefault()
Switches rendering back to the default, windowing system provided framebuffer.
bool bind()
Switches rendering from the default, windowing system provided framebuffer to this framebuffer object...
virtual ~Renderer()
The Renderer is automatically deleted when the scene graph resources for the QQuickFramebufferObject ...
void update()
Call this function when the FBO should be rendered again.
virtual void render()=0
This function is called when the FBO should be rendered into.
virtual QOpenGLFramebufferObject * createFramebufferObject(const QSize &size)
This function is called when a new FBO is needed.
void invalidateFramebufferObject()
Call this function during synchronize() to invalidate the current FBO.
QOpenGLFramebufferObject * framebufferObject() const
Returns the framebuffer object currently being rendered to.
virtual void synchronize(QQuickFramebufferObject *)
This function is called as a result of QQuickFramebufferObject::update().
QSGNode * updatePaintNode(QSGNode *, UpdatePaintNodeData *) override
bool textureFollowsItemSize
This property controls if the size of the FBO's texture should follow the dimensions of the QQuickFra...
void releaseResources() override
\reimp
bool mirrorVertically
This property controls if the size of the FBO's contents should be mirrored vertically when drawing.
void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry) override
void setTextureFollowsItemSize(bool follows)
QQuickFramebufferObject(QQuickItem *parent=nullptr)
Constructs a new QQuickFramebufferObject with parent parent.
bool isTextureProvider() const override
\reimp
QSGTextureProvider * textureProvider() const override
\reimp
virtual Renderer * createRenderer() const =0
Reimplement this function to create a renderer used to render into the FBO.
void mirrorVerticallyChanged(bool)
void textureFollowsItemSizeChanged(bool)
The QQuickItem class provides the most basic of all visual items in \l {Qt Quick}.
Definition qquickitem.h:63
void setFlag(Flag flag, bool enabled=true)
Enables the specified flag for this item if enabled is true; if enabled is false, the flag is disable...
virtual void geometryChange(const QRectF &newGeometry, const QRectF &oldGeometry)
virtual QSGTextureProvider * textureProvider() const
Returns the texture provider for an item.
QQuickWindow * window() const
Returns the window in which this item is rendered.
qreal width
This property holds the width of this item.
Definition qquickitem.h:75
qreal height
This property holds the height of this item.
Definition qquickitem.h:76
void update()
Schedules a call to updatePaintNode() for this item.
virtual bool isTextureProvider() const
Returns true if this item is a texture provider.
static QQuickWindowPrivate * get(QQuickWindow *c)
\qmltype Window \instantiates QQuickWindow \inqmlmodule QtQuick
void update()
Schedules the window to render another frame.
\inmodule QtCore\reentrant
Definition qrect.h:484
constexpr QSizeF size() const noexcept
Returns the size of the rectangle.
Definition qrect.h:735
virtual QSGRendererInterface * rendererInterface(QSGRenderContext *renderContext)
Returns a pointer to the (presumably) global renderer interface.
QQuickFramebufferObject * quickFbo
QSGTexture * texture() const override
Returns a pointer to the texture object.
QOpenGLFramebufferObject * msDisplayFbo
QOpenGLFramebufferObject * fbo
QQuickFramebufferObject::Renderer * renderer
\group qtquick-scenegraph-nodes \title Qt Quick Scene Graph Node classes
Definition qsgnode.h:37
@ DirtyMaterial
Definition qsgnode.h:75
void markDirty(DirtyState bits)
Notifies all connected renderers that the node has dirty bits.
Definition qsgnode.cpp:624
QSGContext * sceneGraphContext() const
An interface providing access to some of the graphics API specific internals of the scenegraph.
The QSGSimpleTextureNode class is provided for convenience to easily draw textured content using the ...
QSGTexture * texture() const
Returns the texture for this texture node.
The QSGTextureProvider class encapsulates texture based entities in QML.
void textureChanged()
This signal is emitted when the texture changes.
\inmodule QtQuick
Definition qsgtexture.h:20
The QScreen class is used to query screen properties. \inmodule QtGui.
Definition qscreen.h:32
\inmodule QtCore
Definition qsize.h:25
static QThread * currentThread()
Definition qthread.cpp:1039
Q_QUICK_EXPORT void resetOpenGLState()
Call this function to reset the current OpenGL context its default state.
Combined button and popup list for selecting options.
#define qWarning
Definition qlogging.h:166
#define SLOT(a)
Definition qobjectdefs.h:52
#define SIGNAL(a)
Definition qobjectdefs.h:53
GLfloat GLfloat GLfloat w
[0]
GLint GLsizei GLsizei height
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLint GLsizei width
GLboolean enable
GLfloat n
static bool isOpenGL(QSGRenderContext *rc)
#define GLuint
void qsgnode_set_description(QSGNode *node, const QString &description)
Definition qsgnode.cpp:641
#define QStringLiteral(str)
#define Q_OBJECT
#define Q_SLOTS
#define emit
#define Q_UNUSED(x)
double qreal
Definition qtypes.h:187
QObject::connect nullptr
QGraphicsItem * item
myWidget render(this)
void wrapper()