You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

1303 lines
55 KiB

#ifndef Magnum_Buffer_h
#define Magnum_Buffer_h
/*
This file is part of Magnum.
Copyright © 2010, 2011, 2012, 2013, 2014
Vladimír Vondruš <mosra@centrum.cz>
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
to deal in the Software without restriction, including without limitation
the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
DEALINGS IN THE SOFTWARE.
*/
/** @file
* @brief Class @ref Magnum::Buffer, enum @ref Magnum::BufferUsage
*/
#include <cstddef>
#include <array>
#include <vector>
#include <Corrade/Containers/Array.h>
#include <Corrade/Containers/EnumSet.h>
#include <Corrade/Utility/Assert.h>
#include "Magnum/AbstractObject.h"
#include "Magnum/Magnum.h"
namespace Magnum {
/**
@brief %Buffer usage
@see @ref Buffer, @ref Buffer::setData(Containers::ArrayReference<const void>, BufferUsage)
*/
enum class BufferUsage: GLenum {
/** Set once by the application and used infrequently for drawing. */
StreamDraw = GL_STREAM_DRAW,
#ifndef MAGNUM_TARGET_GLES2
/**
* Set once as output from an OpenGL command and used infequently for
* drawing.
* @requires_gles30 Only @ref Magnum::BufferUsage::StreamDraw "BufferUsage::StreamDraw"
* is available in OpenGL ES 2.0.
*/
StreamRead = GL_STREAM_READ,
/**
* Set once as output from an OpenGL command and used infrequently for
* drawing or copying to other buffers.
* @requires_gles30 Only @ref Magnum::BufferUsage::StreamDraw "BufferUsage::StreamDraw"
* is available in OpenGL ES 2.0.
*/
StreamCopy = GL_STREAM_COPY,
#endif
/** Set once by the application and used frequently for drawing. */
StaticDraw = GL_STATIC_DRAW,
#ifndef MAGNUM_TARGET_GLES2
/**
* Set once as output from an OpenGL command and queried many times by the
* application.
* @requires_gles30 Only @ref Magnum::BufferUsage::StaticDraw "BufferUsage::StaticDraw"
* is available in OpenGL ES 2.0.
*/
StaticRead = GL_STATIC_READ,
/**
* Set once as output from an OpenGL command and used frequently for
* drawing or copying to other buffers.
* @requires_gles30 Only @ref Magnum::BufferUsage::StaticDraw "BufferUsage::StaticDraw"
* is available in OpenGL ES 2.0.
*/
StaticCopy = GL_STATIC_COPY,
#endif
/**
* Updated frequently by the application and used frequently for drawing or
* copying to other images.
*/
DynamicDraw = GL_DYNAMIC_DRAW,
#ifndef MAGNUM_TARGET_GLES2
/**
* Updated frequently as output from OpenGL command and queried many times
* from the application.
* @requires_gles30 Only @ref Magnum::BufferUsage::DynamicDraw "BufferUsage::DynamicDraw"
* is available in OpenGL ES 2.0.
*/
DynamicRead = GL_DYNAMIC_READ,
/**
* Updated frequently as output from OpenGL command and used frequently for
* drawing or copying to other images.
* @requires_gles30 Only @ref Magnum::BufferUsage::DynamicDraw "BufferUsage::DynamicDraw"
* is available in OpenGL ES 2.0.
*/
DynamicCopy = GL_DYNAMIC_COPY
#endif
};
namespace Implementation { struct BufferState; }
/**
@brief %Buffer
Encapsulates one OpenGL buffer object and provides functions for convenient
data updates.
## Data updating
Default way to set or update buffer data with @ref setData() or @ref setSubData()
is to use @ref Corrade::Containers::ArrayReference. See its documentation for
more information about automatic conversions etc.
@code
Containers::ArrayReference<Vector3> data;
buffer.setData(data, BufferUsage::StaticDraw);
@endcode
There is also overload for array-like containers from STL, such as `std::vector`
or `std::array`:
@code
std::vector<Vector3> data;
buffer.setData(data, BufferUsage::StaticDraw);
@endcode
@anchor Buffer-data-mapping
## Memory mapping
%Buffer data can be also updated asynchronously. First you need to allocate
the buffer to desired size by passing `nullptr` to @ref setData(), e.g.:
@code
buffer.setData({nullptr, 200*sizeof(Vector3)}, BufferUsage::StaticDraw);
@endcode
Then you can map the buffer to client memory and operate with the memory
directly. After you are done with the operation, call @ref unmap() to unmap the
buffer again.
@code
Vector3* data = static_cast<Vector3*>(buffer.map(0, 200*sizeof(Vector3), Buffer::MapFlag::Write|Buffer::MapFlag::InvalidateBuffer));
for(std::size_t i = 0; i != 200; ++i)
data[i] = ...;
CORRADE_INTERNAL_ASSERT_OUTPUT(buffer.unmap());
@endcode
If you are updating only a few discrete portions of the buffer, you can use
@ref MapFlag::FlushExplicit and @ref flushMappedRange() to reduce number of
memory operations performed by OpenGL on unmapping. Example:
@code
Vector3* data = static_cast<Vector3*>(buffer.map(0, 200*sizeof(Vector3), Buffer::MapFlag::Write|Buffer::MapFlag::FlushExplicit));
for(std::size_t i: {7, 27, 56, 128}) {
data[i] = ...;
buffer.flushMappedRange(i*sizeof(Vector3), sizeof(Vector3));
}
CORRADE_INTERNAL_ASSERT_OUTPUT(buffer.unmap());
@endcode
## WebGL and NaCl restrictions
Buffers in @ref MAGNUM_TARGET_WEBGL "WebGL" and @ref CORRADE_TARGET_NACL "NaCl"
need to be bound only to one unique target, i.e., @ref Buffer bound to
@ref Buffer::Target::Array cannot be later rebound to
@ref Buffer::Target::ElementArray. However, %Magnum by default uses any
sufficient target when binding the buffer internally (e.g. for setting data).
To avoid GL errors, set target hint to desired target, either in constructor or
using @ref Buffer::setTargetHint():
@code
Buffer vertices{Buffer::Target::Array};
Buffer indices{Buffer::Target::ElementArray};
@endcode
To ease up the development, @ref Mesh checks proper target hint when adding
vertex and index buffers in both WebGL and NaCl.
## Performance optimizations
The engine tracks currently bound buffers to avoid unnecessary calls to
@fn_gl{BindBuffer}. If the buffer is already bound to some target, functions
@ref copy(), @ref setData(), @ref setSubData(), @ref map(), @ref flushMappedRange()
and @ref unmap() use that target instead of binding the buffer to some specific
target. You can also use @ref setTargetHint() to possibly reduce unnecessary
rebinding. %Buffer limits and implementation-defined values (such as
@ref maxUniformBindings()) are cached, so repeated queries don't result in
repeated @fn_gl{Get} calls.
If extension @extension{EXT,direct_state_access} is available, functions
@ref copy(), @ref setData(), @ref setSubData(), @ref map(), @ref flushMappedRange()
and @ref unmap() use DSA functions to avoid unnecessary calls to
@fn_gl{BindBuffer}. See their respective documentation for more information.
You can use functions @ref invalidateData() and @ref invalidateSubData() if you
don't need buffer data anymore to avoid unnecessary memory operations performed
by OpenGL in order to preserve the data. If running on OpenGL ES or extension
@extension{ARB,invalidate_subdata} (part of OpenGL 4.3) is not available, these
functions do nothing.
*/
class MAGNUM_EXPORT Buffer: public AbstractObject {
friend struct Implementation::BufferState;
public:
/**
* @brief %Buffer target
*
* @see @ref Buffer(), @ref setTargetHint()
*/
enum class TargetHint: GLenum {
/** Used for storing vertex attributes. */
Array = GL_ARRAY_BUFFER,
#ifndef MAGNUM_TARGET_GLES2
/**
* Used for storing atomic counters.
* @requires_gl42 %Extension @extension{ARB,shader_atomic_counters}
* @requires_gles31 Atomic counters are not available in OpenGL ES
* 3.0 and older.
*/
AtomicCounter = GL_ATOMIC_COUNTER_BUFFER,
/**
* Source for copies. See @ref copy().
* @requires_gl31 %Extension @extension{ARB,copy_buffer}
* @requires_gles30 Buffer copying is not available in OpenGL ES
* 2.0.
*/
CopyRead = GL_COPY_READ_BUFFER,
/**
* Target for copies. See @ref copy().
* @requires_gl31 %Extension @extension{ARB,copy_buffer}
* @requires_gles30 Buffer copying is not available in OpenGL ES
* 2.0.
*/
CopyWrite = GL_COPY_WRITE_BUFFER,
/**
* Indirect compute dispatch commands.
* @requires_gl43 %Extension @extension{ARB,compute_shader}
* @requires_gles31 Compute shaders are not available in OpenGL ES
* 3.0 and older.
*/
DispatchIndirect = GL_DISPATCH_INDIRECT_BUFFER,
/**
* Used for supplying arguments for indirect drawing.
* @requires_gl40 %Extension @extension{ARB,draw_indirect}
* @requires_gles31 Indirect drawing not available in OpenGL ES 3.0
* and older.
*/
DrawIndirect = GL_DRAW_INDIRECT_BUFFER,
#endif
/** Used for storing vertex indices. */
ElementArray = GL_ELEMENT_ARRAY_BUFFER,
#ifndef MAGNUM_TARGET_GLES2
/**
* Target for pixel pack operations.
* @requires_gles30 Pixel buffer objects are not available in
* OpenGL ES 2.0.
*/
PixelPack = GL_PIXEL_PACK_BUFFER,
/**
* Source for texture update operations.
* @requires_gles30 Pixel buffer objects are not available in
* OpenGL ES 2.0.
*/
PixelUnpack = GL_PIXEL_UNPACK_BUFFER,
/**
* Used for shader storage.
* @requires_gl43 %Extension @extension{ARB,shader_storage_buffer_object}
* @requires_gles31 Shader storage is not available in OpenGL ES
* 3.0 and older.
*/
ShaderStorage = GL_SHADER_STORAGE_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES
/**
* Source for texel fetches. See @ref BufferTexture.
* @requires_gl31 %Extension @extension{ARB,texture_buffer_object}
* @requires_gl Texture buffers are not available in OpenGL ES.
*/
Texture = GL_TEXTURE_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Target for transform feedback.
* @requires_gl30 %Extension @extension{EXT,transform_feedback}
* @requires_gles30 Transform feedback is not available in OpenGL
* ES 2.0.
*/
TransformFeedback = GL_TRANSFORM_FEEDBACK_BUFFER,
/**
* Used for storing uniforms.
* @requires_gl31 %Extension @extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES
* 2.0.
*/
Uniform = GL_UNIFORM_BUFFER
#endif
};
#if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_BUILD_DEPRECATED)
/**
* @brief %Buffer binding target
*
* @see @ref bind(), @ref unbind()
*/
enum class Target: GLenum {
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copydoc TargetHint::Array
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::Array "TargetHint::Array"
* instead.
*/
Array = GL_ARRAY_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Atomic counter binding
* @requires_gl42 %Extension @extension{ARB,shader_atomic_counters}
* @requires_gles31 Atomic counters are not available in OpenGL ES
* 3.0 and older
*/
AtomicCounter = GL_ATOMIC_COUNTER_BUFFER,
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
#ifndef MAGNUM_TARGET_GLES2
/**
* @copydoc TargetHint::CopyRead
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::CopyRead "TargetHint::CopyRead"
* instead.
*/
CopyRead = GL_COPY_READ_BUFFER,
/**
* @copydoc TargetHint::CopyWrite
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::CopyWrite "TargetHint::CopyWrite"
* instead.
*/
CopyWrite = GL_COPY_WRITE_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @copydoc TargetHint::DispatchIndirect
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::DispatchIndirect "TargetHint::DispatchIndirect"
* instead.
*/
DispatchIndirect = GL_DISPATCH_INDIRECT_BUFFER,
/**
* @copydoc TargetHint::DrawIndirect
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::DrawIndirect "TargetHint::DrawIndirect"
* instead.
*/
DrawIndirect = GL_DRAW_INDIRECT_BUFFER,
#endif
/**
* @copydoc TargetHint::ElementArray
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::ElementArray "TargetHint::ElementArray"
* instead.
*/
ElementArray = GL_ELEMENT_ARRAY_BUFFER,
#ifndef MAGNUM_TARGET_GLES2
/**
* @copydoc TargetHint::PixelPack
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::PixelPack "TargetHint::PixelPack"
* instead.
*/
PixelPack = GL_PIXEL_PACK_BUFFER,
/**
* @copydoc TargetHint::PixelUnpack
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::PixelUnpack "TargetHint::PixelUnpack"
* instead.
*/
PixelUnpack = GL_PIXEL_UNPACK_BUFFER,
#endif
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Shader storage binding
* @requires_gl43 %Extension @extension{ARB,shader_storage_buffer_object}
* @requires_gles31 Shader storage is not available in OpenGL ES
* 3.0 and older
*/
ShaderStorage = GL_SHADER_STORAGE_BUFFER,
#endif
#if defined(MAGNUM_BUILD_DEPRECATED) && !defined(MAGNUM_TARGET_GLES)
/**
* @copydoc TargetHint::Texture
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::Texture "TargetHint::Texture"
* instead.
*/
Texture = GL_TEXTURE_BUFFER,
#endif
#if defined(MAGNUM_BUILD_DEPRECATED) && !defined(MAGNUM_TARGET_GLES2)
/**
* @copydoc TargetHint::TransformFeedback
* @deprecated For @ref Magnum::Buffer::setTargetHint() "setTargetHint()"
* only, use @ref Magnum::Buffer::TargetHint::TransformFeedback "TargetHint::TransformFeedback"
* instead.
*/
TransformFeedback = GL_TRANSFORM_FEEDBACK_BUFFER,
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* Uniform binding
* @requires_gl31 %Extension @extension{ARB,uniform_buffer_object}
* @requires_gles30 Uniform buffers are not available in OpenGL ES
* 2.0
*/
Uniform = GL_UNIFORM_BUFFER
#endif
};
#endif
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief BufferUsage
* @deprecated Use @ref Magnum::BufferUsage "BufferUsage" instead.
*/
typedef CORRADE_DEPRECATED("use BufferUsage instead") BufferUsage Usage;
#endif
/**
* @brief Memory mapping access
*
* @see @ref map(MapAccess), @ref mapSub()
* @requires_es_extension %Extension @es_extension{OES,mapbuffer} or
* @es_extension{CHROMIUM,map_sub}
* @deprecated_gl Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features.
*/
enum class MapAccess: GLenum {
#ifndef MAGNUM_TARGET_GLES
/**
* Map buffer for reading only.
* @requires_gl Only @ref Magnum::Buffer::MapAccess "MapAccess::WriteOnly"
* is available in OpenGL ES.
*/
ReadOnly = GL_READ_ONLY,
#endif
/** Map buffer for writing only. */
#ifdef MAGNUM_TARGET_GLES
WriteOnly = GL_WRITE_ONLY_OES
#else
WriteOnly = GL_WRITE_ONLY,
/**
* Map buffer for both reading and writing.
* @requires_gl Only @ref Magnum::Buffer::MapAccess "MapAccess::WriteOnly"
* is available in OpenGL ES.
*/
ReadWrite = GL_READ_WRITE
#endif
};
/**
* @brief Memory mapping flag
*
* @see @ref MapFlags, @ref map(GLintptr, GLsizeiptr, MapFlags)
* @requires_gl30 %Extension @extension{ARB,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in
* OpenGL ES 2.0
*/
enum class MapFlag: GLbitfield {
/** Map buffer for reading. */
#ifndef MAGNUM_TARGET_GLES2
Read = GL_MAP_READ_BIT,
#else
Read = GL_MAP_READ_BIT_EXT,
#endif
/** Map buffer for writing. */
#ifndef MAGNUM_TARGET_GLES2
Write = GL_MAP_WRITE_BIT,
#else
Write = GL_MAP_WRITE_BIT_EXT,
#endif
/**
* Previous contents of the entire buffer may be discarded. May not
* be used in combination with @ref MapFlag::Read.
* @see @ref invalidateData()
*/
#ifndef MAGNUM_TARGET_GLES2
InvalidateBuffer = GL_MAP_INVALIDATE_BUFFER_BIT,
#else
InvalidateBuffer = GL_MAP_INVALIDATE_BUFFER_BIT_EXT,
#endif
/**
* Previous contents of mapped range may be discarded. May not be
* used in combination with @ref MapFlag::Read.
* @see @ref invalidateSubData()
*/
#ifndef MAGNUM_TARGET_GLES2
InvalidateRange = GL_MAP_INVALIDATE_RANGE_BIT,
#else
InvalidateRange = GL_MAP_INVALIDATE_RANGE_BIT_EXT,
#endif
/**
* Only one or more discrete subranges of the mapping will be
* modified. See @ref flushMappedRange() for more information. May
* only be used in conjuction with @ref MapFlag::Write.
*/
#ifndef MAGNUM_TARGET_GLES2
FlushExplicit = GL_MAP_FLUSH_EXPLICIT_BIT,
#else
FlushExplicit = GL_MAP_FLUSH_EXPLICIT_BIT_EXT,
#endif
/**
* No pending operations on the buffer should be synchronized
* before mapping.
*/
#ifndef MAGNUM_TARGET_GLES2
Unsynchronized = GL_MAP_UNSYNCHRONIZED_BIT
#else
Unsynchronized = GL_MAP_UNSYNCHRONIZED_BIT_EXT
#endif
};
/**
* @brief Memory mapping flags
*
* @see @ref map(GLintptr, GLsizeiptr, MapFlags)
* @requires_gl30 %Extension @extension{ARB,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in
* OpenGL ES 2.0
*/
typedef Containers::EnumSet<MapFlag, GLbitfield> MapFlags;
#ifndef MAGNUM_TARGET_GLES
/**
* @brief Minimal supported mapping alignment
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,map_buffer_alignment}
* (part of OpenGL 4.2) is not available, returns `1`.
* @see @ref map(), @fn_gl{Get} with @def_gl{MIN_MAP_BUFFER_ALIGNMENT}
* @requires_gl No minimal value is specified for OpenGL ES.
*/
static Int minMapAlignment();
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Max supported atomic counter buffer binding count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If neither extension @extension{ARB,shader_atomic_counters}
* (part of OpenGL 4.2) nor OpenGL ES 3.1 is available, returns `0`.
* @see @ref bind(), @ref unbind(), @fn_gl{Get} with
* @def_gl{MAX_ATOMIC_COUNTER_BUFFER_BINDINGS}
* @requires_gles30 Not defined in OpenGL ES 2.0
*/
static Int maxAtomicCounterBindings();
/**
* @brief Max supported shader storage buffer binding count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If neither extension @extension{ARB,shader_storage_buffer_object}
* (part of OpenGL 4.3) nor OpenGL ES 3.1 is available, returns `0`.
* @see @ref bind(), @ref unbind(), @fn_gl{Get} with
* @def_gl{MAX_SHADER_STORAGE_BUFFER_BINDINGS}
* @requires_gles30 Not defined in OpenGL ES 2.0
*/
static Int maxShaderStorageBindings();
/**
* @brief Alignment of uniform buffer binding offset
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_object}
* (part of OpenGL 3.1) is not available, returns `1`.
* @see @ref bind(), @fn_gl{Get} with @def_gl{UNIFORM_BUFFER_OFFSET_ALIGNMENT}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0
*/
static Int uniformOffsetAlignment();
/**
* @brief Alignment of shader storage buffer binding offset
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If neither extension @extension{ARB,shader_storage_buffer_object}
* (part of OpenGL 4.3) nor OpenGL ES 3.1 is available, returns `1`.
* @see @ref bind(), @fn_gl{Get} with @def_gl{SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT}
* @requires_gles30 Not defined in OpenGL ES 2.0
*/
static Int shaderStorageOffsetAlignment();
/**
* @brief Max supported uniform buffer binding count
*
* The result is cached, repeated queries don't result in repeated
* OpenGL calls. If extension @extension{ARB,uniform_buffer_object}
* (part of OpenGL 3.1) is not available, returns `0`.
* @see @ref bind(), @ref unbind(), @fn_gl{Get} with
* @def_gl{MAX_UNIFORM_BUFFER_BINDINGS}
* @requires_gles30 Uniform buffers are not available in OpenGL ES 2.0
*/
static Int maxUniformBindings();
/**
* @brief Unbind any buffer from given indexed target
*
* The @p index parameter must respect limits for given @p target.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(), @ref maxAtomicCounterBindings(),
* @ref maxShaderStorageBindings(), @ref maxUniformBindings(),
* @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
static void unbind(Target target, UnsignedInt index);
/**
* @brief Unbind given range of indexed targets
*
* Unbinds all buffers in given target in range @f$ [ firstIndex ; firstIndex + count ] @f$.
* The range of indices must respect limits for given @p target. If
* @extension{ARB,multi_bind} (part of OpenGL 4.4) is not available,
* the feature is emulated with sequence of @ref unbind(Target, UnsignedInt)
* calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref unbind(Target, UnsignedInt), @ref maxAtomicCounterBindings(),
* @ref maxShaderStorageBindings(), @ref maxUniformBindings(),
* @fn_gl{BindBuffersBase} or @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
static void unbind(Target target, UnsignedInt firstIndex, std::size_t count);
/**
* @brief Bind ranges of buffers to given range of indexed targets
*
* Binds first buffer in the list to @p firstIndex, second to
* `firstIndex + 1` etc. Second parameter is offset, third is size. If
* any buffer is `nullptr`, given indexed target is unbound. The range
* of indices must respect limits for given @p target. The offsets must
* respect alignment, which is 4 bytes for @ref Target::AtomicCounter
* and implementation-defined for other targets. If @extension{ARB,multi_bind}
* (part of OpenGL 4.4) is not available, the feature is emulated with
* sequence of @ref bind(Target, UnsignedInt, GLintptr, GLsizeiptr) /
* @ref unbind(Target, UnsignedInt) calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt, GLintptr, GLsizeiptr),
* @ref maxAtomicCounterBindings(), @ref maxShaderStorageBindings(),
* @ref maxUniformBindings(), @ref shaderStorageOffsetAlignment(),
* @ref uniformOffsetAlignment(), @fn_gl{BindBuffersRange} or
* @fn_gl{BindBufferRange}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
static void bind(Target target, UnsignedInt firstIndex, std::initializer_list<std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers);
/**
* @brief Bind buffers to given range of indexed targets
*
* Binds first buffer in the list to @p firstIndex, second to
* `firstIndex + 1` etc. If any buffer is `nullptr`, given indexed
* target is unbound. The range of indices must respect limits for
* given @p target. If @extension{ARB,multi_bind} (part of OpenGL 4.4)
* is not available, the feature is emulated with sequence of
* @ref bind(Target, UnsignedInt) / @ref unbind(Target, UnsignedInt)
* calls.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt), @ref maxAtomicCounterBindings(),
* @ref maxShaderStorageBindings(), @ref maxUniformBindings(),
* @fn_gl{BindBuffersBase} or @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
static void bind(Target target, UnsignedInt firstIndex, std::initializer_list<Buffer*> buffers);
/**
* @brief Copy one buffer to another
* @param read %Buffer from which to read
* @param write %Buffer to which to copy
* @param readOffset Offset in the read buffer
* @param writeOffset Offset in the write buffer
* @param size Data size
*
* If @extension{EXT,direct_state_access} is not available and the
* buffers aren't already bound somewhere, they are bound to
* @ref Target::CopyRead and @ref Target::CopyWrite before the copy is
* performed.
* @see @fn_gl{BindBuffer} and @fn_gl{CopyBufferSubData} or
* @fn_gl_extension{NamedCopyBufferSubData,EXT,direct_state_access}
* @requires_gl31 %Extension @extension{ARB,copy_buffer}
* @requires_gles30 %Buffer copying is not available in OpenGL ES 2.0.
*/
static void copy(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
#endif
/**
* @brief Constructor
* @param targetHint Target hint, see @ref setTargetHint() for more
* information
*
* Creates new OpenGL buffer object. If @extension{ARB,direct_state_access}
* (part of OpenGL 4.5) is not supported, the buffer is created on
* first use.
* @see @fn_gl{CreateBuffers}, eventually @fn_gl{GenBuffers}
*/
explicit Buffer(TargetHint targetHint = TargetHint::Array);
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief Buffer(TargetHint)
* @deprecated Use @ref Magnum::Buffer::Buffer(Magnum::Buffer::TargetHint) "Buffer(TargetHint)"
* instead.
*/
CORRADE_DEPRECATED("use Buffer(TargetHint) instead") explicit Buffer(Target targetHint): Buffer{static_cast<TargetHint>(targetHint)} {}
#endif
/** @brief Copying is not allowed */
Buffer(const Buffer&) = delete;
/** @brief Move constructor */
Buffer(Buffer&& other) noexcept;
/**
* @brief Destructor
*
* Deletes associated OpenGL buffer object.
* @see @fn_gl{DeleteBuffers}
*/
~Buffer();
/** @brief Copying is not allowed */
Buffer& operator=(const Buffer&) = delete;
/** @brief Move assignment */
Buffer& operator=(Buffer&& other) noexcept;
/** @brief OpenGL buffer ID */
GLuint id() const { return _id; }
/**
* @brief %Buffer label
*
* The result is *not* cached, repeated queries will result in repeated
* OpenGL calls. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function returns empty string.
* @see @fn_gl{GetObjectLabel} with @def_gl{BUFFER} or
* @fn_gl_extension2{GetObjectLabel,EXT,debug_label} with
* @def_gl{BUFFER_OBJECT_EXT}
*/
std::string label();
/**
* @brief Set buffer label
* @return Reference to self (for method chaining)
*
* Default is empty string. If OpenGL 4.3 is not supported and neither
* @extension{KHR,debug} nor @extension2{EXT,debug_label} desktop or ES
* extension is available, this function does nothing.
* @see @ref maxLabelLength(), @fn_gl{ObjectLabel} with @def_gl{BUFFER}
* or @fn_gl_extension2{LabelObject,EXT,debug_label} with
* @def_gl{BUFFER_OBJECT_EXT}
*/
Buffer& setLabel(const std::string& label) {
return setLabelInternal({label.data(), label.size()});
}
/** @overload */
template<std::size_t size> Buffer& setLabel(const char(&label)[size]) {
return setLabelInternal(label);
}
/** @brief Target hint */
TargetHint targetHint() const { return _targetHint; }
/**
* @brief Set target hint
* @return Reference to self (for method chaining)
*
* If @extension{EXT,direct_state_access} is not available, the buffer
* must be internally bound to some target before any operation. You
* can specify target which will always be used when binding the buffer
* internally, possibly saving some calls to @fn_gl{BindBuffer}.
*
* Default target hint is @ref Target::Array.
* @see @ref setData(), @ref setSubData()
* @todo Target::ElementArray cannot be used when no VAO is bound -
* http://www.opengl.org/wiki/Vertex_Specification#Index_buffers
* ... damned GL state
*/
Buffer& setTargetHint(TargetHint hint) {
_targetHint = hint;
return *this;
}
#ifdef MAGNUM_BUILD_DEPRECATED
/**
* @copybrief setTargetHint(TargetHint)
* @deprecated Use @ref Magnum::Buffer::setTargetHint(Magnum::Buffer::TargetHint) "setTargetHint(TargetHint)"
* instead.
*/
CORRADE_DEPRECATED("use setTargetHint(TargetHint) instead") Buffer& setTargetHint(Target hint) {
return setTargetHint(static_cast<TargetHint>(hint));
}
#endif
#ifndef MAGNUM_TARGET_GLES2
/**
* @brief Bind buffer range to given binding index
*
* The @p index parameter must respect limits for given @p target. The
* @p offset parameter must respect alignment, which is 4 bytes for
* @ref Target::AtomicCounter and implementation-defined for other
* targets.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt, std::initializer_list<std::tuple<Buffer*, GLintptr, GLsizeiptr>>),
* @ref maxAtomicCounterBindings(), @ref maxShaderStorageBindings(),
* @ref maxUniformBindings(), @ref shaderStorageOffsetAlignment(),
* @ref uniformOffsetAlignment(), @fn_gl{BindBufferRange}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @todo State tracking for indexed binding
*/
Buffer& bind(Target target, UnsignedInt index, GLintptr offset, GLsizeiptr size);
/**
* @brief Bind buffer to given binding index
*
* The @p index parameter must respect limits for given @p target.
* @note This function is meant to be used only internally from
* @ref AbstractShaderProgram subclasses. See its documentation
* for more information.
* @see @ref bind(Target, UnsignedInt, std::initializer_list<Buffer*>),
* @ref maxAtomicCounterBindings(), @ref maxShaderStorageBindings(),
* @ref maxUniformBindings(), @fn_gl{BindBufferBase}
* @requires_gl30 No form of indexed buffer binding is available in
* OpenGL 2.1, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
* @requires_gles30 No form of indexed buffer binding is available in
* OpenGL ES 2.0, see particular @ref Magnum::Buffer::Target "Target"
* values for version requirements.
*/
Buffer& bind(Target target, UnsignedInt index);
#endif
/**
* @brief %Buffer size
*
* If @extension{EXT,direct_state_access} is not available and the
* buffer is not already bound somewhere, it is bound to hinted target
* before the operation.
* @see @fn_gl{BindBuffer} and @fn_gl{GetBufferParameter} or
* @fn_gl_extension{GetNamedBufferParameter,EXT,direct_state_access}
* with @def_gl{BUFFER_SIZE}
*/
Int size();
#ifndef MAGNUM_TARGET_GLES
/**
* @brief %Buffer data
*
* Returns data of whole buffer. If @extension{EXT,direct_state_access}
* is not available and the buffer is not already bound somewhere, it
* is bound to hinted target before the operation.
* @see @ref size(), @ref subData(), @ref setData(), @fn_gl{BindBuffer}
* and @fn_gl{GetBufferParameter} or
* @fn_gl_extension{GetNamedBufferParameter,EXT,direct_state_access}
* with @def_gl{BUFFER_SIZE}, @fn_gl{GetBufferSubData} or
* @fn_gl_extension{GetNamedBufferSubData,EXT,direct_state_access}
* @requires_gl %Buffer data queries are not available in OpenGL ES.
* Use @ref Magnum::Buffer::map() "map()" instead.
*/
template<class T = unsigned char> Containers::Array<T> data();
/**
* @brief %Buffer subdata
* @param offset Byte offset in the buffer
* @param size Data size (count of @p T values)
*
* Returns data of given buffer portion. If @extension{EXT,direct_state_access}
* is not available and the buffer is not already bound somewhere, it
* is bound to hinted target before the operation.
* @see @ref size(), @ref data(), @ref setSubData(), @fn_gl{BindBuffer}
* and @fn_gl{GetBufferSubData} or
* @fn_gl_extension{GetNamedBufferSubData,EXT,direct_state_access}
* @requires_gl %Buffer data queries are not available in OpenGL ES.
* Use @ref Magnum::Buffer::map() "map()" instead.
*/
template<class T = unsigned char> Containers::Array<T> subData(GLintptr offset, GLsizeiptr size);
#endif
/**
* @brief Set buffer data
* @param data Data
* @param usage %Buffer usage
* @return Reference to self (for method chaining)
*
* If @extension{EXT,direct_state_access} is not available and the
* buffer is not already bound somewhere, it is bound to hinted target
* before the operation.
* @see @ref setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferData}
* or @fn_gl_extension{NamedBufferData,EXT,direct_state_access}
*/
Buffer& setData(Containers::ArrayReference<const void> data, BufferUsage usage);
/** @overload */
template<class T> Buffer& setData(const std::vector<T>& data, BufferUsage usage) {
setData({data.data(), data.size()}, usage);
return *this;
}
/** @overload */
template<std::size_t size, class T> Buffer& setData(const std::array<T, size>& data, BufferUsage usage) {
setData({data.data(), data.size()}, usage);
return *this;
}
/**
* @brief Set buffer subdata
* @param offset Offset in the buffer
* @param data Data
* @return Reference to self (for method chaining)
*
* If @extension{EXT,direct_state_access} is not available and the
* buffer is not already bound somewhere, it is bound to hinted target
* before the operation.
* @see @ref setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{BufferSubData}
* or @fn_gl_extension{NamedBufferSubData,EXT,direct_state_access}
*/
Buffer& setSubData(GLintptr offset, Containers::ArrayReference<const void> data);
/** @overload */
template<class T> Buffer& setSubData(GLintptr offset, const std::vector<T>& data) {
setSubData(offset, {data.data(), data.size()});
return *this;
}
/** @overload */
template<std::size_t size, class T> Buffer& setSubData(GLintptr offset, const std::array<T, size>& data) {
setSubData(offset, {data.data(), data.size()});
return *this;
}
/**
* @brief Invalidate buffer data
* @return Reference to self (for method chaining)
*
* If running on OpenGL ES or extension @extension{ARB,invalidate_subdata}
* (part of OpenGL 4.3) is not available, this function does nothing.
* @see @ref MapFlag::InvalidateBuffer, @fn_gl{InvalidateBufferData}
*/
Buffer& invalidateData();
/**
* @brief Invalidate buffer subdata
* @param offset Offset into the buffer
* @param length Length of the invalidated range
* @return Reference to self (for method chaining)
*
* If running on OpenGL ES or extension @extension{ARB,invalidate_subdata}
* (part of OpenGL 4.3) is not available, this function does nothing.
* @see @ref MapFlag::InvalidateRange, @fn_gl{InvalidateBufferData}
*/
Buffer& invalidateSubData(GLintptr offset, GLsizeiptr length);
/**
* @brief Map buffer to client memory
* @param access Access
* @return Pointer to buffer data
*
* If @extension{EXT,direct_state_access} is not available and the
* buffer is not already bound somewhere, it is bound to hinted target
* before the operation.
* @see @ref minMapAlignment(), @ref unmap(), @ref setTargetHint(),
* @fn_gl{BindBuffer} and @fn_gl{MapBuffer} or
* @fn_gl_extension{MapNamedBuffer,EXT,direct_state_access}
* @requires_es_extension %Extension @es_extension{OES,mapbuffer} in
* OpenGL ES 2.0, use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* in OpenGL ES 3.0 instead.
* @deprecated_gl Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features.
*/
void* map(MapAccess access);
#if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* @brief Map portion of buffer to client memory
* @param offset Offset into the buffer
* @param length Length of the mapped memory
* @param access Access
* @return Pointer to buffer data
*
* If the buffer is not already bound somewhere, it is bound to hinted
* target before the operation.
* @see @ref unmapSub(), @ref setTargetHint(),
* @fn_gl_extension{MapBufferSubData,CHROMIUM,map_sub}
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead.
* @requires_es_extension %Extension @es_extension{CHROMIUM,map_sub}
* @deprecated_gl Prefer to use @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead, as it has more complete set of features.
*/
void* mapSub(GLintptr offset, GLsizeiptr length, MapAccess access);
#endif
/**
* @brief Map buffer to client memory
* @param offset Offset into the buffer
* @param length Length of the mapped memory
* @param flags Flags. At least @ref MapFlag::Read or
* @ref MapFlag::Write must be specified.
* @return Pointer to buffer data
*
* If @extension{EXT,direct_state_access} is not available and the
* buffer is not already bound somewhere, it is bound to hinted target
* before the operation.
* @see @ref minMapAlignment(), @ref flushMappedRange(), @ref unmap(),
* @ref map(MapAccess), @ref setTargetHint(), @fn_gl{BindBuffer}
* and @fn_gl{MapBufferRange} or @fn_gl_extension{MapNamedBufferRange,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{ARB,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in
* OpenGL ES 2.0
*/
void* map(GLintptr offset, GLsizeiptr length, MapFlags flags);
/**
* @brief Flush mapped range
* @param offset Offset relative to start of mapped range
* @param length Length of the flushed memory
* @return Reference to self (for method chaining)
*
* Flushes specified subsection of mapped range. Use only if you called
* @ref map() with @ref MapFlag::FlushExplicit flag. See
* @ref Buffer-data-mapping "class documentation" for usage example.
*
* If @extension{EXT,direct_state_access} is not available and the
* buffer is not already bound somewhere, it is bound to hinted target
* before the operation.
* @see @ref setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{FlushMappedBufferRange}
* or @fn_gl_extension{FlushMappedNamedBufferRange,EXT,direct_state_access}
* @requires_gl30 %Extension @extension{ARB,map_buffer_range}
* @requires_gles30 %Extension @es_extension{EXT,map_buffer_range} in
* OpenGL ES 2.0
*/
Buffer& flushMappedRange(GLintptr offset, GLsizeiptr length);
/**
* @brief Unmap buffer
* @return `False` if the data have become corrupt during the time
* the buffer was mapped (e.g. after screen was resized), `true`
* otherwise.
*
* Unmaps buffer previously mapped with @ref map(), invalidating the
* pointer returned by these functions. If @extension{EXT,direct_state_access}
* is not available and the buffer is not already bound somewhere, it
* is bound to hinted target before the operation.
* @see setTargetHint(), @fn_gl{BindBuffer} and @fn_gl{UnmapBuffer} or
* @fn_gl_extension{UnmapNamedBuffer,EXT,direct_state_access}
* @requires_gles30 %Extension @es_extension{OES,mapbuffer} in OpenGL
* ES 2.0
*/
bool unmap();
#if defined(MAGNUM_TARGET_GLES2) || defined(DOXYGEN_GENERATING_OUTPUT)
/**
* @brief Unmap portion of buffer
*
* Unmaps portion of buffer previously mapped with @ref mapSub(),
* invalidating the pointer returned by the function.
* @see @fn_gl_extension{UnmapBufferSubData,CHROMIUM,map_sub}
* @requires_gles20 Not available in ES 3.0 or desktop OpenGL. Use
* @ref Magnum::Buffer::map(GLintptr, GLsizeiptr, MapFlags) "map(GLintptr, GLsizeiptr, MapFlags)"
* instead.
* @requires_es_extension %Extension @es_extension{CHROMIUM,map_sub}
*/
void unmapSub();
#endif
#ifdef DOXYGEN_GENERATING_OUTPUT
private:
#endif
/* There should be no need to use these from user code. Also it's a bit
unfortunate to have the parameter typed as TargetHint while in this
case it is no hint at all, but it allows to have cleaner public
binding API (just with short Target name) */
static void unbindInternal(TargetHint target) { bindInternal(target, nullptr); }
void bindInternal(TargetHint target) { bindInternal(target, this); }
private:
static void bindInternal(TargetHint hint, Buffer* buffer);
TargetHint MAGNUM_LOCAL bindSomewhereInternal(TargetHint hint);
#ifndef MAGNUM_TARGET_GLES2
static void MAGNUM_LOCAL bindImplementationFallback(Target target, GLuint first, Containers::ArrayReference<Buffer* const> buffers);
#ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL bindImplementationMulti(Target target, GLuint first, Containers::ArrayReference<Buffer* const> buffers);
#endif
static void MAGNUM_LOCAL bindImplementationFallback(Target target, GLuint first, Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers);
#ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL bindImplementationMulti(Target target, GLuint first, Containers::ArrayReference<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers);
#endif
static void MAGNUM_LOCAL copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
#ifndef MAGNUM_TARGET_GLES
static void MAGNUM_LOCAL copyImplementationDSAEXT(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size);
#endif
#endif
void MAGNUM_LOCAL createImplementationDefault();
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL createImplementationDSA();
#endif
void MAGNUM_LOCAL createIfNotAlready();
Buffer& setLabelInternal(Containers::ArrayReference<const char> label);
#ifndef MAGNUM_TARGET_GLES
void subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data);
#endif
void MAGNUM_LOCAL getParameterImplementationDefault(GLenum value, GLint* data);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL getParameterImplementationDSAEXT(GLenum value, GLint* data);
#endif
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL getSubDataImplementationDefault(GLintptr offset, GLsizeiptr size, GLvoid* data);
void MAGNUM_LOCAL getSubDataImplementationDSAEXT(GLintptr offset, GLsizeiptr size, GLvoid* data);
#endif
void MAGNUM_LOCAL dataImplementationDefault(GLsizeiptr size, const GLvoid* data, BufferUsage usage);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL dataImplementationDSAEXT(GLsizeiptr size, const GLvoid* data, BufferUsage usage);
#endif
void MAGNUM_LOCAL subDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL subDataImplementationDSAEXT(GLintptr offset, GLsizeiptr size, const GLvoid* data);
#endif
void MAGNUM_LOCAL invalidateImplementationNoOp();
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL invalidateImplementationARB();
#endif
void MAGNUM_LOCAL invalidateSubImplementationNoOp(GLintptr offset, GLsizeiptr length);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL invalidateSubImplementationARB(GLintptr offset, GLsizeiptr length);
#endif
void MAGNUM_LOCAL * mapImplementationDefault(MapAccess access);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL * mapImplementationDSAEXT(MapAccess access);
#endif
void MAGNUM_LOCAL * mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length, MapFlags access);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL * mapRangeImplementationDSAEXT(GLintptr offset, GLsizeiptr length, MapFlags access);
#endif
void MAGNUM_LOCAL flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr length);
#ifndef MAGNUM_TARGET_GLES
void MAGNUM_LOCAL flushMappedRangeImplementationDSAEXT(GLintptr offset, GLsizeiptr length);
#endif
bool MAGNUM_LOCAL unmapImplementationDefault();
#ifndef MAGNUM_TARGET_GLES
bool MAGNUM_LOCAL unmapImplementationDSAEXT();
#endif
GLuint _id;
TargetHint _targetHint;
#ifdef CORRADE_TARGET_NACL
void* _mappedBuffer;
#endif
bool _created; /* see createIfNotAlready() for details */
};
CORRADE_ENUMSET_OPERATORS(Buffer::MapFlags)
/** @debugoperatorclassenum{Magnum::Buffer,Magnum::Buffer::TargetHint} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Buffer::TargetHint value);
#if !defined(MAGNUM_TARGET_GLES2) || defined(MAGNUM_BUILD_DEPRECATED)
/** @debugoperatorclassenum{Magnum::Buffer,Magnum::Buffer::Target} */
Debug MAGNUM_EXPORT operator<<(Debug debug, Buffer::Target value);
#endif
inline Buffer::Buffer(Buffer&& other) noexcept: _id{other._id}, _targetHint{other._targetHint},
#ifdef CORRADE_TARGET_NACL
_mappedBuffer{other._mappedBuffer},
#endif
_created{other._created}
{
other._id = 0;
#ifdef CORRADE_TARGET_NACL
other._mappedBuffer = nullptr;
#endif
}
inline Buffer& Buffer::operator=(Buffer&& other) noexcept {
std::swap(_id, other._id);
std::swap(_targetHint, other._targetHint);
#ifdef CORRADE_TARGET_NACL
std::swap(_mappedBuffer, other._mappedBuffer);
#endif
std::swap(_created, other._created);
return *this;
}
#ifndef MAGNUM_TARGET_GLES
template<class T> Containers::Array<T> inline Buffer::data() {
const Int bufferSize = size();
#ifndef CORRADE_GCC45_COMPATIBILITY
CORRADE_ASSERT(bufferSize%sizeof(T) == 0, "Buffer::data(): the buffer size is" << bufferSize << "bytes, which can't be expressed as array of types with size" << sizeof(T), nullptr);
#else
CORRADE_ASSERT(bufferSize%sizeof(T) == 0, "Buffer::data(): the buffer size is" << bufferSize << "bytes, which can't be expressed as array of types with size" << sizeof(T), {});
#endif
return subData<T>(0, bufferSize/sizeof(T));
}
template<class T> Containers::Array<T> inline Buffer::subData(const GLintptr offset, const GLsizeiptr size) {
Containers::Array<T> data(size);
if(size) subDataInternal(offset, size*sizeof(T), data);
return std::move(data);
}
#endif
}
#endif