0024224: Suspicious logics in changing clipping planes at OpenGl_Structure
[occt.git] / src / OpenGl / OpenGl_VertexBuffer.cxx
1 // Created by: Kirill GAVRILOV
2 // Copyright (c) 2012 OPEN CASCADE SAS
3 //
4 // The content of this file is subject to the Open CASCADE Technology Public
5 // License Version 6.5 (the "License"). You may not use the content of this file
6 // except in compliance with the License. Please obtain a copy of the License
7 // at http://www.opencascade.org and read it completely before using this file.
8 //
9 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
10 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
11 //
12 // The Original Code and all software distributed under the License is
13 // distributed on an "AS IS" basis, without warranty of any kind, and the
14 // Initial Developer hereby disclaims all such warranties, including without
15 // limitation, any warranties of merchantability, fitness for a particular
16 // purpose or non-infringement. Please see the License for the specific terms
17 // and conditions governing the rights and limitations under the License.
18
19 #include <OpenGl_VertexBuffer.hxx>
20
21 #include <OpenGl_Context.hxx>
22 #include <Standard_Assert.hxx>
23
24 IMPLEMENT_STANDARD_HANDLE (OpenGl_VertexBuffer, OpenGl_Resource)
25 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_VertexBuffer, OpenGl_Resource)
26
27 // =======================================================================
28 // function : OpenGl_VertexBuffer
29 // purpose  :
30 // =======================================================================
31 OpenGl_VertexBuffer::OpenGl_VertexBuffer()
32 : OpenGl_Resource(),
33   myBufferId (NO_BUFFER),
34   myComponentsNb (4),
35   myElemsNb (0),
36   myDataType (GL_FLOAT)
37 {
38   //
39 }
40
41 // =======================================================================
42 // function : ~OpenGl_VertexBuffer
43 // purpose  :
44 // =======================================================================
45 OpenGl_VertexBuffer::~OpenGl_VertexBuffer()
46 {
47   Release (NULL);
48 }
49
50 // =======================================================================
51 // function : GetTarget
52 // purpose  :
53 // =======================================================================
54 GLenum OpenGl_VertexBuffer::GetTarget() const
55 {
56   return GL_ARRAY_BUFFER;
57 }
58
59 // =======================================================================
60 // function : Create
61 // purpose  :
62 // =======================================================================
63 bool OpenGl_VertexBuffer::Create (const Handle(OpenGl_Context)& theGlCtx)
64 {
65   if (myBufferId == NO_BUFFER)
66   {
67     theGlCtx->core15->glGenBuffers (1, &myBufferId);
68   }
69   return myBufferId != NO_BUFFER;
70 }
71
72 // =======================================================================
73 // function : Release
74 // purpose  :
75 // =======================================================================
76 void OpenGl_VertexBuffer::Release (const OpenGl_Context* theGlCtx)
77 {
78   if (myBufferId == NO_BUFFER)
79   {
80     return;
81   }
82
83   // application can not handle this case by exception - this is bug in code
84   Standard_ASSERT_RETURN (theGlCtx != NULL,
85     "OpenGl_VertexBuffer destroyed without GL context! Possible GPU memory leakage...",);
86
87   theGlCtx->core15->glDeleteBuffers (1, &myBufferId);
88   myBufferId = NO_BUFFER;
89 }
90
91 // =======================================================================
92 // function : Bind
93 // purpose  :
94 // =======================================================================
95 void OpenGl_VertexBuffer::Bind (const Handle(OpenGl_Context)& theGlCtx) const
96 {
97   theGlCtx->core15->glBindBuffer (GetTarget(), myBufferId);
98 }
99
100 // =======================================================================
101 // function : Unbind
102 // purpose  :
103 // =======================================================================
104 void OpenGl_VertexBuffer::Unbind (const Handle(OpenGl_Context)& theGlCtx) const
105 {
106   theGlCtx->core15->glBindBuffer (GetTarget(), NO_BUFFER);
107 }
108
109 // =======================================================================
110 // function : Init
111 // purpose  :
112 // =======================================================================
113 bool OpenGl_VertexBuffer::Init (const Handle(OpenGl_Context)& theGlCtx,
114                                 const GLuint   theComponentsNb,
115                                 const GLsizei  theElemsNb,
116                                 const GLfloat* theData)
117 {
118   if (!Create (theGlCtx))
119   {
120     return false;
121   }
122
123   Bind (theGlCtx);
124   myDataType     = GL_FLOAT;
125   myComponentsNb = theComponentsNb;
126   myElemsNb      = theElemsNb;
127   theGlCtx->core15->glBufferData (GetTarget(), GLsizeiptr(myElemsNb) * GLsizeiptr(myComponentsNb) * sizeof(GLfloat), theData, GL_STATIC_DRAW);
128   bool isDone = (glGetError() == GL_NO_ERROR); // GL_OUT_OF_MEMORY
129   Unbind (theGlCtx);
130   return isDone;
131 }
132
133 // =======================================================================
134 // function : SubData
135 // purpose  :
136 // =======================================================================
137 bool OpenGl_VertexBuffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
138                                    const GLsizei  theElemFrom,
139                                    const GLsizei  theElemsNb,
140                                    const GLfloat* theData)
141 {
142   if (!IsValid() || myDataType != GL_FLOAT ||
143       theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb))
144   {
145     return false;
146   }
147
148   Bind (theGlCtx);
149   theGlCtx->core15->glBufferSubData (GetTarget(),
150                                      GLintptr(theElemFrom)  * GLintptr(myComponentsNb)   * sizeof(GLfloat), // offset in bytes
151                                      GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * sizeof(GLfloat), // size   in bytes
152                                      theData);
153   bool isDone = (glGetError() == GL_NO_ERROR); // some dummy error
154   Unbind (theGlCtx);
155   return isDone;
156 }
157
158 // =======================================================================
159 // function : Init
160 // purpose  :
161 // =======================================================================
162 bool OpenGl_VertexBuffer::Init (const Handle(OpenGl_Context)& theGlCtx,
163                                 const GLuint  theComponentsNb,
164                                 const GLsizei theElemsNb,
165                                 const GLuint* theData)
166 {
167   if (!Create (theGlCtx))
168   {
169     return false;
170   }
171
172   Bind (theGlCtx);
173   myDataType     = GL_UNSIGNED_INT;  
174   myComponentsNb = theComponentsNb;
175   myElemsNb      = theElemsNb;
176   theGlCtx->core15->glBufferData (GetTarget(), GLsizeiptr(myElemsNb) * GLsizeiptr(myComponentsNb) * sizeof(GLuint), theData, GL_STATIC_DRAW);
177   bool isDone = (glGetError() == GL_NO_ERROR); // GL_OUT_OF_MEMORY
178   Unbind (theGlCtx);
179   return isDone;
180 }
181
182 // =======================================================================
183 // function : SubData
184 // purpose  :
185 // =======================================================================
186 bool OpenGl_VertexBuffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
187                                    const GLsizei theElemFrom,
188                                    const GLsizei theElemsNb,
189                                    const GLuint* theData)
190 {
191   if (!IsValid() || myDataType != GL_UNSIGNED_INT
192    || theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb))
193   {
194     return false;
195   }
196
197   Bind (theGlCtx);
198   theGlCtx->core15->glBufferSubData (GetTarget(),
199                                      GLintptr(theElemFrom)  * GLintptr(myComponentsNb)   * sizeof(GLuint), // offset in bytes
200                                      GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * sizeof(GLuint), // size   in bytes
201                                      theData);
202   bool isDone = (glGetError() == GL_NO_ERROR); // GL_OUT_OF_MEMORY
203   Unbind (theGlCtx);
204   return isDone;
205 }
206
207 // =======================================================================
208 // function : Init
209 // purpose  :
210 // =======================================================================
211 bool OpenGl_VertexBuffer::Init (const Handle(OpenGl_Context)& theGlCtx,
212                                 const GLuint   theComponentsNb,
213                                 const GLsizei  theElemsNb,
214                                 const GLubyte* theData)
215 {
216   if (!Create (theGlCtx))
217   {
218     return false;
219   }
220
221   Bind (theGlCtx);
222   myDataType     = GL_UNSIGNED_BYTE;
223   myComponentsNb = theComponentsNb;
224   myElemsNb      = theElemsNb;
225   theGlCtx->core15->glBufferData (GetTarget(), GLsizeiptr(myElemsNb) * GLsizeiptr(myComponentsNb) * sizeof(GLubyte), theData, GL_STATIC_DRAW);
226   bool isDone = (glGetError() == GL_NO_ERROR); // GL_OUT_OF_MEMORY
227   Unbind (theGlCtx);
228   return isDone;
229 }
230
231 // =======================================================================
232 // function : SubData
233 // purpose  :
234 // =======================================================================
235 bool OpenGl_VertexBuffer::SubData (const Handle(OpenGl_Context)& theGlCtx,
236                                    const GLsizei  theElemFrom,
237                                    const GLsizei  theElemsNb,
238                                    const GLubyte* theData)
239 {
240   if (!IsValid() || myDataType != GL_UNSIGNED_BYTE
241    || theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb))
242   {
243     return false;
244   }
245
246   Bind (theGlCtx);
247   theGlCtx->core15->glBufferSubData (GetTarget(),
248                                      GLintptr(theElemFrom)  * GLintptr(myComponentsNb)   * sizeof(GLubyte), // offset in bytes
249                                      GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * sizeof(GLubyte), // size   in bytes
250                                      theData);
251   bool isDone = (glGetError() == GL_NO_ERROR); // GL_OUT_OF_MEMORY
252   Unbind (theGlCtx);
253   return isDone;
254 }
255
256 // =======================================================================
257 // function : BindVertexAttrib
258 // purpose  :
259 // =======================================================================
260 void OpenGl_VertexBuffer::BindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
261                                             const GLuint                  theAttribLoc) const
262 {
263   if (!IsValid() || theAttribLoc == GLuint (-1))
264   {
265     return;
266   }
267   Bind (theGlCtx);
268   theGlCtx->core20->glEnableVertexAttribArray (theAttribLoc);
269   theGlCtx->core20->glVertexAttribPointer (theAttribLoc, GLint (myComponentsNb), myDataType, GL_FALSE, 0, NULL);
270 }
271
272 // =======================================================================
273 // function : UnbindVertexAttrib
274 // purpose  :
275 // =======================================================================
276 void OpenGl_VertexBuffer::UnbindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
277                                               const GLuint                  theAttribLoc) const
278 {
279   if (!IsValid() || theAttribLoc == GLuint (-1))
280   {
281     return;
282   }
283   theGlCtx->core20->glDisableVertexAttribArray (theAttribLoc);
284   Unbind (theGlCtx);
285 }
286
287 // =======================================================================
288 // function : BindFixed
289 // purpose  :
290 // =======================================================================
291 void OpenGl_VertexBuffer::BindFixed (const Handle(OpenGl_Context)& theGlCtx,
292                                      const GLenum                  theMode) const
293 {
294   if (!IsValid())
295   {
296     return;
297   }
298
299   Bind (theGlCtx);
300   glEnableClientState (theMode);
301   switch (theMode)
302   {
303     case GL_VERTEX_ARRAY:
304     {
305       glVertexPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
306       break;
307     }
308     case GL_NORMAL_ARRAY:
309     {
310       glNormalPointer (myDataType, 0, NULL);
311       break;
312     }
313     case GL_TEXTURE_COORD_ARRAY:
314     {
315       glTexCoordPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
316       break;
317     }
318     case GL_COLOR_ARRAY:
319     {
320       glColorPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
321       break;
322     }
323     default: break;
324   }
325 }
326
327 // =======================================================================
328 // function : UnbindFixed
329 // purpose  :
330 // =======================================================================
331 void OpenGl_VertexBuffer::UnbindFixed (const Handle(OpenGl_Context)& theGlCtx,
332                                        const GLenum                  theMode) const
333 {
334   if (!IsValid())
335   {
336     return;
337   }
338   Unbind (theGlCtx);
339   glDisableClientState (theMode);
340 }