Merge "drm_hwcomposer: fix logic error in premult blending" into mnc-dr-dev
diff --git a/autogl.h b/autogl.h
index 5eeca85..fc77fb0 100644
--- a/autogl.h
+++ b/autogl.h
@@ -52,8 +52,7 @@
 AUTO_GL_TYPE(AutoGLProgram, GLint, 0, glDeleteProgram(p))
 
 struct AutoEGLDisplayImage {
-  AutoEGLDisplayImage() : display_(EGL_NO_DISPLAY), image_(EGL_NO_IMAGE_KHR) {
-  }
+  AutoEGLDisplayImage() = default;
 
   AutoEGLDisplayImage(EGLDisplay display, EGLImageKHR image)
       : display_(display), image_(image) {
@@ -98,8 +97,8 @@
   }
 
  private:
-  EGLDisplay display_;
-  EGLImageKHR image_;
+  EGLDisplay display_ = EGL_NO_DISPLAY;
+  EGLImageKHR image_ = EGL_NO_IMAGE_KHR;
 };
 
 struct AutoEGLImageAndGLTexture {
diff --git a/drm_hwcomposer.h b/drm_hwcomposer.h
index fdf389b..1490438 100644
--- a/drm_hwcomposer.h
+++ b/drm_hwcomposer.h
@@ -175,7 +175,7 @@
     return importer_ != NULL;
   }
 
-  hwc_drm_bo *operator->();
+  const hwc_drm_bo *operator->() const;
 
   void Clear();
 
@@ -257,11 +257,12 @@
   UniqueFd acquire_fence;
   OutputFd release_fence;
 
-  DrmHwcLayer() = default;
-  DrmHwcLayer(DrmHwcLayer &&rhs) = default;
-
   int InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer,
                        const gralloc_module_t *gralloc);
+
+  buffer_handle_t get_usable_handle() const {
+    return handle.get() != NULL ? handle.get() : sf_handle;
+  }
 };
 
 struct DrmHwcDisplayContents {
diff --git a/drmcomposition.cpp b/drmcomposition.cpp
index 55fa00c..4b293ee 100644
--- a/drmcomposition.cpp
+++ b/drmcomposition.cpp
@@ -58,10 +58,9 @@
     // If the display hasn't been modeset yet, this will be NULL
     DrmCrtc *crtc = drm_->GetCrtcForDisplay(display);
 
-    int ret = composition_map_[(*iter)->display()]->Init(drm_, crtc, importer_,
-                                                         frame_no);
+    int ret = composition_map_[display]->Init(drm_, crtc, importer_, frame_no);
     if (ret) {
-      ALOGE("Failed to init display composition for %d", (*iter)->display());
+      ALOGE("Failed to init display composition for %d", display);
       return ret;
     }
   }
diff --git a/drmcompositor.cpp b/drmcompositor.cpp
index ad4cf88..b486d7b 100644
--- a/drmcompositor.cpp
+++ b/drmcompositor.cpp
@@ -76,7 +76,7 @@
     int ret = compositor_map_[display].QueueComposition(
         composition->TakeDisplayComposition(display));
     if (ret) {
-      ALOGE("Failed to queue composition for display %d", display);
+      ALOGE("Failed to queue composition for display %d (%d)", display, ret);
       return ret;
     }
   }
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index 5676f1d..3b3deef 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -300,7 +300,12 @@
   for (DrmCompositionLayer &layer : *layers) {
     int acquire_fence = layer.acquire_fence.get();
     if (acquire_fence >= 0) {
-      ret = sync_wait(acquire_fence, kAcquireWaitTimeoutMs);
+      for (int i = 0; i < kAcquireWaitTries; ++i) {
+        ret = sync_wait(acquire_fence, kAcquireWaitTimeoutMs);
+        if (ret)
+          ALOGW("Acquire fence %d wait %d failed (%d). Total time %d",
+                acquire_fence, i, ret, (i + 1) * kAcquireWaitTimeoutMs);
+      }
       if (ret) {
         ALOGE("Failed to wait for acquire %d/%d", acquire_fence, ret);
         drmModePropertySetFree(pset);
diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h
index 0f3a12f..419960c 100644
--- a/drmdisplaycompositor.h
+++ b/drmdisplaycompositor.h
@@ -51,9 +51,10 @@
  private:
   DrmDisplayCompositor(const DrmDisplayCompositor &) = delete;
 
-  // Set to 83ms (~12fps) which is somewhere between a reasonable amount of
-  // time to wait for a long render and a small enough delay to limit jank.
-  static const int kAcquireWaitTimeoutMs = 83;
+  // We'll wait for acquire fences to fire for kAcquireWaitTimeoutMs,
+  // kAcquireWaitTries times, logging a warning in between.
+  static const int kAcquireWaitTries = 5;
+  static const int kAcquireWaitTimeoutMs = 100;
 
   int ApplyPreComposite(DrmDisplayComposition *display_comp);
   int ApplyFrame(DrmDisplayComposition *display_comp);
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index a7c9e43..6a0f4cd 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -191,9 +191,9 @@
   return *this;
 }
 
-hwc_drm_bo *DrmHwcBuffer::operator->() {
+const hwc_drm_bo *DrmHwcBuffer::operator->() const {
   if (importer_ == NULL) {
-    ALOGE("Access of none existent BO");
+    ALOGE("Access of non-existent BO");
     exit(1);
     return NULL;
   }
@@ -264,16 +264,15 @@
 int DrmHwcLayer::InitFromHwcLayer(hwc_layer_1_t *sf_layer, Importer *importer,
                                   const gralloc_module_t *gralloc) {
   sf_handle = sf_layer->handle;
-  int ret = buffer.ImportBuffer(sf_layer->handle, importer);
-  if (ret)
-    return ret;
-
-  ret = handle.CopyBufferHandle(sf_layer->handle, gralloc);
-  if (ret)
-    return ret;
-
   alpha = sf_layer->planeAlpha;
 
+  source_crop = DrmHwcRect<float>(
+      sf_layer->sourceCropf.left, sf_layer->sourceCropf.top,
+      sf_layer->sourceCropf.right, sf_layer->sourceCropf.bottom);
+  display_frame = DrmHwcRect<int>(
+      sf_layer->displayFrame.left, sf_layer->displayFrame.top,
+      sf_layer->displayFrame.right, sf_layer->displayFrame.bottom);
+
   switch (sf_layer->transform) {
     case 0:
       transform = DrmHwcTransform::kIdentity;
@@ -313,12 +312,13 @@
       return -EINVAL;
   }
 
-  source_crop = DrmHwcRect<float>(
-      sf_layer->sourceCropf.left, sf_layer->sourceCropf.top,
-      sf_layer->sourceCropf.right, sf_layer->sourceCropf.bottom);
-  display_frame = DrmHwcRect<int>(
-      sf_layer->displayFrame.left, sf_layer->displayFrame.top,
-      sf_layer->displayFrame.right, sf_layer->displayFrame.bottom);
+  int ret = buffer.ImportBuffer(sf_layer->handle, importer);
+  if (ret)
+    return ret;
+
+  ret = handle.CopyBufferHandle(sf_layer->handle, gralloc);
+  if (ret)
+    return ret;
 
   return 0;
 }
@@ -501,13 +501,18 @@
 
     layers_map.emplace_back();
     DrmCompositionDisplayLayersMap &map = layers_map.back();
+    map.display = i;
     std::vector<size_t> &indices_to_composite = layers_indices[i];
     for (size_t j : indices_to_composite) {
       hwc_layer_1_t *sf_layer = &dc->hwLayers[j];
 
       DrmHwcLayer &layer = display_contents.layers[j];
 
-      layer.InitFromHwcLayer(sf_layer, ctx->importer, ctx->gralloc);
+      ret = layer.InitFromHwcLayer(sf_layer, ctx->importer, ctx->gralloc);
+      if (ret) {
+        ALOGE("Failed to init composition from layer %d", ret);
+        return ret;
+      }
       map.layers.emplace_back(std::move(layer));
     }
   }
diff --git a/seperate_rects.cpp b/seperate_rects.cpp
index bdf07bc..06fbe39 100644
--- a/seperate_rects.cpp
+++ b/seperate_rects.cpp
@@ -71,8 +71,8 @@
 }
 
 template <typename TNum, typename TId>
-void seperate_rects(const std::vector<Rect<TNum> > &in,
-                    std::vector<RectSet<TId, TNum> > *out) {
+void seperate_rects(const std::vector<Rect<TNum>> &in,
+                    std::vector<RectSet<TId, TNum>> *out) {
   // Overview:
   // This algorithm is a line sweep algorithm that travels from left to right.
   // The sweep stops at each vertical edge of each input rectangle in sorted
@@ -91,8 +91,8 @@
 
   // Events are when the sweep line encounters the starting or ending edge of
   // any input rectangle.
-  std::set<SweepEvent<TId, TNum> > sweep_h_events;  // Left or right bounds
-  std::set<SweepEvent<TId, TNum> > sweep_v_events;  // Top or bottom bounds
+  std::set<SweepEvent<TId, TNum>> sweep_h_events;  // Left or right bounds
+  std::set<SweepEvent<TId, TNum>> sweep_v_events;  // Top or bottom bounds
 
   // A started rect is a rectangle whose left, top, bottom edge, and set of
   // rectangle IDs is known. The key of this map includes all that information
@@ -102,7 +102,7 @@
 
   // This is cleared after every event. Its declaration is here to avoid
   // reallocating a vector and its buffers every event.
-  std::vector<std::pair<TNum, IdSet<TId> > > active_regions;
+  std::vector<std::pair<TNum, IdSet<TId>>> active_regions;
 
   // This pass will add rectangle start and end events to be triggered as the
   // algorithm sweeps from left to right.
@@ -120,7 +120,7 @@
     sweep_h_events.insert(evt);
   }
 
-  for (typename std::set<SweepEvent<TId, TNum> >::iterator it =
+  for (typename std::set<SweepEvent<TId, TNum>>::iterator it =
            sweep_h_events.begin();
        it != sweep_h_events.end(); ++it) {
     const SweepEvent<TId, TNum> &h_evt = *it;
@@ -142,14 +142,14 @@
     } else {
       v_evt.type = START;
       v_evt.y = rect.top;
-      typename std::set<SweepEvent<TId, TNum> >::iterator start_it =
+      typename std::set<SweepEvent<TId, TNum>>::iterator start_it =
           sweep_v_events.find(v_evt);
       assert(start_it != sweep_v_events.end());
       sweep_v_events.erase(start_it);
 
       v_evt.type = END;
       v_evt.y = rect.bottom;
-      typename std::set<SweepEvent<TId, TNum> >::iterator end_it =
+      typename std::set<SweepEvent<TId, TNum>>::iterator end_it =
           sweep_v_events.find(v_evt);
       assert(end_it != sweep_v_events.end());
       sweep_v_events.erase(end_it);
@@ -159,7 +159,7 @@
     // with the current sweep line. If so, we want to continue marking up the
     // sweep line before actually processing the rectangles the sweep line is
     // intersecting.
-    typename std::set<SweepEvent<TId, TNum> >::iterator next_it = it;
+    typename std::set<SweepEvent<TId, TNum>>::iterator next_it = it;
     ++next_it;
     if (next_it != sweep_h_events.end()) {
       if (next_it->x == h_evt.x) {
@@ -179,7 +179,7 @@
     // 5), active_regions will be [({ 0 }, 3), {}, 5].
     active_regions.clear();
     IdSet<TId> active_set;
-    for (typename std::set<SweepEvent<TId, TNum> >::iterator it =
+    for (typename std::set<SweepEvent<TId, TNum>>::iterator it =
              sweep_v_events.begin();
          it != sweep_v_events.end(); ++it) {
       const SweepEvent<TId, TNum> &v_evt = *it;
@@ -199,7 +199,7 @@
 
 #ifdef RECTS_DEBUG
     std::cout << "x:" << h_evt.x;
-    for (std::vector<std::pair<TNum, IdSet> >::iterator it =
+    for (std::vector<std::pair<TNum, IdSet>>::iterator it =
              active_regions.begin();
          it != active_regions.end(); ++it) {
       std::cout << " " << it->first << "(" << it->second << ")"
@@ -226,7 +226,7 @@
     // case, we have a new rectangle, and the already existing started rectangle
     // will not be marked as seen ("true" in the std::pair) and will get ended
     // by the for loop after this one. This is as intended.
-    for (typename std::vector<std::pair<TNum, IdSet<TId> > >::iterator it =
+    for (typename std::vector<std::pair<TNum, IdSet<TId>>>::iterator it =
              active_regions.begin();
          it != active_regions.end(); ++it) {
       IdSet<TId> region_set = it->second;
@@ -237,8 +237,7 @@
       // An important property of active_regions is that each region where a set
       // of rectangles applies is bounded at the bottom by the next (in the
       // vector) region's starting y-coordinate.
-      typename std::vector<std::pair<TNum, IdSet<TId> > >::iterator next_it =
-          it;
+      typename std::vector<std::pair<TNum, IdSet<TId>>>::iterator next_it = it;
       ++next_it;
       assert(next_it != active_regions.end());
 
@@ -300,8 +299,13 @@
   }
 }
 
-void seperate_frects_64(const std::vector<Rect<float> > &in,
-                        std::vector<RectSet<uint64_t, float> > *out) {
+void seperate_frects_64(const std::vector<Rect<float>> &in,
+                        std::vector<RectSet<uint64_t, float>> *out) {
+  seperate_rects(in, out);
+}
+
+void seperate_rects_64(const std::vector<Rect<int>> &in,
+                       std::vector<RectSet<uint64_t, int>> *out) {
   seperate_rects(in, out);
 }
 
diff --git a/seperate_rects.h b/seperate_rects.h
index 540a5e8..1e0a267 100644
--- a/seperate_rects.h
+++ b/seperate_rects.h
@@ -64,6 +64,18 @@
 
     return true;
   }
+
+  TFloat width() const {
+    return bounds[2] - bounds[0];
+  }
+
+  TFloat height() const {
+    return bounds[3] - bounds[1];
+  }
+
+  TFloat area() const {
+    return width() * height();
+  }
 };
 
 template <typename TUInt>
@@ -140,8 +152,10 @@
 // rectangle indices that overlap the output rectangle encoded in a bitset. For
 // example, an output rectangle that overlaps input rectangles in[0], in[1], and
 // in[4], the bitset would be (ommitting leading zeroes) 10011.
-void seperate_frects_64(const std::vector<Rect<float> > &in,
-                        std::vector<RectSet<uint64_t, float> > *out);
+void seperate_frects_64(const std::vector<Rect<float>> &in,
+                        std::vector<RectSet<uint64_t, float>> *out);
+void seperate_rects_64(const std::vector<Rect<int>> &in,
+                       std::vector<RectSet<uint64_t, int>> *out);
 
 }  // namespace seperate_rects