drm_hwcomposer: Add z order support

Currently, the planner just pops the first available drm plane and if
that can't be used for the DrmHwcLayer it just returns error.

This proposes a slighlty smarter way to do that by trying to see if
any of the DrmPlane can be used for the DrmHwcLayer in question.

More, if the drm_plane doesn't have a fix zorder then we could re-add
him to the list of unused planes, so it could be used for hosting
other less demanding DrmHwcLayers.

Signed-off-by: Alexandru Gheorghe <alexandru-cosmin.gheorghe@arm.com>
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index cd6d4b2..a1ccdc7 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -359,6 +359,17 @@
         }
       }
 
+      if (plane->zpos_property().id() && !plane->zpos_property().immutable()) {
+        ret = drmModeAtomicAddProperty(pset, plane->id(),
+                                       plane->zpos_property().id(),
+                                       source_layers.front()) < 0;
+        if (ret) {
+          ALOGE("Failed to add zpos property %d to plane %d",
+                plane->zpos_property().id(), plane->id());
+          break;
+        }
+      }
+
       rotation = 0;
       if (layer.transform & DrmHwcTransform::kFlipH)
         rotation |= DRM_MODE_REFLECT_X;
diff --git a/drmplane.cpp b/drmplane.cpp
index 6747621..35f91b4 100644
--- a/drmplane.cpp
+++ b/drmplane.cpp
@@ -118,6 +118,10 @@
     return ret;
   }
 
+  ret = drm_->GetPlaneProperty(*this, "zpos", &zpos_property_);
+  if (ret)
+    ALOGE("Could not get zpos property for plane %u", id());
+
   ret = drm_->GetPlaneProperty(*this, "rotation", &rotation_property_);
   if (ret)
     ALOGE("Could not get rotation property");
@@ -189,6 +193,10 @@
   return src_h_property_;
 }
 
+const DrmProperty &DrmPlane::zpos_property() const {
+  return zpos_property_;
+}
+
 const DrmProperty &DrmPlane::rotation_property() const {
   return rotation_property_;
 }
diff --git a/drmplane.h b/drmplane.h
index b7607ff..43e0e8a 100644
--- a/drmplane.h
+++ b/drmplane.h
@@ -52,6 +52,7 @@
   const DrmProperty &src_y_property() const;
   const DrmProperty &src_w_property() const;
   const DrmProperty &src_h_property() const;
+  const DrmProperty &zpos_property() const;
   const DrmProperty &rotation_property() const;
   const DrmProperty &alpha_property() const;
   const DrmProperty &blend_property() const;
@@ -75,6 +76,7 @@
   DrmProperty src_y_property_;
   DrmProperty src_w_property_;
   DrmProperty src_h_property_;
+  DrmProperty zpos_property_;
   DrmProperty rotation_property_;
   DrmProperty alpha_property_;
   DrmProperty blend_property_;
diff --git a/drmproperty.cpp b/drmproperty.cpp
index dcab05e..9faa37e 100644
--- a/drmproperty.cpp
+++ b/drmproperty.cpp
@@ -100,6 +100,10 @@
   }
 }
 
+bool DrmProperty::immutable() const {
+  return id_ && (flags_ & DRM_MODE_PROP_IMMUTABLE);
+}
+
 std::tuple<uint64_t, int> DrmProperty::GetEnumValueWithName(
     std::string name) const {
   for (auto it : enums_) {
diff --git a/drmproperty.h b/drmproperty.h
index 5e358be..f1328fe 100644
--- a/drmproperty.h
+++ b/drmproperty.h
@@ -46,6 +46,7 @@
   std::string name() const;
 
   int value(uint64_t *value) const;
+  bool immutable() const;
 
  private:
   class DrmPropertyEnum {
diff --git a/platform.h b/platform.h
index 6c12fe9..547a297 100644
--- a/platform.h
+++ b/platform.h
@@ -81,16 +81,24 @@
                        DrmCompositionPlane::Type type, DrmCrtc *crtc,
                        std::pair<size_t, DrmHwcLayer *> layer) {
       DrmPlane *plane = PopPlane(planes);
-      int ret;
-      if (!plane)
-        return -ENOENT;
+      std::vector<DrmPlane *> unused_planes;
+      int ret = -ENOENT;
+      while (plane) {
+        ret = ValidatePlane(plane, layer.second);
+        if (!ret)
+          break;
+        if (!plane->zpos_property().immutable())
+          unused_planes.push_back(plane);
+        plane = PopPlane(planes);
+      }
 
-      ret = ValidatePlane(plane, layer.second);
-      if (ret)
-        return -EINVAL;
+      if (!ret) {
+        composition->emplace_back(type, plane, crtc, layer.first);
+        planes->insert(planes->begin(), unused_planes.begin(),
+                       unused_planes.end());
+      }
 
-      composition->emplace_back(type, plane, crtc, layer.first);
-      return 0;
+      return ret;
     }
   };