Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(TFMPrevious)-tizen$(TPVTizenPrevious);$(TFMCurrent)-tizen$(TPVTizenCurrent)</TargetFrameworks>
<TargetFrameworks>$(TFMPrevious)-tizen$(TPVTizenPrevious);$(TFMCurrent)-tizen$(TPVTizenCurrent);$(TFMMinimum)-tizen$(TPVTizenMinimum)</TargetFrameworks>
<PackagingGroup>HarfBuzzSharp</PackagingGroup>
<Title>$(PackagingGroup) - Native Assets for Tizen</Title>
</PropertyGroup>
<ItemGroup>
<PackageFile Include="..\..\output\native\tizen\armel\libHarfBuzzSharp.*" PackagePath="runtimes\tizen-armel\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\i586\libHarfBuzzSharp.*" PackagePath="runtimes\tizen-x86\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\i586\libHarfBuzzSharp.*" PackagePath="runtimes\linux-x86\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\x86_64\libHarfBuzzSharp.*" PackagePath="runtimes\tizen-x64\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\aarch64\libHarfBuzzSharp.*" PackagePath="runtimes\tizen-arm64\native\%(Filename)%(Extension)" />
</ItemGroup>
<Target Name="IncludeAdditionalTfmSpecificPackageFiles">
<ItemGroup>
Expand Down
12 changes: 11 additions & 1 deletion binding/IncludeNativeAssets.HarfBuzzSharp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,24 @@
<ItemGroup Condition="$(TargetFramework.Contains('-tizen'))">
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\i586\libHarfBuzzSharp.so">
<Visible>false</Visible>
<TizenTpkSubDir>bin\runtimes\linux-x86\native\</TizenTpkSubDir>
<TizenTpkSubDir>bin\runtimes\tizen-x86\native\</TizenTpkSubDir>
<TizenTpkFileName>libHarfBuzzSharp.so</TizenTpkFileName>
</TizenTpkFiles>
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\armel\libHarfBuzzSharp.so">
<Visible>false</Visible>
<TizenTpkSubDir>bin\runtimes\tizen-armel\native\</TizenTpkSubDir>
<TizenTpkFileName>libHarfBuzzSharp.so</TizenTpkFileName>
</TizenTpkFiles>
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\x86_64\libHarfBuzzSharp.so" Condition="Exists('$(MSBuildThisFileDirectory)..\output\native\tizen\x86_64\libHarfBuzzSharp.so')">
<Visible>false</Visible>
<TizenTpkSubDir>bin\runtimes\tizen-x64\native\</TizenTpkSubDir>
<TizenTpkFileName>libHarfBuzzSharp.so</TizenTpkFileName>
</TizenTpkFiles>
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\aarch64\libHarfBuzzSharp.so" Condition="Exists('$(MSBuildThisFileDirectory)..\output\native\tizen\aarch64\libHarfBuzzSharp.so')">
<Visible>false</Visible>
<TizenTpkSubDir>bin\runtimes\tizen-arm64\native\</TizenTpkSubDir>
<TizenTpkFileName>libHarfBuzzSharp.so</TizenTpkFileName>
</TizenTpkFiles>
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.Contains('-tvos')) and '$(RuntimeIdentifier)' != ''">
Expand Down
12 changes: 11 additions & 1 deletion binding/IncludeNativeAssets.SkiaSharp.targets
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,24 @@
<ItemGroup Condition="$(TargetFramework.Contains('-tizen'))">
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\i586\libSkiaSharp.so">
<Visible>false</Visible>
<TizenTpkSubDir>bin\runtimes\linux-x86\native\</TizenTpkSubDir>
<TizenTpkSubDir>bin\runtimes\tizen-x86\native\</TizenTpkSubDir>
<TizenTpkFileName>libSkiaSharp.so</TizenTpkFileName>
</TizenTpkFiles>
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\armel\libSkiaSharp.so">
<Visible>false</Visible>
<TizenTpkSubDir>bin\runtimes\tizen-armel\native\</TizenTpkSubDir>
<TizenTpkFileName>libSkiaSharp.so</TizenTpkFileName>
</TizenTpkFiles>
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\x86_64\libSkiaSharp.so" Condition="Exists('$(MSBuildThisFileDirectory)..\output\native\tizen\x86_64\libSkiaSharp.so')">
<Visible>false</Visible>
<TizenTpkSubDir>bin\runtimes\tizen-x64\native\</TizenTpkSubDir>
<TizenTpkFileName>libSkiaSharp.so</TizenTpkFileName>
</TizenTpkFiles>
<TizenTpkFiles Include="$(MSBuildThisFileDirectory)..\output\native\tizen\aarch64\libSkiaSharp.so" Condition="Exists('$(MSBuildThisFileDirectory)..\output\native\tizen\aarch64\libSkiaSharp.so')">
<Visible>false</Visible>
<TizenTpkSubDir>bin\runtimes\tizen-arm64\native\</TizenTpkSubDir>
<TizenTpkFileName>libSkiaSharp.so</TizenTpkFileName>
</TizenTpkFiles>
</ItemGroup>

<ItemGroup Condition="$(TargetFramework.Contains('-tvos')) and '$(RuntimeIdentifier)' != ''">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>$(TFMPrevious)-tizen$(TPVTizenPrevious);$(TFMCurrent)-tizen$(TPVTizenCurrent)</TargetFrameworks>
<TargetFrameworks>$(TFMPrevious)-tizen$(TPVTizenPrevious);$(TFMCurrent)-tizen$(TPVTizenCurrent);$(TFMMinimum)-tizen$(TPVTizenMinimum)</TargetFrameworks>
<PackagingGroup>SkiaSharp</PackagingGroup>
<Title>$(PackagingGroup) - Native Assets for Tizen</Title>
</PropertyGroup>
<ItemGroup>
<PackageFile Include="..\..\output\native\tizen\armel\libSkiaSharp.*" PackagePath="runtimes\tizen-armel\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\i586\libSkiaSharp.*" PackagePath="runtimes\tizen-x86\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\i586\libSkiaSharp.*" PackagePath="runtimes\linux-x86\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\x86_64\libSkiaSharp.*" PackagePath="runtimes\tizen-x64\native\%(Filename)%(Extension)" />
<PackageFile Include="..\..\output\native\tizen\aarch64\libSkiaSharp.*" PackagePath="runtimes\tizen-arm64\native\%(Filename)%(Extension)" />
</ItemGroup>
<Target Name="IncludeAdditionalTfmSpecificPackageFiles">
<ItemGroup>
Expand Down
14 changes: 14 additions & 0 deletions binding/SkiaSharp/GRGlInterface.cs
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,7 @@ private partial class EvasGlLoader
private readonly IntPtr glEvas;
private readonly EvasGlApi api;

#if NET7_0_OR_GREATER
[LibraryImport (libevas)]
internal static partial IntPtr evas_gl_api_get (IntPtr evas_gl);

Expand All @@ -221,6 +222,19 @@ private partial class EvasGlLoader

[LibraryImport(libevas)]
internal static partial IntPtr evas_gl_proc_address_get (IntPtr evas_gl, [MarshalAs (UnmanagedType.LPStr)] string name);
#else
[DllImport (libevas)]
internal static extern IntPtr evas_gl_api_get (IntPtr evas_gl);

[DllImport (libevas)]
internal static extern IntPtr evas_gl_context_api_get (IntPtr evas_gl, IntPtr ctx);

[DllImport (libevas)]
internal static extern IntPtr evas_gl_current_context_get (IntPtr evas_gl);

[DllImport (libevas)]
internal static extern IntPtr evas_gl_proc_address_get (IntPtr evas_gl, [MarshalAs (UnmanagedType.LPStr)] string name);
#endif

static EvasGlLoader ()
{
Expand Down
2 changes: 1 addition & 1 deletion externals/skia
Submodule skia updated 1 files
+9 −1 gn/BUILDCONFIG.gn
55 changes: 40 additions & 15 deletions native/tizen/build.cake
Original file line number Diff line number Diff line change
Expand Up @@ -9,20 +9,31 @@ DirectoryPath TIZEN_STUDIO_HOME = EnvironmentVariable("TIZEN_STUDIO_HOME") ?? PR

var bat = IsRunningOnWindows() ? ".bat" : "";
var tizen = TIZEN_STUDIO_HOME.CombineWithFilePath($"tools/ide/bin/tizen{bat}").FullPath;
var tizenVersion = "6.0";

void SetProjectProfile(string projectDir, string profile)
{
var propFile = MakeAbsolute((FilePath)$"{projectDir}/project_def.prop").FullPath;
var propContent = System.IO.File.ReadAllText(propFile);
propContent = System.Text.RegularExpressions.Regex.Replace(
propContent, @"^profile = .+$", $"profile = {profile}",
System.Text.RegularExpressions.RegexOptions.Multiline);
System.IO.File.WriteAllText(propFile, propContent);
}

Task("libSkiaSharp")
.IsDependentOn("git-sync-deps")
.Does(() =>
{
Build("armel", "arm", $"mobile-{tizenVersion}-device.core");
Build("i586", "x86", $"mobile-{tizenVersion}-emulator.core");
Build("armel", "arm", "arm", "mobile-6.0-device.core", "mobile-6.0", "6.0");
Build("i586", "x86", "x86", "mobile-6.0-emulator.core", "mobile-6.0", "6.0");
Build("x86_64","x64", "x86_64", "tizen-8.0-emulator64.core", "tizen-8.0", "8.0");
Build("aarch64","arm64","aarch64", "tizen-8.0-device64.core", "tizen-8.0", "8.0");

void Build(string arch, string skiaArch, string rootstrap)
void Build(string outputDir, string skiaArch, string tizenArch, string rootstrap, string profile, string ncliVersion)
{
if (Skip(arch)) return;
if (Skip(outputDir)) return;

GnNinja($"tizen/{arch}", "skia modules/skottie",
GnNinja($"tizen/{outputDir}", "skia modules/skottie",
$"target_os='tizen' " +
$"target_cpu='{skiaArch}' " +
$"skia_enable_ganesh=true " +
Expand All @@ -39,14 +50,20 @@ Task("libSkiaSharp")
$"skia_enable_skottie=true " +
$"extra_cflags=[ '-DSKIA_C_DLL', '-DXML_DEV_URANDOM' ] " +
$"ncli='{TIZEN_STUDIO_HOME}' " +
$"ncli_version='{tizenVersion}'");
$"ncli_version='{ncliVersion}'");

SetProjectProfile("libSkiaSharp", profile);

var buildDir = MakeAbsolute((DirectoryPath)$"libSkiaSharp/{CONFIGURATION}");
if (DirectoryExists(buildDir))
DeleteDirectory(buildDir, new DeleteDirectorySettings { Recursive = true, Force = true });

RunProcess(tizen, new ProcessSettings {
Arguments = $"build-native -a {skiaArch} -c llvm -C {CONFIGURATION} -r {rootstrap}" ,
Arguments = $"build-native -a {tizenArch} -c llvm -C {CONFIGURATION} -r {rootstrap}",
WorkingDirectory = MakeAbsolute((DirectoryPath)"libSkiaSharp").FullPath,
});

var outDir = OUTPUT_PATH.Combine(arch);
var outDir = OUTPUT_PATH.Combine(outputDir);
EnsureDirectoryExists(outDir);
CopyFile($"libSkiaSharp/{CONFIGURATION}/libskiasharp.so", outDir.CombineWithFilePath("libSkiaSharp.so"));
}
Expand All @@ -55,19 +72,27 @@ Task("libSkiaSharp")
Task("libHarfBuzzSharp")
.Does(() =>
{
Build("armel", "arm", $"mobile-{tizenVersion}-device.core");
Build("i586", "x86", $"mobile-{tizenVersion}-emulator.core");
Build("armel", "arm", "mobile-6.0-device.core", "mobile-6.0");
Build("i586", "x86", "mobile-6.0-emulator.core", "mobile-6.0");
Build("x86_64","x86_64", "tizen-8.0-emulator64.core", "tizen-8.0");
Build("aarch64","aarch64","tizen-8.0-device64.core", "tizen-8.0");

void Build(string arch, string cliArch, string rootstrap)
void Build(string outputDir, string tizenArch, string rootstrap, string profile)
{
if (Skip(arch)) return;
if (Skip(outputDir)) return;

SetProjectProfile("libHarfBuzzSharp", profile);

var buildDir = MakeAbsolute((DirectoryPath)$"libHarfBuzzSharp/{CONFIGURATION}");
if (DirectoryExists(buildDir))
DeleteDirectory(buildDir, new DeleteDirectorySettings { Recursive = true, Force = true });

RunProcess(tizen, new ProcessSettings {
Arguments = $"build-native -a {cliArch} -c llvm -C {CONFIGURATION} -r {rootstrap}" ,
Arguments = $"build-native -a {tizenArch} -c llvm -C {CONFIGURATION} -r {rootstrap}",
WorkingDirectory = MakeAbsolute((DirectoryPath)"libHarfBuzzSharp").FullPath,
});

var outDir = OUTPUT_PATH.Combine(arch);
var outDir = OUTPUT_PATH.Combine(outputDir);
EnsureDirectoryExists(outDir);
CopyFile($"libHarfBuzzSharp/{CONFIGURATION}/libharfbuzzsharp.so", outDir.CombineWithFilePath("libHarfBuzzSharp.so"));
}
Expand Down
53 changes: 53 additions & 0 deletions samples/Basic/Tizen/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# SkiaSharp Tizen Sample

Demonstrates SkiaSharp views in a Tizen NUI app with a `TabView` for navigating between CPU rendering, GPU shader animation, and interactive drawing.

## Sample Pages

This sample uses `Tizen.NUI.Components.TabView` with three tabs, each demonstrating a different SkiaSharp rendering approach.

### CPU

A static scene rendered on the CPU — a radial gradient background overlaid with semi-transparent colored circles and centered "SkiaSharp" text.

**Features:**

- **`SKCanvasView`** — Software-rendered canvas integrated into the NUI view tree.
- **`SKShader`** — Radial gradient background created with `SKShader.CreateRadialGradient`.
- **`SKCanvas.DrawCircle`** — Semi-transparent colored circles composited over the gradient.
- **`SKCanvas.DrawText`** — Centered "SkiaSharp" text rendered with measured alignment.

### GPU

A real-time animated shader running at full frame rate via the NUI GPU surface, with touch interaction.

**Features:**

- **`SKGLSurfaceView`** — GPU-composited canvas using `NativeImageQueue` double-buffering through the NUI rendering pipeline.
- **`SKRuntimeEffect`** — SkSL metaball "lava lamp" shader compiled at runtime with `SKRuntimeEffect.BuildShader`.
- **Render loop** — Continuous animation driven by a `Timer` at ~60 fps with an FPS counter overlay.
- **Touch interaction** — Touch position is passed as a shader uniform (`iTouchPos`) to create an interactive white blob.

### Drawing

A freehand drawing canvas with a color palette toolbar and touch-based input.

**Features:**

- **`SKCanvasView`** — Software-rendered canvas invalidated on demand after each stroke or clear.
- **`SKPath`** — Freehand strokes captured as paths with `MoveTo` and `LineTo` from NUI touch events.
- **Color palette** — Six selectable color swatches with visual selection indicator.
- **Clear button** — Removes all strokes and resets the canvas.

## Requirements

- [.NET 10 SDK](https://dotnet.microsoft.com/download) or later
- Tizen workload: `dotnet workload install tizen`

## Running the Sample

Build:

```bash
dotnet build -f net10.0-tizen
```
83 changes: 28 additions & 55 deletions samples/Basic/Tizen/SkiaSharpSample/App.cs
Original file line number Diff line number Diff line change
@@ -1,72 +1,45 @@
using System;
using ElmSharp;
using Tizen.Applications;
using Tizen.NUI;
using Tizen.NUI.BaseComponents;
using Tizen.NUI.Components;

using SkiaSharp;
using SkiaSharp.Views.Tizen;
namespace SkiaSharpSample;

namespace SkiaSharpSample
public class App : NUIApplication
{
public class App : CoreUIApplication
{
public static void Main(string[] args)
{
Elementary.Initialize();
Elementary.ThemeOverlay();
public static SamplePage DefaultPage { get; set; } = SamplePage.Cpu;

var app = new App();
app.Run(args);
}
private GpuPage? gpuPage;

protected override void OnCreate()
{
base.OnCreate();
public static void Main(string[] args) => new App().Run(args);

Initialize();
}
protected override void OnCreate()
{
base.OnCreate();

private void Initialize()
{
var window = new Window("SkiaSharp");
window.BackButtonPressed += OnBackButtonPressed;
window.AvailableRotations = DisplayRotation.Degree_0 | DisplayRotation.Degree_180 | DisplayRotation.Degree_270 | DisplayRotation.Degree_90;
window.Show();
GetDefaultWindow().KeyEvent += OnKeyEvent;

var skiaView = new SKCanvasView(window);
skiaView.IgnorePixelScaling = true;
skiaView.PaintSurface += OnPaintSurface;
skiaView.Show();
var tabView = new TabView
{
WidthSpecification = LayoutParamPolicies.MatchParent,
HeightSpecification = LayoutParamPolicies.MatchParent,
};

var conformant = new Conformant(window);
conformant.Show();
conformant.SetContent(skiaView);
}
tabView.AddTab(new TabButton { Text = "CPU" }, new CpuPage());

private void OnPaintSurface(object sender, SKPaintSurfaceEventArgs e)
{
// the the canvas and properties
var canvas = e.Surface.Canvas;
gpuPage = new GpuPage();
tabView.AddTab(new TabButton { Text = "GPU" }, gpuPage);

// make sure the canvas is blank
canvas.Clear(SKColors.White);
tabView.AddTab(new TabButton { Text = "Drawing" }, new DrawingPage());

// draw some text
using var paint = new SKPaint
{
Color = SKColors.Black,
IsAntialias = true,
Style = SKPaintStyle.Fill
};
using var font = new SKFont
{
Size = 24
};
var coord = new SKPoint(e.Info.Width / 2, (e.Info.Height + font.Size) / 2);
canvas.DrawText("SkiaSharp", coord, SKTextAlign.Center, font, paint);
}
GetDefaultWindow().Add(tabView);
}

private void OnBackButtonPressed(object sender, EventArgs e)
void OnKeyEvent(object? sender, Window.KeyEventArgs e)
{
if (e.Key.State == Key.StateType.Down &&
(e.Key.KeyPressedName == "XF86Back" || e.Key.KeyPressedName == "Escape"))
{
gpuPage?.StopAnimation();
Exit();
}
}
Expand Down
Loading