1/************************************************************************** 2 * 3 * Copyright 2008 VMware, Inc. 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 VMWARE 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 validation. 31 * 32 * @author Jose Fonseca <jfonseca@vmware.com> 33 */ 34 35 36#include "pipe/p_compiler.h" 37#include "pipe/p_defines.h" 38#include "util/u_memory.h" 39#include "util/u_debug.h" 40#include "util/u_hash_table.h" 41 42#include "pb_buffer.h" 43#include "pb_validate.h" 44 45 46#define PB_VALIDATE_INITIAL_SIZE 1 /* 512 */ 47 48 49struct pb_validate_entry 50{ 51 struct pb_buffer *buf; 52 unsigned flags; 53}; 54 55 56struct pb_validate 57{ 58 struct pb_validate_entry *entries; 59 unsigned used; 60 unsigned size; 61}; 62 63 64enum pipe_error 65pb_validate_add_buffer(struct pb_validate *vl, 66 struct pb_buffer *buf, 67 enum pb_usage_flags flags, 68 struct hash_table *ht, 69 boolean *already_present) 70{ 71 assert(buf); 72 *already_present = FALSE; 73 if (!buf) 74 return PIPE_ERROR; 75 76 assert(flags & PB_USAGE_GPU_READ_WRITE); 77 assert(!(flags & ~PB_USAGE_GPU_READ_WRITE)); 78 flags &= PB_USAGE_GPU_READ_WRITE; 79 80 if (ht) { 81 unsigned entry_idx = (unsigned)(uintptr_t)util_hash_table_get(ht, buf); 82 83 if (entry_idx) { 84 struct pb_validate_entry *entry = &vl->entries[entry_idx - 1]; 85 86 assert(entry->buf == buf); 87 entry->flags |= flags; 88 *already_present = TRUE; 89 90 return PIPE_OK; 91 } 92 } 93 94 /* Grow the table */ 95 if(vl->used == vl->size) { 96 unsigned new_size; 97 struct pb_validate_entry *new_entries; 98 99 new_size = vl->size * 2; 100 if(!new_size) 101 return PIPE_ERROR_OUT_OF_MEMORY; 102 103 new_entries = (struct pb_validate_entry *)REALLOC(vl->entries, 104 vl->size*sizeof(struct pb_validate_entry), 105 new_size*sizeof(struct pb_validate_entry)); 106 if (!new_entries) 107 return PIPE_ERROR_OUT_OF_MEMORY; 108 109 memset(new_entries + vl->size, 0, (new_size - vl->size)*sizeof(struct pb_validate_entry)); 110 111 vl->size = new_size; 112 vl->entries = new_entries; 113 } 114 115 assert(!vl->entries[vl->used].buf); 116 pb_reference(&vl->entries[vl->used].buf, buf); 117 vl->entries[vl->used].flags = flags; 118 ++vl->used; 119 120 if (ht) 121 _mesa_hash_table_insert(ht, buf, (void *) (uintptr_t) vl->used); 122 123 return PIPE_OK; 124} 125 126 127enum pipe_error 128pb_validate_foreach(struct pb_validate *vl, 129 enum pipe_error (*callback)(struct pb_buffer *buf, void *data), 130 void *data) 131{ 132 unsigned i; 133 for(i = 0; i < vl->used; ++i) { 134 enum pipe_error ret; 135 ret = callback(vl->entries[i].buf, data); 136 if(ret != PIPE_OK) 137 return ret; 138 } 139 return PIPE_OK; 140} 141 142 143enum pipe_error 144pb_validate_validate(struct pb_validate *vl) 145{ 146 unsigned i; 147 148 for(i = 0; i < vl->used; ++i) { 149 enum pipe_error ret; 150 ret = pb_validate(vl->entries[i].buf, vl, vl->entries[i].flags); 151 if(ret != PIPE_OK) { 152 while(i--) 153 pb_validate(vl->entries[i].buf, NULL, 0); 154 return ret; 155 } 156 } 157 158 return PIPE_OK; 159} 160 161 162void 163pb_validate_fence(struct pb_validate *vl, 164 struct pipe_fence_handle *fence) 165{ 166 unsigned i; 167 for(i = 0; i < vl->used; ++i) { 168 pb_fence(vl->entries[i].buf, fence); 169 pb_reference(&vl->entries[i].buf, NULL); 170 } 171 vl->used = 0; 172} 173 174 175void 176pb_validate_destroy(struct pb_validate *vl) 177{ 178 unsigned i; 179 for(i = 0; i < vl->used; ++i) 180 pb_reference(&vl->entries[i].buf, NULL); 181 FREE(vl->entries); 182 FREE(vl); 183} 184 185 186struct pb_validate * 187pb_validate_create() 188{ 189 struct pb_validate *vl; 190 191 vl = CALLOC_STRUCT(pb_validate); 192 if (!vl) 193 return NULL; 194 195 vl->size = PB_VALIDATE_INITIAL_SIZE; 196 vl->entries = (struct pb_validate_entry *)CALLOC(vl->size, sizeof(struct pb_validate_entry)); 197 if(!vl->entries) { 198 FREE(vl); 199 return NULL; 200 } 201 202 return vl; 203} 204 205