winsys/radeon: hook up the new DRM_RADEON_GEM_WAIT ioctl
authorMarek Olšák <maraeo@gmail.com>
Sun, 7 Aug 2011 17:04:37 +0000 (19:04 +0200)
committerMarek Olšák <maraeo@gmail.com>
Tue, 16 Aug 2011 07:15:11 +0000 (09:15 +0200)
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
src/gallium/drivers/r300/r300_screen.c
src/gallium/drivers/r300/r300_transfer.c
src/gallium/winsys/radeon/drm/radeon_drm_bo.c
src/gallium/winsys/radeon/drm/radeon_winsys.h

index 674bd24953caa5b7c73fbde4550185c6c34d89d8..13d25ba7dba9b2b78a232f7185487fbdf899fda3 100644 (file)
@@ -454,7 +454,7 @@ static boolean r300_fence_signalled(struct pipe_screen *screen,
     struct radeon_winsys *rws = r300_screen(screen)->rws;
     struct pb_buffer *rfence = (struct pb_buffer*)fence;
 
-    return !rws->buffer_is_busy(rfence);
+    return !rws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE);
 }
 
 static boolean r300_fence_finish(struct pipe_screen *screen,
@@ -471,7 +471,7 @@ static boolean r300_fence_finish(struct pipe_screen *screen,
         timeout /= 1000;
 
         /* Wait in a loop. */
-        while (rws->buffer_is_busy(rfence)) {
+        while (rws->buffer_is_busy(rfence, RADEON_USAGE_READWRITE)) {
             if (os_time_get() - start_time >= timeout) {
                 return FALSE;
             }
@@ -480,7 +480,7 @@ static boolean r300_fence_finish(struct pipe_screen *screen,
         return TRUE;
     }
 
-    rws->buffer_wait(rfence);
+    rws->buffer_wait(rfence, RADEON_USAGE_READWRITE);
     return TRUE;
 }
 
index e2ea4cbf6c5458aacbb7541ba97dcfdefb1c18b6..65964020adcf39200f34b5e29ba03eab5493f003 100644 (file)
@@ -97,7 +97,7 @@ r300_texture_get_transfer(struct pipe_context *ctx,
         referenced_hw = TRUE;
     } else {
         referenced_hw =
-            r300->rws->buffer_is_busy(tex->buf);
+            r300->rws->buffer_is_busy(tex->buf, RADEON_USAGE_READWRITE);
     }
 
     blittable = desc->layout == UTIL_FORMAT_LAYOUT_PLAIN ||
index 1c8a2b8305e53c0b63804d83049043408823971b..5c91ec48942601cd8930ca16f09061213eaa065f 100644 (file)
 #define RADEON_BO_FLAGS_MICRO_TILE  2
 #define RADEON_BO_FLAGS_MICRO_TILE_SQUARE 0x20
 
+#ifndef DRM_RADEON_GEM_WAIT
+#define DRM_RADEON_GEM_WAIT            0x2b
+
+#define RADEON_GEM_NO_WAIT     0x1
+#define RADEON_GEM_USAGE_READ  0x2
+#define RADEON_GEM_USAGE_WRITE 0x4
+
+struct drm_radeon_gem_wait {
+       uint32_t        handle;
+       uint32_t        flags;  /* one of RADEON_GEM_* */
+};
+
+#endif
+
+
 extern const struct pb_vtbl radeon_bo_vtbl;
 
 
@@ -87,35 +102,49 @@ static struct radeon_bo *get_radeon_bo(struct pb_buffer *_buf)
     return bo;
 }
 
-static void radeon_bo_wait(struct pb_buffer *_buf)
+static void radeon_bo_wait(struct pb_buffer *_buf, enum radeon_bo_usage usage)
 {
     struct radeon_bo *bo = get_radeon_bo(_buf);
-    struct drm_radeon_gem_wait_idle args = {};
 
     while (p_atomic_read(&bo->num_active_ioctls)) {
         sched_yield();
     }
 
-    args.handle = bo->handle;
-    while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE,
-                               &args, sizeof(args)) == -EBUSY);
+    if (bo->rws->info.drm_minor >= 12) {
+        struct drm_radeon_gem_wait args = {};
+        args.handle = bo->handle;
+        args.flags = usage;
+        while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT,
+                                   &args, sizeof(args)) == -EBUSY);
+    } else {
+        struct drm_radeon_gem_wait_idle args = {};
+        args.handle = bo->handle;
+        while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE,
+                                   &args, sizeof(args)) == -EBUSY);
+    }
 }
 
-static boolean radeon_bo_is_busy(struct pb_buffer *_buf)
+static boolean radeon_bo_is_busy(struct pb_buffer *_buf,
+                                 enum radeon_bo_usage usage)
 {
     struct radeon_bo *bo = get_radeon_bo(_buf);
-    struct drm_radeon_gem_busy args = {};
-    boolean busy;
 
     if (p_atomic_read(&bo->num_active_ioctls)) {
         return TRUE;
     }
 
-    args.handle = bo->handle;
-    busy = drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY,
-                               &args, sizeof(args)) != 0;
-
-    return busy;
+    if (bo->rws->info.drm_minor >= 12) {
+        struct drm_radeon_gem_wait args = {};
+        args.handle = bo->handle;
+        args.flags = usage | RADEON_GEM_NO_WAIT;
+        return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT,
+                                   &args, sizeof(args)) != 0;
+    } else {
+        struct drm_radeon_gem_busy args = {};
+        args.handle = bo->handle;
+        return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY,
+                                   &args, sizeof(args)) != 0;
+    }
 }
 
 static void radeon_bo_destroy(struct pb_buffer *_buf)
@@ -173,7 +202,7 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf,
                 return NULL;
             }
 
-            if (radeon_bo_is_busy((struct pb_buffer*)bo)) {
+            if (radeon_bo_is_busy((struct pb_buffer*)bo, RADEON_USAGE_READWRITE)) {
                 return NULL;
             }
         } else {
@@ -187,10 +216,12 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf,
                  * Only check whether the buffer is being used for write. */
                 if (radeon_bo_is_referenced_by_cs_for_write(cs, bo)) {
                     cs->flush_cs(cs->flush_data, 0);
-                    radeon_bo_wait((struct pb_buffer*)bo);
+                    radeon_bo_wait((struct pb_buffer*)bo,
+                                   RADEON_USAGE_READWRITE);
                 } else {
                     /* XXX We could check whether the buffer is busy for write here. */
-                    radeon_bo_wait((struct pb_buffer*)bo);
+                    radeon_bo_wait((struct pb_buffer*)bo,
+                                   RADEON_USAGE_READWRITE);
                 }
             } else {
                 /* Mapping for write. */
@@ -202,7 +233,7 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf,
                         radeon_drm_cs_sync_flush(cs);
                 }
 
-                radeon_bo_wait((struct pb_buffer*)bo);
+                radeon_bo_wait((struct pb_buffer*)bo, RADEON_USAGE_READWRITE);
             }
         }
     }
@@ -338,7 +369,7 @@ static boolean radeon_bomgr_is_buffer_busy(struct pb_manager *_mgr,
        return TRUE;
    }
 
-   if (radeon_bo_is_busy((struct pb_buffer*)bo)) {
+   if (radeon_bo_is_busy((struct pb_buffer*)bo, RADEON_USAGE_READWRITE)) {
        return TRUE;
    }
 
index bf5b144fe2c080eef90b87c32e1b4de643cb530b..90583e3ab8cbcf7754103dadbbfe627508c20cda 100644 (file)
@@ -61,6 +61,12 @@ enum radeon_bo_domain { /* bitfield */
     RADEON_DOMAIN_VRAM = 4
 };
 
+enum radeon_bo_usage { /* bitfield */
+    RADEON_USAGE_READ = 2,
+    RADEON_USAGE_WRITE = 4,
+    RADEON_USAGE_READWRITE = RADEON_USAGE_READ | RADEON_USAGE_WRITE
+};
+
 struct winsys_handle;
 struct radeon_winsys_cs_handle;   /* for write_reloc etc. */
 
@@ -162,8 +168,10 @@ struct radeon_winsys {
      * Return TRUE if a buffer object is being used by the GPU.
      *
      * \param buf       A winsys buffer object.
+     * \param usage     Only check whether the buffer is busy for the given usage.
      */
-    boolean (*buffer_is_busy)(struct pb_buffer *buf);
+    boolean (*buffer_is_busy)(struct pb_buffer *buf,
+                              enum radeon_bo_usage usage);
 
     /**
      * Wait for a buffer object until it is not used by a GPU. This is
@@ -171,8 +179,10 @@ struct radeon_winsys {
      * and synchronizing to the fence.
      *
      * \param buf       A winsys buffer object to wait for.
+     * \param usage     Only wait until the buffer is idle for the given usage,
+     *                  but may still be busy for some other usage.
      */
-    void (*buffer_wait)(struct pb_buffer *buf);
+    void (*buffer_wait)(struct pb_buffer *buf, enum radeon_bo_usage usage);
 
     /**
      * Return tiling flags describing a memory layout of a buffer object.