radeon: lib radeon add bo & cs gem backend

main
Jerome Glisse 2008-11-06 00:40:06 +01:00
parent 2d822542c7
commit 273cc1a698
7 changed files with 367 additions and 39 deletions

View 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_LIBADD = ../libdrm.la @PTHREADSTUBS_LIBS@
libdrm_radeon_la_SOURCES = \ 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 = \ libdrm_radeoninclude_HEADERS = \
radeon_bo.h \ radeon_bo.h \
radeon_cs.h radeon_cs.h \
radeon_bo_gem.h \
radeon_cs_gem.h

View File

@ -42,6 +42,7 @@ struct radeon_bo {
uint32_t alignment; uint32_t alignment;
uint32_t handle; uint32_t handle;
uint32_t size; uint32_t size;
uint32_t domains;
uint32_t flags; uint32_t flags;
unsigned cref; unsigned cref;
void *ptr; void *ptr;
@ -54,6 +55,7 @@ struct radeon_bo_funcs {
uint32_t handle, uint32_t handle,
uint32_t size, uint32_t size,
uint32_t alignment, uint32_t alignment,
uint32_t domains,
uint32_t flags); uint32_t flags);
void (*bo_ref)(struct radeon_bo *bo); void (*bo_ref)(struct radeon_bo *bo);
void (*bo_unref)(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 handle,
uint32_t size, uint32_t size,
uint32_t alignment, uint32_t alignment,
uint32_t domains,
uint32_t flags, uint32_t flags,
const char *file, const char *file,
const char *func, const char *func,
int line) int line)
{ {
struct radeon_bo *bo; 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 #ifdef RADEON_BO_TRACK_OPEN
if (bo) { if (bo) {
_radeon_bo_debug(bo, 1, file, func, line); _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); return bo->bom->funcs->bo_unmap(bo);
} }
#define radeon_bo_open(bom, h, s, a, f)\ #define radeon_bo_open(bom, h, s, a, d, f)\
_radeon_bo_open(bom, h, s, a, f, __FILE__, __FUNCTION__, __LINE__) _radeon_bo_open(bom, h, s, a, d, f, __FILE__, __FUNCTION__, __LINE__)
#define radeon_bo_ref(bo)\ #define radeon_bo_ref(bo)\
_radeon_bo_ref(bo, __FILE__, __FUNCTION__, __LINE__) _radeon_bo_ref(bo, __FILE__, __FUNCTION__, __LINE__)
#define radeon_bo_unref(bo)\ #define radeon_bo_unref(bo)\

View File

@ -42,14 +42,19 @@
struct radeon_bo_gem { struct radeon_bo_gem {
struct radeon_bo base; struct radeon_bo base;
int ref_count; uint32_t name;
int map_count; int map_count;
}; };
struct bo_manager_gem {
struct radeon_bo_manager base;
};
static struct radeon_bo *bo_open(struct radeon_bo_manager *bom, static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
uint32_t handle, uint32_t handle,
uint32_t size, uint32_t size,
uint32_t alignment, uint32_t alignment,
uint32_t domains,
uint32_t flags) uint32_t flags)
{ {
struct radeon_bo_gem *bo; 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.handle = 0;
bo->base.size = size; bo->base.size = size;
bo->base.alignment = alignment; bo->base.alignment = alignment;
bo->base.domains = domains;
bo->base.flags = flags; bo->base.flags = flags;
bo->base.ptr = NULL; bo->base.ptr = NULL;
bo->ref_count = 0;
bo->map_count = 0; bo->map_count = 0;
if (handle) { if (handle) {
struct drm_gem_open open_arg; struct drm_gem_open open_arg;
@ -80,13 +84,15 @@ static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
free(bo); free(bo);
return NULL; return NULL;
} }
bo->base.handle = handle; bo->base.handle = open_arg.handle;
bo->base.size = open_arg.size;
bo->name = handle;
} else { } else {
struct drm_radeon_gem_create args; struct drm_radeon_gem_create args;
args.size = size; args.size = size;
args.alignment = alignment; args.alignment = alignment;
args.initial_domain = RADEON_GEM_DOMAIN_CPU; args.initial_domain = bo->base.domains;
args.no_backing_store = 0; args.no_backing_store = 0;
r = drmCommandWriteRead(bom->fd, DRM_RADEON_GEM_CREATE, r = drmCommandWriteRead(bom->fd, DRM_RADEON_GEM_CREATE,
&args, sizeof(args)); &args, sizeof(args));
@ -99,7 +105,11 @@ static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
return (struct radeon_bo*)bo; 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 radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
struct drm_gem_close args; struct drm_gem_close args;
@ -107,10 +117,10 @@ static void bo_close(struct radeon_bo *bo)
if (bo == NULL) { if (bo == NULL) {
return; return;
} }
if (bo_gem->ref_count) { if (bo->cref) {
/* FIXME: what to do ? */ /* FIXME: what to do ? */
return;
} }
if (bo_gem->map_count) { if (bo_gem->map_count) {
munmap(bo->ptr, bo->size); munmap(bo->ptr, bo->size);
} }
@ -121,33 +131,20 @@ static void bo_close(struct radeon_bo *bo)
free(bo_gem); free(bo_gem);
} }
static void bo_pin(struct radeon_bo *bo) static int bo_map(struct radeon_bo *bo, int write)
{
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)
{ {
struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo;
struct drm_radeon_gem_mmap args; struct drm_radeon_gem_mmap args;
int r; int r;
uint8_t *tt;
if (bo_gem->map_count++ != 0) { if (bo_gem->map_count++ != 0) {
return 0; return 0;
} }
bo->ptr = NULL;
args.handle = bo->handle; args.handle = bo->handle;
args.offset = 0; args.offset = 0;
args.size = bo->size; args.size = (uint64_t)bo->size;
r = drmCommandWriteRead(bo->bom->fd, r = drmCommandWriteRead(bo->bom->fd,
DRM_RADEON_GEM_MMAP, DRM_RADEON_GEM_MMAP,
&args, &args,
@ -155,6 +152,7 @@ static int bo_map(struct radeon_bo *bo, unsigned int flags)
if (!r) { if (!r) {
bo->ptr = (void *)(unsigned long)args.addr_ptr; bo->ptr = (void *)(unsigned long)args.addr_ptr;
} }
tt = bo->ptr;
return r; return r;
} }
@ -165,7 +163,6 @@ static int bo_unmap(struct radeon_bo *bo)
if (--bo_gem->map_count > 0) { if (--bo_gem->map_count > 0) {
return 0; return 0;
} }
munmap(bo->ptr, bo->size); munmap(bo->ptr, bo->size);
bo->ptr = NULL; bo->ptr = NULL;
return 0; return 0;
@ -173,14 +170,31 @@ static int bo_unmap(struct radeon_bo *bo)
static struct radeon_bo_funcs bo_gem_funcs = { static struct radeon_bo_funcs bo_gem_funcs = {
bo_open, bo_open,
bo_close, bo_ref,
bo_pin, bo_unref,
bo_unpin,
bo_map, bo_map,
bo_unmap 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);
} }

View File

@ -33,6 +33,7 @@
#include "radeon_bo.h" #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 #endif

View File

@ -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);
}

View File

@ -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

View File

@ -263,8 +263,9 @@ again:
spin_lock(&dev->object_name_lock); spin_lock(&dev->object_name_lock);
if (obj->name) { if (obj->name) {
args->name = (uint64_t) obj->name;
spin_unlock(&dev->object_name_lock); spin_unlock(&dev->object_name_lock);
return -EEXIST; return 0;
} }
ret = idr_get_new_above(&dev->object_name_idr, obj, 1, ret = idr_get_new_above(&dev->object_name_idr, obj, 1,
&obj->name); &obj->name);