From 273cc1a69887df2bccfab96120f992c506c9035e Mon Sep 17 00:00:00 2001 From: Jerome Glisse Date: Thu, 6 Nov 2008 00:40:06 +0100 Subject: radeon: lib radeon add bo & cs gem backend --- libdrm/radeon/Makefile.am | 9 +- libdrm/radeon/radeon_bo.h | 9 +- libdrm/radeon/radeon_bo_gem.c | 76 +++++++----- libdrm/radeon/radeon_bo_gem.h | 3 +- libdrm/radeon/radeon_cs_gem.c | 266 ++++++++++++++++++++++++++++++++++++++++++ libdrm/radeon/radeon_cs_gem.h | 40 +++++++ linux-core/drm_gem.c | 3 +- 7 files changed, 367 insertions(+), 39 deletions(-) create mode 100644 libdrm/radeon/radeon_cs_gem.c create mode 100644 libdrm/radeon/radeon_cs_gem.h diff --git a/libdrm/radeon/Makefile.am b/libdrm/radeon/Makefile.am index 6af06a7f..cc4951a9 100644 --- a/libdrm/radeon/Makefile.am +++ b/libdrm/radeon/Makefile.am @@ -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 diff --git a/libdrm/radeon/radeon_bo.h b/libdrm/radeon/radeon_bo.h index c1f25fa1..a0739265 100644 --- a/libdrm/radeon/radeon_bo.h +++ b/libdrm/radeon/radeon_bo.h @@ -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)\ diff --git a/libdrm/radeon/radeon_bo_gem.c b/libdrm/radeon/radeon_bo_gem.c index 21fe41f9..04e36c59 100644 --- a/libdrm/radeon/radeon_bo_gem.c +++ b/libdrm/radeon/radeon_bo_gem.c @@ -42,14 +42,19 @@ 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); } diff --git a/libdrm/radeon/radeon_bo_gem.h b/libdrm/radeon/radeon_bo_gem.h index e0ed61fb..d0997614 100644 --- a/libdrm/radeon/radeon_bo_gem.h +++ b/libdrm/radeon/radeon_bo_gem.h @@ -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 index 00000000..7ed5780b --- /dev/null +++ b/libdrm/radeon/radeon_cs_gem.c @@ -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 + */ +#include +#include +#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 index 00000000..a032a8cc --- /dev/null +++ b/libdrm/radeon/radeon_cs_gem.h @@ -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 + * Nicolai Haehnle + * Jérôme Glisse + */ +#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 diff --git a/linux-core/drm_gem.c b/linux-core/drm_gem.c index 0cbf9cab..607c8b67 100644 --- a/linux-core/drm_gem.c +++ b/linux-core/drm_gem.c @@ -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); -- cgit v1.2.3