summaryrefslogtreecommitdiffstats
path: root/src/gallium/winsys/radeon/drm
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/winsys/radeon/drm')
-rw-r--r--src/gallium/winsys/radeon/drm/Makefile5
-rw-r--r--src/gallium/winsys/radeon/drm/SConscript10
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_bo.c599
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_bo.h (renamed from src/gallium/winsys/radeon/drm/radeon_drm_buffer.h)54
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_buffer.c532
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_common.c116
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.c293
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.h93
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_r300.c169
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_winsys.h18
10 files changed, 990 insertions, 899 deletions
diff --git a/src/gallium/winsys/radeon/drm/Makefile b/src/gallium/winsys/radeon/drm/Makefile
index 7e339a2ecfe..e63ae6f5006 100644
--- a/src/gallium/winsys/radeon/drm/Makefile
+++ b/src/gallium/winsys/radeon/drm/Makefile
@@ -5,10 +5,9 @@ include $(TOP)/configs/current
LIBNAME = radeonwinsys
C_SOURCES = \
- radeon_drm_buffer.c \
+ radeon_drm_bo.c \
radeon_drm_cs.c \
- radeon_drm_common.c \
- radeon_r300.c
+ radeon_drm_common.c
LIBRARY_INCLUDES = -I$(TOP)/src/gallium/drivers/r300 \
$(shell pkg-config libdrm --cflags-only-I)
diff --git a/src/gallium/winsys/radeon/drm/SConscript b/src/gallium/winsys/radeon/drm/SConscript
index 80816621848..b16e03556d3 100644
--- a/src/gallium/winsys/radeon/drm/SConscript
+++ b/src/gallium/winsys/radeon/drm/SConscript
@@ -3,13 +3,17 @@ Import('*')
env = env.Clone()
radeon_sources = [
- 'radeon_drm_buffer.c',
+ 'radeon_drm_bo.c',
'radeon_drm_cs.c',
'radeon_drm_common.c',
- 'radeon_r300.c',
]
-env.ParseConfig('pkg-config --cflags libdrm_radeon')
+try:
+ env.ParseConfig('pkg-config --cflags libdrm_radeon')
+except:
+ print 'warning: not building r300g'
+ Return()
+
env.Append(CPPPATH = '#/src/gallium/drivers/r300')
radeonwinsys = env.ConvenienceLibrary(
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
new file mode 100644
index 00000000000..3094337a3cd
--- /dev/null
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
@@ -0,0 +1,599 @@
+/*
+ * Copyright © 2011 Marek Olšák <[email protected]>
+ * 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.
+ */
+
+#define _FILE_OFFSET_BITS 64
+#include "radeon_drm_cs.h"
+
+#include "util/u_hash_table.h"
+#include "util/u_memory.h"
+#include "util/u_simple_list.h"
+#include "os/os_thread.h"
+
+#include "state_tracker/drm_driver.h"
+
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <xf86drm.h>
+#include <errno.h>
+
+#define RADEON_BO_FLAGS_MACRO_TILE 1
+#define RADEON_BO_FLAGS_MICRO_TILE 2
+#define RADEON_BO_FLAGS_MICRO_TILE_SQUARE 0x20
+
+extern const struct pb_vtbl radeon_bo_vtbl;
+
+
+static INLINE struct radeon_bo *radeon_bo(struct pb_buffer *bo)
+{
+ assert(bo->vtbl == &radeon_bo_vtbl);
+ return (struct radeon_bo *)bo;
+}
+
+struct radeon_bomgr {
+ /* Base class. */
+ struct pb_manager base;
+
+ /* Winsys. */
+ struct radeon_drm_winsys *rws;
+
+ /* List of buffer handles and its mutex. */
+ struct util_hash_table *bo_handles;
+ pipe_mutex bo_handles_mutex;
+};
+
+static INLINE struct radeon_bomgr *radeon_bomgr(struct pb_manager *mgr)
+{
+ return (struct radeon_bomgr *)mgr;
+}
+
+static struct radeon_bo *get_radeon_bo(struct pb_buffer *_buf)
+{
+ struct radeon_bo *bo = NULL;
+
+ if (_buf->vtbl == &radeon_bo_vtbl) {
+ bo = radeon_bo(_buf);
+ } else {
+ struct pb_buffer *base_buf;
+ pb_size offset;
+ pb_get_base_buffer(_buf, &base_buf, &offset);
+
+ if (base_buf->vtbl == &radeon_bo_vtbl)
+ bo = radeon_bo(base_buf);
+ }
+
+ return bo;
+}
+
+void radeon_bo_unref(struct radeon_bo *bo)
+{
+ struct drm_gem_close args = {};
+
+ if (!p_atomic_dec_zero(&bo->ref_count))
+ return;
+
+ if (bo->name) {
+ pipe_mutex_lock(bo->mgr->bo_handles_mutex);
+ util_hash_table_remove(bo->mgr->bo_handles,
+ (void*)(uintptr_t)bo->name);
+ pipe_mutex_unlock(bo->mgr->bo_handles_mutex);
+ }
+
+ if (bo->ptr)
+ munmap(bo->ptr, bo->size);
+
+ /* Close object. */
+ args.handle = bo->handle;
+ drmIoctl(bo->rws->fd, DRM_IOCTL_GEM_CLOSE, &args);
+ pipe_mutex_destroy(bo->map_mutex);
+ FREE(bo);
+}
+
+static void radeon_bo_wait(struct r300_winsys_bo *_buf)
+{
+ struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
+ struct drm_radeon_gem_wait_idle args = {};
+
+ while (p_atomic_read(&bo->num_active_ioctls)) {
+ sched_yield();
+ }
+
+ args.handle = bo->handle;
+ while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT_IDLE,
+ &args, sizeof(args)) == -EBUSY);
+}
+
+static boolean radeon_bo_is_busy(struct r300_winsys_bo *_buf)
+{
+ struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
+ struct drm_radeon_gem_busy args = {};
+
+ if (p_atomic_read(&bo->num_active_ioctls)) {
+ return TRUE;
+ }
+
+ args.handle = bo->handle;
+ return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY,
+ &args, sizeof(args)) != 0;
+}
+
+static void radeon_bo_destroy(struct pb_buffer *_buf)
+{
+ struct radeon_bo *bo = radeon_bo(_buf);
+
+ radeon_bo_unref(bo);
+}
+
+static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage)
+{
+ unsigned res = 0;
+
+ if (usage & PIPE_TRANSFER_DONTBLOCK)
+ res |= PB_USAGE_DONTBLOCK;
+
+ if (usage & PIPE_TRANSFER_UNSYNCHRONIZED)
+ res |= PB_USAGE_UNSYNCHRONIZED;
+
+ return res;
+}
+
+static void *radeon_bo_map_internal(struct pb_buffer *_buf,
+ unsigned flags, void *flush_ctx)
+{
+ struct radeon_bo *bo = radeon_bo(_buf);
+ struct radeon_drm_cs *cs = flush_ctx;
+ struct drm_radeon_gem_mmap args = {};
+ void *ptr;
+
+ /* If it's not unsynchronized bo_map, flush CS if needed and then wait. */
+ if (!(flags & PB_USAGE_UNSYNCHRONIZED)) {
+ /* DONTBLOCK doesn't make sense with UNSYNCHRONIZED. */
+ if (flags & PB_USAGE_DONTBLOCK) {
+ if (radeon_bo_is_referenced_by_cs(cs, bo)) {
+ cs->flush_cs(cs->flush_data);
+ return NULL;
+ }
+
+ if (radeon_bo_is_busy((struct r300_winsys_bo*)bo)) {
+ return NULL;
+ }
+ } else {
+ if (radeon_bo_is_referenced_by_cs(cs, bo)) {
+ cs->flush_cs(cs->flush_data);
+ }
+
+ radeon_bo_wait((struct r300_winsys_bo*)bo);
+ }
+ }
+
+ /* Return the pointer if it's already mapped. */
+ if (bo->ptr)
+ return bo->ptr;
+
+ /* Map the buffer. */
+ pipe_mutex_lock(bo->map_mutex);
+ args.handle = bo->handle;
+ args.offset = 0;
+ args.size = (uint64_t)bo->size;
+ if (drmCommandWriteRead(bo->rws->fd,
+ DRM_RADEON_GEM_MMAP,
+ &args,
+ sizeof(args))) {
+ pipe_mutex_unlock(bo->map_mutex);
+ fprintf(stderr, "radeon: gem_mmap failed: %p 0x%08X\n",
+ bo, bo->handle);
+ return NULL;
+ }
+
+ ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ bo->rws->fd, args.addr_ptr);
+ if (ptr == MAP_FAILED) {
+ pipe_mutex_unlock(bo->map_mutex);
+ fprintf(stderr, "radeon: mmap failed, errno: %i\n", errno);
+ return NULL;
+ }
+ bo->ptr = ptr;
+ pipe_mutex_unlock(bo->map_mutex);
+
+ return bo->ptr;
+}
+
+static void radeon_bo_unmap_internal(struct pb_buffer *_buf)
+{
+ /* NOP */
+}
+
+static void radeon_bo_get_base_buffer(struct pb_buffer *buf,
+ struct pb_buffer **base_buf,
+ unsigned *offset)
+{
+ *base_buf = buf;
+ *offset = 0;
+}
+
+static enum pipe_error radeon_bo_validate(struct pb_buffer *_buf,
+ struct pb_validate *vl,
+ unsigned flags)
+{
+ /* Always pinned */
+ return PIPE_OK;
+}
+
+static void radeon_bo_fence(struct pb_buffer *buf,
+ struct pipe_fence_handle *fence)
+{
+}
+
+const struct pb_vtbl radeon_bo_vtbl = {
+ radeon_bo_destroy,
+ radeon_bo_map_internal,
+ radeon_bo_unmap_internal,
+ radeon_bo_validate,
+ radeon_bo_fence,
+ radeon_bo_get_base_buffer,
+};
+
+static struct pb_buffer *radeon_bomgr_create_bo(struct pb_manager *_mgr,
+ pb_size size,
+ const struct pb_desc *desc)
+{
+ struct radeon_bomgr *mgr = radeon_bomgr(_mgr);
+ struct radeon_drm_winsys *rws = mgr->rws;
+ struct radeon_bo *bo;
+ struct drm_radeon_gem_create args = {};
+
+ args.size = size;
+ args.alignment = desc->alignment;
+ args.initial_domain =
+ (desc->usage & RADEON_PB_USAGE_DOMAIN_GTT ?
+ RADEON_GEM_DOMAIN_GTT : 0) |
+ (desc->usage & RADEON_PB_USAGE_DOMAIN_VRAM ?
+ RADEON_GEM_DOMAIN_VRAM : 0);
+
+ if (drmCommandWriteRead(rws->fd, DRM_RADEON_GEM_CREATE,
+ &args, sizeof(args))) {
+ fprintf(stderr, "Failed to allocate :\n");
+ fprintf(stderr, " size : %d bytes\n", size);
+ fprintf(stderr, " alignment : %d bytes\n", desc->alignment);
+ fprintf(stderr, " domains : %d\n", args.initial_domain);
+ return NULL;
+ }
+
+ bo = CALLOC_STRUCT(radeon_bo);
+ if (!bo)
+ return NULL;
+
+ pipe_reference_init(&bo->base.base.reference, 1);
+ bo->base.base.alignment = desc->alignment;
+ bo->base.base.usage = desc->usage;
+ bo->base.base.size = size;
+ bo->base.vtbl = &radeon_bo_vtbl;
+ bo->mgr = mgr;
+ bo->rws = mgr->rws;
+ bo->handle = args.handle;
+ bo->size = size;
+ pipe_mutex_init(bo->map_mutex);
+
+ radeon_bo_ref(bo);
+ return &bo->base;
+}
+
+static void radeon_bomgr_flush(struct pb_manager *mgr)
+{
+ /* NOP */
+}
+
+/* This is for the cache bufmgr. */
+static boolean radeon_bomgr_is_buffer_busy(struct pb_manager *_mgr,
+ struct pb_buffer *_buf)
+{
+ struct radeon_bo *bo = radeon_bo(_buf);
+
+ if (radeon_bo_is_referenced_by_any_cs(bo)) {
+ return TRUE;
+ }
+
+ if (radeon_bo_is_busy((struct r300_winsys_bo*)bo)) {
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void radeon_bomgr_destroy(struct pb_manager *_mgr)
+{
+ struct radeon_bomgr *mgr = radeon_bomgr(_mgr);
+ util_hash_table_destroy(mgr->bo_handles);
+ pipe_mutex_destroy(mgr->bo_handles_mutex);
+ FREE(mgr);
+}
+
+#define PTR_TO_UINT(x) ((unsigned)((intptr_t)(x)))
+
+static unsigned handle_hash(void *key)
+{
+ return PTR_TO_UINT(key);
+}
+
+static int handle_compare(void *key1, void *key2)
+{
+ return PTR_TO_UINT(key1) != PTR_TO_UINT(key2);
+}
+
+struct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws)
+{
+ struct radeon_bomgr *mgr;
+
+ mgr = CALLOC_STRUCT(radeon_bomgr);
+ if (!mgr)
+ return NULL;
+
+ mgr->base.destroy = radeon_bomgr_destroy;
+ mgr->base.create_buffer = radeon_bomgr_create_bo;
+ mgr->base.flush = radeon_bomgr_flush;
+ mgr->base.is_buffer_busy = radeon_bomgr_is_buffer_busy;
+
+ mgr->rws = rws;
+ mgr->bo_handles = util_hash_table_create(handle_hash, handle_compare);
+ pipe_mutex_init(mgr->bo_handles_mutex);
+ return &mgr->base;
+}
+
+static void *radeon_bo_map(struct r300_winsys_bo *buf,
+ struct r300_winsys_cs *cs,
+ enum pipe_transfer_usage usage)
+{
+ struct pb_buffer *_buf = pb_buffer(buf);
+
+ return pb_map(_buf, get_pb_usage_from_transfer_flags(usage), cs);
+}
+
+static void radeon_bo_get_tiling(struct r300_winsys_bo *_buf,
+ enum r300_buffer_tiling *microtiled,
+ enum r300_buffer_tiling *macrotiled)
+{
+ struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
+ struct drm_radeon_gem_set_tiling args = {};
+
+ args.handle = bo->handle;
+
+ drmCommandWriteRead(bo->rws->fd,
+ DRM_RADEON_GEM_GET_TILING,
+ &args,
+ sizeof(args));
+
+ *microtiled = R300_BUFFER_LINEAR;
+ *macrotiled = R300_BUFFER_LINEAR;
+ if (args.tiling_flags & RADEON_BO_FLAGS_MICRO_TILE)
+ *microtiled = R300_BUFFER_TILED;
+
+ if (args.tiling_flags & RADEON_BO_FLAGS_MACRO_TILE)
+ *macrotiled = R300_BUFFER_TILED;
+}
+
+static void radeon_bo_set_tiling(struct r300_winsys_bo *_buf,
+ struct r300_winsys_cs *rcs,
+ enum r300_buffer_tiling microtiled,
+ enum r300_buffer_tiling macrotiled,
+ uint32_t pitch)
+{
+ struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
+ struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
+ struct drm_radeon_gem_set_tiling args = {};
+
+ /* Tiling determines how DRM treats the buffer data.
+ * We must flush CS when changing it if the buffer is referenced. */
+ if (cs && radeon_bo_is_referenced_by_cs(cs, bo)) {
+ radeon_drm_cs_flush(rcs);
+ radeon_drm_cs_sync_flush(rcs);
+ }
+
+ while (p_atomic_read(&bo->num_active_ioctls)) {
+ sched_yield();
+ }
+
+ if (microtiled == R300_BUFFER_TILED)
+ args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE;
+ else if (microtiled == R300_BUFFER_SQUARETILED)
+ args.tiling_flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE;
+
+ if (macrotiled == R300_BUFFER_TILED)
+ args.tiling_flags |= RADEON_BO_FLAGS_MACRO_TILE;
+
+ args.handle = bo->handle;
+ args.pitch = pitch;
+
+ drmCommandWriteRead(bo->rws->fd,
+ DRM_RADEON_GEM_SET_TILING,
+ &args,
+ sizeof(args));
+}
+
+static struct r300_winsys_cs_handle *radeon_drm_get_cs_handle(
+ struct r300_winsys_bo *_buf)
+{
+ /* return radeon_bo. */
+ return (struct r300_winsys_cs_handle*)
+ get_radeon_bo(pb_buffer(_buf));
+}
+
+static unsigned get_pb_usage_from_create_flags(unsigned bind, unsigned usage,
+ enum r300_buffer_domain domain)
+{
+ unsigned res = 0;
+
+ if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
+ res |= RADEON_PB_USAGE_CACHE;
+
+ if (domain & R300_DOMAIN_GTT)
+ res |= RADEON_PB_USAGE_DOMAIN_GTT;
+
+ if (domain & R300_DOMAIN_VRAM)
+ res |= RADEON_PB_USAGE_DOMAIN_VRAM;
+
+ return res;
+}
+
+static struct r300_winsys_bo *
+radeon_winsys_bo_create(struct r300_winsys_screen *rws,
+ unsigned size,
+ unsigned alignment,
+ unsigned bind,
+ unsigned usage,
+ enum r300_buffer_domain domain)
+{
+ struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
+ struct pb_desc desc;
+ struct pb_manager *provider;
+ struct pb_buffer *buffer;
+
+ memset(&desc, 0, sizeof(desc));
+ desc.alignment = alignment;
+ desc.usage = get_pb_usage_from_create_flags(bind, usage, domain);
+
+ /* Assign a buffer manager. */
+ if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
+ provider = ws->cman;
+ else
+ provider = ws->kman;
+
+ buffer = provider->create_buffer(provider, size, &desc);
+ if (!buffer)
+ return NULL;
+
+ return (struct r300_winsys_bo*)buffer;
+}
+
+static struct r300_winsys_bo *radeon_winsys_bo_from_handle(struct r300_winsys_screen *rws,
+ struct winsys_handle *whandle,
+ unsigned *stride,
+ unsigned *size)
+{
+ struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
+ struct radeon_bo *bo;
+ struct radeon_bomgr *mgr = radeon_bomgr(ws->kman);
+ struct drm_gem_open open_arg = {};
+
+ /* We must maintain a list of pairs <handle, bo>, so that we always return
+ * the same BO for one particular handle. If we didn't do that and created
+ * more than one BO for the same handle and then relocated them in a CS,
+ * we would hit a deadlock in the kernel.
+ *
+ * The list of pairs is guarded by a mutex, of course. */
+ pipe_mutex_lock(mgr->bo_handles_mutex);
+
+ /* First check if there already is an existing bo for the handle. */
+ bo = util_hash_table_get(mgr->bo_handles, (void*)(uintptr_t)whandle->handle);
+ if (bo) {
+ /* Increase the refcount. */
+ struct pb_buffer *b = NULL;
+ pb_reference(&b, &bo->base);
+ goto done;
+ }
+
+ /* There isn't, create a new one. */
+ bo = CALLOC_STRUCT(radeon_bo);
+ if (!bo) {
+ goto fail;
+ }
+
+ /* Open the BO. */
+ open_arg.name = whandle->handle;
+ if (drmIoctl(ws->fd, DRM_IOCTL_GEM_OPEN, &open_arg)) {
+ FREE(bo);
+ goto fail;
+ }
+ bo->handle = open_arg.handle;
+ bo->size = open_arg.size;
+ bo->name = whandle->handle;
+ radeon_bo_ref(bo);
+
+ /* Initialize it. */
+ pipe_reference_init(&bo->base.base.reference, 1);
+ bo->base.base.alignment = 0;
+ bo->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
+ bo->base.base.size = bo->size;
+ bo->base.vtbl = &radeon_bo_vtbl;
+ bo->mgr = mgr;
+ bo->rws = mgr->rws;
+ pipe_mutex_init(bo->map_mutex);
+
+ util_hash_table_set(mgr->bo_handles, (void*)(uintptr_t)whandle->handle, bo);
+
+done:
+ pipe_mutex_unlock(mgr->bo_handles_mutex);
+
+ if (stride)
+ *stride = whandle->stride;
+ if (size)
+ *size = bo->base.base.size;
+
+ return (struct r300_winsys_bo*)bo;
+
+fail:
+ pipe_mutex_unlock(mgr->bo_handles_mutex);
+ return NULL;
+}
+
+static boolean radeon_winsys_bo_get_handle(struct r300_winsys_bo *buffer,
+ unsigned stride,
+ struct winsys_handle *whandle)
+{
+ struct drm_gem_flink flink = {};
+ struct radeon_bo *bo = get_radeon_bo(pb_buffer(buffer));
+
+ if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
+ if (!bo->flinked) {
+ flink.handle = bo->handle;
+
+ if (ioctl(bo->rws->fd, DRM_IOCTL_GEM_FLINK, &flink)) {
+ return FALSE;
+ }
+
+ bo->flinked = TRUE;
+ bo->flink = flink.name;
+ }
+ whandle->handle = bo->flink;
+ } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
+ whandle->handle = bo->handle;
+ }
+
+ whandle->stride = stride;
+ return TRUE;
+}
+
+void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws)
+{
+ ws->base.buffer_get_cs_handle = radeon_drm_get_cs_handle;
+ ws->base.buffer_set_tiling = radeon_bo_set_tiling;
+ ws->base.buffer_get_tiling = radeon_bo_get_tiling;
+ ws->base.buffer_map = radeon_bo_map;
+ ws->base.buffer_unmap = pb_unmap;
+ ws->base.buffer_wait = radeon_bo_wait;
+ ws->base.buffer_is_busy = radeon_bo_is_busy;
+ ws->base.buffer_create = radeon_winsys_bo_create;
+ ws->base.buffer_from_handle = radeon_winsys_bo_from_handle;
+ ws->base.buffer_get_handle = radeon_winsys_bo_get_handle;
+}
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.h b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
index 494abdc0b48..a26866b7e75 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
@@ -1,5 +1,6 @@
/*
* Copyright © 2008 Jérôme Glisse
+ * Copyright © 2011 Marek Olšák <[email protected]>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
@@ -26,28 +27,61 @@
/*
* Authors:
* Jérôme Glisse <[email protected]>
+ * Marek Olšák <[email protected]>
*/
#ifndef RADEON_DRM_BUFFER_H
#define RADEON_DRM_BUFFER_H
#include "radeon_winsys.h"
+#include "pipebuffer/pb_bufmgr.h"
+#include "os/os_thread.h"
-#define RADEON_PB_USAGE_VERTEX (1 << 28)
+#define RADEON_PB_USAGE_CACHE (1 << 28)
#define RADEON_PB_USAGE_DOMAIN_GTT (1 << 29)
#define RADEON_PB_USAGE_DOMAIN_VRAM (1 << 30)
+struct radeon_bomgr;
+
+struct radeon_bo {
+ struct pb_buffer base;
+ struct radeon_bomgr *mgr;
+ struct radeon_drm_winsys *rws;
+
+ void *ptr;
+ pipe_mutex map_mutex;
+
+ uint32_t size;
+ uint32_t handle;
+ uint32_t name;
+
+ int ref_count;
+
+ /* how many command streams is this bo referenced in? */
+ int num_cs_references;
+
+ /* how many command streams, which are being emitted in a separate
+ * thread, is this bo referenced in? */
+ int num_active_ioctls;
+
+ boolean flinked;
+ uint32_t flink;
+};
+
+struct pb_manager *radeon_bomgr_create(struct radeon_drm_winsys *rws);
+void radeon_bomgr_init_functions(struct radeon_drm_winsys *ws);
+
+void radeon_bo_unref(struct radeon_bo *buf);
+
+
+static INLINE void radeon_bo_ref(struct radeon_bo *bo)
+{
+ p_atomic_inc(&bo->ref_count);
+}
+
static INLINE struct pb_buffer *
-radeon_pb_buffer(struct r300_winsys_buffer *buffer)
+pb_buffer(struct r300_winsys_bo *buffer)
{
return (struct pb_buffer *)buffer;
}
-struct pb_manager *radeon_drm_bufmgr_create(struct radeon_drm_winsys *rws);
-struct pb_buffer *radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr,
- uint32_t handle);
-void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr);
-boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
- struct winsys_handle *whandle);
-void radeon_drm_bufmgr_init_functions(struct radeon_drm_winsys *ws);
-
#endif
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c b/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
deleted file mode 100644
index 5e14287ec2d..00000000000
--- a/src/gallium/winsys/radeon/drm/radeon_drm_buffer.c
+++ /dev/null
@@ -1,532 +0,0 @@
-#include "radeon_drm_buffer.h"
-#include "radeon_drm_cs.h"
-
-#include "util/u_hash_table.h"
-#include "util/u_memory.h"
-#include "util/u_simple_list.h"
-#include "pipebuffer/pb_bufmgr.h"
-#include "os/os_thread.h"
-
-#include "state_tracker/drm_driver.h"
-
-#include <radeon_drm.h>
-#include <radeon_bo_gem.h>
-#include <sys/ioctl.h>
-
-struct radeon_drm_bufmgr;
-
-struct radeon_drm_buffer {
- struct pb_buffer base;
- struct radeon_drm_bufmgr *mgr;
-
- struct radeon_bo *bo;
-
- boolean flinked;
- uint32_t flink;
-
- struct radeon_drm_buffer *next, *prev;
-};
-
-extern const struct pb_vtbl radeon_drm_buffer_vtbl;
-
-
-static INLINE struct radeon_drm_buffer *
-radeon_drm_buffer(struct pb_buffer *buf)
-{
- assert(buf);
- assert(buf->vtbl == &radeon_drm_buffer_vtbl);
- return (struct radeon_drm_buffer *)buf;
-}
-
-struct radeon_drm_bufmgr {
- /* Base class. */
- struct pb_manager base;
-
- /* Winsys. */
- struct radeon_drm_winsys *rws;
-
- /* List of mapped buffers and its mutex. */
- struct radeon_drm_buffer buffer_map_list;
- pipe_mutex buffer_map_list_mutex;
-
- /* List of buffer handles and its mutex. */
- struct util_hash_table *buffer_handles;
- pipe_mutex buffer_handles_mutex;
-};
-
-static INLINE struct radeon_drm_bufmgr *
-radeon_drm_bufmgr(struct pb_manager *mgr)
-{
- assert(mgr);
- return (struct radeon_drm_bufmgr *)mgr;
-}
-
-static void
-radeon_drm_buffer_destroy(struct pb_buffer *_buf)
-{
- struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
- int name;
-
- if (buf->bo->ptr != NULL) {
- pipe_mutex_lock(buf->mgr->buffer_map_list_mutex);
- /* Now test it again inside the mutex. */
- if (buf->bo->ptr != NULL) {
- remove_from_list(buf);
- radeon_bo_unmap(buf->bo);
- buf->bo->ptr = NULL;
- }
- pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex);
- }
- name = radeon_gem_name_bo(buf->bo);
- if (name) {
- pipe_mutex_lock(buf->mgr->buffer_handles_mutex);
- util_hash_table_remove(buf->mgr->buffer_handles,
- (void*)(uintptr_t)name);
- pipe_mutex_unlock(buf->mgr->buffer_handles_mutex);
- }
- radeon_bo_unref(buf->bo);
-
- FREE(buf);
-}
-
-static unsigned get_pb_usage_from_transfer_flags(enum pipe_transfer_usage usage)
-{
- unsigned res = 0;
-
- if (usage & PIPE_TRANSFER_READ)
- res |= PB_USAGE_CPU_READ;
-
- if (usage & PIPE_TRANSFER_WRITE)
- res |= PB_USAGE_CPU_WRITE;
-
- if (usage & PIPE_TRANSFER_DONTBLOCK)
- res |= PB_USAGE_DONTBLOCK;
-
- if (usage & PIPE_TRANSFER_UNSYNCHRONIZED)
- res |= PB_USAGE_UNSYNCHRONIZED;
-
- return res;
-}
-
-static void *
-radeon_drm_buffer_map_internal(struct pb_buffer *_buf,
- unsigned flags, void *flush_ctx)
-{
- struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
- struct radeon_drm_cs *cs = flush_ctx;
- int write = 0;
-
- /* Note how we use radeon_bo_is_referenced_by_cs here. There are
- * basically two places this map function can be called from:
- * - pb_map
- * - create_buffer (in the buffer reuse case)
- *
- * Since pb managers are per-winsys managers, not per-context managers,
- * and we shouldn't reuse buffers if they are in-use in any context,
- * we simply ask: is this buffer referenced by *any* CS?
- *
- * The problem with buffer_create is that it comes from pipe_screen,
- * so we have no CS to look at, though luckily the following code
- * is sufficient to tell whether the buffer is in use. */
- if (flags & PB_USAGE_DONTBLOCK) {
- if (_buf->base.usage & RADEON_PB_USAGE_VERTEX)
- if (radeon_bo_is_referenced_by_cs(buf->bo, NULL))
- return NULL;
- }
-
- if (buf->bo->ptr != NULL) {
- pipe_mutex_lock(buf->mgr->buffer_map_list_mutex);
- /* Now test ptr again inside the mutex. We might have gotten a race
- * during the first test. */
- if (buf->bo->ptr != NULL) {
- remove_from_list(buf);
- }
- pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex);
- return buf->bo->ptr;
- }
-
- if (flags & PB_USAGE_DONTBLOCK) {
- uint32_t domain;
- if (radeon_bo_is_busy(buf->bo, &domain))
- return NULL;
- }
-
- /* If we don't have any CS and the buffer is referenced,
- * we cannot flush. */
- assert(cs || !radeon_bo_is_referenced_by_cs(buf->bo, NULL));
-
- if (cs && radeon_bo_is_referenced_by_cs(buf->bo, NULL)) {
- cs->flush_cs(cs->flush_data);
- }
-
- if (flags & PB_USAGE_CPU_WRITE) {
- write = 1;
- }
-
- if (radeon_bo_map(buf->bo, write)) {
- return NULL;
- }
-
- pipe_mutex_lock(buf->mgr->buffer_map_list_mutex);
- remove_from_list(buf);
- pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex);
- return buf->bo->ptr;
-}
-
-static void
-radeon_drm_buffer_unmap_internal(struct pb_buffer *_buf)
-{
- struct radeon_drm_buffer *buf = radeon_drm_buffer(_buf);
- pipe_mutex_lock(buf->mgr->buffer_map_list_mutex);
- if (is_empty_list(buf)) { /* = is not inserted... */
- insert_at_tail(&buf->mgr->buffer_map_list, buf);
- }
- pipe_mutex_unlock(buf->mgr->buffer_map_list_mutex);
-}
-
-static void
-radeon_drm_buffer_get_base_buffer(struct pb_buffer *buf,
- struct pb_buffer **base_buf,
- unsigned *offset)
-{
- *base_buf = buf;
- *offset = 0;
-}
-
-
-static enum pipe_error
-radeon_drm_buffer_validate(struct pb_buffer *_buf,
- struct pb_validate *vl,
- unsigned flags)
-{
- /* Always pinned */
- return PIPE_OK;
-}
-
-static void
-radeon_drm_buffer_fence(struct pb_buffer *buf,
- struct pipe_fence_handle *fence)
-{
-}
-
-const struct pb_vtbl radeon_drm_buffer_vtbl = {
- radeon_drm_buffer_destroy,
- radeon_drm_buffer_map_internal,
- radeon_drm_buffer_unmap_internal,
- radeon_drm_buffer_validate,
- radeon_drm_buffer_fence,
- radeon_drm_buffer_get_base_buffer,
-};
-
-static struct pb_buffer *
-radeon_drm_bufmgr_create_buffer_from_handle_unsafe(struct pb_manager *_mgr,
- uint32_t handle)
-{
- struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
- struct radeon_drm_winsys *rws = mgr->rws;
- struct radeon_drm_buffer *buf;
- struct radeon_bo *bo;
-
- buf = util_hash_table_get(mgr->buffer_handles, (void*)(uintptr_t)handle);
-
- if (buf) {
- struct pb_buffer *b = NULL;
- pb_reference(&b, &buf->base);
- return b;
- }
-
- bo = radeon_bo_open(rws->bom, handle, 0,
- 0, 0, 0);
- if (bo == NULL)
- return NULL;
-
- buf = CALLOC_STRUCT(radeon_drm_buffer);
- if (!buf) {
- radeon_bo_unref(bo);
- return NULL;
- }
-
- make_empty_list(buf);
-
- pipe_reference_init(&buf->base.base.reference, 1);
- buf->base.base.alignment = 0;
- buf->base.base.usage = PB_USAGE_GPU_WRITE | PB_USAGE_GPU_READ;
- buf->base.base.size = bo->size;
- buf->base.vtbl = &radeon_drm_buffer_vtbl;
- buf->mgr = mgr;
-
- buf->bo = bo;
-
- util_hash_table_set(mgr->buffer_handles, (void*)(uintptr_t)handle, buf);
-
- return &buf->base;
-}
-
-struct pb_buffer *
-radeon_drm_bufmgr_create_buffer_from_handle(struct pb_manager *_mgr,
- uint32_t handle)
-{
- struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
- struct pb_buffer *pb;
-
- pipe_mutex_lock(mgr->buffer_handles_mutex);
- pb = radeon_drm_bufmgr_create_buffer_from_handle_unsafe(_mgr, handle);
- pipe_mutex_unlock(mgr->buffer_handles_mutex);
-
- return pb;
-}
-
-static struct pb_buffer *
-radeon_drm_bufmgr_create_buffer(struct pb_manager *_mgr,
- pb_size size,
- const struct pb_desc *desc)
-{
- struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
- struct radeon_drm_winsys *rws = mgr->rws;
- struct radeon_drm_buffer *buf;
- uint32_t domain;
-
- buf = CALLOC_STRUCT(radeon_drm_buffer);
- if (!buf)
- goto error1;
-
- pipe_reference_init(&buf->base.base.reference, 1);
- buf->base.base.alignment = desc->alignment;
- buf->base.base.usage = desc->usage;
- buf->base.base.size = size;
- buf->base.vtbl = &radeon_drm_buffer_vtbl;
- buf->mgr = mgr;
-
- make_empty_list(buf);
-
- domain =
- (desc->usage & RADEON_PB_USAGE_DOMAIN_GTT ? RADEON_GEM_DOMAIN_GTT : 0) |
- (desc->usage & RADEON_PB_USAGE_DOMAIN_VRAM ? RADEON_GEM_DOMAIN_VRAM : 0);
-
- buf->bo = radeon_bo_open(rws->bom, 0, size,
- desc->alignment, domain, 0);
- if (buf->bo == NULL)
- goto error2;
-
- return &buf->base;
-
- error2:
- FREE(buf);
- error1:
- return NULL;
-}
-
-static void
-radeon_drm_bufmgr_flush(struct pb_manager *mgr)
-{
- /* NOP */
-}
-
-static void
-radeon_drm_bufmgr_destroy(struct pb_manager *_mgr)
-{
- struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
- util_hash_table_destroy(mgr->buffer_handles);
- pipe_mutex_destroy(mgr->buffer_map_list_mutex);
- pipe_mutex_destroy(mgr->buffer_handles_mutex);
- FREE(mgr);
-}
-
-static unsigned handle_hash(void *key)
-{
- return (unsigned)key;
-}
-
-static int handle_compare(void *key1, void *key2)
-{
- return !((int)key1 == (int)key2);
-}
-
-struct pb_manager *
-radeon_drm_bufmgr_create(struct radeon_drm_winsys *rws)
-{
- struct radeon_drm_bufmgr *mgr;
-
- mgr = CALLOC_STRUCT(radeon_drm_bufmgr);
- if (!mgr)
- return NULL;
-
- mgr->base.destroy = radeon_drm_bufmgr_destroy;
- mgr->base.create_buffer = radeon_drm_bufmgr_create_buffer;
- mgr->base.flush = radeon_drm_bufmgr_flush;
-
- mgr->rws = rws;
- make_empty_list(&mgr->buffer_map_list);
- mgr->buffer_handles = util_hash_table_create(handle_hash, handle_compare);
- pipe_mutex_init(mgr->buffer_map_list_mutex);
- pipe_mutex_init(mgr->buffer_handles_mutex);
- return &mgr->base;
-}
-
-static struct radeon_drm_buffer *get_drm_buffer(struct pb_buffer *_buf)
-{
- struct radeon_drm_buffer *buf = NULL;
-
- if (_buf->vtbl == &radeon_drm_buffer_vtbl) {
- buf = radeon_drm_buffer(_buf);
- } else {
- struct pb_buffer *base_buf;
- pb_size offset;
- pb_get_base_buffer(_buf, &base_buf, &offset);
-
- if (base_buf->vtbl == &radeon_drm_buffer_vtbl)
- buf = radeon_drm_buffer(base_buf);
- }
-
- return buf;
-}
-
-static void *radeon_drm_buffer_map(struct r300_winsys_screen *ws,
- struct r300_winsys_buffer *buf,
- struct r300_winsys_cs *cs,
- enum pipe_transfer_usage usage)
-{
- struct pb_buffer *_buf = radeon_pb_buffer(buf);
-
- return pb_map(_buf, get_pb_usage_from_transfer_flags(usage), radeon_drm_cs(cs));
-}
-
-static void radeon_drm_buffer_unmap(struct r300_winsys_screen *ws,
- struct r300_winsys_buffer *buf)
-{
- struct pb_buffer *_buf = radeon_pb_buffer(buf);
-
- pb_unmap(_buf);
-}
-
-boolean radeon_drm_bufmgr_get_handle(struct pb_buffer *_buf,
- struct winsys_handle *whandle)
-{
- struct drm_gem_flink flink;
- struct radeon_drm_buffer *buf = get_drm_buffer(_buf);
-
- if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
- if (!buf->flinked) {
- flink.handle = buf->bo->handle;
-
- if (ioctl(buf->mgr->rws->fd, DRM_IOCTL_GEM_FLINK, &flink)) {
- return FALSE;
- }
-
- buf->flinked = TRUE;
- buf->flink = flink.name;
- }
- whandle->handle = buf->flink;
- } else if (whandle->type == DRM_API_HANDLE_TYPE_KMS) {
- whandle->handle = buf->bo->handle;
- }
- return TRUE;
-}
-
-static void radeon_drm_buffer_get_tiling(struct r300_winsys_screen *ws,
- struct r300_winsys_buffer *_buf,
- enum r300_buffer_tiling *microtiled,
- enum r300_buffer_tiling *macrotiled)
-{
- struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
- uint32_t flags = 0, pitch;
-
- radeon_bo_get_tiling(buf->bo, &flags, &pitch);
-
- *microtiled = R300_BUFFER_LINEAR;
- *macrotiled = R300_BUFFER_LINEAR;
- if (flags & RADEON_BO_FLAGS_MICRO_TILE)
- *microtiled = R300_BUFFER_TILED;
-
- if (flags & RADEON_BO_FLAGS_MACRO_TILE)
- *macrotiled = R300_BUFFER_TILED;
-}
-
-static void radeon_drm_buffer_set_tiling(struct r300_winsys_screen *ws,
- struct r300_winsys_buffer *_buf,
- enum r300_buffer_tiling microtiled,
- enum r300_buffer_tiling macrotiled,
- uint32_t pitch)
-{
- struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
- uint32_t flags = 0;
- if (microtiled == R300_BUFFER_TILED)
- flags |= RADEON_BO_FLAGS_MICRO_TILE;
-/* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */
-#ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE
- else if (microtiled == R300_BUFFER_SQUARETILED)
- flags |= RADEON_BO_FLAGS_MICRO_TILE_SQUARE;
-#endif
- if (macrotiled == R300_BUFFER_TILED)
- flags |= RADEON_BO_FLAGS_MACRO_TILE;
-
- radeon_bo_set_tiling(buf->bo, flags, pitch);
-}
-
-static struct r300_winsys_cs_buffer *radeon_drm_get_cs_handle(
- struct r300_winsys_screen *rws,
- struct r300_winsys_buffer *_buf)
-{
- /* return pure radeon_bo. */
- return (struct r300_winsys_cs_buffer*)
- get_drm_buffer(radeon_pb_buffer(_buf))->bo;
-}
-
-static boolean radeon_drm_is_buffer_referenced(struct r300_winsys_cs *rcs,
- struct r300_winsys_cs_buffer *_buf,
- enum r300_reference_domain domain)
-{
- struct radeon_bo *bo = (struct radeon_bo*)_buf;
- uint32_t tmp;
-
- if (domain & R300_REF_CS) {
- if (radeon_bo_is_referenced_by_cs(bo, NULL)) {
- return TRUE;
- }
- }
-
- if (domain & R300_REF_HW) {
- if (radeon_bo_is_busy(bo, &tmp)) {
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-void radeon_drm_bufmgr_flush_maps(struct pb_manager *_mgr)
-{
- struct radeon_drm_bufmgr *mgr = radeon_drm_bufmgr(_mgr);
- struct radeon_drm_buffer *rpb, *t_rpb;
-
- pipe_mutex_lock(mgr->buffer_map_list_mutex);
-
- foreach_s(rpb, t_rpb, &mgr->buffer_map_list) {
- radeon_bo_unmap(rpb->bo);
- rpb->bo->ptr = NULL;
- remove_from_list(rpb);
- }
-
- make_empty_list(&mgr->buffer_map_list);
-
- pipe_mutex_unlock(mgr->buffer_map_list_mutex);
-}
-
-static void radeon_drm_buffer_wait(struct r300_winsys_screen *ws,
- struct r300_winsys_buffer *_buf)
-{
- struct radeon_drm_buffer *buf = get_drm_buffer(radeon_pb_buffer(_buf));
-
- radeon_bo_wait(buf->bo);
-}
-
-void radeon_drm_bufmgr_init_functions(struct radeon_drm_winsys *ws)
-{
- ws->base.buffer_get_cs_handle = radeon_drm_get_cs_handle;
- ws->base.buffer_set_tiling = radeon_drm_buffer_set_tiling;
- ws->base.buffer_get_tiling = radeon_drm_buffer_get_tiling;
- ws->base.buffer_map = radeon_drm_buffer_map;
- ws->base.buffer_unmap = radeon_drm_buffer_unmap;
- ws->base.buffer_wait = radeon_drm_buffer_wait;
- ws->base.cs_is_buffer_referenced = radeon_drm_is_buffer_referenced;
-}
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_common.c b/src/gallium/winsys/radeon/drm/radeon_drm_common.c
index fe71f080592..4676c2a1ea9 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_common.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_common.c
@@ -1,5 +1,6 @@
/*
* Copyright © 2009 Corbin Simpson
+ * Copyright © 2011 Marek Olšák <[email protected]>
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining
@@ -27,38 +28,35 @@
* Authors:
* Corbin Simpson <[email protected]>
* Joakim Sindholt <[email protected]>
+ * Marek Olšák <[email protected]>
*/
#include "radeon_winsys.h"
-#include "radeon_drm_buffer.h"
+#include "radeon_drm_bo.h"
#include "radeon_drm_cs.h"
#include "radeon_drm_public.h"
#include "pipebuffer/pb_bufmgr.h"
#include "util/u_memory.h"
-#include <radeon_drm.h>
-#include <radeon_bo_gem.h>
-#include <radeon_cs_gem.h>
#include <xf86drm.h>
#include <stdio.h>
-
-/* Enable/disable Hyper-Z access. Return TRUE on success. */
-static boolean radeon_set_hyperz_access(int fd, boolean enable)
-{
#ifndef RADEON_INFO_WANT_HYPERZ
#define RADEON_INFO_WANT_HYPERZ 7
#endif
+#ifndef RADEON_INFO_WANT_CMASK
+#define RADEON_INFO_WANT_CMASK 8
+#endif
+/* Enable/disable feature access. Return TRUE on success. */
+static boolean radeon_set_fd_access(int fd, unsigned request, boolean enable)
+{
struct drm_radeon_info info = {0};
unsigned value = enable ? 1 : 0;
- if (!debug_get_bool_option("RADEON_HYPERZ", FALSE))
- return FALSE;
-
info.value = (unsigned long)&value;
- info.request = RADEON_INFO_WANT_HYPERZ;
+ info.request = request;
if (drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info)) != 0)
return FALSE;
@@ -107,23 +105,9 @@ static void do_ioctls(struct radeon_drm_winsys *winsys)
exit(1);
}
-/* XXX Remove this ifdef when libdrm version 2.4.19 becomes mandatory. */
-#ifdef RADEON_BO_FLAGS_MICRO_TILE_SQUARE
- // Supported since 2.1.0.
- winsys->squaretiling = version->version_major > 2 ||
- version->version_minor >= 1;
-#endif
-
- winsys->drm_2_3_0 = version->version_major > 2 ||
- version->version_minor >= 3;
-
- winsys->drm_2_6_0 = version->version_major > 2 ||
- (version->version_major == 2 &&
- version->version_minor >= 6);
-
- winsys->drm_2_8_0 = version->version_major > 2 ||
- (version->version_major == 2 &&
- version->version_minor >= 8);
+ winsys->drm_major = version->version_major;
+ winsys->drm_minor = version->version_minor;
+ winsys->drm_patchlevel = version->version_patchlevel;
info.request = RADEON_INFO_DEVICE_ID;
retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_INFO, &info, sizeof(info));
@@ -152,7 +136,15 @@ static void do_ioctls(struct radeon_drm_winsys *winsys)
}
winsys->z_pipes = target;
- winsys->hyperz = radeon_set_hyperz_access(winsys->fd, TRUE);
+ if (debug_get_bool_option("RADEON_HYPERZ", FALSE)) {
+ winsys->hyperz = radeon_set_fd_access(winsys->fd,
+ RADEON_INFO_WANT_HYPERZ, TRUE);
+ }
+
+ if (debug_get_bool_option("RADEON_CMASK", FALSE)) {
+ winsys->aacompress = radeon_set_fd_access(winsys->fd,
+ RADEON_INFO_WANT_CMASK, TRUE);
+ }
retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_GEM_INFO,
&gem_info, sizeof(gem_info));
@@ -164,17 +156,6 @@ static void do_ioctls(struct radeon_drm_winsys *winsys)
winsys->gart_size = gem_info.gart_size;
winsys->vram_size = gem_info.vram_size;
- debug_printf("radeon: Successfully grabbed chipset info from kernel!\n"
- "radeon: DRM version: %d.%d.%d ID: 0x%04x GB: %d Z: %d\n"
- "radeon: GART size: %d MB VRAM size: %d MB\n"
- "radeon: HyperZ: %s\n",
- version->version_major, version->version_minor,
- version->version_patchlevel, winsys->pci_id,
- winsys->gb_pipes, winsys->z_pipes,
- winsys->gart_size / 1024 / 1024,
- winsys->vram_size / 1024 / 1024,
- winsys->hyperz ? "YES" : "NO");
-
drmFreeVersion(version);
}
@@ -184,11 +165,47 @@ static void radeon_winsys_destroy(struct r300_winsys_screen *rws)
ws->cman->destroy(ws->cman);
ws->kman->destroy(ws->kman);
-
- radeon_bo_manager_gem_dtor(ws->bom);
FREE(rws);
}
+static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
+ enum r300_value_id id)
+{
+ struct radeon_drm_winsys *ws = (struct radeon_drm_winsys *)rws;
+
+ switch(id) {
+ case R300_VID_PCI_ID:
+ return ws->pci_id;
+ case R300_VID_GB_PIPES:
+ return ws->gb_pipes;
+ case R300_VID_Z_PIPES:
+ return ws->z_pipes;
+ case R300_VID_GART_SIZE:
+ return ws->gart_size;
+ case R300_VID_VRAM_SIZE:
+ return ws->vram_size;
+ case R300_VID_DRM_MAJOR:
+ return ws->drm_major;
+ case R300_VID_DRM_MINOR:
+ return ws->drm_minor;
+ case R300_VID_DRM_PATCHLEVEL:
+ return ws->drm_patchlevel;
+ case R300_VID_DRM_2_1_0:
+ return ws->drm_major*100 + ws->drm_minor >= 201;
+ case R300_VID_DRM_2_3_0:
+ return ws->drm_major*100 + ws->drm_minor >= 203;
+ case R300_VID_DRM_2_6_0:
+ return ws->drm_major*100 + ws->drm_minor >= 206;
+ case R300_VID_DRM_2_8_0:
+ return ws->drm_major*100 + ws->drm_minor >= 208;
+ case R300_CAN_HYPERZ:
+ return ws->hyperz;
+ case R300_CAN_AACOMPRESS:
+ return ws->aacompress;
+ }
+ return 0;
+}
+
struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd)
{
struct radeon_drm_winsys *ws = CALLOC_STRUCT(radeon_drm_winsys);
@@ -204,10 +221,7 @@ struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd)
}
/* Create managers. */
- ws->bom = radeon_bo_manager_gem_ctor(fd);
- if (!ws->bom)
- goto fail;
- ws->kman = radeon_drm_bufmgr_create(ws);
+ ws->kman = radeon_bomgr_create(ws);
if (!ws->kman)
goto fail;
ws->cman = pb_cache_manager_create(ws->kman, 1000000);
@@ -216,22 +230,18 @@ struct r300_winsys_screen *r300_drm_winsys_screen_create(int fd)
/* Set functions. */
ws->base.destroy = radeon_winsys_destroy;
+ ws->base.get_value = radeon_get_value;
- radeon_drm_bufmgr_init_functions(ws);
+ radeon_bomgr_init_functions(ws);
radeon_drm_cs_init_functions(ws);
- radeon_winsys_init_functions(ws);
return &ws->base;
fail:
- if (ws->bom)
- radeon_bo_manager_gem_dtor(ws->bom);
-
if (ws->cman)
ws->cman->destroy(ws->cman);
if (ws->kman)
ws->kman->destroy(ws->kman);
-
FREE(ws);
return NULL;
}
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
index 60bc36b0929..a38b01048b2 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
@@ -63,17 +63,73 @@
*/
#include "radeon_drm_cs.h"
-#include "radeon_drm_buffer.h"
#include "util/u_memory.h"
+#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
-#include <radeon_bo.h>
#include <xf86drm.h>
#define RELOC_DWORDS (sizeof(struct drm_radeon_cs_reloc) / sizeof(uint32_t))
+static boolean radeon_init_cs_context(struct radeon_cs_context *csc, int fd)
+{
+ csc->fd = fd;
+ csc->nrelocs = 512;
+ csc->relocs_bo = (struct radeon_bo**)
+ CALLOC(1, csc->nrelocs * sizeof(struct radeon_bo*));
+ if (!csc->relocs_bo) {
+ return FALSE;
+ }
+
+ csc->relocs = (struct drm_radeon_cs_reloc*)
+ CALLOC(1, csc->nrelocs * sizeof(struct drm_radeon_cs_reloc));
+ if (!csc->relocs) {
+ FREE(csc->relocs_bo);
+ return FALSE;
+ }
+
+ csc->chunks[0].chunk_id = RADEON_CHUNK_ID_IB;
+ csc->chunks[0].length_dw = 0;
+ csc->chunks[0].chunk_data = (uint64_t)(uintptr_t)csc->buf;
+ csc->chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS;
+ csc->chunks[1].length_dw = 0;
+ csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs;
+
+ csc->chunk_array[0] = (uint64_t)(uintptr_t)&csc->chunks[0];
+ csc->chunk_array[1] = (uint64_t)(uintptr_t)&csc->chunks[1];
+
+ csc->cs.num_chunks = 2;
+ csc->cs.chunks = (uint64_t)(uintptr_t)csc->chunk_array;
+ return TRUE;
+}
+
+static void radeon_cs_context_cleanup(struct radeon_cs_context *csc)
+{
+ unsigned i;
+
+ for (i = 0; i < csc->crelocs; i++) {
+ p_atomic_dec(&csc->relocs_bo[i]->num_cs_references);
+ radeon_bo_unref(csc->relocs_bo[i]);
+ csc->relocs_bo[i] = NULL;
+ }
+
+ csc->crelocs = 0;
+ csc->chunks[0].length_dw = 0;
+ csc->chunks[1].length_dw = 0;
+ csc->used_gart = 0;
+ csc->used_vram = 0;
+ memset(csc->is_handle_added, 0, sizeof(csc->is_handle_added));
+}
+
+static void radeon_destroy_cs_context(struct radeon_cs_context *csc)
+{
+ radeon_cs_context_cleanup(csc);
+ FREE(csc->relocs_bo);
+ FREE(csc->relocs);
+}
+
static struct r300_winsys_cs *radeon_drm_cs_create(struct r300_winsys_screen *rws)
{
struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
@@ -85,34 +141,29 @@ static struct r300_winsys_cs *radeon_drm_cs_create(struct r300_winsys_screen *rw
}
cs->ws = ws;
- cs->nrelocs = 256;
- cs->relocs_bo = (struct radeon_bo**)
- CALLOC(1, cs->nrelocs * sizeof(struct radeon_bo*));
- if (!cs->relocs_bo) {
+
+ if (!radeon_init_cs_context(&cs->csc1, cs->ws->fd)) {
FREE(cs);
return NULL;
}
-
- cs->relocs = (struct drm_radeon_cs_reloc*)
- CALLOC(1, cs->nrelocs * sizeof(struct drm_radeon_cs_reloc));
- if (!cs->relocs) {
- FREE(cs->relocs_bo);
+ if (!radeon_init_cs_context(&cs->csc2, cs->ws->fd)) {
+ radeon_destroy_cs_context(&cs->csc1);
FREE(cs);
return NULL;
}
- cs->chunks[0].chunk_id = RADEON_CHUNK_ID_IB;
- cs->chunks[0].length_dw = 0;
- cs->chunks[0].chunk_data = (uint64_t)(uintptr_t)cs->base.buf;
- cs->chunks[1].chunk_id = RADEON_CHUNK_ID_RELOCS;
- cs->chunks[1].length_dw = 0;
- cs->chunks[1].chunk_data = (uint64_t)(uintptr_t)cs->relocs;
+ /* Set the first command buffer as current. */
+ cs->csc = &cs->csc1;
+ cs->cst = &cs->csc2;
+ cs->base.buf = cs->csc->buf;
+
+ p_atomic_inc(&ws->num_cs);
return &cs->base;
}
#define OUT_CS(cs, value) (cs)->buf[(cs)->cdw++] = (value)
-static inline void update_domains(struct drm_radeon_cs_reloc *reloc,
+static INLINE void update_domains(struct drm_radeon_cs_reloc *reloc,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd,
enum r300_buffer_domain *added_domains)
@@ -131,23 +182,22 @@ static inline void update_domains(struct drm_radeon_cs_reloc *reloc,
}
}
-static int radeon_get_reloc(struct radeon_drm_cs *cs,
- struct radeon_bo *bo)
+int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo)
{
struct drm_radeon_cs_reloc *reloc;
unsigned i;
- unsigned hash = bo->handle & (sizeof(cs->is_handle_added)-1);
+ unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1);
- if (cs->is_handle_added[hash]) {
- reloc = cs->relocs_hashlist[hash];
+ if (csc->is_handle_added[hash]) {
+ reloc = csc->relocs_hashlist[hash];
if (reloc->handle == bo->handle) {
- return cs->reloc_indices_hashlist[hash];
+ return csc->reloc_indices_hashlist[hash];
}
/* Hash collision, look for the BO in the list of relocs linearly. */
- for (i = cs->crelocs; i != 0;) {
+ for (i = csc->crelocs; i != 0;) {
--i;
- reloc = &cs->relocs[i];
+ reloc = &csc->relocs[i];
if (reloc->handle == bo->handle) {
/* Put this reloc in the hash list.
* This will prevent additional hash collisions if there are
@@ -158,8 +208,8 @@ static int radeon_get_reloc(struct radeon_drm_cs *cs,
* AAAAAAAAAAABBBBBBBBBBBBBBCCCCCCCC
* will collide here: ^ and here: ^,
* meaning that we should get very few collisions in the end. */
- cs->relocs_hashlist[hash] = reloc;
- cs->reloc_indices_hashlist[hash] = i;
+ csc->relocs_hashlist[hash] = reloc;
+ csc->reloc_indices_hashlist[hash] = i;
/*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/
return i;
}
@@ -169,7 +219,7 @@ static int radeon_get_reloc(struct radeon_drm_cs *cs,
return -1;
}
-static void radeon_add_reloc(struct radeon_drm_cs *cs,
+static void radeon_add_reloc(struct radeon_cs_context *csc,
struct radeon_bo *bo,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd,
@@ -177,24 +227,24 @@ static void radeon_add_reloc(struct radeon_drm_cs *cs,
{
struct drm_radeon_cs_reloc *reloc;
unsigned i;
- unsigned hash = bo->handle & (sizeof(cs->is_handle_added)-1);
+ unsigned hash = bo->handle & (sizeof(csc->is_handle_added)-1);
- if (cs->is_handle_added[hash]) {
- reloc = cs->relocs_hashlist[hash];
+ if (csc->is_handle_added[hash]) {
+ reloc = csc->relocs_hashlist[hash];
if (reloc->handle == bo->handle) {
update_domains(reloc, rd, wd, added_domains);
return;
}
/* Hash collision, look for the BO in the list of relocs linearly. */
- for (i = cs->crelocs; i != 0;) {
+ for (i = csc->crelocs; i != 0;) {
--i;
- reloc = &cs->relocs[i];
+ reloc = &csc->relocs[i];
if (reloc->handle == bo->handle) {
update_domains(reloc, rd, wd, added_domains);
- cs->relocs_hashlist[hash] = reloc;
- cs->reloc_indices_hashlist[hash] = i;
+ csc->relocs_hashlist[hash] = reloc;
+ csc->reloc_indices_hashlist[hash] = i;
/*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/
return;
}
@@ -202,40 +252,41 @@ static void radeon_add_reloc(struct radeon_drm_cs *cs,
}
/* New relocation, check if the backing array is large enough. */
- if (cs->crelocs >= cs->nrelocs) {
+ if (csc->crelocs >= csc->nrelocs) {
uint32_t size;
- cs->nrelocs += 10;
+ csc->nrelocs += 10;
- size = cs->nrelocs * sizeof(struct radeon_bo*);
- cs->relocs_bo = (struct radeon_bo**)realloc(cs->relocs_bo, size);
+ size = csc->nrelocs * sizeof(struct radeon_bo*);
+ csc->relocs_bo = (struct radeon_bo**)realloc(csc->relocs_bo, size);
- size = cs->nrelocs * sizeof(struct drm_radeon_cs_reloc);
- cs->relocs = (struct drm_radeon_cs_reloc*)realloc(cs->relocs, size);
+ size = csc->nrelocs * sizeof(struct drm_radeon_cs_reloc);
+ csc->relocs = (struct drm_radeon_cs_reloc*)realloc(csc->relocs, size);
- cs->chunks[1].chunk_data = (uint64_t)(uintptr_t)cs->relocs;
+ csc->chunks[1].chunk_data = (uint64_t)(uintptr_t)csc->relocs;
}
/* Initialize the new relocation. */
radeon_bo_ref(bo);
- cs->relocs_bo[cs->crelocs] = bo;
- reloc = &cs->relocs[cs->crelocs];
+ p_atomic_inc(&bo->num_cs_references);
+ csc->relocs_bo[csc->crelocs] = bo;
+ reloc = &csc->relocs[csc->crelocs];
reloc->handle = bo->handle;
reloc->read_domains = rd;
reloc->write_domain = wd;
reloc->flags = 0;
- cs->is_handle_added[hash] = TRUE;
- cs->relocs_hashlist[hash] = reloc;
- cs->reloc_indices_hashlist[hash] = cs->crelocs;
+ csc->is_handle_added[hash] = TRUE;
+ csc->relocs_hashlist[hash] = reloc;
+ csc->reloc_indices_hashlist[hash] = csc->crelocs;
- cs->chunks[1].length_dw += RELOC_DWORDS;
- cs->crelocs++;
+ csc->chunks[1].length_dw += RELOC_DWORDS;
+ csc->crelocs++;
*added_domains = rd | wd;
}
static void radeon_drm_cs_add_reloc(struct r300_winsys_cs *rcs,
- struct r300_winsys_cs_buffer *buf,
+ struct r300_winsys_cs_handle *buf,
enum r300_buffer_domain rd,
enum r300_buffer_domain wd)
{
@@ -243,32 +294,32 @@ static void radeon_drm_cs_add_reloc(struct r300_winsys_cs *rcs,
struct radeon_bo *bo = (struct radeon_bo*)buf;
enum r300_buffer_domain added_domains;
- radeon_add_reloc(cs, bo, rd, wd, &added_domains);
+ radeon_add_reloc(cs->csc, bo, rd, wd, &added_domains);
if (!added_domains)
return;
if (added_domains & R300_DOMAIN_GTT)
- cs->used_gart += bo->size;
+ cs->csc->used_gart += bo->size;
if (added_domains & R300_DOMAIN_VRAM)
- cs->used_vram += bo->size;
+ cs->csc->used_vram += bo->size;
}
static boolean radeon_drm_cs_validate(struct r300_winsys_cs *rcs)
{
struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
- return cs->used_gart < cs->ws->gart_size * 0.8 &&
- cs->used_vram < cs->ws->vram_size * 0.8;
+ return cs->csc->used_gart < cs->ws->gart_size * 0.8 &&
+ cs->csc->used_vram < cs->ws->vram_size * 0.8;
}
static void radeon_drm_cs_write_reloc(struct r300_winsys_cs *rcs,
- struct r300_winsys_cs_buffer *buf)
+ struct r300_winsys_cs_handle *buf)
{
struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
struct radeon_bo *bo = (struct radeon_bo*)buf;
- unsigned index = radeon_get_reloc(cs, bo);
+ unsigned index = radeon_get_reloc(cs->csc, bo);
if (index == -1) {
fprintf(stderr, "r300: Cannot get a relocation in %s.\n", __func__);
@@ -279,75 +330,109 @@ static void radeon_drm_cs_write_reloc(struct r300_winsys_cs *rcs,
OUT_CS(&cs->base, index * RELOC_DWORDS);
}
-static void radeon_drm_cs_emit(struct r300_winsys_cs *rcs)
+static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param)
{
- struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
- uint64_t chunk_array[2];
+ struct radeon_cs_context *csc = (struct radeon_cs_context*)param;
unsigned i;
- int r;
- if (cs->base.cdw) {
- /* Unmap buffers. */
- radeon_drm_bufmgr_flush_maps(cs->ws->kman);
-
- /* Prepare the arguments. */
- cs->chunks[0].length_dw = cs->base.cdw;
-
- chunk_array[0] = (uint64_t)(uintptr_t)&cs->chunks[0];
- chunk_array[1] = (uint64_t)(uintptr_t)&cs->chunks[1];
-
- cs->cs.num_chunks = 2;
- cs->cs.chunks = (uint64_t)(uintptr_t)chunk_array;
-
- /* Emit. */
- r = drmCommandWriteRead(cs->ws->fd, DRM_RADEON_CS,
- &cs->cs, sizeof(struct drm_radeon_cs));
- if (r) {
- if (debug_get_bool_option("RADEON_DUMP_CS", FALSE)) {
- fprintf(stderr, "radeon: The kernel rejected CS, dumping...\n");
- fprintf(stderr, "VENDORID:DEVICEID 0x%04X:0x%04X\n", 0x1002,
- cs->ws->pci_id);
- for (i = 0; i < cs->base.cdw; i++) {
- fprintf(stderr, "0x%08X\n", cs->base.buf[i]);
- }
- } else {
- fprintf(stderr, "radeon: The kernel rejected CS, "
- "see dmesg for more information.\n");
+ if (drmCommandWriteRead(csc->fd, DRM_RADEON_CS,
+ &csc->cs, sizeof(struct drm_radeon_cs))) {
+ if (debug_get_bool_option("RADEON_DUMP_CS", FALSE)) {
+ unsigned i;
+
+ fprintf(stderr, "radeon: The kernel rejected CS, dumping...\n");
+ for (i = 0; i < csc->chunks[0].length_dw; i++) {
+ fprintf(stderr, "0x%08X\n", csc->buf[i]);
}
+ } else {
+ fprintf(stderr, "radeon: The kernel rejected CS, "
+ "see dmesg for more information.\n");
}
}
- /* Unreference buffers, cleanup. */
- for (i = 0; i < cs->crelocs; i++) {
- radeon_bo_unref((struct radeon_bo*)cs->relocs_bo[i]);
- cs->relocs_bo[i] = NULL;
+ for (i = 0; i < csc->crelocs; i++)
+ p_atomic_dec(&csc->relocs_bo[i]->num_active_ioctls);
+ return NULL;
+}
+
+void radeon_drm_cs_sync_flush(struct r300_winsys_cs *rcs)
+{
+ struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
+
+ /* Wait for any pending ioctl to complete. */
+ if (cs->thread) {
+ pipe_thread_wait(cs->thread);
+ cs->thread = 0;
}
+}
+
+DEBUG_GET_ONCE_BOOL_OPTION(thread, "RADEON_THREAD", TRUE)
+
+void radeon_drm_cs_flush(struct r300_winsys_cs *rcs)
+{
+ struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
+ struct radeon_cs_context *tmp;
+
+ radeon_drm_cs_sync_flush(rcs);
+
+ /* If the CS is not empty, emit it in a newly-spawned thread. */
+ if (cs->base.cdw) {
+ unsigned i, crelocs = cs->csc->crelocs;
+ cs->csc->chunks[0].length_dw = cs->base.cdw;
+
+ for (i = 0; i < crelocs; i++)
+ p_atomic_inc(&cs->csc->relocs_bo[i]->num_active_ioctls);
+
+ if (debug_get_option_thread()) {
+ cs->thread = pipe_thread_create(radeon_drm_cs_emit_ioctl, cs->csc);
+ assert(cs->thread);
+ } else {
+ radeon_drm_cs_emit_ioctl(cs->csc);
+ }
+ }
+
+ /* Flip command streams. */
+ tmp = cs->csc;
+ cs->csc = cs->cst;
+ cs->cst = tmp;
+
+ /* Prepare a new CS. */
+ radeon_cs_context_cleanup(cs->csc);
+
+ cs->base.buf = cs->csc->buf;
cs->base.cdw = 0;
- cs->crelocs = 0;
- cs->chunks[0].length_dw = 0;
- cs->chunks[1].length_dw = 0;
- cs->used_gart = 0;
- cs->used_vram = 0;
- memset(cs->is_handle_added, 0, sizeof(cs->is_handle_added));
}
static void radeon_drm_cs_destroy(struct r300_winsys_cs *rcs)
{
struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
- FREE(cs->relocs_bo);
- FREE(cs->relocs);
+ radeon_drm_cs_sync_flush(rcs);
+ radeon_cs_context_cleanup(&cs->csc1);
+ radeon_cs_context_cleanup(&cs->csc2);
+ p_atomic_dec(&cs->ws->num_cs);
+ radeon_destroy_cs_context(&cs->csc1);
+ radeon_destroy_cs_context(&cs->csc2);
FREE(cs);
}
static void radeon_drm_cs_set_flush(struct r300_winsys_cs *rcs,
- void (*flush)(void *), void *user)
+ void (*flush)(void *), void *user)
{
struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
cs->flush_cs = flush;
cs->flush_data = user;
}
+static boolean radeon_bo_is_referenced(struct r300_winsys_cs *rcs,
+ struct r300_winsys_cs_handle *_buf)
+{
+ struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
+ struct radeon_bo *bo = (struct radeon_bo*)_buf;
+
+ return radeon_bo_is_referenced_by_cs(cs, bo);
+}
+
void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws)
{
ws->base.cs_create = radeon_drm_cs_create;
@@ -355,6 +440,8 @@ void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws)
ws->base.cs_add_reloc = radeon_drm_cs_add_reloc;
ws->base.cs_validate = radeon_drm_cs_validate;
ws->base.cs_write_reloc = radeon_drm_cs_write_reloc;
- ws->base.cs_flush = radeon_drm_cs_emit;
+ ws->base.cs_flush = radeon_drm_cs_flush;
+ ws->base.cs_sync_flush = radeon_drm_cs_sync_flush;
ws->base.cs_set_flush = radeon_drm_cs_set_flush;
+ ws->base.cs_is_buffer_referenced = radeon_bo_is_referenced;
}
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
index 76046534b65..4cc97f37e09 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
@@ -1,42 +1,103 @@
+/*
+ * Copyright © 2011 Marek Olšák <[email protected]>
+ * 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.
+ */
+
#ifndef RADEON_DRM_CS_H
#define RADEON_DRM_CS_H
-#include "radeon_winsys.h"
+#include "radeon_drm_bo.h"
#include <radeon_drm.h>
-struct radeon_drm_cs {
- struct r300_winsys_cs base;
-
- /* The winsys. */
- struct radeon_drm_winsys *ws;
+struct radeon_cs_context {
+ uint32_t buf[R300_MAX_CMDBUF_DWORDS];
- /* Flush CS. */
- void (*flush_cs)(void *);
- void *flush_data;
+ int fd;
+ struct drm_radeon_cs cs;
+ struct drm_radeon_cs_chunk chunks[2];
+ uint64_t chunk_array[2];
/* Relocs. */
- unsigned crelocs;
unsigned nrelocs;
- struct drm_radeon_cs_reloc *relocs;
+ unsigned crelocs;
struct radeon_bo **relocs_bo;
- struct drm_radeon_cs cs;
- struct drm_radeon_cs_chunk chunks[2];
-
- unsigned used_vram;
- unsigned used_gart;
+ struct drm_radeon_cs_reloc *relocs;
/* 0 = BO not added, 1 = BO added */
char is_handle_added[256];
struct drm_radeon_cs_reloc *relocs_hashlist[256];
unsigned reloc_indices_hashlist[256];
+
+ unsigned used_vram;
+ unsigned used_gart;
};
+struct radeon_drm_cs {
+ struct r300_winsys_cs base;
+
+ /* We flip between these two CS. While one is being consumed
+ * by the kernel in another thread, the other one is being filled
+ * by the pipe driver. */
+ struct radeon_cs_context csc1;
+ struct radeon_cs_context csc2;
+ /* The currently-used CS. */
+ struct radeon_cs_context *csc;
+ /* The CS being currently-owned by the other thread. */
+ struct radeon_cs_context *cst;
+
+ /* The winsys. */
+ struct radeon_drm_winsys *ws;
+
+ /* Flush CS. */
+ void (*flush_cs)(void *);
+ void *flush_data;
+
+ pipe_thread thread;
+};
+
+int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo);
+
static INLINE struct radeon_drm_cs *
radeon_drm_cs(struct r300_winsys_cs *base)
{
return (struct radeon_drm_cs*)base;
}
+static INLINE boolean radeon_bo_is_referenced_by_cs(struct radeon_drm_cs *cs,
+ struct radeon_bo *bo)
+{
+ return bo->num_cs_references == bo->rws->num_cs ||
+ (bo->num_cs_references && radeon_get_reloc(cs->csc, bo) != -1);
+}
+
+static INLINE boolean radeon_bo_is_referenced_by_any_cs(struct radeon_bo *bo)
+{
+ return bo->num_cs_references;
+}
+
+void radeon_drm_cs_flush(struct r300_winsys_cs *rcs);
+void radeon_drm_cs_sync_flush(struct r300_winsys_cs *rcs);
void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws);
#endif
diff --git a/src/gallium/winsys/radeon/drm/radeon_r300.c b/src/gallium/winsys/radeon/drm/radeon_r300.c
deleted file mode 100644
index bacf181b47c..00000000000
--- a/src/gallium/winsys/radeon/drm/radeon_r300.c
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * Copyright 2008 Corbin Simpson <[email protected]>
- *
- * 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
- * on 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 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 NON-INFRINGEMENT. IN NO EVENT SHALL
- * THE AUTHOR(S) AND/OR THEIR 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. */
-
-#include "radeon_drm_buffer.h"
-
-#include "util/u_memory.h"
-#include "pipebuffer/pb_bufmgr.h"
-
-#include "state_tracker/drm_driver.h"
-
-static unsigned get_pb_usage_from_create_flags(unsigned bind, unsigned usage,
- enum r300_buffer_domain domain)
-{
- unsigned res = 0;
-
- if (bind & (PIPE_BIND_DEPTH_STENCIL | PIPE_BIND_RENDER_TARGET |
- PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT))
- res |= PB_USAGE_GPU_WRITE;
-
- if (bind & PIPE_BIND_SAMPLER_VIEW)
- res |= PB_USAGE_GPU_READ | PB_USAGE_GPU_WRITE;
-
- if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
- res |= PB_USAGE_GPU_READ;
-
- if (bind & PIPE_BIND_TRANSFER_WRITE)
- res |= PB_USAGE_CPU_WRITE;
-
- if (bind & PIPE_BIND_TRANSFER_READ)
- res |= PB_USAGE_CPU_READ;
-
- /* Is usage of any use for us? Probably not. */
-
- /* Now add driver-specific usage flags. */
- if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
- res |= RADEON_PB_USAGE_VERTEX;
-
- if (domain & R300_DOMAIN_GTT)
- res |= RADEON_PB_USAGE_DOMAIN_GTT;
-
- if (domain & R300_DOMAIN_VRAM)
- res |= RADEON_PB_USAGE_DOMAIN_VRAM;
-
- return res;
-}
-
-static struct r300_winsys_buffer *
-radeon_r300_winsys_buffer_create(struct r300_winsys_screen *rws,
- unsigned size,
- unsigned alignment,
- unsigned bind,
- unsigned usage,
- enum r300_buffer_domain domain)
-{
- struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
- struct pb_desc desc;
- struct pb_manager *provider;
- struct pb_buffer *buffer;
-
- memset(&desc, 0, sizeof(desc));
- desc.alignment = alignment;
- desc.usage = get_pb_usage_from_create_flags(bind, usage, domain);
-
- /* Assign a buffer manager. */
- if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
- provider = ws->cman;
- else
- provider = ws->kman;
-
- buffer = provider->create_buffer(provider, size, &desc);
- if (!buffer)
- return NULL;
-
- return (struct r300_winsys_buffer*)buffer;
-}
-
-static void radeon_r300_winsys_buffer_reference(struct r300_winsys_screen *rws,
- struct r300_winsys_buffer **pdst,
- struct r300_winsys_buffer *src)
-{
- struct pb_buffer *_src = radeon_pb_buffer(src);
- struct pb_buffer *_dst = radeon_pb_buffer(*pdst);
-
- pb_reference(&_dst, _src);
-
- *pdst = (struct r300_winsys_buffer*)_dst;
-}
-
-static struct r300_winsys_buffer *radeon_r300_winsys_buffer_from_handle(struct r300_winsys_screen *rws,
- struct winsys_handle *whandle,
- unsigned *stride,
- unsigned *size)
-{
- struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
- struct pb_buffer *_buf;
-
- _buf = radeon_drm_bufmgr_create_buffer_from_handle(ws->kman, whandle->handle);
-
- if (stride)
- *stride = whandle->stride;
- if (size)
- *size = _buf->base.size;
-
- return (struct r300_winsys_buffer*)_buf;
-}
-
-static boolean radeon_r300_winsys_buffer_get_handle(struct r300_winsys_screen *rws,
- struct r300_winsys_buffer *buffer,
- unsigned stride,
- struct winsys_handle *whandle)
-{
- struct pb_buffer *_buf = radeon_pb_buffer(buffer);
- whandle->stride = stride;
- return radeon_drm_bufmgr_get_handle(_buf, whandle);
-}
-
-static uint32_t radeon_get_value(struct r300_winsys_screen *rws,
- enum r300_value_id id)
-{
- struct radeon_drm_winsys *ws = (struct radeon_drm_winsys *)rws;
-
- switch(id) {
- case R300_VID_PCI_ID:
- return ws->pci_id;
- case R300_VID_GB_PIPES:
- return ws->gb_pipes;
- case R300_VID_Z_PIPES:
- return ws->z_pipes;
- case R300_VID_SQUARE_TILING_SUPPORT:
- return ws->squaretiling;
- case R300_VID_DRM_2_3_0:
- return ws->drm_2_3_0;
- case R300_VID_DRM_2_6_0:
- return ws->drm_2_6_0;
- case R300_VID_DRM_2_8_0:
- return ws->drm_2_8_0;
- case R300_CAN_HYPERZ:
- return ws->hyperz;
- }
- return 0;
-}
-
-void radeon_winsys_init_functions(struct radeon_drm_winsys *ws)
-{
- ws->base.get_value = radeon_get_value;
- ws->base.buffer_create = radeon_r300_winsys_buffer_create;
- ws->base.buffer_reference = radeon_r300_winsys_buffer_reference;
- ws->base.buffer_from_handle = radeon_r300_winsys_buffer_from_handle;
- ws->base.buffer_get_handle = radeon_r300_winsys_buffer_get_handle;
-}
diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h
index 492edfef8c3..f8a89abcfe4 100644
--- a/src/gallium/winsys/radeon/drm/radeon_winsys.h
+++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h
@@ -36,8 +36,8 @@ struct radeon_drm_winsys {
struct r300_winsys_screen base;
int fd; /* DRM file descriptor */
+ int num_cs; /* The number of command streams created. */
- struct radeon_bo_manager *bom; /* Radeon BO manager. */
struct pb_manager *kman;
struct pb_manager *cman;
@@ -46,15 +46,15 @@ struct radeon_drm_winsys {
uint32_t z_pipes; /* Z pipe count (rv530 only) */
uint32_t gart_size; /* GART size. */
uint32_t vram_size; /* VRAM size. */
- boolean squaretiling; /* Square tiling support. */
- /* DRM 2.3.0 (R500 VAP regs, MSPOS regs, fixed tex3D size checking) */
- boolean drm_2_3_0;
- /* DRM 2.6.0 (Hyper-Z, GB_Z_PEQ_CONFIG allowed on rv350->r4xx, FG_ALPHA_VALUE) */
- boolean drm_2_6_0;
- /* DRM 2.8.0 (US_FORMAT regs, ARGB2101010 colorbuffer) */
- boolean drm_2_8_0;
+
+ unsigned drm_major;
+ unsigned drm_minor;
+ unsigned drm_patchlevel;
+
/* Hyper-Z user */
boolean hyperz;
+ /* AA compression (CMask) */
+ boolean aacompress;
};
static INLINE struct radeon_drm_winsys *
@@ -63,6 +63,4 @@ radeon_drm_winsys(struct r300_winsys_screen *base)
return (struct radeon_drm_winsys*)base;
}
-void radeon_winsys_init_functions(struct radeon_drm_winsys *ws);
-
#endif