[Tizen] Change tizen graphics backend engine (#2225)

This commit is contained in:
Seungkeun Lee 2022-08-30 08:11:21 +09:00 коммит произвёл GitHub
Родитель 8ab4146cbf
Коммит 88c096095f
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
14 изменённых файлов: 436 добавлений и 47 удалений

Просмотреть файл

@ -2,8 +2,11 @@
<configuration>
<packageSources>
<clear />
<add key="darc-pub-dotnet-runtime-531f715" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-runtime-531f715f/nuget/v3/index.json" />
<add key="darc-pub-dotnet-emsdk-3f6c45a" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-3f6c45a2/nuget/v3/index.json" />
<add key="dotnet-public" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-public/nuget/v3/index.json" />
<add key="dotnet6" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json" />
<add key="dotnet7" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet7/nuget/v3/index.json" />
<add key="dotnet-eng" value="https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet-eng/nuget/v3/index.json" />
</packageSources>
</configuration>

Просмотреть файл

@ -16,7 +16,7 @@ variables:
XCODE_VERSION: 13.2.1
VISUAL_STUDIO_VERSION: '17/pre'
DOTNET_VERSION_PREVIEW: '6.0.400'
DOTNET_WORKLOAD_SOURCE: 'https://aka.ms/dotnet/maui/6.0.486.json'
DOTNET_WORKLOAD_SOURCE: 'https://maui.blob.core.windows.net/metadata/rollbacks/6.0.513.json'
CONFIGURATION: 'Release'
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
THROW_ON_TEST_FAILURE: true

Просмотреть файл

@ -11,8 +11,8 @@ $previewRuntime = 'https://api.nuget.org/v3/index.json'
$previewEmscripten = 'https://api.nuget.org/v3/index.json'
if ($IsPreview) {
$previewFeed = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/dotnet6/nuget/v3/index.json'
$previewRuntime = 'https://api.nuget.org/v3/index.json'
$previewEmscripten = 'https://api.nuget.org/v3/index.json'
$previewRuntime = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-runtime-531f715f/nuget/v3/index.json'
$previewEmscripten = 'https://pkgs.dev.azure.com/dnceng/public/_packaging/darc-pub-dotnet-emsdk-3f6c45a2/nuget/v3/index.json'
}
Write-Host "Installing .NET workloads..."

Просмотреть файл

@ -27,19 +27,7 @@ namespace SkiaSharp.Views.Maui.Controls.Hosting
#if !NETSTANDARD
if (registerRenderers)
{
#if __TIZEN__
#pragma warning disable CS0612 // Type or member is obsolete
if (replaceHandlers)
handlers.AddCompatibilityRenderer<SKCanvasView, SKCanvasViewRenderer>();
else
handlers.TryAddCompatibilityRenderer(typeof(SKCanvasView), typeof(SKCanvasViewRenderer));
if (replaceHandlers)
handlers.AddCompatibilityRenderer<SKGLView, SKGLViewRenderer>();
else
handlers.TryAddCompatibilityRenderer(typeof(SKGLView), typeof(SKGLViewRenderer));
#pragma warning restore CS0612 // Type or member is obsolete
#else
#if !__TIZEN__
if (replaceHandlers)
handlers.AddHandler<SKCanvasView, SKCanvasViewRenderer>();
else
@ -54,10 +42,12 @@ namespace SkiaSharp.Views.Maui.Controls.Hosting
#endif
}
#if !__TIZEN__
CompatRegistrar.Registered.Register(typeof(SKImageImageSource), typeof(SKImageSourceHandler));
CompatRegistrar.Registered.Register(typeof(SKBitmapImageSource), typeof(SKImageSourceHandler));
CompatRegistrar.Registered.Register(typeof(SKPixmapImageSource), typeof(SKImageSourceHandler));
CompatRegistrar.Registered.Register(typeof(SKPictureImageSource), typeof(SKImageSourceHandler));
#endif
#endif
});
}

Просмотреть файл

@ -40,7 +40,7 @@
<None Include="**\*.Tizen.cs" />
</ItemGroup>
<!-- forms files -->
<ItemGroup>
<ItemGroup Condition="!$(TargetFramework.Contains('-tizen'))">
<Compile Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Native.Shared\SKCanvasViewRendererBase.cs" Link="SKCanvasViewRendererBase.cs" />
<Compile Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Native.Shared\SKGLViewRendererBase.cs" Link="SKGLViewRendererBase.cs" />
</ItemGroup>
@ -74,14 +74,4 @@
<None Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.UWP\SKGLViewRenderer.cs" Link="Windows\SKGLViewRenderer.cs" />
<None Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.UWP\SKImageSourceHandler.cs" Link="Windows\SKImageSourceHandler.cs" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.Contains('-tizen'))">
<Compile Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Tizen\SKCanvasViewRenderer.cs" Link="Tizen\SKCanvasViewRenderer.cs" />
<Compile Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Tizen\SKGLViewRenderer.cs" Link="Tizen\SKGLViewRenderer.cs" />
<Compile Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Tizen\SKImageSourceHandler.cs" Link="Tizen\SKImageSourceHandler.cs" />
</ItemGroup>
<ItemGroup Condition="!$(TargetFramework.Contains('-tizen'))">
<None Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Tizen\SKCanvasViewRenderer.cs" Link="Tizen\SKCanvasViewRenderer.cs" />
<None Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Tizen\SKGLViewRenderer.cs" Link="Tizen\SKGLViewRenderer.cs" />
<None Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Tizen\SKImageSourceHandler.cs" Link="Tizen\SKImageSourceHandler.cs" />
</ItemGroup>
</Project>

Просмотреть файл

@ -1,8 +1,7 @@
using Microsoft.Maui;
using Microsoft.Maui.Handlers;
using Microsoft.Maui.Platform;
using SkiaSharp.Views.Tizen;
using Microsoft.Maui.Handlers;
using SkiaSharp.Views.Maui.Platform;
using SkiaSharp.Views.Tizen.NUI;
using ScalingInfo = SkiaSharp.Views.Tizen.ScalingInfo;
namespace SkiaSharp.Views.Maui.Handlers
{
@ -11,7 +10,7 @@ namespace SkiaSharp.Views.Maui.Handlers
private SKSizeI lastCanvasSize;
private SKTouchHandler? touchHandler;
protected override SKCanvasView CreatePlatformView() => new SKCanvasView(PlatformParent);
protected override SKCanvasView CreatePlatformView() => new SKCanvasView();
protected override void ConnectHandler(SKCanvasView platformView)
{

Просмотреть файл

@ -4,16 +4,18 @@ using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Microsoft.Maui;
using Tizen.UIExtensions.ElmSharp;
using Microsoft.Maui.Platform;
namespace SkiaSharp.Views.Maui.Handlers
{
public partial class SKImageSourceService
{
public override Task<IImageSourceServiceResult<Image>?> GetImageAsync(IImageSource imageSource, Image image, CancellationToken cancellationToken = default) =>
GetImageAsync((IStreamImageSource)imageSource, image, cancellationToken);
public override Task<IImageSourceServiceResult<MauiImageSource>?> GetImageAsync(
IImageSource imageSource,
CancellationToken cancellationToken = default) =>
GetImageAsync((IStreamImageSource)imageSource, cancellationToken);
public async Task<IImageSourceServiceResult<Image>?> GetImageAsync(IStreamImageSource imageSource, Image image, CancellationToken cancellationToken = default)
public async Task<IImageSourceServiceResult<MauiImageSource>?> GetImageAsync(IStreamImageSource imageSource, CancellationToken cancellationToken = default)
{
if (imageSource.IsEmpty)
return null;
@ -32,12 +34,11 @@ namespace SkiaSharp.Views.Maui.Handlers
if (stream == null)
throw new InvalidOperationException("Unable to load image stream.");
var isLoadComplated = await image.LoadAsync(stream, cancellationToken);
var image = new MauiImageSource();
await image.LoadSource(stream);
if (!isLoadComplated)
throw new InvalidOperationException("Unable to decode image from stream.");
return new ImageSourceServiceResult(image, image.Dispose);
return new ImageSourceServiceResult(image);
}
catch (Exception ex)
{

Просмотреть файл

@ -1,4 +1,4 @@
using SkiaSharp.Views.Tizen;
using SkiaSharp.Views.Tizen.NUI;
namespace SkiaSharp.Views.Maui.Platform
{

Просмотреть файл

@ -0,0 +1,79 @@
#nullable enable
using System;
using Tizen.NUI;
using NView = Tizen.NUI.BaseComponents.View;
#if __MAUI__
namespace SkiaSharp.Views.Maui.Platform
#else
namespace SkiaSharp.Views.Forms
#endif
{
internal class SKTouchHandler
{
private Action<SKTouchEventArgs>? onTouchAction;
private Func<double, double, SKPoint>? scalePixels;
private bool touchEnabled;
private int currentId = 0;
public SKTouchHandler(Action<SKTouchEventArgs> onTouchAction, Func<double, double, SKPoint> scalePixels)
{
this.onTouchAction = onTouchAction;
this.scalePixels = scalePixels;
}
public void SetEnabled(NView view, bool enableTouchEvents)
{
if (view != null)
{
if (touchEnabled != enableTouchEvents)
{
if (enableTouchEvents)
{
view.TouchEvent += OnTouchEvent;
}
else
{
view.TouchEvent -= OnTouchEvent;
}
touchEnabled = enableTouchEvents;
}
}
}
bool OnTouchEvent(object source, NView.TouchEventArgs e)
{
var pos = e.Touch.GetLocalPosition(0);
var action = ToTouchAction(e.Touch.GetState(0));
if (action == SKTouchAction.Pressed)
{
currentId++;
}
var coords = scalePixels?.Invoke(pos.X, pos.Y) ?? new SKPoint(pos.X, pos.Y);
var inContact = (action == SKTouchAction.Pressed || action == SKTouchAction.Moved) ? true : false;
onTouchAction?.Invoke(new SKTouchEventArgs(currentId, action, coords, inContact));
return true;
}
public void Detach(NView view)
{
// clean the view
SetEnabled(view, false);
// remove references
onTouchAction = null;
scalePixels = null;
}
private static SKTouchAction ToTouchAction(PointStateType state) => state switch
{
PointStateType.Down => SKTouchAction.Pressed,
PointStateType.Up => SKTouchAction.Released,
PointStateType.Motion => SKTouchAction.Moved,
PointStateType.Leave => SKTouchAction.Exited,
PointStateType.Interrupted => SKTouchAction.Cancelled,
_ => SKTouchAction.Cancelled,
};
}
}

Просмотреть файл

@ -79,10 +79,4 @@
<ItemGroup Condition="!$(TargetFramework.Contains('-windows'))">
<None Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.UWP\SKTouchHandler.cs" Link="Platform\Windows\SKTouchHandler.cs" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.Contains('-tizen'))">
<Compile Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Tizen\SKTouchHandler.cs" Link="Platform\Tizen\SKTouchHandler.cs" />
</ItemGroup>
<ItemGroup Condition="!$(TargetFramework.Contains('-tizen'))">
<None Include="..\..\SkiaSharp.Views.Forms\SkiaSharp.Views.Forms.Tizen\SKTouchHandler.cs" Link="Platform\Tizen\SKTouchHandler.cs" />
</ItemGroup>
</Project>

Просмотреть файл

@ -0,0 +1,70 @@
using System;
using System.Threading;
using Tizen.NUI;
using NImageView = Tizen.NUI.BaseComponents.ImageView;
namespace SkiaSharp.Views.Tizen.NUI
{
public abstract class CustomRenderingView : NImageView
{
bool _redrawRequest;
protected SynchronizationContext MainloopContext { get; }
protected CustomRenderingView()
{
Layout = new CustomLayout
{
SizeUpdated = OnResized
};
MainloopContext = SynchronizationContext.Current ?? throw new InvalidOperationException("Must create on main thread");
}
public event EventHandler<SKPaintSurfaceEventArgs>? PaintSurface;
public void Invalidate()
{
if (!_redrawRequest)
{
_redrawRequest = true;
MainloopContext.Post((s) =>
{
_redrawRequest = false;
if (!Disposed)
{
OnDrawFrame();
}
}, null);
}
}
protected abstract void OnResized();
protected abstract void OnDrawFrame();
protected void SendPaintSurface(SKPaintSurfaceEventArgs e)
{
PaintSurface?.Invoke(this, e);
}
class CustomLayout : AbsoluteLayout
{
float _width;
float _height;
public Action? SizeUpdated { get; set; }
protected override void OnLayout(bool changed, LayoutLength left, LayoutLength top, LayoutLength right, LayoutLength bottom)
{
var sizeChanged = _width != Owner.SizeWidth || _height != Owner.SizeHeight;
_width = Owner.SizeWidth;
_height = Owner.SizeHeight;
if (sizeChanged)
{
SizeUpdated?.Invoke();
}
base.OnLayout(changed, left, top, right, bottom);
}
}
}
}

Просмотреть файл

@ -0,0 +1,82 @@
using Tizen.NUI;
namespace SkiaSharp.Views.Tizen.NUI
{
public class SKCanvasView : CustomRenderingView
{
private bool ignorePixelScaling;
public SKCanvasView()
{
OnResized();
}
public bool IgnorePixelScaling
{
get => ignorePixelScaling;
set
{
if (ignorePixelScaling != value)
{
ignorePixelScaling = value;
OnResized();
Invalidate();
}
}
}
protected override void OnDrawFrame()
{
if (Size.Width <= 0 || Size.Height <= 0)
return;
int width = (int)Size.Width;
int height = (int)Size.Height;
int stride = 4 * (int)Size.Width;
SKSizeI canvasSize = default(SKSizeI);
using var pixelBuffer = new PixelBuffer((uint)width, (uint)height, PixelFormat.BGRA8888);
var buffer = pixelBuffer.GetBuffer();
var info = new SKImageInfo(width, height, SKColorType.Bgra8888);
using (var surface = SKSurface.Create(info, buffer, stride))
{
if (surface == null)
{
Invalidate();
return;
}
if (IgnorePixelScaling)
{
var skiaCanvas = surface.Canvas;
skiaCanvas.Scale((float)ScalingInfo.ScalingFactor);
skiaCanvas.Save();
canvasSize.Width = (int)ScalingInfo.FromPixel(width);
canvasSize.Height = (int)ScalingInfo.FromPixel(height);
}
else
{
canvasSize.Width = width;
canvasSize.Height = height;
}
// draw using SkiaSharp
SendPaintSurface(new SKPaintSurfaceEventArgs(surface, info.WithSize(canvasSize), info));
surface.Canvas.Flush();
}
using var pixelData = PixelBuffer.Convert(pixelBuffer);
using var url = pixelData.GenerateUrl();
SetImage(url.ToString());
}
protected override void OnResized()
{
if (Size.Width <= 0 || Size.Height <= 0)
return;
OnDrawFrame();
}
}
}

Просмотреть файл

@ -0,0 +1,177 @@
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Tizen.NUI;
using NGeometry = Tizen.NUI.Geometry;
namespace SkiaSharp.Views.Tizen.NUI
{
public class SKGLSurfaceView : CustomRenderingView
{
static readonly string VERTEX_SHADER =
"attribute mediump vec2 aPosition;\n" +
"varying mediump vec2 vTexCoord;\n" +
"uniform highp mat4 uMvpMatrix;\n" +
"uniform mediump vec3 uSize;\n" +
"varying mediump vec2 sTexCoordRect;\n" +
"void main()\n" +
"{\n" +
" gl_Position = uMvpMatrix * vec4(aPosition * uSize.xy, 0.0, 1.0);\n" +
" vTexCoord = aPosition + vec2(0.5);\n" +
"}\n";
static readonly string FRAGMENT_SHADER =
"#extension GL_OES_EGL_image_external:require\n" +
"uniform lowp vec4 uColor;\n" +
"varying mediump vec2 vTexCoord;\n" +
"uniform samplerExternalOES sTexture;\n" +
"void main()\n" +
"{\n" +
" gl_FragColor = texture2D(sTexture, vTexCoord) * uColor;\n" +
"}\n";
NativeImageQueue? _nativeImageSource;
int _bufferWidth = 0;
int _bufferHeight = 0;
int _bufferStride = 0;
Renderer? _renderer;
NGeometry _geometry;
Shader _shader;
Texture? _texture;
TextureSet? _textureSet;
public SKGLSurfaceView()
{
_geometry = CreateQuadGeometry();
_shader = new Shader(VERTEX_SHADER, FRAGMENT_SHADER);
OnResized();
}
protected override void OnDrawFrame()
{
if (Size.Width == 0 || Size.Height == 0)
return;
if (_nativeImageSource?.CanDequeueBuffer() ?? false)
{
var buffer = _nativeImageSource!.DequeueBuffer(ref _bufferWidth, ref _bufferHeight, ref _bufferStride);
Debug.Assert(buffer != IntPtr.Zero, "AcquireBuffer is faild");
var info = new SKImageInfo(_bufferWidth, _bufferHeight);
using (var surface = SKSurface.Create(info, buffer, _bufferStride))
{
// draw using SkiaSharp
SendPaintSurface(new SKPaintSurfaceEventArgs(surface, info));
surface.Canvas.Flush();
}
_nativeImageSource.EnqueueBuffer(buffer);
Window.Instance.KeepRendering(0);
}
else
{
Invalidate();
}
}
protected override void OnResized()
{
if (Size.Width == 0 || Size.Height == 0)
return;
UpdateSurface();
OnDrawFrame();
UpdateTexture();
}
protected override void Dispose(bool disposing)
{
if (disposing)
{
_nativeImageSource?.Dispose();
_nativeImageSource = null;
}
base.Dispose(disposing);
}
void UpdateSurface()
{
_nativeImageSource?.Dispose();
_nativeImageSource = new NativeImageQueue((uint)Size.Width, (uint)Size.Height, NativeImageQueue.ColorFormat.BGRA8888);
}
void UpdateTexture()
{
_texture?.Dispose();
_textureSet?.Dispose();
_texture = new Texture(_nativeImageSource);
_textureSet = new TextureSet();
_textureSet.SetTexture(0, _texture);
if (_renderer == null)
{
_renderer = new Renderer(_geometry, _shader);
AddRenderer(_renderer);
}
_renderer.SetTextures(_textureSet);
}
static NGeometry CreateQuadGeometry()
{
PropertyBuffer vertexData = CreateVertextBuffer();
TexturedQuadVertex vertex1 = new TexturedQuadVertex();
TexturedQuadVertex vertex2 = new TexturedQuadVertex();
TexturedQuadVertex vertex3 = new TexturedQuadVertex();
TexturedQuadVertex vertex4 = new TexturedQuadVertex();
vertex1.position = new Vec2(-0.5f, -0.5f);
vertex2.position = new Vec2(-0.5f, 0.5f);
vertex3.position = new Vec2(0.5f, -0.5f);
vertex4.position = new Vec2(0.5f, 0.5f);
TexturedQuadVertex[] texturedQuadVertexData = new TexturedQuadVertex[4] { vertex1, vertex2, vertex3, vertex4 };
int lenght = Marshal.SizeOf(vertex1);
IntPtr pA = Marshal.AllocHGlobal(lenght * 4);
for (int i = 0; i < 4; i++)
{
Marshal.StructureToPtr(texturedQuadVertexData[i], pA + i * lenght, true);
}
vertexData.SetData(pA, 4);
NGeometry geometry = new NGeometry();
geometry.AddVertexBuffer(vertexData);
geometry.SetType(NGeometry.Type.TRIANGLE_STRIP);
return geometry;
}
static PropertyBuffer CreateVertextBuffer()
{
PropertyMap vertexFormat = new PropertyMap();
vertexFormat.Add("aPosition", new PropertyValue((int)PropertyType.Vector2));
return new PropertyBuffer(vertexFormat);
}
struct TexturedQuadVertex
{
public Vec2 position;
};
[StructLayout(LayoutKind.Sequential)]
struct Vec2
{
float x;
float y;
public Vec2(float xIn, float yIn)
{
x = xIn;
y = yIn;
}
}
}
}

Просмотреть файл

@ -17,4 +17,8 @@
<ItemGroup>
<Compile Include="..\SkiaSharp.Views.Shared\**\*.cs" Link="%(RecursiveDir)%(Filename)%(Extension)" />
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('tizen')) == true">
<Compile Remove="**\*.nui.cs" />
<None Include="**\*.nui.cs" />
</ItemGroup>
</Project>