diff options
Diffstat (limited to 'libdrm/radeon')
| -rw-r--r-- | libdrm/radeon/Makefile.am | 53 | ||||
| -rw-r--r-- | libdrm/radeon/libdrm_radeon.pc.in | 10 | ||||
| -rw-r--r-- | libdrm/radeon/radeon_bo.h | 179 | ||||
| -rw-r--r-- | libdrm/radeon/radeon_bo_gem.c | 254 | ||||
| -rw-r--r-- | libdrm/radeon/radeon_bo_gem.h | 42 | ||||
| -rw-r--r-- | libdrm/radeon/radeon_cs.h | 208 | ||||
| -rw-r--r-- | libdrm/radeon/radeon_cs_gem.c | 544 | ||||
| -rw-r--r-- | libdrm/radeon/radeon_cs_gem.h | 41 | ||||
| -rw-r--r-- | libdrm/radeon/radeon_track.c | 140 | ||||
| -rw-r--r-- | libdrm/radeon/radeon_track.h | 64 | 
10 files changed, 1535 insertions, 0 deletions
| diff --git a/libdrm/radeon/Makefile.am b/libdrm/radeon/Makefile.am new file mode 100644 index 00000000..bc8a5b87 --- /dev/null +++ b/libdrm/radeon/Makefile.am @@ -0,0 +1,53 @@ +# Copyright © 2008 Jérôme Glisse +# +# 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, sublicense, +# 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 above copyright notice and this permission notice (including the next +# paragraph) shall be included in all copies or substantial portions of the +# Software. +# +# 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 NONINFRINGEMENT.  IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS 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. +# +# Authors: +#    Jérôme Glisse <glisse@freedesktop.org> + +AM_CFLAGS = \ +	$(WARN_CFLAGS) \ +	-I$(top_srcdir)/libdrm \ +	-I$(top_srcdir)/libdrm/radeon \ +	$(PTHREADSTUBS_CFLAGS) \ +	-I$(top_srcdir)/shared-core + +libdrm_radeon_la_LTLIBRARIES = libdrm_radeon.la +libdrm_radeon_ladir = $(libdir) +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_cs_gem.c \ +	radeon_track.c + +libdrm_radeonincludedir = ${includedir}/drm +libdrm_radeoninclude_HEADERS = \ +	radeon_bo.h \ +	radeon_cs.h \ +	radeon_bo_gem.h \ +	radeon_cs_gem.h \ +	radeon_track.h + +pkgconfigdir = @pkgconfigdir@ +pkgconfig_DATA = libdrm_radeon.pc + +EXTRA_DIST = libdrm_radeon.pc.in diff --git a/libdrm/radeon/libdrm_radeon.pc.in b/libdrm/radeon/libdrm_radeon.pc.in new file mode 100644 index 00000000..33068448 --- /dev/null +++ b/libdrm/radeon/libdrm_radeon.pc.in @@ -0,0 +1,10 @@ +prefix=@prefix@ +exec_prefix=@exec_prefix@ +libdir=@libdir@ +includedir=@includedir@ + +Name: libdrm_radeon +Description: Userspace interface to kernel DRM services for radeon +Version: 1.0.1 +Libs: -L${libdir} -ldrm_radeon +Cflags: -I${includedir} -I${includedir}/drm diff --git a/libdrm/radeon/radeon_bo.h b/libdrm/radeon/radeon_bo.h new file mode 100644 index 00000000..3cabdfc4 --- /dev/null +++ b/libdrm/radeon/radeon_bo.h @@ -0,0 +1,179 @@ +/*  + * 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> + */ +#ifndef RADEON_BO_H +#define RADEON_BO_H + +#include <stdio.h> +#include <stdint.h> +#include "radeon_track.h" + +/* bo object */ +#define RADEON_BO_FLAGS_MACRO_TILE  1 +#define RADEON_BO_FLAGS_MICRO_TILE  2 + +struct radeon_bo_manager; + +struct radeon_bo { +    uint32_t                    alignment; +    uint32_t                    handle; +    uint32_t                    size; +    uint32_t                    domains; +    uint32_t                    flags; +    unsigned                    cref; +#ifdef RADEON_BO_TRACK +    struct radeon_track         *track; +#endif +    void                        *ptr; +    struct radeon_bo_manager    *bom; +    uint32_t                    space_accounted; +}; + +/* bo functions */ +struct radeon_bo_funcs { +    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); +    void (*bo_ref)(struct radeon_bo *bo); +    struct radeon_bo *(*bo_unref)(struct radeon_bo *bo); +    int (*bo_map)(struct radeon_bo *bo, int write); +    int (*bo_unmap)(struct radeon_bo *bo); +    int (*bo_wait)(struct radeon_bo *bo); +}; + +struct radeon_bo_manager { +    struct radeon_bo_funcs  *funcs; +    int                     fd; +    struct radeon_tracker   tracker; +}; +     +static inline void _radeon_bo_debug(struct radeon_bo *bo, +                                    const char *op, +                                    const char *file, +                                    const char *func, +                                    int line) +{ +    fprintf(stderr, "%s %p 0x%08X 0x%08X 0x%08X [%s %s %d]\n", +            op, bo, bo->handle, bo->size, bo->cref, file, func, line); +} + +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, domains, flags); +#ifdef RADEON_BO_TRACK +    if (bo) { +        bo->track = radeon_tracker_add_track(&bom->tracker, bo->handle); +        radeon_track_add_event(bo->track, file, func, "open", line); +    } +#endif +    return bo; +} + +static inline void _radeon_bo_ref(struct radeon_bo *bo, +                                  const char *file, +                                  const char *func, +                                  int line) +{ +    bo->cref++; +#ifdef RADEON_BO_TRACK +    radeon_track_add_event(bo->track, file, func, "ref", line);  +#endif +    bo->bom->funcs->bo_ref(bo); +} + +static inline struct radeon_bo *_radeon_bo_unref(struct radeon_bo *bo, +                                                 const char *file, +                                                 const char *func, +                                                 int line) +{ +    bo->cref--; +#ifdef RADEON_BO_TRACK +    radeon_track_add_event(bo->track, file, func, "unref", line); +    if (bo->cref <= 0) { +        radeon_tracker_remove_track(&bo->bom->tracker, bo->track); +        bo->track = NULL; +    } +#endif +    return bo->bom->funcs->bo_unref(bo); +} + +static inline int _radeon_bo_map(struct radeon_bo *bo, +                                 int write, +                                 const char *file, +                                 const char *func, +                                 int line) +{ +    return bo->bom->funcs->bo_map(bo, write); +} + +static inline int _radeon_bo_unmap(struct radeon_bo *bo, +                                   const char *file, +                                   const char *func, +                                   int line) +{ +    return bo->bom->funcs->bo_unmap(bo); +} + +static inline int _radeon_bo_wait(struct radeon_bo *bo, +                                  const char *file, +                                  const char *func, +                                  int line) +{ +    return bo->bom->funcs->bo_wait(bo); +} + +#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)\ +    _radeon_bo_unref(bo, __FILE__, __FUNCTION__, __LINE__) +#define radeon_bo_map(bo, w)\ +    _radeon_bo_map(bo, w, __FILE__, __FUNCTION__, __LINE__) +#define radeon_bo_unmap(bo)\ +    _radeon_bo_unmap(bo, __FILE__, __FUNCTION__, __LINE__) +#define radeon_bo_debug(bo, opcode)\ +    _radeon_bo_debug(bo, opcode, __FILE__, __FUNCTION__, __LINE__) +#define radeon_bo_wait(bo) \ +    _radeon_bo_wait(bo, __FILE__, __func__, __LINE__) + +#endif diff --git a/libdrm/radeon/radeon_bo_gem.c b/libdrm/radeon/radeon_bo_gem.c new file mode 100644 index 00000000..78439b29 --- /dev/null +++ b/libdrm/radeon/radeon_bo_gem.c @@ -0,0 +1,254 @@ +/*  + * Copyright © 2008 Dave Airlie + * 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: + *      Dave Airlie + *      Jérôme Glisse <glisse@freedesktop.org> + */ +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include <errno.h> +#include "xf86drm.h" +#include "drm.h" +#include "radeon_drm.h" +#include "radeon_bo.h" +#include "radeon_bo_gem.h" + +struct radeon_bo_gem { +    struct radeon_bo    base; +    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; +    int r; + +    bo = (struct radeon_bo_gem*)calloc(1, sizeof(struct radeon_bo_gem)); +    if (bo == NULL) { +        return NULL; +    } + +    bo->base.bom = 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->map_count = 0; +    if (handle) { +        struct drm_gem_open open_arg; + +        memset(&open_arg, 0, sizeof(open_arg)); +        open_arg.name = handle; +        r = ioctl(bom->fd, DRM_IOCTL_GEM_OPEN, &open_arg); +        if (r != 0) { +            free(bo); +            return NULL; +        } +        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 = bo->base.domains; +        args.flags = 0; +        args.handle = 0; +        r = drmCommandWriteRead(bom->fd, DRM_RADEON_GEM_CREATE, +                                &args, sizeof(args)); +        bo->base.handle = args.handle; +        if (r) { +            fprintf(stderr, "Failed to allocate :\n"); +            fprintf(stderr, "   size      : %d bytes\n", size); +            fprintf(stderr, "   alignment : %d bytes\n", alignment); +            fprintf(stderr, "   domains   : %d\n", bo->base.domains); +            free(bo); +            return NULL; +        } +    } +    radeon_bo_ref((struct radeon_bo*)bo); +    return (struct radeon_bo*)bo; +} + +static void bo_ref(struct radeon_bo *bo) +{ +} + +static struct radeon_bo *bo_unref(struct radeon_bo *bo) +{ +    struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; +    struct drm_gem_close args; + +    if (bo == NULL) { +        return NULL; +    } +    if (bo->cref) { +        return bo; +    } +    if (bo_gem->map_count) { +        munmap(bo->ptr, bo->size); +    } + +    /* close object */ +    args.handle = bo->handle; +    ioctl(bo->bom->fd, DRM_IOCTL_GEM_CLOSE, &args); +    memset(bo_gem, 0, sizeof(struct radeon_bo_gem)); +    free(bo_gem); +    return NULL; +} + +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; +    void *ptr; + +    if (bo_gem->map_count++ != 0) { +        return 0; +    } +    bo->ptr = NULL; +    args.handle = bo->handle; +    args.offset = 0; +    args.size = (uint64_t)bo->size; +    r = drmCommandWriteRead(bo->bom->fd, +                            DRM_RADEON_GEM_MMAP, +                            &args, +                            sizeof(args)); +    if (r) { +        fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n", +                bo, bo->handle, r); +        return r; +    } +    ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED, bo->bom->fd, args.addr_ptr); +    if (ptr == MAP_FAILED) +        return -errno; +    bo->ptr = ptr; + +    return r; +} + +static int bo_unmap(struct radeon_bo *bo) +{ +    struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; + +    if (--bo_gem->map_count > 0) { +        return 0; +    } +    munmap(bo->ptr, bo->size); +    bo->ptr = NULL; +    return 0; +} + +static int bo_wait(struct radeon_bo *bo) +{ +    struct drm_radeon_gem_wait_idle args; +    int ret; + +    args.handle = bo->handle; +    do { +        ret = drmCommandWriteRead(bo->bom->fd, DRM_RADEON_GEM_WAIT_IDLE, +                                  &args, sizeof(args)); +    } while (ret == -EBUSY); +    return ret; +} + +static struct radeon_bo_funcs bo_gem_funcs = { +    bo_open, +    bo_ref, +    bo_unref, +    bo_map, +    bo_unmap, +    bo_wait +}; + +struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd) +{ +    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_dtor(struct radeon_bo_manager *bom) +{ +    struct bo_manager_gem *bomg = (struct bo_manager_gem*)bom; + +    if (bom == NULL) { +        return; +    } +    free(bomg); +} + +uint32_t radeon_gem_name_bo(struct radeon_bo *bo) +{ +    struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; +    return bo_gem->name; +} + +int radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain) +{ +    struct radeon_bo_gem *bo_gem = (struct radeon_bo_gem*)bo; +    struct drm_radeon_gem_set_domain args; +    int r; + +    args.handle = bo->handle; +    args.read_domains = read_domains; +    args.write_domain = write_domain; + +    r = drmCommandWriteRead(bo->bom->fd, +                            DRM_RADEON_GEM_SET_DOMAIN, +                            &args, +                            sizeof(args)); +    return r; +} diff --git a/libdrm/radeon/radeon_bo_gem.h b/libdrm/radeon/radeon_bo_gem.h new file mode 100644 index 00000000..9d9ce02c --- /dev/null +++ b/libdrm/radeon/radeon_bo_gem.h @@ -0,0 +1,42 @@ +/*  + * Copyright © 2008 Dave Airlie + * 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: + *      Dave Airlie + *      Jérôme Glisse <glisse@freedesktop.org> + */ +#ifndef RADEON_BO_GEM_H +#define RADEON_BO_GEM_H + +#include "radeon_bo.h" + +struct radeon_bo_manager *radeon_bo_manager_gem_ctor(int fd); +void radeon_bo_manager_gem_dtor(struct radeon_bo_manager *bom); + +uint32_t radeon_gem_name_bo(struct radeon_bo *bo); +int radeon_gem_set_domain(struct radeon_bo *bo, uint32_t read_domains, uint32_t write_domain); +#endif diff --git a/libdrm/radeon/radeon_cs.h b/libdrm/radeon/radeon_cs.h new file mode 100644 index 00000000..d8709619 --- /dev/null +++ b/libdrm/radeon/radeon_cs.h @@ -0,0 +1,208 @@ +/*  + * 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_H +#define RADEON_CS_H + +#include <stdint.h> +#include <string.h> +#include "drm.h" +#include "radeon_drm.h" +#include "radeon_bo.h" + +struct radeon_cs_reloc { +    struct radeon_bo    *bo; +    uint32_t            read_domain; +    uint32_t            write_domain; +    uint32_t            flags; +}; + + +#define RADEON_CS_SPACE_OK 0 +#define RADEON_CS_SPACE_OP_TO_BIG 1 +#define RADEON_CS_SPACE_FLUSH 2 + +struct radeon_cs_space_check { +    struct radeon_bo *bo; +    uint32_t read_domains; +    uint32_t write_domain; +    uint32_t new_accounted; +}; + +struct radeon_cs_manager; + +struct radeon_cs { +    struct radeon_cs_manager    *csm; +    void                        *relocs; +    uint32_t                    *packets; +    unsigned                    crelocs; +    unsigned                    relocs_total_size; +    unsigned                    cdw; +    unsigned                    ndw; +    int                         section; +    unsigned                    section_ndw; +    unsigned                    section_cdw; +    const char                  *section_file; +    const char                  *section_func; +    int                         section_line; + +}; + +/* cs functions */ +struct radeon_cs_funcs { +    struct radeon_cs *(*cs_create)(struct radeon_cs_manager *csm, +                                   uint32_t ndw); +    int (*cs_write_reloc)(struct radeon_cs *cs, +                          struct radeon_bo *bo, +                          uint32_t read_domain, +                          uint32_t write_domain, +                          uint32_t flags); +    int (*cs_begin)(struct radeon_cs *cs, +                    uint32_t ndw, +                    const char *file, +                    const char *func, +                    int line); +    int (*cs_end)(struct radeon_cs *cs, +                  const char *file, +                  const char *func, +                  int line); +    int (*cs_emit)(struct radeon_cs *cs); +    int (*cs_destroy)(struct radeon_cs *cs); +    int (*cs_erase)(struct radeon_cs *cs); +    int (*cs_need_flush)(struct radeon_cs *cs); +    void (*cs_print)(struct radeon_cs *cs, FILE *file); +    int (*cs_space_check)(struct radeon_cs *cs, struct radeon_cs_space_check *bos, +			  int num_bo); +}; + +struct radeon_cs_manager { +    struct radeon_cs_funcs  *funcs; +    int                     fd; +    uint32_t vram_limit, gart_limit; +    uint32_t vram_write_used, gart_write_used; +    uint32_t read_used; +}; + +static inline struct radeon_cs *radeon_cs_create(struct radeon_cs_manager *csm, +                                                 uint32_t ndw) +{ +    return csm->funcs->cs_create(csm, ndw); +} + +static inline int radeon_cs_write_reloc(struct radeon_cs *cs, +                                        struct radeon_bo *bo, +                                        uint32_t read_domain, +                                        uint32_t write_domain, +                                        uint32_t flags) +{ +    return cs->csm->funcs->cs_write_reloc(cs, +                                          bo, +                                          read_domain, +                                          write_domain, +                                          flags); +} + +static inline int radeon_cs_begin(struct radeon_cs *cs, +                                  uint32_t ndw, +                                  const char *file, +                                  const char *func, +                                  int line) +{ +    return cs->csm->funcs->cs_begin(cs, ndw, file, func, line); +} + +static inline int radeon_cs_end(struct radeon_cs *cs, +                                const char *file, +                                const char *func, +                                int line) +{ +    return cs->csm->funcs->cs_end(cs, file, func, line); +} + +static inline int radeon_cs_emit(struct radeon_cs *cs) +{ +    return cs->csm->funcs->cs_emit(cs); +} + +static inline int radeon_cs_destroy(struct radeon_cs *cs) +{ +    return cs->csm->funcs->cs_destroy(cs); +} + +static inline int radeon_cs_erase(struct radeon_cs *cs) +{ +    return cs->csm->funcs->cs_erase(cs); +} + +static inline int radeon_cs_need_flush(struct radeon_cs *cs) +{ +    return cs->csm->funcs->cs_need_flush(cs); +} + +static inline void radeon_cs_print(struct radeon_cs *cs, FILE *file) +{ +    cs->csm->funcs->cs_print(cs, file); +} + +static inline int radeon_cs_space_check(struct radeon_cs *cs, +					    struct radeon_cs_space_check *bos, +					    int num_bo) +{ +    return cs->csm->funcs->cs_space_check(cs, bos, num_bo); +} + +static inline void radeon_cs_set_limit(struct radeon_cs *cs, uint32_t domain, uint32_t limit) +{ +     +    if (domain == RADEON_GEM_DOMAIN_VRAM) +	cs->csm->vram_limit = limit; +    else +	cs->csm->gart_limit = limit; +} + +static inline void radeon_cs_write_dword(struct radeon_cs *cs, uint32_t dword) +{ +    cs->packets[cs->cdw++] = dword; +    if (cs->section) { +        cs->section_cdw++; +    } +} + +static inline void radeon_cs_write_qword(struct radeon_cs *cs, uint64_t qword) +{ +    memcpy(cs->packets + cs->cdw, &qword, sizeof(uint64_t)); +    cs->cdw += 2; +    if (cs->section) { +        cs->section_cdw += 2; +    } +} + +#endif diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c new file mode 100644 index 00000000..b9f6f4b7 --- /dev/null +++ b/libdrm/radeon/radeon_cs_gem.c @@ -0,0 +1,544 @@ +/*  + * 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> + */ +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <sys/mman.h> +#include <sys/ioctl.h> +#include "radeon_cs.h" +#include "radeon_cs_gem.h" +#include "radeon_bo_gem.h" +#include "drm.h" +#include "xf86drm.h" +#include "radeon_drm.h" + +#pragma pack(1) +struct cs_reloc_gem { +    uint32_t    handle; +    uint32_t    read_domain; +    uint32_t    write_domain; +    uint32_t    flags; +}; + +#pragma pack() +#define RELOC_SIZE (sizeof(struct cs_reloc_gem) / sizeof(uint32_t)) + +struct cs_gem { +    struct radeon_cs            base; +    struct drm_radeon_cs        cs; +    struct drm_radeon_cs_chunk  chunks[2]; +    unsigned                    nrelocs; +    uint32_t                    *relocs; +    struct radeon_bo            **relocs_bo; +}; + +static struct radeon_cs *cs_gem_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->relocs_bo = (struct radeon_bo**)calloc(1, +                                                csg->nrelocs*sizeof(void*)); +    if (csg->relocs_bo == NULL) { +        free(csg->base.packets); +        free(csg); +        return NULL; +    } +    csg->base.relocs = csg->relocs = (uint32_t*)calloc(1, 4096); +    if (csg->relocs == NULL) { +        free(csg->relocs_bo); +        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_gem_write_reloc(struct radeon_cs *cs, +                              struct radeon_bo *bo, +                              uint32_t read_domain, +                              uint32_t write_domain, +                              uint32_t flags) +{ +    struct cs_gem *csg = (struct cs_gem*)cs; +    struct cs_reloc_gem *reloc; +    uint32_t idx; +    unsigned i; + +    assert(bo->space_accounted); + +    /* check domains */ +    if ((read_domain && write_domain) || (!read_domain && !write_domain)) { +        /* in one CS a bo can only be in read or write domain but not +         * in read & write domain at the same sime +         */ +        return -EINVAL; +    } +    if (read_domain == RADEON_GEM_DOMAIN_CPU) { +        return -EINVAL; +    } +    if (write_domain == RADEON_GEM_DOMAIN_CPU) { +        return -EINVAL; +    } +    /* check if bo is already referenced */ +    for(i = 0; i < cs->crelocs; i++) { +        idx = i * RELOC_SIZE; +        reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; +        if (reloc->handle == bo->handle) { +            /* Check domains must be in read or write. As we check already +             * checked that in argument one of the read or write domain was +             * set we only need to check that if previous reloc as the read +             * domain set then the read_domain should also be set for this +             * new relocation. +             */ +            if (reloc->read_domain && !read_domain) { +                return -EINVAL; +            } +            if (reloc->write_domain && !write_domain) { +                return -EINVAL; +            } +            reloc->read_domain |= read_domain; +            reloc->write_domain |= write_domain; +            /* update flags */ +            reloc->flags |= (flags & reloc->flags); +            /* write relocation packet */ +            radeon_cs_write_dword(cs, 0xc0001000); +            radeon_cs_write_dword(cs, idx); +            return 0; +        } +    } +    /* new relocation */ +    if (csg->base.crelocs >= csg->nrelocs) { +        /* allocate more memory (TODO: should use a slab allocatore maybe) */ +        uint32_t *tmp, size; +        size = ((csg->nrelocs + 1) * sizeof(struct radeon_bo*)); +        tmp = (uint32_t*)realloc(csg->relocs_bo, size); +        if (tmp == NULL) { +            return -ENOMEM; +        } +        csg->relocs_bo = (struct radeon_bo**)tmp; +        size = ((csg->nrelocs + 1) * RELOC_SIZE * 4); +        tmp = (uint32_t*)realloc(csg->relocs, size); +        if (tmp == NULL) { +            return -ENOMEM; +        } +        cs->relocs = csg->relocs = tmp; +        csg->nrelocs += 1; +        csg->chunks[1].chunk_data = (uint64_t)(intptr_t)csg->relocs; +    } +    csg->relocs_bo[csg->base.crelocs] = bo; +    idx = (csg->base.crelocs++) * RELOC_SIZE; +    reloc = (struct cs_reloc_gem*)&csg->relocs[idx]; +    reloc->handle = bo->handle; +    reloc->read_domain = read_domain; +    reloc->write_domain = write_domain; +    reloc->flags = flags; +    csg->chunks[1].length_dw += RELOC_SIZE; +    radeon_bo_ref(bo); +    cs->relocs_total_size += bo->size; +    radeon_cs_write_dword(cs, 0xc0001000); +    radeon_cs_write_dword(cs, idx); +    return 0; +} + +static int cs_gem_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; + + +    if (cs->cdw + ndw > cs->ndw) { +        uint32_t tmp, *ptr; +	int num = (ndw > 0x3FF) ? ndw : 0x3FF; + +        tmp = (cs->cdw + 1 + num) & (~num); +        ptr = (uint32_t*)realloc(cs->packets, 4 * tmp); +        if (ptr == NULL) { +            return -ENOMEM; +        } +        cs->packets = ptr; +        cs->ndw = tmp; +    } + +    return 0; +} + +static int cs_gem_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) %d vs %d\n", +                cs->section_file, cs->section_func, cs->section_line, cs->section_ndw, cs->section_cdw); +        fprintf(stderr, "CS section end at (%s,%s,%d)\n", +                file, func, line); +        return -EPIPE; +    } +    return 0; +} + +static int cs_gem_emit(struct radeon_cs *cs) +{ +    struct cs_gem *csg = (struct cs_gem*)cs; +    uint64_t chunk_array[2]; +    unsigned i; +    int r; + +    csg->chunks[0].length_dw = cs->cdw; + +    chunk_array[0] = (uint64_t)(intptr_t)&csg->chunks[0]; +    chunk_array[1] = (uint64_t)(intptr_t)&csg->chunks[1]; + +    csg->cs.num_chunks = 2; +    csg->cs.chunks = (uint64_t)(intptr_t)chunk_array; + +    r = drmCommandWriteRead(cs->csm->fd, DRM_RADEON_CS, +                            &csg->cs, sizeof(struct drm_radeon_cs)); +    for (i = 0; i < csg->base.crelocs; i++) { +	    csg->relocs_bo[i]->space_accounted = 0; +	    radeon_bo_unref(csg->relocs_bo[i]); +	    csg->relocs_bo[i] = NULL; +    } + +    cs->csm->read_used = 0; +    cs->csm->vram_write_used = 0; +    cs->csm->gart_write_used = 0; +    return r; +} + +static int cs_gem_destroy(struct radeon_cs *cs) +{ +    struct cs_gem *csg = (struct cs_gem*)cs; + +    free(csg->relocs_bo); +    free(cs->relocs); +    free(cs->packets); +    free(cs); +    return 0; +} + +static int cs_gem_erase(struct radeon_cs *cs) +{ +    struct cs_gem *csg = (struct cs_gem*)cs; +    unsigned i; + +    if (csg->relocs_bo) { +        for (i = 0; i < csg->base.crelocs; i++) { +            if (csg->relocs_bo[i]) { +                radeon_bo_unref(csg->relocs_bo[i]); +                csg->relocs_bo[i] = NULL; +            } +        } +    } +    cs->relocs_total_size = 0; +    cs->cdw = 0; +    cs->section = 0; +    cs->crelocs = 0; +    csg->chunks[0].length_dw = 0; +    csg->chunks[1].length_dw = 0; +    return 0; +} + +static int cs_gem_need_flush(struct radeon_cs *cs) +{ +    return 0; //(cs->relocs_total_size > (32*1024*1024)); +} + +#define PACKET_TYPE0 0 +#define PACKET_TYPE1 1 +#define PACKET_TYPE2 2 +#define PACKET_TYPE3 3 +   +#define PACKET3_NOP 0x10 +#define PACKET3_SET_SCISSORS 0x1E +#define PACKET3_3D_DRAW_VBUF 0x28 +#define PACKET3_3D_DRAW_IMMD 0x29 +#define PACKET3_3D_DRAW_INDX 0x2A +#define PACKET3_3D_LOAD_VBPNTR 0x2F +#define PACKET3_INDX_BUFFER 0x33 +#define PACKET3_3D_DRAW_VBUF_2 0x34 +#define PACKET3_3D_DRAW_IMMD_2 0x35 +#define PACKET3_3D_DRAW_INDX_2 0x36 +  +#define CP_PACKET_GET_TYPE(h) (((h) >> 30) & 3) +#define CP_PACKET_GET_COUNT(h) (((h) >> 16) & 0x3FFF) +#define CP_PACKET0_GET_REG(h) (((h) & 0x1FFF) << 2) +#define CP_PACKET0_GET_ONE_REG_WR(h) (((h) >> 15) & 1) +#define CP_PACKET3_GET_OPCODE(h) (((h) >> 8) & 0xFF) + +static void cs_gem_print(struct radeon_cs *cs, FILE *file) +{ +    unsigned opcode; +    unsigned reg; +    unsigned cnt; +    int i, j; + +    for (i = 0; i < cs->cdw;) { +        cnt = CP_PACKET_GET_COUNT(cs->packets[i]); +        switch (CP_PACKET_GET_TYPE(cs->packets[i])) { +        case PACKET_TYPE0: +            fprintf(file, "Pkt0 at %d (%d dwords):\n", i, cnt + 1); +            reg = CP_PACKET0_GET_REG(cs->packets[i]); +            if (CP_PACKET0_GET_ONE_REG_WR(cs->packets[i++])) { +                for (j = 0; j <= cnt; j++) { +                    fprintf(file, "    0x%08X -> 0x%04X\n", +                            cs->packets[i++], reg); +                } +            } else { +                for (j = 0; j <= cnt; j++) { +                    fprintf(file, "    0x%08X -> 0x%04X\n", +                            cs->packets[i++], reg); +                    reg += 4; +                } +            } +            break; +        case PACKET_TYPE3: +            fprintf(file, "Pkt3 at %d :\n", i); +            opcode = CP_PACKET3_GET_OPCODE(cs->packets[i++]); +            switch (opcode) { +            case PACKET3_NOP: +                fprintf(file, "    PACKET3_NOP:\n"); +                break; +            case PACKET3_3D_DRAW_VBUF: +                fprintf(file, "    PACKET3_3D_DRAW_VBUF:\n"); +                break; +            case PACKET3_3D_DRAW_IMMD: +                fprintf(file, "    PACKET3_3D_DRAW_IMMD:\n"); +                break; +            case PACKET3_3D_DRAW_INDX: +                fprintf(file, "    PACKET3_3D_DRAW_INDX:\n"); +                break; +            case PACKET3_3D_LOAD_VBPNTR: +                fprintf(file, "    PACKET3_3D_LOAD_VBPNTR:\n"); +                break; +            case PACKET3_INDX_BUFFER: +                fprintf(file, "    PACKET3_INDX_BUFFER:\n"); +                break; +            case PACKET3_3D_DRAW_VBUF_2: +                fprintf(file, "    PACKET3_3D_DRAW_VBUF_2:\n"); +                break; +            case PACKET3_3D_DRAW_IMMD_2: +                fprintf(file, "    PACKET3_3D_DRAW_IMMD_2:\n"); +                break; +            case PACKET3_3D_DRAW_INDX_2: +                fprintf(file, "    PACKET3_3D_DRAW_INDX_2:\n"); +                break; +            default: +                fprintf(file, "Unknow opcode 0x%02X at %d\n", opcode, i); +                return; +            } +            for (j = 0; j <= cnt; j++) { +                fprintf(file, "        0x%08X\n", cs->packets[i++]); +            } +            break; +        case PACKET_TYPE1: +        case PACKET_TYPE2: +        default: +            fprintf(file, "Unknow packet 0x%08X at %d\n", cs->packets[i], i); +            return; +        } +    } +} + +static int cs_gem_check_space(struct radeon_cs *cs, struct radeon_cs_space_check *bos, int num_bo) +{ +    struct radeon_cs_manager *csm = cs->csm; +    int this_op_read = 0, this_op_gart_write = 0, this_op_vram_write = 0; +    uint32_t read_domains, write_domain; +    int i; +    struct radeon_bo *bo; + +    /* check the totals for this operation */ + +    if (num_bo == 0) +        return 0; + +    /* prepare */ +    for (i = 0; i < num_bo; i++) { +      bo = bos[i].bo; + +      bos[i].new_accounted = 0; +      read_domains = bos[i].read_domains; +      write_domain = bos[i].write_domain; +		 +      /* already accounted this bo */ +      if (write_domain && (write_domain == bo->space_accounted)) { +	      bos[i].new_accounted = bo->space_accounted; +	      continue; +      } +      if (read_domains && ((read_domains << 16) == bo->space_accounted)) { +	      bos[i].new_accounted = bo->space_accounted; +	      continue; +      } +       +      if (bo->space_accounted == 0) { +	  if (write_domain == RADEON_GEM_DOMAIN_VRAM) +	      this_op_vram_write += bo->size; +	  else if (write_domain == RADEON_GEM_DOMAIN_GTT) +	      this_op_gart_write += bo->size; +	  else +	      this_op_read += bo->size; +	  bos[i].new_accounted = (read_domains << 16) | write_domain; +      } else { +	  uint16_t old_read, old_write; +	   +	  old_read = bo->space_accounted >> 16; +	  old_write = bo->space_accounted & 0xffff; + +	  if (write_domain && (old_read & write_domain)) { +	      bos[i].new_accounted = write_domain; +	      /* moving from read to a write domain */ +	      if (write_domain == RADEON_GEM_DOMAIN_VRAM) { +		  this_op_read -= bo->size; +		  this_op_vram_write += bo->size; +	      } else if (write_domain == RADEON_GEM_DOMAIN_VRAM) { +		  this_op_read -= bo->size; +		  this_op_gart_write += bo->size; +	      } +	  } else if (read_domains & old_write) { +	      bos[i].new_accounted = bo->space_accounted & 0xffff; +	  } else { +	      /* rewrite the domains */ +	      if (write_domain != old_write) +		  fprintf(stderr,"WRITE DOMAIN RELOC FAILURE 0x%x %d %d\n", bo->handle, write_domain, old_write); +	      if (read_domains != old_read) +		  fprintf(stderr,"READ DOMAIN RELOC FAILURE 0x%x %d %d\n", bo->handle, read_domains, old_read); +	      return RADEON_CS_SPACE_FLUSH; +	  } +      } +    } +	 +    if (this_op_read < 0) +	    this_op_read = 0; + +    /* check sizes - operation first */ +    if ((this_op_read + this_op_gart_write > csm->gart_limit) || +	(this_op_vram_write > csm->vram_limit)) { +	    return RADEON_CS_SPACE_OP_TO_BIG; +    } +     +    if (((csm->vram_write_used + this_op_vram_write) > csm->vram_limit) || +	((csm->read_used + csm->gart_write_used + this_op_gart_write + this_op_read) > csm->gart_limit)) { +	    return RADEON_CS_SPACE_FLUSH; +    } +     +    csm->gart_write_used += this_op_gart_write; +    csm->vram_write_used += this_op_vram_write; +    csm->read_used += this_op_read; +    /* commit */ +    for (i = 0; i < num_bo; i++) { +	    bo = bos[i].bo; +	    bo->space_accounted = bos[i].new_accounted; +    } +     +    return RADEON_CS_SPACE_OK; +} + +static struct radeon_cs_funcs radeon_cs_gem_funcs = { +    cs_gem_create, +    cs_gem_write_reloc, +    cs_gem_begin, +    cs_gem_end, +    cs_gem_emit, +    cs_gem_destroy, +    cs_gem_erase, +    cs_gem_need_flush, +    cs_gem_print, +    cs_gem_check_space, +}; + +struct radeon_cs_manager *radeon_cs_manager_gem_ctor(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_gem_funcs; +    csm->fd = fd; +    return csm; +} + +void radeon_cs_manager_gem_dtor(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..5efd146f --- /dev/null +++ b/libdrm/radeon/radeon_cs_gem.h @@ -0,0 +1,41 @@ +/*  + * 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_ctor(int fd); +void radeon_cs_manager_gem_dtor(struct radeon_cs_manager *csm); + +#endif diff --git a/libdrm/radeon/radeon_track.c b/libdrm/radeon/radeon_track.c new file mode 100644 index 00000000..1623906f --- /dev/null +++ b/libdrm/radeon/radeon_track.c @@ -0,0 +1,140 @@ +/*  + * 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 <stdio.h> +#include <stdlib.h> +#include <string.h> +#include "radeon_track.h" + +void radeon_track_add_event(struct radeon_track *track, +                            const char *file, +                            const char *func, +                            const char *op, +                            unsigned line) +{ +    struct radeon_track_event *event; + +    if (track == NULL) { +        return; +    } +    event = (void*)calloc(1,sizeof(struct radeon_track_event)); +    if (event == NULL) { +        return; +    } +    event->line = line; +    event->file = strdup(file); +    event->func = strdup(func); +    event->op = strdup(op); +    if (event->file == NULL || event->func == NULL || event->op == NULL) { +        free(event->file); +        free(event->func); +        free(event->op); +        free(event); +        return; +    } +    event->next = track->events; +    track->events = event; +} + +struct radeon_track *radeon_tracker_add_track(struct radeon_tracker *tracker, +                                              unsigned key) +{ +    struct radeon_track *track; + +    track = (struct radeon_track*)calloc(1, sizeof(struct radeon_track)); +    if (track) { +        track->next = tracker->tracks.next; +        track->prev = &tracker->tracks; +        tracker->tracks.next = track; +        if (track->next) { +            track->next->prev = track; +        } +        track->key = key; +        track->events = NULL; +    } +    return track; +} + +void radeon_tracker_remove_track(struct radeon_tracker *tracker, +                                 struct radeon_track *track) +{ +    struct radeon_track_event *event; +    void *tmp; + +    if (track == NULL) { +        return; +    } +    track->prev->next = track->next; +    if (track->next) { +        track->next->prev = track->prev; +    } +    track->next = track->prev = NULL; +    event = track->events; +    while (event) { +        tmp = event; +        free(event->file); +        free(event->func); +        free(event->op); +        event = event->next; +        free(tmp); +    } +    track->events = NULL; +    free(track); +} + +void radeon_tracker_print(struct radeon_tracker *tracker, FILE *file) +{ +    struct radeon_track *track; +    struct radeon_track_event *event; +    void *tmp; + +    track = tracker->tracks.next; +    while (track) { +        event = track->events; +        fprintf(file, "[0x%08X] :\n", track->key); +        while (event) { +            tmp = event; +            fprintf(file, "  [0x%08X:%s](%s:%s:%d)\n", +                    track->key, event->op,  event->file, +                    event->func, event->line); +            free(event->file); +            free(event->func); +            free(event->op); +            event->file = NULL; +            event->func = NULL; +            event->op = NULL; +            event = event->next; +            free(tmp); +        } +        track->events = NULL; +        tmp = track; +        track = track->next; +        free(tmp); +    } +} diff --git a/libdrm/radeon/radeon_track.h b/libdrm/radeon/radeon_track.h new file mode 100644 index 00000000..838d1f38 --- /dev/null +++ b/libdrm/radeon/radeon_track.h @@ -0,0 +1,64 @@ +/*  + * 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> + */ +#ifndef RADEON_TRACK_H +#define RADEON_TRACK_H + +struct radeon_track_event { +    struct radeon_track_event   *next; +    char                        *file; +    char                        *func; +    char                        *op; +    unsigned                    line; +}; + +struct radeon_track { +    struct radeon_track         *next; +    struct radeon_track         *prev; +    unsigned                    key; +    struct radeon_track_event   *events; +}; + +struct radeon_tracker { +    struct radeon_track         tracks;  +}; + +void radeon_track_add_event(struct radeon_track *track, +                            const char *file, +                            const char *func, +                            const char *op, +                            unsigned line); +struct radeon_track *radeon_tracker_add_track(struct radeon_tracker *tracker, +                                              unsigned key); +void radeon_tracker_remove_track(struct radeon_tracker *tracker, +                                 struct radeon_track *track); +void radeon_tracker_print(struct radeon_tracker *tracker, +                          FILE *file); + +#endif | 
