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

Support for EGL contexts in GrDirectContext.MakeGL #287

Closed
Swarzox opened this issue Dec 1, 2024 · 6 comments · May be fixed by #294
Closed

Support for EGL contexts in GrDirectContext.MakeGL #287

Swarzox opened this issue Dec 1, 2024 · 6 comments · May be fixed by #294

Comments

@Swarzox
Copy link

Swarzox commented Dec 1, 2024

Description

I'm encountering an issue while trying to use Skia-Python in headless mode with EGL. The ModernGL context is created successfully, but Skia is unable to detect it when the backend="egl" is used. However, it works correctly with non-EGL backends (e.g., glx or using glfw).

Here is the test code I'm using:

import moderngl
import skia
from PIL import Image

width, height = 800, 600

moderngl_context = moderngl.create_standalone_context(backend="egl")
print("ModernGL context:", moderngl_context)

skia_context = skia.GrDirectContext.MakeGL()
print("Skia context:", skia_context)

info = skia.ImageInfo.MakeN32Premul(width, height)

surface = skia.Surface.MakeRenderTarget(
    skia_context,
    skia.Budgeted.kYes,
    info
)

canvas = surface.getCanvas()
canvas.clear(skia.Color(255, 255, 255, 255))

paint = skia.Paint(
    Color=skia.Color(0, 100, 255, 200),
    Style=skia.Paint.kFill_Style,
    AntiAlias=True
)

canvas.drawCircle(width // 2, height // 2, min(width, height) // 4, paint)
canvas.flush()

image = surface.makeImageSnapshot()

pixels = image.tobytes()
image = Image.frombytes("RGBA", (width, height), pixels)
image.save('skia_circle.png')

Steps to Reproduce

  1. Use the provided code with moderngl.create_standalone_context(backend="egl").
  2. Observe that the skia.GrDirectContext.MakeGL() context is None.

Expected Behavior

Skia should detect the EGL-based ModernGL context and render as expected.


Actual Behavior

Skia fails to detect the EGL context, and skia.GrDirectContext.MakeGL() returns None.


Additional Notes

  • The same code works when backend="glx" or when using glfw, which relies on xorg and GLX.
  • Running headless with EGL is critical for our use case to avoid X11 dependencies.

Let me know if more details or logs are needed.

@HinTak
Copy link
Collaborator

HinTak commented Dec 2, 2024

I don't think we have the resource to look at it at all, for a special use case. I suggest you ask the moderngl people. Also, it would be a good idea to make sure you can run upstream's EGL related code in your setup. I found this on a quick search:

https://github.com/google/skia/blob/master/tests/EGLImageTest.cpp

Maybe reading upstream EGL related code could give you some ideas. Sorry.

@HinTak
Copy link
Collaborator

HinTak commented Dec 8, 2024

@Swarzox two comments: (1) I am not familiar with moderngl, but your code probably are missing a step along the line of "make this glcontext current"? Immediately making it current is probably implicit for the other ways of creating a context, but maybe not "hand-crafted" ones like you did, (2) glfw itself apparently support egl backend too; you may need to compile glfw yourself to get that - and in turn, pass it along to pyglfw, etc

Either way, if you find out how to do it, please share.

@HinTak
Copy link
Collaborator

HinTak commented Dec 8, 2024

I wrote the above because "MakeGL" is supposed to just get the current. If that fails, it is either that you created a context but did not make it current, or the current isn't compatible with skia. So one direction of trying to fix your code, is to dump "what is current" between your moderngl code and the skia code.

@HinTak
Copy link
Collaborator

HinTak commented Dec 8, 2024

How to dump the egl context in glfw:
https://www.glfw.org/docs/3.3/group__native.html

@HinTak
Copy link
Collaborator

HinTak commented Dec 10, 2024

@Swarzox okay, I looked at the upstream skia example code - the urls I posted - and I think this is the definitive answer: you need to build skia itself differently (editing scripts/build_Linux.sh and adding skia_use_egl=true near the end ; you may need to edit setup.py too later when you build skia-python after you have built skia differently too) . However, skia_use_egl is orthogonal to the Linux x11 glx code, as you can see from these two neighbouring lines:
https://github.com/google/skia/blob/e11d707452240d4d69910aa6f4e815b4f0420eea/BUILD.gn#L1003
https://github.com/google/skia/blob/e11d707452240d4d69910aa6f4e815b4f0420eea/BUILD.gn#L1016 . Setting skia_use_egl will make linux x11 use egl too, and will be a complete change of default behavior, so we can't make this change here.

Btw, glfw (and pyglfw) has a egl mode too, but you probably should use the latest of both.

I suggest you try rebuilding skia and skia-python that way, and see if it will do the job. If you need help on that, we can always talk about it separately/privately as a paid commercial commission, as I'll need to know a bit more about your platform, and you may need to arrange for me to have remote login access to it, etc. Depending on your budget, I suppose it might even be possible to patch skia itself, and carry a change permanently, to make egl and x11 switchable at run time. I think it is do-able but will take multiple days of work and testing.

And, you can file upstream at https://issues.skia.org and ask them to make skia switchable between egl and x11 at runtime, rather than either/or at build-time, too.

Cc @kyamagu

@HinTak HinTak closed this as not planned Won't fix, can't repro, duplicate, stale Dec 10, 2024
@HinTak
Copy link
Collaborator

HinTak commented Dec 11, 2024

@Swarzox AFAIC, I needed to make two changes (1) adding skia_use_egl=true to how we build skia, (2) adding EGL to around line 100 of setup.py, near fontconfig, GL etc, the list of libraries to link to. Then your example just works as is in my console login, completely without x11 or wayland. Just two additional lines, one in build_Linux.sh, one in setup.py.

In fact in x11, it seems to behaves just like glx build, too, as far as our test suite goes. In headless console login, our test suite fails to initialize glfw, but that seems to be a glfw wheel problem.

Anyway, your example works as is on my headless console, if you build skia-python as I outlined with those two additional lines. The libEGL libraries on my system comes from libglvnd , and libGL from mesa3d. It is likely you'll have either or both from your GPU vendor, and you should build skia against your GPU vendor's provision, instead of mesa.

HinTak added a commit to HinTak/skia-python that referenced this issue Dec 24, 2024
…L contexts with EGL

There are two ways of enabling EGL support on Linux AFAIK: `skia_use_egl=true` switches over
to X11 completely. Or we just add `GrGLInterfaces::MakeEGL` to GLX builds. This
is the 2nd approach. `skia_use_egl=true` is simpler, but modifies existing X11 behavior.

Fixes kyamagu#287
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants