summaryrefslogtreecommitdiff
path: root/vmwgfx
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2011-09-01 13:59:10 +0200
committerThomas Hellstrom <thellstrom@vmware.com>2011-09-29 20:30:21 +0200
commit5c43481aa639053bbbf7fbf5f72f0edecf616731 (patch)
tree7b9596ab7bf9d364f81fd5f5b95e4f21b8ac646e /vmwgfx
parent3c2f9cc43f7d36952e78d10d224da0ba68ecefea (diff)
vmwgfx: Adapt to vmwgfx kernel driver 2.1
This introduces fence objects with 2.0, and present / present readback ioctls with 2.1. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Jakob Bornecrantz <jakob@vmware.com>
Diffstat (limited to 'vmwgfx')
-rw-r--r--vmwgfx/vmwgfx_driver.c36
-rw-r--r--vmwgfx/vmwgfx_driver.h7
-rw-r--r--vmwgfx/vmwgfx_drm.h313
-rw-r--r--vmwgfx/vmwgfx_drmi.c181
-rw-r--r--vmwgfx/vmwgfx_drmi.h6
-rw-r--r--vmwgfx/vmwgfx_saa.c6
6 files changed, 335 insertions, 214 deletions
diff --git a/vmwgfx/vmwgfx_driver.c b/vmwgfx/vmwgfx_driver.c
index a682e55..42d33ab 100644
--- a/vmwgfx/vmwgfx_driver.c
+++ b/vmwgfx/vmwgfx_driver.c
@@ -60,6 +60,8 @@
#include "vmwgfx_saa.h"
#define XA_VERSION_MINOR_REQUIRED 0
+#define DRM_VERSION_MAJOR_REQUIRED 2
+#define DRM_VERSION_MINOR_REQUIRED 1
/*
* Some macros to deal with function wrapping.
@@ -268,8 +270,22 @@ drv_init_drm(ScrnInfoPtr pScrn)
ms->isMaster = TRUE;
free(BusID);
- if (ms->fd >= 0)
+ if (ms->fd >= 0) {
+ drmVersionPtr ver = drmGetVersion(ms->fd);
+
+ if (ver == NULL) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "Could not determine DRM version.\n");
+ return FALSE;
+ }
+
+ ms->drm_major = ver->version_major;
+ ms->drm_minor = ver->version_minor;
+ ms->drm_patch = ver->version_patchlevel;
+
+ drmFreeVersion(ver);
return TRUE;
+ }
return FALSE;
}
@@ -338,6 +354,22 @@ drv_pre_init(ScrnInfoPtr pScrn, int flags)
if (!drv_init_drm(pScrn))
return FALSE;
+ if (ms->drm_major != DRM_VERSION_MAJOR_REQUIRED ||
+ ms->drm_minor < DRM_VERSION_MINOR_REQUIRED) {
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "DRM driver version is %d.%d.%d\n",
+ ms->drm_major, ms->drm_minor, ms->drm_patch);
+ xf86DrvMsg(pScrn->scrnIndex, X_ERROR,
+ "But this driver needs %d.%d.x to work. Giving up.\n",
+ DRM_VERSION_MAJOR_REQUIRED,
+ DRM_VERSION_MINOR_REQUIRED);
+ return FALSE;
+ } else {
+ xf86DrvMsg(pScrn->scrnIndex, X_PROBED,
+ "DRM driver version is %d.%d.%d\n",
+ ms->drm_major, ms->drm_minor, ms->drm_patch);
+ }
+
ms->check_fb_size = (vmwgfx_max_fb_size(ms->fd, &ms->max_fb_size) == 0);
pScrn->monitor = pScrn->confScreen->monitor;
@@ -515,7 +547,7 @@ vmwgfx_scanout_present(ScreenPtr pScreen, int drm_fd,
return FALSE;
}
- if (vmwgfx_present(drm_fd, 0, 0, dirty, handle) != 0) {
+ if (vmwgfx_present(drm_fd, vpix->fb_id, 0, 0, dirty, handle) != 0) {
LogMessage(X_ERROR, "Could not get present surface handle.\n");
return FALSE;
}
diff --git a/vmwgfx/vmwgfx_driver.h b/vmwgfx/vmwgfx_driver.h
index 8b3017d..c672b62 100644
--- a/vmwgfx/vmwgfx_driver.h
+++ b/vmwgfx/vmwgfx_driver.h
@@ -74,6 +74,9 @@ typedef struct _modesettingRec
{
/* drm */
int fd;
+ int drm_major;
+ int drm_minor;
+ int drm_patch;
/* X */
EntPtr entityPrivate;
@@ -166,10 +169,6 @@ vmw_video_init_adaptor(ScrnInfoPtr pScrn);
void
vmw_video_free_adaptor(XF86VideoAdaptorPtr adaptor, Bool free_ports);
-int
-vmwgfx_present(int drm_fd, unsigned int dst_x, unsigned int dst_y,
- RegionPtr region, uint32_t handle);
-
void
vmw_ctrl_ext_init(ScrnInfoPtr pScrn);
diff --git a/vmwgfx/vmwgfx_drm.h b/vmwgfx/vmwgfx_drm.h
index 650e6bf..bad47a7 100644
--- a/vmwgfx/vmwgfx_drm.h
+++ b/vmwgfx/vmwgfx_drm.h
@@ -31,7 +31,6 @@
#define DRM_VMW_MAX_SURFACE_FACES 6
#define DRM_VMW_MAX_MIP_LEVELS 24
-#define DRM_VMW_EXT_NAME_LEN 128
#define DRM_VMW_GET_PARAM 0
#define DRM_VMW_ALLOC_DMABUF 1
@@ -48,10 +47,13 @@
#define DRM_VMW_UNREF_SURFACE 10
#define DRM_VMW_REF_SURFACE 11
#define DRM_VMW_EXECBUF 12
-#define DRM_VMW_FIFO_DEBUG 13
+#define DRM_VMW_GET_3D_CAP 13
#define DRM_VMW_FENCE_WAIT 14
-/* guarded by minor version >= 2 */
-#define DRM_VMW_UPDATE_LAYOUT 15
+#define DRM_VMW_FENCE_SIGNALED 15
+#define DRM_VMW_FENCE_UNREF 16
+#define DRM_VMW_FENCE_EVENT 17
+#define DRM_VMW_PRESENT 18
+#define DRM_VMW_PRESENT_READBACK 19
/*************************************************************************/
@@ -69,10 +71,10 @@
#define DRM_VMW_PARAM_NUM_STREAMS 0
#define DRM_VMW_PARAM_NUM_FREE_STREAMS 1
#define DRM_VMW_PARAM_3D 2
-#define DRM_VMW_PARAM_FIFO_OFFSET 3
-#define DRM_VMW_PARAM_HW_CAPS 4
-#define DRM_VMW_PARAM_FIFO_CAPS 5
-#define DRM_VMW_PARAM_MAX_FB_SIZE 6
+#define DRM_VMW_PARAM_HW_CAPS 3
+#define DRM_VMW_PARAM_FIFO_CAPS 4
+#define DRM_VMW_PARAM_MAX_FB_SIZE 5
+#define DRM_VMW_PARAM_FIFO_HW_VERSION 6
/**
* struct drm_vmw_getparam_arg
@@ -91,49 +93,6 @@ struct drm_vmw_getparam_arg {
/*************************************************************************/
/**
- * DRM_VMW_EXTENSION - Query device extensions.
- */
-
-/**
- * struct drm_vmw_extension_rep
- *
- * @exists: The queried extension exists.
- * @driver_ioctl_offset: Ioctl number of the first ioctl in the extension.
- * @driver_sarea_offset: Offset to any space in the DRI SAREA
- * used by the extension.
- * @major: Major version number of the extension.
- * @minor: Minor version number of the extension.
- * @pl: Patch level version number of the extension.
- *
- * Output argument to the DRM_VMW_EXTENSION Ioctl.
- */
-
-struct drm_vmw_extension_rep {
- int32_t exists;
- uint32_t driver_ioctl_offset;
- uint32_t driver_sarea_offset;
- uint32_t major;
- uint32_t minor;
- uint32_t pl;
- uint32_t pad64;
-};
-
-/**
- * union drm_vmw_extension_arg
- *
- * @extension - Ascii name of the extension to be queried. //In
- * @rep - Reply as defined above. //Out
- *
- * Argument to the DRM_VMW_EXTENSION Ioctl.
- */
-
-union drm_vmw_extension_arg {
- char extension[DRM_VMW_EXT_NAME_LEN];
- struct drm_vmw_extension_rep rep;
-};
-
-/*************************************************************************/
-/**
* DRM_VMW_CREATE_CONTEXT - Create a host context.
*
* Allocates a device unique context id, and queues a create context command
@@ -292,7 +251,7 @@ union drm_vmw_surface_reference_arg {
* DRM_VMW_EXECBUF
*
* Submit a command buffer for execution on the host, and return a
- * fence sequence that when signaled, indicates that the command buffer has
+ * fence seqno that when signaled, indicates that the command buffer has
* executed.
*/
@@ -314,21 +273,30 @@ union drm_vmw_surface_reference_arg {
* Argument to the DRM_VMW_EXECBUF Ioctl.
*/
-#define DRM_VMW_EXECBUF_VERSION 0
+#define DRM_VMW_EXECBUF_VERSION 1
struct drm_vmw_execbuf_arg {
uint64_t commands;
uint32_t command_size;
uint32_t throttle_us;
uint64_t fence_rep;
- uint32_t version;
- uint32_t flags;
+ uint32_t version;
+ uint32_t flags;
};
/**
* struct drm_vmw_fence_rep
*
- * @fence_seq: Fence sequence associated with a command submission.
+ * @handle: Fence object handle for fence associated with a command submission.
+ * @mask: Fence flags relevant for this fence object.
+ * @seqno: Fence sequence number in fifo. A fence object with a lower
+ * seqno will signal the EXEC flag before a fence object with a higher
+ * seqno. This can be used by user-space to avoid kernel calls to determine
+ * whether a fence has signaled the EXEC flag. Note that @seqno will
+ * wrap at 32-bit.
+ * @passed_seqno: The highest seqno number processed by the hardware
+ * so far. This can be used to mark user-space fence objects as signaled, and
+ * to determine whether a fence seqno might be stale.
* @error: This member should've been set to -EFAULT on submission.
* The following actions should be take on completion:
* error == -EFAULT: Fence communication failed. The host is synchronized.
@@ -342,9 +310,12 @@ struct drm_vmw_execbuf_arg {
*/
struct drm_vmw_fence_rep {
- uint64_t fence_seq;
- int32_t error;
+ uint32_t handle;
+ uint32_t mask;
+ uint32_t seqno;
+ uint32_t passed_seqno;
uint32_t pad64;
+ int32_t error;
};
/*************************************************************************/
@@ -435,39 +406,6 @@ struct drm_vmw_unref_dmabuf_arg {
/*************************************************************************/
/**
- * DRM_VMW_FIFO_DEBUG - Get last FIFO submission.
- *
- * This IOCTL copies the last FIFO submission directly out of the FIFO buffer.
- */
-
-/**
- * struct drm_vmw_fifo_debug_arg
- *
- * @debug_buffer: User space address of a debug_buffer cast to an uint64_t //In
- * @debug_buffer_size: Size in bytes of debug buffer //In
- * @used_size: Number of bytes copied to the buffer // Out
- * @did_not_fit: Boolean indicating that the fifo contents did not fit. //Out
- *
- * Argument to the DRM_VMW_FIFO_DEBUG Ioctl.
- */
-
-struct drm_vmw_fifo_debug_arg {
- uint64_t debug_buffer;
- uint32_t debug_buffer_size;
- uint32_t used_size;
- int32_t did_not_fit;
- uint32_t pad64;
-};
-
-struct drm_vmw_fence_wait_arg {
- uint64_t sequence;
- uint64_t kernel_cookie;
- int32_t cookie_valid;
- int32_t pad64;
-};
-
-/*************************************************************************/
-/**
* DRM_VMW_CONTROL_STREAM - Control overlays, aka streams.
*
* This IOCTL controls the overlay units of the svga device.
@@ -590,26 +528,197 @@ struct drm_vmw_stream_arg {
/*************************************************************************/
/**
- * DRM_VMW_UPDATE_LAYOUT - Update layout
+ * DRM_VMW_GET_3D_CAP
+ *
+ * Read 3D capabilities from the FIFO
*
- * Updates the prefered modes and connection status for connectors. The
- * command conisits of one drm_vmw_update_layout_arg pointing out a array
- * of num_outputs drm_vmw_rect's.
*/
/**
- * struct drm_vmw_update_layout_arg
+ * struct drm_vmw_get_3d_cap_arg
*
- * @num_outputs: number of active
- * @rects: pointer to array of drm_vmw_rect
+ * @buffer: Pointer to a buffer for capability data, cast to an uint64_t
+ * @size: Max size to copy
*
- * Input argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
+ * Input argument to the DRM_VMW_GET_3D_CAP_IOCTL
+ * ioctls.
*/
-struct drm_vmw_update_layout_arg {
- uint32_t num_outputs;
+struct drm_vmw_get_3d_cap_arg {
+ uint64_t buffer;
+ uint32_t max_size;
uint32_t pad64;
- uint64_t rects;
};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_FENCE_WAIT
+ *
+ * Waits for a fence object to signal. The wait is interruptible, so that
+ * signals may be delivered during the interrupt. The wait may timeout,
+ * in which case the calls returns -EBUSY. If the wait is restarted,
+ * that is restarting without resetting @cookie_valid to zero,
+ * the timeout is computed from the first call.
+ *
+ * The flags argument to the DRM_VMW_FENCE_WAIT ioctl indicates what to wait
+ * on:
+ * DRM_VMW_FENCE_FLAG_EXEC: All commands ahead of the fence in the command
+ * stream
+ * have executed.
+ * DRM_VMW_FENCE_FLAG_QUERY: All query results resulting from query finish
+ * commands
+ * in the buffer given to the EXECBUF ioctl returning the fence object handle
+ * are available to user-space.
+ *
+ * DRM_VMW_WAIT_OPTION_UNREF: If this wait option is given, and the
+ * fenc wait ioctl returns 0, the fence object has been unreferenced after
+ * the wait.
+ */
+
+#define DRM_VMW_FENCE_FLAG_EXEC (1 << 0)
+#define DRM_VMW_FENCE_FLAG_QUERY (1 << 1)
+
+#define DRM_VMW_WAIT_OPTION_UNREF (1 << 0)
+
+/**
+ * struct drm_vmw_fence_wait_arg
+ *
+ * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl.
+ * @cookie_valid: Must be reset to 0 on first call. Left alone on restart.
+ * @kernel_cookie: Set to 0 on first call. Left alone on restart.
+ * @timeout_us: Wait timeout in microseconds. 0 for indefinite timeout.
+ * @lazy: Set to 1 if timing is not critical. Allow more than a kernel tick
+ * before returning.
+ * @flags: Fence flags to wait on.
+ * @wait_options: Options that control the behaviour of the wait ioctl.
+ *
+ * Input argument to the DRM_VMW_FENCE_WAIT ioctl.
+ */
+
+struct drm_vmw_fence_wait_arg {
+ uint32_t handle;
+ int32_t cookie_valid;
+ uint64_t kernel_cookie;
+ uint64_t timeout_us;
+ int32_t lazy;
+ int32_t flags;
+ int32_t wait_options;
+ int32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_FENCE_SIGNALED
+ *
+ * Checks if a fence object is signaled..
+ */
+
+/**
+ * struct drm_vmw_fence_signaled_arg
+ *
+ * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl.
+ * @flags: Fence object flags input to DRM_VMW_FENCE_SIGNALED ioctl
+ * @signaled: Out: Flags signaled.
+ * @sequence: Out: Highest sequence passed so far. Can be used to signal the
+ * EXEC flag of user-space fence objects.
+ *
+ * Input/Output argument to the DRM_VMW_FENCE_SIGNALED and DRM_VMW_FENCE_UNREF
+ * ioctls.
+ */
+
+struct drm_vmw_fence_signaled_arg {
+ uint32_t handle;
+ uint32_t flags;
+ int32_t signaled;
+ uint32_t passed_seqno;
+ uint32_t signaled_flags;
+ uint32_t pad64;
+};
+
+/*************************************************************************/
+/**
+ * DRM_VMW_FENCE_UNREF
+ *
+ * Unreferences a fence object, and causes it to be destroyed if there are no
+ * other references to it.
+ *
+ */
+
+/**
+ * struct drm_vmw_fence_arg
+ *
+ * @handle: Fence object handle as returned by the DRM_VMW_EXECBUF ioctl.
+ *
+ * Input/Output argument to the DRM_VMW_FENCE_UNREF ioctl..
+ */
+
+struct drm_vmw_fence_arg {
+ uint32_t handle;
+ uint32_t pad64;
+};
+
+
+/*************************************************************************/
+/**
+ * DRM_VMW_PRESENT
+ *
+ * Executes an SVGA present on a given fb for a given surface. The surface
+ * is placed on the framebuffer. Cliprects are given relative to the given
+ * point (the point disignated by dest_{x|y}).
+ *
+ */
+
+/**
+ * struct drm_vmw_present_arg
+ * @fb_id: framebuffer id to present / read back from.
+ * @sid: Surface id to present from.
+ * @dest_x: X placement coordinate for surface.
+ * @dest_y: Y placement coordinate for surface.
+ * @clips_ptr: Pointer to an array of clip rects cast to an uint64_t.
+ * @num_clips: Number of cliprects given relative to the framebuffer origin,
+ * in the same coordinate space as the frame buffer.
+ * @pad64: Unused 64-bit padding.
+ *
+ * Input argument to the DRM_VMW_PRESENT ioctl.
+ */
+
+struct drm_vmw_present_arg {
+ uint32_t fb_id;
+ uint32_t sid;
+ int32_t dest_x;
+ int32_t dest_y;
+ uint64_t clips_ptr;
+ uint32_t num_clips;
+ uint32_t pad64;
+};
+
+
+/*************************************************************************/
+/**
+ * DRM_VMW_PRESENT_READBACK
+ *
+ * Executes an SVGA present readback from a given fb to the dma buffer
+ * currently bound as the fb. If there is no dma buffer bound to the fb,
+ * an error will be returned.
+ *
+ */
+
+/**
+ * struct drm_vmw_present_arg
+ * @fb_id: fb_id to present / read back from.
+ * @num_clips: Number of cliprects.
+ * @clips_ptr: Pointer to an array of clip rects cast to an uint64_t.
+ * @fence_rep: Pointer to a struct drm_vmw_fence_rep, cast to an uint64_t.
+ * If this member is NULL, then the ioctl should not return a fence.
+ */
+
+struct drm_vmw_present_readback_arg {
+ uint32_t fb_id;
+ uint32_t num_clips;
+ uint64_t clips_ptr;
+ uint64_t fence_rep;
+};
+
+
#endif
diff --git a/vmwgfx/vmwgfx_drmi.c b/vmwgfx/vmwgfx_drmi.c
index f6b6f0b..44904a7 100644
--- a/vmwgfx/vmwgfx_drmi.c
+++ b/vmwgfx/vmwgfx_drmi.c
@@ -46,151 +46,138 @@
#include "vmwgfx_driver.h"
static int
-vmwgfx_fence_wait(int drm_fd, uint64_t seq)
+vmwgfx_fence_wait(int drm_fd, uint32_t handle, Bool unref)
{
struct drm_vmw_fence_wait_arg farg;
memset(&farg, 0, sizeof(farg));
- farg.sequence = seq;
+ farg.handle = handle;
+ farg.flags = DRM_VMW_FENCE_FLAG_EXEC;
+ farg.timeout_us = 10*1000000;
farg.cookie_valid = 0;
+ if (unref)
+ farg.wait_options |= DRM_VMW_WAIT_OPTION_UNREF;
+
return drmCommandWriteRead(drm_fd, DRM_VMW_FENCE_WAIT, &farg,
sizeof(farg));
}
+static void
+vmwgfx_fence_unref(int drm_fd, uint32_t handle)
+{
+ struct drm_vmw_fence_arg farg;
+ memset(&farg, 0, sizeof(farg));
+
+ farg.handle = handle;
+
+ (void) drmCommandWrite(drm_fd, DRM_VMW_FENCE_UNREF, &farg,
+ sizeof(farg));
+}
+
+
int
-vmwgfx_present_readback(int drm_fd, RegionPtr region)
+vmwgfx_present_readback(int drm_fd, uint32_t fb_id, RegionPtr region)
{
BoxPtr clips = REGION_RECTS(region);
unsigned int num_clips = REGION_NUM_RECTS(region);
- struct drm_vmw_execbuf_arg arg;
struct drm_vmw_fence_rep rep;
+ struct drm_vmw_present_readback_arg arg;
int ret;
- unsigned int size;
unsigned i;
- SVGA3dRect *cr;
-
- struct {
- SVGA3dCmdHeader header;
- SVGA3dRect cr;
- } *cmd;
+ struct drm_vmw_rect *rects, *r;
- if (num_clips == 0)
- return 0;
-
- size = sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr);
- cmd = malloc(size);
- if (!cmd)
+ rects = calloc(num_clips, sizeof(*rects));
+ if (!rects) {
+ LogMessage(X_ERROR, "Failed to alloc cliprects for "
+ "present readback.\n");
return -1;
-
- cmd->header.id = SVGA_3D_CMD_PRESENT_READBACK;
- cmd->header.size = num_clips * sizeof(cmd->cr);
-
- for (i=0, cr = &cmd->cr; i < num_clips; i++, cr++, clips++) {
- cr->x = (uint16_t) clips->x1;
- cr->y = (uint16_t) clips->y1;
- cr->w = (uint16_t) (clips->x2 - clips->x1);
- cr->h = (uint16_t) (clips->y2 - clips->y1);
-#if 0
- LogMessage(X_INFO,
- "Readback x: %u y: %u srcx: %u srcy: %u w: %u h: %u\n",
- cr->x, cr->y, cr->x, cr->y, cr->w, cr->h);
-#endif
}
-
memset(&arg, 0, sizeof(arg));
memset(&rep, 0, sizeof(rep));
+ arg.fb_id = fb_id;
+ arg.num_clips = num_clips;
+ arg.clips_ptr = (unsigned long) rects;
+ arg.fence_rep = (unsigned long) &rep;
rep.error = -EFAULT;
- arg.fence_rep = (unsigned long)&rep;
- arg.commands = (unsigned long)cmd;
- arg.command_size = size;
- arg.throttle_us = 0;
- ret = drmCommandWrite(drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg));
+ for (i = 0, r = rects; i < num_clips; ++i, ++r, ++clips) {
+ r->x = clips->x1;
+ r->y = clips->y1;
+ r->w = clips->x2 - clips->x1;
+ r->h = clips->y2 - clips->y1;
+ }
+
+ ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT_READBACK, &arg, sizeof(arg));
if (ret)
LogMessage(X_ERROR, "Present readback error %s.\n", strerror(-ret));
-
- free(cmd);
+ free(rects);
/*
* Sync to avoid racing with Xorg SW rendering.
*/
if (rep.error == 0) {
- ret = vmwgfx_fence_wait(drm_fd, rep.fence_seq);
- if (ret)
+ ret = vmwgfx_fence_wait(drm_fd, rep.handle, TRUE);
+ if (ret) {
LogMessage(X_ERROR, "Present readback fence wait error %s.\n",
strerror(-ret));
+ vmwgfx_fence_unref(drm_fd, rep.handle);
+ }
}
return 0;
}
+
int
-vmwgfx_present(int drm_fd, unsigned int dst_x, unsigned int dst_y,
- RegionPtr region, uint32_t handle)
+vmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x,
+ unsigned int dst_y, RegionPtr region, uint32_t handle)
{
BoxPtr clips = REGION_RECTS(region);
unsigned int num_clips = REGION_NUM_RECTS(region);
- struct drm_vmw_execbuf_arg arg;
- struct drm_vmw_fence_rep rep;
+ struct drm_vmw_present_arg arg;
+ unsigned int i;
+ struct drm_vmw_rect *rects, *r;
int ret;
- unsigned int size;
- unsigned i;
- SVGA3dCopyRect *cr;
-
- struct {
- SVGA3dCmdHeader header;
- SVGA3dCmdPresent body;
- SVGA3dCopyRect cr;
- } *cmd;
if (num_clips == 0)
return 0;
- size = sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cr);
- cmd = malloc(size);
- if (!cmd)
+ rects = calloc(num_clips, sizeof(*rects));
+ if (!rects) {
+ LogMessage(X_ERROR, "Failed to alloc cliprects for "
+ "present.\n");
return -1;
-
- cmd->header.id = SVGA_3D_CMD_PRESENT;
- cmd->header.size = sizeof(cmd->body) + num_clips * sizeof(cmd->cr);
- cmd->body.sid = handle;
-
-
- for (i=0, cr = &cmd->cr; i < num_clips; i++, cr++, clips++) {
- cr->x = (uint16_t) clips->x1 + dst_x;
- cr->y = (uint16_t) clips->y1 + dst_y;
- cr->srcx = (uint16_t) clips->x1;
- cr->srcy = (uint16_t) clips->y1;
- cr->w = (uint16_t) (clips->x2 - clips->x1);
- cr->h = (uint16_t) (clips->y2 - clips->y1);
-#if 0
- LogMessage(X_INFO, "Present: x: %u y: %u srcx: %u srcy: %u w: %u h: %u\n",
- cr->x, cr->y, cr->srcx, cr->srcy, cr->w, cr->h);
-#endif
}
memset(&arg, 0, sizeof(arg));
- memset(&rep, 0, sizeof(rep));
-
- rep.error = -EFAULT;
- arg.fence_rep = (unsigned long)&rep;
- arg.commands = (unsigned long)cmd;
- arg.command_size = size;
- arg.throttle_us = 0;
+ arg.fb_id = fb_id;
+ arg.sid = handle;
+ arg.dest_x = dst_x;
+ arg.dest_y = dst_y;
+ arg.num_clips = num_clips;
+ arg.clips_ptr = (unsigned long) rects;
+
+ for (i = 0, r = rects; i < num_clips; ++i, ++r, ++clips) {
+ r->x = clips->x1;
+ r->y = clips->y1;
+ r->w = clips->x2 - clips->x1;
+ r->h = clips->y2 - clips->y1;
+ }
- ret = drmCommandWrite(drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg));
+ ret = drmCommandWrite(drm_fd, DRM_VMW_PRESENT, &arg, sizeof(arg));
if (ret) {
LogMessage(X_ERROR, "Present error %s.\n", strerror(-ret));
}
- free(cmd);
- return 0;
+ free(rects);
+ return ((ret != 0) ? -1 : 0);
}
+
struct vmwgfx_int_dmabuf {
struct vmwgfx_dmabuf buf;
uint64_t map_handle;
@@ -374,10 +361,11 @@ vmwgfx_dma(unsigned int host_x, unsigned int host_y,
memset(&rep, 0, sizeof(rep));
rep.error = -EFAULT;
- arg.fence_rep = (unsigned long)&rep;
+ arg.fence_rep = ((to_surface) ? 0UL : (unsigned long)&rep);
arg.commands = (unsigned long)cmd;
arg.command_size = size;
arg.throttle_us = 0;
+ arg.version = DRM_VMW_EXECBUF_VERSION;
ret = drmCommandWrite(ibuf->drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg));
if (ret) {
@@ -386,11 +374,13 @@ vmwgfx_dma(unsigned int host_x, unsigned int host_y,
free(cmd);
- if (!to_surface && rep.error == 0) {
- ret = vmwgfx_fence_wait(ibuf->drm_fd, rep.fence_seq);
- if (ret)
+ if (rep.error == 0) {
+ ret = vmwgfx_fence_wait(ibuf->drm_fd, rep.handle, TRUE);
+ if (ret) {
LogMessage(X_ERROR, "DMA from host fence wait error %s.\n",
strerror(-ret));
+ vmwgfx_fence_unref(ibuf->drm_fd, rep.handle);
+ }
}
return 0;
@@ -485,23 +475,12 @@ vmwgfx_cursor_bypass(int drm_fd, int xhot, int yhot)
int
vmwgfx_max_fb_size(int drm_fd, size_t *size)
{
- drmVersionPtr ver;
- int ret = -1;
uint64_t tmp_size;
- ver = drmGetVersion(drm_fd);
- if (ver == NULL ||
- !(ver->version_major > 1 ||
- (ver->version_major == 1 && ver->version_minor >= 3)))
- goto out;
-
if (vmwgfx_get_param(drm_fd, DRM_VMW_PARAM_MAX_FB_SIZE, &tmp_size) != 0)
- goto out;
+ return -1;
*size = tmp_size;
- ret = 0;
- out:
- drmFreeVersion(ver);
- return ret;
+ return 0;
}
diff --git a/vmwgfx/vmwgfx_drmi.h b/vmwgfx/vmwgfx_drmi.h
index 0c92719..ba4c440 100644
--- a/vmwgfx/vmwgfx_drmi.h
+++ b/vmwgfx/vmwgfx_drmi.h
@@ -36,11 +36,11 @@
struct vmwgfx_dma_ctx;
extern int
-vmwgfx_present_readback(int drm_fd, RegionPtr region);
+vmwgfx_present_readback(int drm_fd, uint32_t fb_id, RegionPtr region);
extern int
-vmwgfx_present(int drm_fd, unsigned int dst_x, unsigned int dst_y,
- RegionPtr region, uint32_t handle);
+vmwgfx_present(int drm_fd, uint32_t fb_id, unsigned int dst_x,
+ unsigned int dst_y, RegionPtr region, uint32_t handle);
struct vmwgfx_dmabuf {
uint32_t handle;
diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c
index 41cea13..b0c8301 100644
--- a/vmwgfx/vmwgfx_saa.c
+++ b/vmwgfx/vmwgfx_saa.c
@@ -264,7 +264,8 @@ vmwgfx_pixmap_present_readback(struct vmwgfx_saa *vsaa,
REGION_INTERSECT(vsaa->pScreen, &screen_intersection,
&screen_intersection, &intersection);
- if (vmwgfx_present_readback(vsaa->drm_fd, &intersection) != 0)
+ if (vmwgfx_present_readback(vsaa->drm_fd, vpix->fb_id,
+ &intersection) != 0)
goto out_readback_err;
REGION_SUBTRACT(vsaa->pScreen, &intersection, &intersection,
@@ -926,7 +927,8 @@ vmwgfx_present_done(struct vmwgfx_saa *vsaa)
if (!vsaa->diff_valid)
return;
- (void) vmwgfx_present(vsaa->drm_fd, vsaa->xdiff, vsaa->ydiff,
+ (void) vmwgfx_present(vsaa->drm_fd, dst_vpix->fb_id,
+ vsaa->xdiff, vsaa->ydiff,
&vsaa->present_region, vsaa->src_handle);
REGION_TRANSLATE(pScreen, &vsaa->present_region, vsaa->xdiff, vsaa->ydiff);