summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author John Reck <jreck@google.com> 2016-05-24 15:06:01 -0700
committer John Reck <jreck@google.com> 2016-05-24 15:06:01 -0700
commitc9bb1a38d356087a4e5578307a6839eac0a1e6ee (patch)
treea50435aac169d3bc8897d9c3a1f50a05e3039868
parent2a4001ee62f3374d7fffed72d71f77c5a833c331 (diff)
Fix a translate issue with saveLayer
Bug: 28667141 saveLayer clips the layer to the size it needs to be and will translate content if necessary, but the drawLayerOp that results from that was not translated to handle the shifted draw content. This fixes that Change-Id: I3c9ffd5d0282fa1b958bced94c25e9744281e9be
-rw-r--r--libs/hwui/FrameBuilder.cpp40
-rw-r--r--libs/hwui/OpDumper.cpp4
-rw-r--r--libs/hwui/OpDumper.h1
-rw-r--r--libs/hwui/tests/unit/FrameBuilderTests.cpp5
4 files changed, 49 insertions, 1 deletions
diff --git a/libs/hwui/FrameBuilder.cpp b/libs/hwui/FrameBuilder.cpp
index 746e99a96123..cb8e55fbb21c 100644
--- a/libs/hwui/FrameBuilder.cpp
+++ b/libs/hwui/FrameBuilder.cpp
@@ -878,11 +878,49 @@ void FrameBuilder::deferEndLayerOp(const EndLayerOp& /* ignored */) {
restoreForLayer();
+ // saveLayer will clip & translate the draw contents, so we need
+ // to translate the drawLayer by how much the contents was translated
+ // TODO: Unify this with beginLayerOp so we don't have to calculate this
+ // twice
+ uint32_t layerWidth = (uint32_t) beginLayerOp.unmappedBounds.getWidth();
+ uint32_t layerHeight = (uint32_t) beginLayerOp.unmappedBounds.getHeight();
+
+ auto previous = mCanvasState.currentSnapshot();
+ Vector3 lightCenter = previous->getRelativeLightCenter();
+
+ // Combine all transforms used to present saveLayer content:
+ // parent content transform * canvas transform * bounds offset
+ Matrix4 contentTransform(*(previous->transform));
+ contentTransform.multiply(beginLayerOp.localMatrix);
+ contentTransform.translate(beginLayerOp.unmappedBounds.left,
+ beginLayerOp.unmappedBounds.top);
+
+ Matrix4 inverseContentTransform;
+ inverseContentTransform.loadInverse(contentTransform);
+
+ // map the light center into layer-relative space
+ inverseContentTransform.mapPoint3d(lightCenter);
+
+ // Clip bounds of temporary layer to parent's clip rect, so:
+ Rect saveLayerBounds(layerWidth, layerHeight);
+ // 1) transform Rect(width, height) into parent's space
+ // note: left/top offsets put in contentTransform above
+ contentTransform.mapRect(saveLayerBounds);
+ // 2) intersect with parent's clip
+ saveLayerBounds.doIntersect(previous->getRenderTargetClip());
+ // 3) and transform back
+ inverseContentTransform.mapRect(saveLayerBounds);
+ saveLayerBounds.doIntersect(Rect(layerWidth, layerHeight));
+ saveLayerBounds.roundOut();
+
+ Matrix4 localMatrix(beginLayerOp.localMatrix);
+ localMatrix.translate(saveLayerBounds.left, saveLayerBounds.top);
+
// record the draw operation into the previous layer's list of draw commands
// uses state from the associated beginLayerOp, since it has all the state needed for drawing
LayerOp* drawLayerOp = mAllocator.create_trivial<LayerOp>(
beginLayerOp.unmappedBounds,
- beginLayerOp.localMatrix,
+ localMatrix,
beginLayerOp.localClip,
beginLayerOp.paint,
&(mLayerBuilders[finishedLayerIndex]->offscreenBuffer));
diff --git a/libs/hwui/OpDumper.cpp b/libs/hwui/OpDumper.cpp
index cab93e8faf6a..ec9ffdeebb4c 100644
--- a/libs/hwui/OpDumper.cpp
+++ b/libs/hwui/OpDumper.cpp
@@ -45,5 +45,9 @@ void OpDumper::dump(const RecordedOp& op, std::ostream& output, int level) {
}
}
+const char* OpDumper::opName(const RecordedOp& op) {
+ return sOpNameLut[op.opId];
+}
+
} // namespace uirenderer
} // namespace android
diff --git a/libs/hwui/OpDumper.h b/libs/hwui/OpDumper.h
index c99b51796b5c..a82289c7cca2 100644
--- a/libs/hwui/OpDumper.h
+++ b/libs/hwui/OpDumper.h
@@ -26,6 +26,7 @@ struct RecordedOp;
class OpDumper {
public:
static void dump(const RecordedOp& op, std::ostream& output, int level = 0);
+ static const char* opName(const RecordedOp& op);
};
}; // namespace uirenderer
diff --git a/libs/hwui/tests/unit/FrameBuilderTests.cpp b/libs/hwui/tests/unit/FrameBuilderTests.cpp
index 0f16b1512586..af1fbd8254f9 100644
--- a/libs/hwui/tests/unit/FrameBuilderTests.cpp
+++ b/libs/hwui/tests/unit/FrameBuilderTests.cpp
@@ -2025,6 +2025,7 @@ struct SaveLayerAlphaData {
uint32_t layerHeight = 0;
Rect rectClippedBounds;
Matrix4 rectMatrix;
+ Matrix4 drawLayerMatrix;
};
/**
* Constructs a view to hit the temporary layer alpha property implementation:
@@ -2060,6 +2061,7 @@ void testSaveLayerAlphaClip(SaveLayerAlphaData* outObservedData,
}
void onLayerOp(const LayerOp& op, const BakedOpState& state) override {
EXPECT_EQ(3, mIndex++);
+ mOutData->drawLayerMatrix = state.computedState.transform;
}
void recycleTemporaryLayer(OffscreenBuffer* offscreenBuffer) override {
EXPECT_EQ(4, mIndex++);
@@ -2108,6 +2110,9 @@ RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaClipBig) {
expected.loadTranslate(0, -2000, 0);
EXPECT_MATRIX_APPROX_EQ(expected, observedData.rectMatrix)
<< "expect content to be translated as part of being clipped";
+ expected.loadTranslate(10, 0, 0);
+ EXPECT_MATRIX_APPROX_EQ(expected, observedData.drawLayerMatrix)
+ << "expect drawLayer to be translated as part of being clipped";
}
RENDERTHREAD_TEST(FrameBuilder, renderPropSaveLayerAlphaRotate) {