aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJan Marker <jan.marker@kdab.com>2018-04-08 17:40:36 +0200
committerJan Marker <jan.marker@kdab.com>2018-04-11 14:22:00 +0000
commit10c56615d1418c155648e2a150b45b6cb768b33e (patch)
tree45e177afdd475da8fa1a83462abfed9746f3e752
parent996c6d452702162e909285b5be9a831290cff1c9 (diff)
Make QSGLayer::grab work correctly in software renderer
Fix three separate issues: 1. It was possible that the QSGSoftwarePixmapRenderer's background image's rectangle was set to a non-normalized rectangle. That would have led to the damage area detection creating an empty QRegion for the damage area and QQuickItem::grabToImage would grab an empty image. 2. The QSGSoftwarePixmapRenderer was rendering the image vertically mirrored compared to what its equivalent in the OpenGL backend was doing. Therefore QSGLayer::grab was vertically mirrored, too, so QQuickItem::grabToImage would grab a mirrored image, too. Additionally QSGSoftwareInternalImageNode (used by QQuickShaderEffectSource) now has to mirror its internal texture if that one is a QSGSoftwareLayer. 3. QSGSoftwareInternalImageNode (used by QQuickShaderEffectSource) was not updating correctly when mirroring (with the fix for 2 also in case of a QSGSoftwareLayer as texture). Related to QTBUG-63185 and QTBUG-65975. Change-Id: I0d0ead7fb1c839a8ff427ff7881d8a881e538409 Reviewed-by: Eirik Aavitsland <eirik.aavitsland@qt.io> Reviewed-by: Andy Nichols <andy.nichols@qt.io>
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp14
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h1
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp4
-rw-r--r--src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp2
4 files changed, 15 insertions, 6 deletions
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp
index 3b0f3c48ff..aa83709b72 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode.cpp
@@ -320,6 +320,7 @@ QSGSoftwareInternalImageNode::QSGSoftwareInternalImageNode()
, m_subSourceRect(0, 0, 1, 1)
, m_texture(nullptr)
, m_mirror(false)
+ , m_textureIsLayer(false)
, m_smooth(true)
, m_tileHorizontal(false)
, m_tileVertical(false)
@@ -366,6 +367,7 @@ void QSGSoftwareInternalImageNode::setTexture(QSGTexture *texture)
{
m_texture = texture;
m_cachedMirroredPixmapIsDirty = true;
+ m_textureIsLayer = static_cast<bool>(qobject_cast<QSGSoftwareLayer*>(texture));
markDirty(DirtyMaterial);
}
@@ -415,8 +417,13 @@ void QSGSoftwareInternalImageNode::setVerticalWrapMode(QSGTexture::WrapMode wrap
void QSGSoftwareInternalImageNode::update()
{
if (m_cachedMirroredPixmapIsDirty) {
- if (m_mirror) {
- m_cachedMirroredPixmap = pixmap().transformed(QTransform(-1, 0, 0, 1, 0, 0));
+ if (m_mirror || m_textureIsLayer) {
+ QTransform transform(
+ (m_mirror ? -1 : 1), 0,
+ 0 , (m_textureIsLayer ? -1 :1),
+ 0 , 0
+ );
+ m_cachedMirroredPixmap = pixmap().transformed(transform);
} else {
//Cleanup cached pixmap if necessary
if (!m_cachedMirroredPixmap.isNull())
@@ -436,6 +443,7 @@ void QSGSoftwareInternalImageNode::preprocess()
}
if (doDirty)
markDirty(DirtyMaterial);
+ m_cachedMirroredPixmapIsDirty = doDirty;
}
static Qt::TileRule getTileRule(qreal factor)
@@ -454,7 +462,7 @@ void QSGSoftwareInternalImageNode::paint(QPainter *painter)
{
painter->setRenderHint(QPainter::SmoothPixmapTransform, m_smooth);
- const QPixmap &pm = m_mirror ? m_cachedMirroredPixmap : pixmap();
+ const QPixmap &pm = m_mirror || m_textureIsLayer ? m_cachedMirroredPixmap : pixmap();
if (m_innerTargetRect != m_targetRect) {
// border image
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h
index 5c95eb064a..b80bacbaa0 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwareinternalimagenode_p.h
@@ -136,6 +136,7 @@ private:
QPixmap m_cachedMirroredPixmap;
bool m_mirror;
+ bool m_textureIsLayer;
bool m_smooth;
bool m_tileHorizontal;
bool m_tileVertical;
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp
index b4301451d8..70378d2950 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarelayer.cpp
@@ -240,9 +240,9 @@ void QSGSoftwareLayer::grab()
m_renderer->setDeviceRect(m_size);
m_renderer->setViewportRect(m_size);
QRect mirrored(m_mirrorHorizontal ? m_rect.right() * m_device_pixel_ratio : m_rect.left() * m_device_pixel_ratio,
- m_mirrorVertical ? m_rect.top() * m_device_pixel_ratio : m_rect.bottom() * m_device_pixel_ratio,
+ m_mirrorVertical ? m_rect.bottom() * m_device_pixel_ratio : m_rect.top() * m_device_pixel_ratio,
m_mirrorHorizontal ? -m_rect.width() * m_device_pixel_ratio : m_rect.width() * m_device_pixel_ratio,
- m_mirrorVertical ? m_rect.height() * m_device_pixel_ratio : -m_rect.height() * m_device_pixel_ratio);
+ m_mirrorVertical ? -m_rect.height() * m_device_pixel_ratio : m_rect.height() * m_device_pixel_ratio);
m_renderer->setProjectionRect(mirrored);
m_renderer->setClearColor(Qt::transparent);
diff --git a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp
index 303f98c801..bb4afc8301 100644
--- a/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp
+++ b/src/quick/scenegraph/adaptations/software/qsgsoftwarepixmaprenderer.cpp
@@ -79,7 +79,7 @@ void QSGSoftwarePixmapRenderer::render(QPaintDevice *target)
QElapsedTimer renderTimer;
// Setup background item
- setBackgroundRect(m_projectionRect);
+ setBackgroundRect(m_projectionRect.normalized());
setBackgroundColor(clearColor());
renderTimer.start();