0023226: Extend OpenGl_Context to store map of shared GPU resources
[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 : Init
184 // purpose  :
185 // =======================================================================
186 bool OpenGl_VertexBuffer::Init (const Handle(OpenGl_Context)& theGlCtx,
187                                 const GLuint   theComponentsNb,
188                                 const GLsizei  theElemsNb,
189                                 const GLubyte* theData)
190 {
191   if (!Create (theGlCtx))
192   {
193     return false;
194   }
195
196   Bind (theGlCtx);
197   myDataType     = GL_UNSIGNED_BYTE;
198   myComponentsNb = theComponentsNb;
199   myElemsNb      = theElemsNb;
200   theGlCtx->core15->glBufferData (GetTarget(), GLsizeiptr(myElemsNb) * GLsizeiptr(myComponentsNb) * sizeof(GLubyte), theData, GL_STATIC_DRAW);
201   bool isDone = (glGetError() == GL_NO_ERROR); // GL_OUT_OF_MEMORY
202   Unbind (theGlCtx);
203   return isDone;
204 }
205
206 // =======================================================================
207 // function : BindVertexAttrib
208 // purpose  :
209 // =======================================================================
210 void OpenGl_VertexBuffer::BindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
211                                             const GLuint                  theAttribLoc) const
212 {
213   if (!IsValid() || theAttribLoc == GLuint (-1))
214   {
215     return;
216   }
217   Bind (theGlCtx);
218   theGlCtx->core20->glEnableVertexAttribArray (theAttribLoc);
219   theGlCtx->core20->glVertexAttribPointer (theAttribLoc, GLint (myComponentsNb), myDataType, GL_FALSE, 0, NULL);
220 }
221
222 // =======================================================================
223 // function : UnbindVertexAttrib
224 // purpose  :
225 // =======================================================================
226 void OpenGl_VertexBuffer::UnbindVertexAttrib (const Handle(OpenGl_Context)& theGlCtx,
227                                               const GLuint                  theAttribLoc) const
228 {
229   if (!IsValid() || theAttribLoc == GLuint (-1))
230   {
231     return;
232   }
233   theGlCtx->core20->glDisableVertexAttribArray (theAttribLoc);
234   Unbind (theGlCtx);
235 }
236
237 // =======================================================================
238 // function : BindFixed
239 // purpose  :
240 // =======================================================================
241 void OpenGl_VertexBuffer::BindFixed (const Handle(OpenGl_Context)& theGlCtx,
242                                      const GLenum                  theMode) const
243 {
244   if (!IsValid())
245   {
246     return;
247   }
248
249   Bind (theGlCtx);
250   glEnableClientState (theMode);
251   switch (theMode)
252   {
253     case GL_VERTEX_ARRAY:
254     {
255       glVertexPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
256       break;
257     }
258     case GL_NORMAL_ARRAY:
259     {
260       glNormalPointer (myDataType, 0, NULL);
261       break;
262     }
263     case GL_TEXTURE_COORD_ARRAY:
264     {
265       glTexCoordPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
266       break;
267     }
268     case GL_COLOR_ARRAY:
269     {
270       glColorPointer (static_cast<GLint> (myComponentsNb), myDataType, 0, NULL);
271       break;
272     }
273     default: break;
274   }
275 }
276
277 // =======================================================================
278 // function : UnbindFixed
279 // purpose  :
280 // =======================================================================
281 void OpenGl_VertexBuffer::UnbindFixed (const Handle(OpenGl_Context)& theGlCtx,
282                                        const GLenum                  theMode) const
283 {
284   if (!IsValid())
285   {
286     return;
287   }
288   Unbind (theGlCtx);
289   glDisableClientState (theMode);
290 }