summaryrefslogtreecommitdiff
path: root/vmwgfx
diff options
context:
space:
mode:
authorThomas Hellstrom <thellstrom@vmware.com>2013-12-11 04:59:49 -0800
committerThomas Hellstrom <thellstrom@vmware.com>2013-12-12 00:19:03 -0800
commit4af6062ce281a7f4aaa50985fe757e9569208ee1 (patch)
treef19817c59021896aa6bfe39aa1fee66b6e4e789b /vmwgfx
parentc36cbcefb8526944141eb431e1e736dc4485a36e (diff)
Revert "vmwgfx: Get rid of device-specific DMA code"
This reverts commit 45b2457516a9db4bd1d60fbb24a1efbe2d9dd932. Reverting this because using direct DMA for shared pixmaps should boost performance. It should be usable both in a composited environment and when running hosted. Need to retest the DMA flaws I saw before disabling this code. Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com> Reviewed-by: Jakob Bornecrantz <jakob@vmware.com>
Diffstat (limited to 'vmwgfx')
-rw-r--r--vmwgfx/vmwgfx_drmi.c103
-rw-r--r--vmwgfx/vmwgfx_drmi.h5
-rw-r--r--vmwgfx/vmwgfx_saa.c53
-rw-r--r--vmwgfx/vmwgfx_saa_priv.h1
4 files changed, 136 insertions, 26 deletions
diff --git a/vmwgfx/vmwgfx_drmi.c b/vmwgfx/vmwgfx_drmi.c
index 1e23f4a..496a16b 100644
--- a/vmwgfx/vmwgfx_drmi.c
+++ b/vmwgfx/vmwgfx_drmi.c
@@ -284,6 +284,109 @@ vmwgfx_dmabuf_destroy(struct vmwgfx_dmabuf *buf)
}
int
+vmwgfx_dma(unsigned int host_x, unsigned int host_y,
+ RegionPtr region, struct vmwgfx_dmabuf *buf,
+ uint32_t buf_pitch, uint32_t surface_handle, int to_surface)
+{
+ 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;
+ int ret;
+ unsigned int size;
+ unsigned i;
+ SVGA3dCopyBox *cb;
+ SVGA3dCmdSurfaceDMASuffix *suffix;
+ SVGA3dCmdSurfaceDMA *body;
+ struct vmwgfx_int_dmabuf *ibuf = vmwgfx_int_dmabuf(buf);
+
+ struct {
+ SVGA3dCmdHeader header;
+ SVGA3dCmdSurfaceDMA body;
+ SVGA3dCopyBox cb;
+ } *cmd;
+
+ if (num_clips == 0)
+ return 0;
+
+ size = sizeof(*cmd) + (num_clips - 1) * sizeof(cmd->cb) +
+ sizeof(*suffix);
+ cmd = malloc(size);
+ if (!cmd)
+ return -1;
+
+ cmd->header.id = SVGA_3D_CMD_SURFACE_DMA;
+ cmd->header.size = sizeof(cmd->body) + num_clips * sizeof(cmd->cb) +
+ sizeof(*suffix);
+ cb = &cmd->cb;
+
+ suffix = (SVGA3dCmdSurfaceDMASuffix *) &cb[num_clips];
+ suffix->suffixSize = sizeof(*suffix);
+ suffix->maximumOffset = (uint32_t) -1;
+ suffix->flags.discard = 0;
+ suffix->flags.unsynchronized = 0;
+ suffix->flags.reserved = 0;
+
+ body = &cmd->body;
+ body->guest.ptr.gmrId = buf->gmr_id;
+ body->guest.ptr.offset = buf->gmr_offset;
+ body->guest.pitch = buf_pitch;
+ body->host.sid = surface_handle;
+ body->host.face = 0;
+ body->host.mipmap = 0;
+
+ body->transfer = (to_surface ? SVGA3D_WRITE_HOST_VRAM :
+ SVGA3D_READ_HOST_VRAM);
+
+
+ for (i=0; i < num_clips; i++, cb++, clips++) {
+ cb->x = (uint16_t) clips->x1 + host_x;
+ cb->y = (uint16_t) clips->y1 + host_y;
+ cb->z = 0;
+ cb->srcx = (uint16_t) clips->x1;
+ cb->srcy = (uint16_t) clips->y1;
+ cb->srcz = 0;
+ cb->w = (uint16_t) (clips->x2 - clips->x1);
+ cb->h = (uint16_t) (clips->y2 - clips->y1);
+ cb->d = 1;
+#if 0
+ LogMessage(X_INFO, "DMA! x: %u y: %u srcx: %u srcy: %u w: %u h: %u %s\n",
+ cb->x, cb->y, cb->srcx, cb->srcy, cb->w, cb->h,
+ to_surface ? "to" : "from");
+#endif
+
+ }
+
+ memset(&arg, 0, sizeof(arg));
+ memset(&rep, 0, sizeof(rep));
+
+ rep.error = -EFAULT;
+ 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) {
+ LogMessage(X_ERROR, "DMA error %s.\n", strerror(-ret));
+ }
+
+ free(cmd);
+
+ 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;
+}
+
+int
vmwgfx_get_param(int drm_fd, uint32_t param, uint64_t *out)
{
struct drm_vmw_getparam_arg gp_arg;
diff --git a/vmwgfx/vmwgfx_drmi.h b/vmwgfx/vmwgfx_drmi.h
index fff728a..2435009 100644
--- a/vmwgfx/vmwgfx_drmi.h
+++ b/vmwgfx/vmwgfx_drmi.h
@@ -60,6 +60,11 @@ extern void
vmwgfx_dmabuf_unmap(struct vmwgfx_dmabuf *buf);
extern int
+vmwgfx_dma(unsigned int host_x, unsigned int host_y,
+ RegionPtr region, struct vmwgfx_dmabuf *buf,
+ uint32_t buf_pitch, uint32_t surface_handle, int to_surface);
+
+extern int
vmwgfx_num_streams(int drm_fd, uint32_t *ntot, uint32_t *nfree);
extern int
diff --git a/vmwgfx/vmwgfx_saa.c b/vmwgfx/vmwgfx_saa.c
index 28819c1..96275a5 100644
--- a/vmwgfx/vmwgfx_saa.c
+++ b/vmwgfx/vmwgfx_saa.c
@@ -285,40 +285,40 @@ vmwgfx_saa_dma(struct vmwgfx_saa *vsaa,
Bool to_hw)
{
struct vmwgfx_saa_pixmap *vpix = vmwgfx_saa_pixmap(pixmap);
- void *data = vpix->malloc;
- int ret;
if (!vpix->hw || (!vpix->gmr && !vpix->malloc))
return TRUE;
+ if (vpix->gmr && vsaa->can_optimize_dma) {
+ uint32_t handle, dummy;
- if (vpix->gmr) {
- data = vmwgfx_dmabuf_map(vpix->gmr);
- if (!data)
+ if (xa_surface_handle(vpix->hw, xa_handle_type_shared,
+ &handle, &dummy) != 0)
goto out_err;
- }
-
- ret = xa_surface_dma(vsaa->xa_ctx, vpix->hw, data, pixmap->devKind,
- (int) to_hw,
- (struct xa_box *) REGION_RECTS(reg),
- REGION_NUM_RECTS(reg));
- if (vpix->gmr)
- vmwgfx_dmabuf_unmap(vpix->gmr);
-
- if (ret)
- goto out_err;
+ if (vmwgfx_dma(0, 0, reg, vpix->gmr, pixmap->devKind, handle,
+ to_hw) != 0)
+ goto out_err;
+ } else {
+ void *data = vpix->malloc;
+ int ret;
- ret = xa_surface_dma(vsaa->xa_ctx, vpix->hw, data, pixmap->devKind,
- (int) to_hw,
- (struct xa_box *) REGION_RECTS(reg),
- REGION_NUM_RECTS(reg));
- if (to_hw)
- xa_context_flush(vsaa->xa_ctx);
- if (vpix->gmr)
- vmwgfx_dmabuf_unmap(vpix->gmr);
- if (ret)
- goto out_err;
+ if (vpix->gmr) {
+ data = vmwgfx_dmabuf_map(vpix->gmr);
+ if (!data)
+ goto out_err;
+ }
+ ret = xa_surface_dma(vsaa->xa_ctx, vpix->hw, data, pixmap->devKind,
+ (int) to_hw,
+ (struct xa_box *) REGION_RECTS(reg),
+ REGION_NUM_RECTS(reg));
+ if (to_hw)
+ xa_context_flush(vsaa->xa_ctx);
+ if (vpix->gmr)
+ vmwgfx_dmabuf_unmap(vpix->gmr);
+ if (ret)
+ goto out_err;
+ }
return TRUE;
out_err:
LogMessage(X_ERROR, "DMA %s surface failed.\n",
@@ -1377,6 +1377,7 @@ vmwgfx_saa_init(ScreenPtr pScreen, int drm_fd, struct xa_tracker *xat,
vsaa->xa_ctx = xa_context_default(xat);
vsaa->drm_fd = drm_fd;
vsaa->present_flush = present_flush;
+ vsaa->can_optimize_dma = FALSE;
vsaa->use_present_opt = direct_presents;
vsaa->only_hw_presents = only_hw_presents;
vsaa->rendercheck = rendercheck;
diff --git a/vmwgfx/vmwgfx_saa_priv.h b/vmwgfx/vmwgfx_saa_priv.h
index f5f45ba..16583b0 100644
--- a/vmwgfx/vmwgfx_saa_priv.h
+++ b/vmwgfx/vmwgfx_saa_priv.h
@@ -50,6 +50,7 @@ struct vmwgfx_saa {
int ydiff;
RegionRec present_region;
uint32_t src_handle;
+ Bool can_optimize_dma;
Bool use_present_opt;
Bool only_hw_presents;
Bool rendercheck;