libgui: add layer_state_t::diff

Compares two layer_state_t structs and returns
a set of change flags describing all the states
that are different.

Also introduces change sets describing which
set of client states can affect the hierarchy,
content or the content size.

Bug: 238781169
Test: presubmit
Change-Id: I6e5fb255972aff2373be27e62005ee3a8de7ebf6
diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp
index 924e65e..95962af 100644
--- a/libs/gui/LayerState.cpp
+++ b/libs/gui/LayerState.cpp
@@ -24,10 +24,31 @@
 #include <binder/Parcel.h>
 #include <gui/IGraphicBufferProducer.h>
 #include <gui/LayerState.h>
+#include <gui/SurfaceControl.h>
 #include <private/gui/ParcelUtils.h>
 #include <system/window.h>
 #include <utils/Errors.h>
 
+#define CHECK_DIFF(DIFF_RESULT, CHANGE_FLAG, OTHER, FIELD)          \
+    {                                                               \
+        if ((OTHER.what & CHANGE_FLAG) && (FIELD != OTHER.FIELD)) { \
+            DIFF_RESULT |= CHANGE_FLAG;                             \
+        }                                                           \
+    }
+
+#define CHECK_DIFF2(DIFF_RESULT, CHANGE_FLAG, OTHER, FIELD1, FIELD2) \
+    {                                                                \
+        CHECK_DIFF(DIFF_RESULT, CHANGE_FLAG, OTHER, FIELD1)          \
+        CHECK_DIFF(DIFF_RESULT, CHANGE_FLAG, OTHER, FIELD2)          \
+    }
+
+#define CHECK_DIFF3(DIFF_RESULT, CHANGE_FLAG, OTHER, FIELD1, FIELD2, FIELD3) \
+    {                                                                        \
+        CHECK_DIFF(DIFF_RESULT, CHANGE_FLAG, OTHER, FIELD1)                  \
+        CHECK_DIFF(DIFF_RESULT, CHANGE_FLAG, OTHER, FIELD2)                  \
+        CHECK_DIFF(DIFF_RESULT, CHANGE_FLAG, OTHER, FIELD3)                  \
+    }
+
 namespace android {
 
 using gui::FocusRequest;
@@ -626,6 +647,74 @@
     }
 }
 
+uint64_t layer_state_t::diff(const layer_state_t& other) const {
+    uint64_t diff = 0;
+    CHECK_DIFF2(diff, ePositionChanged, other, x, y);
+    if (other.what & eLayerChanged) {
+        diff |= eLayerChanged;
+        diff &= ~eRelativeLayerChanged;
+    }
+    CHECK_DIFF(diff, eAlphaChanged, other, color.a);
+    CHECK_DIFF(diff, eMatrixChanged, other, matrix);
+    if (other.what & eTransparentRegionChanged &&
+        (!transparentRegion.hasSameRects(other.transparentRegion))) {
+        diff |= eTransparentRegionChanged;
+    }
+    if (other.what & eFlagsChanged) {
+        uint64_t changedFlags = (flags & other.mask) ^ (other.flags & other.mask);
+        if (changedFlags) diff |= eFlagsChanged;
+    }
+    CHECK_DIFF(diff, eLayerStackChanged, other, layerStack);
+    CHECK_DIFF(diff, eCornerRadiusChanged, other, cornerRadius);
+    CHECK_DIFF(diff, eBackgroundBlurRadiusChanged, other, backgroundBlurRadius);
+    if (other.what & eBlurRegionsChanged) diff |= eBlurRegionsChanged;
+    if (other.what & eRelativeLayerChanged) {
+        diff |= eRelativeLayerChanged;
+        diff &= ~eLayerChanged;
+    }
+    if (other.what & eReparent &&
+        !SurfaceControl::isSameSurface(parentSurfaceControlForChild,
+                                       other.parentSurfaceControlForChild)) {
+        diff |= eReparent;
+    }
+    CHECK_DIFF(diff, eBufferTransformChanged, other, bufferTransform);
+    CHECK_DIFF(diff, eTransformToDisplayInverseChanged, other, transformToDisplayInverse);
+    CHECK_DIFF(diff, eCropChanged, other, crop);
+    if (other.what & eBufferChanged) diff |= eBufferChanged;
+    CHECK_DIFF(diff, eDataspaceChanged, other, dataspace);
+    CHECK_DIFF(diff, eHdrMetadataChanged, other, hdrMetadata);
+    if (other.what & eSurfaceDamageRegionChanged &&
+        (!surfaceDamageRegion.hasSameRects(other.surfaceDamageRegion))) {
+        diff |= eSurfaceDamageRegionChanged;
+    }
+    CHECK_DIFF(diff, eApiChanged, other, api);
+    if (other.what & eSidebandStreamChanged) diff |= eSidebandStreamChanged;
+    CHECK_DIFF(diff, eApiChanged, other, api);
+    CHECK_DIFF(diff, eColorTransformChanged, other, colorTransform);
+    if (other.what & eHasListenerCallbacksChanged) diff |= eHasListenerCallbacksChanged;
+    if (other.what & eInputInfoChanged) diff |= eInputInfoChanged;
+    CHECK_DIFF3(diff, eBackgroundColorChanged, other, color.rgb, bgColorAlpha, bgColorDataspace);
+    if (other.what & eMetadataChanged) diff |= eMetadataChanged;
+    CHECK_DIFF(diff, eShadowRadiusChanged, other, shadowRadius);
+    CHECK_DIFF3(diff, eRenderBorderChanged, other, borderEnabled, borderWidth, borderColor);
+    CHECK_DIFF(diff, eDefaultFrameRateCompatibilityChanged, other, defaultFrameRateCompatibility);
+    CHECK_DIFF(diff, eFrameRateSelectionPriority, other, frameRateSelectionPriority);
+    CHECK_DIFF3(diff, eFrameRateChanged, other, frameRate, frameRateCompatibility,
+                changeFrameRateStrategy);
+    CHECK_DIFF(diff, eFixedTransformHintChanged, other, fixedTransformHint);
+    CHECK_DIFF(diff, eAutoRefreshChanged, other, autoRefresh);
+    CHECK_DIFF(diff, eTrustedOverlayChanged, other, isTrustedOverlay);
+    CHECK_DIFF(diff, eStretchChanged, other, stretchEffect);
+    CHECK_DIFF(diff, eBufferCropChanged, other, bufferCrop);
+    CHECK_DIFF(diff, eDestinationFrameChanged, other, destinationFrame);
+    if (other.what & eProducerDisconnect) diff |= eProducerDisconnect;
+    CHECK_DIFF(diff, eDropInputModeChanged, other, dropInputMode);
+    CHECK_DIFF(diff, eColorChanged, other, color.rgb);
+    CHECK_DIFF(diff, eColorSpaceAgnosticChanged, other, colorSpaceAgnostic);
+    CHECK_DIFF(diff, eDimmingEnabledChanged, other, dimmingEnabled);
+    return diff;
+}
+
 bool layer_state_t::hasBufferChanges() const {
     return what & layer_state_t::eBufferChanged;
 }
diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp
index d18d22d..1e43700 100644
--- a/libs/gui/SurfaceComposerClient.cpp
+++ b/libs/gui/SurfaceComposerClient.cpp
@@ -1250,6 +1250,7 @@
     if ((mask & layer_state_t::eLayerOpaque) || (mask & layer_state_t::eLayerHidden) ||
         (mask & layer_state_t::eLayerSecure) || (mask & layer_state_t::eLayerSkipScreenshot) ||
         (mask & layer_state_t::eEnableBackpressure) ||
+        (mask & layer_state_t::eIgnoreDestinationFrame) ||
         (mask & layer_state_t::eLayerIsDisplayDecoration)) {
         s->what |= layer_state_t::eFlagsChanged;
     }
diff --git a/libs/gui/include/gui/LayerState.h b/libs/gui/include/gui/LayerState.h
index 09f171d..6ec6bd7 100644
--- a/libs/gui/include/gui/LayerState.h
+++ b/libs/gui/include/gui/LayerState.h
@@ -201,7 +201,32 @@
     void merge(const layer_state_t& other);
     status_t write(Parcel& output) const;
     status_t read(const Parcel& input);
+    // Compares two layer_state_t structs and returns a set of change flags describing all the
+    // states that are different.
+    uint64_t diff(const layer_state_t& other) const;
     bool hasBufferChanges() const;
+
+    // Changes to the tree structure.
+    static constexpr uint64_t HIERARCHY_CHANGES = layer_state_t::eLayerChanged |
+            layer_state_t::eRelativeLayerChanged | layer_state_t::eReparent |
+            layer_state_t::eBackgroundColorChanged;
+    // Content updates.
+    static constexpr uint64_t CONTENT_CHANGES = layer_state_t::eAlphaChanged |
+            layer_state_t::eTransparentRegionChanged | layer_state_t::eShadowRadiusChanged |
+            layer_state_t::eRenderBorderChanged | layer_state_t::eColorChanged |
+            layer_state_t::eBufferChanged | layer_state_t::eDataspaceChanged |
+            layer_state_t::eApiChanged | layer_state_t::eSidebandStreamChanged |
+            layer_state_t::eColorTransformChanged | layer_state_t::eCornerRadiusChanged |
+            layer_state_t::eBackgroundColorChanged | layer_state_t::eColorSpaceAgnosticChanged |
+            layer_state_t::eBackgroundBlurRadiusChanged | layer_state_t::eBlurRegionsChanged |
+            layer_state_t::eAutoRefreshChanged | layer_state_t::eStretchChanged;
+    // Changes to content or children size.
+    static constexpr uint64_t GEOMETRY_CHANGES = layer_state_t::ePositionChanged |
+            layer_state_t::eMatrixChanged | layer_state_t::eTransparentRegionChanged |
+            layer_state_t::eBufferCropChanged | layer_state_t::eBufferTransformChanged |
+            layer_state_t::eTransformToDisplayInverseChanged | layer_state_t::eCropChanged |
+            layer_state_t::eDestinationFrameChanged;
+
     bool hasValidBuffer() const;
     void sanitize(int32_t permissions);
 
@@ -212,6 +237,11 @@
         float dsdy{0};
         status_t write(Parcel& output) const;
         status_t read(const Parcel& input);
+        inline bool operator==(const matrix22_t& other) const {
+            return std::tie(dsdx, dtdx, dtdy, dsdy) ==
+                    std::tie(other.dsdx, other.dtdx, other.dtdy, other.dsdy);
+        }
+        inline bool operator!=(const matrix22_t& other) const { return !(*this == other); }
     };
     sp<IBinder> surface;
     int32_t layerId;