Support projection in OpReorderer
bug:22480459
Change-Id: Iceb71732dc50957cfb47fa1ba9b8e18e6fc51132
diff --git a/libs/hwui/OpReorderer.cpp b/libs/hwui/OpReorderer.cpp
index 5e954ae..9cbd9c2d 100644
--- a/libs/hwui/OpReorderer.cpp
+++ b/libs/hwui/OpReorderer.cpp
@@ -330,6 +330,7 @@
for (int i = layers.entries().size() - 1; i >= 0; i--) {
RenderNode* layerNode = layers.entries()[i].renderNode;
const Rect& layerDamage = layers.entries()[i].damage;
+ layerNode->computeOrdering();
// map current light center into RenderNode's coordinate space
Vector3 lightCenter = mCanvasState.currentSnapshot()->getRelativeLightCenter();
@@ -339,7 +340,7 @@
layerDamage, lightCenter, nullptr, layerNode);
if (layerNode->getDisplayList()) {
- deferDisplayList(*(layerNode->getDisplayList()));
+ deferNodeOps(*layerNode);
}
restoreForLayer();
}
@@ -347,6 +348,7 @@
// Defer Fbo0
for (const sp<RenderNode>& node : nodes) {
if (node->nothingToDraw()) continue;
+ node->computeOrdering();
int count = mCanvasState.save(SkCanvas::kClip_SaveFlag | SkCanvas::kMatrix_SaveFlag);
deferNodePropsAndOps(*node);
@@ -354,20 +356,6 @@
}
}
-OpReorderer::OpReorderer(int viewportWidth, int viewportHeight, const DisplayList& displayList,
- const Vector3& lightCenter)
- : mCanvasState(*this) {
- ATRACE_NAME("prepare drawing commands");
- // Prepare to defer Fbo0
- mLayerReorderers.emplace_back(viewportWidth, viewportHeight,
- Rect(viewportWidth, viewportHeight));
- mLayerStack.push_back(0);
- mCanvasState.initializeSaveStack(viewportWidth, viewportHeight,
- 0, 0, viewportWidth, viewportHeight, lightCenter);
-
- deferDisplayList(displayList);
-}
-
void OpReorderer::onViewportInitialized() {}
void OpReorderer::onSnapshotRestored(const Snapshot& removed, const Snapshot& restored) {}
@@ -462,10 +450,10 @@
Matrix4::identity(),
saveLayerBounds,
&saveLayerPaint));
- deferDisplayList(*(node.getDisplayList()));
+ deferNodeOps(node);
onEndLayerOp(*new (mAllocator) EndLayerOp());
} else {
- deferDisplayList(*(node.getDisplayList()));
+ deferNodeOps(node);
}
}
}
@@ -610,18 +598,53 @@
}
}
+void OpReorderer::deferProjectedChildren(const RenderNode& renderNode) {
+ const SkPath* projectionReceiverOutline = renderNode.properties().getOutline().getPath();
+ int count = mCanvasState.save(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag);
+
+ // can't be null, since DL=null node rejection happens before deferNodePropsAndOps
+ const DisplayList& displayList = *(renderNode.getDisplayList());
+
+ const RecordedOp* op = (displayList.getOps()[displayList.projectionReceiveIndex]);
+ const RenderNodeOp* backgroundOp = static_cast<const RenderNodeOp*>(op);
+ const RenderProperties& backgroundProps = backgroundOp->renderNode->properties();
+
+ // Transform renderer to match background we're projecting onto
+ // (by offsetting canvas by translationX/Y of background rendernode, since only those are set)
+ mCanvasState.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY());
+
+ // If the projection receiver has an outline, we mask projected content to it
+ // (which we know, apriori, are all tessellated paths)
+ mCanvasState.setProjectionPathMask(mAllocator, projectionReceiverOutline);
+
+ // draw projected nodes
+ for (size_t i = 0; i < renderNode.mProjectedNodes.size(); i++) {
+ RenderNodeOp* childOp = renderNode.mProjectedNodes[i];
+
+ int restoreTo = mCanvasState.save(SkCanvas::kMatrix_SaveFlag);
+ mCanvasState.concatMatrix(childOp->transformFromCompositingAncestor);
+ deferRenderNodeOp(*childOp);
+ mCanvasState.restoreToCount(restoreTo);
+ }
+
+ mCanvasState.restoreToCount(count);
+}
+
/**
* Used to define a list of lambdas referencing private OpReorderer::onXXXXOp() methods.
*
- * This allows opIds embedded in the RecordedOps to be used for dispatching to these lambdas. E.g. a
- * BitmapOp op then would be dispatched to OpReorderer::onBitmapOp(const BitmapOp&)
+ * This allows opIds embedded in the RecordedOps to be used for dispatching to these lambdas.
+ * E.g. a BitmapOp op then would be dispatched to OpReorderer::onBitmapOp(const BitmapOp&)
*/
#define OP_RECEIVER(Type) \
[](OpReorderer& reorderer, const RecordedOp& op) { reorderer.on##Type(static_cast<const Type&>(op)); },
-void OpReorderer::deferDisplayList(const DisplayList& displayList) {
+void OpReorderer::deferNodeOps(const RenderNode& renderNode) {
static std::function<void(OpReorderer& reorderer, const RecordedOp&)> receivers[] = {
MAP_OPS(OP_RECEIVER)
};
+
+ // can't be null, since DL=null node rejection happens before deferNodePropsAndOps
+ const DisplayList& displayList = *(renderNode.getDisplayList());
for (const DisplayList::Chunk& chunk : displayList.getChunks()) {
FatVector<ZRenderNodeOpPair, 16> zTranslatedNodes;
buildZSortedChildList(&zTranslatedNodes, displayList, chunk);
@@ -630,6 +653,12 @@
for (size_t opIndex = chunk.beginOpIndex; opIndex < chunk.endOpIndex; opIndex++) {
const RecordedOp* op = displayList.getOps()[opIndex];
receivers[op->opId](*this, *op);
+
+ if (CC_UNLIKELY(!renderNode.mProjectedNodes.empty()
+ && displayList.projectionReceiveIndex >= 0
+ && static_cast<int>(opIndex) == displayList.projectionReceiveIndex)) {
+ deferProjectedChildren(renderNode);
+ }
}
defer3dChildren(ChildrenSelectMode::Positive, zTranslatedNodes);
}