winsys/svga: Update to vmwgfx kernel module 2.1
authorThomas Hellstrom <thellstrom@vmware.com>
Wed, 28 Sep 2011 07:13:50 +0000 (09:13 +0200)
committerThomas Hellstrom <thellstrom@vmware.com>
Thu, 29 Sep 2011 18:24:57 +0000 (20:24 +0200)
Introduces fence objecs and a size limit on query buffers.
The possibility to map the fifo from user-space is gone, and
replaced by an ioctl that reads the 3D capabilities.

Signed-off-by: Thomas Hellstrom <thellstrom@vmware.com>
Reviewed-by: Jakob Bornecranz <jakob@vmware.com>
src/gallium/drivers/svga/svga_pipe_query.c
src/gallium/drivers/svga/svga_winsys.h
src/gallium/winsys/svga/drm/vmw_context.c
src/gallium/winsys/svga/drm/vmw_fence.c
src/gallium/winsys/svga/drm/vmw_fence.h
src/gallium/winsys/svga/drm/vmw_screen.h
src/gallium/winsys/svga/drm/vmw_screen_dri.c
src/gallium/winsys/svga/drm/vmw_screen_ioctl.c
src/gallium/winsys/svga/drm/vmw_screen_pools.c
src/gallium/winsys/svga/drm/vmw_screen_svga.c
src/gallium/winsys/svga/drm/vmwgfx_drm.h

index 579f8034c7c8b45b5e658ac16c9ce089ac6a02ac..c44e0b8ec498af2a67d00a00d9ec4733695d9786 100644 (file)
@@ -241,7 +241,7 @@ static boolean svga_get_query_result(struct pipe_context *pipe,
       if(!wait)
          return FALSE;
    
-      sws->fence_finish(sws, sq->fence, 0);
+      sws->fence_finish(sws, sq->fence, SVGA_FENCE_FLAG_QUERY);
       
       state = sq->queryResult->state;
    }
index ae61cea083f11d0541469031d0c978327db22d85..d9560efea33b87975ab6110c2c896b3914f60b1d 100644 (file)
@@ -61,7 +61,8 @@ struct winsys_handle;
 #define SVGA_RELOC_WRITE 0x1
 #define SVGA_RELOC_READ  0x2
 
-
+#define SVGA_FENCE_FLAG_EXEC      (1 << 0)
+#define SVGA_FENCE_FLAG_QUERY     (1 << 1)
 
 /** Opaque surface handle */
 struct svga_winsys_surface;
index 633ef385a69f274dc08cc4bafbac1404b15491f3..666e198954bdd55908b9d65ec20ee22aef4b1ce8 100644 (file)
@@ -89,8 +89,6 @@ struct vmw_svga_winsys_context
 
    struct pb_validate *validate;
 
-   uint32_t last_fence;
-
    /**
     * The amount of GMR that is referred by the commands currently batched
     * in the context.
@@ -166,9 +164,7 @@ vmw_swc_flush(struct svga_winsys_context *swc,
                           throttle_us,
                            vswc->command.buffer,
                            vswc->command.used,
-                           &vswc->last_fence);
-
-      fence = vmw_pipe_fence(vswc->last_fence);
+                           &fence);
 
       pb_validate_fence(vswc->validate, fence);
    }
@@ -200,7 +196,9 @@ vmw_swc_flush(struct svga_winsys_context *swc,
    vswc->seen_regions = 0;
 
    if(pfence)
-      *pfence = fence;
+      vmw_fence_reference(vswc->vws, pfence, fence);
+
+   vmw_fence_reference(vswc->vws, &fence, NULL);
 
    return ret;
 }
index 873dd51166cdd06586c7d30450f0afdb906b2db2..754f8a666dfa6cf7a744cd909322961307fb3940 100644 (file)
@@ -1,5 +1,5 @@
 /**********************************************************
- * Copyright 2009 VMware, Inc.  All rights reserved.
+ * Copyright 2009-2011 VMware, Inc.  All rights reserved.
  *
  * Permission is hereby granted, free of charge, to any person
  * obtaining a copy of this software and associated documentation
  * SOFTWARE.
  *
  **********************************************************/
-
+/*
+ * TODO:
+ *
+ * Fencing is currently a bit inefficient, since we need to call the
+ * kernel do determine a fence object signaled status if the fence is not
+ * signaled. This can be greatly improved upon by using the fact that the
+ * execbuf ioctl returns the last signaled fence seqno, as does the
+ * fence signaled ioctl. We should set up a ring of fence objects and
+ * walk through them checking for signaled status each time we receive a
+ * new passed fence seqno.
+ */
 
 #include "util/u_memory.h"
+#include "util/u_atomic.h"
+
 #include "pipebuffer/pb_buffer_fenced.h"
 
 #include "vmw_screen.h"
 #include "vmw_fence.h"
 
-
-
 struct vmw_fence_ops 
 {
    struct pb_fence_ops base;
@@ -39,7 +49,57 @@ struct vmw_fence_ops
    struct vmw_winsys_screen *vws;
 };
 
+struct vmw_fence
+{
+   int32_t refcount;
+   uint32_t handle;
+   uint32_t mask;
+   int32_t signalled;
+};
 
+/**
+ * vmw_fence - return the vmw_fence object identified by a
+ * struct pipe_fence_handle *
+ *
+ * @fence: The opaque pipe fence handle.
+ */
+static INLINE struct vmw_fence *
+vmw_fence(struct pipe_fence_handle *fence)
+{
+   return (struct vmw_fence *) fence;
+}
+
+/**
+ * vmw_fence_create - Create a user-space fence object.
+ *
+ * @handle: Handle identifying the kernel fence object.
+ * @mask: Mask of flags that this fence object may signal.
+ *
+ * Returns NULL on failure.
+ */
+struct pipe_fence_handle *
+vmw_fence_create(uint32_t handle, uint32_t mask)
+{
+   struct vmw_fence *fence = CALLOC_STRUCT(vmw_fence);
+
+   if (!fence)
+      return NULL;
+
+   p_atomic_set(&fence->refcount, 1);
+   fence->handle = handle;
+   fence->mask = mask;
+   p_atomic_set(&fence->signalled, 0);
+
+   return (struct pipe_fence_handle *) fence;
+}
+
+/**
+ * vmw_fence_ops - Return the vmw_fence_ops structure backing a
+ * struct pb_fence_ops pointer.
+ *
+ * @ops: Pointer to a struct pb_fence_ops.
+ *
+ */
 static INLINE struct vmw_fence_ops *
 vmw_fence_ops(struct pb_fence_ops *ops)
 {
@@ -48,37 +108,182 @@ vmw_fence_ops(struct pb_fence_ops *ops)
 }
 
 
+
+/**
+ * vmw_fence_reference - Reference / unreference a vmw fence object.
+ *
+ * @vws: Pointer to the winsys screen.
+ * @ptr: Pointer to reference transfer destination.
+ * @fence: Pointer to object to reference. May be NULL.
+ */
+void
+vmw_fence_reference(struct vmw_winsys_screen *vws,
+                   struct pipe_fence_handle **ptr,
+                   struct pipe_fence_handle *fence)
+{
+   if (*ptr) {
+      struct vmw_fence *vfence = vmw_fence(*ptr);
+
+      if (p_atomic_dec_zero(&vfence->refcount)) {
+        vmw_ioctl_fence_unref(vws, vfence->handle);
+        FREE(vfence);
+      }
+   }
+
+   if (fence) {
+      struct vmw_fence *vfence = vmw_fence(fence);
+
+      p_atomic_inc(&vfence->refcount);
+   }
+
+   *ptr = fence;
+}
+
+
+/**
+ * vmw_fence_signalled - Check whether a fence object is signalled.
+ *
+ * @vws: Pointer to the winsys screen.
+ * @fence: Handle to the fence object.
+ * @flag: Fence flags to check. If the fence object can't signal
+ * a flag, it is assumed to be already signaled.
+ *
+ * Returns 0 if the fence object was signaled, nonzero otherwise.
+ */
+int
+vmw_fence_signalled(struct vmw_winsys_screen *vws,
+                  struct pipe_fence_handle *fence,
+                  unsigned flag)
+{
+   struct vmw_fence *vfence;
+   int32_t vflags = SVGA_FENCE_FLAG_EXEC;
+   int ret;
+   uint32_t old;
+
+   if (!fence)
+      return 0;
+
+   vfence = vmw_fence(fence);
+   old = p_atomic_read(&vfence->signalled);
+
+   vflags &= ~vfence->mask;
+
+   if ((old & vflags) == vflags)
+      return 0;
+
+   ret = vmw_ioctl_fence_signalled(vws, vfence->handle, vflags);
+
+   if (ret == 0) {
+      int32_t prev = old;
+
+      do {
+        old = prev;
+        prev = p_atomic_cmpxchg(&vfence->signalled, old, old | vflags);
+      } while (prev != old);
+   }
+
+   return ret;
+}
+
+/**
+ * vmw_fence_finish - Wait for a fence object to signal.
+ *
+ * @vws: Pointer to the winsys screen.
+ * @fence: Handle to the fence object.
+ * @flag: Fence flags to wait for. If the fence object can't signal
+ * a flag, it is assumed to be already signaled.
+ *
+ * Returns 0 if the wait succeeded. Nonzero otherwise.
+ */
+int
+vmw_fence_finish(struct vmw_winsys_screen *vws,
+                struct pipe_fence_handle *fence,
+                unsigned flag)
+{
+   struct vmw_fence *vfence;
+   int32_t vflags = SVGA_FENCE_FLAG_EXEC;
+   int ret;
+   uint32_t old;
+
+   if (!fence)
+      return 0;
+
+   vfence = vmw_fence(fence);
+   old = p_atomic_read(&vfence->signalled);
+   vflags &= ~vfence->mask;
+
+   if ((old & vflags) == vflags)
+      return 0;
+
+   ret = vmw_ioctl_fence_finish(vws, vfence->handle, vflags);
+
+   if (ret == 0) {
+      int32_t prev = old;
+
+      do {
+        old = prev;
+        prev = p_atomic_cmpxchg(&vfence->signalled, old, old | vflags);
+      } while (prev != old);
+   }
+
+   return ret;
+}
+
+
+/**
+ * vmw_fence_ops_fence_reference - wrapper for the pb_fence_ops api.
+ *
+ * wrapper around vmw_fence_reference.
+ */
 static void
 vmw_fence_ops_fence_reference(struct pb_fence_ops *ops,
                               struct pipe_fence_handle **ptr,
                               struct pipe_fence_handle *fence)
 {
-   *ptr = fence;
-}
+   struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
 
+   vmw_fence_reference(vws, ptr, fence);
+}
 
+/**
+ * vmw_fence_ops_fence_signalled - wrapper for the pb_fence_ops api.
+ *
+ * wrapper around vmw_fence_signalled.
+ */
 static int
 vmw_fence_ops_fence_signalled(struct pb_fence_ops *ops,
                               struct pipe_fence_handle *fence,
                               unsigned flag)
 {
    struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
-   (void)flag;
-   return vmw_ioctl_fence_signalled(vws, vmw_fence(fence));
+
+   return vmw_fence_signalled(vws, fence, flag);
 }
 
 
+/**
+ * vmw_fence_ops_fence_finish - wrapper for the pb_fence_ops api.
+ *
+ * wrapper around vmw_fence_finish.
+ */
 static int
 vmw_fence_ops_fence_finish(struct pb_fence_ops *ops,
                            struct pipe_fence_handle *fence,
                            unsigned flag)
 {
    struct vmw_winsys_screen *vws = vmw_fence_ops(ops)->vws;
-   (void)flag;
-   return vmw_ioctl_fence_finish(vws, vmw_fence(fence));
+
+   return vmw_fence_finish(vws, fence, flag);
 }
 
 
+/**
+ * vmw_fence_ops_destroy - Destroy a pb_fence_ops function table.
+ *
+ * @ops: The function table to destroy.
+ *
+ * Part of the pb_fence_ops api.
+ */
 static void
 vmw_fence_ops_destroy(struct pb_fence_ops *ops)
 {
@@ -86,6 +291,16 @@ vmw_fence_ops_destroy(struct pb_fence_ops *ops)
 }
 
 
+/**
+ * vmw_fence_ops_create - Create a pb_fence_ops function table.
+ *
+ * @vws: Pointer to a struct vmw_winsys_screen.
+ *
+ * Returns a pointer to a pb_fence_ops function table to interface
+ * with pipe_buffer. This function is typically called on driver setup.
+ *
+ * Returns NULL on failure.
+ */
 struct pb_fence_ops *
 vmw_fence_ops_create(struct vmw_winsys_screen *vws) 
 {
index 5357b4f61deb05f538ca8b2ab908a94b5f230438..403ae266d5e81ee08a700c98302ac6176b48a10d 100644 (file)
@@ -36,24 +36,25 @@ struct pb_fence_ops;
 struct vmw_winsys_screen;
 
 
-/** Cast from a pipe_fence_handle pointer into a SVGA fence */
-static INLINE uint32_t
-vmw_fence( struct pipe_fence_handle *fence )
-{
-   return (uint32_t)(uintptr_t)fence;
-}
-
-
-/** Cast from a SVGA fence number to pipe_fence_handle pointer */
-static INLINE struct pipe_fence_handle *
-vmw_pipe_fence( uint32_t fence )
-{
-   return (struct pipe_fence_handle *)(uintptr_t)fence;
-}
-
+struct pipe_fence_handle *
+vmw_fence_create(uint32_t handle, uint32_t mask);
+
+int
+vmw_fence_finish(struct vmw_winsys_screen *vws,
+                struct pipe_fence_handle *fence,
+                unsigned flag);
+int
+vmw_fence_signalled(struct vmw_winsys_screen *vws,
+                   struct pipe_fence_handle *fence,
+                   unsigned flag);
+void
+vmw_fence_reference(struct vmw_winsys_screen *vws,
+                   struct pipe_fence_handle **ptr,
+                   struct pipe_fence_handle *fence);
 
 struct pb_fence_ops *
 vmw_fence_ops_create(struct vmw_winsys_screen *vws); 
 
 
+
 #endif /* VMW_FENCE_H_ */
index b3de72df881dbb8c29a35c5f912830e4288c630e..37ccc91dc0e818080c6d5f60d33e9307219d9a55 100644 (file)
@@ -42,7 +42,7 @@
 
 
 #define VMW_GMR_POOL_SIZE (16*1024*1024)
-
+#define VMW_QUERY_POOL_SIZE (8192)
 
 struct pb_manager;
 struct vmw_region;
@@ -56,15 +56,18 @@ struct vmw_winsys_screen
    uint32_t default_throttle_us;
 
    struct {
-      volatile uint32_t *fifo_map;
-      uint64_t last_fence;
       int drm_fd;
+      uint32_t hwversion;
+      uint32_t *buffer;
    } ioctl;
 
    struct {
       struct pb_manager *gmr;
       struct pb_manager *gmr_mm;
       struct pb_manager *gmr_fenced;
+      struct pb_manager *query;
+      struct pb_manager *query_mm;
+      struct pb_manager *query_fenced;
    } pools;
 };
 
@@ -101,7 +104,7 @@ vmw_ioctl_command(struct vmw_winsys_screen *vws,
                  uint32_t throttle_us,
                  void *commands,
                  uint32_t size,
-                 uint32_t *fence);
+                 struct pipe_fence_handle **fence);
 
 struct vmw_region *
 vmw_ioctl_region_create(struct vmw_winsys_screen *vws, uint32_t size);
@@ -120,17 +123,22 @@ vmw_ioctl_region_unmap(struct vmw_region *region);
 
 int
 vmw_ioctl_fence_finish(struct vmw_winsys_screen *vws,
-                       uint32_t fence);
+                       uint32_t handle, uint32_t flags);
 
 int
 vmw_ioctl_fence_signalled(struct vmw_winsys_screen *vws,
-                          uint32_t fence);
+                          uint32_t handle, uint32_t flags);
+
+void
+vmw_ioctl_fence_unref(struct vmw_winsys_screen *vws,
+                     uint32_t handle);
 
 
 /* Initialize parts of vmw_winsys_screen at startup:
  */
 boolean vmw_ioctl_init(struct vmw_winsys_screen *vws);
 boolean vmw_pools_init(struct vmw_winsys_screen *vws);
+boolean vmw_query_pools_init(struct vmw_winsys_screen *vws);
 boolean vmw_winsys_screen_init_svga(struct vmw_winsys_screen *vws);
 
 void vmw_ioctl_cleanup(struct vmw_winsys_screen *vws);
index 258084a1f10581a6fc40d9bc67934698b6129257..3c92bb9b87eeb77e1939d63023f644d0c6536615 100644 (file)
@@ -56,9 +56,8 @@ vmw_drm_surface_get_handle(struct svga_winsys_screen *sws,
                           unsigned stride,
                           struct winsys_handle *whandle);
 
-static struct dri1_api_version drm_required = { 1, 0, 0 };
-static struct dri1_api_version drm_compat = { 1, 0, 0 };
-static struct dri1_api_version drm_scanout = { 0, 9, 0 };
+static struct dri1_api_version drm_required = { 2, 1, 0 };
+static struct dri1_api_version drm_compat = { 2, 0, 0 };
 
 static boolean
 vmw_dri1_check_version(const struct dri1_api_version *cur,
@@ -88,8 +87,6 @@ struct svga_winsys_screen *
 svga_drm_winsys_screen_create(int fd)
 {
    struct vmw_winsys_screen *vws;
-   boolean use_old_scanout_flag = FALSE;
-
    struct dri1_api_version drm_ver;
    drmVersionPtr ver;
 
@@ -106,11 +103,7 @@ svga_drm_winsys_screen_create(int fd)
                               &drm_compat, "vmwgfx drm driver"))
       return NULL;
 
-   if (!vmw_dri1_check_version(&drm_ver, &drm_scanout,
-                              &drm_compat, "use old scanout field (not a error)"))
-      use_old_scanout_flag = TRUE;
-
-   vws = vmw_winsys_create( fd, use_old_scanout_flag );
+   vws = vmw_winsys_create( fd, FALSE );
    if (!vws)
       goto out_no_vws;
 
index afdbd44458d3084e9a28f812dbaee31fc8996161..e3b183a2ac1c35ac03749af82773e2a41d06d117 100644 (file)
 #include "svgadump/svga_dump.h"
 #include "vmw_screen.h"
 #include "vmw_context.h"
+#include "vmw_fence.h"
 #include "xf86drm.h"
 #include "vmwgfx_drm.h"
+#include "svga3d_caps.h"
 
 #include "os/os_mman.h"
 
@@ -64,62 +66,6 @@ struct vmw_region
  */
 #define SVGA3D_SURFACE_HINT_SCANOUT (1 << 9)
 
-static void
-vmw_check_last_cmd(struct vmw_winsys_screen *vws)
-{
-   static uint32_t buffer[16384];
-   struct drm_vmw_fifo_debug_arg arg;
-   int ret;
-
-   return;
-   memset(&arg, 0, sizeof(arg));
-   arg.debug_buffer = (unsigned long)buffer;
-   arg.debug_buffer_size = 65536;
-
-   ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_FIFO_DEBUG,
-                            &arg, sizeof(arg));
-
-   if (ret) {
-      debug_printf("%s Ioctl error: \"%s\".\n", __FUNCTION__, strerror(-ret));
-      return;
-   }
-
-   if (arg.did_not_fit) {
-      debug_printf("%s Command did not fit completely.\n", __FUNCTION__);
-   }
-
-   svga_dump_commands(buffer, arg.used_size);
-}
-
-static void
-vmw_ioctl_fifo_unmap(struct vmw_winsys_screen *vws, void *mapping)
-{
-   VMW_FUNC;
-   (void)os_munmap(mapping, getpagesize());
-}
-
-
-static void *
-vmw_ioctl_fifo_map(struct vmw_winsys_screen *vws,
-                   uint32_t fifo_offset )
-{
-   void *map;
-
-   VMW_FUNC;
-
-   map = os_mmap(NULL, getpagesize(), PROT_READ, MAP_SHARED,
-             vws->ioctl.drm_fd, fifo_offset);
-
-   if (map == MAP_FAILED) {
-      debug_printf("Map failed %s\n", strerror(errno));
-      return NULL;
-   }
-
-   vmw_printf("Fifo (min) is 0x%08x\n", ((uint32_t *) map)[SVGA_FIFO_MIN]);
-
-   return map;
-}
-
 uint32
 vmw_ioctl_context_create(struct vmw_winsys_screen *vws)
 {
@@ -134,7 +80,6 @@ vmw_ioctl_context_create(struct vmw_winsys_screen *vws)
    if (ret)
       return -1;
 
-   vmw_check_last_cmd(vws);
    vmw_printf("Context id is %d\n", c_arg.cid);
 
    return c_arg.cid;
@@ -153,7 +98,6 @@ vmw_ioctl_context_destroy(struct vmw_winsys_screen *vws, uint32 cid)
    (void)drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_UNREF_CONTEXT,
                         &c_arg, sizeof(c_arg));
 
-   vmw_check_last_cmd(vws);
 }
 
 uint32
@@ -220,7 +164,6 @@ vmw_ioctl_surface_create(struct vmw_winsys_screen *vws,
       return -1;
 
    vmw_printf("Surface id is %d\n", rep->sid);
-   vmw_check_last_cmd(vws);
 
    return rep->sid;
 }
@@ -237,14 +180,12 @@ vmw_ioctl_surface_destroy(struct vmw_winsys_screen *vws, uint32 sid)
 
    (void)drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_UNREF_SURFACE,
                         &s_arg, sizeof(s_arg));
-   vmw_check_last_cmd(vws);
-
 }
 
 void
 vmw_ioctl_command(struct vmw_winsys_screen *vws, int32_t cid,
                  uint32_t throttle_us, void *commands, uint32_t size,
-                 uint32_t *pfence)
+                 struct pipe_fence_handle **pfence)
 {
    struct drm_vmw_execbuf_arg arg;
    struct drm_vmw_fence_rep rep;
@@ -274,10 +215,12 @@ vmw_ioctl_command(struct vmw_winsys_screen *vws, int32_t cid,
    memset(&rep, 0, sizeof(rep));
 
    rep.error = -EFAULT;
-   arg.fence_rep = (unsigned long)&rep;
+   if (pfence)
+      arg.fence_rep = (unsigned long)&rep;
    arg.commands = (unsigned long)commands;
    arg.command_size = size;
    arg.throttle_us = throttle_us;
+   arg.version = DRM_VMW_EXECBUF_VERSION;
 
    do {
        ret = drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_EXECBUF, &arg, sizeof(arg));
@@ -285,26 +228,27 @@ vmw_ioctl_command(struct vmw_winsys_screen *vws, int32_t cid,
    if (ret) {
       debug_printf("%s error %s.\n", __FUNCTION__, strerror(-ret));
    }
+
    if (rep.error) {
 
       /*
-       * Kernel has synced and put the last fence sequence in the FIFO
-       * register.
+       * Kernel has already synced, or caller requested no fence.
        */
-
-      if (rep.error == -EFAULT)
-        rep.fence_seq = vws->ioctl.fifo_map[SVGA_FIFO_FENCE];
-
-      debug_printf("%s Fence error %s.\n", __FUNCTION__,
-                  strerror(-rep.error));
+      if (pfence)
+        *pfence = NULL;
+   } else {
+      if (pfence) {
+        *pfence = vmw_fence_create(rep.handle, rep.mask);
+
+        if (*pfence == NULL) {
+           /*
+            * Fence creation failed. Need to sync.
+            */
+           (void) vmw_ioctl_fence_finish(vws, rep.handle, rep.mask);
+           vmw_ioctl_fence_unref(vws, rep.handle);
+        }
+      }
    }
-
-   vws->ioctl.last_fence = rep.fence_seq;
-
-   if (pfence)
-      *pfence = rep.fence_seq;
-   vmw_check_last_cmd(vws);
-
 }
 
 
@@ -412,67 +356,81 @@ vmw_ioctl_region_unmap(struct vmw_region *region)
    --region->map_count;
 }
 
-
-int
-vmw_ioctl_fence_signalled(struct vmw_winsys_screen *vws,
-                          uint32_t fence)
+void
+vmw_ioctl_fence_unref(struct vmw_winsys_screen *vws,
+                     uint32_t handle)
 {
-   uint32_t expected;
-   uint32_t current;
-   
-   assert(fence);
-   if(!fence)
-      return 0;
-   
-   expected = fence;
-   current = vws->ioctl.fifo_map[SVGA_FIFO_FENCE];
+   struct drm_vmw_fence_arg arg;
+   int ret;
    
-   if ((int32)(current - expected) >= 0)
-      return 0; /* fence passed */
-   else
-      return -1;
-}
+   memset(&arg, 0, sizeof(arg));
+   arg.handle = handle;
 
+   ret = drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_FENCE_UNREF,
+                        &arg, sizeof(arg));
+   if (ret != 0)
+      debug_printf("%s Failed\n", __FUNCTION__);
+}
 
-static void
-vmw_ioctl_sync(struct vmw_winsys_screen *vws, 
-                   uint32_t fence)
+static INLINE uint32_t
+vmw_drm_fence_flags(uint32_t flags)
 {
-   uint32_t cur_fence;
-   struct drm_vmw_fence_wait_arg arg;
-   int ret;
+    uint32_t dflags = 0;
 
-   vmw_printf("%s: fence = %lu\n", __FUNCTION__,
-              (unsigned long)fence);
+    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;
+}
 
-   cur_fence = vws->ioctl.fifo_map[SVGA_FIFO_FENCE];
-   vmw_printf("%s: Fence id read is 0x%08x\n", __FUNCTION__,
-              (unsigned int)cur_fence);
 
-   if ((cur_fence - fence) < (1 << 24))
-      return;
+int
+vmw_ioctl_fence_signalled(struct vmw_winsys_screen *vws,
+                         uint32_t handle,
+                         uint32_t flags)
+{
+   struct drm_vmw_fence_signaled_arg arg;
+   uint32_t vflags = vmw_drm_fence_flags(flags);
+   int ret;
 
    memset(&arg, 0, sizeof(arg));
-   arg.sequence = fence;
+   arg.handle = handle;
+   arg.flags = vflags;
 
-   do {
-       ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_FENCE_WAIT, &arg,
-                                sizeof(arg));
-   } while (ret == -ERESTART);
+   ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_FENCE_SIGNALED,
+                            &arg, sizeof(arg));
+
+   if (ret != 0)
+      return ret;
+
+   return (arg.signaled) ? 0 : -1;
 }
 
 
+
 int
 vmw_ioctl_fence_finish(struct vmw_winsys_screen *vws,
-                       uint32_t fence)
+                       uint32_t handle,
+                      uint32_t flags)
 {
-   assert(fence);
-   
-   if(fence) {
-      if(vmw_ioctl_fence_signalled(vws, fence) != 0) {
-         vmw_ioctl_sync(vws, fence);
-      }
-   }
+   struct drm_vmw_fence_wait_arg arg;
+   uint32_t vflags = vmw_drm_fence_flags(flags);
+   int ret;
+
+   memset(&arg, 0, sizeof(arg));
+
+   arg.handle = handle;
+   arg.timeout_us = 10*1000000;
+   arg.lazy = 0;
+   arg.flags = vflags;
+
+   ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_FENCE_WAIT,
+                            &arg, sizeof(arg));
+
+   if (ret != 0)
+      debug_printf("%s Failed\n", __FUNCTION__);
    
    return 0;
 }
@@ -482,6 +440,8 @@ boolean
 vmw_ioctl_init(struct vmw_winsys_screen *vws)
 {
    struct drm_vmw_getparam_arg gp_arg;
+   struct drm_vmw_get_3d_cap_arg cap_arg;
+   unsigned int size;
    int ret;
 
    VMW_FUNC;
@@ -491,32 +451,46 @@ vmw_ioctl_init(struct vmw_winsys_screen *vws)
    ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM,
                             &gp_arg, sizeof(gp_arg));
    if (ret || gp_arg.value == 0) {
-      debug_printf("No 3D enabled (%i, %s)\n", ret, strerror(-ret));
-      goto out_err1;
+      debug_printf("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_OFFSET;
+   gp_arg.param = DRM_VMW_PARAM_FIFO_HW_VERSION;
    ret = drmCommandWriteRead(vws->ioctl.drm_fd, DRM_VMW_GET_PARAM,
                             &gp_arg, sizeof(gp_arg));
-
    if (ret) {
-      debug_printf("GET_PARAM on %d returned %d: %s\n",
-                  vws->ioctl.drm_fd, ret, strerror(-ret));
-      goto out_err1;
+      debug_printf("Failed to get fifo hw version"
+                  " (%i, %s).\n", ret, strerror(-ret));
+      goto out_no_3d;
+   }
+   vws->ioctl.hwversion = gp_arg.value;
+
+   size = SVGA_FIFO_3D_CAPS_SIZE * sizeof(uint32_t);
+   vws->ioctl.buffer = calloc(1, size);
+   if (!vws->ioctl.buffer) {
+      debug_printf("Failed alloc fifo 3D caps buffer.\n");
+      goto out_no_3d;
    }
 
-   vmw_printf("Offset to map is 0x%08llx\n",
-              (unsigned long long)gp_arg.value);
+   memset(&cap_arg, 0, sizeof(cap_arg));
+   cap_arg.buffer = (uint64_t) (unsigned long) (vws->ioctl.buffer);
+   cap_arg.max_size = size;
 
-   vws->ioctl.fifo_map = vmw_ioctl_fifo_map(vws, gp_arg.value);
-   if (vws->ioctl.fifo_map == NULL)
-      goto out_err1;
+   ret = drmCommandWrite(vws->ioctl.drm_fd, DRM_VMW_GET_3D_CAP,
+                        &cap_arg, sizeof(cap_arg));
+
+   if (ret) {
+      debug_printf("Failed to get 3D capabilities"
+                  " (%i, %s).\n", ret, strerror(-ret));
+      goto out_no_caps;
+   }
 
    vmw_printf("%s OK\n", __FUNCTION__);
    return TRUE;
-
- out_err1:
+  out_no_caps:
+   free(vws->ioctl.buffer);
+  out_no_3d:
    debug_printf("%s Failed\n", __FUNCTION__);
    return FALSE;
 }
@@ -527,6 +501,4 @@ void
 vmw_ioctl_cleanup(struct vmw_winsys_screen *vws)
 {
    VMW_FUNC;
-
-   vmw_ioctl_fifo_unmap(vws, (void *)vws->ioctl.fifo_map);
 }
index b9823d7857502fb50a3e47093877549955920672..6350ea3cd4f3209cbf5ff3f055a67fccd52eaf09 100644 (file)
 #include "pipebuffer/pb_buffer.h"
 #include "pipebuffer/pb_bufmgr.h"
 
+/*
+ * TODO: Have the query pool always ask the fence manager for
+ * SVGA_FENCE_FLAG_QUERY signaled. Unfortunately, pb_fenced doesn't
+ * support that currently, so we'd have to create a separate
+ * pb_fence_ops wrapper that does this implicitly.
+ */
+
+/**
+ * vmw_pools_cleanup - Destroy the buffer pools.
+ *
+ * @vws: pointer to a struct vmw_winsys_screen.
+ */
 void
 vmw_pools_cleanup(struct vmw_winsys_screen *vws)
 {
    if(vws->pools.gmr_fenced)
       vws->pools.gmr_fenced->destroy(vws->pools.gmr_fenced);
+   if (vws->pools.query_fenced)
+      vws->pools.query_fenced->destroy(vws->pools.query_fenced);
 
    /* gmr_mm pool is already destroyed above */
 
    if(vws->pools.gmr)
       vws->pools.gmr->destroy(vws->pools.gmr);
+   if(vws->pools.query)
+      vws->pools.query->destroy(vws->pools.query);
 }
 
 
+/**
+ * vmw_query_pools_init - Create a pool of query buffers.
+ *
+ * @vws: Pointer to a struct vmw_winsys_screen.
+ *
+ * Typically this pool should be created on demand when we
+ * detect that the app will be using queries. There's nothing
+ * special with this pool other than the backing kernel buffer size,
+ * which is limited to 8192.
+ */
+boolean
+vmw_query_pools_init(struct vmw_winsys_screen *vws)
+{
+   vws->pools.query = vmw_gmr_bufmgr_create(vws);
+   if(!vws->pools.query)
+      return FALSE;
+
+   vws->pools.query_mm = mm_bufmgr_create(vws->pools.query,
+                                         VMW_QUERY_POOL_SIZE,
+                                         3 /* 8 alignment */);
+   if(!vws->pools.query_mm)
+      goto out_no_query_mm;
+
+   vws->pools.query_fenced = fenced_bufmgr_create(
+      vws->pools.query_mm,
+      vmw_fence_ops_create(vws),
+      VMW_QUERY_POOL_SIZE,
+      ~0);
+
+   if(!vws->pools.query_fenced)
+      goto out_no_query_fenced;
+
+   return TRUE;
+
+  out_no_query_fenced:
+   vws->pools.query_mm->destroy(vws->pools.query_mm);
+  out_no_query_mm:
+   vws->pools.query->destroy(vws->pools.query);
+   return FALSE;
+}
+
+/**
+ * vmw_pools_init - Create a pool of GMR buffers.
+ *
+ * @vws: Pointer to a struct vmw_winsys_screen.
+ */
 boolean
 vmw_pools_init(struct vmw_winsys_screen *vws)
 {
@@ -88,6 +150,10 @@ vmw_pools_init(struct vmw_winsys_screen *vws)
    if(!vws->pools.gmr_fenced)
       goto error;
 
+   vws->pools.query_fenced = NULL;
+   vws->pools.query_mm = NULL;
+   vws->pools.query = NULL;
+
    return TRUE;
 
 error:
index c362aa399382e1bfca9650277df3de0f4ba3abf1..df4a384d3ee0f57d7b0d9bc3b8829f1e7f8d6356 100644 (file)
@@ -64,7 +64,12 @@ vmw_svga_winsys_buffer_create(struct svga_winsys_screen *sws,
    desc.alignment = alignment;
    desc.usage = usage;
 
-   provider = vws->pools.gmr_fenced;
+   if (usage == SVGA_BUFFER_USAGE_PINNED) {
+      if (vws->pools.query_fenced == NULL && !vmw_query_pools_init(vws))
+        return NULL;
+      provider = vws->pools.query_fenced;
+   } else
+      provider = vws->pools.gmr_fenced;
 
    assert(provider);
    buffer = provider->create_buffer(provider, size, &desc);
@@ -109,8 +114,9 @@ vmw_svga_winsys_fence_reference(struct svga_winsys_screen *sws,
                                 struct pipe_fence_handle **pdst,
                                 struct pipe_fence_handle *src)
 {
-   (void)sws;
-   *pdst = src;
+    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
+
+    vmw_fence_reference(vws, pdst, src);
 }
 
 
@@ -120,8 +126,8 @@ vmw_svga_winsys_fence_signalled(struct svga_winsys_screen *sws,
                                 unsigned flag)
 {
    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
-   (void)flag;
-   return vmw_ioctl_fence_signalled(vws, vmw_fence(fence));
+
+   return vmw_fence_signalled(vws, fence, flag);
 }
 
 
@@ -131,8 +137,8 @@ vmw_svga_winsys_fence_finish(struct svga_winsys_screen *sws,
                              unsigned flag)
 {
    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
-   (void)flag;
-   return vmw_ioctl_fence_finish(vws, vmw_fence(fence));
+
+   return vmw_fence_finish(vws, fence, flag);
 }
 
 
@@ -206,11 +212,7 @@ vmw_svga_winsys_get_hw_version(struct svga_winsys_screen *sws)
 {
    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
 
-   if (!vws->ioctl.fifo_map) {
-      return 0;
-   }
-
-   return vws->ioctl.fifo_map[SVGA_FIFO_3D_HWVERSION];
+   return (SVGA3dHardwareVersion) vws->ioctl.hwversion;
 }
 
 
@@ -226,16 +228,13 @@ vmw_svga_winsys_get_cap(struct svga_winsys_screen *sws,
    const SVGA3dCapPair *capArray;
    int numCaps, first, last;
 
-   if(!vws->ioctl.fifo_map)
-      return FALSE;
-
-   if(vws->ioctl.fifo_map[SVGA_FIFO_3D_HWVERSION] < SVGA3D_HWVERSION_WS6_B1)
+   if(vws->ioctl.hwversion < SVGA3D_HWVERSION_WS6_B1)
       return FALSE;
 
    /*
     * Search linearly through the caps block records for the specified type.
     */
-   capsBlock = (const uint32 *)&vws->ioctl.fifo_map[SVGA_FIFO_3D_CAPS];
+   capsBlock = (const uint32 *)vws->ioctl.buffer;
    for (offset = 0; capsBlock[offset] != 0; offset += capsBlock[offset]) {
       const SVGA3dCapsRecord *record;
       assert(offset < SVGA_FIFO_3D_CAPS_SIZE);
index 2f2807df0b2b7813d92caa4962aab782b9de05b1..bad47a702f2bc38ea22df8c56c63a3182418d54a 100644 (file)
@@ -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
 #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
 
 
 /*************************************************************************/
 #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
@@ -249,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.
  */
 
@@ -271,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.
@@ -299,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;
 };
 
 /*************************************************************************/
@@ -390,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.
@@ -547,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
+ *
+ */
+
+/**
+ * struct drm_vmw_get_3d_cap_arg
+ *
+ * @buffer: Pointer to a buffer for capability data, cast to an uint64_t
+ * @size: Max size to copy
+ *
+ * Input argument to the DRM_VMW_GET_3D_CAP_IOCTL
+ * ioctls.
+ */
+
+struct drm_vmw_get_3d_cap_arg {
+       uint64_t buffer;
+       uint32_t max_size;
+       uint32_t pad64;
+};
+
+
+/*************************************************************************/
+/**
+ * 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
  *
- * 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.
+ * Checks if a fence object is signaled..
  */
 
 /**
- * struct drm_vmw_update_layout_arg
+ * struct drm_vmw_fence_signaled_arg
  *
- * @num_outputs: number of active
- * @rects: pointer to array of drm_vmw_rect
+ * @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 argument to the DRM_VMW_UPDATE_LAYOUT Ioctl.
+ * Input/Output argument to the DRM_VMW_FENCE_SIGNALED and DRM_VMW_FENCE_UNREF
+ * ioctls.
  */
 
-struct drm_vmw_update_layout_arg {
-       uint32_t num_outputs;
+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;
-       uint64_t rects;
 };
 
+
+/*************************************************************************/
+/**
+ * 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