0030058: Visualization, Select3D_SensitivePrimitiveArray - the selection is not fast...
[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 : BindVertexAttrib
165 // purpose  :
166 // =======================================================================
167 void OpenGl_VertexBuffer::BindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
168                                             const GLuint                  theAttribLoc) const
169 {
170   if (!IsValid() || theAttribLoc == GLuint (-1))
171   {
172     return;
173   }
174   Bind (theGlCtx);
175   theGlCtx->core20fwd->glEnableVertexAttribArray (theAttribLoc);
176   theGlCtx->core20fwd->glVertexAttribPointer (theAttribLoc, GLint (myComponentsNb), myDataType, GL_FALSE, 0, myOffset);
177 }
178
179 // =======================================================================
180 // function : UnbindVertexAttrib
181 // purpose  :
182 // =======================================================================
183 void OpenGl_VertexBuffer::UnbindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
184                                               const GLuint                  theAttribLoc) const
185 {
186   if (!IsValid() || theAttribLoc == GLuint (-1))
187   {
188     return;
189   }
190   theGlCtx->core20fwd->glDisableVertexAttribArray (theAttribLoc);
191   Unbind (theGlCtx);
192 }
193
194 // =======================================================================
195 // function : BindAllAttributes
196 // purpose  :
197 // =======================================================================
198 void OpenGl_VertexBuffer::BindAllAttributes (const Handle(OpenGl_Context)& ) const
199 {
200   //
201 }
202
203 // =======================================================================
204 // function : BindPositionAttribute
205 // purpose  :
206 // =======================================================================
207 void OpenGl_VertexBuffer::BindPositionAttribute (const Handle(OpenGl_Context)& ) const
208 {
209   //
210 }
211
212 // =======================================================================
213 // function : UnbindAllAttributes
214 // purpose  :
215 // =======================================================================
216 void OpenGl_VertexBuffer::UnbindAllAttributes (const Handle(OpenGl_Context)& ) const
217 {
218   //
219 }
220
221 // =======================================================================
222 // function : HasColorAttribute
223 // purpose  :
224 // =======================================================================
225 bool OpenGl_VertexBuffer::HasColorAttribute() const
226 {
227   return false;
228 }
229
230 // =======================================================================
231 // function : HasNormalAttribute
232 // purpose  :
233 // =======================================================================
234 bool OpenGl_VertexBuffer::HasNormalAttribute() const
235 {
236   return false;
237 }
238
239 #if !defined(GL_ES_VERSION_2_0)
240 // =======================================================================
241 // function : unbindFixedColor
242 // purpose  :
243 // =======================================================================
244 void OpenGl_VertexBuffer::unbindFixedColor (const Handle(OpenGl_Context)& theCtx)
245 {
246   theCtx->core11->glDisableClientState (GL_COLOR_ARRAY);
247   theCtx->core11fwd->glDisable (GL_COLOR_MATERIAL);
248
249   // invalidate FFP material state after GL_COLOR_MATERIAL has modified it (took values from the vertex color)
250   theCtx->ShaderManager()->UpdateMaterialState();
251 }
252 #endif