1 /* === S Y N F I G ========================================================= */ 2 /*! \file synfig/rendering/opengl/internal/buffers.h 3 ** \brief Buffers Header 4 ** 5 ** $Id$ 6 ** 7 ** \legal 8 ** ......... ... 2015 Ivan Mahonin 9 ** 10 ** This package is free software; you can redistribute it and/or 11 ** modify it under the terms of the GNU General Public License as 12 ** published by the Free Software Foundation; either version 2 of 13 ** the License, or (at your option) any later version. 14 ** 15 ** This package is distributed in the hope that it will be useful, 16 ** but WITHOUT ANY WARRANTY; without even the implied warranty of 17 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 18 ** General Public License for more details. 19 ** \endlegal 20 */ 21 /* ========================================================================= */ 22 23 /* === S T A R T =========================================================== */ 24 25 #ifndef __SYNFIG_RENDERING_GL_BUFFERS_H 26 #define __SYNFIG_RENDERING_GL_BUFFERS_H 27 28 /* === H E A D E R S ======================================================= */ 29 30 #include <list> 31 #include <vector> 32 33 #include "context.h" 34 35 /* === M A C R O S ========================================================= */ 36 37 /* === T Y P E D E F S ===================================================== */ 38 39 /* === C L A S S E S & S T R U C T S ======================================= */ 40 41 namespace synfig 42 { 43 namespace rendering 44 { 45 namespace gl 46 { 47 48 class Buffers 49 { 50 public: 51 class Buffer { 52 public: 53 class Chunk; 54 55 Context &context; 56 GLenum target; 57 GLenum usage; 58 GLuint id; 59 int size; 60 Chunk *first, *last; 61 62 class Chunk { 63 public: 64 const int offset; 65 const int size; 66 Buffer &buffer; 67 Chunk *prev, *next; 68 int locks; 69 Chunk(Buffer & buffer,Chunk * prev,int offset,int size)70 Chunk(Buffer &buffer, Chunk *prev, int offset, int size): 71 offset(offset), size(size), buffer(buffer), prev(prev), next(prev ? prev->next : buffer.first), locks() 72 { 73 (prev ? prev->next : buffer.first) = this; 74 (next ? next->prev : buffer.last) = this; 75 } 76 ~Chunk()77 ~Chunk() 78 { 79 (prev ? prev->next : buffer.first) = next; 80 (next ? next->prev : buffer.last) = prev; 81 } 82 }; 83 84 Buffer(Context &context, GLenum target, GLenum usage, int size); 85 ~Buffer(); 86 Chunk* alloc(int size); is_free()87 bool is_free() const { return !first; } 88 }; 89 90 class BufferLock { 91 private: 92 friend class Buffers; 93 Buffer::Chunk *chunk; 94 set(Buffer::Chunk * chunk)95 void set(Buffer::Chunk *chunk) { 96 if (this->chunk) { 97 --this->chunk->locks; 98 if (!this->chunk->locks) 99 delete this->chunk; 100 } 101 this->chunk = chunk; 102 if (this->chunk) ++this->chunk->locks; 103 } 104 BufferLock(Buffer::Chunk * chunk)105 BufferLock(Buffer::Chunk *chunk): chunk() 106 { set(chunk); } 107 public: BufferLock()108 BufferLock(): chunk() 109 { } BufferLock(const BufferLock & other)110 BufferLock(const BufferLock &other): chunk() 111 { *this = other; } ~BufferLock()112 ~BufferLock() 113 { set(NULL); } 114 BufferLock& operator = (const BufferLock &other) 115 { set(other.chunk); return *this; } get_id()116 GLuint get_id() const 117 { return chunk ? chunk->buffer.id : 0; } get_offset()118 int get_offset() const 119 { return chunk ? chunk->offset : 0; } get_size()120 int get_size() const 121 { return chunk ? chunk->size : 0; } get_pointer()122 const void* get_pointer() const 123 { return (const void*)(ptrdiff_t)get_offset(); } 124 }; 125 126 class VertexArray { 127 public: 128 GLuint id; 129 int locks; VertexArray()130 VertexArray(): id(), locks() { } 131 }; 132 133 class VertexArrayLock { 134 private: 135 friend class Buffers; 136 VertexArray *vertex_array; 137 set(VertexArray * vertex_buffer)138 void set(VertexArray *vertex_buffer) { 139 if (this->vertex_array) --this->vertex_array->locks; 140 this->vertex_array = vertex_buffer; 141 if (this->vertex_array) ++this->vertex_array->locks; 142 } 143 VertexArrayLock(VertexArray * vertex_buffer)144 VertexArrayLock(VertexArray *vertex_buffer): vertex_array() 145 { set(vertex_buffer); } 146 public: VertexArrayLock()147 VertexArrayLock(): vertex_array() 148 { } VertexArrayLock(const VertexArrayLock & other)149 VertexArrayLock(const VertexArrayLock &other): vertex_array() 150 { *this = other; } ~VertexArrayLock()151 ~VertexArrayLock() 152 { set(NULL); } 153 VertexArrayLock& operator = (const VertexArrayLock &other) 154 { set(other.vertex_array); return *this; } get_id()155 GLuint get_id() const 156 { return vertex_array ? vertex_array->id : 0; } 157 }; 158 159 public: 160 Context &context; 161 162 private: 163 Buffer array_buffer; 164 Buffer element_array_buffer; 165 std::list<VertexArray> vertex_arrays; 166 167 BufferLock default_quad_buffer; 168 169 public: 170 Buffers(Context &context); 171 ~Buffers(); 172 173 private: 174 BufferLock get_buffer(Buffer &buffer, const void *data, int size); 175 176 template<typename T> 177 BufferLock get_buffer(Buffer &buffer, const std::vector<T> &data, int offset = 0, int count = 0) 178 { 179 assert(offset >= 0); 180 assert(count >= 0); 181 if (!count) count = (int)data.size() - offset; 182 assert(offset + count <= (int)data.size()); 183 assert(count >= 0); 184 if (!count) return BufferLock(); 185 return get_buffer(buffer, &data.front(), count*sizeof(data.front())); 186 } 187 188 public: 189 // returns buffer with four synfig::Vector: (-1, -1), (-1, 1), (1, -1), (1, 1) get_default_quad_buffer()190 BufferLock get_default_quad_buffer() 191 { return default_quad_buffer; } 192 get_array_buffer(const void * data,int size)193 BufferLock get_array_buffer(const void *data, int size) 194 { return get_buffer(array_buffer, data, size); } 195 196 template<typename T> 197 BufferLock get_array_buffer(const std::vector<T> &data, int offset = 0, int count = 0) 198 { return get_buffer(array_buffer, data, offset, count); } 199 200 template<typename T, int size> 201 BufferLock get_array_buffer(const T (&data)[size], int offset = 0, int count = 0) 202 { return get_buffer(array_buffer, &data[offset], count ? sizeof(T)*count : sizeof(data)); } 203 get_element_array_buffer(const void * data,int size)204 BufferLock get_element_array_buffer(const void *data, int size) 205 { return get_buffer(element_array_buffer, data, size); } 206 207 template<typename T> 208 BufferLock get_element_array_buffer(const std::vector<T> &data, int offset = 0, int count = 0) 209 { return get_buffer(element_array_buffer, data, offset, count); } 210 211 template<typename T, int size> 212 BufferLock get_element_array_buffer(const T (&data)[size], int offset = 0, int count = 0) 213 { return get_buffer(element_array_buffer, &data[offset], count ? sizeof(T)*count : sizeof(data)); } 214 215 VertexArrayLock get_vertex_array(); 216 }; 217 218 }; /* end namespace gl */ 219 }; /* end namespace rendering */ 220 }; /* end namespace synfig */ 221 222 /* -- E N D ----------------------------------------------------------------- */ 223 224 #endif 225