14a49301eSmrg/************************************************************************** 24a49301eSmrg * 3af69d88dSmrg * Copyright 2008 VMware, Inc. 44a49301eSmrg * All Rights Reserved. 54a49301eSmrg * 64a49301eSmrg * Permission is hereby granted, free of charge, to any person obtaining a 74a49301eSmrg * copy of this software and associated documentation files (the 84a49301eSmrg * "Software"), to deal in the Software without restriction, including 94a49301eSmrg * without limitation the rights to use, copy, modify, merge, publish, 104a49301eSmrg * distribute, sub license, and/or sell copies of the Software, and to 114a49301eSmrg * permit persons to whom the Software is furnished to do so, subject to 124a49301eSmrg * the following conditions: 134a49301eSmrg * 144a49301eSmrg * The above copyright notice and this permission notice (including the 154a49301eSmrg * next paragraph) shall be included in all copies or substantial portions 164a49301eSmrg * of the Software. 174a49301eSmrg * 184a49301eSmrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 194a49301eSmrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 204a49301eSmrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 21af69d88dSmrg * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 224a49301eSmrg * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 234a49301eSmrg * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 244a49301eSmrg * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 254a49301eSmrg * 264a49301eSmrg **************************************************************************/ 274a49301eSmrg 284a49301eSmrg/** 294a49301eSmrg * @file 304a49301eSmrg * Buffer validation. 314a49301eSmrg * 32af69d88dSmrg * @author Jose Fonseca <jfonseca@vmware.com> 334a49301eSmrg */ 344a49301eSmrg 354a49301eSmrg 364a49301eSmrg#include "pipe/p_compiler.h" 374a49301eSmrg#include "pipe/p_defines.h" 384a49301eSmrg#include "util/u_memory.h" 394a49301eSmrg#include "util/u_debug.h" 407ec681f3Smrg#include "util/u_hash_table.h" 414a49301eSmrg 424a49301eSmrg#include "pb_buffer.h" 434a49301eSmrg#include "pb_validate.h" 444a49301eSmrg 454a49301eSmrg 464a49301eSmrg#define PB_VALIDATE_INITIAL_SIZE 1 /* 512 */ 474a49301eSmrg 484a49301eSmrg 494a49301eSmrgstruct pb_validate_entry 504a49301eSmrg{ 514a49301eSmrg struct pb_buffer *buf; 524a49301eSmrg unsigned flags; 534a49301eSmrg}; 544a49301eSmrg 554a49301eSmrg 564a49301eSmrgstruct pb_validate 574a49301eSmrg{ 584a49301eSmrg struct pb_validate_entry *entries; 594a49301eSmrg unsigned used; 604a49301eSmrg unsigned size; 614a49301eSmrg}; 624a49301eSmrg 634a49301eSmrg 644a49301eSmrgenum pipe_error 654a49301eSmrgpb_validate_add_buffer(struct pb_validate *vl, 664a49301eSmrg struct pb_buffer *buf, 677ec681f3Smrg enum pb_usage_flags flags, 687ec681f3Smrg struct hash_table *ht, 697ec681f3Smrg boolean *already_present) 704a49301eSmrg{ 714a49301eSmrg assert(buf); 727ec681f3Smrg *already_present = FALSE; 7301e04c3fSmrg if (!buf) 744a49301eSmrg return PIPE_ERROR; 754a49301eSmrg 763464ebd5Sriastradh assert(flags & PB_USAGE_GPU_READ_WRITE); 773464ebd5Sriastradh assert(!(flags & ~PB_USAGE_GPU_READ_WRITE)); 783464ebd5Sriastradh flags &= PB_USAGE_GPU_READ_WRITE; 794a49301eSmrg 807ec681f3Smrg if (ht) { 817ec681f3Smrg unsigned entry_idx = (unsigned)(uintptr_t)util_hash_table_get(ht, buf); 827ec681f3Smrg 837ec681f3Smrg if (entry_idx) { 847ec681f3Smrg struct pb_validate_entry *entry = &vl->entries[entry_idx - 1]; 857ec681f3Smrg 867ec681f3Smrg assert(entry->buf == buf); 877ec681f3Smrg entry->flags |= flags; 887ec681f3Smrg *already_present = TRUE; 897ec681f3Smrg 907ec681f3Smrg return PIPE_OK; 917ec681f3Smrg } 924a49301eSmrg } 937ec681f3Smrg 944a49301eSmrg /* Grow the table */ 954a49301eSmrg if(vl->used == vl->size) { 964a49301eSmrg unsigned new_size; 974a49301eSmrg struct pb_validate_entry *new_entries; 984a49301eSmrg 994a49301eSmrg new_size = vl->size * 2; 1004a49301eSmrg if(!new_size) 1014a49301eSmrg return PIPE_ERROR_OUT_OF_MEMORY; 1024a49301eSmrg 1034a49301eSmrg new_entries = (struct pb_validate_entry *)REALLOC(vl->entries, 1044a49301eSmrg vl->size*sizeof(struct pb_validate_entry), 1054a49301eSmrg new_size*sizeof(struct pb_validate_entry)); 10601e04c3fSmrg if (!new_entries) 1074a49301eSmrg return PIPE_ERROR_OUT_OF_MEMORY; 1084a49301eSmrg 1094a49301eSmrg memset(new_entries + vl->size, 0, (new_size - vl->size)*sizeof(struct pb_validate_entry)); 1104a49301eSmrg 1114a49301eSmrg vl->size = new_size; 1124a49301eSmrg vl->entries = new_entries; 1134a49301eSmrg } 1144a49301eSmrg 1154a49301eSmrg assert(!vl->entries[vl->used].buf); 1164a49301eSmrg pb_reference(&vl->entries[vl->used].buf, buf); 1174a49301eSmrg vl->entries[vl->used].flags = flags; 1184a49301eSmrg ++vl->used; 1197ec681f3Smrg 1207ec681f3Smrg if (ht) 1217ec681f3Smrg _mesa_hash_table_insert(ht, buf, (void *) (uintptr_t) vl->used); 1227ec681f3Smrg 1234a49301eSmrg return PIPE_OK; 1244a49301eSmrg} 1254a49301eSmrg 1264a49301eSmrg 1274a49301eSmrgenum pipe_error 1284a49301eSmrgpb_validate_foreach(struct pb_validate *vl, 1294a49301eSmrg enum pipe_error (*callback)(struct pb_buffer *buf, void *data), 1304a49301eSmrg void *data) 1314a49301eSmrg{ 1324a49301eSmrg unsigned i; 1334a49301eSmrg for(i = 0; i < vl->used; ++i) { 1344a49301eSmrg enum pipe_error ret; 1354a49301eSmrg ret = callback(vl->entries[i].buf, data); 1364a49301eSmrg if(ret != PIPE_OK) 1374a49301eSmrg return ret; 1384a49301eSmrg } 1394a49301eSmrg return PIPE_OK; 1404a49301eSmrg} 1414a49301eSmrg 1424a49301eSmrg 1434a49301eSmrgenum pipe_error 1444a49301eSmrgpb_validate_validate(struct pb_validate *vl) 1454a49301eSmrg{ 1464a49301eSmrg unsigned i; 1474a49301eSmrg 1484a49301eSmrg for(i = 0; i < vl->used; ++i) { 1494a49301eSmrg enum pipe_error ret; 1504a49301eSmrg ret = pb_validate(vl->entries[i].buf, vl, vl->entries[i].flags); 1514a49301eSmrg if(ret != PIPE_OK) { 1524a49301eSmrg while(i--) 1534a49301eSmrg pb_validate(vl->entries[i].buf, NULL, 0); 1544a49301eSmrg return ret; 1554a49301eSmrg } 1564a49301eSmrg } 1574a49301eSmrg 1584a49301eSmrg return PIPE_OK; 1594a49301eSmrg} 1604a49301eSmrg 1614a49301eSmrg 1624a49301eSmrgvoid 1634a49301eSmrgpb_validate_fence(struct pb_validate *vl, 1644a49301eSmrg struct pipe_fence_handle *fence) 1654a49301eSmrg{ 1664a49301eSmrg unsigned i; 1674a49301eSmrg for(i = 0; i < vl->used; ++i) { 1684a49301eSmrg pb_fence(vl->entries[i].buf, fence); 1694a49301eSmrg pb_reference(&vl->entries[i].buf, NULL); 1704a49301eSmrg } 1714a49301eSmrg vl->used = 0; 1724a49301eSmrg} 1734a49301eSmrg 1744a49301eSmrg 1754a49301eSmrgvoid 1764a49301eSmrgpb_validate_destroy(struct pb_validate *vl) 1774a49301eSmrg{ 1784a49301eSmrg unsigned i; 1794a49301eSmrg for(i = 0; i < vl->used; ++i) 1804a49301eSmrg pb_reference(&vl->entries[i].buf, NULL); 1814a49301eSmrg FREE(vl->entries); 1824a49301eSmrg FREE(vl); 1834a49301eSmrg} 1844a49301eSmrg 1854a49301eSmrg 1864a49301eSmrgstruct pb_validate * 1874a49301eSmrgpb_validate_create() 1884a49301eSmrg{ 1894a49301eSmrg struct pb_validate *vl; 1904a49301eSmrg 1914a49301eSmrg vl = CALLOC_STRUCT(pb_validate); 19201e04c3fSmrg if (!vl) 1934a49301eSmrg return NULL; 1944a49301eSmrg 1954a49301eSmrg vl->size = PB_VALIDATE_INITIAL_SIZE; 1964a49301eSmrg vl->entries = (struct pb_validate_entry *)CALLOC(vl->size, sizeof(struct pb_validate_entry)); 1974a49301eSmrg if(!vl->entries) { 1984a49301eSmrg FREE(vl); 1994a49301eSmrg return NULL; 2004a49301eSmrg } 2014a49301eSmrg 2024a49301eSmrg return vl; 2034a49301eSmrg} 2044a49301eSmrg 205