mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-03-31 07:11:32 -04:00
Compare commits
24 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c1d38536c9 | ||
|
|
a945fd8940 | ||
|
|
2bfbec4af1 | ||
|
|
1a9b1292e2 | ||
|
|
ad82740518 | ||
|
|
bba38a0d82 | ||
|
|
df1539d9f0 | ||
|
|
eff5aa52e6 | ||
|
|
8daba3246d | ||
|
|
52564ea97c | ||
|
|
288ba9e75b | ||
|
|
2f14845ce0 | ||
|
|
c4ff394f7f | ||
|
|
88718e84c9 | ||
|
|
6a902237ef | ||
|
|
47a43e14ae | ||
|
|
ba32abbddb | ||
|
|
9c3bfbeb48 | ||
|
|
b727521449 | ||
|
|
af228b879a | ||
|
|
ec26eb250a | ||
|
|
3105ac2b16 | ||
|
|
557fde4d01 | ||
|
|
e444836bf2 |
54 changed files with 204 additions and 690 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
#include <assert.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) },
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -155,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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -410,7 +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);
|
||||
bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer);
|
||||
|
||||
struct wlr_vk_render_pass_texture {
|
||||
struct wlr_vk_texture *texture;
|
||||
|
|
@ -476,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);
|
||||
|
|
@ -490,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 {
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ 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);
|
||||
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
project(
|
||||
'wlroots',
|
||||
'c',
|
||||
version: '0.21.0-dev',
|
||||
version: '0.20.0',
|
||||
license: 'MIT',
|
||||
meson_version: '>=1.3',
|
||||
default_options: [
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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')
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,10 +4,8 @@
|
|||
#include <GLES2/gl2ext.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-server-protocol.h>
|
||||
#include <wayland-util.h>
|
||||
#include <wlr/render/drm_syncobj.h>
|
||||
#include <wlr/render/egl.h>
|
||||
#include <wlr/render/interface.h>
|
||||
#include <wlr/render/wlr_texture.h>
|
||||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -99,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];
|
||||
|
|
@ -115,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;
|
||||
|
|
@ -385,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;
|
||||
|
|
|
|||
|
|
@ -46,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;
|
||||
}
|
||||
|
||||
|
|
@ -379,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;
|
||||
}
|
||||
|
|
@ -434,12 +389,9 @@ bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer, int wait_sync_fi
|
|||
|
||||
uint64_t timeline_point = vulkan_end_command_buffer(cb, renderer);
|
||||
if (timeline_point == 0) {
|
||||
close(wait_sync_file_fd);
|
||||
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,
|
||||
|
|
@ -453,18 +405,6 @@ 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) {
|
||||
close(wait_sync_file_fd);
|
||||
return false;
|
||||
}
|
||||
submit_info.waitSemaphoreCount = 1;
|
||||
submit_info.pWaitSemaphores = &wait_semaphore;
|
||||
submit_info.pWaitDstStageMask = &wait_stage;
|
||||
}
|
||||
|
||||
VkResult res = vkQueueSubmit(renderer->dev->queue, 1, &submit_info, VK_NULL_HANDLE);
|
||||
if (res != VK_SUCCESS) {
|
||||
wlr_vk_error("vkQueueSubmit", res);
|
||||
|
|
@ -1248,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);
|
||||
}
|
||||
|
||||
|
|
@ -1278,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);
|
||||
|
|
@ -1465,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;
|
||||
}
|
||||
|
||||
|
|
@ -2120,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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
@ -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) {
|
||||
|
|
@ -654,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) {
|
||||
|
|
@ -713,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;
|
||||
|
|
|
|||
|
|
@ -81,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;
|
||||
|
|
@ -110,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,
|
||||
|
|
@ -136,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 = {
|
||||
|
|
@ -278,10 +282,20 @@ VkPhysicalDevice vulkan_find_drm_phdev(struct wlr_vk_instance *ini, int drm_fd)
|
|||
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,
|
||||
|
|
@ -460,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])) {
|
||||
|
|
@ -622,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);
|
||||
|
|
|
|||
|
|
@ -1,154 +0,0 @@
|
|||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
test(
|
||||
'box',
|
||||
executable('test-box', 'test_box.c', dependencies: wlroots),
|
||||
)
|
||||
|
||||
benchmark(
|
||||
'scene',
|
||||
executable('bench-scene', 'bench_scene.c', dependencies: wlroots),
|
||||
timeout: 30,
|
||||
)
|
||||
149
test/test_box.c
149
test/test_box.c
|
|
@ -1,149 +0,0 @@
|
|||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <wlr/util/box.h>
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -34,14 +34,13 @@ struct scene_node_source_frame_event {
|
|||
|
||||
static size_t last_output_num = 0;
|
||||
|
||||
static void _get_scene_node_extents(struct wlr_scene_node *node, int lx, int ly,
|
||||
int *x_min, int *y_min, int *x_max, int *y_max) {
|
||||
static void _get_scene_node_extents(struct wlr_scene_node *node, struct wlr_box *box, int lx, int ly) {
|
||||
switch (node->type) {
|
||||
case WLR_SCENE_NODE_TREE:;
|
||||
struct wlr_scene_tree *scene_tree = wlr_scene_tree_from_node(node);
|
||||
struct wlr_scene_node *child;
|
||||
wl_list_for_each(child, &scene_tree->children, link) {
|
||||
_get_scene_node_extents(child, lx + child->x, ly + child->y, x_min, y_min, x_max, y_max);
|
||||
_get_scene_node_extents(child, box, lx + child->x, ly + child->y);
|
||||
}
|
||||
break;
|
||||
case WLR_SCENE_NODE_RECT:
|
||||
|
|
@ -49,30 +48,27 @@ static void _get_scene_node_extents(struct wlr_scene_node *node, int lx, int ly,
|
|||
struct wlr_box node_box = { .x = lx, .y = ly };
|
||||
scene_node_get_size(node, &node_box.width, &node_box.height);
|
||||
|
||||
if (node_box.x < *x_min) {
|
||||
*x_min = node_box.x;
|
||||
if (node_box.x < box->x) {
|
||||
box->x = node_box.x;
|
||||
}
|
||||
if (node_box.y < *y_min) {
|
||||
*y_min = node_box.y;
|
||||
if (node_box.y < box->y) {
|
||||
box->y = node_box.y;
|
||||
}
|
||||
if (node_box.x + node_box.width > *x_max) {
|
||||
*x_max = node_box.x + node_box.width;
|
||||
if (node_box.x + node_box.width > box->x + box->width) {
|
||||
box->width = node_box.x + node_box.width - box->x;
|
||||
}
|
||||
if (node_box.y + node_box.height > *y_max) {
|
||||
*y_max = node_box.y + node_box.height;
|
||||
if (node_box.y + node_box.height > box->y + box->height) {
|
||||
box->height = node_box.y + node_box.height - box->y;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void get_scene_node_extents(struct wlr_scene_node *node, struct wlr_box *box) {
|
||||
*box = (struct wlr_box){ .x = INT_MAX, .y = INT_MAX };
|
||||
int lx = 0, ly = 0;
|
||||
wlr_scene_node_coords(node, &lx, &ly);
|
||||
*box = (struct wlr_box){ .x = INT_MAX, .y = INT_MAX };
|
||||
int x_max = INT_MIN, y_max = INT_MIN;
|
||||
_get_scene_node_extents(node, lx, ly, &box->x, &box->y, &x_max, &y_max);
|
||||
box->width = x_max - box->x;
|
||||
box->height = y_max - box->y;
|
||||
_get_scene_node_extents(node, box, lx, ly);
|
||||
}
|
||||
|
||||
static void source_render(struct scene_node_source *source) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -468,12 +481,28 @@ static void update_node_update_outputs(struct wlr_scene_node *node,
|
|||
(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;
|
||||
|
|
@ -486,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;
|
||||
|
|
@ -496,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);
|
||||
}
|
||||
|
||||
|
|
@ -842,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);
|
||||
|
||||
|
|
@ -2069,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.
|
||||
|
|
@ -2116,17 +2154,6 @@ static enum scene_direct_scanout_result scene_entry_try_direct_scanout(
|
|||
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;
|
||||
|
|
@ -2669,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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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};
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue