summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gallium/state_trackers/dri/dri2.c8
-rw-r--r--src/gallium/winsys/sw/kms-dri/kms_dri_sw_winsys.c82
2 files changed, 79 insertions, 11 deletions
diff --git a/src/gallium/state_trackers/dri/dri2.c b/src/gallium/state_trackers/dri/dri2.c
index 1d79dfcd1aa..24c753ab001 100644
--- a/src/gallium/state_trackers/dri/dri2.c
+++ b/src/gallium/state_trackers/dri/dri2.c
@@ -1328,6 +1328,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)
@@ -1339,6 +1340,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 c9934bb07fa..49b2e6596ac 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"
@@ -121,7 +122,7 @@ kms_sw_displaytarget_create(struct sw_winsys *ws,
int ret;
kms_sw_dt = CALLOC_STRUCT(kms_sw_displaytarget);
- if(!kms_sw_dt)
+ if (!kms_sw_dt)
goto no_dt;
kms_sw_dt->ref_count = 1;
@@ -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 = -1;
+ 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;
+ kms_sw_dt->stride = whandle->stride;
+ *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;
+ }
}
+ /* fallthrough */
+ 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: */