Skip to content

Commit

Permalink
Merge pull request #71 from NickvisionApps/cairo
Browse files Browse the repository at this point in the history
Cairo renderer
  • Loading branch information
fsobolev authored Aug 4, 2023
2 parents e01f135 + dd00826 commit 21de255
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 29 deletions.
8 changes: 8 additions & 0 deletions NickvisionCavalier.GNOME/Blueprints/drawing_view.blp
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,12 @@ Gtk.Stack _root {
auto-render: false;
};
}

Gtk.StackPage _cairoPage {
name: "cairo";
child: Gtk.DrawingArea _cairoArea {
hexpand: true;
vexpand: true;
};
}
}
8 changes: 1 addition & 7 deletions NickvisionCavalier.GNOME/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,7 @@ public Program(string[] args)
_mainWindow = null;
_mainWindowController = new MainWindowController(args);
_mainWindowController.AppInfo.Changelog =
@"* Cavalier can now be controlled from command line. Run the app with --help option to see full list of available options
* Reverse mirror option is now available with full mirror
* It's now possible to set frames per second to 144 or to a custom value
* Added anti-aliasing, so rounded items now look less pixelated
* Added ability to set background image
* New drawing mode - Splitter
* Bars limit was increased to 100
@"* Added Cairo backend that can be used in case of problems with OpenGL. To activate, run the program with environment variable CAVALIER_RENDERER=cairo
* Updated translations (Thanks everyone on Weblate!)";
_application.OnActivate += OnActivate;
if (File.Exists(Path.GetFullPath(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)) + "/org.nickvision.cavalier.gresource"))
Expand Down
87 changes: 74 additions & 13 deletions NickvisionCavalier.GNOME/Views/DrawingView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,17 @@ public partial class DrawingView : Gtk.Stack, IDisposable
private static partial void glClear(uint mask);

[Gtk.Connect] private readonly Gtk.GLArea _glArea;
[Gtk.Connect] private readonly Gtk.DrawingArea _cairoArea;

private bool _disposed;
private readonly DrawingViewController _controller;
private readonly bool _useCairo;
private readonly GSourceFunc _showGl;
private readonly GSourceFunc _queueRender;
private readonly Timer _renderTimer;
private GRContext? _ctx;
private SKSurface? _glSurface;
private Cairo.ImageSurface? _cairoSurface;
private SKSurface? _skSurface;
private float[]? _sample;

Expand All @@ -37,33 +40,50 @@ private DrawingView(Gtk.Builder builder, DrawingViewController controller) : bas
_controller = controller;
//Build UI
builder.Connect(this);
_glArea.OnRealize += (sender, e) =>
if (Environment.GetEnvironmentVariable("CAVALIER_RENDERER")?.ToLower() == "cairo")
{
_glArea.MakeCurrent();
var grInt = GRGlInterface.Create(eglGetProcAddress);
_ctx = GRContext.CreateGl(grInt);
};
_glArea.OnResize += (sender, e) => CreateSurface();
_useCairo = true;
_cairoArea.OnResize += (sender, e) => CreateCairoSurface();
_cairoArea.SetDrawFunc(CairoDrawFunc);
}
else
{
_useCairo = false;
_glArea.OnRealize += (sender, e) =>
{
_glArea.MakeCurrent();
var grInt = GRGlInterface.Create(eglGetProcAddress);
_ctx = GRContext.CreateGl(grInt);
};
_glArea.OnResize += (sender, e) => CreateGLSurface();
_glArea.OnRender += OnRender;
}
_controller.CAVA.OutputReceived += (sender, sample) =>
{
_sample = sample;
GLib.Functions.IdleAdd(0, () =>
{
if (GetVisibleChildName() != "gl")
if (GetVisibleChildName() != (_useCairo ? "cairo" : "gl"))
{
SetVisibleChildName("gl");
SetVisibleChildName(_useCairo ? "cairo" : "gl");
}
return false;
});
};
_glArea.OnRender += OnRender;
_renderTimer = new Timer(1000.0 / _controller.Framerate);
_renderTimer.Elapsed += (sender, e) =>
{
_renderTimer.Interval = 1000.0 / _controller.Framerate;
GLib.Functions.IdleAdd(0, () =>
{
_glArea.QueueRender();
if (_useCairo)
{
_cairoArea.QueueDraw();
}
else
{
_glArea.QueueRender();
}
return false;
});
};
Expand All @@ -86,7 +106,7 @@ public DrawingView(DrawingViewController controller) : this(Builder.FromFile("dr
/// <summary>
/// Frees resources used by the DrawingView object
/// </summary>
public void Dispose()
public new void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
Expand All @@ -109,9 +129,9 @@ protected virtual void Dispose(bool disposing)
}

/// <summary>
/// (Re)creates drawing surface
/// (Re)creates drawing surface when using OpenGL
/// </summary>
private void CreateSurface()
private void CreateGLSurface()
{
_glSurface?.Dispose();
_skSurface?.Dispose();
Expand All @@ -124,9 +144,27 @@ private void CreateSurface()
}
}

/// <summary>
/// (Re)creates drawing surface when using Cairo
/// </summary>
private void CreateCairoSurface()
{
_skSurface?.Dispose();
var imgInfo = new SKImageInfo(_cairoArea.GetAllocatedWidth(), _cairoArea.GetAllocatedHeight());
_cairoSurface = new Cairo.ImageSurface(Cairo.Format.Argb32, imgInfo.Width, imgInfo.Height);
if (_cairoSurface != null)
{
_skSurface = SKSurface.Create(imgInfo, Cairo.Internal.ImageSurface.GetData(_cairoSurface.Handle), imgInfo.RowBytes);
_controller.Canvas = _skSurface.Canvas;
}
}

/// <summary>
/// Occurs on GLArea render frames
/// </summary>
/// <param name="sender">GLArea</param>
/// <param name="e">EventArgs</param>
/// <returns>Whether or not the event was handled</returns>
private bool OnRender(Gtk.GLArea sender, EventArgs e)
{
if (_skSurface == null)
Expand All @@ -146,6 +184,29 @@ private bool OnRender(Gtk.GLArea sender, EventArgs e)
return false;
}

/// <summary>
/// Occurs when DrawingArea should be redrawn
/// </summary>
/// <param name="area">DrawingArea</param>
/// <param name="ctx">Cairo context of the DrawingArea</param>
/// <param name="width">Area width</param>
/// <param name="height">Area height</param>
public void CairoDrawFunc(Gtk.DrawingArea area, Cairo.Context ctx, int width, int height)
{
if (_skSurface == null)
{
return;
}
if (_sample != null)
{
_controller.Render(_sample, (float)width, (float)height);
_cairoSurface!.Flush();
_cairoSurface.MarkDirty();
ctx.SetSourceSurface(_cairoSurface, 0, 0);
ctx.Paint();
}
}

/// <summary>
/// Occurs when settings for CAVA have changed
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ public MainWindowController(string[] args)
{
Aura = new Aura("org.nickvision.cavalier", "Nickvision Cavalier", _("Cavalier"), _("Visualize audio with CAVA"));
Aura.Active.SetConfig<Configuration>("config");
AppInfo.Version = "2023.8.0";
AppInfo.Version = "2023.8.1-next";
AppInfo.SourceRepo = new Uri("https://github.com/NickvisionApps/Cavalier");
AppInfo.IssueTracker = new Uri("https://github.com/NickvisionApps/Cavalier/issues/new");
AppInfo.SupportUrl = new Uri("https://github.com/NickvisionApps/Cavalier/discussions");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,11 @@
</screenshot>
</screenshots>
<releases>
<release type="stable" date="2023-07-04" version="2023.8.0">
<release type="stable" date="2023-07-04" version="2023.8.1-next">
<description translatable="no">
<p>New Cavalier!</p>
<ul>
<li>Cavalier can now be controlled from command line. Run the app with --help option to see full list of available options</li>
<li>Reverse mirror option is now available with full mirror</li>
<li>It's now possible to set frames per second to 144 or to a custom value</li>
<li>Added anti-aliasing, so rounded items now look less pixelated</li>
<li>Added ability to set background image</li>
<li>New drawing mode - Splitter</li>
<li>Bars limit was increased to 100</li>
<li>Added Cairo backend that can be used in case of problems with OpenGL. To activate, run the program with environment variable CAVALIER_RENDERER=cairo</li>
<li>Updated translations (Thanks everyone on Weblate!)</li>
</ul>
</description>
Expand Down

0 comments on commit 21de255

Please sign in to comment.