pb_validate.c revision e06474dbae6979177629fb6187331291ff230c65
1/************************************************************************** 2 * 3 * Copyright 2008 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 validation. 31 * 32 * @author Jose Fonseca <jrfonseca@tungstengraphics.com> 33 */ 34 35 36#include "pipe/p_compiler.h" 37#include "pipe/p_error.h" 38#include "util/u_memory.h" 39#include "pipe/p_debug.h" 40 41#include "pb_buffer.h" 42#include "pb_buffer_fenced.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 unsigned flags) 68{ 69 assert(buf); 70 if(!buf) 71 return PIPE_ERROR; 72 73 assert(flags & PIPE_BUFFER_USAGE_GPU_READ_WRITE); 74 assert(!(flags & ~PIPE_BUFFER_USAGE_GPU_READ_WRITE)); 75 flags &= PIPE_BUFFER_USAGE_GPU_READ_WRITE; 76 77 /* We only need to store one reference for each buffer, so avoid storing 78 * consecutive references for the same buffer. It might not be the most 79 * common pattern, but it is easy to implement. 80 */ 81 if(vl->used && vl->entries[vl->used - 1].buf == buf) { 82 vl->entries[vl->used - 1].flags |= flags; 83 return PIPE_OK; 84 } 85 86 /* Grow the table */ 87 if(vl->used == vl->size) { 88 unsigned new_size; 89 struct pb_validate_entry *new_entries; 90 91 new_size = vl->size * 2; 92 if(!new_size) 93 return PIPE_ERROR_OUT_OF_MEMORY; 94 95 new_entries = (struct pb_validate_entry *)REALLOC(vl->entries, 96 vl->size*sizeof(struct pb_validate_entry), 97 new_size*sizeof(struct pb_validate_entry)); 98 if(!new_entries) 99 return PIPE_ERROR_OUT_OF_MEMORY; 100 101 memset(new_entries + vl->size, 0, (new_size - vl->size)*sizeof(struct pb_validate_entry)); 102 103 vl->size = new_size; 104 vl->entries = new_entries; 105 } 106 107 assert(!vl->entries[vl->used].buf); 108 pb_reference(&vl->entries[vl->used].buf, buf); 109 vl->entries[vl->used].flags = flags; 110 ++vl->used; 111 112 return PIPE_OK; 113} 114 115 116enum pipe_error 117pb_validate_foreach(struct pb_validate *vl, 118 enum pipe_error (*callback)(struct pb_buffer *buf, void *data), 119 void *data) 120{ 121 unsigned i; 122 for(i = 0; i < vl->used; ++i) { 123 enum pipe_error ret; 124 ret = callback(vl->entries[i].buf, data); 125 if(ret != PIPE_OK) 126 return ret; 127 } 128 return PIPE_OK; 129} 130 131 132enum pipe_error 133pb_validate_validate(struct pb_validate *vl) 134{ 135 unsigned i; 136 137 for(i = 0; i < vl->used; ++i) { 138 enum pipe_error ret; 139 ret = pb_validate(vl->entries[i].buf, vl, vl->entries[i].flags); 140 if(ret != PIPE_OK) { 141 while(i--) 142 pb_validate(vl->entries[i].buf, NULL, 0); 143 return ret; 144 } 145 } 146 147 return PIPE_OK; 148} 149 150 151void 152pb_validate_fence(struct pb_validate *vl, 153 struct pipe_fence_handle *fence) 154{ 155 unsigned i; 156 for(i = 0; i < vl->used; ++i) { 157 pb_fence(vl->entries[i].buf, fence); 158 pb_reference(&vl->entries[i].buf, NULL); 159 } 160 vl->used = 0; 161} 162 163 164void 165pb_validate_destroy(struct pb_validate *vl) 166{ 167 unsigned i; 168 for(i = 0; i < vl->used; ++i) 169 pb_reference(&vl->entries[i].buf, NULL); 170 FREE(vl->entries); 171 FREE(vl); 172} 173 174 175struct pb_validate * 176pb_validate_create() 177{ 178 struct pb_validate *vl; 179 180 vl = CALLOC_STRUCT(pb_validate); 181 if(!vl) 182 return NULL; 183 184 vl->size = PB_VALIDATE_INITIAL_SIZE; 185 vl->entries = (struct pb_validate_entry *)CALLOC(vl->size, sizeof(struct pb_validate_entry)); 186 if(!vl->entries) { 187 FREE(vl); 188 return NULL; 189 } 190 191 return vl; 192} 193 194