drm_hwcomposer: duplicate buffer_handles before hwc_set returns
This is needed because SF will sometimes release buffer_handles before GL gets
to using them for composition.
Change-Id: I01db0975cc82d6b59bf4f9521a24071baf89c38a
diff --git a/drmdisplaycomposition.cpp b/drmdisplaycomposition.cpp
index c76a23c..d29b957 100644
--- a/drmdisplaycomposition.cpp
+++ b/drmdisplaycomposition.cpp
@@ -30,7 +30,35 @@
namespace android {
-DrmCompositionLayer::DrmCompositionLayer() : crtc(NULL), plane(NULL) {
+static native_handle_t *dup_buffer_handle(buffer_handle_t handle) {
+ native_handle_t *new_handle =
+ native_handle_create(handle->numFds, handle->numInts);
+ if (new_handle == NULL)
+ return NULL;
+
+ const int *old_data = handle->data;
+ int *new_data = new_handle->data;
+ for (int i = 0; i < handle->numFds; i++) {
+ *new_data = dup(*old_data);
+ old_data++;
+ new_data++;
+ }
+ memcpy(new_data, old_data, sizeof(int) * handle->numInts);
+
+ return new_handle;
+}
+
+static void free_buffer_handle(native_handle_t *handle) {
+ int ret = native_handle_close(handle);
+ if (ret)
+ ALOGE("Failed to close native handle %d", ret);
+ ret = native_handle_delete(handle);
+ if (ret)
+ ALOGE("Failed to delete native handle %d", ret);
+}
+
+DrmCompositionLayer::DrmCompositionLayer()
+ : crtc(NULL), plane(NULL), handle(NULL) {
memset(&layer, 0, sizeof(layer));
layer.acquireFenceFd = -1;
memset(&bo, 0, sizeof(bo));
@@ -55,6 +83,11 @@
if (importer_ && iter->bo.fb_id)
importer_->ReleaseBuffer(&iter->bo);
+ if (iter->handle) {
+ gralloc_->unregisterBuffer(gralloc_, iter->handle);
+ free_buffer_handle(iter->handle);
+ }
+
if (iter->layer.acquireFenceFd >= 0)
close(iter->layer.acquireFenceFd);
}
@@ -70,7 +103,14 @@
drm_ = drm;
importer_ = importer;
- int ret = sw_sync_timeline_create();
+ int ret = hw_get_module(GRALLOC_HARDWARE_MODULE_ID,
+ (const hw_module_t **)&gralloc_);
+ if (ret) {
+ ALOGE("Failed to open gralloc module %d", ret);
+ return ret;
+ }
+
+ ret = sw_sync_timeline_create();
if (ret < 0) {
ALOGE("Failed to create sw sync timeline %d", ret);
return ret;
@@ -92,10 +132,24 @@
if (!validate_composition_type(DRM_COMPOSITION_TYPE_FRAME))
return -EINVAL;
+ native_handle_t *handle_copy = dup_buffer_handle(layer->handle);
+ if (handle_copy == NULL) {
+ ALOGE("Failed to duplicate handle");
+ return -ENOMEM;
+ }
+
+ int ret = gralloc_->registerBuffer(gralloc_, handle_copy);
+ if (ret) {
+ ALOGE("Failed to register buffer handle %d", ret);
+ free_buffer_handle(handle_copy);
+ return ret;
+ }
+
++timeline_;
layer->releaseFenceFd =
sw_sync_fence_create(timeline_fd_, "drm_fence", timeline_);
if (layer->releaseFenceFd < 0) {
+ free_buffer_handle(handle_copy);
ALOGE("Could not create release fence %d", layer->releaseFenceFd);
return layer->releaseFenceFd;
}
@@ -105,6 +159,7 @@
c_layer.bo = *bo;
c_layer.crtc = crtc;
c_layer.plane = plane;
+ c_layer.handle = handle_copy;
layer->acquireFenceFd = -1; // We own this now
layers_.push_back(c_layer);
@@ -150,6 +205,32 @@
return 0;
}
+void DrmDisplayComposition::RemoveNoPlaneLayers() {
+ for (auto &comp_layer : layers_) {
+ if (comp_layer.plane != NULL)
+ continue;
+
+ if (importer_ && comp_layer.bo.fb_id) {
+ importer_->ReleaseBuffer(&comp_layer.bo);
+ }
+
+ if (comp_layer.handle) {
+ gralloc_->unregisterBuffer(gralloc_, comp_layer.handle);
+ free_buffer_handle(comp_layer.handle);
+ }
+
+ if (comp_layer.layer.acquireFenceFd >= 0) {
+ close(comp_layer.layer.acquireFenceFd);
+ comp_layer.layer.acquireFenceFd = -1;
+ }
+ }
+
+ layers_.erase(
+ std::remove_if(layers_.begin(), layers_.end(),
+ [](DrmCompositionLayer_t &l) { return l.plane == NULL; }),
+ layers_.end());
+}
+
int DrmDisplayComposition::FinishComposition() {
int timeline_increase = timeline_ - timeline_current_;
if (timeline_increase <= 0)