Merge branch 'master' into gallium-sampler-view
[mesa.git] / src / gallium / auxiliary / util / u_inlines.h
1 /**************************************************************************
2 *
3 * Copyright 2007 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 #ifndef U_INLINES_H
29 #define U_INLINES_H
30
31 #include "pipe/p_context.h"
32 #include "pipe/p_defines.h"
33 #include "pipe/p_state.h"
34 #include "pipe/p_screen.h"
35 #include "util/u_debug.h"
36 #include "util/u_atomic.h"
37
38
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42
43
44 /*
45 * Reference counting helper functions.
46 */
47
48
49 static INLINE void
50 pipe_reference_init(struct pipe_reference *reference, unsigned count)
51 {
52 p_atomic_set(&reference->count, count);
53 }
54
55 static INLINE boolean
56 pipe_is_referenced(struct pipe_reference *reference)
57 {
58 return p_atomic_read(&reference->count) != 0;
59 }
60
61 /**
62 * Update reference counting.
63 * The old thing pointed to, if any, will be unreferenced.
64 * Both 'ptr' and 'reference' may be NULL.
65 * \return TRUE if the object's refcount hits zero and should be destroyed.
66 */
67 static INLINE boolean
68 pipe_reference(struct pipe_reference *ptr, struct pipe_reference *reference)
69 {
70 boolean destroy = FALSE;
71
72 if(ptr != reference) {
73 /* bump the reference.count first */
74 if (reference) {
75 assert(pipe_is_referenced(reference));
76 p_atomic_inc(&reference->count);
77 }
78
79 if (ptr) {
80 assert(pipe_is_referenced(ptr));
81 if (p_atomic_dec_zero(&ptr->count)) {
82 destroy = TRUE;
83 }
84 }
85 }
86
87 return destroy;
88 }
89
90 static INLINE void
91 pipe_buffer_reference(struct pipe_buffer **ptr, struct pipe_buffer *buf)
92 {
93 struct pipe_buffer *old_buf;
94
95 assert(ptr);
96 old_buf = *ptr;
97
98 if (pipe_reference(&(*ptr)->reference, &buf->reference))
99 old_buf->screen->buffer_destroy(old_buf);
100 *ptr = buf;
101 }
102
103 static INLINE void
104 pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf)
105 {
106 struct pipe_surface *old_surf = *ptr;
107
108 if (pipe_reference(&(*ptr)->reference, &surf->reference))
109 old_surf->texture->screen->tex_surface_destroy(old_surf);
110 *ptr = surf;
111 }
112
113 static INLINE void
114 pipe_texture_reference(struct pipe_texture **ptr, struct pipe_texture *tex)
115 {
116 struct pipe_texture *old_tex = *ptr;
117
118 if (pipe_reference(&(*ptr)->reference, &tex->reference))
119 old_tex->screen->texture_destroy(old_tex);
120 *ptr = tex;
121 }
122
123 static INLINE void
124 pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view)
125 {
126 struct pipe_sampler_view *old_view = *ptr;
127
128 if (pipe_reference(&(*ptr)->reference, &view->reference))
129 old_view->context->sampler_view_destroy(old_view->context, old_view);
130 *ptr = view;
131 }
132
133
134 /*
135 * Convenience wrappers for screen buffer functions.
136 */
137
138 static INLINE struct pipe_buffer *
139 pipe_buffer_create( struct pipe_screen *screen,
140 unsigned alignment, unsigned usage, unsigned size )
141 {
142 return screen->buffer_create(screen, alignment, usage, size);
143 }
144
145 static INLINE struct pipe_buffer *
146 pipe_user_buffer_create( struct pipe_screen *screen, void *ptr, unsigned size )
147 {
148 return screen->user_buffer_create(screen, ptr, size);
149 }
150
151 static INLINE void *
152 pipe_buffer_map(struct pipe_screen *screen,
153 struct pipe_buffer *buf,
154 unsigned usage)
155 {
156 if(screen->buffer_map_range) {
157 unsigned offset = 0;
158 unsigned length = buf->size;
159 return screen->buffer_map_range(screen, buf, offset, length, usage);
160 }
161 else
162 return screen->buffer_map(screen, buf, usage);
163 }
164
165 static INLINE void
166 pipe_buffer_unmap(struct pipe_screen *screen,
167 struct pipe_buffer *buf)
168 {
169 screen->buffer_unmap(screen, buf);
170 }
171
172 static INLINE void *
173 pipe_buffer_map_range(struct pipe_screen *screen,
174 struct pipe_buffer *buf,
175 unsigned offset,
176 unsigned length,
177 unsigned usage)
178 {
179 assert(offset < buf->size);
180 assert(offset + length <= buf->size);
181 assert(length);
182 if(screen->buffer_map_range)
183 return screen->buffer_map_range(screen, buf, offset, length, usage);
184 else
185 return screen->buffer_map(screen, buf, usage);
186 }
187
188 static INLINE void
189 pipe_buffer_flush_mapped_range(struct pipe_screen *screen,
190 struct pipe_buffer *buf,
191 unsigned offset,
192 unsigned length)
193 {
194 assert(offset < buf->size);
195 assert(offset + length <= buf->size);
196 assert(length);
197 if(screen->buffer_flush_mapped_range)
198 screen->buffer_flush_mapped_range(screen, buf, offset, length);
199 }
200
201 static INLINE void
202 pipe_buffer_write(struct pipe_screen *screen,
203 struct pipe_buffer *buf,
204 unsigned offset, unsigned size,
205 const void *data)
206 {
207 void *map;
208
209 assert(offset < buf->size);
210 assert(offset + size <= buf->size);
211 assert(size);
212
213 map = pipe_buffer_map_range(screen, buf, offset, size,
214 PIPE_BUFFER_USAGE_CPU_WRITE |
215 PIPE_BUFFER_USAGE_FLUSH_EXPLICIT |
216 PIPE_BUFFER_USAGE_DISCARD);
217 assert(map);
218 if(map) {
219 memcpy((uint8_t *)map + offset, data, size);
220 pipe_buffer_flush_mapped_range(screen, buf, offset, size);
221 pipe_buffer_unmap(screen, buf);
222 }
223 }
224
225 /**
226 * Special case for writing non-overlapping ranges.
227 *
228 * We can avoid GPU/CPU synchronization when writing range that has never
229 * been written before.
230 */
231 static INLINE void
232 pipe_buffer_write_nooverlap(struct pipe_screen *screen,
233 struct pipe_buffer *buf,
234 unsigned offset, unsigned size,
235 const void *data)
236 {
237 void *map;
238
239 assert(offset < buf->size);
240 assert(offset + size <= buf->size);
241 assert(size);
242
243 map = pipe_buffer_map_range(screen, buf, offset, size,
244 PIPE_BUFFER_USAGE_CPU_WRITE |
245 PIPE_BUFFER_USAGE_FLUSH_EXPLICIT |
246 PIPE_BUFFER_USAGE_DISCARD |
247 PIPE_BUFFER_USAGE_UNSYNCHRONIZED);
248 assert(map);
249 if(map) {
250 memcpy((uint8_t *)map + offset, data, size);
251 pipe_buffer_flush_mapped_range(screen, buf, offset, size);
252 pipe_buffer_unmap(screen, buf);
253 }
254 }
255
256 static INLINE void
257 pipe_buffer_read(struct pipe_screen *screen,
258 struct pipe_buffer *buf,
259 unsigned offset, unsigned size,
260 void *data)
261 {
262 void *map;
263
264 assert(offset < buf->size);
265 assert(offset + size <= buf->size);
266 assert(size);
267
268 map = pipe_buffer_map_range(screen, buf, offset, size, PIPE_BUFFER_USAGE_CPU_READ);
269 assert(map);
270 if(map) {
271 memcpy(data, (const uint8_t *)map + offset, size);
272 pipe_buffer_unmap(screen, buf);
273 }
274 }
275
276 static INLINE void *
277 pipe_transfer_map( struct pipe_transfer *transf )
278 {
279 struct pipe_screen *screen = transf->texture->screen;
280 return screen->transfer_map(screen, transf);
281 }
282
283 static INLINE void
284 pipe_transfer_unmap( struct pipe_transfer *transf )
285 {
286 struct pipe_screen *screen = transf->texture->screen;
287 screen->transfer_unmap(screen, transf);
288 }
289
290 static INLINE void
291 pipe_transfer_destroy( struct pipe_transfer *transf )
292 {
293 struct pipe_screen *screen = transf->texture->screen;
294 screen->tex_transfer_destroy(transf);
295 }
296
297 static INLINE unsigned
298 pipe_transfer_buffer_flags( struct pipe_transfer *transf )
299 {
300 switch (transf->usage & PIPE_TRANSFER_READ_WRITE) {
301 case PIPE_TRANSFER_READ_WRITE:
302 return PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE;
303 case PIPE_TRANSFER_READ:
304 return PIPE_BUFFER_USAGE_CPU_READ;
305 case PIPE_TRANSFER_WRITE:
306 return PIPE_BUFFER_USAGE_CPU_WRITE;
307 default:
308 debug_assert(0);
309 return 0;
310 }
311 }
312
313 #ifdef __cplusplus
314 }
315 #endif
316
317 #endif /* U_INLINES_H */