1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <OpenGl_Buffer.hxx>
17 #include <OpenGl_GlCore30.hxx>
18 #include <OpenGl_Context.hxx>
19 #include <OpenGl_ShaderManager.hxx>
20 #include <Standard_Assert.hxx>
22 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Buffer, OpenGl_Resource)
24 // =======================================================================
25 // function : sizeOfGlType
27 // =======================================================================
28 size_t OpenGl_Buffer::sizeOfGlType (unsigned int theType)
33 case GL_UNSIGNED_BYTE: return sizeof(Standard_Byte);
35 case GL_UNSIGNED_SHORT: return sizeof(unsigned short);
39 case GL_UNSIGNED_INT: return sizeof(unsigned int);
40 case GL_FLOAT: return sizeof(float);
42 case GL_DOUBLE: return sizeof(double);
48 // =======================================================================
49 // function : FormatTarget
51 // =======================================================================
52 TCollection_AsciiString OpenGl_Buffer::FormatTarget (unsigned int theTarget)
56 case GL_ARRAY_BUFFER: return "GL_ARRAY_BUFFER";
57 case GL_ELEMENT_ARRAY_BUFFER: return "GL_ELEMENT_ARRAY_BUFFER";
58 case GL_PIXEL_UNPACK_BUFFER: return "GL_PIXEL_UNPACK_BUFFER";
59 case GL_PIXEL_PACK_BUFFER: return "GL_PIXEL_PACK_BUFFER";
60 case GL_UNIFORM_BUFFER: return "GL_UNIFORM_BUFFER";
61 case GL_TEXTURE_BUFFER: return "GL_TEXTURE_BUFFER";
62 case GL_COPY_READ_BUFFER: return "GL_COPY_READ_BUFFER";
63 case GL_COPY_WRITE_BUFFER: return "GL_COPY_WRITE_BUFFER";
64 case GL_TRANSFORM_FEEDBACK_BUFFER: return "GL_TRANSFORM_FEEDBACK_BUFFER";
65 #ifdef GL_QUERY_BUFFER
66 case GL_QUERY_BUFFER: return "GL_QUERY_BUFFER";
67 case GL_DRAW_INDIRECT_BUFFER: return "GL_DRAW_INDIRECT_BUFFER";
68 case GL_ATOMIC_COUNTER_BUFFER: return "GL_ATOMIC_COUNTER_BUFFER";
69 case GL_DISPATCH_INDIRECT_BUFFER: return "GL_DISPATCH_INDIRECT_BUFFER";
70 case GL_SHADER_STORAGE_BUFFER: return "GL_SHADER_STORAGE_BUFFER";
73 return OpenGl_Context::FormatGlEnumHex (theTarget);
76 // =======================================================================
77 // function : OpenGl_Buffer
79 // =======================================================================
80 OpenGl_Buffer::OpenGl_Buffer()
83 myBufferId (NO_BUFFER),
91 // =======================================================================
92 // function : ~OpenGl_Buffer
94 // =======================================================================
95 OpenGl_Buffer::~OpenGl_Buffer()
100 // =======================================================================
103 // =======================================================================
104 bool OpenGl_Buffer::Create (const Handle(OpenGl_Context)& theGlCtx)
106 if (myBufferId == NO_BUFFER && theGlCtx->core15fwd != NULL)
108 theGlCtx->core15fwd->glGenBuffers (1, &myBufferId);
110 return myBufferId != NO_BUFFER;
113 // =======================================================================
114 // function : Release
116 // =======================================================================
117 void OpenGl_Buffer::Release (OpenGl_Context* theGlCtx)
119 if (myBufferId == NO_BUFFER)
124 // application can not handle this case by exception - this is bug in code
125 Standard_ASSERT_RETURN (theGlCtx != NULL,
126 "OpenGl_Buffer destroyed without GL context! Possible GPU memory leakage...",);
128 if (theGlCtx->IsValid())
130 theGlCtx->core15fwd->glDeleteBuffers (1, &myBufferId);
133 myBufferId = NO_BUFFER;
136 // =======================================================================
139 // =======================================================================
140 void OpenGl_Buffer::Bind (const Handle(OpenGl_Context)& theGlCtx) const
142 theGlCtx->core15fwd->glBindBuffer (GetTarget(), myBufferId);
145 // =======================================================================
148 // =======================================================================
149 void OpenGl_Buffer::Unbind (const Handle(OpenGl_Context)& theGlCtx) const
151 theGlCtx->core15fwd->glBindBuffer (GetTarget(), NO_BUFFER);
154 // =======================================================================
155 // function : BindBufferBase
157 // =======================================================================
158 void OpenGl_Buffer::BindBufferBase (const Handle(OpenGl_Context)& theGlCtx,
159 unsigned int theIndex)
161 theGlCtx->core30->glBindBufferBase (GetTarget(), theIndex, myBufferId);
164 // =======================================================================
165 // function : UnbindBufferBase
167 // =======================================================================
168 void OpenGl_Buffer::UnbindBufferBase (const Handle(OpenGl_Context)& theGlCtx,
169 unsigned int theIndex)
171 theGlCtx->core30->glBindBufferBase (GetTarget(), theIndex, NO_BUFFER);
174 // =======================================================================
175 // function : BindBufferRange
177 // =======================================================================
178 void OpenGl_Buffer::BindBufferRange (const Handle(OpenGl_Context)& theGlCtx,
179 unsigned int theIndex,
180 const intptr_t theOffset,
181 const size_t theSize)
183 theGlCtx->core30->glBindBufferRange (GetTarget(), theIndex, myBufferId, (GLintptr )theOffset, (GLsizeiptr )theSize);
186 // =======================================================================
189 // =======================================================================
190 bool OpenGl_Buffer::Init (const Handle(OpenGl_Context)& theGlCtx,
191 const unsigned int theComponentsNb,
192 const Standard_Integer theElemsNb,
193 const float* theData)
195 return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_FLOAT);
198 // =======================================================================
201 // =======================================================================
202 bool OpenGl_Buffer::Init (const Handle(OpenGl_Context)& theGlCtx,
203 const unsigned int theComponentsNb,
204 const Standard_Integer theElemsNb,
205 const unsigned int* theData)
207 return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_INT);
210 // =======================================================================
213 // =======================================================================
214 bool OpenGl_Buffer::Init (const Handle(OpenGl_Context)& theGlCtx,
215 const unsigned int theComponentsNb,
216 const Standard_Integer theElemsNb,
217 const unsigned short* theData)
219 return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_SHORT);
222 // =======================================================================
225 // =======================================================================
226 bool OpenGl_Buffer::Init (const Handle(OpenGl_Context)& theGlCtx,
227 const unsigned int theComponentsNb,
228 const Standard_Integer theElemsNb,
229 const Standard_Byte* theData)
231 return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_BYTE);
234 // =======================================================================
237 // =======================================================================
238 bool OpenGl_Buffer::init (const Handle(OpenGl_Context)& theGlCtx,
239 const unsigned int theComponentsNb,
240 const Standard_Integer theElemsNb,
242 const unsigned int theDataType,
243 const Standard_Integer theStride)
245 if (!Create (theGlCtx))
251 myDataType = theDataType;
252 myComponentsNb = theComponentsNb;
253 myElemsNb = theElemsNb;
254 theGlCtx->core15fwd->glBufferData (GetTarget(), GLsizeiptr(myElemsNb) * theStride, theData, GL_STATIC_DRAW);
255 const int anErr = theGlCtx->core15fwd->glGetError();
256 if (anErr != GL_NO_ERROR
257 && anErr != GL_OUT_OF_MEMORY) // pass-through out-of-memory error, but log unexpected errors
259 theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
260 TCollection_AsciiString ("Error: glBufferData (")
261 + FormatTarget (GetTarget()) + ","
262 + OpenGl_Context::FormatSize (GLsizeiptr(myElemsNb) * theStride) + ","
263 + OpenGl_Context::FormatPointer (theData) + ") Id: " + (int )myBufferId
264 + " failed with " + OpenGl_Context::FormatGlError (anErr));
267 return anErr == GL_NO_ERROR;
270 // =======================================================================
271 // function : SubData
273 // =======================================================================
274 bool OpenGl_Buffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
275 const Standard_Integer theElemFrom,
276 const Standard_Integer theElemsNb,
277 const float* theData)
279 return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_FLOAT);
282 // =======================================================================
283 // function : SubData
285 // =======================================================================
286 bool OpenGl_Buffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
287 const Standard_Integer theElemFrom,
288 const Standard_Integer theElemsNb,
289 const unsigned int* theData)
291 return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_INT);
294 // =======================================================================
295 // function : SubData
297 // =======================================================================
298 bool OpenGl_Buffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
299 const Standard_Integer theElemFrom,
300 const Standard_Integer theElemsNb,
301 const unsigned short* theData)
303 return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_SHORT);
306 // =======================================================================
307 // function : SubData
309 // =======================================================================
310 bool OpenGl_Buffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
311 const Standard_Integer theElemFrom,
312 const Standard_Integer theElemsNb,
313 const Standard_Byte* theData)
315 return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_BYTE);
318 // =======================================================================
319 // function : subData
321 // =======================================================================
322 bool OpenGl_Buffer::subData (const Handle(OpenGl_Context)& theGlCtx,
323 const Standard_Integer theElemFrom,
324 const Standard_Integer theElemsNb,
326 const unsigned int theDataType)
328 if (!IsValid() || myDataType != theDataType ||
329 theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb))
335 const size_t aDataSize = sizeOfGlType (theDataType);
336 theGlCtx->core15fwd->glBufferSubData (GetTarget(),
337 GLintptr(theElemFrom) * GLintptr (myComponentsNb) * aDataSize, // offset in bytes
338 GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * aDataSize, // size in bytes
340 const int anErr = theGlCtx->core15fwd->glGetError();
341 if (anErr != GL_NO_ERROR)
343 theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
344 TCollection_AsciiString ("Error: glBufferSubData (")
345 + FormatTarget (GetTarget()) + ","
346 + OpenGl_Context::FormatSize (GLintptr(theElemFrom) * GLintptr (myComponentsNb) * aDataSize) + ","
347 + OpenGl_Context::FormatSize (GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * aDataSize) + ","
348 + OpenGl_Context::FormatPointer (theData) + ") Id: " + (int )myBufferId
349 + " failed with " + OpenGl_Context::FormatGlError (anErr));
352 return anErr == GL_NO_ERROR;
355 // =======================================================================
356 // function : subData
358 // =======================================================================
359 bool OpenGl_Buffer::GetSubData (const Handle(OpenGl_Context)& theGlCtx,
360 const Standard_Integer theElemFrom,
361 const Standard_Integer theElemsNb,
364 return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_FLOAT);
367 // =======================================================================
368 // function : GetSubData
370 // =======================================================================
371 bool OpenGl_Buffer::GetSubData (const Handle(OpenGl_Context)& theGlCtx,
372 const Standard_Integer theElemFrom,
373 const Standard_Integer theElemsNb,
374 unsigned short* theData)
376 return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_SHORT);
379 // =======================================================================
380 // function : GetSubData
382 // =======================================================================
383 bool OpenGl_Buffer::GetSubData (const Handle(OpenGl_Context)& theGlCtx,
384 const Standard_Integer theElemFrom,
385 const Standard_Integer theElemsNb,
386 unsigned int* theData)
388 return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_INT);
391 // =======================================================================
392 // function : GetSubData
394 // =======================================================================
395 bool OpenGl_Buffer::GetSubData (const Handle(OpenGl_Context)& theGlCtx,
396 const Standard_Integer theElemFrom,
397 const Standard_Integer theElemsNb,
398 Standard_Byte* theData)
400 return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_BYTE);
403 // =======================================================================
404 // function : getSubData
406 // =======================================================================
407 bool OpenGl_Buffer::getSubData (const Handle(OpenGl_Context)& theGlCtx,
408 const Standard_Integer theElemFrom,
409 const Standard_Integer theElemsNb,
411 const unsigned int theDataType)
413 if (!IsValid() || myDataType != theDataType
414 || theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb)
415 || !theGlCtx->hasGetBufferData)
421 const size_t aDataSize = sizeOfGlType (theDataType);
422 const GLintptr anOffset = GLintptr (theElemFrom) * GLintptr (myComponentsNb) * aDataSize;
423 const GLsizeiptr aSize = GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * aDataSize;
424 bool isDone = theGlCtx->GetBufferSubData (GetTarget(), anOffset, aSize, theData);
425 isDone = isDone && (theGlCtx->core15fwd->glGetError() == GL_NO_ERROR);
430 // =======================================================================
431 // function : DumpJson
433 // =======================================================================
434 void OpenGl_Buffer::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
436 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
437 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, OpenGl_Resource)
439 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, GetTarget())
440 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myOffset)
442 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myBufferId)
443 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myComponentsNb)
444 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myElemsNb)
445 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDataType)