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:
Chris Craik
2014-08-08 18:42:51 -07:00
parent c28aceb11e
commit b3cca876c2
3 changed files with 26 additions and 15 deletions

View File

@@ -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

View File

@@ -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>

View File

@@ -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);