mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-08 02:38:04 +02:00
winsys/svga: Require Guest-Backed (GB) Objects
GB Object/Surface support was introduced over 10 years ago. SVGA devices without GB Objects only support up to GL 2.x which is not incredibly useful in 2026 as most applications that actually need 3D acceleration to run smoothly want GL 3.x or newer. Often times GL apps will simply crash if GL 3.x or greater support is not present. This effectively drops 3D support for Linux Guests running on VMware Virtual Hardware versions less than 11. This means the following VMware products and their predecessors will no longer have 3D support in Linux Guests after this commit. ESXi 5.5 Fusion 6.x Workstation 10.x Player 6.x A future change in the driver portion of the SVGA code that adopts this same requirement will drastically reduce and simply the code there. Signed-off-by: Ian Forbes <ian.forbes@broadcom.com>
This commit is contained in:
parent
2b9e491b67
commit
7e773c8aae
5 changed files with 22 additions and 297 deletions
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue