Buffer.hh 8.93 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2011, Computer Graphics Group RWTH Aachen University         //
// All rights reserved.                                                       //
////////////////////////////////////////////////////////////////////////////////

#ifndef ACGL_OPENGL_OBJECTS_BUFFER_HH
#define ACGL_OPENGL_OBJECTS_BUFFER_HH

/*
 * A generic OpenGL Buffer Object
 *
 * Mostly an OpenGL Buffer Wrapper: names of OpenGL calls are stripped of the
 * 'gl' and 'Buffer' tokens and setters got a 'set' prefix.
 *
 * Calls that give the target the buffer should get bound to have an alternative
 * call that uses the last used or set target.
 *
 * Note: Most methods will bind this buffer!
 */

#include <ACGL/ACGL.hh>

#include <ACGL/Base/Macros.hh>
#include <ACGL/OpenGL/GL.hh>
#include <ACGL/OpenGL/Tools.hh>

#include <string>
#include <vector>
#include <tr1/memory>

namespace ACGL{
namespace OpenGL{

class Buffer
{
    ACGL_NOT_COPYABLE(Buffer)

    // ========================================================================================================= \/
    // ============================================================================================ CONSTRUCTORS \/
    // ========================================================================================================= \/
public:
    Buffer(void) :   mLastTarget(GL_INVALID_VALUE), mObjectName(0)
    {
        glGenBuffers(1, &mObjectName);
    }

    virtual ~Buffer(void)
    {
        // buffer 0 will get ignored by OpenGL
        glDeleteBuffers(1, &mObjectName);
    }

    // ==================================================================================================== \/
    // ============================================================================================ GETTERS \/
    // ==================================================================================================== \/
public:
    inline GLuint operator()    (void) const { return mObjectName; }
    inline GLuint getObjectName (void) const { return mObjectName; }
    inline bool   isValid       (void) const { return glIsBuffer( mObjectName ); }

private:
    inline GLint getParameter( GLenum _parameter ) {
        bind( mLastTarget );
        GLint value;
        glGetBufferParameteriv( mLastTarget, _parameter, &value );
        return value;
    }

#if (ACGL_OPENGL_VERSION >= 32)
    inline GLint64 getParameter64( GLenum _parameter ) {
        bind( mLastTarget );
        GLint64 value;
        glGetBufferParameteri64v( mLastTarget, _parameter, &value );
        return value;
    }

    //! not side effect free! will bind this buffer to it's last target!
    //! caching of these values on RAM could be a good idea if needed very often!
    inline GLint64   getSize()        { return             getParameter64( GL_BUFFER_SIZE         ); }
    inline GLint64   getMapOffset()   { return             getParameter64( GL_BUFFER_MAP_OFFSET   ); }
    inline GLint64   getMapLength()   { return             getParameter64( GL_BUFFER_MAP_LENGTH   ); }
#else // OpenGL pre 3.2:
    inline GLint     getSize()        { return             getParameter  ( GL_BUFFER_SIZE         ); }
    inline GLint     getMapOffset()   { return             getParameter  ( GL_BUFFER_MAP_OFFSET   ); }
    inline GLint     getMapLength()   { return             getParameter  ( GL_BUFFER_MAP_LENGTH   ); }
#endif // OpenGL >= 3.2
    inline GLenum    getUsage()       { return (GLenum)    getParameter  ( GL_BUFFER_USAGE        ); }
    inline GLenum    getAccess()      { return (GLenum)    getParameter  ( GL_BUFFER_ACCESS       ); }
    inline GLint     getAccessFlags() { return (GLint)     getParameter  ( GL_BUFFER_ACCESS_FLAGS ); }
    inline GLboolean isMapped()       { return (GLboolean) getParameter  ( GL_BUFFER_MAPPED       ); }



    // ===================================================================================================== \/
    // ============================================================================================ WRAPPERS \/
    // ===================================================================================================== \/
public:
    //! Bind this buffer
    inline void bind( GLenum _target )
    {
        glBindBuffer( _target, mObjectName );
        openGLRareError();
        mLastTarget = _target;
    }

    //! Bind this buffer to its last target
    inline void bind()
    {
        glBindBuffer( mLastTarget, mObjectName );
        openGLRareError();
    }

    //! Set data for this buffer. Use only to init the buffer!
    //! Note: The function is not const, because it changes the corresponding GPU data
    inline void setData( GLenum _target, GLsizeiptr _size, const GLvoid *_pData = NULL, GLenum _usage = GL_STATIC_DRAW ) {
        bind( _target );
        glBufferData( _target, _size, _pData, _usage );
        openGLRareError();
    }

    //! Set data for this buffer at the last used target. Use only to init the buffer!
    inline void setData( GLsizeiptr _size, const GLvoid *_pData = NULL, GLenum _usage = GL_STATIC_DRAW ) {
        setData( mLastTarget, _size, _pData, _usage );
    }

    //! Use this to modify the buffer
    inline void setSubData( GLenum _target, GLintptr _offset,
                            GLsizeiptr _size, const GLvoid *_pData ) {
        bind( _target );
        glBufferSubData( _target, _offset, _size, _pData );
        openGLRareError();
    }

    //! Use this to modify the buffer
    inline void setSubData( GLintptr _offset, GLsizeiptr _size, const GLvoid *_pData ) {
        setSubData( mLastTarget, _offset, _size, _pData );
    }


#if (ACGL_OPENGL_VERSION >= 30)
    /** Map a part of the buffer to client memory
     * _offset & _length are values in bytes relative to the buffer
     * _access must contain one (or both) of:
     *      GL_MAP_READ_BIT and GL_MAP_WRITE_BIT
     *  and optionally:
     *      GL_MAP_INVALIDATE_RANGE_BIT GL_MAP_INVALIDATE_BUFFER_BIT
     *      GL_MAP_FLUSH_EXPLICIT_BIT GL_MAP_UNSYNCHRONIZED_BIT
     */
    GLvoid *mapRange( GLenum _target, GLintptr _offset, GLsizeiptr _length, GLbitfield _access ) {
        bind( _target );
        GLvoid *ret = glMapBufferRange( _target, _offset, _length, _access );
        openGLRareError();
        return ret;
    }

    inline GLvoid *mapRange( GLintptr _offset, GLsizeiptr _length, GLbitfield _access ) {
        return mapRange( mLastTarget, _offset, _length, _access );
    }

    /**
     * Spec:
     * If a buffer is mapped with the GL_MAP_FLUSH_EXPLICIT_BIT flag, modifications
     * to the mapped range may be indicated by calling this.
     * _offset and _length indicate a modified subrange of the mapping, in byte. The specified
     * subrange to flush is relative to the start of the currently mapped range of buffer.
     * This can be called multiple times to indicate distinct subranges
     * of the mapping which require flushing.
     */
    void flushMappedRange( GLenum _target, GLsizeiptr _offset, GLsizeiptr _length ) {
        bind( _target );
        glFlushMappedBufferRange( _target, _offset, _length );
        openGLRareError();
    }

    inline void flushMappedRange( GLintptr _offset, GLsizeiptr _length ) {
        flushMappedRange( mLastTarget, _offset, _length );
    }

    // TODO: bindBufferRange
    // TODO: bindBufferBase
#endif // OpenGL >= 3.0

    //! Maps the whole buffer, if using GL 3+, better use mapRange!
    //! _access is GL_READ_ONLY GL_WRITE_ONLY or GL_READ_WRITE
    GLvoid *map( GLenum _target, GLenum _access ) {
        bind( _target );
        GLvoid *ret = glMapBuffer( _target, _access );
        openGLRareError();
        return ret;
    }
    inline GLvoid *map( GLenum _access ) {
        return map( mLastTarget, _access );
    }

    GLboolean unmap( GLenum _target ) {
        bind( _target );
        GLboolean ret = glUnmapBuffer( _target );
        openGLRareError();
        return ret;
    }

    inline GLboolean unmap() {
        return unmap( mLastTarget );
    }

    // TODO: CopyBufferSubData

    /**
     * _target must be one of:
        GL_ARRAY_BUFFER
        GL_ATOMIC_COUNTER_BUFFER
        GL_COPY_READ_BUFFER
        GL_COPY_WRITE_BUFFER
        GL_DRAW_INDIRECT_BUFFER
        GL_ELEMENT_ARRAY_BUFFER
        GL_PIXEL_PACK_BUFFER
        GL_PIXEL_UNPACK_BUFFER
        GL_TEXTURE_BUFFER
        GL_TRANSFORM_FEEDBACK_BUFFER
        GL_UNIFORM_BUFFER
     * Can be changed at any time. Will get changed if a _target gets specified at any call.
     */
    inline void setTarget( GLenum _target ) { mLastTarget = _target; }

    // =================================================================================================== \/
    // ============================================================================================ FIELDS \/
    // =================================================================================================== \/
protected:
    GLenum       mLastTarget;
    GLuint       mObjectName;
};

ACGL_SHARED_TYPEDEF(ArrayBuffer)

} // OpenGL
} // ACGL

#endif // ACGL_OPENGL_OBJECTS_BUFFER_HH