Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: code/branches/ode/ode-0.9/GIMPACT/include/GIMPACT/gim_memory.h @ 216

Last change on this file since 216 was 216, checked in by mathiask, 16 years ago

[Physik] add ode-0.9

File size: 33.7 KB
Line 
1#ifndef GIM_MEMORY_H_INCLUDED
2#define GIM_MEMORY_H_INCLUDED
3/*! \file gim_memory.h
4\author Francisco León
5*/
6/*
7-----------------------------------------------------------------------------
8This source file is part of GIMPACT Library.
9
10For the latest info, see http://gimpact.sourceforge.net/
11
12Copyright (c) 2006 Francisco Leon. C.C. 80087371.
13email: projectileman@yahoo.com
14
15 This library is free software; you can redistribute it and/or
16 modify it under the terms of EITHER:
17   (1) The GNU Lesser General Public License as published by the Free
18       Software Foundation; either version 2.1 of the License, or (at
19       your option) any later version. The text of the GNU Lesser
20       General Public License is included with this library in the
21       file GIMPACT-LICENSE-LGPL.TXT.
22   (2) The BSD-style license that is included with this library in
23       the file GIMPACT-LICENSE-BSD.TXT.
24
25 This library is distributed in the hope that it will be useful,
26 but WITHOUT ANY WARRANTY; without even the implied warranty of
27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files
28 GIMPACT-LICENSE-LGPL.TXT and GIMPACT-LICENSE-BSD.TXT for more details.
29
30-----------------------------------------------------------------------------
31*/
32
33
34#include "GIMPACT/gim_math.h"
35#include <memory.h>
36
37//#define PREFETCH 1
38//! \defgroup PREFETCH
39//! @{
40#ifdef PREFETCH
41#include <xmmintrin.h>  // for prefetch
42#define pfval   64
43#define pfval2  128
44//! Prefetch 64
45#define pf(_x,_i)       _mm_prefetch((void *)(_x + _i + pfval), 0)
46//! Prefetch 128
47#define pf2(_x,_i)      _mm_prefetch((void *)(_x + _i + pfval2), 0)
48#else
49//! Prefetch 64
50#define pf(_x,_i)
51//! Prefetch 128
52#define pf2(_x,_i)
53#endif
54//! @}
55
56/*! \defgroup ARRAY_UTILITIES
57\brief
58Functions for manip packed arrays of numbers
59*/
60//! @{
61#define GIM_COPY_ARRAYS(dest_array,source_array,element_count)\
62{\
63    GUINT _i_;\
64    for (_i_=0;_i_<element_count ;_i_++)\
65    {\
66        dest_array[_i_] = source_array[_i_];\
67    }\
68}\
69
70#define GIM_COPY_ARRAYS_1(dest_array,source_array,element_count,copy_macro)\
71{\
72    GUINT _i_;\
73    for (_i_=0;_i_<element_count ;_i_++)\
74    {\
75        copy_macro(dest_array[_i_],source_array[_i_]);\
76    }\
77}\
78
79
80#define GIM_ZERO_ARRAY(array,element_count)\
81{\
82    GUINT _i_;\
83    for (_i_=0;_i_<element_count ;_i_++)\
84    {\
85        array[_i_] = 0;\
86    }\
87}\
88
89#define GIM_CONSTANT_ARRAY(array,element_count,constant)\
90{\
91    GUINT _i_;\
92    for (_i_=0;_i_<element_count ;_i_++)\
93    {\
94        array[_i_] = constant;\
95    }\
96}\
97//! @}
98
99/*! \defgroup MEMORY_FUNCTION_PROTOTYPES
100Function prototypes to allocate and free memory.
101*/
102//! @{
103typedef void * gim_alloc_function (size_t size);
104typedef void * gim_alloca_function (size_t size);//Allocs on the heap
105typedef void * gim_realloc_function (void *ptr, size_t oldsize, size_t newsize);
106typedef void gim_free_function (void *ptr, size_t size);
107//! @}
108
109/*! \defgroup MEMORY_FUNCTION_HANDLERS
110\brief
111Memory Function Handlers
112 set new memory management functions. if fn is 0, the default handlers are
113  used. */
114//! @{
115void gim_set_alloc_handler (gim_alloc_function *fn);
116void gim_set_alloca_handler (gim_alloca_function *fn);
117void gim_set_realloc_handler (gim_realloc_function *fn);
118void gim_set_free_handler (gim_free_function *fn);
119//! @}
120
121/*! \defgroup MEMORY_FUNCTION_GET_HANDLERS
122\brief
123get current memory management functions.
124*/
125//! @{
126gim_alloc_function *gim_get_alloc_handler (void);
127gim_alloca_function *gim_get_alloca_handler(void);
128gim_realloc_function *gim_get_realloc_handler (void);
129gim_free_function  *gim_get_free_handler (void);
130//! @}
131
132/*! \defgroup MEMORY_FUNCTIONS
133Standar Memory functions
134*/
135//! @{
136void * gim_alloc(size_t size);
137void * gim_alloca(size_t size);
138void * gim_realloc(void *ptr, size_t oldsize, size_t newsize);
139void gim_free(void *ptr, size_t size);
140//! @}
141
142/*! \defgroup DYNAMIC_ARRAYS
143\brief
144Dynamic Arrays. Allocated from system memory.
145<ul>
146<li> For initializes a dynamic array, use GIM_DYNARRAY_CREATE or GIM_DYNARRAY_CREATE_SIZED.
147<li> When an array is no longer used, must be terminated with the macro GIM_DYNARRAY_DESTROY.
148</ul>
149*/
150//! @{
151#define G_ARRAY_GROW_SIZE 100
152
153//! Dynamic array handle.
154struct GDYNAMIC_ARRAY
155{
156    char * m_pdata;
157    GUINT m_size;
158    GUINT m_reserve_size;
159};
160//typedef  struct _GDYNAMIC_ARRAY GDYNAMIC_ARRAY;
161
162//! Creates a dynamic array zero sized
163#define GIM_DYNARRAY_CREATE(type,array_data,reserve_size) \
164{ \
165    array_data.m_pdata = (char *)gim_alloc(reserve_size*sizeof(type)); \
166    array_data.m_size = 0; \
167    array_data.m_reserve_size = reserve_size; \
168}\
169
170//! Creates a dynamic array with n = size elements
171#define GIM_DYNARRAY_CREATE_SIZED(type,array_data,size) \
172{ \
173    array_data.m_pdata = (char *)gim_alloc(size*sizeof(type)); \
174    array_data.m_size = size; \
175    array_data.m_reserve_size = size; \
176}\
177
178//! Reserves memory for a dynamic array.
179#define GIM_DYNARRAY_RESERVE_SIZE(type,array_data,reserve_size) \
180{ \
181    if(reserve_size>array_data.m_reserve_size )\
182    { \
183        array_data.m_pdata = (char *) gim_realloc(array_data.m_pdata,array_data.m_size*sizeof(type),reserve_size*sizeof(type));\
184        array_data.m_reserve_size = reserve_size; \
185    }\
186}\
187
188//! Set the size of the array
189#define GIM_DYNARRAY_SET_SIZE(type,array_data,size) \
190{ \
191    GIM_DYNARRAY_RESERVE_SIZE(type,array_data,size);\
192    array_data.m_size = size;\
193}\
194
195//! Gets a pointer from the beginning of the array
196#define GIM_DYNARRAY_POINTER(type,array_data) (type *)(array_data.m_pdata)
197
198//! Gets a pointer from the last elemento of the array
199#define GIM_DYNARRAY_POINTER_LAST(type,array_data) (((type *)array_data.m_pdata)+array_data.m_size-1)
200
201//! Inserts an element at the last position
202#define GIM_DYNARRAY_PUSH_ITEM(type,array_data,item)\
203{\
204    if(array_data.m_reserve_size<=array_data.m_size)\
205    {\
206        GIM_DYNARRAY_RESERVE_SIZE(type,array_data,(array_data.m_size+G_ARRAY_GROW_SIZE));\
207    }\
208    type * _pt = GIM_DYNARRAY_POINTER(type,array_data);\
209    memcpy(&_pt[array_data.m_size],&item,sizeof(type));\
210    array_data.m_size++;    \
211}\
212
213//! Inserts an element at the last position
214#define GIM_DYNARRAY_PUSH_EMPTY(type,array_data)\
215{\
216    if(array_data.m_reserve_size<=array_data.m_size)\
217    {\
218        GIM_DYNARRAY_RESERVE_SIZE(type,array_data,(array_data.m_size+G_ARRAY_GROW_SIZE));\
219    }\
220    array_data.m_size++;    \
221}\
222
223//! Inserts an element
224#define GIM_DYNARRAY_INSERT_ITEM(type,array_data,item,index) \
225{ \
226    if(array_data.m_reserve_size<=array_data.m_size)\
227    {\
228        GIM_DYNARRAY_RESERVE_SIZE(type,array_data,(array_data.m_size+G_ARRAY_GROW_SIZE));\
229    }\
230    type * _pt = GIM_DYNARRAY_POINTER(type,array_data);\
231    if(index<array_data.m_size-1) \
232    { \
233        memcpy(&_pt[index+1],&_pt[index],(array_data.m_size-index)*sizeof(type));\
234    } \
235    memcpy(&_pt[index],&item,sizeof(type));\
236    array_data.m_size++;    \
237}\
238
239//! Removes an element
240#define GIM_DYNARRAY_DELETE_ITEM(type,array_data,index) \
241{ \
242    if(index<array_data.m_size-1) \
243    { \
244        type * _pt = GIM_DYNARRAY_POINTER(type,array_data);\
245        memcpy(&_pt[index],&_pt[index+1],(array_data.m_size-index-1)*sizeof(type));\
246    } \
247    array_data.m_size--;    \
248}\
249
250//! Removes an element at the last position
251#define GIM_DYNARRAY_POP_ITEM(array_data) \
252{ \
253    if(array_data.m_size>0) \
254    { \
255        array_data.m_size--;    \
256    } \
257}\
258
259//! Destroys the array
260void GIM_DYNARRAY_DESTROY(GDYNAMIC_ARRAY & array_data);
261//! @}
262
263/*! \defgroup BITSET
264\brief
265Bitsets , based on \ref DYNAMIC_ARRAYS .
266<ul>
267<li> For initializes a bitset array, use \ref GIM_BITSET_CREATE or \ref GIM_BITSET_CREATE_SIZED.
268<li> When the bitset is no longer used, must be terminated with the macro \ref GIM_DYNARRAY_DESTROY.
269<li> For putting a mark on the bitset, call \ref GIM_BITSET_SET
270<li> For clearing a mark on the bitset, call \ref GIM_BITSET_CLEAR
271<li> For retrieving a bit value from a bitset, call \ref GIM_BITSET_GET-
272</ul>
273*/
274//! @{
275
276//! Creates a bitset
277#define GIM_BITSET_CREATE(array_data) GIM_DYNARRAY_CREATE(GUINT,array_data,G_ARRAY_GROW_SIZE)
278
279//! Creates a bitset, with their bits set to 0.
280#define GIM_BITSET_CREATE_SIZED(array_data,bits_count)\
281{\
282    array_data.m_size = bits_count/GUINT_BIT_COUNT + 1;\
283    GIM_DYNARRAY_CREATE(GUINT,array_data,array_data.m_size);\
284    GUINT * _pt = GIM_DYNARRAY_POINTER(GUINT,array_data);\
285    memset(_pt,0,sizeof(GUINT)*(array_data.m_size));\
286}\
287
288//! Gets the bitset bit count.
289#define GIM_BITSET_SIZE(array_data) (array_data.m_size*GUINT_BIT_COUNT)
290
291//! Resizes a bitset, with their bits set to 0.
292#define GIM_BITSET_RESIZE(array_data,new_bits_count)\
293{    \
294    GUINT _oldsize = array_data.m_size;\
295    array_data.m_size = new_bits_count/GUINT_BIT_COUNT + 1;    \
296    if(_oldsize<array_data.m_size)\
297    {\
298        if(array_data.m_size > array_data.m_reserve_size)\
299        {\
300            GIM_DYNARRAY_RESERVE_SIZE(GUINT,array_data,array_data.m_size+G_ARRAY_GROW_SIZE);\
301        }\
302        GUINT * _pt = GIM_DYNARRAY_POINTER(GUINT,array_data);\
303        memset(&_pt[_oldsize],0,sizeof(GUINT)*(array_data.m_size-_oldsize));\
304    }\
305}\
306
307//! Sets all bitset bit to 0.
308#define GIM_BITSET_CLEAR_ALL(array_data)\
309{\
310    memset(array_data.m_pdata,0,sizeof(GUINT)*array_data.m_size);\
311}\
312
313//! Sets all bitset bit to 1.
314#define GIM_BITSET_SET_ALL(array_data)\
315{\
316    memset(array_data.m_pdata,0xFF,sizeof(GUINT)*array_data.m_size);\
317}\
318
319///Sets the desired bit to 1
320#define GIM_BITSET_SET(array_data,bit_index)\
321{\
322    if(bit_index>=GIM_BITSET_SIZE(array_data))\
323        {\
324            GIM_BITSET_RESIZE(array_data,bit_index);\
325        }\
326        GUINT * _pt = GIM_DYNARRAY_POINTER(GUINT,array_data);\
327        _pt[bit_index >> GUINT_EXPONENT] |= (1 << (bit_index & (GUINT_BIT_COUNT-1)));\
328}\
329
330///Return 0 or 1
331#define GIM_BITSET_GET(array_data,bit_index,get_value) \
332{\
333    if(bit_index>=GIM_BITSET_SIZE(array_data))\
334        {\
335            get_value = 0;\
336        }\
337        else\
338        {\
339        GUINT * _pt = GIM_DYNARRAY_POINTER(GUINT,array_data);\
340        get_value = _pt[bit_index >> GUINT_EXPONENT] & (1 << (bit_index & (GUINT_BIT_COUNT-1)));\
341        }\
342}\
343
344///Sets the desired bit to 0
345#define GIM_BITSET_CLEAR(array_data,bit_index) \
346{\
347    if(bit_index<GIM_BITSET_SIZE(array_data))\
348        {\
349        GUINT * _pt = GIM_DYNARRAY_POINTER(GUINT,array_data);\
350        _pt[bit_index >> GUINT_EXPONENT] &= ~(1 << (bit_index & (GUINT_BIT_COUNT-1)));\
351        }\
352}\
353//! @}
354
355/*! \defgroup MEMORY_ACCESS_CONSTANTS
356\brief
357Memory Access constants.
358\sa BUFFERS
359*/
360//! @{
361#define G_MA_READ_ONLY 1
362#define G_MA_WRITE_ONLY 2
363#define G_MA_READ_WRITE 3
364//! @}
365
366/*! \defgroup MEMORY_USAGE_CONSTANTS
367\brief
368Memory usage constants.
369\sa BUFFERS
370*/
371//! @{
372/// Don't care how memory is used
373#define G_MU_EITHER 0
374/// specified once, doesn't allow read information
375#define G_MU_STATIC_WRITE 1
376/// specified once, allows to read information from a shadow buffer
377#define G_MU_STATIC_READ 2
378/// write directly on buffer, allows to read information from a shadow buffer
379#define G_MU_STATIC_READ_DYNAMIC_WRITE 3
380/// upload data to buffer from the shadow buffer, allows to read information from a shadow buffer
381#define G_MU_STATIC_READ_DYNAMIC_WRITE_COPY 4
382/// specified once, allows to read information directly from memory
383#define G_MU_STATIC_WRITE_DYNAMIC_READ 5
384/// write directly on buffer, allows to read information directly from memory
385#define G_MU_DYNAMIC_READ_WRITE 6
386//! @}
387
388/*! \defgroup BUFFER_ERRORS
389\brief
390Buffer operation errors
391\sa BUFFERS
392*/
393//! @{
394#define G_BUFFER_OP_SUCCESS 0
395#define G_BUFFER_OP_INVALID 1
396#define G_BUFFER_OP_STILLREFCOUNTED 2
397//! @}
398
399/*! \defgroup BUFFER_MANAGER_IDS
400\brief
401Buffer manager identifiers
402\sa BUFFERS, BUFFER_MANAGERS
403*/
404//! @{
405#define G_BUFFER_MANAGER_SYSTEM 0
406#define G_BUFFER_MANAGER_SHARED 1
407#define G_BUFFER_MANAGER_USER 2
408//! @}
409
410/*! \defgroup BUFFERS
411\brief
412Buffer operations and structs.
413<ul>
414<li> Before using buffers you must initializes GIMPACT buffer managers by calling \ref gimpact_init.
415<li> For initializes a buffer, use  \ref gim_create_buffer, \ref gim_create_buffer_from_data , \ref gim_create_common_buffer, \ref gim_create_common_buffer_from_data or \ref gim_create_shared_buffer_from_data.
416<li> For accessing to the buffer memory, you must call \ref gim_lock_buffer, and then \ref gim_unlock_buffer for finish the access.
417<li> When a buffer is no longer needed, you must free it by calling \ref gim_buffer_free.
418<li> You must call \ref gimpact_terminate when finish your application.
419<li> For a safe manipulation of buffers, use \ref BUFFER_ARRAYS
420</ul>
421\sa BUFFER_MANAGERS, BUFFER_ARRAYS
422*/
423//! @{
424
425//! Buffer handle.
426struct GBUFFER_ID
427{
428    GUINT m_buffer_id;
429    GUINT m_buffer_manager_id;
430};
431//typedef  struct _GBUFFER_ID GBUFFER_ID;
432
433//! Buffer internal data
434struct GBUFFER_DATA
435{
436    GUINT m_buffer_handle;//!< if 0, buffer doesn't exists
437    GUINT m_size;
438    GUINT m_usage;
439    GINT m_access;
440    GUINT m_lock_count;
441    char * m_mapped_pointer;
442    GBUFFER_ID m_shadow_buffer;
443    GUINT m_refcount;//! Reference counting for safe garbage collection
444};
445//typedef  struct _GBUFFER_DATA GBUFFER_DATA;
446//! @}
447
448/*! \defgroup BUFFERS_MANAGER_PROTOTYPES
449\brief
450Function prototypes to allocate and free memory for buffers
451\sa BUFFER_MANAGERS, BUFFERS
452*/
453//! @{
454
455//! Returns a Buffer handle
456typedef GUINT gim_buffer_alloc_function(GUINT size,int usage);
457
458//! Returns a Buffer handle, and copies the pdata to the buffer
459typedef GUINT gim_buffer_alloc_data_function(const void * pdata,GUINT size,int usage);
460
461//! Changes the size of the buffer preserving the content, and returns the new buffer id
462typedef GUINT gim_buffer_realloc_function(GUINT buffer_handle,GUINT oldsize,int old_usage,GUINT newsize,int new_usage);
463
464//! It changes the m_buffer_handle member to 0/0
465typedef void gim_buffer_free_function(GUINT buffer_handle,GUINT size);
466
467//! It maps the m_mapped_pointer. Returns a pointer
468typedef char * gim_lock_buffer_function(GUINT buffer_handle,int access);
469
470//! It sets the m_mapped_pointer to 0
471typedef void gim_unlock_buffer_function(GUINT buffer_handle);
472
473typedef void gim_download_from_buffer_function(
474        GUINT source_buffer_handle,
475                GUINT source_pos,
476                void * destdata,
477                GUINT copysize);
478
479typedef void  gim_upload_to_buffer_function(
480        GUINT dest_buffer_handle,
481                GUINT dest_pos,
482                void * sourcedata,
483                GUINT copysize);
484
485typedef void gim_copy_buffers_function(
486                GUINT source_buffer_handle,
487                GUINT source_pos,
488                GUINT dest_buffer_handle,
489                GUINT dest_pos,
490                GUINT copysize);
491//! @}
492
493
494/*! \defgroup BUFFER_MANAGERS
495\brief
496Buffer Manager operations
497*/
498//! @{
499//! Buffer manager prototype
500struct GBUFFER_MANAGER_PROTOTYPE
501{
502    gim_buffer_alloc_function * alloc_fn;
503    gim_buffer_alloc_data_function *alloc_data_fn;
504    gim_buffer_realloc_function * realloc_fn;
505    gim_buffer_free_function * free_fn;
506    gim_lock_buffer_function * lock_buffer_fn;
507    gim_unlock_buffer_function * unlock_buffer_fn;
508    gim_download_from_buffer_function * download_from_buffer_fn;
509    gim_upload_to_buffer_function * upload_to_buffer_fn;
510    gim_copy_buffers_function * copy_buffers_fn;
511};
512//typedef  struct _GBUFFER_MANAGER_PROTOTYPE GBUFFER_MANAGER_PROTOTYPE;
513
514//! Buffer manager
515struct GBUFFER_MANAGER_DATA
516{
517    GDYNAMIC_ARRAY m_buffer_array;//!< Array of GBUFFER_DATA objects
518    GDYNAMIC_ARRAY m_free_positions;//!< Array of GUINT elements. Free positions
519    GBUFFER_MANAGER_PROTOTYPE m_prototype;//! Prototype of functions
520    GUINT m_active; //!< 0 or 1
521};
522//typedef  struct _GBUFFER_MANAGER_DATA GBUFFER_MANAGER_DATA;
523
524//! Adds a buffer Manager to the Memory Singleton
525void gim_create_buffer_manager(GBUFFER_MANAGER_PROTOTYPE * prototype,GUINT buffer_manager_id);
526//! Gets buffer manager
527GUINT gim_get_buffer_manager_count();
528//! Destroys a buffer manager
529void gim_destroy_buffer_manager(GUINT buffer_manager_id);
530void gim_get_buffer_manager_data(GUINT buffer_manager_id,GBUFFER_MANAGER_DATA ** pbm_data);
531void gim_init_buffer_managers();
532void gim_terminate_buffer_managers();
533
534//! @}
535
536
537/*! \addtogroup BUFFERS
538*/
539//! @{
540
541//!Creates a buffer on the buffer manager specified by buffer_manager_id
542/*!
543\param buffer_manager_id
544\param buffer_size
545\param usage An usage constant. Use G_MU_DYNAMIC_READ_WRITE as default.
546\param buffer_id a pointer for receive the new buffer id
547\return An error code. 0 if success.
548\post m_refcount = 0
549*/
550GUINT gim_create_buffer(
551    GUINT buffer_manager_id,
552    GUINT buffer_size,
553    int usage,
554    GBUFFER_ID * buffer_id);
555
556//!Creates a buffer on the buffer manager specified by buffer_manager_id
557/*!
558\param buffer_manager_id
559\param pdata Data for allocating
560\param buffer_size Size of the data buffer
561\param usage An usage constant. Use G_MU_DYNAMIC_READ_WRITE as default.
562\param buffer_id a pointer for receive the new buffer id
563\return An error code. 0 if success.
564\post m_refcount = 0
565*/
566GUINT gim_create_buffer_from_data(
567    GUINT buffer_manager_id,
568    const void * pdata,
569    GUINT buffer_size,
570    int usage,
571    GBUFFER_ID * buffer_id);
572
573//!Allocates on the G_BUFFER_MANAGER_SYSTEM
574GUINT gim_create_common_buffer(GUINT buffer_size, GBUFFER_ID * buffer_id);
575//!Allocates on the G_BUFFER_MANAGER_SYSTEM, and copies the data
576GUINT gim_create_common_buffer_from_data(
577    const void * pdata, GUINT buffer_size, GBUFFER_ID * buffer_id);
578//!Creates a buffer with shared data
579GUINT gim_create_shared_buffer_from_data(
580    const void * pdata, GUINT buffer_size, GBUFFER_ID * buffer_id);
581
582
583//! Add reference counting to buffer.
584GINT gim_buffer_add_ref(GBUFFER_ID * buffer_id);
585
586//! Function for resize buffer, preserving the content
587/*!
588\param buffer_id
589\param newsize
590\return An error code. 0 if success.
591\post If m_refcount>0 then it decrements it.
592*/
593GINT gim_buffer_realloc(GBUFFER_ID * buffer_id,GUINT newsize);
594
595//! Eliminates the buffer.
596/*!
597If the buffer reference counting is <= 1 and is unlocked, then it eliminates the buffer.
598*/
599GINT gim_buffer_free(GBUFFER_ID * buffer_id);
600
601//! Locks the buffer for memory access.
602/*!
603\param buffer_id Id from buffer.
604\param access Must have the following values: G_MA_READ_ONLY,G_MA_WRITE_ONLY or G_MA_READ_WRITE.
605\param map_pointer Dest Pointer of the memory address from buffer.
606\post m_lock_count increases.
607*/
608GINT gim_lock_buffer(GBUFFER_ID * buffer_id,int access,char ** map_pointer);
609
610//! Unlocks the buffer for memory access.
611GINT gim_unlock_buffer(GBUFFER_ID * buffer_id);
612
613//! Gets the buffer size in bytes
614GINT gim_get_buffer_size(GBUFFER_ID * buffer_id,GUINT * buffer_size);
615
616//! Determines if the buffer is locked
617GINT gim_get_buffer_is_locked(GBUFFER_ID * buffer_id,GUINT * lock_count);
618
619//! Copies the content of the buffer to a dest pointer
620GINT gim_download_from_buffer(
621        GBUFFER_ID * buffer_id,
622                GUINT source_pos,
623                void * destdata,
624                GUINT copysize);
625
626//! Copies the content of a memory pointer to the buffer
627GINT  gim_upload_to_buffer(
628                GBUFFER_ID * buffer_id,
629                GUINT dest_pos,
630                void * sourcedata,
631                GUINT copysize);
632
633//! Copies two buffers.
634GINT  gim_copy_buffers(
635                GBUFFER_ID * source_buffer_id,
636                GUINT source_pos,
637                GBUFFER_ID * dest_buffer_id,
638                GUINT dest_pos,
639                GUINT copysize);
640//! @}
641
642
643/*! \defgroup BUFFER_ARRAYS
644
645\brief
646Buffered Arrays, for manip elements on a buffer and treat it as an array.
647<ul>
648<li> Before using buffer arrays you must initializes GIMPACT buffer managers by calling gimpact_init.
649<li> Before creating buffer arrays, you must create a buffer. see \ref BUFFERS.
650<li> Create a buffer narray by calling \ref GIM_BUFFER_ARRAY_INIT_TYPE, \ref GIM_BUFFER_ARRAY_INIT_TYPE_OFFSET or \ref GIM_BUFFER_ARRAY_INIT_OFFSET_STRIDE.
651<li> For accessing to the array elements, you must call \ref gim_buffer_array_lock, and then \ref gim_buffer_array_unlock for finish the access.
652<li> When a buffer array is no longer needed, you must free it by calling \ref GIM_BUFFER_ARRAY_DESTROY.
653</ul>
654The following example shows how Buffer arrays can be used:
655
656\code
657int main()
658{
659    //init gimpact
660    gimpact_init();
661
662    //Buffer handle to use
663    GBUFFER_ID bufferhandle;
664
665    //Create a memory buffer of 100 float numbers
666    gim_create_common_buffer(100*sizeof(float), &bufferhandle);
667
668    //Create a buffer array from the bufferhandle
669    GBUFFER_ARRAY buffer_float_array;
670    GIM_BUFFER_ARRAY_INIT_TYPE(float,buffer_float_array,bufferhandle,100);
671
672    ////Access to the buffer data, set all elements of the array
673
674    int i, count;
675    count = buffer_float_array.m_element_count;
676    //Locks the array
677    gim_buffer_array_lock(&buffer_float_array,G_MA_READ_WRITE);
678    float  * pelements = GIM_BUFFER_ARRAY_POINTER(float, buffer_float_array, 0); // A pointer to the buffer memory
679
680    //fill the array with random numbers
681    for (i = 0;i < count;i++ )
682    {
683        pelements[i] = gim_unit_random();
684    }
685    //unlock buffer
686    gim_buffer_array_unlock(&buffer_float_array);
687
688    //Program code
689        ....
690        ....
691
692    //Destroy array
693    GIM_BUFFER_ARRAY_DESTROY(buffer_float_array);
694
695    //terminate gimpact
696    gimpact_terminate();
697}
698\endcode
699
700\sa BUFFERS
701*/
702//! @{
703
704//! Buffer managed array struct.
705struct GBUFFER_ARRAY
706{
707  GBUFFER_ID m_buffer_id;
708  char * m_buffer_data;
709  char m_byte_stride;
710  GUINT m_byte_offset;
711  GUINT m_element_count;
712};
713//typedef  struct _GBUFFER_ARRAY GBUFFER_ARRAY;
714
715//! Sets offset for a buffered array.
716#define GIM_BUFFER_ARRAY_SET_OFFSET(_array_data,_offset) (_array_data).m_byte_offset = _offset*(_array_data).m_byte_stride;
717
718//! Sets offset for a buffered array.
719#define GIM_BUFFER_ARRAY_GET_OFFSET(_array_data,_offset) _offset = (_array_data).m_byte_offset/(_array_data).m_byte_stride;
720
721//!Return a pointer of the element at the _index
722#define GIM_BUFFER_ARRAY_POINTER(_type,_array_data,_index) (_type *)((_array_data).m_buffer_data + _index*(_array_data).m_byte_stride)
723
724//! Sets stride for a buffered array.
725#define GIM_BUFFER_ARRAY_SET_STRIDE(_type,_array_data) (_array_data).m_byte_stride = sizeof(_type);
726
727//! Is array stride equal to the size of the type ?
728#define GIM_BUFFER_ARRAY_IS_ALIGNED(_type,_array_data) ((_array_data).m_byte_stride == sizeof(_type))
729
730///Verify if two arrays have the same data
731#define GIM_BUFFER_ARRAY_ARE_SAME(_array_data1,_array_data2,aresame)\
732{\
733    aresame = 1;\
734    if((_array_data1).m_buffer_id.m_buffer_id != (_array_data2).m_buffer_id.m_buffer_id || (_array_data1).m_buffer_id.m_buffer_manager_id != (_array_data2).m_buffer_id.m_buffer_manager_id || (_array_data1).m_byte_offset != (_array_data2).m_byte_offset)\
735    {\
736        aresame = 0;\
737    }\
738}\
739
740//! Reserve size for a buffered array.
741/*!
742\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
743*/
744#define GIM_BUFFER_ARRAY_RESERVE_SIZE(type,array_data,reserve_size)\
745{ \
746    if(reserve_size>(array_data).m_element_count)\
747    {\
748        GUINT _buffer_size,_newarray_size;\
749        gim_get_buffer_size(&(array_data).m_buffer_id,_buffer_size);\
750        _newarray_size = reserve_size*(array_data).m_byte_stride;\
751        if(_newarray_size>_buffer_size)\
752        { \
753            _newarray_size += G_ARRAY_GROW_SIZE*(array_data).m_byte_stride;\
754            gim_buffer_realloc(&(array_data).m_buffer_id,_newarray_size);\
755        }\
756    }\
757}\
758
759//! Pushes an element at last position
760/*!
761\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
762*/
763#define GIM_BUFFER_ARRAY_PUSH_ITEM(type,array_data,item)\
764{\
765    GIM_BUFFER_ARRAY_RESERVE_SIZE(type,array_data,(array_data).m_element_count+1);\
766    gim_buffer_array_lock(&array_data,G_MA_WRITE_ONLY);\
767    type * _pt = GIM_BUFFER_ARRAY_POINTER(type,array_data,(array_data).m_element_count);\
768    memcpy(_pt,&item,sizeof(type));\
769    gim_buffer_array_unlock(&array_data);\
770    (array_data)->m_element_count++; \
771}\
772
773//! Pushes a new element at last position
774/*!
775\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
776*/
777#define GIM_BUFFER_ARRAY_PUSH_EMPTY(type,array_data)\
778{\
779    GIM_BUFFER_ARRAY_RESERVE_SIZE(type,array_data,(array_data).m_element_count+1);\
780    array_data->m_element_count++; \
781}\
782
783//! Inserts an element
784/*!
785\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
786*/
787#define GIM_BUFFER_ARRAY_INSERT_ITEM(type,array_data,item,index) \
788{ \
789    GIM_BUFFER_ARRAY_RESERVE_SIZE(type,array_data,(array_data).m_element_count+1);\
790    gim_buffer_array_lock(&array_data,G_MA_WRITE_ONLY);\
791    type * _pt = GIM_BUFFER_ARRAY_POINTER(type,array_data,0);\
792    if(index<(array_data)->m_element_count-1) \
793    { \
794        memcpy(&_pt[index+1],&_pt[index],((array_data).m_element_count-index)*sizeof(type));\
795    } \
796    memcpy(&_pt[index],&item,sizeof(type));\
797    gim_buffer_array_unlock(&array_data);\
798    (array_data).m_element_count++; \
799}\
800
801//! Deletes an element
802/*!
803\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
804*/
805#define GIM_BUFFER_ARRAY_DELETE_ITEM(type,array_data,index) \
806{ \
807    if(index<(array_data).m_element_count-1) \
808    { \
809        gim_buffer_array_lock(&array_data,G_MA_WRITE_ONLY);\
810        type * _pt = GIM_BUFFER_ARRAY_POINTER(type,array_data,0);\
811        memcpy(&_pt[index],&_pt[index+1],((array_data).m_element_count-index-1)*sizeof(type));\
812        gim_buffer_array_unlock(&array_data);\
813    } \
814    (array_data).m_element_count--;    \
815}\
816
817//! Deletes an element at last position
818/*!
819\pre array_data must be unlocked, and must be the aligned (GIM_BUFFER_ARRAY_IS_ALIGNED )
820*/
821#define GIM_BUFFER_ARRAY_POP_ITEM(array_data) \
822{ \
823    if((array_data).m_element_count>0) \
824    { \
825        (array_data).m_element_count--;    \
826    } \
827}\
828
829
830//! Initializes an GBUFFER_ARRAY object from a buffer ID
831/*!
832m_buffer_data will be 0, for acces to the elements, you'd need to call lock_array
833\param array_data Array structure to be filled
834\param buffer_id A GBUFFER_ID structure which this array_daya will refer to
835\param element_count Number of elements
836\param offset element offset, it isn't byte offset. 0 is recomended
837\param byte_stride size of each element.  0 is recomended.
838\post Adds reference to the buffer
839\sa gim_buffer_add_ref
840*/
841#define GIM_BUFFER_ARRAY_INIT_OFFSET_STRIDE(array_data,buffer_id,element_count,offset,byte_stride)\
842{\
843    (array_data).m_buffer_id.m_buffer_id = (buffer_id).m_buffer_id;\
844    (array_data).m_buffer_id.m_buffer_manager_id = (buffer_id).m_buffer_manager_id;\
845    (array_data).m_buffer_data = 0;\
846    (array_data).m_element_count = element_count;\
847    (array_data).m_byte_stride = byte_stride;\
848    GIM_BUFFER_ARRAY_SET_OFFSET(array_data,offset);\
849    gim_buffer_add_ref(&(buffer_id));\
850}\
851
852//! Initializes an GBUFFER_ARRAY object from a buffer ID and a Given type
853/*!
854m_buffer_data will be 0, for acces to the elements, you'd need to call lock_array
855\param type Type of the Array. It determines the stride.
856\param array_data Array structure to be filled
857\param buffer_id A GBUFFER_ID structure which this array_daya will refer to
858\param element_count Number of elements
859\param offset element offset, it isn't byte offset. 0 is recomended
860\post Adds reference to the buffer
861\sa gim_buffer_add_ref
862*/
863#define GIM_BUFFER_ARRAY_INIT_TYPE_OFFSET(type,array_data,buffer_id,element_count,offset)\
864{\
865    (array_data).m_buffer_id.m_buffer_id = (buffer_id).m_buffer_id;\
866    (array_data).m_buffer_id.m_buffer_manager_id = (buffer_id).m_buffer_manager_id;\
867    (array_data).m_buffer_data = 0;\
868    (array_data).m_element_count = element_count;\
869    GIM_BUFFER_ARRAY_SET_STRIDE(type,array_data);\
870    GIM_BUFFER_ARRAY_SET_OFFSET(array_data,offset);\
871    gim_buffer_add_ref(&(buffer_id));\
872}\
873
874//! Initializes a buffer array giving a data type and a buffer id
875/*!
876m_buffer_data will be 0, for acces to the elements, you'd need to call lock_array.
877\param type Type of the Array. It determines the stride.
878\param array_data Array structure to be filled
879\param buffer_id A GBUFFER_ID structure which this array_daya will refer to
880\param element_count Number of elements
881\post Adds reference to the buffer
882\sa gim_buffer_add_ref
883*/
884#define GIM_BUFFER_ARRAY_INIT_TYPE(type,array_data,buffer_id,element_count) GIM_BUFFER_ARRAY_INIT_TYPE_OFFSET(type,array_data,buffer_id,element_count,0)
885
886//! Gain access to the array buffer through the m_buffer_data element
887/*!
888m_buffer_data pointer will be located at the m_byte_offset position of the buffer m_buffer
889Then, You'd need to call unlock_array when finish to using the array access.
890
891\pre if m_buffer_data != 0, the function returns
892\param array_data Array structure to be locked
893\param access A constant for access to the buffer. can be G_MA_READ_ONLY,G_MA_WRITE_ONLY or G_MA_READ_WRITE
894\return an Buffer error code
895*/
896GINT gim_buffer_array_lock(GBUFFER_ARRAY * array_data, int access);
897
898//! close the access to the array buffer through the m_buffer_data element
899/*!
900\param array_data Array structure to be locked
901\return an Buffer error code
902*/
903GINT gim_buffer_array_unlock(GBUFFER_ARRAY * array_data);
904
905//! Copy an array by reference
906/*!
907\post A reference to the m_buffer_id is increased.
908*/
909void gim_buffer_array_copy_ref(GBUFFER_ARRAY * source_data,GBUFFER_ARRAY  * dest_data);
910
911
912//! Copy an array by value
913/*!
914\post A new buffer is created
915*/
916void gim_buffer_array_copy_value(GBUFFER_ARRAY * source_data,GBUFFER_ARRAY  * dest_data, GUINT buffer_manager_id,int usage);
917
918//! Destroys an GBUFFER_ARRAY object
919/*!
920\post Attemps to destroy the buffer, decreases reference counting
921*/
922void GIM_BUFFER_ARRAY_DESTROY(GBUFFER_ARRAY & array_data);
923
924//! Copy the content of the array to a pointer
925/*!
926\pre dest_data must have the same size as the array_data
927\param type
928\param array_data A GBUFFERED_ARRAY structure
929\param dest_data A type pointer
930*/
931#define GIM_BUFFER_ARRAY_DOWNLOAD(type,array_data,dest_data)\
932{\
933    if(GIM_BUFFER_ARRAY_IS_ALIGNED(type,array_data))\
934    {\
935        gim_download_from_buffer(&(array_data).m_buffer_id, (array_data).m_byte_offset,(void *) dest_data, (array_data).m_element_count*(array_data).m_byte_stride);\
936    }\
937    else\
938    {\
939        GUINT _k_, _ecount_= (array_data).m_element_count;\
940        type * _source_vert_;\
941        type * _dest_vert_ = dest_data;\
942        gim_buffer_array_lock(&(array_data),G_MA_READ_ONLY);\
943        for (_k_ = 0;_k_< _ecount_; _k_++)\
944        {\
945            _source_vert_ = GIM_BUFFER_ARRAY_POINTER(type,array_data,_k_);\
946            memcpy(_dest_vert_,_source_vert_,sizeof(type));\
947            _dest_vert_++;\
948        }\
949        gim_buffer_array_unlock(&(array_data));\
950    }\
951}\
952
953//! Upload the content of a a pointer to a buffered array
954/*!
955\pre source_data must have the same size as the array_data
956\param type
957\param array_data A GBUFFERED_ARRAY structure
958\param source_data A void pointer
959*/
960#define GIM_BUFFER_ARRAY_UPLOAD(type,array_data,source_data)\
961{\
962    if(GIM_BUFFER_ARRAY_IS_ALIGNED(type,array_data))\
963    {\
964        gim_upload_to_buffer(&(array_data).m_buffer_id, (array_data).m_byte_offset,(void *) source_data, (array_data).m_element_count*(array_data).m_byte_stride);\
965    }\
966    else\
967    {\
968        GUINT _k_, _ecount_= (array_data).m_element_count;\
969        type * _source_vert_ = source_data;\
970        type * _dest_vert_;\
971        gim_buffer_array_lock(&(array_data),G_MA_WRITE_ONLY);\
972        for (_k_ = 0;_k_< _ecount_; _k_++)\
973        {\
974            _dest_vert_ = GIM_BUFFER_ARRAY_POINTER(type,array_data,_k_);\
975            memcpy(_dest_vert_,_source_vert_,sizeof(type));\
976            _source_vert_++;\
977        }\
978        gim_buffer_array_unlock(&(array_data));\
979    }\
980}\
981
982
983//!Kernel function prototype for process streams, given a buffered array as source and
984/*!
985\param 1 the uniform arguments
986\param 2 the source stream
987\param 3 the destination stream
988*/
989typedef void (* gim_kernel_func)(void *,GBUFFER_ARRAY *,GBUFFER_ARRAY *);
990
991//! Generic Stream Processingp loop
992/*!
993
994This macro executes a kernel macro or function for each element of the streams
995\pre _src_array->m_count <= _dst_array->m_count
996
997\param _uniform_data An argument to be passed to the Kernel function
998\param _src_array An GBUFFER_ARRAY structure passed as the source stream
999\param _dst_array An GBUFFER_ARRAY  structure passed as the source stream
1000\param _kernel Macro or function of the kernel
1001\param _src_type Required. Type of all elements of the source stream
1002\param _dst_type Required. Type of all elements of the dest stream
1003*/
1004#define GIM_PROCESS_BUFFER_ARRAY(_uniform_data,_src_array,_dst_array,_kernel,_src_type,_dst_type) {\
1005\
1006    gim_buffer_array_lock(&_src_array,G_MA_READ_ONLY);\
1007    gim_buffer_array_lock(&_dst_array,G_MA_WRITE_ONLY);\
1008\
1009    GUINT _i_, _count_=(_src_array).m_element_count;\
1010\
1011    _src_type * _source_vert_;\
1012    _dst_type * _dest_vert_;\
1013    if(GIM_BUFFER_ARRAY_IS_ALIGNED(_src_type,_src_array) && GIM_BUFFER_ARRAY_IS_ALIGNED(_dst_type,_dst_array))\
1014    {\
1015\
1016        _source_vert_ = GIM_BUFFER_ARRAY_POINTER(_src_type,_src_array,0);\
1017        _dest_vert_ = GIM_BUFFER_ARRAY_POINTER(_dst_type,_dst_array,0);\
1018        for (_i_ = 0;_i_< _count_; _i_++)\
1019        {\
1020            _kernel(_uniform_data,(*_source_vert_),(*_dest_vert_));\
1021            _source_vert_++;\
1022            _dest_vert_++;\
1023        }\
1024    }\
1025    else\
1026    {\
1027        for (_i_ = 0;_i_< _count_; _i_++)\
1028        {\
1029            _source_vert_ = GIM_BUFFER_ARRAY_POINTER(_src_type,_src_array,_i_);\
1030            _dest_vert_ = GIM_BUFFER_ARRAY_POINTER(_dst_type,_dst_array,_i_);\
1031            _kernel(_uniform_data,(*_source_vert_),(*_dest_vert_));\
1032        }\
1033    }\
1034    gim_buffer_array_unlock(&_src_array);\
1035    gim_buffer_array_unlock(&_dst_array);\
1036}\
1037
1038//! @}
1039
1040#endif // GIM_MEMORY_H_INCLUDED
Note: See TracBrowser for help on using the repository browser.