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.
single-window
EvilSpirit 2016-06-30 21:54:35 +06:00 committed by whitequark
parent 6d2c2aecff
commit 52557ee979
9 changed files with 66 additions and 7 deletions

View File

@ -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();
}

View File

@ -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.
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) {

View File

@ -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) {

View File

@ -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);

View File

@ -211,6 +211,18 @@ Canvas::hFill Canvas::GetFill(const Fill &fill) {
return fills.AddAndAssignId(&fillCopy);
}
std::shared_ptr<BatchCanvas> Canvas::CreateBatch() {
return std::shared_ptr<BatchCanvas>();
}
//-----------------------------------------------------------------------------
// 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
//-----------------------------------------------------------------------------

View File

@ -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<const Pixmap> pm) = 0;
virtual std::shared_ptr<BatchCanvas> 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:

View File

@ -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;
}

View File

@ -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;

View File

@ -501,6 +501,8 @@ public:
static void MenuClipboard(Command id);
std::shared_ptr<ViewportCanvas> canvas;
std::shared_ptr<BatchCanvas> 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);