/* * * Copyright (C) 2025 Brett Terpstra * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program 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 General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include #include #include #include namespace blt::gfx { #define ENSURE_CONTEXT_BOUND BLT_CONTRACT(glfwGetCurrentContext() != nullptr, "Expected active OpenGL context!") #if blt_debug_has_flag(BLT_DEBUG_CONTRACTS) GLuint bound_vao_id; #endif detail::vao_vbo_context_t& detail::vao_vbo_context_t::attribute_ptr(const int attribute_number, const int coordinate_size, const GLenum type, const int stride, const long offset) { if (auto& vec = vbo.attribute_numbers) { for (const auto& v : *vec) { if (static_cast(v) == attribute_number) goto use; } vec->push_back(attribute_number); } use: glEnableVertexAttribArray(attribute_number); glVertexAttribPointer(attribute_number, coordinate_size, type, GL_FALSE, stride < 0 ? 0 : stride, reinterpret_cast(offset)); attributed = true; return *this; } detail::vao_vbo_context_t::~vao_vbo_context_t() { #if blt_debug_has_flag(BLT_DEBUG_CONTRACTS) if (!(vbo.is_element() || attributed)) { BLT_WARN("VBO is not an element array buffer or been assigned to an attribute, are you sure this is what you want?"); BLT_WARN("You can silence this warning by calling .silence()"); } #endif } detail::vao_context_t& detail::vao_context_t::bind() { ENSURE_CONTEXT_BOUND; BLT_CONTRACT(vao.vaoID, "Expected VAO to have an associated VAO ID!"); glBindVertexArray(*vao.vaoID); bound_vao_id = *vao.vaoID; return *this; } detail::vao_context_t& detail::vao_context_t::unbind() // NOLINT { glBindVertexArray(0); bound_vao_id = 0; return *this; } detail::vao_vbo_context_t detail::vao_context_t::attach_vbo(unique_vbo_t&& vbo) const { ENSURE_CONTEXT_BOUND; BLT_CONTRACT(vao.vaoID, "Expected VAO to have an associated VAO ID!"); BLT_CONTRACT(is_bound(), "Expected VAO to be bound before attaching VBO! (If you are using this API correctly, this has been done for you!)"); auto& vbo_storage = vao.vbo_list.emplace_back(std::move(vbo)); vbo_storage.vbo->bind(); return vao_vbo_context_t{vao, vbo_storage}; } bool detail::vao_context_t::is_bound() const { return *vao.vaoID == bound_vao_id; } detail::vao_context_t unique_vao_t::bind() { ENSURE_CONTEXT_BOUND; return detail::vao_context_t{*this}; } }