diff --git a/CMakeLists.txt b/CMakeLists.txt index 36734b459..d57d32aaf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,6 +161,10 @@ SET(PROJECT_SOURCE "src/nodeobs_obspp_manager.hpp" "src/nodeobs_obspp_manager.cpp" "src/nodeobs_obspp_index.hpp" "src/nodeobs_obspp_index.cpp" "src/nodeobs_content.h" + "src/gs-limits.h" + "src/gs-vertex.h" "src/gs-vertex.cpp" + "src/gs-vertexbuffer.h" "src/gs-vertexbuffer.cpp" + "src/util-memory.h" "src/util-memory.cpp" ) SET(PROJECT_LIBRARIES ${CMAKE_JS_LIB} diff --git a/src/gs-limits.h b/src/gs-limits.h new file mode 100644 index 000000000..6c54798a1 --- /dev/null +++ b/src/gs-limits.h @@ -0,0 +1,26 @@ +/* +* Modern effects for a modern Streamer +* Copyright (C) 2017 Michael Fabian Dirks +* +* 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 2 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, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#pragma once +#include + +namespace GS { + static const uint32_t MAXIMUM_VERTICES = 0xFFFFFFu; + static const uint32_t MAXIMUM_UVW_LAYERS = 8u; +} \ No newline at end of file diff --git a/src/gs-vertex.cpp b/src/gs-vertex.cpp new file mode 100644 index 000000000..82463256b --- /dev/null +++ b/src/gs-vertex.cpp @@ -0,0 +1,48 @@ +/* + * Modern effects for a modern Streamer + * Copyright (C) 2017 Michael Fabian Dirks + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "gs-vertex.h" +#include "util-memory.h" + +GS::Vertex::Vertex() { + this->hasStore = true; + this->store = util::malloc_aligned(16, sizeof(vec3) * 3 + sizeof(uint32_t) + sizeof(vec4)*MAXIMUM_UVW_LAYERS); + this->position = reinterpret_cast(store); + this->normal = reinterpret_cast(reinterpret_cast(store) + (16 * 1)); + this->tangent = reinterpret_cast(reinterpret_cast(store) + (16 * 2)); + for (size_t n = 0; n < MAXIMUM_UVW_LAYERS; n++) { + this->uv[n] = reinterpret_cast(reinterpret_cast(store) + (16 * (2 + n))); + } + this->color = reinterpret_cast(reinterpret_cast(store) + (16 * (3 + MAXIMUM_UVW_LAYERS))); +} + +GS::Vertex::~Vertex() { + if (hasStore) + util::free_aligned(store); +} + +GS::Vertex::Vertex(vec3* p, vec3* n, vec3* t, uint32_t* col, vec4* uvs[MAXIMUM_UVW_LAYERS]) + : position(p), normal(n), tangent(t), color(col) { + if (uvs != nullptr) { + for (size_t idx = 0; idx < MAXIMUM_UVW_LAYERS; idx++) { + this->uv[idx] = uvs[idx]; + } + } + this->hasStore = false; +} diff --git a/src/gs-vertex.h b/src/gs-vertex.h new file mode 100644 index 000000000..17581e337 --- /dev/null +++ b/src/gs-vertex.h @@ -0,0 +1,47 @@ +/* + * Modern effects for a modern Streamer + * Copyright (C) 2017 Michael Fabian Dirks + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once +#include "gs-limits.h" +#include +#include +extern "C" { + #pragma warning( push ) + #pragma warning( disable: 4201 ) + #include + #pragma warning( pop ) +} + +namespace GS { + struct Vertex { + vec3* position; + vec3* normal; + vec3* tangent; + uint32_t* color; + vec4* uv[MAXIMUM_UVW_LAYERS]; + + Vertex(); + Vertex(vec3* p, vec3* n, vec3* t, uint32_t* col, vec4* uv[MAXIMUM_UVW_LAYERS]); + ~Vertex(); + + private: + bool hasStore; + void* store; + }; +} diff --git a/src/gs-vertexbuffer.cpp b/src/gs-vertexbuffer.cpp new file mode 100644 index 000000000..655135245 --- /dev/null +++ b/src/gs-vertexbuffer.cpp @@ -0,0 +1,331 @@ +/* + * Modern effects for a modern Streamer + * Copyright (C) 2017 Michael Fabian Dirks + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "gs-vertexbuffer.h" +#include "util-memory.h" +#include +extern "C" { +#pragma warning( push ) +#pragma warning( disable: 4201 ) +#include +#pragma warning( pop ) +} + +GS::VertexBuffer::~VertexBuffer() { + if (m_positions) { + util::free_aligned(m_positions); + m_positions = nullptr; + } + if (m_normals) { + util::free_aligned(m_normals); + m_normals = nullptr; + } + if (m_tangents) { + util::free_aligned(m_tangents); + m_tangents = nullptr; + } + if (m_colors) { + util::free_aligned(m_colors); + m_colors = nullptr; + } + for (size_t n = 0; n < MAXIMUM_UVW_LAYERS; n++) { + if (m_uvs[n]) { + util::free_aligned(m_uvs[n]); + m_uvs[n] = nullptr; + } + } + if (m_layerdata) { + util::free_aligned(m_layerdata); + m_layerdata = nullptr; + } + if (m_vertexbufferdata) { + std::memset(m_vertexbufferdata, 0, sizeof(gs_vb_data)); + if (!m_vertexbuffer) { + gs_vbdata_destroy(m_vertexbufferdata); + m_vertexbufferdata = nullptr; + } + } + if (m_vertexbuffer) { + obs_enter_graphics(); + gs_vertexbuffer_destroy(m_vertexbuffer); + obs_leave_graphics(); + m_vertexbuffer = nullptr; + } +} + +GS::VertexBuffer::VertexBuffer(uint32_t maximumVertices) { + if (maximumVertices > MAXIMUM_VERTICES) { + throw std::out_of_range("maximumVertices out of range"); + } + + // Assign limits. + m_capacity = maximumVertices; + m_layers = MAXIMUM_UVW_LAYERS; + + // Allocate memory for data. + m_vertexbufferdata = gs_vbdata_create(); + m_vertexbufferdata->num = m_capacity; + m_vertexbufferdata->points = m_positions = (vec3*)util::malloc_aligned(16, sizeof(vec3) * m_capacity); + std::memset(m_positions, 0, sizeof(vec3) * m_capacity); + m_vertexbufferdata->normals = m_normals = (vec3*)util::malloc_aligned(16, sizeof(vec3) * m_capacity); + std::memset(m_normals, 0, sizeof(vec3) * m_capacity); + m_vertexbufferdata->tangents = m_tangents = (vec3*)util::malloc_aligned(16, sizeof(vec3) * m_capacity); + std::memset(m_tangents, 0, sizeof(vec3) * m_capacity); + m_vertexbufferdata->colors = m_colors = (uint32_t*)util::malloc_aligned(16, sizeof(uint32_t) * m_capacity); + std::memset(m_colors, 0, sizeof(uint32_t) * m_capacity); + m_vertexbufferdata->num_tex = m_layers; + m_vertexbufferdata->tvarray = m_layerdata = (gs_tvertarray*)util::malloc_aligned(16, sizeof(gs_tvertarray)* m_layers); + for (size_t n = 0; n < MAXIMUM_UVW_LAYERS; n++) { + m_layerdata[n].array = m_uvs[n] = (vec4*)util::malloc_aligned(16, sizeof(vec4) * m_capacity); + m_layerdata[n].width = 4; + std::memset(m_uvs[n], 0, sizeof(vec4) * m_capacity); + } + + // Allocate GPU + obs_enter_graphics(); + m_vertexbuffer = gs_vertexbuffer_create(m_vertexbufferdata, GS_DYNAMIC); + std::memset(m_vertexbufferdata, 0, sizeof(gs_vb_data)); + m_vertexbufferdata->num = m_capacity; + m_vertexbufferdata->num_tex = m_layers; + obs_leave_graphics(); + if (!m_vertexbuffer) { + throw std::runtime_error("Failed to create vertex buffer."); + } +} + +GS::VertexBuffer::VertexBuffer(gs_vertbuffer_t* vb) { + gs_vb_data* vbd = gs_vertexbuffer_get_data(vb); + VertexBuffer((uint32_t)vbd->num); + this->SetUVLayers((uint32_t)vbd->num_tex); + + if (vbd->points != nullptr) + std::memcpy(m_positions, vbd->points, vbd->num * sizeof(vec3)); + if (vbd->normals != nullptr) + std::memcpy(m_normals, vbd->normals, vbd->num * sizeof(vec3)); + if (vbd->tangents != nullptr) + std::memcpy(m_tangents, vbd->tangents, vbd->num * sizeof(vec3)); + if (vbd->colors != nullptr) + std::memcpy(m_colors, vbd->colors, vbd->num * sizeof(uint32_t)); + if (vbd->tvarray != nullptr) { + for (size_t n = 0; n < vbd->num_tex; n++) { + if (vbd->tvarray[n].array != nullptr && vbd->tvarray[n].width <= 4 && vbd->tvarray[n].width > 0) { + if (vbd->tvarray[n].width == 4) { + std::memcpy(m_uvs[n], vbd->tvarray[n].array, vbd->num * sizeof(vec4)); + } else { + for (size_t idx = 0; idx < m_capacity; idx++) { + float* mem = reinterpret_cast(vbd->tvarray[n].array) + + (idx * vbd->tvarray[n].width); + std::memset(&m_uvs[n][idx], 0, sizeof(vec4)); + std::memcpy(&m_uvs[n][idx], mem, vbd->tvarray[n].width); + } + } + } + } + } +} + + +GS::VertexBuffer::VertexBuffer(VertexBuffer const& other) : VertexBuffer(other.m_capacity) { + // Copy Constructor + std::memcpy(m_positions, other.m_positions, m_capacity * sizeof(vec3)); + std::memcpy(m_normals, other.m_normals, m_capacity * sizeof(vec3)); + std::memcpy(m_tangents, other.m_tangents, m_capacity * sizeof(vec3)); + std::memcpy(m_colors, other.m_colors, m_capacity * sizeof(vec3)); + for (size_t n = 0; n < MAXIMUM_UVW_LAYERS; n++) { + std::memcpy(m_uvs[n], other.m_uvs[n], m_capacity * sizeof(vec3)); + } +} + +GS::VertexBuffer::VertexBuffer(VertexBuffer const&& other) { + // Move Constructor + m_capacity = other.m_capacity; + m_size = other.m_size; + m_layers = other.m_layers; + m_positions = other.m_positions; + m_normals = other.m_normals; + m_tangents = other.m_tangents; + for (size_t n = 0; n < MAXIMUM_UVW_LAYERS; n++) { + m_uvs[n] = other.m_uvs[n]; + } + m_vertexbufferdata = other.m_vertexbufferdata; + m_vertexbuffer = other.m_vertexbuffer; + m_layerdata = other.m_layerdata; +} + +void GS::VertexBuffer::operator=(VertexBuffer const&& other) { + // Move Assignment + /// First self-destruct (semi-destruct itself). + if (m_positions) { + util::free_aligned(m_positions); + m_positions = nullptr; + } + if (m_normals) { + util::free_aligned(m_normals); + m_normals = nullptr; + } + if (m_tangents) { + util::free_aligned(m_tangents); + m_tangents = nullptr; + } + if (m_colors) { + util::free_aligned(m_colors); + m_colors = nullptr; + } + for (size_t n = 0; n < MAXIMUM_UVW_LAYERS; n++) { + if (m_uvs[n]) { + util::free_aligned(m_uvs[n]); + m_uvs[n] = nullptr; + } + } + if (m_layerdata) { + util::free_aligned(m_layerdata); + m_layerdata = nullptr; + } + if (m_vertexbufferdata) { + std::memset(m_vertexbufferdata, 0, sizeof(gs_vb_data)); + if (!m_vertexbuffer) { + gs_vbdata_destroy(m_vertexbufferdata); + m_vertexbufferdata = nullptr; + } + } + if (m_vertexbuffer) { + obs_enter_graphics(); + gs_vertexbuffer_destroy(m_vertexbuffer); + obs_leave_graphics(); + m_vertexbuffer = nullptr; + } + + /// Then assign new values. + m_capacity = other.m_capacity; + m_size = other.m_size; + m_layers = other.m_layers; + m_positions = other.m_positions; + m_normals = other.m_normals; + m_tangents = other.m_tangents; + for (size_t n = 0; n < MAXIMUM_UVW_LAYERS; n++) { + m_uvs[n] = other.m_uvs[n]; + } + m_vertexbufferdata = other.m_vertexbufferdata; + m_vertexbuffer = other.m_vertexbuffer; + m_layerdata = other.m_layerdata; +} + +void GS::VertexBuffer::Resize(uint32_t new_size) { + if (new_size > m_capacity) { + throw std::out_of_range("new_size out of range"); + } + m_size = new_size; +} + +uint32_t GS::VertexBuffer::Size() { + return m_size; +} + +bool GS::VertexBuffer::Empty() { + return m_size == 0; +} + +const GS::Vertex GS::VertexBuffer::At(uint32_t idx) { + if ((idx < 0) || (idx >= m_size)) { + throw std::out_of_range("idx out of range"); + } + + GS::Vertex vtx(&m_positions[idx], &m_normals[idx], &m_tangents[idx], &m_colors[idx], nullptr); + for (size_t n = 0; n < MAXIMUM_UVW_LAYERS; n++) { + vtx.uv[n] = &m_uvs[n][idx]; + } + return vtx; +} + +const GS::Vertex GS::VertexBuffer::operator[](uint32_t const pos) { + return At(pos); +} + +void GS::VertexBuffer::SetUVLayers(uint32_t layers) { + m_layers = layers; +} + +uint32_t GS::VertexBuffer::GetUVLayers() { + return m_layers; +} + +vec3* GS::VertexBuffer::GetPositions() { + return m_positions; +} + +vec3* GS::VertexBuffer::GetNormals() { + return m_normals; +} + +vec3* GS::VertexBuffer::GetTangents() { + return m_tangents; +} + +uint32_t* GS::VertexBuffer::GetColors() { + return m_colors; +} + +vec4* GS::VertexBuffer::GetUVLayer(size_t idx) { + if ((idx < 0) || (idx >= m_layers)) { + throw std::out_of_range("idx out of range"); + } + return m_uvs[idx]; +} + +gs_vertbuffer_t* GS::VertexBuffer::Update(bool refreshGPU) { + if (!refreshGPU) + return m_vertexbuffer; + + if (m_size > m_capacity) + throw std::out_of_range("size is larger than capacity"); + + // Update VertexBuffer data. + m_vertexbufferdata = gs_vertexbuffer_get_data(m_vertexbuffer); + std::memset(m_vertexbufferdata, 0, sizeof(gs_vb_data)); + m_vertexbufferdata->num = m_capacity; + m_vertexbufferdata->points = m_positions; + m_vertexbufferdata->normals = m_normals; + m_vertexbufferdata->tangents = m_tangents; + m_vertexbufferdata->colors = m_colors; + m_vertexbufferdata->num_tex = m_layers; + m_vertexbufferdata->tvarray = m_layerdata; + for (size_t n = 0; n < MAXIMUM_UVW_LAYERS; n++) { + m_layerdata[n].array = m_uvs[n]; + m_layerdata[n].width = 4; + } + + // Update GPU + obs_enter_graphics(); + gs_vertexbuffer_flush(m_vertexbuffer); + obs_leave_graphics(); + + // WORKAROUND: OBS Studio 20.x and below incorrectly deletes data that it doesn't own. + std::memset(m_vertexbufferdata, 0, sizeof(gs_vb_data)); + m_vertexbufferdata->num = m_capacity; + m_vertexbufferdata->num_tex = m_layers; + for (uint32_t n = 0; n < m_layers; n++) { + m_layerdata[n].width = 4; + } + + return m_vertexbuffer; +} + +gs_vertbuffer_t* GS::VertexBuffer::Update() { + return Update(true); +} diff --git a/src/gs-vertexbuffer.h b/src/gs-vertexbuffer.h new file mode 100644 index 000000000..a561e603f --- /dev/null +++ b/src/gs-vertexbuffer.h @@ -0,0 +1,179 @@ +/* + * Modern effects for a modern Streamer + * Copyright (C) 2017 Michael Fabian Dirks + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once +#include "gs-limits.h" +#include "gs-vertex.h" +#include "util-memory.h" +#include +extern "C" { +#pragma warning( push ) +#pragma warning( disable: 4201 ) +#include +#pragma warning( pop ) +} + +namespace GS { + class VertexBuffer { + public: + #pragma region Constructor & Destructor + virtual ~VertexBuffer(); + + /*! + * \brief Create a Vertex Buffer with a specific number of Vertices. + * + * \param maximumVertices Maximum amount of vertices to store. + */ + VertexBuffer(uint32_t maximumVertices); + + /*! + * \brief Create a Vertex Buffer with the maximum number of Vertices. + * + * \param maximumVertices Maximum amount of vertices to store. + */ + VertexBuffer() : VertexBuffer(MAXIMUM_VERTICES) {}; + + /*! + * \brief Create a copy of a Vertex Buffer + * Full Description below + * + * \param other The Vertex Buffer to copy + */ + VertexBuffer(gs_vertbuffer_t* other); + + #pragma endregion Constructor & Destructor + + #pragma region Copy/Move Constructors + // Copy Constructor & Assignments + + /*! + * \brief Copy Constructor + * + * + * \param other + */ + VertexBuffer(VertexBuffer const& other); + + /*! + * \brief Copy Assignment + * Unsafe operation and as such marked as deleted. + * + * \param other + */ + void operator=(VertexBuffer const& other) = delete; + + // Move Constructor & Assignments + + /*! + * \brief Move Constructor + * + * + * \param other + */ + VertexBuffer(VertexBuffer const&& other); + + /*! + * \brief Move Assignment + * + * + * \param other + */ + void operator=(VertexBuffer const&& other); + #pragma endregion Copy/Move Constructors + + + + void Resize(uint32_t new_size); + + uint32_t Size(); + + bool Empty(); + + const GS::Vertex At(uint32_t idx); + + const GS::Vertex operator[](uint32_t const pos); + + void SetUVLayers(uint32_t layers); + + uint32_t GetUVLayers(); + + /*! + * \brief Directly access the positions buffer + * Returns the internal memory that is assigned to hold all vertex positions. + * + * \return A that points at the first vertex's position. + */ + vec3* GetPositions(); + + /*! + * \brief Directly access the normals buffer + * Returns the internal memory that is assigned to hold all vertex normals. + * + * \return A that points at the first vertex's normal. + */ + vec3* GetNormals(); + + /*! + * \brief Directly access the tangents buffer + * Returns the internal memory that is assigned to hold all vertex tangents. + * + * \return A that points at the first vertex's tangent. + */ + vec3* GetTangents(); + + /*! + * \brief Directly access the colors buffer + * Returns the internal memory that is assigned to hold all vertex colors. + * + * \return A that points at the first vertex's color. + */ + uint32_t* GetColors(); + + /*! + * \brief Directly access the uv buffer + * Returns the internal memory that is assigned to hold all vertex uvs. + * + * \return A that points at the first vertex's uv. + */ + vec4* GetUVLayer(size_t idx); + + #pragma region Update / Grab GS object + gs_vertbuffer_t* Update(); + + gs_vertbuffer_t* Update(bool refreshGPU); + #pragma endregion Update / Grab GS object + + private: + uint32_t m_size; + uint32_t m_capacity; + uint32_t m_layers; + + // Memory Storage + vec3 *m_positions; + vec3 *m_normals; + vec3 *m_tangents; + uint32_t *m_colors; + vec4 *m_uvs[MAXIMUM_UVW_LAYERS]; + + // OBS GS Data + gs_vb_data* m_vertexbufferdata; + gs_vertbuffer_t* m_vertexbuffer; + gs_tvertarray* m_layerdata; + }; +} diff --git a/src/nodeobs_display.cpp b/src/nodeobs_display.cpp index 043fe679a..f2e992ff4 100644 --- a/src/nodeobs_display.cpp +++ b/src/nodeobs_display.cpp @@ -77,11 +77,11 @@ OBS::Display::Display() { obs_enter_graphics(); m_gsSolidEffect = obs_get_base_effect(OBS_EFFECT_SOLID); - m_lines = new VertexBufferHelper(); - m_triangles = new VertexBufferHelper(); + m_lines = new GS::VertexBuffer(65535); + m_triangles = new GS::VertexBuffer(65535); // Text - m_textVertices = new VertexBufferHelper(); + m_textVertices = new GS::VertexBuffer(65535); m_textEffect = obs_get_base_effect(OBS_EFFECT_DEFAULT); m_textTexture = gs_texture_create_from_file((g_moduleDirectory + "/resources/roboto.png").c_str()); if (!m_textTexture) { @@ -268,7 +268,7 @@ void OBS::Display::SetResizeBoxInnerColor(uint8_t r, uint8_t g, uint8_t b, uint8 m_resizeInnerColor = a << 24 | b << 16 | g << 8 | r; } -static void DrawGlyph(OBS::VertexBufferHelper* vb, float_t x, float_t y, float_t scale, float_t depth, char glyph, uint32_t color) { +static void DrawGlyph(GS::VertexBuffer* vb, float_t x, float_t y, float_t scale, float_t depth, char glyph, uint32_t color) { // I'll be fully honest here, this code is pretty much shit. It works but // it is far from ideal and can just render very basic text. It does the // job but, well, lets just say it shouldn't be used for other things. @@ -328,104 +328,112 @@ static void DrawGlyph(OBS::VertexBufferHelper* vb, float_t x, float_t y, float_t break; } + GS::Vertex v; + size_t bs = vb->Size(); + vb->Resize(bs + 6); + // Top Left - OBS::VertexHelper* v = vb->add(); - vec3_set(&v->pos, x, y, depth); - vec2_set(&v->uv0, uvX, uvY); - v->color = color; + v = vb->At(bs + 0); + vec3_set(v.position, x, y, depth); + vec4_set(v.uv[0], uvX, uvY, 0, 0); + *v.color = color; // Top Right - v = vb->add(); - vec3_set(&v->pos, x + scale, y, depth); - vec2_set(&v->uv0, uvX + uvO, uvY); - v->color = color; + v = vb->At(bs + 1); + vec3_set(v.position, x + scale, y, depth); + vec4_set(v.uv[0], uvX + uvO, uvY, 0, 0); + *v.color = color; // Bottom Left - v = vb->add(); - vec3_set(&v->pos, x, y + scale * 2, depth); - vec2_set(&v->uv0, uvX, uvY + uvO); - v->color = color; + v = vb->At(bs + 2); + vec3_set(v.position, x, y + scale * 2, depth); + vec4_set(v.uv[0], uvX, uvY + uvO, 0, 0); + *v.color = color; // Top Right - v = vb->add(); - vec3_set(&v->pos, x + scale, y, depth); - vec2_set(&v->uv0, uvX + uvO, uvY); - v->color = color; + v = vb->At(bs + 3); + vec3_set(v.position, x + scale, y, depth); + vec4_set(v.uv[0], uvX + uvO, uvY, 0, 0); + *v.color = color; // Bottom Left - v = vb->add(); - vec3_set(&v->pos, x, y + scale * 2, depth); - vec2_set(&v->uv0, uvX, uvY + uvO); - v->color = color; + v = vb->At(bs + 4); + vec3_set(v.position, x, y + scale * 2, depth); + vec4_set(v.uv[0], uvX, uvY + uvO, 0, 0); + *v.color = color; // Bottom Right - v = vb->add(); - vec3_set(&v->pos, x + scale, y + scale * 2, depth); - vec2_set(&v->uv0, uvX + uvO, uvY + uvO); - v->color = color; + v = vb->At(bs + 5); + vec3_set(v.position, x + scale, y + scale * 2, depth); + vec4_set(v.uv[0], uvX + uvO, uvY + uvO, 0, 0); + *v.color = color; } -inline void DrawBox(float_t x, float_t y, float_t w, float_t h, float_t depth, uint32_t color, OBS::VertexBufferHelper* vbh) { - OBS::VertexHelper* v; +inline void DrawBox(float_t x, float_t y, float_t w, float_t h, float_t depth, uint32_t color, GS::VertexBuffer* vbh) { + GS::Vertex v; + size_t bs = vbh->Size(); + vbh->Resize(bs + 6); - v = vbh->add(); - vec3_set(&v->pos, x, y, depth); - v->color = color; + v = vbh->At(bs + 0); + vec3_set(v.position, x, y, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x + w, y, depth); - v->color = color; + v = vbh->At(bs + 1); + vec3_set(v.position, x + w, y, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x, y + h, depth); - v->color = color; + v = vbh->At(bs + 2); + vec3_set(v.position, x, y + h, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x, y + h, depth); - v->color = color; + v = vbh->At(bs + 3); + vec3_set(v.position, x, y + h, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x + w, y, depth); - v->color = color; + v = vbh->At(bs + 4); + vec3_set(v.position, x + w, y, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x + w, y + h, depth); - v->color = color; + v = vbh->At(bs + 5); + vec3_set(v.position, x + w, y + h, depth); + *v.color = color; } -inline void DrawBoxOutline(float_t x, float_t y, float_t w, float_t h, float_t depth, uint32_t color, OBS::VertexBufferHelper* vbh) { - OBS::VertexHelper* v; +inline void DrawBoxOutline(float_t x, float_t y, float_t w, float_t h, float_t depth, uint32_t color, GS::VertexBuffer* vbh) { + GS::Vertex v; + size_t bs = vbh->Size(); + vbh->Resize(bs + 8); - v = vbh->add(); - vec3_set(&v->pos, x, y, depth); - v->color = color; + v = vbh->At(bs + 0); + vec3_set(v.position, x, y, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x + w, y, depth); - v->color = color; + v = vbh->At(bs + 1); + vec3_set(v.position, x + w, y, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x + w, y, depth); - v->color = color; + v = vbh->At(bs + 2); + vec3_set(v.position, x + w, y, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x + w, y + h, depth); - v->color = color; + v = vbh->At(bs + 3); + vec3_set(v.position, x + w, y + h, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x + w, y + h, depth); - v->color = color; + v = vbh->At(bs + 4); + vec3_set(v.position, x + w, y + h, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x, y + h, depth); - v->color = color; + v = vbh->At(bs + 5); + vec3_set(v.position, x, y + h, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x, y + h, depth); - v->color = color; + v = vbh->At(bs + 6); + vec3_set(v.position, x, y + h, depth); + *v.color = color; - v = vbh->add(); - vec3_set(&v->pos, x, y, depth); - v->color = color; + v = vbh->At(bs + 7); + vec3_set(v.position, x, y, depth); + *v.color = color; } bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, void *param) { @@ -441,8 +449,8 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, uint32_t flags = obs_source_get_output_flags(itemSource); bool isOnlyAudio = (flags & OBS_SOURCE_VIDEO) == 0; + GS::Vertex v(nullptr, nullptr, nullptr, nullptr, nullptr); if (obs_sceneitem_selected(item) && !isOnlyAudio && ((itemWidth > 0) && (itemHeight > 0))) { - VertexHelper* v; matrix4 itemMatrix, sceneToView; obs_sceneitem_get_box_transform(item, &itemMatrix); @@ -486,12 +494,16 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, float_t pt = 8; for (size_t n = 0; n < 4; n++) { + bool isIn = (edge[n].x >= 0) && (edge[n].x < sceneWidth * dp->m_worldToPreviewScale.x) && (edge[n].y >= 0) && (edge[n].y < sceneHeight * dp->m_worldToPreviewScale.y); if (!isIn) continue; + size_t bs = dp->m_lines->Size(); + dp->m_lines->Resize(bs + 2); + vec3 alignLeft = { -1, 0, 0 }; vec3 alignTop = { 0, -1, 0 }; @@ -501,13 +513,13 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, float left = vec3_dot(&temp, &alignLeft), top = vec3_dot(&temp, &alignTop); if (left > 0.5) { // LEFT - v = dp->m_lines->add(); - vec3_set(&v->pos, 0, edge[n].y, 0); - v->color = dp->m_guidelineColor; + v = dp->m_lines->At(bs + 0); + vec3_set(v.position, 0, edge[n].y, 0); + *v.color = dp->m_guidelineColor; - v = dp->m_lines->add(); - vec3_set(&v->pos, edge[n].x, edge[n].y, 0); - v->color = dp->m_guidelineColor; + v = dp->m_lines->At(bs + 1); + vec3_set(v.position, edge[n].x, edge[n].y, 0); + *v.color = dp->m_guidelineColor; float_t dist = edge[n].x; if (dist > (pt * 4)) { @@ -524,13 +536,13 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, } } } else if (left < -0.5) { // RIGHT - v = dp->m_lines->add(); - vec3_set(&v->pos, sceneWidth * dp->m_worldToPreviewScale.x, edge[n].y, 0); - v->color = dp->m_guidelineColor; + v = dp->m_lines->At(bs + 0); + vec3_set(v.position, sceneWidth * dp->m_worldToPreviewScale.x, edge[n].y, 0); + *v.color = dp->m_guidelineColor; - v = dp->m_lines->add(); - vec3_set(&v->pos, edge[n].x, edge[n].y, 0); - v->color = dp->m_guidelineColor; + v = dp->m_lines->At(bs + 1); + vec3_set(v.position, edge[n].x, edge[n].y, 0); + *v.color = dp->m_guidelineColor; float_t dist = sceneWidth * dp->m_worldToPreviewScale.x - edge[n].x; if (dist > (pt * 4)) { @@ -547,13 +559,13 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, } } } else if (top > 0.5) { // UP - v = dp->m_lines->add(); - vec3_set(&v->pos, edge[n].x, 0, 0); - v->color = dp->m_guidelineColor; + v = dp->m_lines->At(bs + 0); + vec3_set(v.position, edge[n].x, 0, 0); + *v.color = dp->m_guidelineColor; - v = dp->m_lines->add(); - vec3_set(&v->pos, edge[n].x, edge[n].y, 0); - v->color = dp->m_guidelineColor; + v = dp->m_lines->At(bs + 1); + vec3_set(v.position, edge[n].x, edge[n].y, 0); + *v.color = dp->m_guidelineColor; float_t dist = edge[n].y; if (dist > pt) { @@ -570,13 +582,13 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, } } } else if (top < -0.5) { // DOWN - v = dp->m_lines->add(); - vec3_set(&v->pos, edge[n].x, sceneHeight * dp->m_worldToPreviewScale.y, 0); - v->color = dp->m_guidelineColor; + v = dp->m_lines->At(bs + 0); + vec3_set(v.position, edge[n].x, sceneHeight * dp->m_worldToPreviewScale.y, 0); + *v.color = dp->m_guidelineColor; - v = dp->m_lines->add(); - vec3_set(&v->pos, edge[n].x, edge[n].y, 0); - v->color = dp->m_guidelineColor; + v = dp->m_lines->At(bs + 1); + vec3_set(v.position, edge[n].x, edge[n].y, 0); + *v.color = dp->m_guidelineColor; float_t dist = sceneHeight * dp->m_worldToPreviewScale.y - edge[n].y; if (dist > (pt * 4)) { @@ -594,36 +606,38 @@ bool OBS::Display::DrawSelectedSource(obs_scene_t *scene, obs_sceneitem_t *item, } } } + size_t bs = dp->m_lines->Size(); + dp->m_lines->Resize(bs + 8); // Drawing /// Outline - v = dp->m_lines->add(); - vec3_set(&v->pos, corner[0].x, corner[0].y, 0); - v->color = dp->m_outlineColor; - v = dp->m_lines->add(); - vec3_set(&v->pos, corner[1].x, corner[1].y, 0); - v->color = dp->m_outlineColor; - - v = dp->m_lines->add(); - vec3_set(&v->pos, corner[1].x, corner[1].y, 0); - v->color = dp->m_outlineColor; - v = dp->m_lines->add(); - vec3_set(&v->pos, corner[2].x, corner[2].y, 0); - v->color = dp->m_outlineColor; - - v = dp->m_lines->add(); - vec3_set(&v->pos, corner[2].x, corner[2].y, 0); - v->color = dp->m_outlineColor; - v = dp->m_lines->add(); - vec3_set(&v->pos, corner[3].x, corner[3].y, 0); - v->color = dp->m_outlineColor; - - v = dp->m_lines->add(); - vec3_set(&v->pos, corner[3].x, corner[3].y, 0); - v->color = dp->m_outlineColor; - v = dp->m_lines->add(); - vec3_set(&v->pos, corner[0].x, corner[0].y, 0); - v->color = dp->m_outlineColor; + v = dp->m_lines->At(bs + 0); + vec3_set(v.position, corner[0].x, corner[0].y, 0); + *v.color = dp->m_outlineColor; + v = dp->m_lines->At(bs + 1); + vec3_set(v.position, corner[1].x, corner[1].y, 0); + *v.color = dp->m_outlineColor; + + v = dp->m_lines->At(bs + 2); + vec3_set(v.position, corner[1].x, corner[1].y, 0); + *v.color = dp->m_outlineColor; + v = dp->m_lines->At(bs + 3); + vec3_set(v.position, corner[2].x, corner[2].y, 0); + *v.color = dp->m_outlineColor; + + v = dp->m_lines->At(bs + 4); + vec3_set(v.position, corner[2].x, corner[2].y, 0); + *v.color = dp->m_outlineColor; + v = dp->m_lines->At(bs + 5); + vec3_set(v.position, corner[3].x, corner[3].y, 0); + *v.color = dp->m_outlineColor; + + v = dp->m_lines->At(bs + 6); + vec3_set(v.position, corner[3].x, corner[3].y, 0); + *v.color = dp->m_outlineColor; + v = dp->m_lines->At(bs + 7); + vec3_set(v.position, corner[0].x, corner[0].y, 0); + *v.color = dp->m_outlineColor; /// Resize Boxes DrawBox(corner[0].x - 5, corner[0].y - 5, 10, 10, 0, dp->m_resizeOuterColor, dp->m_triangles); @@ -680,30 +694,30 @@ void OBS::Display::DisplayCallback(OBS::Display* dp, uint32_t cx, uint32_t cy) { dp->m_previewSize.first, dp->m_previewSize.second); #pragma region Background - dp->m_triangles->clear(); + dp->m_triangles->Resize(4); { - VertexHelper* v = dp->m_triangles->add(); - vec3_set(&v->pos, 0, 0, 0); - v->color = dp->m_backgroundColor; + GS::Vertex v = dp->m_triangles->At(0); + vec3_set(v.position, 0, 0, 0); + *v.color = dp->m_backgroundColor; - v = dp->m_triangles->add(); - vec3_set(&v->pos, float(sourceW), 0, 0); - v->color = dp->m_backgroundColor; + v = dp->m_triangles->At(1); + vec3_set(v.position, float(sourceW), 0, 0); + *v.color = dp->m_backgroundColor; - v = dp->m_triangles->add(); - vec3_set(&v->pos, 0, float(sourceH), 0); - v->color = dp->m_backgroundColor; + v = dp->m_triangles->At(2); + vec3_set(v.position, 0, float(sourceH), 0); + *v.color = dp->m_backgroundColor; - v = dp->m_triangles->add(); - vec3_set(&v->pos, float(sourceW), float(sourceH), 0); - v->color = dp->m_backgroundColor; + v = dp->m_triangles->At(3); + vec3_set(v.position, float(sourceW), float(sourceH), 0); + *v.color = dp->m_backgroundColor; } - gs_vertbuffer_t *vb = dp->m_triangles->update(); + gs_vertbuffer_t *vb = dp->m_triangles->Update(); while (gs_effect_loop(dp->m_gsSolidEffect, "SolidColored")) { gs_load_vertexbuffer(vb); gs_load_indexbuffer(nullptr); - gs_draw(GS_TRISTRIP, 0, (uint32_t)dp->m_triangles->size()); + gs_draw(GS_TRISTRIP, 0, (uint32_t)dp->m_triangles->Size()); } #pragma endregion Background @@ -720,9 +734,9 @@ void OBS::Display::DisplayCallback(OBS::Display* dp, uint32_t cx, uint32_t cy) { -100.0f, 100.0f); // Clear Buffers - dp->m_lines->clear(); - dp->m_triangles->clear(); - dp->m_textVertices->clear(); + dp->m_lines->Resize(0); + dp->m_triangles->Resize(0); + dp->m_textVertices->Resize(0); /* Here we assume that channel 0 holds the one and only transition. * We also assume that the active source within that transition is @@ -736,35 +750,35 @@ void OBS::Display::DisplayCallback(OBS::Display* dp, uint32_t cx, uint32_t cy) { obs_source_release(source); // Lines - if (dp->m_lines->size() > 0) { - gs_vertbuffer_t* vb = dp->m_lines->update(); + if (dp->m_lines->Size() > 0) { + gs_vertbuffer_t* vb = dp->m_lines->Update(); while (gs_effect_loop(dp->m_gsSolidEffect, "SolidColored")) { gs_load_vertexbuffer(vb); gs_load_indexbuffer(nullptr); - gs_draw(GS_LINES, 0, (uint32_t)dp->m_lines->size()); + gs_draw(GS_LINES, 0, (uint32_t)dp->m_lines->Size()); } } // Triangles - if (dp->m_triangles->size() > 0) { - gs_vertbuffer_t* vb = dp->m_triangles->update(); + if (dp->m_triangles->Size() > 0) { + gs_vertbuffer_t* vb = dp->m_triangles->Update(); while (gs_effect_loop(dp->m_gsSolidEffect, "SolidColored")) { gs_load_vertexbuffer(vb); gs_load_indexbuffer(nullptr); - gs_draw(GS_TRIS, 0, (uint32_t)dp->m_triangles->size()); + gs_draw(GS_TRIS, 0, (uint32_t)dp->m_triangles->Size()); } } // Text Rendering - if (dp->m_textVertices->size() > 0) { - gs_vertbuffer_t* vb = dp->m_textVertices->update(); + if (dp->m_textVertices->Size() > 0) { + gs_vertbuffer_t* vb = dp->m_textVertices->Update(); while (gs_effect_loop(dp->m_textEffect, "Draw")) { gs_effect_set_texture( gs_effect_get_param_by_name(dp->m_textEffect, "image"), dp->m_textTexture); gs_load_vertexbuffer(vb); gs_load_indexbuffer(nullptr); - gs_draw(GS_TRIS, 0, (uint32_t)dp->m_textVertices->size()); + gs_draw(GS_TRIS, 0, (uint32_t)dp->m_textVertices->Size()); } } } @@ -860,97 +874,3 @@ LRESULT CALLBACK OBS::Display::DisplayWndProc(_In_ HWND hwnd, _In_ UINT uMsg, _I } #endif - -OBS::VertexHelper::VertexHelper() { - vec3_set(&pos, 0, 0, 0); - vec3_set(&normal, 0, 0, 0); - vec3_set(&tangent, 0, 0, 0); - color = 0xFFFFFFFF; - vec2_set(&uv0, 0, 0); - vec2_set(&uv1, 0, 0); -} - -OBS::VertexBufferHelper::VertexBufferHelper(size_t initialSize) { - t_vertices.reserve(initialSize); - t_normals.reserve(initialSize); - t_tangents.reserve(initialSize); - t_colors.reserve(initialSize); - t_uv0.reserve(initialSize); - t_uv1.reserve(initialSize); - - vbdata = gs_vbdata_create(); - std::memset(vbdata, 0, sizeof(gs_vb_data)); - vbdata->num = t_vertices.capacity(); - vbdata->points = t_vertices.data(); - vbdata->colors = t_colors.data(); - vbdata->normals = t_normals.data(); - vbdata->tangents = t_tangents.data(); - vbdata->num_tex = 2; - vbuvdata.resize(2); - vbdata->tvarray = vbuvdata.data(); - - vbuvdata[0].width = 2; - vbuvdata[0].array = t_uv0.data(); - vbuvdata[1].width = 2; - vbuvdata[1].array = t_uv1.data(); - - vb = gs_vertexbuffer_create(vbdata, GS_DYNAMIC); -} - -OBS::VertexBufferHelper::~VertexBufferHelper() { - if (vb) { - std::memset(vbdata, 0, sizeof(gs_vb_data)); - gs_vertexbuffer_destroy(vb); - } - if (vbdata) { - gs_vbdata_destroy(vbdata); - } -} - -void OBS::VertexBufferHelper::clear() { - vertices.clear(); -} - -OBS::VertexHelper* OBS::VertexBufferHelper::add() { - vertices.emplace_back(); - return &vertices.back(); -} - -gs_vertbuffer_t* OBS::VertexBufferHelper::update() { - size_t verts = vertices.size(); - t_vertices.resize(verts); - t_normals.resize(verts); - t_tangents.resize(verts); - t_colors.resize(verts); - t_uv0.resize(verts); - t_uv1.resize(verts); - - for (size_t n = 0; n < verts; n++) { - VertexHelper& v = vertices[n]; - vec3_copy(&t_vertices[n], &v.pos); - vec3_copy(&t_normals[n], &v.normal); - vec3_copy(&t_tangents[n], &v.tangent); - t_colors[n] = v.color; - vec2_copy(&t_uv0[n], &v.uv0); - vec2_copy(&t_uv1[n], &v.uv1); - } - - vbdata->num = verts; - vbdata->points = t_vertices.data(); - vbdata->normals = t_normals.data(); - vbdata->tangents = t_tangents.data(); - vbdata->colors = t_colors.data(); - vbdata->tvarray = vbuvdata.data(); - vbdata->num_tex = 2; - vbuvdata[0].width = 2; - vbuvdata[0].array = t_uv0.data(); - vbuvdata[1].width = 2; - vbuvdata[1].array = t_uv1.data(); - - gs_vertexbuffer_flush(vb); - return vb; -} - -size_t OBS::VertexBufferHelper::size() { - return vertices.size(); -} diff --git a/src/nodeobs_display.h b/src/nodeobs_display.h index a63286862..b05b495bd 100644 --- a/src/nodeobs_display.h +++ b/src/nodeobs_display.h @@ -5,6 +5,7 @@ #include #include #include +#include "gs-vertexbuffer.h" #if defined(_WIN32) #ifdef NOWINOFFSETS @@ -21,34 +22,6 @@ EXTERN_C IMAGE_DOS_HEADER __ImageBase; #endif namespace OBS { - struct VertexHelper { - VertexHelper(); - - vec3 pos, normal, tangent; - uint32_t color; - vec2 uv0, uv1; - }; - - class VertexBufferHelper { - private: - gs_vertbuffer_t* vb; - gs_vb_data* vbdata; - std::vector vertices; - std::vector vbuvdata; - std::vector t_vertices, t_normals, t_tangents; - std::vector t_colors; - std::vector t_uv0, t_uv1; - - public: - VertexBufferHelper(size_t initialSize = 65535); - virtual ~VertexBufferHelper(); - - void clear(); - VertexHelper* add(); - gs_vertbuffer_t* update(); - size_t size(); - }; - class Display { #pragma region Constructors & Finalizer private: @@ -105,7 +78,7 @@ namespace OBS { *m_textEffect; gs_texture_t *m_textTexture; - VertexBufferHelper + GS::VertexBuffer *m_lines, *m_triangles, *m_textVertices; diff --git a/src/util-memory.cpp b/src/util-memory.cpp new file mode 100644 index 000000000..cbe702414 --- /dev/null +++ b/src/util-memory.cpp @@ -0,0 +1,43 @@ +/* +* Modern effects for a modern Streamer +* Copyright (C) 2017 Michael Fabian Dirks +* +* 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 2 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, write to the Free Software +* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA +*/ + +#include "util-memory.h" +#include + +void* util::malloc_aligned(size_t align, size_t size) { + // Ensure that we have space for the pointer and the data. + size_t asize = aligned_offset(align, size + sizeof(void*)); + + // Allocate memory and store integer representation of pointer. + void* ptr = malloc(asize); + + // Calculate actual aligned position + intptr_t ptr_off = aligned_offset(align, reinterpret_cast(ptr)+sizeof(void*)); + + // Store actual pointer at ptr_off - sizeof(void*). + *reinterpret_cast(ptr_off - sizeof(void*)) = reinterpret_cast(ptr); + + // Return aligned pointer + return reinterpret_cast(ptr_off); +} + +void util::free_aligned(void* mem) { + void* ptr = reinterpret_cast(*reinterpret_cast(static_cast(mem)-sizeof(void*))); + free(ptr); +} diff --git a/src/util-memory.h b/src/util-memory.h new file mode 100644 index 000000000..f7b15dc44 --- /dev/null +++ b/src/util-memory.h @@ -0,0 +1,98 @@ +/* + * Modern effects for a modern Streamer + * Copyright (C) 2017 Michael Fabian Dirks + * + * 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 2 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, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#pragma once +#include +#include + +namespace util { + inline size_t aligned_offset(size_t align, size_t pos) { + return ((pos / align) + 1) * align; + } + void* malloc_aligned(size_t align, size_t size); + void free_aligned(void* mem); + + template + class AlignmentAllocator { + public: + typedef T value_type; + typedef size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef T * pointer; + typedef const T * const_pointer; + + typedef T & reference; + typedef const T & const_reference; + + public: + inline AlignmentAllocator() throw () {} + + template + inline AlignmentAllocator(const AlignmentAllocator &) throw () {} + + inline ~AlignmentAllocator() throw () {} + + inline pointer adress(reference r) { + return &r; + } + + inline const_pointer adress(const_reference r) const { + return &r; + } + + inline pointer allocate(size_type n) { + return (pointer)malloc_aligned(n*sizeof(value_type), N); + } + + inline void deallocate(pointer p, size_type) { + free_aligned(p); + } + + inline void construct(pointer p, const value_type & wert) { + new (p)value_type(wert); + } + + inline void destroy(pointer p) { + p->~value_type(); + p; + } + + inline size_type max_size() const throw () { + return size_type(-1) / sizeof(value_type); + } + + template + struct rebind { + typedef AlignmentAllocator other; + }; + + bool operator!=(const AlignmentAllocator& other) const { + return !(*this == other); + } + + // Returns true if and only if storage allocated from *this + // can be deallocated from other, and vice versa. + // Always returns true for stateless allocators. + bool operator==(const AlignmentAllocator& other) const { + return true; + } + }; +}; +