summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJüri Valdmann <juri.valdmann@qt.io>2017-09-18 17:39:47 +0200
committerJüri Valdmann <juri.valdmann@qt.io>2017-09-19 12:54:27 +0000
commit686e0c37d13a39935c5296b5c36151926fec072f (patch)
tree51c48350e218fd3185f577303bc3fe2c49d3cbec
parent8c7ef46d84179024b499bb9654932f2432966279 (diff)
Fix rendering of intersecting quads
Split intersecting quads using a BSP tree in the same manner as Chromium's rendering algorithm. Note that these split quads still will not be correctly rendered in software mode as Qt Quick's software renderer is not at all aware of non-rectangular QSGClipNodes. Task-number: QTBUG-62112 Change-Id: Ibfb72b9220817baebf828bc6183af7bd9c25d050 Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
-rw-r--r--src/core/delegated_frame_node.cpp136
-rw-r--r--src/core/delegated_frame_node.h24
2 files changed, 153 insertions, 7 deletions
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp
index 1ba8992ce..be0858310 100644
--- a/src/core/delegated_frame_node.cpp
+++ b/src/core/delegated_frame_node.cpp
@@ -57,6 +57,8 @@
#include "base/bind.h"
#include "base/message_loop/message_loop.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "cc/base/math_util.h"
+#include "cc/output/bsp_tree.h"
#include "cc/output/delegated_frame_data.h"
#include "cc/quads/debug_border_draw_quad.h"
#include "cc/quads/draw_quad.h"
@@ -910,10 +912,15 @@ 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));
+
for (unsigned i = 0; i < frameData->render_pass_list.size(); ++i) {
cc::RenderPass *pass = frameData->render_pass_list.at(i).get();
QSGNode *renderPassParent = 0;
+ gfx::Rect scissorRect;
if (pass != rootRenderPass) {
QSharedPointer<QSGLayer> rpLayer;
if (buildNewTree) {
@@ -937,30 +944,68 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
rpLayer->setSize(toQt(pass->output_rect.size()));
rpLayer->setFormat(pass->has_transparent_background ? GL_RGBA : GL_RGB);
rpLayer->setMirrorVertical(true);
- } else
+ scissorRect = pass->output_rect;
+ } else {
renderPassParent = this;
+ scissorRect = gfx::Rect(thisSize);
+ scissorRect += rootRenderPass->output_rect.OffsetFromOrigin();
+ }
- const cc::SharedQuadState *currentLayerState = nullptr;
- QSGNode *currentLayerChain = nullptr;
+ if (scissorRect.IsEmpty())
+ continue;
QSGNode *renderPassChain = nullptr;
if (buildNewTree)
renderPassChain = buildRenderPassChain(renderPassParent);
- cc::QuadList::ConstBackToFrontIterator it = pass->quad_list.BackToFrontBegin();
- cc::QuadList::ConstBackToFrontIterator end = pass->quad_list.BackToFrontEnd();
- for (; it != end; ++it) {
+ std::deque<std::unique_ptr<cc::DrawPolygon>> polygonQueue;
+ int nextPolygonId = 0;
+ int currentSortingContextId = 0;
+ const cc::SharedQuadState *currentLayerState = nullptr;
+ QSGNode *currentLayerChain = nullptr;
+ const auto quadListBegin = pass->quad_list.BackToFrontBegin();
+ const auto quadListEnd = pass->quad_list.BackToFrontEnd();
+ for (auto it = quadListBegin; it != quadListEnd; ++it) {
const cc::DrawQuad *quad = *it;
const cc::SharedQuadState *quadState = quad->shared_quad_state;
+ gfx::Rect targetRect =
+ cc::MathUtil::MapEnclosingClippedRect(quadState->quad_to_target_transform,
+ quad->visible_rect);
+ if (quadState->is_clipped)
+ targetRect.Intersect(quadState->clip_rect);
+ targetRect.Intersect(scissorRect);
+ if (targetRect.IsEmpty())
+ continue;
+
+ if (quadState->sorting_context_id != currentSortingContextId) {
+ flushPolygons(&polygonQueue, renderPassChain,
+ nodeHandler.data(), resourceCandidates, apiDelegate);
+ currentSortingContextId = quadState->sorting_context_id;
+ }
+
+ if (currentSortingContextId != 0) {
+ std::unique_ptr<cc::DrawPolygon> polygon(
+ new cc::DrawPolygon(
+ quad,
+ gfx::RectF(quad->visible_rect),
+ quadState->quad_to_target_transform,
+ nextPolygonId++));
+ if (polygon->points().size() > 2u)
+ polygonQueue.push_back(std::move(polygon));
+ continue;
+ }
+
if (renderPassChain && currentLayerState != quadState) {
currentLayerState = quadState;
- currentLayerChain = buildLayerChain(renderPassChain, currentLayerState);
+ currentLayerChain = buildLayerChain(renderPassChain, quadState);
}
handleQuad(quad, currentLayerChain,
nodeHandler.data(), resourceCandidates, apiDelegate);
}
+ flushPolygons(&polygonQueue, renderPassChain,
+ nodeHandler.data(), resourceCandidates, apiDelegate);
}
// Send resources of remaining candidates back to the child compositors so that
// they can be freed or reused.
@@ -972,6 +1017,83 @@ void DelegatedFrameNode::commit(ChromiumCompositorData *chromiumCompositorData,
resourcesToRelease->push_back((*it)->returnResource());
}
+void DelegatedFrameNode::flushPolygons(
+ std::deque<std::unique_ptr<cc::DrawPolygon>> *polygonQueue,
+ QSGNode *renderPassChain,
+ DelegatedNodeTreeHandler *nodeHandler,
+ QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ RenderWidgetHostViewQtDelegate *apiDelegate)
+{
+ if (polygonQueue->empty())
+ return;
+
+ const auto actionHandler = [&](cc::DrawPolygon *polygon) {
+ const cc::DrawQuad *quad = polygon->original_ref();
+ const cc::SharedQuadState *quadState = quad->shared_quad_state;
+
+ QSGNode *currentLayerChain = nullptr;
+ if (renderPassChain)
+ currentLayerChain = buildLayerChain(renderPassChain, quad->shared_quad_state);
+
+ gfx::Transform inverseTransform;
+ bool invertible = quadState->quad_to_target_transform.GetInverse(&inverseTransform);
+ DCHECK(invertible);
+ polygon->TransformToLayerSpace(inverseTransform);
+
+ handlePolygon(polygon, currentLayerChain,
+ nodeHandler, resourceCandidates, apiDelegate);
+ };
+
+ cc::BspTree(polygonQueue).TraverseWithActionHandler(&actionHandler);
+}
+
+void DelegatedFrameNode::handlePolygon(
+ const cc::DrawPolygon *polygon,
+ QSGNode *currentLayerChain,
+ DelegatedNodeTreeHandler *nodeHandler,
+ QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ RenderWidgetHostViewQtDelegate *apiDelegate)
+{
+ const cc::DrawQuad *quad = polygon->original_ref();
+
+ if (!polygon->is_split()) {
+ handleQuad(quad, currentLayerChain,
+ nodeHandler, resourceCandidates, apiDelegate);
+ } else {
+ std::vector<gfx::QuadF> clipRegionList;
+ polygon->ToQuads2D(&clipRegionList);
+ for (const auto & clipRegion : clipRegionList)
+ handleClippedQuad(quad, clipRegion, currentLayerChain,
+ nodeHandler, resourceCandidates, apiDelegate);
+ }
+}
+
+void DelegatedFrameNode::handleClippedQuad(
+ const cc::DrawQuad *quad,
+ const gfx::QuadF &clipRegion,
+ QSGNode *currentLayerChain,
+ DelegatedNodeTreeHandler *nodeHandler,
+ QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ RenderWidgetHostViewQtDelegate *apiDelegate)
+{
+ if (currentLayerChain) {
+ auto clipGeometry = new QSGGeometry(QSGGeometry::defaultAttributes_Point2D(), 4);
+ auto clipGeometryVertices = clipGeometry->vertexDataAsPoint2D();
+ clipGeometryVertices[0].set(clipRegion.p1().x(), clipRegion.p1().y());
+ clipGeometryVertices[1].set(clipRegion.p2().x(), clipRegion.p2().y());
+ clipGeometryVertices[2].set(clipRegion.p4().x(), clipRegion.p4().y());
+ clipGeometryVertices[3].set(clipRegion.p3().x(), clipRegion.p3().y());
+ auto clipNode = new QSGClipNode;
+ clipNode->setGeometry(clipGeometry);
+ clipNode->setIsRectangular(false);
+ clipNode->setFlag(QSGNode::OwnsGeometry);
+ currentLayerChain->appendChildNode(clipNode);
+ currentLayerChain = clipNode;
+ }
+ handleQuad(quad, currentLayerChain,
+ nodeHandler, resourceCandidates, apiDelegate);
+}
+
void DelegatedFrameNode::handleQuad(
const cc::DrawQuad *quad,
QSGNode *currentLayerChain,
diff --git a/src/core/delegated_frame_node.h b/src/core/delegated_frame_node.h
index 40aca23b1..cc682988d 100644
--- a/src/core/delegated_frame_node.h
+++ b/src/core/delegated_frame_node.h
@@ -61,6 +61,11 @@ QT_END_NAMESPACE
namespace cc {
class DelegatedFrameData;
class DrawQuad;
+class DrawPolygon;
+}
+
+namespace gfx {
+class QuadF;
}
namespace QtWebEngineCore {
@@ -88,6 +93,25 @@ public:
void commit(ChromiumCompositorData *chromiumCompositorData, cc::ReturnedResourceArray *resourcesToRelease, RenderWidgetHostViewQtDelegate *apiDelegate);
private:
+ void flushPolygons(
+ std::deque<std::unique_ptr<cc::DrawPolygon>> *polygonQueue,
+ QSGNode *renderPassChain,
+ DelegatedNodeTreeHandler *nodeHandler,
+ QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ RenderWidgetHostViewQtDelegate *apiDelegate);
+ void handlePolygon(
+ const cc::DrawPolygon *polygon,
+ QSGNode *currentLayerChain,
+ DelegatedNodeTreeHandler *nodeHandler,
+ QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ RenderWidgetHostViewQtDelegate *apiDelegate);
+ void handleClippedQuad(
+ const cc::DrawQuad *quad,
+ const gfx::QuadF &clipRegion,
+ QSGNode *currentLayerChain,
+ DelegatedNodeTreeHandler *nodeHandler,
+ QHash<unsigned, QSharedPointer<ResourceHolder> > &resourceCandidates,
+ RenderWidgetHostViewQtDelegate *apiDelegate);
void handleQuad(
const cc::DrawQuad *quad,
QSGNode *currentLayerChain,