Merge commit 'origin/master' into gallium-sampler-view
[mesa.git] / src / gallium / winsys / drm / radeon / core / radeon_r300.c
index 7ea5d1fb4e76da4d1c082458249c3d3b9e509070..5b82a776a8155aef15bcc6d6e6770534ecdc786a 100644 (file)
  * USE OR OTHER DEALINGS IN THE SOFTWARE. */
 
 #include "radeon_r300.h"
+#include "radeon_buffer.h"
 
-static void radeon_r300_set_flush_cb(struct r300_winsys *winsys,
-                                    void (*flush_cb)(void *),
-                                    void *data)
+#include "radeon_bo_gem.h"
+#include "radeon_cs_gem.h"
+#include "state_tracker/drm_api.h"
+
+static struct r300_winsys_buffer *
+radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws,
+                                unsigned alignment,
+                                unsigned usage,
+                                unsigned size)
+{
+    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    struct pb_desc desc;
+    struct pb_manager *provider;
+    struct pb_buffer *buffer;
+
+    memset(&desc, 0, sizeof(desc));
+    desc.alignment = alignment;
+    desc.usage = usage;
+
+    if (usage & PIPE_BUFFER_USAGE_CONSTANT)
+        provider = ws->mman;
+    else
+        provider = ws->kman;
+    buffer = provider->create_buffer(provider, size, &desc);
+    if (!buffer)
+       return NULL;
+
+    return radeon_libdrm_winsys_buffer(buffer);
+}
+
+static void radeon_r300_winsys_buffer_destroy(struct r300_winsys_buffer *buf)
 {
-    struct radeon_winsys_priv* priv =
-        (struct radeon_winsys_priv*)winsys->radeon_winsys;
+    struct pb_buffer *_buf = radeon_pb_buffer(buf);
 
-    radeon_cs_space_set_flush(priv->cs, flush_cb,
-                             data);
+    pb_destroy(_buf);
+}
+static void radeon_r300_winsys_buffer_set_tiling(struct r300_winsys_screen *rws,
+                                                 struct r300_winsys_buffer *buf,
+                                                 uint32_t pitch,
+                                                 boolean microtiled,
+                                                 boolean macrotiled)
+{
+    struct pb_buffer *_buf = radeon_pb_buffer(buf);
+    radeon_drm_bufmgr_set_tiling(_buf, microtiled, macrotiled, pitch);
 }
 
-static boolean radeon_r300_add_buffer(struct r300_winsys* winsys,
-                                      struct pipe_buffer* pbuffer,
-                                      uint32_t rd,
-                                      uint32_t wd)
+static void *radeon_r300_winsys_buffer_map(struct r300_winsys_screen *ws,
+                                          struct r300_winsys_buffer *buf,
+                                          unsigned usage)
 {
-    struct radeon_winsys_priv* priv =
-        (struct radeon_winsys_priv*)winsys->radeon_winsys;
-    struct radeon_bo* bo = ((struct radeon_pipe_buffer*)pbuffer)->bo;
+    struct pb_buffer *_buf = radeon_pb_buffer(buf);
+    
+    return pb_map(_buf, usage);
+}
 
-    radeon_cs_space_add_persistent_bo(priv->cs, bo, rd, wd);
-    return TRUE;
+static void radeon_r300_winsys_buffer_unmap(struct r300_winsys_screen *ws,
+                                           struct r300_winsys_buffer *buf)
+{
+    struct pb_buffer *_buf = radeon_pb_buffer(buf);
+
+    pb_unmap(_buf);
 }
 
-static boolean radeon_r300_validate(struct r300_winsys* winsys)
+static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws,
+                                               struct r300_winsys_buffer **pdst,
+                                               struct r300_winsys_buffer *src)
 {
-    struct radeon_winsys_priv* priv =
-        (struct radeon_winsys_priv*)winsys->radeon_winsys;
+    struct pb_buffer *_src = radeon_pb_buffer(src);
+    struct pb_buffer *_dst = radeon_pb_buffer(*pdst);
 
-    if (radeon_cs_space_check(priv->cs) < 0) {
-        return FALSE;
-    }
+    pb_reference(&_dst, _src);
 
-    /* Things are fine, we can proceed as normal. */
-    return TRUE;
+    *pdst = radeon_libdrm_winsys_buffer(_dst);
 }
 
-static boolean radeon_r300_check_cs(struct r300_winsys* winsys, int size)
+static boolean radeon_r300_winsys_is_buffer_referenced(struct r300_winsys_screen *rws,
+                                                      struct r300_winsys_buffer *buf)
 {
-    /* XXX check size here, lazy ass! */
-    /* XXX also validate buffers */
-    return TRUE;
+    struct pb_buffer *_buf = radeon_pb_buffer(buf);
+
+    return radeon_drm_bufmgr_is_buffer_referenced(_buf);
 }
 
-static void radeon_r300_begin_cs(struct r300_winsys* winsys,
-                                 int size,
-                                 const char* file,
-                                 const char* function,
-                                 int line)
+static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws,
+                                                                       struct pipe_screen *screen,
+                                                                       struct winsys_handle *whandle,
+                                                                       unsigned *stride)
 {
-    struct radeon_winsys_priv* priv =
-        (struct radeon_winsys_priv*)winsys->radeon_winsys;
+    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    struct pb_buffer *_buf;
 
-    radeon_cs_begin(priv->cs, size, file, function, line);
+    _buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle);
+    *stride = whandle->stride;
+    return radeon_libdrm_winsys_buffer(_buf);
 }
 
-static void radeon_r300_write_cs_dword(struct r300_winsys* winsys,
-                                       uint32_t dword)
+static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws,
+                                                   struct r300_winsys_buffer *buffer,
+                                                   unsigned stride,
+                                                   struct winsys_handle *whandle)
 {
-    struct radeon_winsys_priv* priv =
-        (struct radeon_winsys_priv*)winsys->radeon_winsys;
+    struct pb_buffer *_buf = radeon_pb_buffer(buffer);
+    boolean ret;
+    ret = radeon_drm_bufmgr_get_handle(_buf, whandle);
+    if (ret)
+       whandle->stride = stride;
+    return ret;
+}
 
-    radeon_cs_write_dword(priv->cs, dword);
+static void radeon_set_flush_cb(struct r300_winsys_screen *rws,
+                                void (*flush_cb)(void *),
+                                void *data)
+{
+    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    ws->flush_cb = flush_cb;
+    ws->flush_data = data;
+    radeon_cs_space_set_flush(ws->cs, flush_cb, data);
 }
 
-static void radeon_r300_write_cs_reloc(struct r300_winsys* winsys,
-                                       struct pipe_buffer* pbuffer,
-                                       uint32_t rd,
-                                       uint32_t wd,
-                                       uint32_t flags)
+static boolean radeon_add_buffer(struct r300_winsys_screen *rws,
+                                 struct r300_winsys_buffer *buf,
+                                 uint32_t rd,
+                                 uint32_t wd)
 {
-    struct radeon_winsys_priv* priv =
-        (struct radeon_winsys_priv*)winsys->radeon_winsys;
-    int retval = 0;
+    struct pb_buffer *_buf = radeon_pb_buffer(buf);
 
-    retval = radeon_cs_write_reloc(priv->cs,
-            ((struct radeon_pipe_buffer*)pbuffer)->bo, rd, wd, flags);
+    return radeon_drm_bufmgr_add_buffer(_buf, rd, wd);
+}
 
-    if (retval) {
-        debug_printf("radeon: Relocation of %p (%d, %d, %d) failed!\n",
-                pbuffer, rd, wd, flags);
+static boolean radeon_validate(struct r300_winsys_screen *rws)
+{
+    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    if (radeon_cs_space_check(ws->cs) < 0) {
+        return FALSE;
     }
+
+    /* Things are fine, we can proceed as normal. */
+    return TRUE;
 }
 
-static void radeon_r300_reset_bos(struct r300_winsys *winsys)
+static boolean radeon_check_cs(struct r300_winsys_screen *rws, int size)
 {
-    struct radeon_winsys_priv* priv =
-        (struct radeon_winsys_priv*)winsys->radeon_winsys;
-    radeon_cs_space_reset_bos(priv->cs);
+    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    struct radeon_cs *cs = ws->cs;
+
+    return radeon_validate(rws) && cs->cdw + size <= cs->ndw;
 }
 
-static void radeon_r300_end_cs(struct r300_winsys* winsys,
-                               const char* file,
-                               const char* function,
-                               int line)
+static void radeon_begin_cs(struct r300_winsys_screen *rws,
+                            int size,
+                            const char* file,
+                            const char* function,
+                            int line)
 {
-    struct radeon_winsys_priv* priv =
-        (struct radeon_winsys_priv*)winsys->radeon_winsys;
+    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    radeon_cs_begin(ws->cs, size, file, function, line);
+}
 
-    radeon_cs_end(priv->cs, file, function, line);
+static void radeon_write_cs_dword(struct r300_winsys_screen *rws,
+                                  uint32_t dword)
+{
+    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    radeon_cs_write_dword(ws->cs, dword);
 }
 
-static void radeon_r300_flush_cs(struct r300_winsys* winsys)
+static void radeon_write_cs_reloc(struct r300_winsys_screen *rws,
+                                  struct r300_winsys_buffer *buf,
+                                  uint32_t rd,
+                                  uint32_t wd,
+                                  uint32_t flags)
 {
-    struct radeon_winsys_priv* priv =
-        (struct radeon_winsys_priv*)winsys->radeon_winsys;
+    struct pb_buffer *_buf = radeon_pb_buffer(buf);
+    radeon_drm_bufmgr_write_reloc(_buf, rd, wd, flags);
+}
+
+static void radeon_reset_bos(struct r300_winsys_screen *rws)
+{
+    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    radeon_cs_space_reset_bos(ws->cs);
+}
+
+static void radeon_end_cs(struct r300_winsys_screen *rws,
+                          const char* file,
+                          const char* function,
+                          int line)
+{
+    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
+    radeon_cs_end(ws->cs, file, function, line);
+}
+
+static void radeon_flush_cs(struct r300_winsys_screen *rws)
+{
+    struct radeon_libdrm_winsys *ws = radeon_winsys_screen(rws);
     int retval;
 
+    /* Don't flush a zero-sized CS. */
+    if (!ws->cs->cdw) {
+        return;
+    }
+
+    radeon_drm_bufmgr_flush_maps(ws->kman);
     /* Emit the CS. */
-    retval = radeon_cs_emit(priv->cs);
+    retval = radeon_cs_emit(ws->cs);
     if (retval) {
         debug_printf("radeon: Bad CS, dumping...\n");
-        radeon_cs_print(priv->cs, stderr);
+        radeon_cs_print(ws->cs, stderr);
     }
 
     /* Reset CS.
      * Someday, when we care about performance, we should really find a way
      * to rotate between two or three CS objects so that the GPU can be
      * spinning through one CS while another one is being filled. */
-    radeon_cs_erase(priv->cs);
+    radeon_cs_erase(ws->cs);
 }
 
-/* Helper function to do the ioctls needed for setup and init. */
-static void do_ioctls(struct r300_winsys* winsys, int fd)
+static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
+                            enum r300_value_id id)
 {
-    struct drm_radeon_gem_info gem_info = {0};
-    struct drm_radeon_info info = {0};
-    int target = 0;
-    int retval;
-
-    info.value = (unsigned long)&target;
-
-    /* First, get the number of pixel pipes */
-    info.request = RADEON_INFO_NUM_GB_PIPES;
-    retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
-    if (retval) {
-        fprintf(stderr, "%s: Failed to get GB pipe count, "
-                "error number %d\n", __FUNCTION__, retval);
-        exit(1);
+    struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws;
+
+    switch(id) {
+    case R300_VID_PCI_ID:
+       return ws->pci_id;
+    case R300_VID_GB_PIPES:
+       return ws->gb_pipes;
+    case R300_VID_Z_PIPES:
+       return ws->z_pipes;
     }
-    winsys->gb_pipes = target;
-
-    /* get Z pipes */
-    info.request = RADEON_INFO_NUM_Z_PIPES;
-    retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
-    if (retval) {
-        fprintf(stderr, "%s: Failed to get GB pipe count, "
-                "error number %d\n", __FUNCTION__, retval);
-        exit(1);
-    }
-    winsys->z_pipes = target;
-
-    /* Then, get PCI ID */
-    info.request = RADEON_INFO_DEVICE_ID;
-    retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
-    if (retval) {
-        fprintf(stderr, "%s: Failed to get PCI ID, "
-                "error number %d\n", __FUNCTION__, retval);
-        exit(1);
-    }
-    winsys->pci_id = target;
-
-    /* Finally, retrieve MM info */
-    retval = drmCommandWriteRead(fd, DRM_RADEON_GEM_INFO,
-            &gem_info, sizeof(gem_info));
-    if (retval) {
-        fprintf(stderr, "%s: Failed to get MM info, error number %d\n",
-                __FUNCTION__, retval);
-        exit(1);
-    }
-    winsys->gart_size = gem_info.gart_size;
-    /* XXX */
-    winsys->vram_size = gem_info.vram_visible;
+    return 0;
 }
 
-struct r300_winsys*
-radeon_create_r300_winsys(int fd, struct radeon_winsys* old_winsys)
+static void
+radeon_winsys_destroy(struct r300_winsys_screen *rws)
 {
-    struct r300_winsys* winsys = CALLOC_STRUCT(r300_winsys);
-    struct radeon_winsys_priv* priv;
-
-    if (winsys == NULL) {
-        return NULL;
-    }
+    struct radeon_libdrm_winsys *ws = (struct radeon_libdrm_winsys *)rws;
+    radeon_cs_destroy(ws->cs);
 
-    priv = old_winsys->priv;
+    ws->kman->destroy(ws->kman);
+    ws->mman->destroy(ws->mman);
 
-    do_ioctls(winsys, fd);
+    radeon_bo_manager_gem_dtor(ws->bom);
+    radeon_cs_manager_gem_dtor(ws->csm);
+}
 
-    priv->csm = radeon_cs_manager_gem_ctor(fd);
+boolean
+radeon_setup_winsys(int fd, struct radeon_libdrm_winsys* ws)
+{
+    
+    ws->csm = radeon_cs_manager_gem_ctor(fd);
+    if (!ws->csm)
+       goto fail;
+    ws->bom = radeon_bo_manager_gem_ctor(fd);
+    if (!ws->bom)
+       goto fail;
+    ws->kman = radeon_drm_bufmgr_create(ws);
+    if (!ws->kman)
+       goto fail;
+
+    ws->mman = pb_malloc_bufmgr_create();
+    if (!ws->mman)
+       goto fail;
+
+    /* Size limit on IBs is 64 kibibytes. */
+    ws->cs = radeon_cs_create(ws->csm, 1024 * 64 / 4);
+    if (!ws->cs)
+       goto fail;
+    radeon_cs_set_limit(ws->cs,
+            RADEON_GEM_DOMAIN_GTT, ws->gart_size);
+    radeon_cs_set_limit(ws->cs,
+            RADEON_GEM_DOMAIN_VRAM, ws->vram_size);
+
+    ws->base.add_buffer = radeon_add_buffer;
+    ws->base.validate = radeon_validate;
+    ws->base.destroy = radeon_winsys_destroy;
+    ws->base.check_cs = radeon_check_cs;
+    ws->base.begin_cs = radeon_begin_cs;
+    ws->base.write_cs_dword = radeon_write_cs_dword;
+    ws->base.write_cs_reloc = radeon_write_cs_reloc;
+    ws->base.end_cs = radeon_end_cs;
+    ws->base.flush_cs = radeon_flush_cs;
+    ws->base.reset_bos = radeon_reset_bos;
+    ws->base.set_flush_cb = radeon_set_flush_cb;
+    ws->base.get_value = radeon_get_value;
+
+    ws->base.buffer_create = radeon_r300_winsys_buffer_create;
+    ws->base.buffer_destroy = radeon_r300_winsys_buffer_destroy;
+    ws->base.buffer_set_tiling = radeon_r300_winsys_buffer_set_tiling;
+    ws->base.buffer_map = radeon_r300_winsys_buffer_map;
+    ws->base.buffer_unmap = radeon_r300_winsys_buffer_unmap;
+    ws->base.buffer_reference = radeon_r300_winsys_buffer_reference;
+    ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle;
+    ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle;
+    ws->base.is_buffer_referenced = radeon_r300_winsys_is_buffer_referenced;
+    return TRUE;
 
-    priv->cs = radeon_cs_create(priv->csm, 1024 * 64 / 4);
-    radeon_cs_set_limit(priv->cs,
-            RADEON_GEM_DOMAIN_GTT, winsys->gart_size);
-    radeon_cs_set_limit(priv->cs,
-            RADEON_GEM_DOMAIN_VRAM, winsys->vram_size);
+fail:
+    if (ws->csm)
+       radeon_cs_manager_gem_dtor(ws->csm);
 
-    winsys->add_buffer = radeon_r300_add_buffer;
-    winsys->validate = radeon_r300_validate;
+    if (ws->bom)
+       radeon_bo_manager_gem_dtor(ws->bom);
 
-    winsys->check_cs = radeon_r300_check_cs;
-    winsys->begin_cs = radeon_r300_begin_cs;
-    winsys->write_cs_dword = radeon_r300_write_cs_dword;
-    winsys->write_cs_reloc = radeon_r300_write_cs_reloc;
-    winsys->end_cs = radeon_r300_end_cs;
-    winsys->flush_cs = radeon_r300_flush_cs;
-    winsys->reset_bos = radeon_r300_reset_bos;
-    winsys->set_flush_cb = radeon_r300_set_flush_cb;
 
-    memcpy(winsys, old_winsys, sizeof(struct radeon_winsys));
+    if (ws->kman)
+       ws->kman->destroy(ws->kman);
+    if (ws->mman)
+       ws->mman->destroy(ws->mman);
 
-    return winsys;
+    if (ws->cs)
+       radeon_cs_destroy(ws->cs);
+    return FALSE;
 }