0024345: TKOpenGl - GLSL compatibility issues on NV40 (GeForce 6xxx/7xxx)
[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;
7fd59977 210 }
211
2166f0fa
SK
212 // Temporarily disable environment mapping
213 if (myDrawMode <= GL_LINE_STRIP)
214 {
215 glPushAttrib (GL_ENABLE_BIT);
216 glDisable (GL_TEXTURE_1D);
217 glDisable (GL_TEXTURE_2D);
7fd59977 218 }
219
de75ed09 220 if ((myDrawMode > GL_LINE_STRIP && theInteriorStyle != Aspect_IS_EMPTY) ||
221 (myDrawMode <= GL_LINE_STRIP))
2166f0fa
SK
222 {
223 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
224 {
7fd59977 225 pfc = NULL;
226 pvc = NULL;
227 }
228
2166f0fa
SK
229 if (theInteriorStyle == Aspect_IS_HIDDENLINE)
230 {
231 theEdgeFlag = 1;
7fd59977 232 pfc = NULL;
233 pvc = NULL;
234 }
235
2166f0fa 236 // Sometimes the GL_LIGHTING mode is activated here
bf75be98 237 // without glEnable(GL_LIGHTING) call for an unknown reason, so it is necessary
2166f0fa
SK
238 // to call glEnable(GL_LIGHTING) to synchronize Light On/Off mechanism*
239 if (theLightingModel == 0 || myDrawMode <= GL_LINE_STRIP)
240 glDisable (GL_LIGHTING);
241 else
242 glEnable (GL_LIGHTING);
243
5e27df78 244 if (!toDrawVbo())
2166f0fa
SK
245 {
246 if (myPArray->vertices != NULL)
247 {
248 glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
249 glEnableClientState (GL_VERTEX_ARRAY);
250 }
251 if (myPArray->vnormals != NULL)
252 {
253 glNormalPointer (GL_FLOAT, 0, myPArray->vnormals); // array of normals
254 glEnableClientState (GL_NORMAL_ARRAY);
255 }
256 if (myPArray->vtexels != NULL)
257 {
258 glTexCoordPointer (2, GL_FLOAT, 0, myPArray->vtexels); // array of texture coordinates
259 glEnableClientState (GL_TEXTURE_COORD_ARRAY);
260 }
7fd59977 261
a577aaab 262 if ((pvc != NULL) && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0)
2166f0fa
SK
263 {
264 glColorPointer (4, GL_UNSIGNED_BYTE, 0, pvc); // array of colors
265 glEnableClientState (GL_COLOR_ARRAY);
266 glColorMaterial (GL_FRONT_AND_BACK,GL_AMBIENT_AND_DIFFUSE);
267 glEnable (GL_COLOR_MATERIAL);
7fd59977 268 }
269 }
5e27df78 270 else
2166f0fa
SK
271 {
272 // Bindings concrete pointer in accordance with VBO buffer
5e27df78 273 myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY);
274 if (!myVbos[VBOVnormals].IsNull())
2166f0fa 275 {
5e27df78 276 myVbos[VBOVnormals]->BindFixed (aGlContext, GL_NORMAL_ARRAY);
7fd59977 277 }
5e27df78 278 if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
2166f0fa 279 {
5e27df78 280 myVbos[VBOVtexels]->BindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY);
7fd59977 281 }
a577aaab 282 if (!myVbos[VBOVcolours].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT) == 0)
2166f0fa 283 {
5e27df78 284 myVbos[VBOVcolours]->BindFixed (aGlContext, GL_COLOR_ARRAY);
285 glColorMaterial (GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE);
2166f0fa 286 glEnable (GL_COLOR_MATERIAL);
7fd59977 287 }
288 }
2166f0fa 289
5e27df78 290 /// OCC22236 NOTE: draw for all situations:
291 /// 1) draw elements from myPArray->bufferVBO[VBOEdges] indicies array
292 /// 2) draw elements from vertice array, when bounds defines count of primitive's verts.
293 /// 3) draw primitive by vertexes if no edges and bounds array is specified
294 if (toDrawVbo())
2166f0fa 295 {
5e27df78 296 if (!myVbos[VBOEdges].IsNull())
2166f0fa 297 {
5e27df78 298 myVbos[VBOEdges]->Bind (aGlContext);
2166f0fa
SK
299 if (myPArray->num_bounds > 0)
300 {
301 // draw primitives by vertex count with the indicies
302 Tint* anOffset = NULL;
303 for (i = 0; i < myPArray->num_bounds; ++i)
304 {
7cc2d520 305 if (pfc != NULL) glColor3fv (pfc[i].rgb);
5e27df78 306 glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), anOffset);
bf75be98 307 anOffset += myPArray->bounds[i];
762aacae
A
308 }
309 }
2166f0fa
SK
310 else
311 {
312 // draw one (or sequential) primitive by the indicies
5e27df78 313 glDrawElements (myDrawMode, myPArray->num_edges, myVbos[VBOEdges]->GetDataType(), NULL);
762aacae 314 }
5e27df78 315 myVbos[VBOEdges]->Unbind (aGlContext);
7fd59977 316 }
2166f0fa
SK
317 else if (myPArray->num_bounds > 0)
318 {
319 for (i = n = 0; i < myPArray->num_bounds; ++i)
320 {
7cc2d520 321 if (pfc != NULL) glColor3fv (pfc[i].rgb);
2166f0fa
SK
322 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
323 n += myPArray->bounds[i];
7fd59977 324 }
325 }
2166f0fa
SK
326 else
327 {
a577aaab 328 if (myDrawMode == GL_POINTS)
329 {
330 DrawMarkers (theWorkspace);
331 }
332 else
333 {
334 glDrawArrays (myDrawMode, 0, myVbos[VBOVertices]->GetElemsNb());
335 }
762aacae
A
336 }
337
2166f0fa 338 // bind with 0
5e27df78 339 myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY);
340 if (!myVbos[VBOVnormals].IsNull())
341 {
342 myVbos[VBOVnormals]->UnbindFixed (aGlContext, GL_NORMAL_ARRAY);
343 }
344 if (!myVbos[VBOVtexels].IsNull() && (theWorkspace->NamedStatus & OPENGL_NS_FORBIDSETTEX) == 0)
345 {
346 myVbos[VBOVtexels]->UnbindFixed (aGlContext, GL_TEXTURE_COORD_ARRAY);
347 }
348 if (!myVbos[VBOVcolours].IsNull())
349 {
350 myVbos[VBOVcolours]->UnbindFixed (aGlContext, GL_COLOR_ARRAY);
351 glDisable (GL_COLOR_MATERIAL);
352 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
353 }
bf75be98 354 }
2166f0fa
SK
355 else
356 {
357 if (myPArray->num_bounds > 0)
358 {
359 if (myPArray->num_edges > 0)
360 {
361 for (i = n = 0; i < myPArray->num_bounds; ++i)
362 {
363 if (pfc != NULL) glColor3fv (pfc[i].rgb);
5e27df78 364 glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]);
2166f0fa
SK
365 n += myPArray->bounds[i];
366 }
367 }
368 else
369 {
370 for (i = n = 0; i < myPArray->num_bounds; ++i)
371 {
7cc2d520 372 if (pfc != NULL) glColor3fv (pfc[i].rgb);
5e27df78 373 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
2166f0fa
SK
374 n += myPArray->bounds[i];
375 }
7fd59977 376 }
2166f0fa
SK
377 }
378 else if (myPArray->num_edges > 0)
379 {
5e27df78 380 glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges);
2166f0fa
SK
381 }
382 else
383 {
a577aaab 384 if (myDrawMode == GL_POINTS)
385 {
386 DrawMarkers (theWorkspace);
387 }
388 else
389 {
390 glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
391 }
2166f0fa 392 }
7fd59977 393
5e27df78 394 if (pvc != NULL)
395 {
396 glDisable (GL_COLOR_MATERIAL);
397 theWorkspace->NamedStatus |= OPENGL_NS_RESMAT; // Reset material
398 }
2166f0fa 399
2166f0fa 400 glDisableClientState (GL_VERTEX_ARRAY);
5e27df78 401 if (myPArray->vcolours != NULL)
402 glDisableClientState (GL_COLOR_ARRAY);
403 if (myPArray->vnormals != NULL)
404 glDisableClientState (GL_NORMAL_ARRAY);
405 if (myPArray->vtexels != NULL)
406 glDisableClientState (GL_TEXTURE_COORD_ARRAY);
407 }
7fd59977 408 }
409
de75ed09 410 // On some NVIDIA graphic cards, using glEdgeFlagPointer() in
411 // combination with VBO (edge flag data put into a VBO buffer)
412 // leads to a crash in a driver. Therefore, edge flags are simply
413 // igonored when VBOs are enabled, so all the edges are drawn if
414 // edge visibility is turned on. In order to draw edges selectively,
415 // either disable VBO or turn off edge visibilty in the current
416 // primitive array and create a separate primitive array (segments)
417 // and put edges to be drawn into it.
418 if (theEdgeFlag && myDrawMode > GL_LINE_STRIP)
2166f0fa 419 {
de75ed09 420 DrawEdges (theEdgeColour, theWorkspace);
2166f0fa
SK
421 }
422
423 if (myDrawMode <= GL_LINE_STRIP)
7fd59977 424 glPopAttrib();
425}
426
2166f0fa
SK
427// =======================================================================
428// function : DrawEdges
429// purpose :
430// =======================================================================
431void OpenGl_PrimitiveArray::DrawEdges (const TEL_COLOUR* theEdgeColour,
432 const Handle(OpenGl_Workspace)& theWorkspace) const
7fd59977 433{
2166f0fa 434 glDisable (GL_LIGHTING);
7fd59977 435
2166f0fa
SK
436 const Handle(OpenGl_Context)& aGlContext = theWorkspace->GetGlContext();
437 const OpenGl_AspectLine* anAspectLineOld = NULL;
438 if (myDrawMode > GL_LINE_STRIP)
439 {
440 anAspectLineOld = theWorkspace->SetAspectLine (theWorkspace->AspectFace (Standard_True)->AspectEdge());
30f0ad28 441 const OpenGl_AspectLine* anAspect = theWorkspace->AspectLine (Standard_True);
7fd59977 442
2166f0fa
SK
443 glPushAttrib (GL_POLYGON_BIT);
444 glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
30f0ad28 445
446 if (aGlContext->IsGlGreaterEqual (2, 0))
447 {
448 BindProgramWithMaterial (theWorkspace, anAspect);
449 }
2166f0fa 450 }
7fd59977 451
2166f0fa 452 Tint i, j, n;
7fd59977 453
5e27df78 454 /// OCC22236 NOTE: draw edges for all situations:
455 /// 1) draw elements with GL_LINE style as edges from myPArray->bufferVBO[VBOEdges] indicies array
456 /// 2) draw elements from vertice array, when bounds defines count of primitive's verts.
457 /// 3) draw primitive's edges by vertexes if no edges and bounds array is specified
458 if (toDrawVbo())
bf75be98 459 {
5e27df78 460 myVbos[VBOVertices]->BindFixed (aGlContext, GL_VERTEX_ARRAY);
2166f0fa 461 glColor3fv (theEdgeColour->rgb);
5e27df78 462 if (!myVbos[VBOEdges].IsNull())
2166f0fa 463 {
5e27df78 464 myVbos[VBOEdges]->Bind (aGlContext);
2166f0fa 465
762aacae 466 // draw primitives by vertex count with the indicies
2166f0fa
SK
467 if (myPArray->num_bounds > 0)
468 {
762aacae 469 Tint* offset = 0;
2166f0fa
SK
470 for (i = 0, offset = 0; i < myPArray->num_bounds; ++i)
471 {
5e27df78 472 glDrawElements (myDrawMode, myPArray->bounds[i], myVbos[VBOEdges]->GetDataType(), offset);
2166f0fa 473 offset += myPArray->bounds[i];
762aacae
A
474 }
475 }
476 // draw one (or sequential) primitive by the indicies
2166f0fa
SK
477 else
478 {
5e27df78 479 glDrawElements (myDrawMode, myVbos[VBOEdges]->GetElemsNb(), myVbos[VBOEdges]->GetDataType(), NULL);
762aacae 480 }
5e27df78 481 myVbos[VBOEdges]->Unbind (aGlContext);
7fd59977 482 }
2166f0fa
SK
483 else if (myPArray->num_bounds > 0)
484 {
485 for (i = n = 0; i < myPArray->num_bounds; ++i)
486 {
487 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
488 n += myPArray->bounds[i];
7fd59977 489 }
490 }
2166f0fa
SK
491 else
492 {
493 glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
762aacae
A
494 }
495
496 // unbind buffers
5e27df78 497 myVbos[VBOVertices]->UnbindFixed (aGlContext, GL_VERTEX_ARRAY);
2166f0fa
SK
498 }
499 else
500 {
501 glEnableClientState (GL_VERTEX_ARRAY);
502 glVertexPointer (3, GL_FLOAT, 0, myPArray->vertices); // array of vertices
2166f0fa
SK
503
504 glColor3fv (theEdgeColour->rgb);
505 if (myPArray->num_bounds > 0)
506 {
507 if (myPArray->num_edges > 0)
508 {
509 for (i = n = 0; i < myPArray->num_bounds; ++i)
510 {
511 if (myPArray->edge_vis)
512 {
513 glBegin (myDrawMode);
514 for (j = 0; j < myPArray->bounds[i]; ++j)
515 {
516 glEdgeFlag (myPArray->edge_vis[n+j]);
517 glVertex3fv (&myPArray->vertices[myPArray->edges[n+j]].xyz[0]);
518 }
519 glEnd();
7fd59977 520 }
2166f0fa
SK
521 else
522 {
5e27df78 523 glDrawElements (myDrawMode, myPArray->bounds[i], GL_UNSIGNED_INT, (GLenum* )&myPArray->edges[n]);
7fd59977 524 }
2166f0fa 525 n += myPArray->bounds[i];
7fd59977 526 }
2166f0fa 527 }
7fd59977 528 else
2166f0fa
SK
529 {
530 for (i = n = 0 ; i < myPArray->num_bounds; ++i)
531 {
5e27df78 532 glDrawArrays (myDrawMode, n, myPArray->bounds[i]);
2166f0fa
SK
533 n += myPArray->bounds[i];
534 }
535 }
bf75be98 536 }
2166f0fa
SK
537 else if (myPArray->num_edges > 0)
538 {
539 if (myPArray->edge_vis)
540 {
541 glBegin (myDrawMode);
542 for (i = 0; i < myPArray->num_edges; ++i)
543 {
544 glEdgeFlag (myPArray->edge_vis[i]);
545 glVertex3fv (&myPArray->vertices[myPArray->edges[i]].xyz[0]);
546 }
547 glEnd();
548 }
7fd59977 549 else
2166f0fa 550 {
5e27df78 551 glDrawElements (myDrawMode, myPArray->num_edges, GL_UNSIGNED_INT, (GLenum* )myPArray->edges);
7fd59977 552 }
553 }
2166f0fa
SK
554 else
555 {
5e27df78 556 glDrawArrays (myDrawMode, 0, myPArray->num_vertexs);
7fd59977 557 }
2166f0fa
SK
558 }
559
560 if (myDrawMode > GL_LINE_STRIP)
561 {
562 // Restore line context
563 theWorkspace->SetAspectLine (anAspectLineOld);
7fd59977 564 glPopAttrib();
565 }
566}
567
a577aaab 568// =======================================================================
569// function : DrawMarkers
570// purpose :
571// =======================================================================
572void OpenGl_PrimitiveArray::DrawMarkers (const Handle(OpenGl_Workspace)& theWorkspace) const
573{
574 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (Standard_True);
575 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
30f0ad28 576 const Handle(OpenGl_PointSprite)& aSpriteNorm = anAspectMarker->SpriteRes (theWorkspace);
a577aaab 577 const Standard_Boolean isHilight = (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT);
578 if (aCtx->IsGlGreaterEqual (2, 0)
579 && !aSpriteNorm.IsNull() && !aSpriteNorm->IsDisplayList())
580 {
581 // Textured markers will be drawn with the point sprites
582 glPointSize (anAspectMarker->MarkerSize());
583
584 Handle(OpenGl_Texture) aTextureBack;
585 if (anAspectMarker->Type() != Aspect_TOM_POINT)
586 {
30f0ad28 587 const Handle(OpenGl_PointSprite)& aSprite = (isHilight && anAspectMarker->SpriteHighlightRes (theWorkspace)->IsValid())
588 ? anAspectMarker->SpriteHighlightRes (theWorkspace)
a577aaab 589 : aSpriteNorm;
590 aTextureBack = theWorkspace->EnableTexture (aSprite);
591
592 glEnable (GL_ALPHA_TEST);
593 glAlphaFunc (GL_GEQUAL, 0.1f);
594
595 glEnable (GL_BLEND);
596 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
597 }
598
599 glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs);
600
601 glDisable (GL_BLEND);
602 glDisable (GL_ALPHA_TEST);
603 if (anAspectMarker->Type() != Aspect_TOM_POINT)
604 {
605 theWorkspace->EnableTexture (aTextureBack);
606 }
607 glPointSize (1.0f);
608 return;
609 }
610
611 // Textured markers will be drawn with the glBitmap
a577aaab 612 if (anAspectMarker->Type() == Aspect_TOM_POINT
613 || anAspectMarker->Type() == Aspect_TOM_O_POINT)
614 {
abe46077 615 const GLfloat aPntSize = anAspectMarker->Type() == Aspect_TOM_POINT
616 ? anAspectMarker->MarkerSize()
617 : 0.0f;
618 if (aPntSize > 0.0f)
619 {
620 glPointSize (aPntSize);
621 }
a577aaab 622 glDrawArrays (myDrawMode, 0, toDrawVbo() ? myVbos[VBOVertices]->GetElemsNb() : myPArray->num_vertexs);
abe46077 623 if (aPntSize > 0.0f)
624 {
625 glPointSize (1.0f);
626 }
a577aaab 627 }
628
629 if (anAspectMarker->Type() != Aspect_TOM_POINT
630 && !aSpriteNorm.IsNull())
631 {
632 if (!isHilight && (myPArray->vcolours != NULL))
633 {
634 for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++)
635 {
636 glColor4ubv ((GLubyte* )&myPArray->vcolours[anIter]);
637 glRasterPos3fv (myPArray->vertices[anIter].xyz);
638 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
639 }
640 }
641 else
642 {
643 for (Standard_Integer anIter = 0; anIter < myPArray->num_vertexs; anIter++)
644 {
645 glRasterPos3fv (myPArray->vertices[anIter].xyz);
646 aSpriteNorm->DrawBitmap (theWorkspace->GetGlContext());
647 }
648 }
649 }
650}
651
2166f0fa
SK
652// =======================================================================
653// function : OpenGl_PrimitiveArray
654// purpose :
655// =======================================================================
656OpenGl_PrimitiveArray::OpenGl_PrimitiveArray (CALL_DEF_PARRAY* thePArray)
657: myPArray (thePArray),
5e27df78 658 myDrawMode (DRAW_MODE_NONE),
659 myIsVboInit (Standard_False)
2166f0fa
SK
660{
661 switch (myPArray->type)
662 {
663 case TelPointsArrayType:
664 myDrawMode = GL_POINTS;
665 break;
666 case TelPolylinesArrayType:
667 myDrawMode = GL_LINE_STRIP;
668 break;
669 case TelSegmentsArrayType:
670 myDrawMode = GL_LINES;
671 break;
672 case TelPolygonsArrayType:
673 myDrawMode = GL_POLYGON;
674 break;
675 case TelTrianglesArrayType:
676 myDrawMode = GL_TRIANGLES;
677 break;
678 case TelQuadranglesArrayType:
679 myDrawMode = GL_QUADS;
680 break;
681 case TelTriangleStripsArrayType:
682 myDrawMode = GL_TRIANGLE_STRIP;
683 break;
684 case TelQuadrangleStripsArrayType:
685 myDrawMode = GL_QUAD_STRIP;
686 break;
687 case TelTriangleFansArrayType:
688 myDrawMode = GL_TRIANGLE_FAN;
689 break;
690 }
691}
692
693// =======================================================================
694// function : ~OpenGl_PrimitiveArray
695// purpose :
696// =======================================================================
5e27df78 697OpenGl_PrimitiveArray::~OpenGl_PrimitiveArray()
2166f0fa 698{
5e27df78 699 //
700}
2166f0fa 701
5e27df78 702// =======================================================================
703// function : Release
704// purpose :
705// =======================================================================
706void OpenGl_PrimitiveArray::Release (const Handle(OpenGl_Context)& theContext)
707{
708 for (Standard_Integer anIter = 0; anIter < VBOMaxType; ++anIter)
2166f0fa 709 {
5e27df78 710 if (!myVbos[anIter].IsNull())
711 {
dd8a4ce9 712 if (!theContext.IsNull())
713 {
714 theContext->DelayedRelease (myVbos[anIter]);
715 }
5e27df78 716 myVbos[anIter].Nullify();
717 }
2166f0fa
SK
718 }
719}
720
721// =======================================================================
722// function : Render
723// purpose :
724// =======================================================================
725void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
726{
5e27df78 727 if (myPArray == NULL || myDrawMode == DRAW_MODE_NONE || myPArray->num_vertexs <= 0)
bf75be98 728 {
2166f0fa 729 return;
bf75be98 730 }
2166f0fa 731
a577aaab 732 const OpenGl_AspectFace* anAspectFace = theWorkspace->AspectFace (Standard_True);
733 const OpenGl_AspectLine* anAspectLine = theWorkspace->AspectLine (Standard_True);
734 const OpenGl_AspectMarker* anAspectMarker = theWorkspace->AspectMarker (myDrawMode == GL_POINTS);
735
2166f0fa 736 // create VBOs on first render call
58655684 737 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
a577aaab 738 if (!myIsVboInit
739 && !aCtx->caps->vboDisable
740 && aCtx->core15 != NULL
30f0ad28 741 && (myDrawMode != GL_POINTS || anAspectMarker->SpriteRes (theWorkspace).IsNull() || !anAspectMarker->SpriteRes (theWorkspace)->IsDisplayList()))
2166f0fa 742 {
cbf18624 743 if (!BuildVBO (theWorkspace))
744 {
745 TCollection_ExtendedString aMsg;
746 aMsg += "VBO creation for Primitive Array has failed for ";
747 aMsg += myPArray->num_vertexs;
748 aMsg += " vertices. Out of memory?";
749 aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB, GL_DEBUG_TYPE_PERFORMANCE_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMsg);
750 }
5e27df78 751 myIsVboInit = Standard_True;
2166f0fa
SK
752 }
753
754 switch (myPArray->type)
755 {
756 case TelPointsArrayType:
757 case TelPolylinesArrayType:
758 case TelSegmentsArrayType:
759 {
760 glDisable (GL_LIGHTING);
2166f0fa
SK
761 break;
762 }
763 default:
764 break;
765 }
766
fd4a6963 767 Tint aFrontLightingModel = anAspectFace->IntFront().color_mask;
768 const TEL_COLOUR* anInteriorColor = &anAspectFace->IntFront().matcol;
2166f0fa 769 const TEL_COLOUR* anEdgeColor = &anAspectFace->AspectEdge()->Color();
17f65eb2 770 const TEL_COLOUR* aLineColor = (myPArray->type == TelPointsArrayType) ? &anAspectMarker->Color() : &anAspectLine->Color();
2166f0fa
SK
771
772 // Use highlight colors
773 if (theWorkspace->NamedStatus & OPENGL_NS_HIGHLIGHT)
bf75be98 774 {
2166f0fa
SK
775 anEdgeColor = anInteriorColor = aLineColor = theWorkspace->HighlightColor;
776 aFrontLightingModel = 0;
777 }
778
30f0ad28 779 if (aCtx->IsGlGreaterEqual (2, 0))
780 {
781 switch (myPArray->type)
782 {
783 case TelPointsArrayType:
784 {
785 BindProgramWithMaterial (theWorkspace, anAspectMarker);
786 break;
787 }
788 case TelSegmentsArrayType:
789 case TelPolylinesArrayType:
790 {
791 BindProgramWithMaterial (theWorkspace, anAspectLine);
792 break;
793 }
794 default: // polygonal array
795 {
796 BindProgramWithMaterial (theWorkspace, anAspectFace);
797 break;
798 }
799 }
800 }
801
2166f0fa 802 DrawArray (aFrontLightingModel,
fd4a6963 803 anAspectFace->InteriorStyle(),
804 anAspectFace->Edge(),
2166f0fa
SK
805 anInteriorColor,
806 aLineColor,
807 anEdgeColor,
fd4a6963 808 &anAspectFace->IntFront(),
2166f0fa 809 theWorkspace);
2166f0fa 810}