pb_bufmgr_mm.c revision a6d866f72c88d48d2bcfb3e3c882fdb639b5a8ce
1/************************************************************************** 2 * 3 * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. 4 * All Rights Reserved. 5 * 6 * Permission is hereby granted, free of charge, to any person obtaining a 7 * copy of this software and associated documentation files (the 8 * "Software"), to deal in the Software without restriction, including 9 * without limitation the rights to use, copy, modify, merge, publish, 10 * distribute, sub license, and/or sell copies of the Software, and to 11 * permit persons to whom the Software is furnished to do so, subject to 12 * the following conditions: 13 * 14 * The above copyright notice and this permission notice (including the 15 * next paragraph) shall be included in all copies or substantial portions 16 * of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21 * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 22 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25 * 26 **************************************************************************/ 27 28/** 29 * \file 30 * Buffer manager using the old texture memory manager. 31 * 32 * \author Jose Fonseca <jrfonseca@tungstengraphics.com> 33 */ 34 35 36#include "pipe/p_defines.h" 37#include "pipe/p_debug.h" 38#include "pipe/p_thread.h" 39#include "util/u_memory.h" 40#include "util/u_double_list.h" 41#include "util/u_mm.h" 42#include "pb_buffer.h" 43#include "pb_bufmgr.h" 44 45 46/** 47 * Convenience macro (type safe). 48 */ 49#define SUPER(__derived) (&(__derived)->base) 50 51 52struct mm_pb_manager 53{ 54 struct pb_manager base; 55 56 pipe_mutex mutex; 57 58 size_t size; 59 struct mem_block *heap; 60 61 size_t align2; 62 63 struct pb_buffer *buffer; 64 void *map; 65}; 66 67 68static INLINE struct mm_pb_manager * 69mm_pb_manager(struct pb_manager *mgr) 70{ 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 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 enum pipe_error 128mm_buffer_validate(struct pb_buffer *buf, 129 struct pb_validate *vl, 130 unsigned flags) 131{ 132 struct mm_buffer *mm_buf = mm_buffer(buf); 133 struct mm_pb_manager *mm = mm_buf->mgr; 134 return pb_validate(mm->buffer, vl, flags); 135} 136 137 138static void 139mm_buffer_fence(struct pb_buffer *buf, 140 struct pipe_fence_handle *fence) 141{ 142 struct mm_buffer *mm_buf = mm_buffer(buf); 143 struct mm_pb_manager *mm = mm_buf->mgr; 144 pb_fence(mm->buffer, fence); 145} 146 147 148static void 149mm_buffer_get_base_buffer(struct pb_buffer *buf, 150 struct pb_buffer **base_buf, 151 unsigned *offset) 152{ 153 struct mm_buffer *mm_buf = mm_buffer(buf); 154 struct mm_pb_manager *mm = mm_buf->mgr; 155 pb_get_base_buffer(mm->buffer, base_buf, offset); 156 *offset += mm_buf->block->ofs; 157} 158 159 160static const struct pb_vtbl 161mm_buffer_vtbl = { 162 mm_buffer_destroy, 163 mm_buffer_map, 164 mm_buffer_unmap, 165 mm_buffer_validate, 166 mm_buffer_fence, 167 mm_buffer_get_base_buffer 168}; 169 170 171static struct pb_buffer * 172mm_bufmgr_create_buffer(struct pb_manager *mgr, 173 size_t size, 174 const struct pb_desc *desc) 175{ 176 struct mm_pb_manager *mm = mm_pb_manager(mgr); 177 struct mm_buffer *mm_buf; 178 179 /* We don't handle alignments larger then the one initially setup */ 180 assert(desc->alignment % (1 << mm->align2) == 0); 181 if(desc->alignment % (1 << mm->align2)) 182 return NULL; 183 184 pipe_mutex_lock(mm->mutex); 185 186 mm_buf = CALLOC_STRUCT(mm_buffer); 187 if (!mm_buf) { 188 pipe_mutex_unlock(mm->mutex); 189 return NULL; 190 } 191 192 mm_buf->base.base.refcount = 1; 193 mm_buf->base.base.alignment = desc->alignment; 194 mm_buf->base.base.usage = desc->usage; 195 mm_buf->base.base.size = size; 196 197 mm_buf->base.vtbl = &mm_buffer_vtbl; 198 199 mm_buf->mgr = mm; 200 201 mm_buf->block = mmAllocMem(mm->heap, size, mm->align2, 0); 202 if(!mm_buf->block) { 203 debug_printf("warning: heap full\n"); 204#if 0 205 mmDumpMemInfo(mm->heap); 206#endif 207 208 mm_buf->block = mmAllocMem(mm->heap, size, mm->align2, 0); 209 if(!mm_buf->block) { 210 FREE(mm_buf); 211 pipe_mutex_unlock(mm->mutex); 212 return NULL; 213 } 214 } 215 216 /* Some sanity checks */ 217 assert(0 <= (unsigned)mm_buf->block->ofs && (unsigned)mm_buf->block->ofs < mm->size); 218 assert(size <= (unsigned)mm_buf->block->size && (unsigned)mm_buf->block->ofs + (unsigned)mm_buf->block->size <= mm->size); 219 220 pipe_mutex_unlock(mm->mutex); 221 return SUPER(mm_buf); 222} 223 224 225static void 226mm_bufmgr_flush(struct pb_manager *mgr) 227{ 228 /* No-op */ 229} 230 231 232static void 233mm_bufmgr_destroy(struct pb_manager *mgr) 234{ 235 struct mm_pb_manager *mm = mm_pb_manager(mgr); 236 237 pipe_mutex_lock(mm->mutex); 238 239 mmDestroy(mm->heap); 240 241 pb_unmap(mm->buffer); 242 pb_reference(&mm->buffer, NULL); 243 244 pipe_mutex_unlock(mm->mutex); 245 246 FREE(mgr); 247} 248 249 250struct pb_manager * 251mm_bufmgr_create_from_buffer(struct pb_buffer *buffer, 252 size_t size, size_t align2) 253{ 254 struct mm_pb_manager *mm; 255 256 if(!buffer) 257 return NULL; 258 259 mm = CALLOC_STRUCT(mm_pb_manager); 260 if (!mm) 261 return NULL; 262 263 mm->base.destroy = mm_bufmgr_destroy; 264 mm->base.create_buffer = mm_bufmgr_create_buffer; 265 mm->base.flush = mm_bufmgr_flush; 266 267 mm->size = size; 268 mm->align2 = align2; /* 64-byte alignment */ 269 270 pipe_mutex_init(mm->mutex); 271 272 mm->buffer = buffer; 273 274 mm->map = pb_map(mm->buffer, 275 PIPE_BUFFER_USAGE_CPU_READ | 276 PIPE_BUFFER_USAGE_CPU_WRITE); 277 if(!mm->map) 278 goto failure; 279 280 mm->heap = mmInit(0, size); 281 if (!mm->heap) 282 goto failure; 283 284 return SUPER(mm); 285 286failure: 287if(mm->heap) 288 mmDestroy(mm->heap); 289 if(mm->map) 290 pb_unmap(mm->buffer); 291 if(mm) 292 FREE(mm); 293 return NULL; 294} 295 296 297struct pb_manager * 298mm_bufmgr_create(struct pb_manager *provider, 299 size_t size, size_t align2) 300{ 301 struct pb_buffer *buffer; 302 struct pb_manager *mgr; 303 struct pb_desc desc; 304 305 if(!provider) 306 return NULL; 307 308 memset(&desc, 0, sizeof(desc)); 309 desc.alignment = 1 << align2; 310 311 buffer = provider->create_buffer(provider, size, &desc); 312 if (!buffer) 313 return NULL; 314 315 mgr = mm_bufmgr_create_from_buffer(buffer, size, align2); 316 if (!mgr) { 317 pb_reference(&buffer, NULL); 318 return NULL; 319 } 320 321 return mgr; 322} 323