diff --git a/.builds/alpine.yml b/.builds/alpine.yml index f8d75d8b1..affd85411 100644 --- a/.builds/alpine.yml +++ b/.builds/alpine.yml @@ -35,9 +35,6 @@ tasks: cd wlroots ninja -C build sudo ninja -C build install - - test: | - cd wlroots - meson test -C build --verbose - build-features-disabled: | cd wlroots meson setup build --reconfigure -Dauto_features=disabled diff --git a/.builds/archlinux.yml b/.builds/archlinux.yml index 84e04eda7..fae04ab31 100644 --- a/.builds/archlinux.yml +++ b/.builds/archlinux.yml @@ -37,10 +37,6 @@ tasks: - clang: | cd wlroots/build-clang ninja - - test: | - cd wlroots/build-gcc - meson test --verbose - meson test --benchmark --verbose - smoke-test: | cd wlroots/build-gcc/tinywl sudo modprobe vkms diff --git a/.builds/freebsd.yml b/.builds/freebsd.yml index 3bfe37489..a99e9c911 100644 --- a/.builds/freebsd.yml +++ b/.builds/freebsd.yml @@ -32,9 +32,6 @@ tasks: meson setup build --fatal-meson-warnings -Dauto_features=enabled -Dallocators=gbm ninja -C build sudo ninja -C build install - - test: | - cd wlroots - meson test -C build --verbose - tinywl: | cd wlroots/tinywl make diff --git a/backend/drm/atomic.c b/backend/drm/atomic.c index daa8ba9bf..faa535d44 100644 --- a/backend/drm/atomic.c +++ b/backend/drm/atomic.c @@ -1,4 +1,3 @@ -#include #include #include #include @@ -476,62 +475,6 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_backend *drm, atomic_add(atom, id, props->crtc_h, dst_box->height); } -static void set_color_encoding_and_range(struct atomic *atom, - struct wlr_drm_backend *drm, struct wlr_drm_plane *plane, - enum wlr_color_encoding encoding, enum wlr_color_range range) { - uint32_t id = plane->id; - const struct wlr_drm_plane_props *props = &plane->props; - - uint32_t color_encoding; - switch (encoding) { - case WLR_COLOR_ENCODING_NONE: - case WLR_COLOR_ENCODING_BT601: - color_encoding = WLR_DRM_COLOR_YCBCR_BT601; - break; - case WLR_COLOR_ENCODING_BT709: - color_encoding = WLR_DRM_COLOR_YCBCR_BT709; - break; - case WLR_COLOR_ENCODING_BT2020: - color_encoding = WLR_DRM_COLOR_YCBCR_BT2020; - break; - default: - wlr_log(WLR_DEBUG, "Unsupported color encoding %d", encoding); - atom->failed = true; - return; - } - - if (props->color_encoding) { - atomic_add(atom, id, props->color_encoding, color_encoding); - } else { - wlr_log(WLR_DEBUG, "Plane %"PRIu32" is missing the COLOR_ENCODING property", - id); - atom->failed = true; - return; - } - - uint32_t color_range; - switch (range) { - case WLR_COLOR_RANGE_NONE: - case WLR_COLOR_RANGE_LIMITED: - color_range = WLR_DRM_COLOR_YCBCR_LIMITED_RANGE; - break; - case WLR_COLOR_RANGE_FULL: - color_range = WLR_DRM_COLOR_YCBCR_FULL_RANGE; - break; - default: - assert(0); // Unreachable - } - - if (props->color_range) { - atomic_add(atom, id, props->color_range, color_range); - } else { - wlr_log(WLR_DEBUG, "Plane %"PRIu32" is missing the COLOR_RANGE property", - id); - atom->failed = true; - return; - } -} - static bool supports_cursor_hotspots(const struct wlr_drm_plane *plane) { return plane->props.hotspot_x && plane->props.hotspot_y; } @@ -585,10 +528,6 @@ static void atomic_connector_add(struct atomic *atom, set_plane_props(atom, drm, crtc->primary, state->primary_fb, crtc->id, &state->primary_viewport.dst_box, &state->primary_viewport.src_box); - if (state->base->committed & WLR_OUTPUT_STATE_COLOR_REPRESENTATION) { - set_color_encoding_and_range(atom, drm, crtc->primary, - state->base->color_encoding, state->base->color_range); - } if (crtc->primary->props.fb_damage_clips != 0) { atomic_add(atom, crtc->primary->id, crtc->primary->props.fb_damage_clips, state->fb_damage_clips); diff --git a/backend/drm/backend.c b/backend/drm/backend.c index c2806152b..5a545b192 100644 --- a/backend/drm/backend.c +++ b/backend/drm/backend.c @@ -95,7 +95,7 @@ static const struct wlr_backend_impl backend_impl = { .commit = backend_commit, }; -bool wlr_backend_is_drm(const struct wlr_backend *b) { +bool wlr_backend_is_drm(struct wlr_backend *b) { return b->impl == &backend_impl; } diff --git a/backend/drm/drm.c b/backend/drm/drm.c index d2f75f71f..bd29872fb 100644 --- a/backend/drm/drm.c +++ b/backend/drm/drm.c @@ -43,8 +43,7 @@ static const uint32_t COMMIT_OUTPUT_STATE = WLR_OUTPUT_STATE_WAIT_TIMELINE | WLR_OUTPUT_STATE_SIGNAL_TIMELINE | WLR_OUTPUT_STATE_COLOR_TRANSFORM | - WLR_OUTPUT_STATE_IMAGE_DESCRIPTION | - WLR_OUTPUT_STATE_COLOR_REPRESENTATION; + WLR_OUTPUT_STATE_IMAGE_DESCRIPTION; static const uint32_t SUPPORTED_OUTPUT_STATE = WLR_OUTPUT_STATE_BACKEND_OPTIONAL | COMMIT_OUTPUT_STATE; @@ -1321,7 +1320,7 @@ static const struct wlr_output_impl output_impl = { .get_primary_formats = drm_connector_get_primary_formats, }; -bool wlr_output_is_drm(const struct wlr_output *output) { +bool wlr_output_is_drm(struct wlr_output *output) { return output->impl == &output_impl; } diff --git a/backend/drm/fb.c b/backend/drm/fb.c index da736d20e..575f32d91 100644 --- a/backend/drm/fb.c +++ b/backend/drm/fb.c @@ -144,13 +144,7 @@ static struct wlr_drm_fb *drm_fb_create(struct wlr_drm_backend *drm, struct wlr_buffer *buf, const struct wlr_drm_format_set *formats) { struct wlr_dmabuf_attributes attribs; if (!wlr_buffer_get_dmabuf(buf, &attribs)) { - struct wlr_shm_attributes shm; - if (wlr_buffer_get_shm(buf, &shm)) { - wlr_log(WLR_DEBUG, "Failed to get DMA-BUF from shm buffer"); - } else { - wlr_log(WLR_DEBUG, "Failed to get DMA-BUF from buffer"); - } - + wlr_log(WLR_DEBUG, "Failed to get DMA-BUF from buffer"); return NULL; } diff --git a/backend/drm/properties.c b/backend/drm/properties.c index 4c6bdcb36..314023954 100644 --- a/backend/drm/properties.c +++ b/backend/drm/properties.c @@ -50,8 +50,6 @@ static const struct prop_info crtc_info[] = { static const struct prop_info plane_info[] = { #define INDEX(name) (offsetof(struct wlr_drm_plane_props, name) / sizeof(uint32_t)) - { "COLOR_ENCODING", INDEX(color_encoding) }, - { "COLOR_RANGE", INDEX(color_range) }, { "CRTC_H", INDEX(crtc_h) }, { "CRTC_ID", INDEX(crtc_id) }, { "CRTC_W", INDEX(crtc_w) }, diff --git a/backend/drm/util.c b/backend/drm/util.c index 57e68f33f..1e0307dcb 100644 --- a/backend/drm/util.c +++ b/backend/drm/util.c @@ -135,13 +135,13 @@ static bool is_taken(size_t n, const uint32_t arr[static n], uint32_t key) { */ struct match_state { const size_t num_conns; - const uint32_t *conns; + const uint32_t *restrict conns; const size_t num_crtcs; size_t score; size_t replaced; - uint32_t *res; - uint32_t *best; - const uint32_t *orig; + uint32_t *restrict res; + uint32_t *restrict best; + const uint32_t *restrict orig; bool exit_early; }; @@ -236,9 +236,9 @@ static bool match_connectors_with_crtcs_(struct match_state *st, } void match_connectors_with_crtcs(size_t num_conns, - const uint32_t conns[static num_conns], - size_t num_crtcs, const uint32_t prev_crtcs[static num_crtcs], - uint32_t new_crtcs[static num_crtcs]) { + const uint32_t conns[static restrict num_conns], + size_t num_crtcs, const uint32_t prev_crtcs[static restrict num_crtcs], + uint32_t new_crtcs[static restrict num_crtcs]) { uint32_t solution[num_crtcs]; for (size_t i = 0; i < num_crtcs; ++i) { solution[i] = UNMATCHED; diff --git a/backend/headless/backend.c b/backend/headless/backend.c index 0f21b53f4..d03f520b8 100644 --- a/backend/headless/backend.c +++ b/backend/headless/backend.c @@ -81,6 +81,6 @@ struct wlr_backend *wlr_headless_backend_create(struct wl_event_loop *loop) { return &backend->backend; } -bool wlr_backend_is_headless(const struct wlr_backend *backend) { +bool wlr_backend_is_headless(struct wlr_backend *backend) { return backend->impl == &backend_impl; } diff --git a/backend/headless/output.c b/backend/headless/output.c index 0464e0d1b..a4cdb17c3 100644 --- a/backend/headless/output.c +++ b/backend/headless/output.c @@ -106,7 +106,7 @@ static const struct wlr_output_impl output_impl = { .move_cursor = output_move_cursor, }; -bool wlr_output_is_headless(const struct wlr_output *wlr_output) { +bool wlr_output_is_headless(struct wlr_output *wlr_output) { return wlr_output->impl == &output_impl; } diff --git a/backend/libinput/backend.c b/backend/libinput/backend.c index 909292864..121731b31 100644 --- a/backend/libinput/backend.c +++ b/backend/libinput/backend.c @@ -15,12 +15,6 @@ static struct wlr_libinput_backend *get_libinput_backend_from_backend( return backend; } -struct libinput *wlr_backend_get_libinput(struct wlr_backend *wlr_backend) { - struct wlr_libinput_backend *backend = - get_libinput_backend_from_backend(wlr_backend); - return backend->libinput_context; -} - static int libinput_open_restricted(const char *path, int flags, void *_backend) { struct wlr_libinput_backend *backend = _backend; @@ -93,6 +87,13 @@ static bool backend_start(struct wlr_backend *wlr_backend) { get_libinput_backend_from_backend(wlr_backend); wlr_log(WLR_DEBUG, "Starting libinput backend"); + backend->libinput_context = libinput_udev_create_context(&libinput_impl, + backend, backend->session->udev); + if (!backend->libinput_context) { + wlr_log(WLR_ERROR, "Failed to create libinput context"); + return false; + } + if (libinput_udev_assign_seat(backend->libinput_context, backend->session->seat) != 0) { wlr_log(WLR_ERROR, "Failed to assign libinput seat"); @@ -154,7 +155,7 @@ static const struct wlr_backend_impl backend_impl = { .destroy = backend_destroy, }; -bool wlr_backend_is_libinput(const struct wlr_backend *b) { +bool wlr_backend_is_libinput(struct wlr_backend *b) { return b->impl == &backend_impl; } @@ -186,19 +187,11 @@ struct wlr_backend *wlr_libinput_backend_create(struct wlr_session *session) { wlr_log(WLR_ERROR, "Allocation failed: %s", strerror(errno)); return NULL; } - wlr_backend_init(&backend->backend, &backend_impl); - wl_list_init(&backend->devices); - backend->session = session; - backend->libinput_context = libinput_udev_create_context(&libinput_impl, - backend, backend->session->udev); - if (!backend->libinput_context) { - wlr_log(WLR_ERROR, "Failed to create libinput context"); - wlr_backend_finish(&backend->backend); - free(backend); - return NULL; - } + wl_list_init(&backend->devices); + + backend->session = session; backend->session_signal.notify = session_signal; wl_signal_add(&session->events.active, &backend->session_signal); diff --git a/backend/multi/backend.c b/backend/multi/backend.c index 3a9aca7e6..3d8fb96f5 100644 --- a/backend/multi/backend.c +++ b/backend/multi/backend.c @@ -173,7 +173,7 @@ struct wlr_backend *wlr_multi_backend_create(struct wl_event_loop *loop) { return &backend->backend; } -bool wlr_backend_is_multi(const struct wlr_backend *b) { +bool wlr_backend_is_multi(struct wlr_backend *b) { return b->impl == &backend_impl; } diff --git a/backend/session/session.c b/backend/session/session.c index 1e587f793..868774399 100644 --- a/backend/session/session.c +++ b/backend/session/session.c @@ -395,8 +395,8 @@ bool wlr_session_change_vt(struct wlr_session *session, unsigned vt) { /* Tests if 'path' is KMS compatible by trying to open it. Returns the opened * device on success. */ -struct wlr_device *session_open_if_kms(struct wlr_session *session, - const char *path) { +struct wlr_device *session_open_if_kms(struct wlr_session *restrict session, + const char *restrict path) { if (!path) { return NULL; } diff --git a/backend/wayland/backend.c b/backend/wayland/backend.c index 0d294b543..14a783b67 100644 --- a/backend/wayland/backend.c +++ b/backend/wayland/backend.c @@ -577,7 +577,7 @@ static const struct wlr_backend_impl backend_impl = { .get_drm_fd = backend_get_drm_fd, }; -bool wlr_backend_is_wl(const struct wlr_backend *b) { +bool wlr_backend_is_wl(struct wlr_backend *b) { return b->impl == &backend_impl; } diff --git a/backend/wayland/output.c b/backend/wayland/output.c index c3442f411..fb4d1f914 100644 --- a/backend/wayland/output.c +++ b/backend/wayland/output.c @@ -1027,7 +1027,7 @@ static const struct wlr_output_impl output_impl = { .get_primary_formats = output_get_formats, }; -bool wlr_output_is_wl(const struct wlr_output *wlr_output) { +bool wlr_output_is_wl(struct wlr_output *wlr_output) { return wlr_output->impl == &output_impl; } diff --git a/backend/x11/backend.c b/backend/x11/backend.c index ab56e758e..4dc4bf16d 100644 --- a/backend/x11/backend.c +++ b/backend/x11/backend.c @@ -219,7 +219,7 @@ static const struct wlr_backend_impl backend_impl = { .get_drm_fd = backend_get_drm_fd, }; -bool wlr_backend_is_x11(const struct wlr_backend *backend) { +bool wlr_backend_is_x11(struct wlr_backend *backend) { return backend->impl == &backend_impl; } @@ -575,7 +575,8 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_event_loop *loop, } int fd = xcb_get_file_descriptor(x11->xcb); - x11->event_source = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE, x11_event, x11); + uint32_t events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP; + x11->event_source = wl_event_loop_add_fd(loop, fd, events, x11_event, x11); if (!x11->event_source) { wlr_log(WLR_ERROR, "Could not create event source"); goto error_display; diff --git a/backend/x11/output.c b/backend/x11/output.c index 40e601f0b..51a9c1441 100644 --- a/backend/x11/output.c +++ b/backend/x11/output.c @@ -711,7 +711,7 @@ void handle_x11_configure_notify(struct wlr_x11_output *output, wlr_output_state_finish(&state); } -bool wlr_output_is_x11(const struct wlr_output *wlr_output) { +bool wlr_output_is_x11(struct wlr_output *wlr_output) { return wlr_output->impl == &output_impl; } diff --git a/include/backend/drm/properties.h b/include/backend/drm/properties.h index 20e0a5bff..c02d655ba 100644 --- a/include/backend/drm/properties.h +++ b/include/backend/drm/properties.h @@ -65,22 +65,6 @@ struct wlr_drm_plane_props { uint32_t hotspot_x; uint32_t hotspot_y; uint32_t in_fence_fd; - - uint32_t color_encoding; // Not guaranteed to exist - uint32_t color_range; // Not guaranteed to exist -}; - -// Equivalent to wlr_drm_color_encoding defined in the kernel (but not exported) -enum wlr_drm_color_encoding { - WLR_DRM_COLOR_YCBCR_BT601, - WLR_DRM_COLOR_YCBCR_BT709, - WLR_DRM_COLOR_YCBCR_BT2020, -}; - -// Equivalent to wlr_drm_color_range defined in the kernel (but not exported) -enum wlr_drm_color_range { - WLR_DRM_COLOR_YCBCR_FULL_RANGE, - WLR_DRM_COLOR_YCBCR_LIMITED_RANGE, }; bool get_drm_connector_props(int fd, uint32_t id, diff --git a/include/backend/drm/util.h b/include/backend/drm/util.h index a7d36638d..9ba5f435e 100644 --- a/include/backend/drm/util.h +++ b/include/backend/drm/util.h @@ -34,8 +34,8 @@ void generate_cvt_mode(drmModeModeInfo *mode, int hdisplay, int vdisplay, * new_crtcs is populated with the new connector indices. */ void match_connectors_with_crtcs(size_t num_conns, - const uint32_t conns[static num_conns], - size_t num_crtcs, const uint32_t prev_crtcs[static num_crtcs], - uint32_t new_crtcs[static num_crtcs]); + const uint32_t conns[static restrict num_conns], + size_t num_crtcs, const uint32_t prev_crtcs[static restrict num_crtcs], + uint32_t new_crtcs[static restrict num_crtcs]); #endif diff --git a/include/backend/session/session.h b/include/backend/session/session.h index f3ff9f5bd..0275f69fa 100644 --- a/include/backend/session/session.h +++ b/include/backend/session/session.h @@ -14,7 +14,7 @@ bool libseat_change_vt(struct wlr_session *base, unsigned vt); void session_init(struct wlr_session *session); -struct wlr_device *session_open_if_kms(struct wlr_session *session, - const char *path); +struct wlr_device *session_open_if_kms(struct wlr_session *restrict session, + const char *restrict path); #endif diff --git a/include/render/drm_syncobj_merger.h b/include/render/drm_syncobj_merger.h index 397c5ce80..c55c87314 100644 --- a/include/render/drm_syncobj_merger.h +++ b/include/render/drm_syncobj_merger.h @@ -3,8 +3,6 @@ #include -struct wlr_buffer; - /** * Accumulate timeline points, to have a destination timeline point be * signalled when all inputs are @@ -43,22 +41,4 @@ bool wlr_drm_syncobj_merger_add(struct wlr_drm_syncobj_merger *merger, struct wlr_drm_syncobj_timeline *dst_timeline, uint64_t dst_point, struct wl_event_loop *loop); -/** - * Add a new sync file to wait for. - * - * Ownership of fd is transferred to the merger. - */ -bool wlr_drm_syncobj_merger_add_sync_file(struct wlr_drm_syncobj_merger *merger, - int fd); - -/** - * Add a new DMA-BUF release to wait for. - * - * Waits for write access. - * If the platform does not support DMA-BUF<->sync file interop, the supplied - * event_loop is used to schedule a wait. - */ -bool wlr_drm_syncobj_merger_add_dmabuf(struct wlr_drm_syncobj_merger *merger, - struct wlr_buffer *buffer, struct wl_event_loop *event_loop); - #endif diff --git a/include/render/egl.h b/include/render/egl.h index 208362858..103ab57df 100644 --- a/include/render/egl.h +++ b/include/render/egl.h @@ -16,7 +16,6 @@ struct wlr_egl { bool EXT_image_dma_buf_import_modifiers; bool IMG_context_priority; bool EXT_create_context_robustness; - bool KHR_context_flush_control; // Device extensions bool EXT_device_drm; diff --git a/include/render/gles2.h b/include/render/gles2.h index 226592b5b..6b852dcb7 100644 --- a/include/render/gles2.h +++ b/include/render/gles2.h @@ -119,8 +119,8 @@ struct wlr_gles2_texture { GLenum target; - // If this texture is imported from a buffer, the texture does not own - // these states. They cannot be destroyed along with the texture in this + // If this texture is imported from a buffer, the texture is does not own + // these states. These cannot be destroyed along with the texture in this // case. GLuint tex; GLuint fbo; diff --git a/include/render/vulkan.h b/include/render/vulkan.h index c00b1122b..f96619f2c 100644 --- a/include/render/vulkan.h +++ b/include/render/vulkan.h @@ -56,10 +56,6 @@ struct wlr_vk_device { PFN_vkGetSemaphoreFdKHR vkGetSemaphoreFdKHR; PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR; PFN_vkQueueSubmit2KHR vkQueueSubmit2KHR; - PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR; - PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR; - PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR; - PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR; } api; uint32_t format_prop_count; @@ -67,9 +63,6 @@ struct wlr_vk_device { struct wlr_drm_format_set dmabuf_render_formats; struct wlr_drm_format_set dmabuf_texture_formats; struct wlr_drm_format_set shm_texture_formats; - - float timestamp_period; - uint32_t timestamp_valid_bits; }; // Tries to find the VkPhysicalDevice for the given drm fd. @@ -212,7 +205,6 @@ struct wlr_vk_render_format_setup { bool use_blending_buffer; bool use_srgb; VkRenderPass render_pass; - VkRenderPass render_pass_clear; VkPipeline output_pipe_identity; VkPipeline output_pipe_srgb; @@ -285,6 +277,8 @@ struct wlr_vk_command_buffer { uint64_t timeline_point; // Textures to destroy after the command buffer completes struct wl_list destroy_textures; // wlr_vk_texture.destroy_link + // Staging shared buffers to release after the command buffer completes + struct wl_list stage_buffers; // wlr_vk_shared_buffer.link // Color transform to unref after the command buffer completes struct wlr_color_transform *color_transform; @@ -351,7 +345,7 @@ struct wlr_vk_renderer { struct { struct wlr_vk_command_buffer *cb; uint64_t last_timeline_point; - struct wl_list buffers; // wlr_vk_stage_buffer.link + struct wl_list buffers; // wlr_vk_shared_buffer.link } stage; struct { @@ -412,13 +406,7 @@ VkCommandBuffer vulkan_record_stage_cb(struct wlr_vk_renderer *renderer); // Submits the current stage command buffer and waits until it has // finished execution. -bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer, int wait_sync_file_fd); - -struct wlr_vk_render_timer { - struct wlr_render_timer base; - struct wlr_vk_renderer *renderer; - VkQueryPool query_pool; -}; +bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer); struct wlr_vk_render_pass_texture { struct wlr_vk_texture *texture; @@ -444,28 +432,20 @@ struct wlr_vk_render_pass { struct wlr_drm_syncobj_timeline *signal_timeline; uint64_t signal_point; - struct wlr_vk_render_timer *timer; - struct wl_array textures; // struct wlr_vk_render_pass_texture }; struct wlr_vk_render_pass *vulkan_begin_render_pass(struct wlr_vk_renderer *renderer, struct wlr_vk_render_buffer *buffer, const struct wlr_buffer_pass_options *options); -// Suballocates a buffer span with the given size from the staging ring buffer -// that is mapped for CPU access. vulkan_stage_mark_submit must be called after -// allocations are made to mark the timeline point after which the allocations -// will be released. The start of the span will be a multiple of alignment. +// Suballocates a buffer span with the given size that can be mapped +// and used as staging buffer. The allocation is implicitly released when the +// stage cb has finished execution. The start of the span will be a multiple +// of the given alignment. struct wlr_vk_buffer_span vulkan_get_stage_span( struct wlr_vk_renderer *renderer, VkDeviceSize size, VkDeviceSize alignment); -// Records a watermark on all staging buffers with new allocations with the -// specified timeline point. Once the timeline point is passed, the span will -// be reclaimed by vulkan_stage_buffer_reclaim. -void vulkan_stage_mark_submit(struct wlr_vk_renderer *renderer, - uint64_t timeline_point); - // Tries to allocate a texture descriptor set. Will additionally // return the pool it was allocated from when successful (for freeing it later). struct wlr_vk_descriptor_pool *vulkan_alloc_texture_ds( @@ -492,8 +472,6 @@ uint64_t vulkan_end_command_buffer(struct wlr_vk_command_buffer *cb, void vulkan_reset_command_buffer(struct wlr_vk_command_buffer *cb); bool vulkan_wait_command_buffer(struct wlr_vk_command_buffer *cb, struct wlr_vk_renderer *renderer); -VkSemaphore vulkan_command_buffer_wait_sync_file(struct wlr_vk_renderer *renderer, - struct wlr_vk_command_buffer *render_cb, size_t sem_index, int sync_file_fd); bool vulkan_sync_render_pass_release(struct wlr_vk_renderer *renderer, struct wlr_vk_render_pass *pass); @@ -506,8 +484,7 @@ bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer, VkFormat src_format, VkImage src_image, uint32_t drm_format, 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, - struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point); + uint32_t dst_x, uint32_t dst_y, void *data); // State (e.g. image texture) associated with a surface. struct wlr_vk_texture { @@ -549,43 +526,29 @@ struct wlr_vk_descriptor_pool { struct wl_list link; // wlr_vk_renderer.descriptor_pools }; -struct wlr_vk_stage_watermark { - VkDeviceSize head; - uint64_t timeline_point; +struct wlr_vk_allocation { + VkDeviceSize start; + VkDeviceSize size; }; -// Ring buffer for staging transfers -struct wlr_vk_stage_buffer { - struct wl_list link; // wlr_vk_renderer.stage.buffers +// List of suballocated staging buffers. +// Used to upload to/read from device local images. +struct wlr_vk_shared_buffer { + struct wl_list link; // wlr_vk_renderer.stage.buffers or wlr_vk_command_buffer.stage_buffers VkBuffer buffer; VkDeviceMemory memory; VkDeviceSize buf_size; void *cpu_mapping; - - VkDeviceSize head; - VkDeviceSize tail; - - struct wl_array watermarks; // struct wlr_vk_stage_watermark - int empty_gc_cnt; + struct wl_array allocs; // struct wlr_vk_allocation + int64_t last_used_ms; }; -// Suballocated range on a staging ring buffer. +// Suballocated range on a buffer. struct wlr_vk_buffer_span { - struct wlr_vk_stage_buffer *buffer; - VkDeviceSize offset; - VkDeviceSize size; + struct wlr_vk_shared_buffer *buffer; + struct wlr_vk_allocation alloc; }; -// Suballocate a span of size bytes from a staging ring buffer, with the -// returned offset rounded up to the given alignment. Returns the byte offset -// of the allocation, or (VkDeviceSize)-1 if the buffer is too full to fit it. -VkDeviceSize vulkan_stage_buffer_alloc(struct wlr_vk_stage_buffer *buf, - VkDeviceSize size, VkDeviceSize alignment); - -// Free all allocations covered by watermarks whose timeline point has been -// reached. -void vulkan_stage_buffer_reclaim(struct wlr_vk_stage_buffer *buf, - uint64_t current_point); // Prepared form for a color transform struct wlr_vk_color_transform { diff --git a/include/util/rect_union.h b/include/util/rect_union.h index 297c64d43..2d74f94d5 100644 --- a/include/util/rect_union.h +++ b/include/util/rect_union.h @@ -58,15 +58,13 @@ void rect_union_finish(struct rect_union *r); * * Amortized time: O(1) */ -void rect_union_add(struct rect_union *r, const pixman_box32_t *box); +void rect_union_add(struct rect_union *r, pixman_box32_t box); /** * Compute an exact cover of the rectangles added so far, and return * a pointer to a pixman_region32_t giving that cover. The pointer will - * remain valid until the next time *r is modified. - * - * An internal complexity limit is enforced by rect_union. If exceeded, this - * function will instead return a single-rectangle bounding box. + * remain valid until the next time *r is modified. If there was an allocation + * failure, this function may return a single-rectangle bounding box instead. * * This may be called multiple times and interleaved with rect_union_add(). * diff --git a/include/wlr/backend/drm.h b/include/wlr/backend/drm.h index 233bbcb74..3ca6390ab 100644 --- a/include/wlr/backend/drm.h +++ b/include/wlr/backend/drm.h @@ -39,8 +39,8 @@ struct wlr_drm_lease { struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session, struct wlr_device *dev, struct wlr_backend *parent); -bool wlr_backend_is_drm(const struct wlr_backend *backend); -bool wlr_output_is_drm(const struct wlr_output *output); +bool wlr_backend_is_drm(struct wlr_backend *backend); +bool wlr_output_is_drm(struct wlr_output *output); /** * Get the parent DRM backend, if any. diff --git a/include/wlr/backend/headless.h b/include/wlr/backend/headless.h index 5487c6085..126f1ff21 100644 --- a/include/wlr/backend/headless.h +++ b/include/wlr/backend/headless.h @@ -25,7 +25,7 @@ struct wlr_backend *wlr_headless_backend_create(struct wl_event_loop *loop); struct wlr_output *wlr_headless_add_output(struct wlr_backend *backend, unsigned int width, unsigned int height); -bool wlr_backend_is_headless(const struct wlr_backend *backend); -bool wlr_output_is_headless(const struct wlr_output *output); +bool wlr_backend_is_headless(struct wlr_backend *backend); +bool wlr_output_is_headless(struct wlr_output *output); #endif diff --git a/include/wlr/backend/libinput.h b/include/wlr/backend/libinput.h index 18b8e48f3..2a4e1996e 100644 --- a/include/wlr/backend/libinput.h +++ b/include/wlr/backend/libinput.h @@ -28,12 +28,8 @@ struct libinput_device *wlr_libinput_get_device_handle( */ struct libinput_tablet_tool *wlr_libinput_get_tablet_tool_handle( struct wlr_tablet_tool *wlr_tablet_tool); -/** - * Gets the underlying struct libinput for direct access to the libinput context. - */ -struct libinput *wlr_backend_get_libinput(struct wlr_backend *wlr_backend); -bool wlr_backend_is_libinput(const struct wlr_backend *backend); +bool wlr_backend_is_libinput(struct wlr_backend *backend); bool wlr_input_device_is_libinput(struct wlr_input_device *device); #endif diff --git a/include/wlr/backend/multi.h b/include/wlr/backend/multi.h index cc3e41b4e..c4322d98b 100644 --- a/include/wlr/backend/multi.h +++ b/include/wlr/backend/multi.h @@ -26,7 +26,7 @@ bool wlr_multi_backend_add(struct wlr_backend *multi, void wlr_multi_backend_remove(struct wlr_backend *multi, struct wlr_backend *backend); -bool wlr_backend_is_multi(const struct wlr_backend *backend); +bool wlr_backend_is_multi(struct wlr_backend *backend); bool wlr_multi_is_empty(struct wlr_backend *backend); void wlr_multi_for_each_backend(struct wlr_backend *backend, diff --git a/include/wlr/backend/wayland.h b/include/wlr/backend/wayland.h index 7a41b3d09..c732de68c 100644 --- a/include/wlr/backend/wayland.h +++ b/include/wlr/backend/wayland.h @@ -46,7 +46,7 @@ struct wlr_output *wlr_wl_output_create_from_surface(struct wlr_backend *backend /** * Check whether the provided backend is a Wayland backend. */ -bool wlr_backend_is_wl(const struct wlr_backend *backend); +bool wlr_backend_is_wl(struct wlr_backend *backend); /** * Check whether the provided input device is a Wayland input device. @@ -56,7 +56,7 @@ bool wlr_input_device_is_wl(struct wlr_input_device *device); /** * Check whether the provided output device is a Wayland output device. */ -bool wlr_output_is_wl(const struct wlr_output *output); +bool wlr_output_is_wl(struct wlr_output *output); /** * Sets the title of a struct wlr_output which is a Wayland toplevel. diff --git a/include/wlr/backend/x11.h b/include/wlr/backend/x11.h index 8e8bc9870..1791041ce 100644 --- a/include/wlr/backend/x11.h +++ b/include/wlr/backend/x11.h @@ -31,7 +31,7 @@ struct wlr_output *wlr_x11_output_create(struct wlr_backend *backend); /** * Check whether this backend is an X11 backend. */ -bool wlr_backend_is_x11(const struct wlr_backend *backend); +bool wlr_backend_is_x11(struct wlr_backend *backend); /** * Check whether this input device is an X11 input device. @@ -41,7 +41,7 @@ bool wlr_input_device_is_x11(struct wlr_input_device *device); /** * Check whether this output device is an X11 output device. */ -bool wlr_output_is_x11(const struct wlr_output *output); +bool wlr_output_is_x11(struct wlr_output *output); /** * Sets the title of a struct wlr_output which is an X11 window. diff --git a/include/wlr/config.h.in b/include/wlr/config.h.in index 8c9f7bbde..ef186343e 100644 --- a/include/wlr/config.h.in +++ b/include/wlr/config.h.in @@ -10,7 +10,7 @@ #mesondefine WLR_HAS_DRM_BACKEND /** * Whether the libinput backend is compile-time enabled. Equivalent to the - * pkg-config "have_libinput_backend" variable. + * pkg-config "have_libinput_backend" vartiable. * * Required for . */ diff --git a/include/wlr/render/drm_syncobj.h b/include/wlr/render/drm_syncobj.h index c7dd3b34c..fabe23d1c 100644 --- a/include/wlr/render/drm_syncobj.h +++ b/include/wlr/render/drm_syncobj.h @@ -97,11 +97,7 @@ bool wlr_drm_syncobj_timeline_signal(struct wlr_drm_syncobj_timeline *timeline, /** * Asynchronously wait for a timeline point. * - * Flags can be: - * - * - 0 to wait for the point to be signalled - * - DRM_SYNCOBJ_WAIT_FLAGS_WAIT_AVAILABLE to only wait for a fence to - * materialize + * See wlr_drm_syncobj_timeline_check() for a definition of flags. * * A callback must be provided that will be invoked when the waiter has finished. */ diff --git a/include/wlr/render/gles2.h b/include/wlr/render/gles2.h index 87a57fa54..454e7eb0e 100644 --- a/include/wlr/render/gles2.h +++ b/include/wlr/render/gles2.h @@ -42,9 +42,9 @@ struct wlr_gles2_texture_attribs { bool has_alpha; }; -bool wlr_renderer_is_gles2(const struct wlr_renderer *wlr_renderer); -bool wlr_render_timer_is_gles2(const struct wlr_render_timer *timer); -bool wlr_texture_is_gles2(const struct wlr_texture *texture); +bool wlr_renderer_is_gles2(struct wlr_renderer *wlr_renderer); +bool wlr_render_timer_is_gles2(struct wlr_render_timer *timer); +bool wlr_texture_is_gles2(struct wlr_texture *texture); void wlr_gles2_texture_get_attribs(struct wlr_texture *texture, struct wlr_gles2_texture_attribs *attribs); diff --git a/include/wlr/render/pixman.h b/include/wlr/render/pixman.h index 2951f5e9e..206dd78c6 100644 --- a/include/wlr/render/pixman.h +++ b/include/wlr/render/pixman.h @@ -14,8 +14,8 @@ struct wlr_renderer *wlr_pixman_renderer_create(void); -bool wlr_renderer_is_pixman(const struct wlr_renderer *wlr_renderer); -bool wlr_texture_is_pixman(const struct wlr_texture *texture); +bool wlr_renderer_is_pixman(struct wlr_renderer *wlr_renderer); +bool wlr_texture_is_pixman(struct wlr_texture *texture); pixman_image_t *wlr_pixman_renderer_get_buffer_image( struct wlr_renderer *wlr_renderer, struct wlr_buffer *wlr_buffer); diff --git a/include/wlr/render/vulkan.h b/include/wlr/render/vulkan.h index 170665dd0..50f8c558d 100644 --- a/include/wlr/render/vulkan.h +++ b/include/wlr/render/vulkan.h @@ -25,8 +25,8 @@ VkPhysicalDevice wlr_vk_renderer_get_physical_device(struct wlr_renderer *render VkDevice wlr_vk_renderer_get_device(struct wlr_renderer *renderer); uint32_t wlr_vk_renderer_get_queue_family(struct wlr_renderer *renderer); -bool wlr_renderer_is_vk(const struct wlr_renderer *wlr_renderer); -bool wlr_texture_is_vk(const struct wlr_texture *texture); +bool wlr_renderer_is_vk(struct wlr_renderer *wlr_renderer); +bool wlr_texture_is_vk(struct wlr_texture *texture); void wlr_vk_texture_get_image_attribs(struct wlr_texture *texture, struct wlr_vk_image_attribs *attribs); diff --git a/include/wlr/render/wlr_texture.h b/include/wlr/render/wlr_texture.h index b7dcb143b..1e352c6e6 100644 --- a/include/wlr/render/wlr_texture.h +++ b/include/wlr/render/wlr_texture.h @@ -37,8 +37,6 @@ struct wlr_texture_read_pixels_options { uint32_t dst_x, dst_y; /** Source box of the texture to read from. If empty, the full texture is assumed. */ const struct wlr_box src_box; - struct wlr_drm_syncobj_timeline *wait_timeline; - uint64_t wait_point; }; bool wlr_texture_read_pixels(struct wlr_texture *texture, diff --git a/include/wlr/types/wlr_ext_background_effect_v1.h b/include/wlr/types/wlr_ext_background_effect_v1.h deleted file mode 100644 index 72b0dbc8e..000000000 --- a/include/wlr/types/wlr_ext_background_effect_v1.h +++ /dev/null @@ -1,50 +0,0 @@ -/* - * This an unstable interface of wlroots. No guarantees are made regarding the - * future consistency of this API. - */ -#ifndef WLR_USE_UNSTABLE -#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" -#endif - -#ifndef WLR_TYPES_WLR_EXT_BACKGROUND_EFFECT_V1_H -#define WLR_TYPES_WLR_EXT_BACKGROUND_EFFECT_V1_H - -#include -#include -#include - -struct wlr_surface; - -struct wlr_ext_background_effect_surface_v1_state { - pixman_region32_t blur_region; -}; - -struct wlr_ext_background_effect_manager_v1 { - struct wl_global *global; - uint32_t capabilities; // bitmask of enum ext_background_effect_manager_v1_capability - - struct { - struct wl_signal destroy; - } events; - - void *data; - - struct { - struct wl_list resources; // wl_resource_get_link() - struct wl_listener display_destroy; - } WLR_PRIVATE; -}; - -struct wlr_ext_background_effect_manager_v1 *wlr_ext_background_effect_manager_v1_create( - struct wl_display *display, uint32_t version, uint32_t capabilities); - -/** - * Get the committed background effect state for a surface. - * - * Returns NULL if the client has not attached a background effect object to - * the surface. - */ -const struct wlr_ext_background_effect_surface_v1_state * -wlr_ext_background_effect_v1_get_surface_state(struct wlr_surface *surface); - -#endif diff --git a/include/wlr/types/wlr_ext_image_capture_source_v1.h b/include/wlr/types/wlr_ext_image_capture_source_v1.h index 0a93c49f6..6cbbacf76 100644 --- a/include/wlr/types/wlr_ext_image_capture_source_v1.h +++ b/include/wlr/types/wlr_ext_image_capture_source_v1.h @@ -43,8 +43,6 @@ struct wlr_ext_image_capture_source_v1 { struct wl_signal frame; // struct wlr_ext_image_capture_source_v1_frame_event struct wl_signal destroy; } events; - - void *data; }; /** @@ -93,7 +91,7 @@ struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 { struct { struct wl_signal destroy; - struct wl_signal capture_request; // struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_event + struct wl_signal new_request; // struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request } events; struct { @@ -101,7 +99,7 @@ struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 { } WLR_PRIVATE; }; -struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_event { +struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request { struct wlr_ext_foreign_toplevel_handle_v1 *toplevel_handle; struct wl_client *client; @@ -126,7 +124,7 @@ struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 * wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(struct wl_display *display, uint32_t version); bool wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept( - struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_event *request, + struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request, struct wlr_ext_image_capture_source_v1 *source); struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_create_with_scene_node( diff --git a/include/wlr/types/wlr_linux_drm_syncobj_v1.h b/include/wlr/types/wlr_linux_drm_syncobj_v1.h index dfcbc4d43..7fd55ec2e 100644 --- a/include/wlr/types/wlr_linux_drm_syncobj_v1.h +++ b/include/wlr/types/wlr_linux_drm_syncobj_v1.h @@ -74,21 +74,4 @@ bool wlr_linux_drm_syncobj_v1_state_add_release_point( struct wlr_drm_syncobj_timeline *release_timeline, uint64_t release_point, struct wl_event_loop *event_loop); -/** - * Register the DMA-BUF release of a buffer for buffer usage. - * Non-dmabuf buffers are considered to be immediately available (no wait). - * - * This function may be called multiple times for the same commit. The client's - * release point will be signalled when all registered points are signalled, and - * a new buffer has been committed. - * - * Because the platform may not support DMA-BUF fence merges, a wl_event_loop - * must be supplied to schedule a wait internally, if needed - * - * Waits for write access - */ -bool wlr_linux_drm_syncobj_v1_state_add_release_from_implicit_sync( - struct wlr_linux_drm_syncobj_surface_v1_state *state, - struct wlr_buffer *buffer, struct wl_event_loop *event_loop); - #endif diff --git a/include/wlr/types/wlr_output.h b/include/wlr/types/wlr_output.h index c8e44b0e6..4485b3694 100644 --- a/include/wlr/types/wlr_output.h +++ b/include/wlr/types/wlr_output.h @@ -77,7 +77,6 @@ enum wlr_output_state_field { WLR_OUTPUT_STATE_SIGNAL_TIMELINE = 1 << 11, WLR_OUTPUT_STATE_COLOR_TRANSFORM = 1 << 12, WLR_OUTPUT_STATE_IMAGE_DESCRIPTION = 1 << 13, - WLR_OUTPUT_STATE_COLOR_REPRESENTATION = 1 << 14, }; enum wlr_output_state_mode_type { @@ -143,10 +142,6 @@ struct wlr_output_state { * regular page-flip at the next wlr_output.frame event. */ bool tearing_page_flip; - // Set if (committed & WLR_OUTPUT_STATE_COLOR_REPRESENTATION) - enum wlr_color_encoding color_encoding; - enum wlr_color_range color_range; - enum wlr_output_state_mode_type mode_type; struct wlr_output_mode *mode; struct { @@ -210,8 +205,6 @@ struct wlr_output { enum wl_output_transform transform; enum wlr_output_adaptive_sync_status adaptive_sync_status; uint32_t render_format; - enum wlr_color_encoding color_encoding; - enum wlr_color_range color_range; const struct wlr_output_image_description *image_description; // Indicates whether making changes to adaptive sync status is supported. @@ -632,15 +625,6 @@ void wlr_output_state_set_color_transform(struct wlr_output_state *state, bool wlr_output_state_set_image_description(struct wlr_output_state *state, const struct wlr_output_image_description *image_desc); -/** - * Set the color encoding and range of the primary scanout buffer. - * - * Pass WLR_COLOR_ENCODING_NONE / WLR_COLOR_RANGE_NONE to reset to defaults. - */ -void wlr_output_state_set_color_encoding_and_range( - struct wlr_output_state *state, - enum wlr_color_encoding encoding, enum wlr_color_range range); - /** * Copies the output state from src to dst. It is safe to then * wlr_output_state_finish() src and have dst still be valid. diff --git a/include/wlr/types/wlr_pointer_warp_v1.h b/include/wlr/types/wlr_pointer_warp_v1.h deleted file mode 100644 index 466ca3290..000000000 --- a/include/wlr/types/wlr_pointer_warp_v1.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * This an unstable interface of wlroots. No guarantees are made regarding the - * future consistency of this API. - */ -#ifndef WLR_USE_UNSTABLE -#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features" -#endif - -#ifndef WLR_TYPES_WLR_POINTER_WARP_V1_H -#define WLR_TYPES_WLR_POINTER_WARP_V1_H - -#include - -struct wlr_pointer_warp_v1 { - struct wl_global *global; - - struct { - struct wl_signal destroy; - struct wl_signal warp; // struct wlr_pointer_warp_v1_event_warp - } events; - - void *data; - - struct { - struct wl_listener display_destroy; - } WLR_PRIVATE; -}; - -struct wlr_pointer_warp_v1_event_warp { - struct wlr_surface *surface; - struct wlr_seat_client *seat_client; - double x, y; - uint32_t serial; -}; - -struct wlr_pointer_warp_v1 *wlr_pointer_warp_v1_create(struct wl_display *display, - uint32_t version); -#endif diff --git a/include/wlr/types/wlr_scene.h b/include/wlr/types/wlr_scene.h index f6f97cfea..6c627b1f9 100644 --- a/include/wlr/types/wlr_scene.h +++ b/include/wlr/types/wlr_scene.h @@ -171,6 +171,8 @@ struct wlr_scene_buffer { struct { struct wl_signal outputs_update; // struct wlr_scene_outputs_update_event + struct wl_signal output_enter; // struct wlr_scene_output + struct wl_signal output_leave; // struct wlr_scene_output struct wl_signal output_sample; // struct wlr_scene_output_sample_event struct wl_signal frame_done; // struct wlr_scene_frame_done_event } events; diff --git a/include/wlr/types/wlr_xdg_decoration_v1.h b/include/wlr/types/wlr_xdg_decoration_v1.h index 29b10d72a..78f84eb39 100644 --- a/include/wlr/types/wlr_xdg_decoration_v1.h +++ b/include/wlr/types/wlr_xdg_decoration_v1.h @@ -66,8 +66,7 @@ struct wlr_xdg_toplevel_decoration_v1 { }; struct wlr_xdg_decoration_manager_v1 * - wlr_xdg_decoration_manager_v1_create(struct wl_display *display, - uint32_t version); + wlr_xdg_decoration_manager_v1_create(struct wl_display *display); uint32_t wlr_xdg_toplevel_decoration_v1_set_mode( struct wlr_xdg_toplevel_decoration_v1 *decoration, diff --git a/include/wlr/types/wlr_xdg_foreign_v1.h b/include/wlr/types/wlr_xdg_foreign_v1.h index dd20700cd..975828c2c 100644 --- a/include/wlr/types/wlr_xdg_foreign_v1.h +++ b/include/wlr/types/wlr_xdg_foreign_v1.h @@ -56,6 +56,7 @@ struct wlr_xdg_imported_v1 { }; struct wlr_xdg_imported_child_v1 { + struct wlr_xdg_imported_v1 *imported; struct wlr_xdg_toplevel *toplevel; struct wl_list link; // wlr_xdg_imported_v1.children diff --git a/include/wlr/types/wlr_xdg_foreign_v2.h b/include/wlr/types/wlr_xdg_foreign_v2.h index f2b2a9230..0af0be52e 100644 --- a/include/wlr/types/wlr_xdg_foreign_v2.h +++ b/include/wlr/types/wlr_xdg_foreign_v2.h @@ -56,6 +56,7 @@ struct wlr_xdg_imported_v2 { }; struct wlr_xdg_imported_child_v2 { + struct wlr_xdg_imported_v2 *imported; struct wlr_xdg_toplevel *toplevel; struct wl_list link; // wlr_xdg_imported_v2.children diff --git a/include/wlr/util/box.h b/include/wlr/util/box.h index f6809e0c3..64dcbc5cf 100644 --- a/include/wlr/util/box.h +++ b/include/wlr/util/box.h @@ -107,13 +107,6 @@ void wlr_fbox_transform(struct wlr_fbox *dest, const struct wlr_fbox *box, #ifdef WLR_USE_UNSTABLE -/** - * Checks whether two boxes intersect. - * - * Returns false if either box is empty. - */ -bool wlr_box_intersects(const struct wlr_box *a, const struct wlr_box *b); - /** * Returns true if the two boxes are equal, false otherwise. */ diff --git a/include/xwayland/selection.h b/include/xwayland/selection.h index 2f333f8e0..308310232 100644 --- a/include/xwayland/selection.h +++ b/include/xwayland/selection.h @@ -82,9 +82,9 @@ void xwm_handle_selection_notify(struct wlr_xwm *xwm, xcb_selection_notify_event_t *event); int xwm_handle_xfixes_selection_notify(struct wlr_xwm *xwm, xcb_xfixes_selection_notify_event_t *event); -bool data_source_is_xwayland(const struct wlr_data_source *wlr_source); +bool data_source_is_xwayland(struct wlr_data_source *wlr_source); bool primary_selection_source_is_xwayland( - const struct wlr_primary_selection_source *wlr_source); + struct wlr_primary_selection_source *wlr_source); void xwm_seat_handle_start_drag(struct wlr_xwm *xwm, struct wlr_drag *drag); diff --git a/meson.build b/meson.build index 90200d4e3..b232905d6 100644 --- a/meson.build +++ b/meson.build @@ -1,7 +1,7 @@ project( 'wlroots', 'c', - version: '0.21.0-dev', + version: '0.20.1', license: 'MIT', meson_version: '>=1.3', default_options: [ @@ -116,7 +116,7 @@ xkbcommon = dependency('xkbcommon', ], ) pixman = dependency('pixman-1', - version: '>=0.46.0', + version: '>=0.43.0', fallback: 'pixman', default_options: ['werror=false'], ) @@ -178,10 +178,6 @@ if get_option('examples') subdir('tinywl') endif -if get_option('tests') - subdir('test') -endif - pkgconfig = import('pkgconfig') pkgconfig.generate( lib_wlr, diff --git a/meson.options b/meson.options index d8a8ca940..5863764aa 100644 --- a/meson.options +++ b/meson.options @@ -7,6 +7,5 @@ option('backends', type: 'array', choices: ['auto', 'drm', 'libinput', 'x11'], v option('allocators', type: 'array', choices: ['auto', 'gbm', 'udmabuf'], value: ['auto'], description: 'Select built-in allocators') option('session', type: 'feature', value: 'auto', description: 'Enable session support') -option('tests', type: 'boolean', value: true, description: 'Build tests and benchmarks') option('color-management', type: 'feature', value: 'auto', description: 'Enable support for color management') option('libliftoff', type: 'feature', value: 'auto', description: 'Enable support for libliftoff') diff --git a/protocol/meson.build b/protocol/meson.build index 5830272b3..30aeb68c6 100644 --- a/protocol/meson.build +++ b/protocol/meson.build @@ -30,7 +30,6 @@ protocols = { 'content-type-v1': wl_protocol_dir / 'staging/content-type/content-type-v1.xml', 'cursor-shape-v1': wl_protocol_dir / 'staging/cursor-shape/cursor-shape-v1.xml', 'drm-lease-v1': wl_protocol_dir / 'staging/drm-lease/drm-lease-v1.xml', - 'ext-background-effect-v1': wl_protocol_dir / 'staging/ext-background-effect/ext-background-effect-v1.xml', 'ext-foreign-toplevel-list-v1': wl_protocol_dir / 'staging/ext-foreign-toplevel-list/ext-foreign-toplevel-list-v1.xml', 'ext-idle-notify-v1': wl_protocol_dir / 'staging/ext-idle-notify/ext-idle-notify-v1.xml', 'ext-image-capture-source-v1': wl_protocol_dir / 'staging/ext-image-capture-source/ext-image-capture-source-v1.xml', @@ -40,7 +39,6 @@ protocols = { 'ext-workspace-v1': wl_protocol_dir / 'staging/ext-workspace/ext-workspace-v1.xml', 'fractional-scale-v1': wl_protocol_dir / 'staging/fractional-scale/fractional-scale-v1.xml', 'linux-drm-syncobj-v1': wl_protocol_dir / 'staging/linux-drm-syncobj/linux-drm-syncobj-v1.xml', - 'pointer-warp-v1': wl_protocol_dir / 'staging/pointer-warp/pointer-warp-v1.xml', 'security-context-v1': wl_protocol_dir / 'staging/security-context/security-context-v1.xml', 'single-pixel-buffer-v1': wl_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml', 'xdg-activation-v1': wl_protocol_dir / 'staging/xdg-activation/xdg-activation-v1.xml', diff --git a/protocol/virtual-keyboard-unstable-v1.xml b/protocol/virtual-keyboard-unstable-v1.xml index a888e5f87..5095c91b8 100644 --- a/protocol/virtual-keyboard-unstable-v1.xml +++ b/protocol/virtual-keyboard-unstable-v1.xml @@ -39,15 +39,16 @@ Provide a file descriptor to the compositor which can be memory-mapped to provide a keyboard mapping description. + + Format carries a value from the keymap_format enumeration. - + - diff --git a/render/dmabuf_linux.c b/render/dmabuf_linux.c index b28f22beb..53fb909bc 100644 --- a/render/dmabuf_linux.c +++ b/render/dmabuf_linux.c @@ -56,8 +56,7 @@ bool dmabuf_import_sync_file(int dmabuf_fd, uint32_t flags, int sync_file_fd) { .fd = sync_file_fd, }; if (drmIoctl(dmabuf_fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE, &data) != 0) { - enum wlr_log_importance importance = errno == ENOTTY ? WLR_DEBUG : WLR_ERROR; - wlr_log_errno(importance, "drmIoctl(IMPORT_SYNC_FILE) failed"); + wlr_log_errno(WLR_ERROR, "drmIoctl(IMPORT_SYNC_FILE) failed"); return false; } return true; @@ -69,8 +68,7 @@ int dmabuf_export_sync_file(int dmabuf_fd, uint32_t flags) { .fd = -1, }; if (drmIoctl(dmabuf_fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &data) != 0) { - enum wlr_log_importance importance = errno == ENOTTY ? WLR_DEBUG : WLR_ERROR; - wlr_log_errno(importance, "drmIoctl(EXPORT_SYNC_FILE) failed"); + wlr_log_errno(WLR_ERROR, "drmIoctl(EXPORT_SYNC_FILE) failed"); return -1; } return data.fd; diff --git a/render/drm_syncobj.c b/render/drm_syncobj.c index 15f71c536..2abe2cff6 100644 --- a/render/drm_syncobj.c +++ b/render/drm_syncobj.c @@ -222,8 +222,14 @@ bool wlr_drm_syncobj_timeline_waiter_init(struct wlr_drm_syncobj_timeline_waiter return false; } - if (drmSyncobjEventfd(timeline->drm_fd, timeline->handle, point, ev_fd, flags) != 0) { - wlr_log_errno(WLR_ERROR, "drmSyncobjEventfd() failed"); + struct drm_syncobj_eventfd syncobj_eventfd = { + .handle = timeline->handle, + .flags = flags, + .point = point, + .fd = ev_fd, + }; + if (drmIoctl(timeline->drm_fd, DRM_IOCTL_SYNCOBJ_EVENTFD, &syncobj_eventfd) != 0) { + wlr_log_errno(WLR_ERROR, "DRM_IOCTL_SYNCOBJ_EVENTFD failed"); close(ev_fd); return false; } diff --git a/render/drm_syncobj_merger.c b/render/drm_syncobj_merger.c index 66657b2e1..d50d28c28 100644 --- a/render/drm_syncobj_merger.c +++ b/render/drm_syncobj_merger.c @@ -4,10 +4,8 @@ #include #include #include -#include #include #include -#include "render/dmabuf.h" #include "render/drm_syncobj_merger.h" #include "config.h" @@ -81,7 +79,14 @@ void wlr_drm_syncobj_merger_unref(struct wlr_drm_syncobj_merger *merger) { static bool merger_add_exportable(struct wlr_drm_syncobj_merger *merger, struct wlr_drm_syncobj_timeline *src_timeline, uint64_t src_point) { int new_sync = wlr_drm_syncobj_timeline_export_sync_file(src_timeline, src_point); - return wlr_drm_syncobj_merger_add_sync_file(merger, new_sync); + if (merger->sync_fd != -1) { + int fd2 = new_sync; + new_sync = sync_file_merge(merger->sync_fd, fd2); + close(fd2); + close(merger->sync_fd); + } + merger->sync_fd = new_sync; + return true; } struct export_waiter { @@ -118,7 +123,6 @@ bool wlr_drm_syncobj_merger_add(struct wlr_drm_syncobj_merger *merger, } if (!wlr_drm_syncobj_timeline_waiter_init(&add->waiter, src_timeline, src_point, flags, loop, export_waiter_handle_ready)) { - free(add); return false; } add->merger = merger; @@ -127,71 +131,3 @@ bool wlr_drm_syncobj_merger_add(struct wlr_drm_syncobj_merger *merger, merger->n_ref++; return true; } - -bool wlr_drm_syncobj_merger_add_sync_file(struct wlr_drm_syncobj_merger *merger, - int fd) { - int new_sync = fd; - if (merger->sync_fd != -1) { - new_sync = sync_file_merge(merger->sync_fd, fd); - close(fd); - if (new_sync < 0) { - return false; - } - close(merger->sync_fd); - } - merger->sync_fd = new_sync; - return merger->sync_fd != -1; -} - -struct poll_waiter { - struct wl_event_source *event_source; - struct wlr_drm_syncobj_merger *merger; -}; - -static int poll_waiter_handle_done(int fd, uint32_t mask, void *data) { - struct poll_waiter *waiter = data; - wlr_drm_syncobj_merger_unref(waiter->merger); - wl_event_source_remove(waiter->event_source); - free(waiter); - return 0; -} - -bool wlr_drm_syncobj_merger_add_dmabuf(struct wlr_drm_syncobj_merger *merger, - struct wlr_buffer *buffer, struct wl_event_loop *event_loop) { - struct wlr_dmabuf_attributes dmabuf_attributes; - if (!wlr_buffer_get_dmabuf(buffer, &dmabuf_attributes)) { - return true; - } - - bool res = true; - for (int i = 0; i < dmabuf_attributes.n_planes; ++i) { - int sync_fd = dmabuf_export_sync_file(dmabuf_attributes.fd[i], DMA_BUF_SYNC_WRITE); - if (sync_fd == -1) { - res = false; - break; - } - if (!wlr_drm_syncobj_merger_add_sync_file(merger, sync_fd)) { - return false; - } - } - - if (res) { - return true; - } - - for (int i = 0; i < dmabuf_attributes.n_planes; ++i) { - struct poll_waiter *waiter = calloc(1, sizeof(*waiter)); - if (waiter == NULL) { - return false; - } - waiter->merger = wlr_drm_syncobj_merger_ref(merger); - waiter->event_source = wl_event_loop_add_fd(event_loop, - dmabuf_attributes.fd[i], WL_EVENT_WRITABLE, poll_waiter_handle_done, waiter); - if (waiter->event_source == NULL) { - wlr_drm_syncobj_merger_unref(waiter->merger); - free(waiter); - return false; - } - } - return true; -} diff --git a/render/egl.c b/render/egl.c index 9e02cb6df..8673acabf 100644 --- a/render/egl.c +++ b/render/egl.c @@ -295,8 +295,6 @@ static bool egl_init_display(struct wlr_egl *egl, EGLDisplay display, egl->exts.EXT_create_context_robustness = check_egl_ext(display_exts_str, "EGL_EXT_create_context_robustness"); - egl->exts.KHR_context_flush_control = - check_egl_ext(display_exts_str, "EGL_KHR_context_flush_control"); const char *device_exts_str = NULL, *driver_name = NULL; if (egl->exts.EXT_device_query) { @@ -411,7 +409,7 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform, } size_t atti = 0; - EGLint attribs[32]; + EGLint attribs[7]; attribs[atti++] = EGL_CONTEXT_CLIENT_VERSION; attribs[atti++] = 2; @@ -431,11 +429,6 @@ static bool egl_init(struct wlr_egl *egl, EGLenum platform, attribs[atti++] = EGL_LOSE_CONTEXT_ON_RESET_EXT; } - if (egl->exts.KHR_context_flush_control) { - attribs[atti++] = EGL_CONTEXT_RELEASE_BEHAVIOR_KHR; - attribs[atti++] = EGL_CONTEXT_RELEASE_BEHAVIOR_NONE_KHR; - } - attribs[atti++] = EGL_NONE; assert(atti <= sizeof(attribs)/sizeof(attribs[0])); diff --git a/render/gles2/pass.c b/render/gles2/pass.c index 477f1750d..a70ea1320 100644 --- a/render/gles2/pass.c +++ b/render/gles2/pass.c @@ -201,6 +201,8 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, src_fbox.width /= options->texture->width; src_fbox.height /= options->texture->height; + push_gles2_debug(renderer); + if (options->wait_timeline != NULL) { int sync_file_fd = wlr_drm_syncobj_timeline_export_sync_file(options->wait_timeline, options->wait_point); @@ -221,8 +223,6 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, } } - push_gles2_debug(renderer); - setup_blending(!texture->has_alpha && alpha == 1.0 ? WLR_RENDER_BLEND_MODE_NONE : options->blend_mode); diff --git a/render/gles2/renderer.c b/render/gles2/renderer.c index 7f01b8acd..e362daee8 100644 --- a/render/gles2/renderer.c +++ b/render/gles2/renderer.c @@ -29,7 +29,7 @@ static const struct wlr_renderer_impl renderer_impl; static const struct wlr_render_timer_impl render_timer_impl; -bool wlr_renderer_is_gles2(const struct wlr_renderer *wlr_renderer) { +bool wlr_renderer_is_gles2(struct wlr_renderer *wlr_renderer) { return wlr_renderer->impl == &renderer_impl; } @@ -40,7 +40,7 @@ struct wlr_gles2_renderer *gles2_get_renderer( return renderer; } -bool wlr_render_timer_is_gles2(const struct wlr_render_timer *timer) { +bool wlr_render_timer_is_gles2(struct wlr_render_timer *timer) { return timer->impl == &render_timer_impl; } diff --git a/render/gles2/shaders/quad.frag b/render/gles2/shaders/quad.frag index d48aefdbe..97d3a31c1 100644 --- a/render/gles2/shaders/quad.frag +++ b/render/gles2/shaders/quad.frag @@ -4,6 +4,7 @@ precision highp float; precision mediump float; #endif +varying vec4 v_color; varying vec2 v_texcoord; uniform vec4 color; diff --git a/render/gles2/texture.c b/render/gles2/texture.c index 575a11fca..9a967ebdb 100644 --- a/render/gles2/texture.c +++ b/render/gles2/texture.c @@ -4,10 +4,8 @@ #include #include #include -#include #include #include -#include #include #include #include @@ -18,7 +16,7 @@ static const struct wlr_texture_impl texture_impl; -bool wlr_texture_is_gles2(const struct wlr_texture *wlr_texture) { +bool wlr_texture_is_gles2(struct wlr_texture *wlr_texture) { return wlr_texture->impl == &texture_impl; } @@ -203,27 +201,6 @@ static bool gles2_texture_read_pixels(struct wlr_texture *wlr_texture, return false; } - if (options->wait_timeline != NULL) { - int sync_file_fd = - wlr_drm_syncobj_timeline_export_sync_file(options->wait_timeline, options->wait_point); - if (sync_file_fd < 0) { - return false; - } - - struct wlr_gles2_renderer *renderer = texture->renderer; - EGLSyncKHR sync = wlr_egl_create_sync(renderer->egl, sync_file_fd); - close(sync_file_fd); - if (sync == EGL_NO_SYNC_KHR) { - return false; - } - - bool ok = wlr_egl_wait_sync(renderer->egl, sync); - wlr_egl_destroy_sync(renderer->egl, sync); - if (!ok) { - return false; - } - } - // Make sure any pending drawing is finished before we try to read it glFinish(); diff --git a/render/pixman/meson.build b/render/pixman/meson.build index ea9a396ef..dea96b096 100644 --- a/render/pixman/meson.build +++ b/render/pixman/meson.build @@ -1,3 +1,7 @@ +pixman = dependency('pixman-1', version: '>=0.46.0') + +wlr_deps += pixman + wlr_files += files( 'pass.c', 'pixel_format.c', diff --git a/render/pixman/renderer.c b/render/pixman/renderer.c index 25c558a9d..4631a33ab 100644 --- a/render/pixman/renderer.c +++ b/render/pixman/renderer.c @@ -12,7 +12,7 @@ static const struct wlr_renderer_impl renderer_impl; -bool wlr_renderer_is_pixman(const struct wlr_renderer *wlr_renderer) { +bool wlr_renderer_is_pixman(struct wlr_renderer *wlr_renderer) { return wlr_renderer->impl == &renderer_impl; } @@ -69,7 +69,7 @@ static struct wlr_pixman_buffer *get_buffer( static const struct wlr_texture_impl texture_impl; -bool wlr_texture_is_pixman(const struct wlr_texture *texture) { +bool wlr_texture_is_pixman(struct wlr_texture *texture) { return texture->impl == &texture_impl; } diff --git a/render/vulkan/pass.c b/render/vulkan/pass.c index 38be3320b..503e37c07 100644 --- a/render/vulkan/pass.c +++ b/render/vulkan/pass.c @@ -2,9 +2,7 @@ #include #include #include -#include #include -#include #include #include @@ -40,6 +38,17 @@ static void bind_pipeline(struct wlr_vk_render_pass *pass, VkPipeline pipeline) pass->bound_pipeline = pipeline; } +static void get_clip_region(struct wlr_vk_render_pass *pass, + const pixman_region32_t *in, pixman_region32_t *out) { + if (in != NULL) { + pixman_region32_init(out); + pixman_region32_copy(out, in); + } else { + struct wlr_buffer *buffer = pass->render_buffer->wlr_buffer; + pixman_region32_init_rect(out, 0, 0, buffer->width, buffer->height); + } +} + static void convert_pixman_box_to_vk_rect(const pixman_box32_t *box, VkRect2D *rect) { *rect = (VkRect2D){ .offset = { .x = box->x1, .y = box->y1 }, @@ -90,6 +99,53 @@ static void render_pass_destroy(struct wlr_vk_render_pass *pass) { free(pass); } +static VkSemaphore render_pass_wait_sync_file(struct wlr_vk_render_pass *pass, + size_t sem_index, int sync_file_fd) { + struct wlr_vk_renderer *renderer = pass->renderer; + struct wlr_vk_command_buffer *render_cb = pass->command_buffer; + VkResult res; + + VkSemaphore *wait_semaphores = render_cb->wait_semaphores.data; + size_t wait_semaphores_len = render_cb->wait_semaphores.size / sizeof(wait_semaphores[0]); + + VkSemaphore *sem_ptr; + if (sem_index >= wait_semaphores_len) { + sem_ptr = wl_array_add(&render_cb->wait_semaphores, sizeof(*sem_ptr)); + if (sem_ptr == NULL) { + return VK_NULL_HANDLE; + } + *sem_ptr = VK_NULL_HANDLE; + } else { + sem_ptr = &wait_semaphores[sem_index]; + } + + if (*sem_ptr == VK_NULL_HANDLE) { + VkSemaphoreCreateInfo semaphore_info = { + .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, + }; + res = vkCreateSemaphore(renderer->dev->dev, &semaphore_info, NULL, sem_ptr); + if (res != VK_SUCCESS) { + wlr_vk_error("vkCreateSemaphore", res); + return VK_NULL_HANDLE; + } + } + + VkImportSemaphoreFdInfoKHR import_info = { + .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, + .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, + .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, + .semaphore = *sem_ptr, + .fd = sync_file_fd, + }; + res = renderer->dev->api.vkImportSemaphoreFdKHR(renderer->dev->dev, &import_info); + if (res != VK_SUCCESS) { + wlr_vk_error("vkImportSemaphoreFdKHR", res); + return VK_NULL_HANDLE; + } + + return *sem_ptr; +} + static bool render_pass_wait_render_buffer(struct wlr_vk_render_pass *pass, VkSemaphoreSubmitInfoKHR *render_wait, uint32_t *render_wait_len_ptr) { int sync_file_fds[WLR_DMABUF_MAX_PLANES]; @@ -106,8 +162,7 @@ static bool render_pass_wait_render_buffer(struct wlr_vk_render_pass *pass, continue; } - VkSemaphore sem = vulkan_command_buffer_wait_sync_file(pass->renderer, - pass->command_buffer, *render_wait_len_ptr, sync_file_fds[i]); + VkSemaphore sem = render_pass_wait_sync_file(pass, *render_wait_len_ptr, sync_file_fds[i]); if (sem == VK_NULL_HANDLE) { close(sync_file_fds[i]); continue; @@ -193,13 +248,11 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) { int width = pass->render_buffer->wlr_buffer->width; int height = pass->render_buffer->wlr_buffer->height; - struct wlr_box output_box = { 0, 0, width, height }; - float proj[9], final_matrix[9]; - wlr_matrix_identity(proj); - wlr_matrix_project_box(final_matrix, &output_box, - WL_OUTPUT_TRANSFORM_NORMAL, proj); - wlr_matrix_multiply(final_matrix, pass->projection, final_matrix); - + float final_matrix[9] = { + width, 0, -1, + 0, height, -1, + 0, 0, 0, + }; struct wlr_vk_vert_pcr_data vert_pcr_data = { .uv_off = { 0, 0 }, .uv_size = { 1, 1 }, @@ -278,38 +331,16 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) { int clip_rects_len; const pixman_box32_t *clip_rects = pixman_region32_rectangles( clip, &clip_rects_len); - - if (clip_rects_len > 0) { - const VkDeviceSize instance_size = 4 * sizeof(float); - struct wlr_vk_buffer_span span = vulkan_get_stage_span(renderer, - clip_rects_len * instance_size, 16); - if (!span.buffer) { - pass->failed = true; - goto error; - } - - float *instance_data = (float *)((char *)span.buffer->cpu_mapping + span.offset); - for (int i = 0; i < clip_rects_len; i++) { - const pixman_box32_t *b = &clip_rects[i]; - instance_data[i * 4 + 0] = (float)b->x1 / width; - instance_data[i * 4 + 1] = (float)b->y1 / height; - instance_data[i * 4 + 2] = (float)(b->x2 - b->x1) / width; - instance_data[i * 4 + 3] = (float)(b->y2 - b->y1) / height; - } - - VkDeviceSize vb_offset = span.offset; - vkCmdBindVertexBuffers(render_cb->vk, 0, 1, &span.buffer->buffer, &vb_offset); - vkCmdDraw(render_cb->vk, 4, clip_rects_len, 0, 0); + for (int i = 0; i < clip_rects_len; i++) { + VkRect2D rect; + convert_pixman_box_to_vk_rect(&clip_rects[i], &rect); + vkCmdSetScissor(render_cb->vk, 0, 1, &rect); + vkCmdDraw(render_cb->vk, 4, 1, 0, 0); } } vkCmdEndRenderPass(render_cb->vk); - if (pass->timer != NULL) { - vkCmdWriteTimestamp(render_cb->vk, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, - pass->timer->query_pool, 1); - } - size_t pass_textures_len = pass->textures.size / sizeof(struct wlr_vk_render_pass_texture); size_t render_wait_cap = (1 + pass_textures_len) * WLR_DMABUF_MAX_PLANES; render_wait = calloc(render_wait_cap, sizeof(*render_wait)); @@ -400,8 +431,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) { continue; } - VkSemaphore sem = vulkan_command_buffer_wait_sync_file(renderer, render_cb, - render_wait_len, sync_file_fds[i]); + VkSemaphore sem = render_pass_wait_sync_file(pass, render_wait_len, sync_file_fds[i]); if (sem == VK_NULL_HANDLE) { close(sync_file_fds[i]); continue; @@ -429,32 +459,33 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) { } if (pass->two_pass) { - // On the first frame the clear render pass transitions the blend - // image from undefined and we just mark it transitioned. On every - // frame after, the previous frame left it read-only, so we change - // it back to a color attachment before the render pass starts - if (render_buffer->two_pass.blend_transitioned) { - VkImageMemoryBarrier blend_acq_barrier = { - .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, - .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, - .image = render_buffer->two_pass.blend_image, - .oldLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, - .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - .srcAccessMask = VK_ACCESS_SHADER_READ_BIT, - .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, - .subresourceRange = { - .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, - .layerCount = 1, - .levelCount = 1, - }, - }; - vkCmdPipelineBarrier(stage_cb->vk, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, - VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, - 0, 0, NULL, 0, NULL, 1, &blend_acq_barrier); - } else { + // The render pass changes the blend image layout from + // color attachment to read only, so on each frame, before + // the render pass starts, we change it back + VkImageLayout blend_src_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; + if (!render_buffer->two_pass.blend_transitioned) { + blend_src_layout = VK_IMAGE_LAYOUT_UNDEFINED; render_buffer->two_pass.blend_transitioned = true; } + + VkImageMemoryBarrier blend_acq_barrier = { + .sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER, + .srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED, + .image = render_buffer->two_pass.blend_image, + .oldLayout = blend_src_layout, + .newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, + .srcAccessMask = VK_ACCESS_SHADER_READ_BIT, + .dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, + .subresourceRange = { + .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT, + .layerCount = 1, + .levelCount = 1, + }, + }; + vkCmdPipelineBarrier(stage_cb->vk, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, + VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, + 0, 0, NULL, 0, NULL, 1, &blend_acq_barrier); } // acquire render buffer before rendering @@ -604,7 +635,14 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) { free(render_wait); - vulkan_stage_mark_submit(renderer, render_timeline_point); + struct wlr_vk_shared_buffer *stage_buf, *stage_buf_tmp; + wl_list_for_each_safe(stage_buf, stage_buf_tmp, &renderer->stage.buffers, link) { + if (stage_buf->allocs.size == 0) { + continue; + } + wl_list_remove(&stage_buf->link); + wl_list_insert(&stage_cb->stage_buffers, &stage_buf->link); + } if (!vulkan_sync_render_pass_release(renderer, pass)) { wlr_log(WLR_ERROR, "Failed to sync render buffer"); @@ -629,11 +667,18 @@ error: } static void render_pass_mark_box_updated(struct wlr_vk_render_pass *pass, - const pixman_box32_t *box) { + const struct wlr_box *box) { if (!pass->two_pass) { return; } - rect_union_add(&pass->updated_region, box); + + pixman_box32_t pixman_box = { + .x1 = box->x, + .x2 = box->x + box->width, + .y1 = box->y, + .y2 = box->y + box->height, + }; + rect_union_add(&pass->updated_region, pixman_box); } static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, @@ -653,26 +698,29 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, options->color.a, // no conversion for alpha }; - struct wlr_box box; - wlr_render_rect_options_get_box(options, pass->render_buffer->wlr_buffer, &box); - pixman_region32_t clip; - if (options->clip) { - pixman_region32_init(&clip); - pixman_region32_intersect_rect(&clip, options->clip, - box.x, box.y, box.width, box.height); - } else { - pixman_region32_init_rect(&clip, - box.x, box.y, box.width, box.height); - } + get_clip_region(pass, options->clip, &clip); int clip_rects_len; const pixman_box32_t *clip_rects = pixman_region32_rectangles(&clip, &clip_rects_len); - if (clip_rects_len == 0) { - pixman_region32_fini(&clip); - return; + // Record regions possibly updated for use in second subpass + for (int i = 0; i < clip_rects_len; i++) { + struct wlr_box clip_box = { + .x = clip_rects[i].x1, + .y = clip_rects[i].y1, + .width = clip_rects[i].x2 - clip_rects[i].x1, + .height = clip_rects[i].y2 - clip_rects[i].y1, + }; + struct wlr_box intersection; + if (!wlr_box_intersection(&intersection, &options->box, &clip_box)) { + continue; + } + render_pass_mark_box_updated(pass, &intersection); } + struct wlr_box box; + wlr_render_rect_options_get_box(options, pass->render_buffer->wlr_buffer, &box); + switch (options->blend_mode) { case WLR_RENDER_BLEND_MODE_PREMULTIPLIED:; float proj[9], matrix[9]; @@ -691,23 +739,6 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, break; } - const VkDeviceSize instance_size = 4 * sizeof(float); - struct wlr_vk_buffer_span span = vulkan_get_stage_span(pass->renderer, - clip_rects_len * instance_size, 16); - if (!span.buffer) { - pass->failed = true; - break; - } - float *instance_data = (float *)((char *)span.buffer->cpu_mapping + span.offset); - for (int i = 0; i < clip_rects_len; i++) { - const pixman_box32_t *rect = &clip_rects[i]; - render_pass_mark_box_updated(pass, rect); - instance_data[i * 4 + 0] = (float)(rect->x1 - box.x) / box.width; - instance_data[i * 4 + 1] = (float)(rect->y1 - box.y) / box.height; - instance_data[i * 4 + 2] = (float)(rect->x2 - rect->x1) / box.width; - instance_data[i * 4 + 3] = (float)(rect->y2 - rect->y1) / box.height; - } - struct wlr_vk_vert_pcr_data vert_pcr_data = { .uv_off = { 0, 0 }, .uv_size = { 1, 1 }, @@ -721,9 +752,12 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(vert_pcr_data), sizeof(float) * 4, linear_color); - VkDeviceSize vb_offset = span.offset; - vkCmdBindVertexBuffers(cb, 0, 1, &span.buffer->buffer, &vb_offset); - vkCmdDraw(cb, 4, clip_rects_len, 0, 0); + for (int i = 0; i < clip_rects_len; i++) { + VkRect2D rect; + convert_pixman_box_to_vk_rect(&clip_rects[i], &rect); + vkCmdSetScissor(cb, 0, 1, &rect); + vkCmdDraw(cb, 4, 1, 0, 0); + } break; case WLR_RENDER_BLEND_MODE_NONE:; VkClearAttachment clear_att = { @@ -740,9 +774,7 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass, .layerCount = 1, }; for (int i = 0; i < clip_rects_len; i++) { - const pixman_box32_t *rect = &clip_rects[i]; - render_pass_mark_box_updated(pass, rect); - convert_pixman_box_to_vk_rect(rect, &clear_rect.rect); + convert_pixman_box_to_vk_rect(&clip_rects[i], &clear_rect.rect); vkCmdClearAttachments(cb, 1, &clear_att, 1, &clear_rect); } break; @@ -784,31 +816,6 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, wlr_matrix_project_box(matrix, &dst_box, options->transform, proj); wlr_matrix_multiply(matrix, pass->projection, matrix); - pixman_region32_t clip; - if (options->clip) { - pixman_region32_init(&clip); - pixman_region32_intersect_rect(&clip, options->clip, - dst_box.x, dst_box.y, dst_box.width, dst_box.height); - } else { - pixman_region32_init_rect(&clip, - dst_box.x, dst_box.y, dst_box.width, dst_box.height); - } - int clip_rects_len; - const pixman_box32_t *clip_rects = pixman_region32_rectangles(&clip, &clip_rects_len); - if (clip_rects_len == 0) { - pixman_region32_fini(&clip); - return; - } - - const VkDeviceSize instance_size = 4 * sizeof(float); - struct wlr_vk_buffer_span span = vulkan_get_stage_span(renderer, - clip_rects_len * instance_size, 16); - if (!span.buffer) { - pixman_region32_fini(&clip); - pass->failed = true; - return; - } - struct wlr_vk_vert_pcr_data vert_pcr_data = { .uv_off = { src_box.x / options->texture->width, @@ -879,7 +886,6 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, WLR_RENDER_BLEND_MODE_NONE : options->blend_mode, }); if (!pipe) { - pixman_region32_fini(&clip); pass->failed = true; return; } @@ -887,7 +893,6 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, struct wlr_vk_texture_view *view = vulkan_texture_get_or_create_view(texture, pipe->layout, srgb_image_view); if (!view) { - pixman_region32_fini(&clip); pass->failed = true; return; } @@ -925,35 +930,34 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass, VK_SHADER_STAGE_FRAGMENT_BIT, sizeof(vert_pcr_data), sizeof(frag_pcr_data), &frag_pcr_data); - float *instance_data = (float *)((char *)span.buffer->cpu_mapping + span.offset); + pixman_region32_t clip; + get_clip_region(pass, options->clip, &clip); + + int clip_rects_len; + const pixman_box32_t *clip_rects = pixman_region32_rectangles(&clip, &clip_rects_len); for (int i = 0; i < clip_rects_len; i++) { - const pixman_box32_t *rect = &clip_rects[i]; - render_pass_mark_box_updated(pass, rect); + VkRect2D rect; + convert_pixman_box_to_vk_rect(&clip_rects[i], &rect); + vkCmdSetScissor(cb, 0, 1, &rect); + vkCmdDraw(cb, 4, 1, 0, 0); - struct wlr_fbox norm = { - .x = (double)(rect->x1 - dst_box.x) / dst_box.width, - .y = (double)(rect->y1 - dst_box.y) / dst_box.height, - .width = (double)(rect->x2 - rect->x1) / dst_box.width, - .height = (double)(rect->y2 - rect->y1) / dst_box.height, + struct wlr_box clip_box = { + .x = clip_rects[i].x1, + .y = clip_rects[i].y1, + .width = clip_rects[i].x2 - clip_rects[i].x1, + .height = clip_rects[i].y2 - clip_rects[i].y1, }; - - if (options->transform != WL_OUTPUT_TRANSFORM_NORMAL) { - wlr_fbox_transform(&norm, &norm, options->transform, 1.0, 1.0); + struct wlr_box intersection; + if (!wlr_box_intersection(&intersection, &dst_box, &clip_box)) { + continue; } - - instance_data[i * 4 + 0] = (float)norm.x; - instance_data[i * 4 + 1] = (float)norm.y; - instance_data[i * 4 + 2] = (float)norm.width; - instance_data[i * 4 + 3] = (float)norm.height; + render_pass_mark_box_updated(pass, &intersection); } - pixman_region32_fini(&clip); - - VkDeviceSize vb_offset = span.offset; - vkCmdBindVertexBuffers(cb, 0, 1, &span.buffer->buffer, &vb_offset); - vkCmdDraw(cb, 4, clip_rects_len, 0, 0); texture->last_used_cb = pass->command_buffer; + pixman_region32_fini(&clip); + if (texture->dmabuf_imported || (options != NULL && options->wait_timeline != NULL)) { struct wlr_vk_render_pass_texture *pass_texture = wl_array_add(&pass->textures, sizeof(*pass_texture)); @@ -1035,7 +1039,7 @@ static bool create_3d_lut_image(struct wlr_vk_renderer *renderer, res = vkCreateImage(dev, &img_info, NULL, image); if (res != VK_SUCCESS) { wlr_vk_error("vkCreateImage failed", res); - return false; + return NULL; } VkMemoryRequirements mem_reqs = {0}; @@ -1092,13 +1096,13 @@ static bool create_3d_lut_image(struct wlr_vk_renderer *renderer, size_t size = dim_len * dim_len * dim_len * bytes_per_block; struct wlr_vk_buffer_span span = vulkan_get_stage_span(renderer, size, bytes_per_block); - if (!span.buffer || span.size != size) { + if (!span.buffer || span.alloc.size != size) { wlr_log(WLR_ERROR, "Failed to retrieve staging buffer"); goto fail_imageview; } float sample_range = 1.0f / (dim_len - 1); - char *map = (char *)span.buffer->cpu_mapping + span.offset; + char *map = (char *)span.buffer->cpu_mapping + span.alloc.start; float *dst = (float *)map; for (size_t b_index = 0; b_index < dim_len; b_index++) { for (size_t g_index = 0; g_index < dim_len; g_index++) { @@ -1128,7 +1132,7 @@ static bool create_3d_lut_image(struct wlr_vk_renderer *renderer, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_TRANSFER_WRITE_BIT); VkBufferImageCopy copy = { - .bufferOffset = span.offset, + .bufferOffset = span.alloc.start, .imageExtent.width = dim_len, .imageExtent.height = dim_len, .imageExtent.depth = dim_len, @@ -1298,7 +1302,7 @@ struct wlr_vk_render_pass *vulkan_begin_render_pass(struct wlr_vk_renderer *rend struct wlr_vk_command_buffer *cb = vulkan_acquire_command_buffer(renderer); if (cb == NULL) { - render_pass_destroy(pass); + free(pass); return NULL; } @@ -1309,7 +1313,7 @@ struct wlr_vk_render_pass *vulkan_begin_render_pass(struct wlr_vk_renderer *rend if (res != VK_SUCCESS) { wlr_vk_error("vkBeginCommandBuffer", res); vulkan_reset_command_buffer(cb); - render_pass_destroy(pass); + free(pass); return NULL; } @@ -1321,27 +1325,15 @@ struct wlr_vk_render_pass *vulkan_begin_render_pass(struct wlr_vk_renderer *rend VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_ACCESS_SHADER_READ_BIT); } - struct wlr_vk_render_timer *timer = NULL; - if (options != NULL && options->timer != NULL) { - timer = wl_container_of(options->timer, timer, base); - vkCmdResetQueryPool(cb->vk, timer->query_pool, 0, 2); - vkCmdWriteTimestamp(cb->vk, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, - timer->query_pool, 0); - } - int width = buffer->wlr_buffer->width; int height = buffer->wlr_buffer->height; VkRect2D rect = { .extent = { width, height } }; - bool blend_first_use = pass->two_pass && !buffer->two_pass.blend_transitioned; - VkClearValue clear_value = {0}; VkRenderPassBeginInfo rp_info = { .sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO, .renderArea = rect, - .clearValueCount = blend_first_use ? 1 : 0, - .pClearValues = blend_first_use ? &clear_value : NULL, - .renderPass = blend_first_use ? - render_setup->render_pass_clear : render_setup->render_pass, + .clearValueCount = 0, + .renderPass = render_setup->render_pass, .framebuffer = buffer_out->framebuffer, }; vkCmdBeginRenderPass(cb->vk, &rp_info, VK_SUBPASS_CONTENTS_INLINE); @@ -1351,7 +1343,6 @@ struct wlr_vk_render_pass *vulkan_begin_render_pass(struct wlr_vk_renderer *rend .height = height, .maxDepth = 1, }); - vkCmdSetScissor(cb->vk, 0, 1, &rect); // matrix_projection() assumes a GL coordinate system so we need // to pass WL_OUTPUT_TRANSFORM_FLIPPED_180 to adjust it for vulkan. @@ -1362,6 +1353,5 @@ struct wlr_vk_render_pass *vulkan_begin_render_pass(struct wlr_vk_renderer *rend pass->render_buffer_out = buffer_out; pass->render_setup = render_setup; pass->command_buffer = cb; - pass->timer = timer; return pass; } diff --git a/render/vulkan/renderer.c b/render/vulkan/renderer.c index 44f4d39d8..da17a4703 100644 --- a/render/vulkan/renderer.c +++ b/render/vulkan/renderer.c @@ -1,5 +1,6 @@ #include #include +#include #include #include #include @@ -7,7 +8,6 @@ #include #include #include -#include #include #include #include @@ -26,9 +26,11 @@ #include "render/vulkan/shaders/texture.frag.h" #include "render/vulkan/shaders/quad.frag.h" #include "render/vulkan/shaders/output.frag.h" -#include "util/array.h" +#include "types/wlr_buffer.h" +#include "util/time.h" // TODO: +// - simplify stage allocation, don't track allocations but use ringbuffer-like // - use a pipeline cache (not sure when to save though, after every pipeline // creation?) // - create pipelines as derivatives of each other @@ -44,7 +46,7 @@ static bool default_debug = true; static const struct wlr_renderer_impl renderer_impl; -bool wlr_renderer_is_vk(const struct wlr_renderer *wlr_renderer) { +bool wlr_renderer_is_vk(struct wlr_renderer *wlr_renderer) { return wlr_renderer->impl == &renderer_impl; } @@ -169,7 +171,6 @@ static void destroy_render_format_setup(struct wlr_vk_renderer *renderer, VkDevice dev = renderer->dev->dev; vkDestroyRenderPass(dev, setup->render_pass, NULL); - vkDestroyRenderPass(dev, setup->render_pass_clear, NULL); vkDestroyPipeline(dev, setup->output_pipe_identity, NULL); vkDestroyPipeline(dev, setup->output_pipe_srgb, NULL); vkDestroyPipeline(dev, setup->output_pipe_pq, NULL); @@ -186,13 +187,18 @@ static void destroy_render_format_setup(struct wlr_vk_renderer *renderer, free(setup); } -static void stage_buffer_destroy(struct wlr_vk_renderer *r, - struct wlr_vk_stage_buffer *buffer) { +static void shared_buffer_destroy(struct wlr_vk_renderer *r, + struct wlr_vk_shared_buffer *buffer) { if (!buffer) { return; } - wl_array_release(&buffer->watermarks); + if (buffer->allocs.size > 0) { + wlr_log(WLR_ERROR, "shared_buffer_finish: %zu allocations left", + buffer->allocs.size / sizeof(struct wlr_vk_allocation)); + } + + wl_array_release(&buffer->allocs); if (buffer->cpu_mapping) { vkUnmapMemory(r->dev->dev, buffer->memory); buffer->cpu_mapping = NULL; @@ -208,12 +214,75 @@ static void stage_buffer_destroy(struct wlr_vk_renderer *r, free(buffer); } -static struct wlr_vk_stage_buffer *stage_buffer_create( - struct wlr_vk_renderer *r, VkDeviceSize bsize) { - struct wlr_vk_stage_buffer *buf = calloc(1, sizeof(*buf)); +struct wlr_vk_buffer_span vulkan_get_stage_span(struct wlr_vk_renderer *r, + VkDeviceSize size, VkDeviceSize alignment) { + // try to find free span + // simple greedy allocation algorithm - should be enough for this usecase + // since all allocations are freed together after the frame + struct wlr_vk_shared_buffer *buf; + wl_list_for_each_reverse(buf, &r->stage.buffers, link) { + VkDeviceSize start = 0u; + if (buf->allocs.size > 0) { + const struct wlr_vk_allocation *allocs = buf->allocs.data; + size_t allocs_len = buf->allocs.size / sizeof(struct wlr_vk_allocation); + const struct wlr_vk_allocation *last = &allocs[allocs_len - 1]; + start = last->start + last->size; + } + + assert(start <= buf->buf_size); + + // ensure the proposed start is a multiple of alignment + start += alignment - 1 - ((start + alignment - 1) % alignment); + + if (buf->buf_size - start < size) { + continue; + } + + struct wlr_vk_allocation *a = wl_array_add(&buf->allocs, sizeof(*a)); + if (a == NULL) { + wlr_log_errno(WLR_ERROR, "Allocation failed"); + goto error_alloc; + } + + *a = (struct wlr_vk_allocation){ + .start = start, + .size = size, + }; + return (struct wlr_vk_buffer_span) { + .buffer = buf, + .alloc = *a, + }; + } + + if (size > max_stage_size) { + wlr_log(WLR_ERROR, "cannot vulkan stage buffer: " + "requested size (%zu bytes) exceeds maximum (%zu bytes)", + (size_t)size, (size_t)max_stage_size); + goto error_alloc; + } + + // we didn't find a free buffer - create one + // size = clamp(max(size * 2, prev_size * 2), min_size, max_size) + VkDeviceSize bsize = size * 2; + bsize = bsize < min_stage_size ? min_stage_size : bsize; + if (!wl_list_empty(&r->stage.buffers)) { + struct wl_list *last_link = r->stage.buffers.prev; + struct wlr_vk_shared_buffer *prev = wl_container_of( + last_link, prev, link); + VkDeviceSize last_size = 2 * prev->buf_size; + bsize = bsize < last_size ? last_size : bsize; + } + + if (bsize > max_stage_size) { + wlr_log(WLR_INFO, "vulkan stage buffers have reached max size"); + bsize = max_stage_size; + } + + // create buffer + buf = calloc(1, sizeof(*buf)); if (!buf) { wlr_log_errno(WLR_ERROR, "Allocation failed"); - return NULL; + goto error_alloc; } wl_list_init(&buf->link); @@ -223,8 +292,7 @@ static struct wlr_vk_stage_buffer *stage_buffer_create( .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, .size = bsize, .usage = VK_BUFFER_USAGE_TRANSFER_DST_BIT | - VK_BUFFER_USAGE_TRANSFER_SRC_BIT | - VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, + VK_BUFFER_USAGE_TRANSFER_SRC_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, }; res = vkCreateBuffer(r->dev->dev, &buf_info, NULL, &buf->buffer); @@ -251,7 +319,7 @@ static struct wlr_vk_stage_buffer *stage_buffer_create( }; res = vkAllocateMemory(r->dev->dev, &mem_info, NULL, &buf->memory); if (res != VK_SUCCESS) { - wlr_vk_error("vkAllocateMemory", res); + wlr_vk_error("vkAllocatorMemory", res); goto error; } @@ -267,162 +335,34 @@ static struct wlr_vk_stage_buffer *stage_buffer_create( goto error; } + struct wlr_vk_allocation *a = wl_array_add(&buf->allocs, sizeof(*a)); + if (a == NULL) { + wlr_log_errno(WLR_ERROR, "Allocation failed"); + goto error; + } + buf->buf_size = bsize; - return buf; + wl_list_insert(&r->stage.buffers, &buf->link); -error: - stage_buffer_destroy(r, buf); - return NULL; -} - -void vulkan_stage_buffer_reclaim(struct wlr_vk_stage_buffer *buf, - uint64_t current_point) { - - size_t completed = 0; - struct wlr_vk_stage_watermark *mark; - wl_array_for_each(mark, &buf->watermarks) { - if (mark->timeline_point > current_point) { - break; - } - buf->tail = mark->head; - completed++; - } - - if (completed > 0) { - completed *= sizeof(struct wlr_vk_stage_watermark); - if (completed == buf->watermarks.size) { - buf->watermarks.size = 0; - } else { - array_remove_at(&buf->watermarks, 0, completed); - } - } -} - -VkDeviceSize vulkan_stage_buffer_alloc(struct wlr_vk_stage_buffer *buf, - VkDeviceSize size, VkDeviceSize alignment) { - VkDeviceSize head = buf->head; - - // Round up to the next multiple of alignment - VkDeviceSize rem = head % alignment; - if (rem != 0) { - head += alignment - rem; - } - - VkDeviceSize end = head >= buf->tail ? buf->buf_size : buf->tail; - if (head + size < end) { - // Regular allocation head till end of available space - buf->head = head + size; - return head; - } else if (size < buf->tail && head >= buf->tail) { - // First allocation after wrap-around - buf->head = size; - return 0; - } - - return (VkDeviceSize)-1; -} - -struct wlr_vk_buffer_span vulkan_get_stage_span(struct wlr_vk_renderer *r, - VkDeviceSize size, VkDeviceSize alignment) { - if (size >= max_stage_size) { - wlr_log(WLR_ERROR, "cannot allocate stage buffer: " - "requested size (%zu bytes) exceeds maximum (%zu bytes)", - (size_t)size, (size_t)max_stage_size-1); - goto error; - } - - VkDeviceSize max_buf_size = min_stage_size / 2; - struct wlr_vk_stage_buffer *buf; - wl_list_for_each(buf, &r->stage.buffers, link) { - VkDeviceSize offset = vulkan_stage_buffer_alloc(buf, size, alignment); - if (offset != (VkDeviceSize)-1) { - return (struct wlr_vk_buffer_span) { - .buffer = buf, - .offset = offset, - .size = size, - }; - } - if (buf->buf_size > max_buf_size) { - max_buf_size = buf->buf_size; - } - } - - VkDeviceSize bsize = max_buf_size * 2; - while (size * 2 > bsize) { - bsize *= 2; - } - if (bsize > max_stage_size) { - wlr_log(WLR_INFO, "vulkan stage buffer has reached max size"); - bsize = max_stage_size; - } - - struct wlr_vk_stage_buffer *new_buf = stage_buffer_create(r, bsize); - if (new_buf == NULL) { - goto error; - } - - wl_list_insert(r->stage.buffers.prev, &new_buf->link); - - VkDeviceSize offset = vulkan_stage_buffer_alloc(new_buf, size, alignment); - assert(offset != (VkDeviceSize)-1); - - return (struct wlr_vk_buffer_span) { - .buffer = new_buf, - .offset = offset, + *a = (struct wlr_vk_allocation){ + .start = 0, .size = size, }; + return (struct wlr_vk_buffer_span) { + .buffer = buf, + .alloc = *a, + }; error: + shared_buffer_destroy(r, buf); + +error_alloc: return (struct wlr_vk_buffer_span) { .buffer = NULL, - .offset = 0, - .size = 0, + .alloc = (struct wlr_vk_allocation) {0, 0}, }; } -void vulkan_stage_mark_submit(struct wlr_vk_renderer *renderer, - uint64_t timeline_point) { - struct wlr_vk_stage_buffer *buf; - wl_list_for_each(buf, &renderer->stage.buffers, link) { - if (buf->head == buf->tail) { - continue; - } - - struct wlr_vk_stage_watermark *mark = wl_array_add( - &buf->watermarks, sizeof(*mark)); - if (mark == NULL) { - wlr_log_errno(WLR_ERROR, "Allocation failed"); - continue; - } - - *mark = (struct wlr_vk_stage_watermark){ - .head = buf->head, - .timeline_point = timeline_point, - }; - } -} - -static void stage_buffer_gc(struct wlr_vk_renderer *renderer, uint64_t current_point) { - struct wlr_vk_stage_buffer *buf, *buf_tmp; - wl_list_for_each_safe(buf, buf_tmp, &renderer->stage.buffers, link) { - if (buf->head != buf->tail) { - buf->empty_gc_cnt = 0; - vulkan_stage_buffer_reclaim(buf, current_point); - continue; - } - if (buf->buf_size <= min_stage_size) { - // We will not deallocate the first buffer - continue; - } - - buf->empty_gc_cnt++; - if (buf->empty_gc_cnt >= 1000) { - // This buffer hasn't been used for a while, so let's deallocate it - stage_buffer_destroy(renderer, buf); - } - } -} - VkCommandBuffer vulkan_record_stage_cb(struct wlr_vk_renderer *renderer) { if (renderer->stage.cb == NULL) { renderer->stage.cb = vulkan_acquire_command_buffer(renderer); @@ -439,52 +379,7 @@ VkCommandBuffer vulkan_record_stage_cb(struct wlr_vk_renderer *renderer) { return renderer->stage.cb->vk; } -VkSemaphore vulkan_command_buffer_wait_sync_file(struct wlr_vk_renderer *renderer, - struct wlr_vk_command_buffer *render_cb, size_t sem_index, int sync_file_fd) { - VkResult res; - - VkSemaphore *wait_semaphores = render_cb->wait_semaphores.data; - size_t wait_semaphores_len = render_cb->wait_semaphores.size / sizeof(wait_semaphores[0]); - - VkSemaphore *sem_ptr; - if (sem_index >= wait_semaphores_len) { - sem_ptr = wl_array_add(&render_cb->wait_semaphores, sizeof(*sem_ptr)); - if (sem_ptr == NULL) { - return VK_NULL_HANDLE; - } - *sem_ptr = VK_NULL_HANDLE; - } else { - sem_ptr = &wait_semaphores[sem_index]; - } - - if (*sem_ptr == VK_NULL_HANDLE) { - VkSemaphoreCreateInfo semaphore_info = { - .sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO, - }; - res = vkCreateSemaphore(renderer->dev->dev, &semaphore_info, NULL, sem_ptr); - if (res != VK_SUCCESS) { - wlr_vk_error("vkCreateSemaphore", res); - return VK_NULL_HANDLE; - } - } - - VkImportSemaphoreFdInfoKHR import_info = { - .sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR, - .handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT, - .flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT, - .semaphore = *sem_ptr, - .fd = sync_file_fd, - }; - res = renderer->dev->api.vkImportSemaphoreFdKHR(renderer->dev->dev, &import_info); - if (res != VK_SUCCESS) { - wlr_vk_error("vkImportSemaphoreFdKHR", res); - return VK_NULL_HANDLE; - } - - return *sem_ptr; -} - -bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer, int wait_sync_file_fd) { +bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer) { if (renderer->stage.cb == NULL) { return false; } @@ -497,8 +392,6 @@ bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer, int wait_sync_fi return false; } - VkSemaphore wait_semaphore; - VkPipelineStageFlags wait_stage = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT; VkTimelineSemaphoreSubmitInfoKHR timeline_submit_info = { .sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR, .signalSemaphoreValueCount = 1, @@ -512,32 +405,16 @@ bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer, int wait_sync_fi .signalSemaphoreCount = 1, .pSignalSemaphores = &renderer->timeline_semaphore, }; - - if (wait_sync_file_fd != -1) { - wait_semaphore = vulkan_command_buffer_wait_sync_file(renderer, cb, 0, wait_sync_file_fd); - if (wait_semaphore == VK_NULL_HANDLE) { - return false; - } - submit_info.waitSemaphoreCount = 1; - submit_info.pWaitSemaphores = &wait_semaphore; - submit_info.pWaitDstStageMask = &wait_stage; - } - - vulkan_stage_mark_submit(renderer, timeline_point); - VkResult res = vkQueueSubmit(renderer->dev->queue, 1, &submit_info, VK_NULL_HANDLE); if (res != VK_SUCCESS) { wlr_vk_error("vkQueueSubmit", res); return false; } - if (!vulkan_wait_command_buffer(cb, renderer)) { - return false; - } + // NOTE: don't release stage allocations here since they may still be + // used for reading. Will be done next frame. - // We did a blocking wait so this is now the current point - stage_buffer_gc(renderer, timeline_point); - return true; + return vulkan_wait_command_buffer(cb, renderer); } struct wlr_vk_format_props *vulkan_format_props_from_drm( @@ -571,6 +448,7 @@ static bool init_command_buffer(struct wlr_vk_command_buffer *cb, .vk = vk_cb, }; wl_list_init(&cb->destroy_textures); + wl_list_init(&cb->stage_buffers); return true; } @@ -596,7 +474,7 @@ bool vulkan_wait_command_buffer(struct wlr_vk_command_buffer *cb, } static void release_command_buffer_resources(struct wlr_vk_command_buffer *cb, - struct wlr_vk_renderer *renderer) { + struct wlr_vk_renderer *renderer, int64_t now) { struct wlr_vk_texture *texture, *texture_tmp; wl_list_for_each_safe(texture, texture_tmp, &cb->destroy_textures, destroy_link) { wl_list_remove(&texture->destroy_link); @@ -604,6 +482,15 @@ static void release_command_buffer_resources(struct wlr_vk_command_buffer *cb, wlr_texture_destroy(&texture->wlr_texture); } + struct wlr_vk_shared_buffer *buf, *buf_tmp; + wl_list_for_each_safe(buf, buf_tmp, &cb->stage_buffers, link) { + buf->allocs.size = 0; + buf->last_used_ms = now; + + wl_list_remove(&buf->link); + wl_list_insert(&renderer->stage.buffers, &buf->link); + } + if (cb->color_transform) { wlr_color_transform_unref(cb->color_transform); cb->color_transform = NULL; @@ -622,14 +509,22 @@ static struct wlr_vk_command_buffer *get_command_buffer( return NULL; } - stage_buffer_gc(renderer, current_point); + + // Garbage collect any buffers that have remained unused for too long + int64_t now = get_current_time_msec(); + struct wlr_vk_shared_buffer *buf, *buf_tmp; + wl_list_for_each_safe(buf, buf_tmp, &renderer->stage.buffers, link) { + if (buf->allocs.size == 0 && buf->last_used_ms + 10000 < now) { + shared_buffer_destroy(renderer, buf); + } + } // Destroy textures for completed command buffers for (size_t i = 0; i < VULKAN_COMMAND_BUFFERS_CAP; i++) { struct wlr_vk_command_buffer *cb = &renderer->command_buffers[i]; if (cb->vk != VK_NULL_HANDLE && !cb->recording && cb->timeline_point <= current_point) { - release_command_buffer_resources(cb, renderer); + release_command_buffer_resources(cb, renderer, now); } } @@ -1232,7 +1127,7 @@ static void vulkan_destroy(struct wlr_renderer *wlr_renderer) { if (cb->vk == VK_NULL_HANDLE) { continue; } - release_command_buffer_resources(cb, renderer); + release_command_buffer_resources(cb, renderer, 0); if (cb->binary_semaphore != VK_NULL_HANDLE) { vkDestroySemaphore(renderer->dev->dev, cb->binary_semaphore, NULL); } @@ -1244,9 +1139,9 @@ static void vulkan_destroy(struct wlr_renderer *wlr_renderer) { } // stage.cb automatically freed with command pool - struct wlr_vk_stage_buffer *buf, *tmp_buf; + struct wlr_vk_shared_buffer *buf, *tmp_buf; wl_list_for_each_safe(buf, tmp_buf, &renderer->stage.buffers, link) { - stage_buffer_destroy(renderer, buf); + shared_buffer_destroy(renderer, buf); } struct wlr_vk_texture *tex, *tex_tmp; @@ -1293,7 +1188,7 @@ static void vulkan_destroy(struct wlr_renderer *wlr_renderer) { vkDestroyPipelineLayout(dev->dev, pipeline_layout->vk, NULL); vkDestroyDescriptorSetLayout(dev->dev, pipeline_layout->ds, NULL); vkDestroySampler(dev->dev, pipeline_layout->sampler, NULL); - renderer->dev->api.vkDestroySamplerYcbcrConversionKHR(dev->dev, pipeline_layout->ycbcr.conversion, NULL); + vkDestroySamplerYcbcrConversion(dev->dev, pipeline_layout->ycbcr.conversion, NULL); free(pipeline_layout); } @@ -1323,8 +1218,7 @@ bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer, VkFormat src_format, VkImage src_image, uint32_t drm_format, 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, - struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point) { + uint32_t dst_x, uint32_t dst_y, void *data) { VkDevice dev = vk_renderer->dev->dev; const struct wlr_pixel_format_info *pixel_format_info = drm_get_pixel_format_info(drm_format); @@ -1510,17 +1404,7 @@ bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_ACCESS_MEMORY_READ_BIT); - int wait_sync_file_fd = -1; - if (wait_timeline != NULL) { - wait_sync_file_fd = wlr_drm_syncobj_timeline_export_sync_file(wait_timeline, wait_point); - if (wait_sync_file_fd < 0) { - wlr_log(WLR_ERROR, "Failed to export wait timeline point as sync_file"); - return false; - } - } - - if (!vulkan_submit_stage_wait(vk_renderer, wait_sync_file_fd)) { - close(wait_sync_file_fd); + if (!vulkan_submit_stage_wait(vk_renderer)) { return false; } @@ -1601,80 +1485,6 @@ static struct wlr_render_pass *vulkan_begin_buffer_pass(struct wlr_renderer *wlr return &render_pass->base; } -static const struct wlr_render_timer_impl render_timer_impl; - -static struct wlr_render_timer *vulkan_render_timer_create( - struct wlr_renderer *wlr_renderer) { - struct wlr_vk_renderer *renderer = vulkan_get_renderer(wlr_renderer); - if (renderer->dev->timestamp_valid_bits == 0) { - wlr_log(WLR_ERROR, "Failed to create render timer: " - "timestamp queries not supported by queue family"); - return NULL; - } - - struct wlr_vk_render_timer *timer = calloc(1, sizeof(*timer)); - if (!timer) { - wlr_log_errno(WLR_ERROR, "Allocation failed"); - return NULL; - } - - VkQueryPoolCreateInfo pool_info = { - .sType = VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO, - .queryType = VK_QUERY_TYPE_TIMESTAMP, - .queryCount = 2, - }; - VkResult res = vkCreateQueryPool(renderer->dev->dev, &pool_info, - NULL, &timer->query_pool); - if (res != VK_SUCCESS) { - wlr_vk_error("vkCreateQueryPool", res); - free(timer); - return NULL; - } - - timer->base.impl = &render_timer_impl; - timer->renderer = renderer; - return &timer->base; -} - -static int vulkan_render_timer_get_duration_ns( - struct wlr_render_timer *wlr_timer) { - struct wlr_vk_render_timer *timer = - wl_container_of(wlr_timer, timer, base); - struct wlr_vk_renderer *renderer = timer->renderer; - - // Layout: [ timestamp1, avail1, timestamp2, avail2 ] - uint64_t data[4] = {0}; - VkResult res = vkGetQueryPoolResults(renderer->dev->dev, - timer->query_pool, 0, 2, sizeof(data), data, - 2 * sizeof(uint64_t), - VK_QUERY_RESULT_64_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT); - if (res == VK_NOT_READY || data[1] == 0 || data[3] == 0) { - wlr_log(WLR_ERROR, "Failed to get render duration: " - "timestamp query results not yet ready"); - return -1; - } - if (res != VK_SUCCESS) { - wlr_vk_error("vkGetQueryPoolResults", res); - return -1; - } - - uint64_t ticks = data[2] - data[0]; - return (int)(ticks * renderer->dev->timestamp_period); -} - -static void vulkan_render_timer_destroy( - struct wlr_render_timer *wlr_timer) { - struct wlr_vk_render_timer *timer = - wl_container_of(wlr_timer, timer, base); - vkDestroyQueryPool(timer->renderer->dev->dev, timer->query_pool, NULL); - free(timer); -} - -static const struct wlr_render_timer_impl render_timer_impl = { - .get_duration_ns = vulkan_render_timer_get_duration_ns, - .destroy = vulkan_render_timer_destroy, -}; - static const struct wlr_renderer_impl renderer_impl = { .get_texture_formats = vulkan_get_texture_formats, .get_render_formats = vulkan_get_render_formats, @@ -1682,7 +1492,6 @@ static const struct wlr_renderer_impl renderer_impl = { .get_drm_fd = vulkan_get_drm_fd, .texture_from_buffer = vulkan_texture_from_buffer, .begin_buffer_pass = vulkan_begin_buffer_pass, - .render_timer_create = vulkan_render_timer_create, }; // Initializes the VkDescriptorSetLayout and VkPipelineLayout needed @@ -1883,25 +1692,6 @@ static bool pipeline_key_equals(const struct wlr_vk_pipeline_key *a, return true; } -static const VkVertexInputBindingDescription instance_vert_binding = { - .binding = 0, - .stride = sizeof(float) * 4, - .inputRate = VK_VERTEX_INPUT_RATE_INSTANCE, -}; -static const VkVertexInputAttributeDescription instance_vert_attr = { - .location = 0, - .binding = 0, - .format = VK_FORMAT_R32G32B32A32_SFLOAT, - .offset = 0, -}; -static const VkPipelineVertexInputStateCreateInfo instance_vert_input = { - .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, - .vertexBindingDescriptionCount = 1, - .pVertexBindingDescriptions = &instance_vert_binding, - .vertexAttributeDescriptionCount = 1, - .pVertexAttributeDescriptions = &instance_vert_attr, -}; - // Initializes the pipeline for rendering textures and using the given // VkRenderPass and VkPipelineLayout. struct wlr_vk_pipeline *setup_get_or_create_pipeline( @@ -2033,6 +1823,10 @@ struct wlr_vk_pipeline *setup_get_or_create_pipeline( .dynamicStateCount = sizeof(dyn_states) / sizeof(dyn_states[0]), }; + VkPipelineVertexInputStateCreateInfo vertex = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + }; + VkGraphicsPipelineCreateInfo pinfo = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .layout = pipeline_layout->vk, @@ -2047,7 +1841,7 @@ struct wlr_vk_pipeline *setup_get_or_create_pipeline( .pMultisampleState = &multisample, .pViewportState = &viewport, .pDynamicState = &dynamic, - .pVertexInputState = &instance_vert_input, + .pVertexInputState = &vertex, }; VkPipelineCache cache = VK_NULL_HANDLE; @@ -2146,6 +1940,10 @@ static bool init_blend_to_output_pipeline(struct wlr_vk_renderer *renderer, .dynamicStateCount = sizeof(dyn_states) / sizeof(dyn_states[0]), }; + VkPipelineVertexInputStateCreateInfo vertex = { + .sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO, + }; + VkGraphicsPipelineCreateInfo pinfo = { .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, .pNext = NULL, @@ -2160,7 +1958,7 @@ static bool init_blend_to_output_pipeline(struct wlr_vk_renderer *renderer, .pMultisampleState = &multisample, .pViewportState = &viewport, .pDynamicState = &dynamic, - .pVertexInputState = &instance_vert_input, + .pVertexInputState = &vertex, }; VkPipelineCache cache = VK_NULL_HANDLE; @@ -2251,10 +2049,10 @@ struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout( .yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT, .chromaFilter = VK_FILTER_LINEAR, }; - res = renderer->dev->api.vkCreateSamplerYcbcrConversionKHR(renderer->dev->dev, + res = vkCreateSamplerYcbcrConversion(renderer->dev->dev, &conversion_create_info, NULL, &pipeline_layout->ycbcr.conversion); if (res != VK_SUCCESS) { - wlr_vk_error("vkCreateSamplerYcbcrConversionKHR", res); + wlr_vk_error("vkCreateSamplerYcbcrConversion", res); free(pipeline_layout); return NULL; } @@ -2586,14 +2384,6 @@ static struct wlr_vk_render_format_setup *find_or_create_render_setup( goto error; } - attachments[0].loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - attachments[0].initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - res = vkCreateRenderPass(dev, &rp_info, NULL, &setup->render_pass_clear); - if (res != VK_SUCCESS) { - wlr_vk_error("Failed to create 2-step clear render pass", res); - goto error; - } - // this is only well defined if render pass has a 2nd subpass if (!init_blend_to_output_pipeline( renderer, setup->render_pass, renderer->output_pipe_layout, diff --git a/render/vulkan/shaders/common.vert b/render/vulkan/shaders/common.vert index 82ea9658c..f1579790d 100644 --- a/render/vulkan/shaders/common.vert +++ b/render/vulkan/shaders/common.vert @@ -8,14 +8,11 @@ layout(push_constant, row_major) uniform UBO { vec2 uv_size; } data; -layout(location = 0) in vec4 inst_rect; - layout(location = 0) out vec2 uv; void main() { vec2 pos = vec2(float((gl_VertexIndex + 1) & 2) * 0.5f, float(gl_VertexIndex & 2) * 0.5f); - pos = inst_rect.xy + pos * inst_rect.zw; uv = data.uv_offset + pos * data.uv_size; gl_Position = data.proj * vec4(pos, 0.0, 1.0); } diff --git a/render/vulkan/texture.c b/render/vulkan/texture.c index deff70f11..57db97a56 100644 --- a/render/vulkan/texture.c +++ b/render/vulkan/texture.c @@ -15,7 +15,7 @@ static const struct wlr_texture_impl texture_impl; -bool wlr_texture_is_vk(const struct wlr_texture *wlr_texture) { +bool wlr_texture_is_vk(struct wlr_texture *wlr_texture) { return wlr_texture->impl == &texture_impl; } @@ -72,16 +72,16 @@ static bool write_pixels(struct wlr_vk_texture *texture, // get staging buffer struct wlr_vk_buffer_span span = vulkan_get_stage_span(renderer, bsize, format_info->bytes_per_block); - if (!span.buffer || span.size != bsize) { + if (!span.buffer || span.alloc.size != bsize) { wlr_log(WLR_ERROR, "Failed to retrieve staging buffer"); free(copies); return false; } - char *map = (char*)span.buffer->cpu_mapping + span.offset; + char *map = (char*)span.buffer->cpu_mapping + span.alloc.start; // upload data - uint32_t buf_off = span.offset; + uint32_t buf_off = span.alloc.start; for (int i = 0; i < rects_len; i++) { pixman_box32_t rect = rects[i]; uint32_t width = rect.x2 - rect.x1; @@ -238,8 +238,7 @@ static bool vulkan_texture_read_pixels(struct wlr_texture *wlr_texture, void *p = wlr_texture_read_pixel_options_get_data(options); return vulkan_read_pixels(texture->renderer, texture->format->vk, texture->image, - options->format, options->stride, src.width, src.height, src.x, src.y, 0, 0, p, - options->wait_timeline, options->wait_point); + options->format, options->stride, src.width, src.height, src.x, src.y, 0, 0, p); } static uint32_t vulkan_texture_preferred_read_format(struct wlr_texture *wlr_texture) { @@ -330,7 +329,6 @@ struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(struct wlr_vk_text view->ds_pool = vulkan_alloc_texture_ds(texture->renderer, pipeline_layout->ds, &view->ds); if (!view->ds_pool) { - vkDestroyImageView(dev, view->image_view, NULL); free(view); wlr_log(WLR_ERROR, "failed to allocate descriptor"); return NULL; @@ -655,7 +653,7 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer, .sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2, }; - renderer->dev->api.vkGetImageMemoryRequirements2KHR(dev, &memri, &memr); + vkGetImageMemoryRequirements2(dev, &memri, &memr); int mem = vulkan_find_mem_type(renderer->dev, 0, memr.memoryRequirements.memoryTypeBits & fdp.memoryTypeBits); if (mem < 0) { @@ -714,7 +712,7 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer, } } - res = renderer->dev->api.vkBindImageMemory2KHR(dev, mem_count, bindi); + res = vkBindImageMemory2(dev, mem_count, bindi); if (res != VK_SUCCESS) { wlr_vk_error("vkBindMemory failed", res); goto error_image; diff --git a/render/vulkan/vulkan.c b/render/vulkan/vulkan.c index 520a678b1..0c0445d80 100644 --- a/render/vulkan/vulkan.c +++ b/render/vulkan/vulkan.c @@ -10,7 +10,6 @@ #include #include #include -#include #include #include #include @@ -82,6 +81,21 @@ static VKAPI_ATTR VkBool32 debug_callback(VkDebugUtilsMessageSeverityFlagBitsEXT } struct wlr_vk_instance *vulkan_instance_create(bool debug) { + // we require vulkan 1.1 + PFN_vkEnumerateInstanceVersion pfEnumInstanceVersion = + (PFN_vkEnumerateInstanceVersion) + vkGetInstanceProcAddr(VK_NULL_HANDLE, "vkEnumerateInstanceVersion"); + if (!pfEnumInstanceVersion) { + wlr_log(WLR_ERROR, "wlroots requires vulkan 1.1 which is not available"); + return NULL; + } + + uint32_t ini_version; + if (pfEnumInstanceVersion(&ini_version) != VK_SUCCESS || + ini_version < VK_API_VERSION_1_1) { + wlr_log(WLR_ERROR, "wlroots requires vulkan 1.1 which is not available"); + return NULL; + } uint32_t avail_extc = 0; VkResult res; @@ -111,18 +125,7 @@ struct wlr_vk_instance *vulkan_instance_create(bool debug) { } size_t extensions_len = 0; - const char *extensions[8] = {0}; - extensions[extensions_len++] = VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME; - extensions[extensions_len++] = VK_KHR_EXTERNAL_SEMAPHORE_CAPABILITIES_EXTENSION_NAME; - extensions[extensions_len++] = VK_KHR_EXTERNAL_MEMORY_CAPABILITIES_EXTENSION_NAME; - - for (size_t i = 0; i < extensions_len; i++) { - if (!check_extension(avail_ext_props, avail_extc, extensions[i])) { - wlr_log(WLR_ERROR, "vulkan: required instance extension %s not found", - extensions[i]); - goto error; - } - } + const char *extensions[1] = {0}; bool debug_utils_found = false; if (debug && check_extension(avail_ext_props, avail_extc, @@ -137,7 +140,7 @@ struct wlr_vk_instance *vulkan_instance_create(bool debug) { .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO, .pEngineName = "wlroots", .engineVersion = WLR_VERSION_NUM, - .apiVersion = VK_API_VERSION_1_0, + .apiVersion = VK_API_VERSION_1_1, }; VkInstanceCreateInfo instance_info = { @@ -253,14 +256,6 @@ static void log_phdev(const VkPhysicalDeviceProperties *props) { wlr_log(WLR_INFO, " Driver version: %u.%u.%u", dv_major, dv_minor, dv_patch); } -struct wlr_vk_phdev_info { - VkPhysicalDeviceType type; - char name[VK_MAX_PHYSICAL_DEVICE_NAME_SIZE]; - - bool has_drm, has_render; - dev_t primary_devid, render_devid; -}; - VkPhysicalDevice vulkan_find_drm_phdev(struct wlr_vk_instance *ini, int drm_fd) { VkResult res; uint32_t num_phdevs; @@ -278,14 +273,29 @@ VkPhysicalDevice vulkan_find_drm_phdev(struct wlr_vk_instance *ini, int drm_fd) return VK_NULL_HANDLE; } - struct wlr_vk_phdev_info devices[1 + num_phdevs]; + struct stat drm_stat = {0}; + if (drm_fd >= 0 && fstat(drm_fd, &drm_stat) != 0) { + wlr_log_errno(WLR_ERROR, "fstat failed"); + return VK_NULL_HANDLE; + } + for (uint32_t i = 0; i < num_phdevs; ++i) { VkPhysicalDevice phdev = phdevs[i]; + // check whether device supports vulkan 1.1, needed for + // vkGetPhysicalDeviceProperties2 VkPhysicalDeviceProperties phdev_props; vkGetPhysicalDeviceProperties(phdev, &phdev_props); + log_phdev(&phdev_props); + if (phdev_props.apiVersion < VK_API_VERSION_1_1) { + // NOTE: we could additionally check whether the + // VkPhysicalDeviceProperties2KHR extension is supported but + // implementations not supporting 1.1 are unlikely in future + continue; + } + // check for extensions uint32_t avail_extc = 0; res = vkEnumerateDeviceExtensionProperties(phdev, NULL, @@ -334,81 +344,25 @@ VkPhysicalDevice vulkan_find_drm_phdev(struct wlr_vk_instance *ini, int drm_fd) wlr_log(WLR_INFO, " Driver name: %s (%s)", driver_props.driverName, driver_props.driverInfo); } - struct wlr_vk_phdev_info info = { - .type = phdev_props.deviceType, - .has_drm = has_drm_props, - }; - memcpy(info.name, phdev_props.deviceName, sizeof(phdev_props.deviceName)); - if (has_drm_props) { - info.has_render = drm_props.hasRender; - info.primary_devid = makedev(drm_props.primaryMajor, drm_props.primaryMinor); - info.render_devid = makedev(drm_props.renderMajor, drm_props.renderMinor); - } - devices[i] = info; - } - - // Find a Vulkan device matching the DRM device's dev_t - struct stat drm_stat = {0}; - if (drm_fd >= 0 && fstat(drm_fd, &drm_stat) != 0) { - wlr_log_errno(WLR_ERROR, "fstat failed"); - return VK_NULL_HANDLE; - } - - for (size_t i = 0; i < num_phdevs; ++i) { - VkPhysicalDevice phdev = phdevs[i]; - const struct wlr_vk_phdev_info *info = &devices[i]; - bool found; if (drm_fd >= 0) { - if (!info->has_drm) { + if (!has_drm_props) { wlr_log(WLR_DEBUG, " Ignoring physical device \"%s\": " - "VK_EXT_physical_device_drm not supported", info->name); + "VK_EXT_physical_device_drm not supported", + phdev_props.deviceName); continue; } - found = info->primary_devid == drm_stat.st_rdev || info->render_devid == drm_stat.st_rdev; + dev_t primary_devid = makedev(drm_props.primaryMajor, drm_props.primaryMinor); + dev_t render_devid = makedev(drm_props.renderMajor, drm_props.renderMinor); + found = primary_devid == drm_stat.st_rdev || render_devid == drm_stat.st_rdev; } else { - found = info->type == VK_PHYSICAL_DEVICE_TYPE_CPU; + found = phdev_props.deviceType == VK_PHYSICAL_DEVICE_TYPE_CPU; } if (found) { - wlr_log(WLR_INFO, "Found matching Vulkan physical device: %s", info->name); - return phdev; - } - } - - // If the DRM device we're interested in uses the platform bus, is - // KMS-capable, and has no render node associated, search for a sibling - // render-capable platform bus device. The platform bus is a good enough - // hint that these two devices should be compatible. - drmDevice *drm_dev = NULL; - if (drmGetDevice2(drm_fd, 0, &drm_dev) != 0) { - wlr_log(WLR_ERROR, "drmGetDevice2() failed"); - return VK_NULL_HANDLE; - } - bool is_platform_lone_kms = drm_dev->bustype == DRM_BUS_PLATFORM && - !(drm_dev->available_nodes & (1 << DRM_NODE_RENDER)) && drmIsKMS(drm_fd); - drmFreeDevice(&drm_dev); - if (!is_platform_lone_kms) { - return VK_NULL_HANDLE; - } - - for (size_t i = 0; i < num_phdevs; ++i) { - VkPhysicalDevice phdev = phdevs[i]; - const struct wlr_vk_phdev_info *info = &devices[i]; - - if (!info->has_render) { - continue; - } - - drmDevice *drm_dev = NULL; - if (drmGetDeviceFromDevId(info->render_devid, 0, &drm_dev) != 0) { - wlr_log(WLR_ERROR, "drmGetDeviceFromDevId() failed"); - return VK_NULL_HANDLE; - } - - if (drm_dev->bustype == DRM_BUS_PLATFORM) { - wlr_log(WLR_INFO, "Found Vulkan physical device on platform bus: %s", info->name); + wlr_log(WLR_INFO, "Found matching Vulkan physical device: %s", + phdev_props.deviceName); return phdev; } } @@ -520,12 +474,6 @@ struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini, extensions[extensions_len++] = VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME; extensions[extensions_len++] = VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME; // or vulkan 1.2 extensions[extensions_len++] = VK_KHR_SYNCHRONIZATION_2_EXTENSION_NAME; // or vulkan 1.3 - extensions[extensions_len++] = VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME; // or vulkan 1.1 - extensions[extensions_len++] = VK_KHR_BIND_MEMORY_2_EXTENSION_NAME; // or vulkan 1.1 - extensions[extensions_len++] = VK_KHR_SAMPLER_YCBCR_CONVERSION_EXTENSION_NAME; // or vulkan 1.1 - extensions[extensions_len++] = VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME; // or vulkan 1.1 - extensions[extensions_len++] = VK_KHR_MAINTENANCE_1_EXTENSION_NAME; // or vulkan 1.1 - extensions[extensions_len++] = VK_KHR_GET_MEMORY_REQUIREMENTS_2_EXTENSION_NAME; // or vulkan 1.1 for (size_t i = 0; i < extensions_len; i++) { if (!check_extension(avail_ext_props, avail_extc, extensions[i])) { @@ -548,15 +496,10 @@ struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini, graphics_found = queue_props[i].queueFlags & VK_QUEUE_GRAPHICS_BIT; if (graphics_found) { dev->queue_family = i; - dev->timestamp_valid_bits = queue_props[i].timestampValidBits; break; } } assert(graphics_found); - - VkPhysicalDeviceProperties phdev_props; - vkGetPhysicalDeviceProperties(phdev, &phdev_props); - dev->timestamp_period = phdev_props.limits.timestampPeriod; } bool exportable_semaphore = false, importable_semaphore = false; @@ -687,10 +630,6 @@ struct wlr_vk_device *vulkan_device_create(struct wlr_vk_instance *ini, load_device_proc(dev, "vkGetSemaphoreCounterValueKHR", &dev->api.vkGetSemaphoreCounterValueKHR); load_device_proc(dev, "vkQueueSubmit2KHR", &dev->api.vkQueueSubmit2KHR); - load_device_proc(dev, "vkBindImageMemory2KHR", &dev->api.vkBindImageMemory2KHR); - load_device_proc(dev, "vkCreateSamplerYcbcrConversionKHR", &dev->api.vkCreateSamplerYcbcrConversionKHR); - load_device_proc(dev, "vkDestroySamplerYcbcrConversionKHR", &dev->api.vkDestroySamplerYcbcrConversionKHR); - load_device_proc(dev, "vkGetImageMemoryRequirements2KHR", &dev->api.vkGetImageMemoryRequirements2KHR); if (has_external_semaphore_fd) { load_device_proc(dev, "vkGetSemaphoreFdKHR", &dev->api.vkGetSemaphoreFdKHR); diff --git a/test/bench_scene.c b/test/bench_scene.c deleted file mode 100644 index 6d6b270f0..000000000 --- a/test/bench_scene.c +++ /dev/null @@ -1,154 +0,0 @@ -#include -#include -#include - -struct tree_spec { - // Parameters for the tree we'll construct - int depth; - int branching; - int rect_size; - int spread; - - // Stats around the tree we built - int tree_count; - int rect_count; - int max_x; - int max_y; -}; - -static int max(int a, int b) { - return a > b ? a : b; -} - -static double timespec_diff_msec(struct timespec *start, struct timespec *end) { - return (double)(end->tv_sec - start->tv_sec) * 1e3 + - (double)(end->tv_nsec - start->tv_nsec) / 1e6; -} - -static bool build_tree(struct wlr_scene_tree *parent, struct tree_spec *spec, - int depth, int x, int y) { - - if (depth == spec->depth) { - float color[4] = { 1.0f, 1.0f, 1.0f, 1.0f }; - struct wlr_scene_rect *rect = - wlr_scene_rect_create(parent, spec->rect_size, spec->rect_size, color); - if (rect == NULL) { - fprintf(stderr, "wlr_scene_rect_create failed\n"); - return false; - } - wlr_scene_node_set_position(&rect->node, x, y); - spec->max_x = max(spec->max_x, x + spec->rect_size); - spec->max_y = max(spec->max_y, y + spec->rect_size); - spec->rect_count++; - return true; - } - - for (int i = 0; i < spec->branching; i++) { - struct wlr_scene_tree *child = wlr_scene_tree_create(parent); - if (child == NULL) { - fprintf(stderr, "wlr_scene_tree_create failed\n"); - return false; - } - spec->tree_count++; - int offset = i * spec->spread; - wlr_scene_node_set_position(&child->node, offset, offset); - if (!build_tree(child, spec, depth + 1, x + offset, y + offset)) { - return false; - } - } - return true; -} - -static bool bench_create_tree(struct wlr_scene *scene, struct tree_spec *spec) { - struct timespec start, end; - clock_gettime(CLOCK_MONOTONIC, &start); - if (!build_tree(&scene->tree, spec, 0, 0, 0)) { - fprintf(stderr, "build_tree failed\n"); - return false; - } - clock_gettime(CLOCK_MONOTONIC, &end); - - printf("Built tree with %d tree nodes, %d rect nodes\n\n", - spec->tree_count, spec->rect_count); - - double elapsed = timespec_diff_msec(&start, &end); - int nodes = spec->tree_count + spec->rect_count; - printf("create test tree: %d nodes, %.3f ms, %.0f nodes/ms\n", - nodes, elapsed, nodes / elapsed); - return true; -} - -static void bench_scene_node_at(struct wlr_scene *scene, struct tree_spec *spec) { - struct timespec start, end; - int iters = 10000; - int hits = 0; - - clock_gettime(CLOCK_MONOTONIC, &start); - for (int i = 0; i < iters; i++) { - // Spread lookups across the tree extent - double lx = (double)(i * 97 % spec->max_x); - double ly = (double)(i * 53 % spec->max_y); - double nx, ny; - struct wlr_scene_node *node = - wlr_scene_node_at(&scene->tree.node, lx, ly, &nx, &ny); - if (node != NULL) { - hits++; - } - } - clock_gettime(CLOCK_MONOTONIC, &end); - - double elapsed = timespec_diff_msec(&start, &end); - int nodes = (spec->tree_count + spec->rect_count) * iters; - printf("wlr_scene_node_at: %d iters, %.3f ms, %.0f nodes/ms (hits: %d/%d)\n", - iters, elapsed, nodes / elapsed, hits, iters); -} - -static void noop_iterator(struct wlr_scene_buffer *buffer, - int sx, int sy, void *user_data) { - (void)buffer; - (void)sx; - (void)sy; - int *cnt = user_data; - (*cnt)++; -} - -static void bench_scene_node_for_each_buffer(struct wlr_scene *scene, struct tree_spec *spec) { - struct timespec start, end; - int iters = 10000; - int hits = 0; - - clock_gettime(CLOCK_MONOTONIC, &start); - for (int i = 0; i < iters; i++) { - wlr_scene_node_for_each_buffer(&scene->tree.node, - noop_iterator, &hits); - } - clock_gettime(CLOCK_MONOTONIC, &end); - - double elapsed = timespec_diff_msec(&start, &end); - int nodes = (spec->tree_count + spec->rect_count) * iters; - printf("wlr_scene_node_for_each_buffer: %d iters, %.3f ms, %.0f nodes/ms (hits: %d/%d)\n", - iters, elapsed, nodes / elapsed, hits, iters); -} - -int main(void) { - struct wlr_scene *scene = wlr_scene_create(); - if (scene == NULL) { - fprintf(stderr, "wlr_scene_create failed\n"); - return 99; - } - - struct tree_spec spec = { - .depth = 5, - .branching = 5, - .rect_size = 10, - .spread = 100, - }; - if (!bench_create_tree(scene, &spec)) { - return 99; - } - bench_scene_node_at(scene, &spec); - bench_scene_node_for_each_buffer(scene, &spec); - - wlr_scene_node_destroy(&scene->tree.node); - return 0; -} diff --git a/test/meson.build b/test/meson.build deleted file mode 100644 index 9c622e3ef..000000000 --- a/test/meson.build +++ /dev/null @@ -1,32 +0,0 @@ -# Used to test internal symbols -lib_wlr_internal = static_library( - versioned_name + '-internal', - objects: lib_wlr.extract_all_objects(recursive: false), - dependencies: wlr_deps, - include_directories: [wlr_inc], - install: false, -) - -test( - 'box', - executable('test-box', 'test_box.c', dependencies: wlroots), -) - -if features.get('vulkan-renderer') - test( - 'vulkan_stage_buffer', - executable( - 'test-vulkan-stage-buffer', - 'test_vulkan_stage_buffer.c', - link_with: lib_wlr_internal, - dependencies: wlr_deps, - include_directories: wlr_inc, - ), - ) -endif - -benchmark( - 'scene', - executable('bench-scene', 'bench_scene.c', dependencies: wlroots), - timeout: 30, -) diff --git a/test/test_box.c b/test/test_box.c deleted file mode 100644 index fcd95a8e2..000000000 --- a/test/test_box.c +++ /dev/null @@ -1,149 +0,0 @@ -#include -#include -#include - -static void test_box_empty(void) { - // NULL is empty - assert(wlr_box_empty(NULL)); - - // Zero width/height - struct wlr_box box = { .x = 0, .y = 0, .width = 0, .height = 10 }; - assert(wlr_box_empty(&box)); - box = (struct wlr_box){ .x = 0, .y = 0, .width = 10, .height = 0 }; - assert(wlr_box_empty(&box)); - - // Negative width/height - box = (struct wlr_box){ .x = 0, .y = 0, .width = -1, .height = 10 }; - assert(wlr_box_empty(&box)); - box = (struct wlr_box){ .x = 0, .y = 0, .width = 10, .height = -1 }; - assert(wlr_box_empty(&box)); - - // Valid box - box = (struct wlr_box){ .x = 0, .y = 0, .width = 10, .height = 10 }; - assert(!wlr_box_empty(&box)); -} - -static void test_box_intersection(void) { - struct wlr_box dest; - - // Overlapping - struct wlr_box a = { .x = 0, .y = 0, .width = 100, .height = 100 }; - struct wlr_box b = { .x = 50, .y = 50, .width = 100, .height = 100 }; - assert(wlr_box_intersection(&dest, &a, &b)); - assert(dest.x == 50 && dest.y == 50 && - dest.width == 50 && dest.height == 50); - - // Non-overlapping - b = (struct wlr_box){ .x = 200, .y = 200, .width = 50, .height = 50 }; - assert(!wlr_box_intersection(&dest, &a, &b)); - assert(dest.width == 0 && dest.height == 0); - - // Touching edges - b = (struct wlr_box){ .x = 100, .y = 0, .width = 50, .height = 50 }; - assert(!wlr_box_intersection(&dest, &a, &b)); - - // Self-intersection - assert(wlr_box_intersection(&dest, &a, &a)); - assert(dest.x == a.x && dest.y == a.y && - dest.width == a.width && dest.height == a.height); - - // Empty input - struct wlr_box empty = { .x = 0, .y = 0, .width = 0, .height = 0 }; - assert(!wlr_box_intersection(&dest, &a, &empty)); - - // NULL input - assert(!wlr_box_intersection(&dest, &a, NULL)); - assert(!wlr_box_intersection(&dest, NULL, &a)); -} - -static void test_box_intersects_box(void) { - // Overlapping - struct wlr_box a = { .x = 0, .y = 0, .width = 100, .height = 100 }; - struct wlr_box b = { .x = 50, .y = 50, .width = 100, .height = 100 }; - assert(wlr_box_intersects(&a, &b)); - - // Non-overlapping - b = (struct wlr_box){ .x = 200, .y = 200, .width = 50, .height = 50 }; - assert(!wlr_box_intersects(&a, &b)); - - // Touching edges - b = (struct wlr_box){ .x = 100, .y = 0, .width = 50, .height = 50 }; - assert(!wlr_box_intersects(&a, &b)); - - // Self-intersection - assert(wlr_box_intersects(&a, &a)); - - // Empty input - struct wlr_box empty = { .x = 0, .y = 0, .width = 0, .height = 0 }; - assert(!wlr_box_intersects(&a, &empty)); - - // NULL input - assert(!wlr_box_intersects(&a, NULL)); - assert(!wlr_box_intersects(NULL, &a)); -} - -static void test_box_contains_point(void) { - struct wlr_box box = { .x = 10, .y = 20, .width = 100, .height = 50 }; - - // Interior point - assert(wlr_box_contains_point(&box, 50, 40)); - - // Inclusive lower bound - assert(wlr_box_contains_point(&box, 10, 20)); - - // Exclusive upper bound - assert(!wlr_box_contains_point(&box, 110, 70)); - assert(!wlr_box_contains_point(&box, 110, 40)); - assert(!wlr_box_contains_point(&box, 50, 70)); - - // Outside - assert(!wlr_box_contains_point(&box, 5, 40)); - assert(!wlr_box_contains_point(&box, 50, 15)); - - // Empty box - struct wlr_box empty = { .x = 0, .y = 0, .width = 0, .height = 0 }; - assert(!wlr_box_contains_point(&empty, 0, 0)); - - // NULL - assert(!wlr_box_contains_point(NULL, 0, 0)); -} - -static void test_box_contains_box(void) { - struct wlr_box outer = { .x = 0, .y = 0, .width = 100, .height = 100 }; - - // Fully contained - struct wlr_box inner = { .x = 10, .y = 10, .width = 50, .height = 50 }; - assert(wlr_box_contains_box(&outer, &inner)); - - // Self-containment - assert(wlr_box_contains_box(&outer, &outer)); - - // Partial overlap — not contained - struct wlr_box partial = { .x = 50, .y = 50, .width = 100, .height = 100 }; - assert(!wlr_box_contains_box(&outer, &partial)); - - // Empty inner - struct wlr_box empty = { .x = 0, .y = 0, .width = 0, .height = 0 }; - assert(!wlr_box_contains_box(&outer, &empty)); - - // Empty outer - assert(!wlr_box_contains_box(&empty, &inner)); - - // NULL - assert(!wlr_box_contains_box(&outer, NULL)); - assert(!wlr_box_contains_box(NULL, &outer)); -} - -int main(void) { -#ifdef NDEBUG - fprintf(stderr, "NDEBUG must be disabled for tests\n"); - return 1; -#endif - - test_box_empty(); - test_box_intersection(); - test_box_intersects_box(); - test_box_contains_point(); - test_box_contains_box(); - return 0; -} diff --git a/test/test_vulkan_stage_buffer.c b/test/test_vulkan_stage_buffer.c deleted file mode 100644 index 74f230a44..000000000 --- a/test/test_vulkan_stage_buffer.c +++ /dev/null @@ -1,200 +0,0 @@ -#include -#include -#include - -#include "render/vulkan.h" - -#define BUF_SIZE 1024 -#define ALLOC_FAIL ((VkDeviceSize)-1) - -static void stage_buffer_init(struct wlr_vk_stage_buffer *buf) { - *buf = (struct wlr_vk_stage_buffer){ - .buf_size = BUF_SIZE, - }; - wl_array_init(&buf->watermarks); -} - -static void stage_buffer_finish(struct wlr_vk_stage_buffer *buf) { - wl_array_release(&buf->watermarks); -} - -static void push_watermark(struct wlr_vk_stage_buffer *buf, - uint64_t timeline_point) { - struct wlr_vk_stage_watermark *mark = wl_array_add( - &buf->watermarks, sizeof(*mark)); - assert(mark != NULL); - *mark = (struct wlr_vk_stage_watermark){ - .head = buf->head, - .timeline_point = timeline_point, - }; -} - -static size_t watermark_count(const struct wlr_vk_stage_buffer *buf) { - return buf->watermarks.size / sizeof(struct wlr_vk_stage_watermark); -} - -static void test_alloc_simple(void) { - struct wlr_vk_stage_buffer buf; - stage_buffer_init(&buf); - - assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 0); - assert(buf.head == 100); - assert(vulkan_stage_buffer_alloc(&buf, 200, 1) == 100); - assert(buf.head == 300); - assert(buf.tail == 0); - - stage_buffer_finish(&buf); -} - -static void test_alloc_alignment(void) { - struct wlr_vk_stage_buffer buf; - stage_buffer_init(&buf); - - assert(vulkan_stage_buffer_alloc(&buf, 7, 1) == 0); - assert(buf.head == 7); - - assert(vulkan_stage_buffer_alloc(&buf, 4, 16) == 16); - assert(buf.head == 20); - - assert(vulkan_stage_buffer_alloc(&buf, 8, 8) == 24); - assert(buf.head == 32); - - stage_buffer_finish(&buf); -} - -static void test_alloc_limit(void) { - struct wlr_vk_stage_buffer buf; - stage_buffer_init(&buf); - - // We do not allow allocations that would cause head to equal tail - assert(vulkan_stage_buffer_alloc(&buf, BUF_SIZE, 1) == ALLOC_FAIL); - assert(buf.head == 0); - - assert(vulkan_stage_buffer_alloc(&buf, BUF_SIZE-1, 1) == 0); - assert(buf.head == BUF_SIZE-1); - - stage_buffer_finish(&buf); -} - -static void test_alloc_wrap(void) { - struct wlr_vk_stage_buffer buf; - stage_buffer_init(&buf); - - // Fill the first 924 bytes - assert(vulkan_stage_buffer_alloc(&buf, BUF_SIZE - 100, 1) == 0); - push_watermark(&buf, 1); - - // Fill the end of the buffer - assert(vulkan_stage_buffer_alloc(&buf, 50, 1) == 924); - push_watermark(&buf, 2); - - // First, check that we don't wrap prematurely - assert(vulkan_stage_buffer_alloc(&buf, 50, 1) == ALLOC_FAIL); - assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == ALLOC_FAIL); - - // Free the beginning of the buffer and try to wrap again - vulkan_stage_buffer_reclaim(&buf, 1); - assert(vulkan_stage_buffer_alloc(&buf, 50, 1) == 0); - assert(buf.tail == 924); - assert(buf.head == 50); - - // Check that freeing from the end of the buffer still works - vulkan_stage_buffer_reclaim(&buf, 2); - assert(buf.tail == 974); - assert(buf.head == 50); - - // Check that allocations still work - assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 50); - assert(buf.tail == 974); - assert(buf.head == 150); - - stage_buffer_finish(&buf); -} - -static void test_reclaim_empty(void) { - struct wlr_vk_stage_buffer buf; - stage_buffer_init(&buf); - - // Fresh buffer with no watermarks and head == tail == 0 is drained. - vulkan_stage_buffer_reclaim(&buf, 0); - assert(buf.head == buf.tail); - assert(buf.tail == 0); - - stage_buffer_finish(&buf); -} - -static void test_reclaim_pending_not_completed(void) { - struct wlr_vk_stage_buffer buf; - stage_buffer_init(&buf); - - assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 0); - push_watermark(&buf, 1); - - // current point hasn't reached the watermark yet. - vulkan_stage_buffer_reclaim(&buf, 0); - assert(buf.head != buf.tail); - assert(buf.tail == 0); - assert(watermark_count(&buf) == 1); - - stage_buffer_finish(&buf); -} - -static void test_reclaim_partial(void) { - struct wlr_vk_stage_buffer buf; - stage_buffer_init(&buf); - - assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 0); - push_watermark(&buf, 1); - assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 100); - push_watermark(&buf, 2); - - // Only the first watermark is reached. - vulkan_stage_buffer_reclaim(&buf, 1); - assert(buf.head != buf.tail); - assert(buf.tail == 100); - assert(watermark_count(&buf) == 1); - - const struct wlr_vk_stage_watermark *remaining = buf.watermarks.data; - assert(remaining[0].head == 200); - assert(remaining[0].timeline_point == 2); - - stage_buffer_finish(&buf); -} - -static void test_reclaim_all(void) { - struct wlr_vk_stage_buffer buf; - stage_buffer_init(&buf); - - assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 0); - push_watermark(&buf, 1); - assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 100); - push_watermark(&buf, 2); - assert(vulkan_stage_buffer_alloc(&buf, 100, 1) == 200); - push_watermark(&buf, 3); - - vulkan_stage_buffer_reclaim(&buf, 100); - assert(buf.head == buf.tail); - assert(buf.tail == 300); - assert(watermark_count(&buf) == 0); - - stage_buffer_finish(&buf); -} - -int main(void) { -#ifdef NDEBUG - fprintf(stderr, "NDEBUG must be disabled for tests\n"); - return 1; -#endif - - test_alloc_simple(); - test_alloc_alignment(); - test_alloc_limit(); - test_alloc_wrap(); - - test_reclaim_empty(); - test_reclaim_pending_not_completed(); - test_reclaim_partial(); - test_reclaim_all(); - - return 0; -} diff --git a/tinywl/Makefile b/tinywl/Makefile index 0f1c4cb13..2efe4a436 100644 --- a/tinywl/Makefile +++ b/tinywl/Makefile @@ -1,6 +1,6 @@ PKG_CONFIG?=pkg-config -PKGS="wlroots-0.21" wayland-server xkbcommon +PKGS="wlroots-0.20" wayland-server xkbcommon CFLAGS_PKG_CONFIG!=$(PKG_CONFIG) --cflags $(PKGS) CFLAGS+=$(CFLAGS_PKG_CONFIG) LIBS!=$(PKG_CONFIG) --libs $(PKGS) diff --git a/types/ext_image_capture_source_v1/foreign_toplevel.c b/types/ext_image_capture_source_v1/foreign_toplevel.c index 4aa084df6..b1110d155 100644 --- a/types/ext_image_capture_source_v1/foreign_toplevel.c +++ b/types/ext_image_capture_source_v1/foreign_toplevel.c @@ -17,7 +17,7 @@ foreign_toplevel_manager_from_resource(struct wl_resource *resource) { } bool wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept( - struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_event *request, + struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request, struct wlr_ext_image_capture_source_v1 *source) { return wlr_ext_image_capture_source_v1_create_resource(source, request->client, request->new_id); } @@ -34,13 +34,13 @@ static void foreign_toplevel_manager_handle_create_source(struct wl_client *clie return; } - struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_event request = { + struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request request = { .toplevel_handle = toplevel_handle, .client = client, .new_id = new_id, }; - wl_signal_emit_mutable(&manager->events.capture_request, &request); + wl_signal_emit_mutable(&manager->events.new_request, &request); } static void foreign_toplevel_manager_handle_destroy(struct wl_client *client, @@ -71,7 +71,7 @@ static void foreign_toplevel_manager_handle_display_destroy(struct wl_listener * wl_container_of(listener, manager, display_destroy); wl_signal_emit_mutable(&manager->events.destroy, NULL); assert(wl_list_empty(&manager->events.destroy.listener_list)); - assert(wl_list_empty(&manager->events.capture_request.listener_list)); + assert(wl_list_empty(&manager->events.new_request.listener_list)); wl_list_remove(&manager->display_destroy.link); wl_global_destroy(manager->global); free(manager); @@ -97,7 +97,7 @@ wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(struct wl_displa } wl_signal_init(&manager->events.destroy); - wl_signal_init(&manager->events.capture_request); + wl_signal_init(&manager->events.new_request); manager->display_destroy.notify = foreign_toplevel_manager_handle_display_destroy; wl_display_add_destroy_listener(display, &manager->display_destroy); diff --git a/types/meson.build b/types/meson.build index 0513b8fc8..26958f048 100644 --- a/types/meson.build +++ b/types/meson.build @@ -48,7 +48,6 @@ wlr_files += files( 'wlr_data_control_v1.c', 'wlr_drm.c', 'wlr_export_dmabuf_v1.c', - 'wlr_ext_background_effect_v1.c', 'wlr_ext_data_control_v1.c', 'wlr_ext_foreign_toplevel_list_v1.c', 'wlr_ext_image_copy_capture_v1.c', @@ -74,7 +73,6 @@ wlr_files += files( 'wlr_output_swapchain_manager.c', 'wlr_pointer_constraints_v1.c', 'wlr_pointer_gestures_v1.c', - 'wlr_pointer_warp_v1.c', 'wlr_pointer.c', 'wlr_presentation_time.c', 'wlr_primary_selection_v1.c', diff --git a/types/output/cursor.c b/types/output/cursor.c index 4a823dab1..5e93b0b2e 100644 --- a/types/output/cursor.c +++ b/types/output/cursor.c @@ -159,8 +159,9 @@ static void output_cursor_update_visible(struct wlr_output_cursor *cursor) { struct wlr_box cursor_box; output_cursor_get_box(cursor, &cursor_box); + struct wlr_box intersection; cursor->visible = - wlr_box_intersects(&output_box, &cursor_box); + wlr_box_intersection(&intersection, &output_box, &cursor_box); } static bool output_pick_cursor_format(struct wlr_output *output, diff --git a/types/output/output.c b/types/output/output.c index 46da1f425..3715950ce 100644 --- a/types/output/output.c +++ b/types/output/output.c @@ -233,11 +233,6 @@ static void output_apply_state(struct wlr_output *output, output->transform = state->transform; } - if (state->committed & WLR_OUTPUT_STATE_COLOR_REPRESENTATION) { - output->color_encoding = state->color_encoding; - output->color_range = state->color_range; - } - if (state->committed & WLR_OUTPUT_STATE_IMAGE_DESCRIPTION) { if (state->image_description != NULL) { output->image_description_value = *state->image_description; @@ -585,11 +580,6 @@ static uint32_t output_compare_state(struct wlr_output *output, output->color_transform == state->color_transform) { fields |= WLR_OUTPUT_STATE_COLOR_TRANSFORM; } - if ((state->committed & WLR_OUTPUT_STATE_COLOR_REPRESENTATION) && - output->color_encoding == state->color_encoding && - output->color_range == state->color_range) { - fields |= WLR_OUTPUT_STATE_COLOR_REPRESENTATION; - } return fields; } @@ -625,7 +615,7 @@ static bool output_basic_test(struct wlr_output *output, }; struct wlr_box dst_box; output_state_get_buffer_dst_box(state, &dst_box); - if (!wlr_box_intersects(&output_box, &dst_box)) { + if (!wlr_box_intersection(&output_box, &output_box, &dst_box)) { wlr_log(WLR_ERROR, "Primary buffer is entirely off-screen or 0-sized"); return false; } @@ -642,10 +632,6 @@ static bool output_basic_test(struct wlr_output *output, wlr_log(WLR_DEBUG, "Tried to set signal timeline without a buffer"); return false; } - if (state->committed & WLR_OUTPUT_STATE_COLOR_REPRESENTATION) { - wlr_log(WLR_DEBUG, "Tried to set color representation without a buffer"); - return false; - } } if (state->committed & WLR_OUTPUT_STATE_RENDER_FORMAT) { diff --git a/types/output/state.c b/types/output/state.c index 5f44c18e8..f2c655e21 100644 --- a/types/output/state.c +++ b/types/output/state.c @@ -141,14 +141,6 @@ bool wlr_output_state_set_image_description(struct wlr_output_state *state, return true; } -void wlr_output_state_set_color_encoding_and_range( - struct wlr_output_state *state, - enum wlr_color_encoding encoding, enum wlr_color_range range) { - state->committed |= WLR_OUTPUT_STATE_COLOR_REPRESENTATION; - state->color_encoding = encoding; - state->color_range = range; -} - bool wlr_output_state_copy(struct wlr_output_state *dst, const struct wlr_output_state *src) { struct wlr_output_state copy = *src; diff --git a/types/scene/surface.c b/types/scene/surface.c index 33b229955..89c54a9ed 100644 --- a/types/scene/surface.c +++ b/types/scene/surface.c @@ -161,14 +161,6 @@ static void handle_scene_buffer_output_sample( wl_container_of(listener, surface, output_sample); const struct wlr_scene_output_sample_event *event = data; struct wlr_output *output = event->output->output; - - struct wlr_linux_drm_syncobj_surface_v1_state *syncobj_surface_state = - wlr_linux_drm_syncobj_v1_get_surface_state(surface->surface); - if (syncobj_surface_state != NULL && event->release_timeline != NULL) { - wlr_linux_drm_syncobj_v1_state_add_release_point(syncobj_surface_state, - event->release_timeline, event->release_point, output->event_loop); - } - if (get_surface_frame_pacing_output(surface->surface) != output) { return; } @@ -178,6 +170,13 @@ static void handle_scene_buffer_output_sample( } else { wlr_presentation_surface_textured_on_output(surface->surface, output); } + + struct wlr_linux_drm_syncobj_surface_v1_state *syncobj_surface_state = + wlr_linux_drm_syncobj_v1_get_surface_state(surface->surface); + if (syncobj_surface_state != NULL && event->release_timeline != NULL) { + wlr_linux_drm_syncobj_v1_state_add_release_point(syncobj_surface_state, + event->release_timeline, event->release_point, output->event_loop); + } } static void handle_scene_buffer_frame_done( diff --git a/types/scene/wlr_scene.c b/types/scene/wlr_scene.c index 7e4a81004..54c09bbfe 100644 --- a/types/scene/wlr_scene.c +++ b/types/scene/wlr_scene.c @@ -113,11 +113,24 @@ void wlr_scene_node_destroy(struct wlr_scene_node *node) { if (node->type == WLR_SCENE_NODE_BUFFER) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); + uint64_t active = scene_buffer->active_outputs; + if (active) { + struct wlr_scene_output *scene_output; + wl_list_for_each(scene_output, &scene->outputs, link) { + if (active & (1ull << scene_output->index)) { + wl_signal_emit_mutable(&scene_buffer->events.output_leave, + scene_output); + } + } + } + scene_buffer_set_buffer(scene_buffer, NULL); scene_buffer_set_texture(scene_buffer, NULL); pixman_region32_fini(&scene_buffer->opaque_region); wlr_drm_syncobj_timeline_unref(scene_buffer->wait_timeline); + assert(wl_list_empty(&scene_buffer->events.output_leave.listener_list)); + assert(wl_list_empty(&scene_buffer->events.output_enter.listener_list)); assert(wl_list_empty(&scene_buffer->events.outputs_update.listener_list)); assert(wl_list_empty(&scene_buffer->events.output_sample.listener_list)); assert(wl_list_empty(&scene_buffer->events.frame_done.listener_list)); @@ -225,7 +238,7 @@ static bool _scene_nodes_in_box(struct wlr_scene_node *node, struct wlr_box *box struct wlr_box node_box = { .x = lx, .y = ly }; scene_node_get_size(node, &node_box.width, &node_box.height); - if (wlr_box_intersects(&node_box, box) && + if (wlr_box_intersection(&node_box, &node_box, box) && iterator(node, lx, ly, user_data)) { return true; } @@ -463,12 +476,33 @@ static void update_node_update_outputs(struct wlr_scene_node *node, } } + if (old_primary_output != scene_buffer->primary_output) { + scene_buffer->prev_feedback_options = + (struct wlr_linux_dmabuf_feedback_v1_init_options){0}; + } + + uint64_t old_active = scene_buffer->active_outputs; + scene_buffer->active_outputs = active_outputs; + + struct wlr_scene_output *scene_output; + wl_list_for_each(scene_output, outputs, link) { + uint64_t mask = 1ull << scene_output->index; + bool intersects = active_outputs & mask; + bool intersects_before = old_active & mask; + + if (intersects && !intersects_before) { + wl_signal_emit_mutable(&scene_buffer->events.output_enter, scene_output); + } else if (!intersects && intersects_before) { + wl_signal_emit_mutable(&scene_buffer->events.output_leave, scene_output); + } + } + // if there are active outputs on this node, we should always have a primary // output - assert(!active_outputs || scene_buffer->primary_output); + assert(!scene_buffer->active_outputs || scene_buffer->primary_output); // Skip output update event if nothing was updated - if (scene_buffer->active_outputs == active_outputs && + if (old_active == active_outputs && (!force || ((1ull << force->index) & ~active_outputs)) && old_primary_output == scene_buffer->primary_output) { return; @@ -481,7 +515,6 @@ static void update_node_update_outputs(struct wlr_scene_node *node, }; size_t i = 0; - struct wlr_scene_output *scene_output; wl_list_for_each(scene_output, outputs, link) { if (~active_outputs & (1ull << scene_output->index)) { continue; @@ -491,7 +524,6 @@ static void update_node_update_outputs(struct wlr_scene_node *node, outputs_array[i++] = scene_output; } - scene_buffer->active_outputs = active_outputs; wl_signal_emit_mutable(&scene_buffer->events.outputs_update, &event); } @@ -837,6 +869,8 @@ struct wlr_scene_buffer *wlr_scene_buffer_create(struct wlr_scene_tree *parent, scene_node_init(&scene_buffer->node, WLR_SCENE_NODE_BUFFER, parent); wl_signal_init(&scene_buffer->events.outputs_update); + wl_signal_init(&scene_buffer->events.output_enter); + wl_signal_init(&scene_buffer->events.output_leave); wl_signal_init(&scene_buffer->events.output_sample); wl_signal_init(&scene_buffer->events.frame_done); @@ -2064,6 +2098,15 @@ static enum scene_direct_scanout_result scene_entry_try_direct_scanout( return SCANOUT_INELIGIBLE; } + bool is_color_repr_none = buffer->color_encoding == WLR_COLOR_ENCODING_NONE && + buffer->color_range == WLR_COLOR_RANGE_NONE; + bool is_color_repr_identity_full = buffer->color_encoding == WLR_COLOR_ENCODING_IDENTITY && + buffer->color_range == WLR_COLOR_RANGE_FULL; + + if (!(is_color_repr_none || is_color_repr_identity_full)) { + return SCANOUT_INELIGIBLE; + } + // We want to ensure optimal buffer selection, but as direct-scanout can be enabled and disabled // on a frame-by-frame basis, we wait for a few frames to send the new format recommendations. // Maybe we should only send feedback in this case if tests fail. @@ -2106,22 +2149,11 @@ static enum scene_direct_scanout_result scene_entry_try_direct_scanout( wlr_output_state_set_wait_timeline(&pending, buffer->wait_timeline, buffer->wait_point); } - if (scene_output->out_timeline) { + if (scene_output->out_timeline) { scene_output->out_point++; wlr_output_state_set_signal_timeline(&pending, scene_output->out_timeline, scene_output->out_point); } - if (buffer->color_encoding == WLR_COLOR_ENCODING_IDENTITY && - buffer->color_range == WLR_COLOR_RANGE_FULL) { - // IDENTITY+FULL (used for RGB formats) is equivalent to no color - // representation being set at all. - wlr_output_state_set_color_encoding_and_range(&pending, - WLR_COLOR_ENCODING_NONE, WLR_COLOR_RANGE_NONE); - } else { - wlr_output_state_set_color_encoding_and_range(&pending, - buffer->color_encoding, buffer->color_range); - } - if (!wlr_output_test_state(scene_output->output, &pending)) { wlr_output_state_finish(&pending); return SCANOUT_CANDIDATE; @@ -2664,7 +2696,8 @@ static void scene_output_for_each_scene_buffer(const struct wlr_box *output_box, struct wlr_box node_box = { .x = lx, .y = ly }; scene_node_get_size(node, &node_box.width, &node_box.height); - if (wlr_box_intersects(output_box, &node_box)) { + struct wlr_box intersection; + if (wlr_box_intersection(&intersection, output_box, &node_box)) { struct wlr_scene_buffer *scene_buffer = wlr_scene_buffer_from_node(node); user_iterator(scene_buffer, lx, ly, user_data); diff --git a/types/wlr_color_management_v1.c b/types/wlr_color_management_v1.c index 27f9d1829..aa924e36d 100644 --- a/types/wlr_color_management_v1.c +++ b/types/wlr_color_management_v1.c @@ -20,7 +20,6 @@ struct wlr_color_management_output_v1 { struct wlr_color_manager_v1 *manager; struct wl_list link; - struct wl_listener output_commit; struct wl_listener output_destroy; }; @@ -284,21 +283,11 @@ static void cm_output_destroy(struct wlr_color_management_output_v1 *cm_output) return; } wl_resource_set_user_data(cm_output->resource, NULL); // make inert - wl_list_remove(&cm_output->output_commit.link); wl_list_remove(&cm_output->output_destroy.link); wl_list_remove(&cm_output->link); free(cm_output); } -static void cm_output_handle_output_commit(struct wl_listener *listener, void *data) { - struct wlr_color_management_output_v1 *cm_output = wl_container_of(listener, cm_output, output_commit); - const struct wlr_output_event_commit *event = data; - - if (event->state->committed & WLR_OUTPUT_STATE_IMAGE_DESCRIPTION) { - wp_color_management_output_v1_send_image_description_changed(cm_output->resource); - } -} - static void cm_output_handle_output_destroy(struct wl_listener *listener, void *data) { struct wlr_color_management_output_v1 *cm_output = wl_container_of(listener, cm_output, output_destroy); cm_output_destroy(cm_output); @@ -753,9 +742,6 @@ static void manager_handle_get_output(struct wl_client *client, cm_output->manager = manager; cm_output->output = output; - cm_output->output_commit.notify = cm_output_handle_output_commit; - wl_signal_add(&output->events.commit, &cm_output->output_commit); - cm_output->output_destroy.notify = cm_output_handle_output_destroy; wl_signal_add(&output->events.destroy, &cm_output->output_destroy); diff --git a/types/wlr_ext_background_effect_v1.c b/types/wlr_ext_background_effect_v1.c deleted file mode 100644 index 3bf214397..000000000 --- a/types/wlr_ext_background_effect_v1.c +++ /dev/null @@ -1,241 +0,0 @@ -#include -#include -#include -#include -#include -#include "ext-background-effect-v1-protocol.h" - -#define BACKGROUND_EFFECT_VERSION 1 - -struct wlr_ext_background_effect_surface_v1 { - struct wl_resource *resource; - struct wlr_surface *surface; - struct wlr_addon addon; - struct wlr_surface_synced synced; - struct wlr_ext_background_effect_surface_v1_state pending, current; -}; - -static const struct ext_background_effect_surface_v1_interface surface_impl; -static const struct ext_background_effect_manager_v1_interface manager_impl; - -static struct wlr_ext_background_effect_surface_v1 *surface_from_resource( - struct wl_resource *resource) { - assert(wl_resource_instance_of(resource, - &ext_background_effect_surface_v1_interface, &surface_impl)); - - return wl_resource_get_user_data(resource); -} - -static void surface_destroy(struct wlr_ext_background_effect_surface_v1 *surface) { - if (surface == NULL) { - return; - } - - wlr_surface_synced_finish(&surface->synced); - wlr_addon_finish(&surface->addon); - wl_resource_set_user_data(surface->resource, NULL); - free(surface); -} - -static void surface_handle_resource_destroy(struct wl_resource *resource) { - struct wlr_ext_background_effect_surface_v1 *surface = surface_from_resource(resource); - surface_destroy(surface); -} - -static void surface_handle_destroy(struct wl_client *client, struct wl_resource *resource) { - wl_resource_destroy(resource); -} - -static void surface_handle_set_blur_region(struct wl_client *client, struct wl_resource *resource, - struct wl_resource *region_resource) { - struct wlr_ext_background_effect_surface_v1 *surface = surface_from_resource(resource); - - if (surface == NULL) { - wl_resource_post_error(resource, - EXT_BACKGROUND_EFFECT_SURFACE_V1_ERROR_SURFACE_DESTROYED, - "The wl_surface object has been destroyed"); - return; - } - - if (region_resource != NULL) { - const pixman_region32_t *region = wlr_region_from_resource(region_resource); - pixman_region32_copy(&surface->pending.blur_region, region); - } else { - pixman_region32_clear(&surface->pending.blur_region); - } -} - -static const struct ext_background_effect_surface_v1_interface surface_impl = { - .destroy = surface_handle_destroy, - .set_blur_region = surface_handle_set_blur_region, -}; - -static void surface_synced_init_state(void *_state) { - struct wlr_ext_background_effect_surface_v1_state *state = _state; - pixman_region32_init(&state->blur_region); -} - -static void surface_synced_finish_state(void *_state) { - struct wlr_ext_background_effect_surface_v1_state *state = _state; - pixman_region32_fini(&state->blur_region); -} - -static void surface_synced_move_state(void *_dst, void *_src) { - struct wlr_ext_background_effect_surface_v1_state *dst = _dst; - struct wlr_ext_background_effect_surface_v1_state *src = _src; - - pixman_region32_copy(&dst->blur_region, &src->blur_region); -} - -static const struct wlr_surface_synced_impl surface_synced_impl = { - .state_size = sizeof(struct wlr_ext_background_effect_surface_v1_state), - .init_state = surface_synced_init_state, - .finish_state = surface_synced_finish_state, - .move_state = surface_synced_move_state, -}; - -static void surface_addon_destroy(struct wlr_addon *addon) { - struct wlr_ext_background_effect_surface_v1 *surface = wl_container_of(addon, surface, addon); - - surface_destroy(surface); -} - -static const struct wlr_addon_interface surface_addon_impl = { - .name = "ext_background_effect_surface_v1", - .destroy = surface_addon_destroy, -}; - -static struct wlr_ext_background_effect_surface_v1 *surface_from_wlr_surface( - struct wlr_surface *wlr_surface) { - struct wlr_addon *addon = wlr_addon_find(&wlr_surface->addons, NULL, &surface_addon_impl); - if (addon == NULL) { - return NULL; - } - - struct wlr_ext_background_effect_surface_v1 *surface = - wl_container_of(addon, surface, addon); - - return surface; -} - -static void manager_handle_destroy(struct wl_client *client, struct wl_resource *resource) { - wl_resource_destroy(resource); -} - -static void manager_handle_get_background_effect(struct wl_client *client, - struct wl_resource *manager_resource, uint32_t id, struct wl_resource *surface_resource) { - struct wlr_surface *wlr_surface = wlr_surface_from_resource(surface_resource); - - if (surface_from_wlr_surface(wlr_surface) != NULL) { - wl_resource_post_error(manager_resource, - EXT_BACKGROUND_EFFECT_MANAGER_V1_ERROR_BACKGROUND_EFFECT_EXISTS, - "The wl_surface object already has a ext_background_effect_surface_v1 object"); - return; - } - - struct wlr_ext_background_effect_surface_v1 *surface = calloc(1, sizeof(*surface)); - if (surface == NULL) { - wl_resource_post_no_memory(manager_resource); - return; - } - - if (!wlr_surface_synced_init(&surface->synced, wlr_surface, &surface_synced_impl, - &surface->pending, &surface->current)) { - free(surface); - wl_resource_post_no_memory(manager_resource); - return; - } - - uint32_t version = wl_resource_get_version(manager_resource); - surface->resource = - wl_resource_create(client, &ext_background_effect_surface_v1_interface, version, id); - - if (surface->resource == NULL) { - wlr_surface_synced_finish(&surface->synced); - free(surface); - wl_resource_post_no_memory(manager_resource); - return; - } - - wl_resource_set_implementation(surface->resource, &surface_impl, surface, - surface_handle_resource_destroy); - - surface->surface = wlr_surface; - wlr_addon_init(&surface->addon, &wlr_surface->addons, NULL, &surface_addon_impl); -} - -static const struct ext_background_effect_manager_v1_interface manager_impl = { - .destroy = manager_handle_destroy, - .get_background_effect = manager_handle_get_background_effect, -}; - -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 *wl_client, void *data, uint32_t version, uint32_t id) { - struct wlr_ext_background_effect_manager_v1 *manager = data; - - struct wl_resource *resource = wl_resource_create(wl_client, - &ext_background_effect_manager_v1_interface, version, id); - if (resource == NULL) { - wl_client_post_no_memory(wl_client); - return; - } - wl_resource_set_implementation(resource, &manager_impl, manager, - manager_handle_resource_destroy); - wl_list_insert(&manager->resources, wl_resource_get_link(resource)); - - ext_background_effect_manager_v1_send_capabilities(resource, manager->capabilities); -} - -static void handle_display_destroy(struct wl_listener *listener, void *data) { - struct wlr_ext_background_effect_manager_v1 *manager = - wl_container_of(listener, manager, display_destroy); - - wl_signal_emit_mutable(&manager->events.destroy, NULL); - assert(wl_list_empty(&manager->events.destroy.listener_list)); - - wl_global_destroy(manager->global); - wl_list_remove(&manager->display_destroy.link); - free(manager); -} - -struct wlr_ext_background_effect_manager_v1 *wlr_ext_background_effect_manager_v1_create( - struct wl_display *display, uint32_t version, uint32_t capabilities) { - assert(version <= BACKGROUND_EFFECT_VERSION); - - struct wlr_ext_background_effect_manager_v1 *manager = calloc(1, sizeof(*manager)); - if (manager == NULL) { - return NULL; - } - - manager->global = wl_global_create(display, &ext_background_effect_manager_v1_interface, version, - manager, manager_bind); - if (manager->global == NULL) { - free(manager); - return NULL; - } - - manager->capabilities = capabilities; - - wl_signal_init(&manager->events.destroy); - wl_list_init(&manager->resources); - - manager->display_destroy.notify = handle_display_destroy; - wl_display_add_destroy_listener(display, &manager->display_destroy); - - return manager; -} - -const struct wlr_ext_background_effect_surface_v1_state * -wlr_ext_background_effect_v1_get_surface_state(struct wlr_surface *wlr_surface) { - struct wlr_ext_background_effect_surface_v1 *surface = - surface_from_wlr_surface(wlr_surface); - - if (surface == NULL) { - return NULL; - } - - return &surface->current; -} diff --git a/types/wlr_layer_shell_v1.c b/types/wlr_layer_shell_v1.c index 72d3c4923..2d8384981 100644 --- a/types/wlr_layer_shell_v1.c +++ b/types/wlr_layer_shell_v1.c @@ -394,7 +394,6 @@ static void layer_surface_role_commit(struct wlr_surface *wlr_surface) { layer_surface_reset(surface); assert(!surface->initialized); - assert(!surface->initial_commit); surface->initial_commit = false; } else { surface->initial_commit = !surface->initialized; diff --git a/types/wlr_linux_dmabuf_v1.c b/types/wlr_linux_dmabuf_v1.c index 0b2e908fb..3165e8805 100644 --- a/types/wlr_linux_dmabuf_v1.c +++ b/types/wlr_linux_dmabuf_v1.c @@ -901,9 +901,9 @@ static bool set_default_feedback(struct wlr_linux_dmabuf_v1 *linux_dmabuf, if (device->available_nodes & (1 << DRM_NODE_RENDER)) { const char *name = device->nodes[DRM_NODE_RENDER]; main_device_fd = open(name, O_RDWR | O_CLOEXEC); + drmFreeDevice(&device); if (main_device_fd < 0) { wlr_log_errno(WLR_ERROR, "Failed to open DRM device %s", name); - drmFreeDevice(&device); goto error_compiled; } } else { @@ -913,8 +913,8 @@ static bool set_default_feedback(struct wlr_linux_dmabuf_v1 *linux_dmabuf, assert(device->available_nodes & (1 << DRM_NODE_PRIMARY)); wlr_log(WLR_DEBUG, "DRM device %s has no render node, " "skipping DMA-BUF import checks", device->nodes[DRM_NODE_PRIMARY]); + drmFreeDevice(&device); } - drmFreeDevice(&device); size_t tranches_len = feedback->tranches.size / sizeof(struct wlr_linux_dmabuf_feedback_v1_tranche); diff --git a/types/wlr_linux_drm_syncobj_v1.c b/types/wlr_linux_drm_syncobj_v1.c index 6d9188777..2e09b9e2e 100644 --- a/types/wlr_linux_drm_syncobj_v1.c +++ b/types/wlr_linux_drm_syncobj_v1.c @@ -12,7 +12,6 @@ #include #include "config.h" #include "linux-drm-syncobj-v1-protocol.h" -#include "render/dmabuf.h" #include "render/drm_syncobj_merger.h" #define LINUX_DRM_SYNCOBJ_V1_VERSION 1 @@ -542,12 +541,3 @@ bool wlr_linux_drm_syncobj_v1_state_add_release_point( return wlr_drm_syncobj_merger_add(state->release_merger, release_timeline, release_point, event_loop); } - -bool wlr_linux_drm_syncobj_v1_state_add_release_from_implicit_sync( - struct wlr_linux_drm_syncobj_surface_v1_state *state, - struct wlr_buffer *buffer, struct wl_event_loop *event_loop) { - if (state->release_merger == NULL) { - return true; - } - return wlr_drm_syncobj_merger_add_dmabuf(state->release_merger, buffer, event_loop); -} diff --git a/types/wlr_output_layout.c b/types/wlr_output_layout.c index 7226809e7..ef2751179 100644 --- a/types/wlr_output_layout.c +++ b/types/wlr_output_layout.c @@ -260,12 +260,14 @@ bool wlr_output_layout_contains_point(struct wlr_output_layout *layout, bool wlr_output_layout_intersects(struct wlr_output_layout *layout, struct wlr_output *reference, const struct wlr_box *target_lbox) { + struct wlr_box out_box; + if (reference == NULL) { struct wlr_output_layout_output *l_output; wl_list_for_each(l_output, &layout->outputs, link) { struct wlr_box output_box; output_layout_output_get_box(l_output, &output_box); - if (wlr_box_intersects(&output_box, target_lbox)) { + if (wlr_box_intersection(&out_box, &output_box, target_lbox)) { return true; } } @@ -279,7 +281,7 @@ bool wlr_output_layout_intersects(struct wlr_output_layout *layout, struct wlr_box output_box; output_layout_output_get_box(l_output, &output_box); - return wlr_box_intersects(&output_box, target_lbox); + return wlr_box_intersection(&out_box, &output_box, target_lbox); } } diff --git a/types/wlr_pointer_warp_v1.c b/types/wlr_pointer_warp_v1.c deleted file mode 100644 index fc7393e7a..000000000 --- a/types/wlr_pointer_warp_v1.c +++ /dev/null @@ -1,103 +0,0 @@ -#include -#include -#include -#include -#include -#include "pointer-warp-v1-protocol.h" - -#define POINTER_WARP_VERSION 1 - -static const struct wp_pointer_warp_v1_interface pointer_warp_impl; - -static struct wlr_pointer_warp_v1 *pointer_warp_from_resource( - struct wl_resource *resource) { - assert(wl_resource_instance_of(resource, &wp_pointer_warp_v1_interface, - &pointer_warp_impl)); - return wl_resource_get_user_data(resource); -} - -static void resource_destroy(struct wl_client *client, - struct wl_resource *resource) { - wl_resource_destroy(resource); -} - -static void pointer_warp_handle_warp_pointer(struct wl_client *client, - struct wl_resource *resource, struct wl_resource *surface_resource, - struct wl_resource *pointer_resource, wl_fixed_t sx, wl_fixed_t sy, - uint32_t serial) { - struct wlr_pointer_warp_v1 *pointer_warp = - pointer_warp_from_resource(resource); - struct wlr_surface *surface = wlr_surface_from_resource(surface_resource); - struct wlr_seat_client *seat_client = - wlr_seat_client_from_pointer_resource(pointer_resource); - if (seat_client == NULL) { - return; - } - - struct wlr_pointer_warp_v1_event_warp event = { - .surface = surface, - .seat_client = seat_client, - .x = wl_fixed_to_double(sx), - .y = wl_fixed_to_double(sy), - .serial = serial, - }; - - wl_signal_emit_mutable(&pointer_warp->events.warp, &event); -} - -static const struct wp_pointer_warp_v1_interface pointer_warp_impl = { - .destroy = resource_destroy, - .warp_pointer = pointer_warp_handle_warp_pointer, -}; - -static void pointer_warp_bind(struct wl_client *client, void *data, - uint32_t version, uint32_t id) { - struct wlr_pointer_warp_v1 *pointer_warp = data; - struct wl_resource *resource = wl_resource_create(client, - &wp_pointer_warp_v1_interface, version, id); - if (resource == NULL) { - wl_client_post_no_memory(client); - return; - } - - wl_resource_set_implementation(resource, &pointer_warp_impl, pointer_warp, NULL); -} - -static void handle_display_destroy(struct wl_listener *listener, void *data) { - struct wlr_pointer_warp_v1 *pointer_warp = - wl_container_of(listener, pointer_warp, display_destroy); - - wl_signal_emit_mutable(&pointer_warp->events.destroy, NULL); - - assert(wl_list_empty(&pointer_warp->events.destroy.listener_list)); - assert(wl_list_empty(&pointer_warp->events.warp.listener_list)); - - wl_list_remove(&pointer_warp->display_destroy.link); - wl_global_destroy(pointer_warp->global); - free(pointer_warp); -} - -struct wlr_pointer_warp_v1 *wlr_pointer_warp_v1_create(struct wl_display *display, - uint32_t version) { - assert(version <= POINTER_WARP_VERSION); - - struct wlr_pointer_warp_v1 *pointer_warp = calloc(1, sizeof(*pointer_warp)); - if (pointer_warp == NULL) { - return NULL; - } - - pointer_warp->global = wl_global_create(display, &wp_pointer_warp_v1_interface, - version, pointer_warp, pointer_warp_bind); - if (pointer_warp->global == NULL) { - free(pointer_warp); - return NULL; - } - - wl_signal_init(&pointer_warp->events.destroy); - wl_signal_init(&pointer_warp->events.warp); - - pointer_warp->display_destroy.notify = handle_display_destroy; - wl_display_add_destroy_listener(display, &pointer_warp->display_destroy); - - return pointer_warp; -} diff --git a/types/wlr_screencopy_v1.c b/types/wlr_screencopy_v1.c index 30287b79e..9916a604c 100644 --- a/types/wlr_screencopy_v1.c +++ b/types/wlr_screencopy_v1.c @@ -512,16 +512,6 @@ static void capture_output(struct wl_client *wl_client, return; } - struct wlr_screencopy_frame_v1 *existing; - wl_list_for_each(existing, &client->manager->frames, link) { - if (existing->client == client && existing->output == output) { - wl_resource_set_user_data(frame->resource, NULL); - zwlr_screencopy_frame_v1_send_failed(frame->resource); - free(frame); - return; - } - } - frame->client = client; client->ref++; diff --git a/types/wlr_virtual_keyboard_v1.c b/types/wlr_virtual_keyboard_v1.c index 3701f4d53..465b97dd3 100644 --- a/types/wlr_virtual_keyboard_v1.c +++ b/types/wlr_virtual_keyboard_v1.c @@ -44,19 +44,6 @@ static void virtual_keyboard_keymap(struct wl_client *client, return; } - if (!wl_keyboard_keymap_format_is_valid(format, 1)) { - wl_resource_post_error(resource, - ZWP_VIRTUAL_KEYBOARD_V1_ERROR_INVALID_KEYMAP_FORMAT, - "Invalid keymap format"); - return; - } - - if (format == WL_KEYBOARD_KEYMAP_FORMAT_NO_KEYMAP) { - keyboard->has_keymap = true; - close(fd); - return; - } - struct xkb_context *context = xkb_context_new(XKB_CONTEXT_NO_FLAGS); if (!context) { goto context_fail; diff --git a/types/wlr_xdg_decoration_v1.c b/types/wlr_xdg_decoration_v1.c index 7c9b88888..4194942a2 100644 --- a/types/wlr_xdg_decoration_v1.c +++ b/types/wlr_xdg_decoration_v1.c @@ -5,7 +5,7 @@ #include #include "xdg-decoration-unstable-v1-protocol.h" -#define DECORATION_MANAGER_VERSION 2 +#define DECORATION_MANAGER_VERSION 1 static const struct zxdg_toplevel_decoration_v1_interface toplevel_decoration_impl; @@ -171,9 +171,8 @@ static void decoration_manager_handle_get_toplevel_decoration( decoration_manager_from_resource(manager_resource); struct wlr_xdg_toplevel *toplevel = wlr_xdg_toplevel_from_resource(toplevel_resource); - uint32_t version = wl_resource_get_version(manager_resource); - if (version == 1 && wlr_surface_has_buffer(toplevel->base->surface)) { + if (wlr_surface_has_buffer(toplevel->base->surface)) { wl_resource_post_error(manager_resource, ZXDG_TOPLEVEL_DECORATION_V1_ERROR_UNCONFIGURED_BUFFER, "xdg_toplevel_decoration must not have a buffer at creation"); @@ -205,6 +204,7 @@ static void decoration_manager_handle_get_toplevel_decoration( return; } + uint32_t version = wl_resource_get_version(manager_resource); decoration->resource = wl_resource_create(client, &zxdg_toplevel_decoration_v1_interface, version, id); if (decoration->resource == NULL) { @@ -271,9 +271,7 @@ static void handle_display_destroy(struct wl_listener *listener, void *data) { } struct wlr_xdg_decoration_manager_v1 * - wlr_xdg_decoration_manager_v1_create(struct wl_display *display, - uint32_t version) { - assert(version <= DECORATION_MANAGER_VERSION); + wlr_xdg_decoration_manager_v1_create(struct wl_display *display) { struct wlr_xdg_decoration_manager_v1 *manager = calloc(1, sizeof(*manager)); if (manager == NULL) { return NULL; diff --git a/types/xdg_shell/wlr_xdg_surface.c b/types/xdg_shell/wlr_xdg_surface.c index 7b9c99150..8a252d2f8 100644 --- a/types/xdg_shell/wlr_xdg_surface.c +++ b/types/xdg_shell/wlr_xdg_surface.c @@ -320,7 +320,6 @@ static void xdg_surface_role_commit(struct wlr_surface *wlr_surface) { reset_xdg_surface_role_object(surface); reset_xdg_surface(surface); - assert(!surface->initialized); assert(!surface->initial_commit); surface->initial_commit = false; } else { diff --git a/util/box.c b/util/box.c index 62d405488..489c5ad2e 100644 --- a/util/box.c +++ b/util/box.c @@ -102,15 +102,6 @@ bool wlr_box_contains_box(const struct wlr_box *bigger, const struct wlr_box *sm smaller->y + smaller->height <= bigger->y + bigger->height; } -bool wlr_box_intersects(const struct wlr_box *a, const struct wlr_box *b) { - if (wlr_box_empty(a) || wlr_box_empty(b)) { - return false; - } - - return a->x < b->x + b->width && b->x < a->x + a->width && - a->y < b->y + b->height && b->y < a->y + a->height; -} - void wlr_box_transform(struct wlr_box *dest, const struct wlr_box *box, enum wl_output_transform transform, int width, int height) { struct wlr_box src = {0}; diff --git a/util/rect_union.c b/util/rect_union.c index f113fe43e..8cd26d761 100644 --- a/util/rect_union.c +++ b/util/rect_union.c @@ -1,15 +1,15 @@ #include #include "util/rect_union.h" -static void box_union(pixman_box32_t *dst, const pixman_box32_t *box) { - dst->x1 = dst->x1 < box->x1 ? dst->x1 : box->x1; - dst->y1 = dst->y1 < box->y1 ? dst->y1 : box->y1; - dst->x2 = dst->x2 > box->x2 ? dst->x2 : box->x2; - dst->y2 = dst->y2 > box->y2 ? dst->y2 : box->y2; +static void box_union(pixman_box32_t *dst, pixman_box32_t box) { + dst->x1 = dst->x1 < box.x1 ? dst->x1 : box.x1; + dst->y1 = dst->y1 < box.y1 ? dst->y1 : box.y1; + dst->x2 = dst->x2 > box.x2 ? dst->x2 : box.x2; + dst->y2 = dst->y2 > box.y2 ? dst->y2 : box.y2; } -static bool box_empty_or_invalid(const pixman_box32_t *box) { - return box->x1 >= box->x2 || box->y1 >= box->y2; +static bool box_empty_or_invalid(pixman_box32_t box) { + return box.x1 >= box.x2 || box.y1 >= box.y2; } void rect_union_init(struct rect_union *ru) { @@ -37,28 +37,20 @@ static void handle_alloc_failure(struct rect_union *ru) { wl_array_init(&ru->unsorted); } -void rect_union_add(struct rect_union *ru, const pixman_box32_t *box) { +void rect_union_add(struct rect_union *ru, pixman_box32_t box) { if (box_empty_or_invalid(box)) { return; } box_union(&ru->bounding_box, box); - if (ru->alloc_failure) { - return; - } - - int nrects = (int)(ru->unsorted.size / sizeof(pixman_box32_t)); - if (nrects >= 1024) { - handle_alloc_failure(ru); - return; - } - - pixman_box32_t *entry = wl_array_add(&ru->unsorted, sizeof(*entry)); - if (entry) { - *entry = *box; - } else { - handle_alloc_failure(ru); + if (!ru->alloc_failure) { + pixman_box32_t *entry = wl_array_add(&ru->unsorted, sizeof(*entry)); + if (entry) { + *entry = box; + } else { + handle_alloc_failure(ru); + } } } @@ -89,7 +81,7 @@ const pixman_region32_t *rect_union_evaluate(struct rect_union *ru) { return &ru->region; bounding_box: pixman_region32_fini(&ru->region); - if (box_empty_or_invalid(&ru->bounding_box)) { + if (box_empty_or_invalid(ru->bounding_box)) { pixman_region32_init(&ru->region); } else { pixman_region32_init_with_extents(&ru->region, &ru->bounding_box); diff --git a/xwayland/selection/dnd.c b/xwayland/selection/dnd.c index f80a55d4d..31e588baf 100644 --- a/xwayland/selection/dnd.c +++ b/xwayland/selection/dnd.c @@ -83,12 +83,7 @@ static void xwm_dnd_send_enter(struct wlr_xwm *xwm) { // data and must be retrieved with the DND_TYPE_LIST property data.data32[1] |= 1; - xcb_atom_t *targets = malloc(n * sizeof(targets[0])); - if (targets == NULL) { - wlr_log(WLR_ERROR, "Allocation failed"); - return; - } - + xcb_atom_t targets[n]; size_t i = 0; char **mime_type_ptr; wl_array_for_each(mime_type_ptr, mime_types) { @@ -104,8 +99,6 @@ static void xwm_dnd_send_enter(struct wlr_xwm *xwm) { XCB_ATOM_ATOM, 32, // format n, targets); - - free(targets); } xwm_dnd_send_event(xwm, xwm->atoms[DND_ENTER], &data); diff --git a/xwayland/selection/incoming.c b/xwayland/selection/incoming.c index 2e512e7db..85d7775cd 100644 --- a/xwayland/selection/incoming.c +++ b/xwayland/selection/incoming.c @@ -103,7 +103,7 @@ static int write_selection_property_to_wl_client(int fd, uint32_t mask, void *data) { struct wlr_xwm_selection_transfer *transfer = data; - const char *property = xcb_get_property_value(transfer->property_reply); + char *property = xcb_get_property_value(transfer->property_reply); int remainder = xcb_get_property_value_length(transfer->property_reply) - transfer->property_start; @@ -249,7 +249,7 @@ struct x11_data_source { static const struct wlr_data_source_impl data_source_impl; bool data_source_is_xwayland( - const struct wlr_data_source *wlr_source) { + struct wlr_data_source *wlr_source) { return wlr_source->impl == &data_source_impl; } @@ -292,7 +292,7 @@ static const struct wlr_primary_selection_source_impl primary_selection_source_impl; bool primary_selection_source_is_xwayland( - const struct wlr_primary_selection_source *wlr_source) { + struct wlr_primary_selection_source *wlr_source) { return wlr_source->impl == &primary_selection_source_impl; } @@ -343,9 +343,8 @@ static bool source_get_targets(struct wlr_xwm_selection *selection, return false; } - const xcb_atom_t *value = xcb_get_property_value(reply); - uint32_t value_len = xcb_get_property_value_length(reply) / sizeof(value); - for (uint32_t i = 0; i < value_len; i++) { + xcb_atom_t *value = xcb_get_property_value(reply); + for (uint32_t i = 0; i < reply->value_len; i++) { char *mime_type = NULL; if (value[i] == xwm->atoms[UTF8_STRING]) { diff --git a/xwayland/selection/outgoing.c b/xwayland/selection/outgoing.c index a58c92e3e..6216abbb4 100644 --- a/xwayland/selection/outgoing.c +++ b/xwayland/selection/outgoing.c @@ -336,11 +336,7 @@ static void xwm_selection_send_targets(struct wlr_xwm_selection *selection, } size_t n = 2 + mime_types->size / sizeof(char *); - xcb_atom_t *targets = malloc(n * sizeof(targets[0])); - if (targets == NULL) { - wlr_log(WLR_ERROR, "Allocation failure"); - return; - } + xcb_atom_t targets[n]; targets[0] = xwm->atoms[TIMESTAMP]; targets[1] = xwm->atoms[TARGETS]; @@ -360,8 +356,6 @@ static void xwm_selection_send_targets(struct wlr_xwm_selection *selection, 32, // format n, targets); - free(targets); - xwm_selection_send_notify(selection->xwm, req, true); } diff --git a/xwayland/xwm.c b/xwayland/xwm.c index 8cee2961e..e44a11743 100644 --- a/xwayland/xwm.c +++ b/xwayland/xwm.c @@ -630,7 +630,6 @@ static void xwayland_surface_destroy(struct wlr_xwayland_surface *xsurface) { wl_list_remove(&child->parent_link); wl_list_init(&child->parent_link); child->parent = NULL; - wl_signal_emit_mutable(&child->events.set_parent, NULL); } wl_list_remove(&xsurface->unpaired_link); @@ -660,7 +659,7 @@ static void read_surface_class(struct wlr_xwm *xwm, } size_t len = xcb_get_property_value_length(reply); - const char *class = xcb_get_property_value(reply); + char *class = xcb_get_property_value(reply); // Unpack two sequentially stored strings: instance, class size_t instance_len = strnlen(class, len); @@ -668,7 +667,6 @@ static void read_surface_class(struct wlr_xwm *xwm, if (len > 0 && instance_len < len) { surface->instance = strndup(class, instance_len); class += instance_len + 1; - len -= instance_len + 1; } else { surface->instance = NULL; } @@ -692,7 +690,7 @@ static void read_surface_startup_id(struct wlr_xwm *xwm, } size_t len = xcb_get_property_value_length(reply); - const char *startup_id = xcb_get_property_value(reply); + char *startup_id = xcb_get_property_value(reply); free(xsurface->startup_id); if (len > 0) { @@ -721,7 +719,7 @@ static void read_surface_opacity(struct wlr_xwm *xwm, return; } - const uint32_t *val = xcb_get_property_value(reply); + uint32_t *val = xcb_get_property_value(reply); xsurface->opacity = (double)*val / UINT32_MAX; wl_signal_emit_mutable(&xsurface->events.set_opacity, NULL); } @@ -736,7 +734,7 @@ static void read_surface_role(struct wlr_xwm *xwm, } size_t len = xcb_get_property_value_length(reply); - const char *role = xcb_get_property_value(reply); + char *role = xcb_get_property_value(reply); free(xsurface->role); if (len > 0) { @@ -808,12 +806,8 @@ static void read_surface_parent(struct wlr_xwm *xwm, } struct wlr_xwayland_surface *found_parent = NULL; - if (reply->type != XCB_ATOM_NONE) { - if (xcb_get_property_value_length(reply) != sizeof(xcb_window_t)) { - wlr_log(WLR_DEBUG, "Invalid WM_TRANSIENT_FOR property length"); - return; - } - const xcb_window_t *xid = xcb_get_property_value(reply); + xcb_window_t *xid = xcb_get_property_value(reply); + if (reply->type != XCB_ATOM_NONE && xid != NULL) { found_parent = lookup_surface(xwm, *xid); if (!has_parent(found_parent, xsurface)) { xsurface->parent = found_parent; @@ -843,9 +837,9 @@ static void read_surface_window_type(struct wlr_xwm *xwm, return; } - const xcb_atom_t *atoms = xcb_get_property_value(reply); - size_t atoms_len = xcb_get_property_value_length(reply) / sizeof(atoms[0]); - size_t atoms_size = sizeof(atoms[0]) * atoms_len; + xcb_atom_t *atoms = xcb_get_property_value(reply); + size_t atoms_len = reply->value_len; + size_t atoms_size = sizeof(xcb_atom_t) * atoms_len; free(xsurface->window_type); if (atoms_len > 0) { @@ -870,9 +864,9 @@ static void read_surface_protocols(struct wlr_xwm *xwm, return; } - const xcb_atom_t *atoms = xcb_get_property_value(reply); - size_t atoms_len = xcb_get_property_value_length(reply) / sizeof(atoms[0]); - size_t atoms_size = sizeof(atoms[0]) * atoms_len; + xcb_atom_t *atoms = xcb_get_property_value(reply); + size_t atoms_len = reply->value_len; + size_t atoms_size = sizeof(xcb_atom_t) * atoms_len; free(xsurface->protocols); if (atoms_len > 0) { @@ -899,7 +893,7 @@ static void read_surface_hints(struct wlr_xwm *xwm, } free(xsurface->hints); - if (xcb_get_property_value_length(reply) > 0) { + if (reply->value_len > 0) { xsurface->hints = calloc(1, sizeof(*xsurface->hints)); if (xsurface->hints == NULL) { return; @@ -929,7 +923,7 @@ static void read_surface_normal_hints(struct wlr_xwm *xwm, free(xsurface->size_hints); xsurface->size_hints = NULL; - if (xcb_get_property_value_length(reply) == 0) { + if (reply->value_len == 0) { return; } @@ -976,19 +970,18 @@ static void read_surface_normal_hints(struct wlr_xwm *xwm, static void read_surface_motif_hints(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { - if (xcb_get_property_value_length(reply) == 0) { + if (reply->value_len == 0) { xsurface->decorations = 0; wl_signal_emit_mutable(&xsurface->events.set_decorations, NULL); return; } - const uint32_t *motif_hints = xcb_get_property_value(reply); - int motif_hints_len = xcb_get_property_value_length(reply) / sizeof(motif_hints[0]); - if (motif_hints_len < 5) { + if (reply->value_len < 5) { wlr_log(WLR_DEBUG, "Invalid MOTIF_WM_HINTS property type"); return; } + uint32_t *motif_hints = xcb_get_property_value(reply); if (motif_hints[MWM_HINTS_FLAGS_FIELD] & MWM_HINTS_DECORATIONS) { xsurface->decorations = WLR_XWAYLAND_SURFACE_DECORATIONS_ALL; uint32_t decorations = motif_hints[MWM_HINTS_DECORATIONS_FIELD]; @@ -1036,32 +1029,31 @@ static void read_surface_net_wm_state(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface, xcb_get_property_reply_t *reply) { xsurface->fullscreen = 0; - const xcb_atom_t *atoms = xcb_get_property_value(reply); - uint32_t atoms_len = xcb_get_property_value_length(reply) / sizeof(atoms[0]); - for (uint32_t i = 0; i < atoms_len; i++) { - if (atoms[i] == xwm->atoms[NET_WM_STATE_MODAL]) { + xcb_atom_t *atom = xcb_get_property_value(reply); + for (uint32_t i = 0; i < reply->value_len; i++) { + if (atom[i] == xwm->atoms[NET_WM_STATE_MODAL]) { xsurface->modal = true; - } else if (atoms[i] == xwm->atoms[NET_WM_STATE_FULLSCREEN]) { + } else if (atom[i] == xwm->atoms[NET_WM_STATE_FULLSCREEN]) { xsurface->fullscreen = true; - } else if (atoms[i] == xwm->atoms[NET_WM_STATE_MAXIMIZED_VERT]) { + } else if (atom[i] == xwm->atoms[NET_WM_STATE_MAXIMIZED_VERT]) { xsurface->maximized_vert = true; - } else if (atoms[i] == xwm->atoms[NET_WM_STATE_MAXIMIZED_HORZ]) { + } else if (atom[i] == xwm->atoms[NET_WM_STATE_MAXIMIZED_HORZ]) { xsurface->maximized_horz = true; - } else if (atoms[i] == xwm->atoms[NET_WM_STATE_HIDDEN]) { + } else if (atom[i] == xwm->atoms[NET_WM_STATE_HIDDEN]) { xsurface->minimized = true; - } else if (atoms[i] == xwm->atoms[NET_WM_STATE_STICKY]) { + } else if (atom[i] == xwm->atoms[NET_WM_STATE_STICKY]) { xsurface->sticky = true; - } else if (atoms[i] == xwm->atoms[NET_WM_STATE_SHADED]) { + } else if (atom[i] == xwm->atoms[NET_WM_STATE_SHADED]) { xsurface->shaded = true; - } else if (atoms[i] == xwm->atoms[NET_WM_STATE_SKIP_TASKBAR]) { + } else if (atom[i] == xwm->atoms[NET_WM_STATE_SKIP_TASKBAR]) { xsurface->skip_taskbar = true; - } else if (atoms[i] == xwm->atoms[NET_WM_STATE_SKIP_PAGER]) { + } else if (atom[i] == xwm->atoms[NET_WM_STATE_SKIP_PAGER]) { xsurface->skip_pager = true; - } else if (atoms[i] == xwm->atoms[NET_WM_STATE_ABOVE]) { + } else if (atom[i] == xwm->atoms[NET_WM_STATE_ABOVE]) { xsurface->above = true; - } else if (atoms[i] == xwm->atoms[NET_WM_STATE_BELOW]) { + } else if (atom[i] == xwm->atoms[NET_WM_STATE_BELOW]) { xsurface->below = true; - } else if (atoms[i] == xwm->atoms[NET_WM_STATE_DEMANDS_ATTENTION]) { + } else if (atom[i] == xwm->atoms[NET_WM_STATE_DEMANDS_ATTENTION]) { xsurface->demands_attention = true; } } @@ -1467,31 +1459,15 @@ static void xwm_handle_surface_id_message(struct wlr_xwm *xwm, struct wlr_xwayland_surface *xsurface = lookup_surface(xwm, ev->window); if (xsurface == NULL) { wlr_log(WLR_DEBUG, - "Received client message WL_SURFACE_ID but no X11 window %u", + "client message WL_SURFACE_ID but no new window %u ?", ev->window); return; } - if (xsurface->surface != NULL) { - wlr_log(WLR_DEBUG, "Received multiple client messages WL_SURFACE_ID " - "for an already-associated X11 window %u", ev->window); - return; - } - + /* Check if we got notified after wayland surface create event */ uint32_t id = ev->data.data32[0]; - - // Because the X11 and Wayland connections are separate sockets, the - // WL_SURFACE_ID and wl_compositor.create_surface messages may be received - // in any order. struct wl_resource *resource = wl_client_get_object(xwm->xwayland->server->client, id); if (resource) { - if (wl_resource_get_interface(resource) != &wl_surface_interface) { - wlr_log(WLR_DEBUG, "Received client message WL_SURFACE_ID " - "for X11 window %u but Wayland object is not a wl_surface", - ev->window); - return; - } - struct wlr_surface *surface = wlr_surface_from_resource(resource); xwayland_surface_associate(xwm, xsurface, surface); } else { @@ -2795,22 +2771,6 @@ bool xwm_atoms_contains(struct wlr_xwm *xwm, xcb_atom_t *atoms, } void wlr_xwayland_surface_ping(struct wlr_xwayland_surface *surface) { - if (surface->pinging) { - return; - } - - // don't ping if client not supports - bool supports_ping = false; - for(size_t i = 0; i < surface->protocols_len; i++) { - if (surface->protocols[i] == surface->xwm->atoms[NET_WM_PING]) { - supports_ping = true; - break; - } - } - if (!supports_ping) { - return; - } - xcb_client_message_data_t data = { 0 }; data.data32[0] = surface->xwm->atoms[NET_WM_PING]; data.data32[1] = XCB_CURRENT_TIME;