aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--backend/drm/backend.c2
-rw-r--r--backend/drm/drm.c35
-rw-r--r--backend/drm/renderer.c48
-rw-r--r--backend/headless/output.c16
-rw-r--r--backend/wayland/output.c21
-rw-r--r--backend/wayland/wl_seat.c17
-rw-r--r--backend/x11/backend.c11
-rw-r--r--examples/idle-inhibit.c2
-rw-r--r--examples/idle.c6
-rw-r--r--examples/multi-pointer.c28
-rw-r--r--examples/output-layout.c38
-rw-r--r--examples/pointer.c28
-rw-r--r--examples/rotation.c27
-rw-r--r--examples/screenshot.c181
-rw-r--r--examples/simple.c6
-rw-r--r--examples/tablet.c43
-rw-r--r--examples/touch.c35
-rw-r--r--include/backend/drm/drm.h2
-rw-r--r--include/backend/drm/renderer.h2
-rw-r--r--include/backend/wayland.h3
-rw-r--r--include/render/gles2.h49
-rw-r--r--include/rootston/desktop.h8
-rw-r--r--include/rootston/seat.h1
-rw-r--r--include/rootston/server.h2
-rw-r--r--include/rootston/view.h7
-rw-r--r--include/wlr/backend.h23
-rw-r--r--include/wlr/backend/drm.h7
-rw-r--r--include/wlr/backend/headless.h14
-rw-r--r--include/wlr/backend/interface.h4
-rw-r--r--include/wlr/backend/libinput.h4
-rw-r--r--include/wlr/backend/multi.h10
-rw-r--r--include/wlr/render.h149
-rw-r--r--include/wlr/render/egl.h31
-rw-r--r--include/wlr/render/gles2.h2
-rw-r--r--include/wlr/render/interface.h32
-rw-r--r--include/wlr/render/matrix.h22
-rw-r--r--include/wlr/render/wlr_renderer.h75
-rw-r--r--include/wlr/render/wlr_texture.h69
-rw-r--r--include/wlr/types/wlr_compositor.h2
-rw-r--r--include/wlr/types/wlr_linux_dmabuf.h84
-rw-r--r--include/wlr/types/wlr_matrix.h22
-rw-r--r--include/wlr/types/wlr_output.h2
-rw-r--r--include/wlr/types/wlr_surface.h17
-rw-r--r--include/wlr/types/wlr_xdg_shell.h34
-rw-r--r--include/wlr/types/wlr_xdg_shell_v6.h34
-rw-r--r--protocol/meson.build3
-rw-r--r--render/egl.c244
-rw-r--r--render/glapi.txt7
-rw-r--r--render/gles2/pixel_format.c25
-rw-r--r--render/gles2/renderer.c479
-rw-r--r--render/gles2/shaders.c162
-rw-r--r--render/gles2/texture.c272
-rw-r--r--render/matrix.c210
-rw-r--r--render/meson.build1
-rw-r--r--render/wlr_renderer.c32
-rw-r--r--render/wlr_texture.c13
-rw-r--r--rootston/cursor.c2
-rw-r--r--rootston/desktop.c84
-rw-r--r--rootston/main.c2
-rw-r--r--rootston/output.c49
-rw-r--r--rootston/seat.c9
-rw-r--r--rootston/wl_shell.c32
-rw-r--r--rootston/xdg_shell.c88
-rw-r--r--rootston/xdg_shell_v6.c88
-rw-r--r--rootston/xwayland.c55
-rw-r--r--types/meson.build4
-rw-r--r--types/wlr_linux_dmabuf.c463
-rw-r--r--types/wlr_matrix.c169
-rw-r--r--types/wlr_output.c28
-rw-r--r--types/wlr_pointer.c5
-rw-r--r--types/wlr_screenshooter.c2
-rw-r--r--types/wlr_surface.c22
-rw-r--r--types/wlr_xdg_shell.c539
-rw-r--r--types/wlr_xdg_shell_v6.c552
-rw-r--r--wlroots.syms2
75 files changed, 3006 insertions, 1892 deletions
diff --git a/backend/drm/backend.c b/backend/drm/backend.c
index 75b44210..43a8d017 100644
--- a/backend/drm/backend.c
+++ b/backend/drm/backend.c
@@ -173,7 +173,7 @@ struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
}
if (!wlr_egl_bind_display(&drm->renderer.egl, display)) {
- wlr_log(L_INFO, "Failed to bind egl/wl display: %s", egl_error());
+ wlr_log(L_INFO, "Failed to bind egl/wl display");
}
drm->display_destroy.notify = handle_display_destroy;
diff --git a/backend/drm/drm.c b/backend/drm/drm.c
index 0d1d527d..524e80bb 100644
--- a/backend/drm/drm.c
+++ b/backend/drm/drm.c
@@ -15,9 +15,9 @@
#include <wayland-util.h>
#include <wlr/backend/interface.h>
#include <wlr/interfaces/wlr_output.h>
-#include <wlr/render.h>
#include <wlr/render/gles2.h>
-#include <wlr/render/matrix.h>
+#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/util/log.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
@@ -582,13 +582,10 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
return false;
}
- // OpenGL will read the pixels out upside down,
- // so we need to flip the image vertically
- enum wl_output_transform transform = wlr_output_transform_compose(
- wlr_output_transform_invert(output->transform),
- WL_OUTPUT_TRANSFORM_FLIPPED_180);
- wlr_matrix_texture(plane->matrix, plane->surf.width, plane->surf.height,
- transform);
+ enum wl_output_transform transform =
+ wlr_output_transform_invert(output->transform);
+ wlr_matrix_projection(plane->matrix, plane->surf.width,
+ plane->surf.height, transform);
plane->wlr_tex =
wlr_render_texture_create(plane->surf.renderer->wlr_rend);
@@ -643,20 +640,14 @@ static bool wlr_drm_connector_set_cursor(struct wlr_output *output,
wlr_texture_upload_pixels(plane->wlr_tex, WL_SHM_FORMAT_ARGB8888,
stride, width, height, buf);
- glViewport(0, 0, plane->surf.width, plane->surf.height);
- glClearColor(0.0, 0.0, 0.0, 0.0);
- glClear(GL_COLOR_BUFFER_BIT);
+ struct wlr_renderer *rend = plane->surf.renderer->wlr_rend;
+ wlr_renderer_begin(rend, plane->surf.width, plane->surf.height);
+ wlr_renderer_clear(rend, (float[]){ 0.0, 0.0, 0.0, 0.0 });
+ wlr_render_texture(rend, plane->wlr_tex, plane->matrix, 0, 0, 1.0f);
+ wlr_renderer_end(rend);
- float matrix[16];
- wlr_texture_get_matrix(plane->wlr_tex, &matrix, &plane->matrix, 0, 0);
- wlr_render_with_matrix(plane->surf.renderer->wlr_rend, plane->wlr_tex,
- &matrix, 1.0f);
-
- glFinish();
- glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, bo_stride);
- glReadPixels(0, 0, plane->surf.width, plane->surf.height, GL_BGRA_EXT,
- GL_UNSIGNED_BYTE, bo_data);
- glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, 0);
+ wlr_renderer_read_pixels(rend, WL_SHM_FORMAT_ARGB8888, bo_stride,
+ plane->surf.width, plane->surf.height, 0, 0, 0, 0, bo_data);
wlr_drm_surface_swap_buffers(&plane->surf, NULL);
diff --git a/backend/drm/renderer.c b/backend/drm/renderer.c
index 7ee13843..b2998b5f 100644
--- a/backend/drm/renderer.c
+++ b/backend/drm/renderer.c
@@ -1,15 +1,15 @@
+#include <assert.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <gbm.h>
-#include <GLES2/gl2.h>
#include <stdbool.h>
#include <stdlib.h>
#include <unistd.h>
#include <wayland-util.h>
-#include <wlr/render.h>
#include <wlr/render/egl.h>
#include <wlr/render/gles2.h>
-#include <wlr/render/matrix.h>
+#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/util/log.h>
#include "backend/drm/drm.h"
#include "glapi.h"
@@ -106,9 +106,6 @@ void wlr_drm_surface_finish(struct wlr_drm_surface *surf) {
return;
}
- eglMakeCurrent(surf->renderer->egl.display, EGL_NO_SURFACE, EGL_NO_SURFACE,
- EGL_NO_CONTEXT);
-
if (surf->front) {
gbm_surface_release_buffer(surf->gbm, surf->front);
}
@@ -150,9 +147,10 @@ struct gbm_bo *wlr_drm_surface_get_front(struct wlr_drm_surface *surf) {
}
wlr_drm_surface_make_current(surf, NULL);
- glViewport(0, 0, surf->width, surf->height);
- glClearColor(0.0, 0.0, 0.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
+ struct wlr_renderer *renderer = surf->renderer->wlr_rend;
+ wlr_renderer_begin(renderer, surf->width, surf->height);
+ wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 1.0 });
+ wlr_renderer_end(renderer);
return wlr_drm_surface_swap_buffers(surf, NULL);
}
@@ -177,12 +175,15 @@ static void free_eglimage(struct gbm_bo *bo, void *data) {
free(tex);
}
-static struct wlr_texture *get_tex_for_bo(struct wlr_drm_renderer *renderer, struct gbm_bo *bo) {
+static struct wlr_texture *get_tex_for_bo(struct wlr_drm_renderer *renderer,
+ struct gbm_bo *bo) {
struct tex *tex = gbm_bo_get_user_data(bo);
if (tex) {
return tex->tex;
}
+ // TODO: use wlr_texture_upload_dmabuf instead
+
tex = malloc(sizeof(*tex));
if (!tex) {
wlr_log_errno(L_ERROR, "Allocation failed");
@@ -209,7 +210,7 @@ static struct wlr_texture *get_tex_for_bo(struct wlr_drm_renderer *renderer, str
tex->img = eglCreateImageKHR(renderer->egl.display, EGL_NO_CONTEXT,
EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
if (!tex->img) {
- wlr_log(L_ERROR, "Failed to create EGL image: %s", egl_error());
+ wlr_log(L_ERROR, "Failed to create EGL image");
abort();
}
@@ -226,26 +227,23 @@ struct gbm_bo *wlr_drm_surface_mgpu_copy(struct wlr_drm_surface *dest,
wlr_drm_surface_make_current(dest, NULL);
struct wlr_texture *tex = get_tex_for_bo(dest->renderer, src);
+ assert(tex);
- static const float matrix[16] = {
- [0] = 2.0f,
- [3] = -1.0f,
- [5] = 2.0f,
- [7] = -1.0f,
- [10] = 1.0f,
- [15] = 1.0f,
- };
+ float mat[9];
+ wlr_matrix_projection(mat, 1, 1, WL_OUTPUT_TRANSFORM_FLIPPED_180);
- glViewport(0, 0, dest->width, dest->height);
- glClearColor(0.0, 0.0, 0.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
- wlr_render_with_matrix(dest->renderer->wlr_rend, tex, &matrix, 1.0f);
+ struct wlr_renderer *renderer = dest->renderer->wlr_rend;
+ wlr_renderer_begin(renderer, dest->width, dest->height);
+ wlr_renderer_clear(renderer, (float[]){ 0.0, 0.0, 0.0, 1.0 });
+ wlr_render_texture_with_matrix(renderer, tex, mat, 1.0f);
+ wlr_renderer_end(renderer);
return wlr_drm_surface_swap_buffers(dest, NULL);
}
-bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane, struct wlr_drm_backend *drm,
- int32_t width, uint32_t height, uint32_t format) {
+bool wlr_drm_plane_surfaces_init(struct wlr_drm_plane *plane,
+ struct wlr_drm_backend *drm, int32_t width, uint32_t height,
+ uint32_t format) {
if (!drm->parent) {
return wlr_drm_surface_init(&plane->surf, &drm->renderer, width, height,
format, GBM_BO_USE_SCANOUT);
diff --git a/backend/headless/output.c b/backend/headless/output.c
index 6ce8fc35..a13ed22c 100644
--- a/backend/headless/output.c
+++ b/backend/headless/output.c
@@ -1,8 +1,8 @@
#include <EGL/egl.h>
#include <EGL/eglext.h>
-#include <GLES2/gl2.h>
#include <stdlib.h>
#include <wlr/interfaces/wlr_output.h>
+#include <wlr/render/wlr_renderer.h>
#include <wlr/util/log.h>
#include "backend/headless.h"
#include "util/signal.h"
@@ -13,7 +13,7 @@ static EGLSurface egl_create_surface(struct wlr_egl *egl, unsigned int width,
EGLSurface surf = eglCreatePbufferSurface(egl->display, egl->config, attribs);
if (surf == EGL_NO_SURFACE) {
- wlr_log(L_ERROR, "Failed to create EGL surface: %s", egl_error());
+ wlr_log(L_ERROR, "Failed to create EGL surface");
return EGL_NO_SURFACE;
}
return surf;
@@ -120,16 +120,14 @@ struct wlr_output *wlr_headless_add_output(struct wlr_backend *wlr_backend,
snprintf(wlr_output->name, sizeof(wlr_output->name), "HEADLESS-%d",
wl_list_length(&backend->outputs) + 1);
- 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());
+ if (!wlr_egl_make_current(&output->backend->egl, output->egl_surface,
+ NULL)) {
goto error;
}
- glViewport(0, 0, wlr_output->width, wlr_output->height);
- glClearColor(1.0, 1.0, 1.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
+ wlr_renderer_begin(backend->renderer, wlr_output->width, wlr_output->height);
+ wlr_renderer_clear(backend->renderer, (float[]){ 1.0, 1.0, 1.0, 1.0 });
+ wlr_renderer_end(backend->renderer);
struct wl_event_loop *ev = wl_display_get_event_loop(backend->display);
output->frame_timer = wl_event_loop_add_timer(ev, signal_frame, output);
diff --git a/backend/wayland/output.c b/backend/wayland/output.c
index fc40dea0..d528c888 100644
--- a/backend/wayland/output.c
+++ b/backend/wayland/output.c
@@ -1,5 +1,4 @@
#include <assert.h>
-#include <GLES2/gl2.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
@@ -9,6 +8,7 @@
#include <unistd.h>
#include <wayland-client.h>
#include <wlr/interfaces/wlr_output.h>
+#include <wlr/render/wlr_renderer.h>
#include <wlr/util/log.h>
#include "backend/wayland.h"
#include "util/signal.h"
@@ -313,27 +313,26 @@ struct wlr_output *wlr_wl_output_create(struct wlr_backend *_backend) {
output->egl_window = wl_egl_window_create(output->surface,
wlr_output->width, wlr_output->height);
- output->egl_surface = wlr_egl_create_surface(&backend->egl, output->egl_window);
+ output->egl_surface = wlr_egl_create_surface(&backend->egl,
+ output->egl_window);
wl_display_roundtrip(output->backend->remote_display);
// 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());
+ if (!wlr_egl_make_current(&output->backend->egl, output->egl_surface,
+ NULL)) {
goto error;
}
- glViewport(0, 0, wlr_output->width, wlr_output->height);
- glClearColor(1.0, 1.0, 1.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT);
+ wlr_renderer_begin(backend->renderer, wlr_output->width, wlr_output->height);
+ wlr_renderer_clear(backend->renderer, (float[]){ 1.0, 1.0, 1.0, 1.0 });
+ wlr_renderer_end(backend->renderer);
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());
+ if (!wlr_egl_swap_buffers(&output->backend->egl, output->egl_surface,
+ NULL)) {
goto error;
}
diff --git a/backend/wayland/wl_seat.c b/backend/wayland/wl_seat.c
index 841e693d..6ca59130 100644
--- a/backend/wayland/wl_seat.c
+++ b/backend/wayland/wl_seat.c
@@ -26,6 +26,11 @@ static void pointer_handle_enter(void *data, struct wl_pointer *wl_pointer,
// GNOME sends a pointer enter when the surface is being destroyed
return;
}
+ if (wlr_wl_pointer->current_output) {
+ wl_list_remove(&wlr_wl_pointer->output_destroy_listener.link);
+ }
+ wl_signal_add(&output->wlr_output.events.destroy,
+ &wlr_wl_pointer->output_destroy_listener);
wlr_wl_pointer->current_output = output;
output->enter_serial = serial;
wlr_wl_output_update_cursor(output);
@@ -49,7 +54,7 @@ static void pointer_handle_motion(void *data, struct wl_pointer *wl_pointer,
struct wlr_wl_pointer *wlr_wl_pointer =
(struct wlr_wl_pointer *)dev->pointer;
if (!wlr_wl_pointer->current_output) {
- wlr_log(L_ERROR, "pointer motion event without current output");
+ wlr_log(L_DEBUG, "pointer motion event without current output");
return;
}
@@ -231,6 +236,14 @@ static struct wlr_input_device *allocate_device(struct wlr_wl_backend *backend,
return wlr_device;
}
+static void wlr_wl_pointer_handle_output_destroy(struct wl_listener *listener,
+ void *data) {
+ struct wlr_wl_pointer *wlr_wl_pointer =
+ wl_container_of(listener, wlr_wl_pointer, output_destroy_listener);
+ wlr_wl_pointer->current_output = NULL;
+ wl_list_remove(&wlr_wl_pointer->output_destroy_listener.link);
+}
+
static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
enum wl_seat_capability caps) {
struct wlr_wl_backend *backend = data;
@@ -243,6 +256,8 @@ static void seat_handle_capabilities(void *data, struct wl_seat *wl_seat,
wlr_log(L_ERROR, "Unable to allocate wlr_wl_pointer");
return;
}
+ wlr_wl_pointer->output_destroy_listener.notify =
+ wlr_wl_pointer_handle_output_destroy;
struct wlr_input_device *wlr_device;
if (!(wlr_device = allocate_device(backend, WLR_INPUT_DEVICE_POINTER))) {
diff --git a/backend/x11/backend.c b/backend/x11/backend.c
index cb29e518..dd2c0a6e 100644
--- a/backend/x11/backend.c
+++ b/backend/x11/backend.c
@@ -143,6 +143,7 @@ static bool handle_x11_event(struct wlr_x11_backend *x11, xcb_generic_event_t *e
};
wlr_signal_emit_safe(&x11->pointer.events.motion_absolute, &abs);
+ free(pointer);
break;
}
case XCB_CLIENT_MESSAGE: {
@@ -317,12 +318,20 @@ static void wlr_x11_backend_destroy(struct wlr_backend *backend) {
wlr_signal_emit_safe(&backend->events.destroy, backend);
+ if (x11->event_source) {
+ wl_event_source_remove(x11->event_source);
+ }
wl_list_remove(&x11->display_destroy.link);
wl_event_source_remove(x11->frame_timer);
wlr_egl_finish(&x11->egl);
- xcb_disconnect(x11->xcb_conn);
+ if (x11->xcb_conn) {
+ xcb_disconnect(x11->xcb_conn);
+ }
+ if (x11->xlib_conn) {
+ XCloseDisplay(x11->xlib_conn);
+ }
free(x11);
}
diff --git a/examples/idle-inhibit.c b/examples/idle-inhibit.c
index b7b9c21c..c09e6507 100644
--- a/examples/idle-inhibit.c
+++ b/examples/idle-inhibit.c
@@ -5,8 +5,8 @@
#include <wayland-client.h>
#include <wayland-egl.h>
#include <wlr/render/egl.h>
-#include "xdg-shell-client-protocol.h"
#include "idle-inhibit-unstable-v1-client-protocol.h"
+#include "xdg-shell-client-protocol.h"
#include <linux/input-event-codes.h>
diff --git a/examples/idle.c b/examples/idle.c
index 2b155c68..b65a81cf 100644
--- a/examples/idle.c
+++ b/examples/idle.c
@@ -1,11 +1,11 @@
+#include <getopt.h>
+#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
-#include <getopt.h>
-#include <pthread.h>
-#include <wayland-client.h>
#include <wayland-client-protocol.h>
+#include <wayland-client.h>
#include <wlr/util/log.h>
#include "idle-client-protocol.h"
diff --git a/examples/multi-pointer.c b/examples/multi-pointer.c
index d3d425f2..43ccdb66 100644
--- a/examples/multi-pointer.c
+++ b/examples/multi-pointer.c
@@ -1,30 +1,30 @@
#define _POSIX_C_SOURCE 199309L
#define _XOPEN_SOURCE 500
+#include <assert.h>
+#include <GLES2/gl2.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
-#include <math.h>
-#include <assert.h>
-#include <wayland-server.h>
#include <wayland-server-protocol.h>
-#include <xkbcommon/xkbcommon.h>
-#include <GLES2/gl2.h>
-#include <wlr/render/matrix.h>
-#include <wlr/render/gles2.h>
-#include <wlr/render.h>
+#include <wayland-server.h>
#include <wlr/backend.h>
#include <wlr/backend/session.h>
+#include <wlr/render/gles2.h>
+#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_keyboard.h>
+#include <wlr/types/wlr_list.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output_layout.h>
-#include <wlr/xcursor.h>
-#include <wlr/types/wlr_cursor.h>
#include <wlr/util/log.h>
-#include <wlr/types/wlr_list.h>
-#include "support/shared.h"
-#include "support/config.h"
+#include <wlr/xcursor.h>
+#include <xkbcommon/xkbcommon.h>
#include "support/cat.h"
+#include "support/config.h"
+#include "support/shared.h"
struct sample_state;
diff --git a/examples/output-layout.c b/examples/output-layout.c
index 45257be9..45d896b0 100644
--- a/examples/output-layout.c
+++ b/examples/output-layout.c
@@ -1,29 +1,29 @@
#define _POSIX_C_SOURCE 199309L
#define _XOPEN_SOURCE 700
+#include <GLES2/gl2.h>
+#include <limits.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
#include <string.h>
#include <strings.h>
+#include <time.h>
#include <unistd.h>
-#include <limits.h>
-#include <wayland-server.h>
#include <wayland-server-protocol.h>
-#include <xkbcommon/xkbcommon.h>
-#include <GLES2/gl2.h>
-#include <wlr/render/matrix.h>
-#include <wlr/render/gles2.h>
-#include <wlr/render.h>
-#include <wlr/util/log.h>
+#include <wayland-server.h>
#include <wlr/backend.h>
#include <wlr/backend/session.h>
+#include <wlr/render/gles2.h>
+#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_keyboard.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output.h>
-#include <wlr/types/wlr_keyboard.h>
-#include <math.h>
-#include "support/shared.h"
-#include "support/config.h"
+#include <wlr/util/log.h>
+#include <xkbcommon/xkbcommon.h>
#include "support/cat.h"
+#include "support/config.h"
+#include "support/shared.h"
struct sample_state {
struct example_config *config;
@@ -101,8 +101,8 @@ static void handle_output_frame(struct output_state *output,
struct wlr_output *wlr_output = output->output;
wlr_output_make_current(wlr_output, NULL);
- wlr_renderer_begin(sample->renderer, wlr_output);
- wlr_renderer_clear(sample->renderer, &(float[]){0.25f, 0.25f, 0.25f, 1});
+ wlr_renderer_begin(sample->renderer, wlr_output->width, wlr_output->height);
+ wlr_renderer_clear(sample->renderer, (float[]){0.25f, 0.25f, 0.25f, 1});
animate_cat(sample, output->output);
@@ -111,18 +111,14 @@ static void handle_output_frame(struct output_state *output,
.width = 128, .height = 128,
};
if (wlr_output_layout_intersects(sample->layout, output->output, &box)) {
- float matrix[16];
-
// transform global coordinates to local coordinates
double local_x = sample->x_offs;
double local_y = sample->y_offs;
wlr_output_layout_output_coords(sample->layout, output->output,
&local_x, &local_y);
- wlr_texture_get_matrix(sample->cat_texture, &matrix,
- &wlr_output->transform_matrix, local_x, local_y);
- wlr_render_with_matrix(sample->renderer,
- sample->cat_texture, &matrix, 1.0f);
+ wlr_render_texture(sample->renderer, sample->cat_texture,
+ wlr_output->transform_matrix, local_x, local_y, 1.0f);
}
wlr_renderer_end(sample->renderer);
diff --git a/examples/pointer.c b/examples/pointer.c
index 0dbd02d2..e8a0e892 100644
--- a/examples/pointer.c
+++ b/examples/pointer.c
@@ -1,30 +1,30 @@
#define _POSIX_C_SOURCE 199309L
#define _XOPEN_SOURCE 500
+#include <assert.h>
+#include <GLES2/gl2.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
-#include <math.h>
-#include <assert.h>
-#include <wayland-server.h>
#include <wayland-server-protocol.h>
-#include <xkbcommon/xkbcommon.h>
-#include <GLES2/gl2.h>
-#include <wlr/render/matrix.h>
-#include <wlr/render/gles2.h>
-#include <wlr/render.h>
+#include <wayland-server.h>
#include <wlr/backend.h>
#include <wlr/backend/session.h>
+#include <wlr/render/gles2.h>
+#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_keyboard.h>
+#include <wlr/types/wlr_list.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output_layout.h>
-#include <wlr/xcursor.h>
-#include <wlr/types/wlr_cursor.h>
#include <wlr/util/log.h>
-#include <wlr/types/wlr_list.h>
-#include "support/shared.h"
-#include "support/config.h"
+#include <wlr/xcursor.h>
+#include <xkbcommon/xkbcommon.h>
#include "support/cat.h"
+#include "support/config.h"
+#include "support/shared.h"
struct sample_state {
struct compositor_state *compositor;
diff --git a/examples/rotation.c b/examples/rotation.c
index 1158ccc4..cbff09a1 100644
--- a/examples/rotation.c
+++ b/examples/rotation.c
@@ -1,23 +1,23 @@
#define _POSIX_C_SOURCE 199309L
#define _XOPEN_SOURCE 500
+#include <GLES2/gl2.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
#include <string.h>
#include <strings.h>
+#include <time.h>
#include <unistd.h>
-#include <wayland-server.h>
#include <wayland-server-protocol.h>
-#include <xkbcommon/xkbcommon.h>
-#include <GLES2/gl2.h>
-#include <wlr/render/matrix.h>
-#include <wlr/render/gles2.h>
-#include <wlr/render.h>
+#include <wayland-server.h>
#include <wlr/backend.h>
#include <wlr/backend/session.h>
+#include <wlr/render/wlr_renderer.h>
+#include <wlr/render/gles2.h>
#include <wlr/types/wlr_keyboard.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/util/log.h>
-#include <math.h>
+#include <xkbcommon/xkbcommon.h>
#include "support/shared.h"
#include "support/config.h"
#include "support/cat.h"
@@ -43,16 +43,13 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts
wlr_output_effective_resolution(wlr_output, &width, &height);
wlr_output_make_current(wlr_output, NULL);
- wlr_renderer_begin(sample->renderer, wlr_output);
- wlr_renderer_clear(sample->renderer, &(float[]){0.25f, 0.25f, 0.25f, 1});
+ wlr_renderer_begin(sample->renderer, wlr_output->width, wlr_output->height);
+ wlr_renderer_clear(sample->renderer, (float[]){0.25f, 0.25f, 0.25f, 1});
- float matrix[16];
for (int y = -128 + (int)odata->y_offs; y < height; y += 128) {
for (int x = -128 + (int)odata->x_offs; x < width; x += 128) {
- wlr_texture_get_matrix(sample->cat_texture, &matrix,
- &wlr_output->transform_matrix, x, y);
- wlr_render_with_matrix(sample->renderer,
- sample->cat_texture, &matrix, 1.0f);
+ wlr_render_texture(sample->renderer, sample->cat_texture,
+ wlr_output->transform_matrix, x, y, 1.0f);
}
}
diff --git a/examples/screenshot.c b/examples/screenshot.c
index e73989c6..fb37f32c 100644
--- a/examples/screenshot.c
+++ b/examples/screenshot.c
@@ -26,6 +26,7 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -36,33 +37,22 @@
#include <wayland-client.h>
#include <wlr/util/log.h>
#include "screenshooter-client-protocol.h"
-#include "util/os-compatibility.h"
static struct wl_shm *shm = NULL;
static struct orbital_screenshooter *screenshooter = NULL;
static struct wl_list output_list;
-int min_x, min_y, max_x, max_y;
-int buffer_copy_done;
+static bool buffer_copy_done;
struct screenshooter_output {
struct wl_output *output;
- struct wl_buffer *buffer;
- int width, height, offset_x, offset_y;
- enum wl_output_transform transform;
- void *data;
+ int width, height;
struct wl_list link;
};
static void output_handle_geometry(void *data, struct wl_output *wl_output,
int x, int y, int physical_width, int physical_height, int subpixel,
const char *make, const char *model, int transform) {
- struct screenshooter_output *output = wl_output_get_user_data(wl_output);
-
- if (wl_output == output->output) {
- output->offset_x = x;
- output->offset_y = y;
- output->transform = transform;
- }
+ // No-op
}
static void output_handle_mode(void *data, struct wl_output *wl_output,
@@ -86,7 +76,7 @@ static const struct wl_output_listener output_listener = {
};
static void screenshot_done(void *data, struct orbital_screenshot *screenshot) {
- buffer_copy_done = 1;
+ buffer_copy_done = true;
}
static const struct orbital_screenshot_listener screenshot_listener = {
@@ -113,7 +103,7 @@ static void handle_global(void *data, struct wl_registry *registry,
static void handle_global_remove(void *data, struct wl_registry *registry,
uint32_t name) {
- // Unimplemented
+ // Who cares?
}
static const struct wl_registry_listener registry_listener = {
@@ -123,14 +113,15 @@ static const struct wl_registry_listener registry_listener = {
static int backingfile(off_t size) {
char template[] = "/tmp/wlroots-shared-XXXXXX";
- int fd, ret;
-
- fd = mkstemp(template);
+ int fd = mkstemp(template);
if (fd < 0) {
return -1;
}
- while ((ret = ftruncate(fd, size)) == EINTR) {}
+ int ret;
+ while ((ret = ftruncate(fd, size)) == EINTR) {
+ // No-op
+ }
if (ret < 0) {
close(fd);
return -1;
@@ -140,7 +131,6 @@ static int backingfile(off_t size) {
return fd;
}
-
static struct wl_buffer *create_shm_buffer(int width, int height,
void **data_out) {
int stride = width * 4;
@@ -170,91 +160,8 @@ static struct wl_buffer *create_shm_buffer(int width, int height,
return buffer;
}
-static void write_image(const char *filename, int width, int height) {
- int buffer_stride = width * 4;
-
- void *data = calloc(1, buffer_stride * height);
- if (!data) {
- return;
- }
-
- struct screenshooter_output *output, *next;
- wl_list_for_each_safe(output, next, &output_list, link) {
- int output_stride = output->width * 4;
- uint32_t *src = (uint32_t *)output->data;
- uint32_t *dst = (uint32_t *)(data +
- (output->offset_y - min_y) * buffer_stride +
- (output->offset_x - min_x) * 4);
-
- switch (output->transform) {
- case WL_OUTPUT_TRANSFORM_NORMAL:
- for (int i = 0; i < output->height; i++) {
- memcpy(dst, src, output_stride);
- dst += width;
- src += output->width;
- }
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED:
- for (int i = 0; i < output->height; ++i) {
- for (int j = 0; j < output->width; ++j) {
- dst[i * width + j] =
- src[i * output->width + output->width - 1 - j];
- }
- }
- break;
- case WL_OUTPUT_TRANSFORM_90:
- for (int i = 0; i < output->width; ++i) {
- for (int j = 0; j < output->height; ++j) {
- dst[i * width + j] =
- src[j * output->width + output->width - 1 - i];
- }
- }
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED_90:
- for (int i = 0; i < output->width; ++i) {
- for (int j = 0; j < output->height; ++j) {
- dst[i * width + j] =
- src[(output->height - 1 - j) * output->width + output->width - 1 - i];
- }
- }
- break;
- case WL_OUTPUT_TRANSFORM_180:
- for (int i = 0; i < output->height; ++i) {
- for (int j = 0; j < output->width; ++j) {
- dst[i * width + j] =
- src[(output->height - 1 - i) * output->width + output->width - 1 - j];
- }
- }
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED_180:
- for (int i = 0; i < output->height; ++i) {
- for (int j = 0; j < output->width; ++j) {
- dst[i * width + j] =
- src[(output->height - 1 - i) * output->width + j];
- }
- }
- break;
- case WL_OUTPUT_TRANSFORM_270:
- for (int i = 0; i < output->width; ++i) {
- for (int j = 0; j < output->height; ++j) {
- dst[i * width + j] =
- src[(output->height - 1 - j) * output->width + i];
- }
- }
- break;
- case WL_OUTPUT_TRANSFORM_FLIPPED_270:
- for (int i = 0; i < output->width; ++i) {
- for (int j = 0; j < output->height; ++j) {
- dst[i * width + j] =
- src[j * output->width + i];
- }
- }
- break;
- }
-
- free(output);
- }
-
+static void write_image(const char *filename, int width, int height,
+ void *data) {
char size[10 + 1 + 10 + 2 + 1]; // int32_t are max 10 digits
sprintf(size, "%dx%d+0", width, height);
@@ -270,12 +177,11 @@ static void write_image(const char *filename, int width, int height) {
exit(EXIT_FAILURE);
} else if (child != 0) {
close(fd[0]);
- if (write(fd[1], data, buffer_stride * height) < 0) {
+ if (write(fd[1], data, 4 * width * height) < 0) {
fprintf(stderr, "write() failed: %s\n", strerror(errno));
exit(EXIT_FAILURE);
}
close(fd[1]);
- free(data);
waitpid(child, NULL, 0);
} else {
close(fd[1]);
@@ -293,38 +199,9 @@ static void write_image(const char *filename, int width, int height) {
}
}
-static int set_buffer_size(int *width, int *height) {
- int owidth, oheight;
- min_x = min_y = INT_MAX;
- max_x = max_y = INT_MIN;
-
- struct screenshooter_output *output;
- wl_list_for_each(output, &output_list, link) {
- if (output->transform & 0x1) {
- owidth = output->height;
- oheight = output->width;
- } else {
- owidth = output->width;
- oheight = output->height;
- }
- min_x = MIN(min_x, output->offset_x);
- min_y = MIN(min_y, output->offset_y);
- max_x = MAX(max_x, output->offset_x + owidth);
- max_y = MAX(max_y, output->offset_y + oheight);
- }
-
- if (max_x <= min_x || max_y <= min_y) {
- return -1;
- }
-
- *width = max_x - min_x;
- *height = max_y - min_y;
-
- return 0;
-}
-
int main(int argc, char *argv[]) {
wlr_log_init(L_DEBUG, NULL);
+
struct wl_display * display = wl_display_connect(NULL);
if (display == NULL) {
fprintf(stderr, "failed to create display: %m\n");
@@ -342,27 +219,31 @@ int main(int argc, char *argv[]) {
return -1;
}
- int width, height;
- if (set_buffer_size(&width, &height)) {
- fprintf(stderr, "cannot set buffer size\n");
- return -1;
- }
-
+ int i = 0;
struct screenshooter_output *output;
wl_list_for_each(output, &output_list, link) {
- output->buffer = create_shm_buffer(output->width, output->height, &output->data);
- if (output->buffer == NULL) {
+ void *data = NULL;
+ struct wl_buffer *buffer =
+ create_shm_buffer(output->width, output->height, &data);
+ if (buffer == NULL) {
return -1;
}
struct orbital_screenshot *screenshot = orbital_screenshooter_shoot(
- screenshooter, output->output, output->buffer);
- orbital_screenshot_add_listener(screenshot, &screenshot_listener, screenshot);
- buffer_copy_done = 0;
+ screenshooter, output->output, buffer);
+ orbital_screenshot_add_listener(screenshot, &screenshot_listener,
+ screenshot);
+ buffer_copy_done = false;
while (!buffer_copy_done) {
wl_display_roundtrip(display);
}
+
+ char filename[24 + 10]; // int32_t are max 10 digits
+ snprintf(filename, sizeof(filename), "wayland-screenshot-%d.png", i);
+
+ write_image(filename, output->width, output->height, data);
+ wl_buffer_destroy(buffer);
+ ++i;
}
- write_image("wayland-screenshot.png", width, height);
return EXIT_SUCCESS;
}
diff --git a/examples/simple.c b/examples/simple.c
index 90808b0f..79db4a0c 100644
--- a/examples/simple.c
+++ b/examples/simple.c
@@ -1,11 +1,11 @@
#define _POSIX_C_SOURCE 199309L
-#include <string.h>
+#include <GLES2/gl2.h>
+#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include <time.h>
-#include <inttypes.h>
#include <wayland-server.h>
-#include <GLES2/gl2.h>
#include <wlr/backend.h>
#include <wlr/backend/session.h>
#include <wlr/types/wlr_output.h>
diff --git a/examples/tablet.c b/examples/tablet.c
index 5bfa1271..65c559cb 100644
--- a/examples/tablet.c
+++ b/examples/tablet.c
@@ -1,27 +1,27 @@
#define _POSIX_C_SOURCE 199309L
#define _XOPEN_SOURCE 500
+#include <GLES2/gl2.h>
+#include <math.h>
#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
-#include <wayland-server.h>
#include <wayland-server-protocol.h>
-#include <xkbcommon/xkbcommon.h>
-#include <GLES2/gl2.h>
-#include <wlr/render/matrix.h>
-#include <wlr/render/gles2.h>
-#include <wlr/render.h>
+#include <wayland-server.h>
#include <wlr/backend.h>
#include <wlr/backend/session.h>
+#include <wlr/render/gles2.h>
+#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_box.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_output.h>
-#include <wlr/types/wlr_tablet_tool.h>
#include <wlr/types/wlr_tablet_pad.h>
+#include <wlr/types/wlr_tablet_tool.h>
#include <wlr/util/log.h>
-#include <math.h>
-#include "support/shared.h"
+#include <xkbcommon/xkbcommon.h>
#include "support/cat.h"
+#include "support/shared.h"
struct sample_state {
struct wlr_renderer *renderer;
@@ -46,10 +46,10 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts
wlr_output_effective_resolution(wlr_output, &width, &height);
wlr_output_make_current(wlr_output, NULL);
- wlr_renderer_begin(sample->renderer, wlr_output);
- wlr_renderer_clear(sample->renderer, &(float[]){0.25f, 0.25f, 0.25f, 1});
+ wlr_renderer_begin(sample->renderer, wlr_output->width, wlr_output->height);
+ wlr_renderer_clear(sample->renderer, (float[]){0.25f, 0.25f, 0.25f, 1});
- float matrix[16];
+ float matrix[9];
float distance = 0.8f * (1 - sample->distance);
float tool_color[4] = { distance, distance, distance, 1 };
for (size_t i = 0; sample->button && i < 4; ++i) {
@@ -65,9 +65,8 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts
.x = left, .y = top,
.width = pad_width, .height = pad_height,
};
- wlr_matrix_project_box(&matrix, &box, 0, 0,
- &wlr_output->transform_matrix);
- wlr_render_colored_quad(sample->renderer, &sample->pad_color, &matrix);
+ wlr_matrix_project_box(matrix, &box, 0, 0, wlr_output->transform_matrix);
+ wlr_render_colored_quad(sample->renderer, sample->pad_color, matrix);
if (sample->proximity) {
struct wlr_box box = {
@@ -76,16 +75,16 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts
.width = 16 * (sample->pressure + 1),
.height = 16 * (sample->pressure + 1),
};
- wlr_matrix_project_box(&matrix, &box, 0, sample->ring,
- &wlr_output->transform_matrix);
- wlr_render_colored_quad(sample->renderer, &tool_color, &matrix);
+ wlr_matrix_project_box(matrix, &box, 0, sample->ring,
+ wlr_output->transform_matrix);
+ wlr_render_colored_quad(sample->renderer, tool_color, matrix);
box.x += sample->x_tilt;
box.y += sample->y_tilt;
box.width /= 2;
box.height /= 2;
- wlr_matrix_project_box(&matrix, &box, 0, 0,
- &wlr_output->transform_matrix);
- wlr_render_colored_quad(sample->renderer, &tool_color, &matrix);
+ wlr_matrix_project_box(matrix, &box, 0, 0,
+ wlr_output->transform_matrix);
+ wlr_render_colored_quad(sample->renderer, tool_color, matrix);
}
wlr_renderer_end(sample->renderer);
diff --git a/examples/touch.c b/examples/touch.c
index 278252cc..f9c496cf 100644
--- a/examples/touch.c
+++ b/examples/touch.c
@@ -1,25 +1,25 @@
#define _POSIX_C_SOURCE 199309L
#define _XOPEN_SOURCE 500
+#include <GLES2/gl2.h>
+#include <math.h>
+#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
-#include <time.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
-#include <stdint.h>
-#include <math.h>
-#include <wayland-server.h>
#include <wayland-server-protocol.h>
-#include <xkbcommon/xkbcommon.h>
-#include <GLES2/gl2.h>
-#include <wlr/render/matrix.h>
-#include <wlr/render/gles2.h>
-#include <wlr/render.h>
+#include <wayland-server.h>
#include <wlr/backend.h>
#include <wlr/backend/session.h>
+#include <wlr/render/gles2.h>
+#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_list.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/util/log.h>
-#include "support/shared.h"
+#include <xkbcommon/xkbcommon.h>
#include "support/cat.h"
+#include "support/shared.h"
struct sample_state {
struct wlr_renderer *renderer;
@@ -42,18 +42,15 @@ static void handle_output_frame(struct output_state *output, struct timespec *ts
wlr_output_effective_resolution(wlr_output, &width, &height);
wlr_output_make_current(wlr_output, NULL);
- wlr_renderer_begin(sample->renderer, wlr_output);
- wlr_renderer_clear(sample->renderer, &(float[]){0.25f, 0.25f, 0.25f, 1});
+ wlr_renderer_begin(sample->renderer, wlr_output->width, wlr_output->height);
+ wlr_renderer_clear(sample->renderer, (float[]){0.25f, 0.25f, 0.25f, 1});
- float matrix[16];
struct touch_point *p;
wl_list_for_each(p, &sample->touch_points, link) {
- wlr_texture_get_matrix(sample->cat_texture, &matrix,
- &wlr_output->transform_matrix,
- (int)(p->x * width) - sample->cat_texture->width / 2,
- (int)(p->y * height) - sample->cat_texture->height / 2);
- wlr_render_with_matrix(sample->renderer,
- sample->cat_texture, &matrix, 1.0f);
+ int x = (int)(p->x * width) - sample->cat_texture->width / 2;
+ int y = (int)(p->y * height) - sample->cat_texture->height / 2;
+ wlr_render_texture(sample->renderer, sample->cat_texture,
+ wlr_output->transform_matrix, x, y, 1.0f);
}
wlr_renderer_end(sample->renderer);
diff --git a/include/backend/drm/drm.h b/include/backend/drm/drm.h
index ee3fd38e..26189340 100644
--- a/include/backend/drm/drm.h
+++ b/include/backend/drm/drm.h
@@ -26,7 +26,7 @@ struct wlr_drm_plane {
struct wlr_drm_surface mgpu_surf;
// Only used by cursor
- float matrix[16];
+ float matrix[9];
struct wlr_texture *wlr_tex;
struct gbm_bo *cursor_bo;
bool cursor_enabled;
diff --git a/include/backend/drm/renderer.h b/include/backend/drm/renderer.h
index a56a8673..73adfc27 100644
--- a/include/backend/drm/renderer.h
+++ b/include/backend/drm/renderer.h
@@ -5,7 +5,7 @@
#include <gbm.h>
#include <stdbool.h>
#include <stdint.h>
-#include <wlr/render.h>
+#include <wlr/render/wlr_renderer.h>
struct wlr_drm_backend;
struct wlr_drm_plane;
diff --git a/include/backend/wayland.h b/include/backend/wayland.h
index 16c8e13b..00b6ae89 100644
--- a/include/backend/wayland.h
+++ b/include/backend/wayland.h
@@ -7,8 +7,8 @@
#include <wayland-server.h>
#include <wayland-util.h>
#include <wlr/backend/wayland.h>
-#include <wlr/render.h>
#include <wlr/render/egl.h>
+#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_box.h>
struct wlr_wl_backend {
@@ -71,6 +71,7 @@ struct wlr_wl_pointer {
struct wlr_pointer wlr_pointer;
enum wlr_axis_source axis_source;
struct wlr_wl_backend_output *current_output;
+ struct wl_listener output_destroy_listener;
};
void wlr_wl_registry_poll(struct wlr_wl_backend *backend);
diff --git a/include/render/gles2.h b/include/render/gles2.h
index e015160d..43a8d648 100644
--- a/include/render/gles2.h
+++ b/include/render/gles2.h
@@ -9,24 +9,33 @@
#include <stdint.h>
#include <string.h>
#include <wlr/backend.h>
-#include <wlr/render.h>
#include <wlr/render/egl.h>
#include <wlr/render/interface.h>
+#include <wlr/render/wlr_renderer.h>
+#include <wlr/render/wlr_texture.h>
#include <wlr/util/log.h>
extern PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES;
-struct pixel_format {
+struct gles2_pixel_format {
uint32_t wl_format;
GLint gl_format, gl_type;
int depth, bpp;
- GLuint *shader;
+ bool has_alpha;
};
struct wlr_gles2_renderer {
struct wlr_renderer wlr_renderer;
struct wlr_egl *egl;
+
+ struct {
+ GLuint quad;
+ GLuint ellipse;
+ GLuint tex_rgba;
+ GLuint tex_rgbx;
+ GLuint tex_ext;
+ } shaders;
};
struct wlr_gles2_texture {
@@ -34,36 +43,20 @@ struct wlr_gles2_texture {
struct wlr_egl *egl;
GLuint tex_id;
- const struct pixel_format *pixel_format;
+ const struct gles2_pixel_format *pixel_format;
EGLImageKHR image;
+ GLenum target;
};
-struct shaders {
- bool initialized;
- GLuint rgba, rgbx;
- GLuint quad;
- GLuint ellipse;
- GLuint external;
-};
-
-extern struct shaders shaders;
-
-const struct pixel_format *gl_format_for_wl_format(enum wl_shm_format fmt);
+const struct gles2_pixel_format *gles2_format_from_wl(enum wl_shm_format fmt);
+const enum wl_shm_format *gles2_formats(size_t *len);
struct wlr_texture *gles2_texture_create();
+struct wlr_gles2_texture *gles2_get_texture(struct wlr_texture *wlr_texture);
-extern const GLchar quad_vertex_src[];
-extern const GLchar quad_fragment_src[];
-extern const GLchar ellipse_fragment_src[];
-extern const GLchar vertex_src[];
-extern const GLchar fragment_src_rgba[];
-extern const GLchar fragment_src_rgbx[];
-extern const GLchar fragment_src_external[];
-
-bool _gles2_flush_errors(const char *file, int line);
-#define gles2_flush_errors(...) \
- _gles2_flush_errors(wlr_strip_path(__FILE__), __LINE__)
-
-#define GL_CALL(func) func; gles2_flush_errors()
+void gles2_push_marker(const char *file, const char *func);
+void gles2_pop_marker(void);
+#define GLES2_DEBUG_PUSH gles2_push_marker(wlr_strip_path(__FILE__), __func__)
+#define GLES2_DEBUG_POP gles2_pop_marker()
#endif
diff --git a/include/rootston/desktop.h b/include/rootston/desktop.h
index 467de8ab..5986c96f 100644
--- a/include/rootston/desktop.h
+++ b/include/rootston/desktop.h
@@ -7,6 +7,7 @@
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_gamma_control.h>
#include <wlr/types/wlr_idle.h>
+#include <wlr/types/wlr_linux_dmabuf.h>
#include <wlr/types/wlr_list.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_output.h>
@@ -46,6 +47,7 @@ struct roots_desktop {
struct wlr_primary_selection_device_manager *primary_selection_device_manager;
struct wlr_idle *idle;
struct wlr_idle_inhibit_manager_v1 *idle_inhibit;
+ struct wlr_linux_dmabuf *linux_dmabuf;
struct wl_listener new_output;
struct wl_listener layout_change;
@@ -71,14 +73,16 @@ struct roots_output *desktop_output_from_wlr_output(
struct roots_view *desktop_view_at(struct roots_desktop *desktop, double lx,
double ly, struct wlr_surface **surface, double *sx, double *sy);
-void view_init(struct roots_view *view, struct roots_desktop *desktop);
-void view_finish(struct roots_view *view);
+struct roots_view *view_create(struct roots_desktop *desktop);
+void view_destroy(struct roots_view *view);
void view_activate(struct roots_view *view, bool activate);
void view_apply_damage(struct roots_view *view);
void view_damage_whole(struct roots_view *view);
void view_update_position(struct roots_view *view, double x, double y);
void view_update_size(struct roots_view *view, uint32_t width, uint32_t height);
void view_initial_focus(struct roots_view *view);
+void view_map(struct roots_view *view, struct wlr_surface *surface);
+void view_unmap(struct roots_view *view);
void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data);
void handle_xdg_shell_surface(struct wl_listener *listener, void *data);
diff --git a/include/rootston/seat.h b/include/rootston/seat.h
index cc0293b5..0b1dbe2d 100644
--- a/include/rootston/seat.h
+++ b/include/rootston/seat.h
@@ -39,6 +39,7 @@ struct roots_seat_view {
struct wl_list link; // roots_seat::views
+ struct wl_listener view_unmap;
struct wl_listener view_destroy;
};
diff --git a/include/rootston/server.h b/include/rootston/server.h
index 5f35dd90..7ab15682 100644
--- a/include/rootston/server.h
+++ b/include/rootston/server.h
@@ -5,7 +5,7 @@
#include <wlr/backend.h>
#include <wlr/backend/session.h>
#include <wlr/config.h>
-#include <wlr/render.h>
+#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_data_device.h>
#ifdef WLR_HAS_XWAYLAND
#include <wlr/xwayland.h>
diff --git a/include/rootston/view.h b/include/rootston/view.h
index ff5ef44a..775f3d11 100644
--- a/include/rootston/view.h
+++ b/include/rootston/view.h
@@ -27,6 +27,8 @@ struct roots_xdg_surface_v6 {
struct wl_listener destroy;
struct wl_listener new_popup;
+ struct wl_listener map;
+ struct wl_listener unmap;
struct wl_listener request_move;
struct wl_listener request_resize;
struct wl_listener request_maximize;
@@ -42,6 +44,8 @@ struct roots_xdg_surface {
struct wl_listener destroy;
struct wl_listener new_popup;
+ struct wl_listener map;
+ struct wl_listener unmap;
struct wl_listener request_move;
struct wl_listener request_resize;
struct wl_listener request_maximize;
@@ -128,6 +132,7 @@ struct roots_view {
struct wl_listener new_subsurface;
struct {
+ struct wl_signal unmap;
struct wl_signal destroy;
} events;
@@ -140,6 +145,7 @@ struct roots_view {
void (*maximize)(struct roots_view *view, bool maximized);
void (*set_fullscreen)(struct roots_view *view, bool fullscreen);
void (*close)(struct roots_view *view);
+ void (*destroy)(struct roots_view *view);
};
struct roots_view_child {
@@ -181,7 +187,6 @@ struct roots_xdg_popup {
struct wl_listener new_popup;
};
-struct roots_view *view_create();
void view_get_box(const struct roots_view *view, struct wlr_box *box);
void view_activate(struct roots_view *view, bool active);
void view_move(struct roots_view *view, double x, double y);
diff --git a/include/wlr/backend.h b/include/wlr/backend.h
index 00dc9fdc..e3b14add 100644
--- a/include/wlr/backend.h
+++ b/include/wlr/backend.h
@@ -11,16 +11,39 @@ struct wlr_backend {
const struct wlr_backend_impl *impl;
struct {
+ /** Raised when destroyed, passed the wlr_backend reference */
struct wl_signal destroy;
+ /** Raised when new inputs are added, passed the wlr_input_device */
struct wl_signal new_input;
+ /** Raised when new outputs are added, passed the wlr_output */
struct wl_signal new_output;
} events;
};
+/**
+ * Automatically initializes the most suitable backend given the environment.
+ * Will always return a multibackend. The backend is created but not started.
+ * Returns NULL on failure.
+ */
struct wlr_backend *wlr_backend_autocreate(struct wl_display *display);
+/**
+ * Start the backend. This may signal new_input or new_output immediately, but
+ * may also wait until the display's event loop begins. Returns false on
+ * failure.
+ */
bool wlr_backend_start(struct wlr_backend *backend);
+/**
+ * Destroy the backend and clean up all of its resources. Normally called
+ * automatically when the wl_display is destroyed.
+ */
void wlr_backend_destroy(struct wlr_backend *backend);
+/**
+ * Obtains the wlr_egl reference this backend is using.
+ */
struct wlr_egl *wlr_backend_get_egl(struct wlr_backend *backend);
+/**
+ * Obtains the wlr_renderer reference this backend is using.
+ */
struct wlr_renderer *wlr_backend_get_renderer(struct wlr_backend *backend);
uint32_t usec_to_msec(uint64_t usec);
diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h
index 90460647..0c9e5c8b 100644
--- a/include/wlr/backend/drm.h
+++ b/include/wlr/backend/drm.h
@@ -6,6 +6,13 @@
#include <wlr/backend/session.h>
#include <wlr/types/wlr_output.h>
+/**
+ * Creates a DRM backend using the specified GPU file descriptor (typically from
+ * a device node in /dev/dri).
+ *
+ * To slave this to another DRM backend, pass it as the parent (which _must_ be
+ * a DRM backend, other kinds of backends raise SIGABRT).
+ */
struct wlr_backend *wlr_drm_backend_create(struct wl_display *display,
struct wlr_session *session, int gpu_fd, struct wlr_backend *parent);
diff --git a/include/wlr/backend/headless.h b/include/wlr/backend/headless.h
index 8995f7cb..ee784a0d 100644
--- a/include/wlr/backend/headless.h
+++ b/include/wlr/backend/headless.h
@@ -5,9 +5,23 @@
#include <wlr/types/wlr_input_device.h>
#include <wlr/types/wlr_output.h>
+/**
+ * Creates a headless backend. A headless backend has no outputs or inputs by
+ * default.
+ */
struct wlr_backend *wlr_headless_backend_create(struct wl_display *display);
+/**
+ * Create a new headless output backed by an in-memory EGL framebuffer. You can
+ * read pixels from this framebuffer via wlr_renderer_read_pixels but it is
+ * otherwise not displayed.
+ */
struct wlr_output *wlr_headless_add_output(struct wlr_backend *backend,
unsigned int width, unsigned int height);
+/**
+ * Creates a new input device. The caller is responsible for manually raising
+ * any event signals on the new input device if it wants to simulate input
+ * events.
+ */
struct wlr_input_device *wlr_headless_add_input_device(
struct wlr_backend *backend, enum wlr_input_device_type type);
bool wlr_backend_is_headless(struct wlr_backend *backend);
diff --git a/include/wlr/backend/interface.h b/include/wlr/backend/interface.h
index d9212795..f03e95d9 100644
--- a/include/wlr/backend/interface.h
+++ b/include/wlr/backend/interface.h
@@ -12,6 +12,10 @@ struct wlr_backend_impl {
struct wlr_renderer *(*get_renderer)(struct wlr_backend *backend);
};
+/**
+ * Initializes common state on a wlr_backend and sets the implementation to the
+ * provided wlr_backend_impl reference.
+ */
void wlr_backend_init(struct wlr_backend *backend,
const struct wlr_backend_impl *impl);
diff --git a/include/wlr/backend/libinput.h b/include/wlr/backend/libinput.h
index c7cfe894..92d31415 100644
--- a/include/wlr/backend/libinput.h
+++ b/include/wlr/backend/libinput.h
@@ -9,7 +9,9 @@
struct wlr_backend *wlr_libinput_backend_create(struct wl_display *display,
struct wlr_session *session);
-struct libinput_device *wlr_libinput_get_device_handle(struct wlr_input_device *dev);
+/** Gets the underlying libinput_device handle for the given wlr_input_device */
+struct libinput_device *wlr_libinput_get_device_handle(
+ struct wlr_input_device *dev);
bool wlr_backend_is_libinput(struct wlr_backend *backend);
bool wlr_input_device_is_libinput(struct wlr_input_device *device);
diff --git a/include/wlr/backend/multi.h b/include/wlr/backend/multi.h
index 2dee7403..842eed67 100644
--- a/include/wlr/backend/multi.h
+++ b/include/wlr/backend/multi.h
@@ -4,11 +4,21 @@
#include <wlr/backend.h>
#include <wlr/backend/session.h>
+/**
+ * Creates a multi-backend. Multi-backends wrap an arbitrary number of backends
+ * and aggregate their new_output/new_input signals.
+ */
struct wlr_backend *wlr_multi_backend_create(struct wl_display *display);
+/**
+ * Adds the given backend to the multi backend. This should be done before the
+ * new backend is started.
+ */
void wlr_multi_backend_add(struct wlr_backend *multi,
struct wlr_backend *backend);
+
void wlr_multi_backend_remove(struct wlr_backend *multi,
struct wlr_backend *backend);
+
bool wlr_backend_is_multi(struct wlr_backend *backend);
struct wlr_session *wlr_multi_get_session(struct wlr_backend *base);
bool wlr_multi_is_empty(struct wlr_backend *backend);
diff --git a/include/wlr/render.h b/include/wlr/render.h
deleted file mode 100644
index 747603da..00000000
--- a/include/wlr/render.h
+++ /dev/null
@@ -1,149 +0,0 @@
-#ifndef WLR_RENDER_H
-#define WLR_RENDER_H
-
-#include <EGL/egl.h>
-#include <EGL/eglext.h>
-#include <stdint.h>
-#include <wayland-server-protocol.h>
-#include <wlr/types/wlr_box.h>
-#include <wlr/types/wlr_output.h>
-
-struct wlr_texture;
-struct wlr_renderer;
-
-void wlr_renderer_begin(struct wlr_renderer *r, struct wlr_output *output);
-void wlr_renderer_end(struct wlr_renderer *r);
-void wlr_renderer_clear(struct wlr_renderer *r, const float (*color)[4]);
-/**
- * Defines a scissor box. Only pixels that lie within the scissor box can be
- * modified by drawing functions. Providing a NULL `box` disables the scissor
- * box.
- */
-void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box);
-/**
- * Requests a texture handle from this renderer.
- */
-struct wlr_texture *wlr_render_texture_create(struct wlr_renderer *r);
-/**
- * Renders the requested texture using the provided matrix. A typical texture
- * rendering goes like so:
- *
- * struct wlr_renderer *renderer;
- * struct wlr_texture *texture;
- * float projection[16];
- * float matrix[16];
- * wlr_texture_get_matrix(texture, &matrix, &projection, 123, 321);
- * wlr_render_with_matrix(renderer, texture, &matrix, 0.5f);
- *
- * This will render the texture at <123, 321> with an alpha channel of 0.5.
- */
-bool wlr_render_with_matrix(struct wlr_renderer *r,
- struct wlr_texture *texture, const float (*matrix)[16], float alpha);
-
-/**
- * Renders a solid quad in the specified color.
- */
-void wlr_render_colored_quad(struct wlr_renderer *r,
- const float (*color)[4], const float (*matrix)[16]);
-/**
- * Renders a solid ellipse in the specified color.
- */
-void wlr_render_colored_ellipse(struct wlr_renderer *r,
- const float (*color)[4], const float (*matrix)[16]);
-/**
- * Returns a list of pixel formats supported by this renderer.
- */
-const enum wl_shm_format *wlr_renderer_get_formats(
- struct wlr_renderer *r, size_t *len);
-/**
- * Returns true if this wl_buffer is a DRM buffer.
- */
-bool wlr_renderer_buffer_is_drm(struct wlr_renderer *renderer,
- struct wl_resource *buffer);
-/**
- * Reads out of pixels of the currently bound surface into data. `stride` is in
- * bytes.
- */
-bool wlr_renderer_read_pixels(struct wlr_renderer *r, enum wl_shm_format fmt,
- uint32_t stride, uint32_t width, uint32_t height,
- uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, void *data);
-/**
- * Checks if a format is supported.
- */
-bool wlr_renderer_format_supported(struct wlr_renderer *r,
- enum wl_shm_format fmt);
-/**
- * Destroys this wlr_renderer. Textures must be destroyed separately.
- */
-void wlr_renderer_destroy(struct wlr_renderer *renderer);
-
-struct wlr_texture_impl;
-
-struct wlr_texture {
- struct wlr_texture_impl *impl;
-
- bool valid;
- uint32_t format;
- int width, height;
- struct wl_signal destroy_signal;
- struct wl_resource *resource;
-};
-
-/**
- * Copies pixels to this texture. The buffer is not accessed after this function
- * returns.
- */
-bool wlr_texture_upload_pixels(struct wlr_texture *tex,
- enum wl_shm_format format, int stride, int width, int height,
- const unsigned char *pixels);
-/**
- * Copies pixels to this texture. The buffer is not accessed after this function
- * returns. Under some circumstances, this function may re-upload the entire
- * buffer - therefore, the entire buffer must be valid.
- */
-bool wlr_texture_update_pixels(struct wlr_texture *surf,
- enum wl_shm_format format, int stride, int x, int y,
- int width, int height, const unsigned char *pixels);
-/**
- * Copies pixels from a wl_shm_buffer into this texture. The buffer is not
- * accessed after this function returns.
- */
-bool wlr_texture_upload_shm(struct wlr_texture *tex, uint32_t format,
- struct wl_shm_buffer *shm);
-
-/**
- * Attaches the contents from the given wl_drm wl_buffer resource onto the
- * texture. The wl_resource is not used after this call.
- * Will fail (return false) if the given resource is no drm buffer.
- */
-bool wlr_texture_upload_drm(struct wlr_texture *tex,
- struct wl_resource *drm_buffer);
-
-bool wlr_texture_upload_eglimage(struct wlr_texture *tex,
- EGLImageKHR image, uint32_t width, uint32_t height);
-
-/**
- * Copies a rectangle of pixels from a wl_shm_buffer onto the texture. The
- * buffer is not accessed after this function returns. Under some circumstances,
- * this function may re-upload the entire buffer - therefore, the entire buffer
- * must be valid.
- */
-bool wlr_texture_update_shm(struct wlr_texture *surf, uint32_t format,
- int x, int y, int width, int height, struct wl_shm_buffer *shm);
-/**
- * Prepares a matrix with the appropriate scale for the given texture and
- * multiplies it with the projection, producing a matrix that the shader can
- * muptlipy vertex coordinates with to get final screen coordinates.
- *
- * The projection matrix is assumed to be an orthographic projection of [0,
- * width) and [0, height], and the x and y coordinates provided are used as
- * such.
- */
-void wlr_texture_get_matrix(struct wlr_texture *texture,
- float (*matrix)[16], const float (*projection)[16], int x, int y);
-/**
- * Destroys this wlr_texture.
- */
-void wlr_texture_destroy(struct wlr_texture *texture);
-
-#endif
diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h
index 97a28016..aa429e8e 100644
--- a/include/wlr/render/egl.h
+++ b/include/wlr/render/egl.h
@@ -6,6 +6,7 @@
#include <pixman.h>
#include <stdbool.h>
#include <wayland-server.h>
+#include <wlr/types/wlr_linux_dmabuf.h>
struct wlr_egl {
EGLDisplay display;
@@ -18,6 +19,8 @@ struct wlr_egl {
struct {
bool buffer_age;
bool swap_buffers_with_damage;
+ bool dmabuf_import;
+ bool dmabuf_import_modifiers;
} egl_exts;
struct wl_display *wl_display;
@@ -62,14 +65,34 @@ EGLImageKHR wlr_egl_create_image(struct wlr_egl *egl,
EGLenum target, EGLClientBuffer buffer, const EGLint *attribs);
/**
- * Destroys an egl image created with the given wlr_egl.
+ * Creates an egl image from the given dmabuf attributes. Check usability
+ * of the dmabuf with wlr_egl_check_import_dmabuf once first.
*/
-bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImageKHR image);
+EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
+ struct wlr_dmabuf_buffer_attribs *attributes);
/**
- * Returns a string for the last error ocurred with egl.
+ * Try to import the given dmabuf. On success return true false otherwise.
+ * If this succeeds the dmabuf can be used for rendering on a texture
*/
-const char *egl_error(void);
+bool wlr_egl_check_import_dmabuf(struct wlr_egl *egl,
+ struct wlr_dmabuf_buffer *dmabuf);
+
+/**
+ * Get the available dmabuf formats
+ */
+int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl, int **formats);
+
+/**
+ * Get the available dmabuf modifiers for a given format
+ */
+int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl, int format,
+ uint64_t **modifiers);
+
+/**
+ * Destroys an egl image created with the given wlr_egl.
+ */
+bool wlr_egl_destroy_image(struct wlr_egl *egl, EGLImageKHR image);
bool wlr_egl_make_current(struct wlr_egl *egl, EGLSurface surface,
int *buffer_age);
diff --git a/include/wlr/render/gles2.h b/include/wlr/render/gles2.h
index a924a065..b3b43ab2 100644
--- a/include/wlr/render/gles2.h
+++ b/include/wlr/render/gles2.h
@@ -2,7 +2,7 @@
#define WLR_RENDER_GLES2_H
#include <wlr/backend.h>
-#include <wlr/render.h>
+#include <wlr/render/wlr_renderer.h>
struct wlr_egl;
struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_backend *backend);
diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h
index eda5af1c..7f25c0ff 100644
--- a/include/wlr/render/interface.h
+++ b/include/wlr/render/interface.h
@@ -5,28 +5,32 @@
#include <EGL/eglext.h>
#include <stdbool.h>
#include <wayland-server-protocol.h>
-#include <wlr/render.h>
+#include <wlr/render/wlr_renderer.h>
+#include <wlr/render/wlr_texture.h>
#include <wlr/types/wlr_box.h>
+#include <wlr/types/wlr_linux_dmabuf.h>
#include <wlr/types/wlr_output.h>
struct wlr_renderer_impl;
struct wlr_renderer {
- struct wlr_renderer_impl *impl;
+ const struct wlr_renderer_impl *impl;
};
struct wlr_renderer_impl {
- void (*begin)(struct wlr_renderer *renderer, struct wlr_output *output);
+ void (*begin)(struct wlr_renderer *renderer, uint32_t width,
+ uint32_t height);
void (*end)(struct wlr_renderer *renderer);
- void (*clear)(struct wlr_renderer *renderer, const float (*color)[4]);
+ void (*clear)(struct wlr_renderer *renderer, const float color[static 4]);
void (*scissor)(struct wlr_renderer *renderer, struct wlr_box *box);
struct wlr_texture *(*texture_create)(struct wlr_renderer *renderer);
- bool (*render_with_matrix)(struct wlr_renderer *renderer,
- struct wlr_texture *texture, const float (*matrix)[16], float alpha);
+ bool (*render_texture_with_matrix)(struct wlr_renderer *renderer,
+ struct wlr_texture *texture, const float matrix[static 9],
+ float alpha);
void (*render_quad)(struct wlr_renderer *renderer,
- const float (*color)[4], const float (*matrix)[16]);
+ const float color[static 4], const float matrix[static 9]);
void (*render_ellipse)(struct wlr_renderer *renderer,
- const float (*color)[4], const float (*matrix)[16]);
+ const float color[static 4], const float matrix[static 9]);
const enum wl_shm_format *(*formats)(
struct wlr_renderer *renderer, size_t *len);
bool (*buffer_is_drm)(struct wlr_renderer *renderer,
@@ -41,7 +45,7 @@ struct wlr_renderer_impl {
};
void wlr_renderer_init(struct wlr_renderer *renderer,
- struct wlr_renderer_impl *impl);
+ const struct wlr_renderer_impl *impl);
struct wlr_texture_impl {
bool (*upload_pixels)(struct wlr_texture *texture,
@@ -58,18 +62,16 @@ struct wlr_texture_impl {
struct wl_resource *drm_buf);
bool (*upload_eglimage)(struct wlr_texture *texture, EGLImageKHR image,
uint32_t width, uint32_t height);
- void (*get_matrix)(struct wlr_texture *state,
- float (*matrix)[16], const float (*projection)[16], int x, int y);
+ bool (*upload_dmabuf)(struct wlr_texture *texture,
+ struct wl_resource *dmabuf_resource);
void (*get_buffer_size)(struct wlr_texture *texture,
struct wl_resource *resource, int *width, int *height);
- void (*bind)(struct wlr_texture *texture);
void (*destroy)(struct wlr_texture *texture);
};
void wlr_texture_init(struct wlr_texture *texture,
- struct wlr_texture_impl *impl);
-void wlr_texture_bind(struct wlr_texture *texture);
+ const struct wlr_texture_impl *impl);
void wlr_texture_get_buffer_size(struct wlr_texture *texture,
- struct wl_resource *resource, int *width, int *height);
+ struct wl_resource *resource, int *width, int *height);
#endif
diff --git a/include/wlr/render/matrix.h b/include/wlr/render/matrix.h
deleted file mode 100644
index a333bf0f..00000000
--- a/include/wlr/render/matrix.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef WLR_RENDER_MATRIX_H
-#define WLR_RENDER_MATRIX_H
-
-#include <stdint.h>
-#include <wlr/types/wlr_box.h>
-
-void wlr_matrix_identity(float (*output)[16]);
-void wlr_matrix_translate(float (*output)[16], float x, float y, float z);
-void wlr_matrix_scale(float (*output)[16], float x, float y, float z);
-void wlr_matrix_rotate(float (*output)[16], float radians);
-void wlr_matrix_mul(const float (*x)[16], const float (*y)[16], float (*product)[16]);
-
-enum wl_output_transform;
-void wlr_matrix_transform(float mat[static 16],
- enum wl_output_transform transform);
-void wlr_matrix_texture(float mat[static 16], int32_t width, int32_t height,
- enum wl_output_transform transform);
-void wlr_matrix_project_box(float (*mat)[16], struct wlr_box *box,
- enum wl_output_transform transform, float rotation, float
- (*projection)[16]);
-
-#endif
diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h
new file mode 100644
index 00000000..6f0d2ecc
--- /dev/null
+++ b/include/wlr/render/wlr_renderer.h
@@ -0,0 +1,75 @@
+#ifndef WLR_RENDER_WLR_RENDERER_H
+#define WLR_RENDER_WLR_RENDERER_H
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <stdint.h>
+#include <wayland-server-protocol.h>
+#include <wlr/render/wlr_texture.h>
+#include <wlr/types/wlr_box.h>
+
+struct wlr_output;
+
+struct wlr_renderer;
+
+void wlr_renderer_begin(struct wlr_renderer *r, int width, int height);
+void wlr_renderer_end(struct wlr_renderer *r);
+void wlr_renderer_clear(struct wlr_renderer *r, const float color[static 4]);
+/**
+ * Defines a scissor box. Only pixels that lie within the scissor box can be
+ * modified by drawing functions. Providing a NULL `box` disables the scissor
+ * box.
+ */
+void wlr_renderer_scissor(struct wlr_renderer *r, struct wlr_box *box);
+/**
+ * Requests a texture handle from this renderer.
+ */
+struct wlr_texture *wlr_render_texture_create(struct wlr_renderer *r);
+/**
+ * Renders the requested texture.
+ */
+bool wlr_render_texture(struct wlr_renderer *r, struct wlr_texture *texture,
+ const float projection[static 9], int x, int y, float alpha);
+/**
+ * Renders the requested texture using the provided matrix.
+ */
+bool wlr_render_texture_with_matrix(struct wlr_renderer *r,
+ struct wlr_texture *texture, const float matrix[static 9], float alpha);
+/**
+ * Renders a solid quad in the specified color.
+ */
+void wlr_render_colored_quad(struct wlr_renderer *r,
+ const float color[static 4], const float matrix[static 9]);
+/**
+ * Renders a solid ellipse in the specified color.
+ */
+void wlr_render_colored_ellipse(struct wlr_renderer *r,
+ const float color[static 4], const float matrix[static 9]);
+/**
+ * Returns a list of pixel formats supported by this renderer.
+ */
+const enum wl_shm_format *wlr_renderer_get_formats(struct wlr_renderer *r,
+ size_t *len);
+/**
+ * Returns true if this wl_buffer is a DRM buffer.
+ */
+bool wlr_renderer_buffer_is_drm(struct wlr_renderer *renderer,
+ struct wl_resource *buffer);
+/**
+ * Reads out of pixels of the currently bound surface into data. `stride` is in
+ * bytes.
+ */
+bool wlr_renderer_read_pixels(struct wlr_renderer *r, enum wl_shm_format fmt,
+ uint32_t stride, uint32_t width, uint32_t height,
+ uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, void *data);
+/**
+ * Checks if a format is supported.
+ */
+bool wlr_renderer_format_supported(struct wlr_renderer *r,
+ enum wl_shm_format fmt);
+/**
+ * Destroys this wlr_renderer. Textures must be destroyed separately.
+ */
+void wlr_renderer_destroy(struct wlr_renderer *renderer);
+
+#endif
diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h
new file mode 100644
index 00000000..095097e6
--- /dev/null
+++ b/include/wlr/render/wlr_texture.h
@@ -0,0 +1,69 @@
+#ifndef WLR_RENDER_WLR_TEXTURE_H
+#define WLR_RENDER_WLR_TEXTURE_H
+
+#include <EGL/egl.h>
+#include <EGL/eglext.h>
+#include <stdint.h>
+#include <wayland-server-protocol.h>
+
+struct wlr_texture_impl;
+
+struct wlr_texture {
+ const struct wlr_texture_impl *impl;
+
+ bool valid;
+ uint32_t format;
+ int width, height;
+ bool inverted_y;
+ struct wl_signal destroy_signal;
+ struct wl_resource *resource;
+};
+
+/**
+ * Copies pixels to this texture. The buffer is not accessed after this function
+ * returns.
+ */
+bool wlr_texture_upload_pixels(struct wlr_texture *tex,
+ enum wl_shm_format format, int stride, int width, int height,
+ const unsigned char *pixels);
+/**
+ * Copies pixels to this texture. The buffer is not accessed after this function
+ * returns. Under some circumstances, this function may re-upload the entire
+ * buffer - therefore, the entire buffer must be valid.
+ */
+bool wlr_texture_update_pixels(struct wlr_texture *surf,
+ enum wl_shm_format format, int stride, int x, int y,
+ int width, int height, const unsigned char *pixels);
+/**
+ * Copies pixels from a wl_shm_buffer into this texture. The buffer is not
+ * accessed after this function returns.
+ */
+bool wlr_texture_upload_shm(struct wlr_texture *tex, uint32_t format,
+ struct wl_shm_buffer *shm);
+/**
+ * Attaches the contents from the given wl_drm wl_buffer resource onto the
+ * texture. The wl_resource is not used after this call.
+ * Will fail (return false) if the given resource is no drm buffer.
+ */
+bool wlr_texture_upload_drm(struct wlr_texture *tex,
+ struct wl_resource *drm_buffer);
+
+bool wlr_texture_upload_eglimage(struct wlr_texture *tex,
+ EGLImageKHR image, uint32_t width, uint32_t height);
+
+bool wlr_texture_upload_dmabuf(struct wlr_texture *tex,
+ struct wl_resource *dmabuf_resource);
+/**
+ * Copies a rectangle of pixels from a wl_shm_buffer onto the texture. The
+ * buffer is not accessed after this function returns. Under some circumstances,
+ * this function may re-upload the entire buffer - therefore, the entire buffer
+ * must be valid.
+ */
+bool wlr_texture_update_shm(struct wlr_texture *surf, uint32_t format,
+ int x, int y, int width, int height, struct wl_shm_buffer *shm);
+/**
+ * Destroys this wlr_texture.
+ */
+void wlr_texture_destroy(struct wlr_texture *texture);
+
+#endif
diff --git a/include/wlr/types/wlr_compositor.h b/include/wlr/types/wlr_compositor.h
index 5919b934..11bfac71 100644
--- a/include/wlr/types/wlr_compositor.h
+++ b/include/wlr/types/wlr_compositor.h
@@ -2,7 +2,7 @@
#define WLR_TYPES_WLR_COMPOSITOR_H
#include <wayland-server.h>
-#include <wlr/render.h>
+#include <wlr/render/wlr_renderer.h>
struct wlr_compositor {
struct wl_global *wl_global;
diff --git a/include/wlr/types/wlr_linux_dmabuf.h b/include/wlr/types/wlr_linux_dmabuf.h
new file mode 100644
index 00000000..9d71e598
--- /dev/null
+++ b/include/wlr/types/wlr_linux_dmabuf.h
@@ -0,0 +1,84 @@
+#ifndef WLR_TYPES_WLR_LINUX_DMABUF_H
+#define WLR_TYPES_WLR_LINUX_DMABUF_H
+
+#define WLR_LINUX_DMABUF_MAX_PLANES 4
+
+#include <stdint.h>
+#include <wayland-server-protocol.h>
+
+/* So we don't have to pull in linux specific drm headers */
+#ifndef DRM_FORMAT_MOD_INVALID
+#define DRM_FORMAT_MOD_INVALID ((1ULL<<56) - 1)
+#endif
+
+struct wlr_dmabuf_buffer_attribs {
+ /* set via params_add */
+ int n_planes;
+ uint32_t offset[WLR_LINUX_DMABUF_MAX_PLANES];
+ uint32_t stride[WLR_LINUX_DMABUF_MAX_PLANES];
+ uint64_t modifier[WLR_LINUX_DMABUF_MAX_PLANES];
+ int fd[WLR_LINUX_DMABUF_MAX_PLANES];
+ /* set via params_create */
+ int32_t width;
+ int32_t height;
+ uint32_t format;
+ uint32_t flags; /* enum zlinux_buffer_params_flags */
+};
+
+struct wlr_dmabuf_buffer {
+ struct wlr_egl *egl;
+ struct wl_resource *buffer_resource;
+ struct wl_resource *params_resource;
+ struct wlr_dmabuf_buffer_attribs attributes;
+};
+
+/**
+ * Returns true if the given resource was created via the linux-dmabuf
+ * buffer protocol, false otherwise
+ */
+bool wlr_dmabuf_resource_is_buffer(struct wl_resource *buffer_resource);
+
+/**
+ * Returns the wlr_dmabuf_buffer if the given resource was created
+ * via the linux-dmabuf buffer protocol
+ */
+struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_buffer_resource(
+ struct wl_resource *buffer_resource);
+
+/**
+ * Returns the wlr_dmabuf_buffer if the given resource was created
+ * via the linux-dmabuf params protocol
+ */
+struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_params_resource(
+ struct wl_resource *params_resource);
+
+/**
+ * Returns true if the given dmabuf has y-axis inverted, false otherwise
+ */
+bool wlr_dmabuf_buffer_has_inverted_y(struct wlr_dmabuf_buffer *dmabuf);
+
+/* the protocol interface */
+struct wlr_linux_dmabuf {
+ struct wl_global *wl_global;
+ struct wl_listener display_destroy;
+ struct wlr_egl *egl;
+};
+
+/**
+ * Create linux-dmabuf interface
+ */
+struct wlr_linux_dmabuf *wlr_linux_dmabuf_create(struct wl_display *display,
+ struct wlr_egl *egl);
+/**
+ * Destroy the linux-dmabuf interface
+ */
+void wlr_linux_dmabuf_destroy(struct wlr_linux_dmabuf *linux_dmabuf);
+
+/**
+ * Returns the wlr_linux_dmabuf if the given resource was created
+ * via the linux_dmabuf protocol
+ */
+struct wlr_linux_dmabuf *wlr_linux_dmabuf_from_resource(
+ struct wl_resource *resource);
+
+#endif
diff --git a/include/wlr/types/wlr_matrix.h b/include/wlr/types/wlr_matrix.h
new file mode 100644
index 00000000..02111db8
--- /dev/null
+++ b/include/wlr/types/wlr_matrix.h
@@ -0,0 +1,22 @@
+#ifndef WLR_TYPES_WLR_MATRIX_H
+#define WLR_TYPES_WLR_MATRIX_H
+
+#include <wayland-server.h>
+#include <wlr/types/wlr_box.h>
+
+void wlr_matrix_identity(float mat[static 9]);
+void wlr_matrix_multiply(float mat[static 9], const float a[static 9],
+ const float b[static 9]);
+void wlr_matrix_transpose(float mat[static 9], const float a[static 9]);
+void wlr_matrix_translate(float mat[static 9], float x, float y);
+void wlr_matrix_scale(float mat[static 9], float x, float y);
+void wlr_matrix_rotate(float mat[static 9], float rad);
+void wlr_matrix_transform(float mat[static 9],
+ enum wl_output_transform transform);
+void wlr_matrix_projection(float mat[static 9], int width, int height,
+ enum wl_output_transform transform);
+void wlr_matrix_project_box(float mat[static 9], const struct wlr_box *box,
+ enum wl_output_transform transform, float rotation,
+ const float projection[static 9]);
+
+#endif
diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h
index a8138a80..b838a737 100644
--- a/include/wlr/types/wlr_output.h
+++ b/include/wlr/types/wlr_output.h
@@ -76,7 +76,7 @@ struct wlr_output {
// damage for cursors and fullscreen surface, in output-local coordinates
pixman_region32_t damage;
bool frame_pending;
- float transform_matrix[16];
+ float transform_matrix[9];
struct {
struct wl_signal frame;
diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h
index 203345bd..5c5b012f 100644
--- a/include/wlr/types/wlr_surface.h
+++ b/include/wlr/types/wlr_surface.h
@@ -70,8 +70,8 @@ struct wlr_surface {
struct wlr_surface_state *current, *pending;
const char *role; // the lifetime-bound role or null
- float buffer_to_surface_matrix[16];
- float surface_to_buffer_matrix[16];
+ float buffer_to_surface_matrix[9];
+ float surface_to_buffer_matrix[9];
struct {
struct wl_signal commit;
@@ -99,19 +99,6 @@ struct wlr_surface {
struct wlr_renderer;
struct wlr_surface *wlr_surface_create(struct wl_resource *res,
struct wlr_renderer *renderer);
-/**
- * Gets a matrix you can pass into wlr_render_with_matrix to display this
- * surface. `matrix` is the output matrix, `projection` is the wlr_output
- * projection matrix, and `transform` is any additional transformations you want
- * to perform on the surface (or NULL/the identity matrix if you don't).
- * `transform` is used before the surface is scaled, so its geometry extends
- * from 0 to 1 in both dimensions.
- */
-void wlr_surface_get_matrix(struct wlr_surface *surface,
- float (*matrix)[16],
- const float (*projection)[16],
- const float (*transform)[16]);
-
/**
* Set the lifetime role for this surface. Returns 0 on success or -1 if the
diff --git a/include/wlr/types/wlr_xdg_shell.h b/include/wlr/types/wlr_xdg_shell.h
index 8422863c..a5fa093b 100644
--- a/include/wlr/types/wlr_xdg_shell.h
+++ b/include/wlr/types/wlr_xdg_shell.h
@@ -53,6 +53,7 @@ struct wlr_xdg_popup_grab {
struct wlr_seat *seat;
struct wl_list popups;
struct wl_list link; // wlr_xdg_shell::popup_grabs
+ struct wl_listener seat_destroy;
};
enum wlr_xdg_surface_role {
@@ -62,19 +63,10 @@ enum wlr_xdg_surface_role {
};
struct wlr_xdg_toplevel_state {
- bool maximized;
- bool fullscreen;
- bool resizing;
- bool activated;
-
- uint32_t width;
- uint32_t height;
-
- uint32_t max_width;
- uint32_t max_height;
-
- uint32_t min_width;
- uint32_t min_height;
+ bool maximized, fullscreen, resizing, activated;
+ uint32_t width, height;
+ uint32_t max_width, max_height;
+ uint32_t min_width, min_height;
};
struct wlr_xdg_toplevel {
@@ -90,7 +82,8 @@ struct wlr_xdg_toplevel {
struct wlr_xdg_surface_configure {
struct wl_list link; // wlr_xdg_surface::configure_list
uint32_t serial;
- struct wlr_xdg_toplevel_state state;
+
+ struct wlr_xdg_toplevel_state *toplevel_state;
};
struct wlr_xdg_surface {
@@ -101,14 +94,13 @@ struct wlr_xdg_surface {
enum wlr_xdg_surface_role role;
union {
- struct wlr_xdg_toplevel *toplevel_state;
- struct wlr_xdg_popup *popup_state;
+ struct wlr_xdg_toplevel *toplevel;
+ struct wlr_xdg_popup *popup;
};
struct wl_list popups; // wlr_xdg_popup::link
- bool configured;
- bool added;
+ bool added, configured, mapped;
uint32_t configure_serial;
struct wl_event_source *configure_idle;
uint32_t configure_next_serial;
@@ -118,8 +110,8 @@ struct wlr_xdg_surface {
char *app_id;
bool has_next_geometry;
- struct wlr_box *next_geometry;
- struct wlr_box *geometry;
+ struct wlr_box next_geometry;
+ struct wlr_box geometry;
struct wl_listener surface_destroy_listener;
@@ -127,6 +119,8 @@ struct wlr_xdg_surface {
struct wl_signal destroy;
struct wl_signal ping_timeout;
struct wl_signal new_popup;
+ struct wl_signal map;
+ struct wl_signal unmap;
struct wl_signal request_maximize;
struct wl_signal request_fullscreen;
diff --git a/include/wlr/types/wlr_xdg_shell_v6.h b/include/wlr/types/wlr_xdg_shell_v6.h
index 42eb332a..75570127 100644
--- a/include/wlr/types/wlr_xdg_shell_v6.h
+++ b/include/wlr/types/wlr_xdg_shell_v6.h
@@ -113,6 +113,7 @@ struct wlr_xdg_popup_grab_v6 {
struct wlr_seat *seat;
struct wl_list popups;
struct wl_list link; // wlr_xdg_shell_v6::popup_grabs
+ struct wl_listener seat_destroy;
};
enum wlr_xdg_surface_v6_role {
@@ -122,19 +123,10 @@ enum wlr_xdg_surface_v6_role {
};
struct wlr_xdg_toplevel_v6_state {
- bool maximized;
- bool fullscreen;
- bool resizing;
- bool activated;
-
- uint32_t width;
- uint32_t height;
-
- uint32_t max_width;
- uint32_t max_height;
-
- uint32_t min_width;
- uint32_t min_height;
+ bool maximized, fullscreen, resizing, activated;
+ uint32_t width, height;
+ uint32_t max_width, max_height;
+ uint32_t min_width, min_height;
};
struct wlr_xdg_toplevel_v6 {
@@ -150,7 +142,8 @@ struct wlr_xdg_toplevel_v6 {
struct wlr_xdg_surface_v6_configure {
struct wl_list link; // wlr_xdg_surface_v6::configure_list
uint32_t serial;
- struct wlr_xdg_toplevel_v6_state state;
+
+ struct wlr_xdg_toplevel_v6_state *toplevel_state;
};
struct wlr_xdg_surface_v6 {
@@ -161,14 +154,13 @@ struct wlr_xdg_surface_v6 {
enum wlr_xdg_surface_v6_role role;
union {
- struct wlr_xdg_toplevel_v6 *toplevel_state;
- struct wlr_xdg_popup_v6 *popup_state;
+ struct wlr_xdg_toplevel_v6 *toplevel;
+ struct wlr_xdg_popup_v6 *popup;
};
struct wl_list popups; // wlr_xdg_popup_v6::link
- bool configured;
- bool added;
+ bool added, configured, mapped;
uint32_t configure_serial;
struct wl_event_source *configure_idle;
uint32_t configure_next_serial;
@@ -178,8 +170,8 @@ struct wlr_xdg_surface_v6 {
char *app_id;
bool has_next_geometry;
- struct wlr_box *next_geometry;
- struct wlr_box *geometry;
+ struct wlr_box next_geometry;
+ struct wlr_box geometry;
struct wl_listener surface_destroy_listener;
@@ -187,6 +179,8 @@ struct wlr_xdg_surface_v6 {
struct wl_signal destroy;
struct wl_signal ping_timeout;
struct wl_signal new_popup;
+ struct wl_signal map;
+ struct wl_signal unmap;
struct wl_signal request_maximize;
struct wl_signal request_fullscreen;
diff --git a/protocol/meson.build b/protocol/meson.build
index 6c87a887..638b0c46 100644
--- a/protocol/meson.build
+++ b/protocol/meson.build
@@ -21,9 +21,10 @@ wayland_scanner_client = generator(
)
protocols = [
- [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'],
[wl_protocol_dir, 'stable/xdg-shell/xdg-shell.xml'],
[wl_protocol_dir, 'unstable/idle-inhibit/idle-inhibit-unstable-v1.xml'],
+ [wl_protocol_dir, 'unstable/linux-dmabuf/linux-dmabuf-unstable-v1.xml'],
+ [wl_protocol_dir, 'unstable/xdg-shell/xdg-shell-unstable-v6.xml'],
'gamma-control.xml',
'gtk-primary-selection.xml',
'idle.xml',
diff --git a/render/egl.c b/render/egl.c
index 0a68d6e5..b1bd4884 100644
--- a/render/egl.c
+++ b/render/egl.c
@@ -1,4 +1,5 @@
#include <assert.h>
+#include <stdio.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <GLES2/gl2.h>
@@ -11,43 +12,6 @@
// https://www.khronos.org/registry/EGL/extensions/KHR/EGL_KHR_image_base.txt.
// https://cgit.freedesktop.org/mesa/mesa/tree/docs/specs/WL_bind_wayland_display.spec
-const char *egl_error(void) {
- switch (eglGetError()) {
- case EGL_SUCCESS:
- return "Success";
- case EGL_NOT_INITIALIZED:
- return "Not initialized";
- case EGL_BAD_ACCESS:
- return "Bad access";
- case EGL_BAD_ALLOC:
- return "Bad alloc";
- case EGL_BAD_ATTRIBUTE:
- return "Bad attribute";
- case EGL_BAD_CONTEXT:
- return "Bad Context";
- case EGL_BAD_CONFIG:
- return "Bad Config";
- case EGL_BAD_CURRENT_SURFACE:
- return "Bad current surface";
- case EGL_BAD_DISPLAY:
- return "Bad display";
- case EGL_BAD_SURFACE:
- return "Bad surface";
- case EGL_BAD_MATCH:
- return "Bad match";
- case EGL_BAD_PARAMETER:
- return "Bad parameter";
- case EGL_BAD_NATIVE_PIXMAP:
- return "Bad native pixmap";
- case EGL_BAD_NATIVE_WINDOW:
- return "Bad native window";
- case EGL_CONTEXT_LOST:
- return "Context lost";
- default:
- return "Unknown";
- }
-}
-
static bool egl_get_config(EGLDisplay disp, EGLint *attribs, EGLConfig *out,
EGLint visual_id) {
EGLint count = 0, matched = 0, ret;
@@ -83,6 +47,21 @@ static bool egl_get_config(EGLDisplay disp, EGLint *attribs, EGLConfig *out,
return false;
}
+static log_importance_t egl_log_importance_to_wlr(EGLint type) {
+ switch (type) {
+ case EGL_DEBUG_MSG_CRITICAL_KHR: return L_ERROR;
+ case EGL_DEBUG_MSG_ERROR_KHR: return L_ERROR;
+ case EGL_DEBUG_MSG_WARN_KHR: return L_ERROR;
+ case EGL_DEBUG_MSG_INFO_KHR: return L_INFO;
+ default: return L_INFO;
+ }
+}
+
+static void egl_log(EGLenum error, const char *command, EGLint msg_type,
+ EGLLabelKHR thread, EGLLabelKHR obj, const char *msg) {
+ _wlr_log(egl_log_importance_to_wlr(msg_type), "[EGL] %s: %s", command, msg);
+}
+
static bool check_egl_ext(const char *egl_exts, const char *ext) {
size_t extlen = strlen(ext);
const char *end = egl_exts + strlen(egl_exts);
@@ -101,14 +80,45 @@ static bool check_egl_ext(const char *egl_exts, const char *ext) {
return false;
}
+static void print_dmabuf_formats(struct wlr_egl *egl) {
+ /* Avoid log msg if extension is not present */
+ if (!egl->egl_exts.dmabuf_import_modifiers) {
+ return;
+ }
+
+ int *formats;
+ int num = wlr_egl_get_dmabuf_formats(egl, &formats);
+ if (num < 0) {
+ return;
+ }
+
+ char str_formats[num * 5 + 1];
+ for (int i = 0; i < num; i++) {
+ snprintf(&str_formats[i*5], (num - i) * 5 + 1, "%.4s ", (char*)&formats[i]);
+ }
+ wlr_log(L_INFO, "Supported dmabuf buffer formats: %s", str_formats);
+ free(formats);
+}
+
bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display,
EGLint *config_attribs, EGLint visual_id) {
if (!load_glapi()) {
return false;
}
+ if (eglDebugMessageControlKHR) {
+ static const EGLAttrib debug_attribs[] = {
+ EGL_DEBUG_MSG_CRITICAL_KHR, EGL_TRUE,
+ EGL_DEBUG_MSG_ERROR_KHR, EGL_TRUE,
+ EGL_DEBUG_MSG_WARN_KHR, EGL_TRUE,
+ EGL_DEBUG_MSG_INFO_KHR, EGL_TRUE,
+ EGL_NONE,
+ };
+ eglDebugMessageControlKHR(egl_log, debug_attribs);
+ }
+
if (eglBindAPI(EGL_OPENGL_ES_API) == EGL_FALSE) {
- wlr_log(L_ERROR, "Failed to bind to the OpenGL ES API: %s", egl_error());
+ wlr_log(L_ERROR, "Failed to bind to the OpenGL ES API");
goto error;
}
@@ -119,13 +129,13 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display,
egl->display = eglGetPlatformDisplayEXT(platform, remote_display, NULL);
}
if (egl->display == EGL_NO_DISPLAY) {
- wlr_log(L_ERROR, "Failed to create EGL display: %s", egl_error());
+ wlr_log(L_ERROR, "Failed to create EGL display");
goto error;
}
EGLint major, minor;
if (eglInitialize(egl->display, &major, &minor) == EGL_FALSE) {
- wlr_log(L_ERROR, "Failed to initialize EGL: %s", egl_error());
+ wlr_log(L_ERROR, "Failed to initialize EGL");
goto error;
}
@@ -140,7 +150,7 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display,
EGL_NO_CONTEXT, attribs);
if (egl->context == EGL_NO_CONTEXT) {
- wlr_log(L_ERROR, "Failed to create EGL context: %s", egl_error());
+ wlr_log(L_ERROR, "Failed to create EGL context");
goto error;
}
@@ -167,16 +177,29 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display,
check_egl_ext(egl->egl_exts_str, "EGL_EXT_swap_buffers_with_damage") ||
check_egl_ext(egl->egl_exts_str, "EGL_KHR_swap_buffers_with_damage");
+ egl->egl_exts.dmabuf_import =
+ check_egl_ext(egl->egl_exts_str, "EGL_EXT_image_dma_buf_import");
+ egl->egl_exts.dmabuf_import_modifiers =
+ check_egl_ext(egl->egl_exts_str, "EGL_EXT_image_dma_buf_import_modifiers")
+ && eglQueryDmaBufFormatsEXT && eglQueryDmaBufModifiersEXT;
+ print_dmabuf_formats(egl);
+
return true;
error:
eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
- eglTerminate(egl->display);
+ if (egl->display) {
+ eglTerminate(egl->display);
+ }
eglReleaseThread();
return false;
}
void wlr_egl_finish(struct wlr_egl *egl) {
+ if (egl == NULL) {
+ return;
+ }
+
eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (egl->wl_display && eglUnbindWaylandDisplayWL) {
eglUnbindWaylandDisplayWL(egl->display, egl->wl_display);
@@ -231,7 +254,7 @@ EGLSurface wlr_egl_create_surface(struct wlr_egl *egl, void *window) {
EGLSurface surf = eglCreatePlatformWindowSurfaceEXT(egl->display, egl->config,
window, NULL);
if (surf == EGL_NO_SURFACE) {
- wlr_log(L_ERROR, "Failed to create EGL surface: %s", egl_error());
+ wlr_log(L_ERROR, "Failed to create EGL surface");
return EGL_NO_SURFACE;
}
return surf;
@@ -246,7 +269,7 @@ int wlr_egl_get_buffer_age(struct wlr_egl *egl, EGLSurface surface) {
EGLBoolean ok = eglQuerySurface(egl->display, surface,
EGL_BUFFER_AGE_EXT, &buffer_age);
if (!ok) {
- wlr_log(L_ERROR, "Failed to get EGL surface buffer age: %s", egl_error());
+ wlr_log(L_ERROR, "Failed to get EGL surface buffer age");
return -1;
}
@@ -256,7 +279,7 @@ int wlr_egl_get_buffer_age(struct wlr_egl *egl, EGLSurface surface) {
bool wlr_egl_make_current(struct wlr_egl *egl, EGLSurface surface,
int *buffer_age) {
if (!eglMakeCurrent(egl->display, surface, surface, egl->context)) {
- wlr_log(L_ERROR, "eglMakeCurrent failed: %s", egl_error());
+ wlr_log(L_ERROR, "eglMakeCurrent failed");
return false;
}
@@ -294,8 +317,137 @@ bool wlr_egl_swap_buffers(struct wlr_egl *egl, EGLSurface surface,
}
if (!ret) {
- wlr_log(L_ERROR, "eglSwapBuffers failed: %s", egl_error());
+ wlr_log(L_ERROR, "eglSwapBuffers failed");
return false;
}
return true;
}
+
+EGLImage wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl,
+ struct wlr_dmabuf_buffer_attribs *attributes) {
+ int atti = 0;
+ EGLint attribs[20];
+ attribs[atti++] = EGL_WIDTH;
+ attribs[atti++] = attributes->width;
+ attribs[atti++] = EGL_HEIGHT;
+ attribs[atti++] = attributes->height;
+ attribs[atti++] = EGL_LINUX_DRM_FOURCC_EXT;
+ attribs[atti++] = attributes->format;
+
+ bool has_modifier = false;
+ if (attributes->modifier[0] != DRM_FORMAT_MOD_INVALID) {
+ if (!egl->egl_exts.dmabuf_import_modifiers) {
+ return NULL;
+ }
+ has_modifier = true;
+ }
+
+ /* TODO: YUV planes have up four planes but we only support a
+ single EGLImage for now */
+ if (attributes->n_planes > 1) {
+ return NULL;
+ }
+
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_FD_EXT;
+ attribs[atti++] = attributes->fd[0];
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_OFFSET_EXT;
+ attribs[atti++] = attributes->offset[0];
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_PITCH_EXT;
+ attribs[atti++] = attributes->stride[0];
+ if (has_modifier) {
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_LO_EXT;
+ attribs[atti++] = attributes->modifier[0] & 0xFFFFFFFF;
+ attribs[atti++] = EGL_DMA_BUF_PLANE0_MODIFIER_HI_EXT;
+ attribs[atti++] = attributes->modifier[0] >> 32;
+ }
+ attribs[atti++] = EGL_NONE;
+ return eglCreateImageKHR(egl->display, EGL_NO_CONTEXT,
+ EGL_LINUX_DMA_BUF_EXT, NULL, attribs);
+}
+
+#ifndef DRM_FORMAT_BIG_ENDIAN
+# define DRM_FORMAT_BIG_ENDIAN 0x80000000
+#endif
+bool wlr_egl_check_import_dmabuf(struct wlr_egl *egl,
+ struct wlr_dmabuf_buffer *dmabuf) {
+ switch (dmabuf->attributes.format & ~DRM_FORMAT_BIG_ENDIAN) {
+ /* YUV based formats not yet supported */
+ case WL_SHM_FORMAT_YUYV:
+ case WL_SHM_FORMAT_YVYU:
+ case WL_SHM_FORMAT_UYVY:
+ case WL_SHM_FORMAT_VYUY:
+ case WL_SHM_FORMAT_AYUV:
+ return false;
+ default:
+ break;
+ }
+
+ EGLImage egl_image = wlr_egl_create_image_from_dmabuf(egl,
+ &dmabuf->attributes);
+ if (egl_image) {
+ /* We can import the image, good. No need to keep it
+ since wlr_texture_upload_dmabuf will import it again */
+ wlr_egl_destroy_image(egl, egl_image);
+ return true;
+ }
+ /* TODO: import yuv dmabufs */
+ return false;
+}
+
+int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl,
+ int **formats) {
+ if (!egl->egl_exts.dmabuf_import ||
+ !egl->egl_exts.dmabuf_import_modifiers) {
+ wlr_log(L_ERROR, "dmabuf extension not present");
+ return -1;
+ }
+
+ EGLint num;
+ if (!eglQueryDmaBufFormatsEXT(egl->display, 0, NULL, &num)) {
+ wlr_log(L_ERROR, "failed to query number of dmabuf formats");
+ return -1;
+ }
+
+ *formats = calloc(num, sizeof(int));
+ if (*formats == NULL) {
+ wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
+ return -1;
+ }
+
+ if (!eglQueryDmaBufFormatsEXT(egl->display, num, *formats, &num)) {
+ wlr_log(L_ERROR, "failed to query dmabuf format");
+ free(*formats);
+ return -1;
+ }
+ return num;
+}
+
+int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl,
+ int format, uint64_t **modifiers) {
+ if (!egl->egl_exts.dmabuf_import ||
+ !egl->egl_exts.dmabuf_import_modifiers) {
+ wlr_log(L_ERROR, "dmabuf extension not present");
+ return -1;
+ }
+
+ EGLint num;
+ if (!eglQueryDmaBufModifiersEXT(egl->display, format, 0,
+ NULL, NULL, &num)) {
+ wlr_log(L_ERROR, "failed to query dmabuf number of modifiers");
+ return -1;
+ }
+
+ *modifiers = calloc(num, sizeof(uint64_t));
+ if (*modifiers == NULL) {
+ wlr_log(L_ERROR, "Allocation failed: %s", strerror(errno));
+ return -1;
+ }
+
+ if (!eglQueryDmaBufModifiersEXT(egl->display, format, num,
+ *modifiers, NULL, &num)) {
+ wlr_log(L_ERROR, "failed to query dmabuf modifiers");
+ free(*modifiers);
+ return -1;
+ }
+ return num;
+}
diff --git a/render/glapi.txt b/render/glapi.txt
index 0b0b452c..a8e4aaba 100644
--- a/render/glapi.txt
+++ b/render/glapi.txt
@@ -8,3 +8,10 @@ eglCreatePlatformWindowSurfaceEXT
-glEGLImageTargetTexture2DOES
-eglSwapBuffersWithDamageEXT
-eglSwapBuffersWithDamageKHR
+-eglQueryDmaBufFormatsEXT
+-eglQueryDmaBufModifiersEXT
+-eglDebugMessageControlKHR
+-glDebugMessageCallbackKHR
+-glDebugMessageControlKHR
+-glPopDebugGroupKHR
+-glPushDebugGroupKHR
diff --git a/render/gles2/pixel_format.c b/render/gles2/pixel_format.c
index a544077b..89ba762f 100644
--- a/render/gles2/pixel_format.c
+++ b/render/gles2/pixel_format.c
@@ -6,14 +6,14 @@
* The wayland formats are little endian while the GL formats are big endian,
* so WL_SHM_FORMAT_ARGB8888 is actually compatible with GL_BGRA_EXT.
*/
-struct pixel_format formats[] = {
+static const struct gles2_pixel_format formats[] = {
{
.wl_format = WL_SHM_FORMAT_ARGB8888,
.depth = 32,
.bpp = 32,
.gl_format = GL_BGRA_EXT,
.gl_type = GL_UNSIGNED_BYTE,
- .shader = &shaders.rgba
+ .has_alpha = true,
},
{
.wl_format = WL_SHM_FORMAT_XRGB8888,
@@ -21,7 +21,7 @@ struct pixel_format formats[] = {
.bpp = 32,
.gl_format = GL_BGRA_EXT,
.gl_type = GL_UNSIGNED_BYTE,
- .shader = &shaders.rgbx
+ .has_alpha = false,
},
{
.wl_format = WL_SHM_FORMAT_XBGR8888,
@@ -29,7 +29,7 @@ struct pixel_format formats[] = {
.bpp = 32,
.gl_format = GL_RGBA,
.gl_type = GL_UNSIGNED_BYTE,
- .shader = &shaders.rgbx
+ .has_alpha = false,
},
{
.wl_format = WL_SHM_FORMAT_ABGR8888,
@@ -37,12 +37,20 @@ struct pixel_format formats[] = {
.bpp = 32,
.gl_format = GL_RGBA,
.gl_type = GL_UNSIGNED_BYTE,
- .shader = &shaders.rgba
+ .has_alpha = true,
},
};
+
+static const enum wl_shm_format wl_formats[] = {
+ WL_SHM_FORMAT_ARGB8888,
+ WL_SHM_FORMAT_XRGB8888,
+ WL_SHM_FORMAT_ABGR8888,
+ WL_SHM_FORMAT_XBGR8888,
+};
+
// TODO: more pixel formats
-const struct pixel_format *gl_format_for_wl_format(enum wl_shm_format fmt) {
+const struct gles2_pixel_format *gles2_format_from_wl(enum wl_shm_format fmt) {
for (size_t i = 0; i < sizeof(formats) / sizeof(*formats); ++i) {
if (formats[i].wl_format == fmt) {
return &formats[i];
@@ -50,3 +58,8 @@ const struct pixel_format *gl_format_for_wl_format(enum wl_shm_format fmt) {
}
return NULL;
}
+
+const enum wl_shm_format *gles2_formats(size_t *len) {
+ *len = sizeof(wl_formats) / sizeof(wl_formats[0]);
+ return wl_formats;
+}
diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c
index ad739cf8..9403c0ed 100644
--- a/render/gles2/renderer.c
+++ b/render/gles2/renderer.c
@@ -2,143 +2,80 @@
#include <GLES2/gl2.h>
#include <GLES2/gl2ext.h>
#include <stdint.h>
+#include <stdio.h>
#include <stdlib.h>
#include <wayland-server-protocol.h>
#include <wayland-util.h>
#include <wlr/backend.h>
-#include <wlr/render.h>
#include <wlr/render/egl.h>
#include <wlr/render/interface.h>
-#include <wlr/render/matrix.h>
+#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/util/log.h>
#include "render/gles2.h"
#include "glapi.h"
-struct shaders shaders;
-
-static bool compile_shader(GLuint type, const GLchar *src, GLuint *shader) {
- *shader = GL_CALL(glCreateShader(type));
- int len = strlen(src);
- GL_CALL(glShaderSource(*shader, 1, &src, &len));
- GL_CALL(glCompileShader(*shader));
- GLint success;
- GL_CALL(glGetShaderiv(*shader, GL_COMPILE_STATUS, &success));
- if (success == GL_FALSE) {
- GLint loglen;
- GL_CALL(glGetShaderiv(*shader, GL_INFO_LOG_LENGTH, &loglen));
- GLchar msg[loglen];
- GL_CALL(glGetShaderInfoLog(*shader, loglen, &loglen, msg));
- wlr_log(L_ERROR, "Shader compilation failed");
- wlr_log(L_ERROR, "%s", msg);
- glDeleteShader(*shader);
- return false;
- }
- return true;
-}
+static const struct wlr_renderer_impl renderer_impl;
-static bool compile_program(const GLchar *vert_src,
- const GLchar *frag_src, GLuint *program) {
- GLuint vertex, fragment;
- if (!compile_shader(GL_VERTEX_SHADER, vert_src, &vertex)) {
- return false;
- }
- if (!compile_shader(GL_FRAGMENT_SHADER, frag_src, &fragment)) {
- glDeleteShader(vertex);
- return false;
- }
- *program = GL_CALL(glCreateProgram());
- GL_CALL(glAttachShader(*program, vertex));
- GL_CALL(glAttachShader(*program, fragment));
- GL_CALL(glLinkProgram(*program));
- GLint success;
- GL_CALL(glGetProgramiv(*program, GL_LINK_STATUS, &success));
- if (success == GL_FALSE) {
- GLint loglen;
- GL_CALL(glGetProgramiv(*program, GL_INFO_LOG_LENGTH, &loglen));
- GLchar msg[loglen];
- GL_CALL(glGetProgramInfoLog(*program, loglen, &loglen, msg));
- wlr_log(L_ERROR, "Program link failed");
- wlr_log(L_ERROR, "%s", msg);
- glDeleteProgram(*program);
- glDeleteShader(vertex);
- glDeleteShader(fragment);
- return false;
- }
- glDetachShader(*program, vertex);
- glDetachShader(*program, fragment);
- glDeleteShader(vertex);
- glDeleteShader(fragment);
-
- return true;
+static struct wlr_gles2_renderer *gles2_get_renderer(
+ struct wlr_renderer *wlr_renderer) {
+ assert(wlr_renderer->impl == &renderer_impl);
+ struct wlr_gles2_renderer *renderer =
+ (struct wlr_gles2_renderer *)wlr_renderer;
+ assert(eglGetCurrentContext() == renderer->egl->context);
+ return renderer;
}
-static void init_default_shaders() {
- if (shaders.initialized) {
- return;
- }
- if (!compile_program(vertex_src, fragment_src_rgba, &shaders.rgba)) {
- goto error;
- }
- if (!compile_program(vertex_src, fragment_src_rgbx, &shaders.rgbx)) {
- goto error;
- }
- if (!compile_program(quad_vertex_src, quad_fragment_src, &shaders.quad)) {
- goto error;
- }
- if (!compile_program(quad_vertex_src, ellipse_fragment_src, &shaders.ellipse)) {
- goto error;
- }
- if (glEGLImageTargetTexture2DOES) {
- if (!compile_program(quad_vertex_src, fragment_src_external, &shaders.external)) {
- goto error;
- }
- }
+static void gles2_begin(struct wlr_renderer *wlr_renderer, uint32_t width,
+ uint32_t height) {
+ gles2_get_renderer(wlr_renderer);
- wlr_log(L_DEBUG, "Compiled default shaders");
- shaders.initialized = true;
- return;
-error:
- wlr_log(L_ERROR, "Failed to set up default shaders!");
-}
-
-static void init_globals() {
- init_default_shaders();
-}
+ GLES2_DEBUG_PUSH;
-static void wlr_gles2_begin(struct wlr_renderer *wlr_renderer,
- struct wlr_output *output) {
- GL_CALL(glViewport(0, 0, output->width, output->height));
+ glViewport(0, 0, width, height);
// enable transparency
- GL_CALL(glEnable(GL_BLEND));
- GL_CALL(glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA));
+ glEnable(GL_BLEND);
+ glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
- // Note: maybe we should save output projection and remove some of the need
+ // XXX: maybe we should save output projection and remove some of the need
// for users to sling matricies themselves
+
+ GLES2_DEBUG_POP;
}
-static void wlr_gles2_end(struct wlr_renderer *wlr_renderer) {
+static void gles2_end(struct wlr_renderer *wlr_renderer) {
+ gles2_get_renderer(wlr_renderer);
// no-op
}
-static void wlr_gles2_clear(struct wlr_renderer *wlr_renderer,
- const float (*color)[4]) {
- glClearColor((*color)[0], (*color)[1], (*color)[2], (*color)[3]);
+static void gles2_clear(struct wlr_renderer *wlr_renderer,
+ const float color[static 4]) {
+ gles2_get_renderer(wlr_renderer);
+
+ GLES2_DEBUG_PUSH;
+ glClearColor(color[0], color[1], color[2], color[3]);
glClear(GL_COLOR_BUFFER_BIT);
+ GLES2_DEBUG_POP;
}
-static void wlr_gles2_scissor(struct wlr_renderer *wlr_renderer,
+static void gles2_scissor(struct wlr_renderer *wlr_renderer,
struct wlr_box *box) {
+ gles2_get_renderer(wlr_renderer);
+
+ GLES2_DEBUG_PUSH;
if (box != NULL) {
glScissor(box->x, box->y, box->width, box->height);
glEnable(GL_SCISSOR_TEST);
} else {
glDisable(GL_SCISSOR_TEST);
}
+ GLES2_DEBUG_POP;
}
-static struct wlr_texture *wlr_gles2_texture_create(
+static struct wlr_texture *gles2_renderer_texture_create(
struct wlr_renderer *wlr_renderer) {
+ assert(wlr_renderer->impl == &renderer_impl);
struct wlr_gles2_renderer *renderer =
(struct wlr_gles2_renderer *)wlr_renderer;
return gles2_texture_create(renderer->egl);
@@ -158,80 +95,117 @@ static void draw_quad() {
0, 1, // bottom left
};
- GL_CALL(glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts));
- GL_CALL(glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord));
+ glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, verts);
+ glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, texcoord);
- GL_CALL(glEnableVertexAttribArray(0));
- GL_CALL(glEnableVertexAttribArray(1));
+ glEnableVertexAttribArray(0);
+ glEnableVertexAttribArray(1);
- GL_CALL(glDrawArrays(GL_TRIANGLE_STRIP, 0, 4));
+ glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- GL_CALL(glDisableVertexAttribArray(0));
- GL_CALL(glDisableVertexAttribArray(1));
+ glDisableVertexAttribArray(0);
+ glDisableVertexAttribArray(1);
}
-static bool wlr_gles2_render_texture(struct wlr_renderer *wlr_renderer,
- struct wlr_texture *texture, const float (*matrix)[16], float alpha) {
- if (!texture || !texture->valid) {
+static bool gles2_render_texture_with_matrix(
+ struct wlr_renderer *wlr_renderer, struct wlr_texture *wlr_texture,
+ const float matrix[static 9], float alpha) {
+ struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);
+ struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
+ if (!wlr_texture->valid) {
wlr_log(L_ERROR, "attempt to render invalid texture");
return false;
}
- wlr_texture_bind(texture);
- GL_CALL(glUniformMatrix4fv(0, 1, GL_FALSE, *matrix));
- GL_CALL(glUniform1f(2, alpha));
+ GLuint prog = renderer->shaders.tex_rgba;
+ if (texture->target == GL_TEXTURE_EXTERNAL_OES) {
+ prog = renderer->shaders.tex_ext;
+ } else if (!texture->pixel_format->has_alpha) {
+ prog = renderer->shaders.tex_rgbx;
+ }
+
+ // OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set
+ // to GL_FALSE
+ float transposition[9];
+ wlr_matrix_transpose(transposition, matrix);
+
+ GLES2_DEBUG_PUSH;
+ glBindTexture(texture->target, texture->tex_id);
+ glTexParameteri(texture->target, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
+ glTexParameteri(texture->target, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+ glUseProgram(prog);
+
+ glUniformMatrix3fv(0, 1, GL_FALSE, transposition);
+ glUniform1i(1, wlr_texture->inverted_y);
+ glUniform1f(3, alpha);
draw_quad();
+ GLES2_DEBUG_POP;
return true;
}
-static void wlr_gles2_render_quad(struct wlr_renderer *wlr_renderer,
- const float (*color)[4], const float (*matrix)[16]) {
- GL_CALL(glUseProgram(shaders.quad));
- GL_CALL(glUniformMatrix4fv(0, 1, GL_FALSE, *matrix));
- GL_CALL(glUniform4f(1, (*color)[0], (*color)[1], (*color)[2], (*color)[3]));
+static void gles2_render_quad(struct wlr_renderer *wlr_renderer,
+ const float color[static 4], const float matrix[static 9]) {
+ struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);
+
+ // OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set
+ // to GL_FALSE
+ float transposition[9];
+ wlr_matrix_transpose(transposition, matrix);
+
+ GLES2_DEBUG_PUSH;
+ glUseProgram(renderer->shaders.quad);
+ glUniformMatrix3fv(0, 1, GL_FALSE, transposition);
+ glUniform4f(1, color[0], color[1], color[2], color[3]);
draw_quad();
+ GLES2_DEBUG_POP;
}
-static void wlr_gles2_render_ellipse(struct wlr_renderer *wlr_renderer,
- const float (*color)[4], const float (*matrix)[16]) {
- GL_CALL(glUseProgram(shaders.ellipse));
- GL_CALL(glUniformMatrix4fv(0, 1, GL_TRUE, *matrix));
- GL_CALL(glUniform4f(1, (*color)[0], (*color)[1], (*color)[2], (*color)[3]));
+static void gles2_render_ellipse(struct wlr_renderer *wlr_renderer,
+ const float color[static 4], const float matrix[static 9]) {
+ struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);
+
+ // OpenGL ES 2 requires the glUniformMatrix3fv transpose parameter to be set
+ // to GL_FALSE
+ float transposition[9];
+ wlr_matrix_transpose(transposition, matrix);
+
+ GLES2_DEBUG_PUSH;
+ glUseProgram(renderer->shaders.ellipse);
+ glUniformMatrix3fv(0, 1, GL_FALSE, transposition);
+ glUniform4f(1, color[0], color[1], color[2], color[3]);
draw_quad();
+ GLES2_DEBUG_POP;
}
-static const enum wl_shm_format *wlr_gles2_formats(
- struct wlr_renderer *renderer, size_t *len) {
- static enum wl_shm_format formats[] = {
- WL_SHM_FORMAT_ARGB8888,
- WL_SHM_FORMAT_XRGB8888,
- WL_SHM_FORMAT_ABGR8888,
- WL_SHM_FORMAT_XBGR8888,
- };
- *len = sizeof(formats) / sizeof(formats[0]);
- return formats;
+static const enum wl_shm_format *gles2_renderer_formats(
+ struct wlr_renderer *wlr_renderer, size_t *len) {
+ return gles2_formats(len);
}
-static bool wlr_gles2_buffer_is_drm(struct wlr_renderer *wlr_renderer,
+static bool gles2_buffer_is_drm(struct wlr_renderer *wlr_renderer,
struct wl_resource *buffer) {
- struct wlr_gles2_renderer *renderer =
- (struct wlr_gles2_renderer *)wlr_renderer;
+ struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);
+
EGLint format;
- return wlr_egl_query_buffer(renderer->egl, buffer,
- EGL_TEXTURE_FORMAT, &format);
+ return wlr_egl_query_buffer(renderer->egl, buffer, EGL_TEXTURE_FORMAT,
+ &format);
}
-static bool wlr_gles2_read_pixels(struct wlr_renderer *renderer,
+static bool gles2_read_pixels(struct wlr_renderer *wlr_renderer,
enum wl_shm_format wl_fmt, uint32_t stride, uint32_t width,
uint32_t height, uint32_t src_x, uint32_t src_y, uint32_t dst_x,
uint32_t dst_y, void *data) {
- const struct pixel_format *fmt = gl_format_for_wl_format(wl_fmt);
+ gles2_get_renderer(wlr_renderer);
+
+ const struct gles2_pixel_format *fmt = gles2_format_from_wl(wl_fmt);
if (fmt == NULL) {
wlr_log(L_ERROR, "Cannot read pixels: unsupported pixel format");
return false;
}
+ GLES2_DEBUG_PUSH;
+
// Make sure any pending drawing is finished before we try to read it
glFinish();
@@ -243,38 +217,225 @@ static bool wlr_gles2_read_pixels(struct wlr_renderer *renderer,
fmt->gl_type, p + i * stride + dst_x * fmt->bpp / 8);
}
+ GLES2_DEBUG_POP;
+
return true;
}
-static bool wlr_gles2_format_supported(struct wlr_renderer *r,
+static bool gles2_format_supported(struct wlr_renderer *r,
enum wl_shm_format wl_fmt) {
- return gl_format_for_wl_format(wl_fmt);
+ return gles2_format_from_wl(wl_fmt) != NULL;
+}
+
+static void gles2_destroy(struct wlr_renderer *wlr_renderer) {
+ struct wlr_gles2_renderer *renderer = gles2_get_renderer(wlr_renderer);
+
+ wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL);
+
+ GLES2_DEBUG_PUSH;
+ glDeleteProgram(renderer->shaders.quad);
+ glDeleteProgram(renderer->shaders.ellipse);
+ glDeleteProgram(renderer->shaders.tex_rgba);
+ glDeleteProgram(renderer->shaders.tex_rgbx);
+ glDeleteProgram(renderer->shaders.tex_ext);
+ GLES2_DEBUG_POP;
+
+ if (glDebugMessageCallbackKHR) {
+ glDisable(GL_DEBUG_OUTPUT_KHR);
+ glDebugMessageCallbackKHR(NULL, NULL);
+ }
+
+ free(renderer);
}
-static struct wlr_renderer_impl wlr_renderer_impl = {
- .begin = wlr_gles2_begin,
- .end = wlr_gles2_end,
- .clear = wlr_gles2_clear,
- .scissor = wlr_gles2_scissor,
- .texture_create = wlr_gles2_texture_create,
- .render_with_matrix = wlr_gles2_render_texture,
- .render_quad = wlr_gles2_render_quad,
- .render_ellipse = wlr_gles2_render_ellipse,
- .formats = wlr_gles2_formats,
- .buffer_is_drm = wlr_gles2_buffer_is_drm,
- .read_pixels = wlr_gles2_read_pixels,
- .format_supported = wlr_gles2_format_supported,
+static const struct wlr_renderer_impl renderer_impl = {
+ .destroy = gles2_destroy,
+ .begin = gles2_begin,
+ .end = gles2_end,
+ .clear = gles2_clear,
+ .scissor = gles2_scissor,
+ .texture_create = gles2_renderer_texture_create,
+ .render_texture_with_matrix = gles2_render_texture_with_matrix,
+ .render_quad = gles2_render_quad,
+ .render_ellipse = gles2_render_ellipse,
+ .formats = gles2_renderer_formats,
+ .buffer_is_drm = gles2_buffer_is_drm,
+ .read_pixels = gles2_read_pixels,
+ .format_supported = gles2_format_supported,
};
+void gles2_push_marker(const char *file, const char *func) {
+ if (!glPushDebugGroupKHR) {
+ return;
+ }
+
+ int len = snprintf(NULL, 0, "%s:%s", file, func) + 1;
+ char str[len];
+ snprintf(str, len, "%s:%s", file, func);
+ glPushDebugGroupKHR(GL_DEBUG_SOURCE_APPLICATION_KHR, 1, -1, str);
+}
+
+void gles2_pop_marker(void) {
+ if (glPopDebugGroupKHR) {
+ glPopDebugGroupKHR();
+ }
+}
+
+static log_importance_t gles2_log_importance_to_wlr(GLenum type) {
+ switch (type) {
+ case GL_DEBUG_TYPE_ERROR_KHR: return L_ERROR;
+ case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR: return L_DEBUG;
+ case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR: return L_ERROR;
+ case GL_DEBUG_TYPE_PORTABILITY_KHR: return L_DEBUG;
+ case GL_DEBUG_TYPE_PERFORMANCE_KHR: return L_DEBUG;
+ case GL_DEBUG_TYPE_OTHER_KHR: return L_INFO;
+ case GL_DEBUG_TYPE_MARKER_KHR: return L_DEBUG;
+ case GL_DEBUG_TYPE_PUSH_GROUP_KHR: return L_DEBUG;
+ case GL_DEBUG_TYPE_POP_GROUP_KHR: return L_DEBUG;
+ default: return L_INFO;
+ }
+}
+
+static void gles2_log(GLenum src, GLenum type, GLuint id, GLenum severity,
+ GLsizei len, const GLchar *msg, const void *user) {
+ _wlr_log(gles2_log_importance_to_wlr(type), "[GLES2] %s", msg);
+}
+
+static GLuint compile_shader(GLuint type, const GLchar *src) {
+ GLES2_DEBUG_PUSH;
+
+ GLuint shader = glCreateShader(type);
+ glShaderSource(shader, 1, &src, NULL);
+ glCompileShader(shader);
+
+ GLint ok;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &ok);
+ if (ok == GL_FALSE) {
+ glDeleteShader(shader);
+ shader = 0;
+ }
+
+ GLES2_DEBUG_POP;
+ return shader;
+}
+
+static GLuint link_program(const GLchar *vert_src, const GLchar *frag_src) {
+ GLES2_DEBUG_PUSH;
+
+ GLuint vert = compile_shader(GL_VERTEX_SHADER, vert_src);
+ if (!vert) {
+ goto error;
+ }
+
+ GLuint frag = compile_shader(GL_FRAGMENT_SHADER, frag_src);
+ if (!frag) {
+ glDeleteShader(vert);
+ goto error;
+ }
+
+ GLuint prog = glCreateProgram();
+ glAttachShader(prog, vert);
+ glAttachShader(prog, frag);
+ glLinkProgram(prog);
+
+ glDetachShader(prog, vert);
+ glDetachShader(prog, frag);
+ glDeleteShader(vert);
+ glDeleteShader(frag);
+
+ GLint ok;
+ glGetProgramiv(prog, GL_LINK_STATUS, &ok);
+ if (ok == GL_FALSE) {
+ glDeleteProgram(prog);
+ goto error;
+ }
+
+ GLES2_DEBUG_POP;
+ return prog;
+
+error:
+ GLES2_DEBUG_POP;
+ return 0;
+}
+
+extern const GLchar quad_vertex_src[];
+extern const GLchar quad_fragment_src[];
+extern const GLchar ellipse_fragment_src[];
+extern const GLchar tex_vertex_src[];
+extern const GLchar tex_fragment_src_rgba[];
+extern const GLchar tex_fragment_src_rgbx[];
+extern const GLchar tex_fragment_src_external[];
+
struct wlr_renderer *wlr_gles2_renderer_create(struct wlr_backend *backend) {
- init_globals();
- struct wlr_gles2_renderer *renderer;
- if (!(renderer = calloc(1, sizeof(struct wlr_gles2_renderer)))) {
+ struct wlr_gles2_renderer *renderer =
+ calloc(1, sizeof(struct wlr_gles2_renderer));
+ if (renderer == NULL) {
return NULL;
}
- wlr_renderer_init(&renderer->wlr_renderer, &wlr_renderer_impl);
+ wlr_renderer_init(&renderer->wlr_renderer, &renderer_impl);
renderer->egl = wlr_backend_get_egl(backend);
+ wlr_egl_make_current(renderer->egl, EGL_NO_SURFACE, NULL);
+
+ if (glDebugMessageCallbackKHR && glDebugMessageControlKHR) {
+ glEnable(GL_DEBUG_OUTPUT_KHR);
+ glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR);
+ glDebugMessageCallbackKHR(gles2_log, NULL);
+
+ // Silence unwanted message types
+ glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_POP_GROUP_KHR,
+ GL_DONT_CARE, 0, NULL, GL_FALSE);
+ glDebugMessageControlKHR(GL_DONT_CARE, GL_DEBUG_TYPE_PUSH_GROUP_KHR,
+ GL_DONT_CARE, 0, NULL, GL_FALSE);
+ }
+
+ GLES2_DEBUG_PUSH;
+
+ renderer->shaders.quad = link_program(quad_vertex_src, quad_fragment_src);
+ if (!renderer->shaders.quad) {
+ goto error;
+ }
+ renderer->shaders.ellipse =
+ link_program(quad_vertex_src, ellipse_fragment_src);
+ if (!renderer->shaders.ellipse) {
+ goto error;
+ }
+ renderer->shaders.tex_rgba =
+ link_program(tex_vertex_src, tex_fragment_src_rgba);
+ if (!renderer->shaders.tex_rgba) {
+ goto error;
+ }
+ renderer->shaders.tex_rgbx =
+ link_program(tex_vertex_src, tex_fragment_src_rgbx);
+ if (!renderer->shaders.tex_rgbx) {
+ goto error;
+ }
+ if (glEGLImageTargetTexture2DOES) {
+ renderer->shaders.tex_ext =
+ link_program(tex_vertex_src, tex_fragment_src_external);
+ if (!renderer->shaders.tex_ext) {
+ goto error;
+ }
+ }
+
+ GLES2_DEBUG_POP;
return &renderer->wlr_renderer;
+
+error:
+ glDeleteProgram(renderer->shaders.quad);
+ glDeleteProgram(renderer->shaders.ellipse);
+ glDeleteProgram(renderer->shaders.tex_rgba);
+ glDeleteProgram(renderer->shaders.tex_rgbx);
+ glDeleteProgram(renderer->shaders.tex_ext);
+
+ GLES2_DEBUG_POP;
+
+ if (glDebugMessageCallbackKHR) {
+ glDisable(GL_DEBUG_OUTPUT_KHR);
+ glDebugMessageCallbackKHR(NULL, NULL);
+ }
+
+ free(renderer);
+ return NULL;
}
diff --git a/render/gles2/shaders.c b/render/gles2/shaders.c
index 46a10248..ba3bd971 100644
--- a/render/gles2/shaders.c
+++ b/render/gles2/shaders.c
@@ -3,100 +3,88 @@
// Colored quads
const GLchar quad_vertex_src[] =
-"uniform mat4 proj;"
-"uniform vec4 color;"
-"attribute vec2 pos;"
-"attribute vec2 texcoord;"
-"varying vec4 v_color;"
-"varying vec2 v_texcoord;"
-"mat4 transpose(in mat4 inMatrix) {"
-" vec4 i0 = inMatrix[0];"
-" vec4 i1 = inMatrix[1];"
-" vec4 i2 = inMatrix[2];"
-" vec4 i3 = inMatrix[3];"
-" mat4 outMatrix = mat4("
-" vec4(i0.x, i1.x, i2.x, i3.x),"
-" vec4(i0.y, i1.y, i2.y, i3.y),"
-" vec4(i0.z, i1.z, i2.z, i3.z),"
-" vec4(i0.w, i1.w, i2.w, i3.w)"
-" );"
-" return outMatrix;"
-"}"
-"void main() {"
-" gl_Position = transpose(proj) * vec4(pos, 0.0, 1.0);"
-" v_color = color;"
-" v_texcoord = texcoord;"
-"}";
+"uniform mat3 proj;\n"
+"uniform vec4 color;\n"
+"attribute vec2 pos;\n"
+"attribute vec2 texcoord;\n"
+"varying vec4 v_color;\n"
+"varying vec2 v_texcoord;\n"
+"\n"
+"void main() {\n"
+" gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);\n"
+" v_color = color;\n"
+" v_texcoord = texcoord;\n"
+"}\n";
const GLchar quad_fragment_src[] =
-"precision mediump float;"
-"varying vec4 v_color;"
-"varying vec2 v_texcoord;"
-"void main() {"
-" gl_FragColor = v_color;"
-"}";
+"precision mediump float;\n"
+"varying vec4 v_color;\n"
+"varying vec2 v_texcoord;\n"
+"\n"
+"void main() {\n"
+" gl_FragColor = v_color;\n"
+"}\n";
// Colored ellipses
const GLchar ellipse_fragment_src[] =
-"precision mediump float;"
-"varying vec4 v_color;"
-"varying vec2 v_texcoord;"
-"void main() {"
-" float l = length(v_texcoord - vec2(0.5, 0.5));"
-" if (l > 0.5) discard;"
-" gl_FragColor = v_color;"
-"}";
+"precision mediump float;\n"
+"varying vec4 v_color;\n"
+"varying vec2 v_texcoord;\n"
+"\n"
+"void main() {\n"
+" float l = length(v_texcoord - vec2(0.5, 0.5));\n"
+" if (l > 0.5) {\n"
+" discard;\n"
+" }\n"
+" gl_FragColor = v_color;\n"
+"}\n";
// Textured quads
-const GLchar vertex_src[] =
-"uniform mat4 proj;"
-"attribute vec2 pos;"
-"attribute vec2 texcoord;"
-"varying vec2 v_texcoord;"
-"mat4 transpose(in mat4 inMatrix) {"
-" vec4 i0 = inMatrix[0];"
-" vec4 i1 = inMatrix[1];"
-" vec4 i2 = inMatrix[2];"
-" vec4 i3 = inMatrix[3];"
-" mat4 outMatrix = mat4("
-" vec4(i0.x, i1.x, i2.x, i3.x),"
-" vec4(i0.y, i1.y, i2.y, i3.y),"
-" vec4(i0.z, i1.z, i2.z, i3.z),"
-" vec4(i0.w, i1.w, i2.w, i3.w)"
-" );"
-""
-" return outMatrix;"
-"}"
-"void main() {"
-" gl_Position = transpose(proj) * vec4(pos, 0.0, 1.0);"
-" v_texcoord = texcoord;"
-"}";
+const GLchar tex_vertex_src[] =
+"uniform mat3 proj;\n"
+"uniform bool invert_y;\n"
+"attribute vec2 pos;\n"
+"attribute vec2 texcoord;\n"
+"varying vec2 v_texcoord;\n"
+"\n"
+"void main() {\n"
+" gl_Position = vec4(proj * vec3(pos, 1.0), 1.0);\n"
+" if (invert_y) {\n"
+" v_texcoord = vec2(texcoord.s, 1.0 - texcoord.t);\n"
+" } else {\n"
+" v_texcoord = texcoord;\n"
+" }\n"
+"}\n";
-const GLchar fragment_src_rgba[] =
-"precision mediump float;"
-"varying vec2 v_texcoord;"
-"uniform sampler2D tex;"
-"uniform float alpha;"
-"void main() {"
-" gl_FragColor = alpha * texture2D(tex, v_texcoord);"
-"}";
+const GLchar tex_fragment_src_rgba[] =
+"precision mediump float;\n"
+"varying vec2 v_texcoord;\n"
+"uniform sampler2D tex;\n"
+"uniform float alpha;\n"
+"\n"
+"void main() {\n"
+" gl_FragColor = alpha * texture2D(tex, v_texcoord);\n"
+"}\n";
-const GLchar fragment_src_rgbx[] =
-"precision mediump float;"
-"varying vec2 v_texcoord;"
-"uniform sampler2D tex;"
-"uniform float alpha;"
-"void main() {"
-" gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb;"
-" gl_FragColor.a = alpha;"
-"}";
+const GLchar tex_fragment_src_rgbx[] =
+"precision mediump float;\n"
+"varying vec2 v_texcoord;\n"
+"uniform sampler2D tex;\n"
+"uniform float alpha;\n"
+"\n"
+"void main() {\n"
+" gl_FragColor.rgb = alpha * texture2D(tex, v_texcoord).rgb;\n"
+" gl_FragColor.a = alpha;\n"
+"}\n";
-const GLchar fragment_src_external[] =
-"#extension GL_OES_EGL_image_external : require\n"
-"precision mediump float;"
-"varying vec2 v_texcoord;"
-"uniform samplerExternalOES texture0;"
-"void main() {"
-" vec4 col = texture2D(texture0, v_texcoord);"
-" gl_FragColor = vec4(col.rgb, col.a);"
-"}";
+const GLchar tex_fragment_src_external[] =
+"#extension GL_OES_EGL_image_external : require\n\n"
+"precision mediump float;\n"
+"varying vec2 v_texcoord;\n"
+"uniform samplerExternalOES texture0;\n"
+"uniform float alpha;\n"
+"\n"
+"void main() {\n"
+" vec4 col = texture2D(texture0, v_texcoord);\n"
+" gl_FragColor = vec4(col.rgb, col.a * alpha);\n"
+"}\n";
diff --git a/render/gles2/texture.c b/render/gles2/texture.c
index 241b94a8..766c0b15 100644
--- a/render/gles2/texture.c
+++ b/render/gles2/texture.c
@@ -5,39 +5,47 @@
#include <stdlib.h>
#include <wayland-server-protocol.h>
#include <wayland-util.h>
-#include <wlr/render.h>
+#include <wlr/render/wlr_texture.h>
#include <wlr/render/egl.h>
#include <wlr/render/interface.h>
-#include <wlr/render/matrix.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/util/log.h>
#include "render/gles2.h"
#include "util/signal.h"
-static struct pixel_format external_pixel_format = {
+static struct gles2_pixel_format external_pixel_format = {
.wl_format = 0,
.depth = 0,
.bpp = 0,
.gl_format = 0,
.gl_type = 0,
- .shader = &shaders.external
};
-static void gles2_texture_ensure_texture(struct wlr_gles2_texture *texture) {
+static void gles2_texture_ensure(struct wlr_gles2_texture *texture,
+ GLenum target) {
if (texture->tex_id) {
return;
}
- GL_CALL(glGenTextures(1, &texture->tex_id));
- GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id));
- GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE));
- GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE));
+ texture->target = target;
+ glGenTextures(1, &texture->tex_id);
+ glBindTexture(target, texture->tex_id);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
+ glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
}
-static bool gles2_texture_upload_pixels(struct wlr_texture *_texture,
+static const struct wlr_texture_impl texture_impl;
+
+struct wlr_gles2_texture *gles2_get_texture(struct wlr_texture *wlr_texture) {
+ assert(wlr_texture->impl == &texture_impl);
+ return (struct wlr_gles2_texture *)wlr_texture;
+}
+
+static bool gles2_texture_upload_pixels(struct wlr_texture *wlr_texture,
enum wl_shm_format format, int stride, int width, int height,
const unsigned char *pixels) {
- struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture;
- assert(texture);
- const struct pixel_format *fmt = gl_format_for_wl_format(format);
+ struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
+
+ const struct gles2_pixel_format *fmt = gles2_format_from_wl(format);
if (!fmt || !fmt->gl_format) {
wlr_log(L_ERROR, "No supported pixel format for this texture");
return false;
@@ -47,44 +55,50 @@ static bool gles2_texture_upload_pixels(struct wlr_texture *_texture,
texture->wlr_texture.format = format;
texture->pixel_format = fmt;
- gles2_texture_ensure_texture(texture);
- GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id));
- GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride));
- GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0,
- fmt->gl_format, fmt->gl_type, pixels));
+ GLES2_DEBUG_PUSH;
+ gles2_texture_ensure(texture, GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, texture->tex_id);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride);
+ glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0,
+ fmt->gl_format, fmt->gl_type, pixels);
+ GLES2_DEBUG_POP;
+
texture->wlr_texture.valid = true;
return true;
}
-static bool gles2_texture_update_pixels(struct wlr_texture *_texture,
+static bool gles2_texture_update_pixels(struct wlr_texture *wlr_texture,
enum wl_shm_format format, int stride, int x, int y,
int width, int height, const unsigned char *pixels) {
- struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture;
- assert(texture);
+ struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
+
// TODO: Test if the unpack subimage extension is supported and adjust the
// upload strategy if not
if (!texture->wlr_texture.valid
|| texture->wlr_texture.format != format
/* || unpack not supported */) {
- return gles2_texture_upload_pixels(&texture->wlr_texture,
- format, stride, width, height, pixels);
+ return gles2_texture_upload_pixels(&texture->wlr_texture, format,
+ stride, width, height, pixels);
}
- const struct pixel_format *fmt = texture->pixel_format;
- GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id));
- GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride));
- GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x));
- GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y));
- GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
- fmt->gl_format, fmt->gl_type, pixels));
- GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0));
- GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0));
+ const struct gles2_pixel_format *fmt = texture->pixel_format;
+ GLES2_DEBUG_PUSH;
+ glBindTexture(GL_TEXTURE_2D, texture->tex_id);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, stride);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height, fmt->gl_format,
+ fmt->gl_type, pixels);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
+ GLES2_DEBUG_POP;
return true;
}
-static bool gles2_texture_upload_shm(struct wlr_texture *_texture,
+static bool gles2_texture_upload_shm(struct wlr_texture *wlr_texture,
uint32_t format, struct wl_shm_buffer *buffer) {
- struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture;
- const struct pixel_format *fmt = gl_format_for_wl_format(format);
+ struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
+
+ const struct gles2_pixel_format *fmt = gles2_format_from_wl(format);
if (!fmt || !fmt->gl_format) {
wlr_log(L_ERROR, "Unsupported pixel format %"PRIu32" for this texture",
format);
@@ -100,23 +114,26 @@ static bool gles2_texture_upload_shm(struct wlr_texture *_texture,
texture->wlr_texture.format = format;
texture->pixel_format = fmt;
- gles2_texture_ensure_texture(texture);
- GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id));
- GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch));
- GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0));
- GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0));
- GL_CALL(glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0,
- fmt->gl_format, fmt->gl_type, pixels));
+ GLES2_DEBUG_PUSH;
+ gles2_texture_ensure(texture, GL_TEXTURE_2D);
+ glBindTexture(GL_TEXTURE_2D, texture->tex_id);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
+ glTexImage2D(GL_TEXTURE_2D, 0, fmt->gl_format, width, height, 0,
+ fmt->gl_format, fmt->gl_type, pixels);
+ GLES2_DEBUG_POP;
texture->wlr_texture.valid = true;
wl_shm_buffer_end_access(buffer);
return true;
}
-static bool gles2_texture_update_shm(struct wlr_texture *_texture,
+static bool gles2_texture_update_shm(struct wlr_texture *wlr_texture,
uint32_t format, int x, int y, int width, int height,
struct wl_shm_buffer *buffer) {
- struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture;
+ struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
+
// TODO: Test if the unpack subimage extension is supported and adjust the
// upload strategy if not
assert(texture);
@@ -125,28 +142,30 @@ static bool gles2_texture_update_shm(struct wlr_texture *_texture,
/* || unpack not supported */) {
return gles2_texture_upload_shm(&texture->wlr_texture, format, buffer);
}
- const struct pixel_format *fmt = texture->pixel_format;
+ const struct gles2_pixel_format *fmt = texture->pixel_format;
wl_shm_buffer_begin_access(buffer);
uint8_t *pixels = wl_shm_buffer_get_data(buffer);
int pitch = wl_shm_buffer_get_stride(buffer) / (fmt->bpp / 8);
- GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id));
- GL_CALL(glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch));
- GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x));
- GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y));
- GL_CALL(glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
- fmt->gl_format, fmt->gl_type, pixels));
- GL_CALL(glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0));
- GL_CALL(glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0));
+ GLES2_DEBUG_PUSH;
+ glBindTexture(GL_TEXTURE_2D, texture->tex_id);
+ glPixelStorei(GL_UNPACK_ROW_LENGTH_EXT, pitch);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, x);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, y);
+ glTexSubImage2D(GL_TEXTURE_2D, 0, x, y, width, height,
+ fmt->gl_format, fmt->gl_type, pixels);
+ glPixelStorei(GL_UNPACK_SKIP_PIXELS_EXT, 0);
+ glPixelStorei(GL_UNPACK_SKIP_ROWS_EXT, 0);
+ GLES2_DEBUG_POP;
wl_shm_buffer_end_access(buffer);
return true;
}
-static bool gles2_texture_upload_drm(struct wlr_texture *_tex,
+static bool gles2_texture_upload_drm(struct wlr_texture *wlr_texture,
struct wl_resource *buf) {
- struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)_tex;
+ struct wlr_gles2_texture *tex = gles2_get_texture(wlr_texture);
if (!glEGLImageTargetTexture2DOES) {
return false;
}
@@ -158,20 +177,23 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex,
}
wlr_egl_query_buffer(tex->egl, buf, EGL_WIDTH,
- (EGLint*)&tex->wlr_texture.width);
+ (EGLint*)&tex->wlr_texture.width);
wlr_egl_query_buffer(tex->egl, buf, EGL_HEIGHT,
- (EGLint*)&tex->wlr_texture.height);
+ (EGLint*)&tex->wlr_texture.height);
EGLint inverted_y;
- wlr_egl_query_buffer(tex->egl, buf, EGL_WAYLAND_Y_INVERTED_WL, &inverted_y);
+ if (wlr_egl_query_buffer(tex->egl, buf, EGL_WAYLAND_Y_INVERTED_WL,
+ &inverted_y)) {
+ tex->wlr_texture.inverted_y = !!inverted_y;
+ }
GLenum target;
- const struct pixel_format *pf;
+ const struct gles2_pixel_format *pf;
switch (format) {
case EGL_TEXTURE_RGB:
case EGL_TEXTURE_RGBA:
target = GL_TEXTURE_2D;
- pf = gl_format_for_wl_format(WL_SHM_FORMAT_ARGB8888);
+ pf = gles2_format_from_wl(WL_SHM_FORMAT_ARGB8888);
break;
case EGL_TEXTURE_EXTERNAL_WL:
target = GL_TEXTURE_EXTERNAL_OES;
@@ -182,8 +204,10 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex,
return false;
}
- gles2_texture_ensure_texture(tex);
- GL_CALL(glBindTexture(GL_TEXTURE_2D, tex->tex_id));
+ GLES2_DEBUG_PUSH;
+ gles2_texture_ensure(tex, target);
+ glBindTexture(GL_TEXTURE_2D, tex->tex_id);
+ GLES2_DEBUG_POP;
EGLint attribs[] = { EGL_WAYLAND_PLANE_WL, 0, EGL_NONE };
@@ -194,22 +218,24 @@ static bool gles2_texture_upload_drm(struct wlr_texture *_tex,
tex->image = wlr_egl_create_image(tex->egl, EGL_WAYLAND_BUFFER_WL,
(EGLClientBuffer*) buf, attribs);
if (!tex->image) {
- wlr_log(L_ERROR, "failed to create egl image: %s", egl_error());
+ wlr_log(L_ERROR, "failed to create EGL image");
return false;
}
- GL_CALL(glActiveTexture(GL_TEXTURE0));
- GL_CALL(glBindTexture(target, tex->tex_id));
- GL_CALL(glEGLImageTargetTexture2DOES(target, tex->image));
+ GLES2_DEBUG_PUSH;
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(target, tex->tex_id);
+ glEGLImageTargetTexture2DOES(target, tex->image);
+ GLES2_DEBUG_POP;
tex->wlr_texture.valid = true;
tex->pixel_format = pf;
return true;
}
-static bool gles2_texture_upload_eglimage(struct wlr_texture *wlr_tex,
+static bool gles2_texture_upload_eglimage(struct wlr_texture *wlr_texture,
EGLImageKHR image, uint32_t width, uint32_t height) {
- struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)wlr_tex;
+ struct wlr_gles2_texture *tex = gles2_get_texture(wlr_texture);
tex->image = image;
tex->pixel_format = &external_pixel_format;
@@ -217,30 +243,68 @@ static bool gles2_texture_upload_eglimage(struct wlr_texture *wlr_tex,
tex->wlr_texture.width = width;
tex->wlr_texture.height = height;
- gles2_texture_ensure_texture(tex);
-
- GL_CALL(glActiveTexture(GL_TEXTURE0));
- GL_CALL(glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex->tex_id));
- GL_CALL(glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, tex->image));
+ GLES2_DEBUG_PUSH;
+ gles2_texture_ensure(tex, GL_TEXTURE_2D);
+ glActiveTexture(GL_TEXTURE0);
+ glBindTexture(GL_TEXTURE_EXTERNAL_OES, tex->tex_id);
+ glEGLImageTargetTexture2DOES(GL_TEXTURE_EXTERNAL_OES, tex->image);
+ GLES2_DEBUG_POP;
return true;
}
-static void gles2_texture_get_matrix(struct wlr_texture *_texture,
- float (*matrix)[16], const float (*projection)[16], int x, int y) {
- struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture;
- float world[16];
- wlr_matrix_identity(matrix);
- wlr_matrix_translate(&world, x, y, 0);
- wlr_matrix_mul(matrix, &world, matrix);
- wlr_matrix_scale(&world,
- texture->wlr_texture.width, texture->wlr_texture.height, 1);
- wlr_matrix_mul(matrix, &world, matrix);
- wlr_matrix_mul(projection, matrix, matrix);
+static bool gles2_texture_upload_dmabuf(struct wlr_texture *wlr_texture,
+ struct wl_resource *dmabuf_resource) {
+ struct wlr_gles2_texture *tex = gles2_get_texture(wlr_texture);
+ struct wlr_dmabuf_buffer *dmabuf =
+ wlr_dmabuf_buffer_from_buffer_resource(dmabuf_resource);
+
+ if (!tex->egl->egl_exts.dmabuf_import) {
+ wlr_log(L_ERROR, "Want dmabuf but extension not present");
+ return false;
+ }
+
+ tex->wlr_texture.width = dmabuf->attributes.width;
+ tex->wlr_texture.height = dmabuf->attributes.height;
+
+ if (tex->image) {
+ wlr_egl_destroy_image(tex->egl, tex->image);
+ }
+
+ if (wlr_dmabuf_buffer_has_inverted_y(dmabuf)) {
+ wlr_texture->inverted_y = true;
+ }
+
+ GLenum target = GL_TEXTURE_2D;
+ const struct gles2_pixel_format *pf =
+ gles2_format_from_wl(WL_SHM_FORMAT_ARGB8888);
+ GLES2_DEBUG_PUSH;
+ gles2_texture_ensure(tex, target);
+ glBindTexture(target, tex->tex_id);
+ tex->image = wlr_egl_create_image_from_dmabuf(tex->egl, &dmabuf->attributes);
+ glActiveTexture(GL_TEXTURE0);
+ glEGLImageTargetTexture2DOES(target, tex->image);
+ GLES2_DEBUG_POP;
+ tex->pixel_format = pf;
+ tex->wlr_texture.valid = true;
+ return true;
}
-static void gles2_texture_get_buffer_size(struct wlr_texture *texture, struct
+static bool gles2_texture_get_dmabuf_size(struct wlr_texture *texture, struct
wl_resource *resource, int *width, int *height) {
+ if (!wlr_dmabuf_resource_is_buffer(resource)) {
+ return false;
+ }
+
+ struct wlr_dmabuf_buffer *dmabuf =
+ wlr_dmabuf_buffer_from_buffer_resource(resource);
+ *width = dmabuf->attributes.width;
+ *height = dmabuf->attributes.height;
+ return true;
+}
+
+static void gles2_texture_get_buffer_size(struct wlr_texture *texture,
+ struct wl_resource *resource, int *width, int *height) {
struct wl_shm_buffer *buffer = wl_shm_buffer_get(resource);
if (!buffer) {
struct wlr_gles2_texture *tex = (struct wlr_gles2_texture *)texture;
@@ -249,12 +313,13 @@ static void gles2_texture_get_buffer_size(struct wlr_texture *texture, struct
}
if (!wlr_egl_query_buffer(tex->egl, resource, EGL_WIDTH,
(EGLint*)width)) {
- wlr_log(L_ERROR, "could not get size of the buffer "
- "(no buffer found)");
- return;
- };
- wlr_egl_query_buffer(tex->egl, resource, EGL_HEIGHT,
- (EGLint*)height);
+ if (!gles2_texture_get_dmabuf_size(texture, resource, width,
+ height)) {
+ wlr_log(L_ERROR, "could not get size of the buffer");
+ return;
+ }
+ }
+ wlr_egl_query_buffer(tex->egl, resource, EGL_HEIGHT, (EGLint*)height);
return;
}
@@ -263,19 +328,15 @@ static void gles2_texture_get_buffer_size(struct wlr_texture *texture, struct
*height = wl_shm_buffer_get_height(buffer);
}
-static void gles2_texture_bind(struct wlr_texture *_texture) {
- struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture;
- GL_CALL(glBindTexture(GL_TEXTURE_2D, texture->tex_id));
- GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR));
- GL_CALL(glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR));
- GL_CALL(glUseProgram(*texture->pixel_format->shader));
-}
+static void gles2_texture_destroy(struct wlr_texture *wlr_texture) {
+ struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture);
-static void gles2_texture_destroy(struct wlr_texture *_texture) {
- struct wlr_gles2_texture *texture = (struct wlr_gles2_texture *)_texture;
- wlr_signal_emit_safe(&texture->wlr_texture.destroy_signal, &texture->wlr_texture);
+ wlr_signal_emit_safe(&texture->wlr_texture.destroy_signal,
+ &texture->wlr_texture);
if (texture->tex_id) {
- GL_CALL(glDeleteTextures(1, &texture->tex_id));
+ GLES2_DEBUG_PUSH;
+ glDeleteTextures(1, &texture->tex_id);
+ GLES2_DEBUG_POP;
}
if (texture->image) {
@@ -285,16 +346,15 @@ static void gles2_texture_destroy(struct wlr_texture *_texture) {
free(texture);
}
-static struct wlr_texture_impl wlr_texture_impl = {
+static const struct wlr_texture_impl texture_impl = {
.upload_pixels = gles2_texture_upload_pixels,
.update_pixels = gles2_texture_update_pixels,
.upload_shm = gles2_texture_upload_shm,
.update_shm = gles2_texture_update_shm,
.upload_drm = gles2_texture_upload_drm,
+ .upload_dmabuf = gles2_texture_upload_dmabuf,
.upload_eglimage = gles2_texture_upload_eglimage,
- .get_matrix = gles2_texture_get_matrix,
.get_buffer_size = gles2_texture_get_buffer_size,
- .bind = gles2_texture_bind,
.destroy = gles2_texture_destroy,
};
@@ -303,7 +363,7 @@ struct wlr_texture *gles2_texture_create(struct wlr_egl *egl) {
if (!(texture = calloc(1, sizeof(struct wlr_gles2_texture)))) {
return NULL;
}
- wlr_texture_init(&texture->wlr_texture, &wlr_texture_impl);
+ wlr_texture_init(&texture->wlr_texture, &texture_impl);
texture->egl = egl;
return &texture->wlr_texture;
}
diff --git a/render/matrix.c b/render/matrix.c
deleted file mode 100644
index d5d7f49d..00000000
--- a/render/matrix.c
+++ /dev/null
@@ -1,210 +0,0 @@
-#include <math.h>
-#include <string.h>
-#include <wayland-server-protocol.h>
-#include <wlr/render/matrix.h>
-#include <wlr/types/wlr_box.h>
-#include <wlr/types/wlr_output.h>
-
-/* Obtains the index for the given row/column */
-static inline int mind(int row, int col) {
- return (row - 1) * 4 + col - 1;
-}
-
-void wlr_matrix_identity(float (*output)[16]) {
- static const float identity[16] = {
- 1.0f, 0.0f, 0.0f, 0.0f,
- 0.0f, 1.0f, 0.0f, 0.0f,
- 0.0f, 0.0f, 1.0f, 0.0f,
- 0.0f, 0.0f, 0.0f, 1.0f
- };
- memcpy(*output, identity, sizeof(identity));
-}
-
-void wlr_matrix_translate(float (*output)[16], float x, float y, float z) {
- wlr_matrix_identity(output);
- (*output)[mind(1, 4)] = x;
- (*output)[mind(2, 4)] = y;
- (*output)[mind(3, 4)] = z;
-}
-
-void wlr_matrix_scale(float (*output)[16], float x, float y, float z) {
- wlr_matrix_identity(output);
- (*output)[mind(1, 1)] = x;
- (*output)[mind(2, 2)] = y;
- (*output)[mind(3, 3)] = z;
-}
-
-void wlr_matrix_rotate(float (*output)[16], float radians) {
- wlr_matrix_identity(output);
- float _cos = cosf(radians);
- float _sin = sinf(radians);
- (*output)[mind(1, 1)] = _cos;
- (*output)[mind(1, 2)] = _sin;
- (*output)[mind(2, 1)] = -_sin;
- (*output)[mind(2, 2)] = _cos;
-}
-
-void wlr_matrix_mul(const float (*x)[16], const float (*y)[16], float (*product)[16]) {
- float _product[16] = {
- (*x)[mind(1, 1)] * (*y)[mind(1, 1)] + (*x)[mind(1, 2)] * (*y)[mind(2, 1)] +
- (*x)[mind(1, 3)] * (*y)[mind(3, 1)] + (*x)[mind(1, 4)] * (*y)[mind(4, 1)],
- (*x)[mind(1, 1)] * (*y)[mind(1, 2)] + (*x)[mind(1, 2)] * (*y)[mind(2, 2)] +
- (*x)[mind(1, 3)] * (*y)[mind(3, 2)] + (*x)[mind(1, 4)] * (*y)[mind(4, 2)],
- (*x)[mind(1, 1)] * (*y)[mind(1, 3)] + (*x)[mind(1, 2)] * (*y)[mind(2, 3)] +
- (*x)[mind(1, 3)] * (*y)[mind(3, 3)] + (*x)[mind(1, 4)] * (*y)[mind(4, 3)],
- (*x)[mind(1, 1)] * (*y)[mind(1, 4)] + (*x)[mind(1, 2)] * (*y)[mind(2, 4)] +
- (*x)[mind(1, 4)] * (*y)[mind(3, 4)] + (*x)[mind(1, 4)] * (*y)[mind(4, 4)],
-
- (*x)[mind(2, 1)] * (*y)[mind(1, 1)] + (*x)[mind(2, 2)] * (*y)[mind(2, 1)] +
- (*x)[mind(2, 3)] * (*y)[mind(3, 1)] + (*x)[mind(2, 4)] * (*y)[mind(4, 1)],
- (*x)[mind(2, 1)] * (*y)[mind(1, 2)] + (*x)[mind(2, 2)] * (*y)[mind(2, 2)] +
- (*x)[mind(2, 3)] * (*y)[mind(3, 2)] + (*x)[mind(2, 4)] * (*y)[mind(4, 2)],
- (*x)[mind(2, 1)] * (*y)[mind(1, 3)] + (*x)[mind(2, 2)] * (*y)[mind(2, 3)] +
- (*x)[mind(2, 3)] * (*y)[mind(3, 3)] + (*x)[mind(2, 4)] * (*y)[mind(4, 3)],
- (*x)[mind(2, 1)] * (*y)[mind(1, 4)] + (*x)[mind(2, 2)] * (*y)[mind(2, 4)] +
- (*x)[mind(2, 4)] * (*y)[mind(3, 4)] + (*x)[mind(2, 4)] * (*y)[mind(4, 4)],
-
- (*x)[mind(3, 1)] * (*y)[mind(1, 1)] + (*x)[mind(3, 2)] * (*y)[mind(2, 1)] +
- (*x)[mind(3, 3)] * (*y)[mind(3, 1)] + (*x)[mind(3, 4)] * (*y)[mind(4, 1)],
- (*x)[mind(3, 1)] * (*y)[mind(1, 2)] + (*x)[mind(3, 2)] * (*y)[mind(2, 2)] +
- (*x)[mind(3, 3)] * (*y)[mind(3, 2)] + (*x)[mind(3, 4)] * (*y)[mind(4, 2)],
- (*x)[mind(3, 1)] * (*y)[mind(1, 3)] + (*x)[mind(3, 2)] * (*y)[mind(2, 3)] +
- (*x)[mind(3, 3)] * (*y)[mind(3, 3)] + (*x)[mind(3, 4)] * (*y)[mind(4, 3)],
- (*x)[mind(3, 1)] * (*y)[mind(1, 4)] + (*x)[mind(3, 2)] * (*y)[mind(2, 4)] +
- (*x)[mind(3, 4)] * (*y)[mind(3, 4)] + (*x)[mind(3, 4)] * (*y)[mind(4, 4)],
-
- (*x)[mind(4, 1)] * (*y)[mind(1, 1)] + (*x)[mind(4, 2)] * (*y)[mind(2, 1)] +
- (*x)[mind(4, 3)] * (*y)[mind(3, 1)] + (*x)[mind(4, 4)] * (*y)[mind(4, 1)],
- (*x)[mind(4, 1)] * (*y)[mind(1, 2)] + (*x)[mind(4, 2)] * (*y)[mind(2, 2)] +
- (*x)[mind(4, 3)] * (*y)[mind(3, 2)] + (*x)[mind(4, 4)] * (*y)[mind(4, 2)],
- (*x)[mind(4, 1)] * (*y)[mind(1, 3)] + (*x)[mind(4, 2)] * (*y)[mind(2, 3)] +
- (*x)[mind(4, 3)] * (*y)[mind(3, 3)] + (*x)[mind(4, 4)] * (*y)[mind(4, 3)],
- (*x)[mind(4, 1)] * (*y)[mind(1, 4)] + (*x)[mind(4, 2)] * (*y)[mind(2, 4)] +
- (*x)[mind(4, 4)] * (*y)[mind(3, 4)] + (*x)[mind(4, 4)] * (*y)[mind(4, 4)],
- };
- memcpy(*product, _product, sizeof(_product));
-}
-
-static const float transforms[][4] = {
- [WL_OUTPUT_TRANSFORM_NORMAL] = {
- 1.0f, 0.0f,
- 0.0f, 1.0f,
- },
- [WL_OUTPUT_TRANSFORM_90] = {
- 0.0f, -1.0f,
- 1.0f, 0.0f,
- },
- [WL_OUTPUT_TRANSFORM_180] = {
- -1.0f, 0.0f,
- 0.0f, -1.0f,
- },
- [WL_OUTPUT_TRANSFORM_270] = {
- 0.0f, 1.0f,
- -1.0f, 0.0f,
- },
- [WL_OUTPUT_TRANSFORM_FLIPPED] = {
- -1.0f, 0.0f,
- 0.0f, 1.0f,
- },
- [WL_OUTPUT_TRANSFORM_FLIPPED_90] = {
- 0.0f, -1.0f,
- -1.0f, 0.0f,
- },
- [WL_OUTPUT_TRANSFORM_FLIPPED_180] = {
- 1.0f, 0.0f,
- 0.0f, -1.0f,
- },
- [WL_OUTPUT_TRANSFORM_FLIPPED_270] = {
- 0.0f, 1.0f,
- 1.0f, 0.0f,
- },
-};
-
-void wlr_matrix_transform(float mat[static 16],
- enum wl_output_transform transform) {
- memset(mat, 0, sizeof(*mat) * 16);
-
- const float *t = transforms[transform];
-
- // Rotation + reflection
- mat[0] = t[0];
- mat[1] = t[1];
- mat[4] = t[2];
- mat[5] = t[3];
-
- // Identity
- mat[10] = 1.0f;
- mat[15] = 1.0f;
-}
-
-// Equivilent to glOrtho(0, width, 0, height, 1, -1) with the transform applied
-void wlr_matrix_texture(float mat[static 16], int32_t width, int32_t height,
- enum wl_output_transform transform) {
- memset(mat, 0, sizeof(*mat) * 16);
-
- const float *t = transforms[transform];
- float x = 2.0f / width;
- float y = 2.0f / height;
-
- // Rotation + reflection
- mat[0] = x * t[0];
- mat[1] = x * t[1];
- mat[4] = y * -t[2];
- mat[5] = y * -t[3];
-
- // Translation
- mat[3] = -copysign(1.0f, mat[0] + mat[1]);
- mat[7] = -copysign(1.0f, mat[4] + mat[5]);
-
- // Identity
- mat[10] = 1.0f;
- mat[15] = 1.0f;
-}
-
-void wlr_matrix_project_box(float (*mat)[16], struct wlr_box *box,
- enum wl_output_transform transform, float rotation,
- float (*projection)[16]) {
- int x = box->x;
- int y = box->y;
- int width = box->width;
- int height = box->height;
-
- wlr_matrix_translate(mat, x, y, 0);
-
- if (rotation != 0) {
- float translate_center[16];
- wlr_matrix_translate(&translate_center, width/2, height/2, 0);
-
- float rotate[16];
- wlr_matrix_rotate(&rotate, rotation);
-
- float translate_origin[16];
- wlr_matrix_translate(&translate_origin, -width/2, -height/2, 0);
-
- wlr_matrix_mul(mat, &translate_center, mat);
- wlr_matrix_mul(mat, &rotate, mat);
- wlr_matrix_mul(mat, &translate_origin, mat);
- }
-
- float scale[16];
- wlr_matrix_scale(&scale, width, height, 1);
-
- wlr_matrix_mul(mat, &scale, mat);
-
- if (transform != WL_OUTPUT_TRANSFORM_NORMAL) {
- float surface_translate_center[16];
- wlr_matrix_translate(&surface_translate_center, 0.5, 0.5, 0);
-
- float surface_transform[16];
- wlr_matrix_transform(surface_transform, transform);
-
- float surface_translate_origin[16];
- wlr_matrix_translate(&surface_translate_origin, -0.5, -0.5, 0);
-
- wlr_matrix_mul(mat, &surface_translate_center, mat);
- wlr_matrix_mul(mat, &surface_transform, mat);
- wlr_matrix_mul(mat, &surface_translate_origin, mat);
- }
-
- wlr_matrix_mul(projection, mat, mat);
-}
diff --git a/render/meson.build b/render/meson.build
index 8aa70cea..4fe9ea67 100644
--- a/render/meson.build
+++ b/render/meson.build
@@ -15,7 +15,6 @@ lib_wlr_render = static_library(
'gles2/shaders.c',
'gles2/texture.c',
'gles2/util.c',
- 'matrix.c',
'wlr_renderer.c',
'wlr_texture.c',
),
diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c
index ce8fbe36..622aa1dd 100644
--- a/render/wlr_renderer.c
+++ b/render/wlr_renderer.c
@@ -1,9 +1,11 @@
#include <stdbool.h>
#include <stdlib.h>
#include <wlr/render/interface.h>
+#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_matrix.h>
void wlr_renderer_init(struct wlr_renderer *renderer,
- struct wlr_renderer_impl *impl) {
+ const struct wlr_renderer_impl *impl) {
renderer->impl = impl;
}
@@ -15,15 +17,15 @@ void wlr_renderer_destroy(struct wlr_renderer *r) {
}
}
-void wlr_renderer_begin(struct wlr_renderer *r, struct wlr_output *o) {
- r->impl->begin(r, o);
+void wlr_renderer_begin(struct wlr_renderer *r, int width, int height) {
+ r->impl->begin(r, width, height);
}
void wlr_renderer_end(struct wlr_renderer *r) {
r->impl->end(r);
}
-void wlr_renderer_clear(struct wlr_renderer *r, const float (*color)[4]) {
+void wlr_renderer_clear(struct wlr_renderer *r, const float color[static 4]) {
r->impl->clear(r, color);
}
@@ -35,18 +37,30 @@ struct wlr_texture *wlr_render_texture_create(struct wlr_renderer *r) {
return r->impl->texture_create(r);
}
-bool wlr_render_with_matrix(struct wlr_renderer *r,
- struct wlr_texture *texture, const float (*matrix)[16], float alpha) {
- return r->impl->render_with_matrix(r, texture, matrix, alpha);
+bool wlr_render_texture(struct wlr_renderer *r, struct wlr_texture *texture,
+ const float projection[static 9], int x, int y, float alpha) {
+ float mat[9];
+ wlr_matrix_identity(mat);
+ wlr_matrix_translate(mat, x, y);
+ wlr_matrix_scale(mat, texture->width, texture->height);
+ wlr_matrix_multiply(mat, projection, mat);
+
+ return wlr_render_texture_with_matrix(r, texture, mat, alpha);
+}
+
+bool wlr_render_texture_with_matrix(struct wlr_renderer *r,
+ struct wlr_texture *texture, const float matrix[static 9],
+ float alpha) {
+ return r->impl->render_texture_with_matrix(r, texture, matrix, alpha);
}
void wlr_render_colored_quad(struct wlr_renderer *r,
- const float (*color)[4], const float (*matrix)[16]) {
+ const float color[static 4], const float matrix[static 9]) {
r->impl->render_quad(r, color, matrix);
}
void wlr_render_colored_ellipse(struct wlr_renderer *r,
- const float (*color)[4], const float (*matrix)[16]) {
+ const float color[static 4], const float matrix[static 9]) {
r->impl->render_ellipse(r, color, matrix);
}
diff --git a/render/wlr_texture.c b/render/wlr_texture.c
index a82a16b2..33c91822 100644
--- a/render/wlr_texture.c
+++ b/render/wlr_texture.c
@@ -1,9 +1,10 @@
#include <stdbool.h>
#include <stdlib.h>
#include <wlr/render/interface.h>
+#include <wlr/render/wlr_texture.h>
void wlr_texture_init(struct wlr_texture *texture,
- struct wlr_texture_impl *impl) {
+ const struct wlr_texture_impl *impl) {
texture->impl = impl;
wl_signal_init(&texture->destroy_signal);
}
@@ -16,10 +17,6 @@ void wlr_texture_destroy(struct wlr_texture *texture) {
}
}
-void wlr_texture_bind(struct wlr_texture *texture) {
- texture->impl->bind(texture);
-}
-
bool wlr_texture_upload_pixels(struct wlr_texture *texture, uint32_t format,
int stride, int width, int height, const unsigned char *pixels) {
return texture->impl->upload_pixels(texture, format, stride,
@@ -53,9 +50,9 @@ bool wlr_texture_upload_eglimage(struct wlr_texture *texture,
return texture->impl->upload_eglimage(texture, image, width, height);
}
-void wlr_texture_get_matrix(struct wlr_texture *texture,
- float (*matrix)[16], const float (*projection)[16], int x, int y) {
- texture->impl->get_matrix(texture, matrix, projection, x, y);
+bool wlr_texture_upload_dmabuf(struct wlr_texture *texture,
+ struct wl_resource *dmabuf_resource) {
+ return texture->impl->upload_dmabuf(texture, dmabuf_resource);
}
void wlr_texture_get_buffer_size(struct wlr_texture *texture, struct wl_resource
diff --git a/rootston/cursor.c b/rootston/cursor.c
index aa94daeb..52439dff 100644
--- a/rootston/cursor.c
+++ b/rootston/cursor.c
@@ -200,7 +200,7 @@ static void roots_cursor_update_position(struct roots_cursor *cursor,
uy = cursor->offs_y - oy;
int vx = cursor->cursor->x - ox,
vy = cursor->cursor->y - oy;
- float angle = atan2(vx*uy - vy*ux, vx*ux + vy*uy);
+ float angle = atan2(ux*vy - uy*vx, vx*ux + vy*uy);
int steps = 12;
angle = round(angle/M_PI*steps) / (steps/M_PI);
view_rotate(view, cursor->view_rotation + angle);
diff --git a/rootston/desktop.c b/rootston/desktop.c
index 3628b051..65d9a280 100644
--- a/rootston/desktop.c
+++ b/rootston/desktop.c
@@ -9,6 +9,7 @@
#include <wlr/types/wlr_cursor.h>
#include <wlr/types/wlr_gamma_control.h>
#include <wlr/types/wlr_idle.h>
+#include <wlr/types/wlr_linux_dmabuf.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_idle_inhibit_v1.h>
#include <wlr/types/wlr_primary_selection.h>
@@ -23,13 +24,16 @@
#include "rootston/view.h"
#include "rootston/xcursor.h"
-
-struct roots_view *view_create() {
+struct roots_view *view_create(struct roots_desktop *desktop) {
struct roots_view *view = calloc(1, sizeof(struct roots_view));
if (!view) {
return NULL;
}
+ view->desktop = desktop;
view->alpha = 1.0f;
+ wl_signal_init(&view->events.unmap);
+ wl_signal_init(&view->events.destroy);
+ wl_list_init(&view->children);
return view;
}
@@ -52,7 +56,8 @@ void view_get_deco_box(const struct roots_view *view, struct wlr_box *box) {
box->height += (view->border_width * 2 + view->titlebar_height);
}
-enum roots_deco_part view_get_deco_part(struct roots_view *view, double sx, double sy) {
+enum roots_deco_part view_get_deco_part(struct roots_view *view, double sx,
+ double sy) {
if (!view->decorated) {
return ROOTS_DECO_PART_NONE;
}
@@ -92,9 +97,15 @@ enum roots_deco_part view_get_deco_part(struct roots_view *view, double sx, doub
static void view_update_output(const struct roots_view *view,
const struct wlr_box *before) {
struct roots_desktop *desktop = view->desktop;
- struct roots_output *output;
+
+ if (view->wlr_surface == NULL) {
+ return;
+ }
+
struct wlr_box box;
view_get_box(view, &box);
+
+ struct roots_output *output;
wl_list_for_each(output, &desktop->outputs, link) {
bool intersected = before != NULL && wlr_output_layout_intersects(
desktop->layout, output->wlr_output, before);
@@ -402,20 +413,22 @@ struct roots_subsurface *subsurface_create(struct roots_view *view,
return subsurface;
}
-void view_finish(struct roots_view *view) {
- view_damage_whole(view);
- wl_signal_emit(&view->events.destroy, view);
+void view_destroy(struct roots_view *view) {
+ if (view == NULL) {
+ return;
+ }
- wl_list_remove(&view->new_subsurface.link);
+ wl_signal_emit(&view->events.destroy, view);
- struct roots_view_child *child, *tmp;
- wl_list_for_each_safe(child, tmp, &view->children, link) {
- child->destroy(child);
+ if (view->wlr_surface != NULL) {
+ view_unmap(view);
}
- if (view->fullscreen_output) {
- view->fullscreen_output->fullscreen_view = NULL;
+ if (view->destroy) {
+ view->destroy(view);
}
+
+ free(view);
}
static void view_handle_new_subsurface(struct wl_listener *listener,
@@ -425,12 +438,10 @@ static void view_handle_new_subsurface(struct wl_listener *listener,
subsurface_create(view, wlr_subsurface);
}
-void view_init(struct roots_view *view, struct roots_desktop *desktop) {
- assert(view->wlr_surface);
+void view_map(struct roots_view *view, struct wlr_surface *surface) {
+ assert(view->wlr_surface == NULL);
- view->desktop = desktop;
- wl_signal_init(&view->events.destroy);
- wl_list_init(&view->children);
+ view->wlr_surface = surface;
struct wlr_subsurface *subsurface;
wl_list_for_each(subsurface, &view->wlr_surface->subsurface_list,
@@ -442,9 +453,35 @@ void view_init(struct roots_view *view, struct roots_desktop *desktop) {
wl_signal_add(&view->wlr_surface->events.new_subsurface,
&view->new_subsurface);
+ wl_list_insert(&view->desktop->views, &view->link);
view_damage_whole(view);
}
+void view_unmap(struct roots_view *view) {
+ assert(view->wlr_surface != NULL);
+
+ wl_signal_emit(&view->events.unmap, view);
+
+ view_damage_whole(view);
+ wl_list_remove(&view->link);
+
+ wl_list_remove(&view->new_subsurface.link);
+
+ struct roots_view_child *child, *tmp;
+ wl_list_for_each_safe(child, tmp, &view->children, link) {
+ child->destroy(child);
+ }
+
+ if (view->fullscreen_output != NULL) {
+ output_damage_whole(view->fullscreen_output);
+ view->fullscreen_output->fullscreen_view = NULL;
+ view->fullscreen_output = NULL;
+ }
+
+ view->wlr_surface = NULL;
+ view->width = view->height = 0;
+}
+
void view_initial_focus(struct roots_view *view) {
struct roots_input *input = view->desktop->server->input;
// TODO what seat gets focus? the one with the last input event?
@@ -457,7 +494,10 @@ void view_initial_focus(struct roots_view *view) {
void view_setup(struct roots_view *view) {
view_initial_focus(view);
- view_center(view);
+ if (view->fullscreen_output == NULL && !view->maximized) {
+ view_center(view);
+ }
+
view_update_output(view, NULL);
}
@@ -517,8 +557,8 @@ static bool view_at(struct roots_view *view, double lx, double ly,
double ox = view_sx - (double)box.width/2,
oy = view_sy - (double)box.height/2;
// Rotated coordinates
- double rx = cos(view->rotation)*ox - sin(view->rotation)*oy,
- ry = cos(view->rotation)*oy + sin(view->rotation)*ox;
+ double rx = cos(view->rotation)*ox + sin(view->rotation)*oy,
+ ry = cos(view->rotation)*oy - sin(view->rotation)*ox;
view_sx = rx + (double)box.width/2;
view_sy = ry + (double)box.height/2;
}
@@ -729,6 +769,8 @@ struct roots_desktop *desktop_create(struct roots_server *server,
desktop->idle = wlr_idle_create(server->wl_display);
desktop->idle_inhibit = wlr_idle_inhibit_v1_create(server->wl_display);
+ struct wlr_egl *egl = wlr_backend_get_egl(server->backend);
+ desktop->linux_dmabuf = wlr_linux_dmabuf_create(server->wl_display, egl);
return desktop;
}
diff --git a/rootston/main.c b/rootston/main.c
index 5450ade2..d85701ca 100644
--- a/rootston/main.c
+++ b/rootston/main.c
@@ -7,7 +7,7 @@
#include <wlr/backend/headless.h>
#include <wlr/backend/multi.h>
#include <wlr/config.h>
-#include <wlr/render.h>
+#include <wlr/render/wlr_renderer.h>
#include <wlr/util/log.h>
#include "rootston/config.h"
#include "rootston/server.h"
diff --git a/rootston/output.c b/rootston/output.c
index 4d0a9c05..1284c928 100644
--- a/rootston/output.c
+++ b/rootston/output.c
@@ -3,7 +3,7 @@
#include <stdbool.h>
#include <stdlib.h>
#include <time.h>
-#include <wlr/render/matrix.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_output_layout.h>
#include <wlr/types/wlr_wl_shell.h>
@@ -29,8 +29,8 @@ static void rotate_child_position(double *sx, double *sy, double sw, double sh,
double ox = *sx - pw/2 + sw/2,
oy = *sy - ph/2 + sh/2;
// Rotated coordinates
- double rx = cos(-rotation)*ox - sin(-rotation)*oy,
- ry = cos(-rotation)*oy + sin(-rotation)*ox;
+ double rx = cos(rotation)*ox - sin(rotation)*oy,
+ ry = cos(rotation)*oy + sin(rotation)*ox;
*sx = rx + pw/2 - sw/2;
*sy = ry + ph/2 - sh/2;
}
@@ -227,7 +227,7 @@ static bool surface_intersect_output(struct wlr_surface *surface,
.x = lx, .y = ly,
.width = surface->current->width, .height = surface->current->height,
};
- wlr_box_rotated_bounds(&layout_box, -rotation, &layout_box);
+ wlr_box_rotated_bounds(&layout_box, rotation, &layout_box);
return wlr_output_layout_intersects(output_layout, wlr_output, &layout_box);
}
@@ -275,7 +275,7 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly,
}
struct wlr_box rotated;
- wlr_box_rotated_bounds(&box, -rotation, &rotated);
+ wlr_box_rotated_bounds(&box, rotation, &rotated);
pixman_region32_t damage;
pixman_region32_init(&damage);
@@ -287,17 +287,17 @@ static void render_surface(struct wlr_surface *surface, double lx, double ly,
goto damage_finish;
}
- float matrix[16];
+ float matrix[9];
enum wl_output_transform transform =
wlr_output_transform_invert(surface->current->transform);
- wlr_matrix_project_box(&matrix, &box, transform, rotation,
- &output->wlr_output->transform_matrix);
+ wlr_matrix_project_box(matrix, &box, transform, rotation,
+ output->wlr_output->transform_matrix);
int nrects;
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
for (int i = 0; i < nrects; ++i) {
scissor_output(output, &rects[i]);
- wlr_render_with_matrix(renderer, surface->texture, &matrix, data->alpha);
+ wlr_render_texture_with_matrix(renderer, surface->texture, matrix, data->alpha);
}
damage_finish:
@@ -341,7 +341,7 @@ static void render_decorations(struct roots_view *view,
get_decoration_box(view, output, &box);
struct wlr_box rotated;
- wlr_box_rotated_bounds(&box, -view->rotation, &rotated);
+ wlr_box_rotated_bounds(&box, view->rotation, &rotated);
pixman_region32_t damage;
pixman_region32_init(&damage);
@@ -353,9 +353,9 @@ static void render_decorations(struct roots_view *view,
goto damage_finish;
}
- float matrix[16];
- wlr_matrix_project_box(&matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL,
- view->rotation, &output->wlr_output->transform_matrix);
+ float matrix[9];
+ wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL,
+ view->rotation, output->wlr_output->transform_matrix);
float color[] = { 0.2, 0.2, 0.2, view->alpha };
int nrects;
@@ -363,7 +363,7 @@ static void render_decorations(struct roots_view *view,
pixman_region32_rectangles(&damage, &nrects);
for (int i = 0; i < nrects; ++i) {
scissor_output(output, &rects[i]);
- wlr_render_colored_quad(renderer, &color, &matrix);
+ wlr_render_colored_quad(renderer, color, matrix);
}
damage_finish:
@@ -433,7 +433,8 @@ static void render_output(struct roots_output *output) {
float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
// Check if we can delegate the fullscreen surface to the output
- if (output->fullscreen_view != NULL) {
+ if (output->fullscreen_view != NULL &&
+ output->fullscreen_view->wlr_surface != NULL) {
struct roots_view *view = output->fullscreen_view;
// Make sure the view is centered on screen
@@ -478,7 +479,7 @@ static void render_output(struct roots_output *output) {
goto damage_finish;
}
- wlr_renderer_begin(renderer, wlr_output);
+ wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);
if (!pixman_region32_not_empty(&damage)) {
// Output isn't damaged but needs buffer swap
@@ -489,7 +490,7 @@ static void render_output(struct roots_output *output) {
pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
for (int i = 0; i < nrects; ++i) {
scissor_output(output, &rects[i]);
- wlr_renderer_clear(renderer, &clear_color);
+ wlr_renderer_clear(renderer, clear_color);
}
// If a view is fullscreen on this output, render it
@@ -501,7 +502,9 @@ static void render_output(struct roots_output *output) {
goto renderer_end;
}
- view_for_each_surface(view, render_surface, &data);
+ if (view->wlr_surface != NULL) {
+ view_for_each_surface(view, render_surface, &data);
+ }
// During normal rendering the xwayland window tree isn't traversed
// because all windows are rendered. Here we only want to render
@@ -570,6 +573,9 @@ void output_damage_whole(struct roots_output *output) {
static bool view_accept_damage(struct roots_output *output,
struct roots_view *view) {
+ if (view->wlr_surface == NULL) {
+ return false;
+ }
if (output->fullscreen_view == NULL) {
return true;
}
@@ -610,7 +616,7 @@ static void damage_whole_surface(struct wlr_surface *surface,
return;
}
- wlr_box_rotated_bounds(&box, -rotation, &box);
+ wlr_box_rotated_bounds(&box, rotation, &box);
wlr_output_damage_add_box(output->damage, &box);
}
@@ -624,7 +630,7 @@ static void damage_whole_decoration(struct roots_view *view,
struct wlr_box box;
get_decoration_box(view, output, &box);
- wlr_box_rotated_bounds(&box, -view->rotation, &box);
+ wlr_box_rotated_bounds(&box, view->rotation, &box);
wlr_output_damage_add_box(output->damage, &box);
}
@@ -674,6 +680,7 @@ static void damage_from_surface(struct wlr_surface *surface,
}
pixman_region32_translate(&damage, box.x, box.y);
wlr_output_damage_add(output->damage, &damage);
+ pixman_region32_fini(&damage);
} else {
pixman_box32_t *extents =
pixman_region32_extents(&surface->current->surface_damage);
@@ -683,7 +690,7 @@ static void damage_from_surface(struct wlr_surface *surface,
.width = (extents->x2 - extents->x1) * wlr_output->scale,
.height = (extents->y2 - extents->y1) * wlr_output->scale,
};
- wlr_box_rotated_bounds(&damage_box, -rotation, &damage_box);
+ wlr_box_rotated_bounds(&damage_box, rotation, &damage_box);
wlr_output_damage_add_box(output->damage, &damage_box);
}
}
diff --git a/rootston/seat.c b/rootston/seat.c
index 8ac41f6c..d2d211ba 100644
--- a/rootston/seat.c
+++ b/rootston/seat.c
@@ -645,6 +645,7 @@ static void seat_view_destroy(struct roots_seat_view *seat_view) {
seat->cursor->pointer_view = NULL;
}
+ wl_list_remove(&seat_view->view_unmap.link);
wl_list_remove(&seat_view->view_destroy.link);
wl_list_remove(&seat_view->link);
free(seat_view);
@@ -657,6 +658,12 @@ static void seat_view_destroy(struct roots_seat_view *seat_view) {
}
}
+static void seat_view_handle_unmap(struct wl_listener *listener, void *data) {
+ struct roots_seat_view *seat_view =
+ wl_container_of(listener, seat_view, view_unmap);
+ seat_view_destroy(seat_view);
+}
+
static void seat_view_handle_destroy(struct wl_listener *listener, void *data) {
struct roots_seat_view *seat_view =
wl_container_of(listener, seat_view, view_destroy);
@@ -675,6 +682,8 @@ static struct roots_seat_view *seat_add_view(struct roots_seat *seat,
wl_list_insert(seat->views.prev, &seat_view->link);
+ seat_view->view_unmap.notify = seat_view_handle_unmap;
+ wl_signal_add(&view->events.unmap, &seat_view->view_unmap);
seat_view->view_destroy.notify = seat_view_handle_destroy;
wl_signal_add(&view->events.destroy, &seat_view->view_destroy);
diff --git a/rootston/wl_shell.c b/rootston/wl_shell.c
index 899df1c6..d58f030a 100644
--- a/rootston/wl_shell.c
+++ b/rootston/wl_shell.c
@@ -78,6 +78,19 @@ static void close(struct roots_view *view) {
wl_client_destroy(surf->client);
}
+static void destroy(struct roots_view *view) {
+ assert(view->type == ROOTS_WL_SHELL_VIEW);
+ struct roots_wl_shell_surface *roots_surface = view->roots_wl_shell_surface;
+ wl_list_remove(&roots_surface->destroy.link);
+ wl_list_remove(&roots_surface->request_move.link);
+ wl_list_remove(&roots_surface->request_resize.link);
+ wl_list_remove(&roots_surface->request_maximize.link);
+ wl_list_remove(&roots_surface->request_fullscreen.link);
+ wl_list_remove(&roots_surface->set_state.link);
+ wl_list_remove(&roots_surface->surface_commit.link);
+ free(roots_surface);
+}
+
static void handle_request_move(struct wl_listener *listener, void *data) {
struct roots_wl_shell_surface *roots_surface =
wl_container_of(listener, roots_surface, request_move);
@@ -174,17 +187,7 @@ static void handle_new_popup(struct wl_listener *listener, void *data) {
static void handle_destroy(struct wl_listener *listener, void *data) {
struct roots_wl_shell_surface *roots_surface =
wl_container_of(listener, roots_surface, destroy);
- wl_list_remove(&roots_surface->destroy.link);
- wl_list_remove(&roots_surface->request_move.link);
- wl_list_remove(&roots_surface->request_resize.link);
- wl_list_remove(&roots_surface->request_maximize.link);
- wl_list_remove(&roots_surface->request_fullscreen.link);
- wl_list_remove(&roots_surface->set_state.link);
- wl_list_remove(&roots_surface->surface_commit.link);
- wl_list_remove(&roots_surface->view->link);
- view_finish(roots_surface->view);
- free(roots_surface->view);
- free(roots_surface);
+ view_destroy(roots_surface->view);
}
void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
@@ -227,7 +230,7 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
roots_surface->surface_commit.notify = handle_surface_commit;
wl_signal_add(&surface->surface->events.commit, &roots_surface->surface_commit);
- struct roots_view *view = view_create();
+ struct roots_view *view = view_create(desktop);
if (!view) {
free(roots_surface);
return;
@@ -238,13 +241,12 @@ void handle_wl_shell_surface(struct wl_listener *listener, void *data) {
view->wl_shell_surface = surface;
view->roots_wl_shell_surface = roots_surface;
- view->wlr_surface = surface->surface;
view->resize = resize;
view->close = close;
+ view->destroy = destroy;
roots_surface->view = view;
- view_init(view, desktop);
- wl_list_insert(&desktop->views, &view->link);
+ view_map(view, surface->surface);
view_setup(view);
if (surface->state == WLR_WL_SHELL_SURFACE_STATE_TRANSIENT) {
diff --git a/rootston/xdg_shell.c b/rootston/xdg_shell.c
index 9368ce0b..851c0045 100644
--- a/rootston/xdg_shell.c
+++ b/rootston/xdg_shell.c
@@ -60,12 +60,14 @@ static void get_size(const struct roots_view *view, struct wlr_box *box) {
assert(view->type == ROOTS_XDG_SHELL_VIEW);
struct wlr_xdg_surface *surface = view->xdg_surface;
- if (surface->geometry->width > 0 && surface->geometry->height > 0) {
- box->width = surface->geometry->width;
- box->height = surface->geometry->height;
- } else {
+ if (surface->geometry.width > 0 && surface->geometry.height > 0) {
+ box->width = surface->geometry.width;
+ box->height = surface->geometry.height;
+ } else if (view->wlr_surface != NULL) {
box->width = view->wlr_surface->current->width;
box->height = view->wlr_surface->current->height;
+ } else {
+ box->width = box->height = 0;
}
}
@@ -83,7 +85,7 @@ static void apply_size_constraints(struct wlr_xdg_surface *surface,
*dest_width = width;
*dest_height = height;
- struct wlr_xdg_toplevel_state *state = &surface->toplevel_state->current;
+ struct wlr_xdg_toplevel_state *state = &surface->toplevel->current;
if (width < state->min_width) {
*dest_width = state->min_width;
} else if (state->max_width > 0 &&
@@ -180,6 +182,21 @@ static void close(struct roots_view *view) {
}
}
+static void destroy(struct roots_view *view) {
+ assert(view->type == ROOTS_XDG_SHELL_VIEW);
+ struct roots_xdg_surface *roots_xdg_surface = view->roots_xdg_surface;
+ wl_list_remove(&roots_xdg_surface->surface_commit.link);
+ wl_list_remove(&roots_xdg_surface->destroy.link);
+ wl_list_remove(&roots_xdg_surface->new_popup.link);
+ wl_list_remove(&roots_xdg_surface->map.link);
+ wl_list_remove(&roots_xdg_surface->unmap.link);
+ wl_list_remove(&roots_xdg_surface->request_move.link);
+ wl_list_remove(&roots_xdg_surface->request_resize.link);
+ wl_list_remove(&roots_xdg_surface->request_maximize.link);
+ wl_list_remove(&roots_xdg_surface->request_fullscreen.link);
+ free(roots_xdg_surface);
+}
+
static void handle_request_move(struct wl_listener *listener, void *data) {
struct roots_xdg_surface *roots_xdg_surface =
wl_container_of(listener, roots_xdg_surface, request_move);
@@ -219,7 +236,7 @@ static void handle_request_maximize(struct wl_listener *listener, void *data) {
return;
}
- view_maximize(view, surface->toplevel_state->next.maximized);
+ view_maximize(view, surface->toplevel->next.maximized);
}
static void handle_request_fullscreen(struct wl_listener *listener,
@@ -243,6 +260,10 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
struct roots_view *view = roots_surface->view;
struct wlr_xdg_surface *surface = view->xdg_surface;
+ if (!surface->mapped) {
+ return;
+ }
+
view_apply_damage(view);
struct wlr_box size;
@@ -277,20 +298,30 @@ static void handle_new_popup(struct wl_listener *listener, void *data) {
popup_create(roots_xdg_surface->view, wlr_popup);
}
+static void handle_map(struct wl_listener *listener, void *data) {
+ struct roots_xdg_surface *roots_xdg_surface =
+ wl_container_of(listener, roots_xdg_surface, map);
+ struct roots_view *view = roots_xdg_surface->view;
+
+ struct wlr_box box;
+ get_size(view, &box);
+ view->width = box.width;
+ view->height = box.height;
+
+ view_map(view, view->xdg_surface->surface);
+ view_setup(view);
+}
+
+static void handle_unmap(struct wl_listener *listener, void *data) {
+ struct roots_xdg_surface *roots_xdg_surface =
+ wl_container_of(listener, roots_xdg_surface, unmap);
+ view_unmap(roots_xdg_surface->view);
+}
+
static void handle_destroy(struct wl_listener *listener, void *data) {
struct roots_xdg_surface *roots_xdg_surface =
wl_container_of(listener, roots_xdg_surface, destroy);
- wl_list_remove(&roots_xdg_surface->surface_commit.link);
- wl_list_remove(&roots_xdg_surface->destroy.link);
- wl_list_remove(&roots_xdg_surface->new_popup.link);
- wl_list_remove(&roots_xdg_surface->request_move.link);
- wl_list_remove(&roots_xdg_surface->request_resize.link);
- wl_list_remove(&roots_xdg_surface->request_maximize.link);
- wl_list_remove(&roots_xdg_surface->request_fullscreen.link);
- wl_list_remove(&roots_xdg_surface->view->link);
- view_finish(roots_xdg_surface->view);
- free(roots_xdg_surface->view);
- free(roots_xdg_surface);
+ view_destroy(roots_xdg_surface->view);
}
void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
@@ -319,6 +350,10 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
&roots_surface->surface_commit);
roots_surface->destroy.notify = handle_destroy;
wl_signal_add(&surface->events.destroy, &roots_surface->destroy);
+ roots_surface->map.notify = handle_map;
+ wl_signal_add(&surface->events.map, &roots_surface->map);
+ roots_surface->unmap.notify = handle_unmap;
+ wl_signal_add(&surface->events.unmap, &roots_surface->unmap);
roots_surface->request_move.notify = handle_request_move;
wl_signal_add(&surface->events.request_move, &roots_surface->request_move);
roots_surface->request_resize.notify = handle_request_resize;
@@ -333,7 +368,7 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
roots_surface->new_popup.notify = handle_new_popup;
wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup);
- struct roots_view *view = view_create();
+ struct roots_view *view = view_create(desktop);
if (!view) {
free(roots_surface);
return;
@@ -342,22 +377,19 @@ void handle_xdg_shell_surface(struct wl_listener *listener, void *data) {
view->xdg_surface = surface;
view->roots_xdg_surface = roots_surface;
- view->wlr_surface = surface->surface;
view->activate = activate;
view->resize = resize;
view->move_resize = move_resize;
view->maximize = maximize;
view->set_fullscreen = set_fullscreen;
view->close = close;
+ view->destroy = destroy;
roots_surface->view = view;
- struct wlr_box box;
- get_size(view, &box);
- view->width = box.width;
- view->height = box.height;
-
- view_init(view, desktop);
- wl_list_insert(&desktop->views, &view->link);
-
- view_setup(view);
+ if (surface->toplevel->next.maximized) {
+ view_maximize(view, true);
+ }
+ if (surface->toplevel->next.fullscreen) {
+ view_set_fullscreen(view, true, NULL);
+ }
}
diff --git a/rootston/xdg_shell_v6.c b/rootston/xdg_shell_v6.c
index eda349cb..13d25331 100644
--- a/rootston/xdg_shell_v6.c
+++ b/rootston/xdg_shell_v6.c
@@ -60,12 +60,14 @@ static void get_size(const struct roots_view *view, struct wlr_box *box) {
assert(view->type == ROOTS_XDG_SHELL_V6_VIEW);
struct wlr_xdg_surface_v6 *surface = view->xdg_surface_v6;
- if (surface->geometry->width > 0 && surface->geometry->height > 0) {
- box->width = surface->geometry->width;
- box->height = surface->geometry->height;
- } else {
+ if (surface->geometry.width > 0 && surface->geometry.height > 0) {
+ box->width = surface->geometry.width;
+ box->height = surface->geometry.height;
+ } else if (view->wlr_surface != NULL) {
box->width = view->wlr_surface->current->width;
box->height = view->wlr_surface->current->height;
+ } else {
+ box->width = box->height = 0;
}
}
@@ -83,7 +85,7 @@ static void apply_size_constraints(struct wlr_xdg_surface_v6 *surface,
*dest_width = width;
*dest_height = height;
- struct wlr_xdg_toplevel_v6_state *state = &surface->toplevel_state->current;
+ struct wlr_xdg_toplevel_v6_state *state = &surface->toplevel->current;
if (width < state->min_width) {
*dest_width = state->min_width;
} else if (state->max_width > 0 &&
@@ -180,6 +182,21 @@ static void close(struct roots_view *view) {
}
}
+static void destroy(struct roots_view *view) {
+ assert(view->type == ROOTS_XDG_SHELL_V6_VIEW);
+ struct roots_xdg_surface_v6 *roots_xdg_surface = view->roots_xdg_surface_v6;
+ wl_list_remove(&roots_xdg_surface->surface_commit.link);
+ wl_list_remove(&roots_xdg_surface->destroy.link);
+ wl_list_remove(&roots_xdg_surface->new_popup.link);
+ wl_list_remove(&roots_xdg_surface->map.link);
+ wl_list_remove(&roots_xdg_surface->unmap.link);
+ wl_list_remove(&roots_xdg_surface->request_move.link);
+ wl_list_remove(&roots_xdg_surface->request_resize.link);
+ wl_list_remove(&roots_xdg_surface->request_maximize.link);
+ wl_list_remove(&roots_xdg_surface->request_fullscreen.link);
+ free(roots_xdg_surface);
+}
+
static void handle_request_move(struct wl_listener *listener, void *data) {
struct roots_xdg_surface_v6 *roots_xdg_surface =
wl_container_of(listener, roots_xdg_surface, request_move);
@@ -219,7 +236,7 @@ static void handle_request_maximize(struct wl_listener *listener, void *data) {
return;
}
- view_maximize(view, surface->toplevel_state->next.maximized);
+ view_maximize(view, surface->toplevel->next.maximized);
}
static void handle_request_fullscreen(struct wl_listener *listener,
@@ -243,6 +260,10 @@ static void handle_surface_commit(struct wl_listener *listener, void *data) {
struct roots_view *view = roots_surface->view;
struct wlr_xdg_surface_v6 *surface = view->xdg_surface_v6;
+ if (!surface->mapped) {
+ return;
+ }
+
view_apply_damage(view);
struct wlr_box size;
@@ -277,20 +298,30 @@ static void handle_new_popup(struct wl_listener *listener, void *data) {
popup_create(roots_xdg_surface->view, wlr_popup);
}
+static void handle_map(struct wl_listener *listener, void *data) {
+ struct roots_xdg_surface_v6 *roots_xdg_surface =
+ wl_container_of(listener, roots_xdg_surface, map);
+ struct roots_view *view = roots_xdg_surface->view;
+
+ struct wlr_box box;
+ get_size(view, &box);
+ view->width = box.width;
+ view->height = box.height;
+
+ view_map(view, view->xdg_surface_v6->surface);
+ view_setup(view);
+}
+
+static void handle_unmap(struct wl_listener *listener, void *data) {
+ struct roots_xdg_surface_v6 *roots_xdg_surface =
+ wl_container_of(listener, roots_xdg_surface, unmap);
+ view_unmap(roots_xdg_surface->view);
+}
+
static void handle_destroy(struct wl_listener *listener, void *data) {
struct roots_xdg_surface_v6 *roots_xdg_surface =
wl_container_of(listener, roots_xdg_surface, destroy);
- wl_list_remove(&roots_xdg_surface->surface_commit.link);
- wl_list_remove(&roots_xdg_surface->destroy.link);
- wl_list_remove(&roots_xdg_surface->new_popup.link);
- wl_list_remove(&roots_xdg_surface->request_move.link);
- wl_list_remove(&roots_xdg_surface->request_resize.link);
- wl_list_remove(&roots_xdg_surface->request_maximize.link);
- wl_list_remove(&roots_xdg_surface->request_fullscreen.link);
- wl_list_remove(&roots_xdg_surface->view->link);
- view_finish(roots_xdg_surface->view);
- free(roots_xdg_surface->view);
- free(roots_xdg_surface);
+ view_destroy(roots_xdg_surface->view);
}
void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
@@ -319,6 +350,10 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
&roots_surface->surface_commit);
roots_surface->destroy.notify = handle_destroy;
wl_signal_add(&surface->events.destroy, &roots_surface->destroy);
+ roots_surface->map.notify = handle_map;
+ wl_signal_add(&surface->events.map, &roots_surface->map);
+ roots_surface->unmap.notify = handle_unmap;
+ wl_signal_add(&surface->events.unmap, &roots_surface->unmap);
roots_surface->request_move.notify = handle_request_move;
wl_signal_add(&surface->events.request_move, &roots_surface->request_move);
roots_surface->request_resize.notify = handle_request_resize;
@@ -333,7 +368,7 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
roots_surface->new_popup.notify = handle_new_popup;
wl_signal_add(&surface->events.new_popup, &roots_surface->new_popup);
- struct roots_view *view = view_create();
+ struct roots_view *view = view_create(desktop);
if (!view) {
free(roots_surface);
return;
@@ -342,22 +377,19 @@ void handle_xdg_shell_v6_surface(struct wl_listener *listener, void *data) {
view->xdg_surface_v6 = surface;
view->roots_xdg_surface_v6 = roots_surface;
- view->wlr_surface = surface->surface;
view->activate = activate;
view->resize = resize;
view->move_resize = move_resize;
view->maximize = maximize;
view->set_fullscreen = set_fullscreen;
view->close = close;
+ view->destroy = destroy;
roots_surface->view = view;
- struct wlr_box box;
- get_size(view, &box);
- view->width = box.width;
- view->height = box.height;
-
- view_init(view, desktop);
- wl_list_insert(&desktop->views, &view->link);
-
- view_setup(view);
+ if (surface->toplevel->next.maximized) {
+ view_maximize(view, true);
+ }
+ if (surface->toplevel->next.fullscreen) {
+ view_set_fullscreen(view, true, NULL);
+ }
}
diff --git a/rootston/xwayland.c b/rootston/xwayland.c
index 56f068ea..53331b1f 100644
--- a/rootston/xwayland.c
+++ b/rootston/xwayland.c
@@ -106,11 +106,9 @@ static void set_fullscreen(struct roots_view *view, bool fullscreen) {
wlr_xwayland_surface_set_fullscreen(view->xwayland_surface, fullscreen);
}
-static void handle_destroy(struct wl_listener *listener, void *data) {
- struct roots_xwayland_surface *roots_surface =
- wl_container_of(listener, roots_surface, destroy);
- struct wlr_xwayland_surface *xwayland_surface =
- roots_surface->view->xwayland_surface;
+static void destroy(struct roots_view *view) {
+ assert(view->type == ROOTS_XWAYLAND_VIEW);
+ struct roots_xwayland_surface *roots_surface = view->roots_xwayland_surface;
wl_list_remove(&roots_surface->destroy.link);
wl_list_remove(&roots_surface->request_configure.link);
wl_list_remove(&roots_surface->request_move.link);
@@ -118,14 +116,15 @@ static void handle_destroy(struct wl_listener *listener, void *data) {
wl_list_remove(&roots_surface->request_maximize.link);
wl_list_remove(&roots_surface->map_notify.link);
wl_list_remove(&roots_surface->unmap_notify.link);
- if (xwayland_surface->mapped) {
- wl_list_remove(&roots_surface->view->link);
- }
- view_finish(roots_surface->view);
- free(roots_surface->view);
free(roots_surface);
}
+static void handle_destroy(struct wl_listener *listener, void *data) {
+ struct roots_xwayland_surface *roots_surface =
+ wl_container_of(listener, roots_surface, destroy);
+ view_destroy(roots_surface->view);
+}
+
static void handle_request_configure(struct wl_listener *listener, void *data) {
struct roots_xwayland_surface *roots_surface =
wl_container_of(listener, roots_surface, request_configure);
@@ -231,22 +230,13 @@ static void handle_map_notify(struct wl_listener *listener, void *data) {
wl_container_of(listener, roots_surface, map_notify);
struct wlr_xwayland_surface *xsurface = data;
struct roots_view *view = roots_surface->view;
- struct roots_desktop *desktop = view->desktop;
- view->wlr_surface = xsurface->surface;
view->x = xsurface->x;
view->y = xsurface->y;
view->width = xsurface->surface->current->width;
view->height = xsurface->surface->current->height;
- wl_list_insert(&desktop->views, &view->link);
- struct wlr_subsurface *subsurface;
- wl_list_for_each(subsurface, &view->wlr_surface->subsurface_list,
- parent_link) {
- subsurface_create(view, subsurface);
- }
-
- view_damage_whole(view);
+ view_map(view, xsurface->surface);
roots_surface->surface_commit.notify = handle_surface_commit;
wl_signal_add(&xsurface->surface->events.commit,
@@ -260,22 +250,7 @@ static void handle_unmap_notify(struct wl_listener *listener, void *data) {
wl_list_remove(&roots_surface->surface_commit.link);
- view_damage_whole(view);
-
- struct roots_view_child *child, *tmp;
- wl_list_for_each_safe(child, tmp, &view->children, link) {
- child->destroy(child);
- }
-
- if (view->fullscreen_output != NULL) {
- output_damage_whole(view->fullscreen_output);
- view->fullscreen_output->fullscreen_view = NULL;
- view->fullscreen_output = NULL;
- }
-
- view->wlr_surface = NULL;
- view->width = view->height = 0;
- wl_list_remove(&view->link);
+ view_unmap(view);
}
void handle_xwayland_surface(struct wl_listener *listener, void *data) {
@@ -317,7 +292,7 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
wl_signal_add(&surface->surface->events.commit,
&roots_surface->surface_commit);
- struct roots_view *view = view_create();
+ struct roots_view *view = view_create(desktop);
if (view == NULL) {
free(roots_surface);
return;
@@ -330,7 +305,6 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
view->xwayland_surface = surface;
view->roots_xwayland_surface = roots_surface;
- view->wlr_surface = surface->surface;
view->activate = activate;
view->resize = resize;
view->move = move;
@@ -338,9 +312,10 @@ void handle_xwayland_surface(struct wl_listener *listener, void *data) {
view->maximize = maximize;
view->set_fullscreen = set_fullscreen;
view->close = close;
+ view->destroy = destroy;
roots_surface->view = view;
- view_init(view, desktop);
- wl_list_insert(&desktop->views, &view->link);
+
+ view_map(view, surface->surface);
if (!surface->override_redirect) {
if (surface->decorations == WLR_XWAYLAND_SURFACE_DECORATIONS_ALL) {
diff --git a/types/meson.build b/types/meson.build
index 703b06ca..94993b52 100644
--- a/types/meson.build
+++ b/types/meson.build
@@ -6,10 +6,13 @@ lib_wlr_types = static_library(
'wlr_cursor.c',
'wlr_data_device.c',
'wlr_gamma_control.c',
+ 'wlr_idle_inhibit_v1.c',
'wlr_idle.c',
'wlr_input_device.c',
'wlr_keyboard.c',
+ 'wlr_linux_dmabuf.c',
'wlr_list.c',
+ 'wlr_matrix.c',
'wlr_output_damage.c',
'wlr_output_layout.c',
'wlr_output.c',
@@ -27,7 +30,6 @@ lib_wlr_types = static_library(
'wlr_xcursor_manager.c',
'wlr_xdg_shell_v6.c',
'wlr_xdg_shell.c',
- 'wlr_idle_inhibit_v1.c',
),
include_directories: wlr_inc,
dependencies: [pixman, xkbcommon, wayland_server, wlr_protos],
diff --git a/types/wlr_linux_dmabuf.c b/types/wlr_linux_dmabuf.c
new file mode 100644
index 00000000..1883bc49
--- /dev/null
+++ b/types/wlr_linux_dmabuf.c
@@ -0,0 +1,463 @@
+#ifndef _POSIX_C_SOURCE
+#define _POSIX_C_SOURCE 200809L
+#endif
+#include <assert.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <wayland-server.h>
+#include <wlr/render/egl.h>
+#include <wlr/types/wlr_linux_dmabuf.h>
+#include <wlr/util/log.h>
+#include "linux-dmabuf-unstable-v1-protocol.h"
+
+static void wl_buffer_destroy(struct wl_client *client,
+ struct wl_resource *resource) {
+ wl_resource_destroy(resource);
+}
+
+static const struct wl_buffer_interface wl_buffer_impl = {
+ wl_buffer_destroy,
+};
+
+bool wlr_dmabuf_buffer_has_inverted_y(struct wlr_dmabuf_buffer *dmabuf) {
+ return dmabuf->attributes.flags
+ & ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT;
+}
+
+bool wlr_dmabuf_resource_is_buffer(struct wl_resource *buffer_resource) {
+ if (!wl_resource_instance_of(buffer_resource, &wl_buffer_interface,
+ &wl_buffer_impl)) {
+ return false;
+ }
+
+ struct wlr_dmabuf_buffer *buffer = wl_resource_get_user_data(buffer_resource);
+ if (buffer && buffer->buffer_resource && !buffer->params_resource &&
+ buffer->buffer_resource == buffer_resource) {
+ return true;
+ }
+
+ return false;
+}
+
+struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_buffer_resource(
+ struct wl_resource *buffer_resource) {
+ assert(wl_resource_instance_of(buffer_resource, &wl_buffer_interface,
+ &wl_buffer_impl));
+
+ struct wlr_dmabuf_buffer *buffer = wl_resource_get_user_data(buffer_resource);
+ assert(buffer);
+ assert(buffer->buffer_resource);
+ assert(!buffer->params_resource);
+ assert(buffer->buffer_resource == buffer_resource);
+
+ return buffer;
+}
+
+static void linux_dmabuf_buffer_destroy(struct wlr_dmabuf_buffer *buffer) {
+ for (int i = 0; i < buffer->attributes.n_planes; i++) {
+ close(buffer->attributes.fd[i]);
+ buffer->attributes.fd[i] = -1;
+ }
+ buffer->attributes.n_planes = 0;
+ free(buffer);
+}
+
+static void params_destroy(struct wl_client *client, struct wl_resource *resource) {
+ wl_resource_destroy(resource);
+}
+
+static void params_add(struct wl_client *client,
+ struct wl_resource *params_resource, int32_t name_fd,
+ uint32_t plane_idx, uint32_t offset, uint32_t stride,
+ uint32_t modifier_hi, uint32_t modifier_lo) {
+ struct wlr_dmabuf_buffer *buffer = wlr_dmabuf_buffer_from_params_resource(
+ params_resource);
+
+ if (!buffer) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED,
+ "params was already used to create a wl_buffer");
+ close(name_fd);
+ return;
+ }
+
+ if (plane_idx >= WLR_LINUX_DMABUF_MAX_PLANES) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_IDX,
+ "plane index %u > %u", plane_idx, WLR_LINUX_DMABUF_MAX_PLANES);
+ close(name_fd);
+ return;
+ }
+
+ if (buffer->attributes.fd[plane_idx] != -1) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_PLANE_SET,
+ "a dmabuf with id %d has already been added for plane %u",
+ buffer->attributes.fd[plane_idx],
+ plane_idx);
+ close(name_fd);
+ return;
+ }
+
+ buffer->attributes.fd[plane_idx] = name_fd;
+ buffer->attributes.offset[plane_idx] = offset;
+ buffer->attributes.stride[plane_idx] = stride;
+ buffer->attributes.modifier[plane_idx] = ((uint64_t)modifier_hi << 32) |
+ modifier_lo;
+ buffer->attributes.n_planes++;
+}
+
+static void handle_buffer_destroy(struct wl_resource *buffer_resource)
+{
+ struct wlr_dmabuf_buffer *buffer = wlr_dmabuf_buffer_from_buffer_resource(
+ buffer_resource);
+
+ linux_dmabuf_buffer_destroy(buffer);
+}
+
+static void params_create_common(struct wl_client *client,
+ struct wl_resource *params_resource, uint32_t buffer_id, int32_t width,
+ int32_t height, uint32_t format, uint32_t flags) {
+ if (!wl_resource_get_user_data(params_resource)) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_ALREADY_USED,
+ "params was already used to create a wl_buffer");
+ return;
+ }
+ struct wlr_dmabuf_buffer *buffer = wlr_dmabuf_buffer_from_params_resource(
+ params_resource);
+
+ /* Switch the linux_dmabuf_buffer object from params resource to
+ * eventually wl_buffer resource. */
+ wl_resource_set_user_data(buffer->params_resource, NULL);
+ buffer->params_resource = NULL;
+
+ if (!buffer->attributes.n_planes) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
+ "no dmabuf has been added to the params");
+ goto err_out;
+ }
+
+ /* TODO: support more planes */
+ if (buffer->attributes.n_planes != 1) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
+ "only single plane buffers supported not %d",
+ buffer->attributes.n_planes);
+ goto err_out;
+ }
+
+ if (buffer->attributes.fd[0] == -1) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INCOMPLETE,
+ "no dmabuf has been added for plane");
+ goto err_out;
+ }
+
+ buffer->attributes.width = width;
+ buffer->attributes.height = height;
+ buffer->attributes.format = format;
+ buffer->attributes.flags = flags;
+
+ if (width < 1 || height < 1) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_DIMENSIONS,
+ "invalid width %d or height %d", width, height);
+ goto err_out;
+ }
+
+ if ((uint64_t)buffer->attributes.offset[0] + buffer->attributes.stride[0] > UINT32_MAX) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
+ "size overflow for plane");
+ goto err_out;
+ }
+
+ if ((uint64_t)buffer->attributes.offset[0] +
+ (uint64_t)buffer->attributes.stride[0] * height > UINT32_MAX) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
+ "size overflow for plane");
+ goto err_out;
+ }
+
+ off_t size = lseek(buffer->attributes.fd[0], 0, SEEK_END);
+ if (size != -1) { /* Skip checks if kernel does no support seek on buffer */
+ if (buffer->attributes.offset[0] >= size) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
+ "invalid offset %i for plane",
+ buffer->attributes.offset[0]);
+ goto err_out;
+ }
+
+ if (buffer->attributes.offset[0] + buffer->attributes.stride[0] > size) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
+ "invalid stride %i for plane",
+ buffer->attributes.stride[0]);
+ goto err_out;
+ }
+
+ if (buffer->attributes.offset[0] + buffer->attributes.stride[0] * height > size) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_OUT_OF_BOUNDS,
+ "invalid buffer stride or height for plane");
+ goto err_out;
+ }
+ }
+
+ /* reject unknown flags */
+ if (buffer->attributes.flags & ~ZWP_LINUX_BUFFER_PARAMS_V1_FLAGS_Y_INVERT) {
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_FORMAT,
+ "Unknown dmabuf flags %"PRIu32, buffer->attributes.flags);
+ goto err_out;
+ }
+
+ /* Check if dmabuf is usable */
+ if (!wlr_egl_check_import_dmabuf(buffer->egl, buffer)) {
+ goto err_failed;
+ }
+
+ buffer->buffer_resource = wl_resource_create(client, &wl_buffer_interface,
+ 1, buffer_id);
+ if (!buffer->buffer_resource) {
+ wl_resource_post_no_memory(params_resource);
+ goto err_failed;
+ }
+
+ wl_resource_set_implementation(buffer->buffer_resource,
+ &wl_buffer_impl, buffer, handle_buffer_destroy);
+
+ /* send 'created' event when the request is not for an immediate
+ * import, that is buffer_id is zero */
+ if (buffer_id == 0) {
+ zwp_linux_buffer_params_v1_send_created(params_resource,
+ buffer->buffer_resource);
+ }
+ return;
+
+err_failed:
+ if (buffer_id == 0) {
+ zwp_linux_buffer_params_v1_send_failed(params_resource);
+ } else {
+ /* since the behavior is left implementation defined by the
+ * protocol in case of create_immed failure due to an unknown cause,
+ * we choose to treat it as a fatal error and immediately kill the
+ * client instead of creating an invalid handle and waiting for it
+ * to be used.
+ */
+ wl_resource_post_error(params_resource,
+ ZWP_LINUX_BUFFER_PARAMS_V1_ERROR_INVALID_WL_BUFFER,
+ "importing the supplied dmabufs failed");
+ }
+err_out:
+ linux_dmabuf_buffer_destroy(buffer);
+ return;
+}
+
+static void params_create(struct wl_client *client,
+ struct wl_resource *params_resource,
+ int32_t width, int32_t height,uint32_t format, uint32_t flags) {
+ params_create_common(client, params_resource, 0, width, height, format, flags);
+}
+
+static void params_create_immed(struct wl_client *client,
+ struct wl_resource *params_resource, uint32_t buffer_id,
+ int32_t width, int32_t height,uint32_t format, uint32_t flags) {
+ params_create_common(client, params_resource, buffer_id, width, height, format, flags);
+}
+
+static const struct zwp_linux_buffer_params_v1_interface linux_buffer_params_impl = {
+ params_destroy,
+ params_add,
+ params_create,
+ params_create_immed,
+};
+
+struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_params_resource(
+ struct wl_resource *params_resource) {
+ assert(wl_resource_instance_of(params_resource,
+ &zwp_linux_buffer_params_v1_interface,
+ &linux_buffer_params_impl));
+
+ struct wlr_dmabuf_buffer *buffer = wl_resource_get_user_data(params_resource);
+ assert(buffer);
+ assert(buffer->params_resource);
+ assert(!buffer->buffer_resource);
+ assert(buffer->params_resource == params_resource);
+
+ return buffer;
+}
+
+static void handle_params_destroy(struct wl_resource *params_resource) {
+ /* Check for NULL since wlr_dmabuf_buffer_from_params_resource will choke */
+ if (!wl_resource_get_user_data(params_resource)) {
+ return;
+ }
+
+ struct wlr_dmabuf_buffer *buffer =
+ wlr_dmabuf_buffer_from_params_resource(params_resource);
+ linux_dmabuf_buffer_destroy(buffer);
+}
+
+static void linux_dmabuf_create_params(struct wl_client *client,
+ struct wl_resource *linux_dmabuf_resource,
+ uint32_t params_id) {
+ struct wlr_linux_dmabuf *linux_dmabuf = wlr_linux_dmabuf_from_resource(
+ linux_dmabuf_resource);
+
+ uint32_t version = wl_resource_get_version(linux_dmabuf_resource);
+ struct wlr_dmabuf_buffer *buffer = calloc(1, sizeof *buffer);
+ if (!buffer) {
+ goto err;
+ }
+
+ for (int i = 0; i < WLR_LINUX_DMABUF_MAX_PLANES; i++) {
+ buffer->attributes.fd[i] = -1;
+ }
+
+ buffer->egl = linux_dmabuf->egl;
+ buffer->params_resource = wl_resource_create(client,
+ &zwp_linux_buffer_params_v1_interface,
+ version, params_id);
+ if (!buffer->params_resource) {
+ goto err_free;
+ }
+
+ wl_resource_set_implementation(buffer->params_resource,
+ &linux_buffer_params_impl,buffer, handle_params_destroy);
+ return;
+
+err_free:
+ free(buffer);
+err:
+ wl_resource_post_no_memory(linux_dmabuf_resource);
+}
+
+static void linux_dmabuf_destroy(struct wl_client *client, struct wl_resource *resource) {
+ wl_resource_destroy(resource);
+}
+
+static const struct zwp_linux_dmabuf_v1_interface linux_dmabuf_impl = {
+ linux_dmabuf_destroy,
+ linux_dmabuf_create_params
+};
+
+struct wlr_linux_dmabuf *wlr_linux_dmabuf_from_resource(
+ struct wl_resource *resource) {
+ assert(wl_resource_instance_of(resource, &zwp_linux_dmabuf_v1_interface,
+ &linux_dmabuf_impl));
+
+ struct wlr_linux_dmabuf *dmabuf = wl_resource_get_user_data(resource);
+ assert(dmabuf);
+ return dmabuf;
+}
+
+static void linux_dmabuf_send_modifiers(struct wlr_linux_dmabuf *linux_dmabuf,
+ struct wl_resource *resource) {
+ struct wlr_egl *egl = linux_dmabuf->egl;
+ /*
+ * Use EGL_EXT_image_dma_buf_import_modifiers to query and advertise
+ * format/modifier codes.
+ */
+ uint64_t modifier_invalid = DRM_FORMAT_MOD_INVALID;
+ int *formats = NULL;
+ int num_formats = wlr_egl_get_dmabuf_formats(egl, &formats);
+
+ if (num_formats < 0) {
+ return;
+ }
+
+ for (int i = 0; i < num_formats; i++) {
+ int num_modifiers;
+ uint64_t *modifiers = NULL;
+
+ num_modifiers = wlr_egl_get_dmabuf_modifiers(egl, formats[i],
+ &modifiers);
+ if (num_modifiers < 0) {
+ return;
+ }
+ /* send DRM_FORMAT_MOD_INVALID token when no modifiers are supported
+ * for this format */
+ if (num_modifiers == 0) {
+ num_modifiers = 1;
+ modifiers = &modifier_invalid;
+ }
+ for (int j = 0; j < num_modifiers; j++) {
+ uint32_t modifier_lo = modifiers[j] & 0xFFFFFFFF;
+ uint32_t modifier_hi = modifiers[j] >> 32;
+ zwp_linux_dmabuf_v1_send_modifier(resource, formats[i],
+ modifier_hi,
+ modifier_lo);
+ }
+ if (modifiers != &modifier_invalid) {
+ free(modifiers);
+ }
+ }
+ free(formats);
+}
+
+static void linux_dmabuf_bind(struct wl_client *client,
+ void *data, uint32_t version, uint32_t id) {
+ struct wlr_linux_dmabuf *linux_dmabuf = data;
+ struct wl_resource *resource = wl_resource_create(client,
+ &zwp_linux_dmabuf_v1_interface,
+ version, id);
+
+ if (resource == NULL) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+
+ wl_resource_set_implementation(resource, &linux_dmabuf_impl,
+ linux_dmabuf, NULL);
+ if (version < ZWP_LINUX_DMABUF_V1_MODIFIER_SINCE_VERSION) {
+ return;
+ }
+
+ linux_dmabuf_send_modifiers(linux_dmabuf, resource);
+}
+
+void wlr_linux_dmabuf_destroy(struct wlr_linux_dmabuf *linux_dmabuf) {
+ if (!linux_dmabuf) {
+ return;
+ }
+ wl_list_remove(&linux_dmabuf->display_destroy.link);
+
+ wl_global_destroy(linux_dmabuf->wl_global);
+ free(linux_dmabuf);
+}
+
+static void handle_display_destroy(struct wl_listener *listener, void *data) {
+ struct wlr_linux_dmabuf *linux_dmabuf = wl_container_of(listener, linux_dmabuf, display_destroy);
+ wlr_linux_dmabuf_destroy(linux_dmabuf);
+}
+
+struct wlr_linux_dmabuf *wlr_linux_dmabuf_create(struct wl_display *display,
+ struct wlr_egl *egl) {
+ struct wlr_linux_dmabuf *linux_dmabuf =
+ calloc(1, sizeof(struct wlr_linux_dmabuf));
+ if (linux_dmabuf == NULL) {
+ wlr_log(L_ERROR, "could not create simple dmabuf manager");
+ return NULL;
+ }
+
+ linux_dmabuf->display_destroy.notify = handle_display_destroy;
+ wl_display_add_destroy_listener(display, &linux_dmabuf->display_destroy);
+
+ linux_dmabuf->wl_global =
+ wl_global_create(display, &zwp_linux_dmabuf_v1_interface,
+ 3, linux_dmabuf, linux_dmabuf_bind);
+
+ linux_dmabuf->egl = egl;
+ if (!linux_dmabuf->wl_global) {
+ wlr_log(L_ERROR, "could not create linux dmabuf v1 wl global");
+ free(linux_dmabuf);
+ return NULL;
+ }
+
+ return linux_dmabuf;
+}
diff --git a/types/wlr_matrix.c b/types/wlr_matrix.c
new file mode 100644
index 00000000..6eb47ca8
--- /dev/null
+++ b/types/wlr_matrix.c
@@ -0,0 +1,169 @@
+#include <math.h>
+#include <string.h>
+#include <wayland-server-protocol.h>
+#include <wlr/types/wlr_matrix.h>
+#include <wlr/types/wlr_box.h>
+#include <wlr/types/wlr_output.h>
+
+void wlr_matrix_identity(float mat[static 9]) {
+ static const float identity[9] = {
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ };
+ memcpy(mat, identity, sizeof(identity));
+}
+
+void wlr_matrix_multiply(float mat[static 9], const float a[static 9],
+ const float b[static 9]) {
+ float product[9];
+
+ product[0] = a[0]*b[0] + a[1]*b[3] + a[2]*b[6];
+ product[1] = a[0]*b[1] + a[1]*b[4] + a[2]*b[7];
+ product[2] = a[0]*b[2] + a[1]*b[5] + a[2]*b[8];
+
+ product[3] = a[3]*b[0] + a[4]*b[3] + a[5]*b[6];
+ product[4] = a[3]*b[1] + a[4]*b[4] + a[5]*b[7];
+ product[5] = a[3]*b[2] + a[4]*b[5] + a[5]*b[8];
+
+ product[6] = a[6]*b[0] + a[7]*b[3] + a[8]*b[6];
+ product[7] = a[6]*b[1] + a[7]*b[4] + a[8]*b[7];
+ product[8] = a[6]*b[2] + a[7]*b[5] + a[8]*b[8];
+
+ memcpy(mat, product, sizeof(product));
+}
+
+void wlr_matrix_transpose(float mat[static 9], const float a[static 9]) {
+ float transposition[9] = {
+ a[0], a[3], a[6],
+ a[1], a[4], a[7],
+ a[2], a[5], a[8],
+ };
+ memcpy(mat, transposition, sizeof(transposition));
+}
+
+void wlr_matrix_translate(float mat[static 9], float x, float y) {
+ float translate[9] = {
+ 1.0f, 0.0f, x,
+ 0.0f, 1.0f, y,
+ 0.0f, 0.0f, 1.0f,
+ };
+ wlr_matrix_multiply(mat, mat, translate);
+}
+
+void wlr_matrix_scale(float mat[static 9], float x, float y) {
+ float scale[9] = {
+ x, 0.0f, 0.0f,
+ 0.0f, y, 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ };
+ wlr_matrix_multiply(mat, mat, scale);
+}
+
+void wlr_matrix_rotate(float mat[static 9], float rad) {
+ float rotate[9] = {
+ cos(rad), -sin(rad), 0.0f,
+ sin(rad), cos(rad), 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ };
+ wlr_matrix_multiply(mat, mat, rotate);
+}
+
+static const float transforms[][9] = {
+ [WL_OUTPUT_TRANSFORM_NORMAL] = {
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ },
+ [WL_OUTPUT_TRANSFORM_90] = {
+ 0.0f, -1.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ },
+ [WL_OUTPUT_TRANSFORM_180] = {
+ -1.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ },
+ [WL_OUTPUT_TRANSFORM_270] = {
+ 0.0f, 1.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ },
+ [WL_OUTPUT_TRANSFORM_FLIPPED] = {
+ -1.0f, 0.0f, 0.0f,
+ 0.0f, 1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ },
+ [WL_OUTPUT_TRANSFORM_FLIPPED_90] = {
+ 0.0f, -1.0f, 0.0f,
+ -1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ },
+ [WL_OUTPUT_TRANSFORM_FLIPPED_180] = {
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, -1.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ },
+ [WL_OUTPUT_TRANSFORM_FLIPPED_270] = {
+ 0.0f, 1.0f, 0.0f,
+ 1.0f, 0.0f, 0.0f,
+ 0.0f, 0.0f, 1.0f,
+ },
+};
+
+void wlr_matrix_transform(float mat[static 9],
+ enum wl_output_transform transform) {
+ wlr_matrix_multiply(mat, mat, transforms[transform]);
+}
+
+// Equivilent to glOrtho(0, width, 0, height, 1, -1) with the transform applied
+void wlr_matrix_projection(float mat[static 9], int width, int height,
+ enum wl_output_transform transform) {
+ memset(mat, 0, sizeof(*mat) * 9);
+
+ const float *t = transforms[transform];
+ float x = 2.0f / width;
+ float y = 2.0f / height;
+
+ // Rotation + reflection
+ mat[0] = x * t[0];
+ mat[1] = x * t[1];
+ mat[3] = y * -t[3];
+ mat[4] = y * -t[4];
+
+ // Translation
+ mat[2] = -copysign(1.0f, mat[0] + mat[1]);
+ mat[5] = -copysign(1.0f, mat[3] + mat[4]);
+
+ // Identity
+ mat[8] = 1.0f;
+}
+
+void wlr_matrix_project_box(float mat[static 9], const struct wlr_box *box,
+ enum wl_output_transform transform, float rotation,
+ const float projection[static 9]) {
+ int x = box->x;
+ int y = box->y;
+ int width = box->width;
+ int height = box->height;
+
+ wlr_matrix_identity(mat);
+ wlr_matrix_translate(mat, x, y);
+
+ if (rotation != 0) {
+ wlr_matrix_translate(mat, width/2, height/2);
+ wlr_matrix_rotate(mat, rotation);
+ wlr_matrix_translate(mat, -width/2, -height/2);
+ }
+
+ wlr_matrix_scale(mat, width, height);
+
+ if (transform != WL_OUTPUT_TRANSFORM_NORMAL) {
+ wlr_matrix_translate(mat, 0.5, 0.5);
+ wlr_matrix_transform(mat, transform);
+ wlr_matrix_translate(mat, -0.5, -0.5);
+ }
+
+ wlr_matrix_multiply(mat, projection, mat);
+}
diff --git a/types/wlr_output.c b/types/wlr_output.c
index 7f19d1fe..e30c3b78 100644
--- a/types/wlr_output.c
+++ b/types/wlr_output.c
@@ -6,8 +6,8 @@
#include <time.h>
#include <wayland-server.h>
#include <wlr/interfaces/wlr_output.h>
-#include <wlr/render.h>
-#include <wlr/render/matrix.h>
+#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_box.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_surface.h>
@@ -139,8 +139,8 @@ void wlr_output_update_enabled(struct wlr_output *output, bool enabled) {
}
static void wlr_output_update_matrix(struct wlr_output *output) {
- wlr_matrix_texture(output->transform_matrix, output->width, output->height,
- output->transform);
+ wlr_matrix_projection(output->transform_matrix, output->width,
+ output->height, output->transform);
}
void wlr_output_enable(struct wlr_output *output, bool enable) {
@@ -368,25 +368,25 @@ static void output_fullscreen_surface_render(struct wlr_output *output,
assert(renderer);
if (!wlr_surface_has_buffer(surface)) {
- wlr_renderer_clear(renderer, &(float[]){0, 0, 0, 0});
+ wlr_renderer_clear(renderer, (float[]){0, 0, 0, 0});
return;
}
struct wlr_box box;
output_fullscreen_surface_get_box(output, surface, &box);
- float matrix[16];
+ float matrix[9];
enum wl_output_transform transform =
wlr_output_transform_invert(surface->current->transform);
- wlr_matrix_project_box(&matrix, &box, transform, 0,
- &output->transform_matrix);
+ wlr_matrix_project_box(matrix, &box, transform, 0,
+ output->transform_matrix);
int nrects;
pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects);
for (int i = 0; i < nrects; ++i) {
output_scissor(output, &rects[i]);
- wlr_renderer_clear(renderer, &(float[]){0, 0, 0, 0});
- wlr_render_with_matrix(surface->renderer, surface->texture, &matrix, 1.0f);
+ wlr_renderer_clear(renderer, (float[]){0, 0, 0, 0});
+ wlr_render_texture_with_matrix(surface->renderer, surface->texture, matrix, 1.0f);
}
wlr_renderer_scissor(renderer, NULL);
@@ -435,15 +435,15 @@ static void output_cursor_render(struct wlr_output_cursor *cursor,
goto surface_damage_finish;
}
- float matrix[16];
- wlr_matrix_project_box(&matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
- &cursor->output->transform_matrix);
+ float matrix[9];
+ wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
+ cursor->output->transform_matrix);
int nrects;
pixman_box32_t *rects = pixman_region32_rectangles(&surface_damage, &nrects);
for (int i = 0; i < nrects; ++i) {
output_scissor(cursor->output, &rects[i]);
- wlr_render_with_matrix(renderer, texture, &matrix, 1.0f);
+ wlr_render_texture_with_matrix(renderer, texture, matrix, 1.0f);
}
wlr_renderer_scissor(renderer, NULL);
diff --git a/types/wlr_pointer.c b/types/wlr_pointer.c
index bc9efd8c..9d5dc08c 100644
--- a/types/wlr_pointer.c
+++ b/types/wlr_pointer.c
@@ -14,7 +14,10 @@ void wlr_pointer_init(struct wlr_pointer *pointer,
}
void wlr_pointer_destroy(struct wlr_pointer *pointer) {
- if (pointer && pointer->impl && pointer->impl->destroy) {
+ if (!pointer) {
+ return;
+ }
+ if (pointer->impl && pointer->impl->destroy) {
pointer->impl->destroy(pointer);
} else {
wl_list_remove(&pointer->events.motion.listener_list);
diff --git a/types/wlr_screenshooter.c b/types/wlr_screenshooter.c
index e756b6aa..e1386be6 100644
--- a/types/wlr_screenshooter.c
+++ b/types/wlr_screenshooter.c
@@ -3,7 +3,7 @@
#include <string.h>
#include <wayland-server.h>
#include <wlr/backend.h>
-#include <wlr/render.h>
+#include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_output.h>
#include <wlr/types/wlr_screenshooter.h>
#include <wlr/util/log.h>
diff --git a/types/wlr_surface.c b/types/wlr_surface.c
index 23966cd1..b3e0dcd8 100644
--- a/types/wlr_surface.c
+++ b/types/wlr_surface.c
@@ -3,7 +3,7 @@
#include <wayland-server.h>
#include <wlr/render/egl.h>
#include <wlr/render/interface.h>
-#include <wlr/render/matrix.h>
+#include <wlr/types/wlr_matrix.h>
#include <wlr/types/wlr_region.h>
#include <wlr/types/wlr_surface.h>
#include <wlr/util/log.h>
@@ -325,6 +325,10 @@ static void wlr_surface_apply_damage(struct wlr_surface *surface,
surface->current->buffer)) {
wlr_texture_upload_drm(surface->texture, surface->current->buffer);
goto release;
+ } else if (wlr_dmabuf_resource_is_buffer(
+ surface->current->buffer)) {
+ wlr_texture_upload_dmabuf(surface->texture, surface->current->buffer);
+ goto release;
} else {
wlr_log(L_INFO, "Unknown buffer handle attached");
return;
@@ -624,22 +628,6 @@ struct wlr_surface *wlr_surface_create(struct wl_resource *res,
return surface;
}
-void wlr_surface_get_matrix(struct wlr_surface *surface,
- float (*matrix)[16],
- const float (*projection)[16],
- const float (*transform)[16]) {
- int width = surface->texture->width;
- int height = surface->texture->height;
- float scale[16];
- wlr_matrix_identity(matrix);
- if (transform) {
- wlr_matrix_mul(matrix, transform, matrix);
- }
- wlr_matrix_scale(&scale, width, height, 1);
- wlr_matrix_mul(matrix, &scale, matrix);
- wlr_matrix_mul(projection, matrix, matrix);
-}
-
bool wlr_surface_has_buffer(struct wlr_surface *surface) {
return surface->texture && surface->texture->valid;
}
diff --git a/types/wlr_xdg_shell.c b/types/wlr_xdg_shell.c
index 990926cf..f01d81a5 100644
--- a/types/wlr_xdg_shell.c
+++ b/types/wlr_xdg_shell.c
@@ -34,7 +34,7 @@ struct wlr_xdg_positioner {
};
-static void resource_destroy(struct wl_client *client,
+static void resource_handle_destroy(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}
@@ -131,6 +131,24 @@ static const struct wlr_keyboard_grab_interface xdg_keyboard_grab_impl = {
.cancel = xdg_keyboard_grab_cancel,
};
+static void xdg_surface_destroy(struct wlr_xdg_surface *surface);
+
+static void wlr_xdg_popup_grab_handle_seat_destroy(
+ struct wl_listener *listener, void *data) {
+ struct wlr_xdg_popup_grab *xdg_grab =
+ wl_container_of(listener, xdg_grab, seat_destroy);
+
+ wl_list_remove(&xdg_grab->seat_destroy.link);
+
+ struct wlr_xdg_popup *popup, *next;
+ wl_list_for_each_safe(popup, next, &xdg_grab->popups, grab_link) {
+ xdg_surface_destroy(popup->base);
+ }
+
+ wl_list_remove(&xdg_grab->link);
+ free(xdg_grab);
+}
+
static struct wlr_xdg_popup_grab *xdg_shell_popup_grab_from_seat(
struct wlr_xdg_shell *shell, struct wlr_seat *seat) {
struct wlr_xdg_popup_grab *xdg_grab;
@@ -155,47 +173,44 @@ static struct wlr_xdg_popup_grab *xdg_shell_popup_grab_from_seat(
wl_list_insert(&shell->popup_grabs, &xdg_grab->link);
xdg_grab->seat = seat;
+ xdg_grab->seat_destroy.notify = wlr_xdg_popup_grab_handle_seat_destroy;
+ wl_signal_add(&seat->events.destroy, &xdg_grab->seat_destroy);
+
return xdg_grab;
}
-static void xdg_surface_destroy(struct wlr_xdg_surface *surface) {
- // TODO: probably need to ungrab before this event
- wlr_signal_emit_safe(&surface->events.destroy, surface);
-
- if (surface->configure_idle) {
- wl_event_source_remove(surface->configure_idle);
+static void xdg_surface_configure_destroy(
+ struct wlr_xdg_surface_configure *configure) {
+ if (configure == NULL) {
+ return;
}
+ wl_list_remove(&configure->link);
+ free(configure->toplevel_state);
+ free(configure);
+}
- struct wlr_xdg_surface_configure *configure, *tmp;
- wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) {
- free(configure);
- }
+static void xdg_surface_unmap(struct wlr_xdg_surface *surface) {
+ assert(surface->role != WLR_XDG_SURFACE_ROLE_NONE);
+
+ // TODO: probably need to ungrab before this event
+ wlr_signal_emit_safe(&surface->events.unmap, surface);
if (surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL) {
- wl_resource_set_user_data(surface->toplevel_state->resource, NULL);
- free(surface->toplevel_state);
+ wl_resource_set_user_data(surface->toplevel->resource, NULL);
+ free(surface->toplevel);
+ surface->toplevel = NULL;
}
if (surface->role == WLR_XDG_SURFACE_ROLE_POPUP) {
- wl_resource_set_user_data(surface->popup_state->resource, NULL);
+ wl_resource_set_user_data(surface->popup->resource, NULL);
- if (surface->popup_state->seat) {
+ if (surface->popup->seat) {
struct wlr_xdg_popup_grab *grab =
xdg_shell_popup_grab_from_seat(surface->client->shell,
- surface->popup_state->seat);
+ surface->popup->seat);
- struct wlr_xdg_surface *topmost =
- xdg_popup_grab_get_topmost(grab);
-
- if (topmost != surface) {
- wl_resource_post_error(surface->client->resource,
- XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP,
- "xdg_popup was destroyed while it was not the topmost "
- "popup.");
- }
-
- wl_list_remove(&surface->popup_state->grab_link);
+ wl_list_remove(&surface->popup->grab_link);
if (wl_list_empty(&grab->popups)) {
if (grab->seat->pointer_state.grab == &grab->pointer_grab) {
@@ -207,18 +222,46 @@ static void xdg_surface_destroy(struct wlr_xdg_surface *surface) {
}
}
- wl_list_remove(&surface->popup_state->link);
- free(surface->popup_state);
+ wl_list_remove(&surface->popup->link);
+ free(surface->popup);
+ surface->popup = NULL;
}
+ struct wlr_xdg_surface_configure *configure, *tmp;
+ wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) {
+ xdg_surface_configure_destroy(configure);
+ }
+
+ surface->role = WLR_XDG_SURFACE_ROLE_NONE;
+ free(surface->title);
+ surface->title = NULL;
+ free(surface->app_id);
+ surface->app_id = NULL;
+
+ surface->added = surface->configured = surface->mapped = false;
+ surface->configure_serial = 0;
+ if (surface->configure_idle) {
+ wl_event_source_remove(surface->configure_idle);
+ surface->configure_idle = NULL;
+ }
+ surface->configure_next_serial = 0;
+
+ surface->has_next_geometry = false;
+ memset(&surface->geometry, 0, sizeof(struct wlr_box));
+ memset(&surface->next_geometry, 0, sizeof(struct wlr_box));
+}
+
+static void xdg_surface_destroy(struct wlr_xdg_surface *surface) {
+ if (surface->role != WLR_XDG_SURFACE_ROLE_NONE) {
+ xdg_surface_unmap(surface);
+ }
+
+ wlr_signal_emit_safe(&surface->events.destroy, surface);
+
wl_resource_set_user_data(surface->resource, NULL);
wl_list_remove(&surface->link);
wl_list_remove(&surface->surface_destroy_listener.link);
wlr_surface_set_role_committed(surface->surface, NULL, NULL);
- free(surface->geometry);
- free(surface->next_geometry);
- free(surface->title);
- free(surface->app_id);
free(surface);
}
@@ -238,7 +281,7 @@ static void xdg_positioner_destroy(struct wl_resource *resource) {
free(positioner);
}
-static void xdg_positioner_protocol_set_size(struct wl_client *client,
+static void xdg_positioner_handle_set_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_positioner *positioner =
xdg_positioner_from_resource(resource);
@@ -254,7 +297,7 @@ static void xdg_positioner_protocol_set_size(struct wl_client *client,
positioner->size.height = height;
}
-static void xdg_positioner_protocol_set_anchor_rect(struct wl_client *client,
+static void xdg_positioner_handle_set_anchor_rect(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y, int32_t width,
int32_t height) {
struct wlr_xdg_positioner *positioner =
@@ -273,7 +316,7 @@ static void xdg_positioner_protocol_set_anchor_rect(struct wl_client *client,
positioner->anchor_rect.height = height;
}
-static void xdg_positioner_protocol_set_anchor(struct wl_client *client,
+static void xdg_positioner_handle_set_anchor(struct wl_client *client,
struct wl_resource *resource, uint32_t anchor) {
struct wlr_xdg_positioner *positioner =
xdg_positioner_from_resource(resource);
@@ -288,7 +331,7 @@ static void xdg_positioner_protocol_set_anchor(struct wl_client *client,
positioner->anchor = anchor;
}
-static void xdg_positioner_protocol_set_gravity(struct wl_client *client,
+static void xdg_positioner_handle_set_gravity(struct wl_client *client,
struct wl_resource *resource, uint32_t gravity) {
struct wlr_xdg_positioner *positioner =
xdg_positioner_from_resource(resource);
@@ -303,7 +346,7 @@ static void xdg_positioner_protocol_set_gravity(struct wl_client *client,
positioner->gravity = gravity;
}
-static void xdg_positioner_protocol_set_constraint_adjustment(
+static void xdg_positioner_handle_set_constraint_adjustment(
struct wl_client *client, struct wl_resource *resource,
uint32_t constraint_adjustment) {
struct wlr_xdg_positioner *positioner =
@@ -312,7 +355,7 @@ static void xdg_positioner_protocol_set_constraint_adjustment(
positioner->constraint_adjustment = constraint_adjustment;
}
-static void xdg_positioner_protocol_set_offset(struct wl_client *client,
+static void xdg_positioner_handle_set_offset(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y) {
struct wlr_xdg_positioner *positioner =
xdg_positioner_from_resource(resource);
@@ -323,17 +366,17 @@ static void xdg_positioner_protocol_set_offset(struct wl_client *client,
static const struct xdg_positioner_interface
xdg_positioner_implementation = {
- .destroy = resource_destroy,
- .set_size = xdg_positioner_protocol_set_size,
- .set_anchor_rect = xdg_positioner_protocol_set_anchor_rect,
- .set_anchor = xdg_positioner_protocol_set_anchor,
- .set_gravity = xdg_positioner_protocol_set_gravity,
+ .destroy = resource_handle_destroy,
+ .set_size = xdg_positioner_handle_set_size,
+ .set_anchor_rect = xdg_positioner_handle_set_anchor_rect,
+ .set_anchor = xdg_positioner_handle_set_anchor,
+ .set_gravity = xdg_positioner_handle_set_gravity,
.set_constraint_adjustment =
- xdg_positioner_protocol_set_constraint_adjustment,
- .set_offset = xdg_positioner_protocol_set_offset,
+ xdg_positioner_handle_set_constraint_adjustment,
+ .set_offset = xdg_positioner_handle_set_offset,
};
-static void xdg_shell_create_positioner(struct wl_client *wl_client,
+static void xdg_shell_handle_create_positioner(struct wl_client *wl_client,
struct wl_resource *resource, uint32_t id) {
struct wlr_xdg_positioner *positioner =
calloc(1, sizeof(struct wlr_xdg_positioner));
@@ -458,7 +501,7 @@ static struct wlr_xdg_surface *xdg_surface_from_xdg_popup_resource(
return wl_resource_get_user_data(resource);
}
-static void xdg_popup_protocol_grab(struct wl_client *client,
+static void xdg_popup_handle_grab(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial) {
struct wlr_xdg_surface *surface =
@@ -466,8 +509,8 @@ static void xdg_popup_protocol_grab(struct wl_client *client,
struct wlr_seat_client *seat_client =
wlr_seat_client_from_resource(seat_resource);
- if (surface->popup_state->committed) {
- wl_resource_post_error(surface->popup_state->resource,
+ if (surface->popup->committed) {
+ wl_resource_post_error(surface->popup->resource,
XDG_POPUP_ERROR_INVALID_GRAB,
"xdg_popup is already mapped");
return;
@@ -479,10 +522,10 @@ static void xdg_popup_protocol_grab(struct wl_client *client,
struct wlr_xdg_surface *topmost = xdg_popup_grab_get_topmost(popup_grab);
bool parent_is_toplevel =
- surface->popup_state->parent->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL;
+ surface->popup->parent->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL;
if ((topmost == NULL && !parent_is_toplevel) ||
- (topmost != NULL && topmost != surface->popup_state->parent)) {
+ (topmost != NULL && topmost != surface->popup->parent)) {
wl_resource_post_error(surface->client->resource,
XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP,
"xdg_popup was not created on the topmost popup");
@@ -490,9 +533,9 @@ static void xdg_popup_protocol_grab(struct wl_client *client,
}
popup_grab->client = surface->client->client;
- surface->popup_state->seat = seat_client->seat;
+ surface->popup->seat = seat_client->seat;
- wl_list_insert(&popup_grab->popups, &surface->popup_state->grab_link);
+ wl_list_insert(&popup_grab->popups, &surface->popup->grab_link);
wlr_seat_pointer_start_grab(seat_client->seat,
&popup_grab->pointer_grab);
@@ -500,16 +543,36 @@ static void xdg_popup_protocol_grab(struct wl_client *client,
&popup_grab->keyboard_grab);
}
+static void xdg_popup_handle_destroy(struct wl_client *client,
+ struct wl_resource *resource) {
+ struct wlr_xdg_surface *surface =
+ xdg_surface_from_xdg_popup_resource(resource);
+ struct wlr_xdg_popup_grab *grab =
+ xdg_shell_popup_grab_from_seat(surface->client->shell,
+ surface->popup->seat);
+ struct wlr_xdg_surface *topmost =
+ xdg_popup_grab_get_topmost(grab);
+
+ if (topmost != surface) {
+ wl_resource_post_error(surface->client->resource,
+ XDG_WM_BASE_ERROR_NOT_THE_TOPMOST_POPUP,
+ "xdg_popup was destroyed while it was not the topmost popup");
+ return;
+ }
+
+ wl_resource_destroy(resource);
+}
+
static const struct xdg_popup_interface xdg_popup_implementation = {
- .destroy = resource_destroy,
- .grab = xdg_popup_protocol_grab,
+ .destroy = xdg_popup_handle_destroy,
+ .grab = xdg_popup_handle_grab,
};
static void xdg_popup_resource_destroy(struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_popup_resource(resource);
if (surface != NULL) {
- xdg_surface_destroy(surface);
+ xdg_surface_unmap(surface);
}
}
@@ -522,7 +585,7 @@ static struct wlr_xdg_surface *xdg_surface_from_resource(
return wl_resource_get_user_data(resource);
}
-static void xdg_surface_get_popup(struct wl_client *client,
+static void xdg_surface_handle_get_popup(struct wl_client *client,
struct wl_resource *resource, uint32_t id,
struct wl_resource *parent_resource,
struct wl_resource *positioner_resource) {
@@ -545,33 +608,33 @@ static void xdg_surface_get_popup(struct wl_client *client,
return;
}
- surface->popup_state = calloc(1, sizeof(struct wlr_xdg_popup));
- if (!surface->popup_state) {
+ surface->popup = calloc(1, sizeof(struct wlr_xdg_popup));
+ if (!surface->popup) {
wl_resource_post_no_memory(resource);
return;
}
- surface->popup_state->resource =
+ surface->popup->resource =
wl_resource_create(client, &xdg_popup_interface,
wl_resource_get_version(resource), id);
- if (surface->popup_state->resource == NULL) {
- free(surface->popup_state);
+ if (surface->popup->resource == NULL) {
+ free(surface->popup);
wl_resource_post_no_memory(resource);
return;
}
surface->role = WLR_XDG_SURFACE_ROLE_POPUP;
- surface->popup_state->base = surface;
- surface->popup_state->parent = parent;
- surface->popup_state->geometry =
+ surface->popup->base = surface;
+ surface->popup->parent = parent;
+ surface->popup->geometry =
xdg_positioner_get_geometry(positioner, surface, parent);
- wl_list_insert(&parent->popups, &surface->popup_state->link);
+ wl_list_insert(&parent->popups, &surface->popup->link);
- wl_resource_set_implementation(surface->popup_state->resource,
+ wl_resource_set_implementation(surface->popup->resource,
&xdg_popup_implementation, surface,
xdg_popup_resource_destroy);
- wlr_signal_emit_safe(&parent->events.new_popup, surface->popup_state);
+ wlr_signal_emit_safe(&parent->events.new_popup, surface->popup);
}
@@ -584,7 +647,7 @@ static struct wlr_xdg_surface *xdg_surface_from_xdg_toplevel_resource(
return wl_resource_get_user_data(resource);
}
-static void xdg_toplevel_protocol_set_parent(struct wl_client *client,
+static void xdg_toplevel_handle_set_parent(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *parent_resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
@@ -594,10 +657,10 @@ static void xdg_toplevel_protocol_set_parent(struct wl_client *client,
parent = xdg_surface_from_xdg_toplevel_resource(parent_resource);
}
- surface->toplevel_state->parent = parent;
+ surface->toplevel->parent = parent;
}
-static void xdg_toplevel_protocol_set_title(struct wl_client *client,
+static void xdg_toplevel_handle_set_title(struct wl_client *client,
struct wl_resource *resource, const char *title) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
@@ -612,7 +675,7 @@ static void xdg_toplevel_protocol_set_title(struct wl_client *client,
surface->title = tmp;
}
-static void xdg_toplevel_protocol_set_app_id(struct wl_client *client,
+static void xdg_toplevel_handle_set_app_id(struct wl_client *client,
struct wl_resource *resource, const char *app_id) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
@@ -627,7 +690,7 @@ static void xdg_toplevel_protocol_set_app_id(struct wl_client *client,
surface->app_id = tmp;
}
-static void xdg_toplevel_protocol_show_window_menu(struct wl_client *client,
+static void xdg_toplevel_handle_show_window_menu(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial, int32_t x, int32_t y) {
struct wlr_xdg_surface *surface =
@@ -636,7 +699,7 @@ static void xdg_toplevel_protocol_show_window_menu(struct wl_client *client,
wlr_seat_client_from_resource(seat_resource);
if (!surface->configured) {
- wl_resource_post_error(surface->toplevel_state->resource,
+ wl_resource_post_error(surface->toplevel->resource,
XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
"surface has not been configured yet");
return;
@@ -658,7 +721,7 @@ static void xdg_toplevel_protocol_show_window_menu(struct wl_client *client,
wlr_signal_emit_safe(&surface->events.request_show_window_menu, &event);
}
-static void xdg_toplevel_protocol_move(struct wl_client *client,
+static void xdg_toplevel_handle_move(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial) {
struct wlr_xdg_surface *surface =
@@ -667,7 +730,7 @@ static void xdg_toplevel_protocol_move(struct wl_client *client,
wlr_seat_client_from_resource(seat_resource);
if (!surface->configured) {
- wl_resource_post_error(surface->toplevel_state->resource,
+ wl_resource_post_error(surface->toplevel->resource,
XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
"surface has not been configured yet");
return;
@@ -687,7 +750,7 @@ static void xdg_toplevel_protocol_move(struct wl_client *client,
wlr_signal_emit_safe(&surface->events.request_move, &event);
}
-static void xdg_toplevel_protocol_resize(struct wl_client *client,
+static void xdg_toplevel_handle_resize(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial, uint32_t edges) {
struct wlr_xdg_surface *surface =
@@ -696,7 +759,7 @@ static void xdg_toplevel_protocol_resize(struct wl_client *client,
wlr_seat_client_from_resource(seat_resource);
if (!surface->configured) {
- wl_resource_post_error(surface->toplevel_state->resource,
+ wl_resource_post_error(surface->toplevel->resource,
XDG_SURFACE_ERROR_NOT_CONSTRUCTED,
"surface has not been configured yet");
return;
@@ -717,39 +780,39 @@ static void xdg_toplevel_protocol_resize(struct wl_client *client,
wlr_signal_emit_safe(&surface->events.request_resize, &event);
}
-static void xdg_toplevel_protocol_set_max_size(struct wl_client *client,
+static void xdg_toplevel_handle_set_max_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
- surface->toplevel_state->next.max_width = width;
- surface->toplevel_state->next.max_height = height;
+ surface->toplevel->next.max_width = width;
+ surface->toplevel->next.max_height = height;
}
-static void xdg_toplevel_protocol_set_min_size(struct wl_client *client,
+static void xdg_toplevel_handle_set_min_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
- surface->toplevel_state->next.min_width = width;
- surface->toplevel_state->next.min_height = height;
+ surface->toplevel->next.min_width = width;
+ surface->toplevel->next.min_height = height;
}
-static void xdg_toplevel_protocol_set_maximized(struct wl_client *client,
+static void xdg_toplevel_handle_set_maximized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
- surface->toplevel_state->next.maximized = true;
+ surface->toplevel->next.maximized = true;
wlr_signal_emit_safe(&surface->events.request_maximize, surface);
}
-static void xdg_toplevel_protocol_unset_maximized(struct wl_client *client,
+static void xdg_toplevel_handle_unset_maximized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
- surface->toplevel_state->next.maximized = false;
+ surface->toplevel->next.maximized = false;
wlr_signal_emit_safe(&surface->events.request_maximize, surface);
}
-static void xdg_toplevel_protocol_set_fullscreen(struct wl_client *client,
+static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *output_resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
@@ -759,7 +822,7 @@ static void xdg_toplevel_protocol_set_fullscreen(struct wl_client *client,
output = wlr_output_from_resource(output_resource);
}
- surface->toplevel_state->next.fullscreen = true;
+ surface->toplevel->next.fullscreen = true;
struct wlr_xdg_toplevel_set_fullscreen_event event = {
.surface = surface,
@@ -770,12 +833,12 @@ static void xdg_toplevel_protocol_set_fullscreen(struct wl_client *client,
wlr_signal_emit_safe(&surface->events.request_fullscreen, &event);
}
-static void xdg_toplevel_protocol_unset_fullscreen(struct wl_client *client,
+static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
- surface->toplevel_state->next.fullscreen = false;
+ surface->toplevel->next.fullscreen = false;
struct wlr_xdg_toplevel_set_fullscreen_event event = {
.surface = surface,
@@ -786,7 +849,7 @@ static void xdg_toplevel_protocol_unset_fullscreen(struct wl_client *client,
wlr_signal_emit_safe(&surface->events.request_fullscreen, &event);
}
-static void xdg_toplevel_protocol_set_minimized(struct wl_client *client,
+static void xdg_toplevel_handle_set_minimized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
@@ -794,20 +857,20 @@ static void xdg_toplevel_protocol_set_minimized(struct wl_client *client,
}
static const struct xdg_toplevel_interface xdg_toplevel_implementation = {
- .destroy = resource_destroy,
- .set_parent = xdg_toplevel_protocol_set_parent,
- .set_title = xdg_toplevel_protocol_set_title,
- .set_app_id = xdg_toplevel_protocol_set_app_id,
- .show_window_menu = xdg_toplevel_protocol_show_window_menu,
- .move = xdg_toplevel_protocol_move,
- .resize = xdg_toplevel_protocol_resize,
- .set_max_size = xdg_toplevel_protocol_set_max_size,
- .set_min_size = xdg_toplevel_protocol_set_min_size,
- .set_maximized = xdg_toplevel_protocol_set_maximized,
- .unset_maximized = xdg_toplevel_protocol_unset_maximized,
- .set_fullscreen = xdg_toplevel_protocol_set_fullscreen,
- .unset_fullscreen = xdg_toplevel_protocol_unset_fullscreen,
- .set_minimized = xdg_toplevel_protocol_set_minimized
+ .destroy = resource_handle_destroy,
+ .set_parent = xdg_toplevel_handle_set_parent,
+ .set_title = xdg_toplevel_handle_set_title,
+ .set_app_id = xdg_toplevel_handle_set_app_id,
+ .show_window_menu = xdg_toplevel_handle_show_window_menu,
+ .move = xdg_toplevel_handle_move,
+ .resize = xdg_toplevel_handle_resize,
+ .set_max_size = xdg_toplevel_handle_set_max_size,
+ .set_min_size = xdg_toplevel_handle_set_min_size,
+ .set_maximized = xdg_toplevel_handle_set_maximized,
+ .unset_maximized = xdg_toplevel_handle_unset_maximized,
+ .set_fullscreen = xdg_toplevel_handle_set_fullscreen,
+ .unset_fullscreen = xdg_toplevel_handle_unset_fullscreen,
+ .set_minimized = xdg_toplevel_handle_set_minimized,
};
static void xdg_surface_resource_destroy(struct wl_resource *resource) {
@@ -822,11 +885,11 @@ static void xdg_toplevel_resource_destroy(struct wl_resource *resource) {
struct wlr_xdg_surface *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
if (surface != NULL) {
- xdg_surface_destroy(surface);
+ xdg_surface_unmap(surface);
}
}
-static void xdg_surface_get_toplevel(struct wl_client *client,
+static void xdg_surface_handle_get_toplevel(struct wl_client *client,
struct wl_resource *resource, uint32_t id) {
struct wlr_xdg_surface *surface = xdg_surface_from_resource(resource);
@@ -835,24 +898,24 @@ static void xdg_surface_get_toplevel(struct wl_client *client,
return;
}
- surface->toplevel_state = calloc(1, sizeof(struct wlr_xdg_toplevel));
- if (surface->toplevel_state == NULL) {
+ surface->toplevel = calloc(1, sizeof(struct wlr_xdg_toplevel));
+ if (surface->toplevel == NULL) {
wl_resource_post_no_memory(resource);
return;
}
surface->role = WLR_XDG_SURFACE_ROLE_TOPLEVEL;
- surface->toplevel_state->base = surface;
+ surface->toplevel->base = surface;
struct wl_resource *toplevel_resource = wl_resource_create(client,
&xdg_toplevel_interface, wl_resource_get_version(resource), id);
if (toplevel_resource == NULL) {
- free(surface->toplevel_state);
+ free(surface->toplevel);
wl_resource_post_no_memory(resource);
return;
}
- surface->toplevel_state->resource = toplevel_resource;
+ surface->toplevel->resource = toplevel_resource;
wl_resource_set_implementation(toplevel_resource,
&xdg_toplevel_implementation, surface,
@@ -863,12 +926,19 @@ static void wlr_xdg_toplevel_ack_configure(
struct wlr_xdg_surface *surface,
struct wlr_xdg_surface_configure *configure) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
- surface->toplevel_state->next = configure->state;
- surface->toplevel_state->pending.width = 0;
- surface->toplevel_state->pending.height = 0;
+ assert(configure->toplevel_state != NULL);
+
+ surface->toplevel->current.maximized =
+ configure->toplevel_state->maximized;
+ surface->toplevel->current.fullscreen =
+ configure->toplevel_state->fullscreen;
+ surface->toplevel->current.resizing =
+ configure->toplevel_state->resizing;
+ surface->toplevel->current.activated =
+ configure->toplevel_state->activated;
}
-static void xdg_surface_ack_configure(struct wl_client *client,
+static void xdg_surface_handle_ack_configure(struct wl_client *client,
struct wl_resource *resource, uint32_t serial) {
struct wlr_xdg_surface *surface = xdg_surface_from_resource(resource);
@@ -883,10 +953,8 @@ static void xdg_surface_ack_configure(struct wl_client *client,
struct wlr_xdg_surface_configure *configure, *tmp;
wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) {
if (configure->serial < serial) {
- wl_list_remove(&configure->link);
- free(configure);
+ xdg_surface_configure_destroy(configure);
} else if (configure->serial == serial) {
- wl_list_remove(&configure->link);
found = true;
break;
} else {
@@ -914,10 +982,10 @@ static void xdg_surface_ack_configure(struct wl_client *client,
surface->configured = true;
surface->configure_serial = serial;
- free(configure);
+ xdg_surface_configure_destroy(configure);
}
-static void xdg_surface_set_window_geometry(struct wl_client *client,
+static void xdg_surface_handle_set_window_geometry(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y, int32_t width,
int32_t height) {
struct wlr_xdg_surface *surface = xdg_surface_from_resource(resource);
@@ -930,19 +998,31 @@ static void xdg_surface_set_window_geometry(struct wl_client *client,
}
surface->has_next_geometry = true;
- surface->next_geometry->height = height;
- surface->next_geometry->width = width;
- surface->next_geometry->x = x;
- surface->next_geometry->y = y;
+ surface->next_geometry.height = height;
+ surface->next_geometry.width = width;
+ surface->next_geometry.x = x;
+ surface->next_geometry.y = y;
+}
+static void xdg_surface_handle_destroy(struct wl_client *client,
+ struct wl_resource *resource) {
+ struct wlr_xdg_surface *surface = xdg_surface_from_resource(resource);
+
+ if (surface->role != WLR_XDG_SURFACE_ROLE_NONE) {
+ wlr_log(L_ERROR, "Tried to destroy an xdg_surface before its role "
+ "object");
+ return;
+ }
+
+ wl_resource_destroy(resource);
}
static const struct xdg_surface_interface xdg_surface_implementation = {
- .destroy = resource_destroy,
- .get_toplevel = xdg_surface_get_toplevel,
- .get_popup = xdg_surface_get_popup,
- .ack_configure = xdg_surface_ack_configure,
- .set_window_geometry = xdg_surface_set_window_geometry,
+ .destroy = xdg_surface_handle_destroy,
+ .get_toplevel = xdg_surface_handle_get_toplevel,
+ .get_popup = xdg_surface_handle_get_popup,
+ .ack_configure = xdg_surface_handle_ack_configure,
+ .set_window_geometry = xdg_surface_handle_set_window_geometry,
};
static bool wlr_xdg_surface_toplevel_state_compare(
@@ -965,9 +1045,9 @@ static bool wlr_xdg_surface_toplevel_state_compare(
} else {
struct wlr_xdg_surface_configure *configure =
wl_container_of(state->base->configure_list.prev, configure, link);
- configured.state = configure->state;
- configured.width = configure->state.width;
- configured.height = configure->state.height;
+ configured.state = *configure->toplevel_state;
+ configured.width = configure->toplevel_state->width;
+ configured.height = configure->toplevel_state->height;
}
if (state->pending.activated != configured.state.activated) {
@@ -999,13 +1079,19 @@ static void wlr_xdg_toplevel_send_configure(
struct wlr_xdg_surface *surface,
struct wlr_xdg_surface_configure *configure) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
- uint32_t *s;
- struct wl_array states;
- configure->state = surface->toplevel_state->pending;
+ configure->toplevel_state = malloc(sizeof(*configure->toplevel_state));
+ if (configure->toplevel_state == NULL) {
+ wlr_log(L_ERROR, "Allocation failed");
+ wl_resource_post_no_memory(surface->toplevel->resource);
+ return;
+ }
+ *configure->toplevel_state = surface->toplevel->pending;
+ uint32_t *s;
+ struct wl_array states;
wl_array_init(&states);
- if (surface->toplevel_state->pending.maximized) {
+ if (surface->toplevel->pending.maximized) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for maximized xdg_toplevel");
@@ -1013,7 +1099,7 @@ static void wlr_xdg_toplevel_send_configure(
}
*s = XDG_TOPLEVEL_STATE_MAXIMIZED;
}
- if (surface->toplevel_state->pending.fullscreen) {
+ if (surface->toplevel->pending.fullscreen) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for fullscreen xdg_toplevel");
@@ -1021,7 +1107,7 @@ static void wlr_xdg_toplevel_send_configure(
}
*s = XDG_TOPLEVEL_STATE_FULLSCREEN;
}
- if (surface->toplevel_state->pending.resizing) {
+ if (surface->toplevel->pending.resizing) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for resizing xdg_toplevel");
@@ -1029,7 +1115,7 @@ static void wlr_xdg_toplevel_send_configure(
}
*s = XDG_TOPLEVEL_STATE_RESIZING;
}
- if (surface->toplevel_state->pending.activated) {
+ if (surface->toplevel->pending.activated) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for activated xdg_toplevel");
@@ -1038,23 +1124,17 @@ static void wlr_xdg_toplevel_send_configure(
*s = XDG_TOPLEVEL_STATE_ACTIVATED;
}
- uint32_t width = surface->toplevel_state->pending.width;
- uint32_t height = surface->toplevel_state->pending.height;
-
- if (width == 0 || height == 0) {
- width = surface->geometry->width;
- height = surface->geometry->height;
- }
-
- xdg_toplevel_send_configure(surface->toplevel_state->resource, width,
- height, &states);
+ uint32_t width = surface->toplevel->pending.width;
+ uint32_t height = surface->toplevel->pending.height;
+ xdg_toplevel_send_configure(surface->toplevel->resource, width, height,
+ &states);
wl_array_release(&states);
return;
error_out:
wl_array_release(&states);
- wl_resource_post_no_memory(surface->toplevel_state->resource);
+ wl_resource_post_no_memory(surface->toplevel->resource);
}
static void wlr_xdg_surface_send_configure(void *user_data) {
@@ -1080,11 +1160,11 @@ static void wlr_xdg_surface_send_configure(void *user_data) {
wlr_xdg_toplevel_send_configure(surface, configure);
break;
case WLR_XDG_SURFACE_ROLE_POPUP:
- xdg_popup_send_configure(surface->popup_state->resource,
- surface->popup_state->geometry.x,
- surface->popup_state->geometry.y,
- surface->popup_state->geometry.width,
- surface->popup_state->geometry.height);
+ xdg_popup_send_configure(surface->popup->resource,
+ surface->popup->geometry.x,
+ surface->popup->geometry.y,
+ surface->popup->geometry.width,
+ surface->popup->geometry.height);
break;
}
@@ -1103,7 +1183,7 @@ static uint32_t wlr_xdg_surface_schedule_configure(
break;
case WLR_XDG_SURFACE_ROLE_TOPLEVEL:
pending_same =
- wlr_xdg_surface_toplevel_state_compare(surface->toplevel_state);
+ wlr_xdg_surface_toplevel_state_compare(surface->toplevel);
break;
case WLR_XDG_SURFACE_ROLE_POPUP:
break;
@@ -1143,29 +1223,32 @@ static void wlr_xdg_surface_toplevel_committed(
struct wlr_xdg_surface *surface) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
- if (!wlr_surface_has_buffer(surface->surface)
- && !surface->toplevel_state->added) {
+ if (!surface->toplevel->added) {
// on the first commit, send a configure request to tell the client it
// is added
wlr_xdg_surface_schedule_configure(surface);
- surface->toplevel_state->added = true;
- return;
- }
-
- if (!wlr_surface_has_buffer(surface->surface)) {
+ surface->toplevel->added = true;
return;
}
- surface->toplevel_state->current = surface->toplevel_state->next;
+ // update state that doesn't need compositor approval
+ surface->toplevel->current.max_width =
+ surface->toplevel->next.max_width;
+ surface->toplevel->current.min_width =
+ surface->toplevel->next.min_width;
+ surface->toplevel->current.max_height =
+ surface->toplevel->next.max_height;
+ surface->toplevel->current.min_height =
+ surface->toplevel->next.min_height;
}
static void wlr_xdg_surface_popup_committed(
struct wlr_xdg_surface *surface) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_POPUP);
- if (!surface->popup_state->committed) {
+ if (!surface->popup->committed) {
wlr_xdg_surface_schedule_configure(surface);
- surface->popup_state->committed = true;
+ surface->popup->committed = true;
}
}
@@ -1182,10 +1265,10 @@ static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface,
if (surface->has_next_geometry) {
surface->has_next_geometry = false;
- surface->geometry->x = surface->next_geometry->x;
- surface->geometry->y = surface->next_geometry->y;
- surface->geometry->width = surface->next_geometry->width;
- surface->geometry->height = surface->next_geometry->height;
+ surface->geometry.x = surface->next_geometry.x;
+ surface->geometry.y = surface->next_geometry.y;
+ surface->geometry.width = surface->next_geometry.width;
+ surface->geometry.height = surface->next_geometry.height;
}
switch (surface->role) {
@@ -1202,9 +1285,19 @@ static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface,
break;
}
- if (surface->configured && !surface->added) {
+ if (!surface->added) {
surface->added = true;
- wlr_signal_emit_safe(&surface->client->shell->events.new_surface, surface);
+ wlr_signal_emit_safe(&surface->client->shell->events.new_surface,
+ surface);
+ }
+ if (surface->configured && wlr_surface_has_buffer(surface->surface) &&
+ !surface->mapped) {
+ surface->mapped = true;
+ wlr_signal_emit_safe(&surface->events.map, surface);
+ }
+ if (surface->configured && !wlr_surface_has_buffer(surface->surface) &&
+ surface->mapped) {
+ xdg_surface_unmap(surface);
}
}
@@ -1217,27 +1310,15 @@ static struct wlr_xdg_client *xdg_client_from_resource(
return wl_resource_get_user_data(resource);
}
-static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
+static void xdg_shell_handle_get_xdg_surface(struct wl_client *wl_client,
struct wl_resource *client_resource, uint32_t id,
struct wl_resource *surface_resource) {
struct wlr_xdg_client *client =
xdg_client_from_resource(client_resource);
- struct wlr_xdg_surface *surface;
- if (!(surface = calloc(1, sizeof(struct wlr_xdg_surface)))) {
- wl_client_post_no_memory(wl_client);
- return;
- }
-
- if (!(surface->geometry = calloc(1, sizeof(struct wlr_box)))) {
- free(surface);
- wl_client_post_no_memory(wl_client);
- return;
- }
-
- if (!(surface->next_geometry = calloc(1, sizeof(struct wlr_box)))) {
- free(surface->geometry);
- free(surface);
+ struct wlr_xdg_surface *surface =
+ calloc(1, sizeof(struct wlr_xdg_surface));
+ if (surface == NULL) {
wl_client_post_no_memory(wl_client);
return;
}
@@ -1249,8 +1330,6 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
&xdg_surface_interface, wl_resource_get_version(client_resource),
id);
if (surface->resource == NULL) {
- free(surface->next_geometry);
- free(surface->geometry);
free(surface);
wl_client_post_no_memory(wl_client);
return;
@@ -1258,8 +1337,6 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
if (wlr_surface_has_buffer(surface->surface)) {
wl_resource_destroy(surface->resource);
- free(surface->next_geometry);
- free(surface->geometry);
free(surface);
wl_resource_post_error(surface_resource,
XDG_SURFACE_ERROR_UNCONFIGURED_BUFFER,
@@ -1279,6 +1356,8 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
wl_signal_init(&surface->events.destroy);
wl_signal_init(&surface->events.ping_timeout);
wl_signal_init(&surface->events.new_popup);
+ wl_signal_init(&surface->events.map);
+ wl_signal_init(&surface->events.unmap);
wl_signal_add(&surface->surface->events.destroy,
&surface->surface_destroy_listener);
@@ -1293,7 +1372,7 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
wl_list_insert(&client->surfaces, &surface->link);
}
-static void xdg_shell_pong(struct wl_client *wl_client,
+static void xdg_shell_handle_pong(struct wl_client *wl_client,
struct wl_resource *resource, uint32_t serial) {
struct wlr_xdg_client *client = xdg_client_from_resource(resource);
@@ -1305,11 +1384,25 @@ static void xdg_shell_pong(struct wl_client *wl_client,
client->ping_serial = 0;
}
+static void xdg_shell_handle_destroy(struct wl_client *wl_client,
+ struct wl_resource *resource) {
+ struct wlr_xdg_client *client = xdg_client_from_resource(resource);
+
+ if (!wl_list_empty(&client->surfaces)) {
+ wl_resource_post_error(client->resource,
+ XDG_WM_BASE_ERROR_DEFUNCT_SURFACES,
+ "xdg_wm_base was destroyed before children");
+ return;
+ }
+
+ wl_resource_destroy(resource);
+}
+
static const struct xdg_wm_base_interface xdg_shell_impl = {
- .destroy = resource_destroy,
- .create_positioner = xdg_shell_create_positioner,
- .get_xdg_surface = xdg_shell_get_xdg_surface,
- .pong = xdg_shell_pong,
+ .destroy = xdg_shell_handle_destroy,
+ .create_positioner = xdg_shell_handle_create_positioner,
+ .get_xdg_surface = xdg_shell_handle_get_xdg_surface,
+ .pong = xdg_shell_handle_pong,
};
static void wlr_xdg_client_destroy(struct wl_resource *resource) {
@@ -1437,8 +1530,8 @@ void wlr_xdg_surface_ping(struct wlr_xdg_surface *surface) {
uint32_t wlr_xdg_toplevel_set_size(struct wlr_xdg_surface *surface,
uint32_t width, uint32_t height) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
- surface->toplevel_state->pending.width = width;
- surface->toplevel_state->pending.height = height;
+ surface->toplevel->pending.width = width;
+ surface->toplevel->pending.height = height;
return wlr_xdg_surface_schedule_configure(surface);
}
@@ -1446,7 +1539,7 @@ uint32_t wlr_xdg_toplevel_set_size(struct wlr_xdg_surface *surface,
uint32_t wlr_xdg_toplevel_set_activated(struct wlr_xdg_surface *surface,
bool activated) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
- surface->toplevel_state->pending.activated = activated;
+ surface->toplevel->pending.activated = activated;
return wlr_xdg_surface_schedule_configure(surface);
}
@@ -1454,7 +1547,7 @@ uint32_t wlr_xdg_toplevel_set_activated(struct wlr_xdg_surface *surface,
uint32_t wlr_xdg_toplevel_set_maximized(struct wlr_xdg_surface *surface,
bool maximized) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
- surface->toplevel_state->pending.maximized = maximized;
+ surface->toplevel->pending.maximized = maximized;
return wlr_xdg_surface_schedule_configure(surface);
}
@@ -1462,7 +1555,7 @@ uint32_t wlr_xdg_toplevel_set_maximized(struct wlr_xdg_surface *surface,
uint32_t wlr_xdg_toplevel_set_fullscreen(struct wlr_xdg_surface *surface,
bool fullscreen) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
- surface->toplevel_state->pending.fullscreen = fullscreen;
+ surface->toplevel->pending.fullscreen = fullscreen;
return wlr_xdg_surface_schedule_configure(surface);
}
@@ -1470,24 +1563,24 @@ uint32_t wlr_xdg_toplevel_set_fullscreen(struct wlr_xdg_surface *surface,
uint32_t wlr_xdg_toplevel_set_resizing(struct wlr_xdg_surface *surface,
bool resizing) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
- surface->toplevel_state->pending.resizing = resizing;
+ surface->toplevel->pending.resizing = resizing;
return wlr_xdg_surface_schedule_configure(surface);
}
void wlr_xdg_toplevel_send_close(struct wlr_xdg_surface *surface) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_TOPLEVEL);
- xdg_toplevel_send_close(surface->toplevel_state->resource);
+ xdg_toplevel_send_close(surface->toplevel->resource);
}
void wlr_xdg_surface_popup_get_position(struct wlr_xdg_surface *surface,
double *popup_sx, double *popup_sy) {
assert(surface->role == WLR_XDG_SURFACE_ROLE_POPUP);
- struct wlr_xdg_surface *parent = surface->popup_state->parent;
- *popup_sx = parent->geometry->x + surface->popup_state->geometry.x -
- surface->geometry->x;
- *popup_sy = parent->geometry->y + surface->popup_state->geometry.y -
- surface->geometry->y;
+ struct wlr_xdg_surface *parent = surface->popup->parent;
+ *popup_sx = parent->geometry.x + surface->popup->geometry.x -
+ surface->geometry.x;
+ *popup_sy = parent->geometry.y + surface->popup->geometry.y -
+ surface->geometry.y;
}
struct wlr_xdg_surface *wlr_xdg_surface_popup_at(
@@ -1501,30 +1594,30 @@ struct wlr_xdg_surface *wlr_xdg_surface_popup_at(
struct wlr_xdg_surface *popup = popup_state->base;
double _popup_sx =
- surface->geometry->x + popup_state->geometry.x;
+ surface->geometry.x + popup_state->geometry.x;
double _popup_sy =
- surface->geometry->y + popup_state->geometry.y;
+ surface->geometry.y + popup_state->geometry.y;
int popup_width = popup_state->geometry.width;
int popup_height = popup_state->geometry.height;
struct wlr_xdg_surface *_popup =
wlr_xdg_surface_popup_at(popup,
- sx - _popup_sx + popup->geometry->x,
- sy - _popup_sy + popup->geometry->y,
+ sx - _popup_sx + popup->geometry.x,
+ sy - _popup_sy + popup->geometry.y,
popup_sx, popup_sy);
if (_popup) {
- *popup_sx = *popup_sx + _popup_sx - popup->geometry->x;
- *popup_sy = *popup_sy + _popup_sy - popup->geometry->y;
+ *popup_sx = *popup_sx + _popup_sx - popup->geometry.x;
+ *popup_sy = *popup_sy + _popup_sy - popup->geometry.y;
return _popup;
}
if ((sx > _popup_sx && sx < _popup_sx + popup_width) &&
(sy > _popup_sy && sy < _popup_sy + popup_height)) {
if (pixman_region32_contains_point(&popup->surface->current->input,
- sx - _popup_sx + popup->geometry->x,
- sy - _popup_sy + popup->geometry->y, NULL)) {
- *popup_sx = _popup_sx - popup->geometry->x;
- *popup_sy = _popup_sy - popup->geometry->y;
+ sx - _popup_sx + popup->geometry.x,
+ sy - _popup_sy + popup->geometry.y, NULL)) {
+ *popup_sx = _popup_sx - popup->geometry.x;
+ *popup_sy = _popup_sy - popup->geometry.y;
return popup;
}
}
diff --git a/types/wlr_xdg_shell_v6.c b/types/wlr_xdg_shell_v6.c
index c75e5857..0e9419b4 100644
--- a/types/wlr_xdg_shell_v6.c
+++ b/types/wlr_xdg_shell_v6.c
@@ -13,8 +13,8 @@
#include "util/signal.h"
#include "xdg-shell-unstable-v6-protocol.h"
-static const char *wlr_desktop_xdg_toplevel_role = "xdg_toplevel";
-static const char *wlr_desktop_xdg_popup_role = "xdg_popup";
+static const char *wlr_desktop_xdg_toplevel_role = "xdg_toplevel_v6";
+static const char *wlr_desktop_xdg_popup_role = "xdg_popup_v6";
struct wlr_xdg_positioner_v6 {
struct wl_resource *resource;
@@ -34,7 +34,7 @@ struct wlr_xdg_positioner_v6 {
};
-static void resource_destroy(struct wl_client *client,
+static void resource_handle_destroy(struct wl_client *client,
struct wl_resource *resource) {
wl_resource_destroy(resource);
}
@@ -131,6 +131,24 @@ static const struct wlr_keyboard_grab_interface xdg_keyboard_grab_impl = {
.cancel = xdg_keyboard_grab_cancel,
};
+static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface);
+
+static void wlr_xdg_popup_grab_handle_seat_destroy(
+ struct wl_listener *listener, void *data) {
+ struct wlr_xdg_popup_grab_v6 *xdg_grab =
+ wl_container_of(listener, xdg_grab, seat_destroy);
+
+ wl_list_remove(&xdg_grab->seat_destroy.link);
+
+ struct wlr_xdg_popup_v6 *popup, *next;
+ wl_list_for_each_safe(popup, next, &xdg_grab->popups, grab_link) {
+ xdg_surface_destroy(popup->base);
+ }
+
+ wl_list_remove(&xdg_grab->link);
+ free(xdg_grab);
+}
+
static struct wlr_xdg_popup_grab_v6 *xdg_shell_popup_grab_from_seat(
struct wlr_xdg_shell_v6 *shell, struct wlr_seat *seat) {
struct wlr_xdg_popup_grab_v6 *xdg_grab;
@@ -155,47 +173,44 @@ static struct wlr_xdg_popup_grab_v6 *xdg_shell_popup_grab_from_seat(
wl_list_insert(&shell->popup_grabs, &xdg_grab->link);
xdg_grab->seat = seat;
+ xdg_grab->seat_destroy.notify = wlr_xdg_popup_grab_handle_seat_destroy;
+ wl_signal_add(&seat->events.destroy, &xdg_grab->seat_destroy);
+
return xdg_grab;
}
-static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) {
- // TODO: probably need to ungrab before this event
- wlr_signal_emit_safe(&surface->events.destroy, surface);
-
- if (surface->configure_idle) {
- wl_event_source_remove(surface->configure_idle);
+static void xdg_surface_configure_destroy(
+ struct wlr_xdg_surface_v6_configure *configure) {
+ if (configure == NULL) {
+ return;
}
+ wl_list_remove(&configure->link);
+ free(configure->toplevel_state);
+ free(configure);
+}
- struct wlr_xdg_surface_v6_configure *configure, *tmp;
- wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) {
- free(configure);
- }
+static void xdg_surface_unmap(struct wlr_xdg_surface_v6 *surface) {
+ assert(surface->role != WLR_XDG_SURFACE_V6_ROLE_NONE);
+
+ // TODO: probably need to ungrab before this event
+ wlr_signal_emit_safe(&surface->events.unmap, surface);
if (surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL) {
- wl_resource_set_user_data(surface->toplevel_state->resource, NULL);
- free(surface->toplevel_state);
+ wl_resource_set_user_data(surface->toplevel->resource, NULL);
+ free(surface->toplevel);
+ surface->toplevel = NULL;
}
if (surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP) {
- wl_resource_set_user_data(surface->popup_state->resource, NULL);
+ wl_resource_set_user_data(surface->popup->resource, NULL);
- if (surface->popup_state->seat) {
+ if (surface->popup->seat) {
struct wlr_xdg_popup_grab_v6 *grab =
xdg_shell_popup_grab_from_seat(surface->client->shell,
- surface->popup_state->seat);
+ surface->popup->seat);
- struct wlr_xdg_surface_v6 *topmost =
- xdg_popup_grab_get_topmost(grab);
-
- if (topmost != surface) {
- wl_resource_post_error(surface->client->resource,
- ZXDG_SHELL_V6_ERROR_NOT_THE_TOPMOST_POPUP,
- "xdg_popup was destroyed while it was not the topmost "
- "popup.");
- }
-
- wl_list_remove(&surface->popup_state->grab_link);
+ wl_list_remove(&surface->popup->grab_link);
if (wl_list_empty(&grab->popups)) {
if (grab->seat->pointer_state.grab == &grab->pointer_grab) {
@@ -207,18 +222,46 @@ static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) {
}
}
- wl_list_remove(&surface->popup_state->link);
- free(surface->popup_state);
+ wl_list_remove(&surface->popup->link);
+ free(surface->popup);
+ surface->popup = NULL;
}
+ struct wlr_xdg_surface_v6_configure *configure, *tmp;
+ wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) {
+ xdg_surface_configure_destroy(configure);
+ }
+
+ surface->role = WLR_XDG_SURFACE_V6_ROLE_NONE;
+ free(surface->title);
+ surface->title = NULL;
+ free(surface->app_id);
+ surface->app_id = NULL;
+
+ surface->added = surface->configured = surface->mapped = false;
+ surface->configure_serial = 0;
+ if (surface->configure_idle) {
+ wl_event_source_remove(surface->configure_idle);
+ surface->configure_idle = NULL;
+ }
+ surface->configure_next_serial = 0;
+
+ surface->has_next_geometry = false;
+ memset(&surface->geometry, 0, sizeof(struct wlr_box));
+ memset(&surface->next_geometry, 0, sizeof(struct wlr_box));
+}
+
+static void xdg_surface_destroy(struct wlr_xdg_surface_v6 *surface) {
+ if (surface->role != WLR_XDG_SURFACE_V6_ROLE_NONE) {
+ xdg_surface_unmap(surface);
+ }
+
+ wlr_signal_emit_safe(&surface->events.destroy, surface);
+
wl_resource_set_user_data(surface->resource, NULL);
wl_list_remove(&surface->link);
wl_list_remove(&surface->surface_destroy_listener.link);
wlr_surface_set_role_committed(surface->surface, NULL, NULL);
- free(surface->geometry);
- free(surface->next_geometry);
- free(surface->title);
- free(surface->app_id);
free(surface);
}
@@ -237,10 +280,9 @@ static void xdg_positioner_destroy(struct wl_resource *resource) {
struct wlr_xdg_positioner_v6 *positioner =
xdg_positioner_from_resource(resource);
free(positioner);
-
}
-static void xdg_positioner_protocol_set_size(struct wl_client *client,
+static void xdg_positioner_handle_set_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_positioner_v6 *positioner =
xdg_positioner_from_resource(resource);
@@ -256,7 +298,7 @@ static void xdg_positioner_protocol_set_size(struct wl_client *client,
positioner->size.height = height;
}
-static void xdg_positioner_protocol_set_anchor_rect(struct wl_client *client,
+static void xdg_positioner_handle_set_anchor_rect(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y, int32_t width,
int32_t height) {
struct wlr_xdg_positioner_v6 *positioner =
@@ -275,7 +317,7 @@ static void xdg_positioner_protocol_set_anchor_rect(struct wl_client *client,
positioner->anchor_rect.height = height;
}
-static void xdg_positioner_protocol_set_anchor(struct wl_client *client,
+static void xdg_positioner_handle_set_anchor(struct wl_client *client,
struct wl_resource *resource, uint32_t anchor) {
struct wlr_xdg_positioner_v6 *positioner =
xdg_positioner_from_resource(resource);
@@ -293,7 +335,7 @@ static void xdg_positioner_protocol_set_anchor(struct wl_client *client,
positioner->anchor = anchor;
}
-static void xdg_positioner_protocol_set_gravity(struct wl_client *client,
+static void xdg_positioner_handle_set_gravity(struct wl_client *client,
struct wl_resource *resource, uint32_t gravity) {
struct wlr_xdg_positioner_v6 *positioner =
xdg_positioner_from_resource(resource);
@@ -311,7 +353,7 @@ static void xdg_positioner_protocol_set_gravity(struct wl_client *client,
positioner->gravity = gravity;
}
-static void xdg_positioner_protocol_set_constraint_adjustment(
+static void xdg_positioner_handle_set_constraint_adjustment(
struct wl_client *client, struct wl_resource *resource,
uint32_t constraint_adjustment) {
struct wlr_xdg_positioner_v6 *positioner =
@@ -320,7 +362,7 @@ static void xdg_positioner_protocol_set_constraint_adjustment(
positioner->constraint_adjustment = constraint_adjustment;
}
-static void xdg_positioner_protocol_set_offset(struct wl_client *client,
+static void xdg_positioner_handle_set_offset(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y) {
struct wlr_xdg_positioner_v6 *positioner =
xdg_positioner_from_resource(resource);
@@ -331,17 +373,17 @@ static void xdg_positioner_protocol_set_offset(struct wl_client *client,
static const struct zxdg_positioner_v6_interface
zxdg_positioner_v6_implementation = {
- .destroy = resource_destroy,
- .set_size = xdg_positioner_protocol_set_size,
- .set_anchor_rect = xdg_positioner_protocol_set_anchor_rect,
- .set_anchor = xdg_positioner_protocol_set_anchor,
- .set_gravity = xdg_positioner_protocol_set_gravity,
+ .destroy = resource_handle_destroy,
+ .set_size = xdg_positioner_handle_set_size,
+ .set_anchor_rect = xdg_positioner_handle_set_anchor_rect,
+ .set_anchor = xdg_positioner_handle_set_anchor,
+ .set_gravity = xdg_positioner_handle_set_gravity,
.set_constraint_adjustment =
- xdg_positioner_protocol_set_constraint_adjustment,
- .set_offset = xdg_positioner_protocol_set_offset,
+ xdg_positioner_handle_set_constraint_adjustment,
+ .set_offset = xdg_positioner_handle_set_offset,
};
-static void xdg_shell_create_positioner(struct wl_client *wl_client,
+static void xdg_shell_handle_create_positioner(struct wl_client *wl_client,
struct wl_resource *resource, uint32_t id) {
struct wlr_xdg_positioner_v6 *positioner =
calloc(1, sizeof(struct wlr_xdg_positioner_v6));
@@ -430,7 +472,7 @@ static struct wlr_xdg_surface_v6 *xdg_surface_from_xdg_popup_resource(
return wl_resource_get_user_data(resource);
}
-static void xdg_popup_protocol_grab(struct wl_client *client,
+static void xdg_popup_handle_grab(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial) {
struct wlr_xdg_surface_v6 *surface =
@@ -438,8 +480,8 @@ static void xdg_popup_protocol_grab(struct wl_client *client,
struct wlr_seat_client *seat_client =
wlr_seat_client_from_resource(seat_resource);
- if (surface->popup_state->committed) {
- wl_resource_post_error(surface->popup_state->resource,
+ if (surface->popup->committed) {
+ wl_resource_post_error(surface->popup->resource,
ZXDG_POPUP_V6_ERROR_INVALID_GRAB,
"xdg_popup is already mapped");
return;
@@ -451,10 +493,10 @@ static void xdg_popup_protocol_grab(struct wl_client *client,
struct wlr_xdg_surface_v6 *topmost = xdg_popup_grab_get_topmost(popup_grab);
bool parent_is_toplevel =
- surface->popup_state->parent->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL;
+ surface->popup->parent->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL;
if ((topmost == NULL && !parent_is_toplevel) ||
- (topmost != NULL && topmost != surface->popup_state->parent)) {
+ (topmost != NULL && topmost != surface->popup->parent)) {
wl_resource_post_error(surface->client->resource,
ZXDG_SHELL_V6_ERROR_NOT_THE_TOPMOST_POPUP,
"xdg_popup was not created on the topmost popup");
@@ -462,9 +504,9 @@ static void xdg_popup_protocol_grab(struct wl_client *client,
}
popup_grab->client = surface->client->client;
- surface->popup_state->seat = seat_client->seat;
+ surface->popup->seat = seat_client->seat;
- wl_list_insert(&popup_grab->popups, &surface->popup_state->grab_link);
+ wl_list_insert(&popup_grab->popups, &surface->popup->grab_link);
wlr_seat_pointer_start_grab(seat_client->seat,
&popup_grab->pointer_grab);
@@ -472,16 +514,36 @@ static void xdg_popup_protocol_grab(struct wl_client *client,
&popup_grab->keyboard_grab);
}
+static void xdg_popup_handle_destroy(struct wl_client *client,
+ struct wl_resource *resource) {
+ struct wlr_xdg_surface_v6 *surface =
+ xdg_surface_from_xdg_popup_resource(resource);
+ struct wlr_xdg_popup_grab_v6 *grab =
+ xdg_shell_popup_grab_from_seat(surface->client->shell,
+ surface->popup->seat);
+ struct wlr_xdg_surface_v6 *topmost =
+ xdg_popup_grab_get_topmost(grab);
+
+ if (topmost != surface) {
+ wl_resource_post_error(surface->client->resource,
+ ZXDG_SHELL_V6_ERROR_NOT_THE_TOPMOST_POPUP,
+ "xdg_popup was destroyed while it was not the topmost popup");
+ return;
+ }
+
+ wl_resource_destroy(resource);
+}
+
static const struct zxdg_popup_v6_interface zxdg_popup_v6_implementation = {
- .destroy = resource_destroy,
- .grab = xdg_popup_protocol_grab,
+ .destroy = xdg_popup_handle_destroy,
+ .grab = xdg_popup_handle_grab,
};
static void xdg_popup_resource_destroy(struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_popup_resource(resource);
if (surface != NULL) {
- xdg_surface_destroy(surface);
+ xdg_surface_unmap(surface);
}
}
@@ -494,7 +556,7 @@ static struct wlr_xdg_surface_v6 *xdg_surface_from_resource(
return wl_resource_get_user_data(resource);
}
-static void xdg_surface_get_popup(struct wl_client *client,
+static void xdg_surface_handle_get_popup(struct wl_client *client,
struct wl_resource *resource, uint32_t id,
struct wl_resource *parent_resource,
struct wl_resource *positioner_resource) {
@@ -517,39 +579,39 @@ static void xdg_surface_get_popup(struct wl_client *client,
return;
}
- surface->popup_state = calloc(1, sizeof(struct wlr_xdg_popup_v6));
- if (!surface->popup_state) {
+ surface->popup = calloc(1, sizeof(struct wlr_xdg_popup_v6));
+ if (!surface->popup) {
wl_resource_post_no_memory(resource);
return;
}
- surface->popup_state->resource =
+ surface->popup->resource =
wl_resource_create(client, &zxdg_popup_v6_interface,
wl_resource_get_version(resource), id);
- if (surface->popup_state->resource == NULL) {
- free(surface->popup_state);
+ if (surface->popup->resource == NULL) {
+ free(surface->popup);
wl_resource_post_no_memory(resource);
return;
}
surface->role = WLR_XDG_SURFACE_V6_ROLE_POPUP;
- surface->popup_state->base = surface;
- surface->popup_state->parent = parent;
- surface->popup_state->geometry =
+ surface->popup->base = surface;
+ surface->popup->parent = parent;
+ surface->popup->geometry =
xdg_positioner_get_geometry(positioner, surface, parent);
// positioner properties
- surface->popup_state->anchor = (uint32_t)positioner->anchor;
- surface->popup_state->gravity = (uint32_t)positioner->gravity;
- surface->popup_state->constraint_adjustment = (uint32_t)positioner->constraint_adjustment;
+ surface->popup->anchor = (uint32_t)positioner->anchor;
+ surface->popup->gravity = (uint32_t)positioner->gravity;
+ surface->popup->constraint_adjustment = (uint32_t)positioner->constraint_adjustment;
- wl_list_insert(&parent->popups, &surface->popup_state->link);
+ wl_list_insert(&parent->popups, &surface->popup->link);
- wl_resource_set_implementation(surface->popup_state->resource,
+ wl_resource_set_implementation(surface->popup->resource,
&zxdg_popup_v6_implementation, surface,
xdg_popup_resource_destroy);
- wlr_signal_emit_safe(&parent->events.new_popup, surface->popup_state);
+ wlr_signal_emit_safe(&parent->events.new_popup, surface->popup);
}
@@ -562,7 +624,7 @@ static struct wlr_xdg_surface_v6 *xdg_surface_from_xdg_toplevel_resource(
return wl_resource_get_user_data(resource);
}
-static void xdg_toplevel_protocol_set_parent(struct wl_client *client,
+static void xdg_toplevel_handle_set_parent(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *parent_resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
@@ -572,10 +634,10 @@ static void xdg_toplevel_protocol_set_parent(struct wl_client *client,
parent = xdg_surface_from_xdg_toplevel_resource(parent_resource);
}
- surface->toplevel_state->parent = parent;
+ surface->toplevel->parent = parent;
}
-static void xdg_toplevel_protocol_set_title(struct wl_client *client,
+static void xdg_toplevel_handle_set_title(struct wl_client *client,
struct wl_resource *resource, const char *title) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
@@ -589,7 +651,7 @@ static void xdg_toplevel_protocol_set_title(struct wl_client *client,
surface->title = tmp;
}
-static void xdg_toplevel_protocol_set_app_id(struct wl_client *client,
+static void xdg_toplevel_handle_set_app_id(struct wl_client *client,
struct wl_resource *resource, const char *app_id) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
@@ -603,7 +665,7 @@ static void xdg_toplevel_protocol_set_app_id(struct wl_client *client,
surface->app_id = tmp;
}
-static void xdg_toplevel_protocol_show_window_menu(struct wl_client *client,
+static void xdg_toplevel_handle_show_window_menu(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial, int32_t x, int32_t y) {
struct wlr_xdg_surface_v6 *surface =
@@ -612,7 +674,7 @@ static void xdg_toplevel_protocol_show_window_menu(struct wl_client *client,
wlr_seat_client_from_resource(seat_resource);
if (!surface->configured) {
- wl_resource_post_error(surface->toplevel_state->resource,
+ wl_resource_post_error(surface->toplevel->resource,
ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
"surface has not been configured yet");
return;
@@ -634,7 +696,7 @@ static void xdg_toplevel_protocol_show_window_menu(struct wl_client *client,
wlr_signal_emit_safe(&surface->events.request_show_window_menu, &event);
}
-static void xdg_toplevel_protocol_move(struct wl_client *client,
+static void xdg_toplevel_handle_move(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial) {
struct wlr_xdg_surface_v6 *surface =
@@ -643,7 +705,7 @@ static void xdg_toplevel_protocol_move(struct wl_client *client,
wlr_seat_client_from_resource(seat_resource);
if (!surface->configured) {
- wl_resource_post_error(surface->toplevel_state->resource,
+ wl_resource_post_error(surface->toplevel->resource,
ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
"surface has not been configured yet");
return;
@@ -663,7 +725,7 @@ static void xdg_toplevel_protocol_move(struct wl_client *client,
wlr_signal_emit_safe(&surface->events.request_move, &event);
}
-static void xdg_toplevel_protocol_resize(struct wl_client *client,
+static void xdg_toplevel_handle_resize(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *seat_resource,
uint32_t serial, uint32_t edges) {
struct wlr_xdg_surface_v6 *surface =
@@ -672,7 +734,7 @@ static void xdg_toplevel_protocol_resize(struct wl_client *client,
wlr_seat_client_from_resource(seat_resource);
if (!surface->configured) {
- wl_resource_post_error(surface->toplevel_state->resource,
+ wl_resource_post_error(surface->toplevel->resource,
ZXDG_SURFACE_V6_ERROR_NOT_CONSTRUCTED,
"surface has not been configured yet");
return;
@@ -693,39 +755,39 @@ static void xdg_toplevel_protocol_resize(struct wl_client *client,
wlr_signal_emit_safe(&surface->events.request_resize, &event);
}
-static void xdg_toplevel_protocol_set_max_size(struct wl_client *client,
+static void xdg_toplevel_handle_set_max_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
- surface->toplevel_state->next.max_width = width;
- surface->toplevel_state->next.max_height = height;
+ surface->toplevel->next.max_width = width;
+ surface->toplevel->next.max_height = height;
}
-static void xdg_toplevel_protocol_set_min_size(struct wl_client *client,
+static void xdg_toplevel_handle_set_min_size(struct wl_client *client,
struct wl_resource *resource, int32_t width, int32_t height) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
- surface->toplevel_state->next.min_width = width;
- surface->toplevel_state->next.min_height = height;
+ surface->toplevel->next.min_width = width;
+ surface->toplevel->next.min_height = height;
}
-static void xdg_toplevel_protocol_set_maximized(struct wl_client *client,
+static void xdg_toplevel_handle_set_maximized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
- surface->toplevel_state->next.maximized = true;
+ surface->toplevel->next.maximized = true;
wlr_signal_emit_safe(&surface->events.request_maximize, surface);
}
-static void xdg_toplevel_protocol_unset_maximized(struct wl_client *client,
+static void xdg_toplevel_handle_unset_maximized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
- surface->toplevel_state->next.maximized = false;
+ surface->toplevel->next.maximized = false;
wlr_signal_emit_safe(&surface->events.request_maximize, surface);
}
-static void xdg_toplevel_protocol_set_fullscreen(struct wl_client *client,
+static void xdg_toplevel_handle_set_fullscreen(struct wl_client *client,
struct wl_resource *resource, struct wl_resource *output_resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
@@ -735,7 +797,7 @@ static void xdg_toplevel_protocol_set_fullscreen(struct wl_client *client,
output = wlr_output_from_resource(output_resource);
}
- surface->toplevel_state->next.fullscreen = true;
+ surface->toplevel->next.fullscreen = true;
struct wlr_xdg_toplevel_v6_set_fullscreen_event event = {
.surface = surface,
@@ -746,12 +808,12 @@ static void xdg_toplevel_protocol_set_fullscreen(struct wl_client *client,
wlr_signal_emit_safe(&surface->events.request_fullscreen, &event);
}
-static void xdg_toplevel_protocol_unset_fullscreen(struct wl_client *client,
+static void xdg_toplevel_handle_unset_fullscreen(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
- surface->toplevel_state->next.fullscreen = false;
+ surface->toplevel->next.fullscreen = false;
struct wlr_xdg_toplevel_v6_set_fullscreen_event event = {
.surface = surface,
@@ -762,29 +824,29 @@ static void xdg_toplevel_protocol_unset_fullscreen(struct wl_client *client,
wlr_signal_emit_safe(&surface->events.request_fullscreen, &event);
}
-static void xdg_toplevel_protocol_set_minimized(struct wl_client *client,
+static void xdg_toplevel_handle_set_minimized(struct wl_client *client,
struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
wlr_signal_emit_safe(&surface->events.request_minimize, surface);
}
-static const struct zxdg_toplevel_v6_interface zxdg_toplevel_v6_implementation =
-{
- .destroy = resource_destroy,
- .set_parent = xdg_toplevel_protocol_set_parent,
- .set_title = xdg_toplevel_protocol_set_title,
- .set_app_id = xdg_toplevel_protocol_set_app_id,
- .show_window_menu = xdg_toplevel_protocol_show_window_menu,
- .move = xdg_toplevel_protocol_move,
- .resize = xdg_toplevel_protocol_resize,
- .set_max_size = xdg_toplevel_protocol_set_max_size,
- .set_min_size = xdg_toplevel_protocol_set_min_size,
- .set_maximized = xdg_toplevel_protocol_set_maximized,
- .unset_maximized = xdg_toplevel_protocol_unset_maximized,
- .set_fullscreen = xdg_toplevel_protocol_set_fullscreen,
- .unset_fullscreen = xdg_toplevel_protocol_unset_fullscreen,
- .set_minimized = xdg_toplevel_protocol_set_minimized
+static const struct zxdg_toplevel_v6_interface
+ zxdg_toplevel_v6_implementation = {
+ .destroy = resource_handle_destroy,
+ .set_parent = xdg_toplevel_handle_set_parent,
+ .set_title = xdg_toplevel_handle_set_title,
+ .set_app_id = xdg_toplevel_handle_set_app_id,
+ .show_window_menu = xdg_toplevel_handle_show_window_menu,
+ .move = xdg_toplevel_handle_move,
+ .resize = xdg_toplevel_handle_resize,
+ .set_max_size = xdg_toplevel_handle_set_max_size,
+ .set_min_size = xdg_toplevel_handle_set_min_size,
+ .set_maximized = xdg_toplevel_handle_set_maximized,
+ .unset_maximized = xdg_toplevel_handle_unset_maximized,
+ .set_fullscreen = xdg_toplevel_handle_set_fullscreen,
+ .unset_fullscreen = xdg_toplevel_handle_unset_fullscreen,
+ .set_minimized = xdg_toplevel_handle_set_minimized,
};
static void xdg_surface_resource_destroy(struct wl_resource *resource) {
@@ -798,11 +860,11 @@ static void xdg_toplevel_resource_destroy(struct wl_resource *resource) {
struct wlr_xdg_surface_v6 *surface =
xdg_surface_from_xdg_toplevel_resource(resource);
if (surface != NULL) {
- xdg_surface_destroy(surface);
+ xdg_surface_unmap(surface);
}
}
-static void xdg_surface_get_toplevel(struct wl_client *client,
+static void xdg_surface_handle_get_toplevel(struct wl_client *client,
struct wl_resource *resource, uint32_t id) {
struct wlr_xdg_surface_v6 *surface = xdg_surface_from_resource(resource);
@@ -811,24 +873,24 @@ static void xdg_surface_get_toplevel(struct wl_client *client,
return;
}
- surface->toplevel_state = calloc(1, sizeof(struct wlr_xdg_toplevel_v6));
- if (surface->toplevel_state == NULL) {
+ surface->toplevel = calloc(1, sizeof(struct wlr_xdg_toplevel_v6));
+ if (surface->toplevel == NULL) {
wl_resource_post_no_memory(resource);
return;
}
surface->role = WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL;
- surface->toplevel_state->base = surface;
+ surface->toplevel->base = surface;
struct wl_resource *toplevel_resource = wl_resource_create(client,
&zxdg_toplevel_v6_interface, wl_resource_get_version(resource), id);
if (toplevel_resource == NULL) {
- free(surface->toplevel_state);
+ free(surface->toplevel);
wl_resource_post_no_memory(resource);
return;
}
- surface->toplevel_state->resource = toplevel_resource;
+ surface->toplevel->resource = toplevel_resource;
wl_resource_set_implementation(toplevel_resource,
&zxdg_toplevel_v6_implementation, surface,
@@ -839,12 +901,19 @@ static void wlr_xdg_toplevel_v6_ack_configure(
struct wlr_xdg_surface_v6 *surface,
struct wlr_xdg_surface_v6_configure *configure) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
- surface->toplevel_state->next = configure->state;
- surface->toplevel_state->pending.width = 0;
- surface->toplevel_state->pending.height = 0;
+ assert(configure->toplevel_state != NULL);
+
+ surface->toplevel->current.maximized =
+ configure->toplevel_state->maximized;
+ surface->toplevel->current.fullscreen =
+ configure->toplevel_state->fullscreen;
+ surface->toplevel->current.resizing =
+ configure->toplevel_state->resizing;
+ surface->toplevel->current.activated =
+ configure->toplevel_state->activated;
}
-static void xdg_surface_ack_configure(struct wl_client *client,
+static void xdg_surface_handle_ack_configure(struct wl_client *client,
struct wl_resource *resource, uint32_t serial) {
struct wlr_xdg_surface_v6 *surface = xdg_surface_from_resource(resource);
@@ -859,10 +928,8 @@ static void xdg_surface_ack_configure(struct wl_client *client,
struct wlr_xdg_surface_v6_configure *configure, *tmp;
wl_list_for_each_safe(configure, tmp, &surface->configure_list, link) {
if (configure->serial < serial) {
- wl_list_remove(&configure->link);
- free(configure);
+ xdg_surface_configure_destroy(configure);
} else if (configure->serial == serial) {
- wl_list_remove(&configure->link);
found = true;
break;
} else {
@@ -890,10 +957,10 @@ static void xdg_surface_ack_configure(struct wl_client *client,
surface->configured = true;
surface->configure_serial = serial;
- free(configure);
+ xdg_surface_configure_destroy(configure);
}
-static void xdg_surface_set_window_geometry(struct wl_client *client,
+static void xdg_surface_handle_set_window_geometry(struct wl_client *client,
struct wl_resource *resource, int32_t x, int32_t y, int32_t width,
int32_t height) {
struct wlr_xdg_surface_v6 *surface = xdg_surface_from_resource(resource);
@@ -906,19 +973,31 @@ static void xdg_surface_set_window_geometry(struct wl_client *client,
}
surface->has_next_geometry = true;
- surface->next_geometry->height = height;
- surface->next_geometry->width = width;
- surface->next_geometry->x = x;
- surface->next_geometry->y = y;
+ surface->next_geometry.height = height;
+ surface->next_geometry.width = width;
+ surface->next_geometry.x = x;
+ surface->next_geometry.y = y;
+}
+
+static void xdg_surface_handle_destroy(struct wl_client *client,
+ struct wl_resource *resource) {
+ struct wlr_xdg_surface_v6 *surface = xdg_surface_from_resource(resource);
+ if (surface->role != WLR_XDG_SURFACE_V6_ROLE_NONE) {
+ wlr_log(L_ERROR, "Tried to destroy an xdg_surface before its role "
+ "object");
+ return;
+ }
+
+ wl_resource_destroy(resource);
}
static const struct zxdg_surface_v6_interface zxdg_surface_v6_implementation = {
- .destroy = resource_destroy,
- .get_toplevel = xdg_surface_get_toplevel,
- .get_popup = xdg_surface_get_popup,
- .ack_configure = xdg_surface_ack_configure,
- .set_window_geometry = xdg_surface_set_window_geometry,
+ .destroy = xdg_surface_handle_destroy,
+ .get_toplevel = xdg_surface_handle_get_toplevel,
+ .get_popup = xdg_surface_handle_get_popup,
+ .ack_configure = xdg_surface_handle_ack_configure,
+ .set_window_geometry = xdg_surface_handle_set_window_geometry,
};
static bool wlr_xdg_surface_v6_toplevel_state_compare(
@@ -941,9 +1020,9 @@ static bool wlr_xdg_surface_v6_toplevel_state_compare(
} else {
struct wlr_xdg_surface_v6_configure *configure =
wl_container_of(state->base->configure_list.prev, configure, link);
- configured.state = configure->state;
- configured.width = configure->state.width;
- configured.height = configure->state.height;
+ configured.state = *configure->toplevel_state;
+ configured.width = configure->toplevel_state->width;
+ configured.height = configure->toplevel_state->height;
}
if (state->pending.activated != configured.state.activated) {
@@ -975,13 +1054,19 @@ static void wlr_xdg_toplevel_v6_send_configure(
struct wlr_xdg_surface_v6 *surface,
struct wlr_xdg_surface_v6_configure *configure) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
- uint32_t *s;
- struct wl_array states;
- configure->state = surface->toplevel_state->pending;
+ configure->toplevel_state = malloc(sizeof(*configure->toplevel_state));
+ if (configure->toplevel_state == NULL) {
+ wlr_log(L_ERROR, "Allocation failed");
+ wl_resource_post_no_memory(surface->toplevel->resource);
+ return;
+ }
+ *configure->toplevel_state = surface->toplevel->pending;
+ uint32_t *s;
+ struct wl_array states;
wl_array_init(&states);
- if (surface->toplevel_state->pending.maximized) {
+ if (surface->toplevel->pending.maximized) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for maximized xdg_toplevel");
@@ -989,7 +1074,7 @@ static void wlr_xdg_toplevel_v6_send_configure(
}
*s = ZXDG_TOPLEVEL_V6_STATE_MAXIMIZED;
}
- if (surface->toplevel_state->pending.fullscreen) {
+ if (surface->toplevel->pending.fullscreen) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for fullscreen xdg_toplevel");
@@ -997,7 +1082,7 @@ static void wlr_xdg_toplevel_v6_send_configure(
}
*s = ZXDG_TOPLEVEL_V6_STATE_FULLSCREEN;
}
- if (surface->toplevel_state->pending.resizing) {
+ if (surface->toplevel->pending.resizing) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for resizing xdg_toplevel");
@@ -1005,7 +1090,7 @@ static void wlr_xdg_toplevel_v6_send_configure(
}
*s = ZXDG_TOPLEVEL_V6_STATE_RESIZING;
}
- if (surface->toplevel_state->pending.activated) {
+ if (surface->toplevel->pending.activated) {
s = wl_array_add(&states, sizeof(uint32_t));
if (!s) {
wlr_log(L_ERROR, "Could not allocate state for activated xdg_toplevel");
@@ -1014,15 +1099,9 @@ static void wlr_xdg_toplevel_v6_send_configure(
*s = ZXDG_TOPLEVEL_V6_STATE_ACTIVATED;
}
- uint32_t width = surface->toplevel_state->pending.width;
- uint32_t height = surface->toplevel_state->pending.height;
-
- if (width == 0 || height == 0) {
- width = surface->geometry->width;
- height = surface->geometry->height;
- }
-
- zxdg_toplevel_v6_send_configure(surface->toplevel_state->resource, width,
+ uint32_t width = surface->toplevel->pending.width;
+ uint32_t height = surface->toplevel->pending.height;
+ zxdg_toplevel_v6_send_configure(surface->toplevel->resource, width,
height, &states);
wl_array_release(&states);
@@ -1030,7 +1109,7 @@ static void wlr_xdg_toplevel_v6_send_configure(
error_out:
wl_array_release(&states);
- wl_resource_post_no_memory(surface->toplevel_state->resource);
+ wl_resource_post_no_memory(surface->toplevel->resource);
}
static void wlr_xdg_surface_send_configure(void *user_data) {
@@ -1056,11 +1135,11 @@ static void wlr_xdg_surface_send_configure(void *user_data) {
wlr_xdg_toplevel_v6_send_configure(surface, configure);
break;
case WLR_XDG_SURFACE_V6_ROLE_POPUP:
- zxdg_popup_v6_send_configure(surface->popup_state->resource,
- surface->popup_state->geometry.x,
- surface->popup_state->geometry.y,
- surface->popup_state->geometry.width,
- surface->popup_state->geometry.height);
+ zxdg_popup_v6_send_configure(surface->popup->resource,
+ surface->popup->geometry.x,
+ surface->popup->geometry.y,
+ surface->popup->geometry.width,
+ surface->popup->geometry.height);
break;
}
@@ -1079,7 +1158,7 @@ static uint32_t wlr_xdg_surface_v6_schedule_configure(
break;
case WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL:
pending_same =
- wlr_xdg_surface_v6_toplevel_state_compare(surface->toplevel_state);
+ wlr_xdg_surface_v6_toplevel_state_compare(surface->toplevel);
break;
case WLR_XDG_SURFACE_V6_ROLE_POPUP:
break;
@@ -1119,29 +1198,32 @@ static void wlr_xdg_surface_v6_toplevel_committed(
struct wlr_xdg_surface_v6 *surface) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
- if (!wlr_surface_has_buffer(surface->surface)
- && !surface->toplevel_state->added) {
+ if (!surface->toplevel->added) {
// on the first commit, send a configure request to tell the client it
// is added
wlr_xdg_surface_v6_schedule_configure(surface);
- surface->toplevel_state->added = true;
- return;
- }
-
- if (!wlr_surface_has_buffer(surface->surface)) {
+ surface->toplevel->added = true;
return;
}
- surface->toplevel_state->current = surface->toplevel_state->next;
+ // update state that doesn't need compositor approval
+ surface->toplevel->current.max_width =
+ surface->toplevel->next.max_width;
+ surface->toplevel->current.min_width =
+ surface->toplevel->next.min_width;
+ surface->toplevel->current.max_height =
+ surface->toplevel->next.max_height;
+ surface->toplevel->current.min_height =
+ surface->toplevel->next.min_height;
}
static void wlr_xdg_surface_v6_popup_committed(
struct wlr_xdg_surface_v6 *surface) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP);
- if (!surface->popup_state->committed) {
+ if (!surface->popup->committed) {
wlr_xdg_surface_v6_schedule_configure(surface);
- surface->popup_state->committed = true;
+ surface->popup->committed = true;
}
}
@@ -1158,10 +1240,10 @@ static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface,
if (surface->has_next_geometry) {
surface->has_next_geometry = false;
- surface->geometry->x = surface->next_geometry->x;
- surface->geometry->y = surface->next_geometry->y;
- surface->geometry->width = surface->next_geometry->width;
- surface->geometry->height = surface->next_geometry->height;
+ surface->geometry.x = surface->next_geometry.x;
+ surface->geometry.y = surface->next_geometry.y;
+ surface->geometry.width = surface->next_geometry.width;
+ surface->geometry.height = surface->next_geometry.height;
}
switch (surface->role) {
@@ -1178,9 +1260,19 @@ static void handle_wlr_surface_committed(struct wlr_surface *wlr_surface,
break;
}
- if (surface->configured && !surface->added) {
+ if (!surface->added) {
surface->added = true;
- wlr_signal_emit_safe(&surface->client->shell->events.new_surface, surface);
+ wlr_signal_emit_safe(&surface->client->shell->events.new_surface,
+ surface);
+ }
+ if (surface->configured && wlr_surface_has_buffer(surface->surface) &&
+ !surface->mapped) {
+ surface->mapped = true;
+ wlr_signal_emit_safe(&surface->events.map, surface);
+ }
+ if (surface->configured && !wlr_surface_has_buffer(surface->surface) &&
+ surface->mapped) {
+ xdg_surface_unmap(surface);
}
}
@@ -1193,27 +1285,15 @@ static struct wlr_xdg_client_v6 *xdg_client_from_resource(
return wl_resource_get_user_data(resource);
}
-static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
+static void xdg_shell_handle_get_xdg_surface(struct wl_client *wl_client,
struct wl_resource *client_resource, uint32_t id,
struct wl_resource *surface_resource) {
struct wlr_xdg_client_v6 *client =
xdg_client_from_resource(client_resource);
- struct wlr_xdg_surface_v6 *surface;
- if (!(surface = calloc(1, sizeof(struct wlr_xdg_surface_v6)))) {
- wl_client_post_no_memory(wl_client);
- return;
- }
-
- if (!(surface->geometry = calloc(1, sizeof(struct wlr_box)))) {
- free(surface);
- wl_client_post_no_memory(wl_client);
- return;
- }
-
- if (!(surface->next_geometry = calloc(1, sizeof(struct wlr_box)))) {
- free(surface->geometry);
- free(surface);
+ struct wlr_xdg_surface_v6 *surface =
+ calloc(1, sizeof(struct wlr_xdg_surface_v6));
+ if (surface == NULL) {
wl_client_post_no_memory(wl_client);
return;
}
@@ -1225,8 +1305,6 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
&zxdg_surface_v6_interface, wl_resource_get_version(client_resource),
id);
if (surface->resource == NULL) {
- free(surface->next_geometry);
- free(surface->geometry);
free(surface);
wl_client_post_no_memory(wl_client);
return;
@@ -1234,8 +1312,6 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
if (wlr_surface_has_buffer(surface->surface)) {
wl_resource_destroy(surface->resource);
- free(surface->next_geometry);
- free(surface->geometry);
free(surface);
wl_resource_post_error(surface_resource,
ZXDG_SURFACE_V6_ERROR_UNCONFIGURED_BUFFER,
@@ -1255,6 +1331,8 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
wl_signal_init(&surface->events.destroy);
wl_signal_init(&surface->events.ping_timeout);
wl_signal_init(&surface->events.new_popup);
+ wl_signal_init(&surface->events.map);
+ wl_signal_init(&surface->events.unmap);
wl_signal_add(&surface->surface->events.destroy,
&surface->surface_destroy_listener);
@@ -1269,7 +1347,7 @@ static void xdg_shell_get_xdg_surface(struct wl_client *wl_client,
wl_list_insert(&client->surfaces, &surface->link);
}
-static void xdg_shell_pong(struct wl_client *wl_client,
+static void xdg_shell_handle_pong(struct wl_client *wl_client,
struct wl_resource *resource, uint32_t serial) {
struct wlr_xdg_client_v6 *client = xdg_client_from_resource(resource);
@@ -1281,11 +1359,25 @@ static void xdg_shell_pong(struct wl_client *wl_client,
client->ping_serial = 0;
}
+static void xdg_shell_handle_destroy(struct wl_client *wl_client,
+ struct wl_resource *resource) {
+ struct wlr_xdg_client_v6 *client = xdg_client_from_resource(resource);
+
+ if (!wl_list_empty(&client->surfaces)) {
+ wl_resource_post_error(client->resource,
+ ZXDG_SHELL_V6_ERROR_DEFUNCT_SURFACES,
+ "xdg_wm_base was destroyed before children");
+ return;
+ }
+
+ wl_resource_destroy(resource);
+}
+
static const struct zxdg_shell_v6_interface xdg_shell_impl = {
- .destroy = resource_destroy,
- .create_positioner = xdg_shell_create_positioner,
- .get_xdg_surface = xdg_shell_get_xdg_surface,
- .pong = xdg_shell_pong,
+ .destroy = xdg_shell_handle_destroy,
+ .create_positioner = xdg_shell_handle_create_positioner,
+ .get_xdg_surface = xdg_shell_handle_get_xdg_surface,
+ .pong = xdg_shell_handle_pong,
};
static void wlr_xdg_client_v6_destroy(struct wl_resource *resource) {
@@ -1413,8 +1505,8 @@ void wlr_xdg_surface_v6_ping(struct wlr_xdg_surface_v6 *surface) {
uint32_t wlr_xdg_toplevel_v6_set_size(struct wlr_xdg_surface_v6 *surface,
uint32_t width, uint32_t height) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
- surface->toplevel_state->pending.width = width;
- surface->toplevel_state->pending.height = height;
+ surface->toplevel->pending.width = width;
+ surface->toplevel->pending.height = height;
return wlr_xdg_surface_v6_schedule_configure(surface);
}
@@ -1422,7 +1514,7 @@ uint32_t wlr_xdg_toplevel_v6_set_size(struct wlr_xdg_surface_v6 *surface,
uint32_t wlr_xdg_toplevel_v6_set_activated(struct wlr_xdg_surface_v6 *surface,
bool activated) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
- surface->toplevel_state->pending.activated = activated;
+ surface->toplevel->pending.activated = activated;
return wlr_xdg_surface_v6_schedule_configure(surface);
}
@@ -1430,7 +1522,7 @@ uint32_t wlr_xdg_toplevel_v6_set_activated(struct wlr_xdg_surface_v6 *surface,
uint32_t wlr_xdg_toplevel_v6_set_maximized(struct wlr_xdg_surface_v6 *surface,
bool maximized) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
- surface->toplevel_state->pending.maximized = maximized;
+ surface->toplevel->pending.maximized = maximized;
return wlr_xdg_surface_v6_schedule_configure(surface);
}
@@ -1438,7 +1530,7 @@ uint32_t wlr_xdg_toplevel_v6_set_maximized(struct wlr_xdg_surface_v6 *surface,
uint32_t wlr_xdg_toplevel_v6_set_fullscreen(struct wlr_xdg_surface_v6 *surface,
bool fullscreen) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
- surface->toplevel_state->pending.fullscreen = fullscreen;
+ surface->toplevel->pending.fullscreen = fullscreen;
return wlr_xdg_surface_v6_schedule_configure(surface);
}
@@ -1446,24 +1538,24 @@ uint32_t wlr_xdg_toplevel_v6_set_fullscreen(struct wlr_xdg_surface_v6 *surface,
uint32_t wlr_xdg_toplevel_v6_set_resizing(struct wlr_xdg_surface_v6 *surface,
bool resizing) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
- surface->toplevel_state->pending.resizing = resizing;
+ surface->toplevel->pending.resizing = resizing;
return wlr_xdg_surface_v6_schedule_configure(surface);
}
void wlr_xdg_toplevel_v6_send_close(struct wlr_xdg_surface_v6 *surface) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_TOPLEVEL);
- zxdg_toplevel_v6_send_close(surface->toplevel_state->resource);
+ zxdg_toplevel_v6_send_close(surface->toplevel->resource);
}
void wlr_xdg_surface_v6_popup_get_position(struct wlr_xdg_surface_v6 *surface,
double *popup_sx, double *popup_sy) {
assert(surface->role == WLR_XDG_SURFACE_V6_ROLE_POPUP);
- struct wlr_xdg_surface_v6 *parent = surface->popup_state->parent;
- *popup_sx = parent->geometry->x + surface->popup_state->geometry.x -
- surface->geometry->x;
- *popup_sy = parent->geometry->y + surface->popup_state->geometry.y -
- surface->geometry->y;
+ struct wlr_xdg_surface_v6 *parent = surface->popup->parent;
+ *popup_sx = parent->geometry.x + surface->popup->geometry.x -
+ surface->geometry.x;
+ *popup_sy = parent->geometry.y + surface->popup->geometry.y -
+ surface->geometry.y;
}
struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at(
@@ -1477,30 +1569,30 @@ struct wlr_xdg_surface_v6 *wlr_xdg_surface_v6_popup_at(
struct wlr_xdg_surface_v6 *popup = popup_state->base;
double _popup_sx =
- surface->geometry->x + popup_state->geometry.x;
+ surface->geometry.x + popup_state->geometry.x;
double _popup_sy =
- surface->geometry->y + popup_state->geometry.y;
+ surface->geometry.y + popup_state->geometry.y;
int popup_width = popup_state->geometry.width;
int popup_height = popup_state->geometry.height;
struct wlr_xdg_surface_v6 *_popup =
wlr_xdg_surface_v6_popup_at(popup,
- sx - _popup_sx + popup->geometry->x,
- sy - _popup_sy + popup->geometry->y,
+ sx - _popup_sx + popup->geometry.x,
+ sy - _popup_sy + popup->geometry.y,
popup_sx, popup_sy);
if (_popup) {
- *popup_sx = *popup_sx + _popup_sx - popup->geometry->x;
- *popup_sy = *popup_sy + _popup_sy - popup->geometry->y;
+ *popup_sx = *popup_sx + _popup_sx - popup->geometry.x;
+ *popup_sy = *popup_sy + _popup_sy - popup->geometry.y;
return _popup;
}
if ((sx > _popup_sx && sx < _popup_sx + popup_width) &&
(sy > _popup_sy && sy < _popup_sy + popup_height)) {
if (pixman_region32_contains_point(&popup->surface->current->input,
- sx - _popup_sx + popup->geometry->x,
- sy - _popup_sy + popup->geometry->y, NULL)) {
- *popup_sx = _popup_sx - popup->geometry->x;
- *popup_sy = _popup_sy - popup->geometry->y;
+ sx - _popup_sx + popup->geometry.x,
+ sy - _popup_sy + popup->geometry.y, NULL)) {
+ *popup_sx = _popup_sx - popup->geometry.x;
+ *popup_sy = _popup_sy - popup->geometry.y;
return popup;
}
}
diff --git a/wlroots.syms b/wlroots.syms
index 3f45e045..cb030a6d 100644
--- a/wlroots.syms
+++ b/wlroots.syms
@@ -15,8 +15,8 @@ WLROOTS_0_0_0 {
wlr_drm_get_connector_props;
wlr_drm_get_crtc_props;
wlr_drm_get_plane_props;
- wlr_drm_get_prop;
wlr_drm_get_prop_blob;
+ wlr_drm_get_prop;
wlr_drm_plane_surfaces_init;
wlr_drm_renderer_finish;
wlr_drm_renderer_init;