[Mesa-dev] [PATCH] kms-swrast: Support Prime fd handling

Andreas Pokorny andreas.pokorny at canonical.com
Fri Aug 22 06:19:43 PDT 2014


Allows using prime fds as display target and from display target.
Test for PRIME capability after initializing kms_swrast screen.

Signed-off-by: Andreas Pokorny <andreas.pokorny at canonical.com>
---
 src/gallium/state_trackers/dri/dri2.c             |  8 +++
 src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c | 80 ++++++++++++++++++++---
 2 files changed, 78 insertions(+), 10 deletions(-)

diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c
index a63448d..82f8a47 100644
--- a/src/gallium/state_trackers/dri/dri2.c
+++ b/src/gallium/state_trackers/dri/dri2.c
@@ -1333,6 +1333,7 @@ dri_kms_init_screen(__DRIscreen * sPriv)
    const __DRIconfig **configs;
    struct dri_screen *screen;
    struct pipe_screen *pscreen = NULL;
+   uint64_t cap;
 
    screen = CALLOC_STRUCT(dri_screen);
    if (!screen)
@@ -1344,6 +1345,13 @@ dri_kms_init_screen(__DRIscreen * sPriv)
    sPriv->driverPrivate = (void *)screen;
 
    pscreen = kms_swrast_create_screen(screen->fd);
+
+   if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&
+          (cap & DRM_PRIME_CAP_IMPORT)) {
+      dri2ImageExtension.createImageFromFds = dri2_from_fds;
+      dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs;
+   }
+
    sPriv->extensions = dri_screen_extensions;
 
    /* dri_init_screen_helper checks pscreen for us */
diff --git a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c
index c9934bb..286bd9c 100644
--- a/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c
+++ b/src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c
@@ -38,6 +38,7 @@
 #include <sys/mman.h>
 #include <unistd.h>
 #include <dlfcn.h>
+#include <fcntl.h>
 #include <xf86drm.h>
 
 #include "pipe/p_compiler.h"
@@ -210,6 +211,38 @@ kms_sw_displaytarget_map(struct sw_winsys *ws,
    return kms_sw_dt->mapped;
 }
 
+static struct kms_sw_displaytarget *
+kms_sw_displaytarget_add_from_prime(struct kms_sw_winsys *kms_sw, int fd)
+{
+   uint32_t handle;
+   struct kms_sw_displaytarget * kms_sw_dt;
+   int ret;
+
+   ret = drmPrimeFDToHandle(kms_sw->fd, fd, &handle);
+
+   if (ret)
+      return NULL;
+
+   kms_sw_dt = CALLOC_STRUCT(kms_sw_displaytarget);
+   if (!kms_sw_dt)
+      return NULL;
+
+   kms_sw_dt->ref_count = 1;
+   kms_sw_dt->handle = handle;
+   kms_sw_dt->size = lseek(fd, 0, SEEK_END);
+
+   if (kms_sw_dt->size == (off_t)-1) {
+      FREE(kms_sw_dt);
+      return NULL;
+   }
+
+   lseek(fd, 0, SEEK_SET);
+
+   list_add(&kms_sw_dt->link, &kms_sw->bo_list);
+
+   return kms_sw_dt;
+}
+
 static void
 kms_sw_displaytarget_unmap(struct sw_winsys *ws,
                            struct sw_displaytarget *dt)
@@ -231,17 +264,34 @@ kms_sw_displaytarget_from_handle(struct sw_winsys *ws,
    struct kms_sw_winsys *kms_sw = kms_sw_winsys(ws);
    struct kms_sw_displaytarget *kms_sw_dt;
 
-   assert(whandle->type == DRM_API_HANDLE_TYPE_KMS);
+   assert(whandle->type == DRM_API_HANDLE_TYPE_KMS ||
+          whandle->type == DRM_API_HANDLE_TYPE_FD);
 
-   LIST_FOR_EACH_ENTRY(kms_sw_dt, &kms_sw->bo_list, link) {
-      if (kms_sw_dt->handle == whandle->handle) {
+   switch(whandle->type) {
+   case DRM_API_HANDLE_TYPE_FD:
+      kms_sw_dt = kms_sw_displaytarget_add_from_prime(kms_sw, whandle->handle);
+      if (kms_sw_dt) {
          kms_sw_dt->ref_count++;
+         kms_sw_dt->width = templ->width0;
+         kms_sw_dt->height = templ->height0;
+         if (kms_sw_dt->height)
+            kms_sw_dt->stride = kms_sw_dt->size/kms_sw_dt->height;
+         *stride = kms_sw_dt->stride;
+      }
+      return (struct sw_displaytarget *)kms_sw_dt;
+   case DRM_API_HANDLE_TYPE_KMS:
+      LIST_FOR_EACH_ENTRY(kms_sw_dt, &kms_sw->bo_list, link) {
+         if (kms_sw_dt->handle == whandle->handle) {
+            kms_sw_dt->ref_count++;
 
-         DEBUG("KMS-DEBUG: imported buffer %u (size %u)\n", kms_sw_dt->handle, kms_sw_dt->size);
+            DEBUG("KMS-DEBUG: imported buffer %u (size %u)\n", kms_sw_dt->handle, kms_sw_dt->size);
 
-         *stride = kms_sw_dt->stride;
-         return (struct sw_displaytarget *)kms_sw_dt;
+            *stride = kms_sw_dt->stride;
+            return (struct sw_displaytarget *)kms_sw_dt;
+         }
       }
+   default:
+   break;
    }
 
    assert(0);
@@ -253,16 +303,26 @@ kms_sw_displaytarget_get_handle(struct sw_winsys *winsys,
                                 struct sw_displaytarget *dt,
                                 struct winsys_handle *whandle)
 {
+   struct kms_sw_winsys *kms_sw = kms_sw_winsys(winsys);
    struct kms_sw_displaytarget *kms_sw_dt = kms_sw_displaytarget(dt);
 
-   if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
+   switch(whandle->type) {
+   case DRM_API_HANDLE_TYPE_KMS:
       whandle->handle = kms_sw_dt->handle;
       whandle->stride = kms_sw_dt->stride;
-   } else {
+      return TRUE;
+   case DRM_API_HANDLE_TYPE_FD:
+      if (!drmPrimeHandleToFD(kms_sw->fd, kms_sw_dt->handle,
+                             DRM_CLOEXEC, &whandle->handle)) {
+         whandle->stride = kms_sw_dt->stride;
+         return TRUE;
+      }
+      /* fallthrough */
+   default:
       whandle->handle = 0;
       whandle->stride = 0;
+      return FALSE;
    }
-   return TRUE;
 }
 
 static void
@@ -315,4 +375,4 @@ kms_dri_create_winsys(int fd)
    return &ws->base;
 }
 
-/* vim: set sw=3 ts=8 sts=3 expandtab: */
\ No newline at end of file
+/* vim: set sw=3 ts=8 sts=3 expandtab: */
-- 
2.1.0.rc1



More information about the mesa-dev mailing list