Merge remote branch 'origin/master' into glsl2
[mesa.git] / src / gallium / winsys / radeon / drm / radeon_drm_buffer.c
index 9824ada5b33135cbd3b02959bff91b32de60c1dc..017eac8464e16b04d7c0e87ec3bc4ad8559bb1af 100644 (file)
@@ -20,6 +20,9 @@ struct radeon_drm_buffer {
 
     struct radeon_bo *bo;
 
+    /* The CS associated with the last buffer_map. */
+    struct radeon_libdrm_cs *cs;
+
     boolean flinked;
     uint32_t flink;
 
@@ -65,34 +68,53 @@ radeon_drm_buffer_destroy(struct pb_buffer *_buf)
     FREE(buf);
 }
 
+static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage)
+{
+    unsigned res = 0;
+
+    if (usage & PIPE_TRANSFER_READ)
+        res |= PB_USAGE_CPU_READ;
+
+    if (usage & PIPE_TRANSFER_WRITE)
+        res |= PB_USAGE_CPU_WRITE;
+
+    if (usage & PIPE_TRANSFER_DONTBLOCK)
+        res |= PB_USAGE_DONTBLOCK;
+
+    if (usage & PIPE_TRANSFER_UNSYNCHRONIZED)
+        res |= PB_USAGE_UNSYNCHRONIZED;
+
+    return res;
+}
+
 static void *
-radeon_drm_buffer_map(struct pb_buffer *_buf,
+radeon_drm_buffer_map_internal(struct pb_buffer *_buf,
                      unsigned flags)
 {
     struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
+    struct radeon_libdrm_cs *cs = buf->cs;
     int write = 0;
 
-    if (flags & PIPE_TRANSFER_DONTBLOCK) {
-       if ((_buf->base.usage & PIPE_BIND_VERTEX_BUFFER) ||
-           (_buf->base.usage & PIPE_BIND_INDEX_BUFFER))
-           if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs))
+    if (flags & PB_USAGE_DONTBLOCK) {
+        if (_buf->base.usage & RADEON_PB_USAGE_VERTEX)
+            if (cs && radeon_bo_is_referenced_by_cs(buf->bo, cs->cs))
                return NULL;
     }
 
     if (buf->bo->ptr != NULL)
        return buf->bo->ptr;
 
-    if (flags & PIPE_TRANSFER_DONTBLOCK) {
+    if (flags & PB_USAGE_DONTBLOCK) {
         uint32_t domain;
         if (radeon_bo_is_busy(buf->bo, &domain))
             return NULL;
     }
 
-    if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
-        buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data);
+    if (cs && radeon_bo_is_referenced_by_cs(buf->bo, cs->cs)) {
+        cs->flush_cs(cs->flush_data);
     }
 
-    if (flags & PIPE_TRANSFER_WRITE) {
+    if (flags & PB_USAGE_CPU_WRITE) {
         write = 1;
     }
 
@@ -104,7 +126,7 @@ radeon_drm_buffer_map(struct pb_buffer *_buf,
 }
 
 static void
-radeon_drm_buffer_unmap(struct pb_buffer *_buf)
+radeon_drm_buffer_unmap_internal(struct pb_buffer *_buf)
 {
     (void)_buf;
 }
@@ -136,38 +158,13 @@ radeon_drm_buffer_fence(struct pb_buffer *buf,
 
 const struct pb_vtbl radeon_drm_buffer_vtbl = {
     radeon_drm_buffer_destroy,
-    radeon_drm_buffer_map,
-    radeon_drm_buffer_unmap,
+    radeon_drm_buffer_map_internal,
+    radeon_drm_buffer_unmap_internal,
     radeon_drm_buffer_validate,
     radeon_drm_buffer_fence,
     radeon_drm_buffer_get_base_buffer,
 };
 
-
-static uint32_t radeon_domain_from_usage(unsigned usage)
-{
-    uint32_t domain = 0;
-
-    if (usage & PIPE_BIND_RENDER_TARGET) {
-        domain |= RADEON_GEM_DOMAIN_VRAM;
-    }
-    if (usage & PIPE_BIND_DEPTH_STENCIL) {
-        domain |= RADEON_GEM_DOMAIN_VRAM;
-    }
-    if (usage & PIPE_BIND_SAMPLER_VIEW) {
-        domain |= RADEON_GEM_DOMAIN_VRAM;
-    }
-    /* also need BIND_BLIT_SOURCE/DESTINATION ? */
-    if (usage & PIPE_BIND_VERTEX_BUFFER) {
-        domain |= RADEON_GEM_DOMAIN_GTT;
-    }
-    if (usage & PIPE_BIND_INDEX_BUFFER) {
-        domain |= RADEON_GEM_DOMAIN_GTT;
-    }
-
-    return domain;
-}
-
 struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr,
                                                              uint32_t handle)
 {
@@ -191,8 +188,8 @@ struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager
 
     pipe_reference_init(&buf->base.base.reference, 1);
     buf->base.base.alignment = 0;
-    buf->base.base.usage = PIPE_BIND_SAMPLER_VIEW;
-    buf->base.base.size = 0;
+    buf->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
+    buf->base.base.size = bo->size;
     buf->base.vtbl = &radeon_drm_buffer_vtbl;
     buf->mgr = mgr;
 
@@ -223,7 +220,11 @@ radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr,
     buf->mgr = mgr;
 
     make_empty_list(buf);
-    domain = radeon_domain_from_usage(desc->usage);
+
+    domain =
+        (desc->usage & RADEON_PB_USAGE_DOMAIN_GTT  ? RADEON_GEM_DOMAIN_GTT  : 0) |
+        (desc->usage & RADEON_PB_USAGE_DOMAIN_VRAM ? RADEON_GEM_DOMAIN_VRAM : 0);
+
     buf->bo = radeon_bo_open(rws->bom, 0, size,
                             desc->alignment, domain, 0);
     if (buf->bo == NULL)
@@ -270,7 +271,8 @@ radeon_drm_bufmgr_create(struct radeon_libdrm_winsys *rws)
 
 static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf)
 {
-    struct radeon_drm_buffer *buf;
+    struct radeon_drm_buffer *buf = NULL;
+
     if (_buf->vtbl == &radeon_drm_buffer_vtbl) {
         buf = radeon_drm_buffer(_buf);
     } else {
@@ -278,24 +280,46 @@ static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf)
        pb_size offset;
        pb_get_base_buffer(_buf, &base_buf, &offset);
 
-       buf = radeon_drm_buffer(base_buf);
+        if (base_buf->vtbl == &radeon_drm_buffer_vtbl)
+            buf = radeon_drm_buffer(base_buf);
     }
+
     return buf;
 }
 
+void *radeon_drm_buffer_map(struct r300_winsys_screen *ws,
+                            struct r300_winsys_buffer *buf,
+                            struct r300_winsys_cs *cs,
+                            enum pipe_transfer_usage usage)
+{
+    struct pb_buffer *_buf = radeon_pb_buffer(buf);
+    struct radeon_drm_buffer *rbuf = get_drm_buffer(_buf);
+
+    if (rbuf)
+        rbuf->cs = radeon_libdrm_cs(cs);
+
+    return pb_map(_buf, get_pb_usage_from_transfer_flags(usage));
+}
+
+void radeon_drm_buffer_unmap(struct r300_winsys_screen *ws,
+                             struct r300_winsys_buffer *buf)
+{
+    struct pb_buffer *_buf = radeon_pb_buffer(buf);
+
+    pb_unmap(_buf);
+}
+
 boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
                                     struct winsys_handle *whandle)
 {
-    int retval, fd;
     struct drm_gem_flink flink;
     struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
+
     if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
        if (!buf->flinked) {
-           fd = buf->mgr->rws->fd;
            flink.handle = buf->bo->handle;
 
-           retval = ioctl(fd, DRM_IOCTL_GEM_FLINK, &flink);
-           if (retval) {
+            if (ioctl(buf->mgr->rws->fd, DRM_IOCTL_GEM_FLINK, &flink)) {
                return FALSE;
            }
 
@@ -309,11 +333,12 @@ boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
     return TRUE;
 }
 
-void radeon_drm_bufmgr_get_tiling(struct pb_buffer *_buf,
+void radeon_drm_bufmgr_get_tiling(struct r300_winsys_screen *ws,
+                                  struct r300_winsys_buffer *_buf,
                                   enum r300_buffer_tiling *microtiled,
                                   enum r300_buffer_tiling *macrotiled)
 {
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
     uint32_t flags = 0, pitch;
 
     radeon_bo_get_tiling(buf->bo, &flags, &pitch);
@@ -327,13 +352,14 @@ void radeon_drm_bufmgr_get_tiling(struct pb_buffer *_buf,
        *macrotiled = R300_BUFFER_TILED;
 }
 
-void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf,
+void radeon_drm_bufmgr_set_tiling(struct r300_winsys_screen *ws,
+                                  struct r300_winsys_buffer *_buf,
                                   enum r300_buffer_tiling microtiled,
                                   enum r300_buffer_tiling macrotiled,
                                   uint32_t pitch)
 {
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
-    uint32_t flags = 0, old_flags, old_pitch;
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
+    uint32_t flags = 0;
     if (microtiled == R300_BUFFER_TILED)
         flags |= RADEON_BO_FLAGS_MICRO_TILE;
 /* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */
@@ -344,51 +370,63 @@ void radeon_drm_bufmgr_set_tiling(struct pb_buffer *_buf,
     if (macrotiled == R300_BUFFER_TILED)
         flags |= RADEON_BO_FLAGS_MACRO_TILE;
 
-    radeon_bo_get_tiling(buf->bo, &old_flags, &old_pitch);
-
-    if (flags != old_flags || pitch != old_pitch) {
-        /* Tiling determines how DRM treats the buffer data.
-         * We must flush CS when changing it if the buffer is referenced. */
-        if (radeon_bo_is_referenced_by_cs(buf->bo,  buf->mgr->rws->cs)) {
-           buf->mgr->rws->flush_cb(buf->mgr->rws->flush_data);
-        }
-    }
     radeon_bo_set_tiling(buf->bo, flags, pitch);
+}
+
+static uint32_t get_gem_domain(enum r300_buffer_domain domain)
+{
+    uint32_t res = 0;
 
+    if (domain & R300_DOMAIN_GTT)
+        res |= RADEON_GEM_DOMAIN_GTT;
+    if (domain & R300_DOMAIN_VRAM)
+        res |= RADEON_GEM_DOMAIN_VRAM;
+    return res;
 }
 
-boolean radeon_drm_bufmgr_add_buffer(struct pb_buffer *_buf,
-                                    uint32_t rd, uint32_t wd)
+void radeon_drm_bufmgr_add_buffer(struct r300_winsys_cs *rcs,
+                                  struct r300_winsys_buffer *_buf,
+                                  enum r300_buffer_domain rd,
+                                  enum r300_buffer_domain wd)
 {
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
-    radeon_cs_space_add_persistent_bo(buf->mgr->rws->cs, buf->bo,
-                                         rd, wd);
-    return TRUE;
+    struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
+    uint32_t gem_rd = get_gem_domain(rd);
+    uint32_t gem_wd = get_gem_domain(wd);
+
+    radeon_cs_space_add_persistent_bo(cs->cs, buf->bo, gem_rd, gem_wd);
 }
 
-void radeon_drm_bufmgr_write_reloc(struct pb_buffer *_buf,
-                                  uint32_t rd, uint32_t wd,
-                                  uint32_t flags)
+void radeon_drm_bufmgr_write_reloc(struct r300_winsys_cs *rcs,
+                                   struct r300_winsys_buffer *_buf,
+                                  enum r300_buffer_domain rd,
+                                   enum r300_buffer_domain wd)
 {
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
+    struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
     int retval;
+    uint32_t gem_rd = get_gem_domain(rd);
+    uint32_t gem_wd = get_gem_domain(wd);
 
-    retval = radeon_cs_write_reloc(buf->mgr->rws->cs,
-                                  buf->bo, rd, wd, flags);
+    cs->cs->cdw = cs->base.cdw;
+    retval = radeon_cs_write_reloc(cs->cs, buf->bo, gem_rd, gem_wd, 0);
+    cs->base.cdw = cs->cs->cdw;
     if (retval) {
-        debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n",
-                    buf, rd, wd, flags);
+        fprintf(stderr, "radeon: Relocation of %p (%d, %d, %d) failed!\n",
+                buf, gem_rd, gem_wd, 0);
     }
 }
 
-boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf,
+boolean radeon_drm_bufmgr_is_buffer_referenced(struct r300_winsys_cs *rcs,
+                                               struct r300_winsys_buffer *_buf,
                                                enum r300_reference_domain domain)
 {
-    struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
+    struct radeon_libdrm_cs *cs = radeon_libdrm_cs(rcs);
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
     uint32_t tmp;
 
     if (domain & R300_REF_CS) {
-        if (radeon_bo_is_referenced_by_cs(buf->bo, buf->mgr->rws->cs)) {
+        if (radeon_bo_is_referenced_by_cs(buf->bo, cs->cs)) {
             return TRUE;
         }
     }
@@ -402,7 +440,6 @@ boolean radeon_drm_bufmgr_is_buffer_referenced(struct pb_buffer *_buf,
     return FALSE;
 }
 
-
 void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr)
 {
     struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
@@ -416,3 +453,11 @@ void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr)
 
     make_empty_list(&mgr->buffer_map_list);
 }
+
+void radeon_drm_bufmgr_wait(struct r300_winsys_screen *ws,
+                            struct r300_winsys_buffer *_buf)
+{
+    struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
+
+    radeon_bo_wait(buf->bo);
+}