X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=blobdiff_plain;f=src%2Fgallium%2Fdrivers%2Fllvmpipe%2Flp_texture.c;h=93ad789c35d216ccb8cb54cc85c8eabcda9310ca;hp=7f45635542897470e7606f6ca60624194d16d964;hb=f0f04cd12db156ec53b7ea46fae27199af121f90;hpb=4ca70c489baed3e23dbf5e5e5794385113e22252 diff --git a/src/gallium/drivers/llvmpipe/lp_texture.c b/src/gallium/drivers/llvmpipe/lp_texture.c index 7f456355428..93ad789c35d 100644 --- a/src/gallium/drivers/llvmpipe/lp_texture.c +++ b/src/gallium/drivers/llvmpipe/lp_texture.c @@ -40,9 +40,10 @@ #include "lp_context.h" #include "lp_screen.h" +#include "lp_flush.h" #include "lp_texture.h" #include "lp_tile_size.h" -#include "lp_winsys.h" +#include "state_tracker/sw_winsys.h" /** @@ -93,7 +94,7 @@ static boolean llvmpipe_displaytarget_layout(struct llvmpipe_screen *screen, struct llvmpipe_texture *lpt) { - struct llvmpipe_winsys *winsys = screen->winsys; + struct sw_winsys *winsys = screen->winsys; /* Round up the surface size to a multiple of the tile size to * avoid tile clipping. @@ -102,6 +103,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.format, width, height, 16, @@ -125,7 +127,8 @@ llvmpipe_texture_create(struct pipe_screen *_screen, lpt->base.screen = &screen->base; if (lpt->base.tex_usage & (PIPE_TEXTURE_USAGE_DISPLAY_TARGET | - PIPE_TEXTURE_USAGE_PRIMARY)) { + PIPE_TEXTURE_USAGE_SCANOUT | + PIPE_TEXTURE_USAGE_SHARED)) { if (!llvmpipe_displaytarget_layout(screen, lpt)) goto fail; } @@ -142,60 +145,154 @@ llvmpipe_texture_create(struct pipe_screen *_screen, } -static struct pipe_texture * -llvmpipe_texture_blanket(struct pipe_screen * screen, - const struct pipe_texture *base, - const unsigned *stride, - struct pipe_buffer *buffer) +static void +llvmpipe_texture_destroy(struct pipe_texture *pt) { - /* FIXME */ -#if 0 - struct llvmpipe_texture *lpt; - assert(screen); + struct llvmpipe_screen *screen = llvmpipe_screen(pt->screen); + struct llvmpipe_texture *lpt = llvmpipe_texture(pt); - /* Only supports one type */ - if (base->target != PIPE_TEXTURE_2D || - base->last_level != 0 || - base->depth0 != 1) { - return NULL; + if (lpt->dt) { + /* display target */ + struct sw_winsys *winsys = screen->winsys; + winsys->displaytarget_destroy(winsys, lpt->dt); + } + else { + /* regular texture */ + align_free(lpt->data); + } + + FREE(lpt); +} + + +/** + * Map a texture. Without any synchronization. + */ +void * +llvmpipe_texture_map(struct pipe_texture *texture, + unsigned face, + unsigned level, + unsigned zslice) +{ + struct llvmpipe_texture *lpt = llvmpipe_texture(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); + assert(zslice == 0); + + /* FIXME: keep map count? */ + map = winsys->displaytarget_map(winsys, lpt->dt, usage); } + else { + /* regular texture */ + unsigned offset; + unsigned stride; + + map = lpt->data; + + assert(level < LP_MAX_TEXTURE_2D_LEVELS); + + offset = lpt->level_offset[level]; + stride = lpt->stride[level]; + + /* XXX shouldn't that rather be + tex_height = align(u_minify(texture->height0, level), 2) + to account for alignment done in llvmpipe_texture_layout ? + */ + if (texture->target == PIPE_TEXTURE_CUBE) { + unsigned tex_height = u_minify(texture->height0, level); + offset += face * util_format_get_nblocksy(texture->format, tex_height) * stride; + } + else if (texture->target == PIPE_TEXTURE_3D) { + unsigned tex_height = u_minify(texture->height0, level); + offset += zslice * util_format_get_nblocksy(texture->format, tex_height) * stride; + } + else { + assert(face == 0); + assert(zslice == 0); + } + + map += offset; + } + + return map; +} + + +/** + * Unmap a texture. Without any synchronization. + */ +void +llvmpipe_texture_unmap(struct pipe_texture *texture, + unsigned face, + unsigned level, + unsigned zslice) +{ + struct llvmpipe_texture *lpt = llvmpipe_texture(texture); + + if (lpt->dt) { + /* display target */ + struct llvmpipe_screen *lp_screen = llvmpipe_screen(texture->screen); + struct sw_winsys *winsys = lp_screen->winsys; + + assert(face == 0); + assert(level == 0); + assert(zslice == 0); + + winsys->displaytarget_unmap(winsys, lpt->dt); + } +} - lpt = CALLOC_STRUCT(llvmpipe_texture); + +static struct pipe_texture * +llvmpipe_texture_from_handle(struct pipe_screen *screen, + const struct pipe_texture *template, + struct winsys_handle *whandle) +{ + struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; + struct llvmpipe_texture *lpt = CALLOC_STRUCT(llvmpipe_texture); if (!lpt) return NULL; - lpt->base = *base; + lpt->base = *template; pipe_reference_init(&lpt->base.reference, 1); lpt->base.screen = screen; - lpt->stride[0] = stride[0]; - pipe_buffer_reference(&lpt->buffer, buffer); + lpt->dt = winsys->displaytarget_from_handle(winsys, + template, + whandle, + &lpt->stride[0]); + if (!lpt->dt) + goto fail; return &lpt->base; -#else - debug_printf("llvmpipe_texture_blanket() not implemented!"); + + fail: + FREE(lpt); return NULL; -#endif } -static void -llvmpipe_texture_destroy(struct pipe_texture *pt) +static boolean +llvmpipe_texture_get_handle(struct pipe_screen *screen, + struct pipe_texture *pt, + struct winsys_handle *whandle) { - struct llvmpipe_screen *screen = llvmpipe_screen(pt->screen); + struct sw_winsys *winsys = llvmpipe_screen(screen)->winsys; struct llvmpipe_texture *lpt = llvmpipe_texture(pt); - if (lpt->dt) { - /* display target */ - struct llvmpipe_winsys *winsys = screen->winsys; - winsys->displaytarget_destroy(winsys, lpt->dt); - } - else { - /* regular texture */ - align_free(lpt->data); - } + assert(lpt->dt); + if (!lpt->dt) + return FALSE; - FREE(lpt); + return winsys->displaytarget_get_handle(winsys, lpt->dt, whandle); } @@ -217,7 +314,6 @@ llvmpipe_get_tex_surface(struct pipe_screen *screen, ps->format = pt->format; ps->width = u_minify(pt->width0, level); ps->height = u_minify(pt->height0, level); - ps->offset = lpt->level_offset[level]; ps->usage = usage; /* Because we are llvmpipe, anything that the state tracker @@ -243,23 +339,6 @@ llvmpipe_get_tex_surface(struct pipe_screen *screen, ps->face = face; ps->level = level; ps->zslice = zslice; - - /* XXX shouldn't that rather be - tex_height = align(ps->height, 2); - to account for alignment done in llvmpipe_texture_layout ? - */ - if (pt->target == PIPE_TEXTURE_CUBE) { - unsigned tex_height = ps->height; - ps->offset += face * util_format_get_nblocksy(pt->format, tex_height) * lpt->stride[level]; - } - else if (pt->target == PIPE_TEXTURE_3D) { - unsigned tex_height = ps->height; - ps->offset += zslice * util_format_get_nblocksy(pt->format, tex_height) * lpt->stride[level]; - } - else { - assert(face == 0); - assert(zslice == 0); - } } return ps; } @@ -279,7 +358,7 @@ llvmpipe_tex_surface_destroy(struct pipe_surface *surf) static struct pipe_transfer * -llvmpipe_get_tex_transfer(struct pipe_screen *screen, +llvmpipe_get_tex_transfer(struct pipe_context *pipe, struct pipe_texture *texture, unsigned face, unsigned level, unsigned zslice, enum pipe_transfer_usage usage, @@ -305,24 +384,6 @@ llvmpipe_get_tex_transfer(struct pipe_screen *screen, pt->level = level; pt->zslice = zslice; - lpt->offset = lptex->level_offset[level]; - - /* XXX shouldn't that rather be - tex_height = align(u_minify(texture->height0, level), 2) - to account for alignment done in llvmpipe_texture_layout ? - */ - if (texture->target == PIPE_TEXTURE_CUBE) { - unsigned tex_height = u_minify(texture->height0, level); - lpt->offset += face * util_format_get_nblocksy(texture->format, tex_height) * pt->stride; - } - else if (texture->target == PIPE_TEXTURE_3D) { - unsigned tex_height = u_minify(texture->height0, level); - lpt->offset += zslice * util_format_get_nblocksy(texture->format, tex_height) * pt->stride; - } - else { - assert(face == 0); - assert(zslice == 0); - } return pt; } return NULL; @@ -330,7 +391,8 @@ llvmpipe_get_tex_transfer(struct pipe_screen *screen, static void -llvmpipe_tex_transfer_destroy(struct pipe_transfer *transfer) +llvmpipe_tex_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 @@ -343,11 +405,11 @@ llvmpipe_tex_transfer_destroy(struct pipe_transfer *transfer) static void * -llvmpipe_transfer_map( struct pipe_screen *_screen, +llvmpipe_transfer_map( struct pipe_context *pipe, struct pipe_transfer *transfer ) { - struct llvmpipe_screen *screen = llvmpipe_screen(_screen); - ubyte *map, *xfer_map; + struct llvmpipe_screen *screen = llvmpipe_screen(pipe->screen); + ubyte *map; struct llvmpipe_texture *lpt; enum pipe_format format; @@ -355,52 +417,45 @@ llvmpipe_transfer_map( struct pipe_screen *_screen, lpt = llvmpipe_texture(transfer->texture); format = lpt->base.format; - if (lpt->dt) { - /* display target */ - struct llvmpipe_winsys *winsys = screen->winsys; + /* + * Transfers, like other pipe operations, must happen in order, so flush the + * context if necessary. + */ + llvmpipe_flush_texture(pipe, + transfer->texture, transfer->face, transfer->level, + 0, /* flush_flags */ + !(transfer->usage & PIPE_TRANSFER_WRITE), /* read_only */ + TRUE, /* cpu_access */ + FALSE); /* do_not_flush */ - map = winsys->displaytarget_map(winsys, lpt->dt, - pipe_transfer_buffer_flags(transfer)); - if (map == NULL) - return NULL; - } - else { - /* regular texture */ - map = lpt->data; - } + map = llvmpipe_texture_map(transfer->texture, + transfer->face, transfer->level, transfer->zslice); /* May want to different things here depending on read/write nature * of the map: */ - if (transfer->texture && (transfer->usage & PIPE_TRANSFER_WRITE)) { + if (transfer->usage & PIPE_TRANSFER_WRITE) { /* Do something to notify sharing contexts of a texture change. */ screen->timestamp++; } - xfer_map = map + llvmpipe_transfer(transfer)->offset + + map += transfer->y / util_format_get_blockheight(format) * transfer->stride + transfer->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); - /*printf("map = %p xfer map = %p\n", map, xfer_map);*/ - return xfer_map; + + return map; } static void -llvmpipe_transfer_unmap(struct pipe_screen *screen, - struct pipe_transfer *transfer) +llvmpipe_transfer_unmap(struct pipe_context *pipe, + struct pipe_transfer *transfer) { - struct llvmpipe_screen *lp_screen = llvmpipe_screen(screen); - struct llvmpipe_texture *lpt; - assert(transfer->texture); - lpt = llvmpipe_texture(transfer->texture); - if (lpt->dt) { - /* display target */ - struct llvmpipe_winsys *winsys = lp_screen->winsys; - winsys->displaytarget_unmap(winsys, lpt->dt); - } + llvmpipe_texture_unmap(transfer->texture, + transfer->face, transfer->level, transfer->zslice); } @@ -408,14 +463,19 @@ void llvmpipe_init_screen_texture_funcs(struct pipe_screen *screen) { screen->texture_create = llvmpipe_texture_create; - screen->texture_blanket = llvmpipe_texture_blanket; screen->texture_destroy = llvmpipe_texture_destroy; + screen->texture_get_handle = llvmpipe_texture_get_handle; screen->get_tex_surface = llvmpipe_get_tex_surface; screen->tex_surface_destroy = llvmpipe_tex_surface_destroy; +} + - screen->get_tex_transfer = llvmpipe_get_tex_transfer; - screen->tex_transfer_destroy = llvmpipe_tex_transfer_destroy; - screen->transfer_map = llvmpipe_transfer_map; - screen->transfer_unmap = llvmpipe_transfer_unmap; +void +llvmpipe_init_context_texture_funcs(struct pipe_context *pipe) +{ + pipe->get_tex_transfer = llvmpipe_get_tex_transfer; + pipe->tex_transfer_destroy = llvmpipe_tex_transfer_destroy; + pipe->transfer_map = llvmpipe_transfer_map; + pipe->transfer_unmap = llvmpipe_transfer_unmap; }