u_inlines.h revision cdc920a0
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
40extern "C" {
41#endif
42
43
44/*
45 * Reference counting helper functions.
46 */
47
48
49static INLINE void
50pipe_reference_init(struct pipe_reference *reference, unsigned count)
51{
52   p_atomic_set(&reference->count, count);
53}
54
55static INLINE boolean
56pipe_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 */
67static INLINE boolean
68pipe_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
90static INLINE void
91pipe_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
103static INLINE void
104pipe_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
113static INLINE void
114pipe_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
124/*
125 * Convenience wrappers for screen buffer functions.
126 */
127
128static INLINE struct pipe_buffer *
129pipe_buffer_create( struct pipe_screen *screen,
130                    unsigned alignment, unsigned usage, unsigned size )
131{
132   return screen->buffer_create(screen, alignment, usage, size);
133}
134
135static INLINE struct pipe_buffer *
136pipe_user_buffer_create( struct pipe_screen *screen, void *ptr, unsigned size )
137{
138   return screen->user_buffer_create(screen, ptr, size);
139}
140
141static INLINE void *
142pipe_buffer_map(struct pipe_screen *screen,
143                struct pipe_buffer *buf,
144                unsigned usage)
145{
146   if(screen->buffer_map_range) {
147      unsigned offset = 0;
148      unsigned length = buf->size;
149      return screen->buffer_map_range(screen, buf, offset, length, usage);
150   }
151   else
152      return screen->buffer_map(screen, buf, usage);
153}
154
155static INLINE void
156pipe_buffer_unmap(struct pipe_screen *screen,
157                  struct pipe_buffer *buf)
158{
159   screen->buffer_unmap(screen, buf);
160}
161
162static INLINE void *
163pipe_buffer_map_range(struct pipe_screen *screen,
164                struct pipe_buffer *buf,
165                unsigned offset,
166                unsigned length,
167                unsigned usage)
168{
169   assert(offset < buf->size);
170   assert(offset + length <= buf->size);
171   assert(length);
172   if(screen->buffer_map_range)
173      return screen->buffer_map_range(screen, buf, offset, length, usage);
174   else
175      return screen->buffer_map(screen, buf, usage);
176}
177
178static INLINE void
179pipe_buffer_flush_mapped_range(struct pipe_screen *screen,
180                               struct pipe_buffer *buf,
181                               unsigned offset,
182                               unsigned length)
183{
184   assert(offset < buf->size);
185   assert(offset + length <= buf->size);
186   assert(length);
187   if(screen->buffer_flush_mapped_range)
188      screen->buffer_flush_mapped_range(screen, buf, offset, length);
189}
190
191static INLINE void
192pipe_buffer_write(struct pipe_screen *screen,
193                  struct pipe_buffer *buf,
194                  unsigned offset, unsigned size,
195                  const void *data)
196{
197   void *map;
198
199   assert(offset < buf->size);
200   assert(offset + size <= buf->size);
201   assert(size);
202
203   map = pipe_buffer_map_range(screen, buf, offset, size,
204                               PIPE_BUFFER_USAGE_CPU_WRITE |
205                               PIPE_BUFFER_USAGE_FLUSH_EXPLICIT |
206                               PIPE_BUFFER_USAGE_DISCARD);
207   assert(map);
208   if(map) {
209      memcpy((uint8_t *)map + offset, data, size);
210      pipe_buffer_flush_mapped_range(screen, buf, offset, size);
211      pipe_buffer_unmap(screen, buf);
212   }
213}
214
215/**
216 * Special case for writing non-overlapping ranges.
217 *
218 * We can avoid GPU/CPU synchronization when writing range that has never
219 * been written before.
220 */
221static INLINE void
222pipe_buffer_write_nooverlap(struct pipe_screen *screen,
223                            struct pipe_buffer *buf,
224                            unsigned offset, unsigned size,
225                            const void *data)
226{
227   void *map;
228
229   assert(offset < buf->size);
230   assert(offset + size <= buf->size);
231   assert(size);
232
233   map = pipe_buffer_map_range(screen, buf, offset, size,
234                               PIPE_BUFFER_USAGE_CPU_WRITE |
235                               PIPE_BUFFER_USAGE_FLUSH_EXPLICIT |
236                               PIPE_BUFFER_USAGE_DISCARD |
237                               PIPE_BUFFER_USAGE_UNSYNCHRONIZED);
238   assert(map);
239   if(map) {
240      memcpy((uint8_t *)map + offset, data, size);
241      pipe_buffer_flush_mapped_range(screen, buf, offset, size);
242      pipe_buffer_unmap(screen, buf);
243   }
244}
245
246static INLINE void
247pipe_buffer_read(struct pipe_screen *screen,
248                 struct pipe_buffer *buf,
249                 unsigned offset, unsigned size,
250                 void *data)
251{
252   void *map;
253
254   assert(offset < buf->size);
255   assert(offset + size <= buf->size);
256   assert(size);
257
258   map = pipe_buffer_map_range(screen, buf, offset, size, PIPE_BUFFER_USAGE_CPU_READ);
259   assert(map);
260   if(map) {
261      memcpy(data, (const uint8_t *)map + offset, size);
262      pipe_buffer_unmap(screen, buf);
263   }
264}
265
266static INLINE void *
267pipe_transfer_map( struct pipe_transfer *transf )
268{
269   struct pipe_screen *screen = transf->texture->screen;
270   return screen->transfer_map(screen, transf);
271}
272
273static INLINE void
274pipe_transfer_unmap( struct pipe_transfer *transf )
275{
276   struct pipe_screen *screen = transf->texture->screen;
277   screen->transfer_unmap(screen, transf);
278}
279
280static INLINE void
281pipe_transfer_destroy( struct pipe_transfer *transf )
282{
283   struct pipe_screen *screen = transf->texture->screen;
284   screen->tex_transfer_destroy(transf);
285}
286
287static INLINE unsigned
288pipe_transfer_buffer_flags( struct pipe_transfer *transf )
289{
290   switch (transf->usage & PIPE_TRANSFER_READ_WRITE) {
291   case PIPE_TRANSFER_READ_WRITE:
292      return PIPE_BUFFER_USAGE_CPU_READ | PIPE_BUFFER_USAGE_CPU_WRITE;
293   case PIPE_TRANSFER_READ:
294      return PIPE_BUFFER_USAGE_CPU_READ;
295   case PIPE_TRANSFER_WRITE:
296      return PIPE_BUFFER_USAGE_CPU_WRITE;
297   default:
298      debug_assert(0);
299      return 0;
300   }
301}
302
303#ifdef __cplusplus
304}
305#endif
306
307#endif /* U_INLINES_H */
308