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
49 struct pb_validate_entry
50 {
51 struct pb_buffer *buf;
52 unsigned flags;
53 };
54
55
56 struct pb_validate
57 {
58 struct pb_validate_entry *entries;
59 unsigned used;
60 unsigned size;
61 };
62
63
64 enum pipe_error
pb_validate_add_buffer(struct pb_validate * vl,struct pb_buffer * buf,enum pb_usage_flags flags,struct hash_table * ht,boolean * already_present)65 pb_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
127 enum pipe_error
pb_validate_foreach(struct pb_validate * vl,enum pipe_error (* callback)(struct pb_buffer * buf,void * data),void * data)128 pb_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
143 enum pipe_error
pb_validate_validate(struct pb_validate * vl)144 pb_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
162 void
pb_validate_fence(struct pb_validate * vl,struct pipe_fence_handle * fence)163 pb_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
175 void
pb_validate_destroy(struct pb_validate * vl)176 pb_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
186 struct pb_validate *
pb_validate_create()187 pb_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