winsys/svga: Add support for new surface ioctl, multisample pattern
[mesa.git] / src / gallium / winsys / svga / drm / vmw_screen_svga.c
index 17a1e760dd0fd3b4f6a0640f0dbc6e1c745e6cf6..7edd13032796f5c11c2425e28be4782ca2700268 100644 (file)
@@ -32,6 +32,7 @@
  * @author Jose Fonseca
  */
 
+#include <libsync.h>
 
 #include "svga_cmd.h"
 #include "svga3d_caps.h"
@@ -123,18 +124,53 @@ vmw_svga_winsys_fence_signalled(struct svga_winsys_screen *sws,
 static int
 vmw_svga_winsys_fence_finish(struct svga_winsys_screen *sws,
                              struct pipe_fence_handle *fence,
+                             uint64_t timeout,
                              unsigned flag)
 {
    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
 
-   return vmw_fence_finish(vws, fence, flag);
+   return vmw_fence_finish(vws, fence, timeout, flag);
 }
 
 
+static int
+vmw_svga_winsys_fence_get_fd(struct svga_winsys_screen *sws,
+                             struct pipe_fence_handle *fence,
+                             boolean duplicate)
+{
+   if (duplicate)
+      return dup(vmw_fence_get_fd(fence));
+   else
+      return vmw_fence_get_fd(fence);
+}
+
+
+static void
+vmw_svga_winsys_fence_create_fd(struct svga_winsys_screen *sws,
+                                struct pipe_fence_handle **fence,
+                                int32_t fd)
+{
+   *fence = vmw_fence_create(NULL, 0, 0, 0, dup(fd));
+}
+
+static int
+vmw_svga_winsys_fence_server_sync(struct svga_winsys_screen *sws,
+                                  int32_t *context_fd,
+                                  struct pipe_fence_handle *fence)
+{
+   int32_t fd = sws->fence_get_fd(sws, fence, FALSE);
+
+   /* If we don't have fd, we don't need to merge fd into the context's fd. */
+   if (fd == -1)
+      return 0;
+
+   return sync_accumulate("vmwgfx", context_fd, fd);
+}
+
 
 static struct svga_winsys_surface *
 vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws,
-                               SVGA3dSurfaceFlags flags,
+                               SVGA3dSurfaceAllFlags flags,
                                SVGA3dSurfaceFormat format,
                                unsigned usage,
                                SVGA3dSize size,
@@ -147,6 +183,8 @@ vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws,
    struct vmw_buffer_desc desc;
    struct pb_manager *provider;
    uint32_t buffer_size;
+   uint32_t num_samples = 1;
+   SVGA3dMSPattern multisample_pattern = SVGA3D_MS_PATTERN_NONE;
 
    memset(&desc, 0, sizeof(desc));
    surface = CALLOC_STRUCT(vmw_svga_winsys_surface);
@@ -160,12 +198,25 @@ vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws,
    surface->shared = !!(usage & SVGA_SURFACE_USAGE_SHARED);
    provider = (surface->shared) ? vws->pools.gmr : vws->pools.mob_fenced;
 
+   /*
+    * When multisampling is not supported sample count received is 0,
+    * otherwise should have a valid sample count.
+    */
+   if ((flags & SVGA3D_SURFACE_MULTISAMPLE) != 0) {
+      if (sampleCount == 0)
+         goto no_sid;
+      num_samples = sampleCount;
+      multisample_pattern = SVGA3D_MS_PATTERN_STANDARD;
+   }
+
    /*
     * Used for the backing buffer GB surfaces, and to approximate
     * when to flush on non-GB hosts.
     */
-   buffer_size = svga3dsurface_get_serialized_size(format, size, numMipLevels, 
-                                                   numLayers);
+   buffer_size = svga3dsurface_get_serialized_size_extended(format, size,
+                                                            numMipLevels,
+                                                            numLayers,
+                                                            num_samples);
    if (flags & SVGA3D_SURFACE_BIND_STREAM_OUTPUT)
       buffer_size += sizeof(SVGA3dDXSOState);
 
@@ -197,25 +248,30 @@ vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws,
                                                  size, numLayers,
                                                  numMipLevels, sampleCount,
                                                  ptr.gmrId,
+                                                 multisample_pattern,
                                                  surface->buf ? NULL :
                                                 &desc.region);
 
-      if (surface->sid == SVGA3D_INVALID_ID && surface->buf) {
-
-         /*
-          * Kernel refused to allocate a surface for us.
-          * Perhaps something was wrong with our buffer?
-          * This is really a guard against future new size requirements
-          * on the backing buffers.
-          */
-         vmw_svga_winsys_buffer_destroy(sws, surface->buf);
-         surface->buf = NULL;
-         surface->sid = vmw_ioctl_gb_surface_create(vws, flags, format, usage,
-                                                    size, numLayers,
-                                                    numMipLevels, sampleCount,
-                                                    0, &desc.region);
-         if (surface->sid == SVGA3D_INVALID_ID)
+      if (surface->sid == SVGA3D_INVALID_ID) {
+         if (surface->buf == NULL) {
             goto no_sid;
+         } else {
+            /*
+             * Kernel refused to allocate a surface for us.
+             * Perhaps something was wrong with our buffer?
+             * This is really a guard against future new size requirements
+             * on the backing buffers.
+             */
+            vmw_svga_winsys_buffer_destroy(sws, surface->buf);
+            surface->buf = NULL;
+            surface->sid = vmw_ioctl_gb_surface_create(vws, flags, format, usage,
+                                                       size, numLayers,
+                                                       numMipLevels, sampleCount,
+                                                       0, multisample_pattern,
+                                                       &desc.region);
+            if (surface->sid == SVGA3D_INVALID_ID)
+               goto no_sid;
+         }
       }
 
       /*
@@ -238,9 +294,10 @@ vmw_svga_winsys_surface_create(struct svga_winsys_screen *sws,
          }
       }
    } else {
-      surface->sid = vmw_ioctl_surface_create(vws, flags, format, usage,
-                                              size, numLayers, numMipLevels,
-                                              sampleCount);
+      /* Legacy surface only support 32-bit svga3d flags */
+      surface->sid = vmw_ioctl_surface_create(vws, (SVGA3dSurface1Flags)flags,
+                                              format, usage, size, numLayers,
+                                              numMipLevels, sampleCount);
       if(surface->sid == SVGA3D_INVALID_ID)
          goto no_sid;
 
@@ -265,7 +322,8 @@ vmw_svga_winsys_surface_can_create(struct svga_winsys_screen *sws,
                                SVGA3dSurfaceFormat format,
                                SVGA3dSize size,
                                uint32 numLayers,
-                               uint32 numMipLevels)
+                               uint32 numMipLevels,
+                               uint32 numSamples)
 {
    struct vmw_winsys_screen *vws = vmw_winsys_screen(sws);
    uint32_t buffer_size;
@@ -273,6 +331,9 @@ vmw_svga_winsys_surface_can_create(struct svga_winsys_screen *sws,
    buffer_size = svga3dsurface_get_serialized_size(format, size, 
                                                    numMipLevels, 
                                                    numLayers);
+   if (numSamples > 1)
+      buffer_size *= numSamples;
+
    if (buffer_size > vws->ioctl.max_texture_size) {
        return FALSE;
    }
@@ -280,18 +341,6 @@ vmw_svga_winsys_surface_can_create(struct svga_winsys_screen *sws,
 }
 
 
-static void
-vmw_svga_winsys_surface_invalidate(struct svga_winsys_screen *sws,
-                                   struct svga_winsys_surface *surf)
-{
-   /* this is a noop since surface invalidation is not needed for DMA path.
-    * DMA is enabled when guest-backed surface is not enabled or
-    * guest-backed dma is enabled.  Since guest-backed dma is enabled
-    * when guest-backed surface is enabled, that implies DMA is always enabled;
-    * hence, surface invalidation is not needed.
-    */
-}
-
 static boolean
 vmw_svga_winsys_surface_is_flushed(struct svga_winsys_screen *sws,
                                    struct svga_winsys_surface *surface)
@@ -434,7 +483,6 @@ vmw_winsys_screen_init_svga(struct vmw_winsys_screen *vws)
    vws->base.surface_is_flushed = vmw_svga_winsys_surface_is_flushed;
    vws->base.surface_reference = vmw_svga_winsys_surface_ref;
    vws->base.surface_can_create = vmw_svga_winsys_surface_can_create;
-   vws->base.surface_invalidate = vmw_svga_winsys_surface_invalidate;
    vws->base.buffer_create = vmw_svga_winsys_buffer_create;
    vws->base.buffer_map = vmw_svga_winsys_buffer_map;
    vws->base.buffer_unmap = vmw_svga_winsys_buffer_unmap;
@@ -444,6 +492,9 @@ vmw_winsys_screen_init_svga(struct vmw_winsys_screen *vws)
    vws->base.shader_create = vmw_svga_winsys_shader_create;
    vws->base.shader_destroy = vmw_svga_winsys_shader_destroy;
    vws->base.fence_finish = vmw_svga_winsys_fence_finish;
+   vws->base.fence_get_fd = vmw_svga_winsys_fence_get_fd;
+   vws->base.fence_create_fd = vmw_svga_winsys_fence_create_fd;
+   vws->base.fence_server_sync = vmw_svga_winsys_fence_server_sync;
 
    vws->base.query_create = vmw_svga_winsys_query_create;
    vws->base.query_init = vmw_svga_winsys_query_init;