summaryrefslogtreecommitdiffstats
path: root/src/VBox/Additions/3D/win/VBoxSVGA/winsys
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-11 08:17:27 +0000
commitf215e02bf85f68d3a6106c2a1f4f7f063f819064 (patch)
tree6bb5b92c046312c4e95ac2620b10ddf482d3fa8b /src/VBox/Additions/3D/win/VBoxSVGA/winsys
parentInitial commit. (diff)
downloadvirtualbox-upstream/7.0.14-dfsg.tar.xz
virtualbox-upstream/7.0.14-dfsg.zip
Adding upstream version 7.0.14-dfsg.upstream/7.0.14-dfsg
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Additions/3D/win/VBoxSVGA/winsys')
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/winsys/Makefile.kup0
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen.c134
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_ioctl.c979
-rw-r--r--src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_wddm.c177
4 files changed, 1290 insertions, 0 deletions
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/winsys/Makefile.kup b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/Makefile.kup
new file mode 100644
index 00000000..e69de29b
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/Makefile.kup
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen.c b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen.c
new file mode 100644
index 00000000..b96a37ce
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen.c
@@ -0,0 +1,134 @@
+/*
+ * Copyright (C) 2016-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+/**********************************************************
+ * Copyright 2009-2015 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+
+#include "../wddm_screen.h"
+#include "vmw_fence.h"
+#include "vmw_context.h"
+#include "vmwgfx_drm.h"
+
+#include "util/os_file.h"
+#include "util/u_memory.h"
+#include "pipe/p_compiler.h"
+#include "util/u_hash_table.h"
+
+/* Called from vmw_drm_create_screen(), creates and initializes the
+ * vmw_winsys_screen structure, which is the main entity in this
+ * module.
+ * First, check whether a vmw_winsys_screen object already exists for
+ * this device, and in that case return that one, making sure that we
+ * have our own file descriptor open to DRM.
+ */
+
+struct vmw_winsys_screen_wddm *
+vmw_winsys_create_wddm(const WDDMGalliumDriverEnv *pEnv)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm;
+ struct vmw_winsys_screen *vws;
+
+ if ( pEnv->pHWInfo == NULL
+ || pEnv->pHWInfo->u32HwType != VBOX_GA_HW_TYPE_VMSVGA)
+ return NULL;
+
+ vws_wddm = CALLOC_STRUCT(vmw_winsys_screen_wddm);
+ vws = &vws_wddm->base;
+ if (!vws)
+ goto out_no_vws;
+
+ vws_wddm->pEnv = pEnv;
+ vws_wddm->HwInfo = pEnv->pHWInfo->u.svga;
+
+ vws->device = 0; /* not used */
+ vws->open_count = 1;
+ vws->ioctl.drm_fd = -1; /* not used */
+ vws->force_coherent = FALSE;
+ if (!vmw_ioctl_init(vws))
+ goto out_no_ioctl;
+
+ vws->base.have_gb_dma = !vws->force_coherent;
+ vws->base.need_to_rebind_resources = FALSE;
+ vws->base.have_transfer_from_buffer_cmd = vws->base.have_vgpu10;
+ vws->base.have_constant_buffer_offset_cmd = FALSE;
+ vws->cache_maps = FALSE;
+ vws->fence_ops = vmw_fence_ops_create(vws);
+ if (!vws->fence_ops)
+ goto out_no_fence_ops;
+
+ if(!vmw_pools_init(vws))
+ goto out_no_pools;
+
+ if (!vmw_winsys_screen_init_svga(vws))
+ goto out_no_svga;
+
+ cnd_init(&vws->cs_cond);
+ mtx_init(&vws->cs_mutex, mtx_plain);
+
+ return vws_wddm;
+out_no_svga:
+ vmw_pools_cleanup(vws);
+out_no_pools:
+ vws->fence_ops->destroy(vws->fence_ops);
+out_no_fence_ops:
+ vmw_ioctl_cleanup(vws);
+out_no_ioctl:
+ FREE(vws);
+out_no_vws:
+ return NULL;
+}
+
+void
+vmw_winsys_destroy(struct vmw_winsys_screen *vws)
+{
+ if (--vws->open_count == 0) {
+ vmw_pools_cleanup(vws);
+ vws->fence_ops->destroy(vws->fence_ops);
+ vmw_ioctl_cleanup(vws);
+ mtx_destroy(&vws->cs_mutex);
+ cnd_destroy(&vws->cs_cond);
+ FREE(vws);
+ }
+}
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_ioctl.c b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_ioctl.c
new file mode 100644
index 00000000..106ff74a
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_ioctl.c
@@ -0,0 +1,979 @@
+/*
+ * Copyright (C) 2016-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+/**********************************************************
+ * Copyright 2009-2015 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+/**
+ * @file
+ *
+ * Wrappers for DRM ioctl functionlaity used by the rest of the vmw
+ * drm winsys.
+ *
+ * Based on svgaicd_escape.c
+ */
+
+
+#include "svga_cmd.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "svgadump/svga_dump.h"
+#include "frontend/drm_driver.h"
+#include "vmw_screen.h"
+#include "vmw_context.h"
+#include "vmw_fence.h"
+#include "vmwgfx_drm.h"
+#include "svga3d_caps.h"
+#include "svga3d_reg.h"
+#include "svga3d_surfacedefs.h"
+
+#include "../wddm_screen.h"
+#include <iprt/asm.h>
+
+#define VMW_MAX_DEFAULT_TEXTURE_SIZE (128 * 1024 * 1024)
+#define VMW_FENCE_TIMEOUT_SECONDS 3600UL
+
+#define SVGA3D_FLAGS_64(upper32, lower32) (((uint64_t)upper32 << 32) | lower32)
+#define SVGA3D_FLAGS_UPPER_32(svga3d_flags) (svga3d_flags >> 32)
+#define SVGA3D_FLAGS_LOWER_32(svga3d_flags) \
+ (svga3d_flags & ((uint64_t)UINT32_MAX))
+
+struct vmw_region
+{
+ uint32_t handle;
+ uint64_t map_handle;
+ void *data;
+ uint32_t map_count;
+ struct vmw_winsys_screen_wddm *vws_wddm;
+ uint32_t size;
+};
+
+uint32_t
+vmw_region_size(struct vmw_region *region)
+{
+ return region->size;
+}
+
+#if defined(__DragonFly__) || defined(__FreeBSD__) || \
+ defined(__NetBSD__) || defined(__OpenBSD__)
+#define ERESTART EINTR
+#endif
+
+uint32
+vmw_ioctl_context_create(struct vmw_winsys_screen *vws)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ return vws_wddm->pEnv->pfnContextCreate(vws_wddm->pEnv->pvEnv, false, false);
+}
+
+uint32
+vmw_ioctl_extended_context_create(struct vmw_winsys_screen *vws,
+ boolean vgpu10)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ return vws_wddm->pEnv->pfnContextCreate(vws_wddm->pEnv->pvEnv, true, vgpu10);
+}
+
+void
+vmw_ioctl_context_destroy(struct vmw_winsys_screen *vws, uint32 cid)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ vws_wddm->pEnv->pfnContextDestroy(vws_wddm->pEnv->pvEnv, 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)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+
+ GASURFCREATE createParms;
+ GASURFSIZE sizes[DRM_VMW_MAX_SURFACE_FACES*
+ DRM_VMW_MAX_MIP_LEVELS];
+ GASURFSIZE *cur_size;
+ uint32_t iFace;
+ uint32_t iMipLevel;
+ uint32_t u32Sid;
+ int ret;
+
+ RT_NOREF(sampleCount);
+
+ memset(&createParms, 0, sizeof(createParms));
+ createParms.flags = (uint32_t) flags;
+ createParms.format = (uint32_t) format;
+ createParms.usage = (uint32_t) usage;
+
+ if (numFaces * numMipLevels >= GA_MAX_SURFACE_FACES*GA_MAX_MIP_LEVELS) {
+ return (uint32_t)-1;
+ }
+ cur_size = sizes;
+ for (iFace = 0; iFace < numFaces; ++iFace) {
+ SVGA3dSize mipSize = size;
+
+ createParms.mip_levels[iFace] = numMipLevels;
+ for (iMipLevel = 0; iMipLevel < numMipLevels; ++iMipLevel) {
+ cur_size->cWidth = mipSize.width;
+ cur_size->cHeight = mipSize.height;
+ cur_size->cDepth = mipSize.depth;
+ cur_size->u32Reserved = 0;
+ 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) {
+ createParms.mip_levels[iFace] = 0;
+ }
+
+ ret = vws_wddm->pEnv->pfnSurfaceDefine(vws_wddm->pEnv->pvEnv, &createParms, &sizes[0], numFaces * numMipLevels, &u32Sid);
+ if (ret) {
+ return (uint32_t)-1;
+ }
+
+ return u32Sid;
+}
+
+
+uint32
+vmw_ioctl_gb_surface_create(struct vmw_winsys_screen *vws,
+ SVGA3dSurfaceAllFlags flags,
+ SVGA3dSurfaceFormat format,
+ unsigned usage,
+ SVGA3dSize size,
+ uint32_t numFaces,
+ uint32_t numMipLevels,
+ unsigned sampleCount,
+ uint32_t buffer_handle,
+ SVGA3dMSPattern multisamplePattern,
+ SVGA3dMSQualityLevel qualityLevel,
+ struct vmw_region **p_region)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+
+ struct vmw_region *region = NULL;
+ if (p_region)
+ {
+ region = CALLOC_STRUCT(vmw_region);
+ if (!region)
+ return SVGA3D_INVALID_ID;
+ }
+
+ SVGAGBSURFCREATE createParms;
+ createParms.s.flags = flags;
+ createParms.s.format = format;
+ createParms.s.usage = usage;
+ createParms.s.size = size;
+ createParms.s.numFaces = numFaces;
+ createParms.s.numMipLevels = numMipLevels;
+ createParms.s.sampleCount = sampleCount;
+ createParms.s.multisamplePattern = multisamplePattern;
+ createParms.s.qualityLevel = qualityLevel;
+ if (buffer_handle)
+ createParms.gmrid = buffer_handle;
+ else
+ createParms.gmrid = SVGA3D_INVALID_ID;
+ createParms.u64UserAddress = 0; /* out */
+ createParms.u32Sid = 0; /* out */
+
+ createParms.cbGB = svga3dsurface_get_serialized_size(format,
+ size,
+ numMipLevels,
+ numFaces);
+
+ int ret = vws_wddm->pEnv->pfnGBSurfaceDefine(vws_wddm->pEnv->pvEnv, &createParms);
+ if (ret)
+ {
+ FREE(region);
+ return SVGA3D_INVALID_ID;
+ }
+
+ if (p_region)
+ {
+ region->handle = createParms.gmrid;
+ region->map_handle = 0;
+ region->data = (void *)(uintptr_t)createParms.u64UserAddress;
+ region->map_count = 0;
+ region->size = createParms.cbGB;
+ region->vws_wddm = vws_wddm;
+ *p_region = region;
+ }
+ return createParms.u32Sid;
+}
+
+/**
+ * vmw_ioctl_surface_req - Fill in a struct surface_req
+ *
+ * @vws: Winsys screen
+ * @whandle: Surface handle
+ * @req: The struct surface req to fill in
+ * @needs_unref: This call takes a kernel surface reference that needs to
+ * be unreferenced.
+ *
+ * Returns 0 on success, negative error type otherwise.
+ * Fills in the surface_req structure according to handle type and kernel
+ * capabilities.
+ */
+static int
+vmw_ioctl_surface_req(const struct vmw_winsys_screen *vws,
+ const struct winsys_handle *whandle,
+ struct drm_vmw_surface_arg *req,
+ boolean *needs_unref)
+{
+ ASMBreakpoint();
+ RT_NOREF4(vws, whandle, req, needs_unref);
+ return -1;
+}
+
+/**
+ * vmw_ioctl_gb_surface_ref - Put a reference on a guest-backed surface and
+ * get surface information
+ *
+ * @vws: Screen to register the reference on
+ * @handle: Kernel handle of the guest-backed surface
+ * @flags: flags used when the surface was created
+ * @format: Format used when the surface was created
+ * @numMipLevels: Number of mipmap levels of the surface
+ * @p_region: On successful return points to a newly allocated
+ * struct vmw_region holding a reference to the surface backup buffer.
+ *
+ * Returns 0 on success, a system error on failure.
+ */
+int
+vmw_ioctl_gb_surface_ref(struct vmw_winsys_screen *vws,
+ const struct winsys_handle *whandle,
+ SVGA3dSurfaceAllFlags *flags,
+ SVGA3dSurfaceFormat *format,
+ uint32_t *numMipLevels,
+ uint32_t *handle,
+ struct vmw_region **p_region)
+{
+ ASMBreakpoint();
+ RT_NOREF7(vws, whandle, flags, format, numMipLevels, handle, p_region);
+ return -1;
+}
+
+void
+vmw_ioctl_surface_destroy(struct vmw_winsys_screen *vws, uint32 sid)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ vws_wddm->pEnv->pfnSurfaceDestroy(vws_wddm->pEnv->pvEnv, sid);
+}
+
+void
+vmw_ioctl_command(struct vmw_winsys_screen *vws, int32_t cid,
+ uint32_t throttle_us, void *commands, uint32_t size,
+ struct pipe_fence_handle **pfence, int32_t imported_fence_fd,
+ uint32_t flags)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ GAFENCEQUERY FenceQuery;
+ RT_NOREF3(throttle_us, imported_fence_fd, flags);
+#ifdef DEBUG
+ // svga_dump_commands(commands, size);
+#endif
+ memset(&FenceQuery, 0, sizeof(FenceQuery));
+ FenceQuery.u32FenceStatus = GA_FENCE_STATUS_NULL;
+
+ vws_wddm->pEnv->pfnRender(vws_wddm->pEnv->pvEnv, cid, commands, size, pfence? &FenceQuery: NULL);
+ if (FenceQuery.u32FenceStatus == GA_FENCE_STATUS_NULL)
+ {
+ /*
+ * Kernel has already synced, or caller requested no fence.
+ */
+ if (pfence)
+ *pfence = NULL;
+ }
+ else
+ {
+ if (pfence)
+ {
+ vmw_fences_signal(vws->fence_ops, FenceQuery.u32ProcessedSeqNo, FenceQuery.u32SubmittedSeqNo, TRUE);
+
+ *pfence = vmw_fence_create(vws->fence_ops, FenceQuery.u32FenceHandle,
+ FenceQuery.u32SubmittedSeqNo, /* mask */ 0, -1);
+ if (*pfence == NULL)
+ {
+ /*
+ * Fence creation failed. Need to sync.
+ */
+ (void) vmw_ioctl_fence_finish(vws, FenceQuery.u32FenceHandle, /* mask */ 0);
+ vmw_ioctl_fence_unref(vws, FenceQuery.u32FenceHandle);
+ }
+ }
+ }
+}
+
+
+struct vmw_region *
+vmw_ioctl_region_create(struct vmw_winsys_screen *vws, uint32_t size)
+{
+ /* 'region' is a buffer visible both for host and guest */
+ struct vmw_region *region;
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ uint32_t u32GmrId = 0;
+ void *pvMap = NULL;
+ int ret;
+
+ region = CALLOC_STRUCT(vmw_region);
+ if (!region)
+ goto out_err1;
+
+ ret = vws_wddm->pEnv->pfnRegionCreate(vws_wddm->pEnv->pvEnv, size, &u32GmrId, &pvMap);
+
+ if (ret) {
+ vmw_error("IOCTL failed %d: %s\n", ret, strerror(-ret));
+ goto out_err1;
+ }
+
+ region->handle = u32GmrId;
+ region->map_handle = 0;
+ region->data = pvMap;
+ region->map_count = 0;
+ region->size = size;
+ region->vws_wddm = vws_wddm;
+
+ return region;
+
+out_err1:
+ FREE(region);
+ return NULL;
+}
+
+void
+vmw_ioctl_region_destroy(struct vmw_region *region)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = region->vws_wddm;
+
+ vws_wddm->pEnv->pfnRegionDestroy(vws_wddm->pEnv->pvEnv, region->handle, region->data);
+
+ FREE(region);
+}
+
+SVGAGuestPtr
+vmw_ioctl_region_ptr(struct vmw_region *region)
+{
+ SVGAGuestPtr ptr = {region->handle, 0};
+ return ptr;
+}
+
+void *
+vmw_ioctl_region_map(struct vmw_region *region)
+{
+ debug_printf("%s: gmrId = %u\n", __FUNCTION__,
+ region->handle);
+
+ if (region->data == NULL)
+ {
+ /* Should not get here. */
+ return NULL;
+ }
+
+ ++region->map_count;
+
+ return region->data;
+}
+
+void
+vmw_ioctl_region_unmap(struct vmw_region *region)
+{
+ --region->map_count;
+}
+
+/**
+ * vmw_ioctl_syncforcpu - Synchronize a buffer object for CPU usage
+ *
+ * @region: Pointer to a struct vmw_region representing the buffer object.
+ * @dont_block: Dont wait for GPU idle, but rather return -EBUSY if the
+ * GPU is busy with the buffer object.
+ * @readonly: Hint that the CPU access is read-only.
+ * @allow_cs: Allow concurrent command submission while the buffer is
+ * synchronized for CPU. If FALSE command submissions referencing the
+ * buffer will block until a corresponding call to vmw_ioctl_releasefromcpu.
+ *
+ * This function idles any GPU activities touching the buffer and blocks
+ * command submission of commands referencing the buffer, even from
+ * other processes.
+ */
+int
+vmw_ioctl_syncforcpu(struct vmw_region *region,
+ boolean dont_block,
+ boolean readonly,
+ boolean allow_cs)
+{
+ ASMBreakpoint();
+ RT_NOREF4(region, dont_block, readonly, allow_cs);
+ return -1;
+}
+
+/**
+ * vmw_ioctl_releasefromcpu - Undo a previous syncforcpu.
+ *
+ * @region: Pointer to a struct vmw_region representing the buffer object.
+ * @readonly: Should hold the same value as the matching syncforcpu call.
+ * @allow_cs: Should hold the same value as the matching syncforcpu call.
+ */
+void
+vmw_ioctl_releasefromcpu(struct vmw_region *region,
+ boolean readonly,
+ boolean allow_cs)
+{
+ ASMBreakpoint();
+ RT_NOREF3(region, readonly, allow_cs);
+ return;
+}
+
+void
+vmw_ioctl_fence_unref(struct vmw_winsys_screen *vws,
+ uint32_t handle)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ vws_wddm->pEnv->pfnFenceUnref(vws_wddm->pEnv->pvEnv, handle);
+}
+
+static inline uint32_t
+vmw_drm_fence_flags(uint32_t flags)
+{
+ uint32_t dflags = 0;
+
+ if (flags & SVGA_FENCE_FLAG_EXEC)
+ dflags |= DRM_VMW_FENCE_FLAG_EXEC;
+ if (flags & SVGA_FENCE_FLAG_QUERY)
+ dflags |= DRM_VMW_FENCE_FLAG_QUERY;
+
+ return dflags;
+}
+
+
+int
+vmw_ioctl_fence_signalled(struct vmw_winsys_screen *vws,
+ uint32_t handle,
+ uint32_t flags)
+{
+ RT_NOREF(flags);
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+ GAFENCEQUERY FenceQuery;
+ int ret;
+
+ memset(&FenceQuery, 0, sizeof(FenceQuery));
+ FenceQuery.u32FenceStatus = GA_FENCE_STATUS_NULL;
+
+ ret = vws_wddm->pEnv->pfnFenceQuery(vws_wddm->pEnv->pvEnv, handle, &FenceQuery);
+
+ if (ret != 0)
+ return ret;
+
+ if (FenceQuery.u32FenceStatus == GA_FENCE_STATUS_NULL)
+ return 0; /* Treat as signalled. */
+
+ vmw_fences_signal(vws->fence_ops, FenceQuery.u32ProcessedSeqNo, FenceQuery.u32SubmittedSeqNo, TRUE);
+
+ return FenceQuery.u32FenceStatus == GA_FENCE_STATUS_SIGNALED ? 0 : -1;
+}
+
+
+
+int
+vmw_ioctl_fence_finish(struct vmw_winsys_screen *vws,
+ uint32_t handle,
+ uint32_t flags)
+{
+ RT_NOREF(flags);
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+
+ vws_wddm->pEnv->pfnFenceWait(vws_wddm->pEnv->pvEnv, handle, VMW_FENCE_TIMEOUT_SECONDS*1000000);
+
+ return 0; /* Regardless. */
+}
+
+uint32
+vmw_ioctl_shader_create(struct vmw_winsys_screen *vws,
+ SVGA3dShaderType type,
+ uint32 code_len)
+{
+ ASMBreakpoint();
+ RT_NOREF3(vws, type, code_len);
+ return 0;
+}
+
+void
+vmw_ioctl_shader_destroy(struct vmw_winsys_screen *vws, uint32 shid)
+{
+ ASMBreakpoint();
+ RT_NOREF2(vws, shid);
+ return;
+}
+
+static int
+vmw_ioctl_parse_caps(struct vmw_winsys_screen *vws,
+ const uint32_t *cap_buffer)
+{
+ unsigned 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 SVGA3dCapsRecord *capsRecord = NULL;
+ uint32 offset;
+ const SVGA3dCapPair *capArray;
+ unsigned 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 SVGA3dCapsRecord *record;
+ if (offset >= SVGA_FIFO_3D_CAPS_SIZE)
+ break;
+ record = (const SVGA3dCapsRecord *) (capsBlock + offset);
+ if ((record->header.type >= SVGA3DCAPS_RECORD_DEVCAPS_MIN) &&
+ (record->header.type <= SVGA3DCAPS_RECORD_DEVCAPS_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 SVGA3dCapPair *) capsRecord->data;
+ 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);
+ }
+ }
+ }
+ return 0;
+}
+
+#define SVGA_CAP2_DX2 0x00000004
+#define SVGA_CAP2_DX3 0x00000400
+
+enum SVGASHADERMODEL
+{
+ SVGA_SM_LEGACY = 0,
+ SVGA_SM_4,
+ SVGA_SM_4_1,
+ SVGA_SM_5,
+ SVGA_SM_MAX
+};
+
+static enum SVGASHADERMODEL vboxGetShaderModel(struct vmw_winsys_screen_wddm *vws_wddm)
+{
+#if 0
+ (void)vws_wddm;
+ return SVGA_SM_5;
+#else
+ enum SVGASHADERMODEL enmResult = SVGA_SM_LEGACY;
+
+ if ( (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_GBOBJECTS)
+ && (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_CMD_BUFFERS_3 /*=SVGA_CAP_DX*/)
+ && vws_wddm->HwInfo.au32Caps[SVGA3D_DEVCAP_DXCONTEXT])
+ {
+ enmResult = SVGA_SM_4;
+
+ if (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_CAP2_REGISTER)
+ {
+ if ( (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAP2] & SVGA_CAP2_DX2)
+ && vws_wddm->HwInfo.au32Caps[SVGA3D_DEVCAP_SM41])
+ {
+ enmResult = SVGA_SM_4_1;
+
+ if ( (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAP2] & SVGA_CAP2_DX3)
+ && vws_wddm->HwInfo.au32Caps[SVGA3D_DEVCAP_SM5])
+ {
+ enmResult = SVGA_SM_5;
+ }
+ }
+ }
+ }
+
+ return enmResult;
+#endif
+}
+
+static int
+vboxGetParam(struct vmw_winsys_screen_wddm *vws_wddm, struct drm_vmw_getparam_arg *gp_arg)
+{
+ /* DRM_VMW_GET_PARAM */
+ switch (gp_arg->param)
+ {
+ case DRM_VMW_PARAM_NUM_STREAMS:
+ gp_arg->value = 1; /* not used */
+ break;
+ case DRM_VMW_PARAM_NUM_FREE_STREAMS:
+ gp_arg->value = 1; /* not used */
+ break;
+ case DRM_VMW_PARAM_3D:
+ gp_arg->value = (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_3D) != 0;
+ break;
+ case DRM_VMW_PARAM_HW_CAPS:
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES];
+ break;
+ case DRM_VMW_PARAM_FIFO_CAPS:
+ gp_arg->value = vws_wddm->HwInfo.au32Fifo[SVGA_FIFO_CAPABILITIES];
+ break;
+ case DRM_VMW_PARAM_MAX_FB_SIZE:
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_MAX_PRIMARY_BOUNDING_BOX_MEM];
+ break;
+ case DRM_VMW_PARAM_FIFO_HW_VERSION:
+ if (vws_wddm->HwInfo.au32Fifo[SVGA_FIFO_CAPABILITIES] & SVGA_FIFO_CAP_3D_HWVERSION_REVISED)
+ {
+ gp_arg->value =
+ vws_wddm->HwInfo.au32Fifo[SVGA_FIFO_3D_HWVERSION_REVISED];
+ }
+ else
+ {
+ gp_arg->value =
+ vws_wddm->HwInfo.au32Fifo[SVGA_FIFO_3D_HWVERSION];
+ }
+ break;
+ case DRM_VMW_PARAM_MAX_SURF_MEMORY:
+ if (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_GBOBJECTS)
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB] * 1024 / 2;
+ else
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_MEMORY_SIZE];
+ break;
+ case DRM_VMW_PARAM_3D_CAPS_SIZE:
+ if (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_GBOBJECTS)
+ gp_arg->value = SVGA3D_DEVCAP_MAX * sizeof(uint32_t);
+ else
+ gp_arg->value = (SVGA_FIFO_3D_CAPS_LAST - SVGA_FIFO_3D_CAPS + 1) * sizeof(uint32_t);
+ break;
+ case DRM_VMW_PARAM_MAX_MOB_MEMORY:
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_SUGGESTED_GBOBJECT_MEM_SIZE_KB] * 1024;
+ break;
+ case DRM_VMW_PARAM_MAX_MOB_SIZE:
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_MOB_MAX_SIZE];
+ break;
+ case DRM_VMW_PARAM_SCREEN_TARGET:
+ gp_arg->value = 1; /* not used */
+ break;
+ case DRM_VMW_PARAM_DX:
+ gp_arg->value = (vboxGetShaderModel(vws_wddm) >= SVGA_SM_4);
+ break;
+ case DRM_VMW_PARAM_HW_CAPS2:
+ if (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_CAP2_REGISTER)
+ gp_arg->value = vws_wddm->HwInfo.au32Regs[SVGA_REG_CAP2];
+ else
+ gp_arg->value = 0;
+ break;
+ case DRM_VMW_PARAM_SM4_1:
+ gp_arg->value = (vboxGetShaderModel(vws_wddm) >= SVGA_SM_4_1);
+ break;
+ case DRM_VMW_PARAM_SM5:
+ gp_arg->value = (vboxGetShaderModel(vws_wddm) >= SVGA_SM_5);
+ break;
+ default: return -1;
+ }
+ return 0;
+}
+
+static int
+vboxGet3DCap(struct vmw_winsys_screen_wddm *vws_wddm, void *pvCap, size_t cbCap)
+{
+ /* DRM_VMW_GET_3D_CAP */
+ if (vws_wddm->HwInfo.au32Regs[SVGA_REG_CAPABILITIES] & SVGA_CAP_GBOBJECTS)
+ memcpy(pvCap, vws_wddm->HwInfo.au32Caps, cbCap);
+ else
+ memcpy(pvCap, &vws_wddm->HwInfo.au32Fifo[SVGA_FIFO_3D_CAPS], cbCap);
+ return 0;
+}
+
+boolean
+vmw_ioctl_init(struct vmw_winsys_screen *vws)
+{
+ struct vmw_winsys_screen_wddm *vws_wddm = (struct vmw_winsys_screen_wddm *)vws;
+
+ struct drm_vmw_getparam_arg gp_arg;
+ unsigned int size;
+ int ret;
+ uint32_t *cap_buffer;
+ boolean drm_gb_capable;
+ boolean have_drm_2_5;
+
+ VMW_FUNC;
+
+ have_drm_2_5 = 1;
+ vws->ioctl.have_drm_2_6 = 1;
+ vws->ioctl.have_drm_2_9 = 1;
+ vws->ioctl.have_drm_2_15 = 1;
+ vws->ioctl.have_drm_2_16 = 1;
+ vws->ioctl.have_drm_2_17 = 1;
+ vws->ioctl.have_drm_2_18 = 1;
+ vws->ioctl.have_drm_2_19 = 1;
+
+ 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 = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret || gp_arg.value == 0) {
+ vmw_error("No 3D enabled (%i, %s).\n", ret, strerror(-ret));
+ goto out_no_3d;
+ }
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_FIFO_HW_VERSION;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret) {
+ vmw_error("Failed to get fifo hw version (%i, %s).\n",
+ ret, strerror(-ret));
+ goto out_no_3d;
+ }
+ vws->ioctl.hwversion = gp_arg.value;
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_HW_CAPS;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ 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)
+ goto out_no_3d;
+
+ vws->base.have_vgpu10 = FALSE;
+ vws->base.have_sm4_1 = FALSE;
+ vws->base.have_intra_surface_copy = FALSE;
+
+ if (vws->base.have_gb_objects) {
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_MAX_MOB_MEMORY;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret) {
+ /* Just guess a large enough value. */
+ vws->ioctl.max_mob_memory = 256*1024*1024;
+ } else {
+ vws->ioctl.max_mob_memory = gp_arg.value;
+ }
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_MAX_MOB_SIZE;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+
+ if (ret || gp_arg.value == 0) {
+ vws->ioctl.max_texture_size = VMW_MAX_DEFAULT_TEXTURE_SIZE;
+ } else {
+ vws->ioctl.max_texture_size = gp_arg.value;
+ }
+
+ /* Never early flush surfaces, mobs do accounting. */
+ vws->ioctl.max_surface_memory = -1;
+
+ if (vws->ioctl.have_drm_2_9) {
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_DX;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret == 0 && gp_arg.value != 0) {
+ const char *vgpu10_val;
+
+ debug_printf("Have VGPU10 interface and hardware.\n");
+ vws->base.have_vgpu10 = TRUE;
+ vgpu10_val = getenv("SVGA_VGPU10");
+ if (vgpu10_val && strcmp(vgpu10_val, "0") == 0) {
+ debug_printf("Disabling VGPU10 interface.\n");
+ vws->base.have_vgpu10 = FALSE;
+ } else {
+ debug_printf("Enabling VGPU10 interface.\n");
+ }
+ }
+ }
+
+ if (vws->ioctl.have_drm_2_15 && vws->base.have_vgpu10) {
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_HW_CAPS2;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret == 0 && gp_arg.value != 0) {
+ vws->base.have_intra_surface_copy = TRUE;
+ }
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_SM4_1;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret == 0 && gp_arg.value != 0) {
+ vws->base.have_sm4_1 = TRUE;
+ }
+ }
+
+ if (vws->ioctl.have_drm_2_18 && vws->base.have_sm4_1) {
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_SM5;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret == 0 && gp_arg.value != 0) {
+ vws->base.have_sm5 = TRUE;
+ }
+ }
+
+ memset(&gp_arg, 0, sizeof(gp_arg));
+ gp_arg.param = DRM_VMW_PARAM_3D_CAPS_SIZE;
+ ret = vboxGetParam(vws_wddm, &gp_arg);
+ if (ret)
+ size = SVGA_FIFO_3D_CAPS_SIZE * sizeof(uint32_t);
+ 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;
+
+ if (vws->ioctl.have_drm_2_16) {
+ vws->base.have_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 = vboxGetParam(vws_wddm, &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);
+ }
+
+ debug_printf("VGPU10 interface is %s.\n",
+ vws->base.have_vgpu10 ? "on" : "off");
+
+ cap_buffer = calloc(1, size);
+ if (!cap_buffer) {
+ debug_printf("Failed alloc fifo 3D caps buffer.\n");
+ goto out_no_3d;
+ }
+
+ vws->ioctl.cap_3d = calloc(vws->ioctl.num_cap_3d,
+ sizeof(*vws->ioctl.cap_3d));
+ if (!vws->ioctl.cap_3d) {
+ debug_printf("Failed alloc fifo 3D caps buffer.\n");
+ goto out_no_caparray;
+ }
+
+ /*
+ * This call must always be after DRM_VMW_PARAM_MAX_MOB_MEMORY and
+ * DRM_VMW_PARAM_SM4_1. This is because, based on these calls, kernel
+ * driver sends the supported cap.
+ */
+ ret = vboxGet3DCap(vws_wddm, cap_buffer, size);
+
+ if (ret) {
+ debug_printf("Failed to get 3D capabilities"
+ " (%i, %s).\n", ret, strerror(-ret));
+ goto out_no_caps;
+ }
+
+ ret = vmw_ioctl_parse_caps(vws, cap_buffer);
+ if (ret) {
+ debug_printf("Failed to parse 3D capabilities"
+ " (%i, %s).\n", ret, strerror(-ret));
+ goto out_no_caps;
+ }
+
+ if (vws->ioctl.have_drm_2_15 && vws->base.have_vgpu10) {
+
+ /* support for these commands didn't make it into vmwgfx kernel
+ * modules before 2.10.
+ */
+ vws->base.have_generate_mipmap_cmd = TRUE;
+ vws->base.have_set_predication_cmd = TRUE;
+ }
+
+ if (vws->ioctl.have_drm_2_15) {
+ vws->base.have_fence_fd = TRUE;
+ }
+
+ free(cap_buffer);
+ vmw_printf("%s OK\n", __FUNCTION__);
+ return TRUE;
+ out_no_caps:
+ free(vws->ioctl.cap_3d);
+ out_no_caparray:
+ free(cap_buffer);
+ out_no_3d:
+ vws->ioctl.num_cap_3d = 0;
+ debug_printf("%s Failed\n", __FUNCTION__);
+ return FALSE;
+}
+
+
+
+void
+vmw_ioctl_cleanup(struct vmw_winsys_screen *vws)
+{
+ VMW_FUNC;
+
+ free(vws->ioctl.cap_3d);
+}
diff --git a/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_wddm.c b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_wddm.c
new file mode 100644
index 00000000..16b0ac21
--- /dev/null
+++ b/src/VBox/Additions/3D/win/VBoxSVGA/winsys/vmw_screen_wddm.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2016-2023 Oracle and/or its affiliates.
+ *
+ * This file is part of VirtualBox base platform packages, as
+ * available from https://www.virtualbox.org.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, in version 3 of the
+ * License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-only
+ */
+
+/**********************************************************
+ * Copyright 2009-2015 VMware, Inc. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use, copy,
+ * modify, merge, publish, distribute, sublicense, and/or sell copies
+ * of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ **********************************************************/
+
+
+#include "pipe/p_compiler.h"
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+
+#include "vmw_context.h"
+#include "vmw_screen.h"
+#include "vmw_surface.h"
+#include "vmw_buffer.h"
+#include "svga_drm_public.h"
+#include "svga3d_surfacedefs.h"
+
+#include "frontend/drm_driver.h"
+
+#include "vmwgfx_drm.h"
+
+#include "../wddm_screen.h"
+
+#include <iprt/asm.h>
+
+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,
+ SVGA3dSurfaceFormat *format);
+static boolean
+vmw_drm_surface_get_handle(struct svga_winsys_screen *sws,
+ struct svga_winsys_surface *surface,
+ unsigned stride,
+ struct winsys_handle *whandle);
+
+struct vmw_winsys_screen_wddm *
+vmw_winsys_create_wddm(const WDDMGalliumDriverEnv *pEnv);
+
+/* This is actually the entrypoint to the entire driver,
+ * called by the target bootstrap code.
+ */
+struct svga_winsys_screen *
+svga_wddm_winsys_screen_create(const WDDMGalliumDriverEnv *pEnv)
+{
+ struct vmw_winsys_screen_wddm *vws;
+
+ if (pEnv->cb < sizeof(WDDMGalliumDriverEnv))
+ goto out_no_vws;
+
+ vws = vmw_winsys_create_wddm(pEnv);
+ if (!vws)
+ goto out_no_vws;
+
+ /* XXX do this properly */
+ vws->base.base.surface_from_handle = vws->base.base.have_gb_objects ?
+ vmw_drm_gb_surface_from_handle : vmw_drm_surface_from_handle;
+ vws->base.base.surface_get_handle = vmw_drm_surface_get_handle;
+
+ return &vws->base.base;
+
+out_no_vws:
+ return NULL;
+}
+
+static struct svga_winsys_surface *
+vmw_drm_gb_surface_from_handle(struct svga_winsys_screen *sws,
+ struct winsys_handle *whandle,
+ SVGA3dSurfaceFormat *format)
+{
+ RT_NOREF3(sws, whandle, format);
+ return 0;
+}
+
+static struct svga_winsys_surface *
+vmw_drm_surface_from_handle(struct svga_winsys_screen *sws,
+ struct winsys_handle *whandle,
+ SVGA3dSurfaceFormat *format)
+{
+ RT_NOREF3(sws, whandle, format);
+ return 0;
+}
+
+/*
+ * The user mode driver asks the kernel driver to create a resource
+ * (vmw_ioctl_surface_create) and gets a sid (surface id).
+ * This function is supposed to convert the sid to a handle (file descriptor)
+ * which can be used to access the surface.
+ */
+static boolean
+vmw_drm_surface_get_handle(struct svga_winsys_screen *sws,
+ struct svga_winsys_surface *surface,
+ unsigned stride,
+ struct winsys_handle *whandle)
+{
+ struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
+ struct vmw_svga_winsys_surface *vsrf;
+
+ RT_NOREF(vws);
+
+ if (!surface)
+ return FALSE;
+
+ vsrf = vmw_svga_winsys_surface(surface);
+ whandle->handle = vsrf->sid;
+ whandle->stride = stride;
+ whandle->offset = 0;
+
+ switch (whandle->type) {
+ case WINSYS_HANDLE_TYPE_SHARED:
+ case WINSYS_HANDLE_TYPE_KMS:
+ whandle->handle = vsrf->sid;
+ break;
+ case WINSYS_HANDLE_TYPE_FD:
+ whandle->handle = vsrf->sid; /// @todo will this be enough for WDDM?
+ break;
+ default:
+ vmw_error("Attempt to export unsupported handle type %d.\n",
+ whandle->type);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+vmw_svga_winsys_host_log(struct svga_winsys_screen *sws, const char *log)
+{
+ (void)sws;
+ _debug_printf("%s\n", log);
+}