Merge branch 'require-gb' into 'main'

winsys/svga: Require Guest-Backed (GB) Objects

See merge request mesa/mesa!38774
This commit is contained in:
Ian Forbes 2026-05-07 19:11:41 -05:00
commit 081acef9ef
5 changed files with 22 additions and 297 deletions

View file

@ -524,8 +524,6 @@ vmw_swc_surface_relocation(struct svga_winsys_context *swc,
{
struct vmw_svga_winsys_surface *vsurf;
assert(swc->have_gb_objects || mobid == NULL);
if (!surface) {
*where = SVGA3D_INVALID_ID;
if (mobid)
@ -536,7 +534,7 @@ vmw_swc_surface_relocation(struct svga_winsys_context *swc,
vsurf = vmw_svga_winsys_surface(surface);
vmw_swc_surface_only_relocation(swc, where, vsurf, flags);
if (swc->have_gb_objects && vsurf->buf != NULL) {
if (vsurf->buf != NULL) {
/*
* Make sure backup buffer ends up fenced.

View file

@ -118,7 +118,7 @@ vmw_winsys_screen(struct svga_winsys_screen *base)
static inline bool
vmw_has_userspace_surface(struct vmw_winsys_screen *vws)
{
if (!vws->base.have_gb_objects || !vws->base.have_vgpu10)
if (!vws->base.have_vgpu10)
return false;
return vws->userspace_surface;
}
@ -139,15 +139,6 @@ vmw_ioctl_context_destroy(struct vmw_winsys_screen *vws,
uint32 cid);
uint32
vmw_ioctl_surface_create(struct vmw_winsys_screen *vws,
SVGA3dSurface1Flags flags,
SVGA3dSurfaceFormat format,
unsigned usage,
SVGA3dSize size,
uint32 numFaces,
uint32 numMipLevels,
unsigned sampleCount);
uint32
vmw_ioctl_gb_surface_create(struct vmw_winsys_screen *vws,
SVGA3dSurfaceAllFlags flags,
SVGA3dSurfaceFormat format,

View file

@ -32,11 +32,6 @@ struct dri1_api_version {
int patch_level;
};
static struct svga_winsys_surface *
vmw_drm_surface_from_handle(struct svga_winsys_screen *sws,
struct winsys_handle *whandle,
SVGA3dSurfaceFormat *format);
static struct svga_winsys_surface *
vmw_drm_gb_surface_from_handle(struct svga_winsys_screen *sws,
struct winsys_handle *whandle,
@ -97,9 +92,7 @@ svga_drm_winsys_screen_create(int fd)
if (!vws)
goto out_no_vws;
/* XXX do this properly */
vws->base.surface_from_handle = vws->base.have_gb_objects ?
vmw_drm_gb_surface_from_handle : vmw_drm_surface_from_handle;
vws->base.surface_from_handle = vmw_drm_gb_surface_from_handle;
vws->base.surface_get_handle = vmw_drm_surface_get_handle;
return &vws->base;
@ -192,117 +185,6 @@ out_mip:
return NULL;
}
static struct svga_winsys_surface *
vmw_drm_surface_from_handle(struct svga_winsys_screen *sws,
struct winsys_handle *whandle,
SVGA3dSurfaceFormat *format)
{
struct vmw_svga_winsys_surface *vsrf;
struct svga_winsys_surface *ssrf;
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
union drm_vmw_surface_reference_arg arg;
struct drm_vmw_surface_arg *req = &arg.req;
struct drm_vmw_surface_create_req *rep = &arg.rep;
uint32_t handle = 0;
struct drm_vmw_size size;
SVGA3dSize base_size;
int ret;
int i;
if (whandle->offset != 0) {
fprintf(stderr, "Attempt to import unsupported winsys offset %u\n",
whandle->offset);
return NULL;
}
switch (whandle->type) {
case WINSYS_HANDLE_TYPE_SHARED:
case WINSYS_HANDLE_TYPE_KMS:
handle = whandle->handle;
break;
case WINSYS_HANDLE_TYPE_FD:
ret = drmPrimeFDToHandle(vws->ioctl.drm_fd, whandle->handle,
&handle);
if (ret) {
vmw_error("Failed to get handle from prime fd %d.\n",
(int) whandle->handle);
return NULL;
}
break;
default:
vmw_error("Attempt to import unsupported handle type %d.\n",
whandle->type);
return NULL;
}
memset(&arg, 0, sizeof(arg));
req->sid = handle;
rep->size_addr = (unsigned long)&size;
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_REF_SURFACE,
&arg, sizeof(arg));
/*
* Need to close the handle we got from prime.
*/
if (whandle->type == WINSYS_HANDLE_TYPE_FD)
vmw_ioctl_surface_destroy(vws, handle);
if (ret) {
/*
* Any attempt to share something other than a surface, like a dumb
* kms buffer, should fail here.
*/
vmw_error("Failed referencing shared surface. SID %d.\n"
"Error %d (%s).\n",
handle, ret, strerror(-ret));
return NULL;
}
if (rep->mip_levels[0] != 1) {
vmw_error("Incorrect number of mipmap levels on shared surface."
" SID %d, levels %d\n",
handle, rep->mip_levels[0]);
goto out_mip;
}
for (i=1; i < DRM_VMW_MAX_SURFACE_FACES; ++i) {
if (rep->mip_levels[i] != 0) {
vmw_error("Incorrect number of faces levels on shared surface."
" SID %d, face %d present.\n",
handle, i);
goto out_mip;
}
}
vsrf = CALLOC_STRUCT(vmw_svga_winsys_surface);
if (!vsrf)
goto out_mip;
pipe_reference_init(&vsrf->refcnt, 1);
p_atomic_set(&vsrf->validated, 0);
vsrf->screen = vws;
vsrf->sid = handle;
ssrf = svga_winsys_surface(vsrf);
*format = rep->format;
/* Estimate usage, for early flushing. */
base_size.width = size.width;
base_size.height = size.height;
base_size.depth = size.depth;
vsrf->size = vmw_surf_get_serialized_size(rep->format, base_size,
rep->mip_levels[0],
false);
return ssrf;
out_mip:
vmw_ioctl_surface_destroy(vws, handle);
return NULL;
}
static bool
vmw_drm_surface_get_handle(struct svga_winsys_screen *sws,
struct svga_winsys_surface *surface,

View file

@ -116,68 +116,6 @@ vmw_ioctl_context_destroy(struct vmw_winsys_screen *vws, uint32 cid)
}
uint32
vmw_ioctl_surface_create(struct vmw_winsys_screen *vws,
SVGA3dSurface1Flags flags,
SVGA3dSurfaceFormat format,
unsigned usage,
SVGA3dSize size,
uint32_t numFaces, uint32_t numMipLevels,
unsigned sampleCount)
{
union drm_vmw_surface_create_arg s_arg;
struct drm_vmw_surface_create_req *req = &s_arg.req;
struct drm_vmw_surface_arg *rep = &s_arg.rep;
struct drm_vmw_size sizes[DRM_VMW_MAX_SURFACE_FACES*
DRM_VMW_MAX_MIP_LEVELS];
struct drm_vmw_size *cur_size;
uint32_t iFace;
uint32_t iMipLevel;
int ret;
vmw_printf("%s flags %d format %d\n", __func__, flags, format);
memset(&s_arg, 0, sizeof(s_arg));
req->flags = (uint32_t) flags;
req->scanout = !!(usage & SVGA_SURFACE_USAGE_SCANOUT);
req->format = (uint32_t) format;
req->shareable = true;
assert(numFaces * numMipLevels < DRM_VMW_MAX_SURFACE_FACES*
DRM_VMW_MAX_MIP_LEVELS);
cur_size = sizes;
for (iFace = 0; iFace < numFaces; ++iFace) {
SVGA3dSize mipSize = size;
req->mip_levels[iFace] = numMipLevels;
for (iMipLevel = 0; iMipLevel < numMipLevels; ++iMipLevel) {
cur_size->width = mipSize.width;
cur_size->height = mipSize.height;
cur_size->depth = mipSize.depth;
mipSize.width = MAX2(mipSize.width >> 1, 1);
mipSize.height = MAX2(mipSize.height >> 1, 1);
mipSize.depth = MAX2(mipSize.depth >> 1, 1);
cur_size++;
}
}
for (iFace = numFaces; iFace < SVGA3D_MAX_SURFACE_FACES; ++iFace) {
req->mip_levels[iFace] = 0;
}
req->size_addr = (unsigned long)&sizes;
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_CREATE_SURFACE,
&s_arg, sizeof(s_arg));
if (ret)
return -1;
vmw_printf("Surface id is %d\n", rep->sid);
return rep->sid;
}
uint32
vmw_ioctl_gb_surface_create(struct vmw_winsys_screen *vws,
SVGA3dSurfaceAllFlags flags,
@ -911,55 +849,9 @@ static int
vmw_ioctl_parse_caps(struct vmw_winsys_screen *vws,
const uint32_t *cap_buffer)
{
int i;
if (vws->base.have_gb_objects) {
for (i = 0; i < vws->ioctl.num_cap_3d; ++i) {
vws->ioctl.cap_3d[i].has_cap = true;
vws->ioctl.cap_3d[i].result.u = cap_buffer[i];
}
return 0;
} else {
const uint32 *capsBlock;
const struct svga_3d_compat_cap *capsRecord = NULL;
uint32 offset;
const SVGA3dFifoCapPair *capArray;
int numCaps, index;
/*
* Search linearly through the caps block records for the specified type.
*/
capsBlock = cap_buffer;
for (offset = 0; capsBlock[offset] != 0; offset += capsBlock[offset]) {
const struct svga_3d_compat_cap *record;
assert(offset < SVGA_FIFO_3D_CAPS_SIZE);
record = (const struct svga_3d_compat_cap *) (capsBlock + offset);
if ((record->header.type >= 0) &&
(record->header.type <= SVGA3D_DEVCAP_MAX) &&
(!capsRecord || (record->header.type > capsRecord->header.type))) {
capsRecord = record;
}
}
if (!capsRecord)
return -1;
/*
* Calculate the number of caps from the size of the record.
*/
capArray = (const SVGA3dFifoCapPair *) capsRecord->pairs;
numCaps = (int) ((capsRecord->header.length * sizeof(uint32) -
sizeof capsRecord->header) / (2 * sizeof(uint32)));
for (i = 0; i < numCaps; i++) {
index = capArray[i][0];
if (index < vws->ioctl.num_cap_3d) {
vws->ioctl.cap_3d[index].has_cap = true;
vws->ioctl.cap_3d[index].result.u = capArray[i][1];
} else {
debug_printf("Unknown devcaps seen: %d\n", index);
}
}
for (int i = 0; i < vws->ioctl.num_cap_3d; ++i) {
vws->ioctl.cap_3d[i].has_cap = true;
vws->ioctl.cap_3d[i].result.u = cap_buffer[i];
}
return 0;
}
@ -973,7 +865,6 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws)
int ret;
uint32_t *cap_buffer;
drmVersionPtr version;
bool drm_gb_capable;
bool have_drm_2_5;
const char *getenv_val;
@ -1004,8 +895,6 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws)
vws->ioctl.drm_execbuf_version = vws->ioctl.have_drm_2_9 ? 2 : 1;
drm_gb_capable = have_drm_2_5;
memset(&gp_arg, 0, sizeof(gp_arg));
gp_arg.param = DRM_VMW_PARAM_3D;
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM,
@ -1025,23 +914,26 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws)
goto out_no_3d;
}
vws->ioctl.hwversion = gp_arg.value;
getenv_val = os_get_option("SVGA_FORCE_HOST_BACKED");
if (!getenv_val || strcmp(getenv_val, "0") == 0) {
memset(&gp_arg, 0, sizeof(gp_arg));
gp_arg.param = DRM_VMW_PARAM_HW_CAPS;
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM,
memset(&gp_arg, 0, sizeof(gp_arg));
gp_arg.param = DRM_VMW_PARAM_HW_CAPS;
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM,
&gp_arg, sizeof(gp_arg));
} else {
ret = -EINVAL;
}
if (ret)
vws->base.have_gb_objects = false;
else
vws->base.have_gb_objects =
!!(gp_arg.value & (uint64_t) SVGA_CAP_GBOBJECTS);
if (vws->base.have_gb_objects && !drm_gb_capable)
if (!have_drm_2_5) {
vmw_error("SVGA requires a vmwgfx kernel driver >= 2.5! 3D will be disabled.\n");
goto out_no_3d;
}
if (!vws->base.have_gb_objects) {
vmw_error("No GB Objects! 3D will be disabled.\n");
goto out_no_3d;
}
vws->base.have_vgpu10 = false;
vws->base.have_sm4_1 = false;
@ -1057,7 +949,7 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws)
vws->base.device_id = gp_arg.value;
}
if (vws->base.have_gb_objects) {
{
memset(&gp_arg, 0, sizeof(gp_arg));
gp_arg.param = DRM_VMW_PARAM_MAX_MOB_MEMORY;
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM,
@ -1150,10 +1042,7 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws)
else
size = gp_arg.value;
if (vws->base.have_gb_objects)
vws->ioctl.num_cap_3d = size / sizeof(uint32_t);
else
vws->ioctl.num_cap_3d = SVGA3D_DEVCAP_MAX;
vws->ioctl.num_cap_3d = size / sizeof(uint32_t);
if (vws->ioctl.have_drm_2_16) {
vws->base.have_coherent = true;
@ -1161,31 +1050,12 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws)
if (getenv_val && strcmp(getenv_val, "0") != 0)
vws->force_coherent = true;
}
} else {
vws->ioctl.num_cap_3d = SVGA3D_DEVCAP_MAX;
memset(&gp_arg, 0, sizeof(gp_arg));
gp_arg.param = DRM_VMW_PARAM_MAX_SURF_MEMORY;
if (have_drm_2_5)
ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM,
&gp_arg, sizeof(gp_arg));
if (!have_drm_2_5 || ret) {
/* Just guess a large enough value, around 800mb. */
vws->ioctl.max_surface_memory = 0x30000000;
} else {
vws->ioctl.max_surface_memory = gp_arg.value;
}
vws->ioctl.max_texture_size = VMW_MAX_DEFAULT_TEXTURE_SIZE;
size = SVGA_FIFO_3D_CAPS_SIZE * sizeof(uint32_t);
}
/* Userspace surfaces are only supported on guest-backed hardware */
vws->userspace_surface = false;
getenv_val = os_get_option("VMW_SVGA_USERSPACE_SURFACE");
if (getenv_val && atoi(getenv_val)) {
assert(vws->base.have_gb_objects);
assert(vws->base.have_vgpu10);
memset(&gp_arg, 0, sizeof(gp_arg));
gp_arg.param = DRM_VMW_PARAM_USER_SRF;

View file

@ -583,7 +583,7 @@ vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws,
}
swc->flush(swc, NULL);
} else if (sws->have_gb_objects) {
} else {
struct pb_buffer *pb_buf;
surface->sid = vmw_ioctl_gb_surface_create(vws, flags, format, usage,
@ -610,17 +610,6 @@ vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws,
vmw_ioctl_surface_destroy(vws, surface->sid);
goto no_sid;
}
} else {
/* Legacy surface only support 32-bit svga3d flags */
surface->sid = vmw_ioctl_surface_create(vws, (SVGA3dSurface1Flags)flags,
format, usage, size, numLayers,
numMipLevels, sampleCount);
if (surface->sid == SVGA3D_INVALID_ID)
goto no_sid;
/* Best estimate for surface size, used for early flushing. */
surface->size = buffer_size;
surface->buf = NULL;
}
return svga_winsys_surface(surface);
@ -692,12 +681,7 @@ vmw_svga_winsys_destroy(struct svga_winsys_screen *sws)
static SVGA3dHardwareVersion
vmw_svga_winsys_get_hw_version(struct svga_winsys_screen *sws)
{
struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
if (sws->have_gb_objects)
return SVGA3D_HWVERSION_WS8_B1;
return (SVGA3dHardwareVersion) vws->ioctl.hwversion;
return SVGA3D_HWVERSION_WS8_B1;
}