drm_hwcomposer: Check the composition before sending to frame worker

Before we send a composition to the frame worker and display, run it
through the kernel to test whether it can be put on hardware. If the
kernel rejects the composition, use the squashing code to flatten it
on one layer and send the result to the frame worker.

Bug: 25379136
Test: Tested on smaug, frames were squashed, fun was had

Change-Id: Icac3c034d0eb4c0becbdc0f8ace1de75ab8ae2b8
Signed-off-by: Sean Paul <seanpaul@chromium.org>
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index d492f69..d18c71b 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -934,6 +934,25 @@
   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;
+      }
+      // 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 the kernel rejects
+      // it, squash the frame into one layer and use the squashed composition
+      ret = CommitFrame(composition.get(), true);
+      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;
+        }
+      }
       frame_worker_.QueueFrame(std::move(composition), ret);
       break;
     case DRM_COMPOSITION_TYPE_DPMS:
diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h
index 975de63..541d807 100644
--- a/drmdisplaycompositor.h
+++ b/drmdisplaycompositor.h
@@ -32,7 +32,9 @@
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer.h>
 
-#define DRM_DISPLAY_BUFFERS 2
+// One for the front, one for the back, and one for cases where we need to
+// squash a frame that the hw can't display with hw overlays.
+#define DRM_DISPLAY_BUFFERS 3
 
 namespace android {