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