From 9e26808c280cb32f32835231a76b5b105011fd1e Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 21 May 2018 18:50:51 +0100 Subject: output, backend/drm: add wlr_output_export_dmabuf --- include/wlr/interfaces/wlr_output.h | 2 ++ include/wlr/types/wlr_output.h | 3 +++ 2 files changed, 5 insertions(+) (limited to 'include/wlr') diff --git a/include/wlr/interfaces/wlr_output.h b/include/wlr/interfaces/wlr_output.h index 7ecc7551..d39e4edc 100644 --- a/include/wlr/interfaces/wlr_output.h +++ b/include/wlr/interfaces/wlr_output.h @@ -23,6 +23,8 @@ struct wlr_output_impl { void (*set_gamma)(struct wlr_output *output, uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b); uint32_t (*get_gamma_size)(struct wlr_output *output); + bool (*export_dmabuf)(struct wlr_output *output, + struct wlr_dmabuf_buffer_attribs *attribs); }; void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend, diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index cef3fc5d..669b96ed 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -6,6 +6,7 @@ #include #include #include +#include struct wlr_output_mode { uint32_t flags; // enum wl_output_mode @@ -162,6 +163,8 @@ void wlr_output_schedule_frame(struct wlr_output *output); void wlr_output_set_gamma(struct wlr_output *output, uint32_t size, uint16_t *r, uint16_t *g, uint16_t *b); uint32_t wlr_output_get_gamma_size(struct wlr_output *output); +bool wlr_output_export_dmabuf(struct wlr_output *output, + struct wlr_dmabuf_buffer_attribs *attribs); void wlr_output_set_fullscreen_surface(struct wlr_output *output, struct wlr_surface *surface); struct wlr_output *wlr_output_from_resource(struct wl_resource *resource); -- cgit v1.2.3 From 36bd4795d4fe2282dfcc59f26863bac2896a4a3f Mon Sep 17 00:00:00 2001 From: emersion Date: Tue, 22 May 2018 17:38:05 +0100 Subject: export-dmabuf: add basic and incomplete implementation --- include/wlr/types/wlr_export_dmabuf_v1.h | 33 +++++ protocol/meson.build | 3 +- protocol/wlr-export-dmabuf-unstable-v1.xml | 230 +++++++++++++++++++++++++++++ types/meson.build | 1 + types/wlr_export_dmabuf_v1.c | 185 +++++++++++++++++++++++ 5 files changed, 451 insertions(+), 1 deletion(-) create mode 100644 include/wlr/types/wlr_export_dmabuf_v1.h create mode 100644 protocol/wlr-export-dmabuf-unstable-v1.xml create mode 100644 types/wlr_export_dmabuf_v1.c (limited to 'include/wlr') diff --git a/include/wlr/types/wlr_export_dmabuf_v1.h b/include/wlr/types/wlr_export_dmabuf_v1.h new file mode 100644 index 00000000..78db1e61 --- /dev/null +++ b/include/wlr/types/wlr_export_dmabuf_v1.h @@ -0,0 +1,33 @@ +#ifndef WLR_TYPES_WLR_EXPORT_DMABUF_V1_H +#define WLR_TYPES_WLR_EXPORT_DMABUF_V1_H + +#include + +struct wlr_export_dmabuf_manager_v1; + +struct wlr_export_dmabuf_frame_v1 { + struct wl_resource *resource; + struct wlr_export_dmabuf_manager_v1 *manager; + struct wl_list link; + + struct wlr_output *output; +}; + +struct wlr_export_dmabuf_manager_v1 { + struct wl_global *global; + struct wl_list resources; + struct wl_list frames; + + struct wl_listener display_destroy; + + struct { + struct wl_signal destroy; + } events; +}; + +struct wlr_export_dmabuf_manager_v1 *wlr_export_dmabuf_manager_v1_create( + struct wl_display *display); +void wlr_export_dmabuf_manager_v1_destroy( + struct wlr_export_dmabuf_manager_v1 *manager); + +#endif diff --git a/protocol/meson.build b/protocol/meson.build index 8fa64ca9..a14e9723 100644 --- a/protocol/meson.build +++ b/protocol/meson.build @@ -39,8 +39,9 @@ protocols = [ 'screenshooter.xml', 'server-decoration.xml', 'virtual-keyboard-unstable-v1.xml', - 'wlr-layer-shell-unstable-v1.xml', + 'wlr-export-dmabuf-unstable-v1.xml', 'wlr-input-inhibitor-unstable-v1.xml', + 'wlr-layer-shell-unstable-v1.xml', ] client_protocols = [ diff --git a/protocol/wlr-export-dmabuf-unstable-v1.xml b/protocol/wlr-export-dmabuf-unstable-v1.xml new file mode 100644 index 00000000..6332b146 --- /dev/null +++ b/protocol/wlr-export-dmabuf-unstable-v1.xml @@ -0,0 +1,230 @@ + + + + + Copyright © 2018 Rostislav Pehlivanov + + Permission is hereby granted, free of charge, to any person obtaining a + copy of this software and associated documentation files (the "Software"), + to deal in the Software without restriction, including without limitation + the rights to use, copy, modify, merge, publish, distribute, sublicense, + and/or sell copies of the Software, and to permit persons to whom the + Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice (including the next + paragraph) shall be included in all copies or substantial portions of the + Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. + + + + An interface to capture surfaces in an efficient way. + Overall usage: + + 1.) client registers with zwlr_screencontent_manager_v1 + 2.) server sends client info about surfaces via "receive_surface_info" + 3.) client subscribes to capture a surface via the "capture" requests + 4.) server sends client events via the "zwlr_screencontent_frame" interface + 5.) client finishes and informs server via the "frame_destroy" event + 6.) client optionally resubscribes via repeating steps 3.) through 5.) + + + + + This object represents a frame which is ready to have its resources + fetched and used. + + The receive callback shall be called first, followed by either the + "dma_object" callback once per object or the "dma_layer" callback, + once per layer. The "dma_plane" callback shall only be called after + the "dma_layer" callback corresponding to the layer the plane belongs + to has been called. Finally, the "ready" event is called to indicate that + all the data has been made available for readout, as well as the time + at which presentation happened at. + The ownership of the frame is passed to the client, who's responsible for + destroying it via the "destroy" event once finished. + The data the API describes has been based off of what + VASurfaceAttribExternalBuffers contains. + All frames are read-only and may not be written into or altered. + + + + + Special flags that must be respected by the client. + Transient frames indicate short lifetime frames (such as swapchain + images from external clients). Clients are advised to copy them and do + all processing outside of the "ready" event. + + + + + + + Main callback supplying the client with information about the frame, + as well as an object to serve as context for destruction. Always called + first before any other events. + + The "transform" argument describes the orientation needed to be applied + to correctly orient the buffer. For example, a buffer rotated by 90 + degrees will have a value of "3" here, corresponding to the need to + apply a 270 degree transpose to correctly present the buffer. + + + + + + + + + + + + + + + Callback which serves to supply the client with the file descriptors + containing the data for each object. + + + + + + + + Callback which serves to supply the client with information on what's + contained in each file descriptor and how its laid out. + Will be called after the main receive event, once per layer. + + + + + + + + Callback which supplies the client with plane information for each + layer. + + + + + + + + + + Called as soon as the frame is presented, indicating it is available + for reading. + The timestamp is expressed as tv_sec_hi, tv_sec_lo, tv_nsec triples, + each component being an unsigned 32-bit value. Whole seconds are in + tv_sec which is a 64-bit value combined from tv_sec_hi and tv_sec_lo, + and the additional fractional part in tv_nsec as nanoseconds. Hence, + for valid timestamps tv_nsec must be in [0, 999999999]. + The seconds part may have an arbitrary offset at start. + + + + + + + + If the frame is no longer valid after the "frame" event has been called, + this callback will be used to inform the client to scrap the frame. + Source is still valid for as long as the subscription function does not + return NULL. + This may get called if for instance the surface is in the process of + resizing. + + + + + + Unreferences the frame, allowing it to be reused. Must be called as soon + as its no longer used. + + + + + + + This object is a manager which informs clients about capturable windows + and is able to create callbacks from which to begin to receive content + from. The "title" argument in the "surface_info" event shall be used + to provide a user-readable identifier such as a window title or + program name. + + + + + This will be called whenever a surface that's able to be captured + appears. + + + + + + + Called if a surface becomes unavailable to capture, for example if has + been closed. + + + + + + + Request to start capturing from a surface with a given id. + If an ID becomes unavailable, a NULL will be returned. + + + + + + + + Request to start capturing from an entire wl_output. + If an output becomes unavailable, a NULL will be returned. + + + + + + diff --git a/types/meson.build b/types/meson.build index f9f5b469..0842f98c 100644 --- a/types/meson.build +++ b/types/meson.build @@ -22,6 +22,7 @@ lib_wlr_types = static_library( 'wlr_box.c', 'wlr_compositor.c', 'wlr_cursor.c', + 'wlr_export_dmabuf_v1.c', 'wlr_gamma_control.c', 'wlr_idle_inhibit_v1.c', 'wlr_idle.c', diff --git a/types/wlr_export_dmabuf_v1.c b/types/wlr_export_dmabuf_v1.c new file mode 100644 index 00000000..fa732397 --- /dev/null +++ b/types/wlr_export_dmabuf_v1.c @@ -0,0 +1,185 @@ +#include +#include +#include +#include +#include +#include +#include "wlr-export-dmabuf-unstable-v1-protocol.h" + +#define EXPORT_DMABUF_MANAGER_VERSION 1 + + +static const struct zwlr_export_dmabuf_frame_v1_interface frame_impl; + +static struct wlr_export_dmabuf_frame_v1 *frame_from_resource( + struct wl_resource *resource) { + assert(wl_resource_instance_of(resource, + &zwlr_export_dmabuf_frame_v1_interface, &frame_impl)); + return wl_resource_get_user_data(resource); +} + +static void frame_handle_destroy(struct wl_client *client, + struct wl_resource *resource) { + wl_resource_destroy(resource); +} + +static const struct zwlr_export_dmabuf_frame_v1_interface frame_impl = { + .destroy = frame_handle_destroy, +}; + +static void frame_handle_resource_destroy(struct wl_resource *resource) { + struct wlr_export_dmabuf_frame_v1 *frame = frame_from_resource(resource); + wl_list_remove(&frame->link); + free(frame); +} + + +static const struct zwlr_export_dmabuf_manager_v1_interface manager_impl; + +static struct wlr_export_dmabuf_manager_v1 *manager_from_resource( + struct wl_resource *resource) { + assert(wl_resource_instance_of(resource, + &zwlr_export_dmabuf_manager_v1_interface, &manager_impl)); + return wl_resource_get_user_data(resource); +} + +static void manager_handle_capture_client(struct wl_client *client, + struct wl_resource *manager_resource, uint32_t id, + uint32_t client_id, int32_t overlay_cursor) { + // TODO +} + +static void manager_handle_capture_output(struct wl_client *client, + struct wl_resource *manager_resource, uint32_t id, + struct wl_resource *output_resource) { + struct wlr_export_dmabuf_manager_v1 *manager = + manager_from_resource(manager_resource); + struct wlr_output *output = wlr_output_from_resource(output_resource); + + struct wlr_export_dmabuf_frame_v1 *frame = + calloc(1, sizeof(struct wlr_export_dmabuf_frame_v1)); + if (frame == NULL) { + wl_resource_post_no_memory(manager_resource); + return; + } + frame->manager = manager; + frame->output = output; + + uint32_t version = wl_resource_get_version(manager_resource); + frame->resource = wl_resource_create(client, + &zwlr_export_dmabuf_frame_v1_interface, version, id); + if (frame->resource == NULL) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(frame->resource, &frame_impl, frame, + frame_handle_resource_destroy); + + wl_list_insert(&manager->frames, &frame->link); + + struct wlr_dmabuf_buffer_attribs attribs; + if (!wlr_output_export_dmabuf(output, &attribs)) { + zwlr_export_dmabuf_frame_v1_send_abort(frame->resource); + return; + } + + // TODO: multiple layers support + + uint32_t frame_flags = 0; + uint32_t mod_high = attribs.modifier[0] >> 32; + uint32_t mod_low = attribs.modifier[0]; + + zwlr_export_dmabuf_frame_v1_send_frame(frame->resource, + output->width, output->height, output->scale, output->transform, + attribs.flags, frame_flags, mod_high, mod_low, attribs.n_planes, 1); + + zwlr_export_dmabuf_frame_v1_send_dma_layer(frame->resource, 0, + attribs.format, 1); + + for (int i = 0; i < attribs.n_planes; ++i) { + // TODO: what to do if the kernel doesn't support seek on buffer + off_t size = lseek(attribs.fd[i], 0, SEEK_END); + + zwlr_export_dmabuf_frame_v1_send_dma_object(frame->resource, i, + attribs.fd[i], size); + zwlr_export_dmabuf_frame_v1_send_dma_plane(frame->resource, i, 0, i, + attribs.offset[i], attribs.stride[i]); + } + + // TODO: wait for the frame to be ready + // TODO: timestamps + zwlr_export_dmabuf_frame_v1_send_ready(frame->resource, 0, 0, 0); +} + +static const struct zwlr_export_dmabuf_manager_v1_interface manager_impl = { + .capture_client = manager_handle_capture_client, + .capture_output = manager_handle_capture_output, +}; + +static void manager_handle_resource_destroy(struct wl_resource *resource) { + wl_list_remove(wl_resource_get_link(resource)); +} + +static void manager_bind(struct wl_client *client, void *data, uint32_t version, + uint32_t id) { + struct wlr_export_dmabuf_manager_v1 *manager = data; + + struct wl_resource *resource = wl_resource_create(client, + &zwlr_export_dmabuf_manager_v1_interface, version, id); + if (resource == NULL) { + wl_client_post_no_memory(client); + return; + } + wl_resource_set_implementation(resource, &manager_impl, manager, + manager_handle_resource_destroy); + + wl_list_insert(&manager->resources, wl_resource_get_link(resource)); +} + +static void handle_display_destroy(struct wl_listener *listener, void *data) { + struct wlr_export_dmabuf_manager_v1 *manager = + wl_container_of(listener, manager, display_destroy); + wlr_export_dmabuf_manager_v1_destroy(manager); +} + +struct wlr_export_dmabuf_manager_v1 *wlr_export_dmabuf_manager_v1_create( + struct wl_display *display) { + struct wlr_export_dmabuf_manager_v1 *manager = + calloc(1, sizeof(struct wlr_export_dmabuf_manager_v1)); + if (manager == NULL) { + return NULL; + } + wl_list_init(&manager->resources); + wl_list_init(&manager->frames); + + manager->global = wl_global_create(display, + &zwlr_export_dmabuf_manager_v1_interface, EXPORT_DMABUF_MANAGER_VERSION, + manager, manager_bind); + if (manager->global == NULL) { + free(manager); + return NULL; + } + + manager->display_destroy.notify = handle_display_destroy; + wl_display_add_destroy_listener(display, &manager->display_destroy); + + return manager; +} + +void wlr_export_dmabuf_manager_v1_destroy( + struct wlr_export_dmabuf_manager_v1 *manager) { + if (manager == NULL) { + return; + } + wl_list_remove(&manager->display_destroy.link); + wl_global_destroy(manager->global); + struct wl_resource *resource, *resource_tmp; + wl_resource_for_each_safe(resource, resource_tmp, &manager->resources) { + wl_resource_destroy(resource); + } + struct wlr_export_dmabuf_frame_v1 *frame, *frame_tmp; + wl_list_for_each_safe(frame, frame_tmp, &manager->frames, link) { + wl_resource_destroy(frame->resource); + } + free(manager); +} -- cgit v1.2.3 From 5ba1a9af5652aa2407738ec6290e7a9a59a86ea6 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 23 May 2018 00:03:26 +0100 Subject: render: add wlr_texture_to_dmabuf --- include/wlr/render/egl.h | 5 +++++ include/wlr/render/interface.h | 2 ++ include/wlr/render/wlr_texture.h | 3 +++ render/egl.c | 46 +++++++++++++++++++++++++++++++++++++--- render/glapi.txt | 2 ++ render/gles2/texture.c | 29 +++++++++++++++++++++++++ render/wlr_texture.c | 8 +++++++ 7 files changed, 92 insertions(+), 3 deletions(-) (limited to 'include/wlr') diff --git a/include/wlr/render/egl.h b/include/wlr/render/egl.h index 4d837138..17fef7ed 100644 --- a/include/wlr/render/egl.h +++ b/include/wlr/render/egl.h @@ -20,6 +20,7 @@ struct wlr_egl { bool swap_buffers_with_damage; bool dmabuf_import; bool dmabuf_import_modifiers; + bool dmabuf_export; bool bind_wayland_display; } egl_exts; @@ -85,6 +86,10 @@ int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl, int **formats); int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl, int format, uint64_t **modifiers); +bool wlr_egl_export_image_to_dmabuf(struct wlr_egl *egl, EGLImageKHR image, + int32_t width, int32_t height, uint32_t flags, + struct wlr_dmabuf_buffer_attribs *attribs); + /** * Destroys an EGL image created with the given wlr_egl. */ diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index 2267d376..1f075e81 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -62,6 +62,8 @@ struct wlr_texture_impl { 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, const void *data); + bool (*to_dmabuf)(struct wlr_texture *texture, + struct wlr_dmabuf_buffer_attribs *attribs); void (*destroy)(struct wlr_texture *texture); }; diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index 239fc51b..481b2a37 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -48,6 +48,9 @@ bool wlr_texture_write_pixels(struct wlr_texture *texture, uint32_t src_x, uint32_t src_y, uint32_t dst_x, uint32_t dst_y, const void *data); +bool wlr_texture_to_dmabuf(struct wlr_texture *texture, + struct wlr_dmabuf_buffer_attribs *attribs); + /** * Destroys this wlr_texture. */ diff --git a/render/egl.c b/render/egl.c index 579bb5fe..1182a72f 100644 --- a/render/egl.c +++ b/render/egl.c @@ -178,8 +178,12 @@ bool wlr_egl_init(struct wlr_egl *egl, EGLenum platform, void *remote_display, check_egl_ext(egl->exts_str, "EGL_EXT_image_dma_buf_import_modifiers") && eglQueryDmaBufFormatsEXT && eglQueryDmaBufModifiersEXT; + egl->egl_exts.dmabuf_export = + check_egl_ext(egl->exts_str, "EGL_MESA_image_dma_buf_export"); + egl->egl_exts.bind_wayland_display = check_egl_ext(egl->exts_str, "EGL_WL_bind_wayland_display"); + print_dmabuf_formats(egl); return true; @@ -209,7 +213,7 @@ void wlr_egl_finish(struct wlr_egl *egl) { } bool wlr_egl_bind_display(struct wlr_egl *egl, struct wl_display *local_display) { - if (!egl->egl_exts.bind_wayland_display) { + if (!egl->egl_exts.bind_wayland_display || !eglBindWaylandDisplayWL) { return false; } @@ -414,7 +418,7 @@ EGLImageKHR wlr_egl_create_image_from_dmabuf(struct wlr_egl *egl, } #ifndef DRM_FORMAT_BIG_ENDIAN -# define DRM_FORMAT_BIG_ENDIAN 0x80000000 +#define DRM_FORMAT_BIG_ENDIAN 0x80000000 #endif bool wlr_egl_check_import_dmabuf(struct wlr_egl *egl, struct wlr_dmabuf_buffer *dmabuf) { @@ -446,7 +450,7 @@ bool wlr_egl_check_import_dmabuf(struct wlr_egl *egl, int wlr_egl_get_dmabuf_formats(struct wlr_egl *egl, int **formats) { if (!egl->egl_exts.dmabuf_import || - !egl->egl_exts.dmabuf_import_modifiers) { + !egl->egl_exts.dmabuf_import_modifiers) { wlr_log(L_DEBUG, "dmabuf extension not present"); return -1; } @@ -501,6 +505,42 @@ int wlr_egl_get_dmabuf_modifiers(struct wlr_egl *egl, return num; } +bool wlr_egl_export_image_to_dmabuf(struct wlr_egl *egl, EGLImageKHR image, + int32_t width, int32_t height, uint32_t flags, + struct wlr_dmabuf_buffer_attribs *attribs) { + memset(attribs, 0, sizeof(struct wlr_dmabuf_buffer_attribs)); + + if (!egl->egl_exts.dmabuf_export || !eglExportDMABUFImageQueryMESA || + !eglExportDMABUFImageMESA) { + return false; + } + + // Only one set of modifiers is returned for all planes + EGLuint64KHR modifiers; + if (!eglExportDMABUFImageQueryMESA(egl->display, image, + (int *)&attribs->format, &attribs->n_planes, &modifiers)) { + return false; + } + if (attribs->n_planes > WLR_LINUX_DMABUF_MAX_PLANES) { + wlr_log(L_ERROR, "EGL returned %d planes, but only %d are supported", + attribs->n_planes, WLR_LINUX_DMABUF_MAX_PLANES); + return false; + } + for (int i = 0; i < attribs->n_planes; ++i) { + attribs->modifier[i] = modifiers; + } + + if (!eglExportDMABUFImageMESA(egl->display, image, attribs->fd, + (EGLint *)attribs->stride, (EGLint *)attribs->offset)) { + return false; + } + + attribs->width = width; + attribs->height = height; + attribs->flags = flags; + return true; +} + bool wlr_egl_destroy_surface(struct wlr_egl *egl, EGLSurface surface) { if (!surface) { return true; diff --git a/render/glapi.txt b/render/glapi.txt index a8e4aaba..b1166f27 100644 --- a/render/glapi.txt +++ b/render/glapi.txt @@ -10,6 +10,8 @@ eglCreatePlatformWindowSurfaceEXT -eglSwapBuffersWithDamageKHR -eglQueryDmaBufFormatsEXT -eglQueryDmaBufModifiersEXT +-eglExportDMABUFImageQueryMESA +-eglExportDMABUFImageMESA -eglDebugMessageControlKHR -glDebugMessageCallbackKHR -glDebugMessageControlKHR diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 37424802..742f9da0 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -74,6 +74,34 @@ static bool gles2_texture_write_pixels(struct wlr_texture *wlr_texture, return true; } +static bool gles2_texture_to_dmabuf(struct wlr_texture *wlr_texture, + struct wlr_dmabuf_buffer_attribs *attribs) { + struct wlr_gles2_texture *texture = gles2_get_texture(wlr_texture); + + if (!texture->image) { + assert(texture->type == WLR_GLES2_TEXTURE_GLTEX); + + if (!eglCreateImageKHR) { + return false; + } + + texture->image = eglCreateImageKHR(texture->egl->display, + texture->egl->context, EGL_GL_TEXTURE_2D_KHR, + (EGLClientBuffer)(uintptr_t)texture->gl_tex, NULL); + if (texture->image == EGL_NO_IMAGE_KHR) { + return false; + } + } + + uint32_t flags = 0; + if (texture->inverted_y) { + flags |= WLR_DMABUF_BUFFER_ATTRIBS_FLAGS_Y_INVERT; + } + + return wlr_egl_export_image_to_dmabuf(texture->egl, texture->image, + texture->width, texture->height, flags, attribs); +} + static void gles2_texture_destroy(struct wlr_texture *wlr_texture) { if (wlr_texture == NULL) { return; @@ -102,6 +130,7 @@ static void gles2_texture_destroy(struct wlr_texture *wlr_texture) { static const struct wlr_texture_impl texture_impl = { .get_size = gles2_texture_get_size, .write_pixels = gles2_texture_write_pixels, + .to_dmabuf = gles2_texture_to_dmabuf, .destroy = gles2_texture_destroy, }; diff --git a/render/wlr_texture.c b/render/wlr_texture.c index 9aecfd98..f7ce0b44 100644 --- a/render/wlr_texture.c +++ b/render/wlr_texture.c @@ -54,3 +54,11 @@ bool wlr_texture_write_pixels(struct wlr_texture *texture, return texture->impl->write_pixels(texture, wl_fmt, stride, width, height, src_x, src_y, dst_x, dst_y, data); } + +bool wlr_texture_to_dmabuf(struct wlr_texture *texture, + struct wlr_dmabuf_buffer_attribs *attribs) { + if (!texture->impl->to_dmabuf) { + return false; + } + return texture->impl->to_dmabuf(texture, attribs); +} -- cgit v1.2.3 From e26f4dff9843c51762852642719aa0eee1449aca Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 23 May 2018 09:02:19 +0100 Subject: export-dmabuf: wait for the frame to be ready, send timestamp --- include/wlr/types/wlr_export_dmabuf_v1.h | 2 ++ include/wlr/types/wlr_output.h | 8 +++++++- types/wlr_export_dmabuf_v1.c | 23 +++++++++++++++++++---- types/wlr_output.c | 7 ++++++- 4 files changed, 34 insertions(+), 6 deletions(-) (limited to 'include/wlr') diff --git a/include/wlr/types/wlr_export_dmabuf_v1.h b/include/wlr/types/wlr_export_dmabuf_v1.h index 78db1e61..4cb3393f 100644 --- a/include/wlr/types/wlr_export_dmabuf_v1.h +++ b/include/wlr/types/wlr_export_dmabuf_v1.h @@ -11,6 +11,8 @@ struct wlr_export_dmabuf_frame_v1 { struct wl_list link; struct wlr_output *output; + + struct wl_listener output_swap_buffers; }; struct wlr_export_dmabuf_manager_v1 { diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index 669b96ed..96c98dc3 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -82,7 +82,7 @@ struct wlr_output { struct { struct wl_signal frame; struct wl_signal needs_swap; - struct wl_signal swap_buffers; + struct wl_signal swap_buffers; // wlr_output_event_swap_buffers struct wl_signal enable; struct wl_signal mode; struct wl_signal scale; @@ -108,6 +108,12 @@ struct wlr_output { void *data; }; +struct wlr_output_event_swap_buffers { + struct wlr_output *output; + struct timespec *when; + pixman_region32_t *damage; +}; + struct wlr_surface; void wlr_output_enable(struct wlr_output *output, bool enable); diff --git a/types/wlr_export_dmabuf_v1.c b/types/wlr_export_dmabuf_v1.c index fa732397..2f1c88f2 100644 --- a/types/wlr_export_dmabuf_v1.c +++ b/types/wlr_export_dmabuf_v1.c @@ -30,9 +30,25 @@ static const struct zwlr_export_dmabuf_frame_v1_interface frame_impl = { static void frame_handle_resource_destroy(struct wl_resource *resource) { struct wlr_export_dmabuf_frame_v1 *frame = frame_from_resource(resource); wl_list_remove(&frame->link); + wl_list_remove(&frame->output_swap_buffers.link); free(frame); } +static void frame_output_handle_swap_buffers(struct wl_listener *listener, + void *data) { + struct wlr_export_dmabuf_frame_v1 *frame = + wl_container_of(listener, frame, output_swap_buffers); + struct wlr_output_event_swap_buffers *event = data; + + wl_list_remove(&frame->output_swap_buffers.link); + wl_list_init(&frame->output_swap_buffers.link); + + uint32_t tv_sec_hi = event->when->tv_sec << 32; + uint32_t tv_sec_lo = event->when->tv_sec & 0xFFFFFFFF; + zwlr_export_dmabuf_frame_v1_send_ready(frame->resource, + tv_sec_hi, tv_sec_lo, event->when->tv_nsec); +} + static const struct zwlr_export_dmabuf_manager_v1_interface manager_impl; @@ -87,7 +103,7 @@ static void manager_handle_capture_output(struct wl_client *client, uint32_t frame_flags = 0; uint32_t mod_high = attribs.modifier[0] >> 32; - uint32_t mod_low = attribs.modifier[0]; + uint32_t mod_low = attribs.modifier[0] & 0xFFFFFFFF; zwlr_export_dmabuf_frame_v1_send_frame(frame->resource, output->width, output->height, output->scale, output->transform, @@ -106,9 +122,8 @@ static void manager_handle_capture_output(struct wl_client *client, attribs.offset[i], attribs.stride[i]); } - // TODO: wait for the frame to be ready - // TODO: timestamps - zwlr_export_dmabuf_frame_v1_send_ready(frame->resource, 0, 0, 0); + frame->output_swap_buffers.notify = frame_output_handle_swap_buffers; + wl_signal_add(&output->events.swap_buffers, &frame->output_swap_buffers); } static const struct zwlr_export_dmabuf_manager_v1_interface manager_impl = { diff --git a/types/wlr_output.c b/types/wlr_output.c index f7001b16..b0321d7f 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -467,7 +467,12 @@ bool wlr_output_swap_buffers(struct wlr_output *output, struct timespec *when, output->idle_frame = NULL; } - wlr_signal_emit_safe(&output->events.swap_buffers, damage); + struct wlr_output_event_swap_buffers event = { + .output = output, + .when = when, + .damage = damage, + }; + wlr_signal_emit_safe(&output->events.swap_buffers, &event); int width, height; wlr_output_transformed_resolution(output, &width, &height); -- cgit v1.2.3 From 00e108f2fcd0c41d361a45149ad6a310a0a4b85d Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 23 May 2018 23:27:15 +0100 Subject: export-dmabuf: correctly finish wlr_linux_dmabuf_attribs --- include/wlr/types/wlr_export_dmabuf_v1.h | 2 ++ include/wlr/types/wlr_linux_dmabuf.h | 6 ++++++ types/wlr_export_dmabuf_v1.c | 27 +++++++++++++++------------ types/wlr_linux_dmabuf.c | 15 ++++++++++----- 4 files changed, 33 insertions(+), 17 deletions(-) (limited to 'include/wlr') diff --git a/include/wlr/types/wlr_export_dmabuf_v1.h b/include/wlr/types/wlr_export_dmabuf_v1.h index 4cb3393f..218b1635 100644 --- a/include/wlr/types/wlr_export_dmabuf_v1.h +++ b/include/wlr/types/wlr_export_dmabuf_v1.h @@ -2,6 +2,7 @@ #define WLR_TYPES_WLR_EXPORT_DMABUF_V1_H #include +#include struct wlr_export_dmabuf_manager_v1; @@ -10,6 +11,7 @@ struct wlr_export_dmabuf_frame_v1 { struct wlr_export_dmabuf_manager_v1 *manager; struct wl_list link; + struct wlr_dmabuf_buffer_attribs attribs; struct wlr_output *output; struct wl_listener output_swap_buffers; diff --git a/include/wlr/types/wlr_linux_dmabuf.h b/include/wlr/types/wlr_linux_dmabuf.h index 531e68ab..1677398b 100644 --- a/include/wlr/types/wlr_linux_dmabuf.h +++ b/include/wlr/types/wlr_linux_dmabuf.h @@ -37,6 +37,12 @@ struct wlr_dmabuf_buffer { struct wlr_dmabuf_buffer_attribs attributes; }; +/** + * Closes all file descriptors in the DMA-BUF attributes. + */ +void wlr_dmabuf_buffer_attribs_finish( + struct wlr_dmabuf_buffer_attribs *attribs); + /** * Returns true if the given resource was created via the linux-dmabuf * buffer protocol, false otherwise diff --git a/types/wlr_export_dmabuf_v1.c b/types/wlr_export_dmabuf_v1.c index 4a7382a3..1b284c44 100644 --- a/types/wlr_export_dmabuf_v1.c +++ b/types/wlr_export_dmabuf_v1.c @@ -5,6 +5,7 @@ #include #include #include "wlr-export-dmabuf-unstable-v1-protocol.h" +#include #define EXPORT_DMABUF_MANAGER_VERSION 1 @@ -31,6 +32,7 @@ static void frame_handle_resource_destroy(struct wl_resource *resource) { struct wlr_export_dmabuf_frame_v1 *frame = frame_from_resource(resource); wl_list_remove(&frame->link); wl_list_remove(&frame->output_swap_buffers.link); + wlr_dmabuf_buffer_attribs_finish(&frame->attribs); free(frame); } @@ -80,6 +82,7 @@ static void manager_handle_capture_output(struct wl_client *client, } frame->manager = manager; frame->output = output; + wl_list_init(&frame->output_swap_buffers.link); uint32_t version = wl_resource_get_version(manager_resource); frame->resource = wl_resource_create(client, @@ -93,9 +96,8 @@ static void manager_handle_capture_output(struct wl_client *client, wl_list_insert(&manager->frames, &frame->link); - struct wlr_dmabuf_buffer_attribs attribs; - if (!wlr_output_export_dmabuf(output, &attribs)) { - wl_list_init(&frame->output_swap_buffers.link); + struct wlr_dmabuf_buffer_attribs *attribs = &frame->attribs; + if (!wlr_output_export_dmabuf(output, attribs)) { // TODO: abort reason zwlr_export_dmabuf_frame_v1_send_abort(frame->resource, 0); return; @@ -104,28 +106,29 @@ static void manager_handle_capture_output(struct wl_client *client, // TODO: multiple layers support uint32_t frame_flags = 0; - uint32_t mod_high = attribs.modifier[0] >> 32; - uint32_t mod_low = attribs.modifier[0] & 0xFFFFFFFF; + uint32_t mod_high = attribs->modifier[0] >> 32; + uint32_t mod_low = attribs->modifier[0] & 0xFFFFFFFF; zwlr_export_dmabuf_frame_v1_send_frame(frame->resource, output->width, output->height, output->scale, output->transform, - attribs.flags, frame_flags, mod_high, mod_low, attribs.n_planes, 1); + attribs->flags, frame_flags, mod_high, mod_low, attribs->n_planes, 1); zwlr_export_dmabuf_frame_v1_send_layer(frame->resource, 0, - attribs.format, 1); + attribs->format, 1); - for (int i = 0; i < attribs.n_planes; ++i) { + for (int i = 0; i < attribs->n_planes; ++i) { // TODO: what to do if the kernel doesn't support seek on buffer - off_t size = lseek(attribs.fd[i], 0, SEEK_END); + off_t size = lseek(attribs->fd[i], 0, SEEK_END); zwlr_export_dmabuf_frame_v1_send_object(frame->resource, i, - attribs.fd[i], size); + attribs->fd[i], size); zwlr_export_dmabuf_frame_v1_send_plane(frame->resource, i, 0, i, - attribs.offset[i], attribs.stride[i]); + attribs->offset[i], attribs->stride[i]); } - frame->output_swap_buffers.notify = frame_output_handle_swap_buffers; + wl_list_remove(&frame->output_swap_buffers.link); wl_signal_add(&output->events.swap_buffers, &frame->output_swap_buffers); + frame->output_swap_buffers.notify = frame_output_handle_swap_buffers; } static const struct zwlr_export_dmabuf_manager_v1_interface manager_impl = { diff --git a/types/wlr_linux_dmabuf.c b/types/wlr_linux_dmabuf.c index 9bcd473f..8f46539f 100644 --- a/types/wlr_linux_dmabuf.c +++ b/types/wlr_linux_dmabuf.c @@ -51,12 +51,17 @@ struct wlr_dmabuf_buffer *wlr_dmabuf_buffer_from_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; +void wlr_dmabuf_buffer_attribs_finish( + struct wlr_dmabuf_buffer_attribs *attribs) { + for (int i = 0; i < attribs->n_planes; ++i) { + close(attribs->fd[i]); + attribs->fd[i] = -1; } - buffer->attributes.n_planes = 0; + attribs->n_planes = 0; +} + +static void linux_dmabuf_buffer_destroy(struct wlr_dmabuf_buffer *buffer) { + wlr_dmabuf_buffer_attribs_finish(&buffer->attributes); free(buffer); } -- cgit v1.2.3 From e4933ab445c70b9ac3c0026718b29a18be171ed5 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 8 Jun 2018 20:06:13 +0100 Subject: Introduce wlr_buffer --- include/wlr/types/wlr_buffer.h | 36 ++++++++ include/wlr/types/wlr_surface.h | 1 + types/meson.build | 1 + types/wlr_buffer.c | 186 ++++++++++++++++++++++++++++++++++++++++ types/wlr_surface.c | 132 +++++++++------------------- 5 files changed, 264 insertions(+), 92 deletions(-) create mode 100644 include/wlr/types/wlr_buffer.h create mode 100644 types/wlr_buffer.c (limited to 'include/wlr') diff --git a/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h new file mode 100644 index 00000000..28567f26 --- /dev/null +++ b/include/wlr/types/wlr_buffer.h @@ -0,0 +1,36 @@ +#ifndef WLR_TYPES_WLR_BUFFER_H +#define WLR_TYPES_WLR_BUFFER_H + +#include +#include + +struct wlr_buffer { + struct wl_resource *resource; + struct wlr_texture *texture; + bool released; + size_t n_refs; + + struct wl_listener resource_destroy; +}; + +struct wlr_renderer; + +// Checks if a resource is a wl_buffer. +bool wlr_resource_is_buffer(struct wl_resource *resource); +// Returns the buffer size. +bool wlr_buffer_get_resource_size(struct wl_resource *resource, + struct wlr_renderer *renderer, int *width, int *height); + +// Uploads the texture to the GPU and references it. +struct wlr_buffer *wlr_buffer_create(struct wlr_renderer *renderer, + struct wl_resource *resource); +// References and unreferences the buffer. +void wlr_buffer_ref(struct wlr_buffer *buffer); +void wlr_buffer_unref(struct wlr_buffer *buffer); +// Tries to update the texture in the provided buffer. This destroys `buffer` +// and returns a new buffer. +// Fails if `buffer->n_refs` > 1 or if the texture isn't mutable. +struct wlr_buffer *wlr_buffer_apply_damage(struct wlr_buffer *buffer, + struct wl_resource *resource, pixman_region32_t *damage); + +#endif diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index 526e4e2c..64503e78 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -69,6 +69,7 @@ struct wlr_subsurface { struct wlr_surface { struct wl_resource *resource; struct wlr_renderer *renderer; + struct wlr_buffer *buffer; struct wlr_texture *texture; struct wlr_surface_state *current, *pending; const char *role; // the lifetime-bound role or null diff --git a/types/meson.build b/types/meson.build index f9f5b469..87f21c55 100644 --- a/types/meson.build +++ b/types/meson.build @@ -20,6 +20,7 @@ lib_wlr_types = static_library( 'xdg_shell_v6/wlr_xdg_surface_v6.c', 'xdg_shell_v6/wlr_xdg_toplevel_v6.c', 'wlr_box.c', + 'wlr_buffer.c', 'wlr_compositor.c', 'wlr_cursor.c', 'wlr_gamma_control.c', diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c new file mode 100644 index 00000000..e062df4c --- /dev/null +++ b/types/wlr_buffer.c @@ -0,0 +1,186 @@ +#include +#include +#include +#include +#include +#include + +bool wlr_resource_is_buffer(struct wl_resource *resource) { + return strcmp(wl_resource_get_class(resource), wl_buffer_interface.name) == 0; +} + +bool wlr_buffer_get_resource_size(struct wl_resource *resource, + struct wlr_renderer *renderer, int *width, int *height) { + assert(wlr_resource_is_buffer(resource)); + + struct wl_shm_buffer *shm_buf = wl_shm_buffer_get(resource); + if (shm_buf != NULL) { + *width = wl_shm_buffer_get_width(shm_buf); + *height = wl_shm_buffer_get_height(shm_buf); + } else if (wlr_renderer_resource_is_wl_drm_buffer(renderer, + resource)) { + wlr_renderer_wl_drm_buffer_get_size(renderer, resource, + width, height); + } else if (wlr_dmabuf_resource_is_buffer(resource)) { + struct wlr_dmabuf_buffer *dmabuf = + wlr_dmabuf_buffer_from_buffer_resource(resource); + *width = dmabuf->attributes.width; + *height = dmabuf->attributes.height; + } else { + *width = *height = 0; + return false; + } + + return true; +} + + +static void buffer_resource_handle_destroy(struct wl_listener *listener, + void *data) { + struct wlr_buffer *buffer = + wl_container_of(listener, buffer, resource_destroy); + wl_list_remove(&buffer->resource_destroy.link); + wl_list_init(&buffer->resource_destroy.link); + buffer->resource = NULL; + + if (!buffer->released) { + // The texture becomes invalid + wlr_texture_destroy(buffer->texture); + buffer->texture = NULL; + } +} + +struct wlr_buffer *wlr_buffer_create(struct wlr_renderer *renderer, + struct wl_resource *resource) { + assert(wlr_resource_is_buffer(resource)); + + struct wlr_texture *texture = NULL; + bool released = false; + + struct wl_shm_buffer *shm_buf = wl_shm_buffer_get(resource); + if (shm_buf != NULL) { + enum wl_shm_format fmt = wl_shm_buffer_get_format(shm_buf); + int32_t stride = wl_shm_buffer_get_stride(shm_buf); + int32_t width = wl_shm_buffer_get_width(shm_buf); + int32_t height = wl_shm_buffer_get_height(shm_buf); + + wl_shm_buffer_begin_access(shm_buf); + void *data = wl_shm_buffer_get_data(shm_buf); + texture = wlr_texture_from_pixels(renderer, fmt, stride, + width, height, data); + wl_shm_buffer_end_access(shm_buf); + + // We have uploaded the data, we don't need to access the wl_buffer + // anymore + wl_buffer_send_release(resource); + released = true; + } else if (wlr_renderer_resource_is_wl_drm_buffer(renderer, resource)) { + texture = wlr_texture_from_wl_drm(renderer, resource); + } else if (wlr_dmabuf_resource_is_buffer(resource)) { + struct wlr_dmabuf_buffer *dmabuf = + wlr_dmabuf_buffer_from_buffer_resource(resource); + texture = wlr_texture_from_dmabuf(renderer, &dmabuf->attributes); + } else { + wlr_log(L_ERROR, "Cannot upload texture: unknown buffer type"); + return NULL; + } + + if (texture == NULL) { + wlr_log(L_ERROR, "Failed to upload texture"); + return NULL; + } + + struct wlr_buffer *buffer = calloc(1, sizeof(struct wlr_buffer)); + if (buffer == NULL) { + return NULL; + } + buffer->resource = resource; + buffer->texture = texture; + buffer->released = released; + buffer->n_refs = 1; + + wl_resource_add_destroy_listener(resource, &buffer->resource_destroy); + buffer->resource_destroy.notify = buffer_resource_handle_destroy; + + return buffer; +} + +void wlr_buffer_ref(struct wlr_buffer *buffer) { + buffer->n_refs++; +} + +void wlr_buffer_unref(struct wlr_buffer *buffer) { + if (buffer == NULL) { + return; + } + + assert(buffer->n_refs > 0); + buffer->n_refs--; + if (buffer->n_refs > 0) { + return; + } + + if (!buffer->released && buffer->resource != NULL) { + wl_buffer_send_release(buffer->resource); + } + + wl_list_remove(&buffer->resource_destroy.link); + wlr_texture_destroy(buffer->texture); + free(buffer); +} + +struct wlr_buffer *wlr_buffer_apply_damage(struct wlr_buffer *buffer, + struct wl_resource *resource, pixman_region32_t *damage) { + assert(wlr_resource_is_buffer(resource)); + + if (buffer->n_refs > 1) { + // Someone else still has a reference to the buffer + return NULL; + } + + struct wl_shm_buffer *shm_buf = wl_shm_buffer_get(resource); + if (shm_buf == NULL) { + // Uploading only damaged regions only works for wl_shm buffers + return NULL; + } + + enum wl_shm_format fmt = wl_shm_buffer_get_format(shm_buf); + int32_t stride = wl_shm_buffer_get_stride(shm_buf); + int32_t width = wl_shm_buffer_get_width(shm_buf); + int32_t height = wl_shm_buffer_get_height(shm_buf); + + int32_t texture_width, texture_height; + wlr_texture_get_size(buffer->texture, &texture_width, &texture_height); + if (width != texture_width || height != texture_height) { + return NULL; + } + + wl_shm_buffer_begin_access(shm_buf); + void *data = wl_shm_buffer_get_data(shm_buf); + + int n; + pixman_box32_t *rects = pixman_region32_rectangles(damage, &n); + for (int i = 0; i < n; ++i) { + pixman_box32_t *r = &rects[i]; + if (!wlr_texture_write_pixels(buffer->texture, fmt, stride, + r->x2 - r->x1, r->y2 - r->y1, r->x1, r->y1, + r->x1, r->y1, data)) { + wl_shm_buffer_end_access(shm_buf); + return NULL; + } + } + + wl_shm_buffer_end_access(shm_buf); + + // We have uploaded the data, we don't need to access the wl_buffer + // anymore + wl_buffer_send_release(resource); + + wl_list_remove(&buffer->resource_destroy.link); + wl_resource_add_destroy_listener(resource, &buffer->resource_destroy); + buffer->resource_destroy.notify = buffer_resource_handle_destroy; + + buffer->resource = resource; + buffer->released = true; + return buffer; +} diff --git a/types/wlr_surface.c b/types/wlr_surface.c index 9c3eb86d..7d8da02f 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -1,10 +1,9 @@ #include #include #include -#include #include +#include #include -#include #include #include #include @@ -46,13 +45,6 @@ static void surface_handle_buffer_destroy(struct wl_listener *listener, surface_state_reset_buffer(state); } -static void surface_state_release_buffer(struct wlr_surface_state *state) { - if (state->buffer) { - wl_buffer_send_release(state->buffer); - surface_state_reset_buffer(state); - } -} - static void surface_state_set_buffer(struct wlr_surface_state *state, struct wl_resource *buffer) { surface_state_reset_buffer(state); @@ -175,24 +167,8 @@ static bool surface_update_size(struct wlr_surface *surface, int scale = state->scale; enum wl_output_transform transform = state->transform; - struct wl_shm_buffer *buf = wl_shm_buffer_get(state->buffer); - if (buf != NULL) { - state->buffer_width = wl_shm_buffer_get_width(buf); - state->buffer_height = wl_shm_buffer_get_height(buf); - } else if (wlr_renderer_resource_is_wl_drm_buffer(surface->renderer, - state->buffer)) { - wlr_renderer_wl_drm_buffer_get_size(surface->renderer, state->buffer, - &state->buffer_width, &state->buffer_height); - } else if (wlr_dmabuf_resource_is_buffer(state->buffer)) { - struct wlr_dmabuf_buffer *dmabuf = - wlr_dmabuf_buffer_from_buffer_resource(state->buffer); - state->buffer_width = dmabuf->attributes.width; - state->buffer_height = dmabuf->attributes.height; - } else { - wlr_log(L_ERROR, "Unknown buffer handle attached"); - state->buffer_width = 0; - state->buffer_height = 0; - } + wlr_buffer_get_resource_size(state->buffer, surface->renderer, + &state->buffer_width, &state->buffer_height); int width = state->buffer_width / scale; int height = state->buffer_height / scale; @@ -243,7 +219,6 @@ static void surface_move_state(struct wlr_surface *surface, update_size = true; } if ((next->invalid & WLR_SURFACE_INVALID_BUFFER)) { - surface_state_release_buffer(state); surface_state_set_buffer(state, next->buffer); surface_state_reset_buffer(next); state->sx = next->sx; @@ -351,86 +326,60 @@ static void surface_damage_subsurfaces(struct wlr_subsurface *subsurface) { } static void surface_apply_damage(struct wlr_surface *surface, - bool invalid_buffer, bool reupload_buffer) { + bool invalid_buffer) { struct wl_resource *resource = surface->current->buffer; if (resource == NULL) { + // NULL commit + wlr_buffer_unref(surface->buffer); + surface->buffer = NULL; + surface->texture = NULL; return; } - struct wl_shm_buffer *buf = wl_shm_buffer_get(resource); - if (buf != NULL) { - wl_shm_buffer_begin_access(buf); + if (surface->buffer != NULL && !surface->buffer->released && + !invalid_buffer) { + // The buffer is still the same, no need to re-upload + return; + } - enum wl_shm_format fmt = wl_shm_buffer_get_format(buf); - int32_t stride = wl_shm_buffer_get_stride(buf); - int32_t width = wl_shm_buffer_get_width(buf); - int32_t height = wl_shm_buffer_get_height(buf); - void *data = wl_shm_buffer_get_data(buf); + if (surface->buffer != NULL && surface->buffer->released) { + pixman_region32_t damage; + pixman_region32_init(&damage); + pixman_region32_copy(&damage, &surface->current->buffer_damage); + pixman_region32_intersect_rect(&damage, &damage, 0, 0, + surface->current->buffer_width, surface->current->buffer_height); - if (surface->texture == NULL || reupload_buffer) { - wlr_texture_destroy(surface->texture); - surface->texture = wlr_texture_from_pixels(surface->renderer, fmt, - stride, width, height, data); - } else { - pixman_region32_t damage; - pixman_region32_init(&damage); - pixman_region32_copy(&damage, &surface->current->buffer_damage); - pixman_region32_intersect_rect(&damage, &damage, 0, 0, - surface->current->buffer_width, - surface->current->buffer_height); - - int n; - pixman_box32_t *rects = pixman_region32_rectangles(&damage, &n); - for (int i = 0; i < n; ++i) { - pixman_box32_t *r = &rects[i]; - if (!wlr_texture_write_pixels(surface->texture, fmt, stride, - r->x2 - r->x1, r->y2 - r->y1, r->x1, r->y1, - r->x1, r->y1, data)) { - break; - } - } - - pixman_region32_fini(&damage); - } + struct wlr_buffer *updated_buffer = + wlr_buffer_apply_damage(surface->buffer, resource, &damage); - wl_shm_buffer_end_access(buf); - } else if (invalid_buffer || reupload_buffer) { - wlr_texture_destroy(surface->texture); - - if (wlr_renderer_resource_is_wl_drm_buffer(surface->renderer, resource)) { - surface->texture = - wlr_texture_from_wl_drm(surface->renderer, resource); - } else if (wlr_dmabuf_resource_is_buffer(resource)) { - struct wlr_dmabuf_buffer *dmabuf = - wlr_dmabuf_buffer_from_buffer_resource(resource); - surface->texture = - wlr_texture_from_dmabuf(surface->renderer, &dmabuf->attributes); - } else { - surface->texture = NULL; - wlr_log(L_ERROR, "Unknown buffer handle attached"); + pixman_region32_fini(&damage); + + if (updated_buffer != NULL) { + surface->buffer = updated_buffer; + return; } } - surface_state_release_buffer(surface->current); + wlr_buffer_unref(surface->buffer); + surface->buffer = NULL; + surface->texture = NULL; + + struct wlr_buffer *buffer = wlr_buffer_create(surface->renderer, resource); + if (buffer == NULL) { + wlr_log(L_ERROR, "Failed to upload buffer"); + return; + } + + surface->buffer = buffer; + surface->texture = buffer->texture; } static void surface_commit_pending(struct wlr_surface *surface) { - int32_t oldw = surface->current->buffer_width; - int32_t oldh = surface->current->buffer_height; - bool invalid_buffer = surface->pending->invalid & WLR_SURFACE_INVALID_BUFFER; - bool null_buffer_commit = invalid_buffer && surface->pending->buffer == NULL; surface_move_state(surface, surface->pending, surface->current); - if (null_buffer_commit) { - wlr_texture_destroy(surface->texture); - surface->texture = NULL; - } - - bool reupload_buffer = oldw != surface->current->buffer_width || - oldh != surface->current->buffer_height; - surface_apply_damage(surface, invalid_buffer, reupload_buffer); + surface_apply_damage(surface, invalid_buffer); // commit subsurface order struct wlr_subsurface *subsurface; @@ -652,10 +601,9 @@ static void surface_handle_resource_destroy(struct wl_resource *resource) { wl_list_remove(wl_resource_get_link(surface->resource)); wl_list_remove(&surface->renderer_destroy.link); - wlr_texture_destroy(surface->texture); surface_state_destroy(surface->pending); surface_state_destroy(surface->current); - + wlr_buffer_unref(surface->buffer); free(surface); } -- cgit v1.2.3 From 7d24af43e5f2fc04b41c5697101a44d67a384a12 Mon Sep 17 00:00:00 2001 From: emersion Date: Fri, 8 Jun 2018 20:28:57 +0100 Subject: buffer: improve docs --- include/wlr/types/wlr_buffer.h | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-) (limited to 'include/wlr') diff --git a/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h index 28567f26..c57d79ed 100644 --- a/include/wlr/types/wlr_buffer.h +++ b/include/wlr/types/wlr_buffer.h @@ -4,9 +4,12 @@ #include #include +/** + * A client buffer. + */ struct wlr_buffer { - struct wl_resource *resource; - struct wlr_texture *texture; + struct wl_resource *resource; // can be NULL + struct wlr_texture *texture; // can be NULL bool released; size_t n_refs; @@ -15,21 +18,38 @@ struct wlr_buffer { struct wlr_renderer; -// Checks if a resource is a wl_buffer. +/** + * Check if a resource is a wl_buffer resource. + */ bool wlr_resource_is_buffer(struct wl_resource *resource); -// Returns the buffer size. +/** + * Get the size of a wl_buffer resource. + */ bool wlr_buffer_get_resource_size(struct wl_resource *resource, struct wlr_renderer *renderer, int *width, int *height); -// Uploads the texture to the GPU and references it. +/** + * Upload a buffer to the GPU and reference it. + */ struct wlr_buffer *wlr_buffer_create(struct wlr_renderer *renderer, struct wl_resource *resource); -// References and unreferences the buffer. +/** + * Reference the buffer. + */ void wlr_buffer_ref(struct wlr_buffer *buffer); +/** + * Unreference the buffer. After this call, `buffer` may not be accessed + * anymore. + */ void wlr_buffer_unref(struct wlr_buffer *buffer); -// Tries to update the texture in the provided buffer. This destroys `buffer` -// and returns a new buffer. -// Fails if `buffer->n_refs` > 1 or if the texture isn't mutable. +/** + * Try to update the buffer's content. On success, returns the updated buffer + * and destroys the provided `buffer`. On error, `buffer` is intact and NULL is + * returned. + * + * Fails if there's more than one reference to the buffer or if the texture + * isn't mutable. + */ struct wlr_buffer *wlr_buffer_apply_damage(struct wlr_buffer *buffer, struct wl_resource *resource, pixman_region32_t *damage); -- cgit v1.2.3 From 38d415dd2047114badd6a9f65dab6fe0b5b8e5d0 Mon Sep 17 00:00:00 2001 From: emersion Date: Mon, 11 Jun 2018 08:13:35 +0100 Subject: buffer: make wlr_buffer_ref return the buffer --- include/wlr/types/wlr_buffer.h | 2 +- types/wlr_buffer.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'include/wlr') diff --git a/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h index c57d79ed..fc348a1c 100644 --- a/include/wlr/types/wlr_buffer.h +++ b/include/wlr/types/wlr_buffer.h @@ -36,7 +36,7 @@ struct wlr_buffer *wlr_buffer_create(struct wlr_renderer *renderer, /** * Reference the buffer. */ -void wlr_buffer_ref(struct wlr_buffer *buffer); +struct wlr_buffer *wlr_buffer_ref(struct wlr_buffer *buffer); /** * Unreference the buffer. After this call, `buffer` may not be accessed * anymore. diff --git a/types/wlr_buffer.c b/types/wlr_buffer.c index e062df4c..82a359f0 100644 --- a/types/wlr_buffer.c +++ b/types/wlr_buffer.c @@ -105,8 +105,9 @@ struct wlr_buffer *wlr_buffer_create(struct wlr_renderer *renderer, return buffer; } -void wlr_buffer_ref(struct wlr_buffer *buffer) { +struct wlr_buffer *wlr_buffer_ref(struct wlr_buffer *buffer) { buffer->n_refs++; + return buffer; } void wlr_buffer_unref(struct wlr_buffer *buffer) { -- cgit v1.2.3 From 0378d143d9517c7508b64b81e9267a29ab1951aa Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 13 Jun 2018 19:38:10 +0100 Subject: surface: remove wlr_surface.texture The texture is managed by the surface's wlr_buffer now. In particular, the buffer can destroy the texture early if it becomes invalid. --- include/wlr/types/wlr_buffer.h | 11 +++++++++-- include/wlr/types/wlr_surface.h | 14 +++++++++++++- rootston/output.c | 6 +++--- types/wlr_output.c | 10 +++++----- types/wlr_surface.c | 12 ++++++++---- 5 files changed, 38 insertions(+), 15 deletions(-) (limited to 'include/wlr') diff --git a/include/wlr/types/wlr_buffer.h b/include/wlr/types/wlr_buffer.h index fc348a1c..eabc8b51 100644 --- a/include/wlr/types/wlr_buffer.h +++ b/include/wlr/types/wlr_buffer.h @@ -8,8 +8,15 @@ * A client buffer. */ struct wlr_buffer { - struct wl_resource *resource; // can be NULL - struct wlr_texture *texture; // can be NULL + /** + * The buffer resource, if any. Will be NULL if the client destroys it. + */ + struct wl_resource *resource; + /** + * The buffer's texture, if any. A buffer will not have a texture if the + * client destroys the buffer before it has been released. + */ + struct wlr_texture *texture; bool released; size_t n_refs; diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index 64503e78..8517934a 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -69,8 +69,13 @@ struct wlr_subsurface { struct wlr_surface { struct wl_resource *resource; struct wlr_renderer *renderer; + /** + * The surface's buffer, if any. A surface has an attached buffer when it + * commits with a non-null buffer in its pending state. A surface will not + * have a buffer if it has never committed one, has committed a null buffer, + * or something went wrong with uploading the buffer. + */ struct wlr_buffer *buffer; - struct wlr_texture *texture; struct wlr_surface_state *current, *pending; const char *role; // the lifetime-bound role or null @@ -125,6 +130,13 @@ int wlr_surface_set_role(struct wlr_surface *surface, const char *role, */ bool wlr_surface_has_buffer(struct wlr_surface *surface); +/** + * Get the texture of the buffer currently attached to this surface. Returns + * NULL if no buffer is currently attached or if something went wrong with + * uploading the buffer. + */ +struct wlr_texture *wlr_surface_get_texture(struct wlr_surface *surface); + /** * Create a new subsurface resource with the provided new ID. If `resource_list` * is non-NULL, adds the subsurface's resource to the list. diff --git a/rootston/output.c b/rootston/output.c index faa808d1..353d431f 100644 --- a/rootston/output.c +++ b/rootston/output.c @@ -189,7 +189,8 @@ static void render_surface(struct wlr_surface *surface, int sx, int sy, struct roots_output *output = data->output; float rotation = data->layout.rotation; - if (!wlr_surface_has_buffer(surface)) { + struct wlr_texture *texture = wlr_surface_get_texture(surface); + if (texture == NULL) { return; } @@ -230,8 +231,7 @@ static void render_surface(struct wlr_surface *surface, int sx, int sy, pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); for (int i = 0; i < nrects; ++i) { scissor_output(output, &rects[i]); - wlr_render_texture_with_matrix(renderer, surface->texture, matrix, - data->alpha); + wlr_render_texture_with_matrix(renderer, texture, matrix, data->alpha); } damage_finish: diff --git a/types/wlr_output.c b/types/wlr_output.c index a5a6d0eb..7befb651 100644 --- a/types/wlr_output.c +++ b/types/wlr_output.c @@ -367,7 +367,8 @@ static void output_fullscreen_surface_render(struct wlr_output *output, struct wlr_renderer *renderer = wlr_backend_get_renderer(output->backend); assert(renderer); - if (!wlr_surface_has_buffer(surface)) { + struct wlr_texture *texture = wlr_surface_get_texture(surface); + if (texture == NULL) { wlr_renderer_clear(renderer, (float[]){0, 0, 0, 1}); return; } @@ -386,8 +387,7 @@ static void output_fullscreen_surface_render(struct wlr_output *output, for (int i = 0; i < nrects; ++i) { output_scissor(output, &rects[i]); wlr_renderer_clear(renderer, (float[]){0, 0, 0, 1}); - wlr_render_texture_with_matrix(surface->renderer, surface->texture, - matrix, 1.0f); + wlr_render_texture_with_matrix(surface->renderer, texture, matrix, 1.0f); } wlr_renderer_scissor(renderer, NULL); @@ -418,7 +418,7 @@ static void output_cursor_render(struct wlr_output_cursor *cursor, struct wlr_texture *texture = cursor->texture; if (cursor->surface != NULL) { - texture = cursor->surface->texture; + texture = wlr_surface_get_texture(cursor->surface); } if (texture == NULL) { return; @@ -700,7 +700,7 @@ static bool output_cursor_attempt_hardware(struct wlr_output_cursor *cursor) { enum wl_output_transform transform = WL_OUTPUT_TRANSFORM_NORMAL; struct wlr_texture *texture = cursor->texture; if (cursor->surface != NULL) { - texture = cursor->surface->texture; + texture = wlr_surface_get_texture(cursor->surface); scale = cursor->surface->current->scale; transform = cursor->surface->current->transform; } diff --git a/types/wlr_surface.c b/types/wlr_surface.c index 7d8da02f..af1e9446 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -332,7 +332,6 @@ static void surface_apply_damage(struct wlr_surface *surface, // NULL commit wlr_buffer_unref(surface->buffer); surface->buffer = NULL; - surface->texture = NULL; return; } @@ -362,7 +361,6 @@ static void surface_apply_damage(struct wlr_surface *surface, wlr_buffer_unref(surface->buffer); surface->buffer = NULL; - surface->texture = NULL; struct wlr_buffer *buffer = wlr_buffer_create(surface->renderer, resource); if (buffer == NULL) { @@ -371,7 +369,6 @@ static void surface_apply_damage(struct wlr_surface *surface, } surface->buffer = buffer; - surface->texture = buffer->texture; } static void surface_commit_pending(struct wlr_surface *surface) { @@ -660,8 +657,15 @@ struct wlr_surface *wlr_surface_create(struct wl_client *client, return surface; } +struct wlr_texture *wlr_surface_get_texture(struct wlr_surface *surface) { + if (surface->buffer == NULL) { + return NULL; + } + return surface->buffer->texture; +} + bool wlr_surface_has_buffer(struct wlr_surface *surface) { - return surface->texture != NULL; + return wlr_surface_get_texture(surface) != NULL; } int wlr_surface_set_role(struct wlr_surface *surface, const char *role, -- cgit v1.2.3 From 47985d2dc56a6af469ac9375e7548136765aff16 Mon Sep 17 00:00:00 2001 From: Scott Anderson Date: Thu, 14 Jun 2018 20:46:16 +1200 Subject: Multiseat fixes --- backend/libinput/backend.c | 4 +-- backend/session/direct.c | 60 ++++++++++++++++++++++++++----------------- backend/session/logind.c | 5 ++++ backend/session/session.c | 4 +-- include/wlr/backend/session.h | 6 ++++- 5 files changed, 50 insertions(+), 29 deletions(-) (limited to 'include/wlr') diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index f4d54c97..1dde5854 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -55,8 +55,8 @@ static bool backend_start(struct wlr_backend *_backend) { return false; } - // TODO: Let user customize seat used - if (libinput_udev_assign_seat(backend->libinput_context, "seat0") != 0) { + if (libinput_udev_assign_seat(backend->libinput_context, + backend->session->seat) != 0) { wlr_log(L_ERROR, "Failed to assign libinput seat"); return false; } diff --git a/backend/session/direct.c b/backend/session/direct.c index 13a26d99..c1a59647 100644 --- a/backend/session/direct.c +++ b/backend/session/direct.c @@ -1,5 +1,6 @@ #define _POSIX_C_SOURCE 200809L #include +#include #include #include #include @@ -76,30 +77,39 @@ static void direct_session_close(struct wlr_session *base, int fd) { static bool direct_change_vt(struct wlr_session *base, unsigned vt) { struct direct_session *session = wl_container_of(base, session, base); + + // Only seat0 has VTs associated with it + if (strcmp(session->base.seat, "seat0") == 0) { + return true; + } + return ioctl(session->tty_fd, VT_ACTIVATE, (int)vt) == 0; } static void direct_session_destroy(struct wlr_session *base) { struct direct_session *session = wl_container_of(base, session, base); - struct vt_mode mode = { - .mode = VT_AUTO, - }; - errno = 0; + if (strcmp(session->base.seat, "seat0") == 0) { + struct vt_mode mode = { + .mode = VT_AUTO, + }; + errno = 0; + + ioctl(session->tty_fd, KDSKBMODE, session->old_kbmode); + ioctl(session->tty_fd, KDSETMODE, KD_TEXT); + ioctl(session->tty_fd, VT_SETMODE, &mode); - ioctl(session->tty_fd, KDSKBMODE, session->old_kbmode); - ioctl(session->tty_fd, KDSETMODE, KD_TEXT); - ioctl(session->tty_fd, VT_SETMODE, &mode); + if (errno) { + wlr_log(L_ERROR, "Failed to restore tty"); + } - if (errno) { - wlr_log(L_ERROR, "Failed to restore tty"); + wl_event_source_remove(session->vt_source); + close(session->tty_fd); } direct_ipc_finish(session->sock, session->child); close(session->sock); - wl_event_source_remove(session->vt_source); - close(session->tty_fd); free(session); } @@ -138,19 +148,19 @@ static int vt_handler(int signo, void *data) { } static bool setup_tty(struct direct_session *session, struct wl_display *display) { - int fd = dup(STDIN_FILENO); + int fd = open("/dev/tty", O_RDWR); if (fd == -1) { - wlr_log_errno(L_ERROR, "Cannot open tty"); + wlr_log_errno(L_ERROR, "Cannot open /dev/tty"); return false; } - struct stat st; - if (fstat(fd, &st) == -1 || major(st.st_rdev) != TTY_MAJOR || minor(st.st_rdev) == 0) { - wlr_log(L_ERROR, "Not running from a virtual terminal"); + struct vt_stat vt_stat; + if (ioctl(fd, VT_GETSTATE, &vt_stat)) { + wlr_log_errno(L_ERROR, "Could not get current tty number"); goto error; } - int tty = minor(st.st_rdev); + int tty = vt_stat.v_active; int ret, kd_mode, old_kbmode; ret = ioctl(fd, KDGETMODE, &kd_mode); @@ -224,20 +234,24 @@ static struct wlr_session *direct_session_create(struct wl_display *disp) { goto error_session; } - if (!setup_tty(session, disp)) { - goto error_ipc; - } - - // XXX: Is it okay to trust the environment like this? const char *seat = getenv("XDG_SEAT"); if (!seat) { seat = "seat0"; } - wlr_log(L_INFO, "Successfully loaded direct session"); + if (strcmp(seat, "seat0") == 0) { + if (!setup_tty(session, disp)) { + goto error_ipc; + } + } else { + session->base.vtnr = 0; + session->tty_fd = -1; + } snprintf(session->base.seat, sizeof(session->base.seat), "%s", seat); session->base.impl = &session_direct; + + wlr_log(L_INFO, "Successfully loaded direct session"); return &session->base; error_ipc: diff --git a/backend/session/logind.c b/backend/session/logind.c index f0ac1e93..3a3cc57d 100644 --- a/backend/session/logind.c +++ b/backend/session/logind.c @@ -109,6 +109,11 @@ static void logind_release_device(struct wlr_session *base, int fd) { static bool logind_change_vt(struct wlr_session *base, unsigned vt) { struct logind_session *session = wl_container_of(base, session, base); + // Only seat0 has VTs associated with it + if (strcmp(session->base.seat, "seat0") != 0) { + return true; + } + int ret; sd_bus_message *msg = NULL; sd_bus_error error = SD_BUS_ERROR_NULL; diff --git a/backend/session/session.c b/backend/session/session.c index 2d5d9776..026040fd 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -19,9 +19,7 @@ extern const struct session_impl session_logind; extern const struct session_impl session_direct; static const struct session_impl *impls[] = { -#ifdef WLR_HAS_SYSTEMD - &session_logind, -#elif defined(WLR_HAS_ELOGIND) +#if defined(WLR_HAS_SYSTEMD) || defined(WLR_HAS_ELOGIND) &session_logind, #endif &session_direct, diff --git a/include/wlr/backend/session.h b/include/wlr/backend/session.h index 4d04b363..1cf41939 100644 --- a/include/wlr/backend/session.h +++ b/include/wlr/backend/session.h @@ -25,8 +25,12 @@ struct wlr_session { struct wl_signal session_signal; bool active; + /* + * 0 if virtual terminals are not supported + * i.e. seat != "seat0" + */ unsigned vtnr; - char seat[8]; + char seat[256]; struct udev *udev; struct udev_monitor *mon; -- cgit v1.2.3 From a6c0e25d363e850eb5693c081022925b2a31a8a2 Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 20 Jun 2018 20:00:23 +0100 Subject: surface: remove wlr_frame_callback This removes the need to allocate a structure for frame callbacks. wl_resource_get_link is used instead. --- include/wlr/types/wlr_surface.h | 5 ----- types/wlr_surface.c | 45 ++++++++++++++--------------------------- 2 files changed, 15 insertions(+), 35 deletions(-) (limited to 'include/wlr') diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index 8517934a..4f4f9ff4 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -8,11 +8,6 @@ #include #include -struct wlr_frame_callback { - struct wl_resource *resource; - struct wl_list link; -}; - #define WLR_SURFACE_INVALID_BUFFER 1 #define WLR_SURFACE_INVALID_SURFACE_DAMAGE 2 #define WLR_SURFACE_INVALID_BUFFER_DAMAGE 4 diff --git a/types/wlr_surface.c b/types/wlr_surface.c index 0f84312e..59a6fc2c 100644 --- a/types/wlr_surface.c +++ b/types/wlr_surface.c @@ -86,40 +86,25 @@ static void surface_damage(struct wl_client *client, x, y, width, height); } -static struct wlr_frame_callback *frame_callback_from_resource( - struct wl_resource *resource) { - assert(wl_resource_instance_of(resource, &wl_callback_interface, NULL)); - return wl_resource_get_user_data(resource); -} - static void callback_handle_resource_destroy(struct wl_resource *resource) { - struct wlr_frame_callback *cb = frame_callback_from_resource(resource); - wl_list_remove(&cb->link); - free(cb); + wl_list_remove(wl_resource_get_link(resource)); } static void surface_frame(struct wl_client *client, struct wl_resource *resource, uint32_t callback) { struct wlr_surface *surface = wlr_surface_from_resource(resource); - struct wlr_frame_callback *cb = - calloc(1, sizeof(struct wlr_frame_callback)); - if (cb == NULL) { - wl_resource_post_no_memory(resource); - return; - } - - cb->resource = wl_resource_create(client, &wl_callback_interface, - CALLBACK_VERSION, callback); - if (cb->resource == NULL) { - free(cb); + struct wl_resource *callback_resource = wl_resource_create(client, + &wl_callback_interface, CALLBACK_VERSION, callback); + if (callback_resource == NULL) { wl_resource_post_no_memory(resource); return; } - wl_resource_set_implementation(cb->resource, NULL, cb, + wl_resource_set_implementation(callback_resource, NULL, NULL, callback_handle_resource_destroy); - wl_list_insert(surface->pending->frame_callback_list.prev, &cb->link); + wl_list_insert(surface->pending->frame_callback_list.prev, + wl_resource_get_link(callback_resource)); surface->pending->invalid |= WLR_SURFACE_INVALID_FRAME_CALLBACK_LIST; } @@ -549,9 +534,9 @@ static struct wlr_surface_state *surface_state_create(void) { static void surface_state_destroy(struct wlr_surface_state *state) { surface_state_reset_buffer(state); - struct wlr_frame_callback *cb, *tmp; - wl_list_for_each_safe(cb, tmp, &state->frame_callback_list, link) { - wl_resource_destroy(cb->resource); + struct wl_resource *resource, *tmp; + wl_resource_for_each_safe(resource, tmp, &state->frame_callback_list) { + wl_resource_destroy(resource); } pixman_region32_fini(&state->surface_damage); @@ -965,11 +950,11 @@ static inline int64_t timespec_to_msec(const struct timespec *a) { void wlr_surface_send_frame_done(struct wlr_surface *surface, const struct timespec *when) { - struct wlr_frame_callback *cb, *cnext; - wl_list_for_each_safe(cb, cnext, &surface->current->frame_callback_list, - link) { - wl_callback_send_done(cb->resource, timespec_to_msec(when)); - wl_resource_destroy(cb->resource); + struct wl_resource *resource, *tmp; + wl_resource_for_each_safe(resource, tmp, + &surface->current->frame_callback_list) { + wl_callback_send_done(resource, timespec_to_msec(when)); + wl_resource_destroy(resource); } } -- cgit v1.2.3 From 831b7297a4e0efde437ec19e2b4d5a929d0d07ff Mon Sep 17 00:00:00 2001 From: emersion Date: Wed, 20 Jun 2018 21:01:35 +0100 Subject: surface: remove matrices These were unused. --- include/wlr/types/wlr_surface.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'include/wlr') diff --git a/include/wlr/types/wlr_surface.h b/include/wlr/types/wlr_surface.h index 8517934a..f1ab8701 100644 --- a/include/wlr/types/wlr_surface.h +++ b/include/wlr/types/wlr_surface.h @@ -79,9 +79,6 @@ struct wlr_surface { struct wlr_surface_state *current, *pending; const char *role; // the lifetime-bound role or null - float buffer_to_surface_matrix[9]; - float surface_to_buffer_matrix[9]; - struct { struct wl_signal commit; struct wl_signal new_subsurface; -- cgit v1.2.3