/* Copyright © 2010, 2011, 2012 Vladimír Vondruš This file is part of Magnum. Magnum is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License version 3 only, as published by the Free Software Foundation. Magnum is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License version 3 for more details. */ #include "Buffer.h" #include #include "Context.h" #include "Extensions.h" #include "Implementation/State.h" #include "Implementation/BufferState.h" namespace Magnum { Buffer::CopyImplementation Buffer::copyImplementation = &Buffer::copyImplementationDefault; Buffer::SetDataImplementation Buffer::setDataImplementation = &Buffer::setDataImplementationDefault; Buffer::SetSubDataImplementation Buffer::setSubDataImplementation = &Buffer::setSubDataImplementationDefault; void Buffer::initializeContextBasedFunctionality(Context* context) { if(context->isExtensionSupported()) { Debug() << "Buffer: using" << Extensions::GL::EXT::direct_state_access::string() << "features"; copyImplementation = &Buffer::copyImplementationDSA; setDataImplementation = &Buffer::setDataImplementationDSA; setSubDataImplementation = &Buffer::setSubDataImplementationDSA; } } Buffer::~Buffer() { GLuint* bindings = Context::current()->state()->buffer->bindings; /* 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); } void Buffer::bind(Target target, GLuint id) { GLuint& bound = Context::current()->state()->buffer->bindings[Implementation::BufferState::indexForTarget(target)]; /* Already bound, nothing to do */ if(bound == id) return; /* Bind the buffer otherwise */ bound = id; glBindBuffer(static_cast(target), id); } Buffer::Target Buffer::bindInternal(Target hint) { GLuint* bindings = Context::current()->state()->buffer->bindings; 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 */ for(std::size_t i = 1; i != Implementation::BufferState::TargetCount; ++i) if(bindings[i] == _id) return Implementation::BufferState::targetForIndex[i]; /* Bind the buffer to hint target otherwise */ hintBinding = _id; glBindBuffer(static_cast(hint), _id); return hint; } void Buffer::copyImplementationDefault(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { glCopyBufferSubData(static_cast(read->bindInternal(Target::CopyRead)), static_cast(write->bindInternal(Target::CopyWrite)), readOffset, writeOffset, size); } void Buffer::copyImplementationDSA(Buffer* read, Buffer* write, GLintptr readOffset, GLintptr writeOffset, GLsizeiptr size) { glNamedCopyBufferSubDataEXT(read->_id, write->_id, readOffset, writeOffset, size); } void Buffer::setDataImplementationDefault(GLsizeiptr size, const GLvoid* data, Buffer::Usage usage) { glBufferData(static_cast(bindInternal(_targetHint)), size, data, static_cast(usage)); } void Buffer::setDataImplementationDSA(GLsizeiptr size, const GLvoid* data, Buffer::Usage usage) { glNamedBufferDataEXT(_id, size, data, static_cast(usage)); } void Buffer::setSubDataImplementationDefault(GLintptr offset, GLsizeiptr size, const GLvoid* data) { glBufferSubData(static_cast(bindInternal(_targetHint)), offset, size, data); } void Buffer::setSubDataImplementationDSA(GLintptr offset, GLsizeiptr size, const GLvoid* data) { glNamedBufferSubDataEXT(_id, offset, size, data); } }