mirror of
https://github.com/X11Libre/xf86-video-vmware.git
synced 2026-03-24 01:24:37 +00:00
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>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -89,49 +91,6 @@ struct drm_vmw_getparam_arg {
|
||||
uint32_t pad64;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
/**
|
||||
* 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.
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
@@ -433,39 +404,6 @@ struct drm_vmw_unref_dmabuf_arg {
|
||||
uint32_t pad64;
|
||||
};
|
||||
|
||||
/*************************************************************************/
|
||||
/**
|
||||
* 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.
|
||||
@@ -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
|
||||
|
||||
@@ -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 drm_vmw_rect *rects, *r;
|
||||
|
||||
struct {
|
||||
SVGA3dCmdHeader header;
|
||||
SVGA3dRect 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 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));
|
||||
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;
|
||||
|
||||
rep.error = -EFAULT;
|
||||
arg.fence_rep = (unsigned long)&rep;
|
||||
arg.commands = (unsigned long)cmd;
|
||||
arg.command_size = size;
|
||||
arg.throttle_us = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user