From 4dc3249f0d800f9e36ee11ec5c00351e67dbeee3 Mon Sep 17 00:00:00 2001 From: Aapo Tahkola Date: Wed, 26 Oct 2005 16:42:06 +0000 Subject: Sync with my local tree. Changes to current operation: -Elts are no longer converted to 16-bit format -Cube maps --- src/mesa/drivers/dri/r300/radeon_mm.c | 339 ++++++++++++++++++++++++++++++++++ 1 file changed, 339 insertions(+) create mode 100644 src/mesa/drivers/dri/r300/radeon_mm.c (limited to 'src/mesa/drivers/dri/r300/radeon_mm.c') diff --git a/src/mesa/drivers/dri/r300/radeon_mm.c b/src/mesa/drivers/dri/r300/radeon_mm.c new file mode 100644 index 0000000000..b69929e664 --- /dev/null +++ b/src/mesa/drivers/dri/r300/radeon_mm.c @@ -0,0 +1,339 @@ +#include +#include +#include +#include + +#include "r300_context.h" +#include "r300_cmdbuf.h" +#include "radeon_mm.h" + +#ifdef USER_BUFFERS +void radeon_mm_reset(r300ContextPtr rmesa) +{ + drm_r300_cmd_header_t *cmd; + int ret; + + memset(rmesa->rmm, 0, sizeof(struct radeon_memory_manager)); + + rmesa->rmm->u_size = 1024; //2048; + //rmesa->radeon.radeonScreen->scratch[2] = rmesa->rmm->vb_age; +#if 0 /* FIXME */ + cmd = r300AllocCmdBuf(rmesa, 4, __FUNCTION__); + cmd[0].scratch.cmd_type = R300_CMD_SCRATCH; + cmd[0].scratch.reg = 2; + cmd[0].scratch.n_bufs = 1; + cmd[0].scratch.flags = 0; + cmd[1].u = (unsigned long)(&rmesa->rmm->vb_age); + cmd[2].u = (unsigned long)(&rmesa->rmm->u_list[0].age); + cmd[3].u = /*id*/0; + + /* Protect from DRM. */ + LOCK_HARDWARE(&rmesa->radeon); + rmesa->rmm->u_list[0].h_pending ++; + ret = r300FlushCmdBufLocked(rmesa, __FUNCTION__); + UNLOCK_HARDWARE(&rmesa->radeon); + + if (ret) { + WARN_ONCE("r300FlushCmdBufLocked\n"); + exit(1); + } +#endif +} + +void radeon_mm_init(r300ContextPtr rmesa) +{ + + rmesa->mm_ipc_key = 0xdeadbeed; //ftok("/tmp/.r300.mm_lock", "x"); + if(rmesa->mm_ipc_key == -1){ + perror("ftok"); + exit(1); + } + + rmesa->mm_shm_id = shmget(rmesa->mm_ipc_key, sizeof(struct radeon_memory_manager), 0644); + if (rmesa->mm_shm_id == -1) { + rmesa->mm_shm_id = shmget(rmesa->mm_ipc_key, sizeof(struct radeon_memory_manager), 0644 | IPC_CREAT); + + rmesa->rmm = shmat(rmesa->mm_shm_id, (void *)0, 0); + if (rmesa->rmm == (char *)(-1)) { + perror("shmat"); + exit(1); + } + + radeon_mm_reset(rmesa); + + rmesa->mm_sem_id = semget(rmesa->mm_ipc_key, 2, 0666 | IPC_CREAT); + if (rmesa->mm_sem_id == -1) { + perror("semget"); + exit(1); + } + + return ; + } + + rmesa->rmm = shmat(rmesa->mm_shm_id, (void *)0, 0); + if (rmesa->rmm == (char *)(-1)) { + perror("shmat"); + exit(1); + } + /* FIXME */ + radeon_mm_reset(rmesa); + + rmesa->mm_sem_id = semget(rmesa->mm_ipc_key, 2, 0666); + if (rmesa->mm_sem_id == -1) { + perror("semget"); + exit(1); + } +} + +static void radeon_mm_lock(r300ContextPtr rmesa, int sem) +{ + struct sembuf sb = { 0, 1, 0 }; + + sb.sem_num = sem; + + if (semop(rmesa->mm_sem_id, &sb, 1) == -1) { + perror("semop"); + exit(1); + } +} + +static void radeon_mm_unlock(r300ContextPtr rmesa, int sem) +{ + struct sembuf sb = { 0, -1, 0 }; + + sb.sem_num = sem; + + if (semop(rmesa->mm_sem_id, &sb, 1) == -1) { + perror("semop"); + exit(1); + } +} + +void *radeon_mm_ptr(r300ContextPtr rmesa, int id) +{ + return rmesa->rmm->u_list[id].ptr; +} + +//#define MM_DEBUG +int radeon_mm_alloc(r300ContextPtr rmesa, int alignment, int size) +{ + drm_radeon_mem_alloc_t alloc; + int offset, ret; + int i, end, free=-1; + int done_age; + drm_radeon_mem_free_t memfree; + int tries=0, tries2=0; + + memfree.region = RADEON_MEM_REGION_GART; + + radeon_mm_lock(rmesa, RADEON_MM_UL); + + again: + + done_age = rmesa->radeon.radeonScreen->scratch[2]; + + i = 1; //rmesa->rmm->u_head + 1; + //i &= rmesa->rmm->u_size - 1; + + end = i + rmesa->rmm->u_size; + //end &= rmesa->rmm->u_size - 1; + + for (; i != end; i ++/*, i &= rmesa->rmm->u_size-1*/) { + if (rmesa->rmm->u_list[i].ptr == NULL){ + free = i; + continue; + } + + if (rmesa->rmm->u_list[i].h_pending == 0 && + rmesa->rmm->u_list[i].pending && rmesa->rmm->u_list[i].age <= done_age) { + memfree.region_offset = (char *)rmesa->rmm->u_list[i].ptr - + (char *)rmesa->radeon.radeonScreen->gartTextures.map; + + ret = drmCommandWrite(rmesa->radeon.radeonScreen->driScreen->fd, + DRM_RADEON_FREE, &memfree, sizeof(memfree)); + + if (ret) { + //fprintf(stderr, "Failed to free at %p\n", rmesa->rmm->u_list[i].ptr); + //fprintf(stderr, "ret = %s\n", strerror(-ret)); + + //radeon_mm_unlock(rmesa, RADEON_MM_UL); + //exit(1); + } else { +#ifdef MM_DEBUG + fprintf(stderr, "really freed %d at age %x\n", i, rmesa->radeon.radeonScreen->scratch[2]); +#endif + rmesa->rmm->u_list[i].pending = 0; + rmesa->rmm->u_list[i].ptr = NULL; + free = i; + } + } + } + done: + rmesa->rmm->u_head = i; + + if (free == -1) { + //usleep(100); + r300FlushCmdBuf(rmesa, __FUNCTION__); + tries++; + if(tries>100){ + WARN_ONCE("Ran out of slots!\n"); + exit(1); + } + goto again; + } + + alloc.region = RADEON_MEM_REGION_GART; + alloc.alignment = alignment; + alloc.size = size; + alloc.region_offset = &offset; + + ret = drmCommandWriteRead( rmesa->radeon.dri.fd, DRM_RADEON_ALLOC, &alloc, sizeof(alloc)); + if (ret) { + r300FlushCmdBuf(rmesa, __FUNCTION__); + //usleep(100); + tries2++; + tries = 0; + if(tries2>100){ + WARN_ONCE("Ran out of GART memory!\n"); + exit(1); + } + goto again; + } + + i = free; + rmesa->rmm->u_list[i].ptr = ((GLubyte *)rmesa->radeon.radeonScreen->gartTextures.map) + offset; + rmesa->rmm->u_list[i].size = size; + rmesa->rmm->u_list[i].age = 0; + +#ifdef MM_DEBUG + fprintf(stderr, "allocated %d at age %x\n", i, rmesa->radeon.radeonScreen->scratch[2]); +#endif + + radeon_mm_unlock(rmesa, RADEON_MM_UL); + + return i; +} + +void radeon_mm_use(r300ContextPtr rmesa, int id) +{ +#ifdef MM_DEBUG + fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, rmesa->radeon.radeonScreen->scratch[2]); +#endif + drm_r300_cmd_header_t *cmd; + + if(id == 0) + return; + + radeon_mm_lock(rmesa, RADEON_MM_UL); + + cmd = r300AllocCmdBuf(rmesa, 4, __FUNCTION__); + cmd[0].scratch.cmd_type = R300_CMD_SCRATCH; + cmd[0].scratch.reg = 2; + cmd[0].scratch.n_bufs = 1; + cmd[0].scratch.flags = 0; + cmd[1].u = (unsigned long)(&rmesa->rmm->vb_age); + cmd[2].u = (unsigned long)(&rmesa->rmm->u_list[id].age); + cmd[3].u = /*id*/0; + + LOCK_HARDWARE(&rmesa->radeon); /* Protect from DRM. */ + rmesa->rmm->u_list[id].h_pending ++; + UNLOCK_HARDWARE(&rmesa->radeon); + + radeon_mm_unlock(rmesa, RADEON_MM_UL); +} + +void *radeon_mm_map(r300ContextPtr rmesa, int id, int access) +{ +#ifdef MM_DEBUG + fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, rmesa->radeon.radeonScreen->scratch[2]); +#endif + void *ptr; + int tries = 0; + + if (access == RADEON_MM_R) { + radeon_mm_lock(rmesa, RADEON_MM_UL); + + if(rmesa->rmm->u_list[id].mapped == 1) + WARN_ONCE("buffer %d already mapped\n", id); + + rmesa->rmm->u_list[id].mapped = 1; + ptr = radeon_mm_ptr(rmesa, id); + + radeon_mm_unlock(rmesa, RADEON_MM_UL); + + return ptr; + } + + radeon_mm_lock(rmesa, RADEON_MM_UL); + + if (rmesa->rmm->u_list[id].h_pending) + r300FlushCmdBuf(rmesa, __FUNCTION__); + + if (rmesa->rmm->u_list[id].h_pending) { + radeon_mm_unlock(rmesa, RADEON_MM_UL); + return NULL; + } + + while(rmesa->rmm->u_list[id].age > rmesa->radeon.radeonScreen->scratch[2] && tries++ < 1000) + usleep(10); + + if (tries >= 1000) { + fprintf(stderr, "Idling failed (%x vs %x)\n", + rmesa->rmm->u_list[id].age, rmesa->radeon.radeonScreen->scratch[2]); + radeon_mm_unlock(rmesa, RADEON_MM_UL); + return NULL; + } + + if(rmesa->rmm->u_list[id].mapped == 1) + WARN_ONCE("buffer %d already mapped\n", id); + + rmesa->rmm->u_list[id].mapped = 1; + ptr = radeon_mm_ptr(rmesa, id); + + radeon_mm_unlock(rmesa, RADEON_MM_UL); + + return ptr; +} + +void radeon_mm_unmap(r300ContextPtr rmesa, int id) +{ +#ifdef MM_DEBUG + fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, rmesa->radeon.radeonScreen->scratch[2]); +#endif + + radeon_mm_lock(rmesa, RADEON_MM_UL); + + if(rmesa->rmm->u_list[id].mapped == 0) + WARN_ONCE("buffer %d not mapped\n", id); + + rmesa->rmm->u_list[id].mapped = 0; + + radeon_mm_unlock(rmesa, RADEON_MM_UL); +} + +void radeon_mm_free(r300ContextPtr rmesa, int id) +{ +#ifdef MM_DEBUG + fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, rmesa->radeon.radeonScreen->scratch[2]); +#endif + + if(id == 0) + return; + + radeon_mm_lock(rmesa, RADEON_MM_UL); + if(rmesa->rmm->u_list[id].ptr == NULL){ + radeon_mm_unlock(rmesa, RADEON_MM_UL); + WARN_ONCE("Not allocated!\n"); + return ; + } + + if(rmesa->rmm->u_list[id].pending){ + radeon_mm_unlock(rmesa, RADEON_MM_UL); + WARN_ONCE("%p already pended!\n", rmesa->rmm->u_list[id].ptr); + return ; + } + + rmesa->rmm->u_list[id].pending = 1; + radeon_mm_unlock(rmesa, RADEON_MM_UL); +} +#endif -- cgit v1.2.3