pb_bufmgr_mm.c revision c7431552c0ff203cd4b3ae37751b10e6111e4167
11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/************************************************************************** 21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. 41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * All Rights Reserved. 51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Permission is hereby granted, free of charge, to any person obtaining a 71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * copy of this software and associated documentation files (the 81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * "Software"), to deal in the Software without restriction, including 91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * without limitation the rights to use, copy, modify, merge, publish, 101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distribute, sub license, and/or sell copies of the Software, and to 111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * permit persons to whom the Software is furnished to do so, subject to 121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * the following conditions: 131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * The above copyright notice and this permission notice (including the 151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * next paragraph) shall be included in all copies or substantial portions 161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * of the Software. 171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR 221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert **************************************************************************/ 271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * \file 301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Buffer manager using the old texture memory manager. 311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * 321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * \author José Fonseca <jrfonseca@tungstengraphics.com> 331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "pipe/p_defines.h" 371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "pipe/p_debug.h" 381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "pipe/p_thread.h" 391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "util/u_memory.h" 401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "util/u_double_list.h" 411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "util/u_mm.h" 421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "pb_buffer.h" 431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#include "pb_bufmgr.h" 441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/** 471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Convenience macro (type safe). 481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */ 491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert#define SUPER(__derived) (&(__derived)->base) 501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstruct mm_pb_manager 531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{ 541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert struct pb_manager base; 551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert pipe_mutex mutex; 571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert size_t size; 591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert struct mem_block *heap; 601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert size_t align2; 621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert struct pb_buffer *buffer; 641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert void *map; 651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}; 661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic INLINE struct mm_pb_manager * 691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertmm_pb_manager(struct pb_manager *mgr) 701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{ 711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assert(mgr); 721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (struct mm_pb_manager *)mgr; 731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstruct mm_buffer 771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{ 781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert struct pb_buffer base; 791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert struct mm_pb_manager *mgr; 811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert struct mem_block *block; 831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}; 841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert 861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertstatic INLINE struct mm_buffer * 871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertmm_buffer(struct pb_buffer *buf) 881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert{ 891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert assert(buf); 901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert return (struct mm_buffer *)buf; 911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert} 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 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 = 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 FREE(mm_buf); 185 pipe_mutex_unlock(mm->mutex); 186 return NULL; 187 } 188 189 /* Some sanity checks */ 190 assert(0 <= (unsigned)mm_buf->block->ofs && (unsigned)mm_buf->block->ofs < mm->size); 191 assert(size <= (unsigned)mm_buf->block->size && (unsigned)mm_buf->block->ofs + (unsigned)mm_buf->block->size <= mm->size); 192 193 pipe_mutex_unlock(mm->mutex); 194 return SUPER(mm_buf); 195} 196 197 198static void 199mm_bufmgr_flush(struct pb_manager *mgr) 200{ 201 /* No-op */ 202} 203 204 205static void 206mm_bufmgr_destroy(struct pb_manager *mgr) 207{ 208 struct mm_pb_manager *mm = mm_pb_manager(mgr); 209 210 pipe_mutex_lock(mm->mutex); 211 212 mmDestroy(mm->heap); 213 214 pb_unmap(mm->buffer); 215 pb_reference(&mm->buffer, NULL); 216 217 pipe_mutex_unlock(mm->mutex); 218 219 FREE(mgr); 220} 221 222 223struct pb_manager * 224mm_bufmgr_create_from_buffer(struct pb_buffer *buffer, 225 size_t size, size_t align2) 226{ 227 struct mm_pb_manager *mm; 228 229 if(!buffer) 230 return NULL; 231 232 mm = CALLOC_STRUCT(mm_pb_manager); 233 if (!mm) 234 return NULL; 235 236 mm->base.destroy = mm_bufmgr_destroy; 237 mm->base.create_buffer = mm_bufmgr_create_buffer; 238 mm->base.flush = mm_bufmgr_flush; 239 240 mm->size = size; 241 mm->align2 = align2; /* 64-byte alignment */ 242 243 pipe_mutex_init(mm->mutex); 244 245 mm->buffer = buffer; 246 247 mm->map = pb_map(mm->buffer, 248 PIPE_BUFFER_USAGE_CPU_READ | 249 PIPE_BUFFER_USAGE_CPU_WRITE); 250 if(!mm->map) 251 goto failure; 252 253 mm->heap = mmInit(0, size); 254 if (!mm->heap) 255 goto failure; 256 257 return SUPER(mm); 258 259failure: 260if(mm->heap) 261 mmDestroy(mm->heap); 262 if(mm->map) 263 pb_unmap(mm->buffer); 264 if(mm) 265 FREE(mm); 266 return NULL; 267} 268 269 270struct pb_manager * 271mm_bufmgr_create(struct pb_manager *provider, 272 size_t size, size_t align2) 273{ 274 struct pb_buffer *buffer; 275 struct pb_manager *mgr; 276 struct pb_desc desc; 277 278 if(!provider) 279 return NULL; 280 281 memset(&desc, 0, sizeof(desc)); 282 desc.alignment = 1 << align2; 283 284 buffer = provider->create_buffer(provider, size, &desc); 285 if (!buffer) 286 return NULL; 287 288 mgr = mm_bufmgr_create_from_buffer(buffer, size, align2); 289 if (!mgr) { 290 pb_reference(&buffer, NULL); 291 return NULL; 292 } 293 294 return mgr; 295} 296