Hyprland/src/debug/HyprDebugOverlay.cpp

239 lines
9 KiB
C++
Raw Normal View History

2022-05-28 17:32:19 +02:00
#include "HyprDebugOverlay.hpp"
#include "../Compositor.hpp"
2022-07-27 12:32:00 +02:00
void CHyprMonitorDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
2022-05-28 17:32:19 +02:00
m_dLastRenderTimes.push_back(µs / 1000.f);
if (m_dLastRenderTimes.size() > (long unsigned int)pMonitor->refreshRate)
m_dLastRenderTimes.pop_front();
if (!m_pMonitor)
m_pMonitor = pMonitor;
}
2022-07-27 12:32:00 +02:00
void CHyprMonitorDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) {
2022-05-28 17:40:57 +02:00
m_dLastRenderTimesNoOverlay.push_back(µs / 1000.f);
if (m_dLastRenderTimesNoOverlay.size() > (long unsigned int)pMonitor->refreshRate)
m_dLastRenderTimesNoOverlay.pop_front();
if (!m_pMonitor)
m_pMonitor = pMonitor;
}
2022-07-27 12:32:00 +02:00
void CHyprMonitorDebugOverlay::frameData(CMonitor* pMonitor) {
2022-05-28 17:32:19 +02:00
m_dLastFrametimes.push_back(std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::high_resolution_clock::now() - m_tpLastFrame).count() / 1000.f);
if (m_dLastFrametimes.size() > (long unsigned int)pMonitor->refreshRate)
m_dLastFrametimes.pop_front();
m_tpLastFrame = std::chrono::high_resolution_clock::now();
if (!m_pMonitor)
m_pMonitor = pMonitor;
2023-03-03 13:15:59 +01:00
// anim data too
const auto PMONITORFORTICKS = g_pHyprRenderer->m_pMostHzMonitor ? g_pHyprRenderer->m_pMostHzMonitor : g_pCompositor->m_pLastMonitor.get();
2023-03-03 13:15:59 +01:00
if (PMONITORFORTICKS) {
if (m_dLastAnimationTicks.size() > (long unsigned int)PMONITORFORTICKS->refreshRate)
m_dLastAnimationTicks.pop_front();
m_dLastAnimationTicks.push_back(g_pAnimationManager->m_fLastTickTime);
}
2022-05-28 17:32:19 +02:00
}
int CHyprMonitorDebugOverlay::draw(int offset) {
if (!m_pMonitor)
return 0;
int yOffset = offset;
2022-05-28 17:32:19 +02:00
cairo_text_extents_t cairoExtents;
float maxX = 0;
std::string text = "";
2022-05-28 17:32:19 +02:00
// get avg fps
float avgFrametime = 0;
2023-03-03 13:15:59 +01:00
float maxFrametime = 0;
float minFrametime = 9999;
2022-05-28 17:32:19 +02:00
for (auto& ft : m_dLastFrametimes) {
2023-03-03 13:15:59 +01:00
if (ft > maxFrametime)
maxFrametime = ft;
if (ft < minFrametime)
minFrametime = ft;
2022-05-28 17:32:19 +02:00
avgFrametime += ft;
}
2023-03-03 13:15:59 +01:00
float varFrametime = maxFrametime - minFrametime;
2022-05-28 17:32:19 +02:00
avgFrametime /= m_dLastFrametimes.size() == 0 ? 1 : m_dLastFrametimes.size();
float avgRenderTime = 0;
2023-03-03 13:15:59 +01:00
float maxRenderTime = 0;
float minRenderTime = 9999;
2022-05-28 17:32:19 +02:00
for (auto& rt : m_dLastRenderTimes) {
2023-03-03 13:15:59 +01:00
if (rt > maxRenderTime)
maxRenderTime = rt;
if (rt < minRenderTime)
minRenderTime = rt;
2022-05-28 17:32:19 +02:00
avgRenderTime += rt;
}
2023-03-03 13:15:59 +01:00
float varRenderTime = maxRenderTime - minRenderTime;
2022-05-28 17:32:19 +02:00
avgRenderTime /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
2022-05-28 17:40:57 +02:00
float avgRenderTimeNoOverlay = 0;
2023-03-03 13:15:59 +01:00
float maxRenderTimeNoOverlay = 0;
float minRenderTimeNoOverlay = 9999;
2022-05-28 17:40:57 +02:00
for (auto& rt : m_dLastRenderTimesNoOverlay) {
2023-03-03 13:15:59 +01:00
if (rt > maxRenderTimeNoOverlay)
maxRenderTimeNoOverlay = rt;
if (rt < minRenderTimeNoOverlay)
minRenderTimeNoOverlay = rt;
2022-05-28 17:40:57 +02:00
avgRenderTimeNoOverlay += rt;
}
2023-03-03 13:15:59 +01:00
float varRenderTimeNoOverlay = maxRenderTimeNoOverlay - minRenderTimeNoOverlay;
2022-05-28 17:40:57 +02:00
avgRenderTimeNoOverlay /= m_dLastRenderTimes.size() == 0 ? 1 : m_dLastRenderTimes.size();
2023-03-03 13:15:59 +01:00
float avgAnimMgrTick = 0;
float maxAnimMgrTick = 0;
float minAnimMgrTick = 9999;
for (auto& at : m_dLastAnimationTicks) {
if (at > maxAnimMgrTick)
maxAnimMgrTick = at;
if (at < minAnimMgrTick)
minAnimMgrTick = at;
avgAnimMgrTick += at;
}
float varAnimMgrTick = maxAnimMgrTick - minAnimMgrTick;
avgAnimMgrTick /= m_dLastAnimationTicks.size() == 0 ? 1 : m_dLastAnimationTicks.size();
const float FPS = 1.f / (avgFrametime / 1000.f); // frametimes are in ms
2022-05-28 17:32:19 +02:00
const float idealFPS = m_dLastFrametimes.size();
cairo_select_font_face(g_pDebugOverlay->m_pCairo, "Sans", CAIRO_FONT_SLANT_NORMAL, CAIRO_FONT_WEIGHT_NORMAL);
2022-05-28 17:32:19 +02:00
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
yOffset += 10;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = m_pMonitor->szName;
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
2022-05-28 17:32:19 +02:00
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 16);
if (FPS > idealFPS * 0.95f)
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 0.2f, 1.f, 0.2f, 1.f);
else if (FPS > idealFPS * 0.8f)
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 0.2f, 1.f);
else
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 0.2f, 0.2f, 1.f);
yOffset += 17;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::format("{} FPS", (int)FPS);
2022-05-28 17:32:19 +02:00
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
2022-05-28 17:32:19 +02:00
cairo_set_font_size(g_pDebugOverlay->m_pCairo, 10);
cairo_set_source_rgba(g_pDebugOverlay->m_pCairo, 1.f, 1.f, 1.f, 1.f);
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::format("Avg Frametime: {:.2f}ms (var {:.2f}ms)", avgFrametime, varFrametime);
2023-03-03 13:15:59 +01:00
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::format("Avg Rendertime: {:.2f}ms (var {:.2f}ms)", avgRenderTime, varRenderTime);
2022-05-28 17:32:19 +02:00
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
2022-05-28 17:32:19 +02:00
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::format("Avg Rendertime (No Overlay): {:.2f}ms (var {:.2f}ms)", avgRenderTimeNoOverlay, varRenderTimeNoOverlay);
2022-05-28 17:32:19 +02:00
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
2022-05-28 17:32:19 +02:00
2022-05-28 17:40:57 +02:00
yOffset += 11;
cairo_move_to(g_pDebugOverlay->m_pCairo, 0, yOffset);
text = std::format("Avg Anim Tick: {:.2f}ms (var {:.2f}ms) ({:.2f} TPS)", avgAnimMgrTick, varAnimMgrTick, 1.0 / (avgAnimMgrTick / 1000.0));
2022-05-28 17:40:57 +02:00
cairo_show_text(g_pDebugOverlay->m_pCairo, text.c_str());
cairo_text_extents(g_pDebugOverlay->m_pCairo, text.c_str(), &cairoExtents);
if (cairoExtents.width > maxX)
maxX = cairoExtents.width;
2022-05-28 17:40:57 +02:00
2022-05-28 17:32:19 +02:00
yOffset += 11;
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
m_wbLastDrawnBox = {(int)g_pCompositor->m_vMonitors.front()->vecPosition.x, (int)g_pCompositor->m_vMonitors.front()->vecPosition.y + offset - 1, (int)maxX + 2,
yOffset - offset + 2};
2022-05-28 17:32:19 +02:00
g_pHyprRenderer->damageBox(&m_wbLastDrawnBox);
return yOffset - offset;
}
2022-07-27 12:32:00 +02:00
void CHyprDebugOverlay::renderData(CMonitor* pMonitor, float µs) {
2022-05-28 17:32:19 +02:00
m_mMonitorOverlays[pMonitor].renderData(pMonitor, µs);
}
2022-07-27 12:32:00 +02:00
void CHyprDebugOverlay::renderDataNoOverlay(CMonitor* pMonitor, float µs) {
2022-05-28 17:40:57 +02:00
m_mMonitorOverlays[pMonitor].renderDataNoOverlay(pMonitor, µs);
}
2022-07-27 12:32:00 +02:00
void CHyprDebugOverlay::frameData(CMonitor* pMonitor) {
2022-05-28 17:32:19 +02:00
m_mMonitorOverlays[pMonitor].frameData(pMonitor);
}
void CHyprDebugOverlay::draw() {
2022-06-30 15:44:26 +02:00
const auto PMONITOR = g_pCompositor->m_vMonitors.front().get();
2022-05-28 17:32:19 +02:00
if (!m_pCairoSurface || !m_pCairo) {
2023-03-03 13:15:59 +01:00
m_pCairoSurface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y);
m_pCairo = cairo_create(m_pCairoSurface);
2022-05-28 17:32:19 +02:00
}
// clear the pixmap
cairo_save(m_pCairo);
cairo_set_operator(m_pCairo, CAIRO_OPERATOR_CLEAR);
cairo_paint(m_pCairo);
cairo_restore(m_pCairo);
// draw the things
int offsetY = 0;
2022-06-30 15:44:26 +02:00
for (auto& m : g_pCompositor->m_vMonitors) {
offsetY += m_mMonitorOverlays[m.get()].draw(offsetY);
2022-05-28 17:32:19 +02:00
offsetY += 5; // for padding between mons
}
cairo_surface_flush(m_pCairoSurface);
// copy the data to an OpenGL texture we have
const auto DATA = cairo_image_surface_get_data(m_pCairoSurface);
m_tTexture.allocate();
glBindTexture(GL_TEXTURE_2D, m_tTexture.m_iTexID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
#ifndef GLES2
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_B, GL_RED);
#endif
2023-03-03 13:15:59 +01:00
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y, 0, GL_RGBA, GL_UNSIGNED_BYTE, DATA);
2022-05-28 17:32:19 +02:00
CBox pMonBox = {0, 0, PMONITOR->vecPixelSize.x, PMONITOR->vecPixelSize.y};
g_pHyprOpenGL->renderTexture(m_tTexture, &pMonBox, 1.f);
2022-05-28 17:32:19 +02:00
}