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