Holepunch layers for SurfaceView
Update RenderNodeDrawable to hole punch areas into
layers created for SurfaceView
Bug: 184297961
Test: Added CTS test to SurfaceViewTests
Change-Id: I1f03a4fe34c5a8b7411ebe728ea3d4195fcd1fac
diff --git a/libs/hwui/pipeline/skia/HolePunch.cpp b/libs/hwui/pipeline/skia/HolePunch.cpp
new file mode 100644
index 0000000..2b2bca6
--- /dev/null
+++ b/libs/hwui/pipeline/skia/HolePunch.cpp
@@ -0,0 +1,21 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "HolePunch.h"
+#include <string>
+
+using namespace android::uirenderer::skiapipeline;
+
+const std::string HOLE_PUNCH_ANNOTATION = "surface_hole_punch";
diff --git a/libs/hwui/pipeline/skia/HolePunch.h b/libs/hwui/pipeline/skia/HolePunch.h
new file mode 100644
index 0000000..92c6f77
--- /dev/null
+++ b/libs/hwui/pipeline/skia/HolePunch.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <string>
+#include "SkRRect.h"
+
+namespace android {
+namespace uirenderer {
+namespace skiapipeline {
+
+const static std::string HOLE_PUNCH_ANNOTATION;
+
+} // namespace skiapipeline
+} // namespace uirenderer
+} // namespace android
\ No newline at end of file
diff --git a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
index cb0ff8d..5627a7e 100644
--- a/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
+++ b/libs/hwui/pipeline/skia/RenderNodeDrawable.cpp
@@ -18,6 +18,7 @@
#include <SkPaintFilterCanvas.h>
#include "RenderNode.h"
#include "SkiaDisplayList.h"
+#include "TransformCanvas.h"
#include "utils/TraceUtils.h"
#include <include/effects/SkImageFilters.h>
@@ -256,6 +257,11 @@
canvas->drawAnnotation(bounds, String8::format(
"SurfaceID|%" PRId64, renderNode->uniqueId()).c_str(), nullptr);
}
+
+ if (renderNode->hasHolePunches()) {
+ TransformCanvas transformCanvas(canvas);
+ displayList->draw(&transformCanvas);
+ }
canvas->drawImageRect(snapshotImage, bounds, bounds, sampling, &paint,
SkCanvas::kStrict_SrcRectConstraint);
diff --git a/libs/hwui/pipeline/skia/SkiaDisplayList.h b/libs/hwui/pipeline/skia/SkiaDisplayList.h
index 1136e58..90e9bc6 100644
--- a/libs/hwui/pipeline/skia/SkiaDisplayList.h
+++ b/libs/hwui/pipeline/skia/SkiaDisplayList.h
@@ -163,7 +163,7 @@
private:
std::vector<Pair<VectorDrawableRoot*, SkMatrix>> mVectorDrawables;
-
+ bool mHasHolePunches;
public:
void appendVD(VectorDrawableRoot* r) { appendVD(r, SkMatrix::I()); }
@@ -171,6 +171,14 @@
mVectorDrawables.push_back(Pair<VectorDrawableRoot*, SkMatrix>(r, mat));
}
+ void setHasHolePunches(bool hasHolePunches) {
+ mHasHolePunches = hasHolePunches;
+ }
+
+ bool hasHolePunches() {
+ return mHasHolePunches;
+ }
+
std::vector<AnimatedImageDrawable*> mAnimatedImages;
DisplayListData mDisplayList;
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
index 61f9960..82814de 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.cpp
@@ -53,6 +53,27 @@
mDisplayList->attachRecorder(&mRecorder, SkIRect::MakeWH(width, height));
SkiaCanvas::reset(&mRecorder);
+ mDisplayList->setHasHolePunches(false);
+}
+
+void SkiaRecordingCanvas::punchHole(const SkRRect& rect) {
+ // Add the marker annotation to allow HWUI to determine where the current
+ // clip/transformation should be applied
+ SkVector vector = rect.getSimpleRadii();
+ const int dataSize = 2;
+ float data[dataSize];
+ data[0] = vector.x();
+ data[1] = vector.y();
+ mRecorder.drawAnnotation(rect.rect(), HOLE_PUNCH_ANNOTATION.c_str(),
+ SkData::MakeWithCopy(data, dataSize));
+
+ // Clear the current rect within the layer itself
+ SkPaint paint = SkPaint();
+ paint.setColor(0);
+ paint.setBlendMode(SkBlendMode::kClear);
+ mRecorder.drawRRect(rect, paint);
+
+ mDisplayList->setHasHolePunches(true);
}
std::unique_ptr<SkiaDisplayList> SkiaRecordingCanvas::finishRecording() {
diff --git a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
index ff03e0c..06f2a27 100644
--- a/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
+++ b/libs/hwui/pipeline/skia/SkiaRecordingCanvas.h
@@ -15,6 +15,7 @@
*/
#pragma once
+#include "HolePunch.h"
#include "RecordingCanvas.h"
#include "ReorderBarrierDrawables.h"
#include "SkiaCanvas.h"
@@ -43,6 +44,8 @@
initDisplayList(renderNode, width, height);
}
+ virtual void punchHole(const SkRRect& rect) override;
+
virtual void finishRecording(uirenderer::RenderNode* destination) override;
std::unique_ptr<SkiaDisplayList> finishRecording();
diff --git a/libs/hwui/pipeline/skia/TransformCanvas.cpp b/libs/hwui/pipeline/skia/TransformCanvas.cpp
new file mode 100644
index 0000000..6bfbb0d
--- /dev/null
+++ b/libs/hwui/pipeline/skia/TransformCanvas.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "TransformCanvas.h"
+#include "HolePunch.h"
+#include "SkData.h"
+#include "SkDrawable.h"
+
+using namespace android::uirenderer::skiapipeline;
+
+void TransformCanvas::onDrawAnnotation(const SkRect& rect, const char* key, SkData* value) {
+ if (HOLE_PUNCH_ANNOTATION == key) {
+ auto* rectParams = static_cast<const float*>(value->data());
+ float radiusX = rectParams[0];
+ float radiusY = rectParams[1];
+ SkRRect roundRect = SkRRect::MakeRectXY(rect, radiusX, radiusY);
+
+ SkPaint paint;
+ paint.setColor(0);
+ paint.setBlendMode(SkBlendMode::kClear);
+ mWrappedCanvas->drawRRect(roundRect, paint);
+ }
+}
+
+void TransformCanvas::onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) {
+ drawable->draw(this, matrix);
+}
+
+bool TransformCanvas::onFilter(SkPaint& paint) const {
+ return false;
+}
diff --git a/libs/hwui/pipeline/skia/TransformCanvas.h b/libs/hwui/pipeline/skia/TransformCanvas.h
new file mode 100644
index 0000000..47f77f1
--- /dev/null
+++ b/libs/hwui/pipeline/skia/TransformCanvas.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2021 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#pragma once
+
+#include <include/core/SkCanvas.h>
+#include "SkPaintFilterCanvas.h"
+
+class TransformCanvas : public SkPaintFilterCanvas {
+public:
+ TransformCanvas(SkCanvas* target) : SkPaintFilterCanvas(target), mWrappedCanvas(target) {}
+
+protected:
+ bool onFilter(SkPaint& paint) const override;
+
+protected:
+ void onDrawAnnotation(const SkRect& rect, const char* key, SkData* value) override;
+ void onDrawDrawable(SkDrawable* drawable, const SkMatrix* matrix) override;
+
+private:
+ // We don't own the canvas so just maintain a raw pointer to it
+ SkCanvas* mWrappedCanvas;
+};