5e27df78 |
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 | } |