1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2006 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * 6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 8bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 9bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 10bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 11bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 12bf215546Sopenharmony_ci * the following conditions: 13bf215546Sopenharmony_ci * 14bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 15bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 16bf215546Sopenharmony_ci * of the Software. 17bf215546Sopenharmony_ci * 18bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 20bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 22bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 23bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 24bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 25bf215546Sopenharmony_ci * 26bf215546Sopenharmony_ci **************************************************************************/ 27bf215546Sopenharmony_ci 28bf215546Sopenharmony_ci/** 29bf215546Sopenharmony_ci * \file 30bf215546Sopenharmony_ci * Buffer manager using the old texture memory manager. 31bf215546Sopenharmony_ci * 32bf215546Sopenharmony_ci * \author Jose Fonseca <jfonseca@vmware.com> 33bf215546Sopenharmony_ci */ 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci#include "pipe/p_defines.h" 37bf215546Sopenharmony_ci#include "util/u_debug.h" 38bf215546Sopenharmony_ci#include "os/os_thread.h" 39bf215546Sopenharmony_ci#include "util/u_memory.h" 40bf215546Sopenharmony_ci#include "util/list.h" 41bf215546Sopenharmony_ci#include "util/u_mm.h" 42bf215546Sopenharmony_ci#include "pb_buffer.h" 43bf215546Sopenharmony_ci#include "pb_bufmgr.h" 44bf215546Sopenharmony_ci 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci/** 47bf215546Sopenharmony_ci * Convenience macro (type safe). 48bf215546Sopenharmony_ci */ 49bf215546Sopenharmony_ci#define SUPER(__derived) (&(__derived)->base) 50bf215546Sopenharmony_ci 51bf215546Sopenharmony_ci 52bf215546Sopenharmony_cistruct mm_pb_manager 53bf215546Sopenharmony_ci{ 54bf215546Sopenharmony_ci struct pb_manager base; 55bf215546Sopenharmony_ci 56bf215546Sopenharmony_ci mtx_t mutex; 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_ci pb_size size; 59bf215546Sopenharmony_ci struct mem_block *heap; 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci pb_size align2; 62bf215546Sopenharmony_ci 63bf215546Sopenharmony_ci struct pb_buffer *buffer; 64bf215546Sopenharmony_ci void *map; 65bf215546Sopenharmony_ci}; 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci 68bf215546Sopenharmony_cistatic inline struct mm_pb_manager * 69bf215546Sopenharmony_cimm_pb_manager(struct pb_manager *mgr) 70bf215546Sopenharmony_ci{ 71bf215546Sopenharmony_ci assert(mgr); 72bf215546Sopenharmony_ci return (struct mm_pb_manager *)mgr; 73bf215546Sopenharmony_ci} 74bf215546Sopenharmony_ci 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_cistruct mm_buffer 77bf215546Sopenharmony_ci{ 78bf215546Sopenharmony_ci struct pb_buffer base; 79bf215546Sopenharmony_ci 80bf215546Sopenharmony_ci struct mm_pb_manager *mgr; 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci struct mem_block *block; 83bf215546Sopenharmony_ci}; 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_cistatic inline struct mm_buffer * 87bf215546Sopenharmony_cimm_buffer(struct pb_buffer *buf) 88bf215546Sopenharmony_ci{ 89bf215546Sopenharmony_ci assert(buf); 90bf215546Sopenharmony_ci return (struct mm_buffer *)buf; 91bf215546Sopenharmony_ci} 92bf215546Sopenharmony_ci 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_cistatic void 95bf215546Sopenharmony_cimm_buffer_destroy(void *winsys, struct pb_buffer *buf) 96bf215546Sopenharmony_ci{ 97bf215546Sopenharmony_ci struct mm_buffer *mm_buf = mm_buffer(buf); 98bf215546Sopenharmony_ci struct mm_pb_manager *mm = mm_buf->mgr; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci assert(!pipe_is_referenced(&mm_buf->base.reference)); 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci mtx_lock(&mm->mutex); 103bf215546Sopenharmony_ci u_mmFreeMem(mm_buf->block); 104bf215546Sopenharmony_ci FREE(mm_buf); 105bf215546Sopenharmony_ci mtx_unlock(&mm->mutex); 106bf215546Sopenharmony_ci} 107bf215546Sopenharmony_ci 108bf215546Sopenharmony_ci 109bf215546Sopenharmony_cistatic void * 110bf215546Sopenharmony_cimm_buffer_map(struct pb_buffer *buf, 111bf215546Sopenharmony_ci enum pb_usage_flags flags, 112bf215546Sopenharmony_ci void *flush_ctx) 113bf215546Sopenharmony_ci{ 114bf215546Sopenharmony_ci struct mm_buffer *mm_buf = mm_buffer(buf); 115bf215546Sopenharmony_ci struct mm_pb_manager *mm = mm_buf->mgr; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci /* XXX: it will be necessary to remap here to propagate flush_ctx */ 118bf215546Sopenharmony_ci 119bf215546Sopenharmony_ci return (unsigned char *) mm->map + mm_buf->block->ofs; 120bf215546Sopenharmony_ci} 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_cistatic void 124bf215546Sopenharmony_cimm_buffer_unmap(struct pb_buffer *buf) 125bf215546Sopenharmony_ci{ 126bf215546Sopenharmony_ci /* No-op */ 127bf215546Sopenharmony_ci} 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_cistatic enum pipe_error 131bf215546Sopenharmony_cimm_buffer_validate(struct pb_buffer *buf, 132bf215546Sopenharmony_ci struct pb_validate *vl, 133bf215546Sopenharmony_ci enum pb_usage_flags flags) 134bf215546Sopenharmony_ci{ 135bf215546Sopenharmony_ci struct mm_buffer *mm_buf = mm_buffer(buf); 136bf215546Sopenharmony_ci struct mm_pb_manager *mm = mm_buf->mgr; 137bf215546Sopenharmony_ci return pb_validate(mm->buffer, vl, flags); 138bf215546Sopenharmony_ci} 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_cistatic void 142bf215546Sopenharmony_cimm_buffer_fence(struct pb_buffer *buf, 143bf215546Sopenharmony_ci struct pipe_fence_handle *fence) 144bf215546Sopenharmony_ci{ 145bf215546Sopenharmony_ci struct mm_buffer *mm_buf = mm_buffer(buf); 146bf215546Sopenharmony_ci struct mm_pb_manager *mm = mm_buf->mgr; 147bf215546Sopenharmony_ci pb_fence(mm->buffer, fence); 148bf215546Sopenharmony_ci} 149bf215546Sopenharmony_ci 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_cistatic void 152bf215546Sopenharmony_cimm_buffer_get_base_buffer(struct pb_buffer *buf, 153bf215546Sopenharmony_ci struct pb_buffer **base_buf, 154bf215546Sopenharmony_ci pb_size *offset) 155bf215546Sopenharmony_ci{ 156bf215546Sopenharmony_ci struct mm_buffer *mm_buf = mm_buffer(buf); 157bf215546Sopenharmony_ci struct mm_pb_manager *mm = mm_buf->mgr; 158bf215546Sopenharmony_ci pb_get_base_buffer(mm->buffer, base_buf, offset); 159bf215546Sopenharmony_ci *offset += mm_buf->block->ofs; 160bf215546Sopenharmony_ci} 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_cistatic const struct pb_vtbl 164bf215546Sopenharmony_cimm_buffer_vtbl = { 165bf215546Sopenharmony_ci mm_buffer_destroy, 166bf215546Sopenharmony_ci mm_buffer_map, 167bf215546Sopenharmony_ci mm_buffer_unmap, 168bf215546Sopenharmony_ci mm_buffer_validate, 169bf215546Sopenharmony_ci mm_buffer_fence, 170bf215546Sopenharmony_ci mm_buffer_get_base_buffer 171bf215546Sopenharmony_ci}; 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_cistatic struct pb_buffer * 175bf215546Sopenharmony_cimm_bufmgr_create_buffer(struct pb_manager *mgr, 176bf215546Sopenharmony_ci pb_size size, 177bf215546Sopenharmony_ci const struct pb_desc *desc) 178bf215546Sopenharmony_ci{ 179bf215546Sopenharmony_ci struct mm_pb_manager *mm = mm_pb_manager(mgr); 180bf215546Sopenharmony_ci struct mm_buffer *mm_buf; 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci /* We don't handle alignments larger then the one initially setup */ 183bf215546Sopenharmony_ci assert(pb_check_alignment(desc->alignment, 1u << mm->align2)); 184bf215546Sopenharmony_ci if(!pb_check_alignment(desc->alignment, 1u << mm->align2)) 185bf215546Sopenharmony_ci return NULL; 186bf215546Sopenharmony_ci 187bf215546Sopenharmony_ci mtx_lock(&mm->mutex); 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci mm_buf = CALLOC_STRUCT(mm_buffer); 190bf215546Sopenharmony_ci if (!mm_buf) { 191bf215546Sopenharmony_ci mtx_unlock(&mm->mutex); 192bf215546Sopenharmony_ci return NULL; 193bf215546Sopenharmony_ci } 194bf215546Sopenharmony_ci 195bf215546Sopenharmony_ci pipe_reference_init(&mm_buf->base.reference, 1); 196bf215546Sopenharmony_ci mm_buf->base.alignment_log2 = util_logbase2(desc->alignment); 197bf215546Sopenharmony_ci mm_buf->base.usage = desc->usage; 198bf215546Sopenharmony_ci mm_buf->base.size = size; 199bf215546Sopenharmony_ci 200bf215546Sopenharmony_ci mm_buf->base.vtbl = &mm_buffer_vtbl; 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci mm_buf->mgr = mm; 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci mm_buf->block = u_mmAllocMem(mm->heap, (int)size, (int)mm->align2, 0); 205bf215546Sopenharmony_ci if(!mm_buf->block) { 206bf215546Sopenharmony_ci#if 0 207bf215546Sopenharmony_ci debug_printf("warning: heap full\n"); 208bf215546Sopenharmony_ci mmDumpMemInfo(mm->heap); 209bf215546Sopenharmony_ci#endif 210bf215546Sopenharmony_ci FREE(mm_buf); 211bf215546Sopenharmony_ci mtx_unlock(&mm->mutex); 212bf215546Sopenharmony_ci return NULL; 213bf215546Sopenharmony_ci } 214bf215546Sopenharmony_ci 215bf215546Sopenharmony_ci /* Some sanity checks */ 216bf215546Sopenharmony_ci assert(0 <= (pb_size)mm_buf->block->ofs && (pb_size)mm_buf->block->ofs < mm->size); 217bf215546Sopenharmony_ci assert(size <= (pb_size)mm_buf->block->size && (pb_size)mm_buf->block->ofs + (pb_size)mm_buf->block->size <= mm->size); 218bf215546Sopenharmony_ci 219bf215546Sopenharmony_ci mtx_unlock(&mm->mutex); 220bf215546Sopenharmony_ci return SUPER(mm_buf); 221bf215546Sopenharmony_ci} 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_cistatic void 225bf215546Sopenharmony_cimm_bufmgr_flush(struct pb_manager *mgr) 226bf215546Sopenharmony_ci{ 227bf215546Sopenharmony_ci /* No-op */ 228bf215546Sopenharmony_ci} 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_ci 231bf215546Sopenharmony_cistatic void 232bf215546Sopenharmony_cimm_bufmgr_destroy(struct pb_manager *mgr) 233bf215546Sopenharmony_ci{ 234bf215546Sopenharmony_ci struct mm_pb_manager *mm = mm_pb_manager(mgr); 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci mtx_lock(&mm->mutex); 237bf215546Sopenharmony_ci 238bf215546Sopenharmony_ci u_mmDestroy(mm->heap); 239bf215546Sopenharmony_ci 240bf215546Sopenharmony_ci pb_unmap(mm->buffer); 241bf215546Sopenharmony_ci pb_reference(&mm->buffer, NULL); 242bf215546Sopenharmony_ci 243bf215546Sopenharmony_ci mtx_unlock(&mm->mutex); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci FREE(mgr); 246bf215546Sopenharmony_ci} 247bf215546Sopenharmony_ci 248bf215546Sopenharmony_ci 249bf215546Sopenharmony_cistruct pb_manager * 250bf215546Sopenharmony_cimm_bufmgr_create_from_buffer(struct pb_buffer *buffer, 251bf215546Sopenharmony_ci pb_size size, pb_size align2) 252bf215546Sopenharmony_ci{ 253bf215546Sopenharmony_ci struct mm_pb_manager *mm; 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci if (!buffer) 256bf215546Sopenharmony_ci return NULL; 257bf215546Sopenharmony_ci 258bf215546Sopenharmony_ci mm = CALLOC_STRUCT(mm_pb_manager); 259bf215546Sopenharmony_ci if (!mm) 260bf215546Sopenharmony_ci return NULL; 261bf215546Sopenharmony_ci 262bf215546Sopenharmony_ci mm->base.destroy = mm_bufmgr_destroy; 263bf215546Sopenharmony_ci mm->base.create_buffer = mm_bufmgr_create_buffer; 264bf215546Sopenharmony_ci mm->base.flush = mm_bufmgr_flush; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci mm->size = size; 267bf215546Sopenharmony_ci mm->align2 = align2; /* 64-byte alignment */ 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci (void) mtx_init(&mm->mutex, mtx_plain); 270bf215546Sopenharmony_ci 271bf215546Sopenharmony_ci mm->buffer = buffer; 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci mm->map = pb_map(mm->buffer, 274bf215546Sopenharmony_ci PB_USAGE_CPU_READ | 275bf215546Sopenharmony_ci PB_USAGE_CPU_WRITE, NULL); 276bf215546Sopenharmony_ci if(!mm->map) 277bf215546Sopenharmony_ci goto failure; 278bf215546Sopenharmony_ci 279bf215546Sopenharmony_ci mm->heap = u_mmInit(0, (int)size); 280bf215546Sopenharmony_ci if (!mm->heap) 281bf215546Sopenharmony_ci goto failure; 282bf215546Sopenharmony_ci 283bf215546Sopenharmony_ci return SUPER(mm); 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_cifailure: 286bf215546Sopenharmony_ci if(mm->heap) 287bf215546Sopenharmony_ci u_mmDestroy(mm->heap); 288bf215546Sopenharmony_ci if(mm->map) 289bf215546Sopenharmony_ci pb_unmap(mm->buffer); 290bf215546Sopenharmony_ci FREE(mm); 291bf215546Sopenharmony_ci return NULL; 292bf215546Sopenharmony_ci} 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_cistruct pb_manager * 296bf215546Sopenharmony_cimm_bufmgr_create(struct pb_manager *provider, 297bf215546Sopenharmony_ci pb_size size, pb_size align2) 298bf215546Sopenharmony_ci{ 299bf215546Sopenharmony_ci struct pb_buffer *buffer; 300bf215546Sopenharmony_ci struct pb_manager *mgr; 301bf215546Sopenharmony_ci struct pb_desc desc; 302bf215546Sopenharmony_ci 303bf215546Sopenharmony_ci if (!provider) 304bf215546Sopenharmony_ci return NULL; 305bf215546Sopenharmony_ci 306bf215546Sopenharmony_ci memset(&desc, 0, sizeof(desc)); 307bf215546Sopenharmony_ci desc.alignment = 1 << align2; 308bf215546Sopenharmony_ci 309bf215546Sopenharmony_ci buffer = provider->create_buffer(provider, size, &desc); 310bf215546Sopenharmony_ci if (!buffer) 311bf215546Sopenharmony_ci return NULL; 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci mgr = mm_bufmgr_create_from_buffer(buffer, size, align2); 314bf215546Sopenharmony_ci if (!mgr) { 315bf215546Sopenharmony_ci pb_reference(&buffer, NULL); 316bf215546Sopenharmony_ci return NULL; 317bf215546Sopenharmony_ci } 318bf215546Sopenharmony_ci 319bf215546Sopenharmony_ci return mgr; 320bf215546Sopenharmony_ci} 321