libdrm/radeon: add initial libdrm_radeon

requires --enable-radeon-experimental-api for now
main
Dave Airlie 2009-06-17 17:47:42 +10:00
parent 3d4bfe8c89
commit 2fa2db138b
13 changed files with 1679 additions and 2 deletions

View File

@ -47,6 +47,11 @@ AC_ARG_ENABLE(nouveau-experimental-api,
[Enable support for nouveau's experimental API (default: disabled)]),
[NOUVEAU=$enableval], [NOUVEAU=no])
AC_ARG_ENABLE(radeon-experimental-api,
AS_HELP_STRING([--enable-radeon-experimental-api],
[Enable support for radeon's KMS API (default: disabled)]),
[RADEON=$enableval], [RADEON=no])
dnl ===========================================================================
dnl check compiler flags
AC_DEFUN([LIBDRM_CC_TRY_FLAG], [
@ -125,6 +130,8 @@ fi
AM_CONDITIONAL(HAVE_NOUVEAU, [test "x$NOUVEAU" = xyes])
AM_CONDITIONAL(HAVE_RADEON, [test "x$RADEON" = xyes])
PKG_CHECK_MODULES(CAIRO, cairo, [HAVE_CAIRO=yes], [HAVE_CAIRO=no])
if test "x$HAVE_CAIRO" = xyes; then
AC_DEFINE(HAVE_CAIRO, 1, [Have cairo support])
@ -144,6 +151,8 @@ AC_OUTPUT([
Makefile
libdrm/Makefile
libdrm/intel/Makefile
libdrm/radeon/Makefile
libdrm/radeon/libdrm_radeon.pc
libdrm/nouveau/Makefile
libdrm/nouveau/libdrm_nouveau.pc
shared-core/Makefile

View File

@ -22,7 +22,11 @@ if HAVE_NOUVEAU
NOUVEAU_SUBDIR = nouveau
endif
SUBDIRS = . intel $(NOUVEAU_SUBDIR)
if HAVE_RADEON
RADEON_SUBDIR = radeon
endif
SUBDIRS = . intel $(NOUVEAU_SUBDIR) $(RADEON_SUBDIR)
libdrm_la_LTLIBRARIES = libdrm.la
libdrm_ladir = $(libdir)

53
libdrm/radeon/Makefile.am Normal file
View File

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

View File

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

179
libdrm/radeon/radeon_bo.h Normal file
View File

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

View File

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

View File

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

208
libdrm/radeon/radeon_cs.h Normal file
View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -492,6 +492,16 @@ typedef struct {
#define DRM_RADEON_SETPARAM 0x19
#define DRM_RADEON_SURF_ALLOC 0x1a
#define DRM_RADEON_SURF_FREE 0x1b
/* KMS ioctl */
#define DRM_RADEON_GEM_INFO 0x1c
#define DRM_RADEON_GEM_CREATE 0x1d
#define DRM_RADEON_GEM_MMAP 0x1e
#define DRM_RADEON_GEM_PREAD 0x21
#define DRM_RADEON_GEM_PWRITE 0x22
#define DRM_RADEON_GEM_SET_DOMAIN 0x23
#define DRM_RADEON_GEM_WAIT_IDLE 0x24
#define DRM_RADEON_CS 0x26
#define DRM_RADEON_INFO 0x27
#define DRM_IOCTL_RADEON_CP_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_CP_INIT, drm_radeon_init_t)
#define DRM_IOCTL_RADEON_CP_START DRM_IO( DRM_COMMAND_BASE + DRM_RADEON_CP_START)
@ -521,6 +531,17 @@ typedef struct {
#define DRM_IOCTL_RADEON_SURF_ALLOC DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_ALLOC, drm_radeon_surface_alloc_t)
#define DRM_IOCTL_RADEON_SURF_FREE DRM_IOW( DRM_COMMAND_BASE + DRM_RADEON_SURF_FREE, drm_radeon_surface_free_t)
#define DRM_IOCTL_RADEON_GEM_INFO DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_INFO, struct drm_radeon_gem_info)
#define DRM_IOCTL_RADEON_GEM_CREATE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_CREATE, struct drm_radeon_gem_create)
#define DRM_IOCTL_RADEON_GEM_MMAP DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_MMAP, struct drm_radeon_gem_mmap)
#define DRM_IOCTL_RADEON_GEM_PIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PIN, struct drm_radeon_gem_pin)
#define DRM_IOCTL_RADEON_GEM_UNPIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_UNPIN, struct drm_radeon_gem_unpin)
#define DRM_IOCTL_RADEON_GEM_PREAD DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PREAD, struct drm_radeon_gem_pread)
#define DRM_IOCTL_RADEON_GEM_PWRITE DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_PWRITE, struct drm_radeon_gem_pwrite)
#define DRM_IOCTL_RADEON_GEM_SET_DOMAIN DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_GEM_SET_DOMAIN, struct drm_radeon_gem_set_domain)
#define DRM_IOCTL_RADEON_GEM_WAIT_RENDERING DRM_IOW(DRM_COMMAND_BASE + DRM_RADEON_GEM_WAIT_RENDERING, struct drm_radeon_gem_wait_rendering)
#define DRM_IOCTL_RADEON_CS DRM_IOWR(DRM_COMMAND_BASE + DRM_RADEON_CS, struct drm_radeon_cs)
typedef struct drm_radeon_init {
enum {
RADEON_INIT_CP = 0x01,
@ -677,6 +698,7 @@ typedef struct drm_radeon_indirect {
#define RADEON_PARAM_VBLANK_CRTC 13 /* VBLANK CRTC */
#define RADEON_PARAM_FB_LOCATION 14 /* FB location */
#define RADEON_PARAM_NUM_GB_PIPES 15 /* num GB pipes */
#define RADEON_PARAM_DEVICE_ID 16
typedef struct drm_radeon_getparam {
int param;
@ -728,7 +750,6 @@ typedef struct drm_radeon_setparam {
#define RADEON_SETPARAM_FB_LOCATION 1 /* determined framebuffer location */
#define RADEON_SETPARAM_SWITCH_TILING 2 /* enable/disable color tiling */
#define RADEON_SETPARAM_PCIGART_LOCATION 3 /* PCI Gart Location */
#define RADEON_SETPARAM_NEW_MEMMAP 4 /* Use new memory map */
#define RADEON_SETPARAM_PCIGART_TABLE_SIZE 5 /* PCI GART Table Size */
#define RADEON_SETPARAM_VBLANK_CRTC 6 /* VBLANK CRTC */
@ -747,4 +768,112 @@ typedef struct drm_radeon_surface_free {
#define DRM_RADEON_VBLANK_CRTC1 1
#define DRM_RADEON_VBLANK_CRTC2 2
/*
* Kernel modesetting world below.
*/
#define RADEON_GEM_DOMAIN_CPU 0x1
#define RADEON_GEM_DOMAIN_GTT 0x2
#define RADEON_GEM_DOMAIN_VRAM 0x4
struct drm_radeon_gem_info {
uint64_t gart_size;
uint64_t vram_size;
uint64_t vram_visible;
};
#define RADEON_GEM_NO_BACKING_STORE 1
struct drm_radeon_gem_create {
uint64_t size;
uint64_t alignment;
uint32_t handle;
uint32_t initial_domain;
uint32_t flags;
};
struct drm_radeon_gem_mmap {
uint32_t handle;
uint32_t pad;
uint64_t offset;
uint64_t size;
uint64_t addr_ptr;
};
struct drm_radeon_gem_set_domain {
uint32_t handle;
uint32_t read_domains;
uint32_t write_domain;
};
struct drm_radeon_gem_wait_idle {
uint32_t handle;
uint32_t pad;
};
struct drm_radeon_gem_busy {
uint32_t handle;
uint32_t busy;
};
struct drm_radeon_gem_pread {
/** Handle for the object being read. */
uint32_t handle;
uint32_t pad;
/** Offset into the object to read from */
uint64_t offset;
/** Length of data to read */
uint64_t size;
/** Pointer to write the data into. */
/* void *, but pointers are not 32/64 compatible */
uint64_t data_ptr;
};
struct drm_radeon_gem_pwrite {
/** Handle for the object being written to. */
uint32_t handle;
uint32_t pad;
/** Offset into the object to write to */
uint64_t offset;
/** Length of data to write */
uint64_t size;
/** Pointer to read the data from. */
/* void *, but pointers are not 32/64 compatible */
uint64_t data_ptr;
};
#define RADEON_CHUNK_ID_RELOCS 0x01
#define RADEON_CHUNK_ID_IB 0x02
struct drm_radeon_cs_chunk {
uint32_t chunk_id;
uint32_t length_dw;
uint64_t chunk_data;
};
struct drm_radeon_cs_reloc {
uint32_t handle;
uint32_t read_domains;
uint32_t write_domain;
uint32_t flags;
};
struct drm_radeon_cs {
uint32_t num_chunks;
uint32_t cs_id;
/* this points to uint64_t * which point to cs chunks */
uint64_t chunks;
/* updates to the limits after this CS ioctl */
uint64_t gart_limit;
uint64_t vram_limit;
};
#define RADEON_INFO_DEVICE_ID 0x00
#define RADEON_INFO_NUM_GB_PIPES 0x01
struct drm_radeon_info {
uint32_t request;
uint32_t pad;
uint64_t value;
};
#endif