framework2

Форк
0
274 строки · 6.3 Кб
1
#include "ofBufferObject.h"
2
#include "ofAppRunner.h"
3
#include "ofPixels.h"
4
#include "ofGLUtils.h"
5

6

7
ofBufferObject::Data::Data()
8
:id(0)
9
,size(0)
10
,lastTarget(GL_ARRAY_BUFFER)
11

12
#ifdef GLEW_VERSION_4_5
13
,isDSA(ofIsGLProgrammableRenderer() && GLEW_ARB_direct_state_access)
14
#else
15
,isDSA(false)
16
#endif
17

18
{
19
	
20
	// tig: glGenBuffers does not actually create a buffer, it just 
21
	//      returns the next available name, and only a subsequent 
22
	//      call to bind() will actualy initialize the buffer in
23
	//      memory. 
24
	//
25
	//      This is why, for direct state access, we need to call
26
	//      glCreateBuffers(), so that the buffer is initialized
27
	//      when we pin data to it using setData()
28
	// 
29
	//      see also: https://www.opengl.org/registry/specs/ARB/direct_state_access.txt
30
#ifdef GLEW_VERSION_4_5
31
	if(isDSA) {
32
		// the above condition is only true if GLEW can provide us
33
		// with direct state access methods. we use this to test
34
		// whether the driver is OpenGL 4.5 ready.
35
		glCreateBuffers(1,&id);
36
		return;
37
	}
38
#endif
39

40
	glGenBuffers(1,&id);
41
}
42

43
ofBufferObject::Data::~Data(){
44
	glDeleteBuffers(1,&id);
45
}
46

47
ofBufferObject::ofBufferObject()
48
{
49

50
}
51

52
void ofBufferObject::allocate(){
53
	data = std::make_shared<Data>();
54
}
55

56
void ofBufferObject::allocate(GLsizeiptr bytes, GLenum usage){
57
	allocate();
58
	setData(bytes,0,usage);
59
}
60

61
void ofBufferObject::allocate(GLsizeiptr bytes, const void * data, GLenum usage){
62
	allocate();
63
	setData(bytes,data,usage);
64
}
65

66
bool ofBufferObject::isAllocated() const{
67
	return data.get() != nullptr;
68
}
69

70
void ofBufferObject::bind(GLenum target) const{
71
	if(data){
72
		glBindBuffer(target, data->id);
73
		data->lastTarget = target;
74
		data->isBound = true;
75
	}
76
}
77

78
void ofBufferObject::unbind(GLenum target) const{
79
	glBindBuffer(target, 0);
80
	if(data){
81
		data->isBound = false;
82
	}
83
}
84

85
#if !defined(TARGET_OPENGLES) || defined(TARGET_EMSCRIPTEN)
86
void ofBufferObject::bindBase(GLenum target,GLuint index) const{
87
	if(data){
88
		glBindBufferBase(target,index,data->id);
89
		data->lastTarget = target;
90
		data->isBound = true;
91
	}
92
}
93

94
void ofBufferObject::unbindBase(GLenum target,GLuint index) const{
95
	glBindBufferBase(target,index,0);
96
	if(data){
97
		data->isBound = false;
98
	}
99
}
100

101
void ofBufferObject::bindRange(GLenum target,GLuint index, GLintptr offset, GLsizeiptr size) const{
102
	if(data){
103
		glBindBufferRange(target,index,data->id,offset,size);
104
		data->lastTarget = target;
105
		data->isBound = true;
106
	}
107
}
108

109
void ofBufferObject::unbindRange(GLenum target,GLuint index) const{
110
	glBindBufferBase(target,index,0);
111
}
112
#endif
113

114
GLuint ofBufferObject::getId() const{
115
	if(data) return data->id;
116
	else return 0;
117
}
118

119
void ofBufferObject::setData(GLsizeiptr bytes, const void * data, GLenum usage){
120
	if(!this->data) return;
121
	this->data->size = bytes;
122

123
#ifdef GLEW_VERSION_4_5
124
	if(this->data->isDSA) {
125
		glNamedBufferData(this->data->id, bytes, data, usage);
126
		return;
127
	}
128
#endif
129

130
	/// --------| invariant: direct state access is not available
131
	bind(this->data->lastTarget);
132
	glBufferData(this->data->lastTarget, bytes, data, usage);
133
	unbind(this->data->lastTarget);
134
}
135

136
void ofBufferObject::updateData(GLintptr offset, GLsizeiptr bytes, const void * data){
137
	if(!this->data) return;
138

139
#ifdef GLEW_VERSION_4_5
140
	if(this->data->isDSA){
141
		glNamedBufferSubData(this->data->id,offset,bytes,data);
142
		return;
143
	}
144
#endif
145

146
	/// --------| invariant: direct state access is not available
147

148
	bind(this->data->lastTarget);
149
	glBufferSubData(this->data->lastTarget,offset,bytes,data);
150
	unbind(this->data->lastTarget);
151
}
152

153
void ofBufferObject::updateData(GLsizeiptr bytes, const void * data){
154
    updateData(0,bytes,data);
155
}
156

157
#ifndef TARGET_OPENGLES
158
void * ofBufferObject::map(GLenum access){
159
	if(!this->data) return nullptr;
160

161
#ifdef GLEW_VERSION_4_5
162
	if(this->data->isDSA) {
163
		return glMapNamedBuffer(data->id,access);
164
	}
165
#endif
166

167
	/// --------| invariant: direct state access is not available
168
	if(!data->isBound){
169
		// if the buffer wasn't already bound and the operation
170
		// is one of unpack/pack buffer alternate between the 2
171
		// since the tipical use is to pack to copy to the buffer
172
		// then unpack to copy from it.
173
		// for more advanced usages one can just bind the buffer
174
		// before mapping
175
		if(data->lastTarget==GL_PIXEL_PACK_BUFFER){
176
			data->lastTarget = GL_PIXEL_UNPACK_BUFFER;
177
		}else if(data->lastTarget == GL_PIXEL_UNPACK_BUFFER){
178
			data->lastTarget = GL_PIXEL_PACK_BUFFER;
179
		}
180
		glBindBuffer(data->lastTarget, data->id);
181
	}
182

183
	auto ret = glMapBuffer(data->lastTarget,access);
184

185
	if(!data->isBound){
186
		unbind(data->lastTarget);
187
	}
188

189
	return ret;
190
}
191

192
void ofBufferObject::unmap(){
193
	if(!this->data) return;
194

195
#ifdef GLEW_VERSION_4_5
196
	if(this->data->isDSA) {
197
		glUnmapNamedBuffer(data->id);
198
		return;
199
	}
200
#endif
201

202
	/// --------| invariant: direct state access is not available
203
	if(!data->isBound){
204
		glBindBuffer(data->lastTarget, data->id);
205
	}
206

207
	glUnmapBuffer(data->lastTarget);
208

209
	if(!data->isBound){
210
		unbind(data->lastTarget);
211
	}
212
}
213

214
void * ofBufferObject::mapRange(GLintptr offset, GLsizeiptr length, GLenum access){
215
	if(!this->data) return nullptr;
216

217
#ifdef GLEW_VERSION_4_5
218
	if(this->data->isDSA) {
219
		return glMapNamedBufferRange(data->id,offset,length,access);
220
	}
221
#endif
222

223
	/// --------| invariant: direct state access is not available
224

225
	bind(data->lastTarget);
226
	return glMapBufferRange(data->lastTarget,offset,length,access);
227
}
228

229
void ofBufferObject::unmapRange(){
230
	unmap();
231
}
232

233
void ofBufferObject::copyTo(ofBufferObject & dstBuffer) const{
234
#ifdef GLEW_VERSION_4_5
235
	if(this->data->isDSA) {
236
		glCopyNamedBufferSubData(data->id,dstBuffer.getId(),0,0,size());
237
		return;
238
	}
239
#endif
240

241
	bind(GL_COPY_READ_BUFFER);
242
	dstBuffer.bind(GL_COPY_WRITE_BUFFER);
243
	glCopyBufferSubData(GL_COPY_READ_BUFFER,GL_COPY_WRITE_BUFFER,0,0,size());
244
	unbind(GL_COPY_READ_BUFFER);
245
	dstBuffer.unbind(GL_COPY_WRITE_BUFFER);
246
}
247

248
void ofBufferObject::copyTo(ofBufferObject & dstBuffer, int readOffset, int writeOffset, size_t size) const{
249
#ifdef GLEW_VERSION_4_5
250
	if(this->data->isDSA) {
251
		glCopyNamedBufferSubData(data->id,dstBuffer.getId(),readOffset,writeOffset,size);
252
		return;
253
	}
254
#endif
255

256
	bind(GL_COPY_READ_BUFFER);
257
	dstBuffer.bind(GL_COPY_WRITE_BUFFER);
258
	glCopyBufferSubData(GL_COPY_READ_BUFFER,GL_COPY_WRITE_BUFFER,readOffset,writeOffset,size);
259
	unbind(GL_COPY_READ_BUFFER);
260
	dstBuffer.unbind(GL_COPY_WRITE_BUFFER);
261
}
262

263

264

265
void ofBufferObject::invalidate(){
266
    glInvalidateBufferData(data->id);
267
}
268

269
#endif
270

271
GLsizeiptr ofBufferObject::size() const{
272
	if (data) return data->size;
273
	else return 0;
274
}
275

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.