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)
diff --git a/drmdisplaycomposition.h b/drmdisplaycomposition.h
index 7202c7c..76da993 100644
--- a/drmdisplaycomposition.h
+++ b/drmdisplaycomposition.h
@@ -23,6 +23,7 @@
#include <vector>
+#include <hardware/gralloc.h>
#include <hardware/hardware.h>
#include <hardware/hwcomposer.h>
@@ -42,6 +43,7 @@
hwc_drm_bo_t bo;
DrmCrtc *crtc;
DrmPlane *plane;
+ native_handle_t *handle;
} DrmCompositionLayer_t;
typedef std::vector<DrmCompositionLayer_t> DrmCompositionLayerVector_t;
@@ -62,6 +64,7 @@
int AddPlaneDisable(DrmPlane *plane);
int AddDpmsMode(uint32_t dpms_mode);
+ void RemoveNoPlaneLayers();
int FinishComposition();
DrmCompositionLayerVector_t *GetCompositionLayers();
@@ -76,6 +79,7 @@
DrmResources *drm_;
Importer *importer_;
+ const gralloc_module_t *gralloc_;
DrmCompositionType type_;
diff --git a/drmdisplaycompositor.cpp b/drmdisplaycompositor.cpp
index b76d81d..1e02e73 100644
--- a/drmdisplaycompositor.cpp
+++ b/drmdisplaycompositor.cpp
@@ -186,11 +186,6 @@
return -ENOMEM;
}
- std::vector<hwc_layer_1_t> pre_comp_layers;
- for (const auto &comp_layer : *layers)
- if (comp_layer.plane == NULL)
- pre_comp_layers.push_back(comp_layer.layer);
-
if (!pre_compositor_) {
pre_compositor_.reset(new GLWorkerCompositor());
ret = pre_compositor_->Init();
@@ -199,20 +194,32 @@
return ret;
}
}
+
+ std::vector<hwc_layer_1_t> pre_comp_layers;
+ for (auto &comp_layer : *layers) {
+ if (comp_layer.plane == NULL) {
+ pre_comp_layers.push_back(comp_layer.layer);
+ pre_comp_layers.back().handle = comp_layer.handle;
+ comp_layer.layer.acquireFenceFd = -1;
+ }
+ }
+
ret = pre_compositor_->CompositeAndFinish(
pre_comp_layers.data(), pre_comp_layers.size(), fb.buffer());
+
+ for (auto &pre_comp_layer : pre_comp_layers) {
+ if (pre_comp_layer.acquireFenceFd >= 0) {
+ close(pre_comp_layer.acquireFenceFd);
+ pre_comp_layer.acquireFenceFd = -1;
+ }
+ }
+
if (ret) {
ALOGE("Failed to composite layers");
return ret;
}
- for (auto &comp_layer : *layers)
- if (comp_layer.plane == NULL)
- display_comp->importer()->ReleaseBuffer(&comp_layer.bo);
-
- layers->erase(std::remove_if(layers->begin(), layers->end(),
- drm_composition_layer_has_no_plane),
- layers->end());
+ display_comp->RemoveNoPlaneLayers();
hwc_layer_1_t pre_comp_output_layer;
memset(&pre_comp_output_layer, 0, sizeof(pre_comp_output_layer));
diff --git a/glworker.cpp b/glworker.cpp
index df6a8f2..fe2fd66 100644
--- a/glworker.cpp
+++ b/glworker.cpp
@@ -600,11 +600,13 @@
}
for (i = 0; i < num_layers; i++) {
- const struct hwc_layer_1 *layer = &layers[i];
+ struct hwc_layer_1 *layer = &layers[i];
if (ret) {
- if (layer->acquireFenceFd >= 0)
+ if (layer->acquireFenceFd >= 0) {
close(layer->acquireFenceFd);
+ layer->acquireFenceFd = -1;
+ }
continue;
}
@@ -613,6 +615,7 @@
&layer_textures.back());
if (!ret) {
ret = EGLFenceWait(egl_display_, layer->acquireFenceFd);
+ layer->acquireFenceFd = -1;
}
if (ret) {
layer_textures.pop_back();