specific.
radeon_lock.c \
radeon_span.c \
radeon_state.c \
- radeon_mm.c \
+ r300_mem.c \
\
r300_context.c \
r300_ioctl.c \
#include "r300_maos.h"
#ifdef USER_BUFFERS
-#include "radeon_mm.h"
+#include "r300_mem.h"
#endif
#include "vblank.h"
r300InitShaderFuncs(&functions);
#ifdef USER_BUFFERS
- radeon_mm_init(r300);
+ r300_mem_init(r300);
#endif
if (!radeonInitContext(&r300->radeon, &functions,
/* the memory manager might be accessed when Mesa frees the shared
* state, so don't destroy it earlier
*/
- radeon_mm_destroy(r300);
+ r300_mem_destroy(r300);
#endif
/* free the option cache */
GLuint prefer_gart_client_texturing;
#ifdef USER_BUFFERS
- struct radeon_memory_manager *rmm;
+ struct r300_memory_manager *rmm;
GLvector4f dummy_attrib[_TNL_ATTRIB_MAX];
GLvector4f *temp_attrib[_TNL_ATTRIB_MAX];
#endif
}
#ifdef USER_BUFFERS
-#include "radeon_mm.h"
+#include "r300_mem.h"
static void r300RefillCurrentDmaRegion(r300ContextPtr rmesa, int size)
{
dmabuf->buf = (void *)1; /* hack */
dmabuf->refcount = 1;
- dmabuf->id = radeon_mm_alloc(rmesa, 4, size);
+ dmabuf->id = r300_mem_alloc(rmesa, 4, size);
if (dmabuf->id == 0) {
LOCK_HARDWARE(&rmesa->radeon); /* no need to validate */
r300FlushCmdBufLocked(rmesa, __FUNCTION__);
radeonWaitForIdleLocked(&rmesa->radeon);
- dmabuf->id = radeon_mm_alloc(rmesa, 4, size);
+ dmabuf->id = r300_mem_alloc(rmesa, 4, size);
UNLOCK_HARDWARE(&rmesa->radeon);
}
rmesa->dma.current.buf = dmabuf;
- rmesa->dma.current.address = radeon_mm_ptr(rmesa, dmabuf->id);
+ rmesa->dma.current.address = r300_mem_ptr(rmesa, dmabuf->id);
rmesa->dma.current.end = size;
rmesa->dma.current.start = 0;
rmesa->dma.current.ptr = 0;
rmesa->dma.flush(rmesa);
if (--region->buf->refcount == 0) {
- radeon_mm_free(rmesa, region->buf->id);
+ r300_mem_free(rmesa, region->buf->id);
FREE(region->buf);
rmesa->dma.nr_released_bufs++;
}
#include "r300_ioctl.h"
#ifdef USER_BUFFERS
-#include "radeon_mm.h"
+#include "r300_mem.h"
#endif
#if SWIZZLE_X != R300_INPUT_ROUTE_SELECT_X || \
int i;
if (rmesa->state.elt_dma.buf)
- radeon_mm_use(rmesa, rmesa->state.elt_dma.buf->id);
+ r300_mem_use(rmesa, rmesa->state.elt_dma.buf->id);
for (i = 0; i < rmesa->state.aos_count; i++) {
if (rmesa->state.aos[i].buf)
- radeon_mm_use(rmesa, rmesa->state.aos[i].buf->id);
+ r300_mem_use(rmesa, rmesa->state.aos[i].buf->id);
}
}
#endif
--- /dev/null
+/*
+ * Copyright (C) 2005 Aapo Tahkola.
+ *
+ * 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, 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 (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 NONINFRINGEMENT.
+ * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
+ *
+ */
+
+/*
+ * Authors:
+ * Aapo Tahkola <aet@rasterburn.org>
+ */
+#include <unistd.h>
+
+#include "r300_context.h"
+#include "r300_cmdbuf.h"
+#include "r300_ioctl.h"
+#include "r300_mem.h"
+#include "radeon_ioctl.h"
+
+#ifdef USER_BUFFERS
+
+static void resize_u_list(r300ContextPtr rmesa)
+{
+ void *temp;
+ int nsize;
+
+ temp = rmesa->rmm->u_list;
+ nsize = rmesa->rmm->u_size * 2;
+
+ rmesa->rmm->u_list = _mesa_malloc(nsize * sizeof(*rmesa->rmm->u_list));
+ _mesa_memset(rmesa->rmm->u_list, 0, nsize * sizeof(*rmesa->rmm->u_list));
+
+ if (temp) {
+ r300FlushCmdBuf(rmesa, __FUNCTION__);
+
+ _mesa_memcpy(rmesa->rmm->u_list, temp, rmesa->rmm->u_size * sizeof(*rmesa->rmm->u_list));
+ _mesa_free(temp);
+ }
+
+ rmesa->rmm->u_size = nsize;
+}
+
+void r300_mem_init(r300ContextPtr rmesa)
+{
+ rmesa->rmm = malloc(sizeof(struct r300_memory_manager));
+ memset(rmesa->rmm, 0, sizeof(struct r300_memory_manager));
+
+ rmesa->rmm->u_size = 128;
+ resize_u_list(rmesa);
+}
+
+void r300_mem_destroy(r300ContextPtr rmesa)
+{
+ _mesa_free(rmesa->rmm->u_list);
+ rmesa->rmm->u_list = NULL;
+
+ _mesa_free(rmesa->rmm);
+ rmesa->rmm = NULL;
+}
+
+void *r300_mem_ptr(r300ContextPtr rmesa, int id)
+{
+ assert(id <= rmesa->rmm->u_last);
+ return rmesa->rmm->u_list[id].ptr;
+}
+
+int r300_mem_find(r300ContextPtr rmesa, void *ptr)
+{
+ int i;
+
+ 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
+int r300_mem_alloc(r300ContextPtr rmesa, int alignment, int size)
+{
+ drm_radeon_mem_alloc_t alloc;
+ int offset = 0, ret;
+ int i, free=-1;
+ int done_age;
+ drm_radeon_mem_free_t memfree;
+ int tries=0;
+ static int bytes_wasted=0, allocated=0;
+
+ if(size < 4096)
+ bytes_wasted += 4096 - size;
+
+ allocated += size;
+
+#if 0
+ static int t=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;
+
+ again:
+
+ done_age = radeonGetAge((radeonContextPtr)rmesa);
+
+ if (rmesa->rmm->u_last + 1 >= rmesa->rmm->u_size)
+ resize_u_list(rmesa);
+
+ for (i = rmesa->rmm->u_last + 1; i > 0; i --) {
+ 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));
+ exit(1);
+ } else {
+#ifdef MM_DEBUG
+ fprintf(stderr, "really freed %d at age %x\n", i, radeonGetAge((radeonContextPtr)rmesa));
+#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;
+ }
+ }
+ }
+ rmesa->rmm->u_head = i;
+
+ if (free == -1) {
+ WARN_ONCE("Ran out of slots!\n");
+ //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) {
+#if 0
+ WARN_ONCE("Ran out of mem!\n");
+ r300FlushCmdBuf(rmesa, __FUNCTION__);
+ //usleep(100);
+ tries2++;
+ tries = 0;
+ if(tries2>100){
+ WARN_ONCE("Ran out of GART memory!\n");
+ exit(1);
+ }
+ goto again;
+#else
+ WARN_ONCE("Ran out of GART memory (for %d)!\nPlease consider adjusting GARTSize option.\n", size);
+ return 0;
+#endif
+ }
+
+ 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, radeonGetAge((radeonContextPtr)rmesa));
+#endif
+
+ return i;
+}
+
+#include "r300_emit.h"
+static void emit_lin_cp(r300ContextPtr rmesa, unsigned long dst, unsigned long src, unsigned long size)
+{
+ int cmd_reserved = 0;
+ int cmd_written = 0;
+ drm_radeon_cmd_header_t *cmd = NULL;
+ 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(R300_RB3D_DSTCACHE_CTLSTAT,0);
+ e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);
+
+ reg_start(0x342c,0);
+ e32(0x00000005);
+
+ reg_start(0x1720,0);
+ e32(0x00010000);
+}
+
+void r300_mem_use(r300ContextPtr rmesa, int id)
+{
+ uint64_t ull;
+#ifdef MM_DEBUG
+ fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, radeonGetAge((radeonContextPtr)rmesa));
+#endif
+ drm_r300_cmd_header_t *cmd;
+
+ assert(id <= rmesa->rmm->u_last);
+
+ if(id == 0)
+ return;
+
+#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 = (drm_r300_cmd_header_t *)r300AllocCmdBuf(rmesa, 2 + sizeof(ull) / 4, __FUNCTION__);
+ cmd[0].scratch.cmd_type = R300_CMD_SCRATCH;
+ cmd[0].scratch.reg = R300_MEM_SCRATCH;
+ cmd[0].scratch.n_bufs = 1;
+ cmd[0].scratch.flags = 0;
+ cmd ++;
+
+ ull = (uint64_t)(intptr_t)&rmesa->rmm->u_list[id].age;
+ _mesa_memcpy(cmd, &ull, sizeof(ull));
+ cmd += sizeof(ull) / 4;
+
+ cmd[0].u = /*id*/0;
+
+ LOCK_HARDWARE(&rmesa->radeon); /* Protect from DRM. */
+ rmesa->rmm->u_list[id].h_pending ++;
+ UNLOCK_HARDWARE(&rmesa->radeon);
+}
+
+unsigned long r300_mem_offset(r300ContextPtr rmesa, int id)
+{
+ unsigned long offset;
+
+ assert(id <= rmesa->rmm->u_last);
+
+ 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 r300_mem_on_card(r300ContextPtr rmesa, int id)
+{
+ assert(id <= rmesa->rmm->u_last);
+
+ if (rmesa->rmm->u_list[id].fb)
+ return GL_TRUE;
+
+ return GL_FALSE;
+}
+
+void *r300_mem_map(r300ContextPtr rmesa, int id, int access)
+{
+#ifdef MM_DEBUG
+ fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, radeonGetAge((radeonContextPtr)rmesa));
+#endif
+ void *ptr;
+ int tries = 0;
+
+ assert(id <= rmesa->rmm->u_last);
+
+ 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);
+
+ rmesa->rmm->u_list[id].mapped = 1;
+ ptr = r300_mem_ptr(rmesa, id);
+
+ return ptr;
+ }
+
+ if (access == R300_MEM_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 = r300_mem_ptr(rmesa, id);
+
+ return ptr;
+ }
+
+
+ if (rmesa->rmm->u_list[id].h_pending)
+ r300FlushCmdBuf(rmesa, __FUNCTION__);
+
+ if (rmesa->rmm->u_list[id].h_pending) {
+ return NULL;
+ }
+
+ while(rmesa->rmm->u_list[id].age > radeonGetAge((radeonContextPtr)rmesa) && tries++ < 1000)
+ usleep(10);
+
+ if (tries >= 1000) {
+ fprintf(stderr, "Idling failed (%x vs %x)\n",
+ rmesa->rmm->u_list[id].age, radeonGetAge((radeonContextPtr)rmesa));
+ 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 = r300_mem_ptr(rmesa, id);
+
+ return ptr;
+}
+
+void r300_mem_unmap(r300ContextPtr rmesa, int id)
+{
+#ifdef MM_DEBUG
+ fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, radeonGetAge((radeonContextPtr)rmesa));
+#endif
+
+ assert(id <= rmesa->rmm->u_last);
+
+ if(rmesa->rmm->u_list[id].mapped == 0)
+ WARN_ONCE("buffer %d not mapped\n", id);
+
+ rmesa->rmm->u_list[id].mapped = 0;
+
+ 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 r300_mem_free(r300ContextPtr rmesa, int id)
+{
+#ifdef MM_DEBUG
+ fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, radeonGetAge((radeonContextPtr)rmesa));
+#endif
+
+ assert(id <= rmesa->rmm->u_last);
+
+ if(id == 0)
+ return;
+
+ if(rmesa->rmm->u_list[id].ptr == NULL){
+ WARN_ONCE("Not allocated!\n");
+ return ;
+ }
+
+ if(rmesa->rmm->u_list[id].pending){
+ WARN_ONCE("%p already pended!\n", rmesa->rmm->u_list[id].ptr);
+ return ;
+ }
+
+ rmesa->rmm->u_list[id].pending = 1;
+}
+#endif
--- /dev/null
+#ifndef __R300_MEM_H__
+#define __R300_MEM_H__
+
+//#define R300_MEM_PDL 0
+#define R300_MEM_UL 1
+
+#define R300_MEM_R 1
+#define R300_MEM_W 2
+#define R300_MEM_RW (R300_MEM_R | R300_MEM_W)
+
+#define R300_MEM_SCRATCH 2
+
+struct r300_memory_manager {
+ struct {
+ void *ptr;
+ uint32_t size;
+ uint32_t age;
+ uint32_t h_pending;
+ int pending;
+ int mapped;
+ int ref_count;
+ struct mem_block *fb;
+ } *u_list;
+ int u_head, u_tail, u_size, u_last;
+
+};
+
+extern void r300_mem_init(r300ContextPtr rmesa);
+extern void r300_mem_destroy(r300ContextPtr rmesa);
+extern void *r300_mem_ptr(r300ContextPtr rmesa, int id);
+extern int r300_mem_find(r300ContextPtr rmesa, void *ptr);
+extern int r300_mem_alloc(r300ContextPtr rmesa, int alignment, int size);
+extern void r300_mem_use(r300ContextPtr rmesa, int id);
+extern unsigned long r300_mem_offset(r300ContextPtr rmesa, int id);
+extern int r300_mem_on_card(r300ContextPtr rmesa, int id);
+extern void *r300_mem_map(r300ContextPtr rmesa, int id, int access);
+extern void r300_mem_unmap(r300ContextPtr rmesa, int id);
+extern void r300_mem_free(r300ContextPtr rmesa, int id);
+
+#endif
#include <unistd.h> /* for usleep() */
#ifdef USER_BUFFERS
-#include "radeon_mm.h"
+#include "r300_mem.h"
#endif
/**
r300EmitWait(rmesa, R300_WAIT_2D);
#ifdef USER_BUFFERS
- radeon_mm_use(rmesa, region.buf->id);
+ r300_mem_use(rmesa, region.buf->id);
#endif
r300ReleaseDmaRegion(rmesa, ®ion, __FUNCTION__);
+++ /dev/null
-/*
- * Copyright (C) 2005 Aapo Tahkola.
- *
- * 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, 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 (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 NONINFRINGEMENT.
- * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) 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.
- *
- */
-
-/*
- * Authors:
- * Aapo Tahkola <aet@rasterburn.org>
- */
-#include <unistd.h>
-
-#include "r300_context.h"
-#include "r300_cmdbuf.h"
-#include "r300_ioctl.h"
-#include "radeon_mm.h"
-#include "radeon_ioctl.h"
-
-#ifdef USER_BUFFERS
-
-static void resize_u_list(r300ContextPtr rmesa)
-{
- void *temp;
- int nsize;
-
- temp = rmesa->rmm->u_list;
- nsize = rmesa->rmm->u_size * 2;
-
- rmesa->rmm->u_list = _mesa_malloc(nsize * sizeof(*rmesa->rmm->u_list));
- _mesa_memset(rmesa->rmm->u_list, 0, nsize * sizeof(*rmesa->rmm->u_list));
-
- if (temp) {
- r300FlushCmdBuf(rmesa, __FUNCTION__);
-
- _mesa_memcpy(rmesa->rmm->u_list, temp, rmesa->rmm->u_size * sizeof(*rmesa->rmm->u_list));
- _mesa_free(temp);
- }
-
- rmesa->rmm->u_size = nsize;
-}
-
-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 = 128;
- resize_u_list(rmesa);
-}
-
-void radeon_mm_destroy(r300ContextPtr rmesa)
-{
- _mesa_free(rmesa->rmm->u_list);
- rmesa->rmm->u_list = NULL;
-
- _mesa_free(rmesa->rmm);
- rmesa->rmm = NULL;
-}
-
-void *radeon_mm_ptr(r300ContextPtr rmesa, int id)
-{
- assert(id <= rmesa->rmm->u_last);
- return rmesa->rmm->u_list[id].ptr;
-}
-
-int radeon_mm_find(r300ContextPtr rmesa, void *ptr)
-{
- int i;
-
- 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
-int radeon_mm_alloc(r300ContextPtr rmesa, int alignment, int size)
-{
- drm_radeon_mem_alloc_t alloc;
- int offset = 0, ret;
- int i, free=-1;
- int done_age;
- drm_radeon_mem_free_t memfree;
- int tries=0;
- static int bytes_wasted=0, allocated=0;
-
- if(size < 4096)
- bytes_wasted += 4096 - size;
-
- allocated += size;
-
-#if 0
- static int t=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;
-
- again:
-
- done_age = radeonGetAge((radeonContextPtr)rmesa);
-
- if (rmesa->rmm->u_last + 1 >= rmesa->rmm->u_size)
- resize_u_list(rmesa);
-
- for (i = rmesa->rmm->u_last + 1; i > 0; i --) {
- 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));
- exit(1);
- } else {
-#ifdef MM_DEBUG
- fprintf(stderr, "really freed %d at age %x\n", i, radeonGetAge((radeonContextPtr)rmesa));
-#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;
- }
- }
- }
- rmesa->rmm->u_head = i;
-
- if (free == -1) {
- WARN_ONCE("Ran out of slots!\n");
- //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) {
-#if 0
- WARN_ONCE("Ran out of mem!\n");
- r300FlushCmdBuf(rmesa, __FUNCTION__);
- //usleep(100);
- tries2++;
- tries = 0;
- if(tries2>100){
- WARN_ONCE("Ran out of GART memory!\n");
- exit(1);
- }
- goto again;
-#else
- WARN_ONCE("Ran out of GART memory (for %d)!\nPlease consider adjusting GARTSize option.\n", size);
- return 0;
-#endif
- }
-
- 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, radeonGetAge((radeonContextPtr)rmesa));
-#endif
-
- return i;
-}
-
-#include "r300_emit.h"
-static void emit_lin_cp(r300ContextPtr rmesa, unsigned long dst, unsigned long src, unsigned long size)
-{
- int cmd_reserved = 0;
- int cmd_written = 0;
- drm_radeon_cmd_header_t *cmd = NULL;
- 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(R300_RB3D_DSTCACHE_CTLSTAT,0);
- e32(R300_RB3D_DSTCACHE_UNKNOWN_0A);
-
- reg_start(0x342c,0);
- e32(0x00000005);
-
- reg_start(0x1720,0);
- e32(0x00010000);
-}
-
-void radeon_mm_use(r300ContextPtr rmesa, int id)
-{
- uint64_t ull;
-#ifdef MM_DEBUG
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, radeonGetAge((radeonContextPtr)rmesa));
-#endif
- drm_r300_cmd_header_t *cmd;
-
- assert(id <= rmesa->rmm->u_last);
-
- if(id == 0)
- return;
-
-#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 = (drm_r300_cmd_header_t *)r300AllocCmdBuf(rmesa, 2 + sizeof(ull) / 4, __FUNCTION__);
- cmd[0].scratch.cmd_type = R300_CMD_SCRATCH;
- cmd[0].scratch.reg = RADEON_MM_SCRATCH;
- cmd[0].scratch.n_bufs = 1;
- cmd[0].scratch.flags = 0;
- cmd ++;
-
- ull = (uint64_t)(intptr_t)&rmesa->rmm->u_list[id].age;
- _mesa_memcpy(cmd, &ull, sizeof(ull));
- cmd += sizeof(ull) / 4;
-
- cmd[0].u = /*id*/0;
-
- LOCK_HARDWARE(&rmesa->radeon); /* Protect from DRM. */
- rmesa->rmm->u_list[id].h_pending ++;
- UNLOCK_HARDWARE(&rmesa->radeon);
-}
-
-unsigned long radeon_mm_offset(r300ContextPtr rmesa, int id)
-{
- unsigned long offset;
-
- assert(id <= rmesa->rmm->u_last);
-
- 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)
-{
- assert(id <= rmesa->rmm->u_last);
-
- 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
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, radeonGetAge((radeonContextPtr)rmesa));
-#endif
- void *ptr;
- int tries = 0;
-
- assert(id <= rmesa->rmm->u_last);
-
- 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);
-
- rmesa->rmm->u_list[id].mapped = 1;
- ptr = radeon_mm_ptr(rmesa, id);
-
- 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;
- }
-
-
- if (rmesa->rmm->u_list[id].h_pending)
- r300FlushCmdBuf(rmesa, __FUNCTION__);
-
- if (rmesa->rmm->u_list[id].h_pending) {
- return NULL;
- }
-
- while(rmesa->rmm->u_list[id].age > radeonGetAge((radeonContextPtr)rmesa) && tries++ < 1000)
- usleep(10);
-
- if (tries >= 1000) {
- fprintf(stderr, "Idling failed (%x vs %x)\n",
- rmesa->rmm->u_list[id].age, radeonGetAge((radeonContextPtr)rmesa));
- 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);
-
- return ptr;
-}
-
-void radeon_mm_unmap(r300ContextPtr rmesa, int id)
-{
-#ifdef MM_DEBUG
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, radeonGetAge((radeonContextPtr)rmesa));
-#endif
-
- assert(id <= rmesa->rmm->u_last);
-
- if(rmesa->rmm->u_list[id].mapped == 0)
- WARN_ONCE("buffer %d not mapped\n", id);
-
- rmesa->rmm->u_list[id].mapped = 0;
-
- 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)
-{
-#ifdef MM_DEBUG
- fprintf(stderr, "%s: %d at age %x\n", __FUNCTION__, id, radeonGetAge((radeonContextPtr)rmesa));
-#endif
-
- assert(id <= rmesa->rmm->u_last);
-
- if(id == 0)
- return;
-
- if(rmesa->rmm->u_list[id].ptr == NULL){
- WARN_ONCE("Not allocated!\n");
- return ;
- }
-
- if(rmesa->rmm->u_list[id].pending){
- WARN_ONCE("%p already pended!\n", rmesa->rmm->u_list[id].ptr);
- return ;
- }
-
- rmesa->rmm->u_list[id].pending = 1;
-}
-#endif
+++ /dev/null
-#ifndef __RADEON_MM_H__
-#define __RADEON_MM_H__
-
-//#define RADEON_MM_PDL 0
-#define RADEON_MM_UL 1
-
-#define RADEON_MM_R 1
-#define RADEON_MM_W 2
-#define RADEON_MM_RW (RADEON_MM_R | RADEON_MM_W)
-
-#define RADEON_MM_SCRATCH 2
-
-struct radeon_memory_manager {
- struct {
- void *ptr;
- uint32_t size;
- uint32_t age;
- uint32_t h_pending;
- int pending;
- int mapped;
- 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_destroy(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);
-
-#endif