mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 19:58:09 +02:00
winsys/drisw: implement dmabuf handling
this comes in two variants: * util/memfd stuff with a header for metadata * raw fd passing for imports, both have to be tried since the import might be from a hw device, but only the latter needs to be handled in winsys here Reviewed-by: Dave Airlie <airlied@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27805>
This commit is contained in:
parent
17abe3ecbd
commit
e4ae665f93
1 changed files with 70 additions and 5 deletions
|
|
@ -39,11 +39,20 @@
|
|||
|
||||
#include "util/compiler.h"
|
||||
#include "util/format/u_formats.h"
|
||||
#include "util/detect_os.h"
|
||||
|
||||
#if DETECT_OS_UNIX
|
||||
# include <sys/stat.h>
|
||||
# include <errno.h>
|
||||
# include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include "pipe/p_state.h"
|
||||
#include "util/u_inlines.h"
|
||||
#include "util/format/u_format.h"
|
||||
#include "util/u_math.h"
|
||||
#include "util/u_memory.h"
|
||||
#include "util/os_file.h"
|
||||
|
||||
#include "frontend/sw_winsys.h"
|
||||
#include "dri_sw_winsys.h"
|
||||
|
|
@ -61,6 +70,9 @@ struct dri_sw_displaytarget
|
|||
void *data;
|
||||
void *mapped;
|
||||
const void *front_private;
|
||||
/* dmabuf */
|
||||
int fd;
|
||||
int offset;
|
||||
size_t size;
|
||||
bool unbacked;
|
||||
};
|
||||
|
|
@ -146,6 +158,7 @@ dri_sw_displaytarget_create(struct sw_winsys *winsys,
|
|||
dri_sw_dt->size = size;
|
||||
|
||||
dri_sw_dt->shmid = -1;
|
||||
dri_sw_dt->fd = -1;
|
||||
|
||||
#ifdef HAVE_SYS_SHM_H
|
||||
if (ws->lf->put_image_shm)
|
||||
|
|
@ -194,6 +207,7 @@ dri_sw_displaytarget_create_mapped(struct sw_winsys *winsys,
|
|||
dri_sw_dt->size = size;
|
||||
|
||||
dri_sw_dt->shmid = -1;
|
||||
dri_sw_dt->fd = -1;
|
||||
dri_sw_dt->unbacked = true;
|
||||
|
||||
dri_sw_dt->data = data;
|
||||
|
|
@ -209,7 +223,11 @@ dri_sw_displaytarget_destroy(struct sw_winsys *ws,
|
|||
struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
|
||||
|
||||
if (dri_sw_dt->unbacked) {}
|
||||
else if (dri_sw_dt->shmid >= 0) {
|
||||
else if (dri_sw_dt->fd >= 0) {
|
||||
if (dri_sw_dt->mapped)
|
||||
ws->displaytarget_unmap(ws, dt);
|
||||
close(dri_sw_dt->fd);
|
||||
} else if (dri_sw_dt->shmid >= 0) {
|
||||
#ifdef HAVE_SYS_SHM_H
|
||||
shmdt(dri_sw_dt->data);
|
||||
shmctl(dri_sw_dt->shmid, IPC_RMID, NULL);
|
||||
|
|
@ -227,15 +245,45 @@ dri_sw_displaytarget_map(struct sw_winsys *ws,
|
|||
unsigned flags)
|
||||
{
|
||||
struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
|
||||
dri_sw_dt->map_flags = flags;
|
||||
if (dri_sw_dt->unbacked)
|
||||
return dri_sw_dt->mapped;
|
||||
dri_sw_dt->mapped = dri_sw_dt->data;
|
||||
|
||||
#if DETECT_OS_UNIX
|
||||
if (dri_sw_dt->fd > -1) {
|
||||
bool success = false;
|
||||
if (!success) {
|
||||
/* if this fails, it's a dmabuf that wasn't exported by us,
|
||||
* so it doesn't have the header that we're looking for
|
||||
*/
|
||||
off_t size = lseek(dri_sw_dt->fd, 0, SEEK_END);
|
||||
lseek(dri_sw_dt->fd, 0, SEEK_SET);
|
||||
if (size < 1) {
|
||||
fprintf(stderr, "dmabuf import failed: fd has no data\n");
|
||||
return NULL;
|
||||
}
|
||||
unsigned prot = 0;
|
||||
if (flags & PIPE_MAP_READ)
|
||||
prot |= PROT_READ;
|
||||
if (flags & PIPE_MAP_WRITE)
|
||||
prot |= PROT_WRITE;
|
||||
dri_sw_dt->size = size;
|
||||
dri_sw_dt->data = mmap(NULL, dri_sw_dt->size, prot, MAP_SHARED, dri_sw_dt->fd, 0);
|
||||
if (dri_sw_dt->data == MAP_FAILED) {
|
||||
dri_sw_dt->data = NULL;
|
||||
fprintf(stderr, "dmabuf import failed to mmap: %s\n", strerror(errno));
|
||||
} else
|
||||
dri_sw_dt->mapped = ((uint8_t*)dri_sw_dt->data) + dri_sw_dt->offset;
|
||||
} else
|
||||
dri_sw_dt->mapped = ((uint8_t*)dri_sw_dt->data) + dri_sw_dt->offset;
|
||||
} else
|
||||
#endif
|
||||
if (dri_sw_dt->front_private && (flags & PIPE_MAP_READ)) {
|
||||
struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
|
||||
dri_sw_ws->lf->get_image((void *)dri_sw_dt->front_private, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride, dri_sw_dt->data);
|
||||
dri_sw_dt->mapped = dri_sw_dt->data;
|
||||
} else {
|
||||
dri_sw_dt->mapped = dri_sw_dt->data;
|
||||
}
|
||||
dri_sw_dt->map_flags = flags;
|
||||
return dri_sw_dt->mapped;
|
||||
}
|
||||
|
||||
|
|
@ -245,8 +293,16 @@ dri_sw_displaytarget_unmap(struct sw_winsys *ws,
|
|||
{
|
||||
struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(dt);
|
||||
|
||||
if (dri_sw_dt->unbacked)
|
||||
if (dri_sw_dt->unbacked) {
|
||||
dri_sw_dt->map_flags = 0;
|
||||
return;
|
||||
}
|
||||
#if DETECT_OS_UNIX
|
||||
if (dri_sw_dt->fd > -1) {
|
||||
munmap(dri_sw_dt->data, dri_sw_dt->size);
|
||||
dri_sw_dt->data = NULL;
|
||||
} else
|
||||
#endif
|
||||
if (dri_sw_dt->front_private && (dri_sw_dt->map_flags & PIPE_MAP_WRITE)) {
|
||||
struct dri_sw_winsys *dri_sw_ws = dri_sw_winsys(ws);
|
||||
dri_sw_ws->lf->put_image2((void *)dri_sw_dt->front_private, dri_sw_dt->data, 0, 0, dri_sw_dt->width, dri_sw_dt->height, dri_sw_dt->stride);
|
||||
|
|
@ -261,8 +317,17 @@ dri_sw_displaytarget_from_handle(struct sw_winsys *winsys,
|
|||
struct winsys_handle *whandle,
|
||||
unsigned *stride)
|
||||
{
|
||||
#if DETECT_OS_UNIX
|
||||
int fd = os_dupfd_cloexec(whandle->handle);
|
||||
struct sw_displaytarget *sw = dri_sw_displaytarget_create(winsys, templ->usage, templ->format, templ->width0, templ->height0, 64, NULL, stride);
|
||||
struct dri_sw_displaytarget *dri_sw_dt = dri_sw_displaytarget(sw);
|
||||
dri_sw_dt->fd = fd;
|
||||
dri_sw_dt->offset = whandle->offset;
|
||||
return sw;
|
||||
#else
|
||||
assert(0);
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
static bool
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue