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