[Mesa-dev] [PATCH RFC 2/2] GBM: use KMS device to allocate scanout and cursor BOs

Lucas Stach l.stach at pengutronix.de
Fri Mar 4 13:49:16 UTC 2016


If we have a KMS device which is distinct to the render GBM
device, try to allocate cursor and scanout BOs from this device.

Right now this only makes sure that the selected format is
compatible with both devices. We need more internal API to
signal width/height/stride and tiling constraints.

Signed-off-by: Lucas Stach <l.stach at pengutronix.de>
---
 src/gbm/main/gbm.c    | 77 +++++++++++++++++++++++++++++++++++++++++++++------
 src/gbm/main/gbmint.h |  1 +
 2 files changed, 69 insertions(+), 9 deletions(-)

diff --git a/src/gbm/main/gbm.c b/src/gbm/main/gbm.c
index 26339747f3a1..74f0bdb6d0f1 100644
--- a/src/gbm/main/gbm.c
+++ b/src/gbm/main/gbm.c
@@ -87,7 +87,18 @@ GBM_EXPORT int
 gbm_device_is_format_supported(struct gbm_device *gbm,
                                uint32_t format, uint32_t usage)
 {
-   return gbm->is_format_supported(gbm, format, usage);
+   /*
+    * If there is a KMS provider, scanout formats must be supported by both the
+    * KMS and the render device, cursor formats only by the KMS device.
+    */
+   if (gbm->kms_provider && (usage & GBM_BO_USE_CURSOR))
+      return gbm->kms_provider->is_format_supported(gbm->kms_provider,
+                                                    format, usage);
+   else if (gbm->kms_provider && (usage & GBM_BO_USE_SCANOUT))
+      return gbm->kms_provider->is_format_supported(gbm->kms_provider,
+               format, usage) && gbm->is_format_supported(gbm, format, usage);
+   else
+      return gbm->is_format_supported(gbm, format, usage);
 }
 
 /** Set the KMS provider device used for scanout and cursor BO allocations
@@ -339,6 +350,9 @@ gbm_bo_destroy(struct gbm_bo *bo)
    if (bo->destroy_user_data)
       bo->destroy_user_data(bo, bo->user_data);
 
+   if (bo->prime_bo)
+      bo->prime_bo->gbm->bo_destroy(bo->prime_bo);
+
    bo->gbm->bo_destroy(bo);
 }
 
@@ -363,17 +377,54 @@ gbm_bo_create(struct gbm_device *gbm,
               uint32_t width, uint32_t height,
               uint32_t format, uint32_t usage)
 {
-   struct gbm_bo *bo;
-
    if (width == 0 || height == 0) {
       errno = EINVAL;
       return NULL;
    }
 
-   bo = gbm->bo_create(gbm, width, height, format, usage);
-   bo->type = GBM_BO_TYPE_RENDER | GBM_BO_TYPE_KMS;
+   if (gbm->kms_provider && (usage & GBM_BO_USE_CURSOR)) {
+      struct gbm_bo *bo = gbm->kms_provider->bo_create(gbm->kms_provider, width,
+                                                       height, format, usage);
+      bo->type = GBM_BO_TYPE_KMS;
+      return bo;
+   }
+
+   if (gbm->kms_provider && (usage & GBM_BO_USE_SCANOUT)) {
+      struct gbm_bo *kms_bo, *render_bo;
+      struct gbm_import_fd_data import_data;
+
+      /* FIXME: we need a way to communicate constraints here */
+      kms_bo = gbm->kms_provider->bo_create(gbm->kms_provider, width, height,
+                                            format, usage);
+      if (!kms_bo)
+         return NULL;
+
+      kms_bo->type = GBM_BO_TYPE_KMS;
+
+      import_data.fd = gbm_bo_get_fd(kms_bo);
+      import_data.format = gbm_bo_get_format(kms_bo);
+      import_data.height = gbm_bo_get_height(kms_bo);
+      import_data.width = gbm_bo_get_width(kms_bo);
+      import_data.stride = gbm_bo_get_stride(kms_bo);
+
+      render_bo = gbm->bo_import(gbm, GBM_BO_IMPORT_FD, &import_data, usage);
+      close(import_data.fd);
+      if (!render_bo) {
+         gbm->kms_provider->bo_destroy(kms_bo);
+         return NULL;
+      }
+      render_bo->type = GBM_BO_TYPE_RENDER;
 
-   return bo;
+      /* link bos together, so we know they represent the same thing */
+      render_bo->prime_bo = kms_bo;
+      kms_bo->prime_bo = render_bo;
+
+      return render_bo;
+   } else {
+      struct gbm_bo *bo = gbm->bo_create(gbm, width, height, format, usage);
+      bo->type = GBM_BO_TYPE_KMS | GBM_BO_TYPE_RENDER;
+      return bo;
+   }
 }
 
 /**
@@ -412,10 +463,13 @@ gbm_bo_import(struct gbm_device *gbm,
 GBM_EXPORT struct gbm_bo *
 gbm_bo_get_kms_bo(struct gbm_bo *bo)
 {
-   if (!bo || !(bo->type & GBM_BO_TYPE_KMS))
+   if (!bo)
       return NULL;
 
-   return bo;
+   if (bo->type & GBM_BO_TYPE_KMS)
+      return bo;
+   else
+      return bo->prime_bo;
 }
 
 /**
@@ -497,7 +551,12 @@ gbm_surface_lock_front_buffer(struct gbm_surface *surf)
 GBM_EXPORT void
 gbm_surface_release_buffer(struct gbm_surface *surf, struct gbm_bo *bo)
 {
-   surf->gbm->surface_release_buffer(surf, bo);
+   struct gbm_bo *release_bo = bo;
+
+   if (!(bo->type & GBM_BO_TYPE_RENDER))
+      release_bo = bo->prime_bo;
+
+   surf->gbm->surface_release_buffer(surf, release_bo);
 }
 
 /**
diff --git a/src/gbm/main/gbmint.h b/src/gbm/main/gbmint.h
index 218ecf66c0fd..17438141da50 100644
--- a/src/gbm/main/gbmint.h
+++ b/src/gbm/main/gbmint.h
@@ -101,6 +101,7 @@ struct gbm_bo {
    union gbm_bo_handle  handle;
    void *user_data;
    void (*destroy_user_data)(struct gbm_bo *, void *);
+   struct gbm_bo *prime_bo;
 };
 
 struct gbm_surface {
-- 
2.7.0



More information about the mesa-dev mailing list