From 52557ee9795e3e47b71e3dab4c26c6fee4d8d917 Mon Sep 17 00:00:00 2001 From: EvilSpirit Date: Thu, 30 Jun 2016 21:54:35 +0600 Subject: [PATCH] Add an interface for view-independent rendering. To actually achieve improved performance with the OpenGL 2 renderer, we have to cache geometry that doesn't change when the viewport does (note that the rendered pixels can change quite dramatically because we can reconfigure shaders; e.g. stippling can be drawn in screen coordinates). This commit adds a BatchCanvas interface that can be implemented by renderers, and uses it for drawing entities such as lines and points. --- src/confscreen.cpp | 1 + src/draw.cpp | 32 ++++++++++++++++++++++++++------ src/generate.cpp | 2 ++ src/graphicswin.cpp | 4 ++++ src/render/render.cpp | 12 ++++++++++++ src/render/render.h | 15 ++++++++++++++- src/style.cpp | 3 +++ src/textscreens.cpp | 1 + src/ui.h | 3 +++ 9 files changed, 66 insertions(+), 7 deletions(-) diff --git a/src/confscreen.cpp b/src/confscreen.cpp index e70e9216..8fca9c04 100644 --- a/src/confscreen.cpp +++ b/src/confscreen.cpp @@ -80,6 +80,7 @@ void TextWindow::ScreenChangeFixExportColors(int link, uint32_t v) { void TextWindow::ScreenChangeBackFaces(int link, uint32_t v) { SS.drawBackFaces = !SS.drawBackFaces; + SS.GW.persistentDirty = true; InvalidateGraphics(); } diff --git a/src/draw.cpp b/src/draw.cpp index 4f080643..dea1840e 100644 --- a/src/draw.cpp +++ b/src/draw.cpp @@ -562,12 +562,9 @@ void GraphicsWindow::DrawSnapGrid(Canvas *canvas) { } } -void GraphicsWindow::DrawPersistent(Canvas *canvas) { - // Draw the active group; this does stuff like the mesh and edges. - SK.GetGroup(activeGroup)->Draw(canvas); - - // Now draw the entities. +void GraphicsWindow::DrawEntities(Canvas *canvas, bool persistent) { for(Entity &e : SK.entity) { + if(persistent == (e.IsNormal() || e.IsWorkplane())) continue; switch(SS.GW.drawOccludedAs) { case DrawOccludedAs::VISIBLE: e.Draw(Entity::DrawAs::OVERLAY, canvas); @@ -581,6 +578,14 @@ void GraphicsWindow::DrawPersistent(Canvas *canvas) { break; } } +} + +void GraphicsWindow::DrawPersistent(Canvas *canvas) { + // Draw the active group; this does stuff like the mesh and edges. + SK.GetGroup(activeGroup)->Draw(canvas); + + // Now draw the entities that don't change with viewport. + DrawEntities(canvas, /*persistent=*/true); // Draw filled paths in all groups, when those filled paths were requested // specially by assigning a style with a fill color, or when the filled @@ -629,7 +634,22 @@ void GraphicsWindow::Draw(Canvas *canvas) { if(showSnapGrid) DrawSnapGrid(canvas); // Draw all the things that don't change when we rotate. - DrawPersistent(canvas); + if(persistentCanvas != NULL) { + if(persistentDirty) { + persistentDirty = false; + + persistentCanvas->Clear(); + DrawPersistent(&*persistentCanvas); + persistentCanvas->Finalize(); + } + + persistentCanvas->Draw(); + } else { + DrawPersistent(canvas); + } + + // Draw the entities that do change with viewport. + DrawEntities(canvas, /*persistent=*/false); // Draw the polygon errors. if(SS.checkClosedContour) { diff --git a/src/generate.cpp b/src/generate.cpp index 9865efae..ecde2021 100644 --- a/src/generate.cpp +++ b/src/generate.cpp @@ -352,6 +352,8 @@ void SolveSpaceUI::GenerateAll(Generate type, bool andFindFree, bool genForBBox) FreeAllTemporary(); allConsistent = true; + SS.GW.persistentDirty = true; + endMillis = GetMilliseconds(); if(endMillis - startMillis > 30) { diff --git a/src/graphicswin.cpp b/src/graphicswin.cpp index 81f502a0..1a552c28 100644 --- a/src/graphicswin.cpp +++ b/src/graphicswin.cpp @@ -206,6 +206,10 @@ std::string SolveSpace::MakeAcceleratorLabel(int accel) { void GraphicsWindow::Init() { canvas = CreateRenderer(); + if(canvas) { + persistentCanvas = canvas->CreateBatch(); + persistentDirty = true; + } scale = 5; offset = Vector::From(0, 0, 0); diff --git a/src/render/render.cpp b/src/render/render.cpp index a8ae6355..6382fc2d 100644 --- a/src/render/render.cpp +++ b/src/render/render.cpp @@ -211,6 +211,18 @@ Canvas::hFill Canvas::GetFill(const Fill &fill) { return fills.AddAndAssignId(&fillCopy); } +std::shared_ptr Canvas::CreateBatch() { + return std::shared_ptr(); +} + +//----------------------------------------------------------------------------- +// An interface for view-independent visualization +//----------------------------------------------------------------------------- + +const Camera &BatchCanvas::GetCamera() const { + ssassert(false, "Geometry drawn on BatchCanvas must be independent from camera"); +} + //----------------------------------------------------------------------------- // A wrapper around Canvas that simplifies drawing UI in screen coordinates //----------------------------------------------------------------------------- diff --git a/src/render/render.h b/src/render/render.h index a521be41..fa8a7917 100644 --- a/src/render/render.h +++ b/src/render/render.h @@ -50,6 +50,8 @@ public: Vector lightDirection[2]; }; +class BatchCanvas; + // An interface for populating a drawing area with geometry. class Canvas { public: @@ -162,9 +164,11 @@ public: const Vector &o, const Vector &u, const Vector &v, const Point2d &ta, const Point2d &tb, hFill hcf) = 0; virtual void InvalidatePixmap(std::shared_ptr pm) = 0; + + virtual std::shared_ptr CreateBatch(); }; -// An interface for view-dependent visualization +// An interface for view-dependent visualization. class ViewportCanvas : public Canvas { public: virtual void SetCamera(const Camera &camera, bool filp = FLIP_FRAMEBUFFER) = 0; @@ -177,6 +181,15 @@ public: virtual void GetIdent(const char **vendor, const char **renderer, const char **version) = 0; }; +// An interface for view-independent visualization. +class BatchCanvas : public Canvas { +public: + const Camera &GetCamera() const override; + + virtual void Finalize() = 0; + virtual void Draw() = 0; +}; + // A wrapper around Canvas that simplifies drawing UI in screen coordinates. class UiCanvas { public: diff --git a/src/style.cpp b/src/style.cpp index c265dfc7..23a87cf6 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -491,6 +491,7 @@ void TextWindow::ScreenChangeStylePatternType(int link, uint32_t v) { hStyle hs = { v }; Style *s = Style::Get(hs); s->stippleType = (StipplePattern)(link - 1); + SS.GW.persistentDirty = true; } void TextWindow::ScreenChangeStyleMetric(int link, uint32_t v) { @@ -639,6 +640,7 @@ void TextWindow::ScreenChangeStyleYesNo(int link, uint32_t v) { s->textOrigin = (Style::TextOrigin)((uint32_t)s->textOrigin | (uint32_t)Style::TextOrigin::TOP); break; } + SS.GW.persistentDirty = true; InvalidateGraphics(); } @@ -721,6 +723,7 @@ bool TextWindow::EditControlDoneForStyles(const char *str) { } default: return false; } + SS.GW.persistentDirty = true; return true; } diff --git a/src/textscreens.cpp b/src/textscreens.cpp index 07c7eb2e..74ad4f57 100644 --- a/src/textscreens.cpp +++ b/src/textscreens.cpp @@ -61,6 +61,7 @@ void TextWindow::ScreenShowGroupsSpecial(int link, uint32_t v) { Group *g = SK.GetGroup(SK.groupOrder.elem[i]); g->visible = state; } + SS.GW.persistentDirty = true; } void TextWindow::ScreenActivateGroup(int link, uint32_t v) { SS.GW.activeGroup.v = v; diff --git a/src/ui.h b/src/ui.h index 08bc1787..2ad10b5c 100644 --- a/src/ui.h +++ b/src/ui.h @@ -501,6 +501,8 @@ public: static void MenuClipboard(Command id); std::shared_ptr canvas; + std::shared_ptr persistentCanvas; + bool persistentDirty; // The width and height (in pixels) of the window. double width, height; @@ -738,6 +740,7 @@ public: void UpdateDraggedNum(Vector *pos, double mx, double my); void UpdateDraggedPoint(hEntity hp, double mx, double my); + void DrawEntities(Canvas *canvas, bool persistent); void DrawPersistent(Canvas *canvas); void Draw(Canvas *canvas);