diff options
Diffstat (limited to 'src/gallium/drivers/llvmpipe/lp_texture.c')
-rw-r--r-- | src/gallium/drivers/llvmpipe/lp_texture.c | 229 |
1 files changed, 131 insertions, 98 deletions
diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 8137f29af52..972c7ae7c30 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -37,11 +37,13 @@ #include "util/u_format.h" #include "util/u_math.h" #include "util/u_memory.h" +#include "util/u_transfer.h" #include "lp_context.h" #include "lp_screen.h" #include "lp_flush.h" #include "lp_texture.h" +#include "lp_setup.h" #include "lp_tile_size.h" #include "state_tracker/sw_winsys.h" @@ -51,10 +53,10 @@ * Simple, maximally packed layout. */ static boolean -llvmpipe_texture_layout(struct llvmpipe_screen *screen, - struct llvmpipe_texture *lpt) +llvmpipe_resource_layout(struct llvmpipe_screen *screen, + struct llvmpipe_resource *lpt) { - struct pipe_texture *pt = &lpt->base; + struct pipe_resource *pt = &lpt->base; unsigned level; unsigned width = pt->width0; unsigned height = pt->height0; @@ -92,7 +94,7 @@ llvmpipe_texture_layout(struct llvmpipe_screen *screen, static boolean llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, - struct llvmpipe_texture *lpt) + struct llvmpipe_resource *lpt) { struct sw_winsys *winsys = screen->winsys; @@ -103,7 +105,7 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, unsigned height = align(lpt->base.height0, TILE_SIZE); lpt->dt = winsys->displaytarget_create(winsys, - lpt->base.tex_usage, + lpt->base.bind, lpt->base.format, width, height, 16, @@ -113,12 +115,12 @@ llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, } -static struct pipe_texture * -llvmpipe_texture_create(struct pipe_screen *_screen, - const struct pipe_texture *templat) +static struct pipe_resource * +llvmpipe_resource_create(struct pipe_screen *_screen, + const struct pipe_resource *templat) { struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture); + struct llvmpipe_resource *lpt = CALLOC_STRUCT(llvmpipe_resource); if (!lpt) return NULL; @@ -126,17 +128,17 @@ llvmpipe_texture_create(struct pipe_screen *_screen, pipe_reference_init(&lpt->base.reference, 1); lpt->base.screen = &screen->base; - if (lpt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_SCANOUT | - PIPE_TEXTURE_USAGE_SHARED)) { + if (lpt->base.bind & (PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SCANOUT | + PIPE_BIND_SHARED)) { if (!llvmpipe_displaytarget_layout(screen, lpt)) goto fail; } else { - if (!llvmpipe_texture_layout(screen, lpt)) + if (!llvmpipe_resource_layout(screen, lpt)) goto fail; } - + return &lpt->base; fail: @@ -146,17 +148,18 @@ llvmpipe_texture_create(struct pipe_screen *_screen, static void -llvmpipe_texture_destroy(struct pipe_texture *pt) +llvmpipe_resource_destroy(struct pipe_screen *pscreen, + struct pipe_resource *pt) { - struct llvmpipe_screen *screen = llvmpipe_screen(pt->screen); - struct llvmpipe_texture *lpt = llvmpipe_texture(pt); + struct llvmpipe_screen *screen = llvmpipe_screen(pscreen); + struct llvmpipe_resource *lpt = llvmpipe_resource(pt); if (lpt->dt) { /* display target */ struct sw_winsys *winsys = screen->winsys; winsys->displaytarget_destroy(winsys, lpt->dt); } - else { + else if (!lpt->userBuffer) { /* regular texture */ align_free(lpt->data); } @@ -169,19 +172,19 @@ llvmpipe_texture_destroy(struct pipe_texture *pt) * Map a texture. Without any synchronization. */ void * -llvmpipe_texture_map(struct pipe_texture *texture, - unsigned face, - unsigned level, - unsigned zslice) +llvmpipe_resource_map(struct pipe_resource *texture, + unsigned usage, + unsigned face, + unsigned level, + unsigned zslice) { - struct llvmpipe_texture *lpt = llvmpipe_texture(texture); + struct llvmpipe_resource *lpt = llvmpipe_resource(texture); uint8_t *map; if (lpt->dt) { /* display target */ struct llvmpipe_screen *screen = llvmpipe_screen(texture->screen); struct sw_winsys *winsys = screen->winsys; - const unsigned usage = PIPE_BUFFER_USAGE_CPU_READ_WRITE; assert(face == 0); assert(level == 0); @@ -204,7 +207,7 @@ llvmpipe_texture_map(struct pipe_texture *texture, /* XXX shouldn't that rather be tex_height = align(u_minify(texture->height0, level), 2) - to account for alignment done in llvmpipe_texture_layout ? + to account for alignment done in llvmpipe_resource_layout ? */ if (texture->target == PIPE_TEXTURE_CUBE) { unsigned tex_height = u_minify(texture->height0, level); @@ -230,12 +233,12 @@ llvmpipe_texture_map(struct pipe_texture *texture, * Unmap a texture. Without any synchronization. */ void -llvmpipe_texture_unmap(struct pipe_texture *texture, +llvmpipe_resource_unmap(struct pipe_resource *texture, unsigned face, unsigned level, unsigned zslice) { - struct llvmpipe_texture *lpt = llvmpipe_texture(texture); + struct llvmpipe_resource *lpt = llvmpipe_resource(texture); if (lpt->dt) { /* display target */ @@ -251,13 +254,13 @@ llvmpipe_texture_unmap(struct pipe_texture *texture, } -static struct pipe_texture * -llvmpipe_texture_from_handle(struct pipe_screen *screen, - const struct pipe_texture *template, - struct winsys_handle *whandle) +static struct pipe_resource * +llvmpipe_resource_from_handle(struct pipe_screen *screen, + const struct pipe_resource *template, + struct winsys_handle *whandle) { struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; - struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture); + struct llvmpipe_resource *lpt = CALLOC_STRUCT(llvmpipe_resource); if (!lpt) return NULL; @@ -281,12 +284,12 @@ llvmpipe_texture_from_handle(struct pipe_screen *screen, static boolean -llvmpipe_texture_get_handle(struct pipe_screen *screen, - struct pipe_texture *pt, +llvmpipe_resource_get_handle(struct pipe_screen *screen, + struct pipe_resource *pt, struct winsys_handle *whandle) { struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; - struct llvmpipe_texture *lpt = llvmpipe_texture(pt); + struct llvmpipe_resource *lpt = llvmpipe_resource(pt); assert(lpt->dt); if (!lpt->dt) @@ -298,11 +301,10 @@ llvmpipe_texture_get_handle(struct pipe_screen *screen, static struct pipe_surface * llvmpipe_get_tex_surface(struct pipe_screen *screen, - struct pipe_texture *pt, + struct pipe_resource *pt, unsigned face, unsigned level, unsigned zslice, unsigned usage) { - struct llvmpipe_texture *lpt = llvmpipe_texture(pt); struct pipe_surface *ps; assert(level <= pt->last_level); @@ -310,32 +312,12 @@ llvmpipe_get_tex_surface(struct pipe_screen *screen, ps = CALLOC_STRUCT(pipe_surface); if (ps) { pipe_reference_init(&ps->reference, 1); - pipe_texture_reference(&ps->texture, pt); + pipe_resource_reference(&ps->texture, pt); ps->format = pt->format; ps->width = u_minify(pt->width0, level); ps->height = u_minify(pt->height0, level); ps->usage = usage; - /* Because we are llvmpipe, anything that the state tracker - * thought was going to be done with the GPU will actually get - * done with the CPU. Let's adjust the flags to take that into - * account. - */ - if (ps->usage & PIPE_BUFFER_USAGE_GPU_WRITE) { - /* GPU_WRITE means "render" and that can involve reads (blending) */ - ps->usage |= PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_CPU_READ; - } - - if (ps->usage & PIPE_BUFFER_USAGE_GPU_READ) - ps->usage |= PIPE_BUFFER_USAGE_CPU_READ; - - if (ps->usage & (PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_GPU_WRITE)) { - /* Mark the surface as dirty. */ - lpt->timestamp++; - llvmpipe_screen(screen)->timestamp++; - } - ps->face = face; ps->level = level; ps->zslice = zslice; @@ -352,37 +334,31 @@ llvmpipe_tex_surface_destroy(struct pipe_surface *surf) * where it would happen. For llvmpipe, nothing to do. */ assert(surf->texture); - pipe_texture_reference(&surf->texture, NULL); + pipe_resource_reference(&surf->texture, NULL); FREE(surf); } static struct pipe_transfer * -llvmpipe_get_tex_transfer(struct pipe_context *pipe, - struct pipe_texture *texture, - unsigned face, unsigned level, unsigned zslice, - enum pipe_transfer_usage usage, - unsigned x, unsigned y, unsigned w, unsigned h) +llvmpipe_get_transfer(struct pipe_context *pipe, + struct pipe_resource *resource, + struct pipe_subresource sr, + unsigned usage, + const struct pipe_box *box) { - struct llvmpipe_texture *lptex = llvmpipe_texture(texture); + struct llvmpipe_resource *lptex = llvmpipe_resource(resource); struct llvmpipe_transfer *lpt; - assert(texture); - assert(level <= texture->last_level); + assert(resource); + assert(sr.level <= resource->last_level); lpt = CALLOC_STRUCT(llvmpipe_transfer); if (lpt) { struct pipe_transfer *pt = &lpt->base; - pipe_texture_reference(&pt->texture, texture); - pt->x = x; - pt->y = y; - pt->width = align(w, TILE_SIZE); - pt->height = align(h, TILE_SIZE); - pt->stride = lptex->stride[level]; + pipe_resource_reference(&pt->resource, resource); + pt->box = *box; + pt->stride = lptex->stride[sr.level]; pt->usage = usage; - pt->face = face; - pt->level = level; - pt->zslice = zslice; return pt; } @@ -391,15 +367,15 @@ llvmpipe_get_tex_transfer(struct pipe_context *pipe, static void -llvmpipe_tex_transfer_destroy(struct pipe_context *pipe, +llvmpipe_transfer_destroy(struct pipe_context *pipe, struct pipe_transfer *transfer) { /* Effectively do the texture_update work here - if texture images * needed post-processing to put them into hardware layout, this is * where it would happen. For llvmpipe, nothing to do. */ - assert (transfer->texture); - pipe_texture_reference(&transfer->texture, NULL); + assert (transfer->resource); + pipe_resource_reference(&transfer->resource, NULL); FREE(transfer); } @@ -410,11 +386,11 @@ llvmpipe_transfer_map( struct pipe_context *pipe, { struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); ubyte *map; - struct llvmpipe_texture *lpt; + struct llvmpipe_resource *lpt; enum pipe_format format; - assert(transfer->texture); - lpt = llvmpipe_texture(transfer->texture); + assert(transfer->resource); + lpt = llvmpipe_resource(transfer->resource); format = lpt->base.format; /* @@ -422,14 +398,19 @@ llvmpipe_transfer_map( struct pipe_context *pipe, * context if necessary. */ llvmpipe_flush_texture(pipe, - transfer->texture, transfer->face, transfer->level, + transfer->resource, + transfer->sr.face, + transfer->sr.level, 0, /* flush_flags */ !(transfer->usage & PIPE_TRANSFER_WRITE), /* read_only */ TRUE, /* cpu_access */ FALSE); /* do_not_flush */ - map = llvmpipe_texture_map(transfer->texture, - transfer->face, transfer->level, transfer->zslice); + map = llvmpipe_resource_map(transfer->resource, + transfer->usage, + transfer->sr.face, + transfer->sr.level, + transfer->box.z); /* May want to different things here depending on read/write nature * of the map: @@ -441,8 +422,8 @@ llvmpipe_transfer_map( struct pipe_context *pipe, } map += - transfer->y / util_format_get_blockheight(format) * transfer->stride + - transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); + transfer->box.y / util_format_get_blockheight(format) * transfer->stride + + transfer->box.x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); return map; } @@ -452,20 +433,68 @@ static void llvmpipe_transfer_unmap(struct pipe_context *pipe, struct pipe_transfer *transfer) { - assert(transfer->texture); + assert(transfer->resource); + + llvmpipe_resource_unmap(transfer->resource, + transfer->sr.face, + transfer->sr.level, + transfer->box.z); +} + +static unsigned int +llvmpipe_is_resource_referenced( struct pipe_context *pipe, + struct pipe_resource *presource, + unsigned face, unsigned level) +{ + struct llvmpipe_context *llvmpipe = llvmpipe_context( pipe ); + + if (presource->target == PIPE_BUFFER) + return PIPE_UNREFERENCED; + + return lp_setup_is_resource_referenced(llvmpipe->setup, presource); +} + + + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_resource * +llvmpipe_user_buffer_create(struct pipe_screen *screen, + void *ptr, + unsigned bytes, + unsigned bind_flags) +{ + struct llvmpipe_resource *buffer; + + buffer = CALLOC_STRUCT(llvmpipe_resource); + if(!buffer) + return NULL; - llvmpipe_texture_unmap(transfer->texture, - transfer->face, transfer->level, transfer->zslice); + pipe_reference_init(&buffer->base.reference, 1); + buffer->base.screen = screen; + buffer->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */ + buffer->base.bind = bind_flags; + buffer->base._usage = PIPE_USAGE_IMMUTABLE; + buffer->base.flags = 0; + buffer->base.width0 = bytes; + buffer->base.height0 = 1; + buffer->base.depth0 = 1; + buffer->userBuffer = TRUE; + buffer->data = ptr; + + return &buffer->base; } void -llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen) +llvmpipe_init_screen_resource_funcs(struct pipe_screen *screen) { - screen->texture_create = llvmpipe_texture_create; - screen->texture_destroy = llvmpipe_texture_destroy; - screen->texture_from_handle = llvmpipe_texture_from_handle; - screen->texture_get_handle = llvmpipe_texture_get_handle; + screen->resource_create = llvmpipe_resource_create; + screen->resource_destroy = llvmpipe_resource_destroy; + screen->resource_from_handle = llvmpipe_resource_from_handle; + screen->resource_get_handle = llvmpipe_resource_get_handle; + screen->user_buffer_create = llvmpipe_user_buffer_create; screen->get_tex_surface = llvmpipe_get_tex_surface; screen->tex_surface_destroy = llvmpipe_tex_surface_destroy; @@ -473,10 +502,14 @@ llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen) void -llvmpipe_init_context_texture_funcs(struct pipe_context *pipe) +llvmpipe_init_context_resource_funcs(struct pipe_context *pipe) { - pipe->get_tex_transfer = llvmpipe_get_tex_transfer; - pipe->tex_transfer_destroy = llvmpipe_tex_transfer_destroy; + pipe->get_transfer = llvmpipe_get_transfer; + pipe->transfer_destroy = llvmpipe_transfer_destroy; pipe->transfer_map = llvmpipe_transfer_map; pipe->transfer_unmap = llvmpipe_transfer_unmap; + pipe->is_resource_referenced = llvmpipe_is_resource_referenced; + + pipe->transfer_flush_region = u_default_transfer_flush_region; + pipe->transfer_inline_write = u_default_transfer_inline_write; } |