drm_hwcomposer: introduce QueueWorker

Current method to queue work such as display compositions relies on
spinning the CPU until there is space in the queue. This is inefficient
for the time in which the queue happens to fill up.

Introduce a new QueueWorker class to simplify queueing work and handle
blocking for available space more efficiently.

Change-Id: Ida7aa612931700a56ecae3efc7ddd1c86efec699
diff --git a/drmdisplaycompositor.h b/drmdisplaycompositor.h
index 9487cac..961fe72 100644
--- a/drmdisplaycompositor.h
+++ b/drmdisplaycompositor.h
@@ -17,13 +17,13 @@
 #ifndef ANDROID_DRM_DISPLAY_COMPOSITOR_H_
 #define ANDROID_DRM_DISPLAY_COMPOSITOR_H_
 
-#include "drmhwcomposer.h"
 #include "drmcomposition.h"
-#include "drmcompositorworker.h"
 #include "drmframebuffer.h"
+#include "drmhwcomposer.h"
+#include "queue_worker.h"
 #include "separate_rects.h"
 
-#include <pthread.h>
+#include <chrono>
 #include <memory>
 #include <queue>
 #include <sstream>
@@ -81,7 +81,7 @@
   std::vector<Region> regions_;
 };
 
-class DrmDisplayCompositor {
+class DrmDisplayCompositor : public QueueWorker<DrmDisplayComposition> {
  public:
   DrmDisplayCompositor();
   ~DrmDisplayCompositor();
@@ -90,39 +90,42 @@
 
   std::unique_ptr<DrmDisplayComposition> CreateComposition() const;
   int QueueComposition(std::unique_ptr<DrmDisplayComposition> composition);
-  int Composite();
+  void ProcessWork(std::unique_ptr<DrmDisplayComposition> composition);
+  void ProcessIdle();
   int SquashAll();
   void Dump(std::ostringstream *out) const;
 
   std::tuple<uint32_t, uint32_t, int> GetActiveModeResolution();
 
-  bool HaveQueuedComposites() const;
-
   SquashState *squash_state() {
     return &squash_state_;
   }
 
  private:
   struct FrameState {
+    FrameState(std::unique_ptr<DrmDisplayComposition> composition, int status)
+        : composition(std::move(composition)), status(status) {
+    }
+
     std::unique_ptr<DrmDisplayComposition> composition;
     int status = 0;
   };
 
-  class FrameWorker : public Worker {
+  class FrameWorker : public QueueWorker<FrameState> {
    public:
     FrameWorker(DrmDisplayCompositor *compositor);
-    ~FrameWorker() override;
 
     int Init();
     void QueueFrame(std::unique_ptr<DrmDisplayComposition> composition,
                     int status);
 
+    mutable uint64_t max_duration_us;
+
    protected:
-    void Routine() override;
+    void ProcessWork(std::unique_ptr<FrameState> frame);
 
    private:
     DrmDisplayCompositor *compositor_;
-    std::queue<FrameState> frame_queue_;
   };
 
   struct ModeState {
@@ -158,13 +161,10 @@
   DrmResources *drm_;
   int display_;
 
-  DrmCompositorWorker worker_;
   FrameWorker frame_worker_;
 
-  std::queue<std::unique_ptr<DrmDisplayComposition>> composite_queue_;
   std::unique_ptr<DrmDisplayComposition> active_composition_;
 
-  bool initialized_;
   bool active_;
   bool use_hw_overlays_;
 
@@ -179,12 +179,13 @@
   DrmFramebuffer squash_framebuffers_[2];
 
   // mutable since we need to acquire in HaveQueuedComposites
-  mutable pthread_mutex_t lock_;
+  mutable std::mutex mutex_;
 
   // State tracking progress since our last Dump(). These are mutable since
   // we need to reset them on every Dump() call.
   mutable uint64_t dump_frames_composited_;
   mutable uint64_t dump_last_timestamp_ns_;
+  mutable uint64_t max_duration_us;
 };
 }