#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; }