Skip to content

Commit

Permalink
fix(Studio): A few issues with the macOS SkiaSharp rendering
Browse files Browse the repository at this point in the history
  • Loading branch information
psyGamer committed Nov 5, 2024
1 parent fcb21b8 commit 8a95136
Showing 1 changed file with 24 additions and 40 deletions.
64 changes: 24 additions & 40 deletions Studio/CelesteStudio.Mac/SkiaDrawableHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
using Eto.Mac.Forms;
using MonoMac.AppKit;
using MonoMac.CoreGraphics;
using MonoMac.Foundation;
using SkiaSharp;
using System;
using System.Runtime.InteropServices;

namespace CelesteStudio.Mac;

Expand All @@ -21,72 +20,57 @@ public bool CanFocus {
}

public class SkiaDrawableView(SkiaDrawable drawable) : MacPanelView {
private IntPtr bitmapData;
private int lastLength;

private NSMutableData? bitmapData;
private CGDataProvider? dataProvider;
private SKSurface? surface;

private readonly CGColorSpace colorSpace = CGColorSpace.CreateDeviceRGB();
private CGDataProvider? dataProvider;
private CGImage? image;

public override void DrawRect(CGRect dirtyRect)
{
public override void DrawRect(CGRect dirtyRect) {
base.DrawRect(dirtyRect);

var bounds = new CGRect(drawable.DrawX, drawable.DrawY, drawable.DrawWidth, drawable.DrawHeight);
var bounds = new CGRect(drawable.DrawX, drawable.DrawY, drawable.DrawWidth * Window.BackingScaleFactor, drawable.DrawHeight * Window.BackingScaleFactor);
var info = new SKImageInfo((int)bounds.Width, (int)bounds.Height, SKColorType.Rgba8888, SKAlphaType.Premul);

// Allocate a memory block for the drawing process
int newLength = info.BytesSize;
if (lastLength != newLength)
{
lastLength = newLength;
if (bitmapData != IntPtr.Zero) {
bitmapData = Marshal.ReAllocCoTaskMem(bitmapData, newLength);
} else {
bitmapData = Marshal.AllocCoTaskMem(newLength);
}
// Allocate a memory for the drawing process
nuint infoLength = (nuint)info.BytesSize;
if (bitmapData?.Length != infoLength) {
dataProvider?.Dispose();
bitmapData?.Dispose();

surface?.Dispose();
surface = SKSurface.Create(info, bitmapData, info.RowBytes);
bitmapData = NSMutableData.FromLength(infoLength);
dataProvider = new CGDataProvider(bitmapData.MutableBytes, info.BytesSize);

dataProvider?.Dispose();
dataProvider = new CGDataProvider(bitmapData, lastLength);

image?.Dispose();
image = new CGImage(
info.Width, info.Height,
8, info.BitsPerPixel, info.RowBytes,
colorSpace, CGBitmapFlags.ByteOrder32Big | CGBitmapFlags.PremultipliedLast,
dataProvider, null, false, CGColorRenderingIntent.Default);
surface?.Dispose();
surface = SKSurface.Create(info, bitmapData.MutableBytes, info.RowBytes);
}

using (new SKAutoCanvasRestore(surface!.Canvas, true)) {
drawable.Draw(surface);
}
surface.Canvas.Flush();

using var image = new CGImage(
info.Width, info.Height,
8, info.BitsPerPixel, info.RowBytes,
colorSpace, CGBitmapFlags.ByteOrder32Big | CGBitmapFlags.PremultipliedLast,
dataProvider, null, false, CGColorRenderingIntent.Default);

var ctx = NSGraphicsContext.CurrentContext.GraphicsPort;
ctx.DrawImage(bounds, image);
}

protected override void Dispose(bool disposing) {
Marshal.FreeCoTaskMem(bitmapData);
dataProvider?.Dispose();
dataProvider = null;

bitmapData = IntPtr.Zero;
lastLength = 0;
bitmapData?.Dispose();
bitmapData = null;

surface?.Dispose();
surface = null;

colorSpace.Dispose();

dataProvider?.Dispose();
dataProvider = null;

image?.Dispose();
image = null;
}
}
}

0 comments on commit 8a95136

Please sign in to comment.