drm_hwcomposer: Save the atomic_test result between tests

Previously, we would only test the first frame when the geometry
changed. However, if SF sent us the same composition with different
FBs, we could end up sending invalid frames to the kernel.

This change saves the result of the atomic_test between geometry
changes so we avoid using hw composition for all invalid frames.

Bug: 25866352
Test: Tested on smaug, observed squashes between geometry changes

Change-Id: I3b5d9e83a870481bf2e6869900eafaf0ca66a0d5
Signed-off-by: Sean Paul <seanpaul@chromium.org>
(cherry picked from commit 6c18b3b67e50e12f77f76108363493162ff36340)
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index 95e2333..028a6a3 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -241,6 +241,7 @@
       frame_worker_(this),
       initialized_(false),
       active_(false),
+      use_hw_overlays_(true),
       framebuffer_index_(0),
       squash_framebuffer_index_(0),
       dump_frames_composited_(0),
@@ -921,26 +922,34 @@
 
   switch (composition->type()) {
     case DRM_COMPOSITION_TYPE_FRAME:
-      ret = PrepareFrame(composition.get());
-      if (ret) {
-        ALOGE("Failed to prepare frame for display %d", display_);
-        return ret;
+      if (use_hw_overlays_ || composition->geometry_changed()) {
+        ret = PrepareFrame(composition.get());
+        if (ret) {
+          ALOGE("Failed to prepare frame for display %d", display_);
+          return ret;
+        }
       }
       if (composition->geometry_changed()) {
         // Send the composition to the kernel to ensure we can commit it. This
         // is just a test, it won't actually commit the frame. If rejected,
         // squash the frame into one layer and use the squashed composition
         ret = CommitFrame(composition.get(), true);
-        if (ret) {
+        if (ret)
           ALOGI("Commit test failed, squashing frame for display %d", display_);
-          std::unique_ptr<DrmDisplayComposition> squashed = CreateComposition();
-          ret = SquashFrame(composition.get(), squashed.get());
-          if (!ret) {
-            composition = std::move(squashed);
-          } else {
-            ALOGE("Failed to squash frame for display %d", display_);
-            return ret;
-          }
+        use_hw_overlays_ = !ret;
+      }
+
+      // If use_hw_overlays_ is false, we can't use hardware to composite the
+      // frame. So squash all layers into a single composition and queue that
+      // instead.
+      if (!use_hw_overlays_) {
+        std::unique_ptr<DrmDisplayComposition> squashed = CreateComposition();
+        ret = SquashFrame(composition.get(), squashed.get());
+        if (!ret) {
+          composition = std::move(squashed);
+        } else {
+          ALOGE("Failed to squash frame for display %d", display_);
+          return ret;
         }
       }
       frame_worker_.QueueFrame(std::move(composition), ret);
diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h
index 541d807..e4c3b53 100644
--- a/drmdisplaycompositor.h
+++ b/drmdisplaycompositor.h
@@ -165,6 +165,7 @@
 
   bool initialized_;
   bool active_;
+  bool use_hw_overlays_;
 
   ModeState mode_;