6c7a632bdfa303aae3b9ba761598565c7785c2eb
[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 <Standard_Assert.hxx>
19
20 IMPLEMENT_STANDARD_HANDLE (OpenGl_VertexBuffer, OpenGl_Resource)
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   myBufferId (NO_BUFFER),
30   myComponentsNb (4),
31   myElemsNb (0),
32   myDataType (GL_FLOAT)
33 {
34   //
35 }
36
37 // =======================================================================
38 // function : ~OpenGl_VertexBuffer
39 // purpose  :
40 // =======================================================================
41 OpenGl_VertexBuffer::~OpenGl_VertexBuffer()
42 {
43   Release (NULL);
44 }
45
46 // =======================================================================
47 // function : GetTarget
48 // purpose  :
49 // =======================================================================
50 GLenum OpenGl_VertexBuffer::GetTarget() const
51 {
52   return GL_ARRAY_BUFFER;
53 }
54
55 // =======================================================================
56 // function : Create
57 // purpose  :
58 // =======================================================================
59 bool OpenGl_VertexBuffer::Create (const Handle(OpenGl_Context)& theGlCtx)
60 {
61   if (myBufferId == NO_BUFFER)
62   {
63     theGlCtx->core15->glGenBuffers (1, &myBufferId);
64   }
65   return myBufferId != NO_BUFFER;
66 }
67
68 // =======================================================================
69 // function : Release
70 // purpose  :
71 // =======================================================================
72 void OpenGl_VertexBuffer::Release (const OpenGl_Context* theGlCtx)
73 {
74   if (myBufferId == NO_BUFFER)
75   {
76     return;
77   }
78
79   // application can not handle this case by exception - this is bug in code
80   Standard_ASSERT_RETURN (theGlCtx != NULL,
81     "OpenGl_VertexBuffer destroyed without GL context! Possible GPU memory leakage...",);
82
83   if (theGlCtx->IsValid())
84   {
85     theGlCtx->core15->glDeleteBuffers (1, &myBufferId);
86   }
87   myBufferId = NO_BUFFER;
88 }
89
90 // =======================================================================
91 // function : Bind
92 // purpose  :
93 // =======================================================================
94 void OpenGl_VertexBuffer::Bind (const Handle(OpenGl_Context)& theGlCtx) const
95 {
96   theGlCtx->core15->glBindBuffer (GetTarget(), myBufferId);
97 }
98
99 // =======================================================================
100 // function : Unbind
101 // purpose  :
102 // =======================================================================
103 void OpenGl_VertexBuffer::Unbind (const Handle(OpenGl_Context)& theGlCtx) const
104 {
105   theGlCtx->core15->glBindBuffer (GetTarget(), NO_BUFFER);
106 }
107
108 // =======================================================================
109 // function : init
110 // purpose  :
111 // =======================================================================
112 bool OpenGl_VertexBuffer::init (const Handle(OpenGl_Context)& theGlCtx,
113                                 const GLuint   theComponentsNb,
114                                 const GLsizei  theElemsNb,
115                                 const void*    theData,
116                                 const GLenum   theDataType,
117                                 const GLsizei  theStride)
118 {
119   if (!Create (theGlCtx))
120   {
121     return false;
122   }
123
124   Bind (theGlCtx);
125   myDataType     = theDataType;
126   myComponentsNb = theComponentsNb;
127   myElemsNb      = theElemsNb;
128   theGlCtx->core15->glBufferData (GetTarget(), GLsizeiptr(myElemsNb) * theStride, theData, GL_STATIC_DRAW);
129   bool isDone = (glGetError() == GL_NO_ERROR); // GL_OUT_OF_MEMORY
130   Unbind (theGlCtx);
131   return isDone;
132 }
133
134 // =======================================================================
135 // function : subData
136 // purpose  :
137 // =======================================================================
138 bool OpenGl_VertexBuffer::subData (const Handle(OpenGl_Context)& theGlCtx,
139                                    const GLsizei  theElemFrom,
140                                    const GLsizei  theElemsNb,
141                                    const void*    theData,
142                                    const GLenum   theDataType)
143 {
144   if (!IsValid() || myDataType != theDataType ||
145       theElemFrom < 0 || ((theElemFrom + theElemsNb) > myElemsNb))
146   {
147     return false;
148   }
149
150   Bind (theGlCtx);
151   const size_t aDataSize = sizeOfGlType (theDataType);
152   theGlCtx->core15->glBufferSubData (GetTarget(),
153                                      GLintptr(theElemFrom)  * GLintptr  (myComponentsNb) * aDataSize, // offset in bytes
154                                      GLsizeiptr(theElemsNb) * GLsizeiptr(myComponentsNb) * aDataSize, // size   in bytes
155                                      theData);
156   bool isDone = (glGetError() == GL_NO_ERROR); // some dummy error
157   Unbind (theGlCtx);
158   return isDone;
159 }
160
161 // =======================================================================
162 // function : BindVertexAttrib
163 // purpose  :
164 // =======================================================================
165 void OpenGl_VertexBuffer::BindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
166                                             const GLuint                  theAttribLoc) const
167 {
168   if (!IsValid() || theAttribLoc == GLuint (-1))
169   {
170     return;
171   }
172   Bind (theGlCtx);
173   theGlCtx->core20->glEnableVertexAttribArray (theAttribLoc);
174   theGlCtx->core20->glVertexAttribPointer (theAttribLoc, GLint (myComponentsNb), myDataType, GL_FALSE, 0, NULL);
175 }
176
177 // =======================================================================
178 // function : UnbindVertexAttrib
179 // purpose  :
180 // =======================================================================
181 void OpenGl_VertexBuffer::UnbindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
182                                               const GLuint                  theAttribLoc) const
183 {
184   if (!IsValid() || theAttribLoc == GLuint (-1))
185   {
186     return;
187   }
188   theGlCtx->core20->glDisableVertexAttribArray (theAttribLoc);
189   Unbind (theGlCtx);
190 }
191
192 // =======================================================================
193 // function : BindFixed
194 // purpose  :
195 // =======================================================================
196 void OpenGl_VertexBuffer::BindFixed (const Handle(OpenGl_Context)& theGlCtx,
197                                      const GLenum                  theMode) const
198 {
199   if (!IsValid())
200   {
201     return;
202   }
203
204   Bind (theGlCtx);
205   glEnableClientState (theMode);
206   switch (theMode)
207   {
208     case GL_VERTEX_ARRAY:
209     {
210       glVertexPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
211       break;
212     }
213     case GL_NORMAL_ARRAY:
214     {
215       glNormalPointer (myDataType, 0, NULL);
216       break;
217     }
218     case GL_TEXTURE_COORD_ARRAY:
219     {
220       glTexCoordPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
221       break;
222     }
223     case GL_COLOR_ARRAY:
224     {
225       glColorPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
226       glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
227       glEnable (GL_COLOR_MATERIAL);
228       break;
229     }
230     default: break;
231   }
232 }
233
234 // =======================================================================
235 // function : UnbindFixed
236 // purpose  :
237 // =======================================================================
238 void OpenGl_VertexBuffer::UnbindFixed (const Handle(OpenGl_Context)& theGlCtx,
239                                        const GLenum                  theMode) const
240 {
241   if (!IsValid())
242   {
243     return;
244   }
245   Unbind (theGlCtx);
246   glDisableClientState (theMode);
247   if (theMode == GL_COLOR_ARRAY)
248   {
249     glDisable (GL_COLOR_MATERIAL);
250   }
251 }
252
253 // =======================================================================
254 // function : BindFixed
255 // purpose  :
256 // =======================================================================
257 void OpenGl_VertexBuffer::BindFixed (const Handle(OpenGl_Context)& ) const
258 {
259   //
260 }
261
262 // =======================================================================
263 // function : BindFixedPosition
264 // purpose  :
265 // =======================================================================
266 void OpenGl_VertexBuffer::BindFixedPosition (const Handle(OpenGl_Context)& ) const
267 {
268   //
269 }
270
271 // =======================================================================
272 // function : UnbindFixed
273 // purpose  :
274 // =======================================================================
275 void OpenGl_VertexBuffer::UnbindFixed (const Handle(OpenGl_Context)& ) const
276 {
277     //
278 }
279
280 // =======================================================================
281 // function : HasColorAttribute
282 // purpose  :
283 // =======================================================================
284 bool OpenGl_VertexBuffer::HasColorAttribute() const
285 {
286   return false;
287 }