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
This commit is contained in:
@@ -176,15 +176,15 @@ bool DisplayListRenderer::clipRegion(const SkRegion* region, SkRegion::Op op) {
|
||||
status_t DisplayListRenderer::drawRenderNode(RenderNode* renderNode, Rect& dirty, int32_t flags) {
|
||||
// dirty is an out parameter and should not be recorded,
|
||||
// it matters only when replaying the display list
|
||||
DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
|
||||
int opIndex = addDrawOp(op);
|
||||
mDisplayListData->addChild(op);
|
||||
|
||||
if (renderNode->stagingProperties().isProjectionReceiver()) {
|
||||
// use staging property, since recording on UI thread
|
||||
mDisplayListData->projectionReceiveIndex = mDisplayListData->displayListOps.size();
|
||||
mDisplayListData->projectionReceiveIndex = opIndex;
|
||||
}
|
||||
|
||||
DrawRenderNodeOp* op = new (alloc()) DrawRenderNodeOp(renderNode, flags, *currentTransform());
|
||||
addDrawOp(op);
|
||||
mDisplayListData->addChild(op);
|
||||
return DrawGlInfo::kStatusDone;
|
||||
}
|
||||
|
||||
@@ -447,11 +447,11 @@ void DisplayListRenderer::insertTranslate() {
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayListRenderer::addStateOp(StateOp* op) {
|
||||
addOpInternal(op);
|
||||
int DisplayListRenderer::addStateOp(StateOp* op) {
|
||||
return addOpInternal(op);
|
||||
}
|
||||
|
||||
void DisplayListRenderer::addDrawOp(DrawOp* op) {
|
||||
int DisplayListRenderer::addDrawOp(DrawOp* op) {
|
||||
Rect localBounds;
|
||||
if (op->getLocalBounds(localBounds)) {
|
||||
bool rejected = quickRejectConservative(localBounds.left, localBounds.top,
|
||||
@@ -460,7 +460,7 @@ void DisplayListRenderer::addDrawOp(DrawOp* op) {
|
||||
}
|
||||
|
||||
mDisplayListData->hasDrawOps = true;
|
||||
addOpInternal(op);
|
||||
return addOpInternal(op);
|
||||
}
|
||||
|
||||
}; // namespace uirenderer
|
||||
|
||||
@@ -158,12 +158,14 @@ private:
|
||||
void insertTranslate();
|
||||
|
||||
LinearAllocator& alloc() { return mDisplayListData->allocator; }
|
||||
void addStateOp(StateOp* op);
|
||||
void addDrawOp(DrawOp* op);
|
||||
void addOpInternal(DisplayListOp* op) {
|
||||
|
||||
// Each method returns final index of op
|
||||
int addStateOp(StateOp* op);
|
||||
int addDrawOp(DrawOp* op);
|
||||
int addOpInternal(DisplayListOp* op) {
|
||||
insertRestoreToCount();
|
||||
insertTranslate();
|
||||
mDisplayListData->displayListOps.add(op);
|
||||
return mDisplayListData->displayListOps.add(op);
|
||||
}
|
||||
|
||||
template<class T>
|
||||
|
||||
@@ -741,15 +741,24 @@ void RenderNode::issueOperationsOfProjectedChildren(OpenGLRenderer& renderer, T&
|
||||
const SkPath* projectionReceiverOutline = properties().getOutline().getPath();
|
||||
int restoreTo = renderer.getSaveCount();
|
||||
|
||||
LinearAllocator& alloc = handler.allocator();
|
||||
handler(new (alloc) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
|
||||
PROPERTY_SAVECOUNT, properties().getClipToBounds());
|
||||
|
||||
// Transform renderer to match background we're projecting onto
|
||||
// (by offsetting canvas by translationX/Y of background rendernode, since only those are set)
|
||||
const DisplayListOp* op =
|
||||
(mDisplayListData->displayListOps[mDisplayListData->projectionReceiveIndex]);
|
||||
const DrawRenderNodeOp* backgroundOp = reinterpret_cast<const DrawRenderNodeOp*>(op);
|
||||
const RenderProperties& backgroundProps = backgroundOp->mRenderNode->properties();
|
||||
renderer.translate(backgroundProps.getTranslationX(), backgroundProps.getTranslationY());
|
||||
|
||||
// If the projection reciever has an outline, we mask each of the projected rendernodes to it
|
||||
// Either with clipRect, or special saveLayer masking
|
||||
LinearAllocator& alloc = handler.allocator();
|
||||
if (projectionReceiverOutline != NULL) {
|
||||
const SkRect& outlineBounds = projectionReceiverOutline->getBounds();
|
||||
if (projectionReceiverOutline->isRect(NULL)) {
|
||||
// mask to the rect outline simply with clipRect
|
||||
handler(new (alloc) SaveOp(SkCanvas::kMatrix_SaveFlag | SkCanvas::kClip_SaveFlag),
|
||||
PROPERTY_SAVECOUNT, properties().getClipToBounds());
|
||||
ClipRectOp* clipOp = new (alloc) ClipRectOp(
|
||||
outlineBounds.left(), outlineBounds.top(),
|
||||
outlineBounds.right(), outlineBounds.bottom(), SkRegion::kIntersect_Op);
|
||||
|
||||
Reference in New Issue
Block a user