#include "qquickshadereffectsource_p.h"
#include "qquickitem_p.h"
-#include "qquickcanvas_p.h"
+#include "qquickwindow_p.h"
#include <private/qsgadaptationlayer_p.h>
#include <QtQuick/private/qsgrenderer_p.h>
: QSGDynamicTexture()
, m_item(0)
, m_format(GL_RGBA)
- , m_shaderSource(shaderSource)
, m_renderer(0)
, m_fbo(0)
, m_secondaryFbo(0)
, m_live(true)
, m_recursive(false)
, m_dirtyTexture(true)
- , m_multisamplingSupportChecked(false)
+ , m_multisamplingChecked(false)
, m_multisampling(false)
, m_grab(false)
{
bool QQuickShaderEffectTexture::updateTexture()
{
- if ((m_live || m_grab) && m_dirtyTexture) {
+ bool doGrab = (m_live || m_grab) && m_dirtyTexture;
+ if (doGrab)
grab();
- m_grab = false;
- return true;
- }
- return false;
+ if (m_grab)
+ emit scheduledUpdateCompleted();
+ m_grab = false;
+ return doGrab;
}
void QQuickShaderEffectTexture::setHasMipmaps(bool mipmap)
m_fbo = m_secondaryFbo = 0;
m_depthStencilBuffer.clear();
m_dirtyTexture = false;
- if (m_grab)
- emit scheduledUpdateCompleted();
return;
}
QSGNode *root = m_item;
if (!m_fbo || m_fbo->size() != m_size || m_fbo->format().internalTextureFormat() != m_format
|| (!m_fbo->format().mipmap() && m_mipmap))
{
- if (!m_multisamplingSupportChecked) {
- QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
- m_multisampling = extensions.contains("GL_EXT_framebuffer_multisample")
- && extensions.contains("GL_EXT_framebuffer_blit");
- m_multisamplingSupportChecked = true;
+ if (!m_multisamplingChecked) {
+ if (m_context->glContext()->format().samples() <= 1) {
+ m_multisampling = false;
+ } else {
+ QList<QByteArray> extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' ');
+ m_multisampling = extensions.contains("GL_EXT_framebuffer_multisample")
+ && extensions.contains("GL_EXT_framebuffer_blit");
+ }
+ m_multisamplingChecked = true;
}
if (m_multisampling) {
// Don't delete the FBO right away in case it is used recursively.
QOpenGLFramebufferObjectFormat format;
format.setInternalTextureFormat(m_format);
- format.setSamples(8);
+ format.setSamples(m_context->glContext()->format().samples());
m_secondaryFbo = new QOpenGLFramebufferObject(m_size, format);
m_depthStencilBuffer = m_context->depthStencilBufferForFbo(m_secondaryFbo);
} else {
#endif
if (m_recursive)
markDirtyTexture(); // Continuously update if 'live' and 'recursive'.
-
- if (m_grab)
- emit scheduledUpdateCompleted();
}
QImage QQuickShaderEffectTexture::toImage() const
/*!
\qmlclass ShaderEffectSource QQuickShaderEffectSource
\since 5.0
- \ingroup qml-basic-visual-elements
- \brief The ShaderEffectSource element renders a QML element into a texture
- and displays it.
\inherits Item
+ \ingroup qtquick-effects
+ \brief Renders a QtQuick item into a texture and displays it
- The ShaderEffectSource element renders \l sourceItem into a texture and
+ The ShaderEffectSource type renders \l sourceItem into a texture and
displays it in the scene. \l sourceItem is drawn into the texture as though
- it was a fully opaque root element. Thus \l sourceItem itself can be
+ it was a fully opaque root item. Thus \l sourceItem itself can be
invisible, but still appear in the texture.
ShaderEffectSource can be used as:
\list
\li a texture source in a \l ShaderEffect.
- This allows you to apply custom shader effects to any QML element.
- \li a cache for a complex element.
- The complex element can be rendered once into the texture, which can
- then be animated freely without the need to render the complex element
+ This allows you to apply custom shader effects to any QtQuick item.
+ \li a cache for a complex item.
+ The complex item can be rendered once into the texture, which can
+ then be animated freely without the need to render the complex item
again every frame.
\li an opacity layer.
- ShaderEffectSource allows you to apply an opacity to elements as a group
- rather than each element individually.
+ ShaderEffectSource allows you to apply an opacity to items as a group
+ rather than each item individually.
\endlist
\table
}
}
\endqml
- \endrow
\endtable
- The ShaderEffectSource element does not redirect any mouse or keyboard
+ The ShaderEffectSource type does not redirect any mouse or keyboard
input to \l sourceItem. If you hide the \l sourceItem by setting
\l{Item::visible}{visible} to false or \l{Item::opacity}{opacity} to zero,
it will no longer react to input. In cases where the ShaderEffectSource is
border width falls outside the texture. To get the whole border, you can
extend the \l sourceRect.
+ \note The ShaderEffectSource relies on FBO multisampling support
+ to antialias edges. If the underlying hardware does not support this,
+ which is the case for most embedded graphics chips, edges rendered
+ inside a ShaderEffectSource will not be antialiased. One way to remedy
+ this is to double the size of the effect source and render it with
+ \c {smooth: true}. This will be equivalent to 4x multisampling, at
+ the cost of lower performance and higher memory use.
+
\warning In most cases, using a ShaderEffectSource will decrease
performance, and in all cases, it will increase video memory usage.
Rendering through a ShaderEffectSource might also lead to lower quality
QQuickItemPrivate *sd = QQuickItemPrivate::get(m_sourceItem);
sd->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
sd->derefFromEffectItem(m_hideSource);
- if (canvas())
- sd->derefCanvas();
+ if (window())
+ sd->derefWindow();
}
}
if (m_texture)
return;
- Q_ASSERT_X(QQuickItemPrivate::get(this)->canvas
+ Q_ASSERT_X(QQuickItemPrivate::get(this)->window
&& QQuickItemPrivate::get(this)->sceneGraphContext()
&& QThread::currentThread() == QQuickItemPrivate::get(this)->sceneGraphContext()->thread(),
"QQuickShaderEffectSource::ensureTexture",
{
if (!m_provider) {
// Make sure it gets thread affinity on the rendering thread so deletion works properly..
- Q_ASSERT_X(QQuickItemPrivate::get(this)->canvas
+ Q_ASSERT_X(QQuickItemPrivate::get(this)->window
&& QQuickItemPrivate::get(this)->sceneGraphContext()
&& QThread::currentThread() == QQuickItemPrivate::get(this)->sceneGraphContext()->thread(),
"QQuickShaderEffectSource::textureProvider",
\qmlproperty enumeration ShaderEffectSource::wrapMode
This property defines the OpenGL wrap modes associated with the texture.
- Modifying this property makes most sense when the element is used as a
+ Modifying this property makes most sense when the item is used as a
source texture of a \l ShaderEffect.
\list
/*!
\qmlproperty Item ShaderEffectSource::sourceItem
- This property holds the element to be rendered into the texture.
+ This property holds the item to be rendered into the texture.
Setting this to null while \l live is true, will release the texture
resources.
*/
d->derefFromEffectItem(m_hideSource);
d->removeItemChangeListener(this, QQuickItemPrivate::Geometry);
disconnect(m_sourceItem, SIGNAL(destroyed(QObject*)), this, SLOT(sourceItemDestroyed(QObject*)));
- if (canvas())
- d->derefCanvas();
+ if (window())
+ d->derefWindow();
}
m_sourceItem = item;
if (item) {
QQuickItemPrivate *d = QQuickItemPrivate::get(item);
- // 'item' needs a canvas to get a scene graph node. It usually gets one through its
+ // 'item' needs a window to get a scene graph node. It usually gets one through its
// parent, but if the source item is "inline" rather than a reference -- i.e.
// "sourceItem: Item { }" instead of "sourceItem: foo" -- it will not get a parent.
- // In those cases, 'item' should get the canvas from 'this'.
- if (canvas())
- d->refCanvas(canvas());
+ // In those cases, 'item' should get the window from 'this'.
+ if (window())
+ d->refWindow(window());
d->refFromEffectItem(m_hideSource);
d->addItemChangeListener(this, QQuickItemPrivate::Geometry);
connect(m_sourceItem, SIGNAL(destroyed(QObject*)), this, SLOT(sourceItemDestroyed(QObject*)));
\qmlproperty enumeration ShaderEffectSource::format
This property defines the internal OpenGL format of the texture.
- Modifying this property makes most sense when the element is used as a
+ Modifying this property makes most sense when the item is used as a
source texture of a \l ShaderEffect. Depending on the OpenGL
implementation, this property might allow you to save some texture memory.
If this property is true, the texture is updated whenever the
\l sourceItem updates. Otherwise, it will be a frozen image, even if
- \l sourceItem is assigned a new element. The property is true by default.
+ \l sourceItem is assigned a new item. The property is true by default.
*/
bool QQuickShaderEffectSource::live() const
node->setHorizontalWrapMode(hWrap);
node->setVerticalWrapMode(vWrap);
node->setTargetRect(QRectF(0, 0, width(), height()));
- node->setSourceRect(QRectF(0, 0, 1, 1));
+ node->setInnerTargetRect(QRectF(0, 0, width(), height()));
node->update();
return node;
{
if (change == QQuickItem::ItemSceneChange && m_sourceItem) {
// See comment in QQuickShaderEffectSource::setSourceItem().
- if (value.canvas)
- QQuickItemPrivate::get(m_sourceItem)->refCanvas(value.canvas);
+ if (value.window)
+ QQuickItemPrivate::get(m_sourceItem)->refWindow(value.window);
else
- QQuickItemPrivate::get(m_sourceItem)->derefCanvas();
+ QQuickItemPrivate::get(m_sourceItem)->derefWindow();
}
QQuickItem::itemChange(change, value);
}