mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-03-17 05:34:14 -04:00
Compare commits
53 commits
0.20.0-rc1
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1fa8bb8f7a | ||
|
|
ec746d3e3e | ||
|
|
1fc928d528 | ||
|
|
3cb2cf9425 | ||
|
|
7f87c7fe90 | ||
|
|
39e918edc8 | ||
|
|
736c0f3f25 | ||
|
|
3c8d199ec1 | ||
|
|
7ccef7d9eb | ||
|
|
2938c10cd3 | ||
|
|
648790f43a | ||
|
|
ff7d093800 | ||
|
|
285cee5f3a | ||
|
|
9a931d9ffa | ||
|
|
3dafaa4df3 | ||
|
|
67ce318b1f | ||
|
|
14b3c96c1e | ||
|
|
3336d28813 | ||
|
|
2d39166146 | ||
|
|
1b8c3ea8c5 | ||
|
|
55bb69e2c4 | ||
|
|
a55b85e2e1 | ||
|
|
6d9aa17572 | ||
|
|
1ce992d7cb | ||
|
|
2367d78c3c | ||
|
|
8c8d6363a1 | ||
|
|
ff4ce12179 | ||
|
|
43b37e34d6 | ||
|
|
73bbad8433 | ||
|
|
a6e5807e86 | ||
|
|
7be5e3689c | ||
|
|
25bec59c75 | ||
|
|
1efb216c6d | ||
|
|
884d29e5f3 | ||
|
|
25f94c5965 | ||
|
|
910fd264fb | ||
|
|
3676ab4df0 | ||
|
|
c1452d8811 | ||
|
|
436bcf9a47 | ||
|
|
ef88246642 | ||
|
|
bb78861ca9 | ||
|
|
439985fe95 | ||
|
|
4c81cb1b9e | ||
|
|
19d6829601 | ||
|
|
dfccf5ff02 | ||
|
|
bc11ac92ab | ||
|
|
d362ed1eb9 | ||
|
|
90f9f59041 | ||
|
|
7cb4e30bfd | ||
|
|
98196bbd89 | ||
|
|
4fe51aa439 | ||
|
|
12c9502edf | ||
|
|
7f87e258b2 |
85 changed files with 1082 additions and 415 deletions
|
|
@ -35,6 +35,9 @@ 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,6 +37,10 @@ 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,6 +32,9 @@ 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,4 @@
|
|||
include: https://git.sr.ht/~emersion/dalligi/blob/master/templates/multi.yml
|
||||
include: https://gitlab.freedesktop.org/emersion/dalligi/-/raw/master/templates/multi.yml
|
||||
alpine:
|
||||
extends: .dalligi
|
||||
pages: true
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ don't, however, allow me to make a suggestion: feature branches pulled from
|
|||
upstream. Try this:
|
||||
|
||||
1. Fork wlroots
|
||||
2. `git clone git@gitlab.freedesktop.org:<username>/wlroots.git && cd wlroots`
|
||||
2. `git clone git@ssh.gitlab.freedesktop.org:<username>/wlroots.git && cd wlroots`
|
||||
3. `git remote add upstream https://gitlab.freedesktop.org/wlroots/wlroots.git`
|
||||
|
||||
You only need to do this once. You're never going to use your fork's master
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ static const struct wlr_backend_impl backend_impl = {
|
|||
.commit = backend_commit,
|
||||
};
|
||||
|
||||
bool wlr_backend_is_drm(struct wlr_backend *b) {
|
||||
bool wlr_backend_is_drm(const struct wlr_backend *b) {
|
||||
return b->impl == &backend_impl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1299,7 +1299,7 @@ static const struct wlr_output_impl output_impl = {
|
|||
.get_primary_formats = drm_connector_get_primary_formats,
|
||||
};
|
||||
|
||||
bool wlr_output_is_drm(struct wlr_output *output) {
|
||||
bool wlr_output_is_drm(const struct wlr_output *output) {
|
||||
return output->impl == &output_impl;
|
||||
}
|
||||
|
||||
|
|
@ -2104,6 +2104,7 @@ int wlr_drm_backend_get_non_master_fd(struct wlr_backend *backend) {
|
|||
|
||||
if (drmIsMaster(fd) && drmDropMaster(fd) < 0) {
|
||||
wlr_log_errno(WLR_ERROR, "Failed to drop master");
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
@ -2138,7 +2139,7 @@ struct wlr_drm_lease *wlr_drm_create_lease(struct wlr_output **outputs,
|
|||
wlr_log(WLR_DEBUG, "Connector %d", conn->id);
|
||||
|
||||
if (!drm_connector_alloc_crtc(conn)) {
|
||||
wlr_log(WLR_ERROR, "Failled to allocate connector CRTC");
|
||||
wlr_log(WLR_ERROR, "Failed to allocate connector CRTC");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -81,6 +81,6 @@ struct wlr_backend *wlr_headless_backend_create(struct wl_event_loop *loop) {
|
|||
return &backend->backend;
|
||||
}
|
||||
|
||||
bool wlr_backend_is_headless(struct wlr_backend *backend) {
|
||||
bool wlr_backend_is_headless(const 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(struct wlr_output *wlr_output) {
|
||||
bool wlr_output_is_headless(const 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(struct wlr_backend *b) {
|
||||
bool wlr_backend_is_libinput(const struct wlr_backend *b) {
|
||||
return b->impl == &backend_impl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -249,3 +249,15 @@ void handle_libinput_event(struct wlr_libinput_backend *backend,
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool button_state_from_libinput(enum libinput_button_state state, enum wlr_button_state *out) {
|
||||
switch (state) {
|
||||
case LIBINPUT_BUTTON_STATE_RELEASED:
|
||||
*out = WLR_BUTTON_RELEASED;
|
||||
return true;
|
||||
case LIBINPUT_BUTTON_STATE_PRESSED:
|
||||
*out = WLR_BUTTON_PRESSED;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include <libinput.h>
|
||||
#include <stdlib.h>
|
||||
#include <wlr/interfaces/wlr_keyboard.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/libinput.h"
|
||||
|
||||
struct wlr_libinput_input_device *device_from_keyboard(
|
||||
|
|
@ -30,6 +31,18 @@ void init_device_keyboard(struct wlr_libinput_input_device *dev) {
|
|||
libinput_device_led_update(dev->handle, 0);
|
||||
}
|
||||
|
||||
static bool key_state_from_libinput(enum libinput_key_state state, enum wl_keyboard_key_state *out) {
|
||||
switch (state) {
|
||||
case LIBINPUT_KEY_STATE_RELEASED:
|
||||
*out = WL_KEYBOARD_KEY_STATE_RELEASED;
|
||||
return true;
|
||||
case LIBINPUT_KEY_STATE_PRESSED:
|
||||
*out = WL_KEYBOARD_KEY_STATE_PRESSED;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void handle_keyboard_key(struct libinput_event *event,
|
||||
struct wlr_keyboard *kb) {
|
||||
struct libinput_event_keyboard *kbevent =
|
||||
|
|
@ -39,13 +52,9 @@ void handle_keyboard_key(struct libinput_event *event,
|
|||
.keycode = libinput_event_keyboard_get_key(kbevent),
|
||||
.update_state = true,
|
||||
};
|
||||
switch (libinput_event_keyboard_get_key_state(kbevent)) {
|
||||
case LIBINPUT_KEY_STATE_RELEASED:
|
||||
wlr_event.state = WL_KEYBOARD_KEY_STATE_RELEASED;
|
||||
break;
|
||||
case LIBINPUT_KEY_STATE_PRESSED:
|
||||
wlr_event.state = WL_KEYBOARD_KEY_STATE_PRESSED;
|
||||
break;
|
||||
if (!key_state_from_libinput(libinput_event_keyboard_get_key_state(kbevent), &wlr_event.state)) {
|
||||
wlr_log(WLR_DEBUG, "Unhandled libinput key state");
|
||||
return;
|
||||
}
|
||||
wlr_keyboard_notify_key(kb, &wlr_event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,3 +29,7 @@ features += { 'libinput-backend': true }
|
|||
wlr_deps += libinput
|
||||
|
||||
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')
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <wlr/interfaces/wlr_pointer.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/libinput.h"
|
||||
|
||||
const struct wlr_pointer_impl libinput_pointer_impl = {
|
||||
|
|
@ -52,6 +53,38 @@ void handle_pointer_motion_abs(struct libinput_event *event,
|
|||
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
||||
}
|
||||
|
||||
static bool pointer_button_state_from_libinput(enum libinput_button_state state,
|
||||
enum wl_pointer_button_state *out) {
|
||||
switch (state) {
|
||||
case LIBINPUT_BUTTON_STATE_PRESSED:
|
||||
*out = WL_POINTER_BUTTON_STATE_PRESSED;
|
||||
return true;
|
||||
case LIBINPUT_BUTTON_STATE_RELEASED:
|
||||
*out = WL_POINTER_BUTTON_STATE_RELEASED;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool axis_source_from_libinput(enum libinput_pointer_axis_source source,
|
||||
enum wl_pointer_axis_source *out) {
|
||||
switch (source) {
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
|
||||
*out = WL_POINTER_AXIS_SOURCE_WHEEL;
|
||||
return true;
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
|
||||
*out = WL_POINTER_AXIS_SOURCE_FINGER;
|
||||
return true;
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
|
||||
*out = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
|
||||
return true;
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
|
||||
*out = WL_POINTER_AXIS_SOURCE_WHEEL_TILT;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void handle_pointer_button(struct libinput_event *event,
|
||||
struct wlr_pointer *pointer) {
|
||||
struct libinput_event_pointer *pevent =
|
||||
|
|
@ -61,13 +94,10 @@ void handle_pointer_button(struct libinput_event *event,
|
|||
.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)),
|
||||
.button = libinput_event_pointer_get_button(pevent),
|
||||
};
|
||||
switch (libinput_event_pointer_get_button_state(pevent)) {
|
||||
case LIBINPUT_BUTTON_STATE_PRESSED:
|
||||
wlr_event.state = WL_POINTER_BUTTON_STATE_PRESSED;
|
||||
break;
|
||||
case LIBINPUT_BUTTON_STATE_RELEASED:
|
||||
wlr_event.state = WL_POINTER_BUTTON_STATE_RELEASED;
|
||||
break;
|
||||
if (!pointer_button_state_from_libinput(libinput_event_pointer_get_button_state(pevent),
|
||||
&wlr_event.state)) {
|
||||
wlr_log(WLR_DEBUG, "Unhandled libinput button state");
|
||||
return;
|
||||
}
|
||||
wlr_pointer_notify_button(pointer, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
||||
|
|
@ -81,19 +111,9 @@ void handle_pointer_axis(struct libinput_event *event,
|
|||
.pointer = pointer,
|
||||
.time_msec = usec_to_msec(libinput_event_pointer_get_time_usec(pevent)),
|
||||
};
|
||||
switch (libinput_event_pointer_get_axis_source(pevent)) {
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL:
|
||||
wlr_event.source = WL_POINTER_AXIS_SOURCE_WHEEL;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_FINGER:
|
||||
wlr_event.source = WL_POINTER_AXIS_SOURCE_FINGER;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_CONTINUOUS:
|
||||
wlr_event.source = WL_POINTER_AXIS_SOURCE_CONTINUOUS;
|
||||
break;
|
||||
case LIBINPUT_POINTER_AXIS_SOURCE_WHEEL_TILT:
|
||||
wlr_event.source = WL_POINTER_AXIS_SOURCE_WHEEL_TILT;
|
||||
break;
|
||||
if (!axis_source_from_libinput(libinput_event_pointer_get_axis_source(pevent), &wlr_event.source)) {
|
||||
wlr_log(WLR_DEBUG, "Unhandled libinput pointer axis source");
|
||||
return;
|
||||
}
|
||||
const enum libinput_pointer_axis axes[] = {
|
||||
LIBINPUT_POINTER_AXIS_SCROLL_VERTICAL,
|
||||
|
|
|
|||
|
|
@ -1,7 +1,9 @@
|
|||
#include <assert.h>
|
||||
#include <libinput.h>
|
||||
#include <wlr/interfaces/wlr_switch.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "config.h"
|
||||
|
||||
const struct wlr_switch_impl libinput_switch_impl = {
|
||||
.name = "libinput-switch",
|
||||
|
|
@ -22,28 +24,49 @@ struct wlr_libinput_input_device *device_from_switch(
|
|||
return dev;
|
||||
}
|
||||
|
||||
static bool switch_type_from_libinput(enum libinput_switch type, enum wlr_switch_type *out) {
|
||||
switch (type) {
|
||||
case LIBINPUT_SWITCH_LID:
|
||||
*out = WLR_SWITCH_TYPE_LID;
|
||||
return true;
|
||||
case LIBINPUT_SWITCH_TABLET_MODE:
|
||||
*out = WLR_SWITCH_TYPE_TABLET_MODE;
|
||||
return true;
|
||||
#if HAVE_LIBINPUT_SWITCH_KEYPAD_SLIDE
|
||||
case LIBINPUT_SWITCH_KEYPAD_SLIDE:
|
||||
*out = WLR_SWITCH_TYPE_KEYPAD_SLIDE;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool switch_state_from_libinput(enum libinput_switch_state state, enum wlr_switch_state *out) {
|
||||
switch (state) {
|
||||
case LIBINPUT_SWITCH_STATE_OFF:
|
||||
*out = WLR_SWITCH_STATE_OFF;
|
||||
return true;
|
||||
case LIBINPUT_SWITCH_STATE_ON:
|
||||
*out = WLR_SWITCH_STATE_ON;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void handle_switch_toggle(struct libinput_event *event,
|
||||
struct wlr_switch *wlr_switch) {
|
||||
struct libinput_event_switch *sevent =
|
||||
libinput_event_get_switch_event (event);
|
||||
libinput_event_get_switch_event(event);
|
||||
struct wlr_switch_toggle_event wlr_event = {
|
||||
.time_msec = usec_to_msec(libinput_event_switch_get_time_usec(sevent)),
|
||||
};
|
||||
switch (libinput_event_switch_get_switch(sevent)) {
|
||||
case LIBINPUT_SWITCH_LID:
|
||||
wlr_event.switch_type = WLR_SWITCH_TYPE_LID;
|
||||
break;
|
||||
case LIBINPUT_SWITCH_TABLET_MODE:
|
||||
wlr_event.switch_type = WLR_SWITCH_TYPE_TABLET_MODE;
|
||||
break;
|
||||
if (!switch_type_from_libinput(libinput_event_switch_get_switch(sevent), &wlr_event.switch_type)) {
|
||||
wlr_log(WLR_DEBUG, "Unhandled libinput switch type");
|
||||
return;
|
||||
}
|
||||
switch (libinput_event_switch_get_switch_state(sevent)) {
|
||||
case LIBINPUT_SWITCH_STATE_OFF:
|
||||
wlr_event.switch_state = WLR_SWITCH_STATE_OFF;
|
||||
break;
|
||||
case LIBINPUT_SWITCH_STATE_ON:
|
||||
wlr_event.switch_state = WLR_SWITCH_STATE_ON;
|
||||
break;
|
||||
if (!switch_state_from_libinput(libinput_event_switch_get_switch_state(sevent), &wlr_event.switch_state)) {
|
||||
wlr_log(WLR_DEBUG, "Unhandled libinput switch state");
|
||||
return;
|
||||
}
|
||||
wl_signal_emit_mutable(&wlr_switch->events.toggle, &wlr_event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -148,13 +148,9 @@ void handle_tablet_pad_button(struct libinput_event *event,
|
|||
.group = libinput_tablet_pad_mode_group_get_index(
|
||||
libinput_event_tablet_pad_get_mode_group(pevent)),
|
||||
};
|
||||
switch (libinput_event_tablet_pad_get_button_state(pevent)) {
|
||||
case LIBINPUT_BUTTON_STATE_PRESSED:
|
||||
wlr_event.state = WLR_BUTTON_PRESSED;
|
||||
break;
|
||||
case LIBINPUT_BUTTON_STATE_RELEASED:
|
||||
wlr_event.state = WLR_BUTTON_RELEASED;
|
||||
break;
|
||||
if (!button_state_from_libinput(libinput_event_tablet_pad_get_button_state(pevent), &wlr_event.state)) {
|
||||
wlr_log(WLR_DEBUG, "Unhandled libinput button state");
|
||||
return;
|
||||
}
|
||||
wl_signal_emit_mutable(&tablet_pad->events.button, &wlr_event);
|
||||
}
|
||||
|
|
@ -168,6 +164,7 @@ void handle_tablet_pad_ring(struct libinput_event *event,
|
|||
.ring = libinput_event_tablet_pad_get_ring_number(pevent),
|
||||
.position = libinput_event_tablet_pad_get_ring_position(pevent),
|
||||
.mode = libinput_event_tablet_pad_get_mode(pevent),
|
||||
.source = WLR_TABLET_PAD_RING_SOURCE_UNKNOWN,
|
||||
};
|
||||
switch (libinput_event_tablet_pad_get_ring_source(pevent)) {
|
||||
case LIBINPUT_TABLET_PAD_RING_SOURCE_UNKNOWN:
|
||||
|
|
@ -189,6 +186,7 @@ void handle_tablet_pad_strip(struct libinput_event *event,
|
|||
.strip = libinput_event_tablet_pad_get_strip_number(pevent),
|
||||
.position = libinput_event_tablet_pad_get_strip_position(pevent),
|
||||
.mode = libinput_event_tablet_pad_get_mode(pevent),
|
||||
.source = WLR_TABLET_PAD_STRIP_SOURCE_UNKNOWN,
|
||||
};
|
||||
switch (libinput_event_tablet_pad_get_strip_source(pevent)) {
|
||||
case LIBINPUT_TABLET_PAD_STRIP_SOURCE_UNKNOWN:
|
||||
|
|
|
|||
|
|
@ -78,27 +78,61 @@ struct wlr_libinput_input_device *device_from_tablet(
|
|||
return dev;
|
||||
}
|
||||
|
||||
static enum wlr_tablet_tool_type wlr_type_from_libinput_type(
|
||||
enum libinput_tablet_tool_type value) {
|
||||
switch (value) {
|
||||
static bool type_from_libinput(enum libinput_tablet_tool_type type,
|
||||
enum wlr_tablet_tool_type *out) {
|
||||
switch (type) {
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_PEN:
|
||||
return WLR_TABLET_TOOL_TYPE_PEN;
|
||||
*out = WLR_TABLET_TOOL_TYPE_PEN;
|
||||
return true;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_ERASER:
|
||||
return WLR_TABLET_TOOL_TYPE_ERASER;
|
||||
*out = WLR_TABLET_TOOL_TYPE_ERASER;
|
||||
return true;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_BRUSH:
|
||||
return WLR_TABLET_TOOL_TYPE_BRUSH;
|
||||
*out = WLR_TABLET_TOOL_TYPE_BRUSH;
|
||||
return true;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_PENCIL:
|
||||
return WLR_TABLET_TOOL_TYPE_PENCIL;
|
||||
*out = WLR_TABLET_TOOL_TYPE_PENCIL;
|
||||
return true;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_AIRBRUSH:
|
||||
return WLR_TABLET_TOOL_TYPE_AIRBRUSH;
|
||||
*out = WLR_TABLET_TOOL_TYPE_AIRBRUSH;
|
||||
return true;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_MOUSE:
|
||||
return WLR_TABLET_TOOL_TYPE_MOUSE;
|
||||
*out = WLR_TABLET_TOOL_TYPE_MOUSE;
|
||||
return true;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_LENS:
|
||||
return WLR_TABLET_TOOL_TYPE_LENS;
|
||||
*out = WLR_TABLET_TOOL_TYPE_LENS;
|
||||
return true;
|
||||
case LIBINPUT_TABLET_TOOL_TYPE_TOTEM:
|
||||
return WLR_TABLET_TOOL_TYPE_TOTEM;
|
||||
*out = WLR_TABLET_TOOL_TYPE_TOTEM;
|
||||
return true;
|
||||
}
|
||||
abort(); // unreachable
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool proximity_state_from_libinput(enum libinput_tablet_tool_proximity_state state,
|
||||
enum wlr_tablet_tool_proximity_state *out) {
|
||||
switch (state) {
|
||||
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT:
|
||||
*out = WLR_TABLET_TOOL_PROXIMITY_OUT;
|
||||
return true;
|
||||
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN:
|
||||
*out = WLR_TABLET_TOOL_PROXIMITY_IN;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool tip_state_from_libinput(enum libinput_tablet_tool_tip_state state,
|
||||
enum wlr_tablet_tool_tip_state *out) {
|
||||
switch (state) {
|
||||
case LIBINPUT_TABLET_TOOL_TIP_UP:
|
||||
*out = WLR_TABLET_TOOL_TIP_UP;
|
||||
return true;
|
||||
case LIBINPUT_TABLET_TOOL_TIP_DOWN:
|
||||
*out = WLR_TABLET_TOOL_TIP_DOWN;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct tablet_tool *get_tablet_tool(
|
||||
|
|
@ -110,14 +144,19 @@ static struct tablet_tool *get_tablet_tool(
|
|||
return tool;
|
||||
}
|
||||
|
||||
enum wlr_tablet_tool_type type;
|
||||
if (!type_from_libinput(libinput_tablet_tool_get_type(libinput_tool), &type)) {
|
||||
wlr_log(WLR_DEBUG, "Unhandled libinput tablet tool type");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tool = calloc(1, sizeof(*tool));
|
||||
if (tool == NULL) {
|
||||
wlr_log_errno(WLR_ERROR, "failed to allocate wlr_libinput_tablet_tool");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
tool->wlr_tool.type = wlr_type_from_libinput_type(
|
||||
libinput_tablet_tool_get_type(libinput_tool));
|
||||
tool->wlr_tool.type = type;
|
||||
tool->wlr_tool.hardware_serial =
|
||||
libinput_tablet_tool_get_serial(libinput_tool);
|
||||
tool->wlr_tool.hardware_wacom =
|
||||
|
|
@ -209,14 +248,12 @@ void handle_tablet_tool_proximity(struct libinput_event *event,
|
|||
.y = libinput_event_tablet_tool_get_y_transformed(tevent, 1),
|
||||
};
|
||||
|
||||
switch (libinput_event_tablet_tool_get_proximity_state(tevent)) {
|
||||
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_OUT:
|
||||
wlr_event.state = WLR_TABLET_TOOL_PROXIMITY_OUT;
|
||||
break;
|
||||
case LIBINPUT_TABLET_TOOL_PROXIMITY_STATE_IN:
|
||||
wlr_event.state = WLR_TABLET_TOOL_PROXIMITY_IN;
|
||||
break;
|
||||
if (!proximity_state_from_libinput(libinput_event_tablet_tool_get_proximity_state(tevent),
|
||||
&wlr_event.state)) {
|
||||
wlr_log(WLR_DEBUG, "Unhandled libinput tablet tool proximity state");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_signal_emit_mutable(&wlr_tablet->events.proximity, &wlr_event);
|
||||
|
||||
if (libinput_event_tablet_tool_get_proximity_state(tevent) ==
|
||||
|
|
@ -251,14 +288,11 @@ void handle_tablet_tool_tip(struct libinput_event *event,
|
|||
.y = libinput_event_tablet_tool_get_y_transformed(tevent, 1),
|
||||
};
|
||||
|
||||
switch (libinput_event_tablet_tool_get_tip_state(tevent)) {
|
||||
case LIBINPUT_TABLET_TOOL_TIP_UP:
|
||||
wlr_event.state = WLR_TABLET_TOOL_TIP_UP;
|
||||
break;
|
||||
case LIBINPUT_TABLET_TOOL_TIP_DOWN:
|
||||
wlr_event.state = WLR_TABLET_TOOL_TIP_DOWN;
|
||||
break;
|
||||
if (!tip_state_from_libinput(libinput_event_tablet_tool_get_tip_state(tevent), &wlr_event.state)) {
|
||||
wlr_log(WLR_DEBUG, "Unhandled libinput tablet tool tip state");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_signal_emit_mutable(&wlr_tablet->events.tip, &wlr_event);
|
||||
}
|
||||
|
||||
|
|
@ -277,13 +311,11 @@ void handle_tablet_tool_button(struct libinput_event *event,
|
|||
.time_msec = usec_to_msec(libinput_event_tablet_tool_get_time_usec(tevent)),
|
||||
.button = libinput_event_tablet_tool_get_button(tevent),
|
||||
};
|
||||
switch (libinput_event_tablet_tool_get_button_state(tevent)) {
|
||||
case LIBINPUT_BUTTON_STATE_RELEASED:
|
||||
wlr_event.state = WLR_BUTTON_RELEASED;
|
||||
break;
|
||||
case LIBINPUT_BUTTON_STATE_PRESSED:
|
||||
wlr_event.state = WLR_BUTTON_PRESSED;
|
||||
break;
|
||||
|
||||
if (!button_state_from_libinput(libinput_event_tablet_tool_get_button_state(tevent), &wlr_event.state)) {
|
||||
wlr_log(WLR_DEBUG, "Unhandled libinput button state");
|
||||
return;
|
||||
}
|
||||
|
||||
wl_signal_emit_mutable(&wlr_tablet->events.button, &wlr_event);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -173,7 +173,7 @@ struct wlr_backend *wlr_multi_backend_create(struct wl_event_loop *loop) {
|
|||
return &backend->backend;
|
||||
}
|
||||
|
||||
bool wlr_backend_is_multi(struct wlr_backend *b) {
|
||||
bool wlr_backend_is_multi(const 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(struct wlr_backend *b) {
|
||||
bool wlr_backend_is_wl(const 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(struct wlr_output *wlr_output) {
|
||||
bool wlr_output_is_wl(const struct wlr_output *wlr_output) {
|
||||
return wlr_output->impl == &output_impl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ void init_seat_touch(struct wlr_wl_seat *seat) {
|
|||
|
||||
struct wlr_wl_output *output;
|
||||
wl_list_for_each(output, &seat->backend->outputs, link) {
|
||||
/* Multi-output touch not supproted */
|
||||
/* Multi-output touch not supported */
|
||||
seat->wlr_touch.output_name = strdup(output->wlr_output.name);
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -115,6 +115,7 @@ static void handle_x11_event(struct wlr_x11_backend *x11,
|
|||
handle_x11_error(x11, ev);
|
||||
break;
|
||||
}
|
||||
case XCB_DESTROY_NOTIFY:
|
||||
case XCB_UNMAP_NOTIFY:
|
||||
case XCB_MAP_NOTIFY:
|
||||
break;
|
||||
|
|
@ -218,7 +219,7 @@ static const struct wlr_backend_impl backend_impl = {
|
|||
.get_drm_fd = backend_get_drm_fd,
|
||||
};
|
||||
|
||||
bool wlr_backend_is_x11(struct wlr_backend *backend) {
|
||||
bool wlr_backend_is_x11(const struct wlr_backend *backend) {
|
||||
return backend->impl == &backend_impl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,9 @@
|
|||
#include <wlr/util/log.h>
|
||||
|
||||
#include "backend/x11.h"
|
||||
#include "render/pixel_format.h"
|
||||
#include "util/time.h"
|
||||
#include "types/wlr_buffer.h"
|
||||
#include "types/wlr_output.h"
|
||||
|
||||
static const uint32_t SUPPORTED_OUTPUT_STATE =
|
||||
|
|
@ -166,18 +168,20 @@ static bool output_test(struct wlr_output *wlr_output,
|
|||
|
||||
if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
struct wlr_buffer *buffer = state->buffer;
|
||||
struct wlr_dmabuf_attributes dmabuf_attrs;
|
||||
struct wlr_shm_attributes shm_attrs;
|
||||
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;
|
||||
}
|
||||
uint32_t format = buffer_get_drm_format(buffer);
|
||||
if (format != x11->x11_format->drm) {
|
||||
wlr_log(WLR_DEBUG, "Unsupported buffer format");
|
||||
return false;
|
||||
}
|
||||
struct wlr_shm_attributes shm;
|
||||
if (wlr_buffer_get_shm(buffer, &shm)) {
|
||||
const struct wlr_pixel_format_info *info = drm_get_pixel_format_info(format);
|
||||
if (shm.stride != pixel_format_info_min_stride(info, shm.width)) {
|
||||
// xcb_shm_create_pixmap() does not allow arbitrary strides.
|
||||
wlr_log(WLR_DEBUG, "Unsupported shm buffer stride");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state->committed & WLR_OUTPUT_STATE_MODE) {
|
||||
|
|
@ -267,6 +271,12 @@ static xcb_pixmap_t import_shm(struct wlr_x11_output *output,
|
|||
return XCB_PIXMAP_NONE;
|
||||
}
|
||||
|
||||
const struct wlr_pixel_format_info *info = drm_get_pixel_format_info(shm->format);
|
||||
if (shm->stride != pixel_format_info_min_stride(info, shm->width)) {
|
||||
// xcb_shm_create_pixmap() does not allow arbitrary strides.
|
||||
return XCB_PIXMAP_NONE;
|
||||
}
|
||||
|
||||
// xcb closes the FD after sending it
|
||||
int fd = fcntl(shm->fd, F_DUPFD_CLOEXEC, 0);
|
||||
if (fd < 0) {
|
||||
|
|
@ -701,7 +711,7 @@ void handle_x11_configure_notify(struct wlr_x11_output *output,
|
|||
wlr_output_state_finish(&state);
|
||||
}
|
||||
|
||||
bool wlr_output_is_x11(struct wlr_output *wlr_output) {
|
||||
bool wlr_output_is_x11(const struct wlr_output *wlr_output) {
|
||||
return wlr_output->impl == &output_impl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -132,4 +132,6 @@ void handle_tablet_pad_ring(struct libinput_event *event,
|
|||
void handle_tablet_pad_strip(struct libinput_event *event,
|
||||
struct wlr_tablet_pad *tablet_pad);
|
||||
|
||||
bool button_state_from_libinput(enum libinput_button_state state, enum wlr_button_state *out);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -91,7 +91,7 @@ struct wlr_color_transform_lut_3x1d *color_transform_lut_3x1d_from_base(
|
|||
* Create a simplified / normalized wlr_color_transform pipeline.
|
||||
* `transforms` may contain NULL transforms, they will be interpreted as the
|
||||
* identity transform, and removed.
|
||||
* `*result` may be set to a tranform of a type different from
|
||||
* `*result` may be set to a transform of a type different from
|
||||
* `wlr_color_transform_pipeline`, or to NULL if all input transforms are NULL
|
||||
*/
|
||||
bool color_transform_compose(struct wlr_color_transform **result,
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/**
|
||||
* Return true if the DRM FourCC fmt belongs to a YCbCr colorspace family, false otherwise.
|
||||
*/
|
||||
bool pixel_format_is_ycbcr(uint32_t fmt);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@ 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;
|
||||
|
|
@ -86,7 +90,6 @@ struct wlr_vk_format {
|
|||
uint32_t drm;
|
||||
VkFormat vk;
|
||||
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;
|
||||
|
|
@ -125,6 +128,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_props *props, uint64_t mod, bool render);
|
||||
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 {
|
||||
enum wlr_scale_filter_mode filter_mode;
|
||||
|
|
@ -224,7 +228,7 @@ struct wlr_vk_render_buffer_out {
|
|||
bool transitioned;
|
||||
};
|
||||
|
||||
// Renderer-internal represenation of an wlr_buffer imported for rendering.
|
||||
// Renderer-internal representation of an wlr_buffer imported for rendering.
|
||||
struct wlr_vk_render_buffer {
|
||||
struct wlr_buffer *wlr_buffer;
|
||||
struct wlr_addon addon;
|
||||
|
|
@ -473,10 +477,11 @@ 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);
|
||||
|
||||
bool vulkan_sync_render_buffer(struct wlr_vk_renderer *renderer,
|
||||
struct wlr_vk_render_buffer *render_buffer, struct wlr_vk_command_buffer *cb,
|
||||
struct wlr_drm_syncobj_timeline *signal_timeline, uint64_t signal_point);
|
||||
bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
|
||||
bool vulkan_sync_render_pass_release(struct wlr_vk_renderer *renderer,
|
||||
struct wlr_vk_render_pass *pass);
|
||||
bool vulkan_sync_foreign_texture_acquire(struct wlr_vk_texture *texture,
|
||||
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]);
|
||||
bool vulkan_sync_render_buffer_acquire(struct wlr_vk_render_buffer *render_buffer,
|
||||
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]);
|
||||
|
||||
bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
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
|
||||
|
|
|
|||
|
|
@ -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(struct wlr_backend *backend);
|
||||
bool wlr_output_is_drm(struct wlr_output *output);
|
||||
bool wlr_backend_is_drm(const struct wlr_backend *backend);
|
||||
bool wlr_output_is_drm(const 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(struct wlr_backend *backend);
|
||||
bool wlr_output_is_headless(struct wlr_output *output);
|
||||
bool wlr_backend_is_headless(const struct wlr_backend *backend);
|
||||
bool wlr_output_is_headless(const 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(struct wlr_backend *backend);
|
||||
bool wlr_backend_is_libinput(const 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(struct wlr_backend *backend);
|
||||
bool wlr_backend_is_multi(const 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(struct wlr_backend *backend);
|
||||
bool wlr_backend_is_wl(const 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(struct wlr_output *output);
|
||||
bool wlr_output_is_wl(const 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(struct wlr_backend *backend);
|
||||
bool wlr_backend_is_x11(const 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(struct wlr_output *output);
|
||||
bool wlr_output_is_x11(const struct wlr_output *output);
|
||||
|
||||
/**
|
||||
* Sets the title of a struct wlr_output which is an X11 window.
|
||||
|
|
|
|||
|
|
@ -42,9 +42,9 @@ struct wlr_gles2_texture_attribs {
|
|||
bool has_alpha;
|
||||
};
|
||||
|
||||
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);
|
||||
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);
|
||||
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(struct wlr_renderer *wlr_renderer);
|
||||
bool wlr_texture_is_pixman(struct wlr_texture *texture);
|
||||
bool wlr_renderer_is_pixman(const struct wlr_renderer *wlr_renderer);
|
||||
bool wlr_texture_is_pixman(const 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(struct wlr_renderer *wlr_renderer);
|
||||
bool wlr_texture_is_vk(struct wlr_texture *texture);
|
||||
bool wlr_renderer_is_vk(const struct wlr_renderer *wlr_renderer);
|
||||
bool wlr_texture_is_vk(const struct wlr_texture *texture);
|
||||
|
||||
void wlr_vk_texture_get_image_attribs(struct wlr_texture *texture,
|
||||
struct wlr_vk_image_attribs *attribs);
|
||||
|
|
|
|||
|
|
@ -49,30 +49,30 @@ struct wlr_cursor {
|
|||
* your responsibility.
|
||||
*/
|
||||
struct {
|
||||
struct wl_signal motion;
|
||||
struct wl_signal motion_absolute;
|
||||
struct wl_signal button;
|
||||
struct wl_signal axis;
|
||||
struct wl_signal motion; // struct wlr_pointer_motion_event
|
||||
struct wl_signal motion_absolute; // struct wlr_pointer_motion_absolute_event
|
||||
struct wl_signal button; // struct wlr_pointer_button_event
|
||||
struct wl_signal axis; // struct wlr_pointer_axis_event
|
||||
struct wl_signal frame;
|
||||
struct wl_signal swipe_begin;
|
||||
struct wl_signal swipe_update;
|
||||
struct wl_signal swipe_end;
|
||||
struct wl_signal pinch_begin;
|
||||
struct wl_signal pinch_update;
|
||||
struct wl_signal pinch_end;
|
||||
struct wl_signal hold_begin;
|
||||
struct wl_signal hold_end;
|
||||
struct wl_signal swipe_begin; // struct wlr_pointer_swipe_begin_event
|
||||
struct wl_signal swipe_update; // struct wlr_pointer_swipe_update_event
|
||||
struct wl_signal swipe_end; // struct wlr_pointer_swipe_end_event
|
||||
struct wl_signal pinch_begin; // struct wlr_pointer_pinch_begin_event
|
||||
struct wl_signal pinch_update; // struct wlr_pointer_pinch_update_event
|
||||
struct wl_signal pinch_end; // struct wlr_pointer_pinch_end_event
|
||||
struct wl_signal hold_begin; // struct wlr_pointer_hold_begin_event
|
||||
struct wl_signal hold_end; // struct wlr_pointer_hold_end_event
|
||||
|
||||
struct wl_signal touch_up;
|
||||
struct wl_signal touch_down;
|
||||
struct wl_signal touch_motion;
|
||||
struct wl_signal touch_cancel;
|
||||
struct wl_signal touch_up; // struct wlr_touch_up_event
|
||||
struct wl_signal touch_down; // struct wlr_touch_down_event
|
||||
struct wl_signal touch_motion; // struct wlr_touch_motion_event
|
||||
struct wl_signal touch_cancel; // struct wlr_touch_cancel_event
|
||||
struct wl_signal touch_frame;
|
||||
|
||||
struct wl_signal tablet_tool_axis;
|
||||
struct wl_signal tablet_tool_proximity;
|
||||
struct wl_signal tablet_tool_tip;
|
||||
struct wl_signal tablet_tool_button;
|
||||
struct wl_signal tablet_tool_axis; // struct wlr_tablet_tool_axis_event
|
||||
struct wl_signal tablet_tool_proximity; // struct wlr_tablet_tool_proximity_event
|
||||
struct wl_signal tablet_tool_tip; // struct wlr_tablet_tool_tip_event
|
||||
struct wl_signal tablet_tool_button; // struct wlr_tablet_tool_button_event
|
||||
} events;
|
||||
|
||||
void *data;
|
||||
|
|
|
|||
|
|
@ -131,8 +131,6 @@ struct wlr_scene_surface {
|
|||
struct wlr_addon addon;
|
||||
|
||||
struct wl_listener outputs_update;
|
||||
struct wl_listener output_enter;
|
||||
struct wl_listener output_leave;
|
||||
struct wl_listener output_sample;
|
||||
struct wl_listener frame_done;
|
||||
struct wl_listener surface_destroy;
|
||||
|
|
@ -171,8 +169,6 @@ 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;
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ struct wlr_switch {
|
|||
enum wlr_switch_type {
|
||||
WLR_SWITCH_TYPE_LID,
|
||||
WLR_SWITCH_TYPE_TABLET_MODE,
|
||||
WLR_SWITCH_TYPE_KEYPAD_SLIDE,
|
||||
};
|
||||
|
||||
enum wlr_switch_state {
|
||||
|
|
|
|||
|
|
@ -33,12 +33,27 @@ struct wlr_virtual_keyboard_v1 {
|
|||
bool has_keymap;
|
||||
|
||||
struct wl_list link; // wlr_virtual_keyboard_manager_v1.virtual_keyboards
|
||||
|
||||
struct {
|
||||
struct wl_listener seat_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_virtual_keyboard_manager_v1* wlr_virtual_keyboard_manager_v1_create(
|
||||
struct wl_display *display);
|
||||
|
||||
/**
|
||||
* Get the struct wlr_virtual_keyboard_v1 corresponding to a zwp_virtual_keyboard_v1 resource.
|
||||
*
|
||||
* Asserts that the resource is a valid zwp_virtual_keyboard_v1 resource created by wlroots.
|
||||
*
|
||||
* Returns NULL if the resource is inert.
|
||||
*/
|
||||
struct wlr_virtual_keyboard_v1 *wlr_virtual_keyboard_v1_from_resource(
|
||||
struct wl_resource *resource);
|
||||
|
||||
struct wlr_virtual_keyboard_v1 *wlr_input_device_get_virtual_keyboard(
|
||||
struct wlr_input_device *wlr_dev);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -107,6 +107,13 @@ 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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@
|
|||
/**
|
||||
* A still cursor image.
|
||||
*
|
||||
* The buffer contains pixels layed out in a packed DRM_FORMAT_ARGB8888 format.
|
||||
* The buffer contains pixels laid out in a packed DRM_FORMAT_ARGB8888 format.
|
||||
*/
|
||||
struct wlr_xcursor_image {
|
||||
uint32_t width; /* actual width */
|
||||
|
|
|
|||
|
|
@ -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(struct wlr_data_source *wlr_source);
|
||||
bool data_source_is_xwayland(const struct wlr_data_source *wlr_source);
|
||||
bool primary_selection_source_is_xwayland(
|
||||
struct wlr_primary_selection_source *wlr_source);
|
||||
const 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.20.0-rc1',
|
||||
version: '0.20.0-rc4',
|
||||
license: 'MIT',
|
||||
meson_version: '>=1.3',
|
||||
default_options: [
|
||||
|
|
@ -178,6 +178,10 @@ if get_option('examples')
|
|||
subdir('tinywl')
|
||||
endif
|
||||
|
||||
if get_option('tests')
|
||||
subdir('test')
|
||||
endif
|
||||
|
||||
pkgconfig = import('pkgconfig')
|
||||
pkgconfig.generate(
|
||||
lib_wlr,
|
||||
|
|
|
|||
|
|
@ -7,5 +7,6 @@ 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')
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@
|
|||
|
||||
<request name="destroy" type="destructor">
|
||||
<description summary="delete this object, used or not">
|
||||
Unreferences the frame. This request must be called as soon as its no
|
||||
Unreferences the frame. This request must be called as soon as it's no
|
||||
longer used.
|
||||
|
||||
It can be called at any time by the client. The client will still have
|
||||
|
|
|
|||
|
|
@ -167,10 +167,9 @@ bool wlr_drm_syncobj_timeline_check(struct wlr_drm_syncobj_timeline *timeline,
|
|||
etime = ETIME;
|
||||
#endif
|
||||
|
||||
uint32_t signaled_point;
|
||||
int ret = drmSyncobjTimelineWait(timeline->drm_fd, &timeline->handle, &point, 1, 0, flags, &signaled_point);
|
||||
int ret = drmSyncobjTimelineWait(timeline->drm_fd, &timeline->handle, &point, 1, 0, flags, NULL);
|
||||
if (ret != 0 && ret != -etime) {
|
||||
wlr_log_errno(WLR_ERROR, "drmSyncobjWait() failed");
|
||||
wlr_log_errno(WLR_ERROR, "drmSyncobjTimelineWait() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -156,7 +156,7 @@ static void init_dmabuf_formats(struct wlr_egl *egl) {
|
|||
}
|
||||
|
||||
if (modifiers_len == 0) {
|
||||
// Asume the linear layout is supported if the driver doesn't
|
||||
// Assume the linear layout is supported if the driver doesn't
|
||||
// explicitly say otherwise
|
||||
wlr_drm_format_set_add(&egl->dmabuf_texture_formats, fmt,
|
||||
DRM_FORMAT_MOD_LINEAR);
|
||||
|
|
|
|||
|
|
@ -260,17 +260,26 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
|||
|
||||
const struct wlr_render_color *color = &options->color;
|
||||
struct wlr_box box;
|
||||
wlr_render_rect_options_get_box(options, pass->buffer->buffer, &box);
|
||||
struct wlr_buffer *wlr_buffer = pass->buffer->buffer;
|
||||
wlr_render_rect_options_get_box(options, wlr_buffer, &box);
|
||||
|
||||
push_gles2_debug(renderer);
|
||||
setup_blending(color->a == 1.0 ? WLR_RENDER_BLEND_MODE_NONE : options->blend_mode);
|
||||
|
||||
glUseProgram(renderer->shaders.quad.program);
|
||||
|
||||
set_proj_matrix(renderer->shaders.quad.proj, pass->projection_matrix, &box);
|
||||
glUniform4f(renderer->shaders.quad.color, color->r, color->g, color->b, color->a);
|
||||
|
||||
render(&box, options->clip, renderer->shaders.quad.pos_attrib);
|
||||
enum wlr_render_blend_mode blend_mode =
|
||||
color->a == 1.0 ? WLR_RENDER_BLEND_MODE_NONE : options->blend_mode;
|
||||
if (blend_mode == WLR_RENDER_BLEND_MODE_NONE &&
|
||||
options->clip == NULL &&
|
||||
box.x == 0 && box.y == 0 &&
|
||||
box.width == wlr_buffer->width &&
|
||||
box.height == wlr_buffer->height) {
|
||||
glClearColor(color->r, color->g, color->b, color->a);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
} else {
|
||||
setup_blending(blend_mode);
|
||||
glUseProgram(renderer->shaders.quad.program);
|
||||
set_proj_matrix(renderer->shaders.quad.proj, pass->projection_matrix, &box);
|
||||
glUniform4f(renderer->shaders.quad.color, color->r, color->g, color->b, color->a);
|
||||
render(&box, options->clip, renderer->shaders.quad.pos_attrib);
|
||||
}
|
||||
|
||||
pop_gles2_debug(renderer);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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(struct wlr_renderer *wlr_renderer) {
|
||||
bool wlr_renderer_is_gles2(const 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(struct wlr_render_timer *timer) {
|
||||
bool wlr_render_timer_is_gles2(const struct wlr_render_timer *timer) {
|
||||
return timer->impl == &render_timer_impl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
static const struct wlr_texture_impl texture_impl;
|
||||
|
||||
bool wlr_texture_is_gles2(struct wlr_texture *wlr_texture) {
|
||||
bool wlr_texture_is_gles2(const struct wlr_texture *wlr_texture) {
|
||||
return wlr_texture->impl == &texture_impl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -307,3 +307,68 @@ bool pixel_format_has_alpha(uint32_t fmt) {
|
|||
}
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,7 +78,7 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
|||
if (options->transform != WL_OUTPUT_TRANSFORM_NORMAL ||
|
||||
src_box_transformed.width != dst_box.width ||
|
||||
src_box_transformed.height != dst_box.height) {
|
||||
// Cosinus/sinus values are extact integers for enum wl_output_transform entries
|
||||
// Cosinus/sinus values are exact integers for enum wl_output_transform entries
|
||||
int tr_cos = 1, tr_sin = 0, tr_x = 0, tr_y = 0;
|
||||
switch (options->transform) {
|
||||
case WL_OUTPUT_TRANSFORM_NORMAL:
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
static const struct wlr_renderer_impl renderer_impl;
|
||||
|
||||
bool wlr_renderer_is_pixman(struct wlr_renderer *wlr_renderer) {
|
||||
bool wlr_renderer_is_pixman(const 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(struct wlr_texture *texture) {
|
||||
bool wlr_texture_is_pixman(const struct wlr_texture *texture) {
|
||||
return texture->impl == &texture_impl;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -146,6 +146,40 @@ static VkSemaphore render_pass_wait_sync_file(struct wlr_vk_render_pass *pass,
|
|||
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];
|
||||
for (size_t i = 0; i < WLR_DMABUF_MAX_PLANES; i++) {
|
||||
sync_file_fds[i] = -1;
|
||||
}
|
||||
|
||||
if (!vulkan_sync_render_buffer_acquire(pass->render_buffer, sync_file_fds)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < WLR_DMABUF_MAX_PLANES; i++) {
|
||||
if (sync_file_fds[i] < 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
render_wait[*render_wait_len_ptr] = (VkSemaphoreSubmitInfoKHR){
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SUBMIT_INFO_KHR,
|
||||
.semaphore = sem,
|
||||
.stageMask = VK_PIPELINE_STAGE_2_ALL_COMMANDS_BIT_KHR,
|
||||
};
|
||||
|
||||
(*render_wait_len_ptr)++;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool unwrap_color_transform(struct wlr_color_transform *transform,
|
||||
float matrix[static 9], enum wlr_color_transfer_function *tf) {
|
||||
if (transform == NULL) {
|
||||
|
|
@ -308,7 +342,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
|||
vkCmdEndRenderPass(render_cb->vk);
|
||||
|
||||
size_t pass_textures_len = pass->textures.size / sizeof(struct wlr_vk_render_pass_texture);
|
||||
size_t render_wait_cap = pass_textures_len * WLR_DMABUF_MAX_PLANES;
|
||||
size_t render_wait_cap = (1 + pass_textures_len) * WLR_DMABUF_MAX_PLANES;
|
||||
render_wait = calloc(render_wait_cap, sizeof(*render_wait));
|
||||
if (render_wait == NULL) {
|
||||
wlr_log_errno(WLR_ERROR, "Allocation failed");
|
||||
|
|
@ -386,7 +420,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
|||
sync_file_fds[0] = sync_file_fd;
|
||||
} else {
|
||||
struct wlr_vk_texture *texture = pass_texture->texture;
|
||||
if (!vulkan_sync_foreign_texture(texture, sync_file_fds)) {
|
||||
if (!vulkan_sync_foreign_texture_acquire(texture, sync_file_fds)) {
|
||||
wlr_log(WLR_ERROR, "Failed to wait for foreign texture DMA-BUF fence");
|
||||
continue;
|
||||
}
|
||||
|
|
@ -413,6 +447,10 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!render_pass_wait_render_buffer(pass, render_wait, &render_wait_len)) {
|
||||
wlr_log(WLR_ERROR, "Failed to wait for render buffer DMA-BUF fence");
|
||||
}
|
||||
|
||||
// also add acquire/release barriers for the current render buffer
|
||||
VkImageLayout src_layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
if (!pass->render_buffer_out->transitioned) {
|
||||
|
|
@ -606,8 +644,7 @@ static bool render_pass_submit(struct wlr_render_pass *wlr_pass) {
|
|||
wl_list_insert(&stage_cb->stage_buffers, &stage_buf->link);
|
||||
}
|
||||
|
||||
if (!vulkan_sync_render_buffer(renderer, render_buffer, render_cb,
|
||||
pass->signal_timeline, pass->signal_point)) {
|
||||
if (!vulkan_sync_render_pass_release(renderer, pass)) {
|
||||
wlr_log(WLR_ERROR, "Failed to sync render buffer");
|
||||
}
|
||||
|
||||
|
|
@ -822,12 +859,13 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -837,7 +875,7 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
|||
.source = WLR_VK_SHADER_SOURCE_TEXTURE,
|
||||
.layout = {
|
||||
.ycbcr = {
|
||||
.format = texture->format->is_ycbcr ? texture->format : NULL,
|
||||
.format = is_ycbcr ? texture->format : NULL,
|
||||
.encoding = color_encoding,
|
||||
.range = color_range,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -182,37 +182,30 @@ static const struct wlr_vk_format formats[] = {
|
|||
{
|
||||
.drm = DRM_FORMAT_UYVY,
|
||||
.vk = VK_FORMAT_B8G8R8G8_422_UNORM,
|
||||
.is_ycbcr = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_YUYV,
|
||||
.vk = VK_FORMAT_G8B8G8R8_422_UNORM,
|
||||
.is_ycbcr = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_NV12,
|
||||
.vk = VK_FORMAT_G8_B8R8_2PLANE_420_UNORM,
|
||||
.is_ycbcr = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_NV16,
|
||||
.vk = VK_FORMAT_G8_B8R8_2PLANE_422_UNORM,
|
||||
.is_ycbcr = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_YUV420,
|
||||
.vk = VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM,
|
||||
.is_ycbcr = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_YUV422,
|
||||
.vk = VK_FORMAT_G8_B8_R8_3PLANE_422_UNORM,
|
||||
.is_ycbcr = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_YUV444,
|
||||
.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
|
||||
// inverted channel order compared to DRM formats.
|
||||
|
|
@ -220,27 +213,22 @@ static const struct wlr_vk_format formats[] = {
|
|||
{
|
||||
.drm = DRM_FORMAT_P010,
|
||||
.vk = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_420_UNORM_3PACK16,
|
||||
.is_ycbcr = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_P210,
|
||||
.vk = VK_FORMAT_G10X6_B10X6R10X6_2PLANE_422_UNORM_3PACK16,
|
||||
.is_ycbcr = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_P012,
|
||||
.vk = VK_FORMAT_G12X4_B12X4R12X4_2PLANE_420_UNORM_3PACK16,
|
||||
.is_ycbcr = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_P016,
|
||||
.vk = VK_FORMAT_G16_B16R16_2PLANE_420_UNORM,
|
||||
.is_ycbcr = true,
|
||||
},
|
||||
{
|
||||
.drm = DRM_FORMAT_Q410,
|
||||
.vk = VK_FORMAT_G10X6_B10X6_R10X6_3PLANE_444_UNORM_3PACK16,
|
||||
.is_ycbcr = true,
|
||||
},
|
||||
#endif
|
||||
// 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
|
||||
const char *errmsg = "unknown error";
|
||||
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};
|
||||
bool supported = false;
|
||||
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
|
||||
errmsg = "unknown error";
|
||||
VkFormatFeatureFlags features = dma_tex_features;
|
||||
if (props->format.is_ycbcr) {
|
||||
if (vulkan_format_is_ycbcr(&props->format)) {
|
||||
features |= ycbcr_tex_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,
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -551,7 +539,7 @@ void vulkan_format_props_query(struct wlr_vk_device *dev,
|
|||
char shm_texture_status[256];
|
||||
const char *errmsg = "unknown error";
|
||||
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;
|
||||
bool supported = false, has_mutable_srgb = false;
|
||||
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;
|
||||
}
|
||||
|
||||
bool vulkan_format_is_ycbcr(const struct wlr_vk_format *format) {
|
||||
return pixel_format_is_ycbcr(format->drm);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,7 @@ static bool default_debug = true;
|
|||
|
||||
static const struct wlr_renderer_impl renderer_impl;
|
||||
|
||||
bool wlr_renderer_is_vk(struct wlr_renderer *wlr_renderer) {
|
||||
bool wlr_renderer_is_vk(const struct wlr_renderer *wlr_renderer) {
|
||||
return wlr_renderer->impl == &renderer_impl;
|
||||
}
|
||||
|
||||
|
|
@ -968,13 +968,11 @@ static struct wlr_vk_render_buffer *get_render_buffer(
|
|||
return buffer;
|
||||
}
|
||||
|
||||
bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
|
||||
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]) {
|
||||
struct wlr_vk_renderer *renderer = texture->renderer;
|
||||
|
||||
static bool buffer_export_sync_file(struct wlr_vk_renderer *renderer, struct wlr_buffer *buffer,
|
||||
uint32_t flags, int sync_file_fds[static WLR_DMABUF_MAX_PLANES]) {
|
||||
struct wlr_dmabuf_attributes dmabuf = {0};
|
||||
if (!wlr_buffer_get_dmabuf(texture->buffer, &dmabuf)) {
|
||||
wlr_log(WLR_ERROR, "Failed to get texture DMA-BUF");
|
||||
if (!wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
|
||||
wlr_log(WLR_ERROR, "wlr_buffer_get_dmabuf() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -984,7 +982,7 @@ bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
|
|||
for (int i = 0; i < dmabuf.n_planes; i++) {
|
||||
struct pollfd pollfd = {
|
||||
.fd = dmabuf.fd[i],
|
||||
.events = POLLIN,
|
||||
.events = (flags & DMA_BUF_SYNC_WRITE) ? POLLOUT : POLLIN,
|
||||
};
|
||||
int timeout_ms = 1000;
|
||||
int ret = poll(&pollfd, 1, timeout_ms);
|
||||
|
|
@ -1001,7 +999,7 @@ bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
|
|||
}
|
||||
|
||||
for (int i = 0; i < dmabuf.n_planes; i++) {
|
||||
int sync_file_fd = dmabuf_export_sync_file(dmabuf.fd[i], DMA_BUF_SYNC_READ);
|
||||
int sync_file_fd = dmabuf_export_sync_file(dmabuf.fd[i], flags);
|
||||
if (sync_file_fd < 0) {
|
||||
wlr_log(WLR_ERROR, "Failed to extract DMA-BUF fence");
|
||||
return false;
|
||||
|
|
@ -1013,12 +1011,40 @@ bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
|
|||
return true;
|
||||
}
|
||||
|
||||
bool vulkan_sync_render_buffer(struct wlr_vk_renderer *renderer,
|
||||
struct wlr_vk_render_buffer *render_buffer, struct wlr_vk_command_buffer *cb,
|
||||
struct wlr_drm_syncobj_timeline *signal_timeline, uint64_t signal_point) {
|
||||
VkResult res;
|
||||
bool vulkan_sync_foreign_texture_acquire(struct wlr_vk_texture *texture,
|
||||
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]) {
|
||||
return buffer_export_sync_file(texture->renderer, texture->buffer, DMA_BUF_SYNC_READ, sync_file_fds);
|
||||
}
|
||||
|
||||
if (!renderer->dev->implicit_sync_interop && signal_timeline == NULL) {
|
||||
bool vulkan_sync_render_buffer_acquire(struct wlr_vk_render_buffer *render_buffer,
|
||||
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]) {
|
||||
return buffer_export_sync_file(render_buffer->renderer, render_buffer->wlr_buffer,
|
||||
DMA_BUF_SYNC_WRITE, sync_file_fds);
|
||||
}
|
||||
|
||||
static bool buffer_import_sync_file(struct wlr_buffer *buffer, uint32_t flags, int sync_file_fd) {
|
||||
struct wlr_dmabuf_attributes dmabuf = {0};
|
||||
if (!wlr_buffer_get_dmabuf(buffer, &dmabuf)) {
|
||||
wlr_log(WLR_ERROR, "wlr_buffer_get_dmabuf() failed");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < dmabuf.n_planes; i++) {
|
||||
if (!dmabuf_import_sync_file(dmabuf.fd[i], flags,
|
||||
sync_file_fd)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool vulkan_sync_render_pass_release(struct wlr_vk_renderer *renderer,
|
||||
struct wlr_vk_render_pass *pass) {
|
||||
VkResult res;
|
||||
struct wlr_vk_command_buffer *cb = pass->command_buffer;
|
||||
|
||||
if (!renderer->dev->implicit_sync_interop && pass->signal_timeline == NULL) {
|
||||
// We have no choice but to block here sadly
|
||||
return vulkan_wait_command_buffer(cb, renderer);
|
||||
}
|
||||
|
|
@ -1040,21 +1066,19 @@ bool vulkan_sync_render_buffer(struct wlr_vk_renderer *renderer,
|
|||
}
|
||||
|
||||
bool ok = false;
|
||||
if (signal_timeline != NULL) {
|
||||
if (!wlr_drm_syncobj_timeline_import_sync_file(signal_timeline,
|
||||
signal_point, sync_file_fd)) {
|
||||
if (pass->signal_timeline != NULL) {
|
||||
if (!wlr_drm_syncobj_timeline_import_sync_file(pass->signal_timeline,
|
||||
pass->signal_point, sync_file_fd)) {
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
struct wlr_dmabuf_attributes dmabuf = {0};
|
||||
if (!wlr_buffer_get_dmabuf(render_buffer->wlr_buffer, &dmabuf)) {
|
||||
wlr_log(WLR_ERROR, "wlr_buffer_get_dmabuf failed");
|
||||
if (!buffer_import_sync_file(pass->render_buffer->wlr_buffer, DMA_BUF_SYNC_WRITE, sync_file_fd)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (int i = 0; i < dmabuf.n_planes; i++) {
|
||||
if (!dmabuf_import_sync_file(dmabuf.fd[i], DMA_BUF_SYNC_WRITE,
|
||||
sync_file_fd)) {
|
||||
struct wlr_vk_render_pass_texture *pass_texture;
|
||||
wl_array_for_each(pass_texture, &pass->textures) {
|
||||
if (!buffer_import_sync_file(pass_texture->texture->buffer, DMA_BUF_SYNC_READ, sync_file_fd)) {
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
|
@ -1164,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);
|
||||
vkDestroySamplerYcbcrConversion(dev->dev, pipeline_layout->ycbcr.conversion, NULL);
|
||||
renderer->dev->api.vkDestroySamplerYcbcrConversionKHR(dev->dev, pipeline_layout->ycbcr.conversion, NULL);
|
||||
free(pipeline_layout);
|
||||
}
|
||||
|
||||
|
|
@ -1630,8 +1654,8 @@ static bool init_blend_to_output_layouts(struct wlr_vk_renderer *renderer) {
|
|||
static bool pipeline_layout_key_equals(
|
||||
const struct wlr_vk_pipeline_layout_key *a,
|
||||
const struct wlr_vk_pipeline_layout_key *b) {
|
||||
assert(!a->ycbcr.format || a->ycbcr.format->is_ycbcr);
|
||||
assert(!b->ycbcr.format || b->ycbcr.format->is_ycbcr);
|
||||
assert(!a->ycbcr.format || vulkan_format_is_ycbcr(a->ycbcr.format));
|
||||
assert(!b->ycbcr.format || vulkan_format_is_ycbcr(b->ycbcr.format));
|
||||
|
||||
if (a->filter_mode != b->filter_mode) {
|
||||
return false;
|
||||
|
|
@ -2025,10 +2049,10 @@ struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout(
|
|||
.yChromaOffset = VK_CHROMA_LOCATION_MIDPOINT,
|
||||
.chromaFilter = VK_FILTER_LINEAR,
|
||||
};
|
||||
res = vkCreateSamplerYcbcrConversion(renderer->dev->dev,
|
||||
res = renderer->dev->api.vkCreateSamplerYcbcrConversionKHR(renderer->dev->dev,
|
||||
&conversion_create_info, NULL, &pipeline_layout->ycbcr.conversion);
|
||||
if (res != VK_SUCCESS) {
|
||||
wlr_vk_error("vkCreateSamplerYcbcrConversion", res);
|
||||
wlr_vk_error("vkCreateSamplerYcbcrConversionKHR", res);
|
||||
free(pipeline_layout);
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -2039,8 +2063,8 @@ struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout(
|
|||
};
|
||||
sampler_create_info.pNext = &conversion_info;
|
||||
} else {
|
||||
assert(key->ycbcr.encoding == WLR_COLOR_ENCODING_NONE);
|
||||
assert(key->ycbcr.range == WLR_COLOR_RANGE_NONE);
|
||||
assert(key->ycbcr.encoding == WLR_COLOR_ENCODING_NONE || key->ycbcr.encoding == WLR_COLOR_ENCODING_IDENTITY);
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#version 450
|
||||
|
||||
// we use a mat4 since it uses the same size as mat3 due to
|
||||
// alignment. Easier to deal with (tighly-packed) mat4 though.
|
||||
// alignment. Easier to deal with (tightly-packed) mat4 though.
|
||||
layout(push_constant, row_major) uniform UBO {
|
||||
mat4 proj;
|
||||
vec2 uv_offset;
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
static const struct wlr_texture_impl texture_impl;
|
||||
|
||||
bool wlr_texture_is_vk(struct wlr_texture *wlr_texture) {
|
||||
bool wlr_texture_is_vk(const struct wlr_texture *wlr_texture) {
|
||||
return wlr_texture->impl == &texture_impl;
|
||||
}
|
||||
|
||||
|
|
@ -189,7 +189,7 @@ void vulkan_texture_destroy(struct wlr_vk_texture *texture) {
|
|||
// when we recorded a command to fill this image _this_ frame,
|
||||
// it has to be executed before the texture can be destroyed.
|
||||
// Add it to the renderer->destroy_textures list, destroying
|
||||
// _after_ the stage command buffer has exectued
|
||||
// _after_ the stage command buffer has executed
|
||||
if (texture->last_used_cb != NULL) {
|
||||
assert(texture->destroy_link.next == NULL); // not already inserted
|
||||
wl_list_insert(&texture->last_used_cb->destroy_textures,
|
||||
|
|
@ -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.g = 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_ONE,
|
||||
.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;
|
||||
if (texture->format->is_ycbcr) {
|
||||
if (vulkan_format_is_ycbcr(texture->format)) {
|
||||
assert(pipeline_layout->ycbcr.conversion != VK_NULL_HANDLE);
|
||||
ycbcr_conversion_info = (VkSamplerYcbcrConversionInfo){
|
||||
.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,
|
||||
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->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);
|
||||
} else {
|
||||
// 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 =
|
||||
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);
|
||||
wlr_log(WLR_ERROR, "Unsupported pixel format %s (0x%08"PRIX32")",
|
||||
format_name, drm_fmt);
|
||||
|
|
@ -653,7 +653,7 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
|
|||
.sType = VK_STRUCTURE_TYPE_MEMORY_REQUIREMENTS_2,
|
||||
};
|
||||
|
||||
vkGetImageMemoryRequirements2(dev, &memri, &memr);
|
||||
renderer->dev->api.vkGetImageMemoryRequirements2KHR(dev, &memri, &memr);
|
||||
int mem = vulkan_find_mem_type(renderer->dev, 0,
|
||||
memr.memoryRequirements.memoryTypeBits & fdp.memoryTypeBits);
|
||||
if (mem < 0) {
|
||||
|
|
@ -712,7 +712,7 @@ VkImage vulkan_import_dmabuf(struct wlr_vk_renderer *renderer,
|
|||
}
|
||||
}
|
||||
|
||||
res = vkBindImageMemory2(dev, mem_count, bindi);
|
||||
res = renderer->dev->api.vkBindImageMemory2KHR(dev, mem_count, bindi);
|
||||
if (res != VK_SUCCESS) {
|
||||
wlr_vk_error("vkBindMemory failed", res);
|
||||
goto error_image;
|
||||
|
|
|
|||
|
|
@ -81,21 +81,6 @@ 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;
|
||||
|
|
@ -125,7 +110,18 @@ struct wlr_vk_instance *vulkan_instance_create(bool debug) {
|
|||
}
|
||||
|
||||
size_t extensions_len = 0;
|
||||
const char *extensions[1] = {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;
|
||||
}
|
||||
}
|
||||
|
||||
bool debug_utils_found = false;
|
||||
if (debug && check_extension(avail_ext_props, avail_extc,
|
||||
|
|
@ -140,7 +136,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_1,
|
||||
.apiVersion = VK_API_VERSION_1_0,
|
||||
};
|
||||
|
||||
VkInstanceCreateInfo instance_info = {
|
||||
|
|
@ -282,20 +278,10 @@ 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 additionaly 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,
|
||||
|
|
@ -474,6 +460,12 @@ 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])) {
|
||||
|
|
@ -630,6 +622,10 @@ 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);
|
||||
|
|
|
|||
154
test/bench_scene.c
Normal file
154
test/bench_scene.c
Normal file
|
|
@ -0,0 +1,154 @@
|
|||
#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;
|
||||
}
|
||||
10
test/meson.build
Normal file
10
test/meson.build
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
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
Normal file
149
test/test_box.c
Normal file
|
|
@ -0,0 +1,149 @@
|
|||
#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;
|
||||
}
|
||||
|
|
@ -614,7 +614,7 @@ static void server_new_output(struct wl_listener *listener, void *data) {
|
|||
struct wlr_output *wlr_output = data;
|
||||
|
||||
/* Configures the output created by the backend to use our allocator
|
||||
* and our renderer. Must be done once, before commiting the output */
|
||||
* and our renderer. Must be done once, before committing the output */
|
||||
wlr_output_init_render(wlr_output, server->allocator, server->renderer);
|
||||
|
||||
/* The output may be disabled, switch it on. */
|
||||
|
|
@ -723,7 +723,7 @@ static void xdg_toplevel_destroy(struct wl_listener *listener, void *data) {
|
|||
static void begin_interactive(struct tinywl_toplevel *toplevel,
|
||||
enum tinywl_cursor_mode mode, uint32_t edges) {
|
||||
/* This function sets up an interactive move or resize operation, where the
|
||||
* compositor stops propegating pointer events to clients and instead
|
||||
* compositor stops propagating pointer events to clients and instead
|
||||
* consumes them itself, to move or resize windows. */
|
||||
struct tinywl_server *server = toplevel->server;
|
||||
|
||||
|
|
@ -906,7 +906,7 @@ int main(int argc, char *argv[]) {
|
|||
|
||||
struct tinywl_server server = {0};
|
||||
/* The Wayland display is managed by libwayland. It handles accepting
|
||||
* clients from the Unix socket, manging Wayland globals, and so on. */
|
||||
* clients from the Unix socket, managing Wayland globals, and so on. */
|
||||
server.wl_display = wl_display_create();
|
||||
/* The backend is a wlroots feature which abstracts the underlying input and
|
||||
* output hardware. The autocreate option will choose the most suitable
|
||||
|
|
|
|||
|
|
@ -109,14 +109,11 @@ bool wlr_buffer_get_shm(struct wlr_buffer *buffer,
|
|||
|
||||
bool wlr_buffer_is_opaque(struct wlr_buffer *buffer) {
|
||||
void *data;
|
||||
uint32_t format;
|
||||
uint32_t format = buffer_get_drm_format(buffer);
|
||||
size_t stride;
|
||||
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;
|
||||
|
||||
if (format != DRM_FORMAT_INVALID) {
|
||||
// pass
|
||||
} else if (wlr_buffer_begin_data_ptr_access(buffer,
|
||||
WLR_BUFFER_DATA_PTR_ACCESS_READ, &data, &format, &stride)) {
|
||||
bool opaque = false;
|
||||
|
|
@ -135,3 +132,15 @@ bool wlr_buffer_is_opaque(struct wlr_buffer *buffer) {
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,6 +110,10 @@ static const struct wlr_ext_image_capture_source_v1_interface output_source_impl
|
|||
static void source_update_buffer_constraints(struct wlr_ext_output_image_capture_source_v1 *source) {
|
||||
struct wlr_output *output = source->output;
|
||||
|
||||
if (!output->enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!wlr_output_configure_primary_swapchain(output, NULL, &output->swapchain)) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -123,7 +127,8 @@ static void source_handle_output_commit(struct wl_listener *listener,
|
|||
struct wlr_ext_output_image_capture_source_v1 *source = wl_container_of(listener, source, output_commit);
|
||||
struct wlr_output_event_commit *event = data;
|
||||
|
||||
if (event->state->committed & (WLR_OUTPUT_STATE_MODE | WLR_OUTPUT_STATE_RENDER_FORMAT)) {
|
||||
if (event->state->committed & (WLR_OUTPUT_STATE_MODE |
|
||||
WLR_OUTPUT_STATE_RENDER_FORMAT | WLR_OUTPUT_STATE_ENABLED)) {
|
||||
source_update_buffer_constraints(source);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
struct scene_node_source *source = wl_container_of(output, source, output);
|
||||
|
||||
uint32_t supported =
|
||||
WLR_OUTPUT_STATE_BACKEND_OPTIONAL |
|
||||
WLR_OUTPUT_STATE_BUFFER |
|
||||
|
|
|
|||
|
|
@ -159,9 +159,8 @@ 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_intersection(&intersection, &output_box, &cursor_box);
|
||||
wlr_box_intersects(&output_box, &cursor_box);
|
||||
}
|
||||
|
||||
static bool output_pick_cursor_format(struct wlr_output *output,
|
||||
|
|
|
|||
|
|
@ -615,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_intersection(&output_box, &output_box, &dst_box)) {
|
||||
if (!wlr_box_intersects(&output_box, &dst_box)) {
|
||||
wlr_log(WLR_ERROR, "Primary buffer is entirely off-screen or 0-sized");
|
||||
return false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <stdlib.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_layer_shell_v1.h>
|
||||
#include <wlr/util/edges.h>
|
||||
|
||||
static void scene_layer_surface_handle_tree_destroy(
|
||||
struct wl_listener *listener, void *data) {
|
||||
|
|
@ -21,36 +22,23 @@ static void scene_layer_surface_handle_layer_surface_destroy(
|
|||
|
||||
static void layer_surface_exclusive_zone(
|
||||
struct wlr_layer_surface_v1_state *state,
|
||||
enum wlr_edges edge,
|
||||
struct wlr_box *usable_area) {
|
||||
switch (state->anchor) {
|
||||
case ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP:
|
||||
case (ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT):
|
||||
// Anchor top
|
||||
switch (edge) {
|
||||
case WLR_EDGE_NONE:
|
||||
return;
|
||||
case WLR_EDGE_TOP:
|
||||
usable_area->y += state->exclusive_zone + state->margin.top;
|
||||
usable_area->height -= state->exclusive_zone + state->margin.top;
|
||||
break;
|
||||
case ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM:
|
||||
case (ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT |
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT):
|
||||
// Anchor bottom
|
||||
case WLR_EDGE_BOTTOM:
|
||||
usable_area->height -= state->exclusive_zone + state->margin.bottom;
|
||||
break;
|
||||
case ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT:
|
||||
case (ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_LEFT):
|
||||
// Anchor left
|
||||
case WLR_EDGE_LEFT:
|
||||
usable_area->x += state->exclusive_zone + state->margin.left;
|
||||
usable_area->width -= state->exclusive_zone + state->margin.left;
|
||||
break;
|
||||
case ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT:
|
||||
case (ZWLR_LAYER_SURFACE_V1_ANCHOR_TOP |
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_BOTTOM |
|
||||
ZWLR_LAYER_SURFACE_V1_ANCHOR_RIGHT):
|
||||
// Anchor right
|
||||
case WLR_EDGE_RIGHT:
|
||||
usable_area->width -= state->exclusive_zone + state->margin.right;
|
||||
break;
|
||||
}
|
||||
|
|
@ -121,7 +109,8 @@ void wlr_scene_layer_surface_v1_configure(
|
|||
wlr_layer_surface_v1_configure(layer_surface, box.width, box.height);
|
||||
|
||||
if (layer_surface->surface->mapped && state->exclusive_zone > 0) {
|
||||
layer_surface_exclusive_zone(state, usable_area);
|
||||
enum wlr_edges edge = wlr_layer_surface_v1_get_exclusive_edge(layer_surface);
|
||||
layer_surface_exclusive_zone(state, edge, usable_area);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ static struct wlr_output *get_surface_frame_pacing_output(struct wlr_surface *su
|
|||
return frame_pacing_output;
|
||||
}
|
||||
|
||||
static bool get_tf_preference(enum wlr_color_transfer_function tf) {
|
||||
static int get_tf_preference(enum wlr_color_transfer_function tf) {
|
||||
switch (tf) {
|
||||
case WLR_COLOR_TRANSFER_FUNCTION_GAMMA22:
|
||||
return 0;
|
||||
|
|
@ -52,7 +52,7 @@ static bool get_tf_preference(enum wlr_color_transfer_function tf) {
|
|||
abort(); // unreachable
|
||||
}
|
||||
|
||||
static bool get_primaries_preference(enum wlr_color_named_primaries primaries) {
|
||||
static int get_primaries_preference(enum wlr_color_named_primaries primaries) {
|
||||
switch (primaries) {
|
||||
case WLR_COLOR_NAMED_PRIMARIES_SRGB:
|
||||
return 0;
|
||||
|
|
@ -94,14 +94,44 @@ static void handle_scene_buffer_outputs_update(
|
|||
struct wl_listener *listener, void *data) {
|
||||
struct wlr_scene_surface *surface =
|
||||
wl_container_of(listener, surface, outputs_update);
|
||||
struct wlr_scene_outputs_update_event *event = data;
|
||||
struct wlr_scene *scene = scene_node_get_root(&surface->buffer->node);
|
||||
|
||||
// If the surface is no longer visible on any output, keep the last sent
|
||||
// preferred configuration to avoid unnecessary redraws
|
||||
if (wl_list_empty(&surface->surface->current_outputs)) {
|
||||
if (event->size == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// To avoid sending redundant leave/enter events when a surface is hidden and then shown
|
||||
// without moving to a different output the following policy is implemented:
|
||||
//
|
||||
// 1. When a surface transitions from being visible on >0 outputs to being visible on 0 outputs
|
||||
// don't send any leave events.
|
||||
//
|
||||
// 2. When a surface transitions from being visible on 0 outputs to being visible on >0 outputs
|
||||
// send leave events for all entered outputs on which the surface is no longer visible as
|
||||
// well as enter events for any outputs not already entered.
|
||||
struct wlr_surface_output *entered_output, *tmp;
|
||||
wl_list_for_each_safe(entered_output, tmp, &surface->surface->current_outputs, link) {
|
||||
bool active = false;
|
||||
for (size_t i = 0; i < event->size; i++) {
|
||||
if (entered_output->output == event->active[i]->output) {
|
||||
active = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!active) {
|
||||
wlr_surface_send_leave(surface->surface, entered_output->output);
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < event->size; i++) {
|
||||
// This function internally checks if an enter event was already sent for the output
|
||||
// to avoid sending redundant events.
|
||||
wlr_surface_send_enter(surface->surface, event->active[i]->output);
|
||||
}
|
||||
|
||||
double scale = get_surface_preferred_buffer_scale(surface->surface);
|
||||
wlr_fractional_scale_v1_notify_scale(surface->surface, scale);
|
||||
wlr_surface_set_preferred_buffer_scale(surface->surface, ceil(scale));
|
||||
|
|
@ -114,24 +144,6 @@ static void handle_scene_buffer_outputs_update(
|
|||
}
|
||||
}
|
||||
|
||||
static void handle_scene_buffer_output_enter(
|
||||
struct wl_listener *listener, void *data) {
|
||||
struct wlr_scene_surface *surface =
|
||||
wl_container_of(listener, surface, output_enter);
|
||||
struct wlr_scene_output *output = data;
|
||||
|
||||
wlr_surface_send_enter(surface->surface, output->output);
|
||||
}
|
||||
|
||||
static void handle_scene_buffer_output_leave(
|
||||
struct wl_listener *listener, void *data) {
|
||||
struct wlr_scene_surface *surface =
|
||||
wl_container_of(listener, surface, output_leave);
|
||||
struct wlr_scene_output *output = data;
|
||||
|
||||
wlr_surface_send_leave(surface->surface, output->output);
|
||||
}
|
||||
|
||||
static void handle_scene_buffer_output_sample(
|
||||
struct wl_listener *listener, void *data) {
|
||||
struct wlr_scene_surface *surface =
|
||||
|
|
@ -380,8 +392,6 @@ static void surface_addon_destroy(struct wlr_addon *addon) {
|
|||
wlr_addon_finish(&surface->addon);
|
||||
|
||||
wl_list_remove(&surface->outputs_update.link);
|
||||
wl_list_remove(&surface->output_enter.link);
|
||||
wl_list_remove(&surface->output_leave.link);
|
||||
wl_list_remove(&surface->output_sample.link);
|
||||
wl_list_remove(&surface->frame_done.link);
|
||||
wl_list_remove(&surface->surface_destroy.link);
|
||||
|
|
@ -427,12 +437,6 @@ struct wlr_scene_surface *wlr_scene_surface_create(struct wlr_scene_tree *parent
|
|||
surface->outputs_update.notify = handle_scene_buffer_outputs_update;
|
||||
wl_signal_add(&scene_buffer->events.outputs_update, &surface->outputs_update);
|
||||
|
||||
surface->output_enter.notify = handle_scene_buffer_output_enter;
|
||||
wl_signal_add(&scene_buffer->events.output_enter, &surface->output_enter);
|
||||
|
||||
surface->output_leave.notify = handle_scene_buffer_output_leave;
|
||||
wl_signal_add(&scene_buffer->events.output_leave, &surface->output_leave);
|
||||
|
||||
surface->output_sample.notify = handle_scene_buffer_output_sample;
|
||||
wl_signal_add(&scene_buffer->events.output_sample, &surface->output_sample);
|
||||
|
||||
|
|
|
|||
|
|
@ -113,24 +113,11 @@ 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));
|
||||
|
|
@ -238,7 +225,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_intersection(&node_box, &node_box, box) &&
|
||||
if (wlr_box_intersects(&node_box, box) &&
|
||||
iterator(node, lx, ly, user_data)) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -481,28 +468,12 @@ 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(!scene_buffer->active_outputs || scene_buffer->primary_output);
|
||||
assert(!active_outputs || scene_buffer->primary_output);
|
||||
|
||||
// Skip output update event if nothing was updated
|
||||
if (old_active == active_outputs &&
|
||||
if (scene_buffer->active_outputs == active_outputs &&
|
||||
(!force || ((1ull << force->index) & ~active_outputs)) &&
|
||||
old_primary_output == scene_buffer->primary_output) {
|
||||
return;
|
||||
|
|
@ -515,6 +486,7 @@ 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;
|
||||
|
|
@ -524,6 +496,7 @@ 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);
|
||||
}
|
||||
|
||||
|
|
@ -869,8 +842,6 @@ 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);
|
||||
|
||||
|
|
@ -2086,8 +2057,12 @@ static enum scene_direct_scanout_result scene_entry_try_direct_scanout(
|
|||
return SCANOUT_INELIGIBLE;
|
||||
}
|
||||
|
||||
if (buffer->color_encoding != WLR_COLOR_ENCODING_NONE ||
|
||||
buffer->color_range != WLR_COLOR_RANGE_NONE) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
@ -2387,7 +2362,7 @@ bool wlr_scene_output_build_state(struct wlr_scene_output *scene_output,
|
|||
pixman_region32_init(&acc_damage);
|
||||
struct highlight_region *damage, *tmp_damage;
|
||||
wl_list_for_each_safe(damage, tmp_damage, regions, link) {
|
||||
// remove overlaping damage regions
|
||||
// remove overlapping damage regions
|
||||
pixman_region32_subtract(&damage->region, &damage->region, &acc_damage);
|
||||
pixman_region32_union(&acc_damage, &acc_damage, &damage->region);
|
||||
|
||||
|
|
@ -2669,8 +2644,7 @@ 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);
|
||||
|
||||
struct wlr_box intersection;
|
||||
if (wlr_box_intersection(&intersection, output_box, &node_box)) {
|
||||
if (wlr_box_intersects(output_box, &node_box)) {
|
||||
struct wlr_scene_buffer *scene_buffer =
|
||||
wlr_scene_buffer_from_node(node);
|
||||
user_iterator(scene_buffer, lx, ly, user_data);
|
||||
|
|
|
|||
|
|
@ -1,13 +1,17 @@
|
|||
#include <assert.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_color_representation_v1.h>
|
||||
#include <wlr/util/addon.h>
|
||||
#include <wlr/util/log.h>
|
||||
|
||||
#include "color-representation-v1-protocol.h"
|
||||
#include "render/pixel_format.h"
|
||||
#include "types/wlr_buffer.h"
|
||||
#include "util/mem.h"
|
||||
|
||||
#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);
|
||||
}
|
||||
|
||||
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 = {
|
||||
.state_size = sizeof(struct wlr_color_representation_v1_surface_state),
|
||||
.commit = surface_synced_commit
|
||||
};
|
||||
|
||||
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->surface = surface;
|
||||
|
||||
if (!wlr_surface_synced_init(&color_repr->synced, surface,
|
||||
&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];
|
||||
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++) {
|
||||
enum wp_color_representation_surface_v1_coefficients coeffs = coefficients[i];
|
||||
enum wlr_color_encoding enc = wlr_color_representation_v1_color_encoding_to_wlr(coeffs);
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
void *data) {
|
||||
struct wlr_tablet_tool_button *event = data;
|
||||
struct wlr_tablet_tool_button_event *event = data;
|
||||
struct wlr_cursor_device *device;
|
||||
device = wl_container_of(listener, device, tablet_tool_button);
|
||||
wl_signal_emit_mutable(&device->cursor->events.tablet_tool_button, event);
|
||||
|
|
|
|||
|
|
@ -518,14 +518,16 @@ static void cursor_session_handle_get_capture_session(struct wl_client *client,
|
|||
return;
|
||||
}
|
||||
|
||||
cursor_session->capture_session_created = true;
|
||||
|
||||
struct wlr_ext_image_copy_capture_manager_v1 *manager = NULL;
|
||||
struct wlr_ext_image_capture_source_v1 *source = NULL;
|
||||
|
||||
if (cursor_session != NULL) {
|
||||
manager = cursor_session->manager;
|
||||
cursor_session->capture_session_created = true;
|
||||
source = &cursor_session->source->base;
|
||||
}
|
||||
|
||||
session_create(cursor_session_resource, new_id, source, 0, cursor_session->manager);
|
||||
session_create(cursor_session_resource, new_id, source, 0, manager);
|
||||
}
|
||||
|
||||
static const struct ext_image_copy_capture_cursor_session_v1_interface cursor_session_impl = {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
struct keyboard_group_device *device, *tmp_device;
|
||||
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
|
||||
|
|
|
|||
|
|
@ -260,14 +260,12 @@ 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_intersection(&out_box, &output_box, target_lbox)) {
|
||||
if (wlr_box_intersects(&output_box, target_lbox)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -281,7 +279,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_intersection(&out_box, &output_box, target_lbox);
|
||||
return wlr_box_intersects(&output_box, target_lbox);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -505,7 +505,7 @@ static void capture_output(struct wl_client *wl_client,
|
|||
wl_resource_set_implementation(frame->resource, &frame_impl, frame,
|
||||
frame_handle_resource_destroy);
|
||||
|
||||
if (output == NULL) {
|
||||
if (output == NULL || !output->enabled) {
|
||||
wl_resource_set_user_data(frame->resource, NULL);
|
||||
zwlr_screencopy_frame_v1_send_failed(frame->resource);
|
||||
free(frame);
|
||||
|
|
@ -522,10 +522,6 @@ static void capture_output(struct wl_client *wl_client,
|
|||
wl_signal_add(&output->events.destroy, &frame->output_destroy);
|
||||
frame->output_destroy.notify = frame_handle_output_destroy;
|
||||
|
||||
if (output == NULL || !output->enabled) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
struct wlr_renderer *renderer = output->renderer;
|
||||
assert(renderer);
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ static const struct wlr_keyboard_impl keyboard_impl = {
|
|||
|
||||
static const struct zwp_virtual_keyboard_v1_interface virtual_keyboard_impl;
|
||||
|
||||
static struct wlr_virtual_keyboard_v1 *virtual_keyboard_from_resource(
|
||||
struct wlr_virtual_keyboard_v1 *wlr_virtual_keyboard_v1_from_resource(
|
||||
struct wl_resource *resource) {
|
||||
assert(wl_resource_instance_of(resource,
|
||||
&zwp_virtual_keyboard_v1_interface, &virtual_keyboard_impl));
|
||||
|
|
@ -39,7 +39,7 @@ static void virtual_keyboard_keymap(struct wl_client *client,
|
|||
struct wl_resource *resource, uint32_t format, int32_t fd,
|
||||
uint32_t size) {
|
||||
struct wlr_virtual_keyboard_v1 *keyboard =
|
||||
virtual_keyboard_from_resource(resource);
|
||||
wlr_virtual_keyboard_v1_from_resource(resource);
|
||||
if (keyboard == NULL) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -76,7 +76,7 @@ static void virtual_keyboard_key(struct wl_client *client,
|
|||
struct wl_resource *resource, uint32_t time, uint32_t key,
|
||||
uint32_t state) {
|
||||
struct wlr_virtual_keyboard_v1 *keyboard =
|
||||
virtual_keyboard_from_resource(resource);
|
||||
wlr_virtual_keyboard_v1_from_resource(resource);
|
||||
if (keyboard == NULL) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -99,7 +99,7 @@ static void virtual_keyboard_modifiers(struct wl_client *client,
|
|||
struct wl_resource *resource, uint32_t mods_depressed,
|
||||
uint32_t mods_latched, uint32_t mods_locked, uint32_t group) {
|
||||
struct wlr_virtual_keyboard_v1 *keyboard =
|
||||
virtual_keyboard_from_resource(resource);
|
||||
wlr_virtual_keyboard_v1_from_resource(resource);
|
||||
if (keyboard == NULL) {
|
||||
return;
|
||||
}
|
||||
|
|
@ -113,21 +113,24 @@ static void virtual_keyboard_modifiers(struct wl_client *client,
|
|||
mods_depressed, mods_latched, mods_locked, group);
|
||||
}
|
||||
|
||||
static void virtual_keyboard_destroy_resource(struct wl_resource *resource) {
|
||||
struct wlr_virtual_keyboard_v1 *keyboard =
|
||||
virtual_keyboard_from_resource(resource);
|
||||
if (keyboard == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_keyboard_finish(&keyboard->keyboard);
|
||||
|
||||
wl_resource_set_user_data(keyboard->resource, NULL);
|
||||
wl_list_remove(&keyboard->link);
|
||||
free(keyboard);
|
||||
static void virtual_keyboard_destroy(struct wlr_virtual_keyboard_v1 *virtual_keyboard) {
|
||||
wlr_keyboard_finish(&virtual_keyboard->keyboard);
|
||||
wl_resource_set_user_data(virtual_keyboard->resource, NULL);
|
||||
wl_list_remove(&virtual_keyboard->seat_destroy.link);
|
||||
wl_list_remove(&virtual_keyboard->link);
|
||||
free(virtual_keyboard);
|
||||
}
|
||||
|
||||
static void virtual_keyboard_destroy(struct wl_client *client,
|
||||
static void virtual_keyboard_destroy_resource(struct wl_resource *resource) {
|
||||
struct wlr_virtual_keyboard_v1 *virtual_keyboard =
|
||||
wlr_virtual_keyboard_v1_from_resource(resource);
|
||||
if (virtual_keyboard == NULL) {
|
||||
return;
|
||||
}
|
||||
virtual_keyboard_destroy(virtual_keyboard);
|
||||
}
|
||||
|
||||
static void virtual_keyboard_handle_destroy(struct wl_client *client,
|
||||
struct wl_resource *resource) {
|
||||
wl_resource_destroy(resource);
|
||||
}
|
||||
|
|
@ -136,7 +139,7 @@ static const struct zwp_virtual_keyboard_v1_interface virtual_keyboard_impl = {
|
|||
.keymap = virtual_keyboard_keymap,
|
||||
.key = virtual_keyboard_key,
|
||||
.modifiers = virtual_keyboard_modifiers,
|
||||
.destroy = virtual_keyboard_destroy,
|
||||
.destroy = virtual_keyboard_handle_destroy,
|
||||
};
|
||||
|
||||
static const struct zwp_virtual_keyboard_manager_v1_interface manager_impl;
|
||||
|
|
@ -148,6 +151,13 @@ static struct wlr_virtual_keyboard_manager_v1 *manager_from_resource(
|
|||
return wl_resource_get_user_data(resource);
|
||||
}
|
||||
|
||||
static void virtual_keyboard_handle_seat_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_virtual_keyboard_v1 *virtual_keyboard = wl_container_of(listener, virtual_keyboard,
|
||||
seat_destroy);
|
||||
virtual_keyboard_destroy(virtual_keyboard);
|
||||
}
|
||||
|
||||
static void virtual_keyboard_manager_create_virtual_keyboard(
|
||||
struct wl_client *client, struct wl_resource *resource,
|
||||
struct wl_resource *seat, uint32_t id) {
|
||||
|
|
@ -181,6 +191,9 @@ static void virtual_keyboard_manager_create_virtual_keyboard(
|
|||
virtual_keyboard->seat = seat_client->seat;
|
||||
wl_resource_set_user_data(keyboard_resource, virtual_keyboard);
|
||||
|
||||
wl_signal_add(&seat_client->events.destroy, &virtual_keyboard->seat_destroy);
|
||||
virtual_keyboard->seat_destroy.notify = virtual_keyboard_handle_seat_destroy;
|
||||
|
||||
wl_list_insert(&manager->virtual_keyboards, &virtual_keyboard->link);
|
||||
|
||||
wl_signal_emit_mutable(&manager->events.new_virtual_keyboard,
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ bool array_realloc(struct wl_array *arr, size_t size) {
|
|||
// If the size is less than 1/4th of the allocation size, we shrink it.
|
||||
// 1/4th is picked to provide hysteresis, without which an array with size
|
||||
// arr->alloc would constantly reallocate if an element is added and then
|
||||
// removed continously.
|
||||
// removed continuously.
|
||||
size_t alloc;
|
||||
if (arr->alloc > 0 && size > arr->alloc / 4) {
|
||||
alloc = arr->alloc;
|
||||
|
|
|
|||
25
util/box.c
25
util/box.c
|
|
@ -4,6 +4,14 @@
|
|||
#include <wlr/util/box.h>
|
||||
#include <wlr/util/log.h>
|
||||
|
||||
static int max(int a, int b) {
|
||||
return a > b ? a : b;
|
||||
}
|
||||
|
||||
static int min(int a, int b) {
|
||||
return a < b ? a : b;
|
||||
}
|
||||
|
||||
void wlr_box_closest_point(const struct wlr_box *box, double x, double y,
|
||||
double *dest_x, double *dest_y) {
|
||||
// if box is empty, then it contains no points, so no closest point either
|
||||
|
|
@ -56,10 +64,10 @@ bool wlr_box_intersection(struct wlr_box *dest, const struct wlr_box *box_a,
|
|||
return false;
|
||||
}
|
||||
|
||||
int x1 = fmax(box_a->x, box_b->x);
|
||||
int y1 = fmax(box_a->y, box_b->y);
|
||||
int x2 = fmin(box_a->x + box_a->width, box_b->x + box_b->width);
|
||||
int y2 = fmin(box_a->y + box_a->height, box_b->y + box_b->height);
|
||||
int x1 = max(box_a->x, box_b->x);
|
||||
int y1 = max(box_a->y, box_b->y);
|
||||
int x2 = min(box_a->x + box_a->width, box_b->x + box_b->width);
|
||||
int y2 = min(box_a->y + box_a->height, box_b->y + box_b->height);
|
||||
|
||||
dest->x = x1;
|
||||
dest->y = y1;
|
||||
|
|
@ -94,6 +102,15 @@ 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(
|
||||
struct wlr_data_source *wlr_source) {
|
||||
const 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(
|
||||
struct wlr_primary_selection_source *wlr_source) {
|
||||
const struct wlr_primary_selection_source *wlr_source) {
|
||||
return wlr_source->impl == &primary_selection_source_impl;
|
||||
}
|
||||
|
||||
|
|
@ -381,13 +381,15 @@ static bool source_get_targets(struct wlr_xwm_selection *selection,
|
|||
free(mime_type);
|
||||
break;
|
||||
}
|
||||
*mime_type_ptr = mime_type;
|
||||
|
||||
xcb_atom_t *atom_ptr =
|
||||
wl_array_add(mime_types_atoms, sizeof(*atom_ptr));
|
||||
if (atom_ptr == NULL) {
|
||||
mime_types->size -= sizeof(*mime_type_ptr);
|
||||
free(mime_type);
|
||||
break;
|
||||
}
|
||||
*mime_type_ptr = mime_type;
|
||||
*atom_ptr = value[i];
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -283,6 +283,8 @@ static bool xwm_selection_send_data(struct wlr_xwm_selection *selection,
|
|||
int p[2];
|
||||
if (pipe(p) == -1) {
|
||||
wlr_log_errno(WLR_ERROR, "pipe() failed");
|
||||
wl_array_release(&transfer->source_data);
|
||||
free(transfer);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <assert.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.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) {
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue