]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - glsdk/libdrm.git/commitdiff
radeon: lib radeon add bo & cs gem backend
authorJerome Glisse <glisse@freedesktop.org>
Wed, 5 Nov 2008 23:40:06 +0000 (00:40 +0100)
committerJerome Glisse <glisse@freedesktop.org>
Wed, 5 Nov 2008 23:40:06 +0000 (00:40 +0100)
libdrm/radeon/Makefile.am
libdrm/radeon/radeon_bo.h
libdrm/radeon/radeon_bo_gem.c
libdrm/radeon/radeon_bo_gem.h
libdrm/radeon/radeon_cs_gem.c [new file with mode: 0644]
libdrm/radeon/radeon_cs_gem.h [new file with mode: 0644]
linux-core/drm_gem.c

index 6af06a7f51d5156dd49d76b591986331c1e6b554..cc4951a9b877bf4bdb3d149e0ab4fdcbbec29922 100644 (file)
@@ -35,9 +35,12 @@ libdrm_radeon_la_LDFLAGS = -version-number 1:0:0 -no-undefined
 libdrm_radeon_la_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
 
 libdrm_radeon_la_SOURCES = \
-       radeon_bo_gem.c
+       radeon_bo_gem.c \
+       radeon_cs_gem.c
 
-libdrm_radeonincludedir = ${includedir}
+libdrm_radeonincludedir = ${includedir}/drm
 libdrm_radeoninclude_HEADERS = \
        radeon_bo.h \
-       radeon_cs.h
+       radeon_cs.h \
+       radeon_bo_gem.h \
+       radeon_cs_gem.h
index c1f25fa113c0e27a99f746f2079848405f34cc91..a0739265781b1b16beba0d3d49c75c598057e56e 100644 (file)
@@ -42,6 +42,7 @@ struct radeon_bo {
     uint32_t                    alignment;
     uint32_t                    handle;
     uint32_t                    size;
+    uint32_t                    domains;
     uint32_t                    flags;
     unsigned                    cref;
     void                        *ptr;
@@ -54,6 +55,7 @@ struct radeon_bo_funcs {
                                  uint32_t handle,
                                  uint32_t size,
                                  uint32_t alignment,
+                                 uint32_t domains,
                                  uint32_t flags);
     void (*bo_ref)(struct radeon_bo *bo);
     void (*bo_unref)(struct radeon_bo *bo);
@@ -80,13 +82,14 @@ static inline struct radeon_bo *_radeon_bo_open(struct radeon_bo_manager *bom,
                                                 uint32_t handle,
                                                 uint32_t size,
                                                 uint32_t alignment,
+                                                uint32_t domains,
                                                 uint32_t flags,
                                                 const char *file,
                                                 const char *func,
                                                 int line)
 {
     struct radeon_bo *bo;
-    bo = bom->funcs->bo_open(bom, handle, size, alignment, flags);
+    bo = bom->funcs->bo_open(bom, handle, size, alignment, domains, flags);
 #ifdef RADEON_BO_TRACK_OPEN
     if (bo) {
         _radeon_bo_debug(bo, 1, file, func, line);
@@ -142,8 +145,8 @@ static inline int _radeon_bo_unmap(struct radeon_bo *bo,
     return bo->bom->funcs->bo_unmap(bo);
 }
 
-#define radeon_bo_open(bom, h, s, a, f)\
-    _radeon_bo_open(bom, h, s, a, f, __FILE__, __FUNCTION__, __LINE__)
+#define radeon_bo_open(bom, h, s, a, d, f)\
+    _radeon_bo_open(bom, h, s, a, d, f, __FILE__, __FUNCTION__, __LINE__)
 #define radeon_bo_ref(bo)\
     _radeon_bo_ref(bo, __FILE__, __FUNCTION__, __LINE__)
 #define radeon_bo_unref(bo)\
index 21fe41f9f411149b112c52e2fea2e07714933aae..04e36c59b595161e23d9415e2fbdd9eb12422797 100644 (file)
 
 struct radeon_bo_gem {
     struct radeon_bo    base;
-    int                 ref_count;
+    uint32_t            name;
     int                 map_count;
 };
 
+struct bo_manager_gem {
+    struct radeon_bo_manager    base;
+};
+
 static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
                                  uint32_t handle,
                                  uint32_t size,
                                  uint32_t alignment,
+                                 uint32_t domains,
                                  uint32_t flags)
 {
     struct radeon_bo_gem *bo;
@@ -64,11 +69,10 @@ static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
     bo->base.handle = 0;
     bo->base.size = size;
     bo->base.alignment = alignment;
+    bo->base.domains = domains;
     bo->base.flags = flags;
     bo->base.ptr = NULL;
-    bo->ref_count = 0;
     bo->map_count = 0;
-
     if (handle) {
         struct drm_gem_open open_arg;
 
@@ -80,13 +84,15 @@ static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
             free(bo);
             return NULL;
         }
-        bo->base.handle = handle;
+        bo->base.handle = open_arg.handle;
+        bo->base.size = open_arg.size;
+        bo->name = handle;
     } else {
         struct drm_radeon_gem_create args;
 
         args.size = size;
         args.alignment = alignment;
-        args.initial_domain = RADEON_GEM_DOMAIN_CPU;
+        args.initial_domain = bo->base.domains;
         args.no_backing_store = 0;
         r = drmCommandWriteRead(bom->fd, DRM_RADEON_GEM_CREATE,
                                 &args, sizeof(args));
@@ -99,7 +105,11 @@ static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
     return (struct radeon_bo*)bo;
 }
 
-static void bo_close(struct radeon_bo *bo)
+static void bo_ref(struct radeon_bo *bo)
+{
+}
+
+static void bo_unref(struct radeon_bo *bo)
 {
     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
     struct drm_gem_close args;
@@ -107,10 +117,10 @@ static void bo_close(struct radeon_bo *bo)
     if (bo == NULL) {
         return;
     }
-    if (bo_gem->ref_count) {
+    if (bo->cref) {
         /* FIXME: what to do ? */
+        return;
     }
-
     if (bo_gem->map_count) {
         munmap(bo->ptr, bo->size);
     }
@@ -121,33 +131,20 @@ static void bo_close(struct radeon_bo *bo)
     free(bo_gem);
 }
 
-static void bo_pin(struct radeon_bo *bo)
-{
-    struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
-
-    bo_gem->ref_count++;
-}
-
-static void bo_unpin(struct radeon_bo *bo)
-{
-    struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
-
-    bo_gem->ref_count--;
-}
-
-static int bo_map(struct radeon_bo *bo, unsigned int flags)
+static int bo_map(struct radeon_bo *bo, int write)
 {
     struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
     struct drm_radeon_gem_mmap args;
     int r;
+    uint8_t *tt;
 
     if (bo_gem->map_count++ != 0) {
         return 0;
     }
+    bo->ptr = NULL;
     args.handle = bo->handle;
     args.offset = 0;
-    args.size = bo->size;
-
+    args.size = (uint64_t)bo->size;
     r = drmCommandWriteRead(bo->bom->fd,
                             DRM_RADEON_GEM_MMAP,
                             &args,
@@ -155,6 +152,7 @@ static int bo_map(struct radeon_bo *bo, unsigned int flags)
     if (!r) {
         bo->ptr = (void *)(unsigned long)args.addr_ptr;
     }
+    tt = bo->ptr;
     return r;
 }
 
@@ -165,7 +163,6 @@ static int bo_unmap(struct radeon_bo *bo)
     if (--bo_gem->map_count > 0) {
         return 0;
     }
-
     munmap(bo->ptr, bo->size);
     bo->ptr = NULL;
     return 0;
@@ -173,14 +170,31 @@ static int bo_unmap(struct radeon_bo *bo)
 
 static struct radeon_bo_funcs bo_gem_funcs = {
     bo_open,
-    bo_close,
-    bo_pin,
-    bo_unpin,
+    bo_ref,
+    bo_unref,
     bo_map,
     bo_unmap
 };
 
-struct radeon_bo_funcs *radeon_bo_gem_initialize(int fd)
+struct radeon_bo_manager *radeon_bo_manager_gem(int fd)
 {
-    return &bo_gem_funcs; 
+    struct bo_manager_gem *bomg;
+
+    bomg = (struct bo_manager_gem*)calloc(1, sizeof(struct bo_manager_gem));
+    if (bomg == NULL) {
+        return NULL;
+    }
+    bomg->base.funcs = &bo_gem_funcs;
+    bomg->base.fd = fd;
+    return (struct radeon_bo_manager*)bomg;
+}
+
+void radeon_bo_manager_gem_shutdown(struct radeon_bo_manager *bom)
+{
+    struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom;
+
+    if (bom == NULL) {
+        return;
+    }
+    free(bomg);
 }
index e0ed61fb8222baa52ce1aa337fcae2cdeb6d8c9d..d0997614dbd9e52e99865147a9ac6ab594dce46c 100644 (file)
@@ -33,6 +33,7 @@
 
 #include "radeon_bo.h"
 
-struct radeon_bo_funcs *radeon_bo_gem_initialize(int fd);
+struct radeon_bo_manager *radeon_bo_manager_gem(int fd);
+void radeon_bo_manager_gem_shutdown(struct radeon_bo_manager *bom);
 
 #endif
diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c
new file mode 100644 (file)
index 0000000..7ed5780
--- /dev/null
@@ -0,0 +1,266 @@
+/* 
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ *      Jérôme Glisse <glisse@freedesktop.org>
+ */
+#include <errno.h>
+#include <stdlib.h>
+#include "radeon_cs.h"
+#include "radeon_cs_gem.h"
+#include "radeon_bo_gem.h"
+#include "drm.h"
+#include "radeon_drm.h"
+
+#pragma pack(1)
+struct cs_reloc_gem {
+    uint32_t    handle;
+    uint32_t    domains;
+    uint32_t    soffset;
+    uint32_t    eoffset;
+};
+#pragma pack()
+
+struct cs_gem {
+    struct radeon_cs            base;
+    struct drm_radeon_cs2       cs;
+    struct drm_radeon_cs_chunk  chunks[2];
+    unsigned                    nrelocs;
+    uint32_t                    *relocs;
+};
+
+static struct radeon_cs *cs_create(struct radeon_cs_manager *csm,
+                                   uint32_t ndw)
+{
+    struct cs_gem *csg;
+
+    /* max cmd buffer size is 64Kb */
+    if (ndw > (64 * 1024 / 4)) {
+        return NULL;
+    }
+    csg = (struct cs_gem*)calloc(1, sizeof(struct cs_gem));
+    if (csg == NULL) {
+        return NULL;
+    }
+    csg->base.csm = csm;
+    csg->base.ndw = 64 * 1024 / 4;
+    csg->base.packets = (uint32_t*)calloc(1, 64 * 1024);
+    if (csg->base.packets == NULL) {
+        free(csg);
+        return NULL;
+    }
+    csg->base.relocs_total_size = 0;
+    csg->base.crelocs = 0;
+    csg->nrelocs = 4096 / (4 * 4) ;
+    csg->base.relocs = csg->relocs = (uint32_t*)calloc(1, 4096);
+    if (csg->relocs == NULL) {
+        free(csg->base.packets);
+        free(csg);
+        return NULL;
+    }
+    csg->chunks[0].chunk_id = RADEON_CHUNK_ID_IB;
+    csg->chunks[0].length_dw = 0;
+    csg->chunks[0].chunk_data = (uint64_t)(intptr_t)csg->base.packets;
+    csg->chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS;
+    csg->chunks[1].length_dw = 0;
+    csg->chunks[1].chunk_data = (uint64_t)(intptr_t)csg->relocs;
+    return (struct radeon_cs*)csg;
+}
+
+static int cs_write_dword(struct radeon_cs *cs, uint32_t dword)
+{
+    if (cs->cdw >= cs->ndw) {
+        uint32_t tmp, *ptr;
+        tmp = (cs->cdw + 1 + 0x3FF) & (~0x3FF);
+        ptr = (uint32_t*)realloc(cs->packets, 4 * tmp);
+        if (ptr == NULL) {
+            return -ENOMEM;
+        }
+        cs->packets = ptr;
+        cs->ndw = tmp;
+    }
+    cs->packets[cs->cdw++] = dword;
+    if (cs->section) {
+        cs->section_cdw++;
+    }
+    return 0;
+}
+
+static int cs_write_reloc(struct radeon_cs *cs,
+                          struct radeon_bo *bo,
+                          uint32_t soffset,
+                          uint32_t eoffset,
+                          uint32_t domains)
+{
+    struct cs_gem *csg = (struct cs_gem*)cs;
+    struct cs_reloc_gem *reloc;
+    unsigned i;
+
+    /* check reloc window */
+    if (eoffset > bo->size) {
+        return -EINVAL;
+    }
+    if (soffset > eoffset) {
+        return -EINVAL;
+    }
+    /* check if bo is already referenced */
+    for(i = 0; i < cs->crelocs; i++) {
+        reloc = (struct cs_reloc_gem*)&csg->relocs[i * 4];
+
+        if (reloc->handle == bo->handle) {
+            /* update start offset and size */
+            if (eoffset > reloc->eoffset) {
+                reloc->eoffset = eoffset;
+            }
+            if (soffset < reloc->soffset) {
+                reloc->soffset = soffset;
+            }
+            reloc->domains |= domains;
+            return 0;
+        }
+    }
+    /* add bo */
+    if (csg->base.crelocs >= csg->nrelocs) {
+        uint32_t *tmp, size;
+        size = (csg->nrelocs * 4 * 4) + (4096 / (4 * 4));
+        tmp = (uint32_t*)realloc(csg->relocs, size);
+        if (tmp == NULL) {
+            return -ENOMEM;
+        }
+        cs->relocs = csg->relocs = tmp;
+        csg->nrelocs = size / (4 * 4);
+    }
+    reloc = (struct cs_reloc_gem*)&csg->relocs[csg->base.crelocs * 4];
+    reloc->handle = bo->handle;
+    reloc->soffset = soffset;
+    reloc->eoffset = eoffset;
+    reloc->domains = domains;
+    cs->crelocs++;
+    radeon_bo_ref(bo);
+    return 0;
+}
+
+static int cs_begin(struct radeon_cs *cs,
+                    uint32_t ndw,
+                    const char *file,
+                    const char *func,
+                    int line)
+{
+    if (cs->section) {
+        fprintf(stderr, "CS already in a section(%s,%s,%d)\n",
+                cs->section_file, cs->section_func, cs->section_line);
+        fprintf(stderr, "CS can't start section(%s,%s,%d)\n",
+                file, func, line);
+        return -EPIPE;
+    }
+    cs->section = 1;
+    cs->section_ndw = ndw;
+    cs->section_cdw = 0;
+    cs->section_file = file;
+    cs->section_func = func;
+    cs->section_line = line;
+    return 0;
+}
+
+static int cs_end(struct radeon_cs *cs,
+                  const char *file,
+                  const char *func,
+                  int line)
+
+{
+    if (!cs->section) {
+        fprintf(stderr, "CS no section to end at (%s,%s,%d)\n",
+                file, func, line);
+        return -EPIPE;
+    }
+    cs->section = 0;
+    if (cs->section_ndw != cs->section_cdw) {
+        fprintf(stderr, "CS section size missmatch start at (%s,%s,%d)\n",
+                cs->section_file, cs->section_func, cs->section_line);
+        fprintf(stderr, "CS section end at (%s,%s,%d)\n",
+                file, func, line);
+        return -EPIPE;
+    }
+    return 0;
+}
+
+static int cs_emit(struct radeon_cs *cs)
+{
+    return 0;
+}
+
+static int cs_destroy(struct radeon_cs *cs)
+{
+    free(cs->relocs);
+    free(cs->packets);
+    free(cs);
+    return 0;
+}
+
+static int cs_erase(struct radeon_cs *cs)
+{
+    cs->relocs_total_size = 0;
+    cs->relocs = NULL;
+    cs->crelocs = 0;
+    cs->cdw = 0;
+    cs->section = 0;
+    return 0;
+}
+
+static int cs_need_flush(struct radeon_cs *cs)
+{
+    return (cs->relocs_total_size > (7*1024*1024));
+}
+
+struct radeon_cs_funcs  radeon_cs_funcs = {
+    cs_create,
+    cs_write_dword,
+    cs_write_reloc,
+    cs_begin,
+    cs_end,
+    cs_emit,
+    cs_destroy,
+    cs_erase,
+    cs_need_flush
+};
+
+struct radeon_cs_manager *radeon_cs_manager_gem(int fd)
+{
+    struct radeon_cs_manager *csm;
+
+    csm = (struct radeon_cs_manager*)calloc(1,
+                                            sizeof(struct radeon_cs_manager));
+    if (csm == NULL) {
+        return NULL;
+    }
+    csm->funcs = &radeon_cs_funcs;
+    csm->fd = fd;
+    return csm;
+}
+
+void radeon_cs_manager_gem_shutdown(struct radeon_cs_manager *csm)
+{
+    free(csm);
+}
diff --git a/libdrm/radeon/radeon_cs_gem.h b/libdrm/radeon/radeon_cs_gem.h
new file mode 100644 (file)
index 0000000..a032a8c
--- /dev/null
@@ -0,0 +1,40 @@
+/* 
+ * Copyright © 2008 Nicolai Haehnle
+ * Copyright © 2008 Jérôme Glisse
+ * All Rights Reserved.
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
+ * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
+ * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
+ * USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ */
+/*
+ * Authors:
+ *      Aapo Tahkola <aet@rasterburn.org>
+ *      Nicolai Haehnle <prefect_@gmx.net>
+ *      Jérôme Glisse <glisse@freedesktop.org>
+ */
+#ifndef RADEON_CS_GEM_H
+#define RADEON_CS_GEM_H
+
+#include "radeon_cs.h"
+
+struct radeon_cs_manager *radeon_cs_manager_gem(int fd);
+void radeon_cs_manager_gem_shutdown(struct radeon_cs_manager *csm);
+
+#endif
index 0cbf9cab24cabbd19b34ca837e27b04672fc6f84..607c8b6702b16e5ea21f290340079951670cd094 100644 (file)
@@ -263,8 +263,9 @@ again:
 
        spin_lock(&dev->object_name_lock);
        if (obj->name) {
+               args->name = (uint64_t) obj->name;
                spin_unlock(&dev->object_name_lock);
-               return -EEXIST;
+               return 0;
        }
        ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
                                 &obj->name);