diff --git a/NickvisionCavalier.GNOME/Blueprints/drawing_view.blp b/NickvisionCavalier.GNOME/Blueprints/drawing_view.blp
index 8750335..f1dea3f 100644
--- a/NickvisionCavalier.GNOME/Blueprints/drawing_view.blp
+++ b/NickvisionCavalier.GNOME/Blueprints/drawing_view.blp
@@ -23,4 +23,12 @@ Gtk.Stack _root {
auto-render: false;
};
}
+
+ Gtk.StackPage _cairoPage {
+ name: "cairo";
+ child: Gtk.DrawingArea _cairoArea {
+ hexpand: true;
+ vexpand: true;
+ };
+ }
}
\ No newline at end of file
diff --git a/NickvisionCavalier.GNOME/Program.cs b/NickvisionCavalier.GNOME/Program.cs
index 5a81ce9..812b280 100644
--- a/NickvisionCavalier.GNOME/Program.cs
+++ b/NickvisionCavalier.GNOME/Program.cs
@@ -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"))
diff --git a/NickvisionCavalier.GNOME/Views/DrawingView.cs b/NickvisionCavalier.GNOME/Views/DrawingView.cs
index d862ab3..9bde7e6 100644
--- a/NickvisionCavalier.GNOME/Views/DrawingView.cs
+++ b/NickvisionCavalier.GNOME/Views/DrawingView.cs
@@ -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;
@@ -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;
});
};
@@ -86,7 +106,7 @@ public DrawingView(DrawingViewController controller) : this(Builder.FromFile("dr
///
/// Frees resources used by the DrawingView object
///
- public void Dispose()
+ public new void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
@@ -109,9 +129,9 @@ protected virtual void Dispose(bool disposing)
}
///
- /// (Re)creates drawing surface
+ /// (Re)creates drawing surface when using OpenGL
///
- private void CreateSurface()
+ private void CreateGLSurface()
{
_glSurface?.Dispose();
_skSurface?.Dispose();
@@ -124,9 +144,27 @@ private void CreateSurface()
}
}
+ ///
+ /// (Re)creates drawing surface when using Cairo
+ ///
+ 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;
+ }
+ }
+
///
/// Occurs on GLArea render frames
///
+ /// GLArea
+ /// EventArgs
+ /// Whether or not the event was handled
private bool OnRender(Gtk.GLArea sender, EventArgs e)
{
if (_skSurface == null)
@@ -146,6 +184,29 @@ private bool OnRender(Gtk.GLArea sender, EventArgs e)
return false;
}
+ ///
+ /// Occurs when DrawingArea should be redrawn
+ ///
+ /// DrawingArea
+ /// Cairo context of the DrawingArea
+ /// Area width
+ /// Area height
+ 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();
+ }
+ }
+
///
/// Occurs when settings for CAVA have changed
///
diff --git a/NickvisionCavalier.Shared/Controllers/MainWindowController.cs b/NickvisionCavalier.Shared/Controllers/MainWindowController.cs
index f7f2389..5bf6aae 100644
--- a/NickvisionCavalier.Shared/Controllers/MainWindowController.cs
+++ b/NickvisionCavalier.Shared/Controllers/MainWindowController.cs
@@ -60,7 +60,7 @@ public MainWindowController(string[] args)
{
Aura = new Aura("org.nickvision.cavalier", "Nickvision Cavalier", _("Cavalier"), _("Visualize audio with CAVA"));
Aura.Active.SetConfig("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");
diff --git a/NickvisionCavalier.Shared/org.nickvision.cavalier.metainfo.xml.in b/NickvisionCavalier.Shared/org.nickvision.cavalier.metainfo.xml.in
index 28a3d07..2c79060 100644
--- a/NickvisionCavalier.Shared/org.nickvision.cavalier.metainfo.xml.in
+++ b/NickvisionCavalier.Shared/org.nickvision.cavalier.metainfo.xml.in
@@ -35,17 +35,11 @@
-
+
New Cavalier!
- - 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!)