summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Skeggs <skeggsb@gmail.com>2008-02-02 14:21:06 +1100
committerBen Skeggs <skeggsb@gmail.com>2008-02-02 14:22:24 +1100
commitedbeec2b9177fef27b5a04b7b9b975b8abf84367 (patch)
tree6abb4c81dfaa8f4790bcb60961fef40f78e025cf
parent1bcd6b8ff9c25a0d8c2d15c365000a50e643b303 (diff)
nouveau: implement a bo_set_status()
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_bo.c133
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_drmif.h3
-rw-r--r--src/mesa/drivers/dri/nouveau_winsys/nouveau_winsys_pipe.c4
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;
}