Merge "drm_hwcomposer: Clean up error conditions"
diff --git a/drmeventlistener.cpp b/drmeventlistener.cpp
index 1880549..0514aa6 100644
--- a/drmeventlistener.cpp
+++ b/drmeventlistener.cpp
@@ -124,7 +124,7 @@
 
   if (FD_ISSET(drm_->fd(), &fds_)) {
     drmEventContext event_context = {
-        .version = DRM_EVENT_CONTEXT_VERSION,
+        .version = 2,
         .vblank_handler = NULL,
         .page_flip_handler = DrmEventListener::FlipHandler};
     drmHandleEvent(drm_->fd(), &event_context);
diff --git a/platform.cpp b/platform.cpp
index 105d8f7..e920872 100644
--- a/platform.cpp
+++ b/platform.cpp
@@ -140,6 +140,34 @@
   return 0;
 }
 
+int PlanStagePrecomp::ProvisionPlanes(
+    std::vector<DrmCompositionPlane> *composition,
+    std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc,
+    std::vector<DrmPlane *> *planes) {
+  DrmCompositionPlane *precomp = GetPrecomp(composition);
+  if (!precomp || precomp->source_layers().empty())
+    return 0;
+
+  // Find lowest zorder out of precomp layers
+  size_t precomp_zorder = *std::min_element(
+      precomp->source_layers().begin(), precomp->source_layers().end(),
+      [](size_t a, size_t b) { return a < b; });
+
+  // if there are any remaining layers on top of any of the precomp layers,
+  // add them to precomp to avoid blending issues since precomp is always at
+  // highest zorder
+  for (auto i = layers.begin(); i != layers.end();) {
+    if (i->first < precomp_zorder) {
+      i++;
+      continue;
+    }
+    precomp->source_layers().emplace_back(i->first);
+    i = layers.erase(i);
+  }
+
+  return 0;
+}
+
 int PlanStageGreedy::ProvisionPlanes(
     std::vector<DrmCompositionPlane> *composition,
     std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc,
diff --git a/platform.h b/platform.h
index da6b7cb..70e5e81 100644
--- a/platform.h
+++ b/platform.h
@@ -152,6 +152,18 @@
                       std::vector<DrmPlane *> *planes);
 };
 
+// This plan stage provisions the precomp plane with any remaining layers that
+// are on top of the current precomp layers. This stage should be included in
+// all platforms before loosely allocating layers (i.e. PlanStageGreedy) if
+// any previous plan could have modified the precomp plane layers
+// (ex. PlanStageProtected).
+class PlanStagePrecomp : public Planner::PlanStage {
+ public:
+  int ProvisionPlanes(std::vector<DrmCompositionPlane> *composition,
+                      std::map<size_t, DrmHwcLayer *> &layers, DrmCrtc *crtc,
+                      std::vector<DrmPlane *> *planes);
+};
+
 // This plan stage places as many layers on dedicated planes as possible (first
 // come first serve), and then sticks the rest in a precomposition plane (if
 // needed).
diff --git a/platformnv.cpp b/platformnv.cpp
index db7ee36..084d4f0 100644
--- a/platformnv.cpp
+++ b/platformnv.cpp
@@ -190,6 +190,7 @@
   std::unique_ptr<Planner> planner(new Planner);
   planner->AddStage<PlanStageProtectedRotated>();
   planner->AddStage<PlanStageProtected>();
+  planner->AddStage<PlanStagePrecomp>();
   planner->AddStage<PlanStageGreedy>();
   return planner;
 }