diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gallium/auxiliary/pipebuffer/pb_buffer.h | 11 | ||||
-rw-r--r-- | src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c | 67 | ||||
-rw-r--r-- | src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c | 15 |
3 files changed, 68 insertions, 25 deletions
diff --git a/src/gallium/auxiliary/pipebuffer/pb_buffer.h b/src/gallium/auxiliary/pipebuffer/pb_buffer.h index 4b09c80b2a..49705cb862 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_buffer.h +++ b/src/gallium/auxiliary/pipebuffer/pb_buffer.h @@ -193,6 +193,17 @@ pb_reference(struct pb_buffer **dst, /** + * Utility function to check whether a requested alignment is consistent with + * the provided alignment or not. + */ +static INLINE int +pb_check_alignment(size_t requested, size_t provided) +{ + return requested <= provided && (provided % requested) == 0; +} + + +/** * Malloc-based buffer to store data that can't be used by the graphics * hardware. */ diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c index 06de0bb6c3..543fd51253 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_cache.c @@ -136,7 +136,7 @@ _pb_cache_buffer_list_check_free(struct pb_cache_manager *mgr) while(curr != &mgr->delayed) { buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); - if(util_time_timeout(&buf->start, &buf->end, &now) != 0) + if(!util_time_timeout(&buf->start, &buf->end, &now)) break; _pb_cache_buffer_destroy(buf); @@ -202,6 +202,24 @@ pb_cache_buffer_vtbl = { }; +static INLINE boolean +pb_cache_is_buffer_compat(struct pb_cache_buffer *buf, + size_t size, + const struct pb_desc *desc) +{ + /* TODO: be more lenient with size */ + if(buf->base.base.size != size) + return FALSE; + + if(!pb_check_alignment(desc->alignment, buf->base.base.alignment)) + return FALSE; + + /* XXX: check usage too? */ + + return TRUE; +} + + static struct pb_buffer * pb_cache_manager_create_buffer(struct pb_manager *_mgr, size_t size, @@ -209,29 +227,45 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr, { struct pb_cache_manager *mgr = pb_cache_manager(_mgr); struct pb_cache_buffer *buf; + struct pb_cache_buffer *curr_buf; struct list_head *curr, *next; struct util_time now; - util_time_get(&now); + _glthread_LOCK_MUTEX(mgr->mutex); + + buf = NULL; curr = mgr->delayed.next; next = curr->next; + + /* search in the expired buffers, freeing them in the process */ + util_time_get(&now); while(curr != &mgr->delayed) { - buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); - - if(buf->base.base.size == size && - buf->base.base.alignment >= desc->alignment && - (buf->base.base.alignment % desc->alignment) == 0 && - /* buf->base.base.usage == usage */ 1) { - ++buf->base.base.refcount; - return &buf->base; - } - - if(util_time_timeout(&buf->start, &buf->end, &now) != 0) - _pb_cache_buffer_destroy(buf); + curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); + if(!buf && pb_cache_is_buffer_compat(curr_buf, size, desc)) + buf = curr_buf; + else if(util_time_timeout(&curr_buf->start, &curr_buf->end, &now)) + _pb_cache_buffer_destroy(curr_buf); + curr = next; + next = curr->next; + } + /* keep searching in the hot buffers */ + while(!buf && curr != &mgr->delayed) { + curr_buf = LIST_ENTRY(struct pb_cache_buffer, curr, head); + if(pb_cache_is_buffer_compat(curr_buf, size, desc)) + buf = curr_buf; curr = next; next = curr->next; } + + if(buf) { + LIST_DEL(&buf->head); + _glthread_UNLOCK_MUTEX(mgr->mutex); + ++buf->base.base.refcount; + return &buf->base; + } + + _glthread_UNLOCK_MUTEX(mgr->mutex); buf = CALLOC_STRUCT(pb_cache_buffer); if(!buf) @@ -243,6 +277,11 @@ pb_cache_manager_create_buffer(struct pb_manager *_mgr, return NULL; } + assert(buf->buffer->base.refcount >= 1); + assert(pb_check_alignment(desc->alignment, buf->buffer->base.alignment)); + assert((buf->buffer->base.usage & desc->usage) == desc->usage); + assert(buf->buffer->base.size >= size); + buf->base.base.refcount = 1; buf->base.base.alignment = buf->buffer->base.alignment; buf->base.base.usage = buf->buffer->base.usage; diff --git a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c index 9506ac9ae1..b931455056 100644 --- a/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c +++ b/src/gallium/auxiliary/pipebuffer/pb_bufmgr_slab.c @@ -304,13 +304,6 @@ out_err0: } -static int -check_alignment(size_t requested, size_t provided) -{ - return requested <= provided && (provided % requested) == 0; -} - - static struct pb_buffer * pb_slab_manager_create_buffer(struct pb_manager *_mgr, size_t size, @@ -328,11 +321,11 @@ pb_slab_manager_create_buffer(struct pb_manager *_mgr, return NULL; /* check if we can provide the requested alignment */ - assert(check_alignment(desc->alignment, mgr->desc.alignment)); - if(!check_alignment(desc->alignment, mgr->desc.alignment)) + assert(pb_check_alignment(desc->alignment, mgr->desc.alignment)); + if(!pb_check_alignment(desc->alignment, mgr->desc.alignment)) return NULL; - assert(check_alignment(desc->alignment, mgr->bufSize)); - if(!check_alignment(desc->alignment, mgr->bufSize)) + assert(pb_check_alignment(desc->alignment, mgr->bufSize)); + if(!pb_check_alignment(desc->alignment, mgr->bufSize)) return NULL; /* XXX: check for compatible buffer usage too? */ |