summaryrefslogtreecommitdiff
path: root/libdrm
diff options
context:
space:
mode:
Diffstat (limited to 'libdrm')
-rw-r--r--libdrm/Makefile.am5
-rw-r--r--libdrm/intel/intel_bufmgr.h5
-rw-r--r--libdrm/intel/intel_bufmgr_fake.c3
-rw-r--r--libdrm/intel/intel_bufmgr_gem.c9
-rw-r--r--libdrm/radeon/Makefile.am48
-rw-r--r--libdrm/radeon/radeon_bo.h167
-rw-r--r--libdrm/radeon/radeon_bo_gem.c208
-rw-r--r--libdrm/radeon/radeon_bo_gem.h40
-rw-r--r--libdrm/radeon/radeon_cs.h168
-rw-r--r--libdrm/radeon/radeon_cs_gem.c438
-rw-r--r--libdrm/radeon/radeon_cs_gem.h41
-rw-r--r--libdrm/radeon/radeon_track.c140
-rw-r--r--libdrm/radeon/radeon_track.h64
-rw-r--r--libdrm/xf86drm.c42
-rw-r--r--libdrm/xf86drm.h5
-rw-r--r--libdrm/xf86drmMode.c684
-rw-r--r--libdrm/xf86drmMode.h256
17 files changed, 2310 insertions, 13 deletions
diff --git a/libdrm/Makefile.am b/libdrm/Makefile.am
index a5be36e0..edc302f7 100644
--- a/libdrm/Makefile.am
+++ b/libdrm/Makefile.am
@@ -18,7 +18,7 @@
# 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.
-SUBDIRS = . intel
+SUBDIRS = . intel radeon
libdrm_la_LTLIBRARIES = libdrm.la
libdrm_ladir = $(libdir)
@@ -26,9 +26,10 @@ libdrm_la_LDFLAGS = -version-number 2:4:0 -no-undefined
AM_CFLAGS = -I$(top_srcdir)/shared-core
libdrm_la_SOURCES = xf86drm.c xf86drmHash.c xf86drmRandom.c xf86drmSL.c \
+ xf86drmMode.c libdrm_lists.h
libdrm_lists.h
libdrmincludedir = ${includedir}
-libdrminclude_HEADERS = xf86drm.h
+libdrminclude_HEADERS = xf86drm.h xf86drmMode.h
EXTRA_DIST = ChangeLog TODO
diff --git a/libdrm/intel/intel_bufmgr.h b/libdrm/intel/intel_bufmgr.h
index f134f169..e8c2e063 100644
--- a/libdrm/intel/intel_bufmgr.h
+++ b/libdrm/intel/intel_bufmgr.h
@@ -66,6 +66,11 @@ struct _drm_intel_bo {
/** Buffer manager context associated with this buffer object */
drm_intel_bufmgr *bufmgr;
+
+ /**
+ * MM-specific handle for accessing object
+ */
+ int handle;
};
drm_intel_bo *drm_intel_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,
diff --git a/libdrm/intel/intel_bufmgr_fake.c b/libdrm/intel/intel_bufmgr_fake.c
index 6d8ee85a..0e465303 100644
--- a/libdrm/intel/intel_bufmgr_fake.c
+++ b/libdrm/intel/intel_bufmgr_fake.c
@@ -833,7 +833,7 @@ drm_intel_bo_fake_alloc_static(drm_intel_bufmgr *bufmgr, const char *name,
bo_fake->refcount = 1;
bo_fake->id = ++bufmgr_fake->buf_nr;
bo_fake->name = name;
- bo_fake->flags = BM_PINNED | DRM_BO_FLAG_NO_MOVE;
+ bo_fake->flags = BM_PINNED;
bo_fake->is_static = 1;
DBG("drm_bo_alloc_static: (buf %d: %s, %d kb)\n", bo_fake->id, bo_fake->name,
@@ -1070,7 +1070,6 @@ drm_intel_fake_kick_all_locked(drm_intel_bufmgr_fake *bufmgr_fake)
if (!(bo_fake->flags & BM_NO_BACKING_STORE))
bo_fake->dirty = 1;
}
-
}
static int
diff --git a/libdrm/intel/intel_bufmgr_gem.c b/libdrm/intel/intel_bufmgr_gem.c
index e681eee7..f7ad7571 100644
--- a/libdrm/intel/intel_bufmgr_gem.c
+++ b/libdrm/intel/intel_bufmgr_gem.c
@@ -352,6 +352,7 @@ drm_intel_gem_bo_alloc(drm_intel_bufmgr *bufmgr, const char *name,
ret = ioctl(bufmgr_gem->fd, DRM_IOCTL_I915_GEM_CREATE, &create);
bo_gem->gem_handle = create.handle;
+ bo_gem->bo.handle = bo_gem->gem_handle;
if (ret != 0) {
free(bo_gem);
return NULL;
@@ -426,6 +427,14 @@ drm_intel_gem_bo_reference(drm_intel_bo *bo)
}
static void
+dri_gem_bo_reference_locked(dri_bo *bo)
+{
+ drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
+
+ bo_gem->refcount++;
+}
+
+static void
drm_intel_gem_bo_reference_locked(drm_intel_bo *bo)
{
drm_intel_bo_gem *bo_gem = (drm_intel_bo_gem *)bo;
diff --git a/libdrm/radeon/Makefile.am b/libdrm/radeon/Makefile.am
new file mode 100644
index 00000000..39ee021f
--- /dev/null
+++ b/libdrm/radeon/Makefile.am
@@ -0,0 +1,48 @@
+# 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
diff --git a/libdrm/radeon/radeon_bo.h b/libdrm/radeon/radeon_bo.h
new file mode 100644
index 00000000..44dc0901
--- /dev/null
+++ b/libdrm/radeon/radeon_bo.h
@@ -0,0 +1,167 @@
+/*
+ * 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;
+};
+
+/* 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);
+};
+
+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);
+}
+
+#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__)
+
+#endif
diff --git a/libdrm/radeon/radeon_bo_gem.c b/libdrm/radeon/radeon_bo_gem.c
new file mode 100644
index 00000000..fdf852a2
--- /dev/null
+++ b/libdrm/radeon/radeon_bo_gem.c
@@ -0,0 +1,208 @@
+/*
+ * 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>
+ */
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ioctl.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.no_backing_store = 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;
+
+ 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) {
+ bo->ptr = (void *)(unsigned long)args.addr_ptr;
+ } else {
+ fprintf(stderr, "error mapping %p 0x%08X (error = %d)\n",
+ bo, bo->handle, r);
+ }
+ 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 struct radeon_bo_funcs bo_gem_funcs = {
+ bo_open,
+ bo_ref,
+ bo_unref,
+ bo_map,
+ bo_unmap
+};
+
+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);
+}
diff --git a/libdrm/radeon/radeon_bo_gem.h b/libdrm/radeon/radeon_bo_gem.h
new file mode 100644
index 00000000..c0f68e6d
--- /dev/null
+++ b/libdrm/radeon/radeon_bo_gem.h
@@ -0,0 +1,40 @@
+/*
+ * 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);
+
+#endif
diff --git a/libdrm/radeon/radeon_cs.h b/libdrm/radeon/radeon_cs.h
new file mode 100644
index 00000000..e76121ea
--- /dev/null
+++ b/libdrm/radeon/radeon_cs.h
@@ -0,0 +1,168 @@
+/*
+ * 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 "radeon_bo.h"
+
+struct radeon_cs_reloc {
+ struct radeon_bo *bo;
+ uint32_t start_offset;
+ uint32_t end_offset;
+ uint32_t read_domain;
+ uint32_t write_domain;
+ uint32_t flags;
+};
+
+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_dword)(struct radeon_cs *cs, uint32_t dword);
+ int (*cs_write_reloc)(struct radeon_cs *cs,
+ struct radeon_bo *bo,
+ uint32_t start_offset,
+ uint32_t end_offset,
+ 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);
+};
+
+struct radeon_cs_manager {
+ struct radeon_cs_funcs *funcs;
+ int fd;
+};
+
+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_dword(struct radeon_cs *cs, uint32_t dword)
+{
+ return cs->csm->funcs->cs_write_dword(cs, dword);
+}
+
+static inline int radeon_cs_write_reloc(struct radeon_cs *cs,
+ struct radeon_bo *bo,
+ uint32_t start_offset,
+ uint32_t end_offset,
+ uint32_t read_domain,
+ uint32_t write_domain,
+ uint32_t flags)
+{
+ return cs->csm->funcs->cs_write_reloc(cs,
+ bo,
+ start_offset,
+ end_offset,
+ 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);
+}
+
+#endif
diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c
new file mode 100644
index 00000000..319d1b9e
--- /dev/null
+++ b/libdrm/radeon/radeon_cs_gem.c
@@ -0,0 +1,438 @@
+/*
+ * 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 <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 start_offset;
+ uint32_t end_offset;
+ uint32_t read_domain;
+ uint32_t write_domain;
+ uint32_t flags;
+};
+#pragma pack()
+
+struct cs_gem {
+ struct radeon_cs base;
+ struct drm_radeon_cs2 cs;
+ struct drm_radeon_cs_chunk chunks[2];
+ unsigned nrelocs;
+ uint32_t *relocs;
+ 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_dword(struct radeon_cs *cs, uint32_t dword)
+{
+ struct cs_gem *csg = (struct cs_gem*)cs;
+ if (cs->cdw >= cs->ndw) {
+ uint32_t tmp, *ptr;
+ tmp = (cs->cdw + 1 + 0x3FF) & (~0x3FF);
+ ptr = (uint32_t*)realloc(cs->packets, 4 * tmp);
+ if (ptr == NULL) {
+ return -ENOMEM;
+ }
+ cs->packets = ptr;
+ cs->ndw = tmp;
+ csg->chunks[0].chunk_data = (uint64_t)(intptr_t)csg->base.packets;
+ }
+ cs->packets[cs->cdw++] = dword;
+ csg->chunks[0].length_dw += 1;
+ return 0;
+}
+
+static int cs_gem_write_reloc(struct radeon_cs *cs,
+ struct radeon_bo *bo,
+ uint32_t start_offset,
+ uint32_t end_offset,
+ 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;
+
+ /* 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 reloc window */
+ if (end_offset > bo->size) {
+ return -EINVAL;
+ }
+ if (start_offset > end_offset) {
+ return -EINVAL;
+ }
+ /* check if bo is already referenced */
+ for(i = 0; i < cs->crelocs; i++) {
+ idx = i * 6;
+ 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 start and end offset */
+ if (start_offset < reloc->start_offset) {
+ reloc->start_offset = start_offset;
+ }
+ if (end_offset > reloc->end_offset) {
+ reloc->end_offset = end_offset;
+ }
+ /* update flags */
+ reloc->flags |= (flags & reloc->flags);
+ /* write relocation packet */
+ cs_gem_write_dword(cs, 0xc0001000);
+ cs_gem_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) * 6 * 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++) * 6;
+ reloc = (struct cs_reloc_gem*)&csg->relocs[idx];
+ reloc->handle = bo->handle;
+ reloc->start_offset = start_offset;
+ reloc->end_offset = end_offset;
+ reloc->read_domain = read_domain;
+ reloc->write_domain = write_domain;
+ reloc->flags = flags;
+ csg->chunks[1].length_dw += 6;
+ radeon_bo_ref(bo);
+ cs->relocs_total_size += bo->size;
+ cs_gem_write_dword(cs, 0xc0001000);
+ cs_gem_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)
+{
+ return 0;
+}
+
+static int cs_gem_end(struct radeon_cs *cs,
+ const char *file,
+ const char *func,
+ int line)
+
+{
+ cs->section = 0;
+ 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_CS2,
+ &csg->cs, sizeof(struct drm_radeon_cs2));
+ for (i = 0; i < csg->base.crelocs; i++) {
+ radeon_bo_unref(csg->relocs_bo[i]);
+ csg->relocs_bo[i] = NULL;
+ }
+ 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 (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 struct radeon_cs_funcs radeon_cs_gem_funcs = {
+ cs_gem_create,
+ cs_gem_write_dword,
+ 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
+};
+
+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
diff --git a/libdrm/xf86drm.c b/libdrm/xf86drm.c
index c36f1964..94f5dfad 100644
--- a/libdrm/xf86drm.c
+++ b/libdrm/xf86drm.c
@@ -87,6 +87,9 @@
#define DRM_MSG_VERBOSITY 3
+#define DRM_NODE_CONTROL 0
+#define DRM_NODE_RENDER 1
+
static drmServerInfoPtr drm_server_info;
void drmSetServerInfo(drmServerInfoPtr info)
@@ -277,7 +280,7 @@ static int drmMatchBusID(const char *id1, const char *id2)
* special file node with the major and minor numbers specified by \p dev and
* parent directory if necessary and was called by root.
*/
-static int drmOpenDevice(long dev, int minor)
+static int drmOpenDevice(long dev, int minor, int type)
{
stat_t st;
char buf[64];
@@ -287,7 +290,7 @@ static int drmOpenDevice(long dev, int minor)
uid_t user = DRM_DEV_UID;
gid_t group = DRM_DEV_GID, serv_group;
- sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+ sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
drmMsg("drmOpenDevice: node name is %s\n", buf);
if (drm_server_info) {
@@ -386,15 +389,15 @@ wait_for_udev:
* Calls drmOpenDevice() if \p create is set, otherwise assembles the device
* name from \p minor and opens it.
*/
-static int drmOpenMinor(int minor, int create)
+static int drmOpenMinor(int minor, int create, int type)
{
int fd;
char buf[64];
if (create)
- return drmOpenDevice(makedev(DRM_MAJOR, minor), minor);
+ return drmOpenDevice(makedev(DRM_MAJOR, minor), minor, type);
- sprintf(buf, DRM_DEV_NAME, DRM_DIR_NAME, minor);
+ sprintf(buf, type ? DRM_DEV_NAME : DRM_CONTROL_DEV_NAME, DRM_DIR_NAME, minor);
if ((fd = open(buf, O_RDWR, 0)) >= 0)
return fd;
return -errno;
@@ -417,7 +420,7 @@ int drmAvailable(void)
int retval = 0;
int fd;
- if ((fd = drmOpenMinor(0, 1)) < 0) {
+ if ((fd = drmOpenMinor(0, 1, DRM_NODE_RENDER)) < 0) {
#ifdef __linux__
/* Try proc for backward Linux compatibility */
if (!access("/proc/dri/0", R_OK))
@@ -458,7 +461,7 @@ static int drmOpenByBusid(const char *busid)
drmMsg("drmOpenByBusid: Searching for BusID %s\n", busid);
for (i = 0; i < DRM_MAX_MINOR; i++) {
- fd = drmOpenMinor(i, 1);
+ fd = drmOpenMinor(i, 1, DRM_NODE_RENDER);
drmMsg("drmOpenByBusid: drmOpenMinor returns %d\n", fd);
if (fd >= 0) {
sv.drm_di_major = 1;
@@ -520,7 +523,7 @@ static int drmOpenByName(const char *name)
* already in use. If it's in use it will have a busid assigned already.
*/
for (i = 0; i < DRM_MAX_MINOR; i++) {
- if ((fd = drmOpenMinor(i, 1)) >= 0) {
+ if ((fd = drmOpenMinor(i, 1, DRM_NODE_RENDER)) >= 0) {
if ((version = drmGetVersion(fd))) {
if (!strcmp(version->name, name)) {
drmFreeVersion(version);
@@ -564,7 +567,7 @@ static int drmOpenByName(const char *name)
if (*pt) { /* Found busid */
return drmOpenByBusid(++pt);
} else { /* No busid */
- return drmOpenDevice(strtol(devstring, NULL, 0),i);
+ return drmOpenDevice(strtol(devstring, NULL, 0),i, DRM_NODE_RENDER);
}
}
}
@@ -614,6 +617,10 @@ int drmOpen(const char *name, const char *busid)
return -1;
}
+int drmOpenControl(int minor)
+{
+ return drmOpenMinor(minor, 0, DRM_NODE_CONTROL);
+}
/**
* Free the version information returned by drmGetVersion().
@@ -2434,3 +2441,20 @@ void drmCloseOnce(int fd)
}
}
}
+
+int drmSetMaster(int fd)
+{
+ int ret;
+
+ fprintf(stderr,"Setting master \n");
+ ret = ioctl(fd, DRM_IOCTL_SET_MASTER, 0);
+ return ret;
+}
+
+int drmDropMaster(int fd)
+{
+ int ret;
+ fprintf(stderr,"Dropping master \n");
+ ret = ioctl(fd, DRM_IOCTL_DROP_MASTER, 0);
+ return ret;
+}
diff --git a/libdrm/xf86drm.h b/libdrm/xf86drm.h
index f4fa71b0..584d2a41 100644
--- a/libdrm/xf86drm.h
+++ b/libdrm/xf86drm.h
@@ -49,6 +49,7 @@
#define DRM_DIR_NAME "/dev/dri"
#define DRM_DEV_NAME "%s/card%d"
+#define DRM_CONTROL_DEV_NAME "%s/controlD%d"
#define DRM_PROC_NAME "/proc/dri/" /* For backward Linux compatibility */
#define DRM_ERR_NO_DEVICE (-1001)
@@ -508,6 +509,7 @@ do { register unsigned int __old __asm("o0"); \
/* General user-level programmer's API: unprivileged */
extern int drmAvailable(void);
extern int drmOpen(const char *name, const char *busid);
+extern int drmOpenControl(int minor);
extern int drmClose(int fd);
extern drmVersionPtr drmGetVersion(int fd);
extern drmVersionPtr drmGetLibVersion(int fd);
@@ -659,4 +661,7 @@ extern int drmOpenOnce(void *unused, const char *BusID, int *newlyopened);
extern void drmCloseOnce(int fd);
extern void drmMsg(const char *format, ...);
+extern int drmSetMaster(int fd);
+extern int drmDropMaster(int fd);
+
#endif
diff --git a/libdrm/xf86drmMode.c b/libdrm/xf86drmMode.c
new file mode 100644
index 00000000..a0a164de
--- /dev/null
+++ b/libdrm/xf86drmMode.c
@@ -0,0 +1,684 @@
+/*
+ * \file xf86drmMode.c
+ * Header for DRM modesetting interface.
+ *
+ * \author Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ * \par Acknowledgements:
+ * Feb 2007, Dave Airlie <airlied@linux.ie>
+ */
+
+/*
+ * Copyright (c) <year> <copyright holders>
+ *
+ * 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 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.
+ *
+ */
+
+/*
+ * TODO the types we are after are defined in diffrent headers on diffrent
+ * platforms find which headers to include to get uint32_t
+ */
+#include <stdint.h>
+#include <sys/ioctl.h>
+#include <stdio.h>
+
+#include "xf86drmMode.h"
+#include "xf86drm.h"
+#include <drm.h>
+#include <string.h>
+#include <dirent.h>
+#include <errno.h>
+
+#define U642VOID(x) ((void *)(unsigned long)(x))
+#define VOID2U64(x) ((uint64_t)(unsigned long)(x))
+
+/*
+ * Util functions
+ */
+
+void* drmAllocCpy(void *array, int count, int entry_size)
+{
+ char *r;
+ int i;
+
+ if (!count || !array || !entry_size)
+ return 0;
+
+ if (!(r = drmMalloc(count*entry_size)))
+ return 0;
+
+ for (i = 0; i < count; i++)
+ memcpy(r+(entry_size*i), array+(entry_size*i), entry_size);
+
+ return r;
+}
+
+/*
+ * A couple of free functions.
+ */
+
+void drmModeFreeModeInfo(struct drm_mode_modeinfo *ptr)
+{
+ if (!ptr)
+ return;
+
+ drmFree(ptr);
+}
+
+void drmModeFreeResources(drmModeResPtr ptr)
+{
+ if (!ptr)
+ return;
+
+ drmFree(ptr);
+
+}
+
+void drmModeFreeFB(drmModeFBPtr ptr)
+{
+ if (!ptr)
+ return;
+
+ /* we might add more frees later. */
+ drmFree(ptr);
+}
+
+void drmModeFreeCrtc(drmModeCrtcPtr ptr)
+{
+ if (!ptr)
+ return;
+
+ drmFree(ptr);
+
+}
+
+void drmModeFreeConnector(drmModeConnectorPtr ptr)
+{
+ if (!ptr)
+ return;
+
+ drmFree(ptr->modes);
+ drmFree(ptr);
+
+}
+
+void drmModeFreeEncoder(drmModeEncoderPtr ptr)
+{
+ drmFree(ptr);
+}
+
+/*
+ * ModeSetting functions.
+ */
+
+drmModeResPtr drmModeGetResources(int fd)
+{
+ struct drm_mode_card_res res;
+ drmModeResPtr r = 0;
+
+ memset(&res, 0, sizeof(struct drm_mode_card_res));
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res))
+ return 0;
+
+ if (res.count_fbs)
+ res.fb_id_ptr = VOID2U64(drmMalloc(res.count_fbs*sizeof(uint32_t)));
+ if (res.count_crtcs)
+ res.crtc_id_ptr = VOID2U64(drmMalloc(res.count_crtcs*sizeof(uint32_t)));
+ if (res.count_connectors)
+ res.connector_id_ptr = VOID2U64(drmMalloc(res.count_connectors*sizeof(uint32_t)));
+ if (res.count_encoders)
+ res.encoder_id_ptr = VOID2U64(drmMalloc(res.count_encoders*sizeof(uint32_t)));
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETRESOURCES, &res)) {
+ r = NULL;
+ goto err_allocs;
+ }
+
+ /*
+ * return
+ */
+
+
+ if (!(r = drmMalloc(sizeof(*r))))
+ return 0;
+
+ r->min_width = res.min_width;
+ r->max_width = res.max_width;
+ r->min_height = res.min_height;
+ r->max_height = res.max_height;
+ r->count_fbs = res.count_fbs;
+ r->count_crtcs = res.count_crtcs;
+ r->count_connectors = res.count_connectors;
+ r->count_encoders = res.count_encoders;
+ /* TODO we realy should test if these allocs fails. */
+ r->fbs = drmAllocCpy(U642VOID(res.fb_id_ptr), res.count_fbs, sizeof(uint32_t));
+ r->crtcs = drmAllocCpy(U642VOID(res.crtc_id_ptr), res.count_crtcs, sizeof(uint32_t));
+ r->connectors = drmAllocCpy(U642VOID(res.connector_id_ptr), res.count_connectors, sizeof(uint32_t));
+ r->encoders = drmAllocCpy(U642VOID(res.encoder_id_ptr), res.count_encoders, sizeof(uint32_t));
+
+err_allocs:
+ drmFree(U642VOID(res.fb_id_ptr));
+ drmFree(U642VOID(res.crtc_id_ptr));
+ drmFree(U642VOID(res.connector_id_ptr));
+ drmFree(U642VOID(res.encoder_id_ptr));
+
+ return r;
+}
+
+int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
+ uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
+ uint32_t *buf_id)
+{
+ struct drm_mode_fb_cmd f;
+ int ret;
+
+ f.width = width;
+ f.height = height;
+ f.pitch = pitch;
+ f.bpp = bpp;
+ f.depth = depth;
+ f.handle = bo_handle;
+
+ if ((ret = ioctl(fd, DRM_IOCTL_MODE_ADDFB, &f)))
+ return ret;
+
+ *buf_id = f.fb_id;
+ return 0;
+}
+
+int drmModeRmFB(int fd, uint32_t bufferId)
+{
+ return ioctl(fd, DRM_IOCTL_MODE_RMFB, &bufferId);
+
+
+}
+
+drmModeFBPtr drmModeGetFB(int fd, uint32_t buf)
+{
+ struct drm_mode_fb_cmd info;
+ drmModeFBPtr r;
+
+ info.fb_id = buf;
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETFB, &info))
+ return NULL;
+
+ if (!(r = drmMalloc(sizeof(*r))))
+ return NULL;
+
+ r->fb_id = info.fb_id;
+ r->width = info.width;
+ r->height = info.height;
+ r->pitch = info.pitch;
+ r->bpp = info.bpp;
+ r->handle = info.handle;
+ r->depth = info.depth;
+
+ return r;
+}
+
+
+/*
+ * Crtc functions
+ */
+
+drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId)
+{
+ struct drm_mode_crtc crtc;
+ drmModeCrtcPtr r;
+
+ crtc.crtc_id = crtcId;
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETCRTC, &crtc))
+ return 0;
+
+ /*
+ * return
+ */
+
+ if (!(r = drmMalloc(sizeof(*r))))
+ return 0;
+
+ r->crtc_id = crtc.crtc_id;
+ r->x = crtc.x;
+ r->y = crtc.y;
+ r->mode_valid = crtc.mode_valid;
+ if (r->mode_valid)
+ memcpy(&r->mode, &crtc.mode, sizeof(struct drm_mode_modeinfo));
+ r->buffer_id = crtc.fb_id;
+ r->gamma_size = crtc.gamma_size;
+ return r;
+}
+
+
+int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
+ uint32_t x, uint32_t y, uint32_t *connectors, int count,
+ struct drm_mode_modeinfo *mode)
+{
+ struct drm_mode_crtc crtc;
+
+ crtc.x = x;
+ crtc.y = y;
+ crtc.crtc_id = crtcId;
+ crtc.fb_id = bufferId;
+ crtc.set_connectors_ptr = VOID2U64(connectors);
+ crtc.count_connectors = count;
+ if (mode) {
+ memcpy(&crtc.mode, mode, sizeof(struct drm_mode_modeinfo));
+ crtc.mode_valid = 1;
+ } else
+ crtc.mode_valid = 0;
+
+ return ioctl(fd, DRM_IOCTL_MODE_SETCRTC, &crtc);
+}
+
+/*
+ * Cursor manipulation
+ */
+
+int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height)
+{
+ struct drm_mode_cursor arg;
+
+ arg.flags = DRM_MODE_CURSOR_BO;
+ arg.crtc_id = crtcId;
+ arg.width = width;
+ arg.height = height;
+ arg.handle = bo_handle;
+
+ return ioctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
+}
+
+int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y)
+{
+ struct drm_mode_cursor arg;
+
+ arg.flags = DRM_MODE_CURSOR_MOVE;
+ arg.crtc_id = crtcId;
+ arg.x = x;
+ arg.y = y;
+
+ return ioctl(fd, DRM_IOCTL_MODE_CURSOR, &arg);
+}
+
+/*
+ * Encoder get
+ */
+drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id)
+{
+ struct drm_mode_get_encoder enc;
+ drmModeEncoderPtr r = NULL;
+
+ enc.encoder_id = encoder_id;
+ enc.encoder_type = 0;
+ enc.possible_crtcs = 0;
+ enc.possible_clones = 0;
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETENCODER, &enc))
+ return 0;
+
+ if (!(r = drmMalloc(sizeof(*r))))
+ return 0;
+
+ r->encoder_id = enc.encoder_id;
+ r->crtc_id = enc.crtc_id;
+ r->encoder_type = enc.encoder_type;
+ r->possible_crtcs = enc.possible_crtcs;
+ r->possible_clones = enc.possible_clones;
+
+ return r;
+}
+
+/*
+ * Connector manipulation
+ */
+
+drmModeConnectorPtr drmModeGetConnector(int fd, uint32_t connector_id)
+{
+ struct drm_mode_get_connector conn;
+ drmModeConnectorPtr r = NULL;
+
+ conn.connector_id = connector_id;
+ conn.connector_type_id = 0;
+ conn.connector_type = 0;
+ conn.count_modes = 0;
+ conn.modes_ptr = 0;
+ conn.count_props = 0;
+ conn.props_ptr = 0;
+ conn.prop_values_ptr = 0;
+ conn.count_encoders = 0;
+ conn.encoders_ptr = 0;
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
+ return 0;
+
+ if (conn.count_props) {
+ conn.props_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint32_t)));
+ conn.prop_values_ptr = VOID2U64(drmMalloc(conn.count_props*sizeof(uint64_t)));
+ }
+
+ if (conn.count_modes)
+ conn.modes_ptr = VOID2U64(drmMalloc(conn.count_modes*sizeof(struct drm_mode_modeinfo)));
+
+ if (conn.count_encoders)
+ conn.encoders_ptr = VOID2U64(drmMalloc(conn.count_encoders*sizeof(uint32_t)));
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETCONNECTOR, &conn))
+ goto err_allocs;
+
+ if(!(r = drmMalloc(sizeof(*r)))) {
+ goto err_allocs;
+ }
+
+ r->connector_id = conn.connector_id;
+ r->encoder_id = conn.encoder_id;
+ r->connection = conn.connection;
+ r->mmWidth = conn.mm_width;
+ r->mmHeight = conn.mm_height;
+ r->subpixel = conn.subpixel;
+ r->count_modes = conn.count_modes;
+ /* TODO we should test if these alloc & cpy fails. */
+ r->count_props = conn.count_props;
+ r->props = drmAllocCpy(U642VOID(conn.props_ptr), conn.count_props, sizeof(uint32_t));
+ r->prop_values = drmAllocCpy(U642VOID(conn.prop_values_ptr), conn.count_props, sizeof(uint64_t));
+ r->modes = drmAllocCpy(U642VOID(conn.modes_ptr), conn.count_modes, sizeof(struct drm_mode_modeinfo));
+ r->count_encoders = conn.count_encoders;
+ r->encoders = drmAllocCpy(U642VOID(conn.encoders_ptr), conn.count_encoders, sizeof(uint32_t));
+ r->connector_type = conn.connector_type;
+ r->connector_type_id = conn.connector_type_id;
+
+ if (!r->props || !r->prop_values || !r->modes || !r->encoders)
+ goto err_allocs;
+
+err_allocs:
+ drmFree(U642VOID(conn.prop_values_ptr));
+ drmFree(U642VOID(conn.props_ptr));
+ drmFree(U642VOID(conn.modes_ptr));
+ drmFree(U642VOID(conn.encoders_ptr));
+
+ return r;
+}
+
+int drmModeAttachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info)
+{
+ struct drm_mode_mode_cmd res;
+
+ memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
+ res.connector_id = connector_id;
+
+ return ioctl(fd, DRM_IOCTL_MODE_ATTACHMODE, &res);
+}
+
+int drmModeDetachMode(int fd, uint32_t connector_id, struct drm_mode_modeinfo *mode_info)
+{
+ struct drm_mode_mode_cmd res;
+
+ memcpy(&res.mode, mode_info, sizeof(struct drm_mode_modeinfo));
+ res.connector_id = connector_id;
+
+ return ioctl(fd, DRM_IOCTL_MODE_DETACHMODE, &res);
+}
+
+
+drmModePropertyPtr drmModeGetProperty(int fd, uint32_t property_id)
+{
+ struct drm_mode_get_property prop;
+ drmModePropertyPtr r;
+
+ prop.prop_id = property_id;
+ prop.count_enum_blobs = 0;
+ prop.count_values = 0;
+ prop.flags = 0;
+ prop.enum_blob_ptr = 0;
+ prop.values_ptr = 0;
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop))
+ return 0;
+
+ if (prop.count_values)
+ prop.values_ptr = VOID2U64(drmMalloc(prop.count_values * sizeof(uint64_t)));
+
+ if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_ENUM))
+ prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(struct drm_mode_property_enum)));
+
+ if (prop.count_enum_blobs && (prop.flags & DRM_MODE_PROP_BLOB)) {
+ prop.values_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
+ prop.enum_blob_ptr = VOID2U64(drmMalloc(prop.count_enum_blobs * sizeof(uint32_t)));
+ }
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETPROPERTY, &prop)) {
+ r = NULL;
+ goto err_allocs;
+ }
+
+ if (!(r = drmMalloc(sizeof(*r))))
+ return NULL;
+
+ r->prop_id = prop.prop_id;
+ r->count_values = prop.count_values;
+
+ r->flags = prop.flags;
+ if (prop.count_values)
+ r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_values, sizeof(uint64_t));
+ if (prop.flags & DRM_MODE_PROP_ENUM) {
+ r->count_enums = prop.count_enum_blobs;
+ r->enums = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(struct drm_mode_property_enum));
+ } else if (prop.flags & DRM_MODE_PROP_BLOB) {
+ r->values = drmAllocCpy(U642VOID(prop.values_ptr), prop.count_enum_blobs, sizeof(uint32_t));
+ r->blob_ids = drmAllocCpy(U642VOID(prop.enum_blob_ptr), prop.count_enum_blobs, sizeof(uint32_t));
+ r->count_blobs = prop.count_enum_blobs;
+ }
+ strncpy(r->name, prop.name, DRM_PROP_NAME_LEN);
+ r->name[DRM_PROP_NAME_LEN-1] = 0;
+
+err_allocs:
+ drmFree(U642VOID(prop.values_ptr));
+ drmFree(U642VOID(prop.enum_blob_ptr));
+
+ return r;
+}
+
+void drmModeFreeProperty(drmModePropertyPtr ptr)
+{
+ if (!ptr)
+ return;
+
+ drmFree(ptr->values);
+ drmFree(ptr->enums);
+ drmFree(ptr);
+}
+
+drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id)
+{
+ struct drm_mode_get_blob blob;
+ drmModePropertyBlobPtr r;
+
+ blob.length = 0;
+ blob.data = 0;
+ blob.blob_id = blob_id;
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob))
+ return NULL;
+
+ if (blob.length)
+ blob.data = VOID2U64(drmMalloc(blob.length));
+
+ if (ioctl(fd, DRM_IOCTL_MODE_GETPROPBLOB, &blob)) {
+ r = NULL;
+ goto err_allocs;
+ }
+
+ if (!(r = drmMalloc(sizeof(*r))))
+ return NULL;
+
+ r->id = blob.blob_id;
+ r->length = blob.length;
+ r->data = drmAllocCpy(U642VOID(blob.data), 1, blob.length);
+
+err_allocs:
+ drmFree(U642VOID(blob.data));
+ return r;
+}
+
+void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr)
+{
+ if (!ptr)
+ return;
+
+ drmFree(ptr->data);
+ drmFree(ptr);
+}
+
+int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
+ uint64_t value)
+{
+ struct drm_mode_connector_set_property osp;
+ int ret;
+
+ osp.connector_id = connector_id;
+ osp.prop_id = property_id;
+ osp.value = value;
+
+ if ((ret = ioctl(fd, DRM_IOCTL_MODE_SETPROPERTY, &osp)))
+ return ret;
+
+ return 0;
+}
+
+/*
+ * checks if a modesetting capable driver has attached to the pci id
+ * returns 0 if modesetting supported.
+ * -EINVAL or invalid bus id
+ * -ENOSYS if no modesetting support
+*/
+int drmCheckModesettingSupported(const char *busid)
+{
+#ifdef __linux__
+ char pci_dev_dir[1024];
+ int domain, bus, dev, func;
+ DIR *sysdir;
+ struct dirent *dent;
+ int found = 0, ret;
+
+ ret = sscanf(busid, "pci:%04x:%02x:%02x.%d", &domain, &bus, &dev, &func);
+ if (ret != 4)
+ return -EINVAL;
+
+ sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/drm",
+ domain, bus, dev, func);
+
+ sysdir = opendir(pci_dev_dir);
+ if (sysdir) {
+ dent = readdir(sysdir);
+ while (dent) {
+ if (!strncmp(dent->d_name, "controlD", 8)) {
+ found = 1;
+ break;
+ }
+
+ dent = readdir(sysdir);
+ }
+ closedir(sysdir);
+ if (found)
+ return 0;
+ }
+
+ sprintf(pci_dev_dir, "/sys/bus/pci/devices/%04x:%02x:%02x.%d/",
+ domain, bus, dev, func);
+
+ sysdir = opendir(pci_dev_dir);
+ if (!sysdir)
+ return -EINVAL;
+
+ dent = readdir(sysdir);
+ while (dent) {
+ if (!strncmp(dent->d_name, "drm:controlD", 12)) {
+ found = 1;
+ break;
+ }
+
+ dent = readdir(sysdir);
+ }
+
+ closedir(sysdir);
+ if (found)
+ return 0;
+#endif
+ return -ENOSYS;
+
+}
+
+int drmModeReplaceFB(int fd, uint32_t buffer_id,
+ uint32_t width, uint32_t height, uint8_t depth,
+ uint8_t bpp, uint32_t pitch, uint32_t bo_handle)
+{
+ struct drm_mode_fb_cmd f;
+ int ret;
+
+ f.width = width;
+ f.height = height;
+ f.pitch = pitch;
+ f.bpp = bpp;
+ f.depth = depth;
+ f.handle = bo_handle;
+ f.fb_id = buffer_id;
+
+ if ((ret = ioctl(fd, DRM_IOCTL_MODE_REPLACEFB, &f)))
+ return ret;
+
+ return 0;
+}
+
+int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
+ uint16_t *red, uint16_t *green, uint16_t *blue)
+{
+ int ret;
+ struct drm_mode_crtc_lut l;
+
+ l.crtc_id = crtc_id;
+ l.gamma_size = size;
+ l.red = VOID2U64(red);
+ l.green = VOID2U64(green);
+ l.blue = VOID2U64(blue);
+
+ if ((ret = ioctl(fd, DRM_IOCTL_MODE_GETGAMMA, &l)))
+ return ret;
+
+ return 0;
+}
+
+int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
+ uint16_t *red, uint16_t *green, uint16_t *blue)
+{
+ int ret;
+ struct drm_mode_crtc_lut l;
+
+ l.crtc_id = crtc_id;
+ l.gamma_size = size;
+ l.red = VOID2U64(red);
+ l.green = VOID2U64(green);
+ l.blue = VOID2U64(blue);
+
+ if ((ret = ioctl(fd, DRM_IOCTL_MODE_SETGAMMA, &l)))
+ return ret;
+
+ return 0;
+}
diff --git a/libdrm/xf86drmMode.h b/libdrm/xf86drmMode.h
new file mode 100644
index 00000000..b68d1469
--- /dev/null
+++ b/libdrm/xf86drmMode.h
@@ -0,0 +1,256 @@
+/*
+ * \file xf86drmMode.h
+ * Header for DRM modesetting interface.
+ *
+ * \author Jakob Bornecrantz <wallbraker@gmail.com>
+ *
+ * \par Acknowledgements:
+ * Feb 2007, Dave Airlie <airlied@linux.ie>
+ */
+
+/*
+ * Copyright (c) <year> <copyright holders>
+ *
+ * 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 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.
+ *
+ */
+
+#include <drm.h>
+
+/*
+ * This is the interface for modesetting for drm.
+ *
+ * In order to use this interface you must include either <stdint.h> or another
+ * header defining uint32_t, int32_t and uint16_t.
+ *
+ * It aims to provide a randr1.2 compatible interface for modesettings in the
+ * kernel, the interface is also ment to be used by libraries like EGL.
+ *
+ * More information can be found in randrproto.txt which can be found here:
+ * http://gitweb.freedesktop.org/?p=xorg/proto/randrproto.git
+ *
+ * There are some major diffrences to be noted. Unlike the randr1.2 proto you
+ * need to create the memory object of the framebuffer yourself with the ttm
+ * buffer object interface. This object needs to be pinned.
+ */
+
+typedef struct _drmModeRes {
+
+ int count_fbs;
+ uint32_t *fbs;
+
+ int count_crtcs;
+ uint32_t *crtcs;
+
+ int count_connectors;
+ uint32_t *connectors;
+
+ int count_encoders;
+ uint32_t *encoders;
+
+ uint32_t min_width, max_width;
+ uint32_t min_height, max_height;
+} drmModeRes, *drmModeResPtr;
+
+typedef struct drm_mode_fb_cmd drmModeFB, *drmModeFBPtr;
+
+typedef struct _drmModePropertyBlob {
+ uint32_t id;
+ uint32_t length;
+ void *data;
+} drmModePropertyBlobRes, *drmModePropertyBlobPtr;
+
+typedef struct _drmModeProperty {
+ uint32_t prop_id;
+ uint32_t flags;
+ char name[DRM_PROP_NAME_LEN];
+ int count_values;
+ uint64_t *values; // store the blob lengths
+ int count_enums;
+ struct drm_mode_property_enum *enums;
+ int count_blobs;
+ uint32_t *blob_ids; // store the blob IDs
+} drmModePropertyRes, *drmModePropertyPtr;
+
+typedef struct _drmModeCrtc {
+ uint32_t crtc_id;
+ uint32_t buffer_id; /**< FB id to connect to 0 = disconnect */
+
+ uint32_t x, y; /**< Position on the framebuffer */
+ uint32_t width, height;
+ int mode_valid;
+ struct drm_mode_modeinfo mode;
+
+ int gamma_size; /**< Number of gamma stops */
+
+} drmModeCrtc, *drmModeCrtcPtr;
+
+typedef struct _drmModeEncoder {
+ uint32_t encoder_id;
+ uint32_t encoder_type;
+ uint32_t crtc_id;
+ uint32_t possible_crtcs;
+ uint32_t possible_clones;
+} drmModeEncoder, *drmModeEncoderPtr;
+
+typedef enum {
+ DRM_MODE_CONNECTED = 1,
+ DRM_MODE_DISCONNECTED = 2,
+ DRM_MODE_UNKNOWNCONNECTION = 3
+} drmModeConnection;
+
+typedef enum {
+ DRM_MODE_SUBPIXEL_UNKNOWN = 1,
+ DRM_MODE_SUBPIXEL_HORIZONTAL_RGB = 2,
+ DRM_MODE_SUBPIXEL_HORIZONTAL_BGR = 3,
+ DRM_MODE_SUBPIXEL_VERTICAL_RGB = 4,
+ DRM_MODE_SUBPIXEL_VERTICAL_BGR = 5,
+ DRM_MODE_SUBPIXEL_NONE = 6
+} drmModeSubPixel;
+
+typedef struct _drmModeConnector {
+ uint32_t connector_id;
+ uint32_t encoder_id; /**< Encoder currently connected to */
+ uint32_t connector_type;
+ uint32_t connector_type_id;
+ drmModeConnection connection;
+ uint32_t mmWidth, mmHeight; /**< HxW in millimeters */
+ drmModeSubPixel subpixel;
+
+ int count_modes;
+ struct drm_mode_modeinfo *modes;
+
+ int count_props;
+ uint32_t *props; /**< List of property ids */
+ uint64_t *prop_values; /**< List of property values */
+
+ int count_encoders;
+ uint32_t *encoders; /**< List of encoder ids */
+} drmModeConnector, *drmModeConnectorPtr;
+
+
+
+extern void drmModeFreeModeInfo( struct drm_mode_modeinfo *ptr );
+extern void drmModeFreeResources( drmModeResPtr ptr );
+extern void drmModeFreeFB( drmModeFBPtr ptr );
+extern void drmModeFreeCrtc( drmModeCrtcPtr ptr );
+extern void drmModeFreeConnector( drmModeConnectorPtr ptr );
+extern void drmModeFreeEncoder( drmModeEncoderPtr ptr );
+
+/**
+ * Retrives all of the resources associated with a card.
+ */
+extern drmModeResPtr drmModeGetResources(int fd);
+
+/*
+ * FrameBuffer manipulation.
+ */
+
+/**
+ * Retrive information about framebuffer bufferId
+ */
+extern drmModeFBPtr drmModeGetFB(int fd, uint32_t bufferId);
+
+/**
+ * Creates a new framebuffer with an buffer object as its scanout buffer.
+ */
+extern int drmModeAddFB(int fd, uint32_t width, uint32_t height, uint8_t depth,
+ uint8_t bpp, uint32_t pitch, uint32_t bo_handle,
+ uint32_t *buf_id);
+/**
+ * Destroies the given framebuffer.
+ */
+extern int drmModeRmFB(int fd, uint32_t bufferId);
+
+/**
+ * Replace a framebuffer object with a new one - for resizing the screen.
+ */
+extern int drmModeReplaceFB(int fd, uint32_t buffer_id,
+ uint32_t width, uint32_t height, uint8_t depth,
+ uint8_t bpp, uint32_t pitch, uint32_t bo_handle);
+
+/*
+ * Crtc functions
+ */
+
+/**
+ * Retrive information about the ctrt crtcId
+ */
+extern drmModeCrtcPtr drmModeGetCrtc(int fd, uint32_t crtcId);
+
+/**
+ * Set the mode on a crtc crtcId with the given mode modeId.
+ */
+int drmModeSetCrtc(int fd, uint32_t crtcId, uint32_t bufferId,
+ uint32_t x, uint32_t y, uint32_t *connectors, int count,
+ struct drm_mode_modeinfo *mode);
+
+/*
+ * Cursor functions
+ */
+
+/**
+ * Set the cursor on crtc
+ */
+int drmModeSetCursor(int fd, uint32_t crtcId, uint32_t bo_handle, uint32_t width, uint32_t height);
+
+/**
+ * Move the cursor on crtc
+ */
+int drmModeMoveCursor(int fd, uint32_t crtcId, int x, int y);
+
+/**
+ * Encoder functions
+ */
+drmModeEncoderPtr drmModeGetEncoder(int fd, uint32_t encoder_id);
+
+/*
+ * Connector manipulation
+ */
+
+/**
+ * Retrive information about the connector connectorId.
+ */
+extern drmModeConnectorPtr drmModeGetConnector(int fd,
+ uint32_t connectorId);
+
+/**
+ * Attaches the given mode to an connector.
+ */
+extern int drmModeAttachMode(int fd, uint32_t connectorId, struct drm_mode_modeinfo *mode_info);
+
+/**
+ * Detaches a mode from the connector
+ * must be unused, by the given mode.
+ */
+extern int drmModeDetachMode(int fd, uint32_t connectorId, struct drm_mode_modeinfo *mode_info);
+
+extern drmModePropertyPtr drmModeGetProperty(int fd, uint32_t propertyId);
+extern void drmModeFreeProperty(drmModePropertyPtr ptr);
+
+extern drmModePropertyBlobPtr drmModeGetPropertyBlob(int fd, uint32_t blob_id);
+extern void drmModeFreePropertyBlob(drmModePropertyBlobPtr ptr);
+extern int drmModeConnectorSetProperty(int fd, uint32_t connector_id, uint32_t property_id,
+ uint64_t value);
+extern int drmCheckModesettingSupported(const char *busid);
+
+extern int drmModeCrtcSetGamma(int fd, uint32_t crtc_id, uint32_t size,
+ uint16_t *red, uint16_t *green, uint16_t *blue);
+extern int drmModeCrtcGetGamma(int fd, uint32_t crtc_id, uint32_t size,
+ uint16_t *red, uint16_t *green, uint16_t *blue);