drm_hwcomposer: Use a vector for composition source_layers

Instead of a 1:1 mapping of layer:plane, use a vector to store
source layers for a composition plane. This will allow us to
represent squash compositions more easily by adding all source
layers to the vector.

This should also facilitate hardware which allows multiple fbs per plane.

BUG=b/28117135
TEST=Tested on ryu

Signed-off-by: Sean Paul <seanpaul@chromium.org>
Change-Id: I5d4bfc6e9da022eaab047f948cc874d6a8a25746
diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp
index 2089157..2af9d5a 100644
--- a/drmdisplaycomposition.cpp
+++ b/drmdisplaycomposition.cpp
@@ -113,11 +113,8 @@
 }
 
 int DrmDisplayComposition::AddPlaneDisable(DrmPlane *plane) {
-  composition_planes_.emplace_back(
-      DrmCompositionPlane{.plane = plane,
-                          .crtc = crtc_,
-                          .type = DrmCompositionPlaneType::kDisable,
-                          .source_layer = -1});
+  composition_planes_.emplace_back(DrmCompositionPlaneType::kDisable, plane,
+                                   crtc_);
   return 0;
 }
 
@@ -153,8 +150,7 @@
 }
 
 void DrmDisplayComposition::EmplaceCompositionPlane(
-    DrmCompositionPlaneType type, int source_layer,
-    std::vector<DrmPlane *> *primary_planes,
+    DrmCompositionPlaneType type, std::vector<DrmPlane *> *primary_planes,
     std::vector<DrmPlane *> *overlay_planes) {
   DrmPlane *plane = TakePlane(crtc_, primary_planes, overlay_planes);
   if (plane == NULL) {
@@ -163,11 +159,21 @@
         "remaining");
     return;
   }
-  composition_planes_.emplace_back(
-      DrmCompositionPlane{.plane = plane,
-                          .crtc = crtc_,
-                          .type = type,
-                          .source_layer = source_layer});
+  composition_planes_.emplace_back(type, plane, crtc_);
+}
+
+void DrmDisplayComposition::EmplaceCompositionPlane(
+    size_t source_layer, std::vector<DrmPlane *> *primary_planes,
+    std::vector<DrmPlane *> *overlay_planes) {
+  DrmPlane *plane = TakePlane(crtc_, primary_planes, overlay_planes);
+  if (plane == NULL) {
+    ALOGE(
+        "Failed to add composition plane because there are no planes "
+        "remaining");
+    return;
+  }
+  composition_planes_.emplace_back(DrmCompositionPlaneType::kLayer, plane,
+                                   crtc_, source_layer);
 }
 
 static std::vector<size_t> SetBitsToVector(uint64_t in, size_t *index_map) {
@@ -275,10 +281,12 @@
   }
 
   for (const DrmCompositionPlane &plane : composition_planes_) {
-    if (plane.type == DrmCompositionPlaneType::kLayer) {
-      DrmHwcLayer *source_layer = &layers_[plane.source_layer];
-      comp_layers.emplace(source_layer);
-      pre_comp_layers.erase(source_layer);
+    if (plane.type() == DrmCompositionPlaneType::kLayer) {
+      for (auto i : plane.source_layers()) {
+        DrmHwcLayer *source_layer = &layers_[i];
+        comp_layers.emplace(source_layer);
+        pre_comp_layers.erase(source_layer);
+      }
     }
   }
 
@@ -393,8 +401,7 @@
 
   if (planes_can_use == 0 && layers_remaining.size() > 0) {
     for (auto i : protected_layers)
-      EmplaceCompositionPlane(DrmCompositionPlaneType::kLayer, i,
-                              primary_planes, overlay_planes);
+      EmplaceCompositionPlane(i, primary_planes, overlay_planes);
 
     ALOGE("Protected layers consumed all hardware planes");
     return CreateAndAssignReleaseFences();
@@ -430,15 +437,13 @@
     // that again.
     if (protected_idx < protected_layers.size() &&
         idx > protected_layers[protected_idx]) {
-      EmplaceCompositionPlane(DrmCompositionPlaneType::kLayer,
-                              protected_layers[protected_idx], primary_planes,
+      EmplaceCompositionPlane(protected_layers[protected_idx], primary_planes,
                               overlay_planes);
       protected_idx++;
       continue;
     }
 
-    EmplaceCompositionPlane(DrmCompositionPlaneType::kLayer,
-                            layers_remaining[last_hw_comp_layer],
+    EmplaceCompositionPlane(layers_remaining[last_hw_comp_layer],
                             primary_planes, overlay_planes);
     last_hw_comp_layer++;
     planes_can_use--;
@@ -449,14 +454,13 @@
 
   // Enqueue the rest of the protected layers (if any) between the hw composited
   // overlay layers and the squash/precomp layers.
-  for (int i = protected_idx; i < protected_layers.size(); ++i)
-    EmplaceCompositionPlane(DrmCompositionPlaneType::kLayer,
-                            protected_layers[i], primary_planes,
+  for (size_t i = protected_idx; i < protected_layers.size(); ++i)
+    EmplaceCompositionPlane(protected_layers[i], primary_planes,
                             overlay_planes);
 
   if (layers_remaining.size() > 0) {
-    EmplaceCompositionPlane(DrmCompositionPlaneType::kPrecomp, -1,
-                            primary_planes, overlay_planes);
+    EmplaceCompositionPlane(DrmCompositionPlaneType::kPrecomp, primary_planes,
+                            overlay_planes);
     SeparateLayers(layers_.data(), layers_remaining.data(),
                    layers_remaining.size(), protected_layers.data(),
                    protected_layers.size(), exclude_rects.data(),
@@ -464,8 +468,8 @@
   }
 
   if (use_squash_framebuffer) {
-    EmplaceCompositionPlane(DrmCompositionPlaneType::kSquash, -1,
-                            primary_planes, overlay_planes);
+    EmplaceCompositionPlane(DrmCompositionPlaneType::kSquash, primary_planes,
+                            overlay_planes);
   }
 
   return CreateAndAssignReleaseFences();
@@ -631,9 +635,9 @@
   for (size_t i = 0; i < composition_planes_.size(); i++) {
     const DrmCompositionPlane &comp_plane = composition_planes_[i];
     *out << "      [" << i << "]"
-         << " plane=" << (comp_plane.plane ? comp_plane.plane->id() : -1)
+         << " plane=" << (comp_plane.plane() ? comp_plane.plane()->id() : -1)
          << " type=";
-    switch (comp_plane.type) {
+    switch (comp_plane.type()) {
       case DrmCompositionPlaneType::kDisable:
         *out << "DISABLE";
         break;
@@ -651,7 +655,11 @@
         break;
     }
 
-    *out << " source_layer=" << comp_plane.source_layer << "\n";
+    *out << " source_layer=";
+    for (auto i : comp_plane.source_layers()) {
+      *out << i << " ";
+    }
+    *out << "\n";
   }
 
   *out << "    Squash Regions: count=" << squash_regions_.size() << "\n";
diff --git a/drmdisplaycomposition.h b/drmdisplaycomposition.h
index 0362404..768ccfb 100644
--- a/drmdisplaycomposition.h
+++ b/drmdisplaycomposition.h
@@ -53,11 +53,51 @@
   kSquash,
 };
 
-struct DrmCompositionPlane {
-  DrmCompositionPlaneType type;
-  DrmPlane *plane;
-  DrmCrtc *crtc;
-  int source_layer;
+class DrmCompositionPlane {
+ public:
+  DrmCompositionPlane() = default;
+  DrmCompositionPlane(DrmCompositionPlane &&rhs) = default;
+  DrmCompositionPlane &operator=(DrmCompositionPlane &&other) = default;
+  DrmCompositionPlane(DrmCompositionPlaneType type, DrmPlane *plane,
+                      DrmCrtc *crtc)
+      : type_(type), plane_(plane), crtc_(crtc) {
+  }
+  DrmCompositionPlane(DrmCompositionPlaneType type, DrmPlane *plane,
+                      DrmCrtc *crtc, size_t source_layer)
+      : type_(type),
+        plane_(plane),
+        crtc_(crtc),
+        source_layers_(1, source_layer) {
+  }
+
+  DrmCompositionPlaneType type() const {
+    return type_;
+  }
+
+  DrmPlane *plane() const {
+    return plane_;
+  }
+  void set_plane(DrmPlane *plane) {
+    plane_ = plane;
+  }
+
+  DrmCrtc *crtc() const {
+    return crtc_;
+  }
+
+  std::vector<size_t> &source_layers() {
+    return source_layers_;
+  }
+
+  const std::vector<size_t> &source_layers() const {
+    return source_layers_;
+  }
+
+ private:
+  DrmCompositionPlaneType type_ = DrmCompositionPlaneType::kDisable;
+  DrmPlane *plane_ = NULL;
+  DrmCrtc *crtc_ = NULL;
+  std::vector<size_t> source_layers_;
 };
 
 class DrmDisplayComposition {
@@ -139,7 +179,10 @@
 
   int IncreaseTimelineToPoint(int point);
 
-  void EmplaceCompositionPlane(DrmCompositionPlaneType type, int source_layer,
+  void EmplaceCompositionPlane(DrmCompositionPlaneType type,
+                               std::vector<DrmPlane *> *primary_planes,
+                               std::vector<DrmPlane *> *overlay_planes);
+  void EmplaceCompositionPlane(size_t source_layer,
                                std::vector<DrmPlane *> *primary_planes,
                                std::vector<DrmPlane *> *overlay_planes);
   int CreateAndAssignReleaseFences();
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index c9cf40c..fc040dc 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -172,7 +172,7 @@
 static bool UsesSquash(const std::vector<DrmCompositionPlane> &comp_planes) {
   return std::any_of(comp_planes.begin(), comp_planes.end(),
                      [](const DrmCompositionPlane &plane) {
-    return plane.type == DrmCompositionPlaneType::kSquash;
+    return plane.type() == DrmCompositionPlaneType::kSquash;
   });
 }
 
@@ -488,7 +488,7 @@
   std::vector<DrmCompositionPlane> &comp_planes =
       display_comp->composition_planes();
   for (DrmCompositionPlane &comp_plane : comp_planes) {
-    DrmPlane *plane = comp_plane.plane;
+    DrmPlane *plane = comp_plane.plane();
     ret = drmModeAtomicAddProperty(pset, plane->id(),
                                    plane->crtc_property().id(), 0) < 0 ||
           drmModeAtomicAddProperty(pset, plane->id(), plane->fb_property().id(),
@@ -572,9 +572,13 @@
   }
 
   for (DrmCompositionPlane &comp_plane : comp_planes) {
-    switch (comp_plane.type) {
+    std::vector<size_t> &source_layers = comp_plane.source_layers();
+    switch (comp_plane.type()) {
       case DrmCompositionPlaneType::kSquash:
-        comp_plane.source_layer = squash_layer_index;
+        if (source_layers.size())
+          ALOGE("Squash source_layers is expected to be empty (%zu/%d)",
+                source_layers[0], squash_layer_index);
+        source_layers.push_back(squash_layer_index);
         break;
       case DrmCompositionPlaneType::kPrecomp:
         if (!do_pre_comp) {
@@ -583,7 +587,9 @@
               "regions");
           return -EINVAL;
         }
-        comp_plane.source_layer = pre_comp_layer_index;
+        // Replace source_layers with the output of the precomposite
+        source_layers.clear();
+        source_layers.push_back(pre_comp_layer_index);
         break;
       default:
         break;
@@ -636,8 +642,9 @@
   }
 
   for (DrmCompositionPlane &comp_plane : comp_planes) {
-    DrmPlane *plane = comp_plane.plane;
-    DrmCrtc *crtc = comp_plane.crtc;
+    DrmPlane *plane = comp_plane.plane();
+    DrmCrtc *crtc = comp_plane.crtc();
+    std::vector<size_t> &source_layers = comp_plane.source_layers();
 
     int fb_id = -1;
     DrmHwcRect<int> display_frame;
@@ -645,14 +652,19 @@
     uint64_t rotation = 0;
     uint64_t alpha = 0xFF;
 
-    if (comp_plane.type != DrmCompositionPlaneType::kDisable) {
-      if (comp_plane.source_layer < 0 ||
-          static_cast<size_t>(comp_plane.source_layer) >= layers.size()) {
-        ALOGE("Source layer index %d out of bounds %zu type=%d",
-              comp_plane.source_layer, layers.size(), comp_plane.type);
+    if (comp_plane.type() != DrmCompositionPlaneType::kDisable) {
+      if (source_layers.size() > 1) {
+        ALOGE("Can't handle more than one source layer sz=%zu type=%d",
+              source_layers.size(), comp_plane.type());
+        continue;
+      }
+
+      if (source_layers.empty() || source_layers.front() >= layers.size()) {
+        ALOGE("Source layer index %zu out of bounds %zu type=%d",
+              source_layers.front(), layers.size(), comp_plane.type());
         break;
       }
-      DrmHwcLayer &layer = layers[comp_plane.source_layer];
+      DrmHwcLayer &layer = layers[source_layers.front()];
       if (!test_only && layer.acquire_fence.get() >= 0) {
         int acquire_fence = layer.acquire_fence.get();
         int total_fence_timeout = 0;
@@ -1029,7 +1041,7 @@
   // Make sure there is more than one layer to squash.
   size_t src_planes_with_layer = std::count_if(
       src_planes.begin(), src_planes.end(), [](DrmCompositionPlane &p) {
-        return p.type == DrmCompositionPlaneType::kLayer;
+        return p.type() == DrmCompositionPlaneType::kLayer;
       });
   if (src_planes_with_layer <= 1)
     return -EALREADY;
@@ -1047,35 +1059,36 @@
   std::vector<DrmHwcLayer> dst_layers;
   for (DrmCompositionPlane &comp_plane : src_planes) {
     // Composition planes without DRM planes should never happen
-    if (comp_plane.plane == NULL) {
+    if (comp_plane.plane() == NULL) {
       ALOGE("Skipping squash all because of NULL plane");
       ret = -EINVAL;
       goto move_layers_back;
     }
 
-    if (comp_plane.type == DrmCompositionPlaneType::kDisable ||
-        comp_plane.source_layer < 0)
+    if (comp_plane.type() == DrmCompositionPlaneType::kDisable)
       continue;
 
-    DrmHwcLayer &layer = src_layers[comp_plane.source_layer];
+    for (auto i : comp_plane.source_layers()) {
+      DrmHwcLayer &layer = src_layers[i];
 
-    // Squashing protected layers is impossible.
-    if (layer.protected_usage()) {
-      ret = -ENOTSUP;
-      goto move_layers_back;
+      // Squashing protected layers is impossible.
+      if (layer.protected_usage()) {
+        ret = -ENOTSUP;
+        goto move_layers_back;
+      }
+
+      // The OutputFds point to freed memory after hwc_set returns. They are
+      // returned to the default to prevent DrmDisplayComposition::Plan from
+      // filling the OutputFds.
+      layer.release_fence = OutputFd();
+      dst_layers.emplace_back(std::move(layer));
     }
 
-    // The OutputFds point to freed memory after hwc_set returns. They are
-    // returned to the default to prevent DrmDisplayComposition::Plan from
-    // filling the OutputFds.
-    layer.release_fence = OutputFd();
-    dst_layers.emplace_back(std::move(layer));
-
-    if (comp_plane.plane->type() == DRM_PLANE_TYPE_PRIMARY &&
+    if (comp_plane.plane()->type() == DRM_PLANE_TYPE_PRIMARY &&
         primary_planes.size() == 0)
-      primary_planes.push_back(comp_plane.plane);
+      primary_planes.push_back(comp_plane.plane());
     else
-      dst->AddPlaneDisable(comp_plane.plane);
+      dst->AddPlaneDisable(comp_plane.plane());
   }
 
   ret = dst->SetLayers(dst_layers.data(), dst_layers.size(), false);
@@ -1100,9 +1113,14 @@
   pre_comp_layer_index = dst->layers().size() - 1;
   framebuffer_index_ = (framebuffer_index_ + 1) % DRM_DISPLAY_BUFFERS;
 
-  for (DrmCompositionPlane &plane : dst->composition_planes())
-    if (plane.type == DrmCompositionPlaneType::kPrecomp)
-      plane.source_layer = pre_comp_layer_index;
+  for (DrmCompositionPlane &plane : dst->composition_planes()) {
+    if (plane.type() == DrmCompositionPlaneType::kPrecomp) {
+      // Replace source_layers with the output of the precomposite
+      plane.source_layers().clear();
+      plane.source_layers().push_back(pre_comp_layer_index);
+      break;
+    }
+  }
 
   return 0;
 
@@ -1110,10 +1128,13 @@
 // composition.
 move_layers_back:
   for (size_t plane_index = 0;
-       plane_index < src_planes.size() && plane_index < dst_layers.size();
-       plane_index++) {
-    size_t source_layer_index = src_planes[plane_index].source_layer;
-    src_layers[source_layer_index] = std::move(dst_layers[plane_index]);
+       plane_index < src_planes.size() && plane_index < dst_layers.size();) {
+    if (src_planes[plane_index].source_layers().empty()) {
+      plane_index++;
+      continue;
+    }
+    for (auto i : src_planes[plane_index].source_layers())
+      src_layers[i] = std::move(dst_layers[plane_index++]);
   }
 
   return ret;