pb_bufmgr_pool.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  * 
00003  * Copyright 2006 Tungsten Graphics, Inc., Bismarck, ND., USA
00004  * All Rights Reserved.
00005  * 
00006  * Permission is hereby granted, free of charge, to any person obtaining a
00007  * copy of this software and associated documentation files (the
00008  * "Software"), to deal in the Software without restriction, including
00009  * without limitation the rights to use, copy, modify, merge, publish,
00010  * distribute, sub license, and/or sell copies of the Software, and to
00011  * permit persons to whom the Software is furnished to do so, subject to
00012  * the following conditions:
00013  * 
00014  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00015  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00016  * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
00017  * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM,
00018  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
00019  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
00020  * USE OR OTHER DEALINGS IN THE SOFTWARE.
00021  *
00022  * The above copyright notice and this permission notice (including the
00023  * next paragraph) shall be included in all copies or substantial portions
00024  * of the Software.
00025  * 
00026  * 
00027  **************************************************************************/
00028 
00038 #include "pipe/p_compiler.h"
00039 #include "pipe/p_debug.h"
00040 #include "pipe/p_thread.h"
00041 #include "pipe/p_defines.h"
00042 #include "util/u_memory.h"
00043 #include "util/u_double_list.h"
00044 
00045 #include "pb_buffer.h"
00046 #include "pb_bufmgr.h"
00047 
00048 
00052 #define SUPER(__derived) (&(__derived)->base)
00053 
00054 
00055 struct pool_pb_manager
00056 {
00057    struct pb_manager base;
00058    
00059    pipe_mutex mutex;
00060    
00061    size_t bufSize;
00062    size_t bufAlign;
00063    
00064    size_t numFree;
00065    size_t numTot;
00066    
00067    struct list_head free;
00068    
00069    struct pb_buffer *buffer;
00070    void *map;
00071    
00072    struct pool_buffer *bufs;
00073 };
00074 
00075 
00076 static INLINE struct pool_pb_manager *
00077 pool_pb_manager(struct pb_manager *mgr)
00078 {
00079    assert(mgr);
00080    return (struct pool_pb_manager *)mgr;
00081 }
00082 
00083 
00084 struct pool_buffer
00085 {
00086    struct pb_buffer base;
00087    
00088    struct pool_pb_manager *mgr;
00089    
00090    struct list_head head;
00091    
00092    size_t start;
00093 };
00094 
00095 
00096 static INLINE struct pool_buffer *
00097 pool_buffer(struct pb_buffer *buf)
00098 {
00099    assert(buf);
00100    return (struct pool_buffer *)buf;
00101 }
00102 
00103 
00104 
00105 static void
00106 pool_buffer_destroy(struct pb_buffer *buf)
00107 {
00108    struct pool_buffer *pool_buf = pool_buffer(buf);
00109    struct pool_pb_manager *pool = pool_buf->mgr;
00110    
00111    assert(pool_buf->base.base.refcount == 0);
00112 
00113    pipe_mutex_lock(pool->mutex);
00114    LIST_ADD(&pool_buf->head, &pool->free);
00115    pool->numFree++;
00116    pipe_mutex_unlock(pool->mutex);
00117 }
00118 
00119 
00120 static void *
00121 pool_buffer_map(struct pb_buffer *buf, unsigned flags)
00122 {
00123    struct pool_buffer *pool_buf = pool_buffer(buf);
00124    struct pool_pb_manager *pool = pool_buf->mgr;
00125    void *map;
00126 
00127    pipe_mutex_lock(pool->mutex);
00128    map = (unsigned char *) pool->map + pool_buf->start;
00129    pipe_mutex_unlock(pool->mutex);
00130    return map;
00131 }
00132 
00133 
00134 static void
00135 pool_buffer_unmap(struct pb_buffer *buf)
00136 {
00137    /* No-op */
00138 }
00139 
00140 
00141 static void
00142 pool_buffer_get_base_buffer(struct pb_buffer *buf,
00143                             struct pb_buffer **base_buf,
00144                             unsigned *offset)
00145 {
00146    struct pool_buffer *pool_buf = pool_buffer(buf);
00147    struct pool_pb_manager *pool = pool_buf->mgr;
00148    pb_get_base_buffer(pool->buffer, base_buf, offset);
00149    *offset += pool_buf->start;
00150 }
00151 
00152 
00153 static const struct pb_vtbl 
00154 pool_buffer_vtbl = {
00155       pool_buffer_destroy,
00156       pool_buffer_map,
00157       pool_buffer_unmap,
00158       pool_buffer_get_base_buffer
00159 };
00160 
00161 
00162 static struct pb_buffer *
00163 pool_bufmgr_create_buffer(struct pb_manager *mgr,
00164                           size_t size,
00165                           const struct pb_desc *desc)
00166 {
00167    struct pool_pb_manager *pool = pool_pb_manager(mgr);
00168    struct pool_buffer *pool_buf;
00169    struct list_head *item;
00170 
00171    assert(size == pool->bufSize);
00172    assert(pool->bufAlign % desc->alignment == 0);
00173    
00174    pipe_mutex_lock(pool->mutex);
00175 
00176    if (pool->numFree == 0) {
00177       pipe_mutex_unlock(pool->mutex);
00178       debug_printf("warning: out of fixed size buffer objects\n");
00179       return NULL;
00180    }
00181 
00182    item = pool->free.next;
00183 
00184    if (item == &pool->free) {
00185       pipe_mutex_unlock(pool->mutex);
00186       debug_printf("error: fixed size buffer pool corruption\n");
00187       return NULL;
00188    }
00189 
00190    LIST_DEL(item);
00191    --pool->numFree;
00192 
00193    pipe_mutex_unlock(pool->mutex);
00194    
00195    pool_buf = LIST_ENTRY(struct pool_buffer, item, head);
00196    assert(pool_buf->base.base.refcount == 0);
00197    pool_buf->base.base.refcount = 1;
00198    pool_buf->base.base.alignment = desc->alignment;
00199    pool_buf->base.base.usage = desc->usage;
00200    
00201    return SUPER(pool_buf);
00202 }
00203 
00204 
00205 static void
00206 pool_bufmgr_flush(struct pb_manager *mgr)
00207 {
00208    /* No-op */
00209 }
00210 
00211 
00212 static void
00213 pool_bufmgr_destroy(struct pb_manager *mgr)
00214 {
00215    struct pool_pb_manager *pool = pool_pb_manager(mgr);
00216    pipe_mutex_lock(pool->mutex);
00217 
00218    FREE(pool->bufs);
00219    
00220    pb_unmap(pool->buffer);
00221    pb_reference(&pool->buffer, NULL);
00222    
00223    pipe_mutex_unlock(pool->mutex);
00224    
00225    FREE(mgr);
00226 }
00227 
00228 
00229 struct pb_manager *
00230 pool_bufmgr_create(struct pb_manager *provider, 
00231                    size_t numBufs, 
00232                    size_t bufSize,
00233                    const struct pb_desc *desc) 
00234 {
00235    struct pool_pb_manager *pool;
00236    struct pool_buffer *pool_buf;
00237    size_t i;
00238 
00239    if(!provider)
00240       return NULL;
00241    
00242    pool = CALLOC_STRUCT(pool_pb_manager);
00243    if (!pool)
00244       return NULL;
00245 
00246    pool->base.destroy = pool_bufmgr_destroy;
00247    pool->base.create_buffer = pool_bufmgr_create_buffer;
00248    pool->base.flush = pool_bufmgr_flush;
00249 
00250    LIST_INITHEAD(&pool->free);
00251 
00252    pool->numTot = numBufs;
00253    pool->numFree = numBufs;
00254    pool->bufSize = bufSize;
00255    pool->bufAlign = desc->alignment; 
00256    
00257    pipe_mutex_init(pool->mutex);
00258 
00259    pool->buffer = provider->create_buffer(provider, numBufs*bufSize, desc); 
00260    if (!pool->buffer)
00261       goto failure;
00262 
00263    pool->map = pb_map(pool->buffer,
00264                           PIPE_BUFFER_USAGE_CPU_READ |
00265                           PIPE_BUFFER_USAGE_CPU_WRITE);
00266    if(!pool->map)
00267       goto failure;
00268 
00269    pool->bufs = (struct pool_buffer *)CALLOC(numBufs, sizeof(*pool->bufs));
00270    if (!pool->bufs)
00271       goto failure;
00272 
00273    pool_buf = pool->bufs;
00274    for (i = 0; i < numBufs; ++i) {
00275       pool_buf->base.base.refcount = 0;
00276       pool_buf->base.base.alignment = 0;
00277       pool_buf->base.base.usage = 0;
00278       pool_buf->base.base.size = bufSize;
00279       pool_buf->base.vtbl = &pool_buffer_vtbl;
00280       pool_buf->mgr = pool;
00281       pool_buf->start = i * bufSize;
00282       LIST_ADDTAIL(&pool_buf->head, &pool->free);
00283       pool_buf++;
00284    }
00285 
00286    return SUPER(pool);
00287    
00288 failure:
00289    if(pool->bufs)
00290       FREE(pool->bufs);
00291    if(pool->map)
00292       pb_unmap(pool->buffer);
00293    if(pool->buffer)
00294       pb_reference(&pool->buffer, NULL);
00295    if(pool)
00296       FREE(pool);
00297    return NULL;
00298 }

Generated on Tue Sep 29 06:25:14 2009 for Gallium3D by  doxygen 1.5.4