0024245: TKOpenGL - use Message_Messenger interface to report issues
[occt.git] / src / OpenGl / OpenGl_PrimitiveArray.cxx
CommitLineData
b311480e 1// Created on: 2011-07-13
2// Created by: Sergey ZERCHANINOV
de75ed09 3// Copyright (c) 2011-2013 OPEN CASCADE SAS
b311480e 4//
5// The content of this file is subject to the Open CASCADE Technology Public
6// License Version 6.5 (the "License"). You may not use the content of this file
7// except in compliance with the License. Please obtain a copy of the License
8// at http://www.opencascade.org and read it completely before using this file.
9//
10// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12//
13// The Original Code and all software distributed under the License is
14// distributed on an "AS IS" basis, without warranty of any kind, and the
15// Initial Developer hereby disclaims all such warranties, including without
16// limitation, any warranties of merchantability, fitness for a particular
17// purpose or non-infringement. Please see the License for the specific terms
18// and conditions governing the rights and limitations under the License.
19
5e27df78 20#include <OpenGl_IndexBuffer.hxx>
5f8b738e 21#include <OpenGl_Context.hxx>
22
2166f0fa 23#include <OpenGl_PrimitiveArray.hxx>
7fd59977 24
2166f0fa
SK
25#include <OpenGl_AspectFace.hxx>
26#include <OpenGl_GraphicDriver.hxx>
a577aaab 27#include <OpenGl_PointSprite.hxx>
2166f0fa 28#include <OpenGl_Structure.hxx>
bf75be98 29#include <OpenGl_Workspace.hxx>
2166f0fa 30
7fd59977 31#include <InterfaceGraphic_PrimitiveArray.hxx>
2166f0fa 32
2166f0fa
SK
33// =======================================================================
34// function : clearMemoryOwn
35// purpose :
36// =======================================================================
37void OpenGl_PrimitiveArray::clearMemoryOwn() const
7fd59977 38{
5e27df78 39 Standard::Free ((Standard_Address& )myPArray->edges);
40 Standard::Free ((Standard_Address& )myPArray->vertices);
41 Standard::Free ((Standard_Address& )myPArray->vcolours);
42 Standard::Free ((Standard_Address& )myPArray->vnormals);
43 Standard::Free ((Standard_Address& )myPArray->vtexels);
44 Standard::Free ((Standard_Address& )myPArray->edge_vis); /// ???
45
46 myPArray->edges = NULL;
47 myPArray->vertices = NULL;
48 myPArray->vcolours = NULL;
49 myPArray->vnormals = NULL;
50 myPArray->vtexels = NULL;
51 myPArray->edge_vis = NULL;
7fd59977 52}
53
2166f0fa
SK
54// =======================================================================
55// function : clearMemoryGL
56// purpose :
57// =======================================================================
5e27df78 58void OpenGl_PrimitiveArray::clearMemoryGL (const Handle(OpenGl_Context)& theGlCtx) const
7fd59977 59{
5e27df78 60 for (Standard_Integer anIter = 0; anIter < VBOMaxType; ++anIter)
2166f0fa 61 {
5e27df78 62 if (!myVbos[anIter].IsNull())
63 {
64 myVbos[anIter]->Release (theGlCtx.operator->());
65 myVbos[anIter].Nullify();
66 }
2166f0fa 67 }
7fd59977 68}
69
2166f0fa 70// =======================================================================
5e27df78 71// function : BuildVBO
2166f0fa
SK
72// purpose :
73// =======================================================================
5e27df78 74Standard_Boolean OpenGl_PrimitiveArray::BuildVBO (const Handle(OpenGl_Workspace)& theWorkspace) const
7fd59977 75{
5e27df78 76 const Handle(OpenGl_Context)& aGlCtx = theWorkspace->GetGlContext();
77 if (myPArray->vertices == NULL)
2166f0fa 78 {
5e27df78 79 // vertices should be always defined - others are optional
80 return Standard_False;
2166f0fa 81 }
5e27df78 82 myVbos[VBOVertices] = new OpenGl_VertexBuffer();
83 if (!myVbos[VBOVertices]->Init (aGlCtx, 3, myPArray->num_vertexs, &myPArray->vertices[0].xyz[0]))
2166f0fa 84 {
5e27df78 85 clearMemoryGL (aGlCtx);
86 return Standard_False;
2166f0fa 87 }
7fd59977 88
ee1e83b9 89 if (myPArray->edges != NULL
90 && myPArray->num_edges > 0)
2166f0fa 91 {
5e27df78 92 myVbos[VBOEdges] = new OpenGl_IndexBuffer();
93 if (!myVbos[VBOEdges]->Init (aGlCtx, 1, myPArray->num_edges, (GLuint* )myPArray->edges))
94 {
95 clearMemoryGL (aGlCtx);
2166f0fa 96 return Standard_False;
5e27df78 97 }
7fd59977 98 }
2166f0fa
SK
99 if (myPArray->vcolours != NULL)
100 {
5e27df78 101 myVbos[VBOVcolours] = new OpenGl_VertexBuffer();
102 if (!myVbos[VBOVcolours]->Init (aGlCtx, 4, myPArray->num_vertexs, (GLubyte* )myPArray->vcolours))
103 {
104 clearMemoryGL (aGlCtx);
2166f0fa 105 return Standard_False;
5e27df78 106 }
7fd59977 107 }
2166f0fa
SK
108 if (myPArray->vnormals != NULL)
109 {
5e27df78 110 myVbos[VBOVnormals] = new OpenGl_VertexBuffer();
111 if (!myVbos[VBOVnormals]->Init (aGlCtx, 3, myPArray->num_vertexs, &myPArray->vnormals[0].xyz[0]))
112 {
113 clearMemoryGL (aGlCtx);
2166f0fa 114 return Standard_False;
5e27df78 115 }
7fd59977 116 }
2166f0fa
SK
117 if (myPArray->vtexels)
118 {
5e27df78 119 myVbos[VBOVtexels] = new OpenGl_VertexBuffer();
120 if (!myVbos[VBOVtexels]->Init (aGlCtx, 2, myPArray->num_vertexs, &myPArray->vtexels[0].xy[0]))
121 {
122 clearMemoryGL (aGlCtx);
2166f0fa 123 return Standard_False;
5e27df78 124 }
2166f0fa 125 }
7fd59977 126
5e27df78 127 clearMemoryOwn();
2166f0fa 128 return Standard_True;
7fd59977 129}
130
2166f0fa
SK
131// =======================================================================
132// function : DrawArray
133// purpose :
134// =======================================================================
135void OpenGl_PrimitiveArray::DrawArray (Tint theLightingModel,
136 const Aspect_InteriorStyle theInteriorStyle,
137 Tint theEdgeFlag,
138 const TEL_COLOUR* theInteriorColour,
139 const TEL_COLOUR* theLineColour,
140 const TEL_COLOUR* theEdgeColour,
141 const OPENGL_SURF_PROP* theFaceProp,
142 const Handle(OpenGl_Workspace)& theWorkspace) const
7fd59977 143{
2166f0fa
SK
144 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
145
7fd59977 146 Tint i,n;
147 Tint transp = 0;
2166f0fa
SK
148 // Following pointers have been provided for performance improvement
149 tel_colour pfc = myPArray->fcolours;
150 Tint* pvc = myPArray->vcolours;
151 if (pvc != NULL)
152 {
153 for (i = 0; i < myPArray->num_vertexs; ++i)
154 {
155 transp = int(theFaceProp->trans * 255.0f);
bf75be98 156 #if defined (sparc) || defined (__sparc__) || defined (__sparc)
2166f0fa
SK
157 pvc[i] = (pvc[i] & 0xffffff00);
158 pvc[i] += transp;
bf75be98 159 #else
2166f0fa 160 pvc[i] = (pvc[i] & 0x00ffffff);
7fd59977 161 pvc[i] += transp << 24;
2166f0fa 162 #endif
7fd59977 163 }
164 }
7fd59977 165
2166f0fa
SK
166 switch (myPArray->type)
167 {
7fd59977 168 case TelPointsArrayType:
7fd59977 169 case TelPolylinesArrayType:
7fd59977 170 case TelSegmentsArrayType:
2166f0fa 171 glColor3fv (theLineColour->rgb);
7fd59977 172 break;
173 case TelPolygonsArrayType:
7fd59977 174 case TelTrianglesArrayType:
7fd59977 175 case TelQuadranglesArrayType:
7fd59977 176 case TelTriangleStripsArrayType:
7fd59977 177 case TelQuadrangleStripsArrayType:
7fd59977 178 case TelTriangleFansArrayType:
2166f0fa 179 glColor3fv (theInteriorColour->rgb);
7fd59977 180 break;
7fd59977 181 }
182
2166f0fa
SK
183 // Temporarily disable environment mapping
184 if (myDrawMode <= GL_LINE_STRIP)
185 {
186 glPushAttrib (GL_ENABLE_BIT);
187 glDisable (GL_TEXTURE_1D);
188 glDisable (GL_TEXTURE_2D);
7fd59977 189 }
190
de75ed09 191 if ((myDrawMode > GL_LINE_STRIP && theInteriorStyle != Aspect_IS_EMPTY) ||
192 (myDrawMode <= GL_LINE_STRIP))
2166f0fa
SK
193 {
194 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
195 {
7fd59977 196 pfc = NULL;
197 pvc = NULL;
198 }
199
2166f0fa
SK
200 if (theInteriorStyle == Aspect_IS_HIDDENLINE)
201 {
202 theEdgeFlag = 1;
7fd59977 203 pfc = NULL;
204 pvc = NULL;
205 }
206
2166f0fa 207 // Sometimes the GL_LIGHTING mode is activated here
bf75be98 208 // without glEnable(GL_LIGHTING) call for an unknown reason, so it is necessary
2166f0fa
SK
209 // to call glEnable(GL_LIGHTING) to synchronize Light On/Off mechanism*
210 if (theLightingModel == 0 || myDrawMode <= GL_LINE_STRIP)
211 glDisable (GL_LIGHTING);
212 else
213 glEnable (GL_LIGHTING);
214
5e27df78 215 if (!toDrawVbo())
2166f0fa
SK
216 {
217 if (myPArray->vertices != NULL)
218 {
219 glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
220 glEnableClientState (GL_VERTEX_ARRAY);
221 }
222 if (myPArray->vnormals != NULL)
223 {
224 glNormalPointer (GL_FLOAT, 0, myPArray->vnormals); // array of normals
225 glEnableClientState (GL_NORMAL_ARRAY);
226 }
227 if (myPArray->vtexels != NULL)
228 {
229 glTexCoordPointer (2, GL_FLOAT, 0, myPArray->vtexels); // array of texture coordinates
230 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
231 }
7fd59977 232
a577aaab 233 if ((pvc != NULL) && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0)
2166f0fa
SK
234 {
235 glColorPointer (4, GL_UNSIGNED_BYTE, 0, pvc); // array of colors
236 glEnableClientState (GL_COLOR_ARRAY);
237 glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
238 glEnable (GL_COLOR_MATERIAL);
7fd59977 239 }
240 }
5e27df78 241 else
2166f0fa
SK
242 {
243 // Bindings concrete pointer in accordance with VBO buffer
5e27df78 244 myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY);
245 if (!myVbos[VBOVnormals].IsNull())
2166f0fa 246 {
5e27df78 247 myVbos[VBOVnormals]->BindFixed (aGlContext, GL_NORMAL_ARRAY);
7fd59977 248 }
5e27df78 249 if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
2166f0fa 250 {
5e27df78 251 myVbos[VBOVtexels]->BindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY);
7fd59977 252 }
a577aaab 253 if (!myVbos[VBOVcolours].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0)
2166f0fa 254 {
5e27df78 255 myVbos[VBOVcolours]->BindFixed (aGlContext, GL_COLOR_ARRAY);
256 glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
2166f0fa 257 glEnable (GL_COLOR_MATERIAL);
7fd59977 258 }
259 }
2166f0fa 260
5e27df78 261 /// OCC22236 NOTE: draw for all situations:
262 /// 1) draw elements from myPArray->bufferVBO[VBOEdges] indicies array
263 /// 2) draw elements from vertice array, when bounds defines count of primitive's verts.
264 /// 3) draw primitive by vertexes if no edges and bounds array is specified
265 if (toDrawVbo())
2166f0fa 266 {
5e27df78 267 if (!myVbos[VBOEdges].IsNull())
2166f0fa 268 {
5e27df78 269 myVbos[VBOEdges]->Bind (aGlContext);
2166f0fa
SK
270 if (myPArray->num_bounds > 0)
271 {
272 // draw primitives by vertex count with the indicies
273 Tint* anOffset = NULL;
274 for (i = 0; i < myPArray->num_bounds; ++i)
275 {
7cc2d520 276 if (pfc != NULL) glColor3fv (pfc[i].rgb);
5e27df78 277 glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), anOffset);
bf75be98 278 anOffset += myPArray->bounds[i];
762aacae
A
279 }
280 }
2166f0fa
SK
281 else
282 {
283 // draw one (or sequential) primitive by the indicies
5e27df78 284 glDrawElements (myDrawMode, myPArray->num_edges, myVbos[VBOEdges]->GetDataType(), NULL);
762aacae 285 }
5e27df78 286 myVbos[VBOEdges]->Unbind (aGlContext);
7fd59977 287 }
2166f0fa
SK
288 else if (myPArray->num_bounds > 0)
289 {
290 for (i = n = 0; i < myPArray->num_bounds; ++i)
291 {
7cc2d520 292 if (pfc != NULL) glColor3fv (pfc[i].rgb);
2166f0fa
SK
293 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
294 n += myPArray->bounds[i];
7fd59977 295 }
296 }
2166f0fa
SK
297 else
298 {
a577aaab 299 if (myDrawMode == GL_POINTS)
300 {
301 DrawMarkers (theWorkspace);
302 }
303 else
304 {
305 glDrawArrays (myDrawMode, 0, myVbos[VBOVertices]->GetElemsNb());
306 }
762aacae
A
307 }
308
2166f0fa 309 // bind with 0
5e27df78 310 myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY);
311 if (!myVbos[VBOVnormals].IsNull())
312 {
313 myVbos[VBOVnormals]->UnbindFixed (aGlContext, GL_NORMAL_ARRAY);
314 }
315 if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
316 {
317 myVbos[VBOVtexels]->UnbindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY);
318 }
319 if (!myVbos[VBOVcolours].IsNull())
320 {
321 myVbos[VBOVcolours]->UnbindFixed (aGlContext, GL_COLOR_ARRAY);
322 glDisable (GL_COLOR_MATERIAL);
323 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
324 }
bf75be98 325 }
2166f0fa
SK
326 else
327 {
328 if (myPArray->num_bounds > 0)
329 {
330 if (myPArray->num_edges > 0)
331 {
332 for (i = n = 0; i < myPArray->num_bounds; ++i)
333 {
334 if (pfc != NULL) glColor3fv (pfc[i].rgb);
5e27df78 335 glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]);
2166f0fa
SK
336 n += myPArray->bounds[i];
337 }
338 }
339 else
340 {
341 for (i = n = 0; i < myPArray->num_bounds; ++i)
342 {
7cc2d520 343 if (pfc != NULL) glColor3fv (pfc[i].rgb);
5e27df78 344 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
2166f0fa
SK
345 n += myPArray->bounds[i];
346 }
7fd59977 347 }
2166f0fa
SK
348 }
349 else if (myPArray->num_edges > 0)
350 {
5e27df78 351 glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges);
2166f0fa
SK
352 }
353 else
354 {
a577aaab 355 if (myDrawMode == GL_POINTS)
356 {
357 DrawMarkers (theWorkspace);
358 }
359 else
360 {
361 glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
362 }
2166f0fa 363 }
7fd59977 364
5e27df78 365 if (pvc != NULL)
366 {
367 glDisable (GL_COLOR_MATERIAL);
368 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
369 }
2166f0fa 370
2166f0fa 371 glDisableClientState (GL_VERTEX_ARRAY);
5e27df78 372 if (myPArray->vcolours != NULL)
373 glDisableClientState (GL_COLOR_ARRAY);
374 if (myPArray->vnormals != NULL)
375 glDisableClientState (GL_NORMAL_ARRAY);
376 if (myPArray->vtexels != NULL)
377 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
378 }
7fd59977 379 }
380
de75ed09 381 // On some NVIDIA graphic cards, using glEdgeFlagPointer() in
382 // combination with VBO (edge flag data put into a VBO buffer)
383 // leads to a crash in a driver. Therefore, edge flags are simply
384 // igonored when VBOs are enabled, so all the edges are drawn if
385 // edge visibility is turned on. In order to draw edges selectively,
386 // either disable VBO or turn off edge visibilty in the current
387 // primitive array and create a separate primitive array (segments)
388 // and put edges to be drawn into it.
389 if (theEdgeFlag && myDrawMode > GL_LINE_STRIP)
2166f0fa 390 {
de75ed09 391 DrawEdges (theEdgeColour, theWorkspace);
2166f0fa
SK
392 }
393
394 if (myDrawMode <= GL_LINE_STRIP)
7fd59977 395 glPopAttrib();
396}
397
2166f0fa
SK
398// =======================================================================
399// function : DrawEdges
400// purpose :
401// =======================================================================
402void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR* theEdgeColour,
403 const Handle(OpenGl_Workspace)& theWorkspace) const
7fd59977 404{
2166f0fa 405 glDisable (GL_LIGHTING);
7fd59977 406
2166f0fa
SK
407 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
408 const OpenGl_AspectLine* anAspectLineOld = NULL;
409 if (myDrawMode > GL_LINE_STRIP)
410 {
411 anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
412 theWorkspace->AspectLine (Standard_True);
7fd59977 413
2166f0fa
SK
414 glPushAttrib (GL_POLYGON_BIT);
415 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
416 }
7fd59977 417
2166f0fa 418 Tint i, j, n;
7fd59977 419
5e27df78 420 /// OCC22236 NOTE: draw edges for all situations:
421 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indicies array
422 /// 2) draw elements from vertice array, when bounds defines count of primitive's verts.
423 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
424 if (toDrawVbo())
bf75be98 425 {
5e27df78 426 myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY);
2166f0fa 427 glColor3fv (theEdgeColour->rgb);
5e27df78 428 if (!myVbos[VBOEdges].IsNull())
2166f0fa 429 {
5e27df78 430 myVbos[VBOEdges]->Bind (aGlContext);
2166f0fa 431
762aacae 432 // draw primitives by vertex count with the indicies
2166f0fa
SK
433 if (myPArray->num_bounds > 0)
434 {
762aacae 435 Tint* offset = 0;
2166f0fa
SK
436 for (i = 0, offset = 0; i < myPArray->num_bounds; ++i)
437 {
5e27df78 438 glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), offset);
2166f0fa 439 offset += myPArray->bounds[i];
762aacae
A
440 }
441 }
442 // draw one (or sequential) primitive by the indicies
2166f0fa
SK
443 else
444 {
5e27df78 445 glDrawElements (myDrawMode, myVbos[VBOEdges]->GetElemsNb(), myVbos[VBOEdges]->GetDataType(), NULL);
762aacae 446 }
5e27df78 447 myVbos[VBOEdges]->Unbind (aGlContext);
7fd59977 448 }
2166f0fa
SK
449 else if (myPArray->num_bounds > 0)
450 {
451 for (i = n = 0; i < myPArray->num_bounds; ++i)
452 {
453 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
454 n += myPArray->bounds[i];
7fd59977 455 }
456 }
2166f0fa
SK
457 else
458 {
459 glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
762aacae
A
460 }
461
462 // unbind buffers
5e27df78 463 myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY);
2166f0fa
SK
464 }
465 else
466 {
467 glEnableClientState (GL_VERTEX_ARRAY);
468 glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
2166f0fa
SK
469
470 glColor3fv (theEdgeColour->rgb);
471 if (myPArray->num_bounds > 0)
472 {
473 if (myPArray->num_edges > 0)
474 {
475 for (i = n = 0; i < myPArray->num_bounds; ++i)
476 {
477 if (myPArray->edge_vis)
478 {
479 glBegin (myDrawMode);
480 for (j = 0; j < myPArray->bounds[i]; ++j)
481 {
482 glEdgeFlag (myPArray->edge_vis[n+j]);
483 glVertex3fv (&myPArray->vertices[myPArray->edges[n+j]].xyz[0]);
484 }
485 glEnd();
7fd59977 486 }
2166f0fa
SK
487 else
488 {
5e27df78 489 glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]);
7fd59977 490 }
2166f0fa 491 n += myPArray->bounds[i];
7fd59977 492 }
2166f0fa 493 }
7fd59977 494 else
2166f0fa
SK
495 {
496 for (i = n = 0 ; i < myPArray->num_bounds; ++i)
497 {
5e27df78 498 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
2166f0fa
SK
499 n += myPArray->bounds[i];
500 }
501 }
bf75be98 502 }
2166f0fa
SK
503 else if (myPArray->num_edges > 0)
504 {
505 if (myPArray->edge_vis)
506 {
507 glBegin (myDrawMode);
508 for (i = 0; i < myPArray->num_edges; ++i)
509 {
510 glEdgeFlag (myPArray->edge_vis[i]);
511 glVertex3fv (&myPArray->vertices[myPArray->edges[i]].xyz[0]);
512 }
513 glEnd();
514 }
7fd59977 515 else
2166f0fa 516 {
5e27df78 517 glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges);
7fd59977 518 }
519 }
2166f0fa
SK
520 else
521 {
5e27df78 522 glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
7fd59977 523 }
2166f0fa
SK
524 }
525
526 if (myDrawMode > GL_LINE_STRIP)
527 {
528 // Restore line context
529 theWorkspace->SetAspectLine (anAspectLineOld);
7fd59977 530 glPopAttrib();
531 }
532}
533
a577aaab 534// =======================================================================
535// function : DrawMarkers
536// purpose :
537// =======================================================================
538void OpenGl_PrimitiveArray::DrawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
539{
540 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True);
541 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
542 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->Sprite();
543 const Standard_Boolean isHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT);
544 if (aCtx->IsGlGreaterEqual (2, 0)
545 && !aSpriteNorm.IsNull() && !aSpriteNorm->IsDisplayList())
546 {
547 // Textured markers will be drawn with the point sprites
548 glPointSize (anAspectMarker->MarkerSize());
549
550 Handle(OpenGl_Texture) aTextureBack;
551 if (anAspectMarker->Type() != Aspect_TOM_POINT)
552 {
553 const Handle(OpenGl_PointSprite)& aSprite = (isHilight && anAspectMarker->SpriteHighlight()->IsValid())
554 ? anAspectMarker->SpriteHighlight()
555 : aSpriteNorm;
556 aTextureBack = theWorkspace->EnableTexture (aSprite);
557
558 glEnable (GL_ALPHA_TEST);
559 glAlphaFunc (GL_GEQUAL, 0.1f);
560
561 glEnable (GL_BLEND);
562 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
563 }
564
565 glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs);
566
567 glDisable (GL_BLEND);
568 glDisable (GL_ALPHA_TEST);
569 if (anAspectMarker->Type() != Aspect_TOM_POINT)
570 {
571 theWorkspace->EnableTexture (aTextureBack);
572 }
573 glPointSize (1.0f);
574 return;
575 }
576
577 // Textured markers will be drawn with the glBitmap
a577aaab 578 if (anAspectMarker->Type() == Aspect_TOM_POINT
579 || anAspectMarker->Type() == Aspect_TOM_O_POINT)
580 {
abe46077 581 const GLfloat aPntSize = anAspectMarker->Type() == Aspect_TOM_POINT
582 ? anAspectMarker->MarkerSize()
583 : 0.0f;
584 if (aPntSize > 0.0f)
585 {
586 glPointSize (aPntSize);
587 }
a577aaab 588 glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs);
abe46077 589 if (aPntSize > 0.0f)
590 {
591 glPointSize (1.0f);
592 }
a577aaab 593 }
594
595 if (anAspectMarker->Type() != Aspect_TOM_POINT
596 && !aSpriteNorm.IsNull())
597 {
598 if (!isHilight && (myPArray->vcolours != NULL))
599 {
600 for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++)
601 {
602 glColor4ubv ((GLubyte* )&myPArray->vcolours[anIter]);
603 glRasterPos3fv (myPArray->vertices[anIter].xyz);
604 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
605 }
606 }
607 else
608 {
609 for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++)
610 {
611 glRasterPos3fv (myPArray->vertices[anIter].xyz);
612 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
613 }
614 }
615 }
616}
617
2166f0fa
SK
618// =======================================================================
619// function : OpenGl_PrimitiveArray
620// purpose :
621// =======================================================================
622OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (CALL_DEF_PARRAY* thePArray)
623: myPArray (thePArray),
5e27df78 624 myDrawMode (DRAW_MODE_NONE),
625 myIsVboInit (Standard_False)
2166f0fa
SK
626{
627 switch (myPArray->type)
628 {
629 case TelPointsArrayType:
630 myDrawMode = GL_POINTS;
631 break;
632 case TelPolylinesArrayType:
633 myDrawMode = GL_LINE_STRIP;
634 break;
635 case TelSegmentsArrayType:
636 myDrawMode = GL_LINES;
637 break;
638 case TelPolygonsArrayType:
639 myDrawMode = GL_POLYGON;
640 break;
641 case TelTrianglesArrayType:
642 myDrawMode = GL_TRIANGLES;
643 break;
644 case TelQuadranglesArrayType:
645 myDrawMode = GL_QUADS;
646 break;
647 case TelTriangleStripsArrayType:
648 myDrawMode = GL_TRIANGLE_STRIP;
649 break;
650 case TelQuadrangleStripsArrayType:
651 myDrawMode = GL_QUAD_STRIP;
652 break;
653 case TelTriangleFansArrayType:
654 myDrawMode = GL_TRIANGLE_FAN;
655 break;
656 }
657}
658
659// =======================================================================
660// function : ~OpenGl_PrimitiveArray
661// purpose :
662// =======================================================================
5e27df78 663OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
2166f0fa 664{
5e27df78 665 //
666}
2166f0fa 667
5e27df78 668// =======================================================================
669// function : Release
670// purpose :
671// =======================================================================
672void OpenGl_PrimitiveArray::Release (const Handle(OpenGl_Context)& theContext)
673{
674 for (Standard_Integer anIter = 0; anIter < VBOMaxType; ++anIter)
2166f0fa 675 {
5e27df78 676 if (!myVbos[anIter].IsNull())
677 {
dd8a4ce9 678 if (!theContext.IsNull())
679 {
680 theContext->DelayedRelease (myVbos[anIter]);
681 }
5e27df78 682 myVbos[anIter].Nullify();
683 }
2166f0fa
SK
684 }
685}
686
687// =======================================================================
688// function : Render
689// purpose :
690// =======================================================================
691void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
692{
5e27df78 693 if (myPArray == NULL || myDrawMode == DRAW_MODE_NONE || myPArray->num_vertexs <= 0)
bf75be98 694 {
2166f0fa 695 return;
bf75be98 696 }
2166f0fa 697
a577aaab 698 const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
699 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
700 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS);
701
2166f0fa 702 // create VBOs on first render call
58655684 703 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
a577aaab 704 if (!myIsVboInit
705 && !aCtx->caps->vboDisable
706 && aCtx->core15 != NULL
707 && (myDrawMode != GL_POINTS || anAspectMarker->Sprite().IsNull() || !anAspectMarker->Sprite()->IsDisplayList()))
2166f0fa 708 {
cbf18624 709 if (!BuildVBO (theWorkspace))
710 {
711 TCollection_ExtendedString aMsg;
712 aMsg += "VBO creation for Primitive Array has failed for ";
713 aMsg += myPArray->num_vertexs;
714 aMsg += " vertices. Out of memory?";
715 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
716 }
5e27df78 717 myIsVboInit = Standard_True;
2166f0fa
SK
718 }
719
720 switch (myPArray->type)
721 {
722 case TelPointsArrayType:
723 case TelPolylinesArrayType:
724 case TelSegmentsArrayType:
725 {
726 glDisable (GL_LIGHTING);
2166f0fa
SK
727 break;
728 }
729 default:
730 break;
731 }
732
bf75be98 733 Tint aFrontLightingModel = anAspectFace->IntFront.color_mask;
734 const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront.matcol;
2166f0fa 735 const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
17f65eb2 736 const TEL_COLOUR* aLineColor = (myPArray->type == TelPointsArrayType) ? &anAspectMarker->Color() : &anAspectLine->Color();
2166f0fa
SK
737
738 // Use highlight colors
739 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
bf75be98 740 {
2166f0fa
SK
741 anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
742 aFrontLightingModel = 0;
743 }
744
745 DrawArray (aFrontLightingModel,
bf75be98 746 anAspectFace->InteriorStyle,
747 anAspectFace->Edge,
2166f0fa
SK
748 anInteriorColor,
749 aLineColor,
750 anEdgeColor,
bf75be98 751 &anAspectFace->IntFront,
2166f0fa 752 theWorkspace);
2166f0fa 753}