aboutsummaryrefslogtreecommitdiffstats
path: root/src/gallium/winsys/radeon
diff options
context:
space:
mode:
authorStéphane Marchesin <[email protected]>2011-08-26 17:37:25 -0700
committerStéphane Marchesin <[email protected]>2011-08-26 17:37:25 -0700
commitf8e6d19f3f40931be741b44d3edf210c38e13f0f (patch)
treee99e4c619901412ac6448534b0f57ce1c4295c6b /src/gallium/winsys/radeon
parent974c49ed176de55aadb335a2956ef5dfec774a23 (diff)
parente3b0e3776646d0367206e4544229622eb22fe9f8 (diff)
Merge branch 'master' of git://anongit.freedesktop.org/mesa/mesa
Diffstat (limited to 'src/gallium/winsys/radeon')
-rw-r--r--src/gallium/winsys/radeon/drm/Android.mk40
-rw-r--r--src/gallium/winsys/radeon/drm/Makefile6
-rw-r--r--src/gallium/winsys/radeon/drm/Makefile.sources4
-rw-r--r--src/gallium/winsys/radeon/drm/SConscript6
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_bo.c136
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_bo.h13
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.c77
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_cs.h8
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_winsys.c211
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_drm_winsys.h18
-rw-r--r--src/gallium/winsys/radeon/drm/radeon_winsys.h112
11 files changed, 385 insertions, 246 deletions
diff --git a/src/gallium/winsys/radeon/drm/Android.mk b/src/gallium/winsys/radeon/drm/Android.mk
new file mode 100644
index 00000000000..c1922498225
--- /dev/null
+++ b/src/gallium/winsys/radeon/drm/Android.mk
@@ -0,0 +1,40 @@
+# Mesa 3-D graphics library
+#
+# Copyright (C) 2011 Chia-I Wu <[email protected]>
+# Copyright (C) 2011 LunarG Inc.
+#
+# 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.
+
+LOCAL_PATH := $(call my-dir)
+
+# get C_SOURCES
+include $(LOCAL_PATH)/Makefile.sources
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := $(C_SOURCES)
+
+LOCAL_C_INCLUDES := \
+ $(DRM_TOP) \
+ $(DRM_TOP)/include/drm
+
+LOCAL_MODULE := libmesa_winsys_radeon
+
+include $(GALLIUM_COMMON_MK)
+include $(BUILD_STATIC_LIBRARY)
diff --git a/src/gallium/winsys/radeon/drm/Makefile b/src/gallium/winsys/radeon/drm/Makefile
index 913e6ad186a..68b9efebfa4 100644
--- a/src/gallium/winsys/radeon/drm/Makefile
+++ b/src/gallium/winsys/radeon/drm/Makefile
@@ -4,10 +4,8 @@ include $(TOP)/configs/current
LIBNAME = radeonwinsys
-C_SOURCES = \
- radeon_drm_bo.c \
- radeon_drm_cs.c \
- radeon_drm_winsys.c
+# get C_SOURCES
+include Makefile.sources
LIBRARY_INCLUDES = -I$(TOP)/include \
$(shell pkg-config libdrm --cflags-only-I)
diff --git a/src/gallium/winsys/radeon/drm/Makefile.sources b/src/gallium/winsys/radeon/drm/Makefile.sources
new file mode 100644
index 00000000000..1d18d6164d5
--- /dev/null
+++ b/src/gallium/winsys/radeon/drm/Makefile.sources
@@ -0,0 +1,4 @@
+C_SOURCES := \
+ radeon_drm_bo.c \
+ radeon_drm_cs.c \
+ radeon_drm_winsys.c
diff --git a/src/gallium/winsys/radeon/drm/SConscript b/src/gallium/winsys/radeon/drm/SConscript
index 2edb1e94645..e5048d6255d 100644
--- a/src/gallium/winsys/radeon/drm/SConscript
+++ b/src/gallium/winsys/radeon/drm/SConscript
@@ -2,11 +2,7 @@ Import('*')
env = env.Clone()
-radeon_sources = [
- 'radeon_drm_bo.c',
- 'radeon_drm_cs.c',
- 'radeon_drm_winsys.c',
-]
+radeon_sources = env.ParseSourceList('Makefile.sources', 'C_SOURCES')
env.PkgUseModules('DRM')
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
index b6f12727e81..b45efe5f49c 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.c
@@ -31,11 +31,11 @@
#include "util/u_memory.h"
#include "util/u_simple_list.h"
#include "os/os_thread.h"
+#include "os/os_mman.h"
#include "state_tracker/drm_driver.h"
#include <sys/ioctl.h>
-#include <sys/mman.h>
#include <xf86drm.h>
#include <errno.h>
@@ -43,6 +43,21 @@
#define RADEON_BO_FLAGS_MICRO_TILE 2
#define RADEON_BO_FLAGS_MICRO_TILE_SQUARE 0x20
+#ifndef DRM_RADEON_GEM_WAIT
+#define DRM_RADEON_GEM_WAIT 0x2b
+
+#define RADEON_GEM_NO_WAIT 0x1
+#define RADEON_GEM_USAGE_READ 0x2
+#define RADEON_GEM_USAGE_WRITE 0x4
+
+struct drm_radeon_gem_wait {
+ uint32_t handle;
+ uint32_t flags; /* one of RADEON_GEM_* */
+};
+
+#endif
+
+
extern const struct pb_vtbl radeon_bo_vtbl;
@@ -87,39 +102,49 @@ static struct radeon_bo *get_radeon_bo(struct pb_buffer *_buf)
return bo;
}
-static void radeon_bo_wait(struct pb_buffer *_buf)
+static void radeon_bo_wait(struct pb_buffer *_buf, enum radeon_bo_usage usage)
{
- struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
- struct drm_radeon_gem_wait_idle args = {};
+ struct radeon_bo *bo = get_radeon_bo(_buf);
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);
-
- bo->busy_for_write = FALSE;
+ if (bo->rws->info.drm_minor >= 12) {
+ struct drm_radeon_gem_wait args = {};
+ args.handle = bo->handle;
+ args.flags = usage;
+ while (drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT,
+ &args, sizeof(args)) == -EBUSY);
+ } else {
+ struct drm_radeon_gem_wait_idle args = {};
+ 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 pb_buffer *_buf)
+static boolean radeon_bo_is_busy(struct pb_buffer *_buf,
+ enum radeon_bo_usage usage)
{
- struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
- struct drm_radeon_gem_busy args = {};
- boolean busy;
+ struct radeon_bo *bo = get_radeon_bo(_buf);
if (p_atomic_read(&bo->num_active_ioctls)) {
return TRUE;
}
- args.handle = bo->handle;
- busy = drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_BUSY,
- &args, sizeof(args)) != 0;
-
- if (!busy)
- bo->busy_for_write = FALSE;
- return busy;
+ if (bo->rws->info.drm_minor >= 12) {
+ struct drm_radeon_gem_wait args = {};
+ args.handle = bo->handle;
+ args.flags = usage | RADEON_GEM_NO_WAIT;
+ return drmCommandWriteRead(bo->rws->fd, DRM_RADEON_GEM_WAIT,
+ &args, sizeof(args)) != 0;
+ } else {
+ struct drm_radeon_gem_busy args = {};
+ 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)
@@ -135,7 +160,7 @@ static void radeon_bo_destroy(struct pb_buffer *_buf)
}
if (bo->ptr)
- munmap(bo->ptr, bo->size);
+ os_munmap(bo->ptr, bo->size);
/* Close object. */
args.handle = bo->handle;
@@ -172,13 +197,33 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf,
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, RADEON_FLUSH_ASYNC);
- return NULL;
- }
+ if (!(flags & PB_USAGE_CPU_WRITE)) {
+ /* Mapping for read.
+ *
+ * Since we are mapping for read, we don't need to wait
+ * if the GPU is using the buffer for read too
+ * (neither one is changing it).
+ *
+ * Only check whether the buffer is being used for write. */
+ if (radeon_bo_is_referenced_by_cs_for_write(cs, bo)) {
+ cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC);
+ return NULL;
+ }
+
+ if (radeon_bo_is_busy((struct pb_buffer*)bo,
+ RADEON_USAGE_WRITE)) {
+ return NULL;
+ }
+ } else {
+ if (radeon_bo_is_referenced_by_cs(cs, bo)) {
+ cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC);
+ return NULL;
+ }
- if (radeon_bo_is_busy((struct pb_buffer*)bo)) {
- return NULL;
+ if (radeon_bo_is_busy((struct pb_buffer*)bo,
+ RADEON_USAGE_READWRITE)) {
+ return NULL;
+ }
}
} else {
if (!(flags & PB_USAGE_CPU_WRITE)) {
@@ -191,14 +236,9 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf,
* Only check whether the buffer is being used for write. */
if (radeon_bo_is_referenced_by_cs_for_write(cs, bo)) {
cs->flush_cs(cs->flush_data, 0);
- radeon_bo_wait((struct pb_buffer*)bo);
- } else if (bo->busy_for_write) {
- /* Update the busy_for_write field (done by radeon_bo_is_busy)
- * and wait if needed. */
- if (radeon_bo_is_busy((struct pb_buffer*)bo)) {
- radeon_bo_wait((struct pb_buffer*)bo);
- }
}
+ radeon_bo_wait((struct pb_buffer*)bo,
+ RADEON_USAGE_WRITE);
} else {
/* Mapping for write. */
if (radeon_bo_is_referenced_by_cs(cs, bo)) {
@@ -209,7 +249,7 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf,
radeon_drm_cs_sync_flush(cs);
}
- radeon_bo_wait((struct pb_buffer*)bo);
+ radeon_bo_wait((struct pb_buffer*)bo, RADEON_USAGE_READWRITE);
}
}
}
@@ -238,7 +278,7 @@ static void *radeon_bo_map_internal(struct pb_buffer *_buf,
return NULL;
}
- ptr = mmap(0, args.size, PROT_READ|PROT_WRITE, MAP_SHARED,
+ ptr = os_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);
@@ -345,7 +385,7 @@ static boolean radeon_bomgr_is_buffer_busy(struct pb_manager *_mgr,
return TRUE;
}
- if (radeon_bo_is_busy((struct pb_buffer*)bo)) {
+ if (radeon_bo_is_busy((struct pb_buffer*)bo, RADEON_USAGE_READWRITE)) {
return TRUE;
}
@@ -395,16 +435,14 @@ static void *radeon_bo_map(struct pb_buffer *buf,
struct radeon_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);
+ return pb_map(buf, get_pb_usage_from_transfer_flags(usage), cs);
}
static void radeon_bo_get_tiling(struct pb_buffer *_buf,
enum radeon_bo_layout *microtiled,
enum radeon_bo_layout *macrotiled)
{
- struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
+ struct radeon_bo *bo = get_radeon_bo(_buf);
struct drm_radeon_gem_set_tiling args = {};
args.handle = bo->handle;
@@ -429,7 +467,7 @@ static void radeon_bo_set_tiling(struct pb_buffer *_buf,
enum radeon_bo_layout macrotiled,
uint32_t pitch)
{
- struct radeon_bo *bo = get_radeon_bo(pb_buffer(_buf));
+ struct radeon_bo *bo = get_radeon_bo(_buf);
struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
struct drm_radeon_gem_set_tiling args = {};
@@ -464,12 +502,10 @@ static struct radeon_winsys_cs_handle *radeon_drm_get_cs_handle(
struct pb_buffer *_buf)
{
/* return radeon_bo. */
- return (struct radeon_winsys_cs_handle*)
- get_radeon_bo(pb_buffer(_buf));
+ return (struct radeon_winsys_cs_handle*)get_radeon_bo(_buf);
}
-static unsigned get_pb_usage_from_create_flags(unsigned bind, unsigned usage,
- enum radeon_bo_domain domain)
+static unsigned get_pb_usage_from_create_flags(enum radeon_bo_domain domain)
{
unsigned res = 0;
@@ -487,7 +523,6 @@ radeon_winsys_bo_create(struct radeon_winsys *rws,
unsigned size,
unsigned alignment,
unsigned bind,
- unsigned usage,
enum radeon_bo_domain domain)
{
struct radeon_drm_winsys *ws = radeon_drm_winsys(rws);
@@ -497,10 +532,11 @@ radeon_winsys_bo_create(struct radeon_winsys *rws,
memset(&desc, 0, sizeof(desc));
desc.alignment = alignment;
- desc.usage = get_pb_usage_from_create_flags(bind, usage, domain);
+ desc.usage = get_pb_usage_from_create_flags(domain);
/* Assign a buffer manager. */
- if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER))
+ if (bind & (PIPE_BIND_VERTEX_BUFFER | PIPE_BIND_INDEX_BUFFER |
+ PIPE_BIND_CONSTANT_BUFFER))
provider = ws->cman;
else
provider = ws->kman;
@@ -587,7 +623,7 @@ static boolean radeon_winsys_bo_get_handle(struct pb_buffer *buffer,
struct winsys_handle *whandle)
{
struct drm_gem_flink flink = {};
- struct radeon_bo *bo = get_radeon_bo(pb_buffer(buffer));
+ struct radeon_bo *bo = get_radeon_bo(buffer);
if (whandle->type == DRM_API_HANDLE_TYPE_SHARED) {
if (!bo->flinked) {
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_bo.h b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
index b94881bc4ce..047ea6b1cf2 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_bo.h
@@ -60,13 +60,6 @@ struct radeon_bo {
* thread, is this bo referenced in? */
int num_active_ioctls;
- /* Whether the buffer has been relocated for write and is busy since then.
- * This field is updated in:
- * - radeon_drm_cs_flush (to TRUE if it's relocated for write)
- * - radeon_bo_is_busy (to FALSE if it's not busy)
- * - radeon_bo_wait (to FALSE) */
- boolean busy_for_write;
-
boolean flinked;
uint32_t flink;
};
@@ -80,10 +73,4 @@ void radeon_bo_reference(struct radeon_bo **dst, struct radeon_bo *src)
pb_reference((struct pb_buffer**)dst, (struct pb_buffer*)src);
}
-static INLINE struct pb_buffer *
-pb_buffer(struct pb_buffer *buffer)
-{
- return (struct pb_buffer *)buffer;
-}
-
#endif
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
index 0139de1973a..c309354785a 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.c
@@ -115,6 +115,7 @@ static void radeon_cs_context_cleanup(struct radeon_cs_context *csc)
}
csc->crelocs = 0;
+ csc->validated_crelocs = 0;
csc->chunks[0].length_dw = 0;
csc->chunks[1].length_dw = 0;
csc->used_gart = 0;
@@ -218,11 +219,11 @@ int radeon_get_reloc(struct radeon_cs_context *csc, struct radeon_bo *bo)
return -1;
}
-static void radeon_add_reloc(struct radeon_cs_context *csc,
- struct radeon_bo *bo,
- enum radeon_bo_domain rd,
- enum radeon_bo_domain wd,
- enum radeon_bo_domain *added_domains)
+static unsigned radeon_add_reloc(struct radeon_cs_context *csc,
+ struct radeon_bo *bo,
+ enum radeon_bo_domain rd,
+ enum radeon_bo_domain wd,
+ enum radeon_bo_domain *added_domains)
{
struct drm_radeon_cs_reloc *reloc;
unsigned i;
@@ -232,7 +233,7 @@ static void radeon_add_reloc(struct radeon_cs_context *csc,
reloc = csc->relocs_hashlist[hash];
if (reloc->handle == bo->handle) {
update_domains(reloc, rd, wd, added_domains);
- return;
+ return csc->reloc_indices_hashlist[hash];
}
/* Hash collision, look for the BO in the list of relocs linearly. */
@@ -245,7 +246,7 @@ static void radeon_add_reloc(struct radeon_cs_context *csc,
csc->relocs_hashlist[hash] = reloc;
csc->reloc_indices_hashlist[hash] = i;
/*printf("write_reloc collision, hash: %i, handle: %i\n", hash, bo->handle);*/
- return;
+ return i;
}
}
}
@@ -279,37 +280,64 @@ static void radeon_add_reloc(struct radeon_cs_context *csc,
csc->reloc_indices_hashlist[hash] = csc->crelocs;
csc->chunks[1].length_dw += RELOC_DWORDS;
- csc->crelocs++;
*added_domains = rd | wd;
+ return csc->crelocs++;
}
-static void radeon_drm_cs_add_reloc(struct radeon_winsys_cs *rcs,
- struct radeon_winsys_cs_handle *buf,
- enum radeon_bo_domain rd,
- enum radeon_bo_domain wd)
+static unsigned radeon_drm_cs_add_reloc(struct radeon_winsys_cs *rcs,
+ struct radeon_winsys_cs_handle *buf,
+ enum radeon_bo_domain rd,
+ enum radeon_bo_domain wd)
{
struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
struct radeon_bo *bo = (struct radeon_bo*)buf;
enum radeon_bo_domain added_domains;
- radeon_add_reloc(cs->csc, bo, rd, wd, &added_domains);
-
- if (!added_domains)
- return;
+ unsigned index = radeon_add_reloc(cs->csc, bo, rd, wd, &added_domains);
if (added_domains & RADEON_DOMAIN_GTT)
cs->csc->used_gart += bo->size;
if (added_domains & RADEON_DOMAIN_VRAM)
cs->csc->used_vram += bo->size;
+
+ return index;
}
static boolean radeon_drm_cs_validate(struct radeon_winsys_cs *rcs)
{
struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
+ boolean status =
+ cs->csc->used_gart < cs->ws->info.gart_size * 0.8 &&
+ cs->csc->used_vram < cs->ws->info.vram_size * 0.8;
+
+ if (status) {
+ cs->csc->validated_crelocs = cs->csc->crelocs;
+ } else {
+ /* Remove lately-added relocations. The validation failed with them
+ * and the CS is about to be flushed because of that. Keep only
+ * the already-validated relocations. */
+ unsigned i;
+
+ for (i = cs->csc->validated_crelocs; i < cs->csc->crelocs; i++) {
+ p_atomic_dec(&cs->csc->relocs_bo[i]->num_cs_references);
+ radeon_bo_reference(&cs->csc->relocs_bo[i], NULL);
+ }
+ cs->csc->crelocs = cs->csc->validated_crelocs;
+
+ /* Flush if there are any relocs. Clean up otherwise. */
+ if (cs->csc->crelocs) {
+ cs->flush_cs(cs->flush_data, RADEON_FLUSH_ASYNC);
+ } else {
+ radeon_cs_context_cleanup(cs->csc);
- return cs->csc->used_gart < cs->ws->gart_size * 0.8 &&
- cs->csc->used_vram < cs->ws->vram_size * 0.8;
+ assert(cs->base.cdw == 0);
+ if (cs->base.cdw != 0) {
+ fprintf(stderr, "radeon: Unexpected error in %s.\n", __func__);
+ }
+ }
+ }
+ return status;
}
static void radeon_drm_cs_write_reloc(struct radeon_winsys_cs *rcs,
@@ -351,6 +379,8 @@ static PIPE_THREAD_ROUTINE(radeon_drm_cs_emit_ioctl, param)
for (i = 0; i < csc->crelocs; i++)
p_atomic_dec(&csc->relocs_bo[i]->num_active_ioctls);
+
+ radeon_cs_context_cleanup(csc);
return NULL;
}
@@ -381,11 +411,6 @@ static void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs, unsigned flags)
for (i = 0; i < crelocs; i++) {
/* Update the number of active asynchronous CS ioctls for the buffer. */
p_atomic_inc(&cs->csc->relocs_bo[i]->num_active_ioctls);
-
- /* Update whether the buffer is busy for write. */
- if (cs->csc->relocs[i].write_domain) {
- cs->csc->relocs_bo[i]->busy_for_write = TRUE;
- }
}
if (cs->ws->num_cpus > 1 && debug_get_option_thread() &&
@@ -395,6 +420,8 @@ static void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs, unsigned flags)
} else {
radeon_drm_cs_emit_ioctl(cs->csc);
}
+ } else {
+ radeon_cs_context_cleanup(cs->csc);
}
/* Flip command streams. */
@@ -403,8 +430,6 @@ static void radeon_drm_cs_flush(struct radeon_winsys_cs *rcs, unsigned flags)
cs->cst = tmp;
/* Prepare a new CS. */
- radeon_cs_context_cleanup(cs->csc);
-
cs->base.buf = cs->csc->buf;
cs->base.cdw = 0;
}
@@ -447,6 +472,6 @@ void radeon_drm_cs_init_functions(struct radeon_drm_winsys *ws)
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_flush;
- ws->base.cs_set_flush = radeon_drm_cs_set_flush;
+ ws->base.cs_set_flush_callback = 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 339beedc6ab..fe285326884 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_cs.h
@@ -41,6 +41,7 @@ struct radeon_cs_context {
/* Relocs. */
unsigned nrelocs;
unsigned crelocs;
+ unsigned validated_crelocs;
struct radeon_bo **relocs_bo;
struct drm_radeon_cs_reloc *relocs;
@@ -88,8 +89,9 @@ 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);
+ int num_refs = bo->num_cs_references;
+ return num_refs == bo->rws->num_cs ||
+ (num_refs && radeon_get_reloc(cs->csc, bo) != -1);
}
static INLINE boolean
@@ -111,7 +113,7 @@ radeon_bo_is_referenced_by_cs_for_write(struct radeon_drm_cs *cs,
static INLINE boolean
radeon_bo_is_referenced_by_any_cs(struct radeon_bo *bo)
{
- return bo->num_cs_references;
+ return bo->num_cs_references != 0;
}
void radeon_drm_cs_sync_flush(struct radeon_drm_cs *cs);
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
index 0474b381ade..e234321d934 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.c
@@ -41,13 +41,34 @@
#include <xf86drm.h>
#include <stdio.h>
+#ifndef RADEON_INFO_TILING_CONFIG
+#define RADEON_INFO_TILING_CONFIG 6
+#endif
+
#ifndef RADEON_INFO_WANT_HYPERZ
#define RADEON_INFO_WANT_HYPERZ 7
#endif
+
#ifndef RADEON_INFO_WANT_CMASK
#define RADEON_INFO_WANT_CMASK 8
#endif
+#ifndef RADEON_INFO_CLOCK_CRYSTAL_FREQ
+#define RADEON_INFO_CLOCK_CRYSTAL_FREQ 9
+#endif
+
+#ifndef RADEON_INFO_NUM_BACKENDS
+#define RADEON_INFO_NUM_BACKENDS 0xa
+#endif
+
+#ifndef RADEON_INFO_NUM_TILE_PIPES
+#define RADEON_INFO_NUM_TILE_PIPES 0xb
+#endif
+
+#ifndef RADEON_INFO_BACKEND_MAP
+#define RADEON_INFO_BACKEND_MAP 0xd
+#endif
+
/* Enable/disable feature access for one command stream.
* If enable == TRUE, return TRUE on success.
* Otherwise, return FALSE.
@@ -103,17 +124,31 @@ static boolean radeon_set_fd_access(struct radeon_drm_cs *applier,
return FALSE;
}
+static boolean radeon_get_drm_value(int fd, unsigned request,
+ const char *errname, uint32_t *out)
+{
+ struct drm_radeon_info info = {0};
+ int retval;
+
+ info.value = (unsigned long)out;
+ info.request = request;
+
+ retval = drmCommandWriteRead(fd, DRM_RADEON_INFO, &info, sizeof(info));
+ if (retval && errname) {
+ fprintf(stderr, "radeon: Failed to get %s, error number %d\n",
+ errname, retval);
+ return FALSE;
+ }
+ return TRUE;
+}
+
/* Helper function to do the ioctls needed for setup and init. */
-static void do_ioctls(struct radeon_drm_winsys *winsys)
+static boolean do_winsys_init(struct radeon_drm_winsys *ws)
{
struct drm_radeon_gem_info gem_info = {0};
- struct drm_radeon_info info = {0};
- int target = 0;
int retval;
drmVersionPtr version;
- info.value = (unsigned long)&target;
-
/* We do things in a specific order here.
*
* DRM version first. We need to be sure we're running on a KMS chipset.
@@ -123,71 +158,108 @@ static void do_ioctls(struct radeon_drm_winsys *winsys)
* for all Radeons. If this fails, we probably got handed an FD for some
* non-Radeon card.
*
+ * The GEM info is actually bogus on the kernel side, as well as our side
+ * (see radeon_gem_info_ioctl in radeon_gem.c) but that's alright because
+ * we don't actually use the info for anything yet.
+ *
* The GB and Z pipe requests should always succeed, but they might not
* return sensical values for all chipsets, but that's alright because
* the pipe drivers already know that.
- *
- * The GEM info is actually bogus on the kernel side, as well as our side
- * (see radeon_gem_info_ioctl in radeon_gem.c) but that's alright because
- * we don't actually use the info for anything yet. */
+ */
- version = drmGetVersion(winsys->fd);
+ /* Get DRM version. */
+ version = drmGetVersion(ws->fd);
if (version->version_major != 2 ||
version->version_minor < 3) {
fprintf(stderr, "%s: DRM version is %d.%d.%d but this driver is "
- "only compatible with 2.3.x (kernel 2.6.34) and later.\n",
+ "only compatible with 2.3.x (kernel 2.6.34) or later.\n",
__FUNCTION__,
version->version_major,
version->version_minor,
version->version_patchlevel);
drmFreeVersion(version);
- exit(1);
+ return FALSE;
}
- winsys->drm_major = version->version_major;
- winsys->drm_minor = version->version_minor;
- winsys->drm_patchlevel = version->version_patchlevel;
+ ws->info.drm_major = version->version_major;
+ ws->info.drm_minor = version->version_minor;
+ ws->info.drm_patchlevel = version->version_patchlevel;
+ drmFreeVersion(version);
- info.request = RADEON_INFO_DEVICE_ID;
- retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_INFO, &info, sizeof(info));
- if (retval) {
- fprintf(stderr, "%s: Failed to get PCI ID, "
- "error number %d\n", __FUNCTION__, retval);
- exit(1);
- }
- winsys->pci_id = target;
+ /* Get PCI ID. */
+ if (!radeon_get_drm_value(ws->fd, RADEON_INFO_DEVICE_ID, "PCI ID",
+ &ws->info.pci_id))
+ return FALSE;
- info.request = RADEON_INFO_NUM_GB_PIPES;
- retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_INFO, &info, sizeof(info));
- if (retval) {
- fprintf(stderr, "%s: Failed to get GB pipe count, "
- "error number %d\n", __FUNCTION__, retval);
- exit(1);
- }
- winsys->gb_pipes = target;
+ /* Check PCI ID. */
+ switch (ws->info.pci_id) {
+#define CHIPSET(pci_id, name, family) case pci_id:
+#include "pci_ids/r300_pci_ids.h"
+#undef CHIPSET
+ ws->gen = R300;
+ break;
- info.request = RADEON_INFO_NUM_Z_PIPES;
- retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_INFO, &info, sizeof(info));
- if (retval) {
- fprintf(stderr, "%s: Failed to get Z pipe count, "
- "error number %d\n", __FUNCTION__, retval);
- exit(1);
+#define CHIPSET(pci_id, name, family) case pci_id:
+#include "pci_ids/r600_pci_ids.h"
+#undef CHIPSET
+ ws->gen = R600;
+ break;
+
+ default:
+ fprintf(stderr, "radeon: Invalid PCI ID.\n");
+ return FALSE;
}
- winsys->z_pipes = target;
- retval = drmCommandWriteRead(winsys->fd, DRM_RADEON_GEM_INFO,
+ /* Get GEM info. */
+ retval = drmCommandWriteRead(ws->fd, DRM_RADEON_GEM_INFO,
&gem_info, sizeof(gem_info));
if (retval) {
- fprintf(stderr, "%s: Failed to get MM info, error number %d\n",
- __FUNCTION__, retval);
- exit(1);
+ fprintf(stderr, "radeon: Failed to get MM info, error number %d\n",
+ retval);
+ return FALSE;
}
- winsys->gart_size = gem_info.gart_size;
- winsys->vram_size = gem_info.vram_size;
+ ws->info.gart_size = gem_info.gart_size;
+ ws->info.vram_size = gem_info.vram_size;
- drmFreeVersion(version);
+ ws->num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+
+ /* Generation-specific queries. */
+ if (ws->gen == R300) {
+ if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_GB_PIPES,
+ "GB pipe count",
+ &ws->info.r300_num_gb_pipes))
+ return FALSE;
- winsys->num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
+ if (!radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_Z_PIPES,
+ "Z pipe count",
+ &ws->info.r300_num_z_pipes))
+ return FALSE;
+ }
+ else if (ws->gen == R600) {
+ if (ws->info.drm_minor >= 9 &&
+ !radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_BACKENDS,
+ "num backends",
+ &ws->info.r600_num_backends))
+ return FALSE;
+
+ /* get the GPU counter frequency, failure is not fatal */
+ radeon_get_drm_value(ws->fd, RADEON_INFO_CLOCK_CRYSTAL_FREQ, NULL,
+ &ws->info.r600_clock_crystal_freq);
+
+ radeon_get_drm_value(ws->fd, RADEON_INFO_TILING_CONFIG, NULL,
+ &ws->info.r600_tiling_config);
+
+ if (ws->info.drm_minor >= 11) {
+ radeon_get_drm_value(ws->fd, RADEON_INFO_NUM_TILE_PIPES, NULL,
+ &ws->info.r600_num_tile_pipes);
+
+ if (radeon_get_drm_value(ws->fd, RADEON_INFO_BACKEND_MAP, NULL,
+ &ws->info.r600_backend_map))
+ ws->info.r600_backend_map_valid = TRUE;
+ }
+ }
+
+ return TRUE;
}
static void radeon_winsys_destroy(struct radeon_winsys *rws)
@@ -202,34 +274,10 @@ static void radeon_winsys_destroy(struct radeon_winsys *rws)
FREE(rws);
}
-static uint32_t radeon_get_value(struct radeon_winsys *rws,
- enum radeon_value_id id)
+static void radeon_query_info(struct radeon_winsys *rws,
+ struct radeon_info *info)
{
- struct radeon_drm_winsys *ws = (struct radeon_drm_winsys *)rws;
-
- switch(id) {
- case RADEON_VID_PCI_ID:
- return ws->pci_id;
- case RADEON_VID_R300_GB_PIPES:
- return ws->gb_pipes;
- case RADEON_VID_R300_Z_PIPES:
- return ws->z_pipes;
- case RADEON_VID_GART_SIZE:
- return ws->gart_size;
- case RADEON_VID_VRAM_SIZE:
- return ws->vram_size;
- case RADEON_VID_DRM_MAJOR:
- return ws->drm_major;
- case RADEON_VID_DRM_MINOR:
- return ws->drm_minor;
- case RADEON_VID_DRM_PATCHLEVEL:
- return ws->drm_patchlevel;
- case RADEON_VID_DRM_2_6_0:
- return ws->drm_major*100 + ws->drm_minor >= 206;
- case RADEON_VID_DRM_2_8_0:
- return ws->drm_major*100 + ws->drm_minor >= 208;
- }
- return 0;
+ *info = ((struct radeon_drm_winsys *)rws)->info;
}
static boolean radeon_cs_request_feature(struct radeon_winsys_cs *rcs,
@@ -239,7 +287,7 @@ static boolean radeon_cs_request_feature(struct radeon_winsys_cs *rcs,
struct radeon_drm_cs *cs = radeon_drm_cs(rcs);
switch (fid) {
- case RADEON_FID_HYPERZ_RAM_ACCESS:
+ case RADEON_FID_R300_HYPERZ_ACCESS:
if (debug_get_bool_option("RADEON_HYPERZ", FALSE)) {
return radeon_set_fd_access(cs, &cs->ws->hyperz_owner,
&cs->ws->hyperz_owner_mutex,
@@ -248,7 +296,7 @@ static boolean radeon_cs_request_feature(struct radeon_winsys_cs *rcs,
return FALSE;
}
- case RADEON_FID_CMASK_RAM_ACCESS:
+ case RADEON_FID_R300_CMASK_ACCESS:
if (debug_get_bool_option("RADEON_CMASK", FALSE)) {
return radeon_set_fd_access(cs, &cs->ws->cmask_owner,
&cs->ws->cmask_owner_mutex,
@@ -268,16 +316,9 @@ struct radeon_winsys *radeon_drm_winsys_create(int fd)
}
ws->fd = fd;
- do_ioctls(ws);
- switch (ws->pci_id) {
-#define CHIPSET(pci_id, name, family) case pci_id:
-#include "pci_ids/r300_pci_ids.h"
-#undef CHIPSET
- break;
- default:
- goto fail;
- }
+ if (!do_winsys_init(ws))
+ goto fail;
/* Create managers. */
ws->kman = radeon_bomgr_create(ws);
@@ -289,7 +330,7 @@ struct radeon_winsys *radeon_drm_winsys_create(int fd)
/* Set functions. */
ws->base.destroy = radeon_winsys_destroy;
- ws->base.get_value = radeon_get_value;
+ ws->base.query_info = radeon_query_info;
ws->base.cs_request_feature = radeon_cs_request_feature;
radeon_bomgr_init_functions(ws);
diff --git a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h
index d5186bc4d17..69216448496 100644
--- a/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h
+++ b/src/gallium/winsys/radeon/drm/radeon_drm_winsys.h
@@ -31,29 +31,27 @@
#define RADEON_DRM_WINSYS_H
#include "radeon_winsys.h"
-
#include "os/os_thread.h"
+enum radeon_generation {
+ R300,
+ R600
+};
+
struct radeon_drm_winsys {
struct radeon_winsys base;
int fd; /* DRM file descriptor */
int num_cs; /* The number of command streams created. */
+ enum radeon_generation gen;
+ struct radeon_info info;
+
struct pb_manager *kman;
struct pb_manager *cman;
- uint32_t pci_id; /* PCI ID */
- uint32_t gb_pipes; /* GB pipe count */
- uint32_t z_pipes; /* Z pipe count (rv530 only) */
- uint32_t gart_size; /* GART size. */
- uint32_t vram_size; /* VRAM size. */
uint32_t num_cpus; /* Number of CPUs. */
- unsigned drm_major;
- unsigned drm_minor;
- unsigned drm_patchlevel;
-
struct radeon_drm_cs *hyperz_owner;
pipe_mutex hyperz_owner_mutex;
struct radeon_drm_cs *cmask_owner;
diff --git a/src/gallium/winsys/radeon/drm/radeon_winsys.h b/src/gallium/winsys/radeon/drm/radeon_winsys.h
index 3a64e4abc35..90583e3ab8c 100644
--- a/src/gallium/winsys/radeon/drm/radeon_winsys.h
+++ b/src/gallium/winsys/radeon/drm/radeon_winsys.h
@@ -26,6 +26,20 @@
/* The public winsys interface header for the radeon driver. */
+/* R300 features in DRM.
+ *
+ * 2.6.0:
+ * - Hyper-Z
+ * - GB_Z_PEQ_CONFIG on rv350->r4xx
+ * - R500 FG_ALPHA_VALUE
+ *
+ * 2.8.0:
+ * - R500 US_FORMAT regs
+ * - R500 ARGB2101010 colorbuffer
+ * - CMask and AA regs
+ * - R16F/RG16F
+ */
+
#include "pipebuffer/pb_bufmgr.h"
#include "pipe/p_defines.h"
#include "pipe/p_state.h"
@@ -47,6 +61,12 @@ enum radeon_bo_domain { /* bitfield */
RADEON_DOMAIN_VRAM = 4
};
+enum radeon_bo_usage { /* bitfield */
+ RADEON_USAGE_READ = 2,
+ RADEON_USAGE_WRITE = 4,
+ RADEON_USAGE_READWRITE = RADEON_USAGE_READ | RADEON_USAGE_WRITE
+};
+
struct winsys_handle;
struct radeon_winsys_cs_handle; /* for write_reloc etc. */
@@ -55,43 +75,29 @@ struct radeon_winsys_cs {
uint32_t *buf; /* The command buffer. */
};
-enum radeon_value_id {
- RADEON_VID_PCI_ID,
- RADEON_VID_R300_GB_PIPES,
- RADEON_VID_R300_Z_PIPES,
- RADEON_VID_GART_SIZE,
- RADEON_VID_VRAM_SIZE,
- RADEON_VID_DRM_MAJOR,
- RADEON_VID_DRM_MINOR,
- RADEON_VID_DRM_PATCHLEVEL,
-
- /* These should probably go away: */
-
- /* R300 features:
- * - Hyper-Z
- * - GB_Z_PEQ_CONFIG on rv350->r4xx
- * - R500 FG_ALPHA_VALUE
- *
- * R600 features:
- * - TBD
- */
- RADEON_VID_DRM_2_6_0,
+struct radeon_info {
+ uint32_t pci_id;
+ uint32_t gart_size;
+ uint32_t vram_size;
- /* R300 features:
- * - R500 US_FORMAT regs
- * - R500 ARGB2101010 colorbuffer
- * - CMask and AA regs
- * - R16F/RG16F
- *
- * R600 features:
- * - TBD
- */
- RADEON_VID_DRM_2_8_0,
+ uint32_t drm_major; /* version */
+ uint32_t drm_minor;
+ uint32_t drm_patchlevel;
+
+ uint32_t r300_num_gb_pipes;
+ uint32_t r300_num_z_pipes;
+
+ uint32_t r600_num_backends;
+ uint32_t r600_clock_crystal_freq;
+ uint32_t r600_tiling_config;
+ uint32_t r600_num_tile_pipes;
+ uint32_t r600_backend_map;
+ boolean r600_backend_map_valid;
};
enum radeon_feature_id {
- RADEON_FID_HYPERZ_RAM_ACCESS, /* ZMask + HiZ */
- RADEON_FID_CMASK_RAM_ACCESS,
+ RADEON_FID_R300_HYPERZ_ACCESS, /* ZMask + HiZ */
+ RADEON_FID_R300_CMASK_ACCESS,
};
struct radeon_winsys {
@@ -103,13 +109,13 @@ struct radeon_winsys {
void (*destroy)(struct radeon_winsys *ws);
/**
- * Query a system value from a winsys.
+ * Query an info structure from winsys.
*
* \param ws The winsys this function is called from.
- * \param vid One of the RADEON_VID_* enums.
+ * \param info Return structure
*/
- uint32_t (*get_value)(struct radeon_winsys *ws,
- enum radeon_value_id vid);
+ void (*query_info)(struct radeon_winsys *ws,
+ struct radeon_info *info);
/**************************************************************************
* Buffer management. Buffer attributes are mostly fixed over its lifetime.
@@ -126,7 +132,6 @@ struct radeon_winsys {
* \param size The size to allocate.
* \param alignment An alignment of the buffer in memory.
* \param bind A bitmask of the PIPE_BIND_* flags.
- * \param usage A bitmask of the PIPE_USAGE_* flags.
* \param domain A bitmask of the RADEON_DOMAIN_* flags.
* \return The created buffer object.
*/
@@ -134,7 +139,6 @@ struct radeon_winsys {
unsigned size,
unsigned alignment,
unsigned bind,
- unsigned usage,
enum radeon_bo_domain domain);
struct radeon_winsys_cs_handle *(*buffer_get_cs_handle)(
@@ -164,8 +168,10 @@ struct radeon_winsys {
* Return TRUE if a buffer object is being used by the GPU.
*
* \param buf A winsys buffer object.
+ * \param usage Only check whether the buffer is busy for the given usage.
*/
- boolean (*buffer_is_busy)(struct pb_buffer *buf);
+ boolean (*buffer_is_busy)(struct pb_buffer *buf,
+ enum radeon_bo_usage usage);
/**
* Wait for a buffer object until it is not used by a GPU. This is
@@ -173,8 +179,10 @@ struct radeon_winsys {
* and synchronizing to the fence.
*
* \param buf A winsys buffer object to wait for.
+ * \param usage Only wait until the buffer is idle for the given usage,
+ * but may still be busy for some other usage.
*/
- void (*buffer_wait)(struct pb_buffer *buf);
+ void (*buffer_wait)(struct pb_buffer *buf, enum radeon_bo_usage usage);
/**
* Return tiling flags describing a memory layout of a buffer object.
@@ -263,15 +271,18 @@ struct radeon_winsys {
* \param buf A winsys buffer to validate.
* \param rd A read domain containing a bitmask of the RADEON_DOMAIN_* flags.
* \param wd A write domain containing a bitmask of the RADEON_DOMAIN_* flags.
+ * \return Relocation index.
*/
- void (*cs_add_reloc)(struct radeon_winsys_cs *cs,
- struct radeon_winsys_cs_handle *buf,
- enum radeon_bo_domain rd,
- enum radeon_bo_domain wd);
+ unsigned (*cs_add_reloc)(struct radeon_winsys_cs *cs,
+ struct radeon_winsys_cs_handle *buf,
+ enum radeon_bo_domain rd,
+ enum radeon_bo_domain wd);
/**
* Return TRUE if there is enough memory in VRAM and GTT for the relocs
- * added so far.
+ * added so far. If the validation fails, all the relocations which have
+ * been added since the last call of cs_validate will be removed and
+ * the CS will be flushed (provided there are still any relocations).
*
* \param cs A command stream to validate.
*/
@@ -304,9 +315,9 @@ struct radeon_winsys {
* \param flush A flush callback function associated with the command stream.
* \param user A user pointer that will be passed to the flush callback.
*/
- void (*cs_set_flush)(struct radeon_winsys_cs *cs,
- void (*flush)(void *ctx, unsigned flags),
- void *user);
+ void (*cs_set_flush_callback)(struct radeon_winsys_cs *cs,
+ void (*flush)(void *ctx, unsigned flags),
+ void *ctx);
/**
* Return TRUE if a buffer is referenced by a command stream.
@@ -321,7 +332,8 @@ struct radeon_winsys {
* Request access to a feature for a command stream.
*
* \param cs A command stream.
- * \param fid A winsys buffer.
+ * \param fid Feature ID, one of RADEON_FID_*
+ * \param enable Whether to enable or disable the feature.
*/
boolean (*cs_request_feature)(struct radeon_winsys_cs *cs,
enum radeon_feature_id fid,