mirror of https://github.com/mosra/magnum.git
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.
635 lines
22 KiB
635 lines
22 KiB
|
14 years ago
|
/*
|
||
|
|
This file is part of Magnum.
|
||
|
|
|
||
|
8 years ago
|
Copyright © 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018
|
||
|
12 years ago
|
Vladimír Vondruš <mosra@centrum.cz>
|
||
|
13 years ago
|
|
||
|
|
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.
|
||
|
14 years ago
|
*/
|
||
|
|
|
||
|
|
#include "Buffer.h"
|
||
|
|
|
||
|
11 years ago
|
#include <Corrade/Containers/Array.h>
|
||
|
13 years ago
|
#include <Corrade/Utility/Debug.h>
|
||
|
14 years ago
|
|
||
|
8 years ago
|
#include "Magnum/GL/Context.h"
|
||
|
|
#include "Magnum/GL/Extensions.h"
|
||
|
|
#include "Magnum/GL/Implementation/State.h"
|
||
|
|
#include "Magnum/GL/Implementation/BufferState.h"
|
||
|
11 years ago
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
8 years ago
|
#include "Magnum/GL/Implementation/DebugState.h"
|
||
|
11 years ago
|
#endif
|
||
|
8 years ago
|
#include "Magnum/GL/Implementation/MeshState.h"
|
||
|
14 years ago
|
|
||
|
14 years ago
|
namespace Magnum {
|
||
|
|
|
||
|
13 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
Int Buffer::minMapAlignment() {
|
||
|
10 years ago
|
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::map_buffer_alignment>())
|
||
|
12 years ago
|
return 1;
|
||
|
12 years ago
|
|
||
|
10 years ago
|
GLint& value = Context::current().state().buffer->minMapAlignment;
|
||
|
13 years ago
|
|
||
|
|
if(value == 0)
|
||
|
|
glGetIntegerv(GL_MIN_MAP_BUFFER_ALIGNMENT, &value);
|
||
|
|
|
||
|
|
return value;
|
||
|
|
}
|
||
|
12 years ago
|
#endif
|
||
|
13 years ago
|
|
||
|
12 years ago
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
11 years ago
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
13 years ago
|
Int Buffer::maxAtomicCounterBindings() {
|
||
|
12 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
10 years ago
|
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_atomic_counters>())
|
||
|
12 years ago
|
#else
|
||
|
10 years ago
|
if(!Context::current().isVersionSupported(Version::GLES310))
|
||
|
12 years ago
|
#endif
|
||
|
13 years ago
|
return 0;
|
||
|
|
|
||
|
10 years ago
|
GLint& value = Context::current().state().buffer->maxAtomicCounterBindings;
|
||
|
13 years ago
|
|
||
|
|
if(value == 0)
|
||
|
|
glGetIntegerv(GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS, &value);
|
||
|
|
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
Int Buffer::maxShaderStorageBindings() {
|
||
|
12 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
10 years ago
|
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_storage_buffer_object>())
|
||
|
12 years ago
|
#else
|
||
|
10 years ago
|
if(!Context::current().isVersionSupported(Version::GLES310))
|
||
|
12 years ago
|
#endif
|
||
|
13 years ago
|
return 0;
|
||
|
|
|
||
|
10 years ago
|
GLint& value = Context::current().state().buffer->maxShaderStorageBindings;
|
||
|
13 years ago
|
|
||
|
|
if(value == 0)
|
||
|
|
glGetIntegerv(GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS, &value);
|
||
|
|
|
||
|
|
return value;
|
||
|
|
}
|
||
|
11 years ago
|
#endif
|
||
|
13 years ago
|
|
||
|
11 years ago
|
Int Buffer::uniformOffsetAlignment() {
|
||
|
12 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
10 years ago
|
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>())
|
||
|
12 years ago
|
return 1;
|
||
|
11 years ago
|
#endif
|
||
|
13 years ago
|
|
||
|
10 years ago
|
GLint& value = Context::current().state().buffer->uniformOffsetAlignment;
|
||
|
13 years ago
|
|
||
|
|
if(value == 0)
|
||
|
11 years ago
|
glGetIntegerv(GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT, &value);
|
||
|
13 years ago
|
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
11 years ago
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
|
Int Buffer::shaderStorageOffsetAlignment() {
|
||
|
12 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
10 years ago
|
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::shader_storage_buffer_object>())
|
||
|
11 years ago
|
#else
|
||
|
10 years ago
|
if(!Context::current().isVersionSupported(Version::GLES310))
|
||
|
12 years ago
|
#endif
|
||
|
11 years ago
|
return 1;
|
||
|
12 years ago
|
|
||
|
10 years ago
|
GLint& value = Context::current().state().buffer->shaderStorageOffsetAlignment;
|
||
|
12 years ago
|
|
||
|
|
if(value == 0)
|
||
|
11 years ago
|
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT, &value);
|
||
|
12 years ago
|
|
||
|
|
return value;
|
||
|
|
}
|
||
|
11 years ago
|
#endif
|
||
|
12 years ago
|
|
||
|
13 years ago
|
Int Buffer::maxUniformBindings() {
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
10 years ago
|
if(!Context::current().isExtensionSupported<Extensions::GL::ARB::uniform_buffer_object>())
|
||
|
13 years ago
|
return 0;
|
||
|
|
#endif
|
||
|
|
|
||
|
10 years ago
|
GLint& value = Context::current().state().buffer->maxUniformBindings;
|
||
|
13 years ago
|
|
||
|
|
if(value == 0)
|
||
|
|
glGetIntegerv(GL_MAX_UNIFORM_BUFFER_BINDINGS, &value);
|
||
|
|
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
void Buffer::unbind(const Target target, const UnsignedInt index) {
|
||
|
|
glBindBufferBase(GLenum(target), index, 0);
|
||
|
|
}
|
||
|
|
|
||
|
|
void Buffer::unbind(const Target target, const UnsignedInt firstIndex, const std::size_t count) {
|
||
|
10 years ago
|
Context::current().state().buffer->bindBasesImplementation(target, firstIndex, {nullptr, count});
|
||
|
12 years ago
|
}
|
||
|
|
|
||
|
|
/** @todoc const std::initializer_list makes Doxygen grumpy */
|
||
|
|
void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list<std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers) {
|
||
|
10 years ago
|
Context::current().state().buffer->bindRangesImplementation(target, firstIndex, {buffers.begin(), buffers.size()});
|
||
|
12 years ago
|
}
|
||
|
|
|
||
|
|
/** @todoc const std::initializer_list makes Doxygen grumpy */
|
||
|
|
void Buffer::bind(const Target target, const UnsignedInt firstIndex, std::initializer_list<Buffer*> buffers) {
|
||
|
10 years ago
|
Context::current().state().buffer->bindBasesImplementation(target, firstIndex, {buffers.begin(), buffers.size()});
|
||
|
12 years ago
|
}
|
||
|
|
|
||
|
12 years ago
|
void Buffer::copy(Buffer& read, Buffer& write, const GLintptr readOffset, const GLintptr writeOffset, const GLsizeiptr size) {
|
||
|
10 years ago
|
Context::current().state().buffer->copyImplementation(read, write, readOffset, writeOffset, size);
|
||
|
12 years ago
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
9 years ago
|
Buffer::Buffer(const TargetHint targetHint): _targetHint{targetHint}, _flags{ObjectFlag::DeleteOnDestruction} {
|
||
|
10 years ago
|
(this->*Context::current().state().buffer->createImplementation)();
|
||
|
12 years ago
|
CORRADE_INTERNAL_ASSERT(_id != Implementation::State::DisengagedBinding);
|
||
|
13 years ago
|
}
|
||
|
|
|
||
|
12 years ago
|
void Buffer::createImplementationDefault() {
|
||
|
|
glGenBuffers(1, &_id);
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
void Buffer::createImplementationDSA() {
|
||
|
|
glCreateBuffers(1, &_id);
|
||
|
11 years ago
|
_flags |= ObjectFlag::Created;
|
||
|
12 years ago
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
14 years ago
|
Buffer::~Buffer() {
|
||
|
11 years ago
|
/* Moved out or not deleting on destruction, nothing to do */
|
||
|
|
if(!_id || !(_flags & ObjectFlag::DeleteOnDestruction)) return;
|
||
|
13 years ago
|
|
||
|
10 years ago
|
GLuint* bindings = Context::current().state().buffer->bindings;
|
||
|
14 years ago
|
|
||
|
|
/* Remove all current bindings from the state */
|
||
|
|
for(std::size_t i = 1; i != Implementation::BufferState::TargetCount; ++i)
|
||
|
|
if(bindings[i] == _id) bindings[i] = 0;
|
||
|
|
|
||
|
|
glDeleteBuffers(1, &_id);
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
inline void Buffer::createIfNotAlready() {
|
||
|
11 years ago
|
if(_flags & ObjectFlag::Created) return;
|
||
|
12 years ago
|
|
||
|
|
/* glGen*() does not create the object, just reserves the name. Some
|
||
|
|
commands (such as glInvalidateBufferData() or glObjectLabel()) operate
|
||
|
|
with IDs directly and they require the object to be created. Binding the
|
||
|
|
buffer finally creates it. Also all EXT DSA functions implicitly create
|
||
|
|
it. */
|
||
|
|
bindSomewhereInternal(_targetHint);
|
||
|
11 years ago
|
CORRADE_INTERNAL_ASSERT(_flags & ObjectFlag::Created);
|
||
|
12 years ago
|
}
|
||
|
|
|
||
|
11 years ago
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
12 years ago
|
std::string Buffer::label() {
|
||
|
|
createIfNotAlready();
|
||
|
8 years ago
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
10 years ago
|
return Context::current().state().debug->getLabelImplementation(GL_BUFFER, _id);
|
||
|
13 years ago
|
#else
|
||
|
10 years ago
|
return Context::current().state().debug->getLabelImplementation(GL_BUFFER_KHR, _id);
|
||
|
13 years ago
|
#endif
|
||
|
|
}
|
||
|
|
|
||
|
11 years ago
|
Buffer& Buffer::setLabelInternal(const Containers::ArrayView<const char> label) {
|
||
|
12 years ago
|
createIfNotAlready();
|
||
|
8 years ago
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
10 years ago
|
Context::current().state().debug->labelImplementation(GL_BUFFER, _id, label);
|
||
|
13 years ago
|
#else
|
||
|
10 years ago
|
Context::current().state().debug->labelImplementation(GL_BUFFER_KHR, _id, label);
|
||
|
13 years ago
|
#endif
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
11 years ago
|
#endif
|
||
|
13 years ago
|
|
||
|
12 years ago
|
void Buffer::bindInternal(const TargetHint target, Buffer* const buffer) {
|
||
|
12 years ago
|
const GLuint id = buffer ? buffer->_id : 0;
|
||
|
10 years ago
|
GLuint& bound = Context::current().state().buffer->bindings[Implementation::BufferState::indexForTarget(target)];
|
||
|
14 years ago
|
|
||
|
|
/* Already bound, nothing to do */
|
||
|
|
if(bound == id) return;
|
||
|
|
|
||
|
12 years ago
|
/* Bind the buffer otherwise, which will also finally create it */
|
||
|
14 years ago
|
bound = id;
|
||
|
11 years ago
|
if(buffer) buffer->_flags |= ObjectFlag::Created;
|
||
|
13 years ago
|
glBindBuffer(GLenum(target), id);
|
||
|
14 years ago
|
}
|
||
|
|
|
||
|
12 years ago
|
auto Buffer::bindSomewhereInternal(const TargetHint hint) -> TargetHint {
|
||
|
10 years ago
|
GLuint* bindings = Context::current().state().buffer->bindings;
|
||
|
14 years ago
|
GLuint& hintBinding = bindings[Implementation::BufferState::indexForTarget(hint)];
|
||
|
|
|
||
|
|
/* Shortcut - if already bound to hint, return */
|
||
|
|
if(hintBinding == _id) return hint;
|
||
|
|
|
||
|
|
/* Return first target in which the buffer is bound */
|
||
|
13 years ago
|
/** @todo wtf there is one more? */
|
||
|
14 years ago
|
for(std::size_t i = 1; i != Implementation::BufferState::TargetCount; ++i)
|
||
|
13 years ago
|
if(bindings[i] == _id) return Implementation::BufferState::targetForIndex[i-1];
|
||
|
14 years ago
|
|
||
|
9 years ago
|
/* Sorry, this is ugly because GL is also ugly. Blame GL, not me.
|
||
|
|
|
||
|
|
If the buffer target hint is ElementArray and some VAO is bound (or our
|
||
|
|
state tracker is not sure), we have to unbound the VAO first in order to
|
||
|
|
prevent accidental modification of that VAO. See
|
||
|
|
Test::MeshGLTest::unbindVAOwhenSettingIndexBufferData() for details. */
|
||
|
|
if(hint == TargetHint::ElementArray) {
|
||
|
|
auto& currentVAO = Context::current().state().mesh->currentVAO;
|
||
|
|
/* It can be also State::DisengagedBinding, in which case we unbind as
|
||
|
|
well to be sure */
|
||
|
8 years ago
|
if(currentVAO != 0)
|
||
|
|
Context::current().state().mesh->bindVAOImplementation(0);
|
||
|
9 years ago
|
}
|
||
|
|
|
||
|
14 years ago
|
/* Bind the buffer to hint target otherwise */
|
||
|
|
hintBinding = _id;
|
||
|
11 years ago
|
_flags |= ObjectFlag::Created;
|
||
|
13 years ago
|
glBindBuffer(GLenum(hint), _id);
|
||
|
14 years ago
|
return hint;
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
Buffer& Buffer::bind(const Target target, const UnsignedInt index, const GLintptr offset, const GLsizeiptr size) {
|
||
|
|
glBindBufferRange(GLenum(target), index, _id, offset, size);
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
Buffer& Buffer::bind(const Target target, const UnsignedInt index) {
|
||
|
|
glBindBufferBase(GLenum(target), index, _id);
|
||
|
|
return *this;
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
13 years ago
|
Int Buffer::size() {
|
||
|
|
/**
|
||
|
|
* @todo there is something like glGetBufferParameteri64v in 3.2 (I
|
||
|
|
* couldn't find any matching extension, though)
|
||
|
|
*/
|
||
|
|
GLint size;
|
||
|
10 years ago
|
(this->*Context::current().state().buffer->getParameterImplementation)(GL_BUFFER_SIZE, &size);
|
||
|
13 years ago
|
return size;
|
||
|
|
}
|
||
|
|
|
||
|
9 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
Containers::Array<char> Buffer::data() {
|
||
|
|
return subData(0, size());
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
11 years ago
|
Buffer& Buffer::setData(const Containers::ArrayView<const void> data, const BufferUsage usage) {
|
||
|
10 years ago
|
(this->*Context::current().state().buffer->dataImplementation)(data.size(), data, usage);
|
||
|
12 years ago
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
11 years ago
|
Buffer& Buffer::setSubData(const GLintptr offset, const Containers::ArrayView<const void> data) {
|
||
|
10 years ago
|
(this->*Context::current().state().buffer->subDataImplementation)(offset, data.size(), data);
|
||
|
12 years ago
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
Buffer& Buffer::invalidateData() {
|
||
|
10 years ago
|
(this->*Context::current().state().buffer->invalidateImplementation)();
|
||
|
12 years ago
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
|
Buffer& Buffer::invalidateSubData(const GLintptr offset, const GLsizeiptr length) {
|
||
|
10 years ago
|
(this->*Context::current().state().buffer->invalidateSubImplementation)(offset, length);
|
||
|
12 years ago
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
11 years ago
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
9 years ago
|
char* Buffer::map(const MapAccess access) {
|
||
|
|
return static_cast<char*>((this->*Context::current().state().buffer->mapImplementation)(access));
|
||
|
12 years ago
|
}
|
||
|
|
|
||
|
9 years ago
|
Containers::ArrayView<char> Buffer::map(const GLintptr offset, const GLsizeiptr length, const MapFlags flags) {
|
||
|
|
return {static_cast<char*>((this->*Context::current().state().buffer->mapRangeImplementation)(offset, length, flags)), std::size_t(length)};
|
||
|
12 years ago
|
}
|
||
|
|
|
||
|
|
Buffer& Buffer::flushMappedRange(const GLintptr offset, const GLsizeiptr length) {
|
||
|
10 years ago
|
(this->*Context::current().state().buffer->flushMappedRangeImplementation)(offset, length);
|
||
|
12 years ago
|
return *this;
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
bool Buffer::unmap() { return (this->*Context::current().state().buffer->unmapImplementation)(); }
|
||
|
11 years ago
|
#endif
|
||
|
13 years ago
|
|
||
|
12 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
9 years ago
|
Containers::Array<char> Buffer::subData(const GLintptr offset, const GLsizeiptr size) {
|
||
|
|
Containers::Array<char> data(size);
|
||
|
|
if(size) (this->*Context::current().state().buffer->getSubDataImplementation)(offset, size, data);
|
||
|
|
return data;
|
||
|
|
}
|
||
|
|
|
||
|
|
/** @todo remove when this is not used anymore */
|
||
|
|
#ifdef MAGNUM_BUILD_DEPRECATED
|
||
|
12 years ago
|
void Buffer::subDataInternal(GLintptr offset, GLsizeiptr size, GLvoid* data) {
|
||
|
10 years ago
|
(this->*Context::current().state().buffer->getSubDataImplementation)(offset, size, data);
|
||
|
12 years ago
|
}
|
||
|
|
#endif
|
||
|
9 years ago
|
#endif
|
||
|
12 years ago
|
|
||
|
14 years ago
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
11 years ago
|
void Buffer::bindImplementationFallback(const Target target, const GLuint firstIndex, Containers::ArrayView<Buffer* const> buffers) {
|
||
|
12 years ago
|
for(std::size_t i = 0; i != buffers.size(); ++i) {
|
||
|
|
if(buffers && buffers[i]) buffers[i]->bind(target, firstIndex + i);
|
||
|
|
else unbind(target, firstIndex + i);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
11 years ago
|
void Buffer::bindImplementationMulti(const Target target, const GLuint firstIndex, Containers::ArrayView<Buffer* const> buffers) {
|
||
|
|
/** @todo C++1z: VLAs? */
|
||
|
12 years ago
|
Containers::Array<GLuint> ids{buffers ? buffers.size() : 0};
|
||
|
|
if(buffers) for(std::size_t i = 0; i != buffers.size(); ++i) {
|
||
|
|
if(buffers[i]) {
|
||
|
|
buffers[i]->createIfNotAlready();
|
||
|
|
ids[i] = buffers[i]->_id;
|
||
|
|
} else {
|
||
|
|
ids[i] = 0;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
glBindBuffersBase(GLenum(target), firstIndex, buffers.size(), ids);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
11 years ago
|
/** @todoc const Containers::ArrayView makes Doxygen grumpy */
|
||
|
|
void Buffer::bindImplementationFallback(const Target target, const GLuint firstIndex, Containers::ArrayView<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers) {
|
||
|
12 years ago
|
for(std::size_t i = 0; i != buffers.size(); ++i) {
|
||
|
|
if(buffers && std::get<0>(buffers[i]))
|
||
|
|
std::get<0>(buffers[i])->bind(target, firstIndex + i, std::get<1>(buffers[i]), std::get<2>(buffers[i]));
|
||
|
|
else unbind(target, firstIndex + i);
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
11 years ago
|
/** @todoc const Containers::ArrayView makes Doxygen grumpy */
|
||
|
|
void Buffer::bindImplementationMulti(const Target target, const GLuint firstIndex, Containers::ArrayView<const std::tuple<Buffer*, GLintptr, GLsizeiptr>> buffers) {
|
||
|
12 years ago
|
/** @todo use ArrayTuple */
|
||
|
|
Containers::Array<GLuint> ids{buffers ? buffers.size() : 0};
|
||
|
|
Containers::Array<GLintptr> offsetsSizes{buffers ? buffers.size()*2 : 0};
|
||
|
|
if(buffers) for(std::size_t i = 0; i != buffers.size(); ++i) {
|
||
|
|
if(std::get<0>(buffers[i])) {
|
||
|
|
std::get<0>(buffers[i])->createIfNotAlready();
|
||
|
|
ids[i] = std::get<0>(buffers[i])->_id;
|
||
|
|
std::tie(std::ignore, offsetsSizes[i], offsetsSizes[buffers.size() + i]) = buffers[i];
|
||
|
|
} else {
|
||
|
|
ids[i] = 0;
|
||
|
12 years ago
|
offsetsSizes[i] = 0;
|
||
|
|
/** @todo fix workaround when NVidia 343.13 accepts zero sizes */
|
||
|
|
offsetsSizes[buffers.size() + i] = 1;
|
||
|
12 years ago
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
glBindBuffersRange(GLenum(target), firstIndex, buffers.size(), ids, offsetsSizes, offsetsSizes + buffers.size());
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
13 years ago
|
void Buffer::copyImplementationDefault(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
|
||
|
12 years ago
|
glCopyBufferSubData(GLenum(read.bindSomewhereInternal(TargetHint::CopyRead)), GLenum(write.bindSomewhereInternal(TargetHint::CopyWrite)), readOffset, writeOffset, size);
|
||
|
14 years ago
|
}
|
||
|
|
|
||
|
14 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
12 years ago
|
void Buffer::copyImplementationDSA(Buffer& read, Buffer& write, const GLintptr readOffset, const GLintptr writeOffset, const GLsizeiptr size) {
|
||
|
|
glCopyNamedBufferSubData(read._id, write._id, readOffset, writeOffset, size);
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
void Buffer::copyImplementationDSAEXT(Buffer& read, Buffer& write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) {
|
||
|
11 years ago
|
read._flags |= ObjectFlag::Created;
|
||
|
|
write._flags |= ObjectFlag::Created;
|
||
|
13 years ago
|
glNamedCopyBufferSubDataEXT(read._id, write._id, readOffset, writeOffset, size);
|
||
|
14 years ago
|
}
|
||
|
14 years ago
|
#endif
|
||
|
|
#endif
|
||
|
14 years ago
|
|
||
|
13 years ago
|
void Buffer::getParameterImplementationDefault(const GLenum value, GLint* const data) {
|
||
|
12 years ago
|
glGetBufferParameteriv(GLenum(bindSomewhereInternal(_targetHint)), value, data);
|
||
|
13 years ago
|
}
|
||
|
|
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
12 years ago
|
void Buffer::getParameterImplementationDSA(const GLenum value, GLint* const data) {
|
||
|
|
glGetNamedBufferParameteriv(_id, value, data);
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
void Buffer::getParameterImplementationDSAEXT(const GLenum value, GLint* const data) {
|
||
|
11 years ago
|
_flags |= ObjectFlag::Created;
|
||
|
13 years ago
|
glGetNamedBufferParameterivEXT(_id, value, data);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
13 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
13 years ago
|
void Buffer::getSubDataImplementationDefault(const GLintptr offset, const GLsizeiptr size, GLvoid* const data) {
|
||
|
12 years ago
|
glGetBufferSubData(GLenum(bindSomewhereInternal(_targetHint)), offset, size, data);
|
||
|
13 years ago
|
}
|
||
|
|
|
||
|
12 years ago
|
void Buffer::getSubDataImplementationDSA(const GLintptr offset, const GLsizeiptr size, GLvoid* const data) {
|
||
|
|
glGetNamedBufferSubData(_id, offset, size, data);
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
void Buffer::getSubDataImplementationDSAEXT(const GLintptr offset, const GLsizeiptr size, GLvoid* const data) {
|
||
|
11 years ago
|
_flags |= ObjectFlag::Created;
|
||
|
13 years ago
|
glGetNamedBufferSubDataEXT(_id, offset, size, data);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
13 years ago
|
void Buffer::dataImplementationDefault(GLsizeiptr size, const GLvoid* data, BufferUsage usage) {
|
||
|
12 years ago
|
glBufferData(GLenum(bindSomewhereInternal(_targetHint)), size, data, GLenum(usage));
|
||
|
14 years ago
|
}
|
||
|
|
|
||
|
14 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
12 years ago
|
void Buffer::dataImplementationDSA(const GLsizeiptr size, const GLvoid* const data, const BufferUsage usage) {
|
||
|
|
glNamedBufferData(_id, size, data, GLenum(usage));
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
void Buffer::dataImplementationDSAEXT(GLsizeiptr size, const GLvoid* data, BufferUsage usage) {
|
||
|
11 years ago
|
_flags |= ObjectFlag::Created;
|
||
|
13 years ago
|
glNamedBufferDataEXT(_id, size, data, GLenum(usage));
|
||
|
14 years ago
|
}
|
||
|
14 years ago
|
#endif
|
||
|
14 years ago
|
|
||
|
13 years ago
|
void Buffer::subDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data) {
|
||
|
12 years ago
|
glBufferSubData(GLenum(bindSomewhereInternal(_targetHint)), offset, size, data);
|
||
|
14 years ago
|
}
|
||
|
|
|
||
|
14 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
12 years ago
|
void Buffer::subDataImplementationDSA(const GLintptr offset, const GLsizeiptr size, const GLvoid* const data) {
|
||
|
|
glNamedBufferSubData(_id, offset, size, data);
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
void Buffer::subDataImplementationDSAEXT(GLintptr offset, GLsizeiptr size, const GLvoid* data) {
|
||
|
11 years ago
|
_flags |= ObjectFlag::Created;
|
||
|
14 years ago
|
glNamedBufferSubDataEXT(_id, offset, size, data);
|
||
|
|
}
|
||
|
14 years ago
|
#endif
|
||
|
14 years ago
|
|
||
|
14 years ago
|
void Buffer::invalidateImplementationNoOp() {}
|
||
|
|
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
void Buffer::invalidateImplementationARB() {
|
||
|
12 years ago
|
createIfNotAlready();
|
||
|
14 years ago
|
glInvalidateBufferData(_id);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
void Buffer::invalidateSubImplementationNoOp(GLintptr, GLsizeiptr) {}
|
||
|
|
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
|
void Buffer::invalidateSubImplementationARB(GLintptr offset, GLsizeiptr length) {
|
||
|
12 years ago
|
createIfNotAlready();
|
||
|
14 years ago
|
glInvalidateBufferSubData(_id, offset, length);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
11 years ago
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
14 years ago
|
void* Buffer::mapImplementationDefault(MapAccess access) {
|
||
|
14 years ago
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
12 years ago
|
return glMapBuffer(GLenum(bindSomewhereInternal(_targetHint)), GLenum(access));
|
||
|
14 years ago
|
#else
|
||
|
9 years ago
|
return glMapBufferOES(GLenum(bindSomewhereInternal(_targetHint)), GLenum(access));
|
||
|
14 years ago
|
#endif
|
||
|
14 years ago
|
}
|
||
|
|
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
12 years ago
|
void* Buffer::mapImplementationDSA(const MapAccess access) {
|
||
|
|
return glMapNamedBuffer(_id, GLenum(access));
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
void* Buffer::mapImplementationDSAEXT(MapAccess access) {
|
||
|
11 years ago
|
_flags |= ObjectFlag::Created;
|
||
|
14 years ago
|
return glMapNamedBufferEXT(_id, GLenum(access));
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
void* Buffer::mapRangeImplementationDefault(GLintptr offset, GLsizeiptr length, MapFlags access) {
|
||
|
14 years ago
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
12 years ago
|
return glMapBufferRange(GLenum(bindSomewhereInternal(_targetHint)), offset, length, GLenum(access));
|
||
|
14 years ago
|
#else
|
||
|
9 years ago
|
return glMapBufferRangeEXT(GLenum(bindSomewhereInternal(_targetHint)), offset, length, GLenum(access));
|
||
|
14 years ago
|
#endif
|
||
|
14 years ago
|
}
|
||
|
|
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
12 years ago
|
void* Buffer::mapRangeImplementationDSA(const GLintptr offset, const GLsizeiptr length, const MapFlags access) {
|
||
|
|
return glMapNamedBufferRange(_id, offset, length, GLenum(access));
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
void* Buffer::mapRangeImplementationDSAEXT(GLintptr offset, GLsizeiptr length, MapFlags access) {
|
||
|
11 years ago
|
_flags |= ObjectFlag::Created;
|
||
|
14 years ago
|
return glMapNamedBufferRangeEXT(_id, offset, length, GLenum(access));
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
void Buffer::flushMappedRangeImplementationDefault(GLintptr offset, GLsizeiptr length) {
|
||
|
14 years ago
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
12 years ago
|
glFlushMappedBufferRange(GLenum(bindSomewhereInternal(_targetHint)), offset, length);
|
||
|
14 years ago
|
#else
|
||
|
9 years ago
|
glFlushMappedBufferRangeEXT(GLenum(bindSomewhereInternal(_targetHint)), offset, length);
|
||
|
14 years ago
|
#endif
|
||
|
14 years ago
|
}
|
||
|
|
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
12 years ago
|
void Buffer::flushMappedRangeImplementationDSA(const GLintptr offset, const GLsizeiptr length) {
|
||
|
|
glFlushMappedNamedBufferRange(_id, offset, length);
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
void Buffer::flushMappedRangeImplementationDSAEXT(GLintptr offset, GLsizeiptr length) {
|
||
|
11 years ago
|
_flags |= ObjectFlag::Created;
|
||
|
14 years ago
|
glFlushMappedNamedBufferRangeEXT(_id, offset, length);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
|
|
||
|
|
bool Buffer::unmapImplementationDefault() {
|
||
|
14 years ago
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
12 years ago
|
return glUnmapBuffer(GLenum(bindSomewhereInternal(_targetHint)));
|
||
|
14 years ago
|
#else
|
||
|
9 years ago
|
return glUnmapBufferOES(GLenum(bindSomewhereInternal(_targetHint)));
|
||
|
14 years ago
|
#endif
|
||
|
14 years ago
|
}
|
||
|
|
|
||
|
|
#ifndef MAGNUM_TARGET_GLES
|
||
|
12 years ago
|
bool Buffer::unmapImplementationDSA() {
|
||
|
|
return glUnmapNamedBuffer(_id);
|
||
|
|
}
|
||
|
|
|
||
|
12 years ago
|
bool Buffer::unmapImplementationDSAEXT() {
|
||
|
11 years ago
|
_flags |= ObjectFlag::Created;
|
||
|
14 years ago
|
return glUnmapNamedBufferEXT(_id);
|
||
|
|
}
|
||
|
|
#endif
|
||
|
11 years ago
|
#endif
|
||
|
14 years ago
|
|
||
|
13 years ago
|
#ifndef DOXYGEN_GENERATING_OUTPUT
|
||
|
11 years ago
|
Debug& operator<<(Debug& debug, Buffer::TargetHint value) {
|
||
|
13 years ago
|
switch(value) {
|
||
|
10 years ago
|
/* LCOV_EXCL_START */
|
||
|
12 years ago
|
#define _c(value) case Buffer::TargetHint::value: return debug << "Buffer::TargetHint::" #value;
|
||
|
13 years ago
|
_c(Array)
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
11 years ago
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
12 years ago
|
_c(AtomicCounter)
|
||
|
11 years ago
|
#endif
|
||
|
13 years ago
|
_c(CopyRead)
|
||
|
|
_c(CopyWrite)
|
||
|
11 years ago
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
13 years ago
|
_c(DispatchIndirect)
|
||
|
|
_c(DrawIndirect)
|
||
|
|
#endif
|
||
|
11 years ago
|
#endif
|
||
|
13 years ago
|
_c(ElementArray)
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
_c(PixelPack)
|
||
|
|
_c(PixelUnpack)
|
||
|
11 years ago
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
12 years ago
|
_c(ShaderStorage)
|
||
|
13 years ago
|
#endif
|
||
|
11 years ago
|
#endif
|
||
|
9 years ago
|
#if !defined(MAGNUM_TARGET_GLES2) && !defined(MAGNUM_TARGET_WEBGL)
|
||
|
13 years ago
|
_c(Texture)
|
||
|
|
#endif
|
||
|
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
|
_c(TransformFeedback)
|
||
|
|
_c(Uniform)
|
||
|
|
#endif
|
||
|
|
#undef _c
|
||
|
10 years ago
|
/* LCOV_EXCL_STOP */
|
||
|
13 years ago
|
}
|
||
|
|
|
||
|
10 years ago
|
return debug << "Buffer::TargetHint(" << Debug::nospace << reinterpret_cast<void*>(GLenum(value)) << Debug::nospace << ")";
|
||
|
12 years ago
|
}
|
||
|
|
|
||
|
8 years ago
|
#ifndef MAGNUM_TARGET_GLES2
|
||
|
11 years ago
|
Debug& operator<<(Debug& debug, Buffer::Target value) {
|
||
|
12 years ago
|
switch(value) {
|
||
|
|
#define _c(value) case Buffer::Target::value: return debug << "Buffer::Target::" #value;
|
||
|
11 years ago
|
#ifndef MAGNUM_TARGET_WEBGL
|
||
|
12 years ago
|
_c(AtomicCounter)
|
||
|
|
_c(ShaderStorage)
|
||
|
11 years ago
|
#endif
|
||
|
12 years ago
|
_c(Uniform)
|
||
|
|
#undef _c
|
||
|
|
}
|
||
|
|
|
||
|
10 years ago
|
return debug << "Buffer::Target(" << Debug::nospace << reinterpret_cast<void*>(GLenum(value)) << Debug::nospace << ")";
|
||
|
13 years ago
|
}
|
||
|
|
#endif
|
||
|
12 years ago
|
#endif
|
||
|
13 years ago
|
|
||
|
14 years ago
|
}
|