pb_bufmgr_mm.c

Go to the documentation of this file.
00001 /**************************************************************************
00002  *
00003  * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas.
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 above copyright notice and this permission notice (including the
00015  * next paragraph) shall be included in all copies or substantial portions
00016  * of the Software.
00017  *
00018  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
00019  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
00020  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
00021  * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
00022  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
00023  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
00024  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00025  *
00026  **************************************************************************/
00027 
00036 #include "pipe/p_defines.h"
00037 #include "pipe/p_debug.h"
00038 #include "pipe/p_thread.h"
00039 #include "util/u_memory.h"
00040 #include "util/u_double_list.h"
00041 #include "util/u_mm.h"
00042 #include "pb_buffer.h"
00043 #include "pb_bufmgr.h"
00044 
00045 
00049 #define SUPER(__derived) (&(__derived)->base)
00050 
00051 
00052 struct mm_pb_manager
00053 {
00054    struct pb_manager base;
00055    
00056    pipe_mutex mutex;
00057    
00058    size_t size;
00059    struct mem_block *heap;
00060    
00061    size_t align2;
00062    
00063    struct pb_buffer *buffer;
00064    void *map;
00065 };
00066 
00067 
00068 static INLINE struct mm_pb_manager *
00069 mm_pb_manager(struct pb_manager *mgr)
00070 {
00071    assert(mgr);
00072    return (struct mm_pb_manager *)mgr;
00073 }
00074 
00075 
00076 struct mm_buffer
00077 {
00078    struct pb_buffer base;
00079    
00080    struct mm_pb_manager *mgr;
00081    
00082    struct mem_block *block;
00083 };
00084 
00085 
00086 static INLINE struct mm_buffer *
00087 mm_buffer(struct pb_buffer *buf)
00088 {
00089    assert(buf);
00090    return (struct mm_buffer *)buf;
00091 }
00092 
00093 
00094 static void
00095 mm_buffer_destroy(struct pb_buffer *buf)
00096 {
00097    struct mm_buffer *mm_buf = mm_buffer(buf);
00098    struct mm_pb_manager *mm = mm_buf->mgr;
00099    
00100    assert(buf->base.refcount == 0);
00101    
00102    pipe_mutex_lock(mm->mutex);
00103    mmFreeMem(mm_buf->block);
00104    FREE(buf);
00105    pipe_mutex_unlock(mm->mutex);
00106 }
00107 
00108 
00109 static void *
00110 mm_buffer_map(struct pb_buffer *buf,
00111               unsigned flags)
00112 {
00113    struct mm_buffer *mm_buf = mm_buffer(buf);
00114    struct mm_pb_manager *mm = mm_buf->mgr;
00115 
00116    return (unsigned char *) mm->map + mm_buf->block->ofs;
00117 }
00118 
00119 
00120 static void
00121 mm_buffer_unmap(struct pb_buffer *buf)
00122 {
00123    /* No-op */
00124 }
00125 
00126 
00127 static void
00128 mm_buffer_get_base_buffer(struct pb_buffer *buf,
00129                           struct pb_buffer **base_buf,
00130                           unsigned *offset)
00131 {
00132    struct mm_buffer *mm_buf = mm_buffer(buf);
00133    struct mm_pb_manager *mm = mm_buf->mgr;
00134    pb_get_base_buffer(mm->buffer, base_buf, offset);
00135    *offset += mm_buf->block->ofs;
00136 }
00137 
00138 
00139 static const struct pb_vtbl 
00140 mm_buffer_vtbl = {
00141       mm_buffer_destroy,
00142       mm_buffer_map,
00143       mm_buffer_unmap,
00144       mm_buffer_get_base_buffer
00145 };
00146 
00147 
00148 static struct pb_buffer *
00149 mm_bufmgr_create_buffer(struct pb_manager *mgr, 
00150                         size_t size,
00151                         const struct pb_desc *desc)
00152 {
00153    struct mm_pb_manager *mm = mm_pb_manager(mgr);
00154    struct mm_buffer *mm_buf;
00155 
00156    /* We don't handle alignments larger then the one initially setup */
00157    assert(pb_check_alignment(desc->alignment, 1 << mm->align2));
00158    if(!pb_check_alignment(desc->alignment, 1 << mm->align2))
00159       return NULL;
00160    
00161    pipe_mutex_lock(mm->mutex);
00162 
00163    mm_buf = CALLOC_STRUCT(mm_buffer);
00164    if (!mm_buf) {
00165       pipe_mutex_unlock(mm->mutex);
00166       return NULL;
00167    }
00168 
00169    mm_buf->base.base.refcount = 1;
00170    mm_buf->base.base.alignment = desc->alignment;
00171    mm_buf->base.base.usage = desc->usage;
00172    mm_buf->base.base.size = size;
00173    
00174    mm_buf->base.vtbl = &mm_buffer_vtbl;
00175    
00176    mm_buf->mgr = mm;
00177    
00178    mm_buf->block = mmAllocMem(mm->heap, size, mm->align2, 0);
00179    if(!mm_buf->block) {
00180       debug_printf("warning: heap full\n");
00181 #if 0
00182       mmDumpMemInfo(mm->heap);
00183 #endif
00184       FREE(mm_buf);
00185       pipe_mutex_unlock(mm->mutex);
00186       return NULL;
00187    }
00188    
00189    /* Some sanity checks */
00190    assert(0 <= (unsigned)mm_buf->block->ofs && (unsigned)mm_buf->block->ofs < mm->size);
00191    assert(size <= (unsigned)mm_buf->block->size && (unsigned)mm_buf->block->ofs + (unsigned)mm_buf->block->size <= mm->size);
00192    
00193    pipe_mutex_unlock(mm->mutex);
00194    return SUPER(mm_buf);
00195 }
00196 
00197 
00198 static void
00199 mm_bufmgr_flush(struct pb_manager *mgr)
00200 {
00201    /* No-op */
00202 }
00203 
00204 
00205 static void
00206 mm_bufmgr_destroy(struct pb_manager *mgr)
00207 {
00208    struct mm_pb_manager *mm = mm_pb_manager(mgr);
00209    
00210    pipe_mutex_lock(mm->mutex);
00211 
00212    mmDestroy(mm->heap);
00213    
00214    pb_unmap(mm->buffer);
00215    pb_reference(&mm->buffer, NULL);
00216    
00217    pipe_mutex_unlock(mm->mutex);
00218    
00219    FREE(mgr);
00220 }
00221 
00222 
00223 struct pb_manager *
00224 mm_bufmgr_create_from_buffer(struct pb_buffer *buffer, 
00225                              size_t size, size_t align2) 
00226 {
00227    struct mm_pb_manager *mm;
00228 
00229    if(!buffer)
00230       return NULL;
00231    
00232    mm = CALLOC_STRUCT(mm_pb_manager);
00233    if (!mm)
00234       return NULL;
00235 
00236    mm->base.destroy = mm_bufmgr_destroy;
00237    mm->base.create_buffer = mm_bufmgr_create_buffer;
00238    mm->base.flush = mm_bufmgr_flush;
00239 
00240    mm->size = size;
00241    mm->align2 = align2; /* 64-byte alignment */
00242 
00243    pipe_mutex_init(mm->mutex);
00244 
00245    mm->buffer = buffer; 
00246 
00247    mm->map = pb_map(mm->buffer, 
00248                     PIPE_BUFFER_USAGE_CPU_READ |
00249                     PIPE_BUFFER_USAGE_CPU_WRITE);
00250    if(!mm->map)
00251       goto failure;
00252 
00253    mm->heap = mmInit(0, size); 
00254    if (!mm->heap)
00255       goto failure;
00256 
00257    return SUPER(mm);
00258    
00259 failure:
00260 if(mm->heap)
00261    mmDestroy(mm->heap);
00262    if(mm->map)
00263       pb_unmap(mm->buffer);
00264    if(mm)
00265       FREE(mm);
00266    return NULL;
00267 }
00268 
00269 
00270 struct pb_manager *
00271 mm_bufmgr_create(struct pb_manager *provider, 
00272                  size_t size, size_t align2) 
00273 {
00274    struct pb_buffer *buffer;
00275    struct pb_manager *mgr;
00276    struct pb_desc desc;
00277 
00278    if(!provider)
00279       return NULL;
00280    
00281    memset(&desc, 0, sizeof(desc));
00282    desc.alignment = 1 << align2;
00283    
00284    buffer = provider->create_buffer(provider, size, &desc); 
00285    if (!buffer)
00286       return NULL;
00287    
00288    mgr = mm_bufmgr_create_from_buffer(buffer, size, align2);
00289    if (!mgr) {
00290       pb_reference(&buffer, NULL);
00291       return NULL;
00292    }
00293 
00294   return mgr;
00295 }

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