mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-23 06:28:08 +02:00
This allows for testing drm native ctx support without spinning up a VM. Signed-off-by: Rob Clark <robdclark@chromium.org> Reviewed-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Tested-by: Dmitry Osipenko <dmitry.osipenko@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33433>
197 lines
3.8 KiB
C
197 lines
3.8 KiB
C
/*
|
|
* Copyright © 2023 Google, Inc.
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "util/u_math.h"
|
|
#include "util/perf/cpu_trace.h"
|
|
|
|
#include "vdrm.h"
|
|
|
|
struct vdrm_device * vdrm_virtgpu_connect(int fd, uint32_t context_type);
|
|
struct vdrm_device * vdrm_vpipe_connect(uint32_t context_type);
|
|
|
|
struct vdrm_device *
|
|
vdrm_device_connect(int fd, uint32_t context_type)
|
|
{
|
|
struct vdrm_device *vdev;
|
|
|
|
if (fd >= 0) {
|
|
vdev = vdrm_virtgpu_connect(fd, context_type);
|
|
} else {
|
|
vdev = vdrm_vpipe_connect(context_type);
|
|
}
|
|
|
|
if (!vdev)
|
|
return NULL;
|
|
|
|
simple_mtx_init(&vdev->rsp_lock, mtx_plain);
|
|
simple_mtx_init(&vdev->eb_lock, mtx_plain);
|
|
|
|
return vdev;
|
|
}
|
|
|
|
void
|
|
vdrm_device_close(struct vdrm_device *vdev)
|
|
{
|
|
vdev->funcs->close(vdev);
|
|
free(vdev);
|
|
}
|
|
|
|
uint32_t
|
|
vdrm_bo_create(struct vdrm_device *vdev, size_t size, uint32_t blob_flags,
|
|
uint64_t blob_id, struct vdrm_ccmd_req *req)
|
|
{
|
|
uint32_t handle;
|
|
|
|
simple_mtx_lock(&vdev->eb_lock);
|
|
|
|
/* flush any buffered cmds so they are seen by the host *prior* to
|
|
* the cmds associated with bo creation.
|
|
*/
|
|
vdev->funcs->flush_locked(vdev, NULL);
|
|
|
|
req->seqno = ++vdev->next_seqno;
|
|
|
|
handle = vdev->funcs->bo_create(vdev, size, blob_flags, blob_id, req);
|
|
|
|
simple_mtx_unlock(&vdev->eb_lock);
|
|
|
|
return handle;
|
|
}
|
|
|
|
void *
|
|
vdrm_alloc_rsp(struct vdrm_device *vdev, struct vdrm_ccmd_req *req, uint32_t sz)
|
|
{
|
|
unsigned off;
|
|
|
|
simple_mtx_lock(&vdev->rsp_lock);
|
|
|
|
sz = align(sz, 8);
|
|
|
|
if ((vdev->next_rsp_off + sz) >= vdev->rsp_mem_len)
|
|
vdev->next_rsp_off = 0;
|
|
|
|
off = vdev->next_rsp_off;
|
|
vdev->next_rsp_off += sz;
|
|
|
|
simple_mtx_unlock(&vdev->rsp_lock);
|
|
|
|
req->rsp_off = off;
|
|
|
|
struct vdrm_ccmd_rsp *rsp = (void *)&vdev->rsp_mem[off];
|
|
rsp->len = sz;
|
|
|
|
return rsp;
|
|
}
|
|
|
|
static int
|
|
enqueue_req(struct vdrm_device *vdev, struct vdrm_ccmd_req *req)
|
|
{
|
|
simple_mtx_assert_locked(&vdev->eb_lock);
|
|
|
|
req->seqno = ++vdev->next_seqno;
|
|
|
|
if ((vdev->reqbuf_len + req->len) > sizeof(vdev->reqbuf)) {
|
|
int ret = vdev->funcs->flush_locked(vdev, NULL);
|
|
if (ret)
|
|
return ret;
|
|
}
|
|
|
|
memcpy(&vdev->reqbuf[vdev->reqbuf_len], req, req->len);
|
|
vdev->reqbuf_len += req->len;
|
|
vdev->reqbuf_cnt++;
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
vdrm_execbuf(struct vdrm_device *vdev, struct vdrm_execbuf_params *p)
|
|
{
|
|
int ret = 0;
|
|
|
|
MESA_TRACE_FUNC();
|
|
|
|
simple_mtx_lock(&vdev->eb_lock);
|
|
|
|
p->req->seqno = ++vdev->next_seqno;
|
|
|
|
ret = vdev->funcs->flush_locked(vdev, NULL);
|
|
if (ret)
|
|
goto out_unlock;
|
|
|
|
ret = vdev->funcs->execbuf_locked(vdev, p, p->req, p->req->len);
|
|
|
|
out_unlock:
|
|
simple_mtx_unlock(&vdev->eb_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Buffer/send a request cmd to host
|
|
*/
|
|
int
|
|
vdrm_send_req(struct vdrm_device *vdev, struct vdrm_ccmd_req *req, bool sync)
|
|
{
|
|
MESA_TRACE_FUNC();
|
|
|
|
uintptr_t fence = 0;
|
|
int ret = 0;
|
|
|
|
simple_mtx_lock(&vdev->eb_lock);
|
|
ret = enqueue_req(vdev, req);
|
|
|
|
if (ret || !sync)
|
|
goto out_unlock;
|
|
|
|
ret = vdev->funcs->flush_locked(vdev, &fence);
|
|
|
|
out_unlock:
|
|
simple_mtx_unlock(&vdev->eb_lock);
|
|
|
|
if (ret)
|
|
return ret;
|
|
|
|
if (sync) {
|
|
MESA_TRACE_SCOPE("vdrm_execbuf sync");
|
|
vdev->funcs->wait_fence(vdev, fence);
|
|
vdrm_host_sync(vdev, req);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
vdrm_flush(struct vdrm_device *vdev)
|
|
{
|
|
int ret = 0;
|
|
|
|
MESA_TRACE_FUNC();
|
|
|
|
simple_mtx_lock(&vdev->eb_lock);
|
|
ret = vdev->funcs->flush_locked(vdev, NULL);
|
|
simple_mtx_unlock(&vdev->eb_lock);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/**
|
|
* Helper for fence/seqno comparisions which deals properly with rollover.
|
|
* Returns true if fence 'a' is before fence 'b'
|
|
*/
|
|
static bool
|
|
fence_before(uint32_t a, uint32_t b)
|
|
{
|
|
return (int32_t)(a - b) < 0;
|
|
}
|
|
|
|
/**
|
|
* Wait until host has processed the specified request.
|
|
*/
|
|
void
|
|
vdrm_host_sync(struct vdrm_device *vdev, const struct vdrm_ccmd_req *req)
|
|
{
|
|
while (fence_before(vdev->shmem->seqno, req->seqno))
|
|
sched_yield();
|
|
}
|