0030748: Visualization - Marker displayed in immediate layer ruins QT Quick view...
[occt.git] / src / OpenGl / OpenGl_FrameStatsPrs.cxx
CommitLineData
15669413 1// Copyright (c) 2017 OPEN CASCADE SAS
2//
3// This file is part of Open CASCADE Technology software library.
4//
5// This library is free software; you can redistribute it and/or modify it under
6// the terms of the GNU Lesser General Public License version 2.1 as published
7// by the Free Software Foundation, with special exception defined in the file
8// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9// distribution for complete text of the license and disclaimer of any warranty.
10//
11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
13
14#include <OpenGl_FrameStatsPrs.hxx>
15
16#include <OpenGl_View.hxx>
17#include <OpenGl_ShaderManager.hxx>
18#include <OpenGl_Workspace.hxx>
19
5e30547b 20#include <Graphic3d_ArrayOfTriangles.hxx>
21
22namespace
23{
24 //! Auxiliary structure defining vertex with two attributes.
25 struct OpenGl_Vec3Vec4ub
26 {
27 Graphic3d_Vec3 Pos;
28 Graphic3d_Vec4ub Color;
29 };
30
31 //! Auxiliary function formatting rendering time in " 10 ms (100 FPS)" format.
32 static TCollection_AsciiString formatTimeMs (Standard_Real theSeconds)
33 {
34 const Standard_Real aFpsVal = theSeconds != 0.0 ? 1.0 / theSeconds : 0.0;
35 char aFps[50];
36 Sprintf (aFps, "%.1f", aFpsVal);
37 return TCollection_AsciiString() + Standard_Integer(theSeconds * 1000.0) + " ms (" + aFps + " FPS)";
38 }
39}
40
15669413 41// =======================================================================
42// function : OpenGl_FrameStatsPrs
43// purpose :
44// =======================================================================
45OpenGl_FrameStatsPrs::OpenGl_FrameStatsPrs()
5e30547b 46: myStatsPrev (new OpenGl_FrameStats()),
47 myCountersTrsfPers (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_UPPER, Graphic3d_Vec2i (20, 20))),
48 myChartTrsfPers (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_RIGHT_UPPER, Graphic3d_Vec2i (20, 20))),
49 myChartVertices (new OpenGl_VertexBuffer()),
50 myChartIndices (new OpenGl_IndexBuffer()),
51 myChartLines (new OpenGl_VertexBuffer())
15669413 52{
5e30547b 53 //
15669413 54}
55
56// =======================================================================
57// function : ~OpenGl_FrameStatsPrs
58// purpose :
59// =======================================================================
60OpenGl_FrameStatsPrs::~OpenGl_FrameStatsPrs()
61{
62 //
63}
64
65// =======================================================================
66// function : Release
67// purpose :
68// =======================================================================
69void OpenGl_FrameStatsPrs::Release (OpenGl_Context* theCtx)
70{
5e30547b 71 myCountersText.Release (theCtx);
72 myChartLabels[0].Release (theCtx);
73 myChartLabels[1].Release (theCtx);
74 myChartLabels[2].Release (theCtx);
75 myChartVertices->Release (theCtx);
76 myChartIndices->Release (theCtx);
77 myChartLines->Release (theCtx);
15669413 78}
79
80// =======================================================================
81// function : Update
82// purpose :
83// =======================================================================
84void OpenGl_FrameStatsPrs::Update (const Handle(OpenGl_Workspace)& theWorkspace)
85{
86 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
87 const Handle(OpenGl_FrameStats)& aStats = aCtx->FrameStats();
88 const Graphic3d_RenderingParams& aRendParams = theWorkspace->View()->RenderingParams();
5e30547b 89 myCountersTrsfPers = theWorkspace->View()->RenderingParams().StatsPosition;
90 myChartTrsfPers = theWorkspace->View()->RenderingParams().ChartPosition;
15669413 91 myTextAspect.SetAspect (aRendParams.StatsTextAspect);
92
93 // adjust text alignment depending on corner
5e30547b 94 OpenGl_TextParam aParams;
95 aParams.Height = aRendParams.StatsTextHeight;
96 aParams.HAlign = Graphic3d_HTA_CENTER;
97 aParams.VAlign = Graphic3d_VTA_CENTER;
98 if (!myCountersTrsfPers.IsNull() && (myCountersTrsfPers->Corner2d() & Aspect_TOTP_LEFT) != 0)
15669413 99 {
5e30547b 100 aParams.HAlign = Graphic3d_HTA_LEFT;
15669413 101 }
5e30547b 102 else if (!myCountersTrsfPers.IsNull() && (myCountersTrsfPers->Corner2d() & Aspect_TOTP_RIGHT) != 0)
15669413 103 {
5e30547b 104 aParams.HAlign = Graphic3d_HTA_RIGHT;
15669413 105 }
5e30547b 106 if (!myCountersTrsfPers.IsNull() && (myCountersTrsfPers->Corner2d() & Aspect_TOTP_TOP) != 0)
15669413 107 {
5e30547b 108 aParams.VAlign = Graphic3d_VTA_TOP;
15669413 109 }
5e30547b 110 else if (!myCountersTrsfPers.IsNull() && (myCountersTrsfPers->Corner2d() & Aspect_TOTP_BOTTOM) != 0)
15669413 111 {
5e30547b 112 aParams.VAlign = Graphic3d_VTA_BOTTOM;
15669413 113 }
5e30547b 114 if (aParams.Height != myCountersText.FormatParams().Height
115 || aParams.HAlign != myCountersText.FormatParams().HAlign
116 || aParams.VAlign != myCountersText.FormatParams().VAlign)
15669413 117 {
5e30547b 118 myCountersText.Release (aCtx.operator->());
15669413 119 }
120
5e30547b 121 if (!aStats->IsFrameUpdated (myStatsPrev)
122 && !myCountersText.Text().IsEmpty())
15669413 123 {
124 return;
125 }
126
5e30547b 127 TCollection_AsciiString aText = aStats->FormatStats (aRendParams.CollectedStats);
128 myCountersText.Init (aCtx, aText.ToCString(), OpenGl_Vec3 (0.0f, 0.0f, 0.0f), aParams);
129
130 updateChart (theWorkspace);
131}
132
133// =======================================================================
134// function : updateChart
135// purpose :
136// =======================================================================
137void OpenGl_FrameStatsPrs::updateChart (const Handle(OpenGl_Workspace)& theWorkspace)
138{
139 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
140 const Handle(OpenGl_FrameStats)& aStats = aCtx->FrameStats();
141 const Graphic3d_RenderingParams& aRendParams = theWorkspace->View()->RenderingParams();
142
143 const Standard_Integer aNbBins = aStats->DataFrames().Size();
144 if (aNbBins <= 1)
145 {
dc2749cf 146 myChartIndices ->Release (aCtx.get());
147 myChartVertices->Release (aCtx.get());
148 myChartLines ->Release (aCtx.get());
5e30547b 149 return;
150 }
151
152 Standard_Real aMaxDuration = aRendParams.StatsMaxChartTime;
153 if (aMaxDuration <= 0.0f)
154 {
155 for (Standard_Integer aFrameIter = aStats->DataFrames().Lower(); aFrameIter <= aStats->DataFrames().Upper(); ++aFrameIter)
156 {
157 const Graphic3d_FrameStatsData& aFrame = aStats->DataFrames().Value (aFrameIter);
158 aMaxDuration = Max (aMaxDuration, aFrame.TimerValue (Graphic3d_FrameStatsTimer_ElapsedFrame));
159 }
160 aMaxDuration = Ceiling (aMaxDuration * 1000.0 * 0.1) * 0.001 * 10.0; // round number
161 aMaxDuration = Max (Min (aMaxDuration, 0.1), 0.005); // limit by 100 ms (10 FPS) and 5 ms (200 FPS)
162 }
163
164 const Standard_Integer aNbTimers = 4;
165 const Graphic3d_FrameStatsTimer aTimers[4] =
166 {
167 Graphic3d_FrameStatsTimer_CpuDynamics,
168 Graphic3d_FrameStatsTimer_CpuPicking,
169 Graphic3d_FrameStatsTimer_CpuCulling,
170 Graphic3d_FrameStatsTimer_ElapsedFrame,
171 };
172 const Graphic3d_Vec4ub aColors[4] =
173 {
174 Graphic3d_Vec4ub (255, 0, 0, 127),
175 Graphic3d_Vec4ub (255, 127, 39, 127),
176 Graphic3d_Vec4ub (255, 0, 0, 127),
177 Graphic3d_Vec4ub (0, 255, 0, 127),
178 };
179
180 const Standard_Integer aNbVerts = aNbBins * 4 * aNbTimers;
181 const Standard_Integer aNbIndexes = aNbBins * 2 * 3 * aNbTimers;
182 bool toFillEdges = false;
183 if (myChartArray.IsNull()
184 || myChartArray->VertexNumber() != aNbVerts
185 || myChartArray->EdgeNumber() != aNbIndexes)
186 {
187 myChartArray = new Graphic3d_ArrayOfTriangles (aNbVerts, aNbIndexes, false, true);
188 toFillEdges = true;
189 }
190
191 const Graphic3d_Vec2i aViewSize (aCtx->VirtualViewport()[2], aCtx->VirtualViewport()[3]);
192 Graphic3d_Vec2i aCharSize (aRendParams.ChartSize);
193 if (aCharSize.x() <= 0)
194 {
195 aCharSize.x() = aViewSize.x() / 2;
196 }
197 if (aCharSize.y() <= 0)
198 {
199 aCharSize.y() = Standard_Integer(0.15 * aViewSize.y());
200 }
201
202 const Graphic3d_Vec2d aBinSize (Standard_Real(aCharSize.x()) / Standard_Real(aNbBins), 0.15 * aViewSize.y());
203 Graphic3d_Vec2i anOffset;
204 if (!myChartTrsfPers.IsNull()
205 && myChartTrsfPers->IsTrihedronOr2d())
206 {
207 if ((myChartTrsfPers->Corner2d() & Aspect_TOTP_LEFT) != 0)
208 {
209 anOffset.x() = 0;
210 }
211 else if ((myChartTrsfPers->Corner2d() & Aspect_TOTP_RIGHT) != 0)
212 {
213 anOffset.x() = -aCharSize.x();
214 }
215 else
216 {
217 anOffset.x() = -aCharSize.x() / 2;
218 }
219
220 if ((myChartTrsfPers->Corner2d() & Aspect_TOTP_BOTTOM) != 0)
221 {
222 anOffset.y() = aCharSize.y();
223 }
224 else if ((myChartTrsfPers->Corner2d() & Aspect_TOTP_TOP) != 0)
225 {
226 anOffset.y() = 0;
227 }
228 else
229 {
230 anOffset.y() = aCharSize.y() / 2;
231 }
232 }
233
234 Standard_Integer aVertLast = 1;
235 const bool isTopDown = false;
236 for (Standard_Integer aFrameIter = 0; aFrameIter < aNbBins; ++aFrameIter)
237 {
238 Standard_Integer aFrameIndex = aStats->DataFrames().Lower() + aStats->LastDataFrameIndex() + 1 + aFrameIter;
239 if (aFrameIndex > aStats->DataFrames().Upper())
240 {
241 aFrameIndex -= aNbBins;
242 }
243
244 const Graphic3d_FrameStatsData& aFrame = aStats->DataFrames().Value (aFrameIndex);
245 Standard_Real aTimeElapsed = 0.0;
246 Standard_Real aCurrY = 0.0;
247 for (Standard_Integer aTimerIter = 0; aTimerIter < aNbTimers; ++aTimerIter)
248 {
249 if (aTimers[aTimerIter] == Graphic3d_FrameStatsTimer_ElapsedFrame)
250 {
251 aTimeElapsed = aFrame.TimerValue (aTimers[aTimerIter]);
252 }
253 else
254 {
255 aTimeElapsed += aFrame.TimerValue (aTimers[aTimerIter]);
256 }
257
258 const Standard_Real aBinX1 = anOffset.x() + Standard_Real(aFrameIter) * aBinSize.x();
259 const Standard_Real aBinX2 = aBinX1 + aBinSize.x();
260 const Standard_Real aCurrSizeY = Min (aTimeElapsed / aMaxDuration, 1.2) * aBinSize.y();
261 const Standard_Real aBinY1 = isTopDown ? (anOffset.y() - aCurrY) : (anOffset.y() - aBinSize.y() + aCurrY);
262 const Standard_Real aBinY2 = isTopDown ? (anOffset.y() - aCurrSizeY) : (anOffset.y() - aBinSize.y() + aCurrSizeY);
263 myChartArray->SetVertice (aVertLast + 0, gp_Pnt (aBinX1, aBinY2, 0.0));
264 myChartArray->SetVertice (aVertLast + 1, gp_Pnt (aBinX1, aBinY1, 0.0));
265 myChartArray->SetVertice (aVertLast + 2, gp_Pnt (aBinX2, aBinY1, 0.0));
266 myChartArray->SetVertice (aVertLast + 3, gp_Pnt (aBinX2, aBinY2, 0.0));
267
268 if (toFillEdges)
269 {
270 const Graphic3d_Vec4ub& aTimerColor = aColors[aTimerIter];
271 myChartArray->SetVertexColor (aVertLast + 0, aTimerColor);
272 myChartArray->SetVertexColor (aVertLast + 1, aTimerColor);
273 myChartArray->SetVertexColor (aVertLast + 2, aTimerColor);
274 myChartArray->SetVertexColor (aVertLast + 3, aTimerColor);
275 myChartArray->AddEdges (aVertLast + 0, aVertLast + 1, aVertLast + 3);
276 myChartArray->AddEdges (aVertLast + 1, aVertLast + 2, aVertLast + 3);
277 }
278 aVertLast += 4;
279
280 if (aTimers[aTimerIter] == Graphic3d_FrameStatsTimer_ElapsedFrame)
281 {
282 aTimeElapsed = 0.0;
283 aCurrY = 0.0;
284 }
285 else
286 {
287 aCurrY = aCurrSizeY;
288 }
289 }
290 }
291
292 myChartVertices->init (aCtx,
293 myChartArray->Attributes()->Stride,
294 myChartArray->Attributes()->NbElements,
295 myChartArray->Attributes()->Data(),
296 GL_UNSIGNED_BYTE,
297 myChartArray->Attributes()->Stride);
298 if (myChartArray->Indices()->Stride == 2)
299 {
300 myChartIndices ->Init (aCtx,
301 1,
302 myChartArray->Indices()->NbElements,
303 (const GLushort* )myChartArray->Indices()->Data());
304 }
305 else if (myChartArray->Indices()->Stride == 4)
306 {
307 myChartIndices ->Init (aCtx,
308 1,
309 myChartArray->Indices()->NbElements,
310 (const GLuint* )myChartArray->Indices()->Data());
311 }
15669413 312
5e30547b 313 {
314 const Graphic3d_Vec4ub aWhite (255, 255, 255, 255);
315 const OpenGl_Vec3Vec4ub aLines[4] =
316 {
317 { Graphic3d_Vec3((float )anOffset.x(), (float )anOffset.y(), 0.0f), aWhite },
318 { Graphic3d_Vec3(float(anOffset.x() + aCharSize.x()), (float )anOffset.y(), 0.0f), aWhite },
319 { Graphic3d_Vec3((float )anOffset.x(), float(anOffset.y() - aBinSize.y()), 0.0f), aWhite },
320 { Graphic3d_Vec3(float(anOffset.x() + aCharSize.x()), float(anOffset.y() - aBinSize.y()),+ 0.0f), aWhite },
321 };
322 myChartLines->init (aCtx, sizeof(OpenGl_Vec3Vec4ub), 4, aLines, GL_UNSIGNED_BYTE, sizeof(OpenGl_Vec3Vec4ub));
323 }
324
325 {
326 OpenGl_TextParam aParams;
327 aParams.Height = aRendParams.StatsTextHeight;
328 aParams.HAlign = (!myChartTrsfPers.IsNull()
329 && myChartTrsfPers->IsTrihedronOr2d()
330 && (myChartTrsfPers->Corner2d() & Aspect_TOTP_RIGHT) != 0)
331 ? Graphic3d_HTA_RIGHT
332 : Graphic3d_HTA_LEFT;
333 aParams.VAlign = Graphic3d_VTA_CENTER;
334 TCollection_AsciiString aLabels[3] =
335 {
336 TCollection_AsciiString() + 0 + " ms",
337 formatTimeMs(aMaxDuration * 0.5),
338 formatTimeMs(aMaxDuration)
339 };
340
341 const float aLabX = aParams.HAlign == Graphic3d_HTA_RIGHT
342 ? float(anOffset.x())
343 : float(anOffset.x() + aCharSize.x());
344 myChartLabels[0].Init (aCtx, aLabels[isTopDown ? 0 : 2].ToCString(), OpenGl_Vec3 (aLabX, float(anOffset.y()), 0.0f), aParams);
345 myChartLabels[1].Init (aCtx, aLabels[isTopDown ? 1 : 1].ToCString(), OpenGl_Vec3 (aLabX, float(anOffset.y() - aBinSize.y() / 2), 0.0f), aParams);
346 myChartLabels[2].Init (aCtx, aLabels[isTopDown ? 2 : 0].ToCString(), OpenGl_Vec3 (aLabX, float(anOffset.y() - aBinSize.y()), 0.0f), aParams);
347 }
15669413 348}
349
350// =======================================================================
351// function : Render
352// purpose :
353// =======================================================================
354void OpenGl_FrameStatsPrs::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
355{
356 const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
357 const Standard_Boolean wasEnabledDepth = theWorkspace->UseDepthWrite();
358 if (theWorkspace->UseDepthWrite())
359 {
360 theWorkspace->UseDepthWrite() = Standard_False;
361 glDepthMask (GL_FALSE);
362 }
363
bf5f0ca2 364 const OpenGl_Aspects* aTextAspectBack = theWorkspace->SetAspects (&myTextAspect);
5e30547b 365
15669413 366 aCtx->ModelWorldState.Push();
367 aCtx->ModelWorldState.ChangeCurrent().InitIdentity();
368
5e30547b 369 // draw counters
15669413 370 {
5e30547b 371 aCtx->WorldViewState.Push();
372 if (!myCountersTrsfPers.IsNull())
373 {
374 myCountersTrsfPers->Apply (theWorkspace->View()->Camera(),
375 aCtx->ProjectionState.Current(), aCtx->WorldViewState.ChangeCurrent(),
376 aCtx->VirtualViewport()[2], aCtx->VirtualViewport()[3]);
377 }
378 aCtx->ApplyModelViewMatrix();
379 myCountersText.Render (theWorkspace);
380 aCtx->WorldViewState.Pop();
15669413 381 }
382
5e30547b 383 // draw chart
384 if (myChartIndices->IsValid()
385 && myChartIndices->GetElemsNb() > 0)
386 {
387 aCtx->WorldViewState.Push();
388 if (!myChartTrsfPers.IsNull())
389 {
390 myChartTrsfPers->Apply (theWorkspace->View()->Camera(),
391 aCtx->ProjectionState.Current(), aCtx->WorldViewState.ChangeCurrent(),
392 aCtx->VirtualViewport()[2], aCtx->VirtualViewport()[3]);
393 }
394 aCtx->ApplyModelViewMatrix();
15669413 395
5e30547b 396 aCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_TextureSet)(), Graphic3d_TOSM_UNLIT,
397 Graphic3d_AlphaMode_Blend, true, false,
398 Handle(OpenGl_ShaderProgram)());
399 aCtx->SetColor4fv (OpenGl_Vec4 (1.0f, 1.0f, 1.0f, 1.0f));
400 glEnable (GL_BLEND);
401 glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
402 myChartVertices->Bind (aCtx);
403 myChartVertices->bindAttribute (aCtx, Graphic3d_TOA_POS, 3, GL_FLOAT, myChartVertices->GetComponentsNb(), NULL);
404 myChartVertices->bindAttribute (aCtx, Graphic3d_TOA_COLOR, 4, GL_UNSIGNED_BYTE, myChartVertices->GetComponentsNb(), (void* )sizeof(Graphic3d_Vec3));
405
406 myChartIndices->Bind (aCtx);
407 aCtx->core15fwd->glDrawElements (GL_TRIANGLES, myChartIndices->GetElemsNb(), myChartIndices->GetDataType(), NULL);
408 myChartIndices->Unbind (aCtx);
409 myChartVertices->Unbind (aCtx);
410 myChartVertices->unbindAttribute (aCtx, Graphic3d_TOA_COLOR);
411 myChartVertices->unbindAttribute (aCtx, Graphic3d_TOA_POS);
412 glDisable (GL_BLEND);
413
414 myChartLines->Bind (aCtx);
415 myChartLines->bindAttribute (aCtx, Graphic3d_TOA_POS, 3, GL_FLOAT, myChartLines->GetComponentsNb(), NULL);
416 myChartLines->bindAttribute (aCtx, Graphic3d_TOA_COLOR, 4, GL_UNSIGNED_BYTE, myChartLines->GetComponentsNb(), (void* )sizeof(Graphic3d_Vec3));
417 aCtx->core15fwd->glDrawArrays (GL_LINES, 0, myChartLines->GetElemsNb());
418 myChartLines->Unbind (aCtx);
419 myChartLines->unbindAttribute (aCtx, Graphic3d_TOA_COLOR);
420 myChartLines->unbindAttribute (aCtx, Graphic3d_TOA_POS);
421
422 myChartLabels[0].Render (theWorkspace);
423 myChartLabels[1].Render (theWorkspace);
424 myChartLabels[2].Render (theWorkspace);
425
426 aCtx->WorldViewState.Pop();
427 }
15669413 428
15669413 429 aCtx->ModelWorldState.Pop();
430 aCtx->ApplyWorldViewMatrix();
431
bf5f0ca2 432 theWorkspace->SetAspects (aTextAspectBack);
15669413 433 if (theWorkspace->UseDepthWrite() != wasEnabledDepth)
434 {
435 theWorkspace->UseDepthWrite() = wasEnabledDepth;
436 glDepthMask (wasEnabledDepth ? GL_TRUE : GL_FALSE);
437 }
438}