Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FEATURE] Support Blazor Desktop #1834

Closed
IvanJosipovic opened this issue Oct 17, 2021 · 11 comments
Closed

[FEATURE] Support Blazor Desktop #1834

IvanJosipovic opened this issue Oct 17, 2021 · 11 comments

Comments

@IvanJosipovic
Copy link

IvanJosipovic commented Oct 17, 2021

I would like to use the package SkiaSharp.Views.Blazor with Blazor Desktop.

When I try using this library in Blazor Desktop, the following error is shown, "(SkiaSharp currently only works on Web Assembly.)"

@mattleibow
Copy link
Contributor

Interesting... So the Blazor right now only is on wasm, but this is another case where we probably want to use the native apis instead of Web apis...

I will see what I can do.

@mattleibow
Copy link
Contributor

@Eilon what is the story here? I suppose I expected IJSInProcessRuntime to be available on Blazor desktop/mobile since it all exists in a single process on the device.

Should it be? Is this a bug or is there another JS runtime type I should use?

@Eilon
Copy link

Eilon commented Oct 18, 2021

@mattleibow - I logged dotnet/aspnetcore#37647 to track considering adding support for the IJSInProcessRuntime interface in Blazor Desktop. We do already support IJSRuntime, but not the in-proc variation of it.

@SteveSandersonMS
Copy link

SteveSandersonMS commented Jun 13, 2022

For clarification, the only difference between IJSRuntime and IJSInProcessRuntime is that IJSInProcessRuntime supports synchronous calls. As such,

  • Platforms that can offer synchronous calls should offer IJSInProcessRuntime
  • Platforms that cannot (i.e., only support async interop calls) should offer IJSRuntime

As for Blazor Hybrid, the web view we're using is WebView2. WebView2 only supports async interop calls via its ExecuteScriptAsync API. There isn't a synchronous API. So, it is correct and by design that Blazor should only offer IJSRuntime when running on WebView2.

However, I can't think of any particular reason why SkiaSharp shouldn't be able to work on top of IJSRuntime via async calls. At least in the case of Blazor Hybrid, these async calls aren't going over a network, so they will be delivered approximately instantly even if they have a large payload. As for the naming and why this is not "in process": bear in mind that Chromium is a multiprocess browser, so these calls may indeed be crossing a process boundary. But it's still all local to one machine so should remain fast.

If there are technical reasons why it's difficult to dispatch SkiaSharp's calls over IJSRuntime, I'd love to hear more details and maybe we can help figure out a solution!

@RChrisCoble
Copy link

Thanks you @SteveSandersonMS!

@mattleibow, is using IJSRuntime viable with SkiaSharp? Is this something you can evaluate/POC?

@mattleibow
Copy link
Contributor

Hi folks, sorry for the delay I was getting things in a row and doing some research and trying to talk to folks.

As of today, I am not sure that we can technically support "SkiaSharp in the Blazor Desktop environment running in a webview" because of a few limitations. But, there are some potential options that may warrant some investigation.

@SteveSandersonMS mentions that we can try use IJSInProcessRuntime, however as he also points out this is not supported on Windows - one of the primary desktop environments. The main reason for requiring IJSInProcessRuntime is that we actually need direct access to the memory. SkiaSharp will allocate a chunk of memory and draw on that, and then we use JS to read that memory onto a HTML canvas.

@Eilon also makes a comment on the issue (which is closed) he linked:

I think that either way on these, there is no way to implement this right now anyway, and I don't think this is important enough right now to try to push all (or even any) of the browser vendors to support this, plus the relevant interop APIs. As such, I think there is little value in keeping this issue open because it doesn't have any reasonable path forward.

Basically, at this point, SkiaSharp is a .NET library that requires .NET and it requires that the .NET that is running have shared access to the memory that is readable by JS - and that is not something Blazor Desktop supports.

However, there are some potential options here:

Dual Blazor App

There is an option to run an [semi] independent app inside the app. This would be for example a Blazor WASM app that runs on a page inside a Blazor server app. For example, you would have 2 Blazor apps in the solution. You would then build the WASM app as a static asset for the Blazor server app.

This, however, is very much a heavy handed way of drawing pictures - and there is the overhead of converting things to some intermediate format (or you can use the skia internal drawing format) and then replay commands in the WASM app.

@danroth27 I am wondering if you have a link to the issue you mentioned about the other issue where Blazor WASM and Blazor server conflict as of net6.0 and only work with major hacks. And if there is any issues for the support of this for net7.

Dual Apps (Blazor Server and JS WASM)

If we follow on from the approach above, we could technically remove the Blazor on the embedded app. Since all the work is done via the underlying skia library, there is potential for you to take libSkiaSharp.a (the C++ binary) and then write a JS wrapper for it (or at least the bare bones of it) and then have that run in the background on the client and render to HTML canvases.

This approach is basically what skia CnavasKit is - a JS library that talks to a C++ binary. I just replaced JS with C# for SkiaSharp.

This has similar implications because data would have to be transported via some format - maybe binary - between the apps. However, since the app is much smaller - it can be treated as a JS library just like one would maybe write a JS interop with some graphics library or fancy combo box.

It is again important to note that this MUST be a WASM app as that is the only way I am aware of to run C++ code in any sort of browser.

Shared Libraries

This is last as it is requiring that we break out of the confines of pure HTML and Blazor. In this scenario, instead of placing a web view on a page that is "running JS" while being controlled by Blazor in a Desktop app, just use a native control.

Since all the work is shared via SkiaSharp in a very cross-platform dll, you could have the Blazor desktop runtime talk directly to the skia canvas - instead of even using the web view. This is in fact the main benefit of Blazor hybrid - you have direct access to the app. As a result - you don't NEED to stay in the web view.

I am not sure of all the capabilities, but assuming great things - you could potentially have a canvas on part of the screen and the browser on another. So when links/button/filters are changed, it sends commands like normal to the server. But, in this case instead of sending commands back into the webview, commands are sent to the native skia view.

@danroth27
Copy link

@danroth27 I am wondering if you have a link to the issue you mentioned about the other issue where Blazor WASM and Blazor server conflict as of net6.0 and only work with major hacks. And if there is any issues for the support of this for net7.

dotnet/aspnetcore#38128

@mattleibow
Copy link
Contributor

I just wanted to add that all of the options above are out of scope for SkiaSharp as a library.

When this issue (dotnet/aspnetcore#38128) is resolved, we will get the dual blazor apps automatically.

But, the other options are out of scope for now because SkiaSharp is primarily a .NET library, so the JS for WASM is not something that will happen.

And the shared libraries is not something that SkiaSharp does but rather what the developer will do based on app requirements.

But, to make things more exciting, I would consider a contribution for a JS implementation of SkiaSharp. But I do want to first have a discussion if this is actually something that is useful because I am unsure of implications as a general thing to have several WASM libraries together. What if there is a blazor wasm app that is using the JS wasm implementation via some dependency. Will there be conflicts or will the wasm system have issues?

@IvanJosipovic
Copy link
Author

I would find it useful if I could use it in WASM, Desktop and MAUI. This thread is making me feel that we have some fundamental gaps in the architecture of the Blazor Hybrid model and its disappointing.

@danroth27
Copy link

I've opened dotnet/aspnetcore#42216 to discuss how we want to handle this scenario on the Blazor side.

@mattleibow
Copy link
Contributor

Closing this issue now as it basically is not on SkiaSharp to render pictures in the embedded webviews because just like with blazor server, there is no way for skiasharp to access memory across the network or across the process boundary - since the "embedded webviews" are really just windows into another running process.

Hopefully the issue Daniel opened allows us to come up with a better client-server architecture. And the issue for running WASM in a server scenario will also help.

@ghost ghost locked as resolved and limited conversation to collaborators Aug 19, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants