summaryrefslogtreecommitdiff
path: root/src/gallium/drivers/nvc0/nvc0_buffer.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/drivers/nvc0/nvc0_buffer.c')
-rw-r--r--src/gallium/drivers/nvc0/nvc0_buffer.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/src/gallium/drivers/nvc0/nvc0_buffer.c b/src/gallium/drivers/nvc0/nvc0_buffer.c
new file mode 100644
index 0000000000..873016f0d5
--- /dev/null
+++ b/src/gallium/drivers/nvc0/nvc0_buffer.c
@@ -0,0 +1,166 @@
+
+#include "util/u_inlines.h"
+#include "util/u_memory.h"
+#include "util/u_math.h"
+
+#define NOUVEAU_NVC0
+#include "nouveau/nouveau_screen.h"
+#include "nouveau/nouveau_winsys.h"
+#undef NOUVEAU_NVC0
+
+#include "nvc0_context.h"
+#include "nvc0_resource.h"
+
+static void
+nvc0_buffer_destroy(struct pipe_screen *pscreen,
+ struct pipe_resource *presource)
+{
+ struct nvc0_resource *res = nvc0_resource(presource);
+
+ if (res->bo)
+ nouveau_screen_bo_release(pscreen, res->bo);
+
+ if (res->data)
+ FREE(res->data);
+
+ FREE(res);
+}
+
+static void *
+nvc0_buffer_transfer_map(struct pipe_context *pipe,
+ struct pipe_transfer *transfer)
+{
+ struct nvc0_resource *res = nvc0_resource(transfer->resource);
+ uint8_t *map;
+ uint32_t flags;
+
+ if (res->base.bind & PIPE_BIND_VERTEX_BUFFER)
+ nvc0_context(pipe)->vbo_dirty = TRUE;
+
+// #ifdef NOUVEAU_USERPSACE_MM
+ if (res->base.bind & PIPE_BIND_CONSTANT_BUFFER)
+ return res->data + transfer->box.x;
+// #endif
+ flags = nouveau_screen_transfer_flags(transfer->usage);
+
+ map = nouveau_screen_bo_map_range(pipe->screen,
+ res->bo,
+ transfer->box.x, transfer->box.width,
+ flags);
+ if (!map)
+ return NULL;
+
+ return map + transfer->box.x;
+}
+
+
+
+static void
+nvc0_buffer_transfer_flush_region(struct pipe_context *pipe,
+ struct pipe_transfer *transfer,
+ const struct pipe_box *box)
+{
+ struct nvc0_resource *res = nvc0_resource(transfer->resource);
+
+#ifdef NOUVEAU_USERPSACE_MM
+ if (!res->bo)
+ return;
+#endif
+ nouveau_screen_bo_map_flush_range(pipe->screen,
+ res->bo,
+ transfer->box.x + box->x,
+ box->width);
+}
+
+static void
+nvc0_buffer_transfer_unmap(struct pipe_context *pipe,
+ struct pipe_transfer *transfer)
+{
+ struct nvc0_resource *res = nvc0_resource(transfer->resource);
+
+// #ifdef NOUVEAU_USERPSACE_MM
+ if (res->data)
+ return;
+// #endif
+ nouveau_screen_bo_unmap(pipe->screen, res->bo);
+}
+
+const struct u_resource_vtbl nvc0_buffer_vtbl =
+{
+ u_default_resource_get_handle, /* get_handle */
+ nvc0_buffer_destroy, /* resource_destroy */
+ NULL, /* is_resource_referenced */
+ u_default_get_transfer, /* get_transfer */
+ u_default_transfer_destroy, /* transfer_destroy */
+ nvc0_buffer_transfer_map, /* transfer_map */
+ nvc0_buffer_transfer_flush_region, /* transfer_flush_region */
+ nvc0_buffer_transfer_unmap, /* transfer_unmap */
+ u_default_transfer_inline_write /* transfer_inline_write */
+};
+
+struct pipe_resource *
+nvc0_buffer_create(struct pipe_screen *pscreen,
+ const struct pipe_resource *templ)
+{
+ struct nvc0_resource *buffer;
+
+ buffer = CALLOC_STRUCT(nvc0_resource);
+ if (!buffer)
+ return NULL;
+
+ buffer->base = *templ;
+ buffer->vtbl = &nvc0_buffer_vtbl;
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->base.screen = pscreen;
+
+ if (buffer->base.bind & PIPE_BIND_CONSTANT_BUFFER)
+ buffer->data = MALLOC(buffer->base.width0);
+
+ buffer->bo = nouveau_screen_bo_new(pscreen,
+ 16,
+ buffer->base.usage,
+ buffer->base.bind,
+ buffer->base.width0);
+ if (buffer->bo == NULL)
+ goto fail;
+
+ return &buffer->base;
+
+fail:
+ FREE(buffer);
+ return NULL;
+}
+
+
+struct pipe_resource *
+nvc0_user_buffer_create(struct pipe_screen *pscreen,
+ void *ptr,
+ unsigned bytes,
+ unsigned bind)
+{
+ struct nvc0_resource *buffer;
+
+ buffer = CALLOC_STRUCT(nvc0_resource);
+ if (!buffer)
+ return NULL;
+
+ pipe_reference_init(&buffer->base.reference, 1);
+ buffer->vtbl = &nvc0_buffer_vtbl;
+ buffer->base.screen = pscreen;
+ buffer->base.format = PIPE_FORMAT_R8_UNORM;
+ buffer->base.usage = PIPE_USAGE_IMMUTABLE;
+ buffer->base.bind = bind;
+ buffer->base.width0 = bytes;
+ buffer->base.height0 = 1;
+ buffer->base.depth0 = 1;
+
+ buffer->bo = nouveau_screen_bo_user(pscreen, ptr, bytes);
+ if (!buffer->bo)
+ goto fail;
+
+ return &buffer->base;
+
+fail:
+ FREE(buffer);
+ return NULL;
+}