Hi @CHENG-HSUAN
While I understand your request and concerns, a partial implementation is not the correct approach because there are many moving parts here. As you have found out with your patch, the current vtkEGLRenderWindow
won’t work with wayland since it does not have mechanism to use a wayland surface object which is required to correctly invoke eglCreateWindowSurface
. In principle, this could be an X display/Wayland surface/Win32 HDC. The main area that needs work is to adapt vtkEGLRenderWindow
to initialize from native window handles.
From my understanding, it looks like your broader objective is to get VTK applications to use native wayland (not xwayland/X). In this case, I propose extending the vtkEGLRenderWindow
for onscreen rendering. There are two items that need worked on:
- Adapt the
vtkEGLRenderWindow
to initialize EGL context using a wayland surface. Basic samples here - EGL with Wayland give an idea of the API this class will use. - Create a new
vtkWaylandRenderWindowInteractor
for user interaction on wayland. There is no VTK interactor for wayland. TheCylinder
example program exited immediately because the default interactor was in use whoseStart()
method doesn’t do anything.
In case you want to play with something and get it to render onscreen for wayland without interaction, add these lines before you call eglCreateWindowSurface
. This code is not tested and you will need to do some refactoring, like move the handlers in an internals class and declare the new member variables in the vtkInternals
class. I mostly cribbed the code from other wayland-egl samples. Think of it as a teaser on the necessary plumbing.
// Define static handler functions in global namespace and remove static.
static void global_registry_handler(
void* data, struct wl_registry* registry, uint32_t id, const char* interface, uint32_t version)
{
printf("Got a registry event for %s id %d\n", interface, id);
if (strcmp(interface, "wl_compositor") == 0)
{
compositor = wl_registry_bind(registry, id, &wl_compositor_interface, 1);
}
else if (strcmp(interface, "wl_shell") == 0)
{
shell = wl_registry_bind(registry, id, &wl_shell_interface, 1);
}
}
static void global_registry_remover(void* data, struct wl_registry* registry, uint32_t id)
{
printf("Got a registry losing event for %d\n", id);
}
static const struct wl_registry_listener registry_listener = { global_registry_handler,
global_registry_remover };
// Init the NativeDisplay and Display before eglInitialize.
impl->NativeWaylandDisplay = wl_display_connect(NULL);
if (impl->NativeWaylandDisplay == NULL)
{
fprintf(stderr, "Can't connect to display\n");
exit(1);
}
impl->Display = eglGetDisplay((EGLNativeDisplayType)impl->NativeWaylandDisplay);
struct wl_registry* registry = wl_display_get_registry(impl->NativeWaylandDisplay);
wl_registry_add_listener(registry, ®istry_listener, NULL);
wl_display_dispatch(impl->NativeWaylandDisplay);
wl_display_roundtrip(impl->NativeWaylandDisplay);
if (impl->WaylandCompositor == NULL || impl->WaylandShell == NULL)
{
fprintf(stderr, "Can't find compositor or shell\n");
exit(1);
}
else
{
fprintf(stderr, "Found compositor and shell\n");
}
impl->WaylandSurface = wl_compositor_create_surface(impl->WaylandCompositor);
if (impl->WaylandSurface == NULL)
{
fprintf(stderr, "Can't create surface\n");
exit(1);
}
else
{
fprintf(stderr, "Created surface\n");
}
impl->WaylandShellSurface = wl_shell_get_shell_surface(impl->WaylandShell, surface);
wl_shell_surface_set_toplevel(impl->WaylandShellSurface);
impl->Window = wl_egl_window_create(impl->Surface, this->Size[0], this->Size[1]);
if (impl->Window == EGL_NO_SURFACE)
{
fprintf(stderr, "Can't create egl window\n");
exit(1);
}
else
{
fprintf(stderr, "Created egl window\n");
}