summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJüri Valdmann <juri.valdmann@qt.io>2017-09-22 11:12:57 +0200
committerJüri Valdmann <juri.valdmann@qt.io>2017-09-22 12:15:00 +0000
commitabb6af14fb632d32d8cce83b4042acd6f9a4767e (patch)
tree5f0aa9076df8f6c27663c80bf80805d06baa31f2
parent8041548b7c7fc6f28c23d6c5699bc43ffef2428a (diff)
Fix viewport resizing bug in renderer
After the recent fix for rendering intersecting quads, DelegatedFrameNode no longer builds scene graph nodes for DrawQuads that are outside the visible area. This means that the structure of the scene graph now depends on the size of the visible area, however the logic for deciding whether to update or rebuild the scene graph was not updated to reflect this fact. As a result we may try to update e.g. a QSGImageNode as if it were a QSGRectangleNode leading to a crash. Task-number: QTBUG-62112 Change-Id: I6e2e9dee4238d208fc2be98669281c2d4d4962d7 Reviewed-by: Peter Varga <pvarga@inf.u-szeged.hu> Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--src/core/delegated_frame_node.cpp24
-rw-r--r--src/core/delegated_frame_node.h1
-rw-r--r--src/core/type_conversion.h5
3 files changed, 22 insertions, 8 deletions
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp
index be085831..73e0420a 100644
--- a/src/core/delegated_frame_node.cpp
+++ b/src/core/delegated_frame_node.cpp
@@ -850,8 +850,8 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
// countering the scale of devicePixel-scaled tiles when rendering them
// to the final surface.
QMatrix4x4 matrix;
- matrix.scale(1 / m_chromiumCompositorData->frameDevicePixelRatio,
- 1 / m_chromiumCompositorData->frameDevicePixelRatio);
+ const float devicePixelRatio = m_chromiumCompositorData->frameDevicePixelRatio;
+ matrix.scale(1 / devicePixelRatio, 1 / devicePixelRatio);
if (QSGTransformNode::matrix() != matrix)
setMatrix(matrix);
@@ -873,12 +873,21 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
frameData->resource_list.clear();
QScopedPointer<DelegatedNodeTreeHandler> nodeHandler;
+ const QSizeF viewportSizeInPt = apiDelegate->screenRect().size();
+ const QSize viewportSize = (viewportSizeInPt * devicePixelRatio).toSize();
+
// We first compare if the render passes from the previous frame data are structurally
// equivalent to the render passes in the current frame data. If they are, we are going
// to reuse the old nodes. Otherwise, we will delete the old nodes and build a new tree.
+ //
+ // Additionally, because we clip (i.e. don't build scene graph nodes for) quads outside
+ // of the visible area, we also have to rebuild the tree whenever the window is resized.
#if (QT_VERSION >= QT_VERSION_CHECK(5, 8, 0))
cc::DelegatedFrameData *previousFrameData = m_chromiumCompositorData->previousFrameData.get();
- const bool buildNewTree = !areRenderPassStructuresEqual(frameData, previousFrameData) || m_sceneGraphNodes.empty();
+ const bool buildNewTree =
+ !areRenderPassStructuresEqual(frameData, previousFrameData) ||
+ m_sceneGraphNodes.empty() ||
+ viewportSize != m_previousViewportSize;
#else
// No updates possible with old scenegraph nodes
const bool buildNewTree = true;
@@ -912,10 +921,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
// All RenderPasses except the last one are rendered to an FBO.
cc::RenderPass *rootRenderPass = frameData->render_pass_list.back().get();
- QRectF screenRectQt = apiDelegate->screenRect();
- gfx::Size thisSize(int(screenRectQt.width() * m_chromiumCompositorData->frameDevicePixelRatio),
- int(screenRectQt.height() * m_chromiumCompositorData->frameDevicePixelRatio));
-
+ gfx::Rect viewportRect(toGfx(viewportSize));
for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) {
cc::RenderPass *pass = frameData->render_pass_list.at(i).get();
@@ -947,7 +953,7 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
scissorRect = pass->output_rect;
} else {
renderPassParent = this;
- scissorRect = gfx::Rect(thisSize);
+ scissorRect = viewportRect;
scissorRect += rootRenderPass->output_rect.OffsetFromOrigin();
}
@@ -1015,6 +1021,8 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
ResourceHolderIterator end = resourceCandidates.constEnd();
for (ResourceHolderIterator it = resourceCandidates.constBegin(); it != end ; ++it)
resourcesToRelease->push_back((*it)->returnResource());
+
+ m_previousViewportSize = viewportSize;
}
void DelegatedFrameNode::flushPolygons(
diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h
index cc682988..3b6453a4 100644
--- a/src/core/delegated_frame_node.h
+++ b/src/core/delegated_frame_node.h
@@ -143,6 +143,7 @@ private:
bool m_contextShared;
QScopedPointer<QOffscreenSurface> m_offsurface;
#endif
+ QSize m_previousViewportSize;
};
} // namespace QtWebEngineCore
diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h
index ed02a9db..39c4f610 100644
--- a/src/core/type_conversion.h
+++ b/src/core/type_conversion.h
@@ -139,6 +139,11 @@ inline QRectF toQt(const gfx::RectF &rect)
return QRectF(rect.x(), rect.y(), rect.width(), rect.height());
}
+inline gfx::Size toGfx(const QSize &size)
+{
+ return gfx::Size(size.width(), size.height());
+}
+
inline QSize toQt(const gfx::Size &size)
{
return QSize(size.width(), size.height());