16#include "frontend/GPUDisplayInfo.inc"
26#include <condition_variable>
29#include "../utils/linux_helpers.h"
44#include "helpers/GPUDisplayColors.inc"
46constexpr hmm_mat4 MY_HMM_IDENTITY = {{{1, 0, 0, 0}, {0, 1, 0, 0}, {0, 0, 1, 0}, {0, 0, 0, 1}}};
52 static GPUSettingsDisplay defaultConfig;
53 return (
chain &&
chain->mConfigDisplay) ? *
chain->mConfigDisplay : defaultConfig;
58 static GPUSettingsProcessing defaultConfig;
62GPUDisplay::GPUDisplay(
GPUDisplayFrontend* frontend,
GPUChainTracking*
chain,
GPUQA* qa,
const GPUParam*
param,
const GPUCalibObjectsConst* calib,
const GPUSettingsDisplay* config,
const GPUSettingsProcessing* proc) :
GPUDisplayInterface(), mFrontend(frontend), mChain(
chain), mConfig(config ? *config : GetConfig(
chain)), mProcessingSettings(proc ? *proc : GetProcessingConfig(
chain)), mQA(qa)
64 mViewMatrix = std::make_unique<hmm_mat4>();
65 mModelMatrix = std::make_unique<hmm_mat4>();
68 mCfgL = mConfig.light;
69 mCfgH = mConfig.heavy;
70 mCfgR = mConfig.renderer;
73 throw std::runtime_error(
"Error obtaining display backend");
75 mBackend->mDisplay =
this;
78 mCfgR.rendererCompatSmoothing &= !mBackend->CoreProfile();
81void GPUDisplay::calcXYZ(
const float* matrix)
83 mXYZ[0] = -(matrix[0] * matrix[12] + matrix[1] * matrix[13] + matrix[2] * matrix[14]);
84 mXYZ[1] = -(matrix[4] * matrix[12] + matrix[5] * matrix[13] + matrix[6] * matrix[14]);
85 mXYZ[2] = -(matrix[8] * matrix[12] + matrix[9] * matrix[13] + matrix[10] * matrix[14]);
87 mAngle[0] = -asinf(matrix[6]);
88 float A = cosf(mAngle[0]);
89 if (fabsf(
A) > 0.005) {
90 mAngle[1] = atan2f(-matrix[2] /
A, matrix[10] /
A);
91 mAngle[2] = atan2f(matrix[4] /
A, matrix[5] /
A);
94 mAngle[2] = atan2f(-matrix[1], -matrix[0]);
97 mRPhiTheta[0] = sqrtf(mXYZ[0] * mXYZ[0] + mXYZ[1] * mXYZ[1] + mXYZ[2] * mXYZ[2]);
98 mRPhiTheta[1] = atan2f(mXYZ[0], mXYZ[2]);
99 mRPhiTheta[2] = atan2f(mXYZ[1], sqrtf(mXYZ[0] * mXYZ[0] + mXYZ[2] * mXYZ[2]));
101 createQuaternionFromMatrix(mQuat, matrix);
119 mNCollissions = std::max<uint32_t>(mNCollissions, collision + 1);
120 mOverlayTFClusters.resize(mNCollissions);
121 mOverlayTFClusters[collision][sector] = cluster;
124void GPUDisplay::mAnimationCloseAngle(
float& newangle,
float lastAngle)
126 const float delta = lastAngle > newangle ? (2 * CAMath::Pi()) : (-2 *
CAMath::Pi());
127 while (fabsf(newangle + delta - lastAngle) < fabsf(newangle - lastAngle)) {
131void GPUDisplay::mAnimateCloseQuaternion(
float*
v,
float lastx,
float lasty,
float lastz,
float lastw)
133 float distPos2 = (lastx -
v[0]) * (lastx -
v[0]) + (lasty -
v[1]) * (lasty -
v[1]) + (lastz -
v[2]) * (lastz -
v[2]) + (lastw -
v[3]) * (lastw -
v[3]);
134 float distNeg2 = (lastx +
v[0]) * (lastx +
v[0]) + (lasty +
v[1]) * (lasty +
v[1]) + (lastz +
v[2]) * (lastz +
v[2]) + (lastw +
v[3]) * (lastw +
v[3]);
135 if (distPos2 > distNeg2) {
136 for (int32_t
i = 0;
i < 4;
i++) {
157void GPUDisplay::updateConfig()
159 mBackend->setQuality();
160 mBackend->setDepthBuffer();
165 mNDrawCalls += mBackend->drawVertices(
v, t);
170 int32_t
retVal = initFailure;
173 retVal = InitDisplay_internal();
175 }
catch (
const std::runtime_error& e) {
176 GPUError(
"%s", e.what());
179 mInitResult =
retVal == 0 ? 1 : -1;
183int32_t GPUDisplay::InitDisplay_internal()
185 mThreadBuffers.resize(getNumThreads());
186 mThreadTracks.resize(getNumThreads());
187 if (mBackend->InitBackend()) {
190 mYFactor = mBackend->getYFactor();
191 mDrawTextInCompatMode = !mBackend->mFreetypeInitialized && mFrontend->
mCanDrawText == 1;
204 mBackend->ExitBackend();
210 mSemLockDisplay.
Lock();
219 }
else if (!mOverlayTFClusters.size()) {
223 DrawGLScene_internal();
224 }
catch (
const std::runtime_error& e) {
225 GPUError(
"Runtime error %s during display", e.what());
229 if (mLoadAndShowEvent) {
231 std::lock_guard<std::mutex> lock(mMutexLoadAndShowEvent);
232 mLoadAndShowEvent =
false;
234 mCVLoadAndShowEvent.notify_one();
241void GPUDisplay::DrawGLScene_cameraAndAnimation(
float animateTime,
float& mixSlaveImage,
hmm_mat4& nextViewMatrix)
246 bool lookOrigin = mCfgR.camLookOrigin ^ mFrontend->
mKeys[mFrontend->
KEY_ALT];
247 bool yUp = mCfgR.camYUp ^ mFrontend->
mKeys[mFrontend->
KEY_CTRL] ^ lookOrigin;
252 float scalefactor = mFrontend->
mKeys[mFrontend->
KEY_SHIFT] ? 0.2f : 1.0f;
253 float rotatescalefactor = scalefactor * 0.25f;
254 if (mCfgL.drawSector != -1) {
257 float*
const mViewMatrixP = &mViewMatrix->Elements[0][0];
258 float sqrdist = sqrtf(sqrtf(mViewMatrixP[12] * mViewMatrixP[12] + mViewMatrixP[13] * mViewMatrixP[13] + mViewMatrixP[14] * mViewMatrixP[14]) * GL_SCALE_FACTOR) * 0.8f;
259 if (sqrdist < 0.2f) {
265 scalefactor *= sqrdist;
269 if (animateCamera(animateTime, mixSlaveImage, nextViewMatrix)) {
271 }
else if (mResetScene) {
272 const float initialZpos = mCfgH.projectXY ? 16 : (mParam->
par.continuousTracking ? (mMaxClusterZ * GL_SCALE_FACTOR + 8) : 8);
273 nextViewMatrix = nextViewMatrix *
HMM_Translate({{0, 0, -initialZpos}});
277 mCfgL.pointSize = 2.0f;
278 mCfgL.lineWidth = 1.4f;
279 mCfgL.drawSector = -1;
280 mCfgL.showCollision = -1;
281 mCfgH.xAdd = mCfgH.zAdd = 0;
282 mCfgR.camLookOrigin = mCfgR.camYUp =
false;
283 mAngleRollOrigin = -1e9f;
285 mUpdateDrawCommands =
true;
289 float moveZ = scalefactor * ((float)mMouseWheelTmp / 150 + (
float)(mFrontend->
mKeys[(
uint8_t)
'W'] - mFrontend->
mKeys[(uint8_t)
'S']) * (!mFrontend->
mKeys[mFrontend->
KEY_SHIFT]) * 0.2f * mFPSScale);
291 float moveX = scalefactor * ((float)(mFrontend->
mKeys[(uint8_t)
'A'] - mFrontend->
mKeys[(
uint8_t)
'D']) * (!mFrontend->
mKeys[mFrontend->
KEY_SHIFT]) * 0.2f * mFPSScale);
292 float rotRoll = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[(
uint8_t)
'E'] - mFrontend->
mKeys[(uint8_t)
'F']) * (!mFrontend->
mKeys[mFrontend->
KEY_SHIFT]);
293 float rotYaw = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[mFrontend->
KEY_RIGHT] - mFrontend->
mKeys[mFrontend->
KEY_LEFT]);
294 float rotPitch = rotatescalefactor * mFPSScale * 2 * (mFrontend->
mKeys[mFrontend->
KEY_DOWN] - mFrontend->
mKeys[mFrontend->
KEY_UP]);
296 float mouseScale = 1920.f / std::max<float>(1920.f, mBackend->mScreenWidth);
298 moveZ += -scalefactor * mouseScale * ((float)mFrontend->
mMouseMvY - (
float)mFrontend->
mMouseDnY) / 4;
299 rotRoll += -rotatescalefactor * mouseScale * ((float)mFrontend->
mMouseMvX - (
float)mFrontend->
mMouseDnX);
301 moveX += scalefactor * 0.5f * mouseScale * ((float)mFrontend->
mMouseDnX - (
float)mFrontend->
mMouseMvX) / 4;
302 moveY += scalefactor * 0.5f * mouseScale * ((float)mFrontend->
mMouseMvY - (
float)mFrontend->
mMouseDnY) / 4;
304 rotYaw += rotatescalefactor * mouseScale * ((float)mFrontend->
mMouseMvX - (
float)mFrontend->
mMouseDnX);
305 rotPitch += rotatescalefactor * mouseScale * ((float)mFrontend->
mMouseMvY - (
float)mFrontend->
mMouseDnY);
309 mAnimationDelay += moveX;
310 if (mAnimationDelay < 0.05f) {
311 mAnimationDelay = 0.05f;
315 SetInfo(
"Animation delay set to %1.2f", mAnimationDelay);
319 mAngleRollOrigin = 0;
320 }
else if (!lookOrigin) {
321 mAngleRollOrigin = -1e6;
325 if (mAngleRollOrigin < -1e6) {
326 mAngleRollOrigin = yUp ? 0.f : -mAngle[2];
328 mAngleRollOrigin += rotRoll;
329 nextViewMatrix = nextViewMatrix *
HMM_Rotate(mAngleRollOrigin, {{0, 0, 1}});
330 float tmpX = moveX, tmpY = moveY;
331 moveX = tmpX * cosf(mAngle[2]) - tmpY * sinf(mAngle[2]);
332 moveY = tmpX * sinf(mAngle[2]) + tmpY * cosf(mAngle[2]);
335 const float x = mXYZ[0],
y = mXYZ[1],
z = mXYZ[2];
336 float r = sqrtf(
x *
x + +
y *
y +
z *
z);
337 float r2 = sqrtf(
x *
x +
z *
z);
338 float phi = atan2f(
z,
x);
340 float theta = atan2f(mXYZ[1], r2);
341 theta -= moveY * 0.1f;
342 const float max_theta = CAMath::Pi() / 2 - 0.01f;
343 if (theta >= max_theta) {
345 }
else if (theta <= -max_theta) {
348 if (moveZ >=
r - 0.1f) {
352 r2 =
r * cosf(theta);
353 mXYZ[0] = r2 * cosf(phi);
354 mXYZ[2] = r2 * sinf(phi);
355 mXYZ[1] =
r * sinf(theta);
360 nextViewMatrix = nextViewMatrix *
HMM_LookAt({{mXYZ[0], mXYZ[1], mXYZ[2]}}, {{0, 0, 0}}, {{0, 1, 0}});
362 nextViewMatrix = nextViewMatrix *
HMM_Translate({{moveX, moveY * mYFactor, moveZ}});
365 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotYaw, {{0, 1, 0}});
367 if (rotPitch != 0.f) {
368 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotPitch * mYFactor, {{1, 0, 0}});
370 if (!yUp && rotRoll != 0.f) {
371 nextViewMatrix = nextViewMatrix *
HMM_Rotate(rotRoll * mYFactor, {{0, 0, 1}});
374 nextViewMatrix = nextViewMatrix * *mViewMatrix;
376 calcXYZ(&nextViewMatrix.
Elements[0][0]);
377 nextViewMatrix =
HMM_Rotate(mAngle[2] * 180.f / CAMath::Pi(), {{0, 0, 1}}) * nextViewMatrix;
383 if (rotPitch != 0.f) {
386 if (rotRoll != 0.f) {
387 if (rotateModelTPC) {
388 *mModelMatrix =
HMM_Rotate(-rotRoll, {{0, 0, 1}}) * *mModelMatrix;
397 float minSize = 0.4f / (mCfgR.drawQualityDownsampleFSAA > 1 ? mCfgR.drawQualityDownsampleFSAA : 1);
399 mCfgL.lineWidth += (float)deltaLine * mFPSScale * 0.02f * mCfgL.lineWidth;
400 if (mCfgL.lineWidth <
minSize) {
404 SetInfo(
"%s line width: %f", deltaLine > 0 ?
"Increasing" :
"Decreasing", mCfgL.lineWidth);
405 mUpdateDrawCommands =
true;
409 mCfgL.pointSize += (float)deltaPoint * mFPSScale * 0.02f * mCfgL.pointSize;
410 if (mCfgL.pointSize <
minSize) {
414 SetInfo(
"%s point size: %f", deltaPoint > 0 ?
"Increasing" :
"Decreasing", mCfgL.pointSize);
415 mUpdateDrawCommands =
true;
420 if (animateTime < 0) {
421 *mViewMatrix = nextViewMatrix;
422 calcXYZ(&mViewMatrix->Elements[0][0]);
429 if (timer.IsRunning()) {
430 GPUInfo(
"Display Time: Camera:\t\t%6.0f us", timer.GetCurrentElapsedTime(
true) * 1e6);
434void GPUDisplay::DrawGLScene_drawCommands()
436#define LOOP_SECTOR for (int32_t iSector = (mCfgL.drawSector == -1 ? 0 : mCfgL.drawRelatedSectors ? (mCfgL.drawSector % (NSECTORS / 4)) : mCfgL.drawSector); iSector < NSECTORS; iSector += (mCfgL.drawSector == -1 ? 1 : mCfgL.drawRelatedSectors ? (NSECTORS / 4) : NSECTORS))
437#define LOOP_SECTOR2 for (int32_t iSector = (mCfgL.drawSector == -1 ? 0 : mCfgL.drawRelatedSectors ? (mCfgL.drawSector % (NSECTORS / 4)) : mCfgL.drawSector) % (NSECTORS / 2); iSector < NSECTORS / 2; iSector += (mCfgL.drawSector == -1 ? 1 : mCfgL.drawRelatedSectors ? (NSECTORS / 4) : NSECTORS))
438#define LOOP_COLLISION for (int32_t iCol = (mCfgL.showCollision == -1 ? 0 : mCfgL.showCollision); iCol < mNCollissions; iCol += (mCfgL.showCollision == -1 ? 1 : mNCollissions))
439#define LOOP_COLLISION_COL(cmd) \
442 if (mCfgL.colorCollisions) { \
443 SetCollisionColor(iCol); \
448 if (mCfgL.drawGrid) {
458 if (mCfgL.drawClusters) {
461 mBackend->lineWidthFactor(2);
463 if (mCfgL.drawFinal && mCfgL.colorClusters) {
467 mBackend->lineWidthFactor(1);
471 mBackend->pointSizeFactor(2);
474 mBackend->pointSizeFactor(1);
485 if (mCfgL.drawInitLinks) {
486 if (mCfgL.excludeClusters) {
489 if (mCfgL.colorClusters) {
495 if (mCfgL.drawLinks) {
496 if (mCfgL.excludeClusters) {
499 if (mCfgL.colorClusters) {
507 if (mCfgL.drawSeeds) {
508 if (mCfgL.excludeClusters) {
511 if (mCfgL.colorClusters) {
519 if (mCfgL.drawTracklets) {
520 if (mCfgL.excludeClusters) {
523 if (mCfgL.colorClusters) {
529 if (mCfgL.drawTracks) {
530 if (mCfgL.excludeClusters) {
533 if (mCfgL.colorClusters) {
540 if (mCfgL.drawExtrapolatedTracks) {
541 if (mCfgL.excludeClusters) {
544 if (mCfgL.colorClusters) {
545 SetColorExtrapolatedTracks();
553 if (mCfgL.drawFinal && mCfgL.propagateTracks < 2) {
554 if (mCfgL.excludeClusters) {
557 if (mCfgL.colorClusters) {
566 if (!mCfgH.clustersOnly && mCfgL.excludeClusters != 1) {
568 if (mCfgL.drawInitLinks) {
572 if (mCfgL.drawLinks) {
576 if (mCfgL.drawSeeds) {
580 if (mCfgL.drawTracklets) {
584 if (mCfgL.drawTracks) {
588 if (mCfgL.drawExtrapolatedTracks) {
589 SetColorExtrapolatedTracks();
593 if (mCfgL.drawFinal) {
597 if (mCfgL.colorCollisions) {
598 SetCollisionColor(iCol);
600 if (mCfgL.propagateTracks < 2) {
603 if (mCfgL.propagateTracks > 0 && mCfgL.propagateTracks < 3) {
606 if (mCfgL.propagateTracks == 2) {
609 if (mCfgL.propagateTracks == 3) {
613 if (mCfgH.drawTracksAndFilter ? (mCfgH.drawTPCTracks || mCfgH.drawTRDTracks || mCfgH.drawTOFTracks) : mCfgH.drawITSTracks) {
617 if (mCfgH.markClusters || mCfgH.markAdjacentClusters || mCfgH.markFakeClusters) {
618 if (mCfgH.markFakeClusters) {
619 mBackend->pointSizeFactor(3);
623 if (mCfgH.markFakeClusters) {
624 mBackend->pointSizeFactor(1);
630void GPUDisplay::DrawGLScene_internal(
float animateTime,
bool renderToMixBuffer)
632 if (mRequestScreenshot || mAnimateScreenshot) {
633 const uint32_t factor = std::max(1, mCfgR.drawQualityDownsampleFSAA) * std::max(1, mCfgR.screenshotScaleFactor);
634 if (std::max(mBackend->mScreenWidth, mBackend->mScreenHeight) * factor > mBackend->mMaxRenderSize) {
635 GPUError(
"Screenshot not taken: requested render size %u x %u (window x FSAA x screenshot scale) exceeds the maximum size %u x %u", mBackend->mScreenWidth * factor, mBackend->mScreenHeight * factor, mBackend->mMaxRenderSize, mBackend->mMaxRenderSize);
636 mRequestScreenshot =
false;
637 mAnimateScreenshot = 0;
640 bool doScreenshot = (mRequestScreenshot || mAnimateScreenshot) && animateTime < 0;
643 if (animateTime < 0 && (mUpdateEventData || mResetScene || mUpdateVertexLists) && mIOPtrs) {
644 disableUnsupportedOptions();
646 if (mUpdateEventData || mUpdateVertexLists) {
647 mUpdateDrawCommands =
true;
651 if (animateTime < 0 && (mUpdateEventData || mResetScene) && mIOPtrs) {
652 timerDraw.ResetStart();
653 DrawGLScene_updateEventData();
657 mUpdateVertexLists =
true;
658 mUpdateEventData =
false;
662 float mixSlaveImage = 0.f;
663 DrawGLScene_cameraAndAnimation(animateTime, mixSlaveImage, nextViewMatrix);
666 if (mUpdateVertexLists && mIOPtrs) {
667 size_t totalVertizes = DrawGLScene_updateVertexList();
668 if (timerDraw.IsRunning()) {
669 printf(
"Event visualization time: %'d us (vertices %'ld / %'ld bytes)\n", (int32_t)(timerDraw.GetCurrentElapsedTime() * 1000000.), (
int64_t)totalVertizes, (
int64_t)(totalVertizes *
sizeof(mVertexBuffer[0][0])));
674 nextViewMatrix = nextViewMatrix * *mModelMatrix;
675 const float zFar = ((mParam->
par.continuousTracking ? (mMaxClusterZ * GL_SCALE_FACTOR) : 8.f) + 50.f) * 2.f;
677 if (!mBackend->prepareDraw(proj, nextViewMatrix, doScreenshot || mRequestScreenshot, renderToMixBuffer, mixSlaveImage)) {
680 mBackend->pointSizeFactor(1);
681 mBackend->lineWidthFactor(1);
683 if (mUpdateDrawCommands || mBackend->backendNeedRedraw()) {
685 DrawGLScene_drawCommands();
688 if (mCfgL.drawField) {
689 mBackend->drawField();
692 mUpdateDrawCommands =
false;
693 mUpdateRenderPipeline =
false;
694 mBackend->finishDraw(doScreenshot, renderToMixBuffer, mixSlaveImage);
696 if (animateTime < 0) {
701 float fps = (double)mFramesDoneFPS / fpstime;
703 "FPS: %6.2f (Sector: %d, 1:Clusters %d, 2:Prelinks %d, 3:Links %d, 4:Seeds %d, 5:Tracklets %d, 6:Tracks %d, 7:GTracks %d, 8:Merger %d) (%d frames, %d draw calls) "
704 "(X %1.2f Y %1.2f Z %1.2f / R %1.2f Phi %1.1f Theta %1.1f) / Yaw %1.1f Pitch %1.1f Roll %1.1f)",
705 fps, mCfgL.drawSector, mCfgL.drawClusters, mCfgL.drawInitLinks, mCfgL.drawLinks, mCfgL.drawSeeds, mCfgL.drawTracklets, mCfgL.drawTracks, mCfgL.drawExtrapolatedTracks, mCfgL.drawFinal, mFramesDone, mNDrawCalls, mXYZ[0], mXYZ[1], mXYZ[2], mRPhiTheta[0], mRPhiTheta[1] * 180 / CAMath::Pi(),
706 mRPhiTheta[2] * 180 / CAMath::Pi(), mAngle[1] * 180 / CAMath::Pi(), mAngle[0] * 180 / CAMath::Pi(), mAngle[2] * 180 / CAMath::Pi());
708 if (mPrintInfoText & 2) {
711 if (mFPSScaleadjust++) {
712 mFPSScale = 60 / fps;
718 if (mPrintInfoText & 1) {
723 mBackend->finishFrame(mRequestScreenshot, renderToMixBuffer, mixSlaveImage);
725 mRequestScreenshot =
false;
726 std::vector<char>
pixels = mBackend->getPixels();
727 char tmpFileName[48];
728 if (mAnimateScreenshot) {
729 snprintf(tmpFileName, 48,
"mAnimation%d_%05d.bmp", mAnimationExport, mAnimationFrame);
731 DoScreenshot(mAnimateScreenshot ? tmpFileName : mScreenshotFile.c_str(),
pixels);
740 if (mMaxClusterZ <= 0) {
744 mUpdateEventData =
true;
745 mLoadAndShowEvent =
true;
759 std::unique_lock<std::mutex> lock(mMutexLoadAndShowEvent);
760 while (mLoadAndShowEvent) {
761 mCVLoadAndShowEvent.wait(lock);
767 mLoadAndShowEvent =
true;
771 while (mInitResult == 0) {
774 return (mInitResult != 1);
constexpr hmm_mat4 MY_HMM_IDENTITY
#define LOOP_COLLISION_COL(cmd)
HMM_INLINE hmm_mat4 HMM_Perspective(float FOV, float AspectRatio, float Near, float Far)
HMM_INLINE hmm_mat4 HMM_Translate(hmm_vec3 Translation)
HMM_EXTERN hmm_mat4 HMM_LookAt(hmm_vec3 Eye, hmm_vec3 Center, hmm_vec3 Up)
HMM_EXTERN hmm_mat4 HMM_Rotate(float Angle, hmm_vec3 Axis)
double GetCurrentElapsedTime(bool reset=false)
GPUTrackingInOutPointers & mIOPtrs
const GPUCalibObjectsConst & GetCalib() const
const GPUSettingsProcessing & GetProcessingSettings() const
const GPUParam & GetParam() const
static GPUDisplayBackend * getBackend(const char *type)
static constexpr int32_t KEY_ALT
virtual void getSize(int32_t &width, int32_t &height)
static constexpr int32_t KEY_PAGEDOWN
static constexpr int32_t KEY_RALT
static constexpr int32_t KEY_LEFT
volatile int32_t mNeedUpdate
static constexpr int32_t KEY_CTRL
static constexpr int32_t INIT_WIDTH
static constexpr int32_t KEY_SHIFT
static constexpr int32_t KEY_PAGEUP
GPUDisplayBackend * mBackend
static constexpr int32_t KEY_UP
static constexpr int32_t KEY_DOWN
static constexpr int32_t INIT_HEIGHT
static constexpr int32_t KEY_RIGHT
static constexpr int32_t KEY_RCTRL
GPUDisplay(GPUDisplayFrontend *frontend, GPUChainTracking *chain, GPUQA *qa, const GPUParam *param=nullptr, const GPUCalibObjectsConst *calib=nullptr, const GPUSettingsDisplay *config=nullptr, const GPUSettingsProcessing *proc=nullptr)
void SetCollisionFirstCluster(uint32_t collision, int32_t sector, int32_t cluster) override
int32_t StartDisplay() override
GPUDisplayFrontend * frontend()
void BlockTillNextEvent() override
int32_t InitDisplay(bool initFailure=false)
void ShowNextEvent(const GPUTrackingInOutPointers *ptrs=nullptr) override
void WaitTillEventShown() override
void ResizeScene(int32_t width, int32_t height, bool init=false)
GLdouble GLdouble GLdouble GLdouble GLdouble GLdouble zFar
GLint GLsizei GLsizei height
GLint GLint GLsizei GLint GLenum GLenum const void * pixels
GLdouble GLdouble GLdouble z
uint8_t itsSharedClusterMap uint8_t