Merge branch 'master' into glsl-pp-rework-2
[mesa.git] / src / gallium / auxiliary / pipebuffer / pb_validate.c
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_defines.h"
38 #include "util/u_memory.h"
39 #include "util/u_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
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
65 pb_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
116 enum pipe_error
117 pb_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
132 enum pipe_error
133 pb_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
151 void
152 pb_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
164 void
165 pb_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
175 struct pb_validate *
176 pb_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