Skip to content

Commit b3cca87

Browse files
committed
Fix ripples projecting to scrolled view
bug:16873774 1) Fix projectionReceiveIndex, which could in some cases point at translate/restore ops. 2) Use background translateX / translateY for projected RenderNodes. This makes them match background position, and thus properly account for scroll. Change-Id: Idbd5700858fd67c5abea0270a1012952fe09ac22
1 parent c28aceb commit b3cca87

File tree

3 files changed

+26
-15
lines changed

3 files changed

+26
-15
lines changed

libs/hwui/DisplayListRenderer.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -176,15 +176,15 @@ bool DisplayListRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
176176
status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
177177
// dirty is an out parameter and should not be recorded,
178178
// it matters only when replaying the display list
179+
DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
180+
int opIndex = addDrawOp(op);
181+
mDisplayListData->addChild(op);
179182

180183
if (renderNode->stagingProperties().isProjectionReceiver()) {
181184
// use staging property, since recording on UI thread
182-
mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size();
185+
mDisplayListData->projectionReceiveIndex = opIndex;
183186
}
184187

185-
DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
186-
addDrawOp(op);
187-
mDisplayListData->addChild(op);
188188
return DrawGlInfo::kStatusDone;
189189
}
190190

@@ -447,11 +447,11 @@ void DisplayListRenderer::insertTranslate() {
447447
}
448448
}
449449

450-
void DisplayListRenderer::addStateOp(StateOp* op) {
451-
addOpInternal(op);
450+
int DisplayListRenderer::addStateOp(StateOp* op) {
451+
return addOpInternal(op);
452452
}
453453

454-
void DisplayListRenderer::addDrawOp(DrawOp* op) {
454+
int DisplayListRenderer::addDrawOp(DrawOp* op) {
455455
Rect localBounds;
456456
if (op->getLocalBounds(localBounds)) {
457457
bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
@@ -460,7 +460,7 @@ void DisplayListRenderer::addDrawOp(DrawOp* op) {
460460
}
461461

462462
mDisplayListData->hasDrawOps = true;
463-
addOpInternal(op);
463+
return addOpInternal(op);
464464
}
465465

466466
}; // namespace uirenderer

libs/hwui/DisplayListRenderer.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,14 @@ class ANDROID_API DisplayListRenderer: public StatefulBaseRenderer {
158158
void insertTranslate();
159159

160160
LinearAllocator& alloc() { return mDisplayListData->allocator; }
161-
void addStateOp(StateOp* op);
162-
void addDrawOp(DrawOp* op);
163-
void addOpInternal(DisplayListOp* op) {
161+
162+
// Each method returns final index of op
163+
int addStateOp(StateOp* op);
164+
int addDrawOp(DrawOp* op);
165+
int addOpInternal(DisplayListOp* op) {
164166
insertRestoreToCount();
165167
insertTranslate();
166-
mDisplayListData->displayListOps.add(op);
168+
return mDisplayListData->displayListOps.add(op);
167169
}
168170

169171
template<class T>

libs/hwui/RenderNode.cpp

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -741,15 +741,24 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T&
741741
const SkPath* projectionReceiverOutline = properties().getOutline().getPath();
742742
int restoreTo = renderer.getSaveCount();
743743

744+
LinearAllocator& alloc = handler.allocator();
745+
handler(new (alloc) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
746+
PROPERTY_SAVECOUNT, properties().getClipToBounds());
747+
748+
// Transform renderer to match background we're projecting onto
749+
// (by offsetting canvas by translationX/Y of background rendernode, since only those are set)
750+
const DisplayListOp* op =
751+
(mDisplayListData->displayListOps[mDisplayListData->projectionReceiveIndex]);
752+
const DrawRenderNodeOp* backgroundOp = reinterpret_cast<const DrawRenderNodeOp*>(op);
753+
const RenderProperties& backgroundProps = backgroundOp->mRenderNode->properties();
754+
renderer.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY());
755+
744756
// If the projection reciever has an outline, we mask each of the projected rendernodes to it
745757
// Either with clipRect, or special saveLayer masking
746-
LinearAllocator& alloc = handler.allocator();
747758
if (projectionReceiverOutline != NULL) {
748759
const SkRect& outlineBounds = projectionReceiverOutline->getBounds();
749760
if (projectionReceiverOutline->isRect(NULL)) {
750761
// mask to the rect outline simply with clipRect
751-
handler(new (alloc) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
752-
PROPERTY_SAVECOUNT, properties().getClipToBounds());
753762
ClipRectOp* clipOp = new (alloc) ClipRectOp(
754763
outlineBounds.left(), outlineBounds.top(),
755764
outlineBounds.right(), outlineBounds.bottom(), SkRegion::kIntersect_Op);

0 commit comments

Comments
 (0)