f8dfea4e51abec04441ed3fb9d902168bab56ae2
[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 = *ptr;
94
95 if (pipe_reference(&(*ptr)->reference, &buf->reference))
96 old_buf->screen->buffer_destroy(old_buf);
97 *ptr = buf;
98 }
99
100 static INLINE void
101 pipe_surface_reference(struct pipe_surface **ptr, struct pipe_surface *surf)
102 {
103 struct pipe_surface *old_surf = *ptr;
104
105 if (pipe_reference(&(*ptr)->reference, &surf->reference))
106 old_surf->texture->screen->tex_surface_destroy(old_surf);
107 *ptr = surf;
108 }
109
110 static INLINE void
111 pipe_texture_reference(struct pipe_texture **ptr, struct pipe_texture *tex)
112 {
113 struct pipe_texture *old_tex = *ptr;
114
115 if (pipe_reference(&(*ptr)->reference, &tex->reference))
116 old_tex->screen->texture_destroy(old_tex);
117 *ptr = tex;
118 }
119
120 static INLINE void
121 pipe_sampler_view_reference(struct pipe_sampler_view **ptr, struct pipe_sampler_view *view)
122 {
123 struct pipe_sampler_view *old_view = *ptr;
124
125 if (pipe_reference(&(*ptr)->reference, &view->reference))
126 old_view->context->sampler_view_destroy(old_view->context, old_view);
127 *ptr = view;
128 }
129
130
131 /*
132 * Convenience wrappers for screen buffer functions.
133 */
134
135 static INLINE struct pipe_buffer *
136 pipe_buffer_create( struct pipe_screen *screen,
137 unsigned alignment, unsigned usage, unsigned size )
138 {
139 return screen->buffer_create(screen, alignment, usage, size);
140 }
141
142 static INLINE struct pipe_buffer *
143 pipe_user_buffer_create( struct pipe_screen *screen, void *ptr, unsigned size )
144 {
145 return screen->user_buffer_create(screen, ptr, size);
146 }
147
148 static INLINE void *
149 pipe_buffer_map(struct pipe_screen *screen,
150 struct pipe_buffer *buf,
151 unsigned usage)
152 {
153 if(screen->buffer_map_range) {
154 unsigned offset = 0;
155 unsigned length = buf->size;
156 return screen->buffer_map_range(screen, buf, offset, length, usage);
157 }
158 else
159 return screen->buffer_map(screen, buf, usage);
160 }
161
162 static INLINE void
163 pipe_buffer_unmap(struct pipe_screen *screen,
164 struct pipe_buffer *buf)
165 {
166 screen->buffer_unmap(screen, buf);
167 }
168
169 static INLINE void *
170 pipe_buffer_map_range(struct pipe_screen *screen,
171 struct pipe_buffer *buf,
172 unsigned offset,
173 unsigned length,
174 unsigned usage)
175 {
176 assert(offset < buf->size);
177 assert(offset + length <= buf->size);
178 assert(length);
179 if(screen->buffer_map_range)
180 return screen->buffer_map_range(screen, buf, offset, length, usage);
181 else
182 return screen->buffer_map(screen, buf, usage);
183 }
184
185 static INLINE void
186 pipe_buffer_flush_mapped_range(struct pipe_screen *screen,
187 struct pipe_buffer *buf,
188 unsigned offset,
189 unsigned length)
190 {
191 assert(offset < buf->size);
192 assert(offset + length <= buf->size);
193 assert(length);
194 if(screen->buffer_flush_mapped_range)
195 screen->buffer_flush_mapped_range(screen, buf, offset, length);
196 }
197
198 static INLINE void
199 pipe_buffer_write(struct pipe_screen *screen,
200 struct pipe_buffer *buf,
201 unsigned offset, unsigned size,
202 const void *data)
203 {
204 void *map;
205
206 assert(offset < buf->size);
207 assert(offset + size <= buf->size);
208 assert(size);
209
210 map = pipe_buffer_map_range(screen, buf, offset, size,
211 PIPE_BUFFER_USAGE_CPU_WRITE |
212 PIPE_BUFFER_USAGE_FLUSH_EXPLICIT |
213 PIPE_BUFFER_USAGE_DISCARD);
214 assert(map);
215 if(map) {
216 memcpy((uint8_t *)map + offset, data, size);
217 pipe_buffer_flush_mapped_range(screen, buf, offset, size);
218 pipe_buffer_unmap(screen, buf);
219 }
220 }
221
222 /**
223 * Special case for writing non-overlapping ranges.
224 *
225 * We can avoid GPU/CPU synchronization when writing range that has never
226 * been written before.
227 */
228 static INLINE void
229 pipe_buffer_write_nooverlap(struct pipe_screen *screen,
230 struct pipe_buffer *buf,
231 unsigned offset, unsigned size,
232 const void *data)
233 {
234 void *map;
235
236 assert(offset < buf->size);
237 assert(offset + size <= buf->size);
238 assert(size);
239
240 map = pipe_buffer_map_range(screen, buf, offset, size,
241 PIPE_BUFFER_USAGE_CPU_WRITE |
242 PIPE_BUFFER_USAGE_FLUSH_EXPLICIT |
243 PIPE_BUFFER_USAGE_DISCARD |
244 PIPE_BUFFER_USAGE_UNSYNCHRONIZED);
245 assert(map);
246 if(map) {
247 memcpy((uint8_t *)map + offset, data, size);
248 pipe_buffer_flush_mapped_range(screen, buf, offset, size);
249 pipe_buffer_unmap(screen, buf);
250 }
251 }
252
253 static INLINE void
254 pipe_buffer_read(struct pipe_screen *screen,
255 struct pipe_buffer *buf,
256 unsigned offset, unsigned size,
257 void *data)
258 {
259 void *map;
260
261 assert(offset < buf->size);
262 assert(offset + size <= buf->size);
263 assert(size);
264
265 map = pipe_buffer_map_range(screen, buf, offset, size, PIPE_BUFFER_USAGE_CPU_READ);
266 assert(map);
267 if(map) {
268 memcpy(data, (const uint8_t *)map + offset, size);
269 pipe_buffer_unmap(screen, buf);
270 }
271 }
272
273 static INLINE void *
274 pipe_transfer_map( struct pipe_transfer *transf )
275 {
276 struct pipe_screen *screen = transf->texture->screen;
277 return screen->transfer_map(screen, transf);
278 }
279
280 static INLINE void
281 pipe_transfer_unmap( struct pipe_transfer *transf )
282 {
283 struct pipe_screen *screen = transf->texture->screen;
284 screen->transfer_unmap(screen, transf);
285 }
286
287 static INLINE void
288 pipe_transfer_destroy( struct pipe_transfer *transf )
289 {
290 struct pipe_screen *screen = transf->texture->screen;
291 screen->tex_transfer_destroy(transf);
292 }
293
294 static INLINE unsigned
295 pipe_transfer_buffer_flags( struct pipe_transfer *transf )
296 {
297 switch (transf->usage & PIPE_TRANSFER_READ_WRITE) {
298 case PIPE_TRANSFER_READ_WRITE:
299 return PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE;
300 case PIPE_TRANSFER_READ:
301 return PIPE_BUFFER_USAGE_CPU_READ;
302 case PIPE_TRANSFER_WRITE:
303 return PIPE_BUFFER_USAGE_CPU_WRITE;
304 default:
305 debug_assert(0);
306 return 0;
307 }
308 }
309
310 #ifdef __cplusplus
311 }
312 #endif
313
314 #endif /* U_INLINES_H */