DO NOT MERGE: drm_hwcomposer: Use a vector for composition source_layers
am: 9b70717071

* commit '9b70717071da6b5c098d2363a350d1f0f2333423':
  DO NOT MERGE: drm_hwcomposer: Use a vector for composition source_layers

Change-Id: Idf79f87ca6b866c115a7f32c096f5d8946decde1
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;