0032121: Draw Harness, ViewerTest - implement -reset option for vlight command
[occt.git] / src / OpenGl / OpenGl_Buffer.cxx
CommitLineData
1220d98e 1// Created by: Kirill GAVRILOV
2// Copyright (c) 2013-2014 OPEN CASCADE SAS
3//
4// This file is part of Open CASCADE Technology software library.
5//
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.
11//
12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
14
15#include <OpenGl_Buffer.hxx>
16
17#include <OpenGl_GlCore30.hxx>
18#include <OpenGl_Context.hxx>
19#include <OpenGl_ShaderManager.hxx>
20#include <Standard_Assert.hxx>
21
22IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Buffer, OpenGl_Resource)
23
24// =======================================================================
25// function : sizeOfGlType
26// purpose :
27// =======================================================================
28size_t OpenGl_Buffer::sizeOfGlType (unsigned int theType)
29{
30 switch (theType)
31 {
32 case GL_BYTE:
33 case GL_UNSIGNED_BYTE: return sizeof(Standard_Byte);
34 case GL_SHORT:
35 case GL_UNSIGNED_SHORT: return sizeof(unsigned short);
36 #ifdef GL_INT
37 case GL_INT:
38 #endif
39 case GL_UNSIGNED_INT: return sizeof(unsigned int);
40 case GL_FLOAT: return sizeof(float);
41 #ifdef GL_DOUBLE
42 case GL_DOUBLE: return sizeof(double);
43 #endif
44 default: return 0;
45 }
46}
47
48// =======================================================================
49// function : FormatTarget
50// purpose :
51// =======================================================================
52TCollection_AsciiString OpenGl_Buffer::FormatTarget (unsigned int theTarget)
53{
54 switch (theTarget)
55 {
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";
71 #endif
72 }
73 return OpenGl_Context::FormatGlEnumHex (theTarget);
74}
75
76// =======================================================================
77// function : OpenGl_Buffer
78// purpose :
79// =======================================================================
80OpenGl_Buffer::OpenGl_Buffer()
81: OpenGl_Resource(),
82 myOffset (NULL),
83 myBufferId (NO_BUFFER),
84 myComponentsNb (4),
85 myElemsNb (0),
86 myDataType (GL_FLOAT)
87{
88 //
89}
90
91// =======================================================================
92// function : ~OpenGl_Buffer
93// purpose :
94// =======================================================================
95OpenGl_Buffer::~OpenGl_Buffer()
96{
97 Release (NULL);
98}
99
100// =======================================================================
101// function : Create
102// purpose :
103// =======================================================================
104bool OpenGl_Buffer::Create (const Handle(OpenGl_Context)& theGlCtx)
105{
106 if (myBufferId == NO_BUFFER && theGlCtx->core15fwd != NULL)
107 {
108 theGlCtx->core15fwd->glGenBuffers (1, &myBufferId);
109 }
110 return myBufferId != NO_BUFFER;
111}
112
113// =======================================================================
114// function : Release
115// purpose :
116// =======================================================================
117void OpenGl_Buffer::Release (OpenGl_Context* theGlCtx)
118{
119 if (myBufferId == NO_BUFFER)
120 {
121 return;
122 }
123
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...",);
127
128 if (theGlCtx->IsValid())
129 {
130 theGlCtx->core15fwd->glDeleteBuffers (1, &myBufferId);
131 }
132 myOffset = NULL;
133 myBufferId = NO_BUFFER;
134}
135
136// =======================================================================
137// function : Bind
138// purpose :
139// =======================================================================
140void OpenGl_Buffer::Bind (const Handle(OpenGl_Context)& theGlCtx) const
141{
142 theGlCtx->core15fwd->glBindBuffer (GetTarget(), myBufferId);
143}
144
145// =======================================================================
146// function : Unbind
147// purpose :
148// =======================================================================
149void OpenGl_Buffer::Unbind (const Handle(OpenGl_Context)& theGlCtx) const
150{
151 theGlCtx->core15fwd->glBindBuffer (GetTarget(), NO_BUFFER);
152}
153
154// =======================================================================
155// function : BindBufferBase
156// purpose :
157// =======================================================================
158void OpenGl_Buffer::BindBufferBase (const Handle(OpenGl_Context)& theGlCtx,
159 unsigned int theIndex)
160{
161 theGlCtx->core30->glBindBufferBase (GetTarget(), theIndex, myBufferId);
162}
163
164// =======================================================================
165// function : UnbindBufferBase
166// purpose :
167// =======================================================================
168void OpenGl_Buffer::UnbindBufferBase (const Handle(OpenGl_Context)& theGlCtx,
169 unsigned int theIndex)
170{
171 theGlCtx->core30->glBindBufferBase (GetTarget(), theIndex, NO_BUFFER);
172}
173
174// =======================================================================
175// function : BindBufferRange
176// purpose :
177// =======================================================================
178void OpenGl_Buffer::BindBufferRange (const Handle(OpenGl_Context)& theGlCtx,
179 unsigned int theIndex,
180 const intptr_t theOffset,
181 const size_t theSize)
182{
183 theGlCtx->core30->glBindBufferRange (GetTarget(), theIndex, myBufferId, (GLintptr )theOffset, (GLsizeiptr )theSize);
184}
185
186// =======================================================================
187// function : Init
188// purpose :
189// =======================================================================
190bool OpenGl_Buffer::Init (const Handle(OpenGl_Context)& theGlCtx,
191 const unsigned int theComponentsNb,
192 const Standard_Integer theElemsNb,
193 const float* theData)
194{
195 return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_FLOAT);
196}
197
198// =======================================================================
199// function : Init
200// purpose :
201// =======================================================================
202bool OpenGl_Buffer::Init (const Handle(OpenGl_Context)& theGlCtx,
203 const unsigned int theComponentsNb,
204 const Standard_Integer theElemsNb,
205 const unsigned int* theData)
206{
207 return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_INT);
208}
209
210// =======================================================================
211// function : Init
212// purpose :
213// =======================================================================
214bool OpenGl_Buffer::Init (const Handle(OpenGl_Context)& theGlCtx,
215 const unsigned int theComponentsNb,
216 const Standard_Integer theElemsNb,
217 const unsigned short* theData)
218{
219 return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_SHORT);
220}
221
222// =======================================================================
223// function : Init
224// purpose :
225// =======================================================================
226bool OpenGl_Buffer::Init (const Handle(OpenGl_Context)& theGlCtx,
227 const unsigned int theComponentsNb,
228 const Standard_Integer theElemsNb,
229 const Standard_Byte* theData)
230{
231 return init (theGlCtx, theComponentsNb, theElemsNb, theData, GL_UNSIGNED_BYTE);
232}
233
234// =======================================================================
235// function : init
236// purpose :
237// =======================================================================
238bool OpenGl_Buffer::init (const Handle(OpenGl_Context)& theGlCtx,
239 const unsigned int theComponentsNb,
240 const Standard_Integer theElemsNb,
241 const void* theData,
242 const unsigned int theDataType,
243 const Standard_Integer theStride)
244{
245 if (!Create (theGlCtx))
246 {
247 return false;
248 }
249
250 Bind (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
258 {
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));
265 }
266 Unbind (theGlCtx);
267 return anErr == GL_NO_ERROR;
268}
269
270// =======================================================================
271// function : SubData
272// purpose :
273// =======================================================================
274bool OpenGl_Buffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
275 const Standard_Integer theElemFrom,
276 const Standard_Integer theElemsNb,
277 const float* theData)
278{
279 return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_FLOAT);
280}
281
282// =======================================================================
283// function : SubData
284// purpose :
285// =======================================================================
286bool OpenGl_Buffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
287 const Standard_Integer theElemFrom,
288 const Standard_Integer theElemsNb,
289 const unsigned int* theData)
290{
291 return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_INT);
292}
293
294// =======================================================================
295// function : SubData
296// purpose :
297// =======================================================================
298bool OpenGl_Buffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
299 const Standard_Integer theElemFrom,
300 const Standard_Integer theElemsNb,
301 const unsigned short* theData)
302{
303 return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_SHORT);
304}
305
306// =======================================================================
307// function : SubData
308// purpose :
309// =======================================================================
310bool OpenGl_Buffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
311 const Standard_Integer theElemFrom,
312 const Standard_Integer theElemsNb,
313 const Standard_Byte* theData)
314{
315 return subData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_BYTE);
316}
317
318// =======================================================================
319// function : subData
320// purpose :
321// =======================================================================
322bool OpenGl_Buffer::subData (const Handle(OpenGl_Context)& theGlCtx,
323 const Standard_Integer theElemFrom,
324 const Standard_Integer theElemsNb,
325 const void* theData,
326 const unsigned int theDataType)
327{
328 if (!IsValid() || myDataType != theDataType ||
329 theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb))
330 {
331 return false;
332 }
333
334 Bind (theGlCtx);
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
339 theData);
340 const int anErr = theGlCtx->core15fwd->glGetError();
341 if (anErr != GL_NO_ERROR)
342 {
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));
350 }
351 Unbind (theGlCtx);
352 return anErr == GL_NO_ERROR;
353}
354
355// =======================================================================
356// function : subData
357// purpose :
358// =======================================================================
359bool OpenGl_Buffer::GetSubData (const Handle(OpenGl_Context)& theGlCtx,
360 const Standard_Integer theElemFrom,
361 const Standard_Integer theElemsNb,
362 float* theData)
363{
364 return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_FLOAT);
365}
366
367// =======================================================================
368// function : GetSubData
369// purpose :
370// =======================================================================
371bool OpenGl_Buffer::GetSubData (const Handle(OpenGl_Context)& theGlCtx,
372 const Standard_Integer theElemFrom,
373 const Standard_Integer theElemsNb,
374 unsigned short* theData)
375{
376 return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_SHORT);
377}
378
379// =======================================================================
380// function : GetSubData
381// purpose :
382// =======================================================================
383bool OpenGl_Buffer::GetSubData (const Handle(OpenGl_Context)& theGlCtx,
384 const Standard_Integer theElemFrom,
385 const Standard_Integer theElemsNb,
386 unsigned int* theData)
387{
388 return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_INT);
389}
390
391// =======================================================================
392// function : GetSubData
393// purpose :
394// =======================================================================
395bool OpenGl_Buffer::GetSubData (const Handle(OpenGl_Context)& theGlCtx,
396 const Standard_Integer theElemFrom,
397 const Standard_Integer theElemsNb,
398 Standard_Byte* theData)
399{
400 return getSubData (theGlCtx, theElemFrom, theElemsNb, theData, GL_UNSIGNED_BYTE);
401}
402
403// =======================================================================
404// function : getSubData
405// purpose :
406// =======================================================================
407bool OpenGl_Buffer::getSubData (const Handle(OpenGl_Context)& theGlCtx,
408 const Standard_Integer theElemFrom,
409 const Standard_Integer theElemsNb,
410 void* theData,
411 const unsigned int theDataType)
412{
413 if (!IsValid() || myDataType != theDataType
414 || theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb)
415 || !theGlCtx->hasGetBufferData)
416 {
417 return false;
418 }
419
420 Bind (theGlCtx);
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);
426 Unbind (theGlCtx);
427 return isDone;
428}
429
430// =======================================================================
431// function : DumpJson
432// purpose :
433// =======================================================================
434void OpenGl_Buffer::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
435{
436 OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
437 OCCT_DUMP_BASE_CLASS (theOStream, theDepth, OpenGl_Resource)
438
439 OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, GetTarget())
440 OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myOffset)
441
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)
446}