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