Merge "drm_hwcomposer: Use HW overlay planes" into mnc-dev
diff --git a/Android.mk b/Android.mk
index 8024900..9fc17fa 100644
--- a/Android.mk
+++ b/Android.mk
@@ -26,7 +26,6 @@
 	libutils \
 
 LOCAL_C_INCLUDES := \
-	external/drm_gralloc \
 	external/libdrm \
 	external/libdrm/include/drm \
 	system/core/include/utils \
@@ -42,18 +41,19 @@
 	drmconnector.cpp \
 	drmcrtc.cpp \
 	drmencoder.cpp \
-        drmgenericimporter.cpp \
 	drmmode.cpp \
 	drmplane.cpp \
 	drmproperty.cpp \
 	hwcomposer.cpp \
-        nvimporter.cpp \
 	vsyncworker.cpp \
 	worker.cpp
 
 ifeq ($(strip $(BOARD_DRM_HWCOMPOSER_BUFFER_IMPORTER)),nvidia-gralloc)
+LOCAL_SRC_FILES += nvimporter.cpp
 LOCAL_CPPFLAGS += -DUSE_NVIDIA_IMPORTER
 else
+LOCAL_C_INCLUDES += external/drm_gralloc
+LOCAL_SRC_FILES += drmgenericimporter.cpp
 LOCAL_CPPFLAGS += -DUSE_DRM_GENERIC_IMPORTER
 endif
 
diff --git a/compositor.cpp b/compositor.cpp
index 20f860f..3f85dc7 100644
--- a/compositor.cpp
+++ b/compositor.cpp
@@ -16,6 +16,8 @@
 
 #include "compositor.h"
 
+#include <sstream>
+
 namespace android {
 
 Targeting::~Targeting() {
@@ -27,4 +29,7 @@
 Compositor::~Compositor() {
 }
 
+void Compositor::Dump(std::ostringstream */* out */) const {
+}
+
 }  // namespace android
diff --git a/compositor.h b/compositor.h
index b4956b6..e148416 100644
--- a/compositor.h
+++ b/compositor.h
@@ -19,6 +19,8 @@
 
 #include "importer.h"
 
+#include <sstream>
+
 struct hwc_layer_1;
 struct hwc_drm_bo;
 
@@ -98,6 +100,9 @@
   // on a worker thread. Each Composite call handles one composition that was
   // submitted via QueueComposition in FIFO order. Returns 0 on success.
   virtual int Composite() = 0;
+
+  // Dumps state from the Compositor to the out stream
+  virtual void Dump(std::ostringstream *out) const;
 };
 
 }  // namespace android
diff --git a/drmcompositor.cpp b/drmcompositor.cpp
index ffca4df..bf95601 100644
--- a/drmcompositor.cpp
+++ b/drmcompositor.cpp
@@ -22,7 +22,9 @@
 #include "drmresources.h"
 
 #include <pthread.h>
+#include <sstream>
 #include <stdlib.h>
+#include <time.h>
 
 #include <cutils/log.h>
 #include <sync/sync.h>
@@ -34,7 +36,13 @@
       worker_(this),
       active_composition_(NULL),
       frame_no_(0),
-      initialized_(false) {
+      initialized_(false),
+      dump_frames_composited_(0),
+      dump_last_timestamp_ns_(0) {
+  struct timespec ts;
+  if (clock_gettime(CLOCK_MONOTONIC, &ts))
+    return;
+  dump_last_timestamp_ns_ = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
 }
 
 DrmCompositor::~DrmCompositor() {
@@ -218,6 +226,7 @@
 
   DrmComposition *composition = composite_queue_.front();
   composite_queue_.pop();
+  ++dump_frames_composited_;
 
   ret = pthread_mutex_unlock(&lock_);
   if (ret) {
@@ -267,4 +276,31 @@
 
   return empty_ret;
 }
+
+void DrmCompositor::Dump(std::ostringstream *out) const {
+  uint64_t cur_ts;
+
+  int ret = pthread_mutex_lock(&lock_);
+  if (ret)
+    return;
+
+  uint64_t num_frames = dump_frames_composited_;
+  dump_frames_composited_ = 0;
+
+  struct timespec ts;
+  ret = clock_gettime(CLOCK_MONOTONIC, &ts);
+
+  ret |= pthread_mutex_unlock(&lock_);
+  if (ret)
+    return;
+
+  cur_ts = ts.tv_sec * 1000 * 1000 * 1000 + ts.tv_nsec;
+  uint64_t num_ms = (cur_ts - dump_last_timestamp_ns_) / (1000 * 1000);
+  unsigned fps = num_ms ? (num_frames * 1000) / (num_ms) : 0;
+
+  *out << "DrmCompositor: num_frames=" << num_frames << " num_ms=" << num_ms <<
+          " fps=" << fps << "\n";
+
+  dump_last_timestamp_ns_ = cur_ts;
+}
 }
diff --git a/drmcompositor.h b/drmcompositor.h
index 6b92a22..ad1316c 100644
--- a/drmcompositor.h
+++ b/drmcompositor.h
@@ -26,6 +26,7 @@
 
 #include <pthread.h>
 #include <queue>
+#include <sstream>
 
 #include <hardware/hardware.h>
 #include <hardware/hwcomposer.h>
@@ -49,6 +50,7 @@
 
   virtual int QueueComposition(Composition *composition);
   virtual int Composite();
+  virtual void Dump(std::ostringstream *out) const;
 
   bool HaveQueuedComposites() const;
 
@@ -73,6 +75,11 @@
 
   // mutable since we need to acquire in HaveQueuedComposites
   mutable pthread_mutex_t lock_;
+
+  // 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_;
 };
 }
 
diff --git a/gl_compositor.cpp b/gl_compositor.cpp
index c7aeff4..dfe407f 100644
--- a/gl_compositor.cpp
+++ b/gl_compositor.cpp
@@ -149,7 +149,8 @@
     hwc_drm_bo bo;
   };
 
-  GLComposition(GLCompositor *owner) : compositor(owner), target_handle(-1) {
+  GLComposition(GLCompositor *owner, Importer *imp)
+      : compositor(owner), importer(imp), target_handle(-1) {
   }
 
   virtual ~GLComposition() {
@@ -188,7 +189,7 @@
     layer_datum.layer = *layer;
     layer_datum.bo = *bo;
 
-    return 0;
+    return importer->ReleaseBuffer(bo);
   }
 
   virtual unsigned GetRemainingLayers(int display, unsigned num_needed) const {
@@ -197,6 +198,7 @@
   }
 
   GLCompositor *compositor;
+  Importer *importer;
   int target_handle;
   std::vector<LayerData> layer_data;
 };
@@ -343,9 +345,15 @@
   };
   // clang-format on
 
-  const EGLint config_attribs[] = {EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,
-                                   EGL_RED_SIZE, 8, EGL_GREEN_SIZE, 8,
-                                   EGL_BLUE_SIZE, 8, EGL_NONE};
+  const EGLint config_attribs[] = {EGL_RENDERABLE_TYPE,
+                                   EGL_OPENGL_ES2_BIT,
+                                   EGL_RED_SIZE,
+                                   8,
+                                   EGL_GREEN_SIZE,
+                                   8,
+                                   EGL_BLUE_SIZE,
+                                   8,
+                                   EGL_NONE};
 
   const EGLint context_attribs[] = {EGL_CONTEXT_CLIENT_VERSION, 3, EGL_NONE};
 
@@ -526,12 +534,12 @@
   }
 }
 
-Composition *GLCompositor::CreateComposition() {
+Composition *GLCompositor::CreateComposition(Importer *importer) {
   if (priv_->current_target >= 0 &&
       (unsigned)priv_->current_target < priv_->targets.size()) {
     GLTarget *target = &priv_->targets[priv_->current_target];
     if (target->is_some()) {
-      GLComposition *composition = new GLComposition(this);
+      GLComposition *composition = new GLComposition(this, importer);
       composition->target_handle = priv_->current_target;
       target->composition_count++;
       priv_->compositions.push_back(composition);
@@ -586,7 +594,7 @@
       priv_->saved_egl_ctx != eglGetCurrentContext()) {
     if (!eglMakeCurrent(priv_->saved_egl_display, priv_->saved_egl_read,
                         priv_->saved_egl_draw, priv_->saved_egl_ctx)) {
-      ALOGE("Failed to make the OpenGL ES Context current: %s",
+      ALOGE("Failed to make the old OpenGL ES Context current: %s",
             get_egl_error());
       return 1;
     }
diff --git a/gl_compositor.h b/gl_compositor.h
index e88ff13..528d8ac 100644
--- a/gl_compositor.h
+++ b/gl_compositor.h
@@ -35,7 +35,7 @@
   virtual int CreateTarget(sp<android::GraphicBuffer> &buffer);
   virtual void SetTarget(int target);
   virtual void ForgetTarget(int target);
-  virtual Composition *CreateComposition();
+  virtual Composition *CreateComposition(Importer *importer);
   virtual int QueueComposition(Composition *composition);
   virtual int Composite();
 
diff --git a/hwcomposer.cpp b/hwcomposer.cpp
index afb0ebe..2f9640e 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -72,6 +72,16 @@
   Importer *importer;
 };
 
+static void hwc_dump(struct hwc_composer_device_1* dev, char *buff,
+                     int buff_len) {
+  struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
+  std::ostringstream out;
+
+  ctx->drm.compositor()->Dump(&out);
+  std::string out_str = out.str();
+  strncpy(buff, out_str.c_str(), std::min((size_t)buff_len, out_str.length()));
+}
+
 static int hwc_prepare(hwc_composer_device_1_t *dev, size_t num_displays,
                        hwc_display_contents_1_t **display_contents) {
   // XXX: Once we have a GL compositor, just make everything HWC_OVERLAY
@@ -511,6 +521,7 @@
   ctx->device.common.module = const_cast<hw_module_t *>(module);
   ctx->device.common.close = hwc_device_close;
 
+  ctx->device.dump = hwc_dump;
   ctx->device.prepare = hwc_prepare;
   ctx->device.set = hwc_set;
   ctx->device.eventControl = hwc_event_control;