From edbeec2b9177fef27b5a04b7b9b975b8abf84367 Mon Sep 17 00:00:00 2001 From: Ben Skeggs Date: Sat, 2 Feb 2008 14:21:06 +1100 Subject: nouveau: implement a bo_set_status() --- src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c | 133 ++++++++++++--------- .../drivers/dri/nouveau_winsys/nouveau_drmif.h | 3 + .../dri/nouveau_winsys/nouveau_winsys_pipe.c | 4 +- 3 files changed, 80 insertions(+), 60 deletions(-) diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c index 4c235845b7a..6887ffa6886 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c @@ -79,37 +79,6 @@ nouveau_mem_alloc(struct nouveau_device *dev, unsigned size, unsigned align, return 0; } -static int -nouveau_bo_realloc_gpu(struct nouveau_bo_priv *nvbo, uint32_t flags, int size) -{ - int ret; - - if (nvbo->drm.size && nvbo->drm.size != size) { - nouveau_mem_free(nvbo->base.device, &nvbo->drm, &nvbo->map); - } - - if (size && !nvbo->drm.size) { - if (flags) { - nvbo->drm.flags = 0; - if (flags & NOUVEAU_BO_VRAM) - nvbo->drm.flags |= NOUVEAU_MEM_FB; - if (flags & NOUVEAU_BO_GART) - nvbo->drm.flags |= (NOUVEAU_MEM_AGP | - NOUVEAU_MEM_PCI); - nvbo->drm.flags |= NOUVEAU_MEM_MAPPED; - } - - ret = nouveau_mem_alloc(nvbo->base.device, size, - nvbo->drm.alignment, nvbo->drm.flags, - &nvbo->drm, &nvbo->map); - if (ret) { - assert(0); - } - } - - return 0; -} - static void nouveau_bo_tmp_del(void *priv) { @@ -183,26 +152,17 @@ nouveau_bo_new(struct nouveau_device *dev, uint32_t flags, int align, if (!nvbo) return -ENOMEM; nvbo->base.device = dev; + nvbo->base.size = size; + nvbo->base.handle = bo_to_ptr(nvbo); nvbo->drm.alignment = align; + nvbo->refcount = 1; - if (flags & NOUVEAU_BO_PIN) { - ret = nouveau_bo_realloc_gpu(nvbo, flags, size); - if (ret) { - free(nvbo); - return ret; - } - } else { - nvbo->sysmem = malloc(size); - if (!nvbo->sysmem) { - free(nvbo); - return -ENOMEM; - } + ret = nouveau_bo_set_status(&nvbo->base, flags); + if (ret) { + free(nvbo); + return ret; } - nvbo->base.size = size; - nvbo->base.offset = nvbo->drm.offset; - nvbo->base.handle = bo_to_ptr(nvbo); - nvbo->refcount = 1; *bo = &nvbo->base; return 0; } @@ -261,8 +221,7 @@ nouveau_bo_del(struct nouveau_bo **bo) if (nvbo->fence) nouveau_fence_wait(&nvbo->fence); - - nouveau_bo_realloc_gpu(nvbo, 0, 0); + nouveau_mem_free(nvbo->base.device, &nvbo->drm, &nvbo->map); if (nvbo->sysmem && !nvbo->user) free(nvbo->sysmem); free(nvbo); @@ -303,6 +262,66 @@ nouveau_bo_upload(struct nouveau_bo_priv *nvbo) return 0; } +int +nouveau_bo_set_status(struct nouveau_bo *bo, uint32_t flags) +{ + struct nouveau_bo_priv *nvbo = nouveau_bo(bo); + struct drm_nouveau_mem_alloc new; + void *new_map = NULL, *new_sysmem = NULL; + unsigned new_flags = 0, ret; + + assert(!bo->map); + + /* Check current memtype vs requested, if they match do nothing */ + if ((nvbo->drm.flags & NOUVEAU_MEM_FB) && (flags & NOUVEAU_BO_VRAM)) + return 0; + if ((nvbo->drm.flags & NOUVEAU_MEM_AGP) && (flags & NOUVEAU_BO_GART)) + return 0; + if (nvbo->drm.size == 0 && nvbo->sysmem && (flags & NOUVEAU_BO_LOCAL)) + return 0; + + memset(&new, 0x00, sizeof(new)); + + /* Allocate new memory */ + if (flags & NOUVEAU_BO_VRAM) + new_flags |= NOUVEAU_MEM_FB; + else + if (flags & NOUVEAU_BO_GART) + new_flags |= (NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI); + + if (new_flags) { + ret = nouveau_mem_alloc(bo->device, bo->size, + nvbo->drm.alignment, new_flags, + &new, &new_map); + if (ret) + return ret; + } else { + new_sysmem = malloc(bo->size); + } + + /* Copy old -> new */ + /*XXX: use M2MF */ + if (nvbo->sysmem || nvbo->map) { + nouveau_bo_map(bo, NOUVEAU_BO_RD); + memcpy(new_map, bo->map, bo->size); + nouveau_bo_unmap(bo); + } + + /* Free old memory */ + if (nvbo->fence) + nouveau_fence_wait(&nvbo->fence); + nouveau_mem_free(bo->device, &nvbo->drm, &nvbo->map); + if (nvbo->sysmem) + free(nvbo->sysmem); + + nvbo->drm = new; + nvbo->map = new_map; + nvbo->sysmem = new_sysmem; + bo->flags = flags; + bo->offset = nvbo->drm.offset; + return 0; +} + static int nouveau_bo_validate_user(struct nouveau_channel *chan, struct nouveau_bo *bo, struct nouveau_fence *fence, uint32_t flags) @@ -335,18 +354,14 @@ nouveau_bo_validate_bo(struct nouveau_channel *chan, struct nouveau_bo *bo, struct nouveau_fence *fence, uint32_t flags) { struct nouveau_bo_priv *nvbo = nouveau_bo(bo); + int ret; - if (!nvbo->drm.size) { - nouveau_bo_realloc_gpu(nvbo, flags, nvbo->base.size); - nouveau_bo_upload(nvbo); - if (!nvbo->user) { - free(nvbo->sysmem); - nvbo->sysmem = NULL; - } - } else - if (nvbo->user) { + ret = nouveau_bo_set_status(bo, flags); + if (ret) + return ret; + + if (nvbo->user) nouveau_bo_upload(nvbo); - } nvbo->offset = nvbo->drm.offset; if (nvbo->drm.flags & (NOUVEAU_MEM_AGP | NOUVEAU_MEM_PCI)) diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h b/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h index 7ea4c654654..67e19f1cfe8 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h @@ -274,6 +274,9 @@ nouveau_bo_user(struct nouveau_device *, void *ptr, int size, extern int nouveau_bo_ref(struct nouveau_device *, uint64_t handle, struct nouveau_bo **); +extern int +nouveau_bo_set_status(struct nouveau_bo *, uint32_t flags); + extern void nouveau_bo_del(struct nouveau_bo **); diff --git a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_pipe.c b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_pipe.c index f2087aaf9a2..7d7fefa8016 100644 --- a/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_pipe.c +++ b/src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_pipe.c @@ -90,6 +90,7 @@ nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment, struct nouveau_pipe_winsys *nvpws = (struct nouveau_pipe_winsys *)pws; struct nouveau_device *dev = nvpws->nv->nv_screen->device; struct nouveau_pipe_buffer *nvbuf; + uint32_t flags = 0; nvbuf = calloc(1, sizeof(*nvbuf)); if (!nvbuf) @@ -99,7 +100,8 @@ nouveau_pipe_bo_create(struct pipe_winsys *pws, unsigned alignment, nvbuf->base.usage = usage; nvbuf->base.size = size; - if (nouveau_bo_new(dev, NOUVEAU_BO_LOCAL, alignment, size, &nvbuf->bo)) { + flags = NOUVEAU_BO_LOCAL; + if (nouveau_bo_new(dev, flags, alignment, size, &nvbuf->bo)) { free(nvbuf); return NULL; } -- cgit v1.2.3