diff options
| -rw-r--r-- | libs/hwui/FrameBuilder.cpp | 40 | ||||
| -rw-r--r-- | libs/hwui/OpDumper.cpp | 4 | ||||
| -rw-r--r-- | libs/hwui/OpDumper.h | 1 | ||||
| -rw-r--r-- | libs/hwui/tests/unit/FrameBuilderTests.cpp | 5 |
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) { |