diff options
Diffstat (limited to 'src/gallium/drivers')
| -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_tex_tile_cache.c | 3 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_texture.c | 22 | ||||
| -rw-r--r-- | src/gallium/drivers/softpipe/sp_tile_cache.c | 3 | 
5 files changed, 109 insertions, 4 deletions
| 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_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..3533c4fd4f 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" @@ -301,6 +302,27 @@ 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)); +   /* +    * 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; +      } +   } +     spr = CALLOC_STRUCT(softpipe_transfer);     if (spr) {        struct pipe_transfer *pt = &spr->base; diff --git a/src/gallium/drivers/softpipe/sp_tile_cache.c b/src/gallium/drivers/softpipe/sp_tile_cache.c index 4e5a13ba05..f4db6f6ef0 100644 --- a/src/gallium/drivers/softpipe/sp_tile_cache.c +++ b/src/gallium/drivers/softpipe/sp_tile_cache.c @@ -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 || | 
