aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVincent Donnefort <vincent.donnefort@arm.com>2019-08-02 11:18:35 +0100
committerVincent Donnefort <vincent.donnefort@arm.com>2019-12-09 16:12:20 +0000
commitf67c365de917512608cdc6cb3109d1a9cb3ac32b (patch)
tree805e579f2aa5db0c7941a0f3b062a39aeae5b36d
parent0d1a2cdbdf1fa126735f49f07f709a6a501aea52 (diff)
downloaddrm_hwcomposer-f67c365de917512608cdc6cb3109d1a9cb3ac32b.tar.gz
drm_hwcomposer: Add refcount for GEM handle
The linux kernel doesn't provide reference counting for the handle returned by FD_TO_HANDLE ioctl. It means that if the same Gralloc buffer is imported twice, the first GEM_CLOSE will destroy the handle even if it is still in use by another import. Remedy this issue by doing the reference counting directly in the DRM generic platform support: ImportHandle() will increase the reference, while ReleaseHandle() will decrease and close it, if necessary. Signed-off-by: Vincent Donnefort <vincent.donnefort@arm.com>
-rw-r--r--platform/platformdrmgeneric.cpp39
-rw-r--r--platform/platformdrmgeneric.h6
-rw-r--r--platform/platformhisi.cpp2
-rw-r--r--platform/platformimagination.cpp2
-rw-r--r--platform/platformmeson.cpp2
-rw-r--r--platform/platformminigbm.cpp2
6 files changed, 46 insertions, 7 deletions
diff --git a/platform/platformdrmgeneric.cpp b/platform/platformdrmgeneric.cpp
index 0883b90..668742c 100644
--- a/platform/platformdrmgeneric.cpp
+++ b/platform/platformdrmgeneric.cpp
@@ -143,6 +143,8 @@ int DrmGenericImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
return ret;
}
+ ImportHandle(gem_handle);
+
return ret;
}
@@ -151,17 +153,12 @@ int DrmGenericImporter::ReleaseBuffer(hwc_drm_bo_t *bo) {
if (drmModeRmFB(drm_->fd(), bo->fb_id))
ALOGE("Failed to rm fb");
- struct drm_gem_close gem_close;
- memset(&gem_close, 0, sizeof(gem_close));
-
for (int i = 0; i < HWC_DRM_BO_MAX_PLANES; i++) {
if (!bo->gem_handles[i])
continue;
- gem_close.handle = bo->gem_handles[i];
- int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
- if (ret) {
- ALOGE("Failed to close gem handle %d %d", i, ret);
+ if (ReleaseHandle(bo->gem_handles[i])) {
+ ALOGE("Failed to release gem handle %d", bo->gem_handles[i]);
} else {
for (int j = i + 1; j < HWC_DRM_BO_MAX_PLANES; j++)
if (bo->gem_handles[j] == bo->gem_handles[i])
@@ -191,4 +188,32 @@ std::unique_ptr<Planner> Planner::CreateInstance(DrmDevice *) {
return planner;
}
#endif
+
+int DrmGenericImporter::ImportHandle(uint32_t gem_handle) {
+ gem_refcount_[gem_handle]++;
+
+ return 0;
+}
+
+int DrmGenericImporter::ReleaseHandle(uint32_t gem_handle) {
+ if (--gem_refcount_[gem_handle])
+ return 0;
+
+ gem_refcount_.erase(gem_handle);
+
+ return CloseHandle(gem_handle);
+}
+
+int DrmGenericImporter::CloseHandle(uint32_t gem_handle) {
+ struct drm_gem_close gem_close;
+
+ memset(&gem_close, 0, sizeof(gem_close));
+
+ gem_close.handle = gem_handle;
+ int ret = drmIoctl(drm_->fd(), DRM_IOCTL_GEM_CLOSE, &gem_close);
+ if (ret)
+ ALOGE("Failed to close gem handle %d %d", gem_handle, ret);
+
+ return ret;
+}
}
diff --git a/platform/platformdrmgeneric.h b/platform/platformdrmgeneric.h
index 7bb2ea2..a7cf941 100644
--- a/platform/platformdrmgeneric.h
+++ b/platform/platformdrmgeneric.h
@@ -21,6 +21,7 @@
#include "platform.h"
#include <hardware/gralloc.h>
+#include <map>
#include <drm/drm_fourcc.h>
@@ -40,6 +41,8 @@ class DrmGenericImporter : public Importer {
int ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) override;
int ReleaseBuffer(hwc_drm_bo_t *bo) override;
bool CanImportBuffer(buffer_handle_t handle) override;
+ int ImportHandle(uint32_t gem_handle);
+ int ReleaseHandle(uint32_t gem_handle);
uint32_t ConvertHalFormatToDrm(uint32_t hal_format);
uint32_t DrmFormatToBitsPerPixel(uint32_t drm_format);
@@ -50,6 +53,9 @@ class DrmGenericImporter : public Importer {
private:
const gralloc_module_t *gralloc_;
bool exclude_non_hwfb_;
+
+ int CloseHandle(uint32_t gem_handle);
+ std::map<uint32_t, int> gem_refcount_;
};
} // namespace android
diff --git a/platform/platformhisi.cpp b/platform/platformhisi.cpp
index 2e6ac43..81d8039 100644
--- a/platform/platformhisi.cpp
+++ b/platform/platformhisi.cpp
@@ -173,6 +173,8 @@ int HisiImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
return ret;
}
+ ImportHandle(gem_handle);
+
return ret;
}
diff --git a/platform/platformimagination.cpp b/platform/platformimagination.cpp
index 565e6ee..5e0335c 100644
--- a/platform/platformimagination.cpp
+++ b/platform/platformimagination.cpp
@@ -69,6 +69,8 @@ int ImaginationImporter::ImportBuffer(buffer_handle_t handle,
return ret;
}
+ ImportHandle(gem_handle);
+
return 0;
}
diff --git a/platform/platformmeson.cpp b/platform/platformmeson.cpp
index 5184972..7b7a1f1 100644
--- a/platform/platformmeson.cpp
+++ b/platform/platformmeson.cpp
@@ -123,6 +123,8 @@ int MesonImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
return ret;
}
+ ImportHandle(gem_handle);
+
return ret;
}
diff --git a/platform/platformminigbm.cpp b/platform/platformminigbm.cpp
index a65e196..cb1e110 100644
--- a/platform/platformminigbm.cpp
+++ b/platform/platformminigbm.cpp
@@ -74,6 +74,8 @@ int DrmMinigbmImporter::ImportBuffer(buffer_handle_t handle, hwc_drm_bo_t *bo) {
return ret;
}
+ ImportHandle(gem_handle);
+
return ret;
}