00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
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
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
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
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
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;
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 }