Commit Graph

25 Commits (78819ffca3d4b92ede56a99b82f661d7265512bf)

Author SHA1 Message Date
Ryan Pavlik 78819ffca3 Fix "virtual function without virtual destructor" warning. NFC. 2019-09-10 06:44:34 +00:00
Ryan A. Pavlik a4c0022815 Fix a warning about a virtual destructor. 2019-09-10 03:33:05 +00:00
Ryan Pavlik 7bd4b149f7 Traits work for handles to permit sharing functionality and operators. NFC. 2019-07-10 15:40:21 +00:00
whitequark f324477dd0 Implement a platform abstraction for windows.
This commit removes a large amount of code partially duplicated
between the text and the graphics windows, and opens the path to
having more than one model window on screen at any given time,
as well as simplifies platform work.

This commit also adds complete support for High-DPI device pixel
ratio. It adds support for font scale factor (a fractional factor
on top of integral device pixel ratio) on the platform side, but not
on the application side.

This commit also adds error checking to all Windows API calls
(within the abstracted code) and fixes a significant number of
misuses and non-future-proof uses of Windows API.

This commit also makes uses of Windows API idiomatic, e.g. using
the built-in vertical scroll bar, native tooltips, control
subclassing instead of hooks in the global dispatch loop, and so on.

It reinstates tooltip support and removes menu-related hacks.
2018-07-17 13:31:17 +00:00
whitequark 7ab87caa88 Implement a platform abstraction for timers.
This commit temporarily disables tooltip functionality; it will
be handled natively in a platform abstraction for windows using
much simpler code.
2018-07-16 11:21:30 +00:00
whitequark 28f94dcd0a Start using C++ in-place member initialization.
We should make good use of in-place member initialization. Many
new classes have constructors that effectively do nothing but
default-initialize POD members, and when adding new members,
it is very easy to miss initializing them. With in-place
initialization, the code is more compact, the diffs are nicer,
and it's harder to miss them.

This commit only converts render/ and platform/ to use in-place
member initialization, since there was a bug in CairoRenderer,
but we should convert the entire codebase.
2018-07-16 11:21:30 +00:00
EvilSpirit fb667fb8bb Use a dedicated BitmapFont instance per Canvas.
Before this commit, updates to the bitmap font in the graphics window
cause missing characters in the text window and vice versa. This is
because BitmapFont contains a texture that's mutated, and sharing it
would also require sharing display lists between GL contexts, which
is not done (and overly complicated for this case anyway).
2017-01-11 03:33:10 +00:00
whitequark 6bb73a162c GTK: remove GlWidget, use standard Gtk::GLArea.
This removes a large number of hacks from the codebase, speeds up
the rendering, and removes tearing when dragging entities.
2017-01-02 16:21:05 +00:00
whitequark 9db50ed077 Refactor the renderer frame flush functionality.
This commit does three things:
  * Recognizes that BeginFrame()/EndFrame() are badly named, since
    BeginFrame() sets up framebuffer, and EndFrame() flushes a frame,
    and they do not have to be called in pairs; and so renames them
    to NewFrame()/FlushFrame().
  * Reduces the amount of frame flushes in GraphicsWindow::Paint()
    to two, which is the minimum since we use two different cameras
    for geometry and UI;
  * Changes the FPS measurement code to only take into account
    the time spent rendering our main geometry, and not the UI
    rendering or window system interaction time.
2016-11-18 04:05:12 +00:00
whitequark 156fe73bee Allow using z-index in UiCanvas, and use it for tooltips.
Before this commit, tooltips in the text window are drawn under
the red "X" indicating a disabled button. After this commit, they
are moved on top of that.

This commit also alters the OpenGL renderers' SetCamera() method
to clear the depth buffer, as that would interfere with drawing
the UI; the toolbar would get occluded by geometry.
2016-11-18 04:05:12 +00:00
EvilSpirit 92773a5770 Implement BatchCanvas for GL2. 2016-11-18 04:05:12 +00:00
EvilSpirit 52557ee979 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.
2016-11-18 04:04:32 +00:00
EvilSpirit 6d2c2aecff Implement an OpenGL 2 renderer.
There are two main reasons to desire an OpenGL 2 renderer:
 1. Compatibility. The compatibility profile, ironically, does not
    offer a lot of compatibility, and our OpenGL 1 renderer will not
    run on Android, iOS, or WebGL.
 2. Performance. The immediate mode does not scale, and in fact
    becomes very slow with only a moderate amount of lines on screen,
    and only a somewhat large amount of triangles.

This commit implements a basic OpenGL 2 renderer that uses only
features from the (OpenGL 3.2) core profile. It is not yet faster
than the OpenGL 1 renderer, primarily because it uses a lot of small
draw calls.

This commit uses OpenGL 2 on Linux and Mac OS X directly (i.e. links
to the GL symbols from version 2+); on Windows this is impossible
with the default drivers, so for now OpenGL 1 is still used there.
2016-11-18 04:04:29 +00:00
EvilSpirit f8824e1fb2 Reimplement drawing of the mesh wireframe.
OpenGL 2 and newer do not have the glPolygonMode(..., GL_LINES) API,
so produce the wireframe on our side. It's somewhat slow, and draws
every line three times, but it is cached when the OpenGL 2 renderer
is used, and this should do for a debugging feature.
2016-11-18 02:40:43 +00:00
EvilSpirit 7b9d730a23 Hide OpenGL implementation details.
Abstract the exact details of the OpenGL renderer in the render.h
header; this allows us to use GL-specific types in the renderer
class and functions without including OpenGL (and Windows, where
applicable) headers in every source file.
2016-11-14 20:30:46 +00:00
EvilSpirit b37aba00e2 Preserve stipple phase across separate piecewise linear segments.
This significantly increases visual clarity, especially for curves
with a low chord tolerance value.
2016-10-13 23:15:35 +00:00
EvilSpirit 9f97e9aad4 Allow selecting unit (px/mm) in Canvas::Stroke.
By directly specifying the desired end result to the renderer, we
can avoid regeneration of geometry.
2016-10-11 23:32:21 +00:00
Evil-Spirit 1108a6f37d Use Canvas::Stroke, not Canvas::Fill, for drawing a point.
Our points are more like fat lines than actual quads, in that they
are scale-invariant.
2016-10-11 23:32:05 +00:00
whitequark 4f49a8a9d4 Eliminate several memory leaks.
All leaks found with valgrind while running the test suite.
This commit also clears the Cairo cache to improve SNR of Valgrind
output.
2016-08-01 05:39:18 +00:00
whitequark 5e63d8301e Add a simple harness for automated, headless testing.
This commit alters the build system substantially; it adds another
platform, `headless`, that provides stubs in place of all GUI
functions, and provides a library `solvespace_headless` alongside
the main executable. To cut down build times, only the few files
that have #if defined(HEADLESS) are built twice for the executable
and the library; the rest is grouped into a new `solvespace_cad`
library. It is not usable on its own and just serves for grouping.

This commit also gates the tests behind a -DENABLE_TESTS=ON CMake
option, ON by default (but suggested as OFF in the README so that
people don't ever have to install cairo to build the executable.)

The tests introduced in this commit are (so far) rudimentary,
although functional, and they serve as a stepping point towards
introducing coverage analysis.
2016-08-01 00:48:37 +00:00
whitequark 65e2cccde0 Add a Cairo rendering backend.
This backend will be used for reproducible offscreen rendering
in integration tests.
2016-08-01 00:48:37 +00:00
whitequark 8960ee365a Add a new renderer that prepares geometry for 2d backends.
SurfaceRenderer is a new renderer implementing the Canvas interface
running entirely on the CPU; it projects strokes and triangles
in the exact same way as OpenGL would, and it can be used for
rendering into raster or vector 2d surfaces.
2016-08-01 00:48:37 +00:00
whitequark 7265121b24 Refactor GlOffscreen; remove the GLEW dependency.
It was never really needed, since both Linux and OS X, where
GlOffscreen is used, guarantee that the API we need is present,
on all OS versions we're interested in.

Also, reorganize GlOffscreen consistently with the rest of our
codebase, and don't use RAII for OpenGL resource management because
of its requirement for an active context.
2016-07-25 04:21:55 +00:00
EvilSpirit 7f411d1593 Unify displayEdges and displayOutlines.
This has the following benefits:
  * Less geometry to generate; we can do both in one pass;
  * Less geometry to draw;
  * Eliminate overdraw of outlines on top of emphasized edges;
  * In future, being able to seamlessly stitch stippled lines.

The contour edges are now also drawn before emphasized edges;
this makes intersections of contour and emphasized edges look better
as the thinner emphasized edge doesn't clobber the depth buffer.
2016-07-23 22:41:16 +00:00
whitequark e7c8c1c8f2 Abstract all (ex-OpenGL) drawing operations into a Canvas interface.
This has several desirable consequences:
  * It is now possible to port SolveSpace to a later version of
    OpenGL, such as OpenGLES 2, so that it runs on platforms that
    only have that OpenGL version;
  * The majority of geometry is now rendered without references to
    the camera in C++ code, so a renderer can now submit it to
    the video card once and re-rasterize with a different projection
    matrix every time the projection is changed, avoiding expensive
    reuploads;
  * The DOGD (draw or get distance) interface is now
    a straightforward Canvas implementation;
  * There are no more direct references to SS.GW.(projection)
    in sketch rendering code, which allows rendering to multiple
    viewports;
  * There are no more unnecessary framebuffer flips on CPU on Cocoa
    and GTK;
  * The platform-dependent GL code is now confined to rendergl1.cpp.
  * The Microsoft and Apple headers required by it that are prone to
    identifier conflicts are no longer included globally;
  * The rendergl1.cpp implementation can now be omitted from
    compilation to run SolveSpace headless or with a different
    OpenGL version.

Note these implementation details of Canvas:
  * GetCamera currently always returns a reference to the field
    `Camera camera;`. This is so that a future renderer that caches
    geometry in the video memory can define it as asserting, which
    would provide assurance against code that could accidentally
    put something projection-dependent in the cache;
  * Line and triangle rendering is specified through a level of
    indirection, hStroke and hFill. This is so that a future renderer
    that batches geometry could cheaply group identical styles.
  * DrawPixmap and DrawVectorText accept a (o,u,v) and not a matrix.
    This is so that a future renderer into an output format that
    uses 2d transforms (e.g. SVG) could easily derive those.

Some additional internal changes were required to enable this:
  * Pixmap is now always passed as std::shared_ptr<{const ,}Pixmap>.
    This is so that the renderer could cache uploaded textures
    between API calls, which requires it to capture a (weak)
    reference.
  * The PlatformPathEqual function was properly extracted into
    platform-specific code. This is so that the <windows.h> header
    could be included only where needed (in platform/w32* as well
    as rendergl1.cpp).
  * The SBsp{2,3}::DebugDraw functions were removed. They can be
    rewritten using the Canvas API if they are ever needed.

While no visual changes were originally intended, some minor fixes
happened anyway:
  * The "emphasis" yellow line from top-left corner is now correctly
    rendered much wider.
  * The marquee rectangle is now pixel grid aligned.
  * The hidden entities now do not clobber the depth buffer, removing
    some minor artifacts.
  * The workplane "tab" now scales with the font used to render
    the workplane name.
  * The workplane name font is now taken from the normals style.
  * Workplane and constraint line stipple is insignificantly
    different. This is so that it can reuse the existing stipple
    codepaths; rendering of workplanes and constraints predates
    those.

Some debug functionality was added:
  * In graphics window, an fps counter that becomes red when
    rendering under 60fps is drawn.
2016-07-23 22:31:18 +00:00