From 168f0955ab5d6b614eb841bcb0ea684dd9105ef8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 22 Jun 2017 14:26:02 -0400 Subject: [PATCH] Add wl_output globals for wlr_outputs --- backend/drm/backend.c | 1 + backend/drm/drm.c | 1 + backend/egl.c | 8 +-- backend/wayland/output.c | 1 + include/backend/drm.h | 1 + include/wlr/interfaces/wlr_output.h | 2 + include/wlr/types/wlr_output.h | 2 + types/wlr_output.c | 78 +++++++++++++++++++++++++++++ 8 files changed, 87 insertions(+), 7 deletions(-) diff --git a/backend/drm/backend.c b/backend/drm/backend.c index 34c03eea..d52adba9 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -118,6 +118,7 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display, state->drm_invalidated.notify = drm_invalidated; wlr_udev_signal_add(udev, state->dev, &state->drm_invalidated); + state->display = display; struct wl_event_loop *event_loop = wl_display_get_event_loop(display); state->drm_event = wl_event_loop_add_fd(event_loop, state->fd, diff --git a/backend/drm/drm.c b/backend/drm/drm.c index e4790dec..c6e29b86 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -564,6 +564,7 @@ void wlr_drm_scan_connectors(struct wlr_backend_state *state) { scan_property_ids(state->fd, conn, output); + wlr_output_create_global(wlr_output, state->display); list_add(state->outputs, output); wlr_log(L_INFO, "Found display '%s'", wlr_output->name); } else { diff --git a/backend/egl.c b/backend/egl.c index f46a0c83..66aa6a4e 100644 --- a/backend/egl.c +++ b/backend/egl.c @@ -87,7 +87,7 @@ static bool egl_get_config(EGLDisplay disp, EGLConfig *out, EGLenum platform) { for (int i = 0; i < matched; ++i) { EGLint gbm_format; - if(platform == EGL_PLATFORM_WAYLAND_EXT) { + if (platform == EGL_PLATFORM_WAYLAND_EXT) { *out = configs[i]; return true; } @@ -99,8 +99,6 @@ static bool egl_get_config(EGLDisplay disp, EGLConfig *out, EGLenum platform) { continue; } - // XXX: Is GBM_FORMAT_XRGB8888 what we want? - // I don't know if this works for wl_displays. if (gbm_format == GBM_FORMAT_XRGB8888) { *out = configs[i]; return true; @@ -111,7 +109,6 @@ static bool egl_get_config(EGLDisplay disp, EGLConfig *out, EGLenum platform) { return false; } - bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *display) { if (!egl_exts()) { return false; @@ -155,14 +152,12 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *display) { EGL_EXTENSIONS)); wlr_log(L_INFO, "Using %s", glGetString(GL_VERSION)); wlr_log(L_INFO, "Supported OpenGL ES extensions: %s", glGetString(GL_EXTENSIONS)); - return true; error: eglTerminate(egl->display); eglReleaseThread(); eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); - return false; } @@ -180,6 +175,5 @@ EGLSurface wlr_egl_create_surface(struct wlr_egl *egl, void *window) { wlr_log(L_ERROR, "Failed to create EGL surface: %s", egl_error()); return EGL_NO_SURFACE; } - return surf; } diff --git a/backend/wayland/output.c b/backend/wayland/output.c index a01ff015..babca2e1 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -150,6 +150,7 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *_backend) { return false; } + wlr_output_create_global(wlr_output, backend->local_display); list_add(backend->outputs, wlr_output); wl_signal_emit(&backend->backend->events.output_add, wlr_output); return wlr_output; diff --git a/include/backend/drm.h b/include/backend/drm.h index 2c78e3d9..f37a5cd2 100644 --- a/include/backend/drm.h +++ b/include/backend/drm.h @@ -32,6 +32,7 @@ struct wlr_backend_state { dev_t dev; struct wlr_backend *backend; + struct wl_display *display; struct wl_event_source *drm_event; struct wl_listener session_signal; diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h index 4f29b54f..0949bca3 100644 --- a/include/wlr/interfaces/wlr_output.h +++ b/include/wlr/interfaces/wlr_output.h @@ -19,5 +19,7 @@ struct wlr_output *wlr_output_create(struct wlr_output_impl *impl, struct wlr_output_state *state); void wlr_output_free(struct wlr_output *output); void wlr_output_update_matrix(struct wlr_output *output); +struct wl_global *wlr_output_create_global( + struct wlr_output *wlr_output, struct wl_display *display); #endif diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 8ccf87e1..71e1d0fe 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -19,6 +19,8 @@ struct wlr_output_state; struct wlr_output { const struct wlr_output_impl *impl; struct wlr_output_state *state; + struct wl_global *wl_global; + struct wl_list resource_list; uint32_t flags; char name[16]; diff --git a/types/wlr_output.c b/types/wlr_output.c index 5e7f9288..4d2e7778 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -1,3 +1,4 @@ +#include #include #include #include @@ -5,6 +6,83 @@ #include #include #include +#include + +static void wl_output_send_to_resource(struct wl_resource *resource) { + assert(resource); + struct wlr_output *output = wl_resource_get_user_data(resource); + assert(output); + const uint32_t version = wl_resource_get_version(resource); + if (version >= WL_OUTPUT_GEOMETRY_SINCE_VERSION) { + wl_output_send_geometry(resource, 0, 0, // TODO: get position from layout? + output->phys_width, output->phys_height, output->subpixel, + output->make, output->model, output->transform); + } + if (version >= WL_OUTPUT_MODE_SINCE_VERSION) { + for (size_t i = 0; i < output->modes->length; ++i) { + struct wlr_output_mode *mode = output->modes->items[i]; + // TODO: mode->flags should just be preferred + uint32_t flags = mode->flags; + if (output->current_mode == mode) { + flags |= WL_OUTPUT_MODE_CURRENT; + } + wl_output_send_mode(resource, flags, + mode->width, mode->height, mode->refresh); + } + } + if (version >= WL_OUTPUT_SCALE_SINCE_VERSION) { + wl_output_send_scale(resource, output->scale); + } + if (version >= WL_OUTPUT_DONE_SINCE_VERSION) { + wl_output_send_done(resource); + } +} + +static void wl_output_destroy(struct wl_resource *resource) { + struct wlr_output *output = wl_resource_get_user_data(resource); + struct wl_resource *_resource = NULL; + wl_resource_for_each(_resource, &output->resource_list) { + if (_resource == resource) { + struct wl_list *link = wl_resource_get_link(_resource); + wl_list_remove(link); + break; + } + } +} + +static void wl_output_release(struct wl_client *client, struct wl_resource *resource) { + wl_output_destroy(resource); +} + +static struct wl_output_interface wl_output_impl = { + .release = wl_output_release +}; + +static void wl_output_bind(struct wl_client *wl_client, void *_wlr_output, + uint32_t version, uint32_t id) { + struct wlr_output *wlr_output = _wlr_output; + assert(wl_client && wlr_output); + if (version > 3) { + wlr_log(L_ERROR, "Client requested unsupported wl_output version, disconnecting"); + wl_client_destroy(wl_client); + return; + } + struct wl_resource *wl_resource = wl_resource_create( + wl_client, &wl_output_interface, version, id); + wl_resource_set_implementation(wl_resource, &wl_output_impl, + wlr_output, wl_output_destroy); + wl_list_insert(&wlr_output->resource_list, wl_resource_get_link(wl_resource)); + wl_output_send_to_resource(wl_resource); +} + +struct wl_global *wlr_output_create_global( + struct wlr_output *wlr_output, struct wl_display *display) { + struct wl_global *wl_global = wl_global_create(display, + &wl_output_interface, 3, wlr_output, wl_output_bind); + wlr_output->wl_global = wl_global; + wl_list_init(&wlr_output->resource_list); + return wl_global; +} static const float transforms[][4] = { [WL_OUTPUT_TRANSFORM_NORMAL] = {