Compare commits

...

18 commits

Author SHA1 Message Date
Simon Ser
910fd264fb build: bump version to 0.20.0-rc2 2026-02-12 22:47:22 +01:00
Aleksei Bavshin
3676ab4df0
backend/libinput: add support for LIBINPUT_SWITCH_KEYPAD_SLIDE 2026-02-08 11:01:06 -08:00
Aleksei Bavshin
c1452d8811
backend/libinput: fix build with libinput 1.31 2026-02-08 10:56:16 -08:00
Steve Williams
436bcf9a47 color-representation-v1: fix condition in surface commit 2026-02-07 08:36:29 +04:00
Steve Williams
ef88246642 types/wlr_buffer: add buffer_get_drm_format helper function 2026-02-06 13:53:46 +00:00
Steve Williams
bb78861ca9 color-representation: add support for identity+full 2026-02-06 13:53:46 +00:00
Steve Williams
439985fe95 color_representation: ensure encoding/range/drm formats compatibility 2026-02-06 13:53:46 +00:00
Steve Williams
4c81cb1b9e vulkan: make use of new pixel_format_is_ycbcr function 2026-02-06 13:53:46 +00:00
Steve Williams
19d6829601 render/pixel-format: add function to determine YCbCr from drm fourcc 2026-02-06 13:53:46 +00:00
YaoBing Xiao
dfccf5ff02 output/cursor: fix missing newline at end of file 2026-02-06 09:05:52 +00:00
rewine
bc11ac92ab
ext_image_capture_source_v1: remove unused variable 2026-02-06 10:41:42 +08:00
YaoBing Xiao
d362ed1eb9 xwayland: fix wl_array rollback when adding selection targets
Ensure mime_types and mime_types_atoms remain in sync when
wl_array_add() fails. Roll back the partially added entry and
free the allocated mime type to avoid leaks and inconsistent
state.
2026-02-05 09:26:55 +08:00
Simon Ser
90f9f59041 xwayland: try flushing immediately in xwm_schedule_flush()
wl_event_source_fd_update() goes through another event loop cycle, which
delays writes. This extra cycle was introduced in 6ada67da9b
("xwayland/xwm: implement somewhat asynchronous request flushing").

Try flushing the X11 WM FD immediately if we can.

References: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/4044
2026-02-04 00:14:49 +01:00
rewine
7cb4e30bfd
wlr_cursor: fix event type in handle_tablet_tool_button 2026-02-03 21:25:50 +08:00
rewine
98196bbd89
wlr_cursor: add comments for signal parameters 2026-02-03 21:24:32 +08:00
rewine
4fe51aa439 types: Simplify wlr_keyboard_group_destroy
If the wlr_keyboard_group_remove_keyboard function is expanded, the code
is equivalent to:

```
	wl_list_for_each_safe(device, tmp_device, &group->devices, link) {
		struct wlr_keyboard_group *_group = group;
		struct wlr_keyboard *_keyboard = device->keyboard;
		struct keyboard_group_device *_device, *_tmp;
		wl_list_for_each_safe(_device, _tmp, &_group->devices, link) {
			if (_device->keyboard == _keyboard) {
				remove_keyboard_group_device(_device);
				continue;
			}
		}
	}
```

It's just running one more loop meaninglessly.
2026-02-02 10:46:20 -05:00
liupeng
12c9502edf render/drm_syncobj: fix function name in drmSyncobjTimelineWait() error log
Signed-off-by: liupeng <liupeng01@kylinos.cn>
2026-02-02 09:12:39 +08:00
liupeng
7f87e258b2 render/drm_syncobj: drop unnecessary drmSyncobjTimelineWait() arg
Signed-off-by: liupeng <liupeng01@kylinos.cn>
2026-02-02 09:11:41 +08:00
24 changed files with 224 additions and 77 deletions

View file

@ -29,3 +29,7 @@ features += { 'libinput-backend': true }
wlr_deps += libinput wlr_deps += libinput
internal_config.set10('HAVE_LIBINPUT_BUSTYPE', libinput.version().version_compare('>=1.26.0')) internal_config.set10('HAVE_LIBINPUT_BUSTYPE', libinput.version().version_compare('>=1.26.0'))
internal_config.set10(
'HAVE_LIBINPUT_SWITCH_KEYPAD_SLIDE',
libinput.version().version_compare('>=1.30.901')
)

View file

@ -2,6 +2,7 @@
#include <libinput.h> #include <libinput.h>
#include <wlr/interfaces/wlr_switch.h> #include <wlr/interfaces/wlr_switch.h>
#include "backend/libinput.h" #include "backend/libinput.h"
#include "config.h"
const struct wlr_switch_impl libinput_switch_impl = { const struct wlr_switch_impl libinput_switch_impl = {
.name = "libinput-switch", .name = "libinput-switch",
@ -36,6 +37,11 @@ void handle_switch_toggle(struct libinput_event *event,
case LIBINPUT_SWITCH_TABLET_MODE: case LIBINPUT_SWITCH_TABLET_MODE:
wlr_event.switch_type = WLR_SWITCH_TYPE_TABLET_MODE; wlr_event.switch_type = WLR_SWITCH_TYPE_TABLET_MODE;
break; break;
#if HAVE_LIBINPUT_SWITCH_KEYPAD_SLIDE
case LIBINPUT_SWITCH_KEYPAD_SLIDE:
wlr_event.switch_type = WLR_SWITCH_TYPE_KEYPAD_SLIDE;
break;
#endif
} }
switch (libinput_event_switch_get_switch_state(sevent)) { switch (libinput_event_switch_get_switch_state(sevent)) {
case LIBINPUT_SWITCH_STATE_OFF: case LIBINPUT_SWITCH_STATE_OFF:

View file

@ -20,6 +20,7 @@
#include "backend/x11.h" #include "backend/x11.h"
#include "util/time.h" #include "util/time.h"
#include "types/wlr_buffer.h"
#include "types/wlr_output.h" #include "types/wlr_output.h"
static const uint32_t SUPPORTED_OUTPUT_STATE = static const uint32_t SUPPORTED_OUTPUT_STATE =
@ -166,15 +167,8 @@ static bool output_test(struct wlr_output *wlr_output,
if (state->committed & WLR_OUTPUT_STATE_BUFFER) { if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
struct wlr_buffer *buffer = state->buffer; struct wlr_buffer *buffer = state->buffer;
struct wlr_dmabuf_attributes dmabuf_attrs;
struct wlr_shm_attributes shm_attrs; if (buffer_get_drm_format(buffer) != x11->x11_format->drm) {
uint32_t format = DRM_FORMAT_INVALID;
if (wlr_buffer_get_dmabuf(buffer, &dmabuf_attrs)) {
format = dmabuf_attrs.format;
} else if (wlr_buffer_get_shm(buffer, &shm_attrs)) {
format = shm_attrs.format;
}
if (format != x11->x11_format->drm) {
wlr_log(WLR_DEBUG, "Unsupported buffer format"); wlr_log(WLR_DEBUG, "Unsupported buffer format");
return false; return false;
} }

View file

@ -63,4 +63,9 @@ enum wl_shm_format convert_drm_format_to_wl_shm(uint32_t fmt);
*/ */
bool pixel_format_has_alpha(uint32_t fmt); bool pixel_format_has_alpha(uint32_t fmt);
/**
* Return true if the DRM FourCC fmt belongs to a YCbCr colorspace family, false otherwise.
*/
bool pixel_format_is_ycbcr(uint32_t fmt);
#endif #endif

View file

@ -86,7 +86,6 @@ struct wlr_vk_format {
uint32_t drm; uint32_t drm;
VkFormat vk; VkFormat vk;
VkFormat vk_srgb; // sRGB version of the format, or 0 if nonexistent VkFormat vk_srgb; // sRGB version of the format, or 0 if nonexistent
bool is_ycbcr;
}; };
extern const VkImageUsageFlags vulkan_render_usage, vulkan_shm_tex_usage, vulkan_dma_tex_usage; extern const VkImageUsageFlags vulkan_render_usage, vulkan_shm_tex_usage, vulkan_dma_tex_usage;
@ -125,6 +124,7 @@ void vulkan_format_props_query(struct wlr_vk_device *dev,
const struct wlr_vk_format_modifier_props *vulkan_format_props_find_modifier( const struct wlr_vk_format_modifier_props *vulkan_format_props_find_modifier(
const struct wlr_vk_format_props *props, uint64_t mod, bool render); const struct wlr_vk_format_props *props, uint64_t mod, bool render);
void vulkan_format_props_finish(struct wlr_vk_format_props *props); void vulkan_format_props_finish(struct wlr_vk_format_props *props);
bool vulkan_format_is_ycbcr(const struct wlr_vk_format *format);
struct wlr_vk_pipeline_layout_key { struct wlr_vk_pipeline_layout_key {
enum wlr_scale_filter_mode filter_mode; enum wlr_scale_filter_mode filter_mode;

View file

@ -65,4 +65,10 @@ struct wlr_client_buffer *wlr_client_buffer_create(struct wlr_buffer *buffer,
bool wlr_client_buffer_apply_damage(struct wlr_client_buffer *client_buffer, bool wlr_client_buffer_apply_damage(struct wlr_client_buffer *client_buffer,
struct wlr_buffer *next, const pixman_region32_t *damage); struct wlr_buffer *next, const pixman_region32_t *damage);
/**
* Return the DRM format of the buffer. If this buffer isn't shared
* memory or a DMA-BUF, returns DRM_FORMAT_INVALID.
*/
uint32_t buffer_get_drm_format(struct wlr_buffer *buffer);
#endif #endif

View file

@ -49,30 +49,30 @@ struct wlr_cursor {
* your responsibility. * your responsibility.
*/ */
struct { struct {
struct wl_signal motion; struct wl_signal motion; // struct wlr_pointer_motion_event
struct wl_signal motion_absolute; struct wl_signal motion_absolute; // struct wlr_pointer_motion_absolute_event
struct wl_signal button; struct wl_signal button; // struct wlr_pointer_button_event
struct wl_signal axis; struct wl_signal axis; // struct wlr_pointer_axis_event
struct wl_signal frame; struct wl_signal frame;
struct wl_signal swipe_begin; struct wl_signal swipe_begin; // struct wlr_pointer_swipe_begin_event
struct wl_signal swipe_update; struct wl_signal swipe_update; // struct wlr_pointer_swipe_update_event
struct wl_signal swipe_end; struct wl_signal swipe_end; // struct wlr_pointer_swipe_end_event
struct wl_signal pinch_begin; struct wl_signal pinch_begin; // struct wlr_pointer_pinch_begin_event
struct wl_signal pinch_update; struct wl_signal pinch_update; // struct wlr_pointer_pinch_update_event
struct wl_signal pinch_end; struct wl_signal pinch_end; // struct wlr_pointer_pinch_end_event
struct wl_signal hold_begin; struct wl_signal hold_begin; // struct wlr_pointer_hold_begin_event
struct wl_signal hold_end; struct wl_signal hold_end; // struct wlr_pointer_hold_end_event
struct wl_signal touch_up; struct wl_signal touch_up; // struct wlr_touch_up_event
struct wl_signal touch_down; struct wl_signal touch_down; // struct wlr_touch_down_event
struct wl_signal touch_motion; struct wl_signal touch_motion; // struct wlr_touch_motion_event
struct wl_signal touch_cancel; struct wl_signal touch_cancel; // struct wlr_touch_cancel_event
struct wl_signal touch_frame; struct wl_signal touch_frame;
struct wl_signal tablet_tool_axis; struct wl_signal tablet_tool_axis; // struct wlr_tablet_tool_axis_event
struct wl_signal tablet_tool_proximity; struct wl_signal tablet_tool_proximity; // struct wlr_tablet_tool_proximity_event
struct wl_signal tablet_tool_tip; struct wl_signal tablet_tool_tip; // struct wlr_tablet_tool_tip_event
struct wl_signal tablet_tool_button; struct wl_signal tablet_tool_button; // struct wlr_tablet_tool_button_event
} events; } events;
void *data; void *data;

View file

@ -36,6 +36,7 @@ struct wlr_switch {
enum wlr_switch_type { enum wlr_switch_type {
WLR_SWITCH_TYPE_LID, WLR_SWITCH_TYPE_LID,
WLR_SWITCH_TYPE_TABLET_MODE, WLR_SWITCH_TYPE_TABLET_MODE,
WLR_SWITCH_TYPE_KEYPAD_SLIDE,
}; };
enum wlr_switch_state { enum wlr_switch_state {

View file

@ -1,7 +1,7 @@
project( project(
'wlroots', 'wlroots',
'c', 'c',
version: '0.20.0-rc1', version: '0.20.0-rc2',
license: 'MIT', license: 'MIT',
meson_version: '>=1.3', meson_version: '>=1.3',
default_options: [ default_options: [

View file

@ -167,10 +167,9 @@ bool wlr_drm_syncobj_timeline_check(struct wlr_drm_syncobj_timeline *timeline,
etime = ETIME; etime = ETIME;
#endif #endif
uint32_t signaled_point; int ret = drmSyncobjTimelineWait(timeline->drm_fd, &timeline->handle, &point, 1, 0, flags, NULL);
int ret = drmSyncobjTimelineWait(timeline->drm_fd, &timeline->handle, &point, 1, 0, flags, &signaled_point);
if (ret != 0 && ret != -etime) { if (ret != 0 && ret != -etime) {
wlr_log_errno(WLR_ERROR, "drmSyncobjWait() failed"); wlr_log_errno(WLR_ERROR, "drmSyncobjTimelineWait() failed");
return false; return false;
} }

View file

@ -307,3 +307,68 @@ bool pixel_format_has_alpha(uint32_t fmt) {
} }
return true; return true;
} }
bool pixel_format_is_ycbcr(uint32_t format) {
switch (format) {
case DRM_FORMAT_AYUV:
case DRM_FORMAT_NV12:
case DRM_FORMAT_NV15:
case DRM_FORMAT_NV16:
case DRM_FORMAT_NV20:
case DRM_FORMAT_NV21:
case DRM_FORMAT_NV24:
case DRM_FORMAT_NV30:
case DRM_FORMAT_NV42:
case DRM_FORMAT_NV61:
case DRM_FORMAT_P010:
case DRM_FORMAT_P012:
case DRM_FORMAT_P016:
case DRM_FORMAT_P030:
case DRM_FORMAT_P210:
case DRM_FORMAT_Q401:
case DRM_FORMAT_Q410:
case DRM_FORMAT_S010:
case DRM_FORMAT_S012:
case DRM_FORMAT_S016:
case DRM_FORMAT_S210:
case DRM_FORMAT_S212:
case DRM_FORMAT_S216:
case DRM_FORMAT_S410:
case DRM_FORMAT_S412:
case DRM_FORMAT_S416:
case DRM_FORMAT_UYVY:
case DRM_FORMAT_VUY101010:
case DRM_FORMAT_VUY888:
case DRM_FORMAT_VYUY:
case DRM_FORMAT_X0L0:
case DRM_FORMAT_X0L2:
case DRM_FORMAT_XVYU12_16161616:
case DRM_FORMAT_XVYU16161616:
case DRM_FORMAT_XVYU2101010:
case DRM_FORMAT_XYUV8888:
case DRM_FORMAT_Y0L0:
case DRM_FORMAT_Y0L2:
case DRM_FORMAT_Y210:
case DRM_FORMAT_Y212:
case DRM_FORMAT_Y216:
case DRM_FORMAT_Y410:
case DRM_FORMAT_Y412:
case DRM_FORMAT_Y416:
case DRM_FORMAT_YUV410:
case DRM_FORMAT_YUV411:
case DRM_FORMAT_YUV420:
case DRM_FORMAT_YUV420_10BIT:
case DRM_FORMAT_YUV420_8BIT:
case DRM_FORMAT_YUV422:
case DRM_FORMAT_YUV444:
case DRM_FORMAT_YUYV:
case DRM_FORMAT_YVU410:
case DRM_FORMAT_YVU411:
case DRM_FORMAT_YVU420:
case DRM_FORMAT_YVU422:
case DRM_FORMAT_YVU444:
case DRM_FORMAT_YVYU:
return true;
}
return false;
}

View file

@ -822,12 +822,13 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
} }
enum wlr_color_encoding color_encoding = options->color_encoding; enum wlr_color_encoding color_encoding = options->color_encoding;
if (texture->format->is_ycbcr && color_encoding == WLR_COLOR_ENCODING_NONE) { bool is_ycbcr = vulkan_format_is_ycbcr(texture->format);
if (is_ycbcr && color_encoding == WLR_COLOR_ENCODING_NONE) {
color_encoding = WLR_COLOR_ENCODING_BT601; color_encoding = WLR_COLOR_ENCODING_BT601;
} }
enum wlr_color_range color_range = options->color_range; enum wlr_color_range color_range = options->color_range;
if (texture->format->is_ycbcr && color_range == WLR_COLOR_RANGE_NONE) { if (is_ycbcr && color_range == WLR_COLOR_RANGE_NONE) {
color_range = WLR_COLOR_RANGE_LIMITED; color_range = WLR_COLOR_RANGE_LIMITED;
} }
@ -837,7 +838,7 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
.source = WLR_VK_SHADER_SOURCE_TEXTURE, .source = WLR_VK_SHADER_SOURCE_TEXTURE,
.layout = { .layout = {
.ycbcr = { .ycbcr = {
.format = texture->format->is_ycbcr ? texture->format : NULL, .format = is_ycbcr ? texture->format : NULL,
.encoding = color_encoding, .encoding = color_encoding,
.range = color_range, .range = color_range,
}, },

View file

@ -182,37 +182,30 @@ static const struct wlr_vk_format formats[] = {
{ {
.drm = DRM_FORMAT_UYVY, .drm = DRM_FORMAT_UYVY,
.vk = VK_FORMAT_B8G8R8G8_422_UNORM, .vk = VK_FORMAT_B8G8R8G8_422_UNORM,
.is_ycbcr = true,
}, },
{ {
.drm = DRM_FORMAT_YUYV, .drm = DRM_FORMAT_YUYV,
.vk = VK_FORMAT_G8B8G8R8_422_UNORM, .vk = VK_FORMAT_G8B8G8R8_422_UNORM,
.is_ycbcr = true,
}, },
{ {
.drm = DRM_FORMAT_NV12, .drm = DRM_FORMAT_NV12,
.vk = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM, .vk = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
.is_ycbcr = true,
}, },
{ {
.drm = DRM_FORMAT_NV16, .drm = DRM_FORMAT_NV16,
.vk = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM, .vk = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
.is_ycbcr = true,
}, },
{ {
.drm = DRM_FORMAT_YUV420, .drm = DRM_FORMAT_YUV420,
.vk = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM, .vk = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
.is_ycbcr = true,
}, },
{ {
.drm = DRM_FORMAT_YUV422, .drm = DRM_FORMAT_YUV422,
.vk = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM, .vk = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
.is_ycbcr = true,
}, },
{ {
.drm = DRM_FORMAT_YUV444, .drm = DRM_FORMAT_YUV444,
.vk = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM, .vk = VK_FORMAT_G8_B8_R8_3PLANE_444_UNORM,
.is_ycbcr = true,
}, },
// 3PACK16 formats split the memory in three 16-bit words, so they have an // 3PACK16 formats split the memory in three 16-bit words, so they have an
// inverted channel order compared to DRM formats. // inverted channel order compared to DRM formats.
@ -220,27 +213,22 @@ static const struct wlr_vk_format formats[] = {
{ {
.drm = DRM_FORMAT_P010, .drm = DRM_FORMAT_P010,
.vk = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16, .vk = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
.is_ycbcr = true,
}, },
{ {
.drm = DRM_FORMAT_P210, .drm = DRM_FORMAT_P210,
.vk = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16, .vk = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
.is_ycbcr = true,
}, },
{ {
.drm = DRM_FORMAT_P012, .drm = DRM_FORMAT_P012,
.vk = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16, .vk = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
.is_ycbcr = true,
}, },
{ {
.drm = DRM_FORMAT_P016, .drm = DRM_FORMAT_P016,
.vk = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM, .vk = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
.is_ycbcr = true,
}, },
{ {
.drm = DRM_FORMAT_Q410, .drm = DRM_FORMAT_Q410,
.vk = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16, .vk = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
.is_ycbcr = true,
}, },
#endif #endif
// TODO: add DRM_FORMAT_NV24/VK_FORMAT_G8_B8R8_2PLANE_444_UNORM (requires // TODO: add DRM_FORMAT_NV24/VK_FORMAT_G8_B8R8_2PLANE_444_UNORM (requires
@ -446,7 +434,7 @@ static bool query_modifier_support(struct wlr_vk_device *dev,
// check that specific modifier for render usage // check that specific modifier for render usage
const char *errmsg = "unknown error"; const char *errmsg = "unknown error";
if ((m.drmFormatModifierTilingFeatures & render_features) == render_features && if ((m.drmFormatModifierTilingFeatures & render_features) == render_features &&
!props->format.is_ycbcr) { !vulkan_format_is_ycbcr(&props->format)) {
struct wlr_vk_format_modifier_props p = {0}; struct wlr_vk_format_modifier_props p = {0};
bool supported = false; bool supported = false;
if (query_modifier_usage_support(dev, props->format.vk, if (query_modifier_usage_support(dev, props->format.vk,
@ -477,7 +465,7 @@ static bool query_modifier_support(struct wlr_vk_device *dev,
// check that specific modifier for texture usage // check that specific modifier for texture usage
errmsg = "unknown error"; errmsg = "unknown error";
VkFormatFeatureFlags features = dma_tex_features; VkFormatFeatureFlags features = dma_tex_features;
if (props->format.is_ycbcr) { if (vulkan_format_is_ycbcr(&props->format)) {
features |= ycbcr_tex_features; features |= ycbcr_tex_features;
} }
if ((m.drmFormatModifierTilingFeatures & features) == features) { if ((m.drmFormatModifierTilingFeatures & features) == features) {
@ -522,7 +510,7 @@ static bool query_modifier_support(struct wlr_vk_device *dev,
void vulkan_format_props_query(struct wlr_vk_device *dev, void vulkan_format_props_query(struct wlr_vk_device *dev,
const struct wlr_vk_format *format) { const struct wlr_vk_format *format) {
if (format->is_ycbcr && !dev->sampler_ycbcr_conversion) { if (vulkan_format_is_ycbcr(format) && !dev->sampler_ycbcr_conversion) {
return; return;
} }
@ -551,7 +539,7 @@ void vulkan_format_props_query(struct wlr_vk_device *dev,
char shm_texture_status[256]; char shm_texture_status[256];
const char *errmsg = "unknown error"; const char *errmsg = "unknown error";
if ((fmtp.formatProperties.optimalTilingFeatures & shm_tex_features) == shm_tex_features && if ((fmtp.formatProperties.optimalTilingFeatures & shm_tex_features) == shm_tex_features &&
!format->is_ycbcr && format_info != NULL) { !vulkan_format_is_ycbcr(format) && format_info != NULL) {
VkImageFormatProperties ifmtp; VkImageFormatProperties ifmtp;
bool supported = false, has_mutable_srgb = false; bool supported = false, has_mutable_srgb = false;
if (query_shm_support(dev, format->vk, format->vk_srgb, &ifmtp, &errmsg)) { if (query_shm_support(dev, format->vk, format->vk_srgb, &ifmtp, &errmsg)) {
@ -621,3 +609,7 @@ const struct wlr_vk_format_modifier_props *vulkan_format_props_find_modifier(
} }
return NULL; return NULL;
} }
bool vulkan_format_is_ycbcr(const struct wlr_vk_format *format) {
return pixel_format_is_ycbcr(format->drm);
}

View file

@ -1630,8 +1630,8 @@ static bool init_blend_to_output_layouts(struct wlr_vk_renderer *renderer) {
static bool pipeline_layout_key_equals( static bool pipeline_layout_key_equals(
const struct wlr_vk_pipeline_layout_key *a, const struct wlr_vk_pipeline_layout_key *a,
const struct wlr_vk_pipeline_layout_key *b) { const struct wlr_vk_pipeline_layout_key *b) {
assert(!a->ycbcr.format || a->ycbcr.format->is_ycbcr); assert(!a->ycbcr.format || vulkan_format_is_ycbcr(a->ycbcr.format));
assert(!b->ycbcr.format || b->ycbcr.format->is_ycbcr); assert(!b->ycbcr.format || vulkan_format_is_ycbcr(b->ycbcr.format));
if (a->filter_mode != b->filter_mode) { if (a->filter_mode != b->filter_mode) {
return false; return false;
@ -2039,8 +2039,8 @@ struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout(
}; };
sampler_create_info.pNext = &conversion_info; sampler_create_info.pNext = &conversion_info;
} else { } else {
assert(key->ycbcr.encoding == WLR_COLOR_ENCODING_NONE); assert(key->ycbcr.encoding == WLR_COLOR_ENCODING_NONE || key->ycbcr.encoding == WLR_COLOR_ENCODING_IDENTITY);
assert(key->ycbcr.range == WLR_COLOR_RANGE_NONE); assert(key->ycbcr.range == WLR_COLOR_RANGE_NONE || key->ycbcr.range == WLR_COLOR_RANGE_FULL);
} }
res = vkCreateSampler(renderer->dev->dev, &sampler_create_info, NULL, &pipeline_layout->sampler); res = vkCreateSampler(renderer->dev->dev, &sampler_create_info, NULL, &pipeline_layout->sampler);

View file

@ -297,7 +297,7 @@ struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(struct wlr_vk_text
.components.r = VK_COMPONENT_SWIZZLE_IDENTITY, .components.r = VK_COMPONENT_SWIZZLE_IDENTITY,
.components.g = VK_COMPONENT_SWIZZLE_IDENTITY, .components.g = VK_COMPONENT_SWIZZLE_IDENTITY,
.components.b = VK_COMPONENT_SWIZZLE_IDENTITY, .components.b = VK_COMPONENT_SWIZZLE_IDENTITY,
.components.a = texture->has_alpha || texture->format->is_ycbcr .components.a = texture->has_alpha || vulkan_format_is_ycbcr(texture->format)
? VK_COMPONENT_SWIZZLE_IDENTITY ? VK_COMPONENT_SWIZZLE_IDENTITY
: VK_COMPONENT_SWIZZLE_ONE, : VK_COMPONENT_SWIZZLE_ONE,
.subresourceRange = (VkImageSubresourceRange){ .subresourceRange = (VkImageSubresourceRange){
@ -311,7 +311,7 @@ struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(struct wlr_vk_text
}; };
VkSamplerYcbcrConversionInfo ycbcr_conversion_info; VkSamplerYcbcrConversionInfo ycbcr_conversion_info;
if (texture->format->is_ycbcr) { if (vulkan_format_is_ycbcr(texture->format)) {
assert(pipeline_layout->ycbcr.conversion != VK_NULL_HANDLE); assert(pipeline_layout->ycbcr.conversion != VK_NULL_HANDLE);
ycbcr_conversion_info = (VkSamplerYcbcrConversionInfo){ ycbcr_conversion_info = (VkSamplerYcbcrConversionInfo){
.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, .sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
@ -355,7 +355,7 @@ struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(struct wlr_vk_text
static void texture_set_format(struct wlr_vk_texture *texture, static void texture_set_format(struct wlr_vk_texture *texture,
const struct wlr_vk_format *format, bool has_mutable_srgb) { const struct wlr_vk_format *format, bool has_mutable_srgb) {
assert(!(format->is_ycbcr && has_mutable_srgb)); assert(!(vulkan_format_is_ycbcr(format) && has_mutable_srgb));
texture->format = format; texture->format = format;
texture->using_mutable_srgb = has_mutable_srgb; texture->using_mutable_srgb = has_mutable_srgb;
@ -366,7 +366,7 @@ static void texture_set_format(struct wlr_vk_texture *texture,
texture->has_alpha = pixel_format_has_alpha(format->drm); texture->has_alpha = pixel_format_has_alpha(format->drm);
} else { } else {
// We don't have format info for multi-planar formats // We don't have format info for multi-planar formats
assert(texture->format->is_ycbcr); assert(vulkan_format_is_ycbcr(texture->format));
} }
} }
@ -378,7 +378,7 @@ static struct wlr_texture *vulkan_texture_from_pixels(
const struct wlr_vk_format_props *fmt = const struct wlr_vk_format_props *fmt =
vulkan_format_props_from_drm(renderer->dev, drm_fmt); vulkan_format_props_from_drm(renderer->dev, drm_fmt);
if (fmt == NULL || fmt->format.is_ycbcr) { if (fmt == NULL || vulkan_format_is_ycbcr(&fmt->format)) {
char *format_name = drmGetFormatName(drm_fmt); char *format_name = drmGetFormatName(drm_fmt);
wlr_log(WLR_ERROR, "Unsupported pixel format %s (0x%08"PRIX32")", wlr_log(WLR_ERROR, "Unsupported pixel format %s (0x%08"PRIX32")",
format_name, drm_fmt); format_name, drm_fmt);

View file

@ -109,14 +109,11 @@ bool wlr_buffer_get_shm(struct wlr_buffer *buffer,
bool wlr_buffer_is_opaque(struct wlr_buffer *buffer) { bool wlr_buffer_is_opaque(struct wlr_buffer *buffer) {
void *data; void *data;
uint32_t format; uint32_t format = buffer_get_drm_format(buffer);
size_t stride; size_t stride;
struct wlr_dmabuf_attributes dmabuf;
struct wlr_shm_attributes shm; if (format != DRM_FORMAT_INVALID) {
if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) { // pass
format = dmabuf.format;
} else if (wlr_buffer_get_shm(buffer, &shm)) {
format = shm.format;
} else if (wlr_buffer_begin_data_ptr_access(buffer, } else if (wlr_buffer_begin_data_ptr_access(buffer,
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) { WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
bool opaque = false; bool opaque = false;
@ -135,3 +132,15 @@ bool wlr_buffer_is_opaque(struct wlr_buffer *buffer) {
return !pixel_format_has_alpha(format); return !pixel_format_has_alpha(format);
} }
uint32_t buffer_get_drm_format(struct wlr_buffer *buffer) {
uint32_t format = DRM_FORMAT_INVALID;
struct wlr_dmabuf_attributes dmabuf;
struct wlr_shm_attributes shm;
if (wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
format = dmabuf.format;
} else if (wlr_buffer_get_shm(buffer, &shm)) {
format = shm.format;
}
return format;
}

View file

@ -173,8 +173,6 @@ static void source_update_buffer_constraints(struct scene_node_source *source,
} }
static bool output_test(struct wlr_output *output, const struct wlr_output_state *state) { static bool output_test(struct wlr_output *output, const struct wlr_output_state *state) {
struct scene_node_source *source = wl_container_of(output, source, output);
uint32_t supported = uint32_t supported =
WLR_OUTPUT_STATE_BACKEND_OPTIONAL | WLR_OUTPUT_STATE_BACKEND_OPTIONAL |
WLR_OUTPUT_STATE_BUFFER | WLR_OUTPUT_STATE_BUFFER |

View file

@ -535,4 +535,4 @@ bool output_cursor_refresh_color_transform(struct wlr_output_cursor *output_curs
wlr_color_transform_unref(transforms[0]); wlr_color_transform_unref(transforms[0]);
wlr_color_transform_unref(transforms[1]); wlr_color_transform_unref(transforms[1]);
return output_cursor->color_transform != NULL; return output_cursor->color_transform != NULL;
} }

View file

@ -2086,8 +2086,12 @@ static enum scene_direct_scanout_result scene_entry_try_direct_scanout(
return SCANOUT_INELIGIBLE; return SCANOUT_INELIGIBLE;
} }
if (buffer->color_encoding != WLR_COLOR_ENCODING_NONE || bool is_color_repr_none = buffer->color_encoding == WLR_COLOR_ENCODING_NONE &&
buffer->color_range != WLR_COLOR_RANGE_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; return SCANOUT_INELIGIBLE;
} }

View file

@ -1,13 +1,17 @@
#include <assert.h> #include <assert.h>
#include <drm_fourcc.h>
#include <stdlib.h> #include <stdlib.h>
#include <wlr/render/wlr_renderer.h> #include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_buffer.h>
#include <wlr/types/wlr_compositor.h> #include <wlr/types/wlr_compositor.h>
#include <wlr/types/wlr_color_representation_v1.h> #include <wlr/types/wlr_color_representation_v1.h>
#include <wlr/util/addon.h> #include <wlr/util/addon.h>
#include <wlr/util/log.h> #include <wlr/util/log.h>
#include "color-representation-v1-protocol.h" #include "color-representation-v1-protocol.h"
#include "render/pixel_format.h"
#include "types/wlr_buffer.h"
#include "util/mem.h" #include "util/mem.h"
#define WP_COLOR_REPRESENTATION_VERSION 1 #define WP_COLOR_REPRESENTATION_VERSION 1
@ -230,8 +234,44 @@ static void color_repr_manager_handle_destroy(struct wl_client *client,
wl_resource_destroy(resource); wl_resource_destroy(resource);
} }
static void surface_synced_commit(struct wlr_surface_synced *synced) {
struct wlr_color_representation_v1 *color_repr = wl_container_of(synced, color_repr, synced);
if (color_repr->current.coefficients == 0 && color_repr->current.range == 0) {
return;
}
uint32_t drm_format = DRM_FORMAT_INVALID;
if (color_repr->surface->buffer){
drm_format = buffer_get_drm_format(&color_repr->surface->buffer->base);
}
if (drm_format == DRM_FORMAT_INVALID) {
return;
}
bool is_ycbcr = pixel_format_is_ycbcr(drm_format);
bool is_identity_full =
color_repr->current.coefficients == WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_IDENTITY &&
color_repr->current.range == WP_COLOR_REPRESENTATION_SURFACE_V1_RANGE_FULL;
if (is_ycbcr) {
if (is_identity_full) {
wl_resource_post_error(color_repr->resource,
WP_COLOR_REPRESENTATION_SURFACE_V1_ERROR_PIXEL_FORMAT,
"unexpected encoding/range for yuv");
}
} else /* rgb */ {
if (!is_identity_full) {
wl_resource_post_error(color_repr->resource,
WP_COLOR_REPRESENTATION_SURFACE_V1_ERROR_PIXEL_FORMAT,
"unexpected encoding/range for rgb");
}
}
}
static const struct wlr_surface_synced_impl surface_synced_impl = { static const struct wlr_surface_synced_impl surface_synced_impl = {
.state_size = sizeof(struct wlr_color_representation_v1_surface_state), .state_size = sizeof(struct wlr_color_representation_v1_surface_state),
.commit = surface_synced_commit
}; };
static struct wlr_color_representation_v1 *color_repr_from_surface( static struct wlr_color_representation_v1 *color_repr_from_surface(
@ -276,6 +316,7 @@ static void color_repr_manager_handle_get_surface(struct wl_client *client,
} }
color_repr->manager = manager_from_resource(manager_resource); color_repr->manager = manager_from_resource(manager_resource);
color_repr->surface = surface;
if (!wlr_surface_synced_init(&color_repr->synced, surface, if (!wlr_surface_synced_init(&color_repr->synced, surface,
&surface_synced_impl, &color_repr->pending, &color_repr->current)) { &surface_synced_impl, &color_repr->pending, &color_repr->current)) {
@ -427,6 +468,10 @@ struct wlr_color_representation_manager_v1 *wlr_color_representation_manager_v1_
struct wlr_color_representation_v1_coeffs_and_range coeffs_and_ranges[COEFFICIENTS_LEN * RANGES_LEN]; struct wlr_color_representation_v1_coeffs_and_range coeffs_and_ranges[COEFFICIENTS_LEN * RANGES_LEN];
size_t coeffs_and_ranges_len = 0; size_t coeffs_and_ranges_len = 0;
coeffs_and_ranges[coeffs_and_ranges_len++] = (struct wlr_color_representation_v1_coeffs_and_range){
.coeffs = WP_COLOR_REPRESENTATION_SURFACE_V1_COEFFICIENTS_IDENTITY,
.range = WP_COLOR_REPRESENTATION_SURFACE_V1_RANGE_FULL,
};
for (size_t i = 0; i < COEFFICIENTS_LEN; i++) { for (size_t i = 0; i < COEFFICIENTS_LEN; i++) {
enum wp_color_representation_surface_v1_coefficients coeffs = coefficients[i]; enum wp_color_representation_surface_v1_coefficients coeffs = coefficients[i];
enum wlr_color_encoding enc = wlr_color_representation_v1_color_encoding_to_wlr(coeffs); enum wlr_color_encoding enc = wlr_color_representation_v1_color_encoding_to_wlr(coeffs);

View file

@ -956,7 +956,7 @@ static void handle_tablet_tool_axis(struct wl_listener *listener, void *data) {
static void handle_tablet_tool_button(struct wl_listener *listener, static void handle_tablet_tool_button(struct wl_listener *listener,
void *data) { void *data) {
struct wlr_tablet_tool_button *event = data; struct wlr_tablet_tool_button_event *event = data;
struct wlr_cursor_device *device; struct wlr_cursor_device *device;
device = wl_container_of(listener, device, tablet_tool_button); device = wl_container_of(listener, device, tablet_tool_button);
wl_signal_emit_mutable(&device->cursor->events.tablet_tool_button, event); wl_signal_emit_mutable(&device->cursor->events.tablet_tool_button, event);

View file

@ -308,7 +308,7 @@ void wlr_keyboard_group_remove_keyboard(struct wlr_keyboard_group *group,
void wlr_keyboard_group_destroy(struct wlr_keyboard_group *group) { void wlr_keyboard_group_destroy(struct wlr_keyboard_group *group) {
struct keyboard_group_device *device, *tmp_device; struct keyboard_group_device *device, *tmp_device;
wl_list_for_each_safe(device, tmp_device, &group->devices, link) { wl_list_for_each_safe(device, tmp_device, &group->devices, link) {
wlr_keyboard_group_remove_keyboard(group, device->keyboard); remove_keyboard_group_device(device);
} }
// Now group->keys might not be empty if a wlr_keyboard has emitted // Now group->keys might not be empty if a wlr_keyboard has emitted

View file

@ -381,13 +381,15 @@ static bool source_get_targets(struct wlr_xwm_selection *selection,
free(mime_type); free(mime_type);
break; break;
} }
*mime_type_ptr = mime_type;
xcb_atom_t *atom_ptr = xcb_atom_t *atom_ptr =
wl_array_add(mime_types_atoms, sizeof(*atom_ptr)); wl_array_add(mime_types_atoms, sizeof(*atom_ptr));
if (atom_ptr == NULL) { if (atom_ptr == NULL) {
mime_types->size -= sizeof(*mime_type_ptr);
free(mime_type);
break; break;
} }
*mime_type_ptr = mime_type;
*atom_ptr = value[i]; *atom_ptr = value[i];
} }
} }

View file

@ -1,5 +1,6 @@
#include <assert.h> #include <assert.h>
#include <drm_fourcc.h> #include <drm_fourcc.h>
#include <poll.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h> #include <unistd.h>
#include <wlr/types/wlr_buffer.h> #include <wlr/types/wlr_buffer.h>
@ -2881,5 +2882,20 @@ xcb_connection_t *wlr_xwayland_get_xwm_connection(
} }
void xwm_schedule_flush(struct wlr_xwm *xwm) { void xwm_schedule_flush(struct wlr_xwm *xwm) {
struct pollfd pollfd = {
.fd = xcb_get_file_descriptor(xwm->xcb_conn),
.events = POLLOUT,
};
if (poll(&pollfd, 1, 0) < 0) {
wlr_log(WLR_ERROR, "poll() failed");
return;
}
// If we can write immediately, do so
if (pollfd.revents & POLLOUT) {
xcb_flush(xwm->xcb_conn);
return;
}
wl_event_source_fd_update(xwm->event_source, WL_EVENT_READABLE | WL_EVENT_WRITABLE); wl_event_source_fd_update(xwm->event_source, WL_EVENT_READABLE | WL_EVENT_WRITABLE);
} }