From 4b36bca4c6708bc81c6b6e5923a93beb26e696c7 Mon Sep 17 00:00:00 2001 From: Julian Winkler Date: Sun, 17 Nov 2024 16:42:47 +0100 Subject: [PATCH] refactor SurfaceViewWidget for frame_callback in the Wayland server SurfaceViewWidget is now always a child of a GtkGraphicsOffload and handles the GdkTexture on its own. This way the extra GtkPicture is no longer needed and also the frame_callback of the Wayland server can be implemented. --- .../media/android_media_MediaCodec.c | 33 +++----- .../widgets/android_view_SurfaceView.c | 76 ++++++++++++------- .../widgets/android_view_SurfaceView.h | 18 +++++ src/libandroid/native_window.c | 17 ++--- src/libandroid/wayland_server.c | 71 ++++++++++++----- 5 files changed, 132 insertions(+), 83 deletions(-) create mode 100644 src/api-impl-jni/widgets/android_view_SurfaceView.h diff --git a/src/api-impl-jni/media/android_media_MediaCodec.c b/src/api-impl-jni/media/android_media_MediaCodec.c index 0436079b..dc60437e 100644 --- a/src/api-impl-jni/media/android_media_MediaCodec.c +++ b/src/api-impl-jni/media/android_media_MediaCodec.c @@ -33,6 +33,7 @@ #include "../util.h" #include "../defines.h" #include "../../libandroid/native_window.h" +#include "../widgets/android_view_SurfaceView.h" struct ATL_codec_context { AVCodecContext *codec; @@ -42,7 +43,7 @@ struct ATL_codec_context { } audio; struct { struct SwsContext *sws; // for software decoding - GtkPicture *gtk_picture; + SurfaceViewWidget *surface_view_widget; #if !GTK_CHECK_VERSION(4, 14, 0) struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf_v1; struct wp_viewporter *wp_viewporter; @@ -147,7 +148,7 @@ static enum AVPixelFormat get_hw_format(AVCodecContext *ctx, struct render_frame_data { AVFrame *frame; GdkTexture *texture; // for software decoding - GtkPicture *gtk_picture; + SurfaceViewWidget *surface_view_widget; #if !GTK_CHECK_VERSION(4, 14, 0) struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf_v1; struct ANativeWindow *native_window; @@ -351,21 +352,9 @@ JNIEXPORT void JNICALL Java_android_media_MediaCodec_native_1configure_1video(JN i++; } - GtkWidget *surface_view_widget = _PTR(_GET_LONG_FIELD(surface_obj, "widget")); -#if GTK_CHECK_VERSION(4, 14, 0) - GtkWidget *graphics_offload = gtk_widget_get_first_child(surface_view_widget); - if (!GTK_IS_GRAPHICS_OFFLOAD(graphics_offload)) { - graphics_offload = gtk_graphics_offload_new(gtk_picture_new()); - gtk_widget_insert_after(graphics_offload, surface_view_widget, NULL); - } - ctx->video.gtk_picture = GTK_PICTURE(gtk_graphics_offload_get_child(GTK_GRAPHICS_OFFLOAD(graphics_offload))); -#else - GtkWidget *gtk_picture = gtk_widget_get_first_child(surface_view_widget); - if (!GTK_IS_PICTURE(gtk_picture)) { - gtk_picture = gtk_picture_new(); - gtk_widget_insert_after(gtk_picture, surface_view_widget, NULL); - } - ctx->video.gtk_picture = GTK_PICTURE(gtk_picture); + SurfaceViewWidget *surface_view_widget = SURFACE_VIEW_WIDGET(gtk_widget_get_first_child(_PTR(_GET_LONG_FIELD(surface_obj, "widget")))); + ctx->video.surface_view_widget = surface_view_widget; +#if !GTK_CHECK_VERSION(4, 14, 0) struct ANativeWindow *native_window = ANativeWindow_fromSurface(env, surface_obj); ctx->video.native_window = native_window; ctx->video.surface_width = gtk_widget_get_width(native_window->surface_view_widget); @@ -528,8 +517,7 @@ static gboolean render_frame(void *data) #if GTK_CHECK_VERSION(4, 14, 0) GdkTexture *texture = import_drm_frame_desc_as_texture(drm_frame_desc, drm_frame->width, drm_frame->height, drm_frame); - gtk_picture_set_paintable(d->gtk_picture, GDK_PAINTABLE(texture)); - g_object_unref(texture); + surface_view_widget_set_texture(d->surface_view_widget, texture); #else struct wl_buffer *wl_buffer = import_drm_frame_desc(d->zwp_linux_dmabuf_v1, drm_frame_desc, drm_frame->width, drm_frame->height); @@ -553,8 +541,7 @@ static gboolean render_frame(void *data) static gboolean render_texture(void *data) { struct render_frame_data *d = (struct render_frame_data *)data; - gtk_picture_set_paintable(d->gtk_picture, GDK_PAINTABLE(d->texture)); - g_object_unref(d->texture); + surface_view_widget_set_texture(d->surface_view_widget, d->texture); free(d); return G_SOURCE_REMOVE; @@ -608,7 +595,7 @@ JNIEXPORT void JNICALL Java_android_media_MediaCodec_native_1releaseOutputBuffer GdkTexture *texture = gdk_memory_texture_new(frame->width, frame->height, gdk_mem_fmt, bytes, stride); struct render_frame_data *data = malloc(sizeof(struct render_frame_data)); data->texture = texture; - data->gtk_picture = ctx->video.gtk_picture; + data->surface_view_widget = ctx->video.surface_view_widget; g_idle_add(render_texture, data); g_bytes_unref (bytes); av_frame_free(&frame); @@ -618,7 +605,7 @@ JNIEXPORT void JNICALL Java_android_media_MediaCodec_native_1releaseOutputBuffer struct render_frame_data *data = malloc(sizeof(struct render_frame_data)); data->frame = frame; #if GTK_CHECK_VERSION(4, 14, 0) - data->gtk_picture = ctx->video.gtk_picture; + data->surface_view_widget = ctx->video.surface_view_widget; #else data->native_window = ctx->video.native_window; data->zwp_linux_dmabuf_v1 = ctx->video.zwp_linux_dmabuf_v1; diff --git a/src/api-impl-jni/widgets/android_view_SurfaceView.c b/src/api-impl-jni/widgets/android_view_SurfaceView.c index 5fd16288..ce528cad 100644 --- a/src/api-impl-jni/widgets/android_view_SurfaceView.c +++ b/src/api-impl-jni/widgets/android_view_SurfaceView.c @@ -7,20 +7,7 @@ #include "marshal.h" #include "../generated_headers/android_view_SurfaceView.h" - -// TODO: currently this widget class doesn't do anything special, will we ever need it to? -G_DECLARE_FINAL_TYPE (SurfaceViewWidget, surface_view_widget, SURFACE_VIEW, WIDGET, GtkWidget) - -struct _SurfaceViewWidget -{ - GtkWidget parent_instance; -}; - -struct _SurfaceViewWidgetClass -{ - GtkWidgetClass parent_class; -}; - +#include "android_view_SurfaceView.h" G_DEFINE_TYPE(SurfaceViewWidget, surface_view_widget, GTK_TYPE_WIDGET) @@ -45,12 +32,36 @@ static void surface_view_widget_size_allocate(GtkWidget *widget, int width, int } } +static void surface_view_widget_snapshot(GtkWidget *widget, GdkSnapshot *snapshot) +{ + SurfaceViewWidget *surface_view_widget = SURFACE_VIEW_WIDGET(widget); + if (surface_view_widget->texture) { + graphene_rect_t bounds = GRAPHENE_RECT_INIT(0, 0, gtk_widget_get_width(widget), gtk_widget_get_height(widget)); + gtk_snapshot_append_texture(snapshot, surface_view_widget->texture, &bounds); + } + if (surface_view_widget->frame_callback) { + surface_view_widget->frame_callback(surface_view_widget); + surface_view_widget->frame_callback = NULL; + } +} + +static void surface_view_widget_dispose(GObject *object) { + SurfaceViewWidget *surface_view_widget = SURFACE_VIEW_WIDGET(object); + if (surface_view_widget->texture) { + g_object_unref(surface_view_widget->texture); + surface_view_widget->texture = NULL; + } + G_OBJECT_CLASS(surface_view_widget_parent_class)->dispose(object); +} + static void surface_view_widget_class_init(SurfaceViewWidgetClass *class) { GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class); // resize signal copied from GtkDrawingArea widget_class->size_allocate = surface_view_widget_size_allocate; + widget_class->snapshot = surface_view_widget_snapshot; + G_OBJECT_CLASS(class)->dispose = surface_view_widget_dispose; signals[RESIZE] = g_signal_new("resize", @@ -70,6 +81,14 @@ GtkWidget * surface_view_widget_new(void) return g_object_new (surface_view_widget_get_type(), NULL); } +void surface_view_widget_set_texture(SurfaceViewWidget *surface_view_widget, GdkTexture *texture) +{ + if (surface_view_widget->texture) + g_object_unref(surface_view_widget->texture); + surface_view_widget->texture = texture; + gtk_widget_queue_draw(GTK_WIDGET(surface_view_widget)); +} + // --- struct jni_callback_data { JavaVM *jvm; jobject this; jclass this_class;}; @@ -98,16 +117,20 @@ JNIEXPORT jlong JNICALL Java_android_view_SurfaceView_native_1constructor(JNIEnv GtkWidget *wrapper = g_object_ref(wrapper_widget_new()); GtkWidget *dummy = surface_view_widget_new(); gtk_widget_set_name(dummy, "dummy widget for SurfaceView"); - wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), dummy); +#if GTK_CHECK_VERSION(4, 14, 0) + GtkWidget *graphics_offload = gtk_graphics_offload_new(dummy); +#else + // use a dummy GtkBox, so that the SurfaceViewWidget also becomes a grand child of the WrapperWidget + GtkWidget *graphics_offload = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0); + gtk_widget_set_vexpand(dummy, TRUE); + gtk_widget_set_hexpand(dummy, TRUE); + gtk_widget_insert_before(dummy, graphics_offload, NULL); +#endif + wrapper_widget_set_child(WRAPPER_WIDGET(wrapper), graphics_offload); wrapper_widget_set_jobject(WRAPPER_WIDGET(wrapper), env, this); // TODO: is this correct for all usecases? how do we know when it's not? gtk_widget_set_hexpand(wrapper, true); gtk_widget_set_vexpand(wrapper, true); -#if GTK_CHECK_VERSION(4, 14, 0) - gtk_widget_insert_after(gtk_graphics_offload_new(gtk_picture_new()), dummy, NULL); -#else - gtk_widget_insert_after(gtk_picture_new(), dummy, NULL); -#endif JavaVM *jvm; (*env)->GetJavaVM(env, &jvm); @@ -120,7 +143,7 @@ JNIEXPORT jlong JNICALL Java_android_view_SurfaceView_native_1constructor(JNIEnv g_signal_connect(dummy, "resize", G_CALLBACK(on_resize), callback_data); g_signal_connect(dummy, "realize", G_CALLBACK(on_realize), callback_data); - return _INTPTR(dummy); + return _INTPTR(graphics_offload); } JNIEXPORT jlong JNICALL Java_android_view_SurfaceView_native_1createSnapshot(JNIEnv *env, jclass class) @@ -133,19 +156,14 @@ extern GtkWindow *window; JNIEXPORT void JNICALL Java_android_view_SurfaceView_native_1postSnapshot(JNIEnv *env, jclass class, jlong surface_view, jlong snapshot_ptr) { GtkWidget *view = GTK_WIDGET(_PTR(surface_view)); -#if GTK_CHECK_VERSION(4, 14, 0) - GtkPicture *picture = GTK_PICTURE(gtk_widget_get_first_child(gtk_widget_get_first_child(view))); -#else - GtkPicture *picture = GTK_PICTURE(gtk_widget_get_first_child(view)); -#endif + SurfaceViewWidget *surface_view_widget = SURFACE_VIEW_WIDGET(gtk_widget_get_first_child(view)); GtkSnapshot *snapshot = GTK_SNAPSHOT(_PTR(snapshot_ptr)); GskRenderer *renderer = gsk_renderer_new_for_surface(gtk_native_get_surface(GTK_NATIVE(window))); GskRenderNode *node = gtk_snapshot_free_to_node(snapshot); - GdkTexture *paintable = gsk_renderer_render_texture(renderer, node, NULL); + GdkTexture *texture = gsk_renderer_render_texture(renderer, node, NULL); gsk_render_node_unref(node); gsk_renderer_unrealize(renderer); g_object_unref(renderer); - gtk_picture_set_paintable(picture, GDK_PAINTABLE(paintable)); - g_object_unref(paintable); + surface_view_widget_set_texture(surface_view_widget, texture); } diff --git a/src/api-impl-jni/widgets/android_view_SurfaceView.h b/src/api-impl-jni/widgets/android_view_SurfaceView.h new file mode 100644 index 00000000..ffa942f8 --- /dev/null +++ b/src/api-impl-jni/widgets/android_view_SurfaceView.h @@ -0,0 +1,18 @@ +#include + +G_DECLARE_FINAL_TYPE (SurfaceViewWidget, surface_view_widget, SURFACE_VIEW, WIDGET, GtkWidget) + +struct _SurfaceViewWidget +{ + GtkWidget parent_instance; + GdkTexture *texture; + void (*frame_callback)(SurfaceViewWidget *surface_view_widget); + gpointer frame_callback_data; +}; + +struct _SurfaceViewWidgetClass +{ + GtkWidgetClass parent_class; +}; + +void surface_view_widget_set_texture(SurfaceViewWidget *surface_view_widget, GdkTexture *texture); diff --git a/src/libandroid/native_window.c b/src/libandroid/native_window.c index 7a813726..c71f6bf1 100644 --- a/src/libandroid/native_window.c +++ b/src/libandroid/native_window.c @@ -283,7 +283,7 @@ ANativeWindow * ANativeWindow_fromSurface(JNIEnv* env, jobject surface) .global_remove = wl_registry_global_remove_handler }; - GtkWidget *surface_view_widget = _PTR(_GET_LONG_FIELD(surface, "widget")); + GtkWidget *surface_view_widget = gtk_widget_get_first_child(_PTR(_GET_LONG_FIELD(surface, "widget"))); GtkWidget *window = GTK_WIDGET(gtk_widget_get_native(surface_view_widget)); while( (width = gtk_widget_get_width(surface_view_widget)) == 0 ) { // FIXME: UGLY: this loop waits until the SurfaceView widget gets mapped @@ -312,13 +312,6 @@ ANativeWindow * ANativeWindow_fromSurface(JNIEnv* env, jobject surface) GdkDisplay *display = gtk_root_get_display(GTK_ROOT(window)); if (!getenv("ATL_DIRECT_EGL")) { - GtkWidget *graphics_offload = gtk_widget_get_first_child(surface_view_widget); - if (!GTK_IS_GRAPHICS_OFFLOAD(graphics_offload)) { - graphics_offload = gtk_graphics_offload_new(gtk_picture_new()); - gtk_widget_insert_after(graphics_offload, surface_view_widget, NULL); - } - GtkPicture *gtk_picture = GTK_PICTURE(gtk_graphics_offload_get_child(GTK_GRAPHICS_OFFLOAD(graphics_offload))); - if (!wl_compositor) { if (!wl_display_client) wl_display_client = wayland_server_start(); @@ -328,10 +321,10 @@ ANativeWindow * ANativeWindow_fromSurface(JNIEnv* env, jobject surface) printf("XXX: wl_compositor: %p\n", wl_compositor); } struct wl_surface *wayland_surface = wl_compositor_create_surface(wl_compositor); - // transfer the GtkPicture pointer to the wayland server abusing the set_buffer_scale and set_buffer_transform methods - g_object_ref(gtk_picture); - wl_surface_set_buffer_scale(wayland_surface, _INTPTR(gtk_picture)); - wl_surface_set_buffer_transform(wayland_surface, _INTPTR(gtk_picture)>>32); + // transfer the SurfaceViewWidget pointer to the wayland server abusing the set_buffer_scale and set_buffer_transform methods + g_object_ref(surface_view_widget); + wl_surface_set_buffer_scale(wayland_surface, _INTPTR(surface_view_widget)); + wl_surface_set_buffer_transform(wayland_surface, _INTPTR(surface_view_widget)>>32); struct wl_egl_window *egl_window = wl_egl_window_create(wayland_surface, width, height); native_window->egl_window = (EGLNativeWindowType)egl_window; native_window->wayland_display = wl_display_client; diff --git a/src/libandroid/wayland_server.c b/src/libandroid/wayland_server.c index e3c3d8be..305df03e 100644 --- a/src/libandroid/wayland_server.c +++ b/src/libandroid/wayland_server.c @@ -7,13 +7,15 @@ #include #include "../api-impl-jni/defines.h" +#include "../api-impl-jni/widgets/android_view_SurfaceView.h" static EGLDisplay egl_display_gtk = NULL; static GdkGLContext *gl_context_gtk = NULL; static struct wl_event_loop *event_loop = NULL; -static GMutex mutex; static PFNEGLQUERYWAYLANDBUFFERWL eglQueryWaylandBufferWL = NULL; static PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES = NULL; +static GMutex mutex; // synchronize access to wl_display_server +static struct wl_display *wl_display_server; /* runs on main thread */ static gboolean delete_texture(void *data) { @@ -26,7 +28,7 @@ static gboolean delete_texture(void *data) { struct _BufferData { GObject parent; gboolean destroyed; - GtkPicture *picture; + SurfaceViewWidget *surface_view_widget; struct wl_resource *wl_buffer; GdkGLTextureBuilder *texture_builder; }; @@ -39,7 +41,7 @@ static void buffer_data_dispose(GObject *g_object) g_idle_add(delete_texture, _PTR(texture_id)); g_object_unref(buffer->texture_builder); } - g_object_unref(buffer->picture); + g_object_unref(buffer->surface_view_widget); } static void buffer_data_class_init(BufferDataClass *cls) { @@ -50,13 +52,15 @@ G_DEFINE_TYPE(BufferData, buffer_data, G_TYPE_OBJECT) struct surface { struct wl_resource *wl_surface; - GtkPicture *picture; + SurfaceViewWidget *surface_view_widget; struct wl_resource *frame_callback; + struct wl_event_source *frame_timer; BufferData *buffers[3]; }; /* runs on main thread */ -static void destroy_texture(void *data) { +static void destroy_texture(void *data) +{ BufferData *buffer = ATL_BUFFER_DATA(data); g_mutex_lock(&mutex); if (!buffer->destroyed) { @@ -67,7 +71,23 @@ static void destroy_texture(void *data) { } /* runs on main thread */ -static gboolean render_texture(void *data) { +static void draw_callback(SurfaceViewWidget *surface_view_widget) +{ + g_mutex_lock(&mutex); + struct surface *surface = surface_view_widget->frame_callback_data; + if (surface && surface->frame_callback) { + wl_callback_send_done(surface->frame_callback, g_get_monotonic_time()/1000); + wl_resource_destroy(surface->frame_callback); + surface->frame_callback = NULL; + wl_event_source_timer_update(surface->frame_timer, 0); + wl_display_flush_clients(wl_display_server); + } + g_mutex_unlock(&mutex); +} + +/* runs on main thread */ +static gboolean render_texture(void *data) +{ BufferData *buffer = ATL_BUFFER_DATA(data); if (!buffer->texture_builder) { g_mutex_lock(&mutex); @@ -98,8 +118,7 @@ static gboolean render_texture(void *data) { GdkTexture *texture = gdk_gl_texture_builder_build(buffer->texture_builder, destroy_texture, buffer); - gtk_picture_set_paintable(buffer->picture, GDK_PAINTABLE(texture)); - g_object_unref(texture); + surface_view_widget_set_texture(buffer->surface_view_widget, texture); return G_SOURCE_REMOVE; } @@ -126,14 +145,20 @@ static void surface_attach(struct wl_client *client, struct wl_resource *resourc g_object_unref(buffer); buffer = g_object_new(buffer_data_get_type(), NULL); buffer->wl_buffer = wl_buffer; - buffer->picture = g_object_ref(surface->picture); + buffer->surface_view_widget = g_object_ref(surface->surface_view_widget); surface->buffers[0] = buffer; } static void surface_frame(struct wl_client *client, struct wl_resource *resource, uint32_t callback) { struct surface *surface = wl_resource_get_user_data(resource); + if (surface->frame_callback) + wl_resource_destroy(surface->frame_callback); surface->frame_callback = wl_resource_create(client, &wl_callback_interface, 1, callback); + surface->surface_view_widget->frame_callback = draw_callback; + surface->surface_view_widget->frame_callback_data = surface; + // this timer is required in case the main thread and the wayland server thread deadlock each other waiting for the next frame_callback + wl_event_source_timer_update(surface->frame_timer, 1000/20); } static void surface_damage(struct wl_client *client, struct wl_resource *resource, int32_t x, int32_t y, int32_t width, int32_t height) @@ -142,9 +167,12 @@ static void surface_damage(struct wl_client *client, struct wl_resource *resourc static int frame_timer(void *data) { - struct wl_resource *frame_callback = data; - wl_callback_send_done(frame_callback, g_get_monotonic_time()/1000); - wl_resource_destroy(frame_callback); + struct surface *surface = data; + if (surface->frame_callback) { + wl_callback_send_done(surface->frame_callback, g_get_monotonic_time()/1000); + wl_resource_destroy(surface->frame_callback); + surface->frame_callback = NULL; + } return 0; } @@ -152,8 +180,6 @@ static void surface_commit(struct wl_client *client, struct wl_resource *resourc { struct surface *surface = wl_resource_get_user_data(resource); g_idle_add(render_texture, g_object_ref(surface->buffers[0])); - struct wl_event_source *timer = wl_event_loop_add_timer(event_loop, frame_timer, surface->frame_callback); - wl_event_source_timer_update(timer, 1000/60); } static void surface_destroy(struct wl_client *client, struct wl_resource *resource) { @@ -162,8 +188,14 @@ static void surface_destroy(struct wl_client *client, struct wl_resource *resour surface->buffers[i]->destroyed = TRUE; g_object_unref(surface->buffers[i]); } - g_object_unref(surface->picture); + surface->surface_view_widget->frame_callback = NULL; + surface->surface_view_widget->frame_callback_data = NULL; + g_object_unref(surface->surface_view_widget); wl_resource_destroy(surface->wl_surface); + wl_event_source_timer_update(surface->frame_timer, 0); + if (surface->frame_callback) + wl_resource_destroy(surface->frame_callback); + surface->frame_callback = NULL; g_free(surface); } @@ -171,14 +203,14 @@ static void surface_destroy(struct wl_client *client, struct wl_resource *resour static void surface_set_buffer_scale(struct wl_client *client, struct wl_resource *resource, int32_t scale) { struct surface *surface = wl_resource_get_user_data(resource); - surface->picture = _PTR((((uint64_t)(uintptr_t)surface->picture) & 0xffffffff00000000L) | ((uintptr_t)(uint32_t)scale)); + surface->surface_view_widget = _PTR((((uint64_t)(uintptr_t)surface->surface_view_widget) & 0xffffffff00000000L) | ((uintptr_t)(uint32_t)scale)); } /* we abuse this method to set higher 32 bits of the GtkPicture pointer */ static void surface_set_buffer_transform(struct wl_client *client, struct wl_resource *resource, int32_t transform) { struct surface *surface = wl_resource_get_user_data(resource); - surface->picture = _PTR((((uint64_t)(uintptr_t)surface->picture) & 0x00000000ffffffffL) | ((uintptr_t)(uint32_t)transform)<<32); + surface->surface_view_widget = _PTR((((uint64_t)(uintptr_t)surface->surface_view_widget) & 0x00000000ffffffffL) | ((uintptr_t)(uint32_t)transform)<<32); } static struct wl_surface_interface surface_implementation = { @@ -197,6 +229,7 @@ static void compositor_create_surface(struct wl_client *client, struct wl_resour struct surface *surface = g_new0(struct surface, 1); wl_resource_set_implementation(wl_surface, &surface_implementation, surface, NULL); surface->wl_surface = wl_surface; + surface->frame_timer = wl_event_loop_add_timer(event_loop, frame_timer, surface); } static struct wl_compositor_interface compositor_implementation = { @@ -222,7 +255,7 @@ static gpointer wayland_server_thread(gpointer user_data) wl_display_flush_clients(wl_display_server); g_mutex_unlock(&mutex); } - return 0; + return 0; } extern GtkWindow *window; @@ -234,7 +267,7 @@ struct wl_display *wayland_server_start() egl_display_gtk = eglGetPlatformDisplay(EGL_PLATFORM_WAYLAND_KHR, wl_display_gtk, NULL); gl_context_gtk = gdk_surface_create_gl_context(gtk_native_get_surface(GTK_NATIVE(window)), NULL); - struct wl_display *wl_display_server = wl_display_create(); + wl_display_server = wl_display_create(); char tmpname[] = "/tmp/tmpdir.XXXXXX\0socket"; int tmplen = strlen(tmpname); mkdtemp(tmpname);