diff options
Diffstat (limited to 'src/gallium/drivers/softpipe')
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_clear.c | 10 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_flush.c | 68 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_flush.h | 17 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_screen.c | 75 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_tex_tile_cache.c | 3 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_texture.c | 144 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_tile_cache.c | 12 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_tile_cache.h | 2 |
8 files changed, 227 insertions, 104 deletions
diff --git a/src/gallium/drivers/softpipe/sp_clear.c b/src/gallium/drivers/softpipe/sp_clear.c index 5f130453c3..ae3f00f338 100644 --- a/src/gallium/drivers/softpipe/sp_clear.c +++ b/src/gallium/drivers/softpipe/sp_clear.c @@ -69,11 +69,6 @@ softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, util_pack_color(rgba, ps->format, &uc); sp_tile_cache_clear(softpipe->cbuf_cache[i], rgba, uc.ui); - -#if !TILE_CLEAR_OPTIMIZATION - /* non-cached surface */ - pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, uc.ui); -#endif } } @@ -83,11 +78,6 @@ softpipe_clear(struct pipe_context *pipe, unsigned buffers, const float *rgba, cv = util_pack_z_stencil(ps->format, depth, stencil); sp_tile_cache_clear(softpipe->zsbuf_cache, zero, cv); - -#if !TILE_CLEAR_OPTIMIZATION - /* non-cached surface */ - pipe->surface_fill(pipe, ps, 0, 0, ps->width, ps->height, cv); -#endif } softpipe->dirty_render_cache = TRUE; diff --git a/src/gallium/drivers/softpipe/sp_flush.c b/src/gallium/drivers/softpipe/sp_flush.c index 508fe8f764..5024fc8a81 100644 --- a/src/gallium/drivers/softpipe/sp_flush.c +++ b/src/gallium/drivers/softpipe/sp_flush.c @@ -104,3 +104,71 @@ softpipe_flush( struct pipe_context *pipe, *fence = NULL; } + +/** + * Flush context if necessary. + * + * Returns FALSE if it would have block, but do_not_block was set, TRUE + * otherwise. + * + * TODO: move this logic to an auxiliary library? + */ +boolean +softpipe_flush_resource(struct pipe_context *pipe, + struct pipe_resource *texture, + unsigned face, + unsigned level, + unsigned flush_flags, + boolean read_only, + boolean cpu_access, + boolean do_not_block) +{ + unsigned referenced; + + referenced = pipe->is_resource_referenced(pipe, texture, face, level); + + if ((referenced & PIPE_REFERENCED_FOR_WRITE) || + ((referenced & PIPE_REFERENCED_FOR_READ) && !read_only)) { + + /* + * TODO: The semantics of these flush flags are too obtuse. They should + * disappear and the pipe driver should just ensure that all visible + * side-effects happen when they need to happen. + */ + if (referenced & PIPE_REFERENCED_FOR_WRITE) + flush_flags |= PIPE_FLUSH_RENDER_CACHE; + + if (referenced & PIPE_REFERENCED_FOR_READ) + flush_flags |= PIPE_FLUSH_TEXTURE_CACHE; + + if (cpu_access) { + /* + * Flush and wait. + */ + + struct pipe_fence_handle *fence = NULL; + + if (do_not_block) + return FALSE; + + pipe->flush(pipe, flush_flags, &fence); + + if (fence) { + /* + * This is for illustrative purposes only, as softpipe does not + * have fences. + */ + pipe->screen->fence_finish(pipe->screen, fence, 0); + pipe->screen->fence_reference(pipe->screen, &fence, NULL); + } + } else { + /* + * Just flush. + */ + + pipe->flush(pipe, flush_flags, NULL); + } + } + + return TRUE; +} diff --git a/src/gallium/drivers/softpipe/sp_flush.h b/src/gallium/drivers/softpipe/sp_flush.h index 68d9b5fa83..cb97482a71 100644 --- a/src/gallium/drivers/softpipe/sp_flush.h +++ b/src/gallium/drivers/softpipe/sp_flush.h @@ -28,10 +28,23 @@ #ifndef SP_FLUSH_H #define SP_FLUSH_H +#include "pipe/p_compiler.h" + struct pipe_context; struct pipe_fence_handle; -void softpipe_flush(struct pipe_context *pipe, unsigned flags, - struct pipe_fence_handle **fence); +void +softpipe_flush(struct pipe_context *pipe, unsigned flags, + struct pipe_fence_handle **fence); + +boolean +softpipe_flush_resource(struct pipe_context *pipe, + struct pipe_resource *texture, + unsigned face, + unsigned level, + unsigned flush_flags, + boolean read_only, + boolean cpu_access, + boolean do_not_block); #endif diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index 7b1e058ac8..8bb0294238 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -27,6 +27,7 @@ #include "util/u_memory.h" +#include "util/u_format.h" #include "util/u_format_s3tc.h" #include "pipe/p_defines.h" #include "pipe/p_screen.h" @@ -70,6 +71,8 @@ softpipe_get_param(struct pipe_screen *screen, int param) return 1; case PIPE_CAP_GLSL: return 1; + case PIPE_CAP_SM3: + return 1; case PIPE_CAP_ANISOTROPIC_FILTER: return 0; case PIPE_CAP_POINT_SPRITE: @@ -144,43 +147,77 @@ static boolean softpipe_is_format_supported( struct pipe_screen *screen, enum pipe_format format, enum pipe_texture_target target, - unsigned tex_usage, + unsigned bind, unsigned geom_flags ) { struct sw_winsys *winsys = softpipe_screen(screen)->winsys; + const struct util_format_description *format_desc; assert(target == PIPE_TEXTURE_1D || target == PIPE_TEXTURE_2D || target == PIPE_TEXTURE_3D || target == PIPE_TEXTURE_CUBE); - switch(format) { - case PIPE_FORMAT_YUYV: - case PIPE_FORMAT_UYVY: + format_desc = util_format_description(format); + if (!format_desc) return FALSE; - case PIPE_FORMAT_DXT1_RGB: - case PIPE_FORMAT_DXT1_RGBA: - case PIPE_FORMAT_DXT3_RGBA: - case PIPE_FORMAT_DXT5_RGBA: - return util_format_s3tc_enabled; + if (bind & (PIPE_BIND_DISPLAY_TARGET | + PIPE_BIND_SCANOUT | + PIPE_BIND_SHARED)) { + if(!winsys->is_displaytarget_format_supported(winsys, bind, format)) + return FALSE; + } - case PIPE_FORMAT_Z32_FLOAT: - case PIPE_FORMAT_NONE: - return FALSE; + if (bind & PIPE_BIND_RENDER_TARGET) { + if (format_desc->colorspace == UTIL_FORMAT_COLORSPACE_ZS) + return FALSE; - default: - break; + /* + * Although possible, it is unnatural to render into compressed or YUV + * surfaces. So disable these here to avoid going into weird paths + * inside the state trackers. + */ + if (format_desc->block.width != 1 || + format_desc->block.height != 1) + return FALSE; + + /* + * TODO: Unfortunately we cannot render into anything more than 32 bits + * because we encode color clear values into a 32bit word. + */ + if (format_desc->block.bits > 32) + return FALSE; } - if(tex_usage & (PIPE_BIND_DISPLAY_TARGET | - PIPE_BIND_SCANOUT | - PIPE_BIND_SHARED)) { - if(!winsys->is_displaytarget_format_supported(winsys, tex_usage, format)) + if (bind & PIPE_BIND_DEPTH_STENCIL) { + if (format_desc->colorspace != UTIL_FORMAT_COLORSPACE_ZS) return FALSE; + + /* + * TODO: Unfortunately we cannot render into anything more than 32 bits + * because we encode depth and stencil clear values into a 32bit word. + */ + if (format_desc->block.bits > 32) + return FALSE; + + /* + * TODO: eliminate this restriction + */ + if (format == PIPE_FORMAT_Z32_FLOAT) + return FALSE; + } + + /* + * All other operations (sampling, transfer, etc). + */ + + if (format_desc->layout == UTIL_FORMAT_LAYOUT_S3TC) { + return util_format_s3tc_enabled; } - /* XXX: this is often a lie. Pull in logic from llvmpipe to fix. + /* + * Everything else should be supported by u_format. */ return TRUE; } diff --git a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c index c79f5fb05a..fbce9e042b 100644 --- a/src/gallium/drivers/softpipe/sp_tex_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tex_tile_cache.c @@ -248,7 +248,8 @@ sp_find_cached_tile_tex(struct softpipe_tex_tile_cache *tc, addr.bits.face, addr.bits.level, addr.bits.z, - PIPE_TRANSFER_READ, 0, 0, + PIPE_TRANSFER_READ | PIPE_TRANSFER_UNSYNCHRONIZED, + 0, 0, u_minify(tc->texture->width0, addr.bits.level), u_minify(tc->texture->height0, addr.bits.level)); diff --git a/src/gallium/drivers/softpipe/sp_texture.c b/src/gallium/drivers/softpipe/sp_texture.c index 167b6b1161..7aa85559b2 100644 --- a/src/gallium/drivers/softpipe/sp_texture.c +++ b/src/gallium/drivers/softpipe/sp_texture.c @@ -39,6 +39,7 @@ #include "util/u_transfer.h" #include "sp_context.h" +#include "sp_flush.h" #include "sp_texture.h" #include "sp_screen.h" @@ -214,6 +215,35 @@ softpipe_resource_get_handle(struct pipe_screen *screen, /** + * Helper function to compute offset (in bytes) for a particular + * texture level/face/slice from the start of the buffer. + */ +static unsigned +sp_get_tex_image_offset(const struct softpipe_resource *spr, + unsigned level, unsigned face, unsigned zslice) +{ + const unsigned hgt = u_minify(spr->base.height0, level); + const unsigned nblocksy = util_format_get_nblocksy(spr->base.format, hgt); + unsigned offset = spr->level_offset[level]; + + if (spr->base.target == PIPE_TEXTURE_CUBE) { + assert(zslice == 0); + offset += face * nblocksy * spr->stride[level]; + } + else if (spr->base.target == PIPE_TEXTURE_3D) { + assert(face == 0); + offset += zslice * nblocksy * spr->stride[level]; + } + else { + assert(face == 0); + assert(zslice == 0); + } + + return offset; +} + + +/** * Get a pipe_surface "view" into a texture resource. */ static struct pipe_surface * @@ -234,25 +264,12 @@ softpipe_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 = spr->level_offset[level]; + ps->offset = sp_get_tex_image_offset(spr, level, face, zslice); ps->usage = usage; ps->face = face; ps->level = level; ps->zslice = zslice; - - if (pt->target == PIPE_TEXTURE_CUBE) { - ps->offset += face * util_format_get_nblocksy(pt->format, u_minify(pt->height0, level)) * - spr->stride[level]; - } - else if (pt->target == PIPE_TEXTURE_3D) { - ps->offset += zslice * util_format_get_nblocksy(pt->format, u_minify(pt->height0, level)) * - spr->stride[level]; - } - else { - assert(face == 0); - assert(zslice == 0); - } } return ps; } @@ -290,8 +307,8 @@ softpipe_get_transfer(struct pipe_context *pipe, unsigned usage, const struct pipe_box *box) { - struct softpipe_resource *sprex = softpipe_resource(resource); - struct softpipe_transfer *spr; + struct softpipe_resource *spr = softpipe_resource(resource); + struct softpipe_transfer *spt; assert(resource); assert(sr.level <= resource->last_level); @@ -301,33 +318,41 @@ softpipe_get_transfer(struct pipe_context *pipe, assert(box->y + box->height <= u_minify(resource->height0, sr.level)); assert(box->z + box->depth <= u_minify(resource->depth0, sr.level)); - spr = CALLOC_STRUCT(softpipe_transfer); - if (spr) { - struct pipe_transfer *pt = &spr->base; + /* + * Transfers, like other pipe operations, must happen in order, so flush the + * context if necessary. + */ + if (!(usage & PIPE_TRANSFER_UNSYNCHRONIZED)) { + boolean read_only = !(usage & PIPE_TRANSFER_WRITE); + boolean do_not_block = !!(usage & PIPE_TRANSFER_DONTBLOCK); + if (!softpipe_flush_resource(pipe, resource, + sr.face, sr.level, + 0, /* flush_flags */ + read_only, + TRUE, /* cpu_access */ + do_not_block)) { + /* + * It would have blocked, but state tracker requested no to. + */ + assert(do_not_block); + return NULL; + } + } + + spt = CALLOC_STRUCT(softpipe_transfer); + if (spt) { + struct pipe_transfer *pt = &spt->base; enum pipe_format format = resource->format; - int nblocksy = util_format_get_nblocksy(resource->format, - u_minify(resource->height0, sr.level)); pipe_resource_reference(&pt->resource, resource); pt->sr = sr; pt->usage = usage; pt->box = *box; - pt->stride = sprex->stride[sr.level]; + pt->stride = spr->stride[sr.level]; - spr->offset = sprex->level_offset[sr.level]; - - if (resource->target == PIPE_TEXTURE_CUBE) { - spr->offset += sr.face * nblocksy * pt->stride; - } - else if (resource->target == PIPE_TEXTURE_3D) { - spr->offset += box->z * nblocksy * pt->stride; - } - else { - assert(sr.face == 0); - assert(box->z == 0); - } - - spr->offset += - box->y / util_format_get_blockheight(format) * spr->base.stride + + spt->offset = sp_get_tex_image_offset(spr, sr.level, sr.face, box->z); + + spt->offset += + box->y / util_format_get_blockheight(format) * spt->base.stride + box->x / util_format_get_blockwidth(format) * util_format_get_blocksize(format); return pt; @@ -356,26 +381,24 @@ static void * softpipe_transfer_map(struct pipe_context *pipe, struct pipe_transfer *transfer) { - struct softpipe_transfer *sp_transfer = softpipe_transfer(transfer); - struct softpipe_resource *sp_resource = softpipe_resource(transfer->resource); + struct softpipe_transfer *spt = softpipe_transfer(transfer); + struct softpipe_resource *spr = softpipe_resource(transfer->resource); struct sw_winsys *winsys = softpipe_screen(pipe->screen)->winsys; uint8_t *map; /* resources backed by display target treated specially: */ - if (sp_resource->dt) { - map = winsys->displaytarget_map(winsys, - sp_resource->dt, - transfer->usage); + if (spr->dt) { + map = winsys->displaytarget_map(winsys, spr->dt, transfer->usage); } else { - map = sp_resource->data; + map = spr->data; } if (map == NULL) return NULL; else - return map + sp_transfer->offset; + return map + spt->offset; } @@ -412,26 +435,25 @@ softpipe_user_buffer_create(struct pipe_screen *screen, unsigned bytes, unsigned bind_flags) { - struct softpipe_resource *buffer; + struct softpipe_resource *spr; - buffer = CALLOC_STRUCT(softpipe_resource); - if(!buffer) + spr = CALLOC_STRUCT(softpipe_resource); + if (!spr) return NULL; - - 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; + pipe_reference_init(&spr->base.reference, 1); + spr->base.screen = screen; + spr->base.format = PIPE_FORMAT_R8_UNORM; /* ?? */ + spr->base.bind = bind_flags; + spr->base.usage = PIPE_USAGE_IMMUTABLE; + spr->base.flags = 0; + spr->base.width0 = bytes; + spr->base.height0 = 1; + spr->base.depth0 = 1; + spr->userBuffer = TRUE; + spr->data = ptr; - return &buffer->base; + return &spr->base; } diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index d996c2a342..f4db6f6ef0 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -103,7 +103,7 @@ sp_create_tile_cache( struct pipe_context *pipe ) * However, it breaks clearing in other situations (such as in * progs/tests/drawbuffers, see bug 24402). */ -#if 0 && TILE_CLEAR_OPTIMIZATION +#if 0 /* set flags to indicate all the tiles are cleared */ memset(tc->clear_flags, 255, sizeof(tc->clear_flags)); #endif @@ -155,7 +155,8 @@ sp_tile_cache_set_surface(struct softpipe_tile_cache *tc, if (ps) { tc->transfer = pipe_get_transfer(pipe, ps->texture, ps->face, ps->level, ps->zslice, - PIPE_TRANSFER_READ_WRITE, + PIPE_TRANSFER_READ_WRITE | + PIPE_TRANSFER_UNSYNCHRONIZED, 0, 0, ps->width, ps->height); tc->depth_stencil = (ps->format == PIPE_FORMAT_Z24_UNORM_S8_USCALED || @@ -344,9 +345,7 @@ sp_flush_tile_cache(struct softpipe_tile_cache *tc) } } -#if TILE_CLEAR_OPTIMIZATION sp_tile_cache_flush_clear(tc); -#endif } #if 0 @@ -448,13 +447,8 @@ sp_tile_cache_clear(struct softpipe_tile_cache *tc, const float *rgba, tc->clear_val = clearValue; -#if TILE_CLEAR_OPTIMIZATION /* set flags to indicate all the tiles are cleared */ memset(tc->clear_flags, 255, sizeof(tc->clear_flags)); -#else - /* disable the optimization */ - memset(tc->clear_flags, 0, sizeof(tc->clear_flags)); -#endif for (pos = 0; pos < NUM_ENTRIES; pos++) { struct softpipe_cached_tile *tile = tc->entries + pos; diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.h b/src/gallium/drivers/softpipe/sp_tile_cache.h index 753d8c0daa..e03d53eb24 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.h +++ b/src/gallium/drivers/softpipe/sp_tile_cache.h @@ -28,8 +28,6 @@ #ifndef SP_TILE_CACHE_H #define SP_TILE_CACHE_H -#define TILE_CLEAR_OPTIMIZATION 1 - #include "pipe/p_compiler.h" |
