Skip to content

Commit 2ed2c1f

Browse files
committed
GPU Display: Add an integrated console for manipulating the configuration and steering the display
1 parent 2ec906d commit 2ed2c1f

31 files changed

Lines changed: 566 additions & 38 deletions

‎GPU/GPUTracking/Definitions/GPUSettingsList.h‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -526,6 +526,10 @@ AddOptionVec(filterMacros, std::string, "", 0, "ROOT macros used as track filter
526526
AddOption(guiReplyTimeout, uint32_t, 100, "", 0, "Time in ms the Qt GUI waits at most for the display to process its update")
527527
AddOption(guiMaxUpdatesAhead, uint32_t, 3, "", 0, "Number of updates the Qt GUI may send ahead of the last one the display has processed, before it waits for the display")
528528
AddOption(listFrontendOptionHandling, bool, false, "", 0, "List all assigned keys in frontend, Configurable settings in Qt GUI, and missing configuration options")
529+
AddOption(consoleDelay, float, 0.5f, "", 0, "Time in seconds to open / close the console (^ key)")
530+
AddOption(consoleAlpha, float, 0.8f, "", 0, "Opacity of the console background")
531+
AddOption(consoleVertical, float, 0.5f, "", 0, "Fraction of the window height covered by the fully opened console")
532+
AddOption(consoleHistorySize, uint32_t, 1000000, "", 0, "Number of console lines kept, the history is shortened to this when it reaches twice the size")
529533
AddSubConfig(GPUSettingsDisplayLight, light)
530534
AddSubConfig(GPUSettingsDisplayHeavy, heavy)
531535
AddSubConfig(GPUSettingsDisplayRenderer, renderer)

‎GPU/GPUTracking/display/CMakeLists.txt‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ set(SRCS ../utils/qsem.cxx
117117
GPUDisplay.cxx
118118
helpers/GPUDisplayMagneticField.cxx
119119
frontend/GPUDisplayFrontend.cxx
120+
frontend/GPUDisplayConsole.cxx
120121
frontend/GPUDisplayFrontendNone.cxx
121122
backend/GPUDisplayBackend.cxx
122123
backend/GPUDisplayBackendNone.cxx)

‎GPU/GPUTracking/display/GPUDisplay.cxx‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -727,9 +727,23 @@ void GPUDisplay::DrawGLScene_internal(bool suspended, float animateTime, bool re
727727
mFramesDoneFPS = 0;
728728
}
729729

730+
const float consoleFraction = consoleVerticalFraction();
731+
const bool drawText = (mCfgC.mPrintInfoText & 1) || consoleFraction > 0.f;
732+
if (drawText) {
733+
mBackend->updateFontScale(mFrontend->getDisplayScale());
734+
mBackend->prepareText();
735+
}
730736
if (mCfgC.mPrintInfoText & 1 || mCfgC.mPrintInfoTextGUI) {
731737
showInfo(info);
732738
}
739+
if (consoleFraction > 0.f) {
740+
const bool cursor = mCfgC.showConsole && std::fmod(mConsoleTimer.GetCurrentElapsedTime(), 1.0) < 0.5; // Blinking, the timer runs while the console is open
741+
mBackend->GLDrawConsole(consoleFraction, mFrontend->mConsole->mConsoleHistory, mFrontend->mConsole->shownText(), cursor ? (int32_t)mFrontend->mConsole->mConsoleTextPos : -1);
742+
}
743+
if (drawText) {
744+
mBackend->finishText();
745+
}
746+
mFrontend->mConsole->consoleLimitHistory(mConfig.consoleHistorySize);
733747
}
734748

735749
mBackend->finishFrame(doScreenshot, renderToMixBuffer, mixSlaveImage);

‎GPU/GPUTracking/display/GPUDisplay.h‎

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ class GPUDisplay : public GPUDisplayInterface
6161
void UpdateCalib(const GPUCalibObjectsConst* calib) override { mCalib = calib; }
6262
void UpdateParam(const GPUParam* param) override { mParam = param; }
6363

64-
void HandleKey(uint8_t key);
64+
void HandleKey(uint8_t key, bool external = false); // external: from the Qt GUI or the console, not typed into the event display console
6565
int32_t DrawGLScene(bool suspended = false);
6666
void HandleExternalGUIKey(int32_t key);
6767
int32_t InitDisplay(bool initFailure = false);
@@ -198,6 +198,7 @@ class GPUDisplay : public GPUDisplayInterface
198198
void startAnimation();
199199
int32_t animateCamera(bool suspended, float& animateTime, float& mixSlaveImage, hmm_mat4& nextViewMatrix);
200200
void showInfo(const char* info);
201+
float consoleVerticalFraction(); // Fraction of the window covered by the console (animated), 0 if hidden
201202
void ActivateColor();
202203
void SetColorTRD();
203204
void SetColorTOF();
@@ -321,10 +322,11 @@ class GPUDisplay : public GPUDisplayInterface
321322
opengl_spline mAnimationSplines[8];
322323

323324
char mInfoText2[1024];
324-
std::string mGUIInfoStatus; // Latest status line (FPS etc.) for the Qt GUI
325-
std::string mGUIInfoText; // Latest info message (SetInfo) for the Qt GUI
326-
uint64_t mGUIInfoTextCounter = 0; // Number of info messages, the GUI shows a new one for some seconds
327-
HighResTimer mInfoText2Timer, mInfoHelpTimer;
325+
std::string mGUIInfoStatus; // Latest status line (FPS etc.) for the Qt GUI
326+
std::string mGUIInfoText; // Latest info message (SetInfo) for the Qt GUI
327+
uint64_t mGUIInfoTextCounter = 0; // Number of info messages, the GUI shows a new one for some seconds
328+
HighResTimer mInfoText2Timer, mInfoHelpTimer, mConsoleTimer; // mConsoleTimer: opening / closing animation of the console
329+
bool mConsoleShown = false; // showConsole of the last checkAndApplyConfigChanges
328330

329331
std::vector<threadVertexBuffer> mThreadBuffers;
330332
std::vector<std::vector<std::array<std::array<vecpod<int32_t>, 2>, NSECTORS>>> mThreadTracks;

‎GPU/GPUTracking/display/GPUDisplayControl.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ BeginHiddenConfig(GPUDisplayControl, control)
4040
AddVariable(mGLAnimationFile, std::string, "glanimation.tmp") // File for saving / loading the animation path
4141
AddVariable(mGuiDarkMode, int8_t, -1) // Dark mode of the Qt GUI, -1 = not yet set: the GUI reports the system scheme when it starts
4242
AddVariable(mGuiScale, float, 1.f) // Scale factor of text and elements of the Qt GUI (on top of the system scaling), Ctrl + mouse wheel / Ctrl + 0 in the GUI
43+
AddVariable(showConsole, bool, false) // Console shown (^ key): all other keys go to the console
4344
AddVariable(dummy, bool, false) // dummy value to reference for keys that do not change variables
4445
EndConfig()
4546
EndNamespace() // o2::gpu

‎GPU/GPUTracking/display/backend/GPUDisplayBackend.cxx‎

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ void GPUDisplayBackend::loadFont()
132132
mFontRasterScale = mDisplay->frontend()->getDisplayScale();
133133
FT_Set_Pixel_Sizes(face, 0, (uint32_t)(fontSize * mFontRasterScale + 0.5f)); // Rasterize at physical pixel size for HiDPI
134134

135-
for (uint32_t i = 0; i < 128; i++) {
135+
for (uint32_t i = 0; i < SOLID_GLYPH; i++) {
136136
if (FT_Load_Char(face, i, FT_LOAD_RENDER)) {
137137
GPUError("Error loading freetype symbol");
138138
FT_Done_Face(face);
@@ -145,6 +145,8 @@ void GPUDisplayBackend::loadFont()
145145
}
146146
addFontSymbol(i, glyph->bitmap.width, glyph->bitmap.rows, glyph->bitmap_left, glyph->bitmap_top, glyph->advance.x, glyph->bitmap.buffer);
147147
}
148+
std::vector<uint8_t> solid(8 * 8, 255);
149+
addFontSymbol(SOLID_GLYPH, 8, 8, 0, 0, 0, solid.data());
148150
initializeTextDrawing();
149151
FT_Done_Face(face);
150152
FT_Done_FreeType(ft);
@@ -207,3 +209,42 @@ bool GPUDisplayBackend::smoothFont()
207209
{
208210
return mDisplay->cfg().smoothFont < 0 ? (mDisplay->cfg().fontSize > 12) : mDisplay->cfg().smoothFont;
209211
}
212+
213+
void GPUDisplayBackend::GLDrawLine(float x0, float y0, float x1, float y1, float width, const float* color)
214+
{
215+
const float dx = x1 - x0, dy = y1 - y0, length = std::sqrt(dx * dx + dy * dy);
216+
if (length == 0.f) {
217+
return;
218+
}
219+
const float nx = -dy / length * width * 0.5f, ny = dx / length * width * 0.5f; // Perpendicular, half the width
220+
GLDrawQuad({{x0 + nx, y0 + ny}, {x0 - nx, y0 - ny}, {x1 - nx, y1 - ny}, {x1 + nx, y1 + ny}}, color);
221+
}
222+
223+
void GPUDisplayBackend::GLDrawConsole(float verticalFraction, std::span<const std::string> previous, const std::string& current, int32_t cursorPos)
224+
{
225+
if (!mFreetypeInitialized) {
226+
return;
227+
}
228+
const float scale = mDisplay->frontend()->getDisplayScale();
229+
const float colorValue = mDisplay->cfgL().invertColors ? 0.f : 1.f;
230+
float textColor[4] = {colorValue, colorValue, colorValue, 1.f};
231+
const float backgroundColor[4] = {1.f - colorValue, 1.f - colorValue, 1.f - colorValue, mDisplay->cfg().consoleAlpha};
232+
const float width = mScreenWidth, top = mScreenHeight, bottom = top * (1.f - verticalFraction);
233+
GLDrawQuad({{0.f, bottom}, {width, bottom}, {width, top}, {0.f, top}}, backgroundColor);
234+
GLDrawLine(0.f, bottom, width, bottom, scale, textColor);
235+
236+
static constexpr float MARGIN = 6.f; // Logical pixels from the text to the left border and to the line
237+
const float lineHeight = std::max(20, mDisplay->drawTextFontSize() + 4) * scale; // As the info text of GPUDisplay
238+
const float descent = 0.25f * mDisplay->drawTextFontSize() * scale; // Below the baseline, approximately
239+
const size_t maxChars = mFontCharWidth > 0.f ? std::max(0.f, (width / scale - 2 * MARGIN) / mFontCharWidth) : SIZE_MAX; // Longer lines are cut
240+
float y = bottom + (0.5f + MARGIN) * scale + descent; // Baseline of the lowest line, MARGIN above the line (half its width)
241+
if (cursorPos >= 0 && (size_t)cursorPos < maxChars && mFontCharWidth > 0.f) { // Monospace font: position from the character width
242+
GLPrintText("_", (MARGIN + cursorPos * mFontCharWidth) * scale, y, textColor, scale / mFontRasterScale, 0);
243+
}
244+
for (size_t i = 0; i <= previous.size() && y + lineHeight - descent <= top; i++, y += lineHeight) {
245+
const std::string& text = i == 0 ? current : previous[previous.size() - i];
246+
if (!text.empty() && maxChars) {
247+
GLPrintText(text.c_str(), MARGIN * scale, y, textColor, scale / mFontRasterScale, std::min(text.size(), maxChars));
248+
}
249+
}
250+
}

‎GPU/GPUTracking/display/backend/GPUDisplayBackend.h‎

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717

1818
#include "GPUCommonDef.h"
1919
#include "../utils/vecpod.h"
20+
#include <span>
21+
#include <string>
2022
#include <array>
2123
#include <cstddef>
2224
#include <memory>
@@ -99,7 +101,10 @@ class GPUDisplayBackend
99101
const char* backendName() const { return mBackendName; }
100102
virtual void resizeScene(uint32_t width, uint32_t height) {}
101103
virtual size_t needMultiVBO() { return 0; }
102-
virtual void GLPrintText(const char* s, float x, float y, float* color, float scale, uint32_t nCharacters) = 0; // nCharacters > 0: at most that many characters, otherwise until the terminating 0
104+
virtual void GLPrintText(const char* s, float x, float y, float* color, float scale, uint32_t nCharacters) = 0; // nCharacters > 0: at most that many characters, otherwise until the terminating 0
105+
virtual void GLDrawQuad(const float (&corners)[4][2], const float* color) = 0; // Filled quad with the corners counterclockwise, in pixels with y from the bottom, drawn with the text (SOLID_GLYPH)
106+
void GLDrawLine(float x0, float y0, float x1, float y1, float width, const float* color); // As GLDrawQuad
107+
void GLDrawConsole(float verticalFraction, std::span<const std::string> previous, const std::string& current, int32_t cursorPos); // Console over the top verticalFraction of the window: current text in the lowest line, previous ones above (last one lowest), cursor _ at cursorPos (< 0: none)
103108
static GPUDisplayBackend* getBackend(const char* type);
104109
std::vector<char> getPixels();
105110
virtual float getYFactor() const { return 1.0f; }
@@ -119,8 +124,9 @@ class GPUDisplayBackend
119124
std::vector<int32_t> mIndirectSectorOffset;
120125
vecpod<DrawArraysIndirectCommand> mCmdBuffer;
121126
bool mFreetypeInitialized = false;
122-
float mFontRasterScale = 1.f; // Display scale the font was rasterized for
123-
float mFontCharWidth = 0.f; // Advance of a character of the (monospace) font in logical pixels, 0 without Freetype font
127+
float mFontRasterScale = 1.f; // Display scale the font was rasterized for
128+
static constexpr int32_t SOLID_GLYPH = 128; // Fully opaque glyph after the characters (0 - 127), for quads drawn with the text
129+
float mFontCharWidth = 0.f; // Advance of a character of the (monospace) font in logical pixels, 0 without Freetype font
124130
std::vector<char> mScreenshotPixels;
125131

126132
static constexpr float SMOOTH_POINT_EXTRA_SIZE = 0.6f;

‎GPU/GPUTracking/display/backend/GPUDisplayBackendNone.h‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ class GPUDisplayBackendNone : public GPUDisplayBackend
4040
void pointSizeFactor(float factor) override {}
4141
void lineWidthFactor(float factor) override {}
4242
void GLPrintText(const char* s, float x, float y, float* color, float scale, uint32_t nCharacters) override {}
43+
void GLDrawQuad(const float (&corners)[4][2], const float* color) override {}
4344
void addFontSymbol(int32_t symbol, int32_t sizex, int32_t sizey, int32_t offsetx, int32_t offsety, int32_t advance, void* data) override {}
4445
void initializeTextDrawing() override {}
4546
};

‎GPU/GPUTracking/display/backend/GPUDisplayBackendOpenGL.cxx‎

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -684,8 +684,8 @@ void GPUDisplayBackendOpenGL::GLPrintText(const char* s, float x, float y, float
684684
scale *= 0.25f; // Font size is 48 to have nice bitmap, scale to size 12
685685
}
686686
for (const unsigned char* c = (const unsigned char*)s; *c && (nCharacters == 0 || c < (const unsigned char*)s + nCharacters); c++) {
687-
if ((int32_t)*c >= (int32_t)mFontSymbols.size()) {
688-
GPUError("Trying to draw unsupported symbol: %d > %d\n", (int32_t)*c, (int32_t)mFontSymbols.size());
687+
if (*c < 32 || *c >= SOLID_GLYPH) { // Printable ASCII only, SOLID_GLYPH is not a character
688+
GPUError("Trying to draw unsupported symbol: %d", (int32_t)*c);
689689
continue;
690690
}
691691
FontSymbolOpenGL sym = mFontSymbols[*c];
@@ -701,11 +701,7 @@ void GPUDisplayBackendOpenGL::GLPrintText(const char* s, float x, float y, float
701701
{xpos, ypos + h, 0.0f, 0.0f},
702702
{xpos + w, ypos, 1.0f, 1.0f},
703703
{xpos + w, ypos + h, 1.0f, 0.0f}};
704-
CHKERR(glBindTexture(GL_TEXTURE_2D, sym.texId));
705-
CHKERR(glBindBuffer(GL_ARRAY_BUFFER, VBO_text));
706-
CHKERR(glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices));
707-
CHKERR(glBindBuffer(GL_ARRAY_BUFFER, 0));
708-
CHKERR(glDrawArrays(GL_TRIANGLES, 0, 6));
704+
drawTextVertices(vertices, sym.texId);
709705
}
710706
x += (sym.advance >> 6) * scale; // shift is in 1/64th of a pixel
711707
}
@@ -714,6 +710,34 @@ void GPUDisplayBackendOpenGL::GLPrintText(const char* s, float x, float y, float
714710
}
715711
}
716712

713+
void GPUDisplayBackendOpenGL::drawTextVertices(const float (&vertices)[6][4], uint32_t texId)
714+
{
715+
CHKERR(glBindTexture(GL_TEXTURE_2D, texId));
716+
CHKERR(glBindBuffer(GL_ARRAY_BUFFER, VBO_text));
717+
CHKERR(glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vertices), vertices));
718+
CHKERR(glBindBuffer(GL_ARRAY_BUFFER, 0));
719+
CHKERR(glDrawArrays(GL_TRIANGLES, 0, 6));
720+
}
721+
722+
void GPUDisplayBackendOpenGL::GLDrawQuad(const float (&corners)[4][2], const float* color)
723+
{
724+
if (!mFreetypeInitialized) {
725+
return;
726+
}
727+
CHKERR(glUniform4fv(UNIFORM_LOCATION_COLOR, 1, color));
728+
static constexpr int32_t order[6] = {0, 1, 2, 0, 2, 3};
729+
float vertices[6][4];
730+
for (int32_t i = 0; i < 6; i++) {
731+
vertices[i][0] = corners[order[i]][0];
732+
vertices[i][1] = corners[order[i]][1];
733+
vertices[i][2] = vertices[i][3] = 0.5f; // Center of the opaque glyph
734+
}
735+
drawTextVertices(vertices, mFontSymbols[SOLID_GLYPH].texId);
736+
if (!mDisplay->useMultiVBO()) {
737+
CHKERR(glBindBuffer(GL_ARRAY_BUFFER, mVBOId[0])); // As in GLPrintText
738+
}
739+
}
740+
717741
void GPUDisplayBackendOpenGL::ClearOffscreenBuffers()
718742
{
719743
if (mMixBuffer.created) {

‎GPU/GPUTracking/display/backend/GPUDisplayBackendOpenGL.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,8 @@ class GPUDisplayBackendOpenGL : public GPUDisplayBackend
8080
void initializeTextDrawing() override;
8181
void clearFontSymbols() override;
8282
void GLPrintText(const char* s, float x, float y, float* color, float scale, uint32_t nCharacters) override;
83+
void GLDrawQuad(const float (&corners)[4][2], const float* color) override;
84+
void drawTextVertices(const float (&vertices)[6][4], uint32_t texId); // One quad with the text shader, after GLPrintText / GLDrawQuad set the color
8385

8486
struct FontSymbolOpenGL : public FontSymbol {
8587
uint32_t texId;

0 commit comments

Comments
 (0)