Merge "drm_hwcomposer: integrate GLCompositor with hwcomposer" into mnc-dev
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/drm_hwcomposer.h b/drm_hwcomposer.h
index c82506c..cebdbee 100644
--- a/drm_hwcomposer.h
+++ b/drm_hwcomposer.h
@@ -60,6 +60,7 @@
uint32_t gem_handles[4];
uint32_t fb_id;
int acquire_fence_fd;
+ void *priv;
} hwc_drm_bo_t;
int hwc_import_init(struct hwc_import_context **ctx);
diff --git a/drmcomposition.cpp b/drmcomposition.cpp
index 8fcb12d..07e08da 100644
--- a/drmcomposition.cpp
+++ b/drmcomposition.cpp
@@ -29,7 +29,7 @@
namespace android {
-static const bool kUseOverlayPlanes = false;
+static const bool kUseOverlayPlanes = true;
DrmCompositionLayer::DrmCompositionLayer() : crtc(NULL), plane(NULL) {
memset(&layer, 0, sizeof(layer));
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/hwcomposer.cpp b/hwcomposer.cpp
index f1d1e1e..6a30fbe 100644
--- a/hwcomposer.cpp
+++ b/hwcomposer.cpp
@@ -154,6 +154,16 @@
GLCompositor pre_compositor;
};
+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) {
struct hwc_context_t *ctx = (struct hwc_context_t *)&dev->common;
@@ -714,6 +724,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;
diff --git a/nvimporter.cpp b/nvimporter.cpp
index d673438..93b9129 100644
--- a/nvimporter.cpp
+++ b/nvimporter.cpp
@@ -20,6 +20,7 @@
#include "importer.h"
#include "nvimporter.h"
+#include <stdatomic.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
@@ -70,6 +71,7 @@
memset(bo, 0, sizeof(hwc_drm_bo_t));
NvBuffer_t *buf = GrallocGetNvBuffer(handle);
if (buf) {
+ atomic_fetch_add(&buf->ref, 1);
*bo = buf->bo;
return 0;
}
@@ -79,8 +81,14 @@
ALOGE("Failed to allocate new NvBuffer_t");
return -ENOMEM;
}
+ buf->bo.priv = buf;
buf->importer = this;
+ // We initialize the reference count to 2 since NvGralloc is still using this
+ // buffer (will be cleared in the NvGrallocRelease), and the other
+ // reference is for HWC (this ImportBuffer call).
+ atomic_init(&buf->ref, 2);
+
int ret = gralloc_->perform(gralloc_, GRALLOC_MODULE_PERFORM_DRM_IMPORT,
drm_->fd(), handle, &buf->bo);
if (ret) {
@@ -113,16 +121,24 @@
return 0;
}
-int NvImporter::ReleaseBuffer(hwc_drm_bo_t * /* bo */) {
- /* Stub this out since we don't want hwc releasing buffers */
+int NvImporter::ReleaseBuffer(hwc_drm_bo_t * bo) {
+ NvBuffer_t *buf = (NvBuffer_t *)bo->priv;
+ if (!buf) {
+ ALOGE("Freeing bo %ld, buf is NULL!", bo->fb_id);
+ return 0;
+ }
+ if (atomic_fetch_sub(&buf->ref, 1) > 1)
+ return 0;
+
+ ReleaseBufferImpl(bo);
+ delete buf;
return 0;
}
// static
-void NvImporter::ReleaseBufferCallback(void *nv_buffer) {
- NvBuffer_t *buf = (NvBuffer_t *)nv_buffer;
- buf->importer->ReleaseBufferImpl(&buf->bo);
- delete buf;
+void NvImporter::NvGrallocRelease(void *nv_buffer) {
+ NvBuffer_t *buf = (NvBuffer *)nv_buffer;
+ buf->importer->ReleaseBuffer(&buf->bo);
}
void NvImporter::ReleaseBufferImpl(hwc_drm_bo_t *bo) {
@@ -152,13 +168,13 @@
void *priv = NULL;
int ret =
gralloc_->perform(gralloc_, GRALLOC_MODULE_PERFORM_GET_IMPORTER_PRIVATE,
- handle, ReleaseBufferCallback, &priv);
+ handle, NvGrallocRelease, &priv);
return ret ? NULL : (NvBuffer_t *)priv;
}
int NvImporter::GrallocSetNvBuffer(buffer_handle_t handle, NvBuffer_t *buf) {
return gralloc_->perform(gralloc_,
GRALLOC_MODULE_PERFORM_SET_IMPORTER_PRIVATE, handle,
- ReleaseBufferCallback, buf);
+ NvGrallocRelease, buf);
}
}
diff --git a/nvimporter.h b/nvimporter.h
index e3bdd1c..a07f577 100644
--- a/nvimporter.h
+++ b/nvimporter.h
@@ -20,6 +20,8 @@
#include "drmresources.h"
#include "importer.h"
+#include <stdatomic.h>
+
#include <hardware/gralloc.h>
namespace android {
@@ -38,9 +40,10 @@
typedef struct NvBuffer {
NvImporter *importer;
hwc_drm_bo_t bo;
+ atomic_int ref;
} NvBuffer_t;
- static void ReleaseBufferCallback(void *nv_buffer);
+ static void NvGrallocRelease(void *nv_buffer);
void ReleaseBufferImpl(hwc_drm_bo_t *bo);
NvBuffer_t *GrallocGetNvBuffer(buffer_handle_t handle);