aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornyorain <nyorain@gmail.com>2017-06-20 18:27:05 +0200
committernyorain <nyorain@gmail.com>2017-06-20 18:27:05 +0200
commit50ce35e9da4e2604b0adb15703cfcd87204472e5 (patch)
tree5a4a3bf7d99c28b1ec4550a6531cb4363f807418
parent62b1421635581fbffc50eac680bb5a5d7a0b8535 (diff)
Implement wayland backend output
-rw-r--r--backend/wayland/backend.c27
-rw-r--r--backend/wayland/output.c88
-rw-r--r--include/backend/wayland.h6
3 files changed, 117 insertions, 4 deletions
diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c
index 6d3e2f32..e57cfed9 100644
--- a/backend/wayland/backend.c
+++ b/backend/wayland/backend.c
@@ -9,6 +9,23 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
+static int dispatch_events(int fd, uint32_t mask, void *data) {
+ struct wlr_backend_state *state = data;
+
+ int count = 0;
+ if(mask & WL_EVENT_READABLE)
+ count = wl_display_dispatch(state->remote_display);
+ if(mask & WL_EVENT_WRITABLE)
+ count = wl_display_flush(state->remote_display);
+
+ if (mask == 0) {
+ count = wl_display_dispatch_pending(state->remote_display);
+ wl_display_flush(state->remote_display);
+ }
+
+ return count;
+}
+
/*
* Initializes the wayland backend. Opens a connection to a remote wayland
* compositor and creates surfaces for each output, then registers globals on
@@ -34,7 +51,7 @@ static bool wlr_wl_backend_init(struct wlr_backend_state* state) {
return false;
}
- wlr_egl_init(&state->egl, EGL_PLATFORM_WAYLAND_KHR, state->remote_display);
+ wlr_egl_init(&state->egl, EGL_PLATFORM_WAYLAND_EXT, state->remote_display);
for (size_t i = 0; i < state->num_outputs; ++i) {
if(!(state->outputs[i] = wlr_wl_output_create(state, i))) {
wlr_log_errno(L_ERROR, "Failed to create %zuth output", i);
@@ -42,6 +59,14 @@ static bool wlr_wl_backend_init(struct wlr_backend_state* state) {
}
}
+ struct wl_event_loop *loop = wl_display_get_event_loop(state->local_display);
+ int fd = wl_display_get_fd(state->remote_display);
+ int events = WL_EVENT_READABLE | WL_EVENT_ERROR |
+ WL_EVENT_HANGUP | WL_EVENT_WRITABLE;
+ state->remote_display_src = wl_event_loop_add_fd(loop, fd, events,
+ dispatch_events, state);
+ wl_event_source_check(state->remote_display_src);
+
return true;
}
diff --git a/backend/wayland/output.c b/backend/wayland/output.c
index e6c7cf99..f8751c3c 100644
--- a/backend/wayland/output.c
+++ b/backend/wayland/output.c
@@ -1,19 +1,70 @@
+#include <assert.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <wayland-client.h>
#include <wlr/types.h>
+#include <GLES3/gl3.h>
#include "types.h"
#include "backend/wayland.h"
#include "common/log.h"
-// TODO
+static struct wl_callback_listener frame_listener;
+
+static void surface_frame_callback(void *data, struct wl_callback *cb, uint32_t time) {
+ struct wlr_output_state *output = data;
+ assert(output);
+
+ if (!eglMakeCurrent(output->backend->egl.display,
+ output->egl_surface, output->egl_surface,
+ output->backend->egl.context)) {
+ wlr_log(L_ERROR, "eglMakeCurrent failed: %s", egl_error());
+ return;
+ }
+
+ wl_signal_emit(&output->output->events.frame, output->output);
+ output->frame_callback = wl_surface_frame(output->surface);
+ wl_callback_add_listener(output->frame_callback, &frame_listener, output);
+ wl_callback_destroy(cb);
+
+ if (!eglSwapBuffers(output->backend->egl.display, output->egl_surface)) {
+ wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error());
+ return;
+ }
+}
+
+static struct wl_callback_listener frame_listener = {
+ .done = surface_frame_callback
+};
+
+// TODO: enable/cursor etc
static void wlr_wl_output_enable(struct wlr_output_state *output, bool enable) {
}
static bool wlr_wl_output_set_mode(struct wlr_output_state *output,
struct wlr_output_mode *mode) {
output->output->current_mode = mode;
+
+ // start rendering loop per callbacks by rendering first frame
+ if (!eglMakeCurrent(output->backend->egl.display,
+ output->egl_surface, output->egl_surface,
+ output->backend->egl.context)) {
+ wlr_log(L_ERROR, "eglMakeCurrent failed: %s", egl_error());
+ return false;
+ }
+
+ glViewport(0, 0, output->width, output->height);
+ glClearColor(1.0, 1.0, 1.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT);
+
+ output->frame_callback = wl_surface_frame(output->surface);
+ wl_callback_add_listener(output->frame_callback, &frame_listener, output);
+
+ if (!eglSwapBuffers(output->backend->egl.display, output->egl_surface)) {
+ wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error());
+ return false;
+ }
+
return true;
}
@@ -47,11 +98,32 @@ static struct wlr_output_impl output_impl = {
.destroy = wlr_wl_output_destroy,
};
+void handle_ping(void* data, struct wl_shell_surface* ssurface, uint32_t serial) {
+ struct wlr_output_state *output = data;
+ assert(output && output->shell_surface == ssurface);
+ wl_shell_surface_pong(ssurface, serial);
+}
+
+void handle_configure(void *data, struct wl_shell_surface *wl_shell_surface,
+ uint32_t edges, int32_t width, int32_t height){
+ wlr_log(L_DEBUG, "resize %d %d", width, height);
+}
+
+void handle_popup_done(void *data, struct wl_shell_surface *wl_shell_surface) {
+ wlr_log(L_ERROR, "Unexpected call");
+}
+
+static struct wl_shell_surface_listener shell_surface_listener = {
+ .ping = handle_ping,
+ .configure = handle_configure,
+ .popup_done = handle_popup_done
+};
+
struct wlr_output *wlr_wl_output_create(struct wlr_backend_state* backend,
size_t id) {
// TODO: dont hardcode stuff like size
- static unsigned int width = 1100;
- static unsigned int height = 720;
+ static unsigned int width = 800;
+ static unsigned int height = 500;
struct wlr_output_state *ostate;
if (!(ostate = calloc(sizeof(struct wlr_output_state), 1))) {
@@ -82,9 +154,19 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend_state* backend,
list_add(wlr_output->modes, &mode);
ostate->id = id;
+ ostate->width = width;
+ ostate->height = height;
+ ostate->backend = backend;
ostate->output = wlr_output;
+
+ // TODO: error handling
ostate->surface = wl_compositor_create_surface(backend->compositor);
ostate->shell_surface = wl_shell_get_shell_surface(backend->shell, ostate->surface);
+
+ wl_shell_surface_set_class(ostate->shell_surface, "sway");
+ wl_shell_surface_set_title(ostate->shell_surface, "sway-wl");
+ wl_shell_surface_add_listener(ostate->shell_surface, &shell_surface_listener, ostate);
+
ostate->egl_window = wl_egl_window_create(ostate->surface, width, height);
ostate->egl_surface = wlr_egl_create_surface(&backend->egl, ostate->egl_window);
diff --git a/include/backend/wayland.h b/include/backend/wayland.h
index 4cad565d..d2f1fb1d 100644
--- a/include/backend/wayland.h
+++ b/include/backend/wayland.h
@@ -23,6 +23,8 @@ struct wlr_backend_state {
struct wlr_backend *backend;
list_t *devices;
+ struct wl_event_source* remote_display_src;
+
size_t num_outputs;
struct wlr_output **outputs;
struct wlr_egl egl;
@@ -30,10 +32,14 @@ struct wlr_backend_state {
struct wlr_output_state {
size_t id;
+ unsigned int width;
+ unsigned int height;
+ struct wlr_backend_state *backend;
struct wlr_output *output;
struct wl_surface *surface;
struct wl_shell_surface *shell_surface;
struct wl_egl_window* egl_window;
+ struct wl_callback* frame_callback;
void* egl_surface;
};