summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPauli Nieminen <suokkos@gmail.com>2009-08-26 03:09:55 +0300
committerPauli Nieminen <suokkos@gmail.com>2009-08-29 09:28:50 +0300
commit2e1e3f184239ab8adb53421f1eb5881de1b5c420 (patch)
treea0d6652036a42b2c97b068152583fdb8d0bb4b6c
parent73b59c894380995a2889b98e79acadd2da0bb237 (diff)
libdrm_radeon: Optimize bo relocation.relocation_rewrite
Instead of looping over all relocations store pointer in bo. This allows direct reference from passed bot to find the relocation information that we have to update. Signed-off-by: Pauli Nieminen <suokkos@gmail.com>
-rw-r--r--libdrm/radeon/radeon_bo.h1
-rw-r--r--libdrm/radeon/radeon_bo_gem.c2
-rw-r--r--libdrm/radeon/radeon_cs_gem.c71
3 files changed, 41 insertions, 33 deletions
diff --git a/libdrm/radeon/radeon_bo.h b/libdrm/radeon/radeon_bo.h
index 1e2e6c20..156a41a7 100644
--- a/libdrm/radeon/radeon_bo.h
+++ b/libdrm/radeon/radeon_bo.h
@@ -53,6 +53,7 @@ struct radeon_bo {
void *ptr;
struct radeon_bo_manager *bom;
uint32_t space_accounted;
+ uint32_t relocation;
};
/* bo functions */
diff --git a/libdrm/radeon/radeon_bo_gem.c b/libdrm/radeon/radeon_bo_gem.c
index 76d80e7e..49d55318 100644
--- a/libdrm/radeon/radeon_bo_gem.c
+++ b/libdrm/radeon/radeon_bo_gem.c
@@ -80,6 +80,8 @@ static struct radeon_bo *bo_open(struct radeon_bo_manager *bom,
bo->base.domains = domains;
bo->base.flags = flags;
bo->base.ptr = NULL;
+ bo->base.space_accounted = 0;
+ bo->base.relocation = 0;
bo->map_count = 0;
if (handle) {
struct drm_gem_open open_arg;
diff --git a/libdrm/radeon/radeon_cs_gem.c b/libdrm/radeon/radeon_cs_gem.c
index a0db53bb..2c889a16 100644
--- a/libdrm/radeon/radeon_cs_gem.c
+++ b/libdrm/radeon/radeon_cs_gem.c
@@ -116,7 +116,6 @@ static int cs_gem_write_reloc(struct radeon_cs *cs,
struct cs_gem *csg = (struct cs_gem*)cs;
struct cs_reloc_gem *reloc;
uint32_t idx;
- unsigned i;
assert(bo->space_accounted);
@@ -133,40 +132,43 @@ static int cs_gem_write_reloc(struct radeon_cs *cs,
if (write_domain == RADEON_GEM_DOMAIN_CPU) {
return -EINVAL;
}
- /* check if bo is already referenced */
- for(i = 0; i < cs->crelocs; i++) {
- idx = i * RELOC_SIZE;
+ /* check if bo is already referenced
+ * assumbtion is that we use only one cs per context so we store relocation
+ * pointer in bo for fast reference checking. */
+ if (bo->relocation) {
+ /* one has been added to relocation calue because zero is reserved */
+ idx = bo->relocation - 1;
reloc = (struct cs_reloc_gem*)&csg->relocs[idx];
- if (reloc->handle == bo->handle) {
- /* Check domains must be in read or write. As we check already
- * checked that in argument one of the read or write domain was
- * set we only need to check that if previous reloc as the read
- * domain set then the read_domain should also be set for this
- * new relocation.
- */
- /* the DDX expects to read and write from same pixmap */
- if (write_domain && (reloc->read_domain & write_domain)) {
- reloc->read_domain = 0;
- reloc->write_domain = write_domain;
- } else if (read_domain & reloc->write_domain) {
- reloc->read_domain = 0;
- } else {
- if (write_domain != reloc->write_domain)
- return -EINVAL;
- if (read_domain != reloc->read_domain)
- return -EINVAL;
- }
-
- reloc->read_domain |= read_domain;
- reloc->write_domain |= write_domain;
- /* update flags */
- reloc->flags |= (flags & reloc->flags);
- /* write relocation packet */
- radeon_cs_write_dword(cs, 0xc0001000);
- radeon_cs_write_dword(cs, idx);
- return 0;
- }
+ assert(reloc->handle == bo->handle);
+ /* Check domains must be in read or write. As we check already
+ * checked that in argument one of the read or write domain was
+ * set we only need to check that if previous reloc as the read
+ * domain set then the read_domain should also be set for this
+ * new relocation.
+ */
+ /* the DDX expects to read and write from same pixmap */
+ if (write_domain && (reloc->read_domain & write_domain)) {
+ reloc->read_domain = 0;
+ reloc->write_domain = write_domain;
+ } else if (read_domain & reloc->write_domain) {
+ reloc->read_domain = 0;
+ } else {
+ if (write_domain != reloc->write_domain)
+ return -EINVAL;
+ if (read_domain != reloc->read_domain)
+ return -EINVAL;
+ }
+
+ reloc->read_domain |= read_domain;
+ reloc->write_domain |= write_domain;
+ /* update flags */
+ reloc->flags |= (flags & reloc->flags);
+ /* write relocation packet */
+ radeon_cs_write_dword(cs, 0xc0001000);
+ radeon_cs_write_dword(cs, idx);
+ return 0;
}
+
/* new relocation */
if (csg->base.crelocs >= csg->nrelocs) {
/* allocate more memory (TODO: should use a slab allocatore maybe) */
@@ -195,6 +197,8 @@ static int cs_gem_write_reloc(struct radeon_cs *cs,
reloc->flags = flags;
csg->chunks[1].length_dw += RELOC_SIZE;
radeon_bo_ref(bo);
+ /* zero is reserved for not used so have to add one to idx */
+ bo->relocation = idx + 1;
cs->relocs_total_size += bo->size;
radeon_cs_write_dword(cs, 0xc0001000);
radeon_cs_write_dword(cs, idx);
@@ -279,6 +283,7 @@ static int cs_gem_emit(struct radeon_cs *cs)
&csg->cs, sizeof(struct drm_radeon_cs));
for (i = 0; i < csg->base.crelocs; i++) {
csg->relocs_bo[i]->space_accounted = 0;
+ csg->relocs_bo[i]->relocation = 0;
radeon_bo_unref(csg->relocs_bo[i]);
csg->relocs_bo[i] = NULL;
}