summaryrefslogtreecommitdiff
path: root/libs/hwui/Snapshot.cpp
diff options
context:
space:
mode:
author Chris Craik <ccraik@google.com> 2015-04-28 11:45:59 -0700
committer Chris Craik <ccraik@google.com> 2015-05-26 17:53:16 -0700
commitfca52b7583d1e5f5ff8ed06554875d2a30ef56fa (patch)
treee383a2db169421a722fa9c559dd01904e83fa504 /libs/hwui/Snapshot.cpp
parentaa1cd25db72297f13539928e8aa45ba992f2f230 (diff)
Use path intersection instead of saveLayer+mesh to mask projected ripples
bug:14297149 SaveLayer's performance cost is high, and proportional to the surface being projected onto. Since ripples (even unbounded ones) are now always projected to the arbitrary background content behind them, this cost is especially important to avoid. This removes the last semi-secret, saveLayer from the projected ripple implementation. Also fixes the HW test app to correctly demonstrate this projection masking behavior. Additionaly, alters PathTessellator to gracefully handle counter-clockwise paths, and simplifies the work done by ShadowTessellator to ensure all of its paths are counterclockwise. Change-Id: Ibe9e12812bd10a774e20b1d444a140c368cbba8c
Diffstat (limited to 'libs/hwui/Snapshot.cpp')
-rw-r--r--libs/hwui/Snapshot.cpp42
1 files changed, 42 insertions, 0 deletions
diff --git a/libs/hwui/Snapshot.cpp b/libs/hwui/Snapshot.cpp
index 9e7faee69fba..beb2e1d0481c 100644
--- a/libs/hwui/Snapshot.cpp
+++ b/libs/hwui/Snapshot.cpp
@@ -36,6 +36,7 @@ Snapshot::Snapshot()
, empty(false)
, alpha(1.0f)
, roundRectClipState(nullptr)
+ , projectionPathMask(nullptr)
, mClipArea(&mClipAreaRoot) {
transform = &mTransformRoot;
region = nullptr;
@@ -54,6 +55,7 @@ Snapshot::Snapshot(const sp<Snapshot>& s, int saveFlags)
, empty(false)
, alpha(s->alpha)
, roundRectClipState(s->roundRectClipState)
+ , projectionPathMask(s->projectionPathMask)
, mClipArea(nullptr)
, mViewportData(s->mViewportData)
, mRelativeLightCenter(s->mRelativeLightCenter) {
@@ -141,6 +143,34 @@ void Snapshot::resetTransform(float x, float y, float z) {
transform->loadTranslate(x, y, z);
}
+void Snapshot::buildScreenSpaceTransform(Matrix4* outTransform) const {
+ // build (reverse ordered) list of the stack of snapshots, terminated with a NULL
+ Vector<const Snapshot*> snapshotList;
+ snapshotList.push(nullptr);
+ const Snapshot* current = this;
+ do {
+ snapshotList.push(current);
+ current = current->previous.get();
+ } while (current);
+
+ // traverse the list, adding in each transform that contributes to the total transform
+ outTransform->loadIdentity();
+ for (size_t i = snapshotList.size() - 1; i > 0; i--) {
+ // iterate down the stack
+ const Snapshot* current = snapshotList[i];
+ const Snapshot* next = snapshotList[i - 1];
+ if (current->flags & kFlagIsFboLayer) {
+ // if we've hit a layer, translate by the layer's draw offset
+ outTransform->translate(current->layer->layer.left, current->layer->layer.top);
+ }
+ if (!next || (next->flags & kFlagIsFboLayer)) {
+ // if this snapshot is last, or if this snapshot is last before an
+ // FBO layer (which reset the transform), apply it
+ outTransform->multiply(*(current->transform));
+ }
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// Clipping round rect
///////////////////////////////////////////////////////////////////////////////
@@ -191,6 +221,18 @@ void Snapshot::setClippingRoundRect(LinearAllocator& allocator, const Rect& boun
roundRectClipState = state;
}
+void Snapshot::setProjectionPathMask(LinearAllocator& allocator, const SkPath* path) {
+ if (path) {
+ ProjectionPathMask* mask = new (allocator) ProjectionPathMask;
+ mask->projectionMask = path;
+ buildScreenSpaceTransform(&(mask->projectionMaskTransform));
+
+ projectionPathMask = mask;
+ } else {
+ projectionPathMask = nullptr;
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// Queries
///////////////////////////////////////////////////////////////////////////////