X-Git-Url: http://git.tdb.fi/?p=libs%2Fgl.git;a=blobdiff_plain;f=source%2Fbackends%2Fopengl%2Fvertexsetup_backend.cpp;fp=source%2Fbackends%2Fopengl%2Fvertexsetup_backend.cpp;h=90189db7227eba94575f99a27fc98ab39e234843;hp=0000000000000000000000000000000000000000;hb=160e9eea29bd10034733d59507fa1bcca36be401;hpb=93448d16e72e38afbaecbccf6fdedd46d6a82a73 diff --git a/source/backends/opengl/vertexsetup_backend.cpp b/source/backends/opengl/vertexsetup_backend.cpp new file mode 100644 index 00000000..90189db7 --- /dev/null +++ b/source/backends/opengl/vertexsetup_backend.cpp @@ -0,0 +1,153 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "buffer.h" +#include "vertexarray.h" +#include "vertexformat.h" +#include "vertexsetup.h" +#include "vertexsetup_backend.h" + +using namespace std; + +namespace Msp { +namespace GL { + +OpenGLVertexSetup::OpenGLVertexSetup() +{ + static Require req(ARB_vertex_array_object); + if(ARB_direct_state_access) + glCreateVertexArrays(1, &id); + else + glGenVertexArrays(1, &id); +} + +OpenGLVertexSetup::~OpenGLVertexSetup() +{ + glDeleteVertexArrays(1, &id); +} + +void OpenGLVertexSetup::require_format(const VertexFormat &fmt, bool instanced) +{ + if(any_of(fmt.begin(), fmt.end(), is_integer_attribute)) + static Require _req(EXT_gpu_shader4); + if(instanced) + static Require req(ARB_instanced_arrays); +} + +void OpenGLVertexSetup::update(unsigned mask) const +{ + static bool direct = ARB_direct_state_access && ARB_vertex_attrib_binding; + + if(mask&VertexSetup::VERTEX_ARRAY) + update_vertex_array(*static_cast(this)->vertex_array, 0, 0, direct); + + if(mask&VertexSetup::INSTANCE_ARRAY) + update_vertex_array(*static_cast(this)->inst_array, 1, 1, direct); + + if(mask&VertexSetup::INDEX_BUFFER) + { + unsigned buf_id = static_cast(this)->index_buffer->id; + if(direct) + glVertexArrayElementBuffer(id, buf_id); + else + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buf_id); + } +} + +void OpenGLVertexSetup::update_vertex_array(const VertexArray &array, unsigned binding, unsigned divisor, bool direct) const +{ + if(!direct) + { + OpenGLBuffer::unbind_scratch(); + glBindBuffer(GL_ARRAY_BUFFER, array.get_buffer()->id); + } + + const VertexFormat &fmt = array.get_format(); + unsigned stride = fmt.stride(); + if(direct) + { + glVertexArrayVertexBuffer(id, binding, array.get_buffer()->id, 0, stride); + glVertexArrayBindingDivisor(id, binding, divisor); + } + + unsigned offset = 0; + for(VertexAttribute a: fmt) + { + unsigned sem = get_attribute_semantic(a); + bool integer = is_integer_attribute(a); + GLenum type = get_gl_type(get_attribute_source_type(a)); + unsigned cc = get_attribute_component_count(a); + if(direct) + { + if(integer) + glVertexArrayAttribIFormat(id, sem, cc, type, offset); + else + glVertexArrayAttribFormat(id, sem, cc, type, true, offset); + glVertexArrayAttribBinding(id, sem, binding); + glEnableVertexArrayAttrib(id, sem); + } + else + { + if(integer) + glVertexAttribIPointer(sem, cc, type, stride, reinterpret_cast(offset)); + else + glVertexAttribPointer(sem, cc, type, true, stride, reinterpret_cast(offset)); + if(ARB_instanced_arrays) + glVertexAttribDivisor(sem, divisor); + glEnableVertexAttribArray(sem); + } + offset += get_attribute_size(a); + } + + if(!direct) + glBindBuffer(GL_ARRAY_BUFFER, 0); +} + +void OpenGLVertexSetup::unload() +{ + if(ARB_direct_state_access) + { + glVertexArrayVertexBuffer(id, 0, 0, 0, 0); + glVertexArrayVertexBuffer(id, 1, 0, 0, 0); + glVertexArrayElementBuffer(id, 0); + } + else + { + glBindVertexArray(id); + glBindBuffer(GL_ARRAY_BUFFER, 0); + + for(VertexAttribute a: static_cast(this)->vertex_format) + { + unsigned sem = get_attribute_semantic(a); + glDisableVertexAttribArray(sem); + glVertexAttribPointer(sem, 1, GL_FLOAT, false, 0, 0); + } + for(VertexAttribute a: static_cast(this)->inst_format) + { + unsigned sem = get_attribute_semantic(a); + glDisableVertexAttribArray(sem); + glVertexAttribPointer(sem, 1, GL_FLOAT, false, 0, 0); + } + + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + } +} + +void OpenGLVertexSetup::set_debug_name(const string &name) +{ +#ifdef DEBUG + if(KHR_debug) + glObjectLabel(GL_VERTEX_ARRAY, id, name.size(), name.c_str()); +#else + (void)name; +#endif +} + +} // namespace GL +} // namespace Msp