0031279: Visualization, TKOpenGl - environment background is misplaced within Ray...
[occt.git] / src / OpenGl / OpenGl_VertexBuffer.cxx
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_VertexBuffer.hxx>
16
17 #include <OpenGl_Context.hxx>
18 #include <OpenGl_ShaderManager.hxx>
19 #include <Standard_Assert.hxx>
20
21 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_VertexBuffer,OpenGl_Resource)
22
23 // =======================================================================
24 // function : OpenGl_VertexBuffer
25 // purpose  :
26 // =======================================================================
27 OpenGl_VertexBuffer::OpenGl_VertexBuffer()
28 : OpenGl_Resource(),
29   myOffset (NULL),
30   myBufferId (NO_BUFFER),
31   myComponentsNb (4),
32   myElemsNb (0),
33   myDataType (GL_FLOAT)
34 {
35   //
36 }
37
38 // =======================================================================
39 // function : ~OpenGl_VertexBuffer
40 // purpose  :
41 // =======================================================================
42 OpenGl_VertexBuffer::~OpenGl_VertexBuffer()
43 {
44   Release (NULL);
45 }
46
47 // =======================================================================
48 // function : GetTarget
49 // purpose  :
50 // =======================================================================
51 GLenum OpenGl_VertexBuffer::GetTarget() const
52 {
53   return GL_ARRAY_BUFFER;
54 }
55
56 // =======================================================================
57 // function : Create
58 // purpose  :
59 // =======================================================================
60 bool OpenGl_VertexBuffer::Create (const Handle(OpenGl_Context)& theGlCtx)
61 {
62   if (myBufferId == NO_BUFFER && theGlCtx->core15fwd != NULL)
63   {
64     theGlCtx->core15fwd->glGenBuffers (1, &myBufferId);
65   }
66   return myBufferId != NO_BUFFER;
67 }
68
69 // =======================================================================
70 // function : Release
71 // purpose  :
72 // =======================================================================
73 void OpenGl_VertexBuffer::Release (OpenGl_Context* theGlCtx)
74 {
75   if (myBufferId == NO_BUFFER)
76   {
77     return;
78   }
79
80   // application can not handle this case by exception - this is bug in code
81   Standard_ASSERT_RETURN (theGlCtx != NULL,
82     "OpenGl_VertexBuffer destroyed without GL context! Possible GPU memory leakage...",);
83
84   if (theGlCtx->IsValid())
85   {
86     theGlCtx->core15fwd->glDeleteBuffers (1, &myBufferId);
87   }
88   myOffset   = NULL;
89   myBufferId = NO_BUFFER;
90 }
91
92 // =======================================================================
93 // function : Bind
94 // purpose  :
95 // =======================================================================
96 void OpenGl_VertexBuffer::Bind (const Handle(OpenGl_Context)& theGlCtx) const
97 {
98   theGlCtx->core15fwd->glBindBuffer (GetTarget(), myBufferId);
99 }
100
101 // =======================================================================
102 // function : Unbind
103 // purpose  :
104 // =======================================================================
105 void OpenGl_VertexBuffer::Unbind (const Handle(OpenGl_Context)& theGlCtx) const
106 {
107   theGlCtx->core15fwd->glBindBuffer (GetTarget(), NO_BUFFER);
108 }
109
110 // =======================================================================
111 // function : init
112 // purpose  :
113 // =======================================================================
114 bool OpenGl_VertexBuffer::init (const Handle(OpenGl_Context)& theGlCtx,
115                                 const GLuint   theComponentsNb,
116                                 const GLsizei  theElemsNb,
117                                 const void*    theData,
118                                 const GLenum   theDataType,
119                                 const GLsizei  theStride)
120 {
121   if (!Create (theGlCtx))
122   {
123     return false;
124   }
125
126   Bind (theGlCtx);
127   myDataType     = theDataType;
128   myComponentsNb = theComponentsNb;
129   myElemsNb      = theElemsNb;
130   theGlCtx->core15fwd->glBufferData (GetTarget(), GLsizeiptr(myElemsNb) * theStride, theData, GL_STATIC_DRAW);
131   bool isDone = (glGetError() == GL_NO_ERROR); // GL_OUT_OF_MEMORY
132   Unbind (theGlCtx);
133   return isDone;
134 }
135
136 // =======================================================================
137 // function : subData
138 // purpose  :
139 // =======================================================================
140 bool OpenGl_VertexBuffer::subData (const Handle(OpenGl_Context)& theGlCtx,
141                                    const GLsizei  theElemFrom,
142                                    const GLsizei  theElemsNb,
143                                    const void*    theData,
144                                    const GLenum   theDataType)
145 {
146   if (!IsValid() || myDataType != theDataType ||
147       theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb))
148   {
149     return false;
150   }
151
152   Bind (theGlCtx);
153   const size_t aDataSize = sizeOfGlType (theDataType);
154   theGlCtx->core15fwd->glBufferSubData (GetTarget(),
155                                         GLintptr(theElemFrom)  * GLintptr  (myComponentsNb) * aDataSize, // offset in bytes
156                                         GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * aDataSize, // size   in bytes
157                                         theData);
158   bool isDone = (glGetError() == GL_NO_ERROR); // some dummy error
159   Unbind (theGlCtx);
160   return isDone;
161 }
162
163 // =======================================================================
164 // function : getSubData
165 // purpose  :
166 // =======================================================================
167 bool OpenGl_VertexBuffer::getSubData (const Handle(OpenGl_Context)& theGlCtx,
168                                       const GLsizei theElemFrom,
169                                       const GLsizei theElemsNb,
170                                       void*         theData,
171                                       const GLenum  theDataType)
172 {
173   if (!IsValid() || myDataType != theDataType
174    || theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb)
175    || !theGlCtx->hasGetBufferData)
176   {
177     return false;
178   }
179
180   Bind (theGlCtx);
181   const size_t  aDataSize = sizeOfGlType (theDataType);
182   const GLintptr anOffset = GLintptr (theElemFrom) * GLintptr  (myComponentsNb) * aDataSize;
183   const GLsizeiptr  aSize = GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * aDataSize;
184   bool isDone = theGlCtx->GetBufferSubData (GetTarget(), anOffset, aSize, theData);
185   isDone = isDone && (glGetError() == GL_NO_ERROR);
186   Unbind (theGlCtx);
187   return isDone;
188 }
189
190 // =======================================================================
191 // function : BindVertexAttrib
192 // purpose  :
193 // =======================================================================
194 void OpenGl_VertexBuffer::BindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
195                                             const GLuint                  theAttribLoc) const
196 {
197   if (!IsValid() || theAttribLoc == GLuint (-1))
198   {
199     return;
200   }
201   Bind (theGlCtx);
202   theGlCtx->core20fwd->glEnableVertexAttribArray (theAttribLoc);
203   theGlCtx->core20fwd->glVertexAttribPointer (theAttribLoc, GLint (myComponentsNb), myDataType, GL_FALSE, 0, myOffset);
204 }
205
206 // =======================================================================
207 // function : UnbindVertexAttrib
208 // purpose  :
209 // =======================================================================
210 void OpenGl_VertexBuffer::UnbindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
211                                               const GLuint                  theAttribLoc) const
212 {
213   if (!IsValid() || theAttribLoc == GLuint (-1))
214   {
215     return;
216   }
217   theGlCtx->core20fwd->glDisableVertexAttribArray (theAttribLoc);
218   Unbind (theGlCtx);
219 }
220
221 // =======================================================================
222 // function : BindAllAttributes
223 // purpose  :
224 // =======================================================================
225 void OpenGl_VertexBuffer::BindAllAttributes (const Handle(OpenGl_Context)& ) const
226 {
227   //
228 }
229
230 // =======================================================================
231 // function : BindPositionAttribute
232 // purpose  :
233 // =======================================================================
234 void OpenGl_VertexBuffer::BindPositionAttribute (const Handle(OpenGl_Context)& ) const
235 {
236   //
237 }
238
239 // =======================================================================
240 // function : UnbindAllAttributes
241 // purpose  :
242 // =======================================================================
243 void OpenGl_VertexBuffer::UnbindAllAttributes (const Handle(OpenGl_Context)& ) const
244 {
245   //
246 }
247
248 // =======================================================================
249 // function : HasColorAttribute
250 // purpose  :
251 // =======================================================================
252 bool OpenGl_VertexBuffer::HasColorAttribute() const
253 {
254   return false;
255 }
256
257 // =======================================================================
258 // function : HasNormalAttribute
259 // purpose  :
260 // =======================================================================
261 bool OpenGl_VertexBuffer::HasNormalAttribute() const
262 {
263   return false;
264 }
265
266 #if !defined(GL_ES_VERSION_2_0)
267 // =======================================================================
268 // function : unbindFixedColor
269 // purpose  :
270 // =======================================================================
271 void OpenGl_VertexBuffer::unbindFixedColor (const Handle(OpenGl_Context)& theCtx)
272 {
273   theCtx->core11->glDisableClientState (GL_COLOR_ARRAY);
274   theCtx->core11fwd->glDisable (GL_COLOR_MATERIAL);
275
276   // invalidate FFP material state after GL_COLOR_MATERIAL has modified it (took values from the vertex color)
277   theCtx->ShaderManager()->UpdateMaterialState();
278 }
279 #endif
280
281 // =======================================================================
282 // function : DumpJson
283 // purpose  :
284 // =======================================================================
285 void OpenGl_VertexBuffer::DumpJson (Standard_OStream& theOStream, Standard_Integer theDepth) const
286 {
287   OCCT_DUMP_TRANSIENT_CLASS_BEGIN (theOStream)
288   OCCT_DUMP_BASE_CLASS (theOStream, theDepth, OpenGl_Resource)
289
290   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, GetTarget())
291   OCCT_DUMP_FIELD_VALUE_POINTER (theOStream, myOffset)
292
293   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myBufferId)
294   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myComponentsNb)
295   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myElemsNb)
296   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDataType)
297 }