1 /* === S Y N F I G ========================================================= */
2 /*!	\file synfig/rendering/opengl/internal/buffers.cpp
3 **	\brief Buffers
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 /* === H E A D E R S ======================================================= */
24 
25 #ifdef USING_PCH
26 #	include "pch.h"
27 #else
28 #ifdef HAVE_CONFIG_H
29 #	include <config.h>
30 #endif
31 
32 #ifndef _WIN32
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <signal.h>
36 #endif
37 
38 #include <cmath>
39 #include <cstring>
40 
41 #include <synfig/general.h>
42 #include <synfig/localization.h>
43 #include <synfig/vector.h>
44 
45 #include "buffers.h"
46 
47 #endif
48 
49 using namespace synfig;
50 using namespace rendering;
51 
52 /* === M A C R O S ========================================================= */
53 
54 /* === G L O B A L S ======================================================= */
55 
56 /* === P R O C E D U R E S ================================================= */
57 
58 /* === M E T H O D S ======================================================= */
59 
Buffer(Context & context,GLenum target,GLenum usage,int size)60 gl::Buffers::Buffer::Buffer(Context &context, GLenum target, GLenum usage, int size):
61 	context(context), target(target), usage(usage), id(), size(size), first(), last()
62 {
63 	Context::Lock lock(context);
64 	glGenBuffers(1, &id);
65 	glBindBuffer(target, id);
66 	glBufferData(target, size, NULL, usage);
67 	glBindBuffer(target, 0);
68 }
69 
~Buffer()70 gl::Buffers::Buffer::~Buffer() {
71 	Context::Lock lock(context);
72 	assert(is_free());
73 	glBindBuffer(target, 0);
74 	glDeleteBuffers(1, &id);
75 }
76 
77 
78 gl::Buffers::Buffer::Chunk*
alloc(int size)79 gl::Buffers::Buffer::alloc(int size)
80 {
81 	// find empty chunk
82 	Chunk *curr = NULL;
83 	Chunk *next = first;
84 	int offset = 0;
85 	while(true) {
86 		offset = curr ? curr->offset + curr->size : 0;
87 		int free_size = (next ? next->offset : this->size) - offset;
88 		if (size <= free_size)
89 			return new Chunk(*this, curr, offset, size);
90 		if (!next) break;
91 		curr = next;
92 		next = next->next;
93 	};
94 
95 	{ // resize
96 		Context::Lock lock(context);
97 		int new_size = (int)ceil(1.5*(offset + size));
98 		std::vector<char> data(new_size);
99 		glBindBuffer(target, id);
100 		glGetBufferSubData(target, 0, this->size, &data.front());
101 		this->size = new_size;
102 		glBufferData(target, this->size, &data.front(), usage);
103 		glBindBuffer(target, 0);
104 	}
105 
106 	return new Chunk(*this, last, offset, size);
107 }
108 
109 
110 
Buffers(Context & context)111 gl::Buffers::Buffers(Context &context):
112 	context(context),
113 	array_buffer(context, GL_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 1024*1024),
114 	element_array_buffer(context, GL_ELEMENT_ARRAY_BUFFER, GL_DYNAMIC_DRAW, 1024*1024)
115 {
116 	Context::Lock lock(context);
117 
118 	Vector default_quad_buffer_data[] = {
119 		Vector(-1.0, -1.0),
120 		Vector(-1.0,  1.0),
121 		Vector( 1.0, -1.0),
122 		Vector( 1.0,  1.0) };
123 	default_quad_buffer = get_array_buffer(default_quad_buffer_data);
124 }
125 
~Buffers()126 gl::Buffers::~Buffers()
127 {
128 	Context::Lock lock(context);
129 
130 	default_quad_buffer = BufferLock();
131 
132 	// delete vertex arrays
133 	for(std::list<VertexArray>::iterator i = vertex_arrays.begin(); i != vertex_arrays.end(); ++i)
134 	{
135 		assert(!i->locks);
136 		glDeleteVertexArrays(1, &i->id);
137 	}
138 }
139 
140 gl::Buffers::BufferLock
get_buffer(Buffer & buffer,const void * data,int size)141 gl::Buffers::get_buffer(Buffer &buffer, const void *data, int size)
142 {
143 	if (!data) return BufferLock();
144 	assert(size >= 0);
145 	if (!size) return BufferLock();
146 
147 	Context::Lock lock(context);
148 	Buffer::Chunk *chunk = buffer.alloc(size);
149 	glBindBuffer(buffer.target, buffer.id);
150 	glBufferSubData(buffer.target, chunk->offset, size, data);
151 	glBindBuffer(buffer.target, 0);
152 	return BufferLock(chunk);
153 }
154 
155 gl::Buffers::VertexArrayLock
get_vertex_array()156 gl::Buffers::get_vertex_array()
157 {
158 	Context::Lock lock(context);
159 	for(std::list<VertexArray>::iterator i = vertex_arrays.begin(); i != vertex_arrays.end(); ++i)
160 		if (!i->locks)
161 			return VertexArrayLock(&*i);
162 	vertex_arrays.push_back(VertexArray());
163 	glGenVertexArrays(1, &vertex_arrays.back().id);
164 	return VertexArrayLock(&vertex_arrays.back());
165 }
166 
167 /* === E N T R Y P O I N T ================================================= */
168