mirror of
https://github.com/The-Powder-Toy/The-Powder-Toy.git
synced 2025-08-26 17:34:35 +02:00
Copy the result of rendering only if needed
That is, only if the Renderer needs to immediately blast off to render another frame. If we run it on the main thread, we can just use its video buffer directly.
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
#include "DecorationTool.h"
|
||||
|
||||
#include "graphics/Renderer.h"
|
||||
|
||||
#include "simulation/SimulationData.h"
|
||||
#include "simulation/Simulation.h"
|
||||
#include "GameView.h"
|
||||
|
||||
std::unique_ptr<VideoBuffer> DecorationTool::GetIcon(int ToolID, Vec2<int> size)
|
||||
{
|
||||
@@ -54,6 +53,7 @@ void DecorationTool::DrawRect(Simulation * sim, Brush const &brush, ui::Point po
|
||||
|
||||
void DecorationTool::DrawFill(Simulation * sim, Brush const &brush, ui::Point position)
|
||||
{
|
||||
auto &rendererFrame = gameView->GetRendererFrame();
|
||||
if (!rendererFrame.Size().OriginRect().Contains(position))
|
||||
{
|
||||
return;
|
||||
|
@@ -5,18 +5,19 @@
|
||||
#include "graphics/RendererFrame.h"
|
||||
|
||||
class Renderer;
|
||||
class GameView;
|
||||
class DecorationTool: public Tool
|
||||
{
|
||||
public:
|
||||
RGBA<uint8_t> Colour;
|
||||
RendererFrame &rendererFrame;
|
||||
GameView *gameView;
|
||||
|
||||
std::unique_ptr<VideoBuffer> GetIcon(int toolID, Vec2<int> size);
|
||||
|
||||
DecorationTool(RendererFrame &newRendererFrame, int decoMode, String name, String description, RGB<uint8_t> colour, ByteString identifier):
|
||||
DecorationTool(GameView *newGameView, int decoMode, String name, String description, RGB<uint8_t> colour, ByteString identifier):
|
||||
Tool(decoMode, name, description, colour, identifier),
|
||||
Colour(0x000000_rgb .WithAlpha(0x00)),
|
||||
rendererFrame(newRendererFrame)
|
||||
gameView(newGameView)
|
||||
{}
|
||||
|
||||
virtual ~DecorationTool()
|
||||
|
@@ -396,13 +396,13 @@ void GameModel::BuildMenus()
|
||||
menuList[SC_LIFE]->AddTool(new GOLTool(*this));
|
||||
|
||||
//Add decoration tools to menu
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view->rendererFrame, DECO_ADD, "ADD", "Colour blending: Add.", 0x000000_rgb, "DEFAULT_DECOR_ADD"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view->rendererFrame, DECO_SUBTRACT, "SUB", "Colour blending: Subtract.", 0x000000_rgb, "DEFAULT_DECOR_SUB"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view->rendererFrame, DECO_MULTIPLY, "MUL", "Colour blending: Multiply.", 0x000000_rgb, "DEFAULT_DECOR_MUL"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view->rendererFrame, DECO_DIVIDE, "DIV", "Colour blending: Divide." , 0x000000_rgb, "DEFAULT_DECOR_DIV"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view->rendererFrame, DECO_SMUDGE, "SMDG", "Smudge tool, blends surrounding deco together.", 0x000000_rgb, "DEFAULT_DECOR_SMDG"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view->rendererFrame, DECO_CLEAR, "CLR", "Erase any set decoration.", 0x000000_rgb, "DEFAULT_DECOR_CLR"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view->rendererFrame, DECO_DRAW, "SET", "Draw decoration (No blending).", 0x000000_rgb, "DEFAULT_DECOR_SET"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view, DECO_ADD, "ADD", "Colour blending: Add.", 0x000000_rgb, "DEFAULT_DECOR_ADD"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view, DECO_SUBTRACT, "SUB", "Colour blending: Subtract.", 0x000000_rgb, "DEFAULT_DECOR_SUB"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view, DECO_MULTIPLY, "MUL", "Colour blending: Multiply.", 0x000000_rgb, "DEFAULT_DECOR_MUL"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view, DECO_DIVIDE, "DIV", "Colour blending: Divide." , 0x000000_rgb, "DEFAULT_DECOR_DIV"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view, DECO_SMUDGE, "SMDG", "Smudge tool, blends surrounding deco together.", 0x000000_rgb, "DEFAULT_DECOR_SMDG"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view, DECO_CLEAR, "CLR", "Erase any set decoration.", 0x000000_rgb, "DEFAULT_DECOR_CLR"));
|
||||
menuList[SC_DECO]->AddTool(new DecorationTool(view, DECO_DRAW, "SET", "Draw decoration (No blending).", 0x000000_rgb, "DEFAULT_DECOR_SET"));
|
||||
SetColourSelectorColour(colour); // update tool colors
|
||||
decoToolset[0] = GetToolFromIdentifier("DEFAULT_DECOR_SET");
|
||||
decoToolset[1] = GetToolFromIdentifier("DEFAULT_DECOR_CLR");
|
||||
|
@@ -734,6 +734,7 @@ void GameView::NotifyColourSelectorColourChanged(GameModel * sender)
|
||||
void GameView::NotifyRendererChanged(GameModel * sender)
|
||||
{
|
||||
ren = sender->GetRenderer();
|
||||
rendererFrame = &ren->GetVideo();
|
||||
rendererSettings = &sender->GetRendererSettings();
|
||||
}
|
||||
|
||||
@@ -916,7 +917,7 @@ ByteString GameView::TakeScreenshot(int captureUI, int fileType)
|
||||
std::unique_ptr<VideoBuffer> screenshot;
|
||||
if (captureUI)
|
||||
{
|
||||
screenshot = std::make_unique<VideoBuffer>(rendererFrame);
|
||||
screenshot = std::make_unique<VideoBuffer>(*rendererFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2158,7 +2159,8 @@ void GameView::OnDraw()
|
||||
{
|
||||
StartRendererThread();
|
||||
WaitForRendererThread();
|
||||
rendererFrame = ren->GetVideo();
|
||||
*rendererThreadResult = ren->GetVideo();
|
||||
rendererFrame = rendererThreadResult.get();
|
||||
DispatchRendererThread();
|
||||
}
|
||||
else
|
||||
@@ -2166,10 +2168,10 @@ void GameView::OnDraw()
|
||||
PauseRendererThread();
|
||||
ren->ApplySettings(*rendererSettings);
|
||||
RenderSimulation(*sim, true);
|
||||
rendererFrame = ren->GetVideo();
|
||||
rendererFrame = &ren->GetVideo();
|
||||
}
|
||||
|
||||
std::copy_n(rendererFrame.data(), rendererFrame.Size().X * rendererFrame.Size().Y, g->Data());
|
||||
std::copy_n(rendererFrame->data(), rendererFrame->Size().X * rendererFrame->Size().Y, g->Data());
|
||||
|
||||
if (showBrush && selectMode == SelectNone && (!zoomEnabled || zoomCursorFixed) && activeBrush && (isMouseDown || (currentMouse.X >= 0 && currentMouse.X < XRES && currentMouse.Y >= 0 && currentMouse.Y < YRES)))
|
||||
{
|
||||
@@ -2284,7 +2286,7 @@ void GameView::OnDraw()
|
||||
|
||||
if(recording)
|
||||
{
|
||||
std::vector<char> data = VideoBuffer(rendererFrame).ToPPM();
|
||||
std::vector<char> data = VideoBuffer(*rendererFrame).ToPPM();
|
||||
|
||||
ByteString filename = ByteString::Build("recordings", PATH_SEP_CHAR, recordingFolder, PATH_SEP_CHAR, "frame_", Format::Width(recordingIndex++, 6), ".ppm");
|
||||
|
||||
@@ -2609,11 +2611,11 @@ std::optional<FindingElement> GameView::FindingElementCandidate() const
|
||||
pixel GameView::GetPixelUnderMouse() const
|
||||
{
|
||||
auto point = c->PointTranslate(currentMouse);
|
||||
if (!rendererFrame.Size().OriginRect().Contains(point))
|
||||
if (!rendererFrame->Size().OriginRect().Contains(point))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
return rendererFrame[point];
|
||||
return (*rendererFrame)[point];
|
||||
}
|
||||
|
||||
void GameView::RendererThread()
|
||||
@@ -2645,6 +2647,7 @@ void GameView::StartRendererThread()
|
||||
if (rendererThreadState == rendererThreadAbsent)
|
||||
{
|
||||
rendererThreadSim = std::make_unique<RenderableSimulation>();
|
||||
rendererThreadResult = std::make_unique<RendererFrame>();
|
||||
rendererThreadState = rendererThreadRunning;
|
||||
start = true;
|
||||
}
|
||||
|
@@ -171,6 +171,8 @@ private:
|
||||
void WaitForRendererThread();
|
||||
void DispatchRendererThread();
|
||||
std::unique_ptr<RenderableSimulation> rendererThreadSim;
|
||||
std::unique_ptr<RendererFrame> rendererThreadResult;
|
||||
const RendererFrame *rendererFrame = nullptr;
|
||||
|
||||
public:
|
||||
GameView();
|
||||
@@ -261,7 +263,10 @@ public:
|
||||
void SkipIntroText();
|
||||
pixel GetPixelUnderMouse() const;
|
||||
|
||||
RendererFrame rendererFrame;
|
||||
const RendererFrame &GetRendererFrame() const
|
||||
{
|
||||
return *rendererFrame;
|
||||
}
|
||||
// Call this before accessing Renderer "out of turn", e.g. from RenderView. This *does not*
|
||||
// include OptionsModel or Lua setting functions because they only access the RendererSettings
|
||||
// in GameModel, or Lua drawing functions because they only access Renderer in eventTraitSimGraphics
|
||||
|
@@ -834,7 +834,7 @@ static int floodDeco(lua_State *L)
|
||||
|
||||
auto *lsi = GetLSI();
|
||||
// hilariously broken, intersects with console and all Lua graphics
|
||||
auto &rendererFrame = lsi->gameModel->view->rendererFrame;
|
||||
auto &rendererFrame = lsi->gameModel->view->GetRendererFrame();
|
||||
auto loc = RGB<uint8_t>::Unpack(rendererFrame[{ x, y }]);
|
||||
lsi->sim->ApplyDecorationFill(rendererFrame, x, y, r, g, b, a, loc.Red, loc.Green, loc.Blue);
|
||||
return 0;
|
||||
|
Reference in New Issue
Block a user