Skip to content

Commit

Permalink
perf: predetermine history trail draw function
Browse files Browse the repository at this point in the history
On every render, we were checking the fields to determine the type of dot
we are rendering. However, we don't need to do this, as the dot type can only change
as part of an ASR load or configuration menu change.

This change saves the draw function as a lambda when something changes, allowing us to
reduce the render time by approximately 25% - went from 12ms to 8ms in testing.
  • Loading branch information
AndyTWF committed Jul 1, 2023
1 parent 8c200db commit 0d87dc5
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 51 deletions.
115 changes: 68 additions & 47 deletions src/plugin/historytrail/HistoryTrailRenderer.cpp
Expand Up @@ -57,6 +57,9 @@ namespace UKControllerPlugin {
userSetting.GetIntegerEntry(this->maxAltitudeFilterUserSettingKey, this->defaultMaxAltitude);
this->filledDots = userSetting.GetBooleanEntry(this->dotFillUserSettingKey, false);
this->rotatedDots = userSetting.GetBooleanEntry(this->dotRotateUserSettingKey, false);

// Load the dot drawing function
this->drawDot = this->GetDrawDotFunction();
}

/*
Expand Down Expand Up @@ -136,51 +139,6 @@ namespace UKControllerPlugin {
return this->antialiasedTrails;
}

/*
Draws a single dot to the screen.
*/
void
HistoryTrailRenderer::DrawDot(GdiGraphicsInterface& graphics, Gdiplus::Pen& pen, const Gdiplus::RectF& area)
{
if (this->historyTrailType == this->trailTypeDiamond) {
graphics.DrawDiamond(area, pen);
} else if (this->historyTrailType == this->trailTypeCircle) {
graphics.DrawCircle(area, pen);
} else if (this->historyTrailType == this->trailTypeLine) {
graphics.DrawLine(
pen,
Gdiplus::PointF{area.GetLeft(), area.GetBottom()},
Gdiplus::PointF{area.GetRight(), area.GetTop()});
} else {
graphics.DrawRect(area, pen);
}
}

/*
Fills a single dot to the screen.
*/
void
HistoryTrailRenderer::FillDot(GdiGraphicsInterface& graphics, Gdiplus::Brush& brush, const Gdiplus::RectF& area)
{
if (this->historyTrailType == this->trailTypeDiamond) {
graphics.FillDiamond(area, brush);
} else if (this->historyTrailType == this->trailTypeCircle) {
graphics.FillCircle(area, brush);
} else {
graphics.FillRect(area, brush);
}
}

void HistoryTrailRenderer::DoDot(GdiGraphicsInterface& graphics, const Gdiplus::RectF& area)
{
// Draw the dot
if (this->filledDots && this->historyTrailType != this->trailTypeLine) {
this->FillDot(graphics, *this->brush, area);
} else {
this->DrawDot(graphics, *this->pen, area);
}
}

/*
Returns the configuration menu item.
*/
Expand Down Expand Up @@ -372,9 +330,9 @@ namespace UKControllerPlugin {
if (this->rotatedDots) {
graphics.Rotated(
static_cast<Gdiplus::REAL>(position->heading),
[&graphics, &dot, this]() { this->DoDot(graphics, dot); });
[&graphics, &dot, this]() { this->drawDot(graphics, dot); });
} else {
this->DoDot(graphics, dot);
this->drawDot(graphics, dot);
}
});

Expand Down Expand Up @@ -405,5 +363,68 @@ namespace UKControllerPlugin {
void HistoryTrailRenderer::ResetPosition(void)
{
}

auto HistoryTrailRenderer::GetDoDotFunction() const
-> std::function<void(GdiGraphicsInterface&, const Gdiplus::RectF&)>
{
return this->filledDots && this->historyTrailType != this->trailTypeLine ? this->GetFillDotFunction()
: this->GetDrawDotFunction();
}

auto HistoryTrailRenderer::GetDrawDotFunction() const
-> std::function<void(Windows::GdiGraphicsInterface&, const Gdiplus::RectF&)>
{
// Diamonds
if (this->historyTrailType == this->trailTypeDiamond) {
return [this](Windows::GdiGraphicsInterface& graphics, const Gdiplus::RectF& area) {
graphics.DrawDiamond(area, *this->pen);
};
}

// Circles
if (this->historyTrailType == this->trailTypeCircle) {
return [this](Windows::GdiGraphicsInterface& graphics, const Gdiplus::RectF& area) {
graphics.DrawCircle(area, *this->pen);
};
}

// Lines
if (this->historyTrailType == this->trailTypeLine) {
return [this](Windows::GdiGraphicsInterface& graphics, const Gdiplus::RectF& area) {
graphics.DrawLine(
*this->pen,
Gdiplus::PointF{area.GetLeft(), area.GetBottom()},
Gdiplus::PointF{area.GetRight(), area.GetTop()});
};
}

// Rectangles
return [this](Windows::GdiGraphicsInterface& graphics, const Gdiplus::RectF& area) {
graphics.DrawRect(area, *this->pen);
};
}

auto HistoryTrailRenderer::GetFillDotFunction() const
-> std::function<void(Windows::GdiGraphicsInterface&, const Gdiplus::RectF&)>
{
// Diamonds
if (this->historyTrailType == this->trailTypeDiamond) {
return [this](Windows::GdiGraphicsInterface& graphics, const Gdiplus::RectF& area) {
graphics.FillDiamond(area, *this->brush);
};
}

// Circles
if (this->historyTrailType == this->trailTypeCircle) {
return [this](Windows::GdiGraphicsInterface& graphics, const Gdiplus::RectF& area) {
graphics.FillCircle(area, *this->brush);
};
}

// Rects
return [this](Windows::GdiGraphicsInterface& graphics, const Gdiplus::RectF& area) {
graphics.FillRect(area, *this->brush);
};
}
} // namespace HistoryTrail
} // namespace UKControllerPlugin
13 changes: 9 additions & 4 deletions src/plugin/historytrail/HistoryTrailRenderer.h
Expand Up @@ -158,10 +158,12 @@ namespace UKControllerPlugin {
const int defaultMaxAltitude = 99999;

private:
void DrawDot(Windows::GdiGraphicsInterface& graphics, Gdiplus::Pen& pen, const Gdiplus::RectF& area);

void FillDot(Windows::GdiGraphicsInterface& graphics, Gdiplus::Brush& brush, const Gdiplus::RectF& area);
void DoDot(Windows::GdiGraphicsInterface& graphics, const Gdiplus::RectF& area);
[[nodiscard]] auto GetDoDotFunction() const
-> std::function<void(Windows::GdiGraphicsInterface&, const Gdiplus::RectF&)>;
[[nodiscard]] auto GetFillDotFunction() const
-> std::function<void(Windows::GdiGraphicsInterface&, const Gdiplus::RectF&)>;
[[nodiscard]] auto GetDrawDotFunction() const
-> std::function<void(Windows::GdiGraphicsInterface&, const Gdiplus::RectF&)>;

// Handles dialogs
const Dialog::DialogManager& dialogManager;
Expand Down Expand Up @@ -222,6 +224,9 @@ namespace UKControllerPlugin {

// The dot command for opening the configuration modal.
const std::string dotCommand = ".ukcp h";

// Function for drawing the dot - saved as a lambda so we dont have to keep checking the trail type
std::function<void(Windows::GdiGraphicsInterface&, const Gdiplus::RectF&)> drawDot;
};
} // namespace HistoryTrail
} // namespace UKControllerPlugin

0 comments on commit 0d87dc5

Please sign in to comment.