diff options
author | Vincent Donnefort <vincent.donnefort@arm.com> | 2019-08-02 11:18:35 +0100 |
---|---|---|
committer | Vincent Donnefort <vincent.donnefort@arm.com> | 2019-12-09 16:12:20 +0000 |
commit | f67c365de917512608cdc6cb3109d1a9cb3ac32b (patch) | |
tree | 805e579f2aa5db0c7941a0f3b062a39aeae5b36d | |
parent | 0d1a2cdbdf1fa126735f49f07f709a6a501aea52 (diff) | |
download | drm_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.cpp | 39 | ||||
-rw-r--r-- | platform/platformdrmgeneric.h | 6 | ||||
-rw-r--r-- | platform/platformhisi.cpp | 2 | ||||
-rw-r--r-- | platform/platformimagination.cpp | 2 | ||||
-rw-r--r-- | platform/platformmeson.cpp | 2 | ||||
-rw-r--r-- | platform/platformminigbm.cpp | 2 |
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; } |