diff options
-rw-r--r-- | src/mesa/drivers/dri/r300/radeon_mm.c | 326 | ||||
-rw-r--r-- | src/mesa/drivers/dri/r300/radeon_mm.h | 10 |
2 files changed, 204 insertions, 132 deletions
diff --git a/src/mesa/drivers/dri/r300/radeon_mm.c b/src/mesa/drivers/dri/r300/radeon_mm.c index b69929e664..a18d69122d 100644 --- a/src/mesa/drivers/dri/r300/radeon_mm.c +++ b/src/mesa/drivers/dri/r300/radeon_mm.c @@ -8,110 +8,38 @@ #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->rmm = malloc(sizeof(struct radeon_memory_manager)); + memset(rmesa->rmm, 0, sizeof(struct radeon_memory_manager)); + rmesa->rmm->u_size = 512; //2048; - 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); - } + rmesa->rmm->u_list = malloc(rmesa->rmm->u_size *sizeof(*rmesa->rmm->u_list)); + memset(rmesa->rmm->u_list, 0, rmesa->rmm->u_size*sizeof(*rmesa->rmm->u_list)); } -static void radeon_mm_lock(r300ContextPtr rmesa, int sem) +void *radeon_mm_ptr(r300ContextPtr rmesa, int id) { - struct sembuf sb = { 0, 1, 0 }; - - sb.sem_num = sem; - - if (semop(rmesa->mm_sem_id, &sb, 1) == -1) { - perror("semop"); - exit(1); - } + return rmesa->rmm->u_list[id].ptr; } -static void radeon_mm_unlock(r300ContextPtr rmesa, int sem) +int radeon_mm_find(r300ContextPtr rmesa, void *ptr) { - struct sembuf sb = { 0, -1, 0 }; + int i; + int id = 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; + for (i=1; i < rmesa->rmm->u_size+1; i++) + if(rmesa->rmm->u_list[i].ptr && + ptr >= rmesa->rmm->u_list[i].ptr && + ptr < rmesa->rmm->u_list[i].ptr + rmesa->rmm->u_list[i].size) + break; + + if (i < rmesa->rmm->u_size + 1) + return i; + + fprintf(stderr, "%p failed\n", ptr); + return 0; } //#define MM_DEBUG @@ -119,27 +47,33 @@ 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 i, free=-1; int done_age; drm_radeon_mem_free_t memfree; int tries=0, tries2=0; + static int t=0; + static int bytes_wasted=0, allocated=0; + + if(size < 4096) + bytes_wasted += 4096 - size; + + allocated += size; + +#if 0 + if (t != time(NULL)) { + t = time(NULL); + fprintf(stderr, "slots used %d, wasted %d kb, allocated %d\n", rmesa->rmm->u_last, bytes_wasted/1024, allocated/1024); + } +#endif 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){ + for (i = rmesa->rmm->u_last + 1; i > 0; i --) { + if (rmesa->rmm->u_list[i].ptr == NULL) { free = i; continue; } @@ -153,17 +87,33 @@ int radeon_mm_alloc(r300ContextPtr rmesa, int alignment, int size) 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); + fprintf(stderr, "Failed to free at %p\n", rmesa->rmm->u_list[i].ptr); + fprintf(stderr, "ret = %s\n", strerror(-ret)); + exit(1); } else { #ifdef MM_DEBUG fprintf(stderr, "really freed %d at age %x\n", i, rmesa->radeon.radeonScreen->scratch[2]); #endif + if (i == rmesa->rmm->u_last) + rmesa->rmm->u_last --; + + if(rmesa->rmm->u_list[i].size < 4096) + bytes_wasted -= 4096 - rmesa->rmm->u_list[i].size; + + allocated -= rmesa->rmm->u_list[i].size; rmesa->rmm->u_list[i].pending = 0; rmesa->rmm->u_list[i].ptr = NULL; + + if (rmesa->rmm->u_list[i].fb) { + LOCK_HARDWARE(&(rmesa->radeon)); + ret = mmFreeMem(rmesa->rmm->u_list[i].fb); + UNLOCK_HARDWARE(&(rmesa->radeon)); + + if (ret != 0) + fprintf(stderr, "failed to free!\n"); + rmesa->rmm->u_list[i].fb = NULL; + } + rmesa->rmm->u_list[i].ref_count = 0; free = i; } } @@ -172,6 +122,7 @@ int radeon_mm_alloc(r300ContextPtr rmesa, int alignment, int size) rmesa->rmm->u_head = i; if (free == -1) { + WARN_ONCE("Ran out of slots!\n"); //usleep(100); r300FlushCmdBuf(rmesa, __FUNCTION__); tries++; @@ -189,6 +140,7 @@ int radeon_mm_alloc(r300ContextPtr rmesa, int alignment, int size) ret = drmCommandWriteRead( rmesa->radeon.dri.fd, DRM_RADEON_ALLOC, &alloc, sizeof(alloc)); if (ret) { + WARN_ONCE("Ran out of mem!\n"); r300FlushCmdBuf(rmesa, __FUNCTION__); //usleep(100); tries2++; @@ -201,19 +153,78 @@ int radeon_mm_alloc(r300ContextPtr rmesa, int alignment, int size) } i = free; + + if (i > rmesa->rmm->u_last) + rmesa->rmm->u_last = i; + 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; + rmesa->rmm->u_list[i].fb = NULL; + //fprintf(stderr, "alloc %p at id %d\n", rmesa->rmm->u_list[i].ptr, i); #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; } +#include "r300_emit.h" +void emit_lin_cp(r300ContextPtr rmesa, unsigned long dst, unsigned long src, unsigned long size) +{ + LOCAL_VARS + int cp_size; + + + while (size > 0){ + cp_size = size; + if(cp_size > /*8190*/4096) + cp_size = /*8190*/4096; + + reg_start(0x146c,1); + e32(0x52cc32fb); + + reg_start(0x15ac,1); + e32(src); + e32(cp_size); + + reg_start(0x1704,0); + e32(0x0); + + reg_start(0x1404,1); + e32(dst); + e32(cp_size); + + reg_start(0x1700,0); + e32(0x0); + + reg_start(0x1640,3); + e32(0x00000000); + e32(0x00001fff); + e32(0x00000000); + e32(0x00001fff); + + start_packet3(RADEON_CP_PACKET3_UNK1B, 2); + e32(0 << 16 | 0); + e32(0 << 16 | 0); + e32(cp_size << 16 | 0x1); + + dst += cp_size; + src += cp_size; + size -= cp_size; + } + + reg_start(0x4e4c,0); + e32(0x0000000a); + + reg_start(0x342c,0); + e32(0x00000005); + + reg_start(0x1720,0); + e32(0x00010000); +} + void radeon_mm_use(r300ContextPtr rmesa, int id) { #ifdef MM_DEBUG @@ -224,7 +235,38 @@ void radeon_mm_use(r300ContextPtr rmesa, int id) if(id == 0) return; - radeon_mm_lock(rmesa, RADEON_MM_UL); +#if 0 /* FB VBOs. Needs further changes... */ + rmesa->rmm->u_list[id].ref_count ++; + if (rmesa->rmm->u_list[id].ref_count > 100 && rmesa->rmm->u_list[id].fb == NULL && + rmesa->rmm->u_list[id].size != RADEON_BUFFER_SIZE*16 /*&& rmesa->rmm->u_list[id].size > 40*/) { + driTexHeap *heap; + struct mem_block *mb; + + LOCK_HARDWARE(&(rmesa->radeon)); + + heap = rmesa->texture_heaps[0]; + + mb = mmAllocMem(heap->memory_heap, rmesa->rmm->u_list[id].size, heap->alignmentShift, 0); + + UNLOCK_HARDWARE(&(rmesa->radeon)); + + if (mb) { + rmesa->rmm->u_list[id].fb = mb; + + emit_lin_cp(rmesa, rmesa->radeon.radeonScreen->texOffset[0] + rmesa->rmm->u_list[id].fb->ofs, + r300GartOffsetFromVirtual(rmesa, rmesa->rmm->u_list[id].ptr), + rmesa->rmm->u_list[id].size); + } else { + WARN_ONCE("Upload to fb failed, %d, %d\n", rmesa->rmm->u_list[id].size, id); + } + //fprintf(stderr, "Upload to fb! %d, %d\n", rmesa->rmm->u_list[id].ref_count, id); + } + /*if (rmesa->rmm->u_list[id].fb) { + emit_lin_cp(rmesa, rmesa->radeon.radeonScreen->texOffset[0] + rmesa->rmm->u_list[id].fb->ofs, + r300GartOffsetFromVirtual(rmesa, rmesa->rmm->u_list[id].ptr), + rmesa->rmm->u_list[id].size); + }*/ +#endif cmd = r300AllocCmdBuf(rmesa, 4, __FUNCTION__); cmd[0].scratch.cmd_type = R300_CMD_SCRATCH; @@ -238,10 +280,31 @@ void radeon_mm_use(r300ContextPtr rmesa, int id) 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); } +unsigned long radeon_mm_offset(r300ContextPtr rmesa, int id) +{ + unsigned long offset; + + if (rmesa->rmm->u_list[id].fb) { + offset = rmesa->radeon.radeonScreen->texOffset[0] + rmesa->rmm->u_list[id].fb->ofs; + } else { + offset = (char *)rmesa->rmm->u_list[id].ptr - + (char *)rmesa->radeon.radeonScreen->gartTextures.map; + offset += rmesa->radeon.radeonScreen->gart_texture_offset; + } + + return offset; +} + +int radeon_mm_on_card(r300ContextPtr rmesa, int id) +{ + if (rmesa->rmm->u_list[id].fb) + return GL_TRUE; + + return GL_FALSE; +} + void *radeon_mm_map(r300ContextPtr rmesa, int id, int access) { #ifdef MM_DEBUG @@ -250,8 +313,12 @@ void *radeon_mm_map(r300ContextPtr rmesa, int id, int access) void *ptr; int tries = 0; - if (access == RADEON_MM_R) { - radeon_mm_lock(rmesa, RADEON_MM_UL); + rmesa->rmm->u_list[id].ref_count = 0; + if (rmesa->rmm->u_list[id].fb) { + WARN_ONCE("Mapping fb!\n"); + /* Idle gart only and do upload on unmap */ + //rmesa->rmm->u_list[id].fb = NULL; + if(rmesa->rmm->u_list[id].mapped == 1) WARN_ONCE("buffer %d already mapped\n", id); @@ -259,18 +326,25 @@ void *radeon_mm_map(r300ContextPtr rmesa, int id, int access) rmesa->rmm->u_list[id].mapped = 1; ptr = radeon_mm_ptr(rmesa, id); - radeon_mm_unlock(rmesa, RADEON_MM_UL); + return ptr; + } + + if (access == RADEON_MM_R) { + + 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); 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; } @@ -280,7 +354,6 @@ void *radeon_mm_map(r300ContextPtr rmesa, int id, int access) 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; } @@ -290,8 +363,6 @@ void *radeon_mm_map(r300ContextPtr rmesa, int id, int access) rmesa->rmm->u_list[id].mapped = 1; ptr = radeon_mm_ptr(rmesa, id); - radeon_mm_unlock(rmesa, RADEON_MM_UL); - return ptr; } @@ -301,14 +372,15 @@ void radeon_mm_unmap(r300ContextPtr rmesa, int id) 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); + if (rmesa->rmm->u_list[id].fb) + emit_lin_cp(rmesa, rmesa->radeon.radeonScreen->texOffset[0] + rmesa->rmm->u_list[id].fb->ofs, + r300GartOffsetFromVirtual(rmesa, rmesa->rmm->u_list[id].ptr), + rmesa->rmm->u_list[id].size); } void radeon_mm_free(r300ContextPtr rmesa, int id) @@ -320,20 +392,16 @@ void radeon_mm_free(r300ContextPtr rmesa, int id) 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 diff --git a/src/mesa/drivers/dri/r300/radeon_mm.h b/src/mesa/drivers/dri/r300/radeon_mm.h index 637ecb1dda..5fdeac52a7 100644 --- a/src/mesa/drivers/dri/r300/radeon_mm.h +++ b/src/mesa/drivers/dri/r300/radeon_mm.h @@ -10,7 +10,6 @@ struct radeon_memory_manager { uint32_t vb_age; - /*uint32_t ages[1024];*/ struct { void *ptr; @@ -19,15 +18,20 @@ struct radeon_memory_manager { uint32_t h_pending; int pending; int mapped; - } u_list[/*4096*/2048]; - int u_head, u_tail, u_size; + int ref_count; + struct mem_block *fb; + } *u_list; + int u_head, u_tail, u_size, u_last; }; extern void radeon_mm_init(r300ContextPtr rmesa); extern void *radeon_mm_ptr(r300ContextPtr rmesa, int id); +extern int radeon_mm_find(r300ContextPtr rmesa, void *ptr); extern int radeon_mm_alloc(r300ContextPtr rmesa, int alignment, int size); extern void radeon_mm_use(r300ContextPtr rmesa, int id); +extern unsigned long radeon_mm_offset(r300ContextPtr rmesa, int id); +extern int radeon_mm_on_card(r300ContextPtr rmesa, int id); extern void *radeon_mm_map(r300ContextPtr rmesa, int id, int access); extern void radeon_mm_unmap(r300ContextPtr rmesa, int id); extern void radeon_mm_free(r300ContextPtr rmesa, int id); |