amdgpu: Use bo_release to free DRI images.

Previously these would get leaked if we had multiple bo structs
pointing to the same image/GEM BO as each has their own DRI image,
but bo_destroy only gets called on the last struct.

To mitigate this we have a new callback for every struct where we
can free the DRI image.

BUG=b:185869479
TEST=Repeatedly open/close camera app on Grunt.

Change-Id: I6188346b5bf9e5cbbbbf32a3db621a3fe0276d4f
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/minigbm/+/3270684
Tested-by: Bas Nieuwenhuizen <basni@chromium.org>
Reviewed-by: Yiwei Zhang <zzyiwei@chromium.org>
Commit-Queue: Bas Nieuwenhuizen <basni@chromium.org>
diff --git a/amdgpu.c b/amdgpu.c
index 3ebf1ab..f0053d6 100644
--- a/amdgpu.c
+++ b/amdgpu.c
@@ -631,6 +631,14 @@
 		return drv_prime_bo_import(bo, data);
 }
 
+static int amdgpu_release_bo(struct bo *bo)
+{
+	if (bo->priv)
+		return dri_bo_release(bo);
+
+	return 0;
+}
+
 static int amdgpu_destroy_bo(struct bo *bo)
 {
 	if (bo->priv)
@@ -780,6 +788,7 @@
 	.close = amdgpu_close,
 	.bo_create = amdgpu_create_bo,
 	.bo_create_with_modifiers = amdgpu_create_bo_with_modifiers,
+	.bo_release = amdgpu_release_bo,
 	.bo_destroy = amdgpu_destroy_bo,
 	.bo_import = amdgpu_import_bo,
 	.bo_map = amdgpu_map_bo,
diff --git a/dri.c b/dri.c
index 8b55c32..4ee133d 100644
--- a/dri.c
+++ b/dri.c
@@ -389,13 +389,20 @@
 	return 0;
 }
 
-int dri_bo_destroy(struct bo *bo)
+int dri_bo_release(struct bo *bo)
 {
 	struct dri_driver *dri = bo->drv->priv;
 
 	assert(bo->priv);
-	close_gem_handle(bo->handles[0].u32, bo->drv->fd);
 	dri->image_extension->destroyImage(bo->priv);
+	/* Not clearing bo->priv as we still use it to determine which destroy to call. */
+	return 0;
+}
+
+int dri_bo_destroy(struct bo *bo)
+{
+	assert(bo->priv);
+	close_gem_handle(bo->handles[0].u32, bo->drv->fd);
 	bo->priv = NULL;
 	return 0;
 }
diff --git a/dri.h b/dri.h
index ac5d033..daadf30 100644
--- a/dri.h
+++ b/dri.h
@@ -33,6 +33,7 @@
 int dri_bo_create_with_modifiers(struct bo *bo, uint32_t width, uint32_t height, uint32_t format,
 				 const uint64_t *modifiers, uint32_t modifier_count);
 int dri_bo_import(struct bo *bo, struct drv_import_fd_data *data);
+int dri_bo_release(struct bo *bo);
 int dri_bo_destroy(struct bo *bo);
 void *dri_bo_map(struct bo *bo, struct vma *vma, size_t plane, uint32_t map_flags);
 int dri_bo_unmap(struct bo *bo, struct vma *vma);