pb_bufmgr_mm.c revision 3ad56968f09397a8dd417eae025b9506efaf8414
19db7f57c1e3db8a2d06a833a4e0341f0fe310640Richard Smith/************************************************************************** 29db7f57c1e3db8a2d06a833a4e0341f0fe310640Richard Smith * 3acd954bd8f28383e7538c4d0fd989763744f5e99Richard Smith * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. 4acd954bd8f28383e7538c4d0fd989763744f5e99Richard Smith * All Rights Reserved. 5acd954bd8f28383e7538c4d0fd989763744f5e99Richard Smith * 6acd954bd8f28383e7538c4d0fd989763744f5e99Richard Smith * Permission is hereby granted, free of charge, to any person obtaining a 7acd954bd8f28383e7538c4d0fd989763744f5e99Richard Smith * copy of this software and associated documentation files (the 8acd954bd8f28383e7538c4d0fd989763744f5e99Richard Smith * "Software"), to deal in the Software without restriction, including 998f0723ca24c604d72a10047b10b60743ac71f27Richard Smith * without limitation the rights to use, copy, modify, merge, publish, 1098f0723ca24c604d72a10047b10b60743ac71f27Richard Smith * distribute, sub license, and/or sell copies of the Software, and to 1198f0723ca24c604d72a10047b10b60743ac71f27Richard Smith * permit persons to whom the Software is furnished to do so, subject to 1298f0723ca24c604d72a10047b10b60743ac71f27Richard Smith * the following conditions: 139db7f57c1e3db8a2d06a833a4e0341f0fe310640Richard Smith * 149db7f57c1e3db8a2d06a833a4e0341f0fe310640Richard Smith * The above copyright notice and this permission notice (including the 159db7f57c1e3db8a2d06a833a4e0341f0fe310640Richard Smith * next paragraph) shall be included in all copies or substantial portions 169db7f57c1e3db8a2d06a833a4e0341f0fe310640Richard Smith * of the Software. 17b775100fea6d8955149897dae1adca50ca471d17Richard Smith * 18b775100fea6d8955149897dae1adca50ca471d17Richard Smith * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19b775100fea6d8955149897dae1adca50ca471d17Richard Smith * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 208bfc1e118169229960b90a4ef8761ee0eb296755Richard Smith * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 218bfc1e118169229960b90a4ef8761ee0eb296755Richard Smith * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 228bfc1e118169229960b90a4ef8761ee0eb296755Richard Smith * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23b775100fea6d8955149897dae1adca50ca471d17Richard Smith * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24b775100fea6d8955149897dae1adca50ca471d17Richard Smith * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25b775100fea6d8955149897dae1adca50ca471d17Richard Smith * 26b775100fea6d8955149897dae1adca50ca471d17Richard Smith **************************************************************************/ 27b775100fea6d8955149897dae1adca50ca471d17Richard Smith 28b775100fea6d8955149897dae1adca50ca471d17Richard Smith/** 29b775100fea6d8955149897dae1adca50ca471d17Richard Smith * \file 30b775100fea6d8955149897dae1adca50ca471d17Richard Smith * Buffer manager using the old texture memory manager. 31b775100fea6d8955149897dae1adca50ca471d17Richard Smith * 32b775100fea6d8955149897dae1adca50ca471d17Richard Smith * \author José Fonseca <jrfonseca@tungstengraphics.com> 33b775100fea6d8955149897dae1adca50ca471d17Richard Smith */ 34b775100fea6d8955149897dae1adca50ca471d17Richard Smith 351888b910a5512262228e785cc9caf90296c06a45Richard Smith 361888b910a5512262228e785cc9caf90296c06a45Richard Smith#include "pipe/p_defines.h" 371888b910a5512262228e785cc9caf90296c06a45Richard Smith#include "pipe/p_debug.h" 381888b910a5512262228e785cc9caf90296c06a45Richard Smith#include "pipe/p_thread.h" 391888b910a5512262228e785cc9caf90296c06a45Richard Smith#include "util/u_memory.h" 401888b910a5512262228e785cc9caf90296c06a45Richard Smith#include "util/u_double_list.h" 41b60fae50d38a0291e1c5731b2fb22849d26ca342Richard Smith#include "util/u_mm.h" 42b60fae50d38a0291e1c5731b2fb22849d26ca342Richard Smith#include "pb_buffer.h" 43b60fae50d38a0291e1c5731b2fb22849d26ca342Richard Smith#include "pb_bufmgr.h" 44b60fae50d38a0291e1c5731b2fb22849d26ca342Richard Smith 45b60fae50d38a0291e1c5731b2fb22849d26ca342Richard Smith 46b60fae50d38a0291e1c5731b2fb22849d26ca342Richard Smith/** 47d692a84e18fb48e6442bee83364f1d301f5b8404Richard Smith * Convenience macro (type safe). 48d692a84e18fb48e6442bee83364f1d301f5b8404Richard Smith */ 49d692a84e18fb48e6442bee83364f1d301f5b8404Richard Smith#define SUPER(__derived) (&(__derived)->base) 50d692a84e18fb48e6442bee83364f1d301f5b8404Richard Smith 51d692a84e18fb48e6442bee83364f1d301f5b8404Richard Smith 52d692a84e18fb48e6442bee83364f1d301f5b8404Richard Smithstruct mm_pb_manager 53d692a84e18fb48e6442bee83364f1d301f5b8404Richard Smith{ 547a3dfcdfb32c08f2f6f4a90a097bb240fdc1a94cRichard Smith struct pb_manager base; 557a3dfcdfb32c08f2f6f4a90a097bb240fdc1a94cRichard Smith 567a3dfcdfb32c08f2f6f4a90a097bb240fdc1a94cRichard Smith pipe_mutex mutex; 577a3dfcdfb32c08f2f6f4a90a097bb240fdc1a94cRichard Smith 587a3dfcdfb32c08f2f6f4a90a097bb240fdc1a94cRichard Smith size_t size; 597a3dfcdfb32c08f2f6f4a90a097bb240fdc1a94cRichard Smith struct mem_block *heap; 607a3dfcdfb32c08f2f6f4a90a097bb240fdc1a94cRichard Smith 617a3dfcdfb32c08f2f6f4a90a097bb240fdc1a94cRichard Smith size_t align2; 62b775100fea6d8955149897dae1adca50ca471d17Richard Smith 63b775100fea6d8955149897dae1adca50ca471d17Richard Smith struct pb_buffer *buffer; 64b775100fea6d8955149897dae1adca50ca471d17Richard Smith void *map; 65b775100fea6d8955149897dae1adca50ca471d17Richard Smith}; 66b775100fea6d8955149897dae1adca50ca471d17Richard Smith 67b775100fea6d8955149897dae1adca50ca471d17Richard Smith 68b775100fea6d8955149897dae1adca50ca471d17Richard Smithstatic INLINE struct mm_pb_manager * 69651f13cea278ec967336033dd032faef0e9fc2ecStephen Hinesmm_pb_manager(struct pb_manager *mgr) 70b775100fea6d8955149897dae1adca50ca471d17Richard Smith{ 71 assert(mgr); 72 return (struct mm_pb_manager *)mgr; 73} 74 75 76struct mm_buffer 77{ 78 struct pb_buffer base; 79 80 struct mm_pb_manager *mgr; 81 82 struct mem_block *block; 83}; 84 85 86static INLINE struct mm_buffer * 87mm_buffer(struct pb_buffer *buf) 88{ 89 assert(buf); 90 return (struct mm_buffer *)buf; 91} 92 93 94static void 95mm_buffer_destroy(struct pb_buffer *buf) 96{ 97 struct mm_buffer *mm_buf = mm_buffer(buf); 98 struct mm_pb_manager *mm = mm_buf->mgr; 99 100 assert(buf->base.refcount == 0); 101 102 pipe_mutex_lock(mm->mutex); 103 u_mmFreeMem(mm_buf->block); 104 FREE(buf); 105 pipe_mutex_unlock(mm->mutex); 106} 107 108 109static void * 110mm_buffer_map(struct pb_buffer *buf, 111 unsigned flags) 112{ 113 struct mm_buffer *mm_buf = mm_buffer(buf); 114 struct mm_pb_manager *mm = mm_buf->mgr; 115 116 return (unsigned char *) mm->map + mm_buf->block->ofs; 117} 118 119 120static void 121mm_buffer_unmap(struct pb_buffer *buf) 122{ 123 /* No-op */ 124} 125 126 127static void 128mm_buffer_get_base_buffer(struct pb_buffer *buf, 129 struct pb_buffer **base_buf, 130 unsigned *offset) 131{ 132 struct mm_buffer *mm_buf = mm_buffer(buf); 133 struct mm_pb_manager *mm = mm_buf->mgr; 134 pb_get_base_buffer(mm->buffer, base_buf, offset); 135 *offset += mm_buf->block->ofs; 136} 137 138 139static const struct pb_vtbl 140mm_buffer_vtbl = { 141 mm_buffer_destroy, 142 mm_buffer_map, 143 mm_buffer_unmap, 144 mm_buffer_get_base_buffer 145}; 146 147 148static struct pb_buffer * 149mm_bufmgr_create_buffer(struct pb_manager *mgr, 150 size_t size, 151 const struct pb_desc *desc) 152{ 153 struct mm_pb_manager *mm = mm_pb_manager(mgr); 154 struct mm_buffer *mm_buf; 155 156 /* We don't handle alignments larger then the one initially setup */ 157 assert(desc->alignment % (1 << mm->align2) == 0); 158 if(desc->alignment % (1 << mm->align2)) 159 return NULL; 160 161 pipe_mutex_lock(mm->mutex); 162 163 mm_buf = CALLOC_STRUCT(mm_buffer); 164 if (!mm_buf) { 165 pipe_mutex_unlock(mm->mutex); 166 return NULL; 167 } 168 169 mm_buf->base.base.refcount = 1; 170 mm_buf->base.base.alignment = desc->alignment; 171 mm_buf->base.base.usage = desc->usage; 172 mm_buf->base.base.size = size; 173 174 mm_buf->base.vtbl = &mm_buffer_vtbl; 175 176 mm_buf->mgr = mm; 177 178 mm_buf->block = u_mmAllocMem(mm->heap, size, mm->align2, 0); 179 if(!mm_buf->block) { 180 debug_printf("warning: heap full\n"); 181#if 0 182 mmDumpMemInfo(mm->heap); 183#endif 184 185 mm_buf->block = u_mmAllocMem(mm->heap, size, mm->align2, 0); 186 if(!mm_buf->block) { 187 FREE(mm_buf); 188 pipe_mutex_unlock(mm->mutex); 189 return NULL; 190 } 191 } 192 193 /* Some sanity checks */ 194 assert(0 <= (unsigned)mm_buf->block->ofs && (unsigned)mm_buf->block->ofs < mm->size); 195 assert(size <= (unsigned)mm_buf->block->size && (unsigned)mm_buf->block->ofs + (unsigned)mm_buf->block->size <= mm->size); 196 197 pipe_mutex_unlock(mm->mutex); 198 return SUPER(mm_buf); 199} 200 201 202static void 203mm_bufmgr_flush(struct pb_manager *mgr) 204{ 205 /* No-op */ 206} 207 208 209static void 210mm_bufmgr_destroy(struct pb_manager *mgr) 211{ 212 struct mm_pb_manager *mm = mm_pb_manager(mgr); 213 214 pipe_mutex_lock(mm->mutex); 215 216 u_mmDestroy(mm->heap); 217 218 pb_unmap(mm->buffer); 219 pb_reference(&mm->buffer, NULL); 220 221 pipe_mutex_unlock(mm->mutex); 222 223 FREE(mgr); 224} 225 226 227struct pb_manager * 228mm_bufmgr_create_from_buffer(struct pb_buffer *buffer, 229 size_t size, size_t align2) 230{ 231 struct mm_pb_manager *mm; 232 233 if(!buffer) 234 return NULL; 235 236 mm = CALLOC_STRUCT(mm_pb_manager); 237 if (!mm) 238 return NULL; 239 240 mm->base.destroy = mm_bufmgr_destroy; 241 mm->base.create_buffer = mm_bufmgr_create_buffer; 242 mm->base.flush = mm_bufmgr_flush; 243 244 mm->size = size; 245 mm->align2 = align2; /* 64-byte alignment */ 246 247 pipe_mutex_init(mm->mutex); 248 249 mm->buffer = buffer; 250 251 mm->map = pb_map(mm->buffer, 252 PIPE_BUFFER_USAGE_CPU_READ | 253 PIPE_BUFFER_USAGE_CPU_WRITE); 254 if(!mm->map) 255 goto failure; 256 257 mm->heap = u_mmInit(0, size); 258 if (!mm->heap) 259 goto failure; 260 261 return SUPER(mm); 262 263failure: 264if(mm->heap) 265 mmDestroy(mm->heap); 266 if(mm->map) 267 pb_unmap(mm->buffer); 268 if(mm) 269 FREE(mm); 270 return NULL; 271} 272 273 274struct pb_manager * 275mm_bufmgr_create(struct pb_manager *provider, 276 size_t size, size_t align2) 277{ 278 struct pb_buffer *buffer; 279 struct pb_manager *mgr; 280 struct pb_desc desc; 281 282 if(!provider) 283 return NULL; 284 285 memset(&desc, 0, sizeof(desc)); 286 desc.alignment = 1 << align2; 287 288 buffer = provider->create_buffer(provider, size, &desc); 289 if (!buffer) 290 return NULL; 291 292 mgr = mm_bufmgr_create_from_buffer(buffer, size, align2); 293 if (!mgr) { 294 pb_reference(&buffer, NULL); 295 return NULL; 296 } 297 298 return mgr; 299} 300