mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2025-11-03 09:01:40 -05:00
Compare commits
No commits in common. "master" and "0.18.0" have entirely different histories.
323 changed files with 3699 additions and 13574 deletions
|
|
@ -20,13 +20,8 @@ packages:
|
|||
- xwayland-dev
|
||||
- libseat-dev
|
||||
- hwdata-dev
|
||||
# for docs
|
||||
- go
|
||||
- zip
|
||||
sources:
|
||||
- https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||
artifacts:
|
||||
- public.zip
|
||||
tasks:
|
||||
- setup: |
|
||||
cd wlroots
|
||||
|
|
@ -42,16 +37,3 @@ tasks:
|
|||
- tinywl: |
|
||||
cd wlroots/tinywl
|
||||
make
|
||||
- docs: |
|
||||
go install 'codeberg.org/emersion/gyosu@latest'
|
||||
include_dir="$(echo /usr/local/include/wlroots-*)"
|
||||
~/go/bin/gyosu \
|
||||
-DWLR_USE_UNSTABLE \
|
||||
$(pkg-config --cflags-only-I $(basename "$include_dir")) \
|
||||
-Iwlroots/build/protocol/ \
|
||||
-fexported-symbols='wlr_*' -fexported-symbols='WLR_*' \
|
||||
-ffile-prefix-map="$include_dir/"= \
|
||||
-fsite-name=wlroots \
|
||||
-o public \
|
||||
"$include_dir/wlr/"
|
||||
zip -r ~/public.zip public/
|
||||
|
|
|
|||
|
|
@ -41,10 +41,9 @@ tasks:
|
|||
cd wlroots/build-gcc/tinywl
|
||||
sudo modprobe vkms
|
||||
udevadm settle
|
||||
card="/dev/dri/$(ls /sys/devices/faux/vkms/drm/ | grep ^card)"
|
||||
export WLR_BACKENDS=drm
|
||||
export WLR_RENDERER=pixman
|
||||
export WLR_DRM_DEVICES="$card"
|
||||
export WLR_DRM_DEVICES=/dev/dri/by-path/platform-vkms-card
|
||||
export UBSAN_OPTIONS=halt_on_error=1
|
||||
sudo chmod ugo+rw "$card"
|
||||
sudo chmod ugo+rw /dev/dri/by-path/platform-vkms-card
|
||||
sudo -E seatd-launch -- ./tinywl -s 'kill $PPID' || [ $? = 143 ]
|
||||
|
|
|
|||
|
|
@ -20,18 +20,19 @@ packages:
|
|||
- x11/xcb-util-errors
|
||||
- x11/xcb-util-renderutil
|
||||
- x11/xcb-util-wm
|
||||
- x11-servers/xwayland
|
||||
- x11-servers/xwayland-devel
|
||||
- sysutils/libdisplay-info
|
||||
- sysutils/seatd
|
||||
- gmake
|
||||
- hwdata
|
||||
sources:
|
||||
- https://gitlab.freedesktop.org/wlroots/wlroots.git
|
||||
tasks:
|
||||
- wlroots: |
|
||||
cd wlroots
|
||||
meson setup build --fatal-meson-warnings -Dauto_features=enabled -Dallocators=gbm
|
||||
meson setup build --fatal-meson-warnings -Dauto_features=enabled
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
- tinywl: |
|
||||
cd wlroots/tinywl
|
||||
make
|
||||
gmake
|
||||
|
|
|
|||
3
.gitignore
vendored
3
.gitignore
vendored
|
|
@ -1,2 +1 @@
|
|||
/subprojects/*
|
||||
!/subprojects/*.wrap
|
||||
/subprojects/
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
include: https://git.sr.ht/~emersion/dalligi/blob/master/templates/multi.yml
|
||||
alpine:
|
||||
extends: .dalligi
|
||||
pages: true
|
||||
archlinux:
|
||||
extends: .dalligi
|
||||
freebsd:
|
||||
|
|
|
|||
1
.mailmap
1
.mailmap
|
|
@ -1,2 +1 @@
|
|||
Isaac Freund <mail@isaacfreund.com> <ifreund@ifreund.xyz>
|
||||
Kirill Primak <vyivel@eclair.cafe> <vyivel@posteo.net>
|
||||
|
|
|
|||
|
|
@ -213,27 +213,6 @@ reinitialized to be used again.
|
|||
it, and free the memory. Such functions should always be able to accept a NULL
|
||||
pointer.
|
||||
|
||||
If the object has signals, the destructor function must assert that their
|
||||
listener lists are empty.
|
||||
|
||||
```c
|
||||
void wlr_thing_init(struct wlr_thing *thing) {
|
||||
*thing = (struct wlr_thing){
|
||||
// ...
|
||||
};
|
||||
|
||||
wl_signal_init(&thing->events.destroy);
|
||||
wl_signal_init(&thing->events.foo);
|
||||
}
|
||||
|
||||
void wlr_thing_finish(struct wlr_thing *thing) {
|
||||
wl_signal_emit_mutable(&thing->events.destroy, NULL);
|
||||
|
||||
assert(wl_list_empty(&thing->events.destroy.listener_list));
|
||||
assert(wl_list_empty(&thing->events.foo.listener_list));
|
||||
}
|
||||
```
|
||||
|
||||
### Error Codes
|
||||
|
||||
For functions not returning a value, they should return a (stdbool.h) bool to
|
||||
|
|
@ -258,13 +237,6 @@ used and `#undef` them after.
|
|||
* Document the contents and container of a `struct wl_list` with a
|
||||
`// content.link` and `// container.list` comment.
|
||||
|
||||
### Private fields
|
||||
|
||||
Wrap private fields of public structures with `struct { … } WLR_PRIVATE`. This
|
||||
ensures that compositor authors don't use them by accident. Within wlroots
|
||||
`WLR_PRIVATE` is expanded to nothing, so private fields are accessed in the same
|
||||
way as public ones.
|
||||
|
||||
### Safety
|
||||
|
||||
* Avoid string manipulation functions which don't take the size of the
|
||||
|
|
@ -353,14 +325,12 @@ struct wlr_compositor {
|
|||
struct wl_global *global;
|
||||
…
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
|
||||
struct {
|
||||
struct wl_signal new_surface;
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -11,6 +12,9 @@
|
|||
#include <wlr/config.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/backend.h"
|
||||
#include "backend/multi.h"
|
||||
#include "render/allocator/allocator.h"
|
||||
#include "types/wlr_output.h"
|
||||
#include "util/env.h"
|
||||
#include "util/time.h"
|
||||
|
|
@ -46,10 +50,6 @@ void wlr_backend_init(struct wlr_backend *backend,
|
|||
|
||||
void wlr_backend_finish(struct wlr_backend *backend) {
|
||||
wl_signal_emit_mutable(&backend->events.destroy, backend);
|
||||
|
||||
assert(wl_list_empty(&backend->events.destroy.listener_list));
|
||||
assert(wl_list_empty(&backend->events.new_input.listener_list));
|
||||
assert(wl_list_empty(&backend->events.new_output.listener_list));
|
||||
}
|
||||
|
||||
bool wlr_backend_start(struct wlr_backend *backend) {
|
||||
|
|
@ -121,6 +121,14 @@ int wlr_backend_get_drm_fd(struct wlr_backend *backend) {
|
|||
return backend->impl->get_drm_fd(backend);
|
||||
}
|
||||
|
||||
uint32_t backend_get_buffer_caps(struct wlr_backend *backend) {
|
||||
if (!backend->impl->get_buffer_caps) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return backend->impl->get_buffer_caps(backend);
|
||||
}
|
||||
|
||||
static size_t parse_outputs_env(const char *name) {
|
||||
const char *outputs_str = getenv(name);
|
||||
if (outputs_str == NULL) {
|
||||
|
|
@ -485,10 +493,5 @@ bool wlr_backend_commit(struct wlr_backend *backend,
|
|||
output_apply_commit(state->output, &state->base);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < states_len; i++) {
|
||||
const struct wlr_backend_output_state *state = &states[i];
|
||||
output_send_commit_event(state->output, &state->base);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,16 +1,13 @@
|
|||
#include <drm_fourcc.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <wlr/render/drm_syncobj.h>
|
||||
#include <wlr/util/box.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
#include "backend/drm/drm.h"
|
||||
#include "backend/drm/fb.h"
|
||||
#include "backend/drm/iface.h"
|
||||
#include "backend/drm/util.h"
|
||||
#include "render/color.h"
|
||||
|
||||
static char *atomic_commit_flags_str(uint32_t flags) {
|
||||
const char *const l[] = {
|
||||
|
|
@ -155,20 +152,18 @@ static bool create_gamma_lut_blob(struct wlr_drm_backend *drm,
|
|||
|
||||
bool create_fb_damage_clips_blob(struct wlr_drm_backend *drm,
|
||||
int width, int height, const pixman_region32_t *damage, uint32_t *blob_id) {
|
||||
if (!pixman_region32_not_empty(damage)) {
|
||||
*blob_id = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
pixman_region32_t clipped;
|
||||
pixman_region32_init(&clipped);
|
||||
pixman_region32_intersect_rect(&clipped, damage, 0, 0, width, height);
|
||||
|
||||
int rects_len;
|
||||
const pixman_box32_t *rects = pixman_region32_rectangles(&clipped, &rects_len);
|
||||
|
||||
int ret;
|
||||
if (rects_len > 0) {
|
||||
ret = drmModeCreatePropertyBlob(drm->fd, rects, sizeof(*rects) * rects_len, blob_id);
|
||||
} else {
|
||||
ret = 0;
|
||||
*blob_id = 0;
|
||||
}
|
||||
int ret = drmModeCreatePropertyBlob(drm->fd, rects, sizeof(*rects) * rects_len, blob_id);
|
||||
pixman_region32_fini(&clipped);
|
||||
if (ret != 0) {
|
||||
wlr_log_errno(WLR_ERROR, "Failed to create FB_DAMAGE_CLIPS property blob");
|
||||
|
|
@ -178,85 +173,6 @@ bool create_fb_damage_clips_blob(struct wlr_drm_backend *drm,
|
|||
return true;
|
||||
}
|
||||
|
||||
static uint8_t convert_cta861_eotf(enum wlr_color_transfer_function tf) {
|
||||
switch (tf) {
|
||||
case WLR_COLOR_TRANSFER_FUNCTION_SRGB:
|
||||
abort(); // unsupported
|
||||
case WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ:
|
||||
return 2;
|
||||
case WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR:
|
||||
abort(); // unsupported
|
||||
case WLR_COLOR_TRANSFER_FUNCTION_GAMMA22:
|
||||
abort(); // unsupported
|
||||
case WLR_COLOR_TRANSFER_FUNCTION_BT1886:
|
||||
abort(); // unsupported
|
||||
}
|
||||
abort(); // unreachable
|
||||
}
|
||||
|
||||
static uint16_t convert_cta861_color_coord(double v) {
|
||||
if (v < 0) {
|
||||
v = 0;
|
||||
}
|
||||
if (v > 1) {
|
||||
v = 1;
|
||||
}
|
||||
return (uint16_t)round(v * 50000);
|
||||
}
|
||||
|
||||
static bool create_hdr_output_metadata_blob(struct wlr_drm_backend *drm,
|
||||
const struct wlr_output_image_description *img_desc, uint32_t *blob_id) {
|
||||
if (img_desc == NULL) {
|
||||
*blob_id = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct hdr_output_metadata metadata = {
|
||||
.metadata_type = 0,
|
||||
.hdmi_metadata_type1 = {
|
||||
.eotf = convert_cta861_eotf(img_desc->transfer_function),
|
||||
.metadata_type = 0,
|
||||
.display_primaries = {
|
||||
{
|
||||
.x = convert_cta861_color_coord(img_desc->mastering_display_primaries.red.x),
|
||||
.y = convert_cta861_color_coord(img_desc->mastering_display_primaries.red.y),
|
||||
},
|
||||
{
|
||||
.x = convert_cta861_color_coord(img_desc->mastering_display_primaries.green.x),
|
||||
.y = convert_cta861_color_coord(img_desc->mastering_display_primaries.green.y),
|
||||
},
|
||||
{
|
||||
.x = convert_cta861_color_coord(img_desc->mastering_display_primaries.blue.x),
|
||||
.y = convert_cta861_color_coord(img_desc->mastering_display_primaries.blue.y),
|
||||
},
|
||||
},
|
||||
.white_point = {
|
||||
.x = convert_cta861_color_coord(img_desc->mastering_display_primaries.white.x),
|
||||
.y = convert_cta861_color_coord(img_desc->mastering_display_primaries.white.y),
|
||||
},
|
||||
.max_display_mastering_luminance = img_desc->mastering_luminance.max,
|
||||
.min_display_mastering_luminance = img_desc->mastering_luminance.min * 0.0001,
|
||||
.max_cll = img_desc->max_cll,
|
||||
.max_fall = img_desc->max_fall,
|
||||
},
|
||||
};
|
||||
if (drmModeCreatePropertyBlob(drm->fd, &metadata, sizeof(metadata), blob_id) != 0) {
|
||||
wlr_log_errno(WLR_ERROR, "Failed to create HDR_OUTPUT_METADATA property");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint64_t convert_primaries_to_colorspace(uint32_t primaries) {
|
||||
switch (primaries) {
|
||||
case 0:
|
||||
return 0; // Default
|
||||
case WLR_COLOR_NAMED_PRIMARIES_BT2020:
|
||||
return 9; // BT2020_RGB
|
||||
}
|
||||
abort(); // unreachable
|
||||
}
|
||||
|
||||
static uint64_t max_bpc_for_format(uint32_t format) {
|
||||
switch (format) {
|
||||
case DRM_FORMAT_XRGB2101010:
|
||||
|
|
@ -331,25 +247,19 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo
|
|||
}
|
||||
|
||||
uint32_t gamma_lut = crtc->gamma_lut;
|
||||
if (state->base->committed & WLR_OUTPUT_STATE_COLOR_TRANSFORM) {
|
||||
size_t dim = 0;
|
||||
uint16_t *lut = NULL;
|
||||
if (state->base->color_transform != NULL) {
|
||||
struct wlr_color_transform_lut_3x1d *tr =
|
||||
color_transform_lut_3x1d_from_base(state->base->color_transform);
|
||||
dim = tr->dim;
|
||||
lut = tr->lut_3x1d;
|
||||
}
|
||||
|
||||
if (state->base->committed & WLR_OUTPUT_STATE_GAMMA_LUT) {
|
||||
// Fallback to legacy gamma interface when gamma properties are not
|
||||
// available (can happen on older Intel GPUs that support gamma but not
|
||||
// degamma).
|
||||
if (crtc->props.gamma_lut == 0) {
|
||||
if (!drm_legacy_crtc_set_gamma(drm, crtc, dim, lut)) {
|
||||
if (!drm_legacy_crtc_set_gamma(drm, crtc,
|
||||
state->base->gamma_lut_size,
|
||||
state->base->gamma_lut)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!create_gamma_lut_blob(drm, dim, lut, &gamma_lut)) {
|
||||
if (!create_gamma_lut_blob(drm, state->base->gamma_lut_size,
|
||||
state->base->gamma_lut, &gamma_lut)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -362,15 +272,6 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo
|
|||
state->primary_fb->wlr_buf->height, &state->base->damage, &fb_damage_clips);
|
||||
}
|
||||
|
||||
int in_fence_fd = -1;
|
||||
if (state->wait_timeline != NULL) {
|
||||
in_fence_fd = wlr_drm_syncobj_timeline_export_sync_file(state->wait_timeline,
|
||||
state->wait_point);
|
||||
if (in_fence_fd < 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool prev_vrr_enabled =
|
||||
output->adaptive_sync_status == WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED;
|
||||
bool vrr_enabled = prev_vrr_enabled;
|
||||
|
|
@ -381,25 +282,10 @@ bool drm_atomic_connector_prepare(struct wlr_drm_connector_state *state, bool mo
|
|||
vrr_enabled = state->base->adaptive_sync_enabled;
|
||||
}
|
||||
|
||||
uint32_t colorspace = conn->colorspace;
|
||||
if (state->base->committed & WLR_OUTPUT_STATE_IMAGE_DESCRIPTION) {
|
||||
colorspace = convert_primaries_to_colorspace(
|
||||
state->base->image_description ? state->base->image_description->primaries : 0);
|
||||
}
|
||||
|
||||
uint32_t hdr_output_metadata = conn->hdr_output_metadata;
|
||||
if ((state->base->committed & WLR_OUTPUT_STATE_IMAGE_DESCRIPTION) &&
|
||||
!create_hdr_output_metadata_blob(drm, state->base->image_description, &hdr_output_metadata)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
state->mode_id = mode_id;
|
||||
state->gamma_lut = gamma_lut;
|
||||
state->fb_damage_clips = fb_damage_clips;
|
||||
state->primary_in_fence_fd = in_fence_fd;
|
||||
state->vrr_enabled = vrr_enabled;
|
||||
state->colorspace = colorspace;
|
||||
state->hdr_output_metadata = hdr_output_metadata;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -414,23 +300,11 @@ void drm_atomic_connector_apply_commit(struct wlr_drm_connector_state *state) {
|
|||
crtc->own_mode_id = true;
|
||||
commit_blob(drm, &crtc->mode_id, state->mode_id);
|
||||
commit_blob(drm, &crtc->gamma_lut, state->gamma_lut);
|
||||
commit_blob(drm, &conn->hdr_output_metadata, state->hdr_output_metadata);
|
||||
|
||||
conn->output.adaptive_sync_status = state->vrr_enabled ?
|
||||
WLR_OUTPUT_ADAPTIVE_SYNC_ENABLED : WLR_OUTPUT_ADAPTIVE_SYNC_DISABLED;
|
||||
|
||||
destroy_blob(drm, state->fb_damage_clips);
|
||||
if (state->primary_in_fence_fd >= 0) {
|
||||
close(state->primary_in_fence_fd);
|
||||
}
|
||||
if (state->out_fence_fd >= 0) {
|
||||
// TODO: error handling
|
||||
wlr_drm_syncobj_timeline_import_sync_file(state->base->signal_timeline,
|
||||
state->base->signal_point, state->out_fence_fd);
|
||||
close(state->out_fence_fd);
|
||||
}
|
||||
|
||||
conn->colorspace = state->colorspace;
|
||||
}
|
||||
|
||||
void drm_atomic_connector_rollback_commit(struct wlr_drm_connector_state *state) {
|
||||
|
|
@ -440,15 +314,8 @@ void drm_atomic_connector_rollback_commit(struct wlr_drm_connector_state *state)
|
|||
|
||||
rollback_blob(drm, &crtc->mode_id, state->mode_id);
|
||||
rollback_blob(drm, &crtc->gamma_lut, state->gamma_lut);
|
||||
rollback_blob(drm, &conn->hdr_output_metadata, state->hdr_output_metadata);
|
||||
|
||||
destroy_blob(drm, state->fb_damage_clips);
|
||||
if (state->primary_in_fence_fd >= 0) {
|
||||
close(state->primary_in_fence_fd);
|
||||
}
|
||||
if (state->out_fence_fd >= 0) {
|
||||
close(state->out_fence_fd);
|
||||
}
|
||||
}
|
||||
|
||||
static void plane_disable(struct atomic *atom, struct wlr_drm_plane *plane) {
|
||||
|
|
@ -460,8 +327,7 @@ static void plane_disable(struct atomic *atom, struct wlr_drm_plane *plane) {
|
|||
|
||||
static void set_plane_props(struct atomic *atom, struct wlr_drm_backend *drm,
|
||||
struct wlr_drm_plane *plane, struct wlr_drm_fb *fb, uint32_t crtc_id,
|
||||
const struct wlr_box *dst_box,
|
||||
const struct wlr_fbox *src_box) {
|
||||
int32_t x, int32_t y) {
|
||||
uint32_t id = plane->id;
|
||||
const struct wlr_drm_plane_props *props = &plane->props;
|
||||
|
||||
|
|
@ -471,50 +337,28 @@ static void set_plane_props(struct atomic *atom, struct wlr_drm_backend *drm,
|
|||
return;
|
||||
}
|
||||
|
||||
uint32_t width = fb->wlr_buf->width;
|
||||
uint32_t height = fb->wlr_buf->height;
|
||||
|
||||
// The src_* properties are in 16.16 fixed point
|
||||
atomic_add(atom, id, props->src_x, src_box->x * (1 << 16));
|
||||
atomic_add(atom, id, props->src_y, src_box->y * (1 << 16));
|
||||
atomic_add(atom, id, props->src_w, src_box->width * (1 << 16));
|
||||
atomic_add(atom, id, props->src_h, src_box->height * (1 << 16));
|
||||
atomic_add(atom, id, props->src_x, 0);
|
||||
atomic_add(atom, id, props->src_y, 0);
|
||||
atomic_add(atom, id, props->src_w, (uint64_t)width << 16);
|
||||
atomic_add(atom, id, props->src_h, (uint64_t)height << 16);
|
||||
atomic_add(atom, id, props->crtc_w, width);
|
||||
atomic_add(atom, id, props->crtc_h, height);
|
||||
atomic_add(atom, id, props->fb_id, fb->id);
|
||||
atomic_add(atom, id, props->crtc_id, crtc_id);
|
||||
atomic_add(atom, id, props->crtc_x, dst_box->x);
|
||||
atomic_add(atom, id, props->crtc_y, dst_box->y);
|
||||
atomic_add(atom, id, props->crtc_w, dst_box->width);
|
||||
atomic_add(atom, id, props->crtc_h, dst_box->height);
|
||||
atomic_add(atom, id, props->crtc_x, (uint64_t)x);
|
||||
atomic_add(atom, id, props->crtc_y, (uint64_t)y);
|
||||
}
|
||||
|
||||
static bool supports_cursor_hotspots(const struct wlr_drm_plane* plane) {
|
||||
return plane->props.hotspot_x && plane->props.hotspot_y;
|
||||
}
|
||||
|
||||
static void set_plane_in_fence_fd(struct atomic *atom,
|
||||
struct wlr_drm_plane *plane, int sync_file_fd) {
|
||||
if (!plane->props.in_fence_fd) {
|
||||
wlr_log(WLR_ERROR, "Plane %"PRIu32 " is missing the IN_FENCE_FD property",
|
||||
plane->id);
|
||||
atom->failed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
atomic_add(atom, plane->id, plane->props.in_fence_fd, sync_file_fd);
|
||||
}
|
||||
|
||||
static void set_crtc_out_fence_ptr(struct atomic *atom, struct wlr_drm_crtc *crtc,
|
||||
int *fd_ptr) {
|
||||
if (!crtc->props.out_fence_ptr) {
|
||||
wlr_log(WLR_ERROR,
|
||||
"CRTC %"PRIu32" is missing the OUT_FENCE_PTR property",
|
||||
crtc->id);
|
||||
atom->failed = true;
|
||||
return;
|
||||
}
|
||||
|
||||
atomic_add(atom, crtc->id, crtc->props.out_fence_ptr, (uintptr_t)fd_ptr);
|
||||
}
|
||||
|
||||
static void atomic_connector_add(struct atomic *atom,
|
||||
struct wlr_drm_connector_state *state, bool modeset) {
|
||||
const struct wlr_drm_connector_state *state, bool modeset) {
|
||||
struct wlr_drm_connector *conn = state->connector;
|
||||
struct wlr_drm_backend *drm = conn->backend;
|
||||
struct wlr_drm_crtc *crtc = conn->crtc;
|
||||
|
|
@ -532,12 +376,6 @@ static void atomic_connector_add(struct atomic *atom,
|
|||
if (modeset && active && conn->props.max_bpc != 0 && conn->max_bpc_bounds[1] != 0) {
|
||||
atomic_add(atom, conn->id, conn->props.max_bpc, pick_max_bpc(conn, state->primary_fb));
|
||||
}
|
||||
if (conn->props.colorspace != 0) {
|
||||
atomic_add(atom, conn->id, conn->props.colorspace, state->colorspace);
|
||||
}
|
||||
if (conn->props.hdr_output_metadata != 0) {
|
||||
atomic_add(atom, conn->id, conn->props.hdr_output_metadata, state->hdr_output_metadata);
|
||||
}
|
||||
atomic_add(atom, crtc->id, crtc->props.mode_id, state->mode_id);
|
||||
atomic_add(atom, crtc->id, crtc->props.active, active);
|
||||
if (active) {
|
||||
|
|
@ -547,33 +385,16 @@ static void atomic_connector_add(struct atomic *atom,
|
|||
if (crtc->props.vrr_enabled != 0) {
|
||||
atomic_add(atom, crtc->id, crtc->props.vrr_enabled, state->vrr_enabled);
|
||||
}
|
||||
|
||||
set_plane_props(atom, drm, crtc->primary, state->primary_fb, crtc->id,
|
||||
&state->primary_viewport.dst_box, &state->primary_viewport.src_box);
|
||||
0, 0);
|
||||
if (crtc->primary->props.fb_damage_clips != 0) {
|
||||
atomic_add(atom, crtc->primary->id,
|
||||
crtc->primary->props.fb_damage_clips, state->fb_damage_clips);
|
||||
}
|
||||
if (state->primary_in_fence_fd >= 0) {
|
||||
set_plane_in_fence_fd(atom, crtc->primary, state->primary_in_fence_fd);
|
||||
}
|
||||
if (state->base->committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE) {
|
||||
set_crtc_out_fence_ptr(atom, crtc, &state->out_fence_fd);
|
||||
}
|
||||
if (crtc->cursor) {
|
||||
if (drm_connector_is_cursor_visible(conn)) {
|
||||
struct wlr_fbox cursor_src = {
|
||||
.width = state->cursor_fb->wlr_buf->width,
|
||||
.height = state->cursor_fb->wlr_buf->height,
|
||||
};
|
||||
struct wlr_box cursor_dst = {
|
||||
.x = conn->cursor_x,
|
||||
.y = conn->cursor_y,
|
||||
.width = state->cursor_fb->wlr_buf->width,
|
||||
.height = state->cursor_fb->wlr_buf->height,
|
||||
};
|
||||
set_plane_props(atom, drm, crtc->cursor, state->cursor_fb,
|
||||
crtc->id, &cursor_dst, &cursor_src);
|
||||
crtc->id, conn->cursor_x, conn->cursor_y);
|
||||
if (supports_cursor_hotspots(crtc->cursor)) {
|
||||
atomic_add(atom, crtc->cursor->id,
|
||||
crtc->cursor->props.hotspot_x, conn->cursor_hotspot_x);
|
||||
|
|
@ -616,7 +437,7 @@ static bool atomic_device_commit(struct wlr_drm_backend *drm,
|
|||
if (state->modeset) {
|
||||
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||
}
|
||||
if (state->nonblock) {
|
||||
if (!test_only && state->nonblock) {
|
||||
flags |= DRM_MODE_ATOMIC_NONBLOCK;
|
||||
}
|
||||
|
||||
|
|
@ -635,6 +456,33 @@ out:
|
|||
return ok;
|
||||
}
|
||||
|
||||
bool drm_atomic_reset(struct wlr_drm_backend *drm) {
|
||||
struct atomic atom;
|
||||
atomic_begin(&atom);
|
||||
|
||||
for (size_t i = 0; i < drm->num_crtcs; i++) {
|
||||
struct wlr_drm_crtc *crtc = &drm->crtcs[i];
|
||||
atomic_add(&atom, crtc->id, crtc->props.mode_id, 0);
|
||||
atomic_add(&atom, crtc->id, crtc->props.active, 0);
|
||||
}
|
||||
|
||||
struct wlr_drm_connector *conn;
|
||||
wl_list_for_each(conn, &drm->connectors, link) {
|
||||
atomic_add(&atom, conn->id, conn->props.crtc_id, 0);
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < drm->num_planes; i++) {
|
||||
plane_disable(&atom, &drm->planes[i]);
|
||||
}
|
||||
|
||||
uint32_t flags = DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||
bool ok = atomic_commit(&atom, drm, NULL, NULL, flags);
|
||||
atomic_finish(&atom);
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
const struct wlr_drm_interface atomic_iface = {
|
||||
.commit = atomic_device_commit,
|
||||
.reset = drm_atomic_reset,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -1,8 +1,10 @@
|
|||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/backend/interface.h>
|
||||
#include <wlr/backend/session.h>
|
||||
|
|
@ -11,7 +13,6 @@
|
|||
#include <xf86drm.h>
|
||||
#include "backend/drm/drm.h"
|
||||
#include "backend/drm/fb.h"
|
||||
#include "render/drm_format_set.h"
|
||||
|
||||
struct wlr_drm_backend *get_drm_backend_from_backend(
|
||||
struct wlr_backend *wlr_backend) {
|
||||
|
|
@ -52,8 +53,7 @@ static void backend_destroy(struct wlr_backend *backend) {
|
|||
wl_list_remove(&drm->dev_change.link);
|
||||
wl_list_remove(&drm->dev_remove.link);
|
||||
|
||||
if (drm->mgpu_renderer.wlr_rend) {
|
||||
wlr_drm_format_set_finish(&drm->mgpu_formats);
|
||||
if (drm->parent) {
|
||||
finish_drm_renderer(&drm->mgpu_renderer);
|
||||
}
|
||||
|
||||
|
|
@ -75,6 +75,10 @@ static int backend_get_drm_fd(struct wlr_backend *backend) {
|
|||
return drm->fd;
|
||||
}
|
||||
|
||||
static uint32_t backend_get_buffer_caps(struct wlr_backend *backend) {
|
||||
return WLR_BUFFER_CAP_DMABUF;
|
||||
}
|
||||
|
||||
static bool backend_test(struct wlr_backend *backend,
|
||||
const struct wlr_backend_output_state *states, size_t states_len) {
|
||||
struct wlr_drm_backend *drm = get_drm_backend_from_backend(backend);
|
||||
|
|
@ -91,6 +95,7 @@ static const struct wlr_backend_impl backend_impl = {
|
|||
.start = backend_start,
|
||||
.destroy = backend_destroy,
|
||||
.get_drm_fd = backend_get_drm_fd,
|
||||
.get_buffer_caps = backend_get_buffer_caps,
|
||||
.test = backend_test,
|
||||
.commit = backend_commit,
|
||||
};
|
||||
|
|
@ -112,18 +117,11 @@ static void handle_session_active(struct wl_listener *listener, void *data) {
|
|||
wlr_log(WLR_INFO, "DRM FD %s", session->active ? "resumed" : "paused");
|
||||
|
||||
if (!session->active) {
|
||||
// Disconnect any active connectors so that the client will modeset and
|
||||
// rerender when the session is activated again.
|
||||
struct wlr_drm_connector *conn;
|
||||
wl_list_for_each(conn, &drm->connectors, link) {
|
||||
if (conn->status == DRM_MODE_CONNECTED) {
|
||||
wlr_output_destroy(&conn->output);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
scan_drm_connectors(drm, NULL);
|
||||
restore_drm_device(drm);
|
||||
}
|
||||
|
||||
static void handle_dev_change(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -167,44 +165,6 @@ static void handle_parent_destroy(struct wl_listener *listener, void *data) {
|
|||
backend_destroy(&drm->backend);
|
||||
}
|
||||
|
||||
static void sanitize_mgpu_modifiers(struct wlr_drm_format_set *set) {
|
||||
for (size_t idx = 0; idx < set->len; idx++) {
|
||||
// Implicit modifiers are not well-defined across devices, so strip
|
||||
// them from all formats in multi-gpu scenarios.
|
||||
struct wlr_drm_format *fmt = &set->formats[idx];
|
||||
wlr_drm_format_set_remove(set, fmt->format, DRM_FORMAT_MOD_INVALID);
|
||||
}
|
||||
}
|
||||
|
||||
static bool init_mgpu_renderer(struct wlr_drm_backend *drm) {
|
||||
if (!init_drm_renderer(drm, &drm->mgpu_renderer)) {
|
||||
wlr_log(WLR_INFO, "Failed to initialize mgpu blit renderer"
|
||||
", falling back to scanning out from primary GPU");
|
||||
|
||||
for (uint32_t plane_idx = 0; plane_idx < drm->num_planes; plane_idx++) {
|
||||
struct wlr_drm_plane *plane = &drm->planes[plane_idx];
|
||||
sanitize_mgpu_modifiers(&plane->formats);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// We'll perform a multi-GPU copy for all submitted buffers, we need
|
||||
// to be able to texture from them
|
||||
struct wlr_renderer *renderer = drm->mgpu_renderer.wlr_rend;
|
||||
const struct wlr_drm_format_set *texture_formats =
|
||||
wlr_renderer_get_texture_formats(renderer, WLR_BUFFER_CAP_DMABUF);
|
||||
if (texture_formats == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to query renderer texture formats");
|
||||
return false;
|
||||
}
|
||||
|
||||
wlr_drm_format_set_copy(&drm->mgpu_formats, texture_formats);
|
||||
sanitize_mgpu_modifiers(&drm->mgpu_formats);
|
||||
drm->backend.features.timeline = drm->backend.features.timeline &&
|
||||
drm->mgpu_renderer.wlr_rend->features.timeline;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session,
|
||||
struct wlr_device *dev, struct wlr_backend *parent) {
|
||||
assert(session && dev);
|
||||
|
|
@ -232,8 +192,6 @@ struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session,
|
|||
}
|
||||
wlr_backend_init(&drm->backend, &backend_impl);
|
||||
|
||||
drm->backend.buffer_caps = WLR_BUFFER_CAP_DMABUF;
|
||||
|
||||
drm->session = session;
|
||||
wl_list_init(&drm->fbs);
|
||||
wl_list_init(&drm->connectors);
|
||||
|
|
@ -276,10 +234,36 @@ struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session,
|
|||
goto error_event;
|
||||
}
|
||||
|
||||
if (drm->parent && !init_mgpu_renderer(drm)) {
|
||||
if (drm->parent) {
|
||||
if (!init_drm_renderer(drm, &drm->mgpu_renderer)) {
|
||||
wlr_log(WLR_ERROR, "Failed to initialize renderer");
|
||||
goto error_resources;
|
||||
}
|
||||
|
||||
// We'll perform a multi-GPU copy for all submitted buffers, we need
|
||||
// to be able to texture from them
|
||||
struct wlr_renderer *renderer = drm->mgpu_renderer.wlr_rend;
|
||||
const struct wlr_drm_format_set *texture_formats =
|
||||
wlr_renderer_get_texture_formats(renderer, WLR_BUFFER_CAP_DMABUF);
|
||||
if (texture_formats == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to query renderer texture formats");
|
||||
goto error_mgpu_renderer;
|
||||
}
|
||||
|
||||
// Forbid implicit modifiers, because their meaning changes from one
|
||||
// GPU to another.
|
||||
for (size_t i = 0; i < texture_formats->len; i++) {
|
||||
const struct wlr_drm_format *fmt = &texture_formats->formats[i];
|
||||
for (size_t j = 0; j < fmt->len; j++) {
|
||||
uint64_t mod = fmt->modifiers[j];
|
||||
if (mod == DRM_FORMAT_MOD_INVALID) {
|
||||
continue;
|
||||
}
|
||||
wlr_drm_format_set_add(&drm->mgpu_formats, fmt->format, mod);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
drm->session_destroy.notify = handle_session_destroy;
|
||||
wl_signal_add(&session->events.destroy, &drm->session_destroy);
|
||||
|
||||
|
|
@ -287,6 +271,7 @@ struct wlr_backend *wlr_drm_backend_create(struct wlr_session *session,
|
|||
|
||||
error_mgpu_renderer:
|
||||
finish_drm_renderer(&drm->mgpu_renderer);
|
||||
error_resources:
|
||||
finish_drm_resources(drm);
|
||||
error_event:
|
||||
wl_list_remove(&drm->session_active.link);
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include <assert.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <drm_mode.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <inttypes.h>
|
||||
#include <stdint.h>
|
||||
|
|
@ -13,7 +14,6 @@
|
|||
#include <wayland-util.h>
|
||||
#include <wlr/backend/interface.h>
|
||||
#include <wlr/interfaces/wlr_output.h>
|
||||
#include <wlr/render/drm_syncobj.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/util/box.h>
|
||||
#include <wlr/util/log.h>
|
||||
|
|
@ -24,7 +24,9 @@
|
|||
#include "backend/drm/fb.h"
|
||||
#include "backend/drm/iface.h"
|
||||
#include "backend/drm/util.h"
|
||||
#include "render/color.h"
|
||||
#include "render/pixel_format.h"
|
||||
#include "render/drm_format_set.h"
|
||||
#include "render/wlr_renderer.h"
|
||||
#include "types/wlr_output.h"
|
||||
#include "util/env.h"
|
||||
#include "config.h"
|
||||
|
|
@ -38,12 +40,9 @@ static const uint32_t COMMIT_OUTPUT_STATE =
|
|||
WLR_OUTPUT_STATE_BUFFER |
|
||||
WLR_OUTPUT_STATE_MODE |
|
||||
WLR_OUTPUT_STATE_ENABLED |
|
||||
WLR_OUTPUT_STATE_GAMMA_LUT |
|
||||
WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED |
|
||||
WLR_OUTPUT_STATE_LAYERS |
|
||||
WLR_OUTPUT_STATE_WAIT_TIMELINE |
|
||||
WLR_OUTPUT_STATE_SIGNAL_TIMELINE |
|
||||
WLR_OUTPUT_STATE_COLOR_TRANSFORM |
|
||||
WLR_OUTPUT_STATE_IMAGE_DESCRIPTION;
|
||||
WLR_OUTPUT_STATE_LAYERS;
|
||||
|
||||
static const uint32_t SUPPORTED_OUTPUT_STATE =
|
||||
WLR_OUTPUT_STATE_BACKEND_OPTIONAL | COMMIT_OUTPUT_STATE;
|
||||
|
|
@ -122,7 +121,6 @@ bool check_drm_features(struct wlr_drm_backend *drm) {
|
|||
drm->supports_tearing_page_flips = drmGetCap(drm->fd, DRM_CAP_ASYNC_PAGE_FLIP, &cap) == 0 && cap == 1;
|
||||
} else {
|
||||
drm->supports_tearing_page_flips = drmGetCap(drm->fd, DRM_CAP_ATOMIC_ASYNC_PAGE_FLIP, &cap) == 0 && cap == 1;
|
||||
drm->backend.features.timeline = drmGetCap(drm->fd, DRM_CAP_SYNCOBJ_TIMELINE, &cap) == 0 && cap == 1;
|
||||
}
|
||||
|
||||
if (env_parse_bool("WLR_DRM_NO_MODIFIERS")) {
|
||||
|
|
@ -172,7 +170,7 @@ static bool init_plane(struct wlr_drm_backend *drm,
|
|||
}
|
||||
|
||||
p->type = type;
|
||||
p->id = id;
|
||||
p->id = drm_plane->plane_id;
|
||||
p->props = props;
|
||||
p->initial_crtc_id = drm_plane->crtc_id;
|
||||
|
||||
|
|
@ -398,7 +396,6 @@ void finish_drm_resources(struct wlr_drm_backend *drm) {
|
|||
struct wlr_drm_plane *plane = &drm->planes[i];
|
||||
drm_plane_finish_surface(plane);
|
||||
wlr_drm_format_set_finish(&plane->formats);
|
||||
free(plane->cursor_sizes);
|
||||
}
|
||||
|
||||
free(drm->planes);
|
||||
|
|
@ -556,7 +553,6 @@ static void drm_connector_apply_commit(const struct wlr_drm_connector_state *sta
|
|||
struct wlr_drm_crtc *crtc = conn->crtc;
|
||||
|
||||
drm_fb_copy(&crtc->primary->queued_fb, state->primary_fb);
|
||||
crtc->primary->viewport = state->primary_viewport;
|
||||
if (crtc->cursor != NULL) {
|
||||
drm_fb_copy(&crtc->cursor->queued_fb, state->cursor_fb);
|
||||
}
|
||||
|
|
@ -580,16 +576,6 @@ static void drm_connector_apply_commit(const struct wlr_drm_connector_state *sta
|
|||
|
||||
conn->cursor_enabled = false;
|
||||
conn->crtc = NULL;
|
||||
|
||||
// Legacy uAPI doesn't support requesting page-flip events when
|
||||
// turning off a CRTC
|
||||
if (page_flip != NULL && conn->backend->iface == &legacy_iface) {
|
||||
drm_page_flip_pop(page_flip, crtc->id);
|
||||
conn->pending_page_flip = NULL;
|
||||
if (page_flip->connectors_len == 0) {
|
||||
drm_page_flip_destroy(page_flip);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -621,7 +607,6 @@ static bool drm_commit(struct wlr_drm_backend *drm,
|
|||
if (page_flip == NULL) {
|
||||
return false;
|
||||
}
|
||||
page_flip->async = (flags & DRM_MODE_PAGE_FLIP_ASYNC);
|
||||
}
|
||||
|
||||
bool ok = drm->iface->commit(drm, state, page_flip, flags, test_only);
|
||||
|
|
@ -645,8 +630,6 @@ static void drm_connector_state_init(struct wlr_drm_connector_state *state,
|
|||
.connector = conn,
|
||||
.base = base,
|
||||
.active = output_pending_enabled(&conn->output, base),
|
||||
.primary_in_fence_fd = -1,
|
||||
.out_fence_fd = -1,
|
||||
};
|
||||
|
||||
struct wlr_output_mode *mode = conn->output.current_mode;
|
||||
|
|
@ -656,7 +639,7 @@ static void drm_connector_state_init(struct wlr_drm_connector_state *state,
|
|||
|
||||
if (base->committed & WLR_OUTPUT_STATE_MODE) {
|
||||
switch (base->mode_type) {
|
||||
case WLR_OUTPUT_STATE_MODE_FIXED:
|
||||
case WLR_OUTPUT_STATE_MODE_FIXED:;
|
||||
mode = base->mode;
|
||||
break;
|
||||
case WLR_OUTPUT_STATE_MODE_CUSTOM:
|
||||
|
|
@ -683,10 +666,8 @@ static void drm_connector_state_init(struct wlr_drm_connector_state *state,
|
|||
struct wlr_drm_plane *primary = conn->crtc->primary;
|
||||
if (primary->queued_fb != NULL) {
|
||||
state->primary_fb = drm_fb_lock(primary->queued_fb);
|
||||
state->primary_viewport = primary->viewport;
|
||||
} else if (primary->current_fb != NULL) {
|
||||
state->primary_fb = drm_fb_lock(primary->current_fb);
|
||||
state->primary_viewport = primary->viewport;
|
||||
}
|
||||
|
||||
if (conn->cursor_enabled) {
|
||||
|
|
@ -706,7 +687,6 @@ static void drm_connector_state_init(struct wlr_drm_connector_state *state,
|
|||
static void drm_connector_state_finish(struct wlr_drm_connector_state *state) {
|
||||
drm_fb_clear(&state->primary_fb);
|
||||
drm_fb_clear(&state->cursor_fb);
|
||||
wlr_drm_syncobj_timeline_unref(state->wait_timeline);
|
||||
}
|
||||
|
||||
static bool drm_connector_state_update_primary_fb(struct wlr_drm_connector *conn,
|
||||
|
|
@ -721,16 +701,8 @@ static bool drm_connector_state_update_primary_fb(struct wlr_drm_connector *conn
|
|||
struct wlr_drm_plane *plane = crtc->primary;
|
||||
struct wlr_buffer *source_buf = state->base->buffer;
|
||||
|
||||
struct wlr_drm_syncobj_timeline *wait_timeline = NULL;
|
||||
uint64_t wait_point = 0;
|
||||
if (state->base->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) {
|
||||
wait_timeline = state->base->wait_timeline;
|
||||
wait_point = state->base->wait_point;
|
||||
}
|
||||
assert(state->wait_timeline == NULL);
|
||||
|
||||
struct wlr_buffer *local_buf;
|
||||
if (drm->mgpu_renderer.wlr_rend) {
|
||||
if (drm->parent) {
|
||||
struct wlr_drm_format format = {0};
|
||||
if (!drm_plane_pick_render_format(plane, &format, &drm->mgpu_renderer)) {
|
||||
wlr_log(WLR_ERROR, "Failed to pick primary plane format");
|
||||
|
|
@ -745,23 +717,12 @@ static bool drm_connector_state_update_primary_fb(struct wlr_drm_connector *conn
|
|||
return false;
|
||||
}
|
||||
|
||||
local_buf = drm_surface_blit(&plane->mgpu_surf, source_buf,
|
||||
wait_timeline, wait_point);
|
||||
local_buf = drm_surface_blit(&plane->mgpu_surf, source_buf);
|
||||
if (local_buf == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (plane->mgpu_surf.timeline != NULL) {
|
||||
state->wait_timeline = wlr_drm_syncobj_timeline_ref(plane->mgpu_surf.timeline);
|
||||
state->wait_point = plane->mgpu_surf.point;
|
||||
}
|
||||
} else {
|
||||
local_buf = wlr_buffer_lock(source_buf);
|
||||
|
||||
if (wait_timeline != NULL) {
|
||||
state->wait_timeline = wlr_drm_syncobj_timeline_ref(wait_timeline);
|
||||
state->wait_point = wait_point;
|
||||
}
|
||||
}
|
||||
|
||||
bool ok = drm_fb_import(&state->primary_fb, drm, local_buf,
|
||||
|
|
@ -773,9 +734,6 @@ static bool drm_connector_state_update_primary_fb(struct wlr_drm_connector *conn
|
|||
return false;
|
||||
}
|
||||
|
||||
output_state_get_buffer_src_box(state->base, &state->primary_viewport.src_box);
|
||||
output_state_get_buffer_dst_box(state->base, &state->primary_viewport.dst_box);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -784,7 +742,7 @@ static bool drm_connector_set_pending_layer_fbs(struct wlr_drm_connector *conn,
|
|||
struct wlr_drm_backend *drm = conn->backend;
|
||||
|
||||
struct wlr_drm_crtc *crtc = conn->crtc;
|
||||
if (!crtc || drm->mgpu_renderer.wlr_rend) {
|
||||
if (!crtc || drm->parent) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -826,13 +784,14 @@ static bool drm_connector_prepare(struct wlr_drm_connector_state *conn_state, bo
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled &&
|
||||
output->width == 0 && output->height == 0 &&
|
||||
if ((state->committed & WLR_OUTPUT_STATE_ENABLED) && state->enabled) {
|
||||
if (output->current_mode == NULL &&
|
||||
!(state->committed & WLR_OUTPUT_STATE_MODE)) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG,
|
||||
"Can't enable an output without a mode");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED) &&
|
||||
state->adaptive_sync_enabled &&
|
||||
|
|
@ -842,36 +801,7 @@ static bool drm_connector_prepare(struct wlr_drm_connector_state *conn_state, bo
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_BUFFER) && conn->backend->mgpu_renderer.wlr_rend) {
|
||||
struct wlr_dmabuf_attributes dmabuf;
|
||||
if (!wlr_buffer_get_dmabuf(state->buffer, &dmabuf)) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG, "Buffer is not a DMA-BUF");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!wlr_drm_format_set_has(&conn->backend->mgpu_formats, dmabuf.format, dmabuf.modifier)) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG,
|
||||
"Buffer format 0x%"PRIX32" with modifier 0x%"PRIX64" cannot be "
|
||||
"imported into multi-GPU renderer",
|
||||
dmabuf.format, dmabuf.modifier);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_COLOR_TRANSFORM) && state->color_transform != NULL &&
|
||||
state->color_transform->type != COLOR_TRANSFORM_LUT_3X1D) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG,
|
||||
"Only 3x1D LUT color transforms are supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_IMAGE_DESCRIPTION) &&
|
||||
conn->backend->iface != &atomic_iface) {
|
||||
wlr_log(WLR_DEBUG, "Image descriptions are only supported by the atomic interface");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (test_only && conn->backend->mgpu_renderer.wlr_rend) {
|
||||
if (test_only && conn->backend->parent) {
|
||||
// If we're running as a secondary GPU, we can't perform an atomic
|
||||
// commit without blitting a buffer.
|
||||
return true;
|
||||
|
|
@ -941,7 +871,7 @@ static bool drm_connector_commit_state(struct wlr_drm_connector *conn,
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (test_only && conn->backend->mgpu_renderer.wlr_rend) {
|
||||
if (test_only && conn->backend->parent) {
|
||||
// If we're running as a secondary GPU, we can't perform an atomic
|
||||
// commit without blitting a buffer.
|
||||
ok = true;
|
||||
|
|
@ -1138,7 +1068,7 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
|
|||
}
|
||||
|
||||
struct wlr_buffer *local_buf;
|
||||
if (drm->mgpu_renderer.wlr_rend) {
|
||||
if (drm->parent) {
|
||||
struct wlr_drm_format format = {0};
|
||||
if (!drm_plane_pick_render_format(plane, &format, &drm->mgpu_renderer)) {
|
||||
wlr_log(WLR_ERROR, "Failed to pick cursor plane format");
|
||||
|
|
@ -1152,7 +1082,7 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
|
|||
return false;
|
||||
}
|
||||
|
||||
local_buf = drm_surface_blit(&plane->mgpu_surf, buffer, NULL, 0);
|
||||
local_buf = drm_surface_blit(&plane->mgpu_surf, buffer);
|
||||
if (local_buf == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -1172,6 +1102,7 @@ static bool drm_connector_set_cursor(struct wlr_output *output,
|
|||
conn->cursor_height = buffer->height;
|
||||
}
|
||||
|
||||
wlr_output_update_needs_frame(output);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1201,6 +1132,7 @@ static bool drm_connector_move_cursor(struct wlr_output *output,
|
|||
conn->cursor_x = box.x;
|
||||
conn->cursor_y = box.y;
|
||||
|
||||
wlr_output_update_needs_frame(output);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -1223,8 +1155,6 @@ static void dealloc_crtc(struct wlr_drm_connector *conn);
|
|||
static void drm_connector_destroy_output(struct wlr_output *output) {
|
||||
struct wlr_drm_connector *conn = get_drm_connector_from_output(output);
|
||||
|
||||
wlr_output_finish(output);
|
||||
|
||||
dealloc_crtc(conn);
|
||||
|
||||
conn->status = DRM_MODE_DISCONNECTED;
|
||||
|
|
@ -1252,7 +1182,7 @@ static const struct wlr_drm_format_set *drm_connector_get_cursor_formats(
|
|||
if (!plane) {
|
||||
return NULL;
|
||||
}
|
||||
if (conn->backend->mgpu_renderer.wlr_rend) {
|
||||
if (conn->backend->parent) {
|
||||
return &conn->backend->mgpu_formats;
|
||||
}
|
||||
return &plane->formats;
|
||||
|
|
@ -1281,7 +1211,7 @@ static const struct wlr_drm_format_set *drm_connector_get_primary_formats(
|
|||
if (!drm_connector_alloc_crtc(conn)) {
|
||||
return NULL;
|
||||
}
|
||||
if (conn->backend->mgpu_renderer.wlr_rend) {
|
||||
if (conn->backend->parent) {
|
||||
return &conn->backend->mgpu_formats;
|
||||
}
|
||||
return &conn->crtc->primary->formats;
|
||||
|
|
@ -1418,7 +1348,7 @@ static void realloc_crtcs(struct wlr_drm_backend *drm,
|
|||
++i;
|
||||
}
|
||||
|
||||
match_connectors_with_crtcs(num_connectors, connector_constraints,
|
||||
match_obj(num_connectors, connector_constraints,
|
||||
drm->num_crtcs, previous_match, new_match);
|
||||
|
||||
// Converts our crtc=>connector result into a connector=>crtc one.
|
||||
|
|
@ -1546,14 +1476,14 @@ static struct wlr_drm_connector *create_drm_connector(struct wlr_drm_backend *dr
|
|||
return NULL;
|
||||
}
|
||||
|
||||
const char *conn_type_name =
|
||||
const char *conn_name =
|
||||
drmModeGetConnectorTypeName(drm_conn->connector_type);
|
||||
if (conn_type_name == NULL) {
|
||||
conn_type_name = "Unknown";
|
||||
if (conn_name == NULL) {
|
||||
conn_name = "Unknown";
|
||||
}
|
||||
|
||||
snprintf(wlr_conn->name, sizeof(wlr_conn->name),
|
||||
"%s-%"PRIu32, conn_type_name, drm_conn->connector_type_id);
|
||||
"%s-%"PRIu32, conn_name, drm_conn->connector_type_id);
|
||||
|
||||
wlr_conn->possible_crtcs =
|
||||
drmModeConnectorGetPossibleCrtcs(drm->fd, drm_conn);
|
||||
|
|
@ -1624,7 +1554,6 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
|
|||
|
||||
wlr_log(WLR_INFO, "Detected modes:");
|
||||
|
||||
bool found_current_mode = false;
|
||||
for (int i = 0; i < drm_conn->count_modes; ++i) {
|
||||
if (drm_conn->modes[i].flags & DRM_MODE_FLAG_INTERLACE) {
|
||||
continue;
|
||||
|
|
@ -1643,7 +1572,14 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
|
|||
if (current_modeinfo != NULL && memcmp(&mode->drm_mode,
|
||||
current_modeinfo, sizeof(*current_modeinfo)) == 0) {
|
||||
wlr_output_state_set_mode(&state, &mode->wlr_mode);
|
||||
found_current_mode = true;
|
||||
|
||||
uint64_t mode_id = 0;
|
||||
get_drm_prop(drm->fd, wlr_conn->crtc->id,
|
||||
wlr_conn->crtc->props.mode_id, &mode_id);
|
||||
|
||||
wlr_conn->crtc->own_mode_id = false;
|
||||
wlr_conn->crtc->mode_id = mode_id;
|
||||
wlr_conn->refresh = calculate_refresh_rate(current_modeinfo);
|
||||
}
|
||||
|
||||
wlr_log(WLR_INFO, " %"PRId32"x%"PRId32" @ %.3f Hz %s",
|
||||
|
|
@ -1654,23 +1590,6 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
|
|||
wl_list_insert(modes.prev, &mode->wlr_mode.link);
|
||||
}
|
||||
|
||||
if (current_modeinfo != NULL) {
|
||||
int32_t refresh = calculate_refresh_rate(current_modeinfo);
|
||||
|
||||
if (!found_current_mode) {
|
||||
wlr_output_state_set_custom_mode(&state,
|
||||
current_modeinfo->hdisplay, current_modeinfo->vdisplay, refresh);
|
||||
}
|
||||
|
||||
uint64_t mode_id = 0;
|
||||
get_drm_prop(drm->fd, wlr_conn->crtc->id,
|
||||
wlr_conn->crtc->props.mode_id, &mode_id);
|
||||
|
||||
wlr_conn->crtc->own_mode_id = false;
|
||||
wlr_conn->crtc->mode_id = mode_id;
|
||||
wlr_conn->refresh = refresh;
|
||||
}
|
||||
|
||||
free(current_modeinfo);
|
||||
|
||||
wlr_output_init(output, &drm->backend, &output_impl, drm->session->event_loop, &state);
|
||||
|
|
@ -1717,11 +1636,7 @@ static bool connect_drm_connector(struct wlr_drm_connector *wlr_conn,
|
|||
size_t edid_len = 0;
|
||||
uint8_t *edid = get_drm_prop_blob(drm->fd,
|
||||
wlr_conn->id, wlr_conn->props.edid, &edid_len);
|
||||
if (edid_len > 0) {
|
||||
parse_edid(wlr_conn, edid_len, edid);
|
||||
} else {
|
||||
wlr_log(WLR_DEBUG, "Connector has no EDID");
|
||||
}
|
||||
free(edid);
|
||||
|
||||
char *subconnector = NULL;
|
||||
|
|
@ -1787,10 +1702,6 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
|
|||
}
|
||||
}
|
||||
|
||||
if (wlr_conn && wlr_conn->lease) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// If the hotplug event contains a connector ID, ignore any other
|
||||
// connector.
|
||||
if (event != NULL && event->connector_id != 0 &&
|
||||
|
|
@ -1868,6 +1779,8 @@ void scan_drm_connectors(struct wlr_drm_backend *drm,
|
|||
destroy_drm_connector(conn);
|
||||
}
|
||||
|
||||
realloc_crtcs(drm, NULL);
|
||||
|
||||
for (size_t i = 0; i < new_outputs_len; ++i) {
|
||||
struct wlr_drm_connector *conn = new_outputs[i];
|
||||
|
||||
|
|
@ -1907,6 +1820,108 @@ void scan_drm_leases(struct wlr_drm_backend *drm) {
|
|||
drmFree(list);
|
||||
}
|
||||
|
||||
static void build_current_connector_state(struct wlr_output_state *state,
|
||||
struct wlr_drm_connector *conn) {
|
||||
bool enabled = conn->status != DRM_MODE_DISCONNECTED && conn->output.enabled;
|
||||
|
||||
wlr_output_state_init(state);
|
||||
wlr_output_state_set_enabled(state, enabled);
|
||||
if (!enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (conn->output.current_mode != NULL) {
|
||||
wlr_output_state_set_mode(state, conn->output.current_mode);
|
||||
} else {
|
||||
wlr_output_state_set_custom_mode(state,
|
||||
conn->output.width, conn->output.height, conn->output.refresh);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether we need to perform a full reset after a VT switch.
|
||||
*
|
||||
* If any connector or plane has a different CRTC, we need to perform a full
|
||||
* reset to restore our mapping. We couldn't avoid a full reset even if we
|
||||
* used a single KMS atomic commit to apply our state: the kernel rejects
|
||||
* commits which migrate a plane from one CRTC to another without going through
|
||||
* an intermediate state where the plane is disabled.
|
||||
*/
|
||||
static bool skip_reset_for_restore(struct wlr_drm_backend *drm) {
|
||||
struct wlr_drm_connector *conn;
|
||||
wl_list_for_each(conn, &drm->connectors, link) {
|
||||
drmModeConnector *drm_conn = drmModeGetConnectorCurrent(drm->fd, conn->id);
|
||||
if (drm_conn == NULL) {
|
||||
return false;
|
||||
}
|
||||
struct wlr_drm_crtc *crtc = connector_get_current_crtc(conn, drm_conn);
|
||||
drmModeFreeConnector(drm_conn);
|
||||
|
||||
if (crtc != NULL && conn->crtc != crtc) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < drm->num_planes; i++) {
|
||||
struct wlr_drm_plane *plane = &drm->planes[i];
|
||||
|
||||
drmModePlane *drm_plane = drmModeGetPlane(drm->fd, plane->id);
|
||||
if (drm_plane == NULL) {
|
||||
return false;
|
||||
}
|
||||
uint32_t crtc_id = drm_plane->crtc_id;
|
||||
drmModeFreePlane(drm_plane);
|
||||
|
||||
struct wlr_drm_crtc *crtc = NULL;
|
||||
for (size_t i = 0; i < drm->num_crtcs; i++) {
|
||||
if (drm->crtcs[i].id == crtc_id) {
|
||||
crtc = &drm->crtcs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (crtc == NULL) {
|
||||
continue;
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
switch (plane->type) {
|
||||
case DRM_PLANE_TYPE_PRIMARY:
|
||||
ok = crtc->primary == plane;
|
||||
break;
|
||||
case DRM_PLANE_TYPE_CURSOR:
|
||||
ok = crtc->cursor == plane;
|
||||
break;
|
||||
}
|
||||
if (!ok) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void restore_drm_device(struct wlr_drm_backend *drm) {
|
||||
// The previous DRM master leaves KMS in an undefined state. We need
|
||||
// to restore our own state, but be careful to avoid invalid
|
||||
// configurations. The connector/CRTC mapping may have changed, so
|
||||
// first disable all CRTCs, then light up the ones we were using
|
||||
// before the VT switch.
|
||||
// TODO: better use the atomic API to improve restoration after a VT switch
|
||||
if (!skip_reset_for_restore(drm) && !drm->iface->reset(drm)) {
|
||||
wlr_log(WLR_ERROR, "Failed to reset state after VT switch");
|
||||
}
|
||||
|
||||
struct wlr_drm_connector *conn;
|
||||
wl_list_for_each(conn, &drm->connectors, link) {
|
||||
struct wlr_output_state state;
|
||||
build_current_connector_state(&state, conn);
|
||||
if (!drm_connector_commit_state(conn, &state, false)) {
|
||||
wlr_drm_conn_log(conn, WLR_ERROR, "Failed to restore state after VT switch");
|
||||
}
|
||||
wlr_output_state_finish(&state);
|
||||
}
|
||||
}
|
||||
|
||||
bool commit_drm_device(struct wlr_drm_backend *drm,
|
||||
const struct wlr_backend_output_state *output_states, size_t output_states_len,
|
||||
bool test_only) {
|
||||
|
|
@ -1955,7 +1970,7 @@ bool commit_drm_device(struct wlr_drm_backend *drm,
|
|||
modeset |= output_state->base.allow_reconfiguration;
|
||||
}
|
||||
|
||||
if (test_only && drm->mgpu_renderer.wlr_rend) {
|
||||
if (test_only && drm->parent) {
|
||||
// If we're running as a secondary GPU, we can't perform an atomic
|
||||
// commit without blitting a buffer.
|
||||
ok = true;
|
||||
|
|
@ -1993,12 +2008,6 @@ static void handle_page_flip(int fd, unsigned seq,
|
|||
if (conn != NULL) {
|
||||
conn->pending_page_flip = NULL;
|
||||
}
|
||||
|
||||
uint32_t present_flags = WLR_OUTPUT_PRESENT_HW_CLOCK | WLR_OUTPUT_PRESENT_HW_COMPLETION;
|
||||
if (!page_flip->async) {
|
||||
present_flags |= WLR_OUTPUT_PRESENT_VSYNC;
|
||||
}
|
||||
|
||||
if (page_flip->connectors_len == 0) {
|
||||
drm_page_flip_destroy(page_flip);
|
||||
}
|
||||
|
|
@ -2029,23 +2038,26 @@ static void handle_page_flip(int fd, unsigned seq,
|
|||
drm_fb_move(&layer->current_fb, &layer->queued_fb);
|
||||
}
|
||||
|
||||
uint32_t present_flags = WLR_OUTPUT_PRESENT_VSYNC |
|
||||
WLR_OUTPUT_PRESENT_HW_CLOCK | WLR_OUTPUT_PRESENT_HW_COMPLETION;
|
||||
/* Don't report ZERO_COPY in multi-gpu situations, because we had to copy
|
||||
* data between the GPUs, even if we were using the direct scanout
|
||||
* interface.
|
||||
*/
|
||||
if (!drm->mgpu_renderer.wlr_rend) {
|
||||
if (!drm->parent) {
|
||||
present_flags |= WLR_OUTPUT_PRESENT_ZERO_COPY;
|
||||
}
|
||||
|
||||
struct timespec present_time = {
|
||||
.tv_sec = tv_sec,
|
||||
.tv_nsec = tv_usec * 1000,
|
||||
};
|
||||
struct wlr_output_event_present present_event = {
|
||||
/* The DRM backend guarantees that the presentation event will be for
|
||||
* the last submitted frame. */
|
||||
.commit_seq = conn->output.commit_seq,
|
||||
.presented = drm->session->active,
|
||||
.when = {
|
||||
.tv_sec = tv_sec,
|
||||
.tv_nsec = tv_usec * 1000,
|
||||
},
|
||||
.when = &present_time,
|
||||
.seq = seq,
|
||||
.refresh = mhz_to_nsec(conn->refresh),
|
||||
.flags = present_flags,
|
||||
|
|
@ -2179,7 +2191,6 @@ struct wlr_drm_lease *wlr_drm_create_lease(struct wlr_output **outputs,
|
|||
get_drm_connector_from_output(outputs[i]);
|
||||
conn->lease = lease;
|
||||
conn->crtc->lease = lease;
|
||||
disconnect_drm_connector(conn);
|
||||
}
|
||||
|
||||
return lease;
|
||||
|
|
@ -2202,8 +2213,6 @@ void drm_lease_destroy(struct wlr_drm_lease *lease) {
|
|||
|
||||
wl_signal_emit_mutable(&lease->events.destroy, NULL);
|
||||
|
||||
assert(wl_list_empty(&lease->events.destroy.listener_list));
|
||||
|
||||
struct wlr_drm_connector *conn;
|
||||
wl_list_for_each(conn, &drm->connectors, link) {
|
||||
if (conn->lease == lease) {
|
||||
|
|
@ -2218,5 +2227,4 @@ void drm_lease_destroy(struct wlr_drm_lease *lease) {
|
|||
}
|
||||
|
||||
free(lease);
|
||||
scan_drm_connectors(drm, NULL);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,6 @@
|
|||
#include "backend/drm/fb.h"
|
||||
#include "backend/drm/iface.h"
|
||||
#include "backend/drm/util.h"
|
||||
#include "render/color.h"
|
||||
#include "types/wlr_output.h"
|
||||
|
||||
static bool legacy_fb_props_match(struct wlr_drm_fb *fb1,
|
||||
struct wlr_drm_fb *fb2) {
|
||||
|
|
@ -41,27 +39,7 @@ static bool legacy_crtc_test(const struct wlr_drm_connector_state *state,
|
|||
struct wlr_drm_connector *conn = state->connector;
|
||||
struct wlr_drm_crtc *crtc = conn->crtc;
|
||||
|
||||
if (state->base->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
// If the size doesn't match, reject buffer (scaling is not supported)
|
||||
int pending_width, pending_height;
|
||||
output_pending_resolution(&state->connector->output, state->base,
|
||||
&pending_width, &pending_height);
|
||||
if (state->base->buffer->width != pending_width ||
|
||||
state->base->buffer->height != pending_height) {
|
||||
wlr_log(WLR_DEBUG, "Primary buffer size mismatch");
|
||||
return false;
|
||||
}
|
||||
// Source crop is also not supported
|
||||
struct wlr_fbox src_box;
|
||||
output_state_get_buffer_src_box(state->base, &src_box);
|
||||
if (src_box.x != 0.0 || src_box.y != 0.0 ||
|
||||
src_box.width != (double)state->base->buffer->width ||
|
||||
src_box.height != (double)state->base->buffer->height) {
|
||||
wlr_log(WLR_DEBUG, "Source crop not supported in DRM-legacy output");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!modeset) {
|
||||
if ((state->base->committed & WLR_OUTPUT_STATE_BUFFER) && !modeset) {
|
||||
struct wlr_drm_fb *pending_fb = state->primary_fb;
|
||||
|
||||
struct wlr_drm_fb *prev_fb = crtc->primary->queued_fb;
|
||||
|
|
@ -77,7 +55,6 @@ static bool legacy_crtc_test(const struct wlr_drm_connector_state *state,
|
|||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -125,17 +102,9 @@ static bool legacy_crtc_commit(const struct wlr_drm_connector_state *state,
|
|||
}
|
||||
}
|
||||
|
||||
if (state->base->committed & WLR_OUTPUT_STATE_COLOR_TRANSFORM) {
|
||||
size_t dim = 0;
|
||||
uint16_t *lut = NULL;
|
||||
if (state->base->color_transform != NULL) {
|
||||
struct wlr_color_transform_lut_3x1d *tr =
|
||||
color_transform_lut_3x1d_from_base(state->base->color_transform);
|
||||
dim = tr->dim;
|
||||
lut = tr->lut_3x1d;
|
||||
}
|
||||
|
||||
if (!drm_legacy_crtc_set_gamma(drm, crtc, dim, lut)) {
|
||||
if (state->base->committed & WLR_OUTPUT_STATE_GAMMA_LUT) {
|
||||
if (!drm_legacy_crtc_set_gamma(drm, crtc,
|
||||
state->base->gamma_lut_size, state->base->gamma_lut)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -159,7 +128,7 @@ static bool legacy_crtc_commit(const struct wlr_drm_connector_state *state,
|
|||
state->base->adaptive_sync_enabled ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
if (cursor != NULL && state->active && drm_connector_is_cursor_visible(conn)) {
|
||||
if (cursor != NULL && drm_connector_is_cursor_visible(conn)) {
|
||||
struct wlr_drm_fb *cursor_fb = state->cursor_fb;
|
||||
if (cursor_fb == NULL) {
|
||||
wlr_drm_conn_log(conn, WLR_DEBUG, "Failed to acquire cursor FB");
|
||||
|
|
@ -201,9 +170,7 @@ static bool legacy_crtc_commit(const struct wlr_drm_connector_state *state,
|
|||
}
|
||||
}
|
||||
|
||||
// Legacy uAPI doesn't support requesting page-flip events when
|
||||
// turning off a CRTC
|
||||
if (state->active && (flags & DRM_MODE_PAGE_FLIP_EVENT)) {
|
||||
if (flags & DRM_MODE_PAGE_FLIP_EVENT) {
|
||||
if (drmModePageFlip(drm->fd, crtc->id, fb_id, flags, page_flip)) {
|
||||
wlr_drm_conn_log_errno(conn, WLR_ERROR, "drmModePageFlip failed");
|
||||
return false;
|
||||
|
|
@ -281,6 +248,20 @@ bool drm_legacy_crtc_set_gamma(struct wlr_drm_backend *drm,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool legacy_reset(struct wlr_drm_backend *drm) {
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < drm->num_crtcs; i++) {
|
||||
struct wlr_drm_crtc *crtc = &drm->crtcs[i];
|
||||
if (drmModeSetCrtc(drm->fd, crtc->id, 0, 0, 0, NULL, 0, NULL) != 0) {
|
||||
wlr_log_errno(WLR_ERROR, "Failed to disable CRTC %"PRIu32,
|
||||
crtc->id);
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
const struct wlr_drm_interface legacy_iface = {
|
||||
.commit = legacy_commit,
|
||||
.reset = legacy_reset,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -4,14 +4,12 @@
|
|||
#include <stdlib.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <wlr/util/box.h>
|
||||
#include <wlr/util/log.h>
|
||||
|
||||
#include "backend/drm/drm.h"
|
||||
#include "backend/drm/fb.h"
|
||||
#include "backend/drm/iface.h"
|
||||
#include "config.h"
|
||||
#include "types/wlr_output.h"
|
||||
|
||||
static void log_handler(enum liftoff_log_priority priority, const char *fmt, va_list args) {
|
||||
enum wlr_log_importance importance = WLR_SILENT;
|
||||
|
|
@ -151,23 +149,25 @@ static bool add_prop(drmModeAtomicReq *req, uint32_t obj,
|
|||
}
|
||||
|
||||
static bool set_plane_props(struct wlr_drm_plane *plane,
|
||||
struct liftoff_layer *layer, struct wlr_drm_fb *fb, uint64_t zpos,
|
||||
const struct wlr_box *dst_box, const struct wlr_fbox *src_box) {
|
||||
struct liftoff_layer *layer, struct wlr_drm_fb *fb, int32_t x, int32_t y, uint64_t zpos) {
|
||||
if (fb == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to acquire FB for plane %"PRIu32, plane->id);
|
||||
return false;
|
||||
}
|
||||
|
||||
// The src_* properties are in 16.16 fixed point
|
||||
uint32_t width = fb->wlr_buf->width;
|
||||
uint32_t height = fb->wlr_buf->height;
|
||||
|
||||
// The SRC_* properties are in 16.16 fixed point
|
||||
return liftoff_layer_set_property(layer, "zpos", zpos) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_X", src_box->x * (1 << 16)) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_Y", src_box->y * (1 << 16)) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_W", src_box->width * (1 << 16)) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_H", src_box->height * (1 << 16)) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_X", dst_box->x) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_Y", dst_box->y) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_W", dst_box->width) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_H", dst_box->height) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_X", 0) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_Y", 0) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_W", (uint64_t)width << 16) == 0 &&
|
||||
liftoff_layer_set_property(layer, "SRC_H", (uint64_t)height << 16) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_X", (uint64_t)x) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_Y", (uint64_t)y) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_W", width) == 0 &&
|
||||
liftoff_layer_set_property(layer, "CRTC_H", height) == 0 &&
|
||||
liftoff_layer_set_property(layer, "FB_ID", fb->id) == 0;
|
||||
}
|
||||
|
||||
|
|
@ -331,32 +331,14 @@ static bool add_connector(drmModeAtomicReq *req,
|
|||
if (crtc->props.vrr_enabled != 0) {
|
||||
ok = ok && add_prop(req, crtc->id, crtc->props.vrr_enabled, state->vrr_enabled);
|
||||
}
|
||||
|
||||
ok = ok && set_plane_props(crtc->primary,
|
||||
crtc->primary->liftoff_layer, state->primary_fb, 0,
|
||||
&state->primary_viewport.dst_box,
|
||||
&state->primary_viewport.src_box);
|
||||
ok = ok && set_plane_props(crtc->primary,
|
||||
crtc->liftoff_composition_layer, state->primary_fb, 0,
|
||||
&state->primary_viewport.dst_box,
|
||||
&state->primary_viewport.src_box);
|
||||
|
||||
ok = ok &&
|
||||
set_plane_props(crtc->primary, crtc->primary->liftoff_layer, state->primary_fb, 0, 0, 0) &&
|
||||
set_plane_props(crtc->primary, crtc->liftoff_composition_layer, state->primary_fb, 0, 0, 0);
|
||||
liftoff_layer_set_property(crtc->primary->liftoff_layer,
|
||||
"FB_DAMAGE_CLIPS", state->fb_damage_clips);
|
||||
liftoff_layer_set_property(crtc->liftoff_composition_layer,
|
||||
"FB_DAMAGE_CLIPS", state->fb_damage_clips);
|
||||
|
||||
if (state->primary_in_fence_fd >= 0) {
|
||||
liftoff_layer_set_property(crtc->primary->liftoff_layer,
|
||||
"IN_FENCE_FD", state->primary_in_fence_fd);
|
||||
liftoff_layer_set_property(crtc->liftoff_composition_layer,
|
||||
"IN_FENCE_FD", state->primary_in_fence_fd);
|
||||
}
|
||||
if (state->base->committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE) {
|
||||
ok = ok && add_prop(req, crtc->id, crtc->props.out_fence_ptr,
|
||||
(uintptr_t)&state->out_fence_fd);
|
||||
}
|
||||
|
||||
if (state->base->committed & WLR_OUTPUT_STATE_LAYERS) {
|
||||
for (size_t i = 0; i < state->base->layers_len; i++) {
|
||||
const struct wlr_output_layer_state *layer_state = &state->base->layers[i];
|
||||
|
|
@ -367,19 +349,9 @@ static bool add_connector(drmModeAtomicReq *req,
|
|||
|
||||
if (crtc->cursor) {
|
||||
if (drm_connector_is_cursor_visible(conn)) {
|
||||
struct wlr_fbox cursor_src = {
|
||||
.width = state->cursor_fb->wlr_buf->width,
|
||||
.height = state->cursor_fb->wlr_buf->height,
|
||||
};
|
||||
struct wlr_box cursor_dst = {
|
||||
.x = conn->cursor_x,
|
||||
.y = conn->cursor_y,
|
||||
.width = state->cursor_fb->wlr_buf->width,
|
||||
.height = state->cursor_fb->wlr_buf->height,
|
||||
};
|
||||
ok = ok && set_plane_props(crtc->cursor, crtc->cursor->liftoff_layer,
|
||||
state->cursor_fb, wl_list_length(&crtc->layers) + 1,
|
||||
&cursor_dst, &cursor_src);
|
||||
state->cursor_fb, conn->cursor_x, conn->cursor_y,
|
||||
wl_list_length(&crtc->layers) + 1);
|
||||
} else {
|
||||
ok = ok && disable_plane(crtc->cursor);
|
||||
}
|
||||
|
|
@ -425,7 +397,7 @@ static bool commit(struct wlr_drm_backend *drm,
|
|||
if (state->modeset) {
|
||||
flags |= DRM_MODE_ATOMIC_ALLOW_MODESET;
|
||||
}
|
||||
if (state->nonblock) {
|
||||
if (!test_only && state->nonblock) {
|
||||
flags |= DRM_MODE_ATOMIC_NONBLOCK;
|
||||
}
|
||||
|
||||
|
|
@ -507,4 +479,5 @@ const struct wlr_drm_interface liftoff_iface = {
|
|||
.init = init,
|
||||
.finish = finish,
|
||||
.commit = commit,
|
||||
.reset = drm_atomic_reset,
|
||||
};
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@ hwdata = dependency(
|
|||
|
||||
libdisplay_info = dependency(
|
||||
'libdisplay-info',
|
||||
version: '>=0.2.0',
|
||||
required: 'drm' in backends,
|
||||
fallback: 'libdisplay-info',
|
||||
not_found_message: 'Required for the DRM backend.',
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@
|
|||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <xf86drm.h>
|
||||
#include <xf86drmMode.h>
|
||||
|
|
@ -22,10 +21,8 @@ struct prop_info {
|
|||
static const struct prop_info connector_info[] = {
|
||||
#define INDEX(name) (offsetof(struct wlr_drm_connector_props, name) / sizeof(uint32_t))
|
||||
{ "CRTC_ID", INDEX(crtc_id) },
|
||||
{ "Colorspace", INDEX(colorspace) },
|
||||
{ "DPMS", INDEX(dpms) },
|
||||
{ "EDID", INDEX(edid) },
|
||||
{ "HDR_OUTPUT_METADATA", INDEX(hdr_output_metadata) },
|
||||
{ "PATH", INDEX(path) },
|
||||
{ "content type", INDEX(content_type) },
|
||||
{ "link-status", INDEX(link_status) },
|
||||
|
|
@ -43,7 +40,6 @@ static const struct prop_info crtc_info[] = {
|
|||
{ "GAMMA_LUT", INDEX(gamma_lut) },
|
||||
{ "GAMMA_LUT_SIZE", INDEX(gamma_lut_size) },
|
||||
{ "MODE_ID", INDEX(mode_id) },
|
||||
{ "OUT_FENCE_PTR", INDEX(out_fence_ptr) },
|
||||
{ "VRR_ENABLED", INDEX(vrr_enabled) },
|
||||
#undef INDEX
|
||||
};
|
||||
|
|
@ -59,7 +55,6 @@ static const struct prop_info plane_info[] = {
|
|||
{ "FB_ID", INDEX(fb_id) },
|
||||
{ "HOTSPOT_X", INDEX(hotspot_x) },
|
||||
{ "HOTSPOT_Y", INDEX(hotspot_y) },
|
||||
{ "IN_FENCE_FD", INDEX(in_fence_fd) },
|
||||
{ "IN_FORMATS", INDEX(in_formats) },
|
||||
{ "SIZE_HINTS", INDEX(size_hints) },
|
||||
{ "SRC_H", INDEX(src_h) },
|
||||
|
|
@ -82,14 +77,14 @@ static bool scan_properties(int fd, uint32_t id, uint32_t type, uint32_t *result
|
|||
const struct prop_info *info, size_t info_len) {
|
||||
drmModeObjectProperties *props = drmModeObjectGetProperties(fd, id, type);
|
||||
if (!props) {
|
||||
wlr_log_errno(WLR_ERROR, "Failed to get DRM object %" PRIu32 " properties", id);
|
||||
wlr_log_errno(WLR_ERROR, "Failed to get DRM object properties");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < props->count_props; ++i) {
|
||||
drmModePropertyRes *prop = drmModeGetProperty(fd, props->props[i]);
|
||||
if (!prop) {
|
||||
wlr_log_errno(WLR_ERROR, "Failed to get property %" PRIu32 " of DRM object %" PRIu32, props->props[i], id);
|
||||
wlr_log_errno(WLR_ERROR, "Failed to get DRM object property");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,35 +1,31 @@
|
|||
#include <assert.h>
|
||||
#include <drm_fourcc.h>
|
||||
#include <wlr/render/allocator.h>
|
||||
#include <wlr/render/drm_syncobj.h>
|
||||
#include <wlr/render/swapchain.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/drm/drm.h"
|
||||
#include "backend/drm/fb.h"
|
||||
#include "backend/drm/renderer.h"
|
||||
#include "backend/backend.h"
|
||||
#include "render/drm_format_set.h"
|
||||
#include "render/allocator/allocator.h"
|
||||
#include "render/pixel_format.h"
|
||||
#include "render/wlr_renderer.h"
|
||||
|
||||
bool init_drm_renderer(struct wlr_drm_backend *drm,
|
||||
struct wlr_drm_renderer *renderer) {
|
||||
wlr_log(WLR_DEBUG, "Creating multi-GPU renderer");
|
||||
renderer->wlr_rend = renderer_autocreate_with_drm_fd(drm->fd);
|
||||
if (!renderer->wlr_rend) {
|
||||
return false;
|
||||
}
|
||||
if (wlr_renderer_get_texture_formats(renderer->wlr_rend, WLR_BUFFER_CAP_DMABUF) == NULL) {
|
||||
wlr_log(WLR_ERROR, "Renderer did not support importing DMA-BUFs");
|
||||
wlr_renderer_destroy(renderer->wlr_rend);
|
||||
renderer->wlr_rend = NULL;
|
||||
wlr_log(WLR_ERROR, "Failed to create renderer");
|
||||
return false;
|
||||
}
|
||||
|
||||
renderer->allocator = wlr_allocator_autocreate(&drm->backend, renderer->wlr_rend);
|
||||
uint32_t backend_caps = backend_get_buffer_caps(&drm->backend);
|
||||
renderer->allocator = allocator_autocreate_with_drm_fd(backend_caps,
|
||||
renderer->wlr_rend, drm->fd);
|
||||
if (renderer->allocator == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to create allocator");
|
||||
wlr_renderer_destroy(renderer->wlr_rend);
|
||||
renderer->wlr_rend = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +46,6 @@ void finish_drm_surface(struct wlr_drm_surface *surf) {
|
|||
return;
|
||||
}
|
||||
|
||||
wlr_drm_syncobj_timeline_unref(surf->timeline);
|
||||
wlr_swapchain_destroy(surf->swapchain);
|
||||
|
||||
*surf = (struct wlr_drm_surface){0};
|
||||
|
|
@ -73,24 +68,13 @@ bool init_drm_surface(struct wlr_drm_surface *surf,
|
|||
return false;
|
||||
}
|
||||
|
||||
int drm_fd = wlr_renderer_get_drm_fd(renderer->wlr_rend);
|
||||
if (renderer->wlr_rend->features.timeline && drm_fd >= 0) {
|
||||
surf->timeline = wlr_drm_syncobj_timeline_create(drm_fd);
|
||||
if (surf->timeline == NULL) {
|
||||
finish_drm_surface(surf);
|
||||
wlr_log(WLR_ERROR, "Failed to create DRM syncobj timeline");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
surf->renderer = renderer;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
||||
struct wlr_buffer *buffer,
|
||||
struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point) {
|
||||
struct wlr_buffer *buffer) {
|
||||
struct wlr_renderer *renderer = surf->renderer->wlr_rend;
|
||||
|
||||
if (surf->swapchain->width != buffer->width ||
|
||||
|
|
@ -105,18 +89,13 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
struct wlr_buffer *dst = wlr_swapchain_acquire(surf->swapchain);
|
||||
struct wlr_buffer *dst = wlr_swapchain_acquire(surf->swapchain, NULL);
|
||||
if (!dst) {
|
||||
wlr_log(WLR_ERROR, "Failed to acquire multi-GPU swapchain buffer");
|
||||
goto error_tex;
|
||||
}
|
||||
|
||||
surf->point++;
|
||||
const struct wlr_buffer_pass_options pass_options = {
|
||||
.signal_timeline = surf->timeline,
|
||||
.signal_point = surf->point,
|
||||
};
|
||||
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, dst, &pass_options);
|
||||
struct wlr_render_pass *pass = wlr_renderer_begin_buffer_pass(renderer, dst, NULL);
|
||||
if (pass == NULL) {
|
||||
wlr_log(WLR_ERROR, "Failed to begin render pass with multi-GPU destination buffer");
|
||||
goto error_dst;
|
||||
|
|
@ -125,8 +104,6 @@ struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
|||
wlr_render_pass_add_texture(pass, &(struct wlr_render_texture_options){
|
||||
.texture = tex,
|
||||
.blend_mode = WLR_RENDER_BLEND_MODE_NONE,
|
||||
.wait_timeline = wait_timeline,
|
||||
.wait_point = wait_point,
|
||||
});
|
||||
if (!wlr_render_pass_submit(pass)) {
|
||||
wlr_log(WLR_ERROR, "Failed to submit multi-GPU render pass");
|
||||
|
|
|
|||
|
|
@ -83,17 +83,6 @@ void parse_edid(struct wlr_drm_connector *conn, size_t len, const uint8_t *data)
|
|||
output->model = di_info_get_model(info);
|
||||
output->serial = di_info_get_serial(info);
|
||||
|
||||
const struct di_supported_signal_colorimetry *colorimetry = di_info_get_supported_signal_colorimetry(info);
|
||||
bool has_bt2020 = colorimetry->bt2020_cycc || colorimetry->bt2020_ycc || colorimetry->bt2020_rgb;
|
||||
if (conn->props.colorspace != 0 && has_bt2020) {
|
||||
output->supported_primaries |= WLR_COLOR_NAMED_PRIMARIES_BT2020;
|
||||
}
|
||||
|
||||
const struct di_hdr_static_metadata *hdr_static_metadata = di_info_get_hdr_static_metadata(info);
|
||||
if (conn->props.hdr_output_metadata != 0 && hdr_static_metadata->type1 && hdr_static_metadata->pq) {
|
||||
output->supported_transfer_functions |= WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ;
|
||||
}
|
||||
|
||||
di_info_destroy(info);
|
||||
}
|
||||
|
||||
|
|
@ -123,9 +112,9 @@ static bool is_taken(size_t n, const uint32_t arr[static n], uint32_t key) {
|
|||
* passing 12 arguments to a function.
|
||||
*/
|
||||
struct match_state {
|
||||
const size_t num_conns;
|
||||
const uint32_t *restrict conns;
|
||||
const size_t num_crtcs;
|
||||
const size_t num_objs;
|
||||
const uint32_t *restrict objs;
|
||||
const size_t num_res;
|
||||
size_t score;
|
||||
size_t replaced;
|
||||
uint32_t *restrict res;
|
||||
|
|
@ -134,31 +123,27 @@ struct match_state {
|
|||
bool exit_early;
|
||||
};
|
||||
|
||||
/**
|
||||
* Step to process a CRTC.
|
||||
*
|
||||
* This is a naive implementation of maximum bipartite matching.
|
||||
*
|
||||
* score: The number of connectors we've matched so far.
|
||||
/*
|
||||
* skips: The number of SKIP elements encountered so far.
|
||||
* score: The number of resources we've matched so far.
|
||||
* replaced: The number of changes from the original solution.
|
||||
* crtc_index: The index of the current CRTC.
|
||||
* i: The index of the current element.
|
||||
*
|
||||
* This tries to match a solution as close to st->orig as it can.
|
||||
*
|
||||
* Returns whether we've set a new best element with this solution.
|
||||
*/
|
||||
static bool match_connectors_with_crtcs_(struct match_state *st,
|
||||
size_t score, size_t replaced, size_t crtc_index) {
|
||||
static bool match_obj_(struct match_state *st, size_t skips, size_t score, size_t replaced, size_t i) {
|
||||
// Finished
|
||||
if (crtc_index >= st->num_crtcs) {
|
||||
if (i >= st->num_res) {
|
||||
if (score > st->score ||
|
||||
(score == st->score && replaced < st->replaced)) {
|
||||
st->score = score;
|
||||
st->replaced = replaced;
|
||||
memcpy(st->best, st->res, sizeof(st->best[0]) * st->num_crtcs);
|
||||
memcpy(st->best, st->res, sizeof(st->best[0]) * st->num_res);
|
||||
|
||||
st->exit_early = (st->score == st->num_crtcs
|
||||
|| st->score == st->num_conns)
|
||||
st->exit_early = (st->score == st->num_res - skips
|
||||
|| st->score == st->num_objs)
|
||||
&& st->replaced == 0;
|
||||
|
||||
return true;
|
||||
|
|
@ -167,16 +152,27 @@ static bool match_connectors_with_crtcs_(struct match_state *st,
|
|||
}
|
||||
}
|
||||
|
||||
if (st->orig[i] == SKIP) {
|
||||
st->res[i] = SKIP;
|
||||
return match_obj_(st, skips + 1, score, replaced, i + 1);
|
||||
}
|
||||
|
||||
bool has_best = false;
|
||||
|
||||
/*
|
||||
* Attempt to use the current solution first, to try and avoid
|
||||
* recalculating everything
|
||||
*/
|
||||
if (st->orig[crtc_index] != UNMATCHED && !is_taken(crtc_index, st->res, st->orig[crtc_index])) {
|
||||
st->res[crtc_index] = st->orig[crtc_index];
|
||||
size_t crtc_score = st->conns[st->res[crtc_index]] != 0 ? 1 : 0;
|
||||
if (match_connectors_with_crtcs_(st, score + crtc_score, replaced, crtc_index + 1)) {
|
||||
if (st->orig[i] != UNMATCHED && !is_taken(i, st->res, st->orig[i])) {
|
||||
st->res[i] = st->orig[i];
|
||||
size_t obj_score = st->objs[st->res[i]] != 0 ? 1 : 0;
|
||||
if (match_obj_(st, skips, score + obj_score, replaced, i + 1)) {
|
||||
has_best = true;
|
||||
}
|
||||
}
|
||||
if (st->orig[i] == UNMATCHED) {
|
||||
st->res[i] = UNMATCHED;
|
||||
if (match_obj_(st, skips, score, replaced, i + 1)) {
|
||||
has_best = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -184,29 +180,29 @@ static bool match_connectors_with_crtcs_(struct match_state *st,
|
|||
return true;
|
||||
}
|
||||
|
||||
if (st->orig[crtc_index] != UNMATCHED) {
|
||||
if (st->orig[i] != UNMATCHED) {
|
||||
++replaced;
|
||||
}
|
||||
|
||||
for (size_t candidate = 0; candidate < st->num_conns; ++candidate) {
|
||||
for (size_t candidate = 0; candidate < st->num_objs; ++candidate) {
|
||||
// We tried this earlier
|
||||
if (candidate == st->orig[crtc_index]) {
|
||||
if (candidate == st->orig[i]) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Not compatible
|
||||
if (!(st->conns[candidate] & (1 << crtc_index))) {
|
||||
if (!(st->objs[candidate] & (1 << i))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Already taken
|
||||
if (is_taken(crtc_index, st->res, candidate)) {
|
||||
if (is_taken(i, st->res, candidate)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
st->res[crtc_index] = candidate;
|
||||
size_t crtc_score = st->conns[candidate] != 0 ? 1 : 0;
|
||||
if (match_connectors_with_crtcs_(st, score + crtc_score, replaced, crtc_index + 1)) {
|
||||
st->res[i] = candidate;
|
||||
size_t obj_score = st->objs[candidate] != 0 ? 1 : 0;
|
||||
if (match_obj_(st, skips, score + obj_score, replaced, i + 1)) {
|
||||
has_best = true;
|
||||
}
|
||||
|
||||
|
|
@ -215,37 +211,37 @@ static bool match_connectors_with_crtcs_(struct match_state *st,
|
|||
}
|
||||
}
|
||||
|
||||
// Maybe this CRTC can't be matched
|
||||
st->res[crtc_index] = UNMATCHED;
|
||||
if (match_connectors_with_crtcs_(st, score, replaced, crtc_index + 1)) {
|
||||
has_best = true;
|
||||
if (has_best) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return has_best;
|
||||
// Maybe this resource can't be matched
|
||||
st->res[i] = UNMATCHED;
|
||||
return match_obj_(st, skips, score, replaced, i + 1);
|
||||
}
|
||||
|
||||
void match_connectors_with_crtcs(size_t num_conns,
|
||||
const uint32_t conns[static restrict num_conns],
|
||||
size_t num_crtcs, const uint32_t prev_crtcs[static restrict num_crtcs],
|
||||
uint32_t new_crtcs[static restrict num_crtcs]) {
|
||||
uint32_t solution[num_crtcs];
|
||||
for (size_t i = 0; i < num_crtcs; ++i) {
|
||||
size_t match_obj(size_t num_objs, const uint32_t objs[static restrict num_objs],
|
||||
size_t num_res, const uint32_t res[static restrict num_res],
|
||||
uint32_t out[static restrict num_res]) {
|
||||
uint32_t solution[num_res];
|
||||
for (size_t i = 0; i < num_res; ++i) {
|
||||
solution[i] = UNMATCHED;
|
||||
}
|
||||
|
||||
struct match_state st = {
|
||||
.num_conns = num_conns,
|
||||
.num_crtcs = num_crtcs,
|
||||
.num_objs = num_objs,
|
||||
.num_res = num_res,
|
||||
.score = 0,
|
||||
.replaced = SIZE_MAX,
|
||||
.conns = conns,
|
||||
.objs = objs,
|
||||
.res = solution,
|
||||
.best = new_crtcs,
|
||||
.orig = prev_crtcs,
|
||||
.best = out,
|
||||
.orig = res,
|
||||
.exit_early = false,
|
||||
};
|
||||
|
||||
match_connectors_with_crtcs_(&st, 0, 0, 0);
|
||||
match_obj_(&st, 0, 0, 0, 0);
|
||||
return st.score;
|
||||
}
|
||||
|
||||
void generate_cvt_mode(drmModeModeInfo *mode, int hdisplay, int vdisplay,
|
||||
|
|
|
|||
|
|
@ -45,9 +45,16 @@ static void backend_destroy(struct wlr_backend *wlr_backend) {
|
|||
free(backend);
|
||||
}
|
||||
|
||||
static uint32_t get_buffer_caps(struct wlr_backend *wlr_backend) {
|
||||
return WLR_BUFFER_CAP_DATA_PTR
|
||||
| WLR_BUFFER_CAP_DMABUF
|
||||
| WLR_BUFFER_CAP_SHM;
|
||||
}
|
||||
|
||||
static const struct wlr_backend_impl backend_impl = {
|
||||
.start = backend_start,
|
||||
.destroy = backend_destroy,
|
||||
.get_buffer_caps = get_buffer_caps,
|
||||
};
|
||||
|
||||
static void handle_event_loop_destroy(struct wl_listener *listener, void *data) {
|
||||
|
|
@ -67,17 +74,12 @@ struct wlr_backend *wlr_headless_backend_create(struct wl_event_loop *loop) {
|
|||
|
||||
wlr_backend_init(&backend->backend, &backend_impl);
|
||||
|
||||
backend->backend.buffer_caps =
|
||||
WLR_BUFFER_CAP_DATA_PTR | WLR_BUFFER_CAP_DMABUF | WLR_BUFFER_CAP_SHM;
|
||||
|
||||
backend->event_loop = loop;
|
||||
wl_list_init(&backend->outputs);
|
||||
|
||||
backend->event_loop_destroy.notify = handle_event_loop_destroy;
|
||||
wl_event_loop_add_destroy_listener(loop, &backend->event_loop_destroy);
|
||||
|
||||
backend->backend.features.timeline = true;
|
||||
|
||||
return &backend->backend;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -79,20 +79,9 @@ static bool output_commit(struct wlr_output *wlr_output,
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool output_set_cursor(struct wlr_output *wlr_output,
|
||||
struct wlr_buffer *buffer, int hotspot_x, int hotspot_y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool output_move_cursor(struct wlr_output *wlr_output, int x, int y) {
|
||||
return true;
|
||||
}
|
||||
|
||||
static void output_destroy(struct wlr_output *wlr_output) {
|
||||
struct wlr_headless_output *output = headless_output_from_output(wlr_output);
|
||||
|
||||
wlr_output_finish(wlr_output);
|
||||
|
||||
struct wlr_headless_output *output =
|
||||
headless_output_from_output(wlr_output);
|
||||
wl_list_remove(&output->link);
|
||||
wl_event_source_remove(output->frame_timer);
|
||||
free(output);
|
||||
|
|
@ -100,10 +89,7 @@ static void output_destroy(struct wlr_output *wlr_output) {
|
|||
|
||||
static const struct wlr_output_impl output_impl = {
|
||||
.destroy = output_destroy,
|
||||
.test = output_test,
|
||||
.commit = output_commit,
|
||||
.set_cursor = output_set_cursor,
|
||||
.move_cursor = output_move_cursor,
|
||||
};
|
||||
|
||||
bool wlr_output_is_headless(struct wlr_output *wlr_output) {
|
||||
|
|
|
|||
|
|
@ -61,15 +61,25 @@ 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),
|
||||
};
|
||||
// Ignore events which aren't a seat-wide state change. For instance, if
|
||||
// the same button is pressed twice on the same seat, ignore the second
|
||||
// press.
|
||||
uint32_t seat_count = libinput_event_pointer_get_seat_button_count(pevent);
|
||||
switch (libinput_event_pointer_get_button_state(pevent)) {
|
||||
case LIBINPUT_BUTTON_STATE_PRESSED:
|
||||
wlr_event.state = WL_POINTER_BUTTON_STATE_PRESSED;
|
||||
if (seat_count != 1) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
case LIBINPUT_BUTTON_STATE_RELEASED:
|
||||
wlr_event.state = WL_POINTER_BUTTON_STATE_RELEASED;
|
||||
if (seat_count != 0) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
wlr_pointer_notify_button(pointer, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.button, &wlr_event);
|
||||
wl_signal_emit_mutable(&pointer->events.frame, pointer);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -104,7 +104,6 @@ void init_device_tablet_pad(struct wlr_libinput_input_device *dev) {
|
|||
struct udev_device *udev = libinput_device_get_udev_device(handle);
|
||||
char **dst = wl_array_add(&wlr_tablet_pad->paths, sizeof(char *));
|
||||
*dst = strdup(udev_device_get_syspath(udev));
|
||||
udev_device_unref(udev);
|
||||
|
||||
int groups = libinput_device_tablet_pad_get_num_mode_groups(handle);
|
||||
for (int i = 0; i < groups; ++i) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@
|
|||
#include <wlr/interfaces/wlr_tablet_tool.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/libinput.h"
|
||||
#include "config.h"
|
||||
|
||||
struct tablet_tool {
|
||||
struct wlr_tablet_tool wlr_tool;
|
||||
|
|
@ -37,7 +36,6 @@ void init_device_tablet(struct wlr_libinput_input_device *dev) {
|
|||
struct udev_device *udev = libinput_device_get_udev_device(dev->handle);
|
||||
char **dst = wl_array_add(&wlr_tablet->paths, sizeof(char *));
|
||||
*dst = strdup(udev_device_get_syspath(udev));
|
||||
udev_device_unref(udev);
|
||||
|
||||
wl_list_init(&dev->tablet_tools);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "backend/backend.h"
|
||||
#include "backend/multi.h"
|
||||
|
||||
struct subbackend_state {
|
||||
|
|
@ -51,9 +52,6 @@ static void multi_backend_destroy(struct wlr_backend *wlr_backend) {
|
|||
|
||||
wlr_backend_finish(wlr_backend);
|
||||
|
||||
assert(wl_list_empty(&backend->events.backend_add.listener_list));
|
||||
assert(wl_list_empty(&backend->events.backend_remove.listener_list));
|
||||
|
||||
// Some backends may depend on other backends, ie. destroying a backend may
|
||||
// also destroy other backends
|
||||
while (!wl_list_empty(&backend->backends)) {
|
||||
|
|
@ -78,6 +76,28 @@ static int multi_backend_get_drm_fd(struct wlr_backend *backend) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
static uint32_t multi_backend_get_buffer_caps(struct wlr_backend *backend) {
|
||||
struct wlr_multi_backend *multi = multi_backend_from_backend(backend);
|
||||
|
||||
if (wl_list_empty(&multi->backends)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t caps = WLR_BUFFER_CAP_DATA_PTR | WLR_BUFFER_CAP_DMABUF
|
||||
| WLR_BUFFER_CAP_SHM;
|
||||
|
||||
struct subbackend_state *sub;
|
||||
wl_list_for_each(sub, &multi->backends, link) {
|
||||
uint32_t backend_caps = backend_get_buffer_caps(sub->backend);
|
||||
if (backend_caps != 0) {
|
||||
// only count backend capable of presenting a buffer
|
||||
caps = caps & backend_caps;
|
||||
}
|
||||
}
|
||||
|
||||
return caps;
|
||||
}
|
||||
|
||||
static int compare_output_state_backend(const void *data_a, const void *data_b) {
|
||||
const struct wlr_backend_output_state *a = data_a;
|
||||
const struct wlr_backend_output_state *b = data_b;
|
||||
|
|
@ -106,24 +126,22 @@ static bool commit(struct wlr_backend *backend,
|
|||
qsort(by_backend, states_len, sizeof(by_backend[0]), compare_output_state_backend);
|
||||
|
||||
bool ok = true;
|
||||
for (size_t i = 0; i < states_len;) {
|
||||
for (size_t i = 0; i < states_len; i++) {
|
||||
struct wlr_backend *sub = by_backend[i].output->backend;
|
||||
|
||||
size_t len = 1;
|
||||
while (i + len < states_len &&
|
||||
by_backend[i + len].output->backend == sub) {
|
||||
len++;
|
||||
size_t j = i;
|
||||
while (j < states_len && by_backend[j].output->backend == sub) {
|
||||
j++;
|
||||
}
|
||||
|
||||
if (test_only) {
|
||||
ok = wlr_backend_test(sub, &by_backend[i], len);
|
||||
ok = wlr_backend_test(sub, &by_backend[i], j - i);
|
||||
} else {
|
||||
ok = wlr_backend_commit(sub, &by_backend[i], len);
|
||||
ok = wlr_backend_commit(sub, &by_backend[i], j - i);
|
||||
}
|
||||
if (!ok) {
|
||||
break;
|
||||
}
|
||||
i += len;
|
||||
}
|
||||
|
||||
free(by_backend);
|
||||
|
|
@ -144,6 +162,7 @@ static const struct wlr_backend_impl backend_impl = {
|
|||
.start = multi_backend_start,
|
||||
.destroy = multi_backend_destroy,
|
||||
.get_drm_fd = multi_backend_get_drm_fd,
|
||||
.get_buffer_caps = multi_backend_get_buffer_caps,
|
||||
.test = multi_backend_test,
|
||||
.commit = multi_backend_commit,
|
||||
};
|
||||
|
|
@ -206,33 +225,6 @@ static struct subbackend_state *multi_backend_get_subbackend(struct wlr_multi_ba
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static void multi_backend_refresh_features(struct wlr_multi_backend *multi) {
|
||||
multi->backend.buffer_caps = 0;
|
||||
multi->backend.features.timeline = true;
|
||||
|
||||
bool has_buffer_cap = false;
|
||||
uint32_t buffer_caps_intersection =
|
||||
WLR_BUFFER_CAP_DATA_PTR | WLR_BUFFER_CAP_DMABUF | WLR_BUFFER_CAP_SHM;
|
||||
struct subbackend_state *sub = NULL;
|
||||
wl_list_for_each(sub, &multi->backends, link) {
|
||||
// Only take into account backends capable of presenting a buffer
|
||||
if (sub->backend->buffer_caps != 0) {
|
||||
has_buffer_cap = true;
|
||||
buffer_caps_intersection &= sub->backend->buffer_caps;
|
||||
}
|
||||
|
||||
// timeline is only applicable to backends that support DMABUFs
|
||||
if (sub->backend->buffer_caps & WLR_BUFFER_CAP_DMABUF) {
|
||||
multi->backend.features.timeline = multi->backend.features.timeline &&
|
||||
sub->backend->features.timeline;
|
||||
}
|
||||
}
|
||||
|
||||
if (has_buffer_cap) {
|
||||
multi->backend.buffer_caps = buffer_caps_intersection;
|
||||
}
|
||||
}
|
||||
|
||||
bool wlr_multi_backend_add(struct wlr_backend *_multi,
|
||||
struct wlr_backend *backend) {
|
||||
assert(_multi && backend);
|
||||
|
|
@ -264,7 +256,6 @@ bool wlr_multi_backend_add(struct wlr_backend *_multi,
|
|||
wl_signal_add(&backend->events.new_output, &sub->new_output);
|
||||
sub->new_output.notify = new_output_reemit;
|
||||
|
||||
multi_backend_refresh_features(multi);
|
||||
wl_signal_emit_mutable(&multi->events.backend_add, backend);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -279,7 +270,6 @@ void wlr_multi_backend_remove(struct wlr_backend *_multi,
|
|||
if (sub) {
|
||||
wl_signal_emit_mutable(&multi->events.backend_remove, backend);
|
||||
subbackend_state_destroy(sub);
|
||||
multi_backend_refresh_features(multi);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -191,40 +191,32 @@ static int handle_udev_event(int fd, uint32_t mask, void *data) {
|
|||
goto out;
|
||||
}
|
||||
|
||||
dev_t devnum = udev_device_get_devnum(udev_dev);
|
||||
if (strcmp(action, "add") == 0) {
|
||||
struct wlr_device *dev;
|
||||
wl_list_for_each(dev, &session->devices, link) {
|
||||
if (dev->dev == devnum) {
|
||||
wlr_log(WLR_DEBUG, "Skipping duplicate device %s", sysname);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
wlr_log(WLR_DEBUG, "DRM device %s added", sysname);
|
||||
struct wlr_session_add_event event = {
|
||||
.path = devnode,
|
||||
};
|
||||
wl_signal_emit_mutable(&session->events.add_drm_card, &event);
|
||||
} else if (strcmp(action, "change") == 0) {
|
||||
} else if (strcmp(action, "change") == 0 || strcmp(action, "remove") == 0) {
|
||||
dev_t devnum = udev_device_get_devnum(udev_dev);
|
||||
struct wlr_device *dev;
|
||||
wl_list_for_each(dev, &session->devices, link) {
|
||||
if (dev->dev == devnum) {
|
||||
if (dev->dev != devnum) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (strcmp(action, "change") == 0) {
|
||||
wlr_log(WLR_DEBUG, "DRM device %s changed", sysname);
|
||||
struct wlr_device_change_event event = {0};
|
||||
read_udev_change_event(&event, udev_dev);
|
||||
wl_signal_emit_mutable(&dev->events.change, &event);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (strcmp(action, "remove") == 0) {
|
||||
struct wlr_device *dev;
|
||||
wl_list_for_each(dev, &session->devices, link) {
|
||||
if (dev->dev == devnum) {
|
||||
wlr_log(WLR_DEBUG, "DRM device %s removed", sysname);
|
||||
wl_signal_emit_mutable(&dev->events.remove, NULL);
|
||||
break;
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -303,11 +295,6 @@ void wlr_session_destroy(struct wlr_session *session) {
|
|||
}
|
||||
|
||||
wl_signal_emit_mutable(&session->events.destroy, session);
|
||||
|
||||
assert(wl_list_empty(&session->events.active.listener_list));
|
||||
assert(wl_list_empty(&session->events.add_drm_card.listener_list));
|
||||
assert(wl_list_empty(&session->events.destroy.listener_list));
|
||||
|
||||
wl_list_remove(&session->event_loop_destroy.link);
|
||||
|
||||
wl_event_source_remove(session->udev_event);
|
||||
|
|
@ -365,13 +352,6 @@ void wlr_session_close_file(struct wlr_session *session,
|
|||
if (libseat_close_device(session->seat_handle, dev->device_id) == -1) {
|
||||
wlr_log_errno(WLR_ERROR, "Failed to close device %d", dev->device_id);
|
||||
}
|
||||
|
||||
assert(wl_list_empty(&dev->events.change.listener_list));
|
||||
// TODO: assert that the "remove" listener list is empty as well. Listeners
|
||||
// will typically call wlr_session_close_file() in response, and
|
||||
// wl_signal_emit_mutable() installs two phantom listeners, so we'd count
|
||||
// these two.
|
||||
|
||||
close(dev->fd);
|
||||
wl_list_remove(&dev->link);
|
||||
free(dev);
|
||||
|
|
@ -519,6 +499,8 @@ ssize_t wlr_session_find_gpus(struct wlr_session *session,
|
|||
break;
|
||||
}
|
||||
|
||||
bool is_boot_vga = false;
|
||||
|
||||
const char *path = udev_list_entry_get_name(entry);
|
||||
struct udev_device *dev = udev_device_new_from_syspath(session->udev, path);
|
||||
if (!dev) {
|
||||
|
|
@ -534,11 +516,6 @@ ssize_t wlr_session_find_gpus(struct wlr_session *session,
|
|||
continue;
|
||||
}
|
||||
|
||||
bool is_primary = false;
|
||||
const char *boot_display = udev_device_get_sysattr_value(dev, "boot_display");
|
||||
if (boot_display && strcmp(boot_display, "1") == 0) {
|
||||
is_primary = true;
|
||||
} else {
|
||||
// This is owned by 'dev', so we don't need to free it
|
||||
struct udev_device *pci =
|
||||
udev_device_get_parent_with_subsystem_devtype(dev, "pci", NULL);
|
||||
|
|
@ -546,8 +523,7 @@ ssize_t wlr_session_find_gpus(struct wlr_session *session,
|
|||
if (pci) {
|
||||
const char *id = udev_device_get_sysattr_value(pci, "boot_vga");
|
||||
if (id && strcmp(id, "1") == 0) {
|
||||
is_primary = true;
|
||||
}
|
||||
is_boot_vga = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -561,7 +537,7 @@ ssize_t wlr_session_find_gpus(struct wlr_session *session,
|
|||
udev_device_unref(dev);
|
||||
|
||||
ret[i] = wlr_dev;
|
||||
if (is_primary) {
|
||||
if (is_boot_vga) {
|
||||
struct wlr_device *tmp = ret[0];
|
||||
ret[0] = ret[i];
|
||||
ret[i] = tmp;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,6 @@
|
|||
|
||||
#include "drm-client-protocol.h"
|
||||
#include "linux-dmabuf-v1-client-protocol.h"
|
||||
#include "linux-drm-syncobj-v1-client-protocol.h"
|
||||
#include "pointer-gestures-unstable-v1-client-protocol.h"
|
||||
#include "presentation-time-client-protocol.h"
|
||||
#include "xdg-activation-v1-client-protocol.h"
|
||||
|
|
@ -55,6 +54,14 @@ struct wlr_wl_backend *get_wl_backend_from_backend(struct wlr_backend *wlr_backe
|
|||
static int dispatch_events(int fd, uint32_t mask, void *data) {
|
||||
struct wlr_wl_backend *wl = data;
|
||||
|
||||
if ((mask & WL_EVENT_HANGUP) || (mask & WL_EVENT_ERROR)) {
|
||||
if (mask & WL_EVENT_ERROR) {
|
||||
wlr_log(WLR_ERROR, "Failed to read from remote Wayland display");
|
||||
}
|
||||
wlr_backend_destroy(&wl->backend);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
if (mask & WL_EVENT_READABLE) {
|
||||
count = wl_display_dispatch(wl->remote_display);
|
||||
|
|
@ -67,18 +74,6 @@ static int dispatch_events(int fd, uint32_t mask, void *data) {
|
|||
wl_display_flush(wl->remote_display);
|
||||
}
|
||||
|
||||
// Make sure we've consumed all data before disconnecting due to hangup,
|
||||
// so that we process any wl_display.error events
|
||||
if (!(mask & WL_EVENT_READABLE) && (mask & (WL_EVENT_HANGUP | WL_EVENT_ERROR))) {
|
||||
if (mask & WL_EVENT_ERROR) {
|
||||
wlr_log(WLR_ERROR, "Failed to read from remote Wayland display");
|
||||
} else {
|
||||
wlr_log(WLR_DEBUG, "Disconnected from remote Wayland display");
|
||||
}
|
||||
wlr_backend_destroy(&wl->backend);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (count < 0) {
|
||||
wlr_log(WLR_ERROR, "Failed to dispatch remote Wayland display");
|
||||
wlr_backend_destroy(&wl->backend);
|
||||
|
|
@ -183,9 +178,7 @@ static void linux_dmabuf_feedback_v1_handle_main_device(void *data,
|
|||
"falling back to primary node", name);
|
||||
}
|
||||
|
||||
struct wlr_wl_backend *wl = feedback_data->backend;
|
||||
assert(wl->drm_render_name == NULL);
|
||||
wl->drm_render_name = strdup(name);
|
||||
feedback_data->backend->drm_render_name = strdup(name);
|
||||
|
||||
drmFreeDevice(&device);
|
||||
}
|
||||
|
|
@ -312,7 +305,6 @@ static char *get_render_name(const char *name) {
|
|||
static void legacy_drm_handle_device(void *data, struct wl_drm *drm,
|
||||
const char *name) {
|
||||
struct wlr_wl_backend *wl = data;
|
||||
assert(wl->drm_render_name == NULL);
|
||||
wl->drm_render_name = get_render_name(name);
|
||||
}
|
||||
|
||||
|
|
@ -416,9 +408,6 @@ static void registry_global(void *data, struct wl_registry *registry,
|
|||
} else if (strcmp(iface, wp_viewporter_interface.name) == 0) {
|
||||
wl->viewporter = wl_registry_bind(registry, name,
|
||||
&wp_viewporter_interface, 1);
|
||||
} else if (strcmp(iface, wp_linux_drm_syncobj_manager_v1_interface.name) == 0) {
|
||||
wl->drm_syncobj_manager_v1 = wl_registry_bind(registry, name,
|
||||
&wp_linux_drm_syncobj_manager_v1_interface, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -492,11 +481,6 @@ static void backend_destroy(struct wlr_backend *backend) {
|
|||
destroy_wl_buffer(buffer);
|
||||
}
|
||||
|
||||
struct wlr_wl_drm_syncobj_timeline *timeline, *tmp_timeline;
|
||||
wl_list_for_each_safe(timeline, tmp_timeline, &wl->drm_syncobj_timelines, link) {
|
||||
destroy_wl_drm_syncobj_timeline(timeline);
|
||||
}
|
||||
|
||||
wlr_backend_finish(backend);
|
||||
|
||||
wl_list_remove(&wl->event_loop_destroy.link);
|
||||
|
|
@ -531,9 +515,6 @@ static void backend_destroy(struct wlr_backend *backend) {
|
|||
if (wl->zwp_linux_dmabuf_v1) {
|
||||
zwp_linux_dmabuf_v1_destroy(wl->zwp_linux_dmabuf_v1);
|
||||
}
|
||||
if (wl->drm_syncobj_manager_v1) {
|
||||
wp_linux_drm_syncobj_manager_v1_destroy(wl->drm_syncobj_manager_v1);
|
||||
}
|
||||
if (wl->legacy_drm != NULL) {
|
||||
wl_drm_destroy(wl->legacy_drm);
|
||||
}
|
||||
|
|
@ -559,7 +540,6 @@ static void backend_destroy(struct wlr_backend *backend) {
|
|||
wl_compositor_destroy(wl->compositor);
|
||||
wl_registry_destroy(wl->registry);
|
||||
wl_display_flush(wl->remote_display);
|
||||
wl_event_queue_destroy(wl->busy_loop_queue);
|
||||
if (wl->own_remote_display) {
|
||||
wl_display_disconnect(wl->remote_display);
|
||||
}
|
||||
|
|
@ -571,10 +551,17 @@ static int backend_get_drm_fd(struct wlr_backend *backend) {
|
|||
return wl->drm_fd;
|
||||
}
|
||||
|
||||
static uint32_t get_buffer_caps(struct wlr_backend *backend) {
|
||||
struct wlr_wl_backend *wl = get_wl_backend_from_backend(backend);
|
||||
return (wl->zwp_linux_dmabuf_v1 ? WLR_BUFFER_CAP_DMABUF : 0)
|
||||
| (wl->shm ? WLR_BUFFER_CAP_SHM : 0);
|
||||
}
|
||||
|
||||
static const struct wlr_backend_impl backend_impl = {
|
||||
.start = backend_start,
|
||||
.destroy = backend_destroy,
|
||||
.get_drm_fd = backend_get_drm_fd,
|
||||
.get_buffer_caps = get_buffer_caps,
|
||||
};
|
||||
|
||||
bool wlr_backend_is_wl(struct wlr_backend *b) {
|
||||
|
|
@ -602,7 +589,6 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_event_loop *loop,
|
|||
wl_list_init(&wl->outputs);
|
||||
wl_list_init(&wl->seats);
|
||||
wl_list_init(&wl->buffers);
|
||||
wl_list_init(&wl->drm_syncobj_timelines);
|
||||
|
||||
if (remote_display != NULL) {
|
||||
wl->remote_display = remote_display;
|
||||
|
|
@ -615,16 +601,10 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_event_loop *loop,
|
|||
wl->own_remote_display = true;
|
||||
}
|
||||
|
||||
wl->busy_loop_queue = wl_display_create_queue(wl->remote_display);
|
||||
if (wl->busy_loop_queue == NULL) {
|
||||
wlr_log_errno(WLR_ERROR, "Could not create a Wayland event queue");
|
||||
goto error_display;
|
||||
}
|
||||
|
||||
wl->registry = wl_display_get_registry(wl->remote_display);
|
||||
if (!wl->registry) {
|
||||
wlr_log_errno(WLR_ERROR, "Could not obtain reference to remote registry");
|
||||
goto error_queue;
|
||||
goto error_display;
|
||||
}
|
||||
wl_registry_add_listener(wl->registry, ®istry_listener, wl);
|
||||
|
||||
|
|
@ -641,10 +621,6 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_event_loop *loop,
|
|||
goto error_registry;
|
||||
}
|
||||
|
||||
wl->backend.features.timeline = wl->drm_syncobj_manager_v1 != NULL;
|
||||
|
||||
wl_display_roundtrip(wl->remote_display); // process initial event bursts
|
||||
|
||||
struct zwp_linux_dmabuf_feedback_v1 *linux_dmabuf_feedback_v1 = NULL;
|
||||
struct wlr_wl_linux_dmabuf_feedback_v1 feedback_data = { .backend = wl };
|
||||
if (wl->zwp_linux_dmabuf_v1 != NULL &&
|
||||
|
|
@ -662,27 +638,18 @@ struct wlr_backend *wlr_wl_backend_create(struct wl_event_loop *loop,
|
|||
if (wl->legacy_drm != NULL) {
|
||||
wl_drm_destroy(wl->legacy_drm);
|
||||
wl->legacy_drm = NULL;
|
||||
|
||||
free(wl->drm_render_name);
|
||||
wl->drm_render_name = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
wl_display_roundtrip(wl->remote_display); // get linux-dmabuf feedback events
|
||||
wl_display_roundtrip(wl->remote_display); // get linux-dmabuf formats
|
||||
|
||||
if (feedback_data.format_table != NULL) {
|
||||
munmap(feedback_data.format_table, feedback_data.format_table_size);
|
||||
}
|
||||
|
||||
if (linux_dmabuf_feedback_v1 != NULL) {
|
||||
zwp_linux_dmabuf_feedback_v1_destroy(linux_dmabuf_feedback_v1);
|
||||
}
|
||||
|
||||
if (wl->zwp_linux_dmabuf_v1) {
|
||||
wl->backend.buffer_caps |= WLR_BUFFER_CAP_DMABUF;
|
||||
}
|
||||
if (wl->shm) {
|
||||
wl->backend.buffer_caps |= WLR_BUFFER_CAP_SHM;
|
||||
}
|
||||
|
||||
int fd = wl_display_get_fd(wl->remote_display);
|
||||
wl->remote_display_src = wl_event_loop_add_fd(loop, fd, WL_EVENT_READABLE,
|
||||
dispatch_events, wl);
|
||||
|
|
@ -726,8 +693,6 @@ error_registry:
|
|||
xdg_wm_base_destroy(wl->xdg_wm_base);
|
||||
}
|
||||
wl_registry_destroy(wl->registry);
|
||||
error_queue:
|
||||
wl_event_queue_destroy(wl->busy_loop_queue);
|
||||
error_display:
|
||||
if (wl->own_remote_display) {
|
||||
wl_display_disconnect(wl->remote_display);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
wayland_client = dependency('wayland-client',
|
||||
kwargs: wayland_kwargs,
|
||||
fallback: 'wayland',
|
||||
default_options: wayland_project_options,
|
||||
)
|
||||
wlr_deps += wayland_client
|
||||
|
||||
|
|
@ -14,7 +15,6 @@ wlr_files += files(
|
|||
client_protos = [
|
||||
'drm',
|
||||
'linux-dmabuf-v1',
|
||||
'linux-drm-syncobj-v1',
|
||||
'pointer-gestures-unstable-v1',
|
||||
'presentation-time',
|
||||
'relative-pointer-unstable-v1',
|
||||
|
|
|
|||
|
|
@ -11,7 +11,6 @@
|
|||
#include <wayland-client-protocol.h>
|
||||
|
||||
#include <wlr/interfaces/wlr_output.h>
|
||||
#include <wlr/render/drm_syncobj.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_output_layer.h>
|
||||
#include <wlr/util/log.h>
|
||||
|
|
@ -21,7 +20,6 @@
|
|||
#include "types/wlr_output.h"
|
||||
|
||||
#include "linux-dmabuf-v1-client-protocol.h"
|
||||
#include "linux-drm-syncobj-v1-client-protocol.h"
|
||||
#include "presentation-time-client-protocol.h"
|
||||
#include "viewporter-client-protocol.h"
|
||||
#include "xdg-activation-v1-client-protocol.h"
|
||||
|
|
@ -33,9 +31,7 @@ static const uint32_t SUPPORTED_OUTPUT_STATE =
|
|||
WLR_OUTPUT_STATE_BUFFER |
|
||||
WLR_OUTPUT_STATE_ENABLED |
|
||||
WLR_OUTPUT_STATE_MODE |
|
||||
WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED |
|
||||
WLR_OUTPUT_STATE_WAIT_TIMELINE |
|
||||
WLR_OUTPUT_STATE_SIGNAL_TIMELINE;
|
||||
WLR_OUTPUT_STATE_ADAPTIVE_SYNC_ENABLED;
|
||||
|
||||
static size_t last_output_num = 0;
|
||||
|
||||
|
|
@ -98,13 +94,14 @@ static void presentation_feedback_handle_presented(void *data,
|
|||
uint32_t seq_hi, uint32_t seq_lo, uint32_t flags) {
|
||||
struct wlr_wl_presentation_feedback *feedback = data;
|
||||
|
||||
struct timespec t = {
|
||||
.tv_sec = ((uint64_t)tv_sec_hi << 32) | tv_sec_lo,
|
||||
.tv_nsec = tv_nsec,
|
||||
};
|
||||
struct wlr_output_event_present event = {
|
||||
.commit_seq = feedback->commit_seq,
|
||||
.presented = true,
|
||||
.when = {
|
||||
.tv_sec = ((uint64_t)tv_sec_hi << 32) | tv_sec_lo,
|
||||
.tv_nsec = tv_nsec,
|
||||
},
|
||||
.when = &t,
|
||||
.seq = ((uint64_t)seq_hi << 32) | seq_lo,
|
||||
.refresh = refresh_ns,
|
||||
.flags = flags,
|
||||
|
|
@ -134,11 +131,6 @@ static const struct wp_presentation_feedback_listener
|
|||
.discarded = presentation_feedback_handle_discarded,
|
||||
};
|
||||
|
||||
static void buffer_remove_drm_syncobj_waiter(struct wlr_wl_buffer *buffer) {
|
||||
wlr_drm_syncobj_timeline_waiter_finish(&buffer->drm_syncobj_waiter);
|
||||
buffer->has_drm_syncobj_waiter = false;
|
||||
}
|
||||
|
||||
void destroy_wl_buffer(struct wlr_wl_buffer *buffer) {
|
||||
if (buffer == NULL) {
|
||||
return;
|
||||
|
|
@ -146,42 +138,22 @@ void destroy_wl_buffer(struct wlr_wl_buffer *buffer) {
|
|||
wl_list_remove(&buffer->buffer_destroy.link);
|
||||
wl_list_remove(&buffer->link);
|
||||
wl_buffer_destroy(buffer->wl_buffer);
|
||||
if (buffer->has_drm_syncobj_waiter) {
|
||||
buffer_remove_drm_syncobj_waiter(buffer);
|
||||
}
|
||||
if (!buffer->released) {
|
||||
wlr_buffer_unlock(buffer->buffer);
|
||||
}
|
||||
wlr_drm_syncobj_timeline_unref(buffer->fallback_signal_timeline);
|
||||
free(buffer);
|
||||
}
|
||||
|
||||
static void buffer_release(struct wlr_wl_buffer *buffer) {
|
||||
if (buffer->released) {
|
||||
return;
|
||||
}
|
||||
buffer->released = true;
|
||||
wlr_buffer_unlock(buffer->buffer); // might free buffer
|
||||
}
|
||||
|
||||
static void buffer_handle_release(void *data, struct wl_buffer *wl_buffer) {
|
||||
struct wlr_wl_buffer *buffer = data;
|
||||
if (buffer->has_drm_syncobj_waiter) {
|
||||
return;
|
||||
}
|
||||
buffer_release(buffer);
|
||||
buffer->released = true;
|
||||
wlr_buffer_unlock(buffer->buffer); // might free buffer
|
||||
}
|
||||
|
||||
static const struct wl_buffer_listener buffer_listener = {
|
||||
.release = buffer_handle_release,
|
||||
};
|
||||
|
||||
static void buffer_handle_drm_syncobj_ready(struct wlr_drm_syncobj_timeline_waiter *waiter) {
|
||||
struct wlr_wl_buffer *buffer = wl_container_of(waiter, buffer, drm_syncobj_waiter);
|
||||
buffer_remove_drm_syncobj_waiter(buffer);
|
||||
buffer_release(buffer);
|
||||
}
|
||||
|
||||
static void buffer_handle_buffer_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct wlr_wl_buffer *buffer =
|
||||
|
|
@ -204,30 +176,6 @@ static bool test_buffer(struct wlr_wl_backend *wl,
|
|||
}
|
||||
}
|
||||
|
||||
struct dmabuf_listener_data {
|
||||
struct wl_buffer *wl_buffer;
|
||||
bool done;
|
||||
};
|
||||
|
||||
static void dmabuf_handle_created(void *data_, struct zwp_linux_buffer_params_v1 *params,
|
||||
struct wl_buffer *buffer) {
|
||||
struct dmabuf_listener_data *data = data_;
|
||||
data->wl_buffer = buffer;
|
||||
data->done = true;
|
||||
wlr_log(WLR_DEBUG, "DMA-BUF imported into parent Wayland compositor");
|
||||
}
|
||||
|
||||
static void dmabuf_handle_failed(void *data_, struct zwp_linux_buffer_params_v1 *params) {
|
||||
struct dmabuf_listener_data *data = data_;
|
||||
data->done = true;
|
||||
wlr_log(WLR_ERROR, "Failed to import DMA-BUF into parent Wayland compositor");
|
||||
}
|
||||
|
||||
static const struct zwp_linux_buffer_params_v1_listener dmabuf_listener = {
|
||||
.created = dmabuf_handle_created,
|
||||
.failed = dmabuf_handle_failed,
|
||||
};
|
||||
|
||||
static struct wl_buffer *import_dmabuf(struct wlr_wl_backend *wl,
|
||||
struct wlr_dmabuf_attributes *dmabuf) {
|
||||
uint32_t modifier_hi = dmabuf->modifier >> 32;
|
||||
|
|
@ -239,35 +187,18 @@ static struct wl_buffer *import_dmabuf(struct wlr_wl_backend *wl,
|
|||
dmabuf->offset[i], dmabuf->stride[i], modifier_hi, modifier_lo);
|
||||
}
|
||||
|
||||
struct dmabuf_listener_data data = {0};
|
||||
zwp_linux_buffer_params_v1_add_listener(params, &dmabuf_listener, &data);
|
||||
zwp_linux_buffer_params_v1_create(params, dmabuf->width, dmabuf->height, dmabuf->format, 0);
|
||||
|
||||
struct wl_event_queue *display_queue =
|
||||
wl_proxy_get_queue((struct wl_proxy *)wl->remote_display);
|
||||
wl_proxy_set_queue((struct wl_proxy *)params, wl->busy_loop_queue);
|
||||
|
||||
while (!data.done) {
|
||||
if (wl_display_dispatch_queue(wl->remote_display, wl->busy_loop_queue) < 0) {
|
||||
wlr_log(WLR_ERROR, "wl_display_dispatch_queue() failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct wl_buffer *buffer = data.wl_buffer;
|
||||
if (buffer != NULL) {
|
||||
wl_proxy_set_queue((struct wl_proxy *)buffer, display_queue);
|
||||
}
|
||||
|
||||
struct wl_buffer *wl_buffer = zwp_linux_buffer_params_v1_create_immed(
|
||||
params, dmabuf->width, dmabuf->height, dmabuf->format, 0);
|
||||
zwp_linux_buffer_params_v1_destroy(params);
|
||||
return buffer;
|
||||
// TODO: handle create() errors
|
||||
return wl_buffer;
|
||||
}
|
||||
|
||||
static struct wl_buffer *import_shm(struct wlr_wl_backend *wl,
|
||||
struct wlr_shm_attributes *shm) {
|
||||
enum wl_shm_format wl_shm_format = convert_drm_format_to_wl_shm(shm->format);
|
||||
uint32_t size = shm->stride * shm->height;
|
||||
struct wl_shm_pool *pool = wl_shm_create_pool(wl->shm, shm->fd, shm->offset + size);
|
||||
struct wl_shm_pool *pool = wl_shm_create_pool(wl->shm, shm->fd, size);
|
||||
if (pool == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -331,58 +262,6 @@ static struct wlr_wl_buffer *get_or_create_wl_buffer(struct wlr_wl_backend *wl,
|
|||
return create_wl_buffer(wl, wlr_buffer);
|
||||
}
|
||||
|
||||
void destroy_wl_drm_syncobj_timeline(struct wlr_wl_drm_syncobj_timeline *timeline) {
|
||||
wp_linux_drm_syncobj_timeline_v1_destroy(timeline->wl);
|
||||
wlr_addon_finish(&timeline->addon);
|
||||
wl_list_remove(&timeline->link);
|
||||
free(timeline);
|
||||
}
|
||||
|
||||
static void drm_syncobj_timeline_addon_destroy(struct wlr_addon *addon) {
|
||||
struct wlr_wl_drm_syncobj_timeline *timeline = wl_container_of(addon, timeline, addon);
|
||||
destroy_wl_drm_syncobj_timeline(timeline);
|
||||
}
|
||||
|
||||
static const struct wlr_addon_interface drm_syncobj_timeline_addon_impl = {
|
||||
.name = "wlr_wl_drm_syncobj_timeline",
|
||||
.destroy = drm_syncobj_timeline_addon_destroy,
|
||||
};
|
||||
|
||||
static struct wlr_wl_drm_syncobj_timeline *get_or_create_drm_syncobj_timeline(
|
||||
struct wlr_wl_backend *wl, struct wlr_drm_syncobj_timeline *wlr_timeline) {
|
||||
struct wlr_addon *addon =
|
||||
wlr_addon_find(&wlr_timeline->addons, wl, &drm_syncobj_timeline_addon_impl);
|
||||
if (addon != NULL) {
|
||||
struct wlr_wl_drm_syncobj_timeline *timeline = wl_container_of(addon, timeline, addon);
|
||||
return timeline;
|
||||
}
|
||||
|
||||
struct wlr_wl_drm_syncobj_timeline *timeline = calloc(1, sizeof(*timeline));
|
||||
if (timeline == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
timeline->base = wlr_timeline;
|
||||
|
||||
int fd = wlr_drm_syncobj_timeline_export(wlr_timeline);
|
||||
if (fd < 0) {
|
||||
free(timeline);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
timeline->wl = wp_linux_drm_syncobj_manager_v1_import_timeline(wl->drm_syncobj_manager_v1, fd);
|
||||
close(fd);
|
||||
if (timeline->wl == NULL) {
|
||||
free(timeline);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wlr_addon_init(&timeline->addon, &wlr_timeline->addons, wl, &drm_syncobj_timeline_addon_impl);
|
||||
wl_list_insert(&wl->drm_syncobj_timelines, &timeline->link);
|
||||
|
||||
return timeline;
|
||||
}
|
||||
|
||||
static bool update_title(struct wlr_wl_output *output, const char *title) {
|
||||
struct wlr_output *wlr_output = &output->wlr_output;
|
||||
|
||||
|
|
@ -422,28 +301,6 @@ static bool output_test(struct wlr_output *wlr_output,
|
|||
struct wlr_wl_output *output =
|
||||
get_wl_output_from_output(wlr_output);
|
||||
|
||||
if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
// If the size doesn't match, reject buffer (scaling is not currently
|
||||
// supported but could be implemented with viewporter)
|
||||
int pending_width, pending_height;
|
||||
output_pending_resolution(wlr_output, state,
|
||||
&pending_width, &pending_height);
|
||||
if (state->buffer->width != pending_width ||
|
||||
state->buffer->height != pending_height) {
|
||||
wlr_log(WLR_DEBUG, "Primary buffer size mismatch");
|
||||
return false;
|
||||
}
|
||||
// Source crop is also not currently supported
|
||||
struct wlr_fbox src_box;
|
||||
output_state_get_buffer_src_box(state, &src_box);
|
||||
if (src_box.x != 0.0 || src_box.y != 0.0 ||
|
||||
src_box.width != (double)state->buffer->width ||
|
||||
src_box.height != (double)state->buffer->height) {
|
||||
wlr_log(WLR_DEBUG, "Source crop not supported in wayland output");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t unsupported = state->committed & ~SUPPORTED_OUTPUT_STATE;
|
||||
if (unsupported != 0) {
|
||||
wlr_log(WLR_DEBUG, "Unsupported output state fields: 0x%"PRIx32,
|
||||
|
|
@ -477,21 +334,6 @@ static bool output_test(struct wlr_output *wlr_output,
|
|||
return false;
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE) &&
|
||||
!(state->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE)) {
|
||||
wlr_log(WLR_DEBUG, "Signal timeline requires a wait timeline");
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) ||
|
||||
(state->committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE)) {
|
||||
struct wlr_dmabuf_attributes dmabuf;
|
||||
if (!wlr_buffer_get_dmabuf(state->buffer, &dmabuf)) {
|
||||
wlr_log(WLR_DEBUG, "Wait/signal timelines require DMA-BUFs");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (state->committed & WLR_OUTPUT_STATE_LAYERS) {
|
||||
// If we can't use a sub-surface for a layer, then we can't use a
|
||||
// sub-surface for any layer underneath
|
||||
|
|
@ -723,15 +565,15 @@ static const struct wl_callback_listener unmap_callback_listener = {
|
|||
.done = unmap_callback_handle_done,
|
||||
};
|
||||
|
||||
static bool output_commit(struct wlr_output *wlr_output, const struct wlr_output_state *state) {
|
||||
struct wlr_wl_output *output = get_wl_output_from_output(wlr_output);
|
||||
static bool output_commit(struct wlr_output *wlr_output,
|
||||
const struct wlr_output_state *state) {
|
||||
struct wlr_wl_output *output =
|
||||
get_wl_output_from_output(wlr_output);
|
||||
|
||||
if (!output_test(wlr_output, state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
struct wlr_wl_backend *wl = output->backend;
|
||||
|
||||
bool pending_enabled = output_pending_enabled(wlr_output, state);
|
||||
|
||||
if (wlr_output->enabled && !pending_enabled) {
|
||||
|
|
@ -756,28 +598,15 @@ static bool output_commit(struct wlr_output *wlr_output, const struct wlr_output
|
|||
wl_surface_commit(output->surface);
|
||||
output->initialized = true;
|
||||
|
||||
struct wl_event_queue *display_queue =
|
||||
wl_proxy_get_queue((struct wl_proxy *)wl->remote_display);
|
||||
wl_proxy_set_queue((struct wl_proxy *)output->xdg_surface, wl->busy_loop_queue);
|
||||
wl_proxy_set_queue((struct wl_proxy *)output->xdg_toplevel, wl->busy_loop_queue);
|
||||
|
||||
wl_display_flush(wl->remote_display);
|
||||
wl_display_flush(output->backend->remote_display);
|
||||
while (!output->configured) {
|
||||
if (wl_display_dispatch_queue(wl->remote_display, wl->busy_loop_queue) == -1) {
|
||||
wlr_log(WLR_ERROR, "wl_display_dispatch_queue() failed");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
wl_proxy_set_queue((struct wl_proxy *)output->xdg_surface, display_queue);
|
||||
wl_proxy_set_queue((struct wl_proxy *)output->xdg_toplevel, display_queue);
|
||||
|
||||
if (!output->configured) {
|
||||
if (wl_display_dispatch(output->backend->remote_display) == -1) {
|
||||
wlr_log(WLR_ERROR, "wl_display_dispatch() failed");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct wlr_wl_buffer *buffer = NULL;
|
||||
if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
const pixman_region32_t *damage = NULL;
|
||||
if (state->committed & WLR_OUTPUT_STATE_DAMAGE) {
|
||||
|
|
@ -785,7 +614,8 @@ static bool output_commit(struct wlr_output *wlr_output, const struct wlr_output
|
|||
}
|
||||
|
||||
struct wlr_buffer *wlr_buffer = state->buffer;
|
||||
buffer = get_or_create_wl_buffer(wl, wlr_buffer);
|
||||
struct wlr_wl_buffer *buffer =
|
||||
get_or_create_wl_buffer(output->backend, wlr_buffer);
|
||||
if (buffer == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -794,63 +624,6 @@ static bool output_commit(struct wlr_output *wlr_output, const struct wlr_output
|
|||
damage_surface(output->surface, damage);
|
||||
}
|
||||
|
||||
if (state->committed & WLR_OUTPUT_STATE_WAIT_TIMELINE) {
|
||||
struct wlr_wl_drm_syncobj_timeline *wait_timeline =
|
||||
get_or_create_drm_syncobj_timeline(wl, state->wait_timeline);
|
||||
|
||||
struct wlr_wl_drm_syncobj_timeline *signal_timeline;
|
||||
uint64_t signal_point;
|
||||
if (state->committed & WLR_OUTPUT_STATE_SIGNAL_TIMELINE) {
|
||||
signal_timeline = get_or_create_drm_syncobj_timeline(wl, state->signal_timeline);
|
||||
signal_point = state->signal_point;
|
||||
} else {
|
||||
if (buffer->fallback_signal_timeline == NULL) {
|
||||
buffer->fallback_signal_timeline =
|
||||
wlr_drm_syncobj_timeline_create(wl->drm_fd);
|
||||
if (buffer->fallback_signal_timeline == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
signal_timeline =
|
||||
get_or_create_drm_syncobj_timeline(wl, buffer->fallback_signal_timeline);
|
||||
signal_point = ++buffer->fallback_signal_point;
|
||||
}
|
||||
|
||||
if (wait_timeline == NULL || signal_timeline == NULL) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (output->drm_syncobj_surface_v1 == NULL) {
|
||||
output->drm_syncobj_surface_v1 = wp_linux_drm_syncobj_manager_v1_get_surface(
|
||||
wl->drm_syncobj_manager_v1, output->surface);
|
||||
if (output->drm_syncobj_surface_v1 == NULL) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t wait_point_hi = state->wait_point >> 32;
|
||||
uint32_t wait_point_lo = state->wait_point & UINT32_MAX;
|
||||
uint32_t signal_point_hi = signal_point >> 32;
|
||||
uint32_t signal_point_lo = signal_point & UINT32_MAX;
|
||||
|
||||
wp_linux_drm_syncobj_surface_v1_set_acquire_point(output->drm_syncobj_surface_v1,
|
||||
wait_timeline->wl, wait_point_hi, wait_point_lo);
|
||||
wp_linux_drm_syncobj_surface_v1_set_release_point(output->drm_syncobj_surface_v1,
|
||||
signal_timeline->wl, signal_point_hi, signal_point_lo);
|
||||
|
||||
if (!wlr_drm_syncobj_timeline_waiter_init(&buffer->drm_syncobj_waiter,
|
||||
signal_timeline->base, signal_point, 0, wl->event_loop,
|
||||
buffer_handle_drm_syncobj_ready)) {
|
||||
return false;
|
||||
}
|
||||
buffer->has_drm_syncobj_waiter = true;
|
||||
} else {
|
||||
if (output->drm_syncobj_surface_v1 != NULL) {
|
||||
wp_linux_drm_syncobj_surface_v1_destroy(output->drm_syncobj_surface_v1);
|
||||
output->drm_syncobj_surface_v1 = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if ((state->committed & WLR_OUTPUT_STATE_LAYERS) &&
|
||||
!commit_layers(output, state->layers, state->layers_len)) {
|
||||
return false;
|
||||
|
|
@ -864,8 +637,9 @@ static bool output_commit(struct wlr_output *wlr_output, const struct wlr_output
|
|||
wl_callback_add_listener(output->frame_callback, &frame_listener, output);
|
||||
|
||||
struct wp_presentation_feedback *wp_feedback = NULL;
|
||||
if (wl->presentation != NULL) {
|
||||
wp_feedback = wp_presentation_feedback(wl->presentation, output->surface);
|
||||
if (output->backend->presentation != NULL) {
|
||||
wp_feedback = wp_presentation_feedback(output->backend->presentation,
|
||||
output->surface);
|
||||
}
|
||||
|
||||
if (output->has_configure_serial) {
|
||||
|
|
@ -898,7 +672,7 @@ static bool output_commit(struct wlr_output *wlr_output, const struct wlr_output
|
|||
}
|
||||
}
|
||||
|
||||
wl_display_flush(wl->remote_display);
|
||||
wl_display_flush(output->backend->remote_display);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -954,8 +728,6 @@ static void output_destroy(struct wlr_output *wlr_output) {
|
|||
return;
|
||||
}
|
||||
|
||||
wlr_output_finish(wlr_output);
|
||||
|
||||
wl_list_remove(&output->link);
|
||||
|
||||
if (output->cursor.surface) {
|
||||
|
|
@ -976,9 +748,6 @@ static void output_destroy(struct wlr_output *wlr_output) {
|
|||
wl_callback_destroy(output->unmap_callback);
|
||||
}
|
||||
|
||||
if (output->drm_syncobj_surface_v1) {
|
||||
wp_linux_drm_syncobj_surface_v1_destroy(output->drm_syncobj_surface_v1);
|
||||
}
|
||||
if (output->zxdg_toplevel_decoration_v1) {
|
||||
zxdg_toplevel_decoration_v1_destroy(output->zxdg_toplevel_decoration_v1);
|
||||
}
|
||||
|
|
@ -1055,12 +824,6 @@ static void xdg_surface_handle_configure(void *data,
|
|||
output->has_configure_serial = true;
|
||||
output->configure_serial = serial;
|
||||
|
||||
if (!output->wlr_output.enabled) {
|
||||
// We're waiting for a configure event after an initial commit to enable
|
||||
// the output. Do not notify the compositor about the requested state.
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_output_state state;
|
||||
wlr_output_state_init(&state);
|
||||
wlr_output_state_set_custom_mode(&state, req_width, req_height, 0);
|
||||
|
|
|
|||
|
|
@ -112,7 +112,7 @@ static void pointer_handle_button(void *data, struct wl_pointer *wl_pointer,
|
|||
.state = state,
|
||||
.time_msec = time,
|
||||
};
|
||||
wlr_pointer_notify_button(&pointer->wlr_pointer, &event);
|
||||
wl_signal_emit_mutable(&pointer->wlr_pointer.events.button, &event);
|
||||
}
|
||||
|
||||
static void pointer_handle_axis(void *data, struct wl_pointer *wl_pointer,
|
||||
|
|
|
|||
|
|
@ -27,14 +27,12 @@ static void keyboard_handle_enter(void *data, struct wl_keyboard *wl_keyboard,
|
|||
uint32_t serial, struct wl_surface *surface, struct wl_array *keys) {
|
||||
struct wlr_keyboard *keyboard = data;
|
||||
|
||||
int64_t time_msec = get_current_time_msec();
|
||||
|
||||
uint32_t *keycode_ptr;
|
||||
wl_array_for_each(keycode_ptr, keys) {
|
||||
struct wlr_keyboard_key_event event = {
|
||||
.keycode = *keycode_ptr,
|
||||
.state = WL_KEYBOARD_KEY_STATE_PRESSED,
|
||||
.time_msec = time_msec,
|
||||
.time_msec = get_current_time_msec(),
|
||||
.update_state = false,
|
||||
};
|
||||
wlr_keyboard_notify_key(keyboard, &event);
|
||||
|
|
@ -45,12 +43,18 @@ static void keyboard_handle_leave(void *data, struct wl_keyboard *wl_keyboard,
|
|||
uint32_t serial, struct wl_surface *surface) {
|
||||
struct wlr_keyboard *keyboard = data;
|
||||
|
||||
int64_t time_msec = get_current_time_msec();
|
||||
while (keyboard->num_keycodes > 0) {
|
||||
size_t num_keycodes = keyboard->num_keycodes;
|
||||
uint32_t pressed[num_keycodes + 1];
|
||||
memcpy(pressed, keyboard->keycodes,
|
||||
num_keycodes * sizeof(uint32_t));
|
||||
|
||||
for (size_t i = 0; i < num_keycodes; ++i) {
|
||||
uint32_t keycode = pressed[i];
|
||||
|
||||
struct wlr_keyboard_key_event event = {
|
||||
.keycode = keyboard->keycodes[keyboard->num_keycodes - 1],
|
||||
.keycode = keycode,
|
||||
.state = WL_KEYBOARD_KEY_STATE_RELEASED,
|
||||
.time_msec = time_msec,
|
||||
.time_msec = get_current_time_msec(),
|
||||
.update_state = false,
|
||||
};
|
||||
wlr_keyboard_notify_key(keyboard, &event);
|
||||
|
|
|
|||
|
|
@ -212,10 +212,17 @@ static int backend_get_drm_fd(struct wlr_backend *backend) {
|
|||
return x11->drm_fd;
|
||||
}
|
||||
|
||||
static uint32_t get_buffer_caps(struct wlr_backend *backend) {
|
||||
struct wlr_x11_backend *x11 = get_x11_backend_from_backend(backend);
|
||||
return (x11->have_dri3 ? WLR_BUFFER_CAP_DMABUF : 0)
|
||||
| (x11->have_shm ? WLR_BUFFER_CAP_SHM : 0);
|
||||
}
|
||||
|
||||
static const struct wlr_backend_impl backend_impl = {
|
||||
.start = backend_start,
|
||||
.destroy = backend_destroy,
|
||||
.get_drm_fd = backend_get_drm_fd,
|
||||
.get_buffer_caps = get_buffer_caps,
|
||||
};
|
||||
|
||||
bool wlr_backend_is_x11(struct wlr_backend *backend) {
|
||||
|
|
@ -402,7 +409,7 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_event_loop *loop,
|
|||
wl_list_init(&x11->outputs);
|
||||
|
||||
x11->xcb = xcb_connect(x11_display, NULL);
|
||||
if (xcb_connection_has_error(x11->xcb)) {
|
||||
if (!x11->xcb || xcb_connection_has_error(x11->xcb)) {
|
||||
wlr_log(WLR_ERROR, "Failed to open xcb connection");
|
||||
goto error_x11;
|
||||
}
|
||||
|
|
@ -505,10 +512,7 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_event_loop *loop,
|
|||
xcb_present_query_version(x11->xcb, 1, 2);
|
||||
xcb_present_query_version_reply_t *present_reply =
|
||||
xcb_present_query_version_reply(x11->xcb, present_cookie, NULL);
|
||||
if (!present_reply) {
|
||||
wlr_log(WLR_ERROR, "Failed to query Present version");
|
||||
goto error_display;
|
||||
} else if (present_reply->major_version < 1) {
|
||||
if (!present_reply || present_reply->major_version < 1) {
|
||||
wlr_log(WLR_ERROR, "X11 does not support required Present version "
|
||||
"(has %"PRIu32".%"PRIu32", want 1.0)",
|
||||
present_reply->major_version, present_reply->minor_version);
|
||||
|
|
@ -529,10 +533,7 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_event_loop *loop,
|
|||
xcb_xfixes_query_version(x11->xcb, 4, 0);
|
||||
xcb_xfixes_query_version_reply_t *fixes_reply =
|
||||
xcb_xfixes_query_version_reply(x11->xcb, fixes_cookie, NULL);
|
||||
if (!fixes_reply) {
|
||||
wlr_log(WLR_ERROR, "Failed to query Xfixes version");
|
||||
goto error_display;
|
||||
} else if (fixes_reply->major_version < 4) {
|
||||
if (!fixes_reply || fixes_reply->major_version < 4) {
|
||||
wlr_log(WLR_ERROR, "X11 does not support required Xfixes version "
|
||||
"(has %"PRIu32".%"PRIu32", want 4.0)",
|
||||
fixes_reply->major_version, fixes_reply->minor_version);
|
||||
|
|
@ -554,10 +555,7 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_event_loop *loop,
|
|||
xcb_input_xi_query_version(x11->xcb, 2, 0);
|
||||
xcb_input_xi_query_version_reply_t *xi_reply =
|
||||
xcb_input_xi_query_version_reply(x11->xcb, xi_cookie, NULL);
|
||||
if (!xi_reply) {
|
||||
wlr_log(WLR_ERROR, "Failed to query Xinput version");
|
||||
goto error_display;
|
||||
} else if (xi_reply->major_version < 2) {
|
||||
if (!xi_reply || xi_reply->major_version < 2) {
|
||||
wlr_log(WLR_ERROR, "X11 does not support required Xinput version "
|
||||
"(has %"PRIu32".%"PRIu32", want 2.0)",
|
||||
xi_reply->major_version, xi_reply->minor_version);
|
||||
|
|
@ -566,13 +564,6 @@ struct wlr_backend *wlr_x11_backend_create(struct wl_event_loop *loop,
|
|||
}
|
||||
free(xi_reply);
|
||||
|
||||
if (x11->have_dri3) {
|
||||
x11->backend.buffer_caps |= WLR_BUFFER_CAP_DMABUF;
|
||||
}
|
||||
if (x11->have_shm) {
|
||||
x11->backend.buffer_caps |= WLR_BUFFER_CAP_SHM;
|
||||
}
|
||||
|
||||
int fd = xcb_get_file_descriptor(x11->xcb);
|
||||
uint32_t events = WL_EVENT_READABLE | WL_EVENT_ERROR | WL_EVENT_HANGUP;
|
||||
x11->event_source = wl_event_loop_add_fd(loop, fd, events, x11_event, x11);
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ static void send_button_event(struct wlr_x11_output *output, uint32_t key,
|
|||
.button = key,
|
||||
.state = st,
|
||||
};
|
||||
wlr_pointer_notify_button(&output->pointer, &ev);
|
||||
wl_signal_emit_mutable(&output->pointer.events.button, &ev);
|
||||
wl_signal_emit_mutable(&output->pointer.events.frame, &output->pointer);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -94,8 +94,6 @@ static void output_destroy(struct wlr_output *wlr_output) {
|
|||
struct wlr_x11_output *output = get_x11_output_from_output(wlr_output);
|
||||
struct wlr_x11_backend *x11 = output->x11;
|
||||
|
||||
wlr_output_finish(wlr_output);
|
||||
|
||||
pixman_region32_fini(&output->exposed);
|
||||
|
||||
wlr_pointer_finish(&output->pointer);
|
||||
|
|
@ -131,27 +129,6 @@ static bool output_test(struct wlr_output *wlr_output,
|
|||
return false;
|
||||
}
|
||||
|
||||
if (state->committed & WLR_OUTPUT_STATE_BUFFER) {
|
||||
// If the size doesn't match, reject buffer (scaling is not supported)
|
||||
int pending_width, pending_height;
|
||||
output_pending_resolution(wlr_output, state,
|
||||
&pending_width, &pending_height);
|
||||
if (state->buffer->width != pending_width ||
|
||||
state->buffer->height != pending_height) {
|
||||
wlr_log(WLR_DEBUG, "Primary buffer size mismatch");
|
||||
return false;
|
||||
}
|
||||
// Source crop is not supported
|
||||
struct wlr_fbox src_box;
|
||||
output_state_get_buffer_src_box(state, &src_box);
|
||||
if (src_box.x != 0.0 || src_box.y != 0.0 ||
|
||||
src_box.width != (double)state->buffer->width ||
|
||||
src_box.height != (double)state->buffer->height) {
|
||||
wlr_log(WLR_DEBUG, "Source crop not supported in X11 output");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// All we can do to influence adaptive sync on the X11 backend is set the
|
||||
// _VARIABLE_REFRESH window property like mesa automatically does. We don't
|
||||
// have any control beyond that, so we set the state to enabled on creating
|
||||
|
|
@ -770,6 +747,9 @@ void handle_x11_present_event(struct wlr_x11_backend *x11,
|
|||
|
||||
output->last_msc = complete_notify->msc;
|
||||
|
||||
struct timespec t;
|
||||
timespec_from_nsec(&t, complete_notify->ust * 1000);
|
||||
|
||||
uint32_t flags = 0;
|
||||
if (complete_notify->mode == XCB_PRESENT_COMPLETE_MODE_FLIP) {
|
||||
flags |= WLR_OUTPUT_PRESENT_ZERO_COPY;
|
||||
|
|
@ -780,10 +760,10 @@ void handle_x11_present_event(struct wlr_x11_backend *x11,
|
|||
.output = &output->wlr_output,
|
||||
.commit_seq = complete_notify->serial,
|
||||
.presented = presented,
|
||||
.when = &t,
|
||||
.seq = complete_notify->msc,
|
||||
.flags = flags,
|
||||
};
|
||||
timespec_from_nsec(&present_event.when, complete_notify->ust * 1000);
|
||||
wlr_output_send_present(&output->wlr_output, &present_event);
|
||||
|
||||
wlr_output_send_frame(&output->wlr_output);
|
||||
|
|
|
|||
|
|
@ -12,10 +12,6 @@ wlroots reads these environment variables
|
|||
renderers: gles2, pixman, vulkan)
|
||||
* *WLR_RENDER_DRM_DEVICE*: specifies the DRM node to use for
|
||||
hardware-accelerated renderers.
|
||||
* *WLR_RENDER_NO_EXPLICIT_SYNC*: set to 1 to disable explicit synchronization
|
||||
support in renderers.
|
||||
* *WLR_RENDERER_FORCE_SOFTWARE*: set to 1 to force software rendering for GLES2
|
||||
and Vulkan
|
||||
* *WLR_EGL_NO_MODIFIERS*: set to 1 to disable format modifiers in EGL, this can
|
||||
be used to understand and work around driver bugs.
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ struct cairo_buffer {
|
|||
|
||||
static void cairo_buffer_destroy(struct wlr_buffer *wlr_buffer) {
|
||||
struct cairo_buffer *buffer = wl_container_of(wlr_buffer, buffer, base);
|
||||
wlr_buffer_finish(wlr_buffer);
|
||||
cairo_surface_destroy(buffer->surface);
|
||||
free(buffer);
|
||||
}
|
||||
|
|
|
|||
258
examples/fullscreen-shell.c
Normal file
258
examples/fullscreen-shell.c
Normal file
|
|
@ -0,0 +1,258 @@
|
|||
#include <getopt.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/backend.h>
|
||||
#include <wlr/render/allocator.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/types/wlr_compositor.h>
|
||||
#include <wlr/types/wlr_fullscreen_shell_v1.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/util/box.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include <wlr/util/transform.h>
|
||||
|
||||
/**
|
||||
* A minimal fullscreen-shell server. It only supports rendering.
|
||||
*/
|
||||
|
||||
struct fullscreen_server {
|
||||
struct wl_display *wl_display;
|
||||
struct wlr_backend *backend;
|
||||
struct wlr_renderer *renderer;
|
||||
struct wlr_allocator *allocator;
|
||||
|
||||
struct wlr_fullscreen_shell_v1 *fullscreen_shell;
|
||||
struct wl_listener present_surface;
|
||||
|
||||
struct wlr_output_layout *output_layout;
|
||||
struct wl_list outputs;
|
||||
struct wl_listener new_output;
|
||||
};
|
||||
|
||||
struct fullscreen_output {
|
||||
struct wl_list link;
|
||||
struct fullscreen_server *server;
|
||||
struct wlr_output *wlr_output;
|
||||
struct wlr_surface *surface;
|
||||
struct wl_listener surface_destroy;
|
||||
|
||||
struct wl_listener frame;
|
||||
};
|
||||
|
||||
struct render_data {
|
||||
struct wlr_output *output;
|
||||
struct wlr_render_pass *render_pass;
|
||||
struct timespec *when;
|
||||
};
|
||||
|
||||
static void render_surface(struct wlr_surface *surface,
|
||||
int sx, int sy, void *data) {
|
||||
struct render_data *rdata = data;
|
||||
struct wlr_output *output = rdata->output;
|
||||
|
||||
struct wlr_texture *texture = wlr_surface_get_texture(surface);
|
||||
if (texture == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
struct wlr_box box = {
|
||||
.x = sx * output->scale,
|
||||
.y = sy * output->scale,
|
||||
.width = surface->current.width * output->scale,
|
||||
.height = surface->current.height * output->scale,
|
||||
};
|
||||
|
||||
enum wl_output_transform transform = wlr_output_transform_invert(surface->current.transform);
|
||||
transform = wlr_output_transform_compose(transform, output->transform);
|
||||
|
||||
wlr_render_pass_add_texture(rdata->render_pass, &(struct wlr_render_texture_options){
|
||||
.texture = texture,
|
||||
.dst_box = box,
|
||||
.transform = transform,
|
||||
});
|
||||
|
||||
wlr_surface_send_frame_done(surface, rdata->when);
|
||||
}
|
||||
|
||||
static void output_handle_frame(struct wl_listener *listener, void *data) {
|
||||
struct fullscreen_output *output =
|
||||
wl_container_of(listener, output, frame);
|
||||
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
int width, height;
|
||||
wlr_output_effective_resolution(output->wlr_output, &width, &height);
|
||||
|
||||
struct wlr_output_state state;
|
||||
wlr_output_state_init(&state);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, &state, NULL,
|
||||
NULL);
|
||||
if (pass == NULL) {
|
||||
return;
|
||||
}
|
||||
|
||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||
.color = { 0.3, 0.3, 0.3, 1.0 },
|
||||
.box = { .width = width, .height = height },
|
||||
});
|
||||
|
||||
if (output->surface != NULL) {
|
||||
struct render_data rdata = {
|
||||
.output = output->wlr_output,
|
||||
.render_pass = pass,
|
||||
.when = &now,
|
||||
};
|
||||
wlr_surface_for_each_surface(output->surface, render_surface, &rdata);
|
||||
}
|
||||
|
||||
wlr_render_pass_submit(pass);
|
||||
wlr_output_commit_state(output->wlr_output, &state);
|
||||
wlr_output_state_finish(&state);
|
||||
}
|
||||
|
||||
static void output_set_surface(struct fullscreen_output *output,
|
||||
struct wlr_surface *surface);
|
||||
|
||||
static void output_handle_surface_destroy(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct fullscreen_output *output =
|
||||
wl_container_of(listener, output, surface_destroy);
|
||||
output_set_surface(output, NULL);
|
||||
}
|
||||
|
||||
static void output_set_surface(struct fullscreen_output *output,
|
||||
struct wlr_surface *surface) {
|
||||
if (output->surface == surface) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (output->surface != NULL) {
|
||||
wl_list_remove(&output->surface_destroy.link);
|
||||
output->surface = NULL;
|
||||
}
|
||||
|
||||
if (surface != NULL) {
|
||||
output->surface_destroy.notify = output_handle_surface_destroy;
|
||||
wl_signal_add(&surface->events.destroy, &output->surface_destroy);
|
||||
output->surface = surface;
|
||||
}
|
||||
|
||||
wlr_log(WLR_DEBUG, "Presenting surface %p on output %s",
|
||||
surface, output->wlr_output->name);
|
||||
}
|
||||
|
||||
static void server_handle_new_output(struct wl_listener *listener, void *data) {
|
||||
struct fullscreen_server *server =
|
||||
wl_container_of(listener, server, new_output);
|
||||
struct wlr_output *wlr_output = data;
|
||||
|
||||
wlr_output_init_render(wlr_output, server->allocator, server->renderer);
|
||||
|
||||
struct fullscreen_output *output = calloc(1, sizeof(*output));
|
||||
output->wlr_output = wlr_output;
|
||||
output->server = server;
|
||||
output->frame.notify = output_handle_frame;
|
||||
wl_signal_add(&wlr_output->events.frame, &output->frame);
|
||||
wl_list_insert(&server->outputs, &output->link);
|
||||
|
||||
wlr_output_layout_add_auto(server->output_layout, wlr_output);
|
||||
wlr_output_create_global(wlr_output, server->wl_display);
|
||||
|
||||
struct wlr_output_state state;
|
||||
wlr_output_state_init(&state);
|
||||
wlr_output_state_set_enabled(&state, true);
|
||||
struct wlr_output_mode *mode = wlr_output_preferred_mode(wlr_output);
|
||||
if (mode != NULL) {
|
||||
wlr_output_state_set_mode(&state, mode);
|
||||
}
|
||||
wlr_output_commit_state(wlr_output, &state);
|
||||
wlr_output_state_finish(&state);
|
||||
}
|
||||
|
||||
static void server_handle_present_surface(struct wl_listener *listener,
|
||||
void *data) {
|
||||
struct fullscreen_server *server =
|
||||
wl_container_of(listener, server, present_surface);
|
||||
struct wlr_fullscreen_shell_v1_present_surface_event *event = data;
|
||||
|
||||
struct fullscreen_output *output;
|
||||
wl_list_for_each(output, &server->outputs, link) {
|
||||
if (event->output == NULL || event->output == output->wlr_output) {
|
||||
output_set_surface(output, event->surface);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
wlr_log_init(WLR_DEBUG, NULL);
|
||||
|
||||
char *startup_cmd = NULL;
|
||||
|
||||
int c;
|
||||
while ((c = getopt(argc, argv, "s:")) != -1) {
|
||||
switch (c) {
|
||||
case 's':
|
||||
startup_cmd = optarg;
|
||||
break;
|
||||
default:
|
||||
printf("usage: %s [-s startup-command]\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
if (optind < argc) {
|
||||
printf("usage: %s [-s startup-command]\n", argv[0]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
struct fullscreen_server server = {0};
|
||||
server.wl_display = wl_display_create();
|
||||
server.backend = wlr_backend_autocreate(wl_display_get_event_loop(server.wl_display), NULL);
|
||||
server.renderer = wlr_renderer_autocreate(server.backend);
|
||||
wlr_renderer_init_wl_display(server.renderer, server.wl_display);
|
||||
server.allocator = wlr_allocator_autocreate(server.backend,
|
||||
server.renderer);
|
||||
|
||||
wlr_compositor_create(server.wl_display, 5, server.renderer);
|
||||
|
||||
server.output_layout = wlr_output_layout_create(server.wl_display);
|
||||
|
||||
wl_list_init(&server.outputs);
|
||||
server.new_output.notify = server_handle_new_output;
|
||||
wl_signal_add(&server.backend->events.new_output, &server.new_output);
|
||||
|
||||
server.fullscreen_shell = wlr_fullscreen_shell_v1_create(server.wl_display);
|
||||
server.present_surface.notify = server_handle_present_surface;
|
||||
wl_signal_add(&server.fullscreen_shell->events.present_surface,
|
||||
&server.present_surface);
|
||||
|
||||
const char *socket = wl_display_add_socket_auto(server.wl_display);
|
||||
if (!socket) {
|
||||
wl_display_destroy(server.wl_display);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (!wlr_backend_start(server.backend)) {
|
||||
wl_display_destroy(server.wl_display);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
setenv("WAYLAND_DISPLAY", socket, true);
|
||||
if (startup_cmd != NULL) {
|
||||
if (fork() == 0) {
|
||||
execl("/bin/sh", "/bin/sh", "-c", startup_cmd, (void *)NULL);
|
||||
}
|
||||
}
|
||||
|
||||
wlr_log(WLR_INFO, "Running Wayland compositor on WAYLAND_DISPLAY=%s",
|
||||
socket);
|
||||
wl_display_run(server.wl_display);
|
||||
|
||||
wl_display_destroy_clients(server.wl_display);
|
||||
wl_display_destroy(server.wl_display);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -25,6 +25,10 @@ compositors = {
|
|||
'output-layout': {
|
||||
'src': ['output-layout.c', 'cat.c'],
|
||||
},
|
||||
'fullscreen-shell': {
|
||||
'src': 'fullscreen-shell.c',
|
||||
'proto': ['fullscreen-shell-unstable-v1'],
|
||||
},
|
||||
'scene-graph': {
|
||||
'src': 'scene-graph.c',
|
||||
'proto': ['xdg-shell'],
|
||||
|
|
|
|||
|
|
@ -87,14 +87,16 @@ static void output_handle_frame(struct wl_listener *listener, void *data) {
|
|||
layers_arr.size / sizeof(struct wlr_output_layer_state));
|
||||
|
||||
if (!wlr_output_test_state(output->wlr_output, &output_state)) {
|
||||
wlr_log(WLR_ERROR, "wlr_output_test_state() failed");
|
||||
wlr_log(WLR_ERROR, "wlr_output_test() failed");
|
||||
return;
|
||||
}
|
||||
|
||||
int width, height;
|
||||
wlr_output_effective_resolution(output->wlr_output, &width, &height);
|
||||
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, &output_state, NULL);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(output->wlr_output, &output_state,
|
||||
NULL, NULL);
|
||||
|
||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||
.box = { .width = width, .height = height },
|
||||
.color = { 0.3, 0.3, 0.3, 1 },
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
|||
|
||||
struct wlr_output_state output_state;
|
||||
wlr_output_state_init(&output_state);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL);
|
||||
|
||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
||||
|
|
|
|||
|
|
@ -101,7 +101,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
|||
|
||||
struct wlr_output_state output_state;
|
||||
wlr_output_state_init(&output_state);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL);
|
||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
||||
.color = {
|
||||
|
|
|
|||
|
|
@ -59,7 +59,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
|||
|
||||
struct wlr_output_state output_state;
|
||||
wlr_output_state_init(&output_state);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL);
|
||||
|
||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
|||
|
||||
struct wlr_output_state state;
|
||||
wlr_output_state_init(&state);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &state, NULL);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &state, NULL, NULL);
|
||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
||||
.color = {
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
|||
|
||||
struct wlr_output_state output_state;
|
||||
wlr_output_state_init(&output_state);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL);
|
||||
|
||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||
.box = { .width = wlr_output->width, .height = wlr_output->height },
|
||||
|
|
|
|||
|
|
@ -76,7 +76,7 @@ static void output_frame_notify(struct wl_listener *listener, void *data) {
|
|||
|
||||
struct wlr_output_state output_state;
|
||||
wlr_output_state_init(&output_state);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL);
|
||||
struct wlr_render_pass *pass = wlr_output_begin_render_pass(wlr_output, &output_state, NULL, NULL);
|
||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
||||
.box = { .width = width, .height = height },
|
||||
.color = { 0.25, 0.25, 0.25, 1 },
|
||||
|
|
|
|||
13
include/backend/backend.h
Normal file
13
include/backend/backend.h
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef BACKEND_WLR_BACKEND_H
|
||||
#define BACKEND_WLR_BACKEND_H
|
||||
|
||||
#include <wlr/backend.h>
|
||||
|
||||
/**
|
||||
* Get the supported buffer capabilities.
|
||||
*
|
||||
* This functions returns a bitfield of supported wlr_buffer_cap.
|
||||
*/
|
||||
uint32_t backend_get_buffer_caps(struct wlr_backend *backend);
|
||||
|
||||
#endif
|
||||
|
|
@ -15,11 +15,6 @@
|
|||
#include "backend/drm/properties.h"
|
||||
#include "backend/drm/renderer.h"
|
||||
|
||||
struct wlr_drm_viewport {
|
||||
struct wlr_fbox src_box;
|
||||
struct wlr_box dst_box;
|
||||
};
|
||||
|
||||
struct wlr_drm_plane {
|
||||
uint32_t type;
|
||||
uint32_t id;
|
||||
|
|
@ -31,8 +26,6 @@ struct wlr_drm_plane {
|
|||
struct wlr_drm_fb *queued_fb;
|
||||
/* Buffer currently displayed on screen */
|
||||
struct wlr_drm_fb *current_fb;
|
||||
/* Viewport belonging to the last committed fb */
|
||||
struct wlr_drm_viewport viewport;
|
||||
|
||||
struct wlr_drm_format_set formats;
|
||||
|
||||
|
|
@ -146,20 +139,13 @@ struct wlr_drm_connector_state {
|
|||
bool active;
|
||||
drmModeModeInfo mode;
|
||||
struct wlr_drm_fb *primary_fb;
|
||||
struct wlr_drm_viewport primary_viewport;
|
||||
struct wlr_drm_fb *cursor_fb;
|
||||
|
||||
struct wlr_drm_syncobj_timeline *wait_timeline;
|
||||
uint64_t wait_point;
|
||||
|
||||
// used by atomic
|
||||
uint32_t mode_id;
|
||||
uint32_t gamma_lut;
|
||||
uint32_t fb_damage_clips;
|
||||
int primary_in_fence_fd, out_fence_fd;
|
||||
bool vrr_enabled;
|
||||
uint32_t colorspace;
|
||||
uint32_t hdr_output_metadata;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -178,8 +164,6 @@ struct wlr_drm_page_flip {
|
|||
struct wl_list link; // wlr_drm_connector.page_flips
|
||||
struct wlr_drm_page_flip_connector *connectors;
|
||||
size_t connectors_len;
|
||||
// True if DRM_MODE_PAGE_FLIP_ASYNC was set
|
||||
bool async;
|
||||
};
|
||||
|
||||
struct wlr_drm_page_flip_connector {
|
||||
|
|
@ -214,10 +198,6 @@ struct wlr_drm_connector {
|
|||
// Last committed page-flip
|
||||
struct wlr_drm_page_flip *pending_page_flip;
|
||||
|
||||
// Atomic modesetting only
|
||||
uint32_t colorspace;
|
||||
uint32_t hdr_output_metadata;
|
||||
|
||||
int32_t refresh;
|
||||
};
|
||||
|
||||
|
|
@ -231,6 +211,7 @@ void scan_drm_connectors(struct wlr_drm_backend *state,
|
|||
void scan_drm_leases(struct wlr_drm_backend *drm);
|
||||
bool commit_drm_device(struct wlr_drm_backend *drm,
|
||||
const struct wlr_backend_output_state *states, size_t states_len, bool test_only);
|
||||
void restore_drm_device(struct wlr_drm_backend *drm);
|
||||
int handle_drm_event(int fd, uint32_t mask, void *data);
|
||||
void destroy_drm_connector(struct wlr_drm_connector *conn);
|
||||
bool drm_connector_is_cursor_visible(struct wlr_drm_connector *conn);
|
||||
|
|
|
|||
|
|
@ -2,10 +2,6 @@
|
|||
#define BACKEND_DRM_FB_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <wlr/util/addon.h>
|
||||
|
||||
struct wlr_drm_format_set;
|
||||
|
||||
struct wlr_drm_fb {
|
||||
struct wlr_buffer *wlr_buf;
|
||||
|
|
|
|||
|
|
@ -22,6 +22,8 @@ struct wlr_drm_interface {
|
|||
bool (*commit)(struct wlr_drm_backend *drm,
|
||||
const struct wlr_drm_device_state *state,
|
||||
struct wlr_drm_page_flip *page_flip, uint32_t flags, bool test_only);
|
||||
// Turn off everything
|
||||
bool (*reset)(struct wlr_drm_backend *drm);
|
||||
};
|
||||
|
||||
extern const struct wlr_drm_interface atomic_iface;
|
||||
|
|
|
|||
|
|
@ -26,8 +26,6 @@ struct wlr_drm_connector_props {
|
|||
// atomic-modesetting only
|
||||
|
||||
uint32_t crtc_id;
|
||||
uint32_t colorspace;
|
||||
uint32_t hdr_output_metadata;
|
||||
};
|
||||
|
||||
struct wlr_drm_crtc_props {
|
||||
|
|
@ -40,7 +38,6 @@ struct wlr_drm_crtc_props {
|
|||
|
||||
uint32_t active;
|
||||
uint32_t mode_id;
|
||||
uint32_t out_fence_ptr;
|
||||
};
|
||||
|
||||
struct wlr_drm_plane_props {
|
||||
|
|
@ -64,7 +61,6 @@ struct wlr_drm_plane_props {
|
|||
uint32_t fb_damage_clips;
|
||||
uint32_t hotspot_x;
|
||||
uint32_t hotspot_y;
|
||||
uint32_t in_fence_fd;
|
||||
};
|
||||
|
||||
bool get_drm_connector_props(int fd, uint32_t id,
|
||||
|
|
|
|||
|
|
@ -20,9 +20,6 @@ struct wlr_drm_renderer {
|
|||
struct wlr_drm_surface {
|
||||
struct wlr_drm_renderer *renderer;
|
||||
struct wlr_swapchain *swapchain;
|
||||
|
||||
struct wlr_drm_syncobj_timeline *timeline;
|
||||
uint64_t point;
|
||||
};
|
||||
|
||||
bool init_drm_renderer(struct wlr_drm_backend *drm,
|
||||
|
|
@ -35,8 +32,7 @@ bool init_drm_surface(struct wlr_drm_surface *surf,
|
|||
void finish_drm_surface(struct wlr_drm_surface *surf);
|
||||
|
||||
struct wlr_buffer *drm_surface_blit(struct wlr_drm_surface *surf,
|
||||
struct wlr_buffer *buffer,
|
||||
struct wlr_drm_syncobj_timeline *wait_timeline, uint64_t wait_point);
|
||||
struct wlr_buffer *buffer);
|
||||
|
||||
bool drm_plane_pick_render_format(struct wlr_drm_plane *plane,
|
||||
struct wlr_drm_format *fmt, struct wlr_drm_renderer *renderer);
|
||||
|
|
|
|||
|
|
@ -18,24 +18,26 @@ const char *drm_connector_status_str(drmModeConnection status);
|
|||
void generate_cvt_mode(drmModeModeInfo *mode, int hdisplay, int vdisplay,
|
||||
float vrefresh);
|
||||
|
||||
// Part of match_connectors_with_crtcs
|
||||
#define UNMATCHED ((uint32_t)-1)
|
||||
// Part of match_obj
|
||||
enum {
|
||||
UNMATCHED = (uint32_t)-1,
|
||||
SKIP = (uint32_t)-2,
|
||||
};
|
||||
|
||||
/**
|
||||
* Tries to match DRM connectors with DRM CRTCs.
|
||||
/*
|
||||
* Tries to match some DRM objects with some other DRM resource.
|
||||
* e.g. Match CRTCs with Encoders, CRTCs with Planes.
|
||||
*
|
||||
* conns contains an array of bitmasks describing compatible CRTCs. For
|
||||
* instance bit 0 set in an connector element means that it's compatible with
|
||||
* CRTC 0.
|
||||
* objs contains a bit array which resources it can be matched with.
|
||||
* e.g. Bit 0 set means can be matched with res[0]
|
||||
*
|
||||
* prev_crtcs contains connector indices each CRTC was previously matched with,
|
||||
* or UNMATCHED.
|
||||
* res contains an index of which objs it is matched with or UNMATCHED.
|
||||
*
|
||||
* new_crtcs is populated with the new connector indices.
|
||||
* This solution is left in out.
|
||||
* Returns the total number of matched solutions.
|
||||
*/
|
||||
void match_connectors_with_crtcs(size_t num_conns,
|
||||
const uint32_t conns[static restrict num_conns],
|
||||
size_t num_crtcs, const uint32_t prev_crtcs[static restrict num_crtcs],
|
||||
uint32_t new_crtcs[static restrict num_crtcs]);
|
||||
size_t match_obj(size_t num_objs, const uint32_t objs[static restrict num_objs],
|
||||
size_t num_res, const uint32_t res[static restrict num_res],
|
||||
uint32_t out[static restrict num_res]);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
#include <wlr/types/wlr_tablet_tool.h>
|
||||
#include <wlr/types/wlr_touch.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
struct wlr_libinput_backend {
|
||||
struct wlr_backend backend;
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@
|
|||
#include <wlr/types/wlr_tablet_tool.h>
|
||||
#include <wlr/types/wlr_touch.h>
|
||||
#include <wlr/render/drm_format_set.h>
|
||||
#include <wlr/render/drm_syncobj.h>
|
||||
|
||||
struct wlr_wl_backend {
|
||||
struct wlr_backend backend;
|
||||
|
|
@ -22,7 +21,6 @@ struct wlr_wl_backend {
|
|||
/* local state */
|
||||
bool started;
|
||||
struct wl_event_loop *event_loop;
|
||||
struct wl_event_queue *busy_loop_queue;
|
||||
struct wl_list outputs;
|
||||
int drm_fd;
|
||||
struct wl_list buffers; // wlr_wl_buffer.link
|
||||
|
|
@ -42,8 +40,6 @@ struct wlr_wl_backend {
|
|||
struct wp_presentation *presentation;
|
||||
struct wl_shm *shm;
|
||||
struct zwp_linux_dmabuf_v1 *zwp_linux_dmabuf_v1;
|
||||
struct wp_linux_drm_syncobj_manager_v1 *drm_syncobj_manager_v1;
|
||||
struct wl_list drm_syncobj_timelines; // wlr_wl_drm_syncobj_timeline.link
|
||||
struct zwp_relative_pointer_manager_v1 *zwp_relative_pointer_manager_v1;
|
||||
struct wl_list seats; // wlr_wl_seat.link
|
||||
struct zwp_tablet_manager_v2 *tablet_manager;
|
||||
|
|
@ -62,19 +58,6 @@ struct wlr_wl_buffer {
|
|||
bool released;
|
||||
struct wl_list link; // wlr_wl_backend.buffers
|
||||
struct wl_listener buffer_destroy;
|
||||
|
||||
bool has_drm_syncobj_waiter;
|
||||
struct wlr_drm_syncobj_timeline_waiter drm_syncobj_waiter;
|
||||
|
||||
struct wlr_drm_syncobj_timeline *fallback_signal_timeline;
|
||||
uint64_t fallback_signal_point;
|
||||
};
|
||||
|
||||
struct wlr_wl_drm_syncobj_timeline {
|
||||
struct wlr_drm_syncobj_timeline *base;
|
||||
struct wlr_addon addon;
|
||||
struct wl_list link; // wlr_wl_backend.drm_syncobj_timelines
|
||||
struct wp_linux_drm_syncobj_timeline_v1 *wl;
|
||||
};
|
||||
|
||||
struct wlr_wl_presentation_feedback {
|
||||
|
|
@ -105,7 +88,6 @@ struct wlr_wl_output {
|
|||
struct xdg_surface *xdg_surface;
|
||||
struct xdg_toplevel *xdg_toplevel;
|
||||
struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1;
|
||||
struct wp_linux_drm_syncobj_surface_v1 *drm_syncobj_surface_v1;
|
||||
struct wl_list presentation_feedbacks;
|
||||
|
||||
char *title;
|
||||
|
|
@ -208,7 +190,6 @@ bool create_wl_seat(struct wl_seat *wl_seat, struct wlr_wl_backend *wl,
|
|||
uint32_t global_name);
|
||||
void destroy_wl_seat(struct wlr_wl_seat *seat);
|
||||
void destroy_wl_buffer(struct wlr_wl_buffer *buffer);
|
||||
void destroy_wl_drm_syncobj_timeline(struct wlr_wl_drm_syncobj_timeline *timeline);
|
||||
|
||||
extern const struct wlr_pointer_impl wl_pointer_impl;
|
||||
extern const struct wlr_tablet_pad_impl wl_tablet_pad_impl;
|
||||
|
|
|
|||
9
include/render/allocator/allocator.h
Normal file
9
include/render/allocator/allocator.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef RENDER_ALLOCATOR_ALLOCATOR_H
|
||||
#define RENDER_ALLOCATOR_ALLOCATOR_H
|
||||
|
||||
#include <wlr/render/allocator.h>
|
||||
|
||||
struct wlr_allocator *allocator_autocreate_with_drm_fd(
|
||||
uint32_t backend_caps, struct wlr_renderer *renderer, int drm_fd);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
#ifndef RENDER_ALLOCATOR_DRM_DUMB_H
|
||||
#define RENDER_ALLOCATOR_DRM_DUMB_H
|
||||
|
||||
#include <wlr/render/allocator.h>
|
||||
#include <wlr/render/dmabuf.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include "render/allocator/allocator.h"
|
||||
|
||||
struct wlr_drm_dumb_buffer {
|
||||
struct wlr_buffer base;
|
||||
|
|
|
|||
|
|
@ -2,9 +2,9 @@
|
|||
#define RENDER_ALLOCATOR_GBM_H
|
||||
|
||||
#include <gbm.h>
|
||||
#include <wlr/render/allocator.h>
|
||||
#include <wlr/render/dmabuf.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include "render/allocator/allocator.h"
|
||||
|
||||
struct wlr_gbm_buffer {
|
||||
struct wlr_buffer base;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
#ifndef RENDER_ALLOCATOR_SHM_H
|
||||
#define RENDER_ALLOCATOR_SHM_H
|
||||
|
||||
#include <wlr/render/allocator.h>
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include "render/allocator/allocator.h"
|
||||
|
||||
struct wlr_shm_buffer {
|
||||
struct wlr_buffer base;
|
||||
|
|
|
|||
|
|
@ -1,23 +0,0 @@
|
|||
#ifndef RENDER_ALLOCATOR_UDMABUF_H
|
||||
#define RENDER_ALLOCATOR_UDMABUF_H
|
||||
|
||||
#include <wlr/types/wlr_buffer.h>
|
||||
#include <wlr/render/allocator.h>
|
||||
|
||||
struct wlr_udmabuf_buffer {
|
||||
struct wlr_buffer base;
|
||||
|
||||
size_t size;
|
||||
struct wlr_shm_attributes shm;
|
||||
struct wlr_dmabuf_attributes dmabuf;
|
||||
};
|
||||
|
||||
struct wlr_udmabuf_allocator {
|
||||
struct wlr_allocator base;
|
||||
|
||||
int fd;
|
||||
};
|
||||
|
||||
struct wlr_allocator *wlr_udmabuf_allocator_create(void);
|
||||
|
||||
#endif
|
||||
|
|
@ -2,14 +2,30 @@
|
|||
#define RENDER_COLOR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <wlr/render/color.h>
|
||||
#include <wlr/util/addon.h>
|
||||
|
||||
/**
|
||||
* The formula is approximated via a 3D look-up table. A 3D LUT is a
|
||||
* three-dimensional array where each element is an RGB triplet. The flat lut_3d
|
||||
* array has a length of dim_len³.
|
||||
*
|
||||
* Color channel values in the range [0.0, 1.0] are mapped linearly to
|
||||
* 3D LUT indices such that 0.0 maps exactly to the first element and 1.0 maps
|
||||
* exactly to the last element in each dimension.
|
||||
*
|
||||
* The offset of the RGB triplet given red, green and blue indices r_index,
|
||||
* g_index and b_index is:
|
||||
*
|
||||
* offset = 3 * (r_index + dim_len * g_index + dim_len * dim_len * b_index)
|
||||
*/
|
||||
struct wlr_color_transform_lut3d {
|
||||
float *lut_3d;
|
||||
size_t dim_len;
|
||||
};
|
||||
|
||||
enum wlr_color_transform_type {
|
||||
COLOR_TRANSFORM_INVERSE_EOTF,
|
||||
COLOR_TRANSFORM_LCMS2,
|
||||
COLOR_TRANSFORM_LUT_3X1D,
|
||||
COLOR_TRANSFORM_PIPELINE,
|
||||
COLOR_TRANSFORM_SRGB,
|
||||
COLOR_TRANSFORM_LUT_3D,
|
||||
};
|
||||
|
||||
struct wlr_color_transform {
|
||||
|
|
@ -17,84 +33,7 @@ struct wlr_color_transform {
|
|||
struct wlr_addon_set addons; // per-renderer helper state
|
||||
|
||||
enum wlr_color_transform_type type;
|
||||
struct wlr_color_transform_lut3d lut3d;
|
||||
};
|
||||
|
||||
struct wlr_color_transform_inverse_eotf {
|
||||
struct wlr_color_transform base;
|
||||
|
||||
enum wlr_color_transfer_function tf;
|
||||
};
|
||||
|
||||
/**
|
||||
* The formula is approximated via three 1D look-up tables. The flat lut_3x1d
|
||||
* array has a length of 3 * dim.
|
||||
*
|
||||
* The offset of a color value for a given channel and color index is:
|
||||
*
|
||||
* offset = channel_index * dim + color_index
|
||||
*/
|
||||
struct wlr_color_transform_lut_3x1d {
|
||||
struct wlr_color_transform base;
|
||||
|
||||
uint16_t *lut_3x1d;
|
||||
size_t dim;
|
||||
};
|
||||
|
||||
struct wlr_color_transform_pipeline {
|
||||
struct wlr_color_transform base;
|
||||
|
||||
struct wlr_color_transform **transforms;
|
||||
size_t len;
|
||||
};
|
||||
|
||||
void wlr_color_transform_init(struct wlr_color_transform *tr,
|
||||
enum wlr_color_transform_type type);
|
||||
|
||||
/**
|
||||
* Get a struct wlr_color_transform_lcms2 from a generic struct wlr_color_transform.
|
||||
* Asserts that the base type is COLOR_TRANSFORM_LCMS2.
|
||||
*/
|
||||
struct wlr_color_transform_lcms2 *color_transform_lcms2_from_base(
|
||||
struct wlr_color_transform *tr);
|
||||
|
||||
void color_transform_lcms2_finish(struct wlr_color_transform_lcms2 *tr);
|
||||
|
||||
/**
|
||||
* Evaluate a LCMS2 color transform for a given RGB triplet.
|
||||
*/
|
||||
void color_transform_lcms2_eval(struct wlr_color_transform_lcms2 *tr,
|
||||
float out[static 3], const float in[static 3]);
|
||||
|
||||
/**
|
||||
* Gets a wlr_color_transform_inverse_eotf from a generic wlr_color_transform.
|
||||
* Asserts that the base type is COLOR_TRANSFORM_INVERSE_EOTF
|
||||
*/
|
||||
struct wlr_color_transform_inverse_eotf *wlr_color_transform_inverse_eotf_from_base(
|
||||
struct wlr_color_transform *tr);
|
||||
|
||||
/**
|
||||
* Get a struct wlr_color_transform_lut_3x1d from a generic
|
||||
* struct wlr_color_transform. Asserts that the base type is
|
||||
* COLOR_TRANSFORM_LUT_3X1D.
|
||||
*/
|
||||
struct wlr_color_transform_lut_3x1d *color_transform_lut_3x1d_from_base(
|
||||
struct wlr_color_transform *tr);
|
||||
|
||||
/**
|
||||
* Obtain primaries values from a well-known primaries name.
|
||||
*/
|
||||
void wlr_color_primaries_from_named(struct wlr_color_primaries *out,
|
||||
enum wlr_color_named_primaries named);
|
||||
|
||||
/**
|
||||
* Compute the matrix to convert RGB color values to CIE 1931 XYZ.
|
||||
*/
|
||||
void wlr_color_primaries_to_xyz(const struct wlr_color_primaries *primaries, float matrix[static 9]);
|
||||
|
||||
/**
|
||||
* Get default luminances for a transfer function.
|
||||
*/
|
||||
void wlr_color_transfer_function_get_default_luminance(enum wlr_color_transfer_function tf,
|
||||
struct wlr_color_luminances *lum);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -38,10 +38,6 @@ struct wlr_egl {
|
|||
PFNEGLQUERYDISPLAYATTRIBEXTPROC eglQueryDisplayAttribEXT;
|
||||
PFNEGLQUERYDEVICESTRINGEXTPROC eglQueryDeviceStringEXT;
|
||||
PFNEGLQUERYDEVICESEXTPROC eglQueryDevicesEXT;
|
||||
PFNEGLCREATESYNCKHRPROC eglCreateSyncKHR;
|
||||
PFNEGLDESTROYSYNCKHRPROC eglDestroySyncKHR;
|
||||
PFNEGLDUPNATIVEFENCEFDANDROIDPROC eglDupNativeFenceFDANDROID;
|
||||
PFNEGLWAITSYNCKHRPROC eglWaitSyncKHR;
|
||||
} procs;
|
||||
|
||||
bool has_modifiers;
|
||||
|
|
@ -109,12 +105,4 @@ bool wlr_egl_make_current(struct wlr_egl *egl, struct wlr_egl_context *save_cont
|
|||
|
||||
bool wlr_egl_unset_current(struct wlr_egl *egl);
|
||||
|
||||
EGLSyncKHR wlr_egl_create_sync(struct wlr_egl *egl, int fence_fd);
|
||||
|
||||
void wlr_egl_destroy_sync(struct wlr_egl *egl, EGLSyncKHR sync);
|
||||
|
||||
int wlr_egl_dup_fence_fd(struct wlr_egl *egl, EGLSyncKHR sync);
|
||||
|
||||
bool wlr_egl_wait_sync(struct wlr_egl *egl, EGLSyncKHR sync);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@
|
|||
#include <GLES2/gl2ext.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <wlr/render/egl.h>
|
||||
#include <wlr/render/gles2.h>
|
||||
|
|
@ -137,8 +138,6 @@ struct wlr_gles2_render_pass {
|
|||
float projection_matrix[9];
|
||||
struct wlr_egl_context prev_ctx;
|
||||
struct wlr_gles2_render_timer *timer;
|
||||
struct wlr_drm_syncobj_timeline *signal_timeline;
|
||||
uint64_t signal_point;
|
||||
};
|
||||
|
||||
bool is_gles2_pixel_format_supported(const struct wlr_gles2_renderer *renderer,
|
||||
|
|
@ -170,7 +169,6 @@ void push_gles2_debug_(struct wlr_gles2_renderer *renderer,
|
|||
void pop_gles2_debug(struct wlr_gles2_renderer *renderer);
|
||||
|
||||
struct wlr_gles2_render_pass *begin_gles2_buffer_pass(struct wlr_gles2_buffer *buffer,
|
||||
struct wlr_egl_context *prev_ctx, struct wlr_gles2_render_timer *timer,
|
||||
struct wlr_drm_syncobj_timeline *signal_timeline, uint64_t signal_point);
|
||||
struct wlr_egl_context *prev_ctx, struct wlr_gles2_render_timer *timer);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
#include <vulkan/vulkan.h>
|
||||
#include <wlr/render/wlr_renderer.h>
|
||||
#include <wlr/render/wlr_texture.h>
|
||||
#include <wlr/render/color.h>
|
||||
#include <wlr/render/drm_format_set.h>
|
||||
#include <wlr/render/interface.h>
|
||||
#include <wlr/util/addon.h>
|
||||
|
|
@ -41,7 +40,6 @@ struct wlr_vk_device {
|
|||
|
||||
int drm_fd;
|
||||
|
||||
bool sync_file_import_export;
|
||||
bool implicit_sync_interop;
|
||||
bool sampler_ycbcr_conversion;
|
||||
|
||||
|
|
@ -152,9 +150,6 @@ struct wlr_vk_pipeline_layout {
|
|||
enum wlr_vk_texture_transform {
|
||||
WLR_VK_TEXTURE_TRANSFORM_IDENTITY = 0,
|
||||
WLR_VK_TEXTURE_TRANSFORM_SRGB = 1,
|
||||
WLR_VK_TEXTURE_TRANSFORM_ST2084_PQ = 2,
|
||||
WLR_VK_TEXTURE_TRANSFORM_GAMMA22 = 3,
|
||||
WLR_VK_TEXTURE_TRANSFORM_BT1886 = 4,
|
||||
};
|
||||
|
||||
enum wlr_vk_shader_source {
|
||||
|
|
@ -165,12 +160,8 @@ enum wlr_vk_shader_source {
|
|||
// Constants used to pick the color transform for the blend-to-output
|
||||
// fragment shader. Must match those in shaders/output.frag
|
||||
enum wlr_vk_output_transform {
|
||||
WLR_VK_OUTPUT_TRANSFORM_IDENTITY = 0,
|
||||
WLR_VK_OUTPUT_TRANSFORM_INVERSE_SRGB = 1,
|
||||
WLR_VK_OUTPUT_TRANSFORM_INVERSE_ST2084_PQ = 2,
|
||||
WLR_VK_OUTPUT_TRANSFORM_LUT3D = 3,
|
||||
WLR_VK_OUTPUT_TRANSFORM_INVERSE_GAMMA22 = 4,
|
||||
WLR_VK_OUTPUT_TRANSFORM_INVERSE_BT1886 = 5,
|
||||
WLR_VK_OUTPUT_TRANSFORM_INVERSE_SRGB = 0,
|
||||
WLR_VK_OUTPUT_TRANSFORM_LUT3D = 1,
|
||||
};
|
||||
|
||||
struct wlr_vk_pipeline_key {
|
||||
|
|
@ -199,24 +190,13 @@ struct wlr_vk_render_format_setup {
|
|||
bool use_blending_buffer;
|
||||
VkRenderPass render_pass;
|
||||
|
||||
VkPipeline output_pipe_identity;
|
||||
VkPipeline output_pipe_srgb;
|
||||
VkPipeline output_pipe_pq;
|
||||
VkPipeline output_pipe_lut3d;
|
||||
VkPipeline output_pipe_gamma22;
|
||||
VkPipeline output_pipe_bt1886;
|
||||
|
||||
struct wlr_vk_renderer *renderer;
|
||||
struct wl_list pipelines; // struct wlr_vk_pipeline.link
|
||||
};
|
||||
|
||||
// Final output framebuffer and image view
|
||||
struct wlr_vk_render_buffer_out {
|
||||
VkImageView image_view;
|
||||
VkFramebuffer framebuffer;
|
||||
bool transitioned;
|
||||
};
|
||||
|
||||
// Renderer-internal represenation of an wlr_buffer imported for rendering.
|
||||
struct wlr_vk_render_buffer {
|
||||
struct wlr_buffer *wlr_buffer;
|
||||
|
|
@ -228,40 +208,36 @@ struct wlr_vk_render_buffer {
|
|||
uint32_t mem_count;
|
||||
VkImage image;
|
||||
|
||||
// Framebuffer and image view for rendering directly onto the buffer image,
|
||||
// without any color transform.
|
||||
struct {
|
||||
struct wlr_vk_render_buffer_out out;
|
||||
struct wlr_vk_render_format_setup *render_setup;
|
||||
} linear;
|
||||
|
||||
// Framebuffer and image view for rendering directly onto the buffer image.
|
||||
// This requires that the image support an _SRGB VkFormat, and does
|
||||
// not work with color transforms.
|
||||
struct {
|
||||
struct wlr_vk_render_buffer_out out;
|
||||
struct wlr_vk_render_format_setup *render_setup;
|
||||
VkImageView image_view;
|
||||
VkFramebuffer framebuffer;
|
||||
bool transitioned;
|
||||
} srgb;
|
||||
|
||||
// Framebuffer, image view, and blending image to render indirectly
|
||||
// onto the buffer image. This works for general image types and permits
|
||||
// color transforms.
|
||||
struct {
|
||||
struct wlr_vk_render_buffer_out out;
|
||||
struct wlr_vk_render_format_setup *render_setup;
|
||||
|
||||
VkImageView image_view;
|
||||
VkFramebuffer framebuffer;
|
||||
bool transitioned;
|
||||
|
||||
VkImage blend_image;
|
||||
VkImageView blend_image_view;
|
||||
VkDeviceMemory blend_memory;
|
||||
VkDescriptorSet blend_descriptor_set;
|
||||
struct wlr_vk_descriptor_pool *blend_attachment_pool;
|
||||
bool blend_transitioned;
|
||||
} two_pass;
|
||||
} plain;
|
||||
};
|
||||
|
||||
bool vulkan_setup_one_pass_framebuffer(struct wlr_vk_render_buffer *buffer,
|
||||
const struct wlr_dmabuf_attributes *dmabuf, bool srgb);
|
||||
bool vulkan_setup_two_pass_framebuffer(struct wlr_vk_render_buffer *buffer,
|
||||
bool vulkan_setup_plain_framebuffer(struct wlr_vk_render_buffer *buffer,
|
||||
const struct wlr_dmabuf_attributes *dmabuf);
|
||||
|
||||
struct wlr_vk_command_buffer {
|
||||
|
|
@ -277,8 +253,6 @@ struct wlr_vk_command_buffer {
|
|||
|
||||
// For DMA-BUF implicit sync interop, may be NULL
|
||||
VkSemaphore binary_semaphore;
|
||||
|
||||
struct wl_array wait_semaphores; // VkSemaphore
|
||||
};
|
||||
|
||||
#define VULKAN_COMMAND_BUFFERS_CAP 64
|
||||
|
|
@ -357,15 +331,7 @@ struct wlr_vk_vert_pcr_data {
|
|||
float uv_size[2];
|
||||
};
|
||||
|
||||
struct wlr_vk_frag_texture_pcr_data {
|
||||
float matrix[4][4]; // only a 3x3 subset is used
|
||||
float alpha;
|
||||
float luminance_multiplier;
|
||||
};
|
||||
|
||||
struct wlr_vk_frag_output_pcr_data {
|
||||
float matrix[4][4]; // only a 3x3 subset is used
|
||||
float luminance_multiplier;
|
||||
float lut_3d_offset;
|
||||
float lut_3d_scale;
|
||||
};
|
||||
|
|
@ -373,7 +339,6 @@ struct wlr_vk_frag_output_pcr_data {
|
|||
struct wlr_vk_texture_view {
|
||||
struct wl_list link; // struct wlr_vk_texture.views
|
||||
const struct wlr_vk_pipeline_layout *layout;
|
||||
bool srgb;
|
||||
|
||||
VkDescriptorSet ds;
|
||||
VkImageView image_view;
|
||||
|
|
@ -388,7 +353,7 @@ struct wlr_vk_pipeline_layout *get_or_create_pipeline_layout(
|
|||
const struct wlr_vk_pipeline_layout_key *key);
|
||||
struct wlr_vk_texture_view *vulkan_texture_get_or_create_view(
|
||||
struct wlr_vk_texture *texture,
|
||||
const struct wlr_vk_pipeline_layout *layout, bool srgb);
|
||||
const struct wlr_vk_pipeline_layout *layout);
|
||||
|
||||
// Creates a vulkan renderer for the given device.
|
||||
struct wlr_renderer *vulkan_renderer_create_for_device(struct wlr_vk_device *dev);
|
||||
|
|
@ -402,34 +367,17 @@ VkCommandBuffer vulkan_record_stage_cb(struct wlr_vk_renderer *renderer);
|
|||
// finished execution.
|
||||
bool vulkan_submit_stage_wait(struct wlr_vk_renderer *renderer);
|
||||
|
||||
struct wlr_vk_render_pass_texture {
|
||||
struct wlr_vk_texture *texture;
|
||||
|
||||
struct wlr_drm_syncobj_timeline *wait_timeline;
|
||||
uint64_t wait_point;
|
||||
};
|
||||
|
||||
struct wlr_vk_render_pass {
|
||||
struct wlr_render_pass base;
|
||||
struct wlr_vk_renderer *renderer;
|
||||
struct wlr_vk_render_buffer *render_buffer;
|
||||
struct wlr_vk_render_buffer_out *render_buffer_out;
|
||||
struct wlr_vk_render_format_setup *render_setup;
|
||||
struct wlr_vk_command_buffer *command_buffer;
|
||||
struct rect_union updated_region;
|
||||
VkPipeline bound_pipeline;
|
||||
float projection[9];
|
||||
bool failed;
|
||||
bool two_pass; // rendering via intermediate blending buffer
|
||||
bool srgb_pathway; // if false, rendering via intermediate blending buffer
|
||||
struct wlr_color_transform *color_transform;
|
||||
|
||||
bool has_primaries;
|
||||
struct wlr_color_primaries primaries;
|
||||
|
||||
struct wlr_drm_syncobj_timeline *signal_timeline;
|
||||
uint64_t signal_point;
|
||||
|
||||
struct wl_array textures; // struct wlr_vk_render_pass_texture
|
||||
};
|
||||
|
||||
struct wlr_vk_render_pass *vulkan_begin_render_pass(struct wlr_vk_renderer *renderer,
|
||||
|
|
@ -471,10 +419,8 @@ 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,
|
||||
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]);
|
||||
struct wlr_vk_render_buffer *render_buffer, struct wlr_vk_command_buffer *cb);
|
||||
bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture);
|
||||
|
||||
bool vulkan_read_pixels(struct wlr_vk_renderer *vk_renderer,
|
||||
VkFormat src_format, VkImage src_image,
|
||||
|
|
@ -490,12 +436,13 @@ struct wlr_vk_texture {
|
|||
VkDeviceMemory memories[WLR_DMABUF_MAX_PLANES];
|
||||
VkImage image;
|
||||
const struct wlr_vk_format *format;
|
||||
enum wlr_vk_texture_transform transform;
|
||||
struct wlr_vk_command_buffer *last_used_cb; // to track when it can be destroyed
|
||||
bool dmabuf_imported;
|
||||
bool owned; // if dmabuf_imported: whether we have ownership of the image
|
||||
bool transitioned; // if dma_imported: whether we transitioned it away from preinit
|
||||
bool has_alpha; // whether the image is has alpha channel
|
||||
bool using_mutable_srgb; // can be accessed through _SRGB format view
|
||||
bool using_mutable_srgb; // is this accessed through _SRGB format view
|
||||
struct wl_list foreign_link; // wlr_vk_renderer.foreign_textures
|
||||
struct wl_list destroy_link; // wlr_vk_command_buffer.destroy_textures
|
||||
struct wl_list link; // wlr_vk_renderer.textures
|
||||
|
|
@ -503,8 +450,10 @@ struct wlr_vk_texture {
|
|||
// If imported from a wlr_buffer
|
||||
struct wlr_buffer *buffer;
|
||||
struct wlr_addon buffer_addon;
|
||||
// For DMA-BUF implicit sync interop
|
||||
VkSemaphore foreign_semaphores[WLR_DMABUF_MAX_PLANES];
|
||||
|
||||
struct wl_list views; // struct wlr_vk_texture_view.link
|
||||
struct wl_list views; // struct wlr_vk_texture_ds.link
|
||||
};
|
||||
|
||||
struct wlr_vk_texture *vulkan_get_texture(struct wlr_texture *wlr_texture);
|
||||
|
|
@ -536,7 +485,6 @@ struct wlr_vk_shared_buffer {
|
|||
VkDeviceSize buf_size;
|
||||
void *cpu_mapping;
|
||||
struct wl_array allocs; // struct wlr_vk_allocation
|
||||
int64_t last_used_ms;
|
||||
};
|
||||
|
||||
// Suballocated range on a buffer.
|
||||
|
|
@ -552,7 +500,6 @@ struct wlr_vk_color_transform {
|
|||
struct wl_list link; // wlr_vk_renderer, list of all color transforms
|
||||
|
||||
struct {
|
||||
size_t dim;
|
||||
VkImage image;
|
||||
VkImageView image_view;
|
||||
VkDeviceMemory memory;
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@
|
|||
struct wlr_renderer *renderer_autocreate_with_drm_fd(int drm_fd);
|
||||
/**
|
||||
* Get the supported render formats. Buffers allocated with a format from this
|
||||
* list may be used with wlr_renderer_begin_buffer_pass().
|
||||
* list may be attached via wlr_renderer_begin_with_buffer.
|
||||
*/
|
||||
const struct wlr_drm_format_set *wlr_renderer_get_render_formats(
|
||||
struct wlr_renderer *renderer);
|
||||
|
|
|
|||
|
|
@ -50,6 +50,15 @@ struct wlr_dmabuf_buffer *dmabuf_buffer_create(
|
|||
*/
|
||||
bool dmabuf_buffer_drop(struct wlr_dmabuf_buffer *buffer);
|
||||
|
||||
/**
|
||||
* Check whether a buffer is fully opaque.
|
||||
*
|
||||
* When true is returned, the buffer is guaranteed to be fully opaque, but the
|
||||
* reverse is not true: false may be returned in cases where the buffer is fully
|
||||
* opaque.
|
||||
*/
|
||||
bool buffer_is_opaque(struct wlr_buffer *buffer);
|
||||
|
||||
/**
|
||||
* Creates a struct wlr_client_buffer from a given struct wlr_buffer by creating
|
||||
* a texture from it, and copying its struct wl_resource.
|
||||
|
|
|
|||
15
include/types/wlr_matrix.h
Normal file
15
include/types/wlr_matrix.h
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
#ifndef TYPES_WLR_MATRIX_H
|
||||
#define TYPES_WLR_MATRIX_H
|
||||
|
||||
#include <wlr/types/wlr_matrix.h>
|
||||
|
||||
/**
|
||||
* Writes a 2D orthographic projection matrix to mat of (width, height) with a
|
||||
* specified wl_output_transform.
|
||||
*
|
||||
* Equivalent to glOrtho(0, width, 0, height, 1, -1) with the transform applied.
|
||||
*/
|
||||
void matrix_projection(float mat[static 9], int width, int height,
|
||||
enum wl_output_transform transform);
|
||||
|
||||
#endif
|
||||
|
|
@ -8,8 +8,6 @@ void output_pending_resolution(struct wlr_output *output,
|
|||
const struct wlr_output_state *state, int *width, int *height);
|
||||
bool output_pending_enabled(struct wlr_output *output,
|
||||
const struct wlr_output_state *state);
|
||||
const struct wlr_output_image_description *output_pending_image_description(
|
||||
struct wlr_output *output, const struct wlr_output_state *state);
|
||||
|
||||
bool output_pick_format(struct wlr_output *output,
|
||||
const struct wlr_drm_format_set *display_formats,
|
||||
|
|
@ -20,18 +18,11 @@ bool output_ensure_buffer(struct wlr_output *output,
|
|||
bool output_cursor_set_texture(struct wlr_output_cursor *cursor,
|
||||
struct wlr_texture *texture, bool own_texture, const struct wlr_fbox *src_box,
|
||||
int dst_width, int dst_height, enum wl_output_transform transform,
|
||||
int32_t hotspot_x, int32_t hotspot_y, struct wlr_drm_syncobj_timeline *wait_timeline,
|
||||
uint64_t wait_point);
|
||||
int32_t hotspot_x, int32_t hotspot_y);
|
||||
|
||||
void output_defer_present(struct wlr_output *output, struct wlr_output_event_present event);
|
||||
|
||||
bool output_prepare_commit(struct wlr_output *output, const struct wlr_output_state *state);
|
||||
void output_apply_commit(struct wlr_output *output, const struct wlr_output_state *state);
|
||||
void output_send_commit_event(struct wlr_output *output, const struct wlr_output_state *state);
|
||||
|
||||
void output_state_get_buffer_src_box(const struct wlr_output_state *state,
|
||||
struct wlr_fbox *out);
|
||||
void output_state_get_buffer_dst_box(const struct wlr_output_state *state,
|
||||
struct wlr_box *out);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef TYPES_WLR_REGION_H
|
||||
#define TYPES_WLR_REGION_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <wlr/types/wlr_region.h>
|
||||
|
||||
struct wl_client;
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,6 @@
|
|||
|
||||
struct wlr_scene *scene_node_get_root(struct wlr_scene_node *node);
|
||||
|
||||
void scene_node_get_size(struct wlr_scene_node *node, int *width, int *height);
|
||||
|
||||
void scene_surface_set_clip(struct wlr_scene_surface *surface, struct wlr_box *clip);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,14 +0,0 @@
|
|||
#ifndef UTIL_MEM_H
|
||||
#define UTIL_MEM_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
|
||||
/**
|
||||
* Allocate a new block of memory and copy *src to it, then store the address
|
||||
* of the new allocation in *out. Returns true if it worked, or false if
|
||||
* allocation failed.
|
||||
*/
|
||||
bool memdup(void *out, const void *src, size_t size);
|
||||
|
||||
#endif // UTIL_MEM_H
|
||||
|
|
@ -4,8 +4,6 @@
|
|||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
|
||||
static const long NSEC_PER_SEC = 1000000000;
|
||||
|
||||
/**
|
||||
* Get the current time, in milliseconds.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -25,21 +25,10 @@ struct wlr_backend_output_state {
|
|||
|
||||
/**
|
||||
* A backend provides a set of input and output devices.
|
||||
*
|
||||
* Buffer capabilities and features can change over the lifetime of a backend,
|
||||
* for instance when a child backend is added to a multi-backend.
|
||||
*/
|
||||
struct wlr_backend {
|
||||
const struct wlr_backend_impl *impl;
|
||||
|
||||
// Bitfield of supported buffer capabilities (see enum wlr_buffer_cap)
|
||||
uint32_t buffer_caps;
|
||||
|
||||
struct {
|
||||
// Whether wait/signal timelines are supported in output commits
|
||||
bool timeline;
|
||||
} features;
|
||||
|
||||
struct {
|
||||
/** Raised when destroyed */
|
||||
struct wl_signal destroy;
|
||||
|
|
@ -65,12 +54,13 @@ struct wlr_backend *wlr_backend_autocreate(struct wl_event_loop *loop,
|
|||
struct wlr_session **session_ptr);
|
||||
/**
|
||||
* Start the backend. This may signal new_input or new_output immediately, but
|
||||
* may also wait until the event loop is started. Returns false on failure.
|
||||
* may also wait until the display's event loop begins. Returns false on
|
||||
* failure.
|
||||
*/
|
||||
bool wlr_backend_start(struct wlr_backend *backend);
|
||||
/**
|
||||
* Destroy the backend and clean up all of its resources. Normally called
|
||||
* automatically when the event loop is destroyed.
|
||||
* automatically when the struct wl_display is destroyed.
|
||||
*/
|
||||
void wlr_backend_destroy(struct wlr_backend *backend);
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ struct wlr_backend_impl {
|
|||
bool (*start)(struct wlr_backend *backend);
|
||||
void (*destroy)(struct wlr_backend *backend);
|
||||
int (*get_drm_fd)(struct wlr_backend *backend);
|
||||
uint32_t (*get_buffer_caps)(struct wlr_backend *backend);
|
||||
bool (*test)(struct wlr_backend *backend,
|
||||
const struct wlr_backend_output_state *states, size_t states_len);
|
||||
bool (*commit)(struct wlr_backend *backend,
|
||||
|
|
|
|||
|
|
@ -43,6 +43,11 @@ struct wlr_session {
|
|||
*/
|
||||
bool active;
|
||||
|
||||
/*
|
||||
* 0 if virtual terminals are not supported
|
||||
* i.e. seat != "seat0"
|
||||
*/
|
||||
unsigned vtnr;
|
||||
char seat[256];
|
||||
|
||||
struct udev *udev;
|
||||
|
|
@ -55,16 +60,13 @@ struct wlr_session {
|
|||
struct wl_list devices; // wlr_device.link
|
||||
|
||||
struct wl_event_loop *event_loop;
|
||||
struct wl_listener event_loop_destroy;
|
||||
|
||||
struct {
|
||||
struct wl_signal active;
|
||||
struct wl_signal add_drm_card; // struct wlr_session_add_event
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct {
|
||||
struct wl_listener event_loop_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_session_add_event {
|
||||
|
|
|
|||
|
|
@ -1,76 +1,19 @@
|
|||
#ifndef WLR_CONFIG_H
|
||||
#define WLR_CONFIG_H
|
||||
|
||||
/**
|
||||
* Whether the DRM backend is compile-time enabled. Equivalent to the
|
||||
* pkg-config "have_drm_backend" variable.
|
||||
*
|
||||
* Required for <wlr/backend/drm.h>.
|
||||
*/
|
||||
#mesondefine WLR_HAS_DRM_BACKEND
|
||||
/**
|
||||
* Whether the libinput backend is compile-time enabled. Equivalent to the
|
||||
* pkg-config "have_libinput_backend" vartiable.
|
||||
*
|
||||
* Required for <wlr/backend/libinput.h>.
|
||||
*/
|
||||
#mesondefine WLR_HAS_LIBINPUT_BACKEND
|
||||
/**
|
||||
* Whether the X11 backend is compile-time enabled. Equivalent to the
|
||||
* pkg-config "have_x11_backend" variable.
|
||||
*
|
||||
* Required for <wlr/backend/x11.h>.
|
||||
*/
|
||||
#mesondefine WLR_HAS_X11_BACKEND
|
||||
|
||||
/**
|
||||
* Whether the GLES2 renderer is compile-time enabled. Equivalent to the
|
||||
* pkg-config "have_gles2_renderer" variable.
|
||||
*
|
||||
* Required for <wlr/render/gles2.h>.
|
||||
*/
|
||||
#mesondefine WLR_HAS_GLES2_RENDERER
|
||||
/**
|
||||
* Whether the Vulkan renderer is compile-time enabled. Equivalent to the
|
||||
* pkg-config "have_vulkan_renderer" variable.
|
||||
*
|
||||
* Required for <wlr/render/vulkan.h>.
|
||||
*/
|
||||
#mesondefine WLR_HAS_VULKAN_RENDERER
|
||||
|
||||
/**
|
||||
* Whether the GBM allocator is compile-time enabled. Equivalent to the
|
||||
* pkg-config "have_gbm_allocator" variable.
|
||||
*/
|
||||
#mesondefine WLR_HAS_GBM_ALLOCATOR
|
||||
/**
|
||||
* Whether the udmabuf allocator is compile-time enabled. Equivalent to the
|
||||
* pkg-config "have_udmabuf_allocator" variable.
|
||||
*/
|
||||
#mesondefine WLR_HAS_UDMABUF_ALLOCATOR
|
||||
|
||||
/**
|
||||
* Whether Xwayland support is compile-time enabled. Equivalent to the
|
||||
* pkg-config "have_xwayland" variable.
|
||||
*
|
||||
* Required for <wlr/xwayland/…>.
|
||||
*/
|
||||
#mesondefine WLR_HAS_XWAYLAND
|
||||
|
||||
/**
|
||||
* Whether session support is compile-time enabled. Equivalent to the
|
||||
* pkg-config "have_session" variable.
|
||||
*
|
||||
* Required for <wlr/backend/session.h>.
|
||||
*/
|
||||
#mesondefine WLR_HAS_SESSION
|
||||
|
||||
/**
|
||||
* Whether traditional color management support is compile-time enabled.
|
||||
* Equivalent to the pkg-config "have_color_management" variable.
|
||||
*
|
||||
* Required for ICC profile support in <wlr/render/color.h>.
|
||||
*/
|
||||
#mesondefine WLR_HAS_COLOR_MANAGEMENT
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -36,11 +36,6 @@ struct wlr_buffer_resource_interface {
|
|||
void wlr_buffer_init(struct wlr_buffer *buffer,
|
||||
const struct wlr_buffer_impl *impl, int width, int height);
|
||||
|
||||
/**
|
||||
* Emit the destroy event and clean up common buffer state.
|
||||
*/
|
||||
void wlr_buffer_finish(struct wlr_buffer *buffer);
|
||||
|
||||
/**
|
||||
* Allows the registration of a struct wl_resource implementation.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,45 +0,0 @@
|
|||
/*
|
||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||
* future consistency of this API.
|
||||
*/
|
||||
#ifndef WLR_USE_UNSTABLE
|
||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||
#endif
|
||||
|
||||
#ifndef WLR_INTERFACES_WLR_EXT_IMAGE_CAPTURE_SOURCE_V1_H
|
||||
#define WLR_INTERFACES_WLR_EXT_IMAGE_CAPTURE_SOURCE_V1_H
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_ext_image_capture_source_v1.h>
|
||||
|
||||
struct wlr_ext_image_copy_capture_frame_v1;
|
||||
struct wlr_swapchain;
|
||||
struct wlr_renderer;
|
||||
struct wlr_seat;
|
||||
|
||||
struct wlr_ext_image_capture_source_v1_interface {
|
||||
// TODO: drop with_cursors flag
|
||||
void (*start)(struct wlr_ext_image_capture_source_v1 *source, bool with_cursors);
|
||||
void (*stop)(struct wlr_ext_image_capture_source_v1 *source);
|
||||
void (*schedule_frame)(struct wlr_ext_image_capture_source_v1 *source);
|
||||
void (*copy_frame)(struct wlr_ext_image_capture_source_v1 *source,
|
||||
struct wlr_ext_image_copy_capture_frame_v1 *dst_frame,
|
||||
struct wlr_ext_image_capture_source_v1_frame_event *frame_event);
|
||||
struct wlr_ext_image_capture_source_v1_cursor *(*get_pointer_cursor)(
|
||||
struct wlr_ext_image_capture_source_v1 *source, struct wlr_seat *seat);
|
||||
};
|
||||
|
||||
void wlr_ext_image_capture_source_v1_init(struct wlr_ext_image_capture_source_v1 *source,
|
||||
const struct wlr_ext_image_capture_source_v1_interface *impl);
|
||||
void wlr_ext_image_capture_source_v1_finish(struct wlr_ext_image_capture_source_v1 *source);
|
||||
bool wlr_ext_image_capture_source_v1_create_resource(struct wlr_ext_image_capture_source_v1 *source,
|
||||
struct wl_client *client, uint32_t new_id);
|
||||
bool wlr_ext_image_capture_source_v1_set_constraints_from_swapchain(
|
||||
struct wlr_ext_image_capture_source_v1 *source,
|
||||
struct wlr_swapchain *swapchain, struct wlr_renderer *renderer);
|
||||
|
||||
void wlr_ext_image_capture_source_v1_cursor_init(struct wlr_ext_image_capture_source_v1_cursor *source_cursor,
|
||||
const struct wlr_ext_image_capture_source_v1_interface *impl);
|
||||
void wlr_ext_image_capture_source_v1_cursor_finish(struct wlr_ext_image_capture_source_v1_cursor *source_cursor);
|
||||
|
||||
#endif
|
||||
|
|
@ -108,10 +108,6 @@ struct wlr_output_impl {
|
|||
void wlr_output_init(struct wlr_output *output, struct wlr_backend *backend,
|
||||
const struct wlr_output_impl *impl, struct wl_event_loop *event_loop,
|
||||
const struct wlr_output_state *state);
|
||||
/**
|
||||
* Emit the destroy event and clean up common output state.
|
||||
*/
|
||||
void wlr_output_finish(struct wlr_output *output);
|
||||
/**
|
||||
* Notify compositors that they need to submit a new frame in order to apply
|
||||
* output changes.
|
||||
|
|
|
|||
|
|
@ -19,7 +19,4 @@ void wlr_pointer_init(struct wlr_pointer *pointer,
|
|||
const struct wlr_pointer_impl *impl, const char *name);
|
||||
void wlr_pointer_finish(struct wlr_pointer *pointer);
|
||||
|
||||
void wlr_pointer_notify_button(struct wlr_pointer *pointer,
|
||||
struct wlr_pointer_button_event *event);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -10,100 +10,8 @@
|
|||
#define WLR_RENDER_COLOR_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
/**
|
||||
* Well-known color primaries.
|
||||
*/
|
||||
enum wlr_color_named_primaries {
|
||||
WLR_COLOR_NAMED_PRIMARIES_SRGB = 1 << 0,
|
||||
WLR_COLOR_NAMED_PRIMARIES_BT2020 = 1 << 1,
|
||||
};
|
||||
|
||||
/**
|
||||
* Well-known color transfer functions.
|
||||
*/
|
||||
enum wlr_color_transfer_function {
|
||||
WLR_COLOR_TRANSFER_FUNCTION_SRGB = 1 << 0,
|
||||
WLR_COLOR_TRANSFER_FUNCTION_ST2084_PQ = 1 << 1,
|
||||
WLR_COLOR_TRANSFER_FUNCTION_EXT_LINEAR = 1 << 2,
|
||||
WLR_COLOR_TRANSFER_FUNCTION_GAMMA22 = 1 << 3,
|
||||
WLR_COLOR_TRANSFER_FUNCTION_BT1886 = 1 << 4,
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies alpha blending modes. Note that premultiplied_electrical
|
||||
* is the default, so there is no "none" or "unset" value.
|
||||
*/
|
||||
enum wlr_alpha_mode {
|
||||
WLR_COLOR_ALPHA_MODE_PREMULTIPLIED_ELECTRICAL,
|
||||
WLR_COLOR_ALPHA_MODE_PREMULTIPLIED_OPTICAL,
|
||||
WLR_COLOR_ALPHA_MODE_STRAIGHT,
|
||||
};
|
||||
|
||||
/**
|
||||
* Well-known color encodings, each representing a set of matrix coefficients
|
||||
* used to convert that particular YCbCr encoding to RGB. NONE means the
|
||||
* value is unset or unknown.
|
||||
*/
|
||||
enum wlr_color_encoding {
|
||||
WLR_COLOR_ENCODING_NONE,
|
||||
WLR_COLOR_ENCODING_IDENTITY,
|
||||
WLR_COLOR_ENCODING_BT709,
|
||||
WLR_COLOR_ENCODING_FCC,
|
||||
WLR_COLOR_ENCODING_BT601,
|
||||
WLR_COLOR_ENCODING_SMPTE240,
|
||||
WLR_COLOR_ENCODING_BT2020,
|
||||
WLR_COLOR_ENCODING_BT2020_CL,
|
||||
WLR_COLOR_ENCODING_ICTCP,
|
||||
};
|
||||
|
||||
/**
|
||||
* Specifies whether a particular color-encoding uses full- or limited-range
|
||||
* values. NONE means the value is unset or unknown.
|
||||
*/
|
||||
enum wlr_color_range {
|
||||
WLR_COLOR_RANGE_NONE,
|
||||
WLR_COLOR_RANGE_LIMITED,
|
||||
WLR_COLOR_RANGE_FULL,
|
||||
};
|
||||
|
||||
/**
|
||||
* Chroma sample locations, corresponding to Chroma420SampleLocType code
|
||||
* points in H.273. NONE means the value is unset or unknown.
|
||||
*/
|
||||
enum wlr_color_chroma_location {
|
||||
WLR_COLOR_CHROMA_LOCATION_NONE,
|
||||
WLR_COLOR_CHROMA_LOCATION_TYPE0,
|
||||
WLR_COLOR_CHROMA_LOCATION_TYPE1,
|
||||
WLR_COLOR_CHROMA_LOCATION_TYPE2,
|
||||
WLR_COLOR_CHROMA_LOCATION_TYPE3,
|
||||
WLR_COLOR_CHROMA_LOCATION_TYPE4,
|
||||
WLR_COLOR_CHROMA_LOCATION_TYPE5,
|
||||
};
|
||||
|
||||
/**
|
||||
* CIE 1931 xy chromaticity coordinates.
|
||||
*/
|
||||
struct wlr_color_cie1931_xy {
|
||||
float x, y;
|
||||
};
|
||||
|
||||
/**
|
||||
* Color primaries and white point describing a color volume.
|
||||
*/
|
||||
struct wlr_color_primaries {
|
||||
struct wlr_color_cie1931_xy red, green, blue, white;
|
||||
};
|
||||
|
||||
/**
|
||||
* Luminance range and reference white luminance level, in cd/m².
|
||||
*/
|
||||
struct wlr_color_luminances {
|
||||
float min, max, reference;
|
||||
};
|
||||
|
||||
/**
|
||||
* A color transformation formula, which maps a linear color space with
|
||||
* sRGB primaries to an output color space.
|
||||
|
|
@ -128,30 +36,15 @@ struct wlr_color_transform *wlr_color_transform_init_linear_to_icc(
|
|||
const void *data, size_t size);
|
||||
|
||||
/**
|
||||
* Initialize a color transformation to apply EOTF⁻¹ encoding. Returns
|
||||
* NULL on failure.
|
||||
* Initialize a color transformation to apply sRGB encoding.
|
||||
* Returns NULL on failure.
|
||||
*/
|
||||
struct wlr_color_transform *wlr_color_transform_init_linear_to_inverse_eotf(
|
||||
enum wlr_color_transfer_function tf);
|
||||
|
||||
/**
|
||||
* Initialize a color transformation to apply three 1D look-up tables. dim
|
||||
* is the number of elements in each individual LUT. Returns NULL on failure.
|
||||
*/
|
||||
struct wlr_color_transform *wlr_color_transform_init_lut_3x1d(size_t dim,
|
||||
const uint16_t *r, const uint16_t *g, const uint16_t *b);
|
||||
|
||||
/**
|
||||
* Initialize a color transformation to apply a sequence of color transforms
|
||||
* one after another.
|
||||
*/
|
||||
struct wlr_color_transform *wlr_color_transform_init_pipeline(
|
||||
struct wlr_color_transform **transforms, size_t len);
|
||||
struct wlr_color_transform *wlr_color_transform_init_srgb(void);
|
||||
|
||||
/**
|
||||
* Increase the reference count of the color transform by 1.
|
||||
*/
|
||||
struct wlr_color_transform *wlr_color_transform_ref(struct wlr_color_transform *tr);
|
||||
void wlr_color_transform_ref(struct wlr_color_transform *tr);
|
||||
|
||||
/**
|
||||
* Reduce the reference count of the color transform by 1; freeing it and
|
||||
|
|
@ -159,10 +52,4 @@ struct wlr_color_transform *wlr_color_transform_ref(struct wlr_color_transform *
|
|||
*/
|
||||
void wlr_color_transform_unref(struct wlr_color_transform *tr);
|
||||
|
||||
/**
|
||||
* Evaluate a color transform for a given RGB triplet.
|
||||
*/
|
||||
void wlr_color_transform_eval(struct wlr_color_transform *tr,
|
||||
float out[static 3], const float in[static 3]);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -69,9 +69,6 @@ void wlr_drm_format_set_finish(struct wlr_drm_format_set *set);
|
|||
const struct wlr_drm_format *wlr_drm_format_set_get(
|
||||
const struct wlr_drm_format_set *set, uint32_t format);
|
||||
|
||||
bool wlr_drm_format_set_remove(struct wlr_drm_format_set *set, uint32_t format,
|
||||
uint64_t modifier);
|
||||
|
||||
bool wlr_drm_format_set_has(const struct wlr_drm_format_set *set,
|
||||
uint32_t format, uint64_t modifier);
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@
|
|||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/util/addon.h>
|
||||
|
||||
/**
|
||||
* A synchronization timeline.
|
||||
|
|
@ -30,24 +29,20 @@ struct wlr_drm_syncobj_timeline {
|
|||
int drm_fd;
|
||||
uint32_t handle;
|
||||
|
||||
struct wlr_addon_set addons;
|
||||
// private state
|
||||
|
||||
struct {
|
||||
size_t n_refs;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_drm_syncobj_timeline_waiter;
|
||||
|
||||
typedef void (*wlr_drm_syncobj_timeline_ready_callback)(
|
||||
struct wlr_drm_syncobj_timeline_waiter *waiter);
|
||||
|
||||
struct wlr_drm_syncobj_timeline_waiter {
|
||||
struct {
|
||||
struct wl_signal ready;
|
||||
} events;
|
||||
|
||||
// private state
|
||||
|
||||
int ev_fd;
|
||||
struct wl_event_source *event_source;
|
||||
wlr_drm_syncobj_timeline_ready_callback callback;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -67,17 +62,6 @@ struct wlr_drm_syncobj_timeline *wlr_drm_syncobj_timeline_ref(struct wlr_drm_syn
|
|||
* Unreference a synchronization timeline.
|
||||
*/
|
||||
void wlr_drm_syncobj_timeline_unref(struct wlr_drm_syncobj_timeline *timeline);
|
||||
/**
|
||||
* Export a drm_syncobj FD from a timeline.
|
||||
*/
|
||||
int wlr_drm_syncobj_timeline_export(struct wlr_drm_syncobj_timeline *timeline);
|
||||
/**
|
||||
* Transfer a point from a timeline to another.
|
||||
*
|
||||
* Both timelines must have been created with the same DRM FD.
|
||||
*/
|
||||
bool wlr_drm_syncobj_timeline_transfer(struct wlr_drm_syncobj_timeline *dst,
|
||||
uint64_t dst_point, struct wlr_drm_syncobj_timeline *src, uint64_t src_point);
|
||||
/**
|
||||
* Check if a timeline point has been signalled or has materialized.
|
||||
*
|
||||
|
|
@ -94,12 +78,10 @@ bool wlr_drm_syncobj_timeline_check(struct wlr_drm_syncobj_timeline *timeline,
|
|||
* Asynchronously wait for a timeline point.
|
||||
*
|
||||
* See wlr_drm_syncobj_timeline_check() for a definition of flags.
|
||||
*
|
||||
* A callback must be provided that will be invoked when the waiter has finished.
|
||||
*/
|
||||
bool wlr_drm_syncobj_timeline_waiter_init(struct wlr_drm_syncobj_timeline_waiter *waiter,
|
||||
struct wlr_drm_syncobj_timeline *timeline, uint64_t point, uint32_t flags,
|
||||
struct wl_event_loop *loop, wlr_drm_syncobj_timeline_ready_callback callback);
|
||||
struct wl_event_loop *loop);
|
||||
/**
|
||||
* Cancel a timeline waiter.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#include <pixman.h>
|
||||
#include <stdint.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/render/color.h>
|
||||
#include <wlr/util/box.h>
|
||||
|
||||
struct wlr_renderer;
|
||||
|
|
@ -31,23 +30,9 @@ struct wlr_render_timer;
|
|||
struct wlr_buffer_pass_options {
|
||||
/* Timer to measure the duration of the render pass */
|
||||
struct wlr_render_timer *timer;
|
||||
/* Color transform to apply to the output of the render pass.
|
||||
* Leave NULL to indicate the default transform (Gamma 2.2 encoding for
|
||||
* sRGB monitors) */
|
||||
/* Color transform to apply to the output of the render pass,
|
||||
* leave NULL to indicate sRGB/no custom transform */
|
||||
struct wlr_color_transform *color_transform;
|
||||
/** Primaries describing the color volume of the destination buffer */
|
||||
const struct wlr_color_primaries *primaries;
|
||||
|
||||
/* Signal a timeline synchronization point when the render pass completes.
|
||||
*
|
||||
* When a compositor provides a signal timeline, the renderer may skip
|
||||
* implicit signal synchronization.
|
||||
*
|
||||
* Support for this feature is advertised by features.timeline in
|
||||
* struct wlr_renderer.
|
||||
*/
|
||||
struct wlr_drm_syncobj_timeline *signal_timeline;
|
||||
uint64_t signal_point;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -103,21 +88,6 @@ struct wlr_render_texture_options {
|
|||
enum wlr_scale_filter_mode filter_mode;
|
||||
/* Blend mode */
|
||||
enum wlr_render_blend_mode blend_mode;
|
||||
/* Transfer function the source texture is encoded with */
|
||||
enum wlr_color_transfer_function transfer_function;
|
||||
/* Primaries describing the color volume of the source texture */
|
||||
const struct wlr_color_primaries *primaries;
|
||||
|
||||
/* Wait for a timeline synchronization point before texturing.
|
||||
*
|
||||
* When a compositor provides a wait timeline, the renderer may skip
|
||||
* implicit wait synchronization.
|
||||
*
|
||||
* Support for this feature is advertised by features.timeline in
|
||||
* struct wlr_renderer.
|
||||
*/
|
||||
struct wlr_drm_syncobj_timeline *wait_timeline;
|
||||
uint64_t wait_point;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -10,10 +10,9 @@
|
|||
struct wlr_swapchain_slot {
|
||||
struct wlr_buffer *buffer;
|
||||
bool acquired; // waiting for release
|
||||
int age;
|
||||
|
||||
struct {
|
||||
struct wl_listener release;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_swapchain {
|
||||
|
|
@ -24,9 +23,7 @@ struct wlr_swapchain {
|
|||
|
||||
struct wlr_swapchain_slot slots[WLR_SWAPCHAIN_CAP];
|
||||
|
||||
struct {
|
||||
struct wl_listener allocator_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_swapchain *wlr_swapchain_create(
|
||||
|
|
@ -39,12 +36,21 @@ void wlr_swapchain_destroy(struct wlr_swapchain *swapchain);
|
|||
* The returned buffer is locked. When the caller is done with it, they must
|
||||
* unlock it by calling wlr_buffer_unlock.
|
||||
*/
|
||||
struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain);
|
||||
struct wlr_buffer *wlr_swapchain_acquire(struct wlr_swapchain *swapchain,
|
||||
int *age);
|
||||
/**
|
||||
* Returns true if this buffer has been created by this swapchain, and false
|
||||
* otherwise.
|
||||
*/
|
||||
bool wlr_swapchain_has_buffer(struct wlr_swapchain *swapchain,
|
||||
struct wlr_buffer *buffer);
|
||||
/**
|
||||
* Mark the buffer as submitted for presentation. This needs to be called by
|
||||
* swap chain users on frame boundaries.
|
||||
*
|
||||
* If the buffer hasn't been created via the swap chain, the call is ignored.
|
||||
*/
|
||||
void wlr_swapchain_set_buffer_submitted(struct wlr_swapchain *swapchain,
|
||||
struct wlr_buffer *buffer);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -41,25 +41,15 @@ struct wlr_renderer {
|
|||
} events;
|
||||
|
||||
struct {
|
||||
/**
|
||||
* Whether color transforms are supported for input textures
|
||||
*/
|
||||
bool input_color_transform;
|
||||
/**
|
||||
* Does the renderer support color transforms on its output?
|
||||
*/
|
||||
bool output_color_transform;
|
||||
/**
|
||||
* Whether wait/signal timelines are supported.
|
||||
*
|
||||
* See struct wlr_drm_syncobj_timeline.
|
||||
*/
|
||||
bool timeline;
|
||||
} features;
|
||||
|
||||
struct {
|
||||
// private state
|
||||
|
||||
const struct wlr_renderer_impl *impl;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -20,9 +20,9 @@ struct wlr_alpha_modifier_surface_v1_state {
|
|||
struct wlr_alpha_modifier_v1 {
|
||||
struct wl_global *global;
|
||||
|
||||
struct {
|
||||
// private state
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_alpha_modifier_v1 *wlr_alpha_modifier_v1_create(struct wl_display *display);
|
||||
|
|
|
|||
|
|
@ -17,15 +17,11 @@
|
|||
struct wlr_buffer;
|
||||
struct wlr_renderer;
|
||||
|
||||
/**
|
||||
* Shared-memory attributes for a buffer.
|
||||
*/
|
||||
struct wlr_shm_attributes {
|
||||
int fd;
|
||||
uint32_t format; // FourCC code, see DRM_FORMAT_* in <drm_fourcc.h>
|
||||
int width, height;
|
||||
int stride; // Number of bytes between consecutive pixel lines
|
||||
off_t offset; // Offset in bytes of the first pixel in FD
|
||||
uint32_t format;
|
||||
int width, height, stride;
|
||||
off_t offset;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -109,15 +105,6 @@ bool wlr_buffer_get_shm(struct wlr_buffer *buffer,
|
|||
*/
|
||||
struct wlr_buffer *wlr_buffer_try_from_resource(struct wl_resource *resource);
|
||||
|
||||
/**
|
||||
* Check whether a buffer is fully opaque.
|
||||
*
|
||||
* When true is returned, the buffer is guaranteed to be fully opaque, but the
|
||||
* reverse is not true: false may be returned in cases where the buffer is fully
|
||||
* opaque.
|
||||
*/
|
||||
bool wlr_buffer_is_opaque(struct wlr_buffer *buffer);
|
||||
|
||||
/**
|
||||
* Buffer data pointer access flags.
|
||||
*/
|
||||
|
|
@ -143,12 +130,6 @@ enum wlr_buffer_data_ptr_access_flag {
|
|||
*/
|
||||
bool wlr_buffer_begin_data_ptr_access(struct wlr_buffer *buffer, uint32_t flags,
|
||||
void **data, uint32_t *format, size_t *stride);
|
||||
/**
|
||||
* Indicate that a pointer to a buffer's underlying memory will no longer be
|
||||
* used.
|
||||
*
|
||||
* This function must be called after wlr_buffer_begin_data_ptr_access().
|
||||
*/
|
||||
void wlr_buffer_end_data_ptr_access(struct wlr_buffer *buffer);
|
||||
|
||||
/**
|
||||
|
|
@ -167,12 +148,12 @@ struct wlr_client_buffer {
|
|||
*/
|
||||
struct wlr_buffer *source;
|
||||
|
||||
struct {
|
||||
// private state
|
||||
|
||||
struct wl_listener source_destroy;
|
||||
struct wl_listener renderer_destroy;
|
||||
|
||||
size_t n_ignore_locks;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -181,29 +162,4 @@ struct wlr_client_buffer {
|
|||
*/
|
||||
struct wlr_client_buffer *wlr_client_buffer_get(struct wlr_buffer *buffer);
|
||||
|
||||
/**
|
||||
* A single-pixel buffer. Used by clients to draw solid-color rectangles.
|
||||
*/
|
||||
struct wlr_single_pixel_buffer_v1 {
|
||||
struct wlr_buffer base;
|
||||
|
||||
// Full-scale for each component is UINT32_MAX
|
||||
uint32_t r, g, b, a;
|
||||
|
||||
struct {
|
||||
struct wl_resource *resource;
|
||||
struct wl_listener release;
|
||||
|
||||
// Packed little-endian DRM_FORMAT_ARGB8888. Used for data_ptr_access
|
||||
uint8_t argb8888[4];
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
/**
|
||||
* If the wlr_buffer is a wlr_single_pixel_buffer_v1 then unwrap it.
|
||||
* Otherwise, returns NULL.
|
||||
*/
|
||||
struct wlr_single_pixel_buffer_v1 *wlr_single_pixel_buffer_v1_try_from_buffer(
|
||||
struct wlr_buffer *buffer);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,122 +0,0 @@
|
|||
/*
|
||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||
* future consistency of this API.
|
||||
*/
|
||||
#ifndef WLR_USE_UNSTABLE
|
||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||
#endif
|
||||
|
||||
#ifndef WLR_TYPES_WLR_COLOR_MANAGEMENT_V1_H
|
||||
#define WLR_TYPES_WLR_COLOR_MANAGEMENT_V1_H
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
#include <wayland-protocols/color-management-v1-enum.h>
|
||||
|
||||
#include <wlr/render/color.h>
|
||||
|
||||
struct wlr_surface;
|
||||
|
||||
struct wlr_image_description_v1_data {
|
||||
uint32_t tf_named; // enum wp_color_manager_v1_transfer_function, zero if unset
|
||||
uint32_t primaries_named; // enum wp_color_manager_v1_primaries, zero if unset
|
||||
|
||||
bool has_mastering_display_primaries;
|
||||
struct wlr_color_primaries mastering_display_primaries;
|
||||
|
||||
bool has_mastering_luminance;
|
||||
struct {
|
||||
float min, max; // cd/m²
|
||||
} mastering_luminance;
|
||||
|
||||
uint32_t max_cll, max_fall; // cd/m², zero if unset
|
||||
};
|
||||
|
||||
struct wlr_color_manager_v1_features {
|
||||
bool icc_v2_v4;
|
||||
bool parametric;
|
||||
bool set_primaries;
|
||||
bool set_tf_power;
|
||||
bool set_luminances;
|
||||
bool set_mastering_display_primaries;
|
||||
bool extended_target_volume;
|
||||
bool windows_scrgb;
|
||||
};
|
||||
|
||||
struct wlr_color_manager_v1_options {
|
||||
struct wlr_color_manager_v1_features features;
|
||||
|
||||
const enum wp_color_manager_v1_render_intent *render_intents;
|
||||
size_t render_intents_len;
|
||||
|
||||
const enum wp_color_manager_v1_transfer_function *transfer_functions;
|
||||
size_t transfer_functions_len;
|
||||
|
||||
const enum wp_color_manager_v1_primaries *primaries;
|
||||
size_t primaries_len;
|
||||
};
|
||||
|
||||
struct wlr_color_manager_v1 {
|
||||
struct wl_global *global;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct {
|
||||
struct wlr_color_manager_v1_features features;
|
||||
|
||||
enum wp_color_manager_v1_render_intent *render_intents;
|
||||
size_t render_intents_len;
|
||||
|
||||
enum wp_color_manager_v1_transfer_function *transfer_functions;
|
||||
size_t transfer_functions_len;
|
||||
|
||||
enum wp_color_manager_v1_primaries *primaries;
|
||||
size_t primaries_len;
|
||||
|
||||
struct wl_list outputs; // wlr_color_management_output_v1.link
|
||||
struct wl_list surface_feedbacks; // wlr_color_management_surface_feedback_v1.link
|
||||
|
||||
uint32_t last_image_desc_identity;
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_color_manager_v1 *wlr_color_manager_v1_create(struct wl_display *display,
|
||||
uint32_t version, const struct wlr_color_manager_v1_options *options);
|
||||
|
||||
const struct wlr_image_description_v1_data *
|
||||
wlr_surface_get_image_description_v1_data(struct wlr_surface *surface);
|
||||
|
||||
void wlr_color_manager_v1_set_surface_preferred_image_description(
|
||||
struct wlr_color_manager_v1 *manager, struct wlr_surface *surface,
|
||||
const struct wlr_image_description_v1_data *data);
|
||||
|
||||
/**
|
||||
* Convert a protocol transfer function to enum wlr_color_transfer_function.
|
||||
* Aborts if there is no matching wlroots entry.
|
||||
*/
|
||||
enum wlr_color_transfer_function
|
||||
wlr_color_manager_v1_transfer_function_to_wlr(enum wp_color_manager_v1_transfer_function tf);
|
||||
|
||||
/**
|
||||
* Convert an enum wlr_color_transfer_function value into a protocol transfer function.
|
||||
*/
|
||||
enum wp_color_manager_v1_transfer_function
|
||||
wlr_color_manager_v1_transfer_function_from_wlr(enum wlr_color_transfer_function tf);
|
||||
|
||||
/**
|
||||
* Convert a protocol named primaries to enum wlr_color_named_primaries.
|
||||
* Aborts if there is no matching wlroots entry.
|
||||
*/
|
||||
enum wlr_color_named_primaries
|
||||
wlr_color_manager_v1_primaries_to_wlr(enum wp_color_manager_v1_primaries primaries);
|
||||
|
||||
/**
|
||||
* Convert an enum wlr_color_named_primaries value into protocol primaries.
|
||||
*/
|
||||
enum wp_color_manager_v1_primaries
|
||||
wlr_color_manager_v1_primaries_from_wlr(enum wlr_color_named_primaries primaries);
|
||||
|
||||
#endif
|
||||
|
|
@ -1,93 +0,0 @@
|
|||
/*
|
||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||
* future consistency of this API.
|
||||
*/
|
||||
#ifndef WLR_USE_UNSTABLE
|
||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||
#endif
|
||||
|
||||
#ifndef WLR_TYPES_WLR_COLOR_REPRESENTATION_V1_H
|
||||
#define WLR_TYPES_WLR_COLOR_REPRESENTATION_V1_H
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
#include <wayland-protocols/color-representation-v1-enum.h>
|
||||
#include <wlr/render/color.h>
|
||||
|
||||
struct wlr_surface;
|
||||
|
||||
// Supported coefficients and range are always paired together
|
||||
struct wlr_color_representation_v1_coeffs_and_range {
|
||||
enum wp_color_representation_surface_v1_coefficients coeffs;
|
||||
enum wp_color_representation_surface_v1_range range;
|
||||
};
|
||||
|
||||
struct wlr_color_representation_manager_v1 {
|
||||
struct wl_global *global;
|
||||
|
||||
struct {
|
||||
// Manager is being destroyed
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct {
|
||||
enum wp_color_representation_surface_v1_alpha_mode
|
||||
*supported_alpha_modes;
|
||||
size_t supported_alpha_modes_len;
|
||||
|
||||
struct wlr_color_representation_v1_coeffs_and_range
|
||||
*supported_coeffs_and_ranges;
|
||||
size_t supported_coeffs_and_ranges_len;
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
// Options used when initialising a wlr_color_representation_manager_v1
|
||||
struct wlr_color_representation_v1_options {
|
||||
enum wp_color_representation_surface_v1_alpha_mode
|
||||
*supported_alpha_modes;
|
||||
size_t supported_alpha_modes_len;
|
||||
|
||||
const struct wlr_color_representation_v1_coeffs_and_range
|
||||
*supported_coeffs_and_ranges;
|
||||
size_t supported_coeffs_and_ranges_len;
|
||||
};
|
||||
|
||||
struct wlr_color_representation_manager_v1 *wlr_color_representation_manager_v1_create(
|
||||
struct wl_display *display, uint32_t version,
|
||||
const struct wlr_color_representation_v1_options *options);
|
||||
|
||||
// This is all the color-representation state which can be attached to a
|
||||
// surface, double-buffered and made current on commit
|
||||
struct wlr_color_representation_v1_surface_state {
|
||||
// The enum premultiplied_electrical has value zero and is defined
|
||||
// to be the default if unspecified.
|
||||
enum wp_color_representation_surface_v1_alpha_mode alpha_mode;
|
||||
|
||||
// If zero then indicates unset, otherwise values correspond to
|
||||
// enum wp_color_representation_surface_v1_coefficients
|
||||
uint32_t coefficients;
|
||||
|
||||
// If zero then indicates unset, otherwise values correspond to
|
||||
// enum wp_color_representation_surface_v1_range
|
||||
uint32_t range;
|
||||
|
||||
// If zero then indicates unset, otherwise values correspond to
|
||||
// enum wp_color_representation_surface_v1_chroma_location
|
||||
uint32_t chroma_location;
|
||||
};
|
||||
|
||||
// Get the current color representation state committed to a surface
|
||||
const struct wlr_color_representation_v1_surface_state *wlr_color_representation_v1_get_surface_state(
|
||||
struct wlr_surface *surface);
|
||||
|
||||
enum wlr_alpha_mode wlr_color_representation_v1_alpha_mode_to_wlr(
|
||||
enum wp_color_representation_surface_v1_alpha_mode wp_val);
|
||||
enum wlr_color_encoding wlr_color_representation_v1_color_encoding_to_wlr(
|
||||
enum wp_color_representation_surface_v1_coefficients wp_val);
|
||||
enum wlr_color_range wlr_color_representation_v1_color_range_to_wlr(
|
||||
enum wp_color_representation_surface_v1_range wp_val);
|
||||
enum wlr_color_chroma_location wlr_color_representation_v1_chroma_location_to_wlr(
|
||||
enum wp_color_representation_surface_v1_chroma_location wp_val);
|
||||
|
||||
#endif // WLR_TYPES_WLR_COLOR_REPRESENTATION_V1_H
|
||||
|
|
@ -14,11 +14,10 @@
|
|||
#include <stdint.h>
|
||||
#include <time.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
#include <wlr/util/addon.h>
|
||||
#include <wlr/util/box.h>
|
||||
|
||||
struct wlr_surface;
|
||||
|
||||
enum wlr_surface_state_field {
|
||||
WLR_SURFACE_STATE_BUFFER = 1 << 0,
|
||||
WLR_SURFACE_STATE_SURFACE_DAMAGE = 1 << 1,
|
||||
|
|
@ -98,13 +97,6 @@ struct wlr_surface_role {
|
|||
* such object exists.
|
||||
*/
|
||||
void (*commit)(struct wlr_surface *surface);
|
||||
/**
|
||||
* Called when the surface is mapped. May be NULL.
|
||||
*
|
||||
* If the role is represented by an object, this is only called if
|
||||
* such object exists.
|
||||
*/
|
||||
void (*map)(struct wlr_surface *surface);
|
||||
/**
|
||||
* Called when the surface is unmapped. May be NULL.
|
||||
*
|
||||
|
|
@ -123,11 +115,8 @@ struct wlr_surface_output {
|
|||
struct wlr_output *output;
|
||||
|
||||
struct wl_list link; // wlr_surface.current_outputs
|
||||
|
||||
struct {
|
||||
struct wl_listener bind;
|
||||
struct wl_listener destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_surface {
|
||||
|
|
@ -191,47 +180,28 @@ struct wlr_surface {
|
|||
struct wl_resource *role_resource;
|
||||
|
||||
struct {
|
||||
/**
|
||||
* Signals that the client has sent a wl_surface.commit request.
|
||||
*
|
||||
* The state to be committed can be accessed in wlr_surface.pending.
|
||||
*
|
||||
* The commit may not be applied immediately, in which case it's marked
|
||||
* as "cached" and put into a queue. See wlr_surface_lock_pending().
|
||||
*/
|
||||
struct wl_signal client_commit;
|
||||
/**
|
||||
* Signals that a commit has been applied.
|
||||
*
|
||||
* The new state can be accessed in wlr_surface.current.
|
||||
*/
|
||||
struct wl_signal commit;
|
||||
|
||||
/**
|
||||
* Signals that the surface has a non-null buffer committed and is
|
||||
* ready to be displayed.
|
||||
* The `map` event signals that the surface has a non-null buffer
|
||||
* committed and is ready to be displayed.
|
||||
*/
|
||||
struct wl_signal map;
|
||||
/**
|
||||
* Signals that the surface shouldn't be displayed anymore. This can
|
||||
* happen when a null buffer is committed, the associated role object
|
||||
* is destroyed, or when the role-specific conditions for the surface
|
||||
* to be mapped no longer apply.
|
||||
* The `unmap` event signals that the surface shouldn't be displayed
|
||||
* anymore. This can happen when a null buffer is committed,
|
||||
* the associated role object is destroyed, or when the role-specific
|
||||
* conditions for the surface to be mapped no longer apply.
|
||||
*/
|
||||
struct wl_signal unmap;
|
||||
|
||||
/**
|
||||
* Signals that a new child sub-surface has been added.
|
||||
*
|
||||
* Note: unlike other new_* signals, new_subsurface is emitted when
|
||||
* the subsurface is added to the parent surface's current state,
|
||||
* not when the object is created.
|
||||
*/
|
||||
struct wl_signal new_subsurface; // struct wlr_subsurface
|
||||
|
||||
/**
|
||||
* Signals that the surface is being destroyed.
|
||||
*/
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
|
|
@ -240,7 +210,8 @@ struct wlr_surface {
|
|||
struct wlr_addon_set addons;
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
// private state
|
||||
|
||||
struct wl_listener role_resource_destroy;
|
||||
|
||||
struct {
|
||||
|
|
@ -266,7 +237,6 @@ struct wlr_surface {
|
|||
|
||||
struct wl_resource *pending_buffer_resource;
|
||||
struct wl_listener pending_buffer_resource_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_renderer;
|
||||
|
|
@ -275,15 +245,13 @@ struct wlr_compositor {
|
|||
struct wl_global *global;
|
||||
struct wlr_renderer *renderer; // may be NULL
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
struct wl_listener renderer_destroy;
|
||||
|
||||
struct {
|
||||
struct wl_signal new_surface;
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
struct wl_listener renderer_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
typedef void (*wlr_surface_iterator_func_t)(struct wlr_surface *surface,
|
||||
|
|
@ -413,7 +381,7 @@ void wlr_surface_send_frame_done(struct wlr_surface *surface,
|
|||
* surface coordinates.
|
||||
* X and y may be negative, if there are subsurfaces with negative position.
|
||||
*/
|
||||
void wlr_surface_get_extents(struct wlr_surface *surface, struct wlr_box *box);
|
||||
void wlr_surface_get_extends(struct wlr_surface *surface, struct wlr_box *box);
|
||||
|
||||
/**
|
||||
* Get the struct wlr_surface corresponding to a wl_surface resource.
|
||||
|
|
@ -485,8 +453,6 @@ void wlr_surface_set_preferred_buffer_scale(struct wlr_surface *surface,
|
|||
void wlr_surface_set_preferred_buffer_transform(struct wlr_surface *surface,
|
||||
enum wl_output_transform transform);
|
||||
|
||||
struct wlr_surface_synced;
|
||||
|
||||
/**
|
||||
* Implementation for struct wlr_surface_synced.
|
||||
*
|
||||
|
|
@ -503,11 +469,6 @@ struct wlr_surface_synced_impl {
|
|||
void (*finish_state)(void *state);
|
||||
// Move a state. If NULL, memcpy() is used.
|
||||
void (*move_state)(void *dst, void *src);
|
||||
|
||||
// Called when the state is committed. If NULL, this is a no-op.
|
||||
// If an object is a surface role object which has state synchronized with
|
||||
// the surface state, the role commit hook should be preferred over this.
|
||||
void (*commit)(struct wlr_surface_synced *synced);
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#define WLR_TYPES_WLR_CONTENT_TYPE_V1_H
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
#include <wayland-protocols/content-type-v1-enum.h>
|
||||
#include "content-type-v1-protocol.h"
|
||||
|
||||
struct wlr_surface;
|
||||
|
||||
|
|
@ -23,9 +23,9 @@ struct wlr_content_type_manager_v1 {
|
|||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
// private state
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_content_type_manager_v1 *wlr_content_type_manager_v1_create(
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@
|
|||
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_output_layout.h>
|
||||
#include <wlr/types/wlr_output.h>
|
||||
|
||||
struct wlr_input_device;
|
||||
struct wlr_surface;
|
||||
struct wlr_xcursor_manager;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
#define WLR_TYPES_WLR_CURSOR_SHAPE_V1_H
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
#include <wayland-protocols/cursor-shape-v1-enum.h>
|
||||
#include "cursor-shape-v1-protocol.h"
|
||||
|
||||
/**
|
||||
* Manager for the cursor-shape-v1 protocol.
|
||||
|
|
@ -28,9 +28,9 @@ struct wlr_cursor_shape_manager_v1 {
|
|||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
// private state
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
enum wlr_cursor_shape_manager_v1_device_type {
|
||||
|
|
|
|||
|
|
@ -15,27 +15,32 @@
|
|||
#include <pixman.h>
|
||||
#include <wayland-server-core.h>
|
||||
|
||||
/* For triple buffering, a history of two frames is required. */
|
||||
#define WLR_DAMAGE_RING_PREVIOUS_LEN 2
|
||||
|
||||
struct wlr_box;
|
||||
|
||||
struct wlr_damage_ring_buffer {
|
||||
struct wlr_buffer *buffer;
|
||||
struct wl_listener destroy;
|
||||
pixman_region32_t damage;
|
||||
|
||||
struct wlr_damage_ring *ring;
|
||||
struct wl_list link; // wlr_damage_ring.buffers
|
||||
|
||||
struct {
|
||||
struct wl_listener destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_damage_ring {
|
||||
int32_t width, height;
|
||||
|
||||
// Difference between the current buffer and the previous one
|
||||
pixman_region32_t current;
|
||||
|
||||
struct {
|
||||
// private state
|
||||
|
||||
pixman_region32_t previous[WLR_DAMAGE_RING_PREVIOUS_LEN];
|
||||
size_t previous_idx;
|
||||
|
||||
struct wl_list buffers; // wlr_damage_ring_buffer.link
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
void wlr_damage_ring_init(struct wlr_damage_ring *ring);
|
||||
|
|
@ -43,17 +48,30 @@ void wlr_damage_ring_init(struct wlr_damage_ring *ring);
|
|||
void wlr_damage_ring_finish(struct wlr_damage_ring *ring);
|
||||
|
||||
/**
|
||||
* Add a region to the current damage. The region must be in the buffer-local
|
||||
* coordinate space.
|
||||
* Set ring bounds and damage the ring fully.
|
||||
*
|
||||
* Next time damage will be added, it will be cropped to the ring bounds.
|
||||
* If at least one of the dimensions is 0, bounds are removed.
|
||||
*
|
||||
* By default, a damage ring doesn't have bounds.
|
||||
*/
|
||||
void wlr_damage_ring_add(struct wlr_damage_ring *ring,
|
||||
void wlr_damage_ring_set_bounds(struct wlr_damage_ring *ring,
|
||||
int32_t width, int32_t height);
|
||||
|
||||
/**
|
||||
* Add a region to the current damage.
|
||||
*
|
||||
* Returns true if the region intersects the ring bounds, false otherwise.
|
||||
*/
|
||||
bool wlr_damage_ring_add(struct wlr_damage_ring *ring,
|
||||
const pixman_region32_t *damage);
|
||||
|
||||
/**
|
||||
* Add a box to the current damage. The box must be in the buffer-local
|
||||
* coordinate space.
|
||||
* Add a box to the current damage.
|
||||
*
|
||||
* Returns true if the box intersects the ring bounds, false otherwise.
|
||||
*/
|
||||
void wlr_damage_ring_add_box(struct wlr_damage_ring *ring,
|
||||
bool wlr_damage_ring_add_box(struct wlr_damage_ring *ring,
|
||||
const struct wlr_box *box);
|
||||
|
||||
/**
|
||||
|
|
@ -61,6 +79,20 @@ void wlr_damage_ring_add_box(struct wlr_damage_ring *ring,
|
|||
*/
|
||||
void wlr_damage_ring_add_whole(struct wlr_damage_ring *ring);
|
||||
|
||||
/**
|
||||
* Rotate the damage ring. This needs to be called after using the accumulated
|
||||
* damage, e.g. after rendering to an output's back buffer.
|
||||
*/
|
||||
void wlr_damage_ring_rotate(struct wlr_damage_ring *ring);
|
||||
|
||||
/**
|
||||
* Get accumulated damage, which is the difference between the current buffer
|
||||
* and the buffer with age of buffer_age; in context of rendering, this is
|
||||
* the region that needs to be redrawn.
|
||||
*/
|
||||
void wlr_damage_ring_get_buffer_damage(struct wlr_damage_ring *ring,
|
||||
int buffer_age, pixman_region32_t *damage);
|
||||
|
||||
/**
|
||||
* Get accumulated buffer damage and rotate the damage ring.
|
||||
*
|
||||
|
|
@ -70,8 +102,6 @@ void wlr_damage_ring_add_whole(struct wlr_damage_ring *ring);
|
|||
*
|
||||
* Users should damage the ring if an error occurs while rendering or
|
||||
* submitting the new buffer to the backend.
|
||||
*
|
||||
* The returned damage will be in the buffer-local coordinate space.
|
||||
*/
|
||||
void wlr_damage_ring_rotate_buffer(struct wlr_damage_ring *ring,
|
||||
struct wlr_buffer *buffer, pixman_region32_t *damage);
|
||||
|
|
|
|||
|
|
@ -12,12 +12,6 @@
|
|||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
|
||||
/**
|
||||
* Deprecated: this protocol is legacy and superseded by ext-data-control-v1.
|
||||
* The implementation will be dropped in a future wlroots version.
|
||||
*
|
||||
* Consider using `wlr_ext_data_control_manager_v1` as a replacement.
|
||||
*/
|
||||
struct wlr_data_control_manager_v1 {
|
||||
struct wl_global *global;
|
||||
struct wl_list devices; // wlr_data_control_device_v1.link
|
||||
|
|
@ -27,9 +21,7 @@ struct wlr_data_control_manager_v1 {
|
|||
struct wl_signal new_device; // wlr_data_control_device_v1
|
||||
} events;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_data_control_device_v1 {
|
||||
|
|
@ -41,11 +33,9 @@ struct wlr_data_control_device_v1 {
|
|||
struct wl_resource *selection_offer_resource; // current selection offer
|
||||
struct wl_resource *primary_selection_offer_resource; // current primary selection offer
|
||||
|
||||
struct {
|
||||
struct wl_listener seat_destroy;
|
||||
struct wl_listener seat_set_selection;
|
||||
struct wl_listener seat_set_primary_selection;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_data_control_manager_v1 *wlr_data_control_manager_v1_create(
|
||||
|
|
|
|||
|
|
@ -16,15 +16,13 @@ struct wlr_data_device_manager {
|
|||
struct wl_global *global;
|
||||
struct wl_list data_sources;
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
enum wlr_data_offer_type {
|
||||
|
|
@ -42,9 +40,7 @@ struct wlr_data_offer {
|
|||
enum wl_data_device_manager_dnd_action preferred_action;
|
||||
bool in_ask;
|
||||
|
||||
struct {
|
||||
struct wl_listener source_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -93,11 +89,9 @@ struct wlr_drag_icon {
|
|||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_listener surface_destroy;
|
||||
} WLR_PRIVATE;
|
||||
|
||||
void *data;
|
||||
};
|
||||
|
||||
enum wlr_drag_grab_type {
|
||||
|
|
@ -130,14 +124,11 @@ struct wlr_drag {
|
|||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_listener source_destroy;
|
||||
struct wl_listener seat_client_destroy;
|
||||
struct wl_listener focus_destroy;
|
||||
struct wl_listener icon_destroy;
|
||||
} WLR_PRIVATE;
|
||||
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct wlr_drag_motion_event {
|
||||
|
|
|
|||
|
|
@ -21,9 +21,7 @@ struct wlr_drm_buffer {
|
|||
struct wl_resource *resource; // can be NULL if the client destroyed it
|
||||
struct wlr_dmabuf_attributes dmabuf;
|
||||
|
||||
struct {
|
||||
struct wl_listener release;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
@ -42,12 +40,12 @@ struct wlr_drm {
|
|||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct {
|
||||
// private state
|
||||
|
||||
char *node_name;
|
||||
struct wlr_drm_format_set formats;
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_drm_buffer *wlr_drm_buffer_try_from_resource(
|
||||
|
|
|
|||
|
|
@ -18,10 +18,9 @@ struct wlr_drm_lease_v1_manager {
|
|||
struct wl_list devices; // wlr_drm_lease_device_v1.link
|
||||
|
||||
struct wl_display *display;
|
||||
struct wl_listener display_destroy;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
|
||||
/**
|
||||
* Upon receiving this signal, call
|
||||
* wlr_drm_lease_device_v1_grant_lease_request() to grant a lease of the
|
||||
|
|
@ -30,10 +29,6 @@ struct wlr_drm_lease_v1_manager {
|
|||
*/
|
||||
struct wl_signal request;
|
||||
} events;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_drm_lease_device_v1 {
|
||||
|
|
@ -48,11 +43,9 @@ struct wlr_drm_lease_device_v1 {
|
|||
struct wl_list requests; // wlr_drm_lease_request_v1.link
|
||||
struct wl_list link; // wlr_drm_lease_v1_manager.devices
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_listener backend_destroy;
|
||||
} WLR_PRIVATE;
|
||||
|
||||
void *data;
|
||||
};
|
||||
|
||||
struct wlr_drm_lease_v1;
|
||||
|
|
@ -62,12 +55,12 @@ struct wlr_drm_lease_connector_v1 {
|
|||
|
||||
struct wlr_output *output;
|
||||
struct wlr_drm_lease_device_v1 *device;
|
||||
/** NULL if no client is currently leasing this connector */
|
||||
struct wlr_drm_lease_v1 *active_lease;
|
||||
|
||||
struct wl_listener destroy;
|
||||
|
||||
struct wl_list link; // wlr_drm_lease_device_v1.connectors
|
||||
|
||||
struct {
|
||||
struct wl_listener destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_drm_lease_request_v1 {
|
||||
|
|
@ -91,13 +84,14 @@ struct wlr_drm_lease_v1 {
|
|||
|
||||
struct wlr_drm_lease_device_v1 *device;
|
||||
|
||||
struct wlr_drm_lease_connector_v1 **connectors;
|
||||
size_t n_connectors;
|
||||
|
||||
struct wl_list link; // wlr_drm_lease_device_v1.leases
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_listener destroy;
|
||||
} WLR_PRIVATE;
|
||||
|
||||
void *data;
|
||||
};
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -17,13 +17,11 @@ struct wlr_export_dmabuf_manager_v1 {
|
|||
struct wl_global *global;
|
||||
struct wl_list frames; // wlr_export_dmabuf_frame_v1.link
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_export_dmabuf_frame_v1 {
|
||||
|
|
@ -35,10 +33,8 @@ struct wlr_export_dmabuf_frame_v1 {
|
|||
|
||||
bool cursor_locked;
|
||||
|
||||
struct {
|
||||
struct wl_listener output_commit;
|
||||
struct wl_listener output_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_export_dmabuf_manager_v1 *wlr_export_dmabuf_manager_v1_create(
|
||||
|
|
|
|||
|
|
@ -1,51 +0,0 @@
|
|||
/*
|
||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||
* future consistency of this API.
|
||||
*/
|
||||
#ifndef WLR_USE_UNSTABLE
|
||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||
#endif
|
||||
|
||||
#ifndef WLR_TYPES_WLR_EXT_DATA_CONTROL_V1_H
|
||||
#define WLR_TYPES_WLR_EXT_DATA_CONTROL_V1_H
|
||||
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
|
||||
struct wlr_ext_data_control_manager_v1 {
|
||||
struct wl_global *global;
|
||||
struct wl_list devices; // wlr_ext_data_control_device_v1.link
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
struct wl_signal new_device; // wlr_ext_data_control_device_v1
|
||||
} events;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_ext_data_control_device_v1 {
|
||||
struct wl_resource *resource;
|
||||
struct wlr_ext_data_control_manager_v1 *manager;
|
||||
struct wl_list link; // wlr_ext_data_control_manager_v1.devices
|
||||
|
||||
struct wlr_seat *seat;
|
||||
struct wl_resource *selection_offer_resource; // current selection offer
|
||||
struct wl_resource *primary_selection_offer_resource; // current primary selection offer
|
||||
|
||||
struct {
|
||||
struct wl_listener seat_destroy;
|
||||
struct wl_listener seat_set_selection;
|
||||
struct wl_listener seat_set_primary_selection;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_ext_data_control_manager_v1 *wlr_ext_data_control_manager_v1_create(
|
||||
struct wl_display *display, uint32_t version);
|
||||
|
||||
void wlr_ext_data_control_device_v1_destroy(
|
||||
struct wlr_ext_data_control_device_v1 *device);
|
||||
|
||||
#endif
|
||||
|
|
@ -16,15 +16,13 @@ struct wlr_ext_foreign_toplevel_list_v1 {
|
|||
struct wl_list resources; // wl_resource_get_link()
|
||||
struct wl_list toplevels; // ext_foreign_toplevel_handle_v1.link
|
||||
|
||||
struct wl_listener display_destroy;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
|
||||
void *data;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_ext_foreign_toplevel_handle_v1 {
|
||||
|
|
@ -66,7 +64,4 @@ void wlr_ext_foreign_toplevel_handle_v1_update_state(
|
|||
struct wlr_ext_foreign_toplevel_handle_v1 *toplevel,
|
||||
const struct wlr_ext_foreign_toplevel_handle_v1_state *state);
|
||||
|
||||
struct wlr_ext_foreign_toplevel_handle_v1 *wlr_ext_foreign_toplevel_handle_v1_from_resource(
|
||||
struct wl_resource *resource);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,134 +0,0 @@
|
|||
/*
|
||||
* This an unstable interface of wlroots. No guarantees are made regarding the
|
||||
* future consistency of this API.
|
||||
*/
|
||||
#ifndef WLR_USE_UNSTABLE
|
||||
#error "Add -DWLR_USE_UNSTABLE to enable unstable wlroots features"
|
||||
#endif
|
||||
|
||||
#ifndef WLR_TYPES_WLR_EXT_IMAGE_CAPTURE_SOURCE_V1_H
|
||||
#define WLR_TYPES_WLR_EXT_IMAGE_CAPTURE_SOURCE_V1_H
|
||||
|
||||
#include <pixman.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/render/drm_format_set.h>
|
||||
|
||||
struct wlr_scene_node;
|
||||
struct wlr_allocator;
|
||||
struct wlr_renderer;
|
||||
|
||||
/**
|
||||
* A screen capture source.
|
||||
*
|
||||
* When the size, device or formats change, the constraints_update event is
|
||||
* emitted.
|
||||
*
|
||||
* The device and formats advertised are suitable for copying into a
|
||||
* struct wlr_buffer.
|
||||
*/
|
||||
struct wlr_ext_image_capture_source_v1 {
|
||||
const struct wlr_ext_image_capture_source_v1_interface *impl;
|
||||
struct wl_list resources; // wl_resource_get_link()
|
||||
|
||||
uint32_t width, height;
|
||||
|
||||
uint32_t *shm_formats;
|
||||
size_t shm_formats_len;
|
||||
|
||||
dev_t dmabuf_device;
|
||||
struct wlr_drm_format_set dmabuf_formats;
|
||||
|
||||
struct {
|
||||
struct wl_signal constraints_update;
|
||||
struct wl_signal frame; // struct wlr_ext_image_capture_source_v1_frame_event
|
||||
struct wl_signal destroy;
|
||||
} events;
|
||||
};
|
||||
|
||||
/**
|
||||
* Event indicating that the source has produced a new frame.
|
||||
*/
|
||||
struct wlr_ext_image_capture_source_v1_frame_event {
|
||||
const pixman_region32_t *damage;
|
||||
};
|
||||
|
||||
/**
|
||||
* A cursor capture source.
|
||||
*
|
||||
* Provides additional cursor-specific functionality on top of
|
||||
* struct wlr_ext_image_capture_source_v1.
|
||||
*/
|
||||
struct wlr_ext_image_capture_source_v1_cursor {
|
||||
struct wlr_ext_image_capture_source_v1 base;
|
||||
|
||||
bool entered;
|
||||
int32_t x, y;
|
||||
struct {
|
||||
int32_t x, y;
|
||||
} hotspot;
|
||||
|
||||
struct {
|
||||
struct wl_signal update;
|
||||
} events;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface exposing one screen capture source per output.
|
||||
*/
|
||||
struct wlr_ext_output_image_capture_source_manager_v1 {
|
||||
struct wl_global *global;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
/**
|
||||
* Interface exposing one screen capture source per foreign toplevel.
|
||||
*/
|
||||
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 {
|
||||
struct wl_global *global;
|
||||
|
||||
struct {
|
||||
struct wl_signal destroy;
|
||||
struct wl_signal new_request; // struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request
|
||||
} events;
|
||||
|
||||
struct {
|
||||
struct wl_listener display_destroy;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request {
|
||||
struct wlr_ext_foreign_toplevel_handle_v1 *toplevel_handle;
|
||||
struct wl_client *client;
|
||||
|
||||
struct {
|
||||
uint32_t new_id;
|
||||
} WLR_PRIVATE;
|
||||
};
|
||||
|
||||
/**
|
||||
* Obtain a struct wlr_ext_image_capture_source_v1 from an ext_image_capture_source_v1
|
||||
* resource.
|
||||
*
|
||||
* Asserts that the resource has the correct type. Returns NULL if the resource
|
||||
* is inert.
|
||||
*/
|
||||
struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_from_resource(struct wl_resource *resource);
|
||||
|
||||
struct wlr_ext_output_image_capture_source_manager_v1 *wlr_ext_output_image_capture_source_manager_v1_create(
|
||||
struct wl_display *display, uint32_t version);
|
||||
|
||||
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1 *
|
||||
wlr_ext_foreign_toplevel_image_capture_source_manager_v1_create(struct wl_display *display, uint32_t version);
|
||||
|
||||
bool wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request_accept(
|
||||
struct wlr_ext_foreign_toplevel_image_capture_source_manager_v1_request *request,
|
||||
struct wlr_ext_image_capture_source_v1 *source);
|
||||
|
||||
struct wlr_ext_image_capture_source_v1 *wlr_ext_image_capture_source_v1_create_with_scene_node(
|
||||
struct wlr_scene_node *node, struct wl_event_loop *event_loop,
|
||||
struct wlr_allocator *allocator, struct wlr_renderer *renderer);
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue