diff options
Diffstat (limited to 'src/gallium/drivers/softpipe/sp_texture.c')
-rw-r--r-- | src/gallium/drivers/softpipe/sp_texture.c | 174 |
1 files changed, 110 insertions, 64 deletions
diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index a64dc89f43..28a9784b16 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -33,7 +33,7 @@ #include "pipe/p_context.h" #include "pipe/p_defines.h" #include "pipe/p_inlines.h" -#include "pipe/p_winsys.h" +#include "pipe/internal/p_winsys_screen.h" #include "util/u_math.h" #include "util/u_memory.h" @@ -94,49 +94,23 @@ softpipe_texture_layout(struct pipe_screen *screen, return spt->buffer != NULL; } -/* Hack it up to use the old winsys->surface_alloc_storage() - * method for now: - */ static boolean softpipe_displaytarget_layout(struct pipe_screen *screen, struct softpipe_texture * spt) { struct pipe_winsys *ws = screen->winsys; - struct pipe_surface surf; - unsigned flags = (PIPE_BUFFER_USAGE_CPU_READ | - PIPE_BUFFER_USAGE_CPU_WRITE | - PIPE_BUFFER_USAGE_GPU_READ | - PIPE_BUFFER_USAGE_GPU_WRITE); - int ret; - - - memset(&surf, 0, sizeof(surf)); - - ret =ws->surface_alloc_storage( ws, - &surf, - spt->base.width[0], - spt->base.height[0], - spt->base.format, - flags, - spt->base.tex_usage); - if(ret != 0) - return FALSE; - - if (!surf.buffer) { - /* allocation failed */ - return FALSE; - } + unsigned usage = (PIPE_BUFFER_USAGE_CPU_READ_WRITE | + PIPE_BUFFER_USAGE_GPU_READ_WRITE); - /* Now extract the goodies: - */ spt->base.nblocksx[0] = pf_get_nblocksx(&spt->base.block, spt->base.width[0]); spt->base.nblocksy[0] = pf_get_nblocksy(&spt->base.block, spt->base.height[0]); - spt->stride[0] = surf.stride; - /* Transfer the reference: - */ - spt->buffer = surf.buffer; - surf.buffer = NULL; + spt->buffer = ws->surface_buffer_create( ws, + spt->base.width[0], + spt->base.height[0], + spt->base.format, + usage, + &spt->stride[0]); return spt->buffer != NULL; } @@ -231,28 +205,21 @@ softpipe_get_tex_surface(struct pipe_screen *screen, unsigned face, unsigned level, unsigned zslice, unsigned usage) { - struct pipe_winsys *ws = screen->winsys; struct softpipe_texture *spt = softpipe_texture(pt); struct pipe_surface *ps; assert(level <= pt->last_level); ps = CALLOC_STRUCT(pipe_surface); - ps->refcount = 1; if (ps) { - assert(ps->refcount); + ps->refcount = 1; pipe_texture_reference(&ps->texture, pt); - pipe_buffer_reference(screen, &ps->buffer, spt->buffer); ps->format = pt->format; - ps->block = pt->block; ps->width = pt->width[level]; ps->height = pt->height[level]; - ps->nblocksx = pt->nblocksx[level]; - ps->nblocksy = pt->nblocksy[level]; - ps->stride = spt->stride[level]; ps->offset = spt->level_offset[level]; ps->usage = usage; - + /* Because we are softpipe, 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 @@ -278,8 +245,7 @@ softpipe_get_tex_surface(struct pipe_screen *screen, if (pt->target == PIPE_TEXTURE_CUBE || pt->target == PIPE_TEXTURE_3D) { ps->offset += ((pt->target == PIPE_TEXTURE_CUBE) ? face : zslice) * - ps->nblocksy * - ps->stride; + pt->nblocksy[level] * spt->stride[level]; } else { assert(face == 0); @@ -299,37 +265,108 @@ softpipe_tex_surface_release(struct pipe_screen *screen, * needed post-processing to put them into hardware layout, this is * where it would happen. For softpipe, nothing to do. */ - assert ((*s)->texture); + assert(surf->texture); if (--surf->refcount == 0) { - pipe_texture_reference(&surf->texture, NULL); - pipe_buffer_reference(screen, &surf->buffer, NULL); + pipe_texture_reference(&surf->texture, NULL); FREE(surf); } *s = NULL; } +static struct pipe_transfer * +softpipe_get_tex_transfer(struct pipe_screen *screen, + struct pipe_texture *texture, + unsigned face, unsigned level, unsigned zslice, + enum pipe_transfer_usage usage, + unsigned x, unsigned y, unsigned w, unsigned h) +{ + struct softpipe_texture *sptex = softpipe_texture(texture); + struct softpipe_transfer *spt; + struct pipe_transfer *pt; + + assert(texture); + assert(level <= texture->last_level); + + spt = CALLOC_STRUCT(softpipe_transfer); + pt = &spt->base; + if (spt) { + pt->refcount = 1; + pipe_texture_reference(&pt->texture, texture); + pt->format = texture->format; + pt->block = texture->block; + pt->x = x; + pt->y = y; + pt->width = w; + pt->height = h; + pt->nblocksx = texture->nblocksx[level]; + pt->nblocksy = texture->nblocksy[level]; + pt->stride = sptex->stride[level]; + spt->offset = sptex->level_offset[level]; + pt->usage = usage; + pt->face = face; + pt->level = level; + pt->zslice = zslice; + + if (texture->target == PIPE_TEXTURE_CUBE || + texture->target == PIPE_TEXTURE_3D) { + spt->offset += ((texture->target == PIPE_TEXTURE_CUBE) ? face : + zslice) * pt->nblocksy * pt->stride; + } + else { + assert(face == 0); + assert(zslice == 0); + } + } + return pt; +} + + +static void +softpipe_tex_transfer_release(struct pipe_screen *screen, + struct pipe_transfer **t) +{ + struct softpipe_transfer *transfer = softpipe_transfer(*t); + /* 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 softpipe, nothing to do. + */ + assert (transfer->base.texture); + if (--transfer->base.refcount == 0) { + pipe_texture_reference(&transfer->base.texture, NULL); + FREE(transfer); + } + *t = NULL; +} + + static void * -softpipe_surface_map( struct pipe_screen *screen, - struct pipe_surface *surface, - unsigned flags ) +softpipe_transfer_map( struct pipe_screen *screen, + struct pipe_transfer *transfer ) { ubyte *map; + struct softpipe_texture *spt; + unsigned flags = 0; - if (flags & ~surface->usage) { - assert(0); - return NULL; + assert(transfer->texture); + spt = softpipe_texture(transfer->texture); + + if (transfer->usage != PIPE_TRANSFER_READ) { + flags |= PIPE_BUFFER_USAGE_CPU_WRITE; + } + + if (transfer->usage != PIPE_TRANSFER_WRITE) { + flags |= PIPE_BUFFER_USAGE_CPU_READ; } - map = pipe_buffer_map( screen, surface->buffer, flags ); + map = pipe_buffer_map(screen, spt->buffer, flags); if (map == NULL) return NULL; /* May want to different things here depending on read/write nature * of the map: */ - if (surface->texture && - (flags & PIPE_BUFFER_USAGE_CPU_WRITE)) + if (transfer->texture && transfer->usage != PIPE_TRANSFER_READ) { /* Do something to notify sharing contexts of a texture change. * In softpipe, that would mean flushing the texture cache. @@ -337,15 +374,22 @@ softpipe_surface_map( struct pipe_screen *screen, softpipe_screen(screen)->timestamp++; } - return map + surface->offset; + return map + softpipe_transfer(transfer)->offset + + transfer->y / transfer->block.height * transfer->stride + + transfer->x / transfer->block.width * transfer->block.size; } static void -softpipe_surface_unmap(struct pipe_screen *screen, - struct pipe_surface *surface) +softpipe_transfer_unmap(struct pipe_screen *screen, + struct pipe_transfer *transfer) { - pipe_buffer_unmap( screen, surface->buffer ); + struct softpipe_texture *spt; + + assert(transfer->texture); + spt = softpipe_texture(transfer->texture); + + pipe_buffer_unmap( screen, spt->buffer ); } @@ -365,6 +409,8 @@ softpipe_init_screen_texture_funcs(struct pipe_screen *screen) screen->get_tex_surface = softpipe_get_tex_surface; screen->tex_surface_release = softpipe_tex_surface_release; - screen->surface_map = softpipe_surface_map; - screen->surface_unmap = softpipe_surface_unmap; + screen->get_tex_transfer = softpipe_get_tex_transfer; + screen->tex_transfer_release = softpipe_tex_transfer_release; + screen->transfer_map = softpipe_transfer_map; + screen->transfer_unmap = softpipe_transfer_unmap; } |